summaryrefslogtreecommitdiff
path: root/lib/libcurses
diff options
context:
space:
mode:
authorblymn <blymn@NetBSD.org>2013-12-06 11:23:47 +0000
committerblymn <blymn@NetBSD.org>2013-12-06 11:23:47 +0000
commitcd3fcee8ba72145f28b4be42408d174b23d3359f (patch)
treeffa8127a523d5198aa53b1762cb49e3bbba0059c /lib/libcurses
parent08bb0b90d820e2cca0050d8f1bd0afca41007999 (diff)
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.
Diffstat (limited to 'lib/libcurses')
-rw-r--r--lib/libcurses/refresh.c95
-rw-r--r--lib/libcurses/touchwin.c35
2 files changed, 95 insertions, 35 deletions
diff --git a/lib/libcurses/refresh.c b/lib/libcurses/refresh.c
index 1a294cf06e0..970b15329c0 100644
--- a/lib/libcurses/refresh.c
+++ b/lib/libcurses/refresh.c
@@ -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, WINDOW *win, int begy, int begx,
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, WINDOW *win, int begy, int begx,
"_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, WINDOW *win, int begy, int begx,
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, WINDOW *win, int begy, int begx,
#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) ||
diff --git a/lib/libcurses/touchwin.c b/lib/libcurses/touchwin.c
index f01d524e319..07ca0c68b38 100644
--- a/lib/libcurses/touchwin.c
+++ b/lib/libcurses/touchwin.c
@@ -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, int changed)
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, int changed)
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, int ex)
#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;