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 = ␣ 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;