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.
This commit is contained in:
blymn 2013-12-06 11:23:47 +00:00
parent f8da61b0f1
commit d345484675
2 changed files with 95 additions and 35 deletions

View File

@ -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) ||

View File

@ -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)
{
@ -189,6 +192,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",
@ -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;