Module Name:    src
Committed By:   blymn
Date:           Tue Apr 19 22:26:57 UTC 2022

Modified Files:
        src/lib/libcurses: background.c curses.c curses_private.h refresh.c

Log Message:
fix for PR 55496

 * Fix bkgrndset so that it actually sets the background character in
   in line with the SUSv2 specification.

 * Add an internal function to copy a complex character

 * Make the previously static celleq function into a libcurses private
   function so that it can be called in other files.


To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/lib/libcurses/background.c
cvs rdiff -u -r1.28 -r1.29 src/lib/libcurses/curses.c
cvs rdiff -u -r1.78 -r1.79 src/lib/libcurses/curses_private.h
cvs rdiff -u -r1.121 -r1.122 src/lib/libcurses/refresh.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/background.c
diff -u src/lib/libcurses/background.c:1.29 src/lib/libcurses/background.c:1.30
--- src/lib/libcurses/background.c:1.29	Tue Apr 12 07:03:04 2022
+++ src/lib/libcurses/background.c	Tue Apr 19 22:26:57 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: background.c,v 1.29 2022/04/12 07:03:04 blymn Exp $	*/
+/*	$NetBSD: background.c,v 1.30 2022/04/19 22:26:57 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.29 2022/04/12 07:03:04 blymn Exp $");
+__RCSID("$NetBSD: background.c,v 1.30 2022/04/19 22:26:57 blymn Exp $");
 #endif				/* not lint */
 
 #include <stdlib.h>
@@ -160,7 +160,9 @@ wbkgrndset(WINDOW *win, const cchar_t *w
 {
 	attr_t battr;
 	nschar_t *np, *tnp;
-	int i;
+	int i, wy, wx;
+	__LDATA obkgrnd, nbkgrnd;
+	__LINE *wlp;
 
 	__CTRACE(__CTRACE_ATTR, "wbkgrndset: (%p), '%s', %x\n",
 	    win, (const char *)wunctrl(wch), wch->attributes);
@@ -169,6 +171,14 @@ wbkgrndset(WINDOW *win, const cchar_t *w
 	if (!wch->elements || wcwidth(wch->vals[0]) > 1)
 		return;
 
+	/* get a copy of the old background, we will need it. */
+	obkgrnd.ch = win->bch;
+	obkgrnd.attr = win->battr;
+	obkgrnd.wflags = 0;
+	obkgrnd.wcols = win->wcols;
+	obkgrnd.nsp = NULL;
+	_cursesi_copy_nsp(win->bnsp, &obkgrnd);
+
 	/* Background character. */
 	tnp = np = win->bnsp;
 	if (wcwidth( wch->vals[0]))
@@ -204,11 +214,7 @@ wbkgrndset(WINDOW *win, const cchar_t *w
 		}
 	}
 	/* clear the old non-spacing characters */
-	while (np) {
-		tnp = np->next;
-		free(np);
-		np = tnp;
-	}
+	__cursesi_free_nsp(np);
 
 	/* Background attributes (check colour). */
 	battr = wch->attributes & WA_ATTRIBUTES;
@@ -216,6 +222,29 @@ wbkgrndset(WINDOW *win, const cchar_t *w
 		battr |= __default_color;
 	win->battr = battr;
 	win->wcols = 1;
+
+	/*
+	 * Now do the dirty work of updating all the locations
+	 * that have the old background character with the new.
+	 */
+
+	nbkgrnd.ch = win->bch;
+	nbkgrnd.attr = win->battr;
+	nbkgrnd.wflags = 0;
+	nbkgrnd.wcols = win->wcols;
+	nbkgrnd.nsp = NULL;
+	_cursesi_copy_nsp(win->bnsp, &nbkgrnd);
+
+	for (wy = 0; wy < win->maxy; wy++) {
+		wlp = win->alines[wy];
+		for (wx = 0; wx < win->maxx; wx++) {
+			if (_cursesi_celleq(&obkgrnd, &wlp->line[wx])) {
+				_cursesi_copy_wchar(&nbkgrnd, &wlp->line[wx]);
+			}
+		}
+	}
+	__touchwin(win, 1);
+
 }
 
 

Index: src/lib/libcurses/curses.c
diff -u src/lib/libcurses/curses.c:1.28 src/lib/libcurses/curses.c:1.29
--- src/lib/libcurses/curses.c:1.28	Tue Jan 31 09:17:53 2017
+++ src/lib/libcurses/curses.c	Tue Apr 19 22:26:57 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: curses.c,v 1.28 2017/01/31 09:17:53 roy Exp $	*/
+/*	$NetBSD: curses.c,v 1.29 2022/04/19 22:26:57 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -35,7 +35,7 @@
 #if 0
 static char sccsid[] = "@(#)curses.c	8.3 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: curses.c,v 1.28 2017/01/31 09:17:53 roy Exp $");
+__RCSID("$NetBSD: curses.c,v 1.29 2022/04/19 22:26:57 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -77,7 +77,55 @@ char	 __GT;				/* Gtty indicates tabs. *
 char	 __NONL;			/* Term can't hack LF doing a CR. */
 char	 __UPPERCASE;			/* Terminal is uppercase only. */
 
+/* compare two cells on screen, must have the same foreground/background,
+ * and for wide characters the same sequence of non-spacing characters
+ */
+int
+_cursesi_celleq(__LDATA *x, __LDATA *y)
+{
 #ifdef HAVE_WCHAR
+	nschar_t *xnp = x->nsp, *ynp = y->nsp;
+#endif /* HAVE_WCHAR */
+	int ret = ( x->ch == y->ch ) && ( x->attr == y->attr );
+
+#ifdef HAVE_WCHAR
+	if (!ret)
+		return 0;
+
+	if (!xnp && !ynp)
+		return 1;
+
+	if ((xnp && !ynp) || (!xnp && ynp))
+		return 0;
+
+	while (xnp && ynp) {
+		if (xnp->ch != ynp->ch)
+			return 0;
+		xnp = xnp->next;
+		ynp = ynp->next;
+	}
+
+	return !xnp && !ynp;
+#else
+	return ret;
+#endif /* HAVE_WCHAR */
+}
+
+#ifdef HAVE_WCHAR
+/*
+ * Copy a complex character from source to destination.
+ *
+ */
+void
+_cursesi_copy_wchar(__LDATA *src, __LDATA *dest)
+{
+	dest->ch = src->ch;
+	dest->attr = src->attr;
+	dest->wflags = src->wflags;
+	dest->wcols = src->wcols;
+	_cursesi_copy_nsp(src->nsp, dest);
+}
+
 /*
  * Copy the non-spacing character list (src_nsp) to the given character,
  * allocate or free storage as required.

Index: src/lib/libcurses/curses_private.h
diff -u src/lib/libcurses/curses_private.h:1.78 src/lib/libcurses/curses_private.h:1.79
--- src/lib/libcurses/curses_private.h:1.78	Tue Apr 12 07:03:04 2022
+++ src/lib/libcurses/curses_private.h	Tue Apr 19 22:26:57 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: curses_private.h,v 1.78 2022/04/12 07:03:04 blymn Exp $	*/
+/*	$NetBSD: curses_private.h,v 1.79 2022/04/19 22:26:57 blymn Exp $	*/
 
 /*-
  * Copyright (c) 1998-2000 Brett Lymn
@@ -361,10 +361,12 @@ unsigned int	 __hash_line(const __LDATA 
 void	 __id_subwins(WINDOW *);
 void	 __init_getch(SCREEN *);
 void	 __init_acs(SCREEN *);
+int	 _cursesi_celleq(__LDATA *, __LDATA *);
 #ifdef HAVE_WCHAR
 void	 __init_get_wch(SCREEN *);
 void	 __init_wacs(SCREEN *);
 int	__cputwchar_args( wchar_t, void * );
+void	_cursesi_copy_wchar(__LDATA *, __LDATA *);
 int     _cursesi_copy_nsp(nschar_t *, struct __ldata *);
 void	__cursesi_free_nsp(nschar_t *);
 void	__cursesi_win_free_nsp(WINDOW *);

Index: src/lib/libcurses/refresh.c
diff -u src/lib/libcurses/refresh.c:1.121 src/lib/libcurses/refresh.c:1.122
--- src/lib/libcurses/refresh.c:1.121	Wed Apr 13 19:17:09 2022
+++ src/lib/libcurses/refresh.c	Tue Apr 19 22:26:57 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: refresh.c,v 1.121 2022/04/13 19:17:09 pgoyette Exp $	*/
+/*	$NetBSD: refresh.c,v 1.122 2022/04/19 22:26:57 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.121 2022/04/13 19:17:09 pgoyette Exp $");
+__RCSID("$NetBSD: refresh.c,v 1.122 2022/04/19 22:26:57 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -57,7 +57,6 @@ static void	scrolln(int, int, int, int, 
 
 static int	_wnoutrefresh(WINDOW *, int, int, int, int, int, int);
 
-static int celleq(__LDATA *, __LDATA *);
 static int lineeq(__LDATA *, __LDATA *, size_t);
 
 #define	CHECK_INTERVAL		5 /* Change N lines before checking typeahead */
@@ -1174,7 +1173,7 @@ makech(int wy)
 	    || (__using_color && back_color_erase))) {
 		cp = &win->alines[wy]->line[win->maxx - 1];
 #ifdef HAVE_WCHAR
-		while ((celleq(cp, &space) == 1) &&
+		while ((_cursesi_celleq(cp, &space) == 1) &&
 #else
 		while (cp->ch == space.ch &&
 #endif /* HAVE_WCHAR */
@@ -1200,7 +1199,7 @@ makech(int wy)
 		__CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d\n", wx, lch);
 #ifdef HAVE_WCHAR
 		__CTRACE(__CTRACE_REFRESH, "makech: farnarkle: flags 0x%x, wflags 0x%x, color_init %d, celleq %d\n",
-			wlp->flags, nsp->wflags, __do_color_init, celleq(nsp, csp));
+			wlp->flags, nsp->wflags, __do_color_init, _cursesi_celleq(nsp, csp));
 		__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);
@@ -1212,10 +1211,10 @@ makech(int wy)
 #ifdef HAVE_WCHAR
 		    ((nsp->wflags & WCA_CONTINUATION) != WCA_CONTINUATION) &&
 #endif
-		    celleq(nsp, csp))
+		    _cursesi_celleq(nsp, csp))
 		{
 			if (wx <= lch) {
-				while (wx <= lch && celleq(nsp, csp)) {
+				while (wx <= lch && _cursesi_celleq(nsp, csp)) {
 #ifdef HAVE_WCHAR
 					wx += nsp->wcols;
 #else
@@ -1239,7 +1238,7 @@ makech(int wy)
 		_cursesi_screen->lx = wx;
 		owx = wx;
 		while (wx <= lch &&
-		       ((wlp->flags & __ISFORCED) || !celleq(nsp, csp)))
+		       ((wlp->flags & __ISFORCED) || !_cursesi_celleq(nsp, csp)))
 		{
 			if ((ce != NULL) && (wx >= nlsp) &&
 			    (nsp->ch == space.ch) &&
@@ -1346,7 +1345,7 @@ makech(int wy)
 			    !(win->flags & __SCROLLWIN))
 			{
 				tld = nsp;
-				if (celleq(&blank, nsp))
+				if (_cursesi_celleq(&blank, nsp))
 					tld = &blank;
 				
 				if (putch(tld, csp, wy, wx) == ERR)
@@ -1711,7 +1710,7 @@ done:
 				if (clp->hash != blank_hash ||
 				    !lineeq(clp->line, clp->line + 1,
 					    (__virtscr->maxx - 1)) ||
-				    !celleq(clp->line, buf))
+				    !_cursesi_celleq(clp->line, buf))
 				{
 					for (i = __virtscr->maxx;
 					    i > BLANKSIZE;
@@ -1990,40 +1989,6 @@ __unsetattr(int checkms)
 		__unset_color(curscr);
 }
 
-/* compare two cells on screen, must have the same foreground/background,
- * and for wide characters the same sequence of non-spacing characters
- */
-static int
-celleq(__LDATA *x, __LDATA *y)
-{
-#ifdef HAVE_WCHAR
-	nschar_t *xnp = x->nsp, *ynp = y->nsp;
-#endif /* HAVE_WCHAR */
-	int ret = ( x->ch == y->ch ) && ( x->attr == y->attr );
-
-#ifdef HAVE_WCHAR
-	if (!ret)
-		return 0;
-
-	if (!xnp && !ynp)
-		return 1;
-
-	if ((xnp && !ynp) || (!xnp && ynp))
-		return 0;
-
-	while (xnp && ynp) {
-		if (xnp->ch != ynp->ch)
-			return 0;
-		xnp = xnp->next;
-		ynp = ynp->next;
-	}
-
-	return !xnp && !ynp;
-#else
-	return ret;
-#endif /* HAVE_WCHAR */
-}
-
 /* compare two line segments */
 static int
 lineeq(__LDATA *xl, __LDATA *yl, size_t len)
@@ -2032,7 +1997,7 @@ lineeq(__LDATA *xl, __LDATA *yl, size_t 
 	__LDATA *xp = xl, *yp = yl;
 
 	for (i = 0; i < len; i++, xp++, yp++) {
-		if (!celleq(xp, yp))
+		if (!_cursesi_celleq(xp, yp))
 			return 0;
 	}
 	return 1;

Reply via email to