Module Name:    src
Committed By:   blymn
Date:           Fri Dec  6 11:23:47 UTC 2013

Modified Files:
        src/lib/libcurses: refresh.c touchwin.c

Log Message:
Make the touch family of calls actually force an update of the
terminal bypassing optimisations.  Previously if curses thought curscr
was in sync with virtscr (curses concept of what is on the screen) then
nothing would be output.  This change forces an update out to the terminal
regardless.


To generate a diff of this commit:
cvs rdiff -u -r1.77 -r1.78 src/lib/libcurses/refresh.c
cvs rdiff -u -r1.26 -r1.27 src/lib/libcurses/touchwin.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/refresh.c
diff -u src/lib/libcurses/refresh.c:1.77 src/lib/libcurses/refresh.c:1.78
--- src/lib/libcurses/refresh.c:1.77	Sun May  5 14:22:07 2013
+++ src/lib/libcurses/refresh.c	Fri Dec  6 11:23:47 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: refresh.c,v 1.77 2013/05/05 14:22:07 jdc Exp $	*/
+/*	$NetBSD: refresh.c,v 1.78 2013/12/06 11:23:47 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.77 2013/05/05 14:22:07 jdc Exp $");
+__RCSID("$NetBSD: refresh.c,v 1.78 2013/12/06 11:23:47 blymn Exp $");
 #endif
 #endif				/* not lint */
 
@@ -180,6 +180,12 @@ _cursesi_wnoutrefresh(SCREEN *screen, WI
 					sub_win->alines[sy]->flags
 					    &= ~__ISDIRTY;
 				}
+				if (sub_win->alines[sy]->flags & __ISFORCED) {
+					orig->alines[sy + sub_win->begy - orig->begy]->flags
+					    |= __ISFORCED;
+					sub_win->alines[sy]->flags
+					    &= ~__ISFORCED;
+				}
 			}
 		}
 	}
@@ -209,7 +215,7 @@ _cursesi_wnoutrefresh(SCREEN *screen, WI
 		    "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n",
 		    wy, *wlp->firstchp, *wlp->lastchp, wlp->flags);
 #endif
-		if ((wlp->flags & __ISDIRTY) == 0)
+		if ((wlp->flags & (__ISDIRTY | __ISFORCED)) == 0)
 			continue;
 		vlp = screen->__virtscr->alines[y_off];
 
@@ -274,6 +280,8 @@ _cursesi_wnoutrefresh(SCREEN *screen, WI
 				vlp->flags &= ~__ISPASTEOL;
 			if (wlp->flags & __ISDIRTY)
 				vlp->flags |= __ISDIRTY;
+			if (wlp->flags & __ISFORCED)
+				vlp->flags |= __ISFORCED;
 
 #ifdef DEBUG
 			__CTRACE(__CTRACE_REFRESH,
@@ -282,24 +290,25 @@ _cursesi_wnoutrefresh(SCREEN *screen, WI
 #endif
 			/* Set change pointers on "__virtscr". */
 			if (*vlp->firstchp >
-			    *wlp->firstchp + wbegx - win->ch_off)
-				*vlp->firstchp =
-				    *wlp->firstchp + wbegx - win->ch_off;
+				*wlp->firstchp + wbegx - win->ch_off)
+					*vlp->firstchp =
+					    *wlp->firstchp + wbegx - win->ch_off;
 			if (*vlp->lastchp <
-			    *wlp->lastchp + wbegx - win->ch_off)
-				*vlp->lastchp =
-				    *wlp->lastchp + wbegx - win->ch_off;
+				*wlp->lastchp + wbegx - win->ch_off)
+					*vlp->lastchp =
+					    *wlp->lastchp + wbegx - win->ch_off;
 #ifdef DEBUG
 			__CTRACE(__CTRACE_REFRESH,
 			    "__virtscr: firstch = %d, lastch = %d\n",
 			    *vlp->firstchp, *vlp->lastchp);
 #endif
 			/*
-			 * Unset change pointers only if a window, as a pad
-			 * can be displayed again without any of the contents
-			 * changing.
+			 * Unset change pointers only if a window and we
+			 * are not forcing a redraw. A pad can be displayed
+			 * again without any of the contents changing.
 			 */
-			if (!(win->flags & __ISPAD)) {
+			if ((!(win->flags & __ISPAD)) ||
+			    ((wlp->flags & __ISFORCED) == __ISFORCED)) {
 				/* Set change pointers on "win". */
 				if (*wlp->firstchp >= win->ch_off)
 					*wlp->firstchp = maxx + win->ch_off;
@@ -395,9 +404,9 @@ int
 doupdate(void)
 {
 	WINDOW	*win;
-	__LINE	*wlp;
+	__LINE	*wlp, *vlp;
 	short	 wy;
-	int	 dnum;
+	int	 dnum, was_cleared;
 #ifdef HAVE_WCHAR
 	__LDATA *lp;
 	nschar_t *np;
@@ -450,6 +459,7 @@ doupdate(void)
 		}
 	}
 
+	was_cleared = 0;
 	if ((win->flags & __CLEAROK) || (curscr->flags & __CLEAROK) ||
 	    _cursesi_screen->curwin) {
 		if (curscr->wattr & __COLOR)
@@ -465,6 +475,8 @@ doupdate(void)
 		}
 		__touchwin(win);
 		win->flags &= ~__CLEAROK;
+		/* note we cleared for later */
+		was_cleared = 1;
 	}
 	if (!cursor_address) {
 		if (win->curx != 0)
@@ -544,6 +556,7 @@ doupdate(void)
 
 	for (wy = 0; wy < win->maxy; wy++) {
 		wlp = win->alines[wy];
+		vlp = _cursesi_screen->__virtscr->alines[win->begy + wy];
 /* XXX: remove this debug */
 #ifdef DEBUG
 		__CTRACE(__CTRACE_REFRESH,
@@ -552,29 +565,47 @@ doupdate(void)
 #endif /* DEBUG */
 		if (!_cursesi_screen->curwin)
 			curscr->alines[wy]->hash = wlp->hash;
-		if (wlp->flags & __ISDIRTY) {
+		if ((wlp->flags & __ISDIRTY) ||
+		    (wlp->flags & __ISFORCED)) {
 #ifdef DEBUG
 			__CTRACE(__CTRACE_REFRESH,
 			    "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy,
 			    *wlp->firstchp, *wlp->lastchp);
 #endif /* DEBUG */
+			/*
+		 	* We have just cleared so don't force an update
+		 	* otherwise we spray neeedless blanks to a cleared
+		 	* screen.
+		 	*/
+			if (was_cleared == 1)
+				win->alines[wy]->flags &= ~__ISFORCED;
+
 			if (makech(wy) == ERR)
 				return (ERR);
 			else {
 				if (*wlp->firstchp >= 0)
 					*wlp->firstchp = win->maxx;
 				if (*wlp->lastchp < win->maxx)
-					*wlp->lastchp = 0;
+					*wlp->lastchp = win->ch_off;
 				if (*wlp->lastchp < *wlp->firstchp) {
 #ifdef DEBUG
 					__CTRACE(__CTRACE_REFRESH,
 					    "doupdate: line %d notdirty\n", wy);
 #endif /* DEBUG */
-					wlp->flags &= ~__ISDIRTY;
+					wlp->flags &= ~(__ISDIRTY | __ISFORCED);
 				}
 			}
-
 		}
+
+		/*
+		 * virtscr is now synced for the line, unset the change
+		 * pointers.
+		 */
+		if (*vlp->firstchp >= 0)
+			*vlp->firstchp = _cursesi_screen->__virtscr->maxx;
+		if (*vlp->lastchp <= _cursesi_screen->__virtscr->maxx)
+			*vlp->lastchp = 0;
+
 #ifdef DEBUG
 		__CTRACE(__CTRACE_REFRESH, "\t%d\t%d\n",
 		    *wlp->firstchp, *wlp->lastchp);
@@ -641,6 +672,7 @@ makech(int wy)
 	WINDOW	*win;
 	static __LDATA blank;
 	__LDATA *nsp, *csp, *cp, *cep;
+	__LINE *wlp;
 	size_t	clsp, nlsp;	/* Last space in lines. */
 	int	lch, wx;
 	const char	*ce;
@@ -691,6 +723,7 @@ makech(int wy)
 		_cursesi_screen->ly++;
 		_cursesi_screen->lx = 0;
 	}
+	wlp = win->alines[wy];
 	wx = *win->alines[wy]->firstchp;
 	if (wx < 0)
 		wx = 0;
@@ -754,7 +787,8 @@ makech(int wy)
 		__CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d\n", wx, lch);
 #endif /* DEBUG */
 #ifndef HAVE_WCHAR
-		if (memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
+		if (!(wlp->flags & __ISFORCED) && 
+		    (memcmp(nsp, csp, sizeof(__LDATA)) == 0)) {
 			if (wx <= lch) {
 				while (wx <= lch &&
 				    memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
@@ -774,8 +808,9 @@ makech(int wy)
 		__CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%x,%x,%p)\n",
 			csp->ch, csp->attr, win->bch, win->battr, csp->nsp);
 #endif /* DEBUG */
-		if (((nsp->attr & __WCWIDTH) != __WCWIDTH) &&
-		    cellcmp(nsp, csp)) {
+		if (!(wlp->flags & __ISFORCED) &&
+		     (((nsp->attr & __WCWIDTH) != __WCWIDTH) &&
+		       cellcmp(nsp, csp))) {
 			if (wx <= lch) {
 				while (wx <= lch && cellcmp( csp, nsp )) {
 					nsp++;
@@ -798,11 +833,13 @@ makech(int wy)
 		_cursesi_screen->ly = wy;
 		_cursesi_screen->lx = wx;
 #ifndef HAVE_WCHAR
-		while (wx <= lch && memcmp(nsp, csp, sizeof(__LDATA)) != 0) {
+		while (wx <= lch && (memcmp(nsp, csp, sizeof(__LDATA)) != 0) ||
+			(wlp->flags & __ISFORCED)) {
 			if (ce != NULL &&
 			    wx >= nlsp && nsp->ch == ' ' && nsp->attr == lspc) {
 #else
-		while (!cellcmp(nsp, csp) && wx <= lch) {
+		while ((!cellcmp(nsp, csp) || (wlp->flags & __ISFORCED)) &&
+			wx <= lch) {
 			if (ce != NULL && wx >= nlsp
 			   && nsp->ch == (wchar_t)btowc((int)' ') /* XXX */
 			   && (nsp->attr & WA_ATTRIBUTES) == lspc) {
@@ -818,12 +855,18 @@ makech(int wy)
 #endif /* HAVE_WCHAR */
 					if (cep-- <= csp)
 						break;
-				clsp = cep - curscr->alines[wy]->line -
-				    win->begx * __LDATASIZE;
+				if (cep > (curscr->alines[wy]->line + win->begx * __LDATASIZE))
+					clsp = cep - curscr->alines[wy]->line -
+				    	win->begx * __LDATASIZE;
+				else
+					clsp = 0;
 #ifdef DEBUG
 				__CTRACE(__CTRACE_REFRESH,
 				    "makech: clsp = %zu, nlsp = %zu\n",
 				    clsp, nlsp);
+				__CTRACE(__CTRACE_REFRESH,
+				    "makech: line = %p, cep = %p, begx = %u\n",
+				    curscr->alines[wy]->line, cep, win->begx);
 #endif
 				if (((clsp - nlsp >= strlen(clr_eol) &&
 				    clsp < win->maxx * __LDATASIZE) ||

Index: src/lib/libcurses/touchwin.c
diff -u src/lib/libcurses/touchwin.c:1.26 src/lib/libcurses/touchwin.c:1.27
--- src/lib/libcurses/touchwin.c:1.26	Tue Feb 23 19:48:26 2010
+++ src/lib/libcurses/touchwin.c	Fri Dec  6 11:23:47 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: touchwin.c,v 1.26 2010/02/23 19:48:26 drochner Exp $	*/
+/*	$NetBSD: touchwin.c,v 1.27 2013/12/06 11:23:47 blymn Exp $	*/
 
 /*
  * Copyright (c) 1981, 1993, 1994
@@ -34,13 +34,15 @@
 #if 0
 static char sccsid[] = "@(#)touchwin.c	8.2 (Berkeley) 5/4/94";
 #else
-__RCSID("$NetBSD: touchwin.c,v 1.26 2010/02/23 19:48:26 drochner Exp $");
+__RCSID("$NetBSD: touchwin.c,v 1.27 2013/12/06 11:23:47 blymn Exp $");
 #endif
 #endif				/* not lint */
 
 #include "curses.h"
 #include "curses_private.h"
 
+static int _cursesi_touchline_force(WINDOW *, int, int, int, int);
+
 /*
  * is_linetouched --
  *	Indicate if line has been touched or not.
@@ -157,7 +159,8 @@ wtouchln(WINDOW *win, int line, int n, i
 		line = win->maxy - n;
 	for (y = line; y < line + n; y++) {
 		if (changed == 1)
-			__touchline(win, y, 0, (int) win->maxx - 1);
+			_cursesi_touchline_force(win, y, 0,
+			    (int) win->maxx - 1, 1);
 		else {
 			wlp = win->alines[y];
 			if (*wlp->firstchp >= win->ch_off &&
@@ -166,13 +169,13 @@ wtouchln(WINDOW *win, int line, int n, i
 			if (*wlp->lastchp >= win->ch_off &&
 			    *wlp->lastchp < win->maxx + win->ch_off)
 				*wlp->lastchp = win->ch_off;
-			wlp->flags &= ~__ISDIRTY;
+			wlp->flags &= ~(__ISDIRTY | __ISFORCED);
 		}
 	}
 
 	return OK;
 }
-		
+
 int
 __touchwin(WINDOW *win)
 {
@@ -190,6 +193,19 @@ __touchwin(WINDOW *win)
 int
 __touchline(WINDOW *win, int y, int sx, int ex)
 {
+	return (_cursesi_touchline_force(win, y, sx, ex, 0));
+}
+
+/*
+ * Touch line y on window win starting from column sx and ending at
+ * column ex.  If force is 1 then we mark this line as a forced update
+ * which will bypass screen optimisation in the refresh code to rewrite
+ * this line unconditionally (even if refresh thinks the screen matches
+ * what is in the virtscr)
+ */
+static int
+_cursesi_touchline_force(WINDOW *win, int y, int sx, int ex, int force)
+{
 #ifdef DEBUG
 	__CTRACE(__CTRACE_LINE, "__touchline: (%p, %d, %d, %d)\n",
 	    win, y, sx, ex);
@@ -198,8 +214,9 @@ __touchline(WINDOW *win, int y, int sx, 
 #endif
 	sx += win->ch_off;
 	ex += win->ch_off;
-	if (!(win->alines[y]->flags & __ISDIRTY))
-		win->alines[y]->flags |= __ISDIRTY;
+	win->alines[y]->flags |= __ISDIRTY;
+	if (force == 1)
+		win->alines[y]->flags |= __ISFORCED;
 	/* firstchp/lastchp are shared between parent window and sub-window. */
 	if (*win->alines[y]->firstchp > sx)
 		*win->alines[y]->firstchp = sx;
@@ -217,7 +234,7 @@ wsyncup(WINDOW *win)
 {
 
 	do {
-		touchwin(win);
+		__touchwin(win);
 		win = win->orig;
 	} while (win);
 }
@@ -229,7 +246,7 @@ wsyncdown(WINDOW *win)
 
 	while (w) {
 		if (is_wintouched(w)) {
-			touchwin(win);
+			__touchwin(win);
 			break;
 		}
 		w = w->orig;

Reply via email to