Module Name:    src
Committed By:   blymn
Date:           Tue Jan 25 03:05:06 UTC 2022

Modified Files:
        src/lib/libcurses: add_wchstr.c addbytes.c background.c border.c
            clrtobot.c clrtoeol.c cr_put.c curses_private.h delch.c erase.c
            in_wch.c in_wchstr.c ins_wch.c ins_wstr.c insch.c insdelln.c
            insstr.c inwstr.c newwin.c refresh.c resize.c slk.c

Log Message:
Correct (hopefully) the handling of wide characters.

* Remove the WCOL family of macros, these were "stealing" the upper bits
  of a character attribute to store the column width of a character.  No
  warning was given about this in curses.h which meant it was easy to
  accidentally reuse the bits in use by the WCOL macros (we already did).
  Add couple of 16bit ints to the character structure iff HAVE_WCHAR is
  true to hold the display width and wide char related flags (just
  continuation at the moment)
* Convert all instances of WCOL macros to just reference the column width
  in the char structure so it is not obfuscated.
* Fix cursor positioning so placing a cursor in the middle of a wide char
  actually does just that.
* Fix plod so it understands that if the cursor is going to be positioned
  in the middle of a wide char it cannot just reprint the char to get there.
* Fix plodput so it correctly counts the number of output characters for
  wide characters.
* Fix slk routines to properly size the wctomb() buffer.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/lib/libcurses/add_wchstr.c
cvs rdiff -u -r1.60 -r1.61 src/lib/libcurses/addbytes.c
cvs rdiff -u -r1.27 -r1.28 src/lib/libcurses/background.c \
    src/lib/libcurses/clrtobot.c
cvs rdiff -u -r1.21 -r1.22 src/lib/libcurses/border.c \
    src/lib/libcurses/ins_wstr.c
cvs rdiff -u -r1.32 -r1.33 src/lib/libcurses/clrtoeol.c
cvs rdiff -u -r1.37 -r1.38 src/lib/libcurses/cr_put.c
cvs rdiff -u -r1.76 -r1.77 src/lib/libcurses/curses_private.h
cvs rdiff -u -r1.26 -r1.27 src/lib/libcurses/delch.c \
    src/lib/libcurses/insch.c
cvs rdiff -u -r1.33 -r1.34 src/lib/libcurses/erase.c \
    src/lib/libcurses/resize.c
cvs rdiff -u -r1.7 -r1.8 src/lib/libcurses/in_wch.c
cvs rdiff -u -r1.9 -r1.10 src/lib/libcurses/in_wchstr.c \
    src/lib/libcurses/insstr.c src/lib/libcurses/inwstr.c
cvs rdiff -u -r1.17 -r1.18 src/lib/libcurses/ins_wch.c
cvs rdiff -u -r1.19 -r1.20 src/lib/libcurses/insdelln.c
cvs rdiff -u -r1.63 -r1.64 src/lib/libcurses/newwin.c
cvs rdiff -u -r1.117 -r1.118 src/lib/libcurses/refresh.c
cvs rdiff -u -r1.18 -r1.19 src/lib/libcurses/slk.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libcurses/add_wchstr.c
diff -u src/lib/libcurses/add_wchstr.c:1.10 src/lib/libcurses/add_wchstr.c:1.11
--- src/lib/libcurses/add_wchstr.c:1.10	Mon Sep  6 07:45:48 2021
+++ src/lib/libcurses/add_wchstr.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: add_wchstr.c,v 1.10 2021/09/06 07:45:48 rin Exp $ */
+/*   $NetBSD: add_wchstr.c,v 1.11 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: add_wchstr.c,v 1.10 2021/09/06 07:45:48 rin Exp $");
+__RCSID("$NetBSD: add_wchstr.c,v 1.11 2022/01/25 03:05:06 blymn Exp $");
 #endif				/* not lint */
 
 #include <stdlib.h>
@@ -163,7 +163,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t 
 	lp = &win->alines[y]->line[x];
 	lnp = win->alines[y];
 
-	cw = WCOL(*lp);
+	cw = (*lp).wcols;
 	if (cw >= 0) {
 		sx = x;
 	} else {
@@ -174,7 +174,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t 
 				if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
 					return ERR;
 				tp->attr = win->battr;
-				SET_WCOL(*tp, 1);
+				(*tp).wcols = 1;
 				np = tp->nsp;
 			}
 		} else {
@@ -211,7 +211,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t 
 					    == ERR)
 						return ERR;
 					lp->attr = win->battr;
-					SET_WCOL(*lp, 1);
+					(*lp).wcols = 1;
 					lp++, ex++;
 				}
 				ex = win->maxx - 1;
@@ -230,7 +230,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t 
 			}
 			lp->ch = chp->vals[0];
 			lp->attr = chp->attributes & WA_ATTRIBUTES;
-			SET_WCOL(*lp, cw);
+			(*lp).wcols = cw;
 			if (chp->elements > 1) {
 				for (i = 1; i < chp->elements; i++) {
 					np = (nschar_t *)
@@ -258,7 +258,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t 
 				}
 				lp->ch = chp->vals[0];
 				lp->attr = chp->attributes & WA_ATTRIBUTES;
-				SET_WCOL(*lp, x - ex);
+				(*lp).wcols = x - ex;
 				lp++, ex++;
 			}
 		} else {

Index: src/lib/libcurses/addbytes.c
diff -u src/lib/libcurses/addbytes.c:1.60 src/lib/libcurses/addbytes.c:1.61
--- src/lib/libcurses/addbytes.c:1.60	Sun Jan 16 10:30:45 2022
+++ src/lib/libcurses/addbytes.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: addbytes.c,v 1.60 2022/01/16 10:30:45 rillig Exp $	*/
+/*	$NetBSD: addbytes.c,v 1.61 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1987, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)addbytes.c	8.4 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: addbytes.c,v 1.60 2022/01/16 10:30:45 rillig Exp $");
+__RCSID("$NetBSD: addbytes.c,v 1.61 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -203,7 +203,7 @@ _cursesi_addbyte(WINDOW *win, __LINE **l
 {
 	static char	 blank[] = " ";
 	int		 tabsize;
-	int		 newx, i;
+	int		 newx, i, wcols;
 	attr_t		 attributes;
 
 	if (char_interp) {
@@ -275,6 +275,11 @@ _cursesi_addbyte(WINDOW *win, __LINE **l
 	else if (win->wattr & __COLOR)
 		attributes |= win->wattr & __COLOR;
 
+
+	wcols = wcwidth(c);
+	if (wcols < 0)
+		wcols = 1;
+
 	/*
 	 * Always update the change pointers.  Otherwise,
 	 * we could end up not displaying 'blank' characters
@@ -294,10 +299,17 @@ _cursesi_addbyte(WINDOW *win, __LINE **l
 	    *(*lp)->firstchp, *(*lp)->lastchp,
 	    *(*lp)->firstchp - win->ch_off,
 	    *(*lp)->lastchp - win->ch_off);
-	if (win->bch != ' ' && c == ' ')
+	if (win->bch != ' ' && c == ' ') {
 		(*lp)->line[*x].ch = win->bch;
-	else
+#ifdef HAVE_CHAR
+		(*lp)->line[*x].wcols = win->wcols;
+#endif
+	} else {
 		(*lp)->line[*x].ch = c;
+#ifdef HAVE_CHAR
+		(*lp)->line[*x].wcols = wcols;
+#endif
+	}
 
 	if (attributes & __COLOR)
 		(*lp)->line[*x].attr =
@@ -391,7 +403,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 		__CTRACE(__CTRACE_INPUT,
 		    "_cursesi_addwchar: char '%c' is non-spacing\n",
 		    wch->vals[0]);
-		cw = WCOL(*lp);
+		cw = (*lp).wcols;
 		if (cw < 0) {
 			lp += cw;
 			*x += cw;
@@ -427,7 +439,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 		lp = &win->alines[*y]->line[*x];
 	}
 	/* clear out the current character */
-	cw = WCOL(*lp);
+	cw = (*lp).wcols;
 	if (cw >= 0) {
 		sx = *x;
 	} else {
@@ -441,7 +453,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 				return ERR;
 
 			tp->attr = win->battr;
-			SET_WCOL(*tp, 1);
+			tp->wcols = win->wcols;
 		}
 		sx = *x + cw;
 		(*lnp)->flags |= __ISDIRTY;
@@ -473,7 +485,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 			if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
 				return ERR;
 			tp->attr = win->battr;
-			SET_WCOL(*tp, 1);
+			tp->wcols = win->wcols;
 		}
 		newx = win->maxx - 1 + win->ch_off;
 		if (newx > *(*lnp)->lastchp)
@@ -513,11 +525,11 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 	else
 		lp->attr = attributes | win->battr;
 
-	SET_WCOL(*lp, cw);
+	lp->wcols = cw;
 
 	__CTRACE(__CTRACE_INPUT,
-	    "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x\n",
-	    lp->ch, lp->attr);
+	    "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x, width %d\n",
+	    lp->ch, lp->attr, lp->wcols);
 
 	if (wch->elements > 1) {
 		for (i = 1; i < wch->elements; i++) {
@@ -547,10 +559,11 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 		tp->ch = wch->vals[0];
 		tp->attr = lp->attr & WA_ATTRIBUTES;
 		/* Mark as "continuation" cell */
-		tp->attr |= __WCWIDTH;
+		tp->wflags |= WCA_CONTINUATION;
 	}
 
-	if (*x == win->maxx) {
+
+	if (*x >= win->maxx) {
 		__CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: do line wrap\n");
 		if (*y == win->scr_b) {
 			__CTRACE(__CTRACE_INPUT,
@@ -577,7 +590,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 		if (*x && *x < win->maxx) {
 			ex = sx + cw;
 			tp = &win->alines[*y]->line[ex];
-			while (ex < win->maxx && WCOL(*tp) < 0) {
+			while (ex < win->maxx && tp->wcols < 0) {
 				__CTRACE(__CTRACE_INPUT,
 				    "_cursesi_addwchar: clear "
 				    "remaining of current char (%d,%d)nn",
@@ -586,7 +599,7 @@ _cursesi_addwchar(WINDOW *win, __LINE **
 				if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
 					return ERR;
 				tp->attr = win->battr;
-				SET_WCOL(*tp, 1);
+				tp->wcols = win->wcols;
 				tp++, ex++;
 			}
 			newx = ex - 1 + win->ch_off;

Index: src/lib/libcurses/background.c
diff -u src/lib/libcurses/background.c:1.27 src/lib/libcurses/background.c:1.28
--- src/lib/libcurses/background.c:1.27	Mon Sep  6 07:45:48 2021
+++ src/lib/libcurses/background.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: background.c,v 1.27 2021/09/06 07:45:48 rin Exp $	*/
+/*	$NetBSD: background.c,v 1.28 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: background.c,v 1.27 2021/09/06 07:45:48 rin Exp $");
+__RCSID("$NetBSD: background.c,v 1.28 2022/01/25 03:05:06 blymn Exp $");
 #endif				/* not lint */
 
 #include <stdlib.h>
@@ -106,7 +106,7 @@ wbkgd(WINDOW *win, chtype ch)
 			/* Update/merge attributes */
 			cp->attr = win->battr | (cp->attr & __ALTCHARSET);
 #ifdef HAVE_WCHAR
-			SET_WCOL(*cp, 1);
+			cp->wcols = 1;
 #endif
 		}
 	}
@@ -215,7 +215,7 @@ wbkgrndset(WINDOW *win, const cchar_t *w
 	if (__using_color && !( battr & __COLOR))
 		battr |= __default_color;
 	win->battr = battr;
-	SET_BGWCOL((*win), 1);
+	win->wcols = 1;
 }
 
 
Index: src/lib/libcurses/clrtobot.c
diff -u src/lib/libcurses/clrtobot.c:1.27 src/lib/libcurses/clrtobot.c:1.28
--- src/lib/libcurses/clrtobot.c:1.27	Sun Mar 15 01:18:43 2020
+++ src/lib/libcurses/clrtobot.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: clrtobot.c,v 1.27 2020/03/15 01:18:43 uwe Exp $	*/
+/*	$NetBSD: clrtobot.c,v 1.28 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)clrtobot.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: clrtobot.c,v 1.27 2020/03/15 01:18:43 uwe Exp $");
+__RCSID("$NetBSD: clrtobot.c,v 1.28 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -105,7 +105,7 @@ wclrtobot(WINDOW *win)
 #ifdef HAVE_WCHAR
 			if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
 				return ERR;
-			SET_WCOL(*sp, 1);
+			sp->wcols = 1;
 #endif
 		}
 

Index: src/lib/libcurses/border.c
diff -u src/lib/libcurses/border.c:1.21 src/lib/libcurses/border.c:1.22
--- src/lib/libcurses/border.c:1.21	Tue Oct 19 06:41:03 2021
+++ src/lib/libcurses/border.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: border.c,v 1.21 2021/10/19 06:41:03 blymn Exp $	*/
+/*	$NetBSD: border.c,v 1.22 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: border.c,v 1.21 2021/10/19 06:41:03 blymn Exp $");
+__RCSID("$NetBSD: border.c,v 1.22 2022/01/25 03:05:06 blymn Exp $");
 #endif				/* not lint */
 
 #include <stdlib.h>
@@ -312,9 +312,9 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[i]->line[j].nsp = NULL;
 			}
 			if (j)
-				SET_WCOL(win->alines[i]->line[j], -j);
+				win->alines[i]->line[j].wcols = -j;
 			else {
-				SET_WCOL(win->alines[i]->line[j], cw);
+				win->alines[i]->line[j].wcols = cw;
 				if (left.elements > 1) {
 					for (k = 1; k < left.elements; k++) {
 						np = malloc(sizeof(nschar_t));
@@ -328,20 +328,20 @@ int wborder_set(WINDOW *win, const cchar
 				}
 			}
 		}
-		for (j = cw; WCOL(win->alines[i]->line[j]) < 0; j++) {
+		for (j = cw; win->alines[i]->line[j].wcols < 0; j++) {
 			__CTRACE(__CTRACE_INPUT,
 			    "wborder_set: clean out partial char[%d]", j);
 			win->alines[i]->line[j].ch = ( wchar_t )btowc(win->bch);
 			if (_cursesi_copy_nsp(win->bnsp,
 					      &win->alines[i]->line[j]) == ERR)
 				return ERR;
-			SET_WCOL(win->alines[i]->line[j], 1);
+			win->alines[i]->line[j].wcols = 1;
 		}
 		/* right border */
 		cw = wcwidth(right.vals[0]);
 		if (cw < 0)
 			cw = 1;
-		pcw = WCOL( win->alines[i]->line[endx - cw]);
+		pcw = win->alines[i]->line[endx - cw].wcols;
 		for ( j = endx - cw + 1; j <= endx; j++ ) {
 			win->alines[i]->line[j].ch = right.vals[0];
 			win->alines[i]->line[j].attr = right.attributes;
@@ -355,7 +355,7 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[i]->line[j].nsp = NULL;
 			}
 			if (j == endx - cw + 1) {
-				SET_WCOL(win->alines[i]->line[j], cw);
+				win->alines[i]->line[j].wcols = cw;
 				if (right.elements > 1) {
 					for (k = 1; k < right.elements; k++) {
 						np = malloc(sizeof(nschar_t));
@@ -368,8 +368,8 @@ int wborder_set(WINDOW *win, const cchar
 					}
 				}
 			} else
-				SET_WCOL(win->alines[i]->line[j],
-					 endx - cw + 1 - j);
+				win->alines[i]->line[j].wcols =
+				    endx - cw + 1 - j;
 		}
 		if (pcw != 1) {
 			__CTRACE(__CTRACE_INPUT,
@@ -383,7 +383,7 @@ int wborder_set(WINDOW *win, const cchar
 					       &win->alines[i]->line[j]) == ERR)
 					return ERR;
 				win->alines[i]->line[j].attr = win->battr;
-				SET_WCOL(win->alines[i]->line[j], 1);
+				win->alines[i]->line[j].wcols = 1;
 			}
 		}
 	}
@@ -417,9 +417,9 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[0]->line[i + j].nsp = NULL;
 			}
 			if (j)
-				SET_WCOL(win->alines[ 0 ]->line[ i + j ], -j);
+				win->alines[ 0 ]->line[ i + j ].wcols = -j;
 			else {
-				SET_WCOL(win->alines[ 0 ]->line[ i + j ], cw);
+				win->alines[ 0 ]->line[ i + j ].wcols = cw;
 				if ( top.elements > 1 ) {
 					for (k = 1; k < top.elements; k++) {
 						np = malloc(sizeof(nschar_t));
@@ -441,7 +441,7 @@ int wborder_set(WINDOW *win, const cchar
 				      &win->alines[0]->line[i]) == ERR)
 			return ERR;
 		win->alines[0]->line[i].attr = win->battr;
-		SET_WCOL(win->alines[0]->line[i], 1);
+		win->alines[0]->line[i].wcols = 1;
 		i++;
 	}
 	/* lower border */
@@ -459,9 +459,9 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[endy]->line[i + j].nsp = NULL;
 			}
 			if (j)
-				SET_WCOL(win->alines[endy]->line[i + j], -j);
+				win->alines[endy]->line[i + j].wcols = -j;
 			else {
-				SET_WCOL(win->alines[endy]->line[i + j], cw);
+				win->alines[endy]->line[i + j].wcols = cw;
 				if (bottom.elements > 1) {
 					for (k = 1; k < bottom.elements; k++) {
 						np = malloc(sizeof(nschar_t));
@@ -481,7 +481,7 @@ int wborder_set(WINDOW *win, const cchar
 				      &win->alines[endy]->line[i]) == ERR)
 			return ERR;
 		win->alines[endy]->line[i].attr = win->battr;
-		SET_WCOL(win->alines[endy]->line[ i ], 1);
+		win->alines[endy]->line[i].wcols = 1;
 		i++;
 	}
 
@@ -501,9 +501,9 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[0]->line[i].nsp = NULL;
 			}
 			if (i)
-				SET_WCOL(win->alines[0]->line[i], -i);
+				win->alines[0]->line[i].wcols = -i;
 			else {
-				SET_WCOL(win->alines[0]->line[i], tlcw);
+				win->alines[0]->line[i].wcols = tlcw;
 				if (topleft.elements > 1) {
 					for (k = 1; k < topleft.elements; k++)
 					{
@@ -530,7 +530,7 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[0]->line[i].nsp = NULL;
 			}
 			if (i == endx - trcw + 1) {
-				SET_WCOL(win->alines[0]->line[i], trcw);
+				win->alines[0]->line[i].wcols = trcw;
 				if (topright.elements > 1) {
 					for (k = 1; k < topright.elements;k ++)
 					{
@@ -543,8 +543,8 @@ int wborder_set(WINDOW *win, const cchar
 					}
 				}
 			} else
-				SET_WCOL(win->alines[0]->line[i],
-					 endx - trcw + 1 - i);
+				win->alines[0]->line[i].wcols =
+				    endx - trcw + 1 - i;
 		}
 		for (i = 0; i < blcw; i++) {
 			win->alines[endy]->line[i].ch = botleft.vals[0];
@@ -559,9 +559,9 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[endy]->line[i].nsp = NULL;
 			}
 			if (i)
-				SET_WCOL(win->alines[endy]->line[i], -i);
+				win->alines[endy]->line[i].wcols = -i;
 			else {
-				SET_WCOL(win->alines[endy]->line[i], blcw);
+				win->alines[endy]->line[i].wcols = blcw;
 				if (botleft.elements > 1) {
 					for (k = 1; k < botleft.elements; k++) {
 						np = malloc(sizeof(nschar_t));
@@ -587,7 +587,7 @@ int wborder_set(WINDOW *win, const cchar
 				win->alines[endy]->line[i].nsp = NULL;
 			}
 			if (i == endx - brcw + 1) {
-				SET_WCOL(win->alines[endy]->line[i], brcw);
+				win->alines[endy]->line[i].wcols = brcw;
 				if (botright.elements > 1) {
 					for (k = 1; k < botright.elements; k++){
 						np = malloc(sizeof(nschar_t));
@@ -599,8 +599,8 @@ int wborder_set(WINDOW *win, const cchar
 					}
 				}
 			} else
-				SET_WCOL(win->alines[endy]->line[i],
-					 endx - brcw + 1 - i);
+				win->alines[endy]->line[i].wcols =
+				    endx - brcw + 1 - i;
 		}
 	}
 	__touchwin(win);
Index: src/lib/libcurses/ins_wstr.c
diff -u src/lib/libcurses/ins_wstr.c:1.21 src/lib/libcurses/ins_wstr.c:1.22
--- src/lib/libcurses/ins_wstr.c:1.21	Sun Jan 16 10:30:45 2022
+++ src/lib/libcurses/ins_wstr.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: ins_wstr.c,v 1.21 2022/01/16 10:30:45 rillig Exp $ */
+/*   $NetBSD: ins_wstr.c,v 1.22 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ins_wstr.c,v 1.21 2022/01/16 10:30:45 rillig Exp $");
+__RCSID("$NetBSD: ins_wstr.c,v 1.22 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include <string.h>
@@ -280,13 +280,13 @@ loopdone:
 		start = &win->alines[y]->line[x];
 		sx = x;
 		lnp = win->alines[y];
-		pcw = WCOL(*start);
+		pcw = start->wcols;
 		if (pcw < 0) {
 			sx += pcw;
 			start += pcw;
 		}
 		__CTRACE(__CTRACE_INPUT, "wins_nwstr: start@(%d)\n", sx);
-		pcw = WCOL(*start);
+		pcw = start->wcols;
 		lnp->flags |= __ISDIRTY;
 		newx = sx + win->ch_off;
 		if (newx < *lnp->firstchp)
@@ -310,7 +310,7 @@ loopdone:
 			__CTRACE(__CTRACE_INPUT, "wins_nwstr: shift all characters by %d\n", width);
 			temp1 = &win->alines[y]->line[win->maxx - 1];
 			temp2 = temp1 - width;
-			pcw = WCOL(*(temp2 + 1));
+			pcw = (temp2 + 1)->wcols;
 			if (pcw < 0) {
 				__CTRACE(__CTRACE_INPUT,
 				    "wins_nwstr: clear from %d to EOL(%d)\n",
@@ -323,7 +323,7 @@ loopdone:
 						return ERR;
 					}
 					temp1->attr = win->battr;
-					SET_WCOL(*temp1, 1);
+					temp1->wcols = 1;
 					__CTRACE(__CTRACE_INPUT,
 					    "wins_nwstr: empty cell(%p)\n", temp1);
 					temp1--;

Index: src/lib/libcurses/clrtoeol.c
diff -u src/lib/libcurses/clrtoeol.c:1.32 src/lib/libcurses/clrtoeol.c:1.33
--- src/lib/libcurses/clrtoeol.c:1.32	Mon Sep  6 07:03:49 2021
+++ src/lib/libcurses/clrtoeol.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: clrtoeol.c,v 1.32 2021/09/06 07:03:49 rin Exp $	*/
+/*	$NetBSD: clrtoeol.c,v 1.33 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)clrtoeol.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: clrtoeol.c,v 1.32 2021/09/06 07:03:49 rin Exp $");
+__RCSID("$NetBSD: clrtoeol.c,v 1.33 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -107,7 +107,7 @@ wclrtoeol(WINDOW *win)
 #ifdef HAVE_WCHAR
 		if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
 			return ERR;
-		SET_WCOL(*sp, 1);
+		sp->wcols = 1;
 #endif
 	}
 

Index: src/lib/libcurses/cr_put.c
diff -u src/lib/libcurses/cr_put.c:1.37 src/lib/libcurses/cr_put.c:1.38
--- src/lib/libcurses/cr_put.c:1.37	Mon Sep  6 07:45:48 2021
+++ src/lib/libcurses/cr_put.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: cr_put.c,v 1.37 2021/09/06 07:45:48 rin Exp $	*/
+/*	$NetBSD: cr_put.c,v 1.38 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -30,11 +30,13 @@
  */
 
 #include <sys/cdefs.h>
+#include <limits.h>
+#include <stdlib.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)cr_put.c	8.3 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: cr_put.c,v 1.37 2021/09/06 07:45:48 rin Exp $");
+__RCSID("$NetBSD: cr_put.c,v 1.38 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -188,18 +190,29 @@ fgoto(int in_refresh)
  * Otherwise just use cursor motions, hacking use of tabs and overtabbing
  * and backspace.
  *
- * XXX this needs to be revisited for wide characters since we may output
- * XXX more than one byte for a character.
  */
 
 static int plodcnt, plodflg;
+#ifdef HAVE_WCHAR
+static char s[MB_LEN_MAX];
+#endif
 
 static int
 plodput(int c)
 {
-	if (plodflg)
-		--plodcnt;
-	else
+	if (plodflg) {
+		int cw;
+
+#ifdef HAVE_WCHAR
+		cw = wctomb(s, c);
+		if (cw < 0)
+			cw = 1;
+#else
+		cw = 1;
+#endif /* HAVE_WCHAR */
+
+		plodcnt -= cw;
+	} else
 		__cputchar(c);
 	return 0;
 }
@@ -404,6 +417,21 @@ dontcr:while (outline < destline) {
 			}
 		}
 	}
+
+#ifdef HAVE_WCHAR
+	/*
+	 * If destcol is halfway through a multicolumn
+	 * wide char, we have no chance of plodding.
+	 */
+	k = outcol - destcol;
+	if (k < 0)
+		k = -k;
+	if ((k != 0) && (curscr->alines[outline]->line[outcol].wcols > k)) {
+		plodcnt = -1;
+		goto out;
+	}
+#endif /* HAVE_WCHAR */
+
 	while (outcol < destcol) {
 		/*
 		 * Move one char to the right.  We don't use nd space because
@@ -423,17 +451,17 @@ dontcr:while (outline < destline) {
 				if ((curscr->alines[outline]->line[outcol].attr
 				    & WA_ATTRIBUTES)
 				    == curscr->wattr) {
-					switch (WCOL(curscr->alines[outline]->line[outcol])) {
+					switch (curscr->alines[outline]->line[outcol].wcols) {
 					case 1:
 						__cputwchar(curscr->alines[outline]->line[outcol].ch);
 						__cursesi_putnsp(curscr->alines[outline]->line[outcol].nsp,
 								outline,
 								outcol);
 						__CTRACE(__CTRACE_OUTPUT,
-						    "plod: (%d,%d)WCOL(%d), "
+						    "plod: (%d,%d)wcols(%d), "
 						    "putwchar(%x)\n",
 						    outline, outcol,
-						    WCOL(curscr->alines[outline]->line[outcol]),
+						    curscr->alines[outline]->line[outcol].wcols,
 						    curscr->alines[outline]->line[outcol].ch);
 					/*FALLTHROUGH*/
 					case 0:

Index: src/lib/libcurses/curses_private.h
diff -u src/lib/libcurses/curses_private.h:1.76 src/lib/libcurses/curses_private.h:1.77
--- src/lib/libcurses/curses_private.h:1.76	Tue Sep  7 01:23:09 2021
+++ src/lib/libcurses/curses_private.h	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: curses_private.h,v 1.76 2021/09/07 01:23:09 rin Exp $	*/
+/*	$NetBSD: curses_private.h,v 1.77 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*-
  * Copyright (c) 1998-2000 Brett Lymn
@@ -72,23 +72,12 @@ struct __ldata {
 	attr_t	attr;			/* Attributes */
 #ifdef HAVE_WCHAR
 	nschar_t	*nsp;	/* Foreground non-spacing character pointer */
+#define WCA_CONTINUATION	0x0001	/* a continuation cell */
+	int16_t		wflags;		/* internal attributes for wide char */
+	int16_t		wcols;		/* display width of a wide char */
 #endif /* HAVE_WCHAR */
 };
 
-#ifdef HAVE_WCHAR
-/* macros to extract the width of a wide character */
-#define __WCWIDTH 0xfc000000
-#define WCW_SHIFT 26
-#define WCOL(wc) ((((unsigned) (wc).attr) >> WCW_SHIFT ) > MB_LEN_MAX ? ((int)(((unsigned) (wc).attr ) >> WCW_SHIFT )) - 64 : ((int)(((unsigned) (wc).attr ) >> WCW_SHIFT)))
-#define SET_WCOL(c, w) do { 						\
-	((c).attr) = ((((c).attr) & WA_ATTRIBUTES ) | ((w) << WCW_SHIFT )); \
-} while(/*CONSTCOND*/0)
-#define BGWCOL(wc) ((((wc).battr) >> WCW_SHIFT ) > MB_LEN_MAX ? (((wc).battr ) >> WCW_SHIFT ) - 64 : (((wc).battr ) >> WCW_SHIFT ))
-#define SET_BGWCOL(c, w) do { 						\
-	((c).battr) = ((((c).battr) & WA_ATTRIBUTES ) | ((w) << WCW_SHIFT )); \
-} while(/*CONSTCOND*/0)
-#endif /* HAVE_WCHAR */
-
 #define __LDATASIZE	(sizeof(__LDATA))
 
 struct __line {
@@ -139,6 +128,7 @@ struct __window {		/* Window structure. 
 	attr_t	wattr;			/* Character attributes */
 	wchar_t	bch;			/* Background character */
 	attr_t	battr;			/* Background attributes */
+	uint32_t wcols;			/* Background column width */
 	int	scr_t, scr_b;		/* Scrolling region top, bottom */
 	SCREEN	*screen;		/* Screen for this window */
 	int	pbegy, pbegx,
@@ -299,15 +289,8 @@ struct __screen {
 	bool		 slk_hidden;
 	struct __slk_label *slk_labels;
 
-/*
- * XXX: This conflicts with the value in <limits.h> (32)
- * which should be used here instead of defining a different value,
- * but I am not changing it because it is also used in the WCOL()
- * macro and I don't understand the effects of it.
- */
-#define MB_LEN_MAX 8
+#define MAX_CBUF_SIZE 8
 #ifdef HAVE_WCHAR
-#define MAX_CBUF_SIZE MB_LEN_MAX
 	int		cbuf_head;		/* header to cbuf */
 	int		cbuf_tail;		/* tail to cbuf */
 	int		cbuf_cur;		/* the current char in cbuf */
@@ -351,7 +334,7 @@ void	 __CTRACE(int, const char *, ...) _
 	((_sp)->ch != (_bch) ||					\
 	    ((_sp)->attr & WA_ATTRIBUTES) != (_battr) ||	\
 	    (_sp)->nsp != NULL ||				\
-	    WCOL(*_sp) < 0)
+	    (_sp)->wcols < 0)
 #else
 #define __NEED_ERASE(_sp, _bch, _battr)				\
 	((_sp)->ch != (_bch) || (_sp)->attr != (_battr))
@@ -442,4 +425,5 @@ extern int		 __noqch;
 extern attr_t		 __mask_op, __mask_me, __mask_ue, __mask_se;
 extern WINDOW		*__virtscr;
 extern int		 __using_color;
+extern int		 __do_color_init;
 extern attr_t		 __default_color;

Index: src/lib/libcurses/delch.c
diff -u src/lib/libcurses/delch.c:1.26 src/lib/libcurses/delch.c:1.27
--- src/lib/libcurses/delch.c:1.26	Sun Jun  9 07:40:14 2019
+++ src/lib/libcurses/delch.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: delch.c,v 1.26 2019/06/09 07:40:14 blymn Exp $	*/
+/*	$NetBSD: delch.c,v 1.27 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)delch.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: delch.c,v 1.26 2019/06/09 07:40:14 blymn Exp $");
+__RCSID("$NetBSD: delch.c,v 1.27 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -111,11 +111,11 @@ wdelch(WINDOW *win)
 	end = &win->alines[win->cury]->line[win->maxx - 1];
 	sx = win->curx;
 	temp1 = &win->alines[win->cury]->line[win->curx];
-	cw = WCOL(*temp1);
+	cw = temp1->wcols;
 	if (cw < 0) {
 		temp1 += cw;
 		sx += cw;
-		cw = WCOL(*temp1);
+		cw = temp1->wcols;
 	}
 	np = temp1->nsp;
 	if (np) {
@@ -138,7 +138,7 @@ wdelch(WINDOW *win)
 		temp1->attr = 0;
 		if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR)
 			return ERR;
-		SET_WCOL(*temp1, 1);
+		temp1->wcols = 1;
 		temp1++;
 	}
 	__touchline(win, (int)win->cury, sx, (int)win->maxx - 1);
Index: src/lib/libcurses/insch.c
diff -u src/lib/libcurses/insch.c:1.26 src/lib/libcurses/insch.c:1.27
--- src/lib/libcurses/insch.c:1.26	Mon Jul  6 22:46:50 2020
+++ src/lib/libcurses/insch.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: insch.c,v 1.26 2020/07/06 22:46:50 uwe Exp $	*/
+/*	$NetBSD: insch.c,v 1.27 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)insch.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: insch.c,v 1.26 2020/07/06 22:46:50 uwe Exp $");
+__RCSID("$NetBSD: insch.c,v 1.27 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -116,7 +116,7 @@ winsch(WINDOW *win, chtype ch)
 #ifdef HAVE_WCHAR
 	if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR)
 		return ERR;
-	SET_WCOL(*temp1, 1);
+	temp1->wcols = 1;
 #endif /* HAVE_WCHAR */
 	__touchline(win, (int)win->cury, (int)win->curx, (int)win->maxx - 1);
 	if (win->cury == LINES - 1 &&

Index: src/lib/libcurses/erase.c
diff -u src/lib/libcurses/erase.c:1.33 src/lib/libcurses/erase.c:1.34
--- src/lib/libcurses/erase.c:1.33	Mon Sep  6 07:03:49 2021
+++ src/lib/libcurses/erase.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: erase.c,v 1.33 2021/09/06 07:03:49 rin Exp $	*/
+/*	$NetBSD: erase.c,v 1.34 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)erase.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: erase.c,v 1.33 2021/09/06 07:03:49 rin Exp $");
+__RCSID("$NetBSD: erase.c,v 1.34 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -92,7 +92,7 @@ werase(WINDOW *win)
 #ifdef HAVE_WCHAR
 			if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
 				return ERR;
-			SET_WCOL(*sp, 1);
+			sp->wcols = 1;
 #endif
 		}
 	}
Index: src/lib/libcurses/resize.c
diff -u src/lib/libcurses/resize.c:1.33 src/lib/libcurses/resize.c:1.34
--- src/lib/libcurses/resize.c:1.33	Tue Sep  7 01:23:09 2021
+++ src/lib/libcurses/resize.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: resize.c,v 1.33 2021/09/07 01:23:09 rin Exp $	*/
+/*	$NetBSD: resize.c,v 1.34 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 2001
@@ -33,7 +33,7 @@
 #if 0
 static char sccsid[] = "@(#)resize.c   blymn 2001/08/26";
 #else
-__RCSID("$NetBSD: resize.c,v 1.33 2021/09/07 01:23:09 rin Exp $");
+__RCSID("$NetBSD: resize.c,v 1.34 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -357,7 +357,7 @@ __resizewin(WINDOW *win, int nlines, int
 			sp->nsp = NULL;
 			if (_cursesi_copy_nsp(win->bnsp, sp) == ERR)
 				return ERR;
-			SET_WCOL(*sp, 1);
+			sp->wcols = 1;
 #endif /* HAVE_WCHAR */
 		}
 		lp->hash = __hash_line(lp->line, ncols);

Index: src/lib/libcurses/in_wch.c
diff -u src/lib/libcurses/in_wch.c:1.7 src/lib/libcurses/in_wch.c:1.8
--- src/lib/libcurses/in_wch.c:1.7	Sun Jun  9 07:40:14 2019
+++ src/lib/libcurses/in_wch.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: in_wch.c,v 1.7 2019/06/09 07:40:14 blymn Exp $ */
+/*   $NetBSD: in_wch.c,v 1.8 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: in_wch.c,v 1.7 2019/06/09 07:40:14 blymn Exp $");
+__RCSID("$NetBSD: in_wch.c,v 1.8 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include "curses.h"
@@ -84,7 +84,7 @@ win_wch(WINDOW *win, cchar_t *wcval)
 {
 	nschar_t *np;
 	__LDATA *lp = &win->alines[win->cury]->line[win->curx];
-	int cw = WCOL(*lp);
+	int cw = lp->wcols;
 
 	if (cw < 0)
 		lp += cw;

Index: src/lib/libcurses/in_wchstr.c
diff -u src/lib/libcurses/in_wchstr.c:1.9 src/lib/libcurses/in_wchstr.c:1.10
--- src/lib/libcurses/in_wchstr.c:1.9	Sun Aug 15 15:12:36 2021
+++ src/lib/libcurses/in_wchstr.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: in_wchstr.c,v 1.9 2021/08/15 15:12:36 rillig Exp $ */
+/*   $NetBSD: in_wchstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: in_wchstr.c,v 1.9 2021/08/15 15:12:36 rillig Exp $");
+__RCSID("$NetBSD: in_wchstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include "curses.h"
@@ -132,7 +132,7 @@ win_wchnstr(WINDOW *win, cchar_t *wchstr
 
 	start = &win->alines[win->cury]->line[win->curx];
 	x = win->curx;
-	cw = WCOL(*start);
+	cw = start->wcols;
 	if (cw < 0) {
 		start += cw;
 		x += cw;
@@ -140,7 +140,7 @@ win_wchnstr(WINDOW *win, cchar_t *wchstr
 	wcp = wchstr;
 	/* (n - 1) to leave room for the trailing 0 element */
 	while ((x < win->maxx) && ((n < 0) || ((n > 1) && (cnt < n - 1)))) {
-		cw = WCOL(*start);
+		cw = start->wcols;
 		wcp->vals[0] = start->ch;
 		wcp->attributes = start->attr;
 		wcp->elements = 1;
Index: src/lib/libcurses/insstr.c
diff -u src/lib/libcurses/insstr.c:1.9 src/lib/libcurses/insstr.c:1.10
--- src/lib/libcurses/insstr.c:1.9	Mon Sep  6 07:03:49 2021
+++ src/lib/libcurses/insstr.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: insstr.c,v 1.9 2021/09/06 07:03:49 rin Exp $ */
+/*   $NetBSD: insstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: insstr.c,v 1.9 2021/09/06 07:03:49 rin Exp $");
+__RCSID("$NetBSD: insstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include <string.h>
@@ -187,7 +187,7 @@ winsnstr(WINDOW *win, const char *str, i
 		temp1->ch = (wchar_t)*scp & __CHARTEXT;
 		temp1->attr = win->wattr;
 #ifdef HAVE_WCHAR
-		SET_WCOL(*temp1, 1);
+		temp1->wcols = 1;
 #endif /* HAVE_WCHAR */
 	}
 #ifdef DEBUG
Index: src/lib/libcurses/inwstr.c
diff -u src/lib/libcurses/inwstr.c:1.9 src/lib/libcurses/inwstr.c:1.10
--- src/lib/libcurses/inwstr.c:1.9	Sun Aug 15 15:12:36 2021
+++ src/lib/libcurses/inwstr.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: inwstr.c,v 1.9 2021/08/15 15:12:36 rillig Exp $ */
+/*   $NetBSD: inwstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: inwstr.c,v 1.9 2021/08/15 15:12:36 rillig Exp $");
+__RCSID("$NetBSD: inwstr.c,v 1.10 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include "curses.h"
@@ -136,7 +136,7 @@ winnwstr(WINDOW *win, wchar_t *wstr, int
 
 	start = &win->alines[win->cury]->line[win->curx];
 	x = win->curx;
-	cw = WCOL(*start);
+	cw = start->wcols;
 	if (cw < 0) {
 		start += cw;
 		x += cw;
@@ -145,7 +145,7 @@ winnwstr(WINDOW *win, wchar_t *wstr, int
 	wcp = wstr;
 	/* (n - 1) to leave room for the trailing 0 element */
 	while ((x < win->maxx) && ((n < 0) || ((n > 1) && (cnt < n - 1)))) {
-		cw = WCOL(*start);
+		cw = start->wcols;
 		*wcp = start->ch;
 		wcp++;
 		cnt++;

Index: src/lib/libcurses/ins_wch.c
diff -u src/lib/libcurses/ins_wch.c:1.17 src/lib/libcurses/ins_wch.c:1.18
--- src/lib/libcurses/ins_wch.c:1.17	Mon Sep  6 07:03:49 2021
+++ src/lib/libcurses/ins_wch.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*   $NetBSD: ins_wch.c,v 1.17 2021/09/06 07:03:49 rin Exp $ */
+/*   $NetBSD: ins_wch.c,v 1.18 2022/01/25 03:05:06 blymn Exp $ */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation Inc.
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ins_wch.c,v 1.17 2021/09/06 07:03:49 rin Exp $");
+__RCSID("$NetBSD: ins_wch.c,v 1.18 2022/01/25 03:05:06 blymn Exp $");
 #endif						  /* not lint */
 
 #include <string.h>
@@ -134,7 +134,7 @@ wins_wch(WINDOW *win, const cchar_t *wch
 	lnp = win->alines[y];
 	start = &win->alines[y]->line[x];
 	sx = x;
-	pcw = WCOL(*start);
+	pcw = start->wcols;
 	if (pcw < 0) {
 		start += pcw;
 		sx += pcw;
@@ -150,7 +150,7 @@ wins_wch(WINDOW *win, const cchar_t *wch
 	__CTRACE(__CTRACE_INPUT, "wins_wch: shift all characters\n");
 	temp1 = &win->alines[y]->line[win->maxx - 1];
 	temp2 = temp1 - cw;
-	pcw = WCOL(*(temp2 + 1));
+	pcw = (temp2 + 1)->wcols;
 	if (pcw < 0) {
 		__CTRACE(__CTRACE_INPUT, "wins_wch: clear EOL\n");
 		temp2 += pcw;
@@ -168,7 +168,7 @@ wins_wch(WINDOW *win, const cchar_t *wch
 			if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR)
 				return ERR;
 			temp1->attr = win->battr;
-			SET_WCOL(*temp1, 1);
+			temp1->wcols = 1;
 			temp1--;
 		}
 	}
@@ -181,7 +181,7 @@ wins_wch(WINDOW *win, const cchar_t *wch
 	start->nsp = NULL;
 	start->ch = wch->vals[0];
 	start->attr = wch->attributes & WA_ATTRIBUTES;
-	SET_WCOL(*start, cw);
+	start->wcols = cw;
 	if (wch->elements > 1) {
 		for (i = 1; i < wch->elements; i++) {
 			np = malloc(sizeof(nschar_t));
@@ -198,7 +198,7 @@ wins_wch(WINDOW *win, const cchar_t *wch
 	ex = x + 1;
 	while (ex - x < cw) {
 		temp1->ch = wch->vals[0];
-		SET_WCOL(*temp1, x - ex);
+		temp1->wcols = x - ex;
 		temp1->nsp = NULL;
 		ex++, temp1++;
 	}

Index: src/lib/libcurses/insdelln.c
diff -u src/lib/libcurses/insdelln.c:1.19 src/lib/libcurses/insdelln.c:1.20
--- src/lib/libcurses/insdelln.c:1.19	Mon Sep  6 07:03:49 2021
+++ src/lib/libcurses/insdelln.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: insdelln.c,v 1.19 2021/09/06 07:03:49 rin Exp $	*/
+/*	$NetBSD: insdelln.c,v 1.20 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: insdelln.c,v 1.19 2021/09/06 07:03:49 rin Exp $");
+__RCSID("$NetBSD: insdelln.c,v 1.20 2022/01/25 03:05:06 blymn Exp $");
 #endif				/* not lint */
 
 /*
@@ -124,7 +124,7 @@ winsdelln(WINDOW *win, int nlines)
 				lp = &win->alines[y]->line[i];
 				if (_cursesi_copy_nsp(win->bnsp, lp) == ERR)
 					return ERR;
-				SET_WCOL(*lp, 1);
+				lp->wcols = 1;
 #endif /* HAVE_WCHAR */
 			}
 		for (y = last; y >= win->cury; --y)
@@ -166,7 +166,7 @@ winsdelln(WINDOW *win, int nlines)
 				win->alines[y]->line[i].ch
 					= (wchar_t)btowc((int)win->bch);
 				lp = &win->alines[y]->line[i];
-				SET_WCOL( *lp, 1 );
+				lp->wcols = 1;
 				if (_cursesi_copy_nsp(win->bnsp, lp) == ERR)
 					return ERR;
 #endif /* HAVE_WCHAR */

Index: src/lib/libcurses/newwin.c
diff -u src/lib/libcurses/newwin.c:1.63 src/lib/libcurses/newwin.c:1.64
--- src/lib/libcurses/newwin.c:1.63	Tue Oct 19 06:41:03 2021
+++ src/lib/libcurses/newwin.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: newwin.c,v 1.63 2021/10/19 06:41:03 blymn Exp $	*/
+/*	$NetBSD: newwin.c,v 1.64 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)newwin.c	8.3 (Berkeley) 7/27/94";
 #else
-__RCSID("$NetBSD: newwin.c,v 1.63 2021/10/19 06:41:03 blymn Exp $");
+__RCSID("$NetBSD: newwin.c,v 1.64 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -166,7 +166,7 @@ __newwin(SCREEN *screen, int nlines, int
 #else
 			sp->ch = (wchar_t)btowc((int) win->bch);
 			sp->nsp = NULL;
-			SET_WCOL(*sp, 1);
+			sp->wcols = 1;
 #endif /* HAVE_WCHAR */
 		}
 		lp->hash = __hash_line(lp->line, maxx);
@@ -351,7 +351,7 @@ __makenew(SCREEN *screen, int nlines, in
 	win->battr = 0;
 #ifdef HAVE_WCHAR
 	win->bnsp = NULL;
-	SET_BGWCOL(*win, 1);
+	win->wcols = 1;
 #endif /* HAVE_WCHAR */
 	win->scr_t = 0;
 	win->scr_b = win->maxy - 1;

Index: src/lib/libcurses/refresh.c
diff -u src/lib/libcurses/refresh.c:1.117 src/lib/libcurses/refresh.c:1.118
--- src/lib/libcurses/refresh.c:1.117	Fri Dec 17 03:50:18 2021
+++ src/lib/libcurses/refresh.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: refresh.c,v 1.117 2021/12/17 03:50:18 uwe Exp $	*/
+/*	$NetBSD: refresh.c,v 1.118 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)refresh.c	8.7 (Berkeley) 8/13/94";
 #else
-__RCSID("$NetBSD: refresh.c,v 1.117 2021/12/17 03:50:18 uwe Exp $");
+__RCSID("$NetBSD: refresh.c,v 1.118 2022/01/25 03:05:06 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -316,22 +316,25 @@ _wnoutrefresh(WINDOW *win, int begy, int
 				vlp->line[x_off].ch = wlp->line[wx].ch;
 				/* Copy attributes  */
 				vlp->line[x_off].attr = wlp->line[wx].attr;
-				/* Check for nca conflict with colour */
-				if ((vlp->line[x_off].attr & __COLOR) &&
-				    (vlp->line[x_off].attr & screen->nca))
-					vlp->line[x_off].attr &= ~__COLOR;
+#ifdef HAVE_WCHAR
+				vlp->line[x_off].wcols = wlp->line[wx].wcols;
+#endif /* HAVE_WCHAR */
 				if (win->flags & __ISDERWIN) {
 					dwlp->line[dx_off].ch =
 						wlp->line[wx].ch;
 					dwlp->line[dx_off].attr =
 						wlp->line[wx].attr;
+#ifdef HAVE_WCHAR
+					dwlp->line[dx_off].wcols =
+						wlp->line[wx].wcols;
+#endif /* HAVE_WCHAR */
 				}
 
 #ifdef HAVE_WCHAR
 				if (wlp->line[wx].ch
 				    == (wchar_t)btowc((int) win->bch)) {
 					vlp->line[x_off].ch = win->bch;
-					SET_WCOL(vlp->line[x_off], 1);
+					vlp->line[x_off].wcols = win->wcols;
 					if (_cursesi_copy_nsp(win->bnsp,
 							      &vlp->line[x_off])
 					    == ERR)
@@ -339,7 +342,8 @@ _wnoutrefresh(WINDOW *win, int begy, int
 					if (win->flags & __ISDERWIN) {
 						dwlp->line[dx_off].ch =
 							win->bch;
-						SET_WCOL(dwlp->line[dx_off], 1);
+						dwlp->line[dx_off].wcols =
+						    win->wcols;
 						if (_cursesi_copy_nsp(win->bnsp,
 						     &dwlp->line[dx_off])
 						    == ERR)
@@ -602,6 +606,13 @@ doupdate(void)
 				__CTRACE(__CTRACE_REFRESH, " %x",
 				    curscr->alines[i]->line[j].attr);
 			__CTRACE(__CTRACE_REFRESH, "\n");
+#ifdef HAVE_WCHAR
+			__CTRACE(__CTRACE_REFRESH, " wcols:");
+			for (j = 0; j < curscr->maxx; j++)
+				__CTRACE(__CTRACE_REFRESH, " %d",
+				    curscr->alines[i]->line[j].wcols);
+			__CTRACE(__CTRACE_REFRESH, "\n");
+#endif /* HAVE_WCHAR */
 			__CTRACE(__CTRACE_REFRESH, "W: %d:", i);
 			__CTRACE(__CTRACE_REFRESH, " 0x%x \n",
 			    win->alines[i]->hash);
@@ -617,6 +628,11 @@ doupdate(void)
 				    win->alines[i]->line[j].attr);
 			__CTRACE(__CTRACE_REFRESH, "\n");
 #ifdef HAVE_WCHAR
+			__CTRACE(__CTRACE_REFRESH, " wcols:");
+			for (j = 0; j < win->maxx; j++)
+				__CTRACE(__CTRACE_REFRESH, " %d",
+				    win->alines[i]->line[j].wcols);
+			__CTRACE(__CTRACE_REFRESH, "\n");
 			__CTRACE(__CTRACE_REFRESH, " nsp:");
 			for (j = 0; j < curscr->maxx; j++)
 				__CTRACE(__CTRACE_REFRESH, " %p",
@@ -731,13 +747,15 @@ cleanup:
 		for (i = 0; i < curscr->maxy; i++) {
 			for (j = 0; j < curscr->maxx; j++)
 				__CTRACE(__CTRACE_REFRESH,
-				    "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n",
+				    "[%d,%d](%x,%x,%d,%p)-(%x,%x,%d,%p)\n",
 				    i, j,
 				    curscr->alines[i]->line[j].ch,
 				    curscr->alines[i]->line[j].attr,
+				    curscr->alines[i]->line[j].wcols,
 				    curscr->alines[i]->line[j].nsp,
 				    _cursesi_screen->__virtscr->alines[i]->line[j].ch,
 				    _cursesi_screen->__virtscr->alines[i]->line[j].attr,
+				    _cursesi_screen->__virtscr->alines[i]->line[j].wcols,
 				    _cursesi_screen->__virtscr->alines[i]->line[j].nsp);
 		}
 	}
@@ -954,13 +972,14 @@ putch(__LDATA *nsp, __LDATA *csp, int wy
 #ifdef HAVE_WCHAR
 		if (_cursesi_copy_nsp(nsp->nsp, csp) == ERR)
 			return ERR;
+		csp->wcols = nsp->wcols;
 #endif /* HAVE_WCHAR */
 	}
 
 #ifndef HAVE_WCHAR
 	__cputchar((int)nsp->ch);
 #else
-	if (WCOL(*nsp) <= 0)
+	if (nsp->wcols <= 0)
 		goto out;
 	__cputwchar((int)nsp->ch);
 	__CTRACE(__CTRACE_REFRESH,
@@ -995,8 +1014,8 @@ putchbr(__LDATA *nsp, __LDATA *csp, __LD
 
 	/* We need to insert characters. */
 #ifdef HAVE_WCHAR
-	cw = WCOL(*nsp);
-	pcw = WCOL(*psp);
+	cw = nsp->wcols;
+	pcw = psp->wcols;
 	if (cw < 1 || pcw < 1)
 		return ERR; /* Nothing to insert */
 
@@ -1056,7 +1075,7 @@ makech(int wy)
 	__LDATA *nsp, *csp, *cp, *cep, *fsp;
 	__LINE *wlp;
 	size_t	clsp, nlsp;	/* Last space in lines. */
-	int	lch, wx, chw;
+	int	lch, wx, owx, chw;
 	const char	*ce;
 	attr_t	lspc;		/* Last space colour */
 
@@ -1072,7 +1091,7 @@ makech(int wy)
 	blank.attr = 0;
 	if (_cursesi_copy_nsp(win->bnsp, &blank) == ERR)
 		return ERR;
-	SET_WCOL(blank, 1);
+	blank.wcols = win->wcols;
 #endif /* HAVE_WCHAR */
 #ifdef DEBUG
 #if HAVE_WCHAR
@@ -1087,12 +1106,12 @@ makech(int wy)
 			lp = &curscr->alines[wy]->line[x];
 			vlp = &__virtscr->alines[wy]->line[x];
 			__CTRACE(__CTRACE_REFRESH,
-			    "[%d,%d](%x,%x,%x,%x,%p)-"
-			    "(%x,%x,%x,%x,%p)\n",
-			    wy, x, lp->ch, lp->attr,
-			    win->bch, win->battr, lp->nsp,
-			    vlp->ch, vlp->attr,
-			    win->bch, win->battr, vlp->nsp);
+			    "[%d,%d](%x,%x,%d,%x,%x,%d,%p)-"
+			    "(%x,%x,%d,%x,%x,%d,%p)\n",
+			    wy, x, lp->ch, lp->attr, lp->wcols,
+			    win->bch, win->battr, win->wcols, lp->nsp,
+			    vlp->ch, vlp->attr, vlp->wcols,
+			    win->bch, win->battr, win->wcols, vlp->nsp);
 		}
 	}
 #endif /* HAVE_WCHAR */
@@ -1163,23 +1182,29 @@ makech(int wy)
 #ifndef HAVE_WCHAR
 		__CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d\n", wx, lch);
 #else
-		__CTRACE(__CTRACE_REFRESH, "makech: nsp=(%x,%x,%x,%x,%p)\n",
-			nsp->ch, nsp->attr, win->bch, win->battr, nsp->nsp);
-		__CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%x,%x,%p)\n",
-			csp->ch, csp->attr, win->bch, win->battr, csp->nsp);
+		__CTRACE(__CTRACE_REFRESH, "makech: nsp=(%x,%x,%d,%x,%x,%d,%p)\n",
+			nsp->ch, nsp->attr, nsp->wcols, win->bch, win->battr,
+			win->wcols, nsp->nsp);
+		__CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%d,%x,%x,%d,%p)\n",
+			csp->ch, csp->attr, csp->wcols, win->bch, win->battr,
+			win->wcols, csp->nsp);
 #endif
 		if (!(wlp->flags & __ISFORCED) &&
 #ifdef HAVE_WCHAR
-		    ((nsp->attr & __WCWIDTH) != __WCWIDTH) &&
+		    ((nsp->wflags & WCA_CONTINUATION) != WCA_CONTINUATION) &&
 #endif
 		    celleq(nsp, csp))
 		{
 			if (wx <= lch) {
 				while (wx <= lch && celleq(nsp, csp)) {
+#ifdef HAVE_WCHAR
+					wx += nsp->wcols;
+#else
+					wx++;
+#endif
 					nsp++;
 					if (!_cursesi_screen->curwin)
 						++csp;
-					++wx;
 				}
 				continue;
 			}
@@ -1193,6 +1218,7 @@ makech(int wy)
 		    wx, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx);
 		_cursesi_screen->ly = wy;
 		_cursesi_screen->lx = wx;
+		owx = wx;
 		while (wx <= lch &&
 		       ((wlp->flags & __ISFORCED) || !celleq(nsp, csp)))
 		{
@@ -1246,7 +1272,7 @@ makech(int wy)
 						csp->ch = ' '; /* XXX */
 #else
 						csp->ch = (wchar_t)btowc((int)' ');
-						SET_WCOL( *csp, 1 );
+						csp->wcols = 1;
 #endif /* HAVE_WCHAR */
 						assert(csp != &blank);
 						csp++;
@@ -1257,12 +1283,13 @@ makech(int wy)
 			}
 
 #ifdef HAVE_WCHAR
-			chw = WCOL(*nsp);
+			chw = nsp->wcols;
 			if (chw < 0)
 				chw = 0; /* match putch() */
 #else
 			chw = 1;
 #endif /* HAVE_WCHAR */
+			owx = wx;
 			if (wx + chw >= win->maxx &&
 			    wy == win->maxy - 1 && !_cursesi_screen->curwin)
 			{
@@ -1304,14 +1331,28 @@ makech(int wy)
 				putattr_out(nsp);
 			}
 			wx += chw;
-			nsp++;
+			nsp += chw;
 			__CTRACE(__CTRACE_REFRESH,
 			    "makech: 2: wx = %d, lx = %d\n",
 			    wx, _cursesi_screen->lx);
 		}
 		if (_cursesi_screen->lx == wx)	/* If no change. */
 			break;
-		_cursesi_screen->lx = wx;
+
+		/*
+		 * We need to work out if the cursor has been put in the
+		 * middle of a wide character so check if curx is between
+		 * where we were and where we are and we are on the right
+		 * line.  If so, move the cursor now.
+		 */
+		if ((wy == win->cury) && (wx > win->curx) &&
+		    (owx < win->curx)) {
+			_cursesi_screen->lx = win->curx;
+			domvcur(win, _cursesi_screen->ly, wx,
+			    _cursesi_screen->ly, _cursesi_screen->lx);
+		} else
+			_cursesi_screen->lx = wx;
+
 		if (_cursesi_screen->lx >= COLS && auto_right_margin)
 			_cursesi_screen->lx = COLS - 1;
 		else
@@ -1339,12 +1380,12 @@ makech(int wy)
 			lp = &curscr->alines[wy]->line[x];
 			vlp = &__virtscr->alines[wy]->line[x];
 			__CTRACE(__CTRACE_REFRESH,
-			    "[%d,%d](%x,%x,%x,%x,%p)-"
-			    "(%x,%x,%x,%x,%p)\n",
-			    wy, x, lp->ch, lp->attr,
-			    win->bch, win->battr, lp->nsp,
-			    vlp->ch, vlp->attr,
-			    win->bch, win->battr, vlp->nsp);
+			    "[%d,%d](%x,%x,%d,%x,%x,%d,%p)-"
+			    "(%x,%x,%d,%x,%x,%d,%p)\n",
+			    wy, x, lp->ch, lp->attr, lp->wcols,
+			    win->bch, win->battr, win->wcols, lp->nsp,
+			    vlp->ch, vlp->attr, vlp->wcols,
+			    win->bch, win->battr, win->wcols, vlp->nsp);
 		}
 	}
 #endif /* HAVE_WCHAR */
@@ -1556,12 +1597,12 @@ done:
 	}
 #else
 	if (buf[0].ch != (wchar_t)btowc((int)curscr->bch )) {
-		for (i = 0; i < BLANKSIZE; i++) {
+		for (i = 0; i < BLANKSIZE; i++) { /* XXXX: BLANKSIZE may not be valid if wcols > 1 */
 			buf[i].ch = (wchar_t)btowc((int)curscr->bch);
 			if (_cursesi_copy_nsp(curscr->bnsp, &buf[i]) == ERR)
 				return;
 			buf[i].attr = 0;
-			SET_WCOL(buf[i], 1);
+			buf[i].wcols = curscr->wcols;
 		}
 	}
 #endif /* HAVE_WCHAR */

Index: src/lib/libcurses/slk.c
diff -u src/lib/libcurses/slk.c:1.18 src/lib/libcurses/slk.c:1.19
--- src/lib/libcurses/slk.c:1.18	Thu Jan  6 20:50:18 2022
+++ src/lib/libcurses/slk.c	Tue Jan 25 03:05:06 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: slk.c,v 1.18 2022/01/06 20:50:18 blymn Exp $	*/
+/*	$NetBSD: slk.c,v 1.19 2022/01/25 03:05:06 blymn Exp $	*/
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -30,8 +30,9 @@
  */
 
 #include <sys/cdefs.h>
+#include <limits.h>
 #ifndef lint
-__RCSID("$NetBSD: slk.c,v 1.18 2022/01/06 20:50:18 blymn Exp $");
+__RCSID("$NetBSD: slk.c,v 1.19 2022/01/25 03:05:06 blymn Exp $");
 #endif				/* not lint */
 
 #include <ctype.h>

Reply via email to