diff options
| author | blymn <blymn@NetBSD.org> | 2013-12-06 11:23:47 +0000 |
|---|---|---|
| committer | blymn <blymn@NetBSD.org> | 2013-12-06 11:23:47 +0000 |
| commit | cd3fcee8ba72145f28b4be42408d174b23d3359f (patch) | |
| tree | ffa8127a523d5198aa53b1762cb49e3bbba0059c /lib/libcurses | |
| parent | 08bb0b90d820e2cca0050d8f1bd0afca41007999 (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.c | 95 | ||||
| -rw-r--r-- | lib/libcurses/touchwin.c | 35 |
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; |
