Annotation of src/lib/libcurses/refresh.c, Revision 1.116
1.116 ! rin 1: /* $NetBSD: refresh.c,v 1.115 2021/09/06 07:45:48 rin Exp $ */
1.8 mikel 2:
1.1 cgd 3: /*
1.7 cgd 4: * Copyright (c) 1981, 1993, 1994
1.5 cgd 5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.58 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.8 mikel 32: #include <sys/cdefs.h>
1.1 cgd 33: #ifndef lint
1.8 mikel 34: #if 0
1.7 cgd 35: static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94";
1.8 mikel 36: #else
1.116 ! rin 37: __RCSID("$NetBSD: refresh.c,v 1.115 2021/09/06 07:45:48 rin Exp $");
1.8 mikel 38: #endif
1.11 mrg 39: #endif /* not lint */
1.1 cgd 40:
1.81 roy 41: #include <poll.h>
1.38 matt 42: #include <stdlib.h>
1.4 mycroft 43: #include <string.h>
1.113 mrg 44: #include <assert.h>
1.1 cgd 45:
1.7 cgd 46: #include "curses.h"
1.15 blymn 47: #include "curses_private.h"
1.7 cgd 48:
1.110 blymn 49: static void domvcur(WINDOW *, int, int, int, int);
1.91 roy 50: static void putattr(__LDATA *);
51: static void putattr_out(__LDATA *);
52: static int putch(__LDATA *, __LDATA *, int, int);
53: static int putchbr(__LDATA *, __LDATA *, __LDATA *, int, int);
1.65 blymn 54: static int makech(int);
55: static void quickch(void);
56: static void scrolln(int, int, int, int, int);
57:
1.86 roy 58: static int _wnoutrefresh(WINDOW *, int, int, int, int, int, int);
1.65 blymn 59:
60: #ifdef HAVE_WCHAR
1.95 uwe 61: static int celleq(__LDATA *, __LDATA *);
62: static int lineeq(__LDATA *, __LDATA *, size_t);
1.96 uwe 63: #else /* !HAVE_WCHAR */
64: static inline int
65: celleq(__LDATA *x, __LDATA *y)
66: {
67: return memcmp(x, y, sizeof(__LDATA)) == 0;
68: }
69:
70: static int
71: lineeq(__LDATA *xl, __LDATA *yl, size_t len)
72: {
73: return memcmp(xl, yl, len * __LDATASIZE) == 0;
74: }
1.65 blymn 75: #endif /* HAVE_WCHAR */
1.55 dsl 76:
1.85 roy 77: #define CHECK_INTERVAL 5 /* Change N lines before checking typeahead */
78:
1.17 blymn 79: #ifndef _CURSES_USE_MACROS
80:
81: /*
82: * refresh --
83: * Make the current screen look like "stdscr" over the area covered by
84: * stdscr.
85: */
86: int
87: refresh(void)
88: {
1.83 roy 89:
1.17 blymn 90: return wrefresh(stdscr);
91: }
92:
93: #endif
94:
1.4 mycroft 95: /*
1.23 jdc 96: * wnoutrefresh --
97: * Add the contents of "win" to the virtual window.
98: */
99: int
100: wnoutrefresh(WINDOW *win)
101: {
1.83 roy 102:
1.115 rin 103: __CTRACE(__CTRACE_REFRESH,
104: "wnoutrefresh: win %p, begy %d, begx %d, maxy %d, maxx %d\n",
105: win, win->begy, win->begx, win->maxy, win->maxx);
1.50 jdc 106:
1.86 roy 107: return _wnoutrefresh(win, 0, 0, win->begy, win->begx,
108: win->maxy, win->maxx);
1.44 blymn 109: }
110:
1.50 jdc 111: /*
112: * pnoutrefresh --
113: * Add the contents of "pad" to the virtual window.
114: */
115: int
116: pnoutrefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx,
1.83 roy 117: int smaxy, int smaxx)
1.50 jdc 118: {
119: int pmaxy, pmaxx;
120:
1.64 jdc 121: __CTRACE(__CTRACE_REFRESH, "pnoutrefresh: pad %p, flags 0x%08x\n",
122: pad, pad->flags);
123: __CTRACE(__CTRACE_REFRESH,
124: "pnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
125: pbegy, pbegx, sbegy, sbegx, smaxy, smaxx);
1.50 jdc 126:
127: /* SUS says if these are negative, they should be treated as zero */
128: if (pbegy < 0)
129: pbegy = 0;
130: if (pbegx < 0)
131: pbegx = 0;
132: if (sbegy < 0)
133: sbegy = 0;
134: if (sbegx < 0)
135: sbegx = 0;
136:
1.86 roy 137: /* Calculate rectangle on pad - used by _wnoutrefresh */
1.50 jdc 138: pmaxy = pbegy + smaxy - sbegy + 1;
139: pmaxx = pbegx + smaxx - sbegx + 1;
140:
141: /* Check rectangle fits in pad */
142: if (pmaxy > pad->maxy - pad->begy)
143: pmaxy = pad->maxy - pad->begy;
144: if (pmaxx > pad->maxx - pad->begx)
145: pmaxx = pad->maxx - pad->begx;
1.65 blymn 146:
1.50 jdc 147: if (smaxy - sbegy < 0 || smaxx - sbegx < 0 )
148: return ERR;
149:
1.86 roy 150: return _wnoutrefresh(pad,
1.50 jdc 151: pad->begy + pbegy, pad->begx + pbegx, pad->begy + sbegy,
152: pad->begx + sbegx, pmaxy, pmaxx);
153: }
1.44 blymn 154:
155: /*
1.86 roy 156: * _wnoutrefresh --
1.65 blymn 157: * Does the grunt work for wnoutrefresh to the given screen.
1.50 jdc 158: * Copies the part of the window given by the rectangle
159: * (begy, begx) to (maxy, maxx) at screen position (wbegy, wbegx).
1.44 blymn 160: */
1.86 roy 161: static int
162: _wnoutrefresh(WINDOW *win, int begy, int begx, int wbegy, int wbegx,
163: int maxy, int maxx)
1.44 blymn 164: {
1.86 roy 165: SCREEN *screen = win->screen;
1.79 blymn 166: short sy, wy, wx, y_off, x_off, mx, dy_off, dx_off, endy;
1.105 uwe 167: int newy, newx;
1.79 blymn 168: __LINE *wlp, *vlp, *dwlp;
169: WINDOW *sub_win, *orig, *swin, *dwin;
1.23 jdc 170:
1.64 jdc 171: __CTRACE(__CTRACE_REFRESH, "_wnoutrefresh: win %p, flags 0x%08x\n",
172: win, win->flags);
173: __CTRACE(__CTRACE_REFRESH,
174: "_wnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n",
1.56 jdc 175: begy, begx, wbegy, wbegx, maxy, maxx);
1.23 jdc 176:
1.44 blymn 177: if (screen->curwin)
1.57 jdc 178: return OK;
179:
1.79 blymn 180: swin = dwin = win;
181: if (win->flags & __ISDERWIN)
182: swin = win->orig;
183:
1.57 jdc 184: /*
185: * Recurse through any sub-windows, mark as dirty lines on the parent
186: * window that are dirty on the sub-window and clear the dirty flag on
187: * the sub-window.
188: */
1.79 blymn 189: if (dwin->orig == 0) {
190: orig = dwin;
191: for (sub_win = dwin->nextp; sub_win != orig;
1.57 jdc 192: sub_win = sub_win->nextp) {
1.79 blymn 193: if (sub_win->flags & __ISDERWIN)
194: continue;
1.64 jdc 195: __CTRACE(__CTRACE_REFRESH,
196: "wnout_refresh: win %p, sub_win %p\n",
1.57 jdc 197: orig, sub_win);
198: for (sy = 0; sy < sub_win->maxy; sy++) {
1.74 jdc 199: if (sub_win->alines[sy]->flags & __ISDIRTY) {
1.71 roy 200: orig->alines[sy + sub_win->begy - orig->begy]->flags
1.65 blymn 201: |= __ISDIRTY;
1.71 roy 202: sub_win->alines[sy]->flags
1.65 blymn 203: &= ~__ISDIRTY;
1.57 jdc 204: }
1.78 blymn 205: if (sub_win->alines[sy]->flags & __ISFORCED) {
206: orig->alines[sy + sub_win->begy - orig->begy]->flags
207: |= __ISFORCED;
208: sub_win->alines[sy]->flags
209: &= ~__ISFORCED;
210: }
1.57 jdc 211: }
212: }
213: }
1.50 jdc 214:
215: /* Check that cursor position on "win" is valid for "__virtscr" */
1.105 uwe 216: newy = wbegy + dwin->cury - begy;
217: newx = wbegx + dwin->curx - begx;
218: if (begy <= dwin->cury && dwin->cury < maxy
219: && 0 <= newy && newy < screen->__virtscr->maxy)
220: screen->__virtscr->cury = newy;
221: if (begx <= dwin->curx && dwin->curx < maxx
222: && 0 <= newx && newx < screen->__virtscr->maxx)
223: screen->__virtscr->curx = newx;
1.23 jdc 224:
225: /* Copy the window flags from "win" to "__virtscr" */
1.79 blymn 226: if (dwin->flags & __CLEAROK) {
227: if (dwin->flags & __FULLWIN)
1.44 blymn 228: screen->__virtscr->flags |= __CLEAROK;
1.79 blymn 229: dwin->flags &= ~__CLEAROK;
1.33 mycroft 230: }
1.44 blymn 231: screen->__virtscr->flags &= ~__LEAVEOK;
1.79 blymn 232: screen->__virtscr->flags |= dwin->flags;
1.23 jdc 233:
1.79 blymn 234: if ((dwin->flags & __ISDERWIN) != 0)
235: endy = begy + maxy;
236: else
237: endy = maxy;
238:
239: for (wy = begy, y_off = wbegy, dy_off = 0; wy < endy &&
1.83 roy 240: y_off < screen->__virtscr->maxy; wy++, y_off++, dy_off++)
241: {
1.79 blymn 242: wlp = swin->alines[wy];
243: dwlp = dwin->alines[dy_off];
1.23 jdc 244: #ifdef DEBUG
1.64 jdc 245: __CTRACE(__CTRACE_REFRESH,
246: "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n",
1.57 jdc 247: wy, *wlp->firstchp, *wlp->lastchp, wlp->flags);
1.79 blymn 248:
1.108 blymn 249: char *_wintype;
250:
251: if ((dwin->flags & __ISDERWIN) != 0)
252: _wintype = "derwin";
253: else
254: _wintype = "dwin";
255:
256: __CTRACE(__CTRACE_REFRESH,
1.115 rin 257: "_wnoutrefresh: %s wy %d\tf %d\tl %d\tflags %x\n",
258: _wintype, dy_off, *dwlp->firstchp, *dwlp->lastchp,
259: dwlp->flags);
1.108 blymn 260: __CTRACE(__CTRACE_REFRESH,
1.115 rin 261: "_wnoutrefresh: %s maxx %d\tch_off %d wlp %p\n",
262: _wintype, dwin->maxx, dwin->ch_off, wlp);
1.23 jdc 263: #endif
1.79 blymn 264: if (((wlp->flags & (__ISDIRTY | __ISFORCED)) == 0) &&
265: ((dwlp->flags & (__ISDIRTY | __ISFORCED)) == 0))
1.33 mycroft 266: continue;
1.109 blymn 267: __CTRACE(__CTRACE_REFRESH,
1.115 rin 268: "_wnoutrefresh: line y_off %d (dy_off %d) is dirty\n",
269: y_off, dy_off);
1.109 blymn 270:
271: wlp = swin->alines[wy];
1.71 roy 272: vlp = screen->__virtscr->alines[y_off];
1.33 mycroft 273:
1.79 blymn 274: if ((*wlp->firstchp < maxx + swin->ch_off &&
275: *wlp->lastchp >= swin->ch_off) ||
276: ((((dwin->flags & __ISDERWIN) != 0) &&
277: (*dwlp->firstchp < dwin->maxx + dwin->ch_off &&
1.83 roy 278: *dwlp->lastchp >= dwin->ch_off))))
279: {
1.57 jdc 280: /* Set start column */
281: wx = begx;
282: x_off = wbegx;
1.79 blymn 283: dx_off = 0;
284: /*
285: * if a derwin then source change pointers aren't
286: * relevant.
287: */
288: if ((dwin->flags & __ISDERWIN) != 0)
289: mx = wx + maxx;
290: else {
291: if (*wlp->firstchp - swin->ch_off > 0) {
292: wx += *wlp->firstchp - swin->ch_off;
293: x_off += *wlp->firstchp - swin->ch_off;
294: }
295: mx = maxx;
296: if (mx > *wlp->lastchp - swin->ch_off + 1)
297: mx = *dwlp->lastchp - dwin->ch_off + 1;
1.87 roy 298: if (x_off + (mx - wx) > screen->__virtscr->maxx)
299: mx -= (x_off + maxx) -
300: screen->__virtscr->maxx;
1.79 blymn 301: }
302:
1.23 jdc 303: /* Copy line from "win" to "__virtscr". */
1.57 jdc 304: while (wx < mx) {
1.64 jdc 305: __CTRACE(__CTRACE_REFRESH,
306: "_wnoutrefresh: copy from %d, "
1.77 jdc 307: "%d to %d, %d: %s, 0x%x",
308: wy, wx, y_off, x_off,
309: unctrl(wlp->line[wx].ch),
310: wlp->line[wx].attr);
1.115 rin 311: __CTRACE(__CTRACE_REFRESH,
312: " (curdest %s, 0x%x)",
1.109 blymn 313: unctrl(vlp->line[x_off].ch),
314: vlp->line[x_off].attr);
1.63 jdc 315: /* Copy character */
316: vlp->line[x_off].ch = wlp->line[wx].ch;
317: /* Copy attributes */
1.33 mycroft 318: vlp->line[x_off].attr = wlp->line[wx].attr;
1.52 jdc 319: /* Check for nca conflict with colour */
320: if ((vlp->line[x_off].attr & __COLOR) &&
1.87 roy 321: (vlp->line[x_off].attr & screen->nca))
1.52 jdc 322: vlp->line[x_off].attr &= ~__COLOR;
1.79 blymn 323: if (win->flags & __ISDERWIN) {
324: dwlp->line[dx_off].ch =
325: wlp->line[wx].ch;
1.83 roy 326: dwlp->line[dx_off].attr =
1.79 blymn 327: wlp->line[wx].attr;
328: }
329:
1.65 blymn 330: #ifdef HAVE_WCHAR
331: if (wlp->line[wx].ch
332: == (wchar_t)btowc((int) win->bch)) {
333: vlp->line[x_off].ch = win->bch;
1.87 roy 334: SET_WCOL(vlp->line[x_off], 1);
1.65 blymn 335: if (_cursesi_copy_nsp(win->bnsp,
336: &vlp->line[x_off])
337: == ERR)
338: return ERR;
1.79 blymn 339: if (win->flags & __ISDERWIN) {
340: dwlp->line[dx_off].ch =
341: win->bch;
342: SET_WCOL(dwlp->line[dx_off], 1);
343: if (_cursesi_copy_nsp(win->bnsp,
344: &dwlp->line[dx_off])
1.83 roy 345: == ERR)
1.79 blymn 346: return ERR;
347: }
1.65 blymn 348: }
349: #endif /* HAVE_WCHAR */
1.77 jdc 350: __CTRACE(__CTRACE_REFRESH, " = %s, 0x%x\n",
351: unctrl(vlp->line[x_off].ch),
352: vlp->line[x_off].attr);
1.57 jdc 353: wx++;
354: x_off++;
1.79 blymn 355: dx_off++;
1.23 jdc 356: }
357:
358: /* Set flags on "__virtscr" and unset on "win". */
1.33 mycroft 359: if (wlp->flags & __ISPASTEOL)
360: vlp->flags |= __ISPASTEOL;
1.23 jdc 361: else
1.33 mycroft 362: vlp->flags &= ~__ISPASTEOL;
363: if (wlp->flags & __ISDIRTY)
364: vlp->flags |= __ISDIRTY;
1.78 blymn 365: if (wlp->flags & __ISFORCED)
366: vlp->flags |= __ISFORCED;
1.23 jdc 367:
368: #ifdef DEBUG
1.64 jdc 369: __CTRACE(__CTRACE_REFRESH,
370: "win: firstch = %d, lastch = %d\n",
1.33 mycroft 371: *wlp->firstchp, *wlp->lastchp);
1.79 blymn 372: if (win->flags & __ISDERWIN) {
373: __CTRACE(__CTRACE_REFRESH,
374: "derwin: fistch = %d, lastch = %d\n",
375: *dwlp->firstchp, *dwlp->lastchp);
376: }
1.23 jdc 377: #endif
378: /* Set change pointers on "__virtscr". */
1.33 mycroft 379: if (*vlp->firstchp >
1.78 blymn 380: *wlp->firstchp + wbegx - win->ch_off)
381: *vlp->firstchp =
382: *wlp->firstchp + wbegx - win->ch_off;
1.33 mycroft 383: if (*vlp->lastchp <
1.78 blymn 384: *wlp->lastchp + wbegx - win->ch_off)
385: *vlp->lastchp =
386: *wlp->lastchp + wbegx - win->ch_off;
1.79 blymn 387:
388: if (win->flags & __ISDERWIN) {
1.83 roy 389: if (*vlp->firstchp >
390: *dwlp->firstchp + wbegx - dwin->ch_off)
391: {
1.79 blymn 392: *vlp->firstchp =
393: *dwlp->firstchp + wbegx
394: - dwin->ch_off;
395: vlp->flags |= __ISDIRTY;
396: }
397:
398: if (*vlp->lastchp <
1.83 roy 399: *dwlp->lastchp + wbegx - dwin->ch_off)
400: {
1.79 blymn 401: *vlp->lastchp = *dwlp->lastchp
402: + wbegx - dwin->ch_off;
403: vlp->flags |= __ISDIRTY;
404: }
405: }
406:
1.64 jdc 407: __CTRACE(__CTRACE_REFRESH,
408: "__virtscr: firstch = %d, lastch = %d\n",
1.33 mycroft 409: *vlp->firstchp, *vlp->lastchp);
1.50 jdc 410: /*
1.78 blymn 411: * Unset change pointers only if a window and we
412: * are not forcing a redraw. A pad can be displayed
413: * again without any of the contents changing.
1.50 jdc 414: */
1.78 blymn 415: if ((!(win->flags & __ISPAD)) ||
1.83 roy 416: ((wlp->flags & __ISFORCED) == __ISFORCED))
417: {
1.50 jdc 418: /* Set change pointers on "win". */
419: if (*wlp->firstchp >= win->ch_off)
420: *wlp->firstchp = maxx + win->ch_off;
421: if (*wlp->lastchp < maxx + win->ch_off)
422: *wlp->lastchp = win->ch_off;
1.57 jdc 423: if ((*wlp->lastchp < *wlp->firstchp) ||
424: (*wlp->firstchp >= maxx + win->ch_off) ||
425: (*wlp->lastchp <= win->ch_off)) {
1.64 jdc 426: __CTRACE(__CTRACE_REFRESH,
427: "_wnoutrefresh: "
428: "line %d notdirty\n", wy);
1.80 jdc 429: wlp->flags &= ~(__ISDIRTY | __ISFORCED);
1.50 jdc 430: }
1.23 jdc 431: }
432: }
433: }
1.55 dsl 434: return OK;
1.23 jdc 435: }
436:
437: /*
1.4 mycroft 438: * wrefresh --
1.50 jdc 439: * Make the current screen look like "win" over the area covered by
1.4 mycroft 440: * win.
441: */
442: int
1.17 blymn 443: wrefresh(WINDOW *win)
1.1 cgd 444: {
1.44 blymn 445: int retval;
1.79 blymn 446: int pbegx, pbegy;
1.45 blymn 447:
1.64 jdc 448: __CTRACE(__CTRACE_REFRESH, "wrefresh: win %p\n", win);
1.50 jdc 449:
1.44 blymn 450: _cursesi_screen->curwin = (win == _cursesi_screen->curscr);
1.79 blymn 451: if (!_cursesi_screen->curwin) {
452: pbegx = pbegy = 0;
453: if ((win->flags & __ISDERWIN) == __ISDERWIN) {
454: pbegx = win->derx;
455: pbegy = win->dery;
456: __CTRACE(__CTRACE_REFRESH, "wrefresh: derwin, begy = %d, begx = %x\n",
457: pbegy, pbegx);
458: }
1.86 roy 459: retval = _wnoutrefresh(win, pbegy, pbegx, win->begy, win->begx,
460: win->maxy, win->maxx);
1.79 blymn 461: } else
1.23 jdc 462: retval = OK;
463: if (retval == OK) {
464: retval = doupdate();
1.55 dsl 465: if (!(win->flags & __LEAVEOK)) {
1.24 jdc 466: win->cury = max(0, curscr->cury - win->begy);
467: win->curx = max(0, curscr->curx - win->begx);
468: }
1.23 jdc 469: }
1.43 blymn 470: _cursesi_screen->curwin = 0;
1.83 roy 471: return retval;
1.50 jdc 472: }
473:
474: /*
475: * prefresh --
476: * Make the current screen look like "pad" over the area coverd by
477: * the specified area of pad.
478: */
479: int
480: prefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx,
1.65 blymn 481: int smaxy, int smaxx)
1.50 jdc 482: {
483: int retval;
484:
1.64 jdc 485: __CTRACE(__CTRACE_REFRESH, "prefresh: pad %p, flags 0x%08x\n",
486: pad, pad->flags);
1.59 jdc 487: /* Retain values in case pechochar() is called. */
488: pad->pbegy = pbegy;
489: pad->pbegx = pbegx;
490: pad->sbegy = sbegy;
491: pad->sbegx = sbegx;
492: pad->smaxy = smaxy;
493: pad->smaxx = smaxx;
1.50 jdc 494:
495: /* Use pnoutrefresh() to avoid duplicating code here */
496: retval = pnoutrefresh(pad, pbegy, pbegx, sbegy, sbegx, smaxy, smaxx);
497: if (retval == OK) {
498: retval = doupdate();
1.55 dsl 499: if (!(pad->flags & __LEAVEOK)) {
1.103 uwe 500: pad->cury = max(0, pbegy + (curscr->cury - sbegy));
501: pad->curx = max(0, pbegx + (curscr->curx - sbegx));
1.50 jdc 502: }
503: }
1.83 roy 504: return retval;
1.23 jdc 505: }
506:
507: /*
508: * doupdate --
509: * Make the current screen look like the virtual window "__virtscr".
510: */
511: int
512: doupdate(void)
513: {
514: WINDOW *win;
1.78 blymn 515: __LINE *wlp, *vlp;
1.23 jdc 516: short wy;
1.85 roy 517: int dnum, was_cleared, changed;
1.9 phil 518:
519: /* Check if we need to restart ... */
1.43 blymn 520: if (_cursesi_screen->endwin)
1.9 phil 521: __restartwin();
1.7 cgd 522:
1.43 blymn 523: if (_cursesi_screen->curwin)
1.23 jdc 524: win = curscr;
525: else
1.44 blymn 526: win = _cursesi_screen->__virtscr;
1.23 jdc 527:
1.4 mycroft 528: /* Initialize loop parameters. */
1.43 blymn 529: _cursesi_screen->ly = curscr->cury;
530: _cursesi_screen->lx = curscr->curx;
1.1 cgd 531: wy = 0;
532:
1.65 blymn 533: if (!_cursesi_screen->curwin) {
1.5 cgd 534: for (wy = 0; wy < win->maxy; wy++) {
1.71 roy 535: wlp = win->alines[wy];
1.116 ! rin 536: if (wlp->flags & __ISDIRTY)
! 537: wlp->hash = __hash_line(wlp->line, win->maxx);
1.5 cgd 538: }
1.65 blymn 539: }
1.5 cgd 540:
1.78 blymn 541: was_cleared = 0;
1.43 blymn 542: if ((win->flags & __CLEAROK) || (curscr->flags & __CLEAROK) ||
1.83 roy 543: _cursesi_screen->curwin)
544: {
1.23 jdc 545: if (curscr->wattr & __COLOR)
546: __unsetattr(0);
1.72 roy 547: tputs(clear_screen, 0, __cputchar);
1.43 blymn 548: _cursesi_screen->ly = 0;
549: _cursesi_screen->lx = 0;
550: if (!_cursesi_screen->curwin) {
1.23 jdc 551: curscr->flags &= ~__CLEAROK;
552: curscr->cury = 0;
553: curscr->curx = 0;
554: werase(curscr);
1.1 cgd 555: }
1.23 jdc 556: __touchwin(win);
1.5 cgd 557: win->flags &= ~__CLEAROK;
1.78 blymn 558: /* note we cleared for later */
559: was_cleared = 1;
1.1 cgd 560: }
1.72 roy 561: if (!cursor_address) {
1.5 cgd 562: if (win->curx != 0)
1.39 itojun 563: __cputchar('\n');
1.43 blymn 564: if (!_cursesi_screen->curwin)
1.1 cgd 565: werase(curscr);
566: }
1.64 jdc 567: __CTRACE(__CTRACE_REFRESH, "doupdate: (%p): curwin = %d\n", win,
1.65 blymn 568: _cursesi_screen->curwin);
1.64 jdc 569: __CTRACE(__CTRACE_REFRESH, "doupdate: \tfirstch\tlastch\n");
1.5 cgd 570:
1.43 blymn 571: if (!_cursesi_screen->curwin) {
1.5 cgd 572: /*
573: * Invoke quickch() only if more than a quarter of the lines
574: * in the window are dirty.
575: */
576: for (wy = 0, dnum = 0; wy < win->maxy; wy++)
1.71 roy 577: if (win->alines[wy]->flags & __ISDIRTY)
1.5 cgd 578: dnum++;
579: if (!__noqch && dnum > (int) win->maxy / 4)
1.23 jdc 580: quickch();
1.5 cgd 581: }
582:
583: #ifdef DEBUG
1.11 mrg 584: {
585: int i, j;
586:
1.64 jdc 587: __CTRACE(__CTRACE_REFRESH,
588: "#####################################\n");
1.65 blymn 589: __CTRACE(__CTRACE_REFRESH,
590: "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
591: stdscr, curscr, _cursesi_screen->__virtscr);
1.5 cgd 592: for (i = 0; i < curscr->maxy; i++) {
1.64 jdc 593: __CTRACE(__CTRACE_REFRESH, "C: %d:", i);
594: __CTRACE(__CTRACE_REFRESH, " 0x%x \n",
1.71 roy 595: curscr->alines[i]->hash);
1.7 cgd 596: for (j = 0; j < curscr->maxx; j++)
1.64 jdc 597: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 598: curscr->alines[i]->line[j].ch);
1.64 jdc 599: __CTRACE(__CTRACE_REFRESH, "\n");
600: __CTRACE(__CTRACE_REFRESH, " attr:");
1.7 cgd 601: for (j = 0; j < curscr->maxx; j++)
1.64 jdc 602: __CTRACE(__CTRACE_REFRESH, " %x",
1.71 roy 603: curscr->alines[i]->line[j].attr);
1.64 jdc 604: __CTRACE(__CTRACE_REFRESH, "\n");
605: __CTRACE(__CTRACE_REFRESH, "W: %d:", i);
606: __CTRACE(__CTRACE_REFRESH, " 0x%x \n",
1.71 roy 607: win->alines[i]->hash);
1.64 jdc 608: __CTRACE(__CTRACE_REFRESH, " 0x%x ",
1.71 roy 609: win->alines[i]->flags);
1.23 jdc 610: for (j = 0; j < win->maxx; j++)
1.64 jdc 611: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 612: win->alines[i]->line[j].ch);
1.64 jdc 613: __CTRACE(__CTRACE_REFRESH, "\n");
614: __CTRACE(__CTRACE_REFRESH, " attr:");
1.23 jdc 615: for (j = 0; j < win->maxx; j++)
1.64 jdc 616: __CTRACE(__CTRACE_REFRESH, " %x",
1.71 roy 617: win->alines[i]->line[j].attr);
1.64 jdc 618: __CTRACE(__CTRACE_REFRESH, "\n");
1.65 blymn 619: #ifdef HAVE_WCHAR
620: __CTRACE(__CTRACE_REFRESH, " nsp:");
621: for (j = 0; j < curscr->maxx; j++)
622: __CTRACE(__CTRACE_REFRESH, " %p",
1.71 roy 623: win->alines[i]->line[j].nsp);
1.65 blymn 624: __CTRACE(__CTRACE_REFRESH, "\n");
625: __CTRACE(__CTRACE_REFRESH, " bnsp:");
626: for (j = 0; j < curscr->maxx; j++)
627: __CTRACE(__CTRACE_REFRESH, " %p",
628: win->bnsp);
629: __CTRACE(__CTRACE_REFRESH, "\n");
630: #endif /* HAVE_WCHAR */
1.5 cgd 631: }
1.11 mrg 632: }
1.65 blymn 633: #endif /* DEBUG */
1.5 cgd 634:
1.85 roy 635: changed = 0;
1.5 cgd 636: for (wy = 0; wy < win->maxy; wy++) {
1.71 roy 637: wlp = win->alines[wy];
1.78 blymn 638: vlp = _cursesi_screen->__virtscr->alines[win->begy + wy];
1.114 rin 639: /* XXX: remove this */
1.64 jdc 640: __CTRACE(__CTRACE_REFRESH,
641: "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n",
642: wy, *wlp->firstchp, *wlp->lastchp, wlp->flags);
1.43 blymn 643: if (!_cursesi_screen->curwin)
1.71 roy 644: curscr->alines[wy]->hash = wlp->hash;
1.84 roy 645: if (wlp->flags & __ISDIRTY || wlp->flags & __ISFORCED) {
1.65 blymn 646: __CTRACE(__CTRACE_REFRESH,
647: "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy,
648: *wlp->firstchp, *wlp->lastchp);
1.78 blymn 649: /*
1.83 roy 650: * We have just cleared so don't force an update
651: * otherwise we spray neeedless blanks to a cleared
652: * screen.
653: */
1.78 blymn 654: if (was_cleared == 1)
655: win->alines[wy]->flags &= ~__ISFORCED;
656:
1.23 jdc 657: if (makech(wy) == ERR)
1.83 roy 658: return ERR;
1.1 cgd 659: else {
1.33 mycroft 660: if (*wlp->firstchp >= 0)
661: *wlp->firstchp = win->maxx;
662: if (*wlp->lastchp < win->maxx)
1.78 blymn 663: *wlp->lastchp = win->ch_off;
1.33 mycroft 664: if (*wlp->lastchp < *wlp->firstchp) {
1.64 jdc 665: __CTRACE(__CTRACE_REFRESH,
666: "doupdate: line %d notdirty\n", wy);
1.78 blymn 667: wlp->flags &= ~(__ISDIRTY | __ISFORCED);
1.5 cgd 668: }
1.85 roy 669:
670: /* Check if we have input after
671: * changing N lines. */
672: if (_cursesi_screen->checkfd != -1 &&
673: ++changed == CHECK_INTERVAL)
674: {
675: struct pollfd fds[1];
676:
677: /* If we have input, abort. */
678: fds[0].fd = _cursesi_screen->checkfd;
679: fds[0].events = POLLIN;
680: if (poll(fds, 1, 0) > 0)
681: goto cleanup;
682: changed = 0;
683: }
1.1 cgd 684: }
1.78 blymn 685: }
686:
687: /*
688: * virtscr is now synced for the line, unset the change
689: * pointers.
690: */
691: if (*vlp->firstchp >= 0)
692: *vlp->firstchp = _cursesi_screen->__virtscr->maxx;
693: if (*vlp->lastchp <= _cursesi_screen->__virtscr->maxx)
694: *vlp->lastchp = 0;
1.5 cgd 695:
1.65 blymn 696: __CTRACE(__CTRACE_REFRESH, "\t%d\t%d\n",
1.64 jdc 697: *wlp->firstchp, *wlp->lastchp);
1.1 cgd 698: }
1.7 cgd 699:
1.64 jdc 700: __CTRACE(__CTRACE_REFRESH, "doupdate: ly=%d, lx=%d\n",
701: _cursesi_screen->ly, _cursesi_screen->lx);
1.1 cgd 702:
1.43 blymn 703: if (_cursesi_screen->curwin)
1.84 roy 704: domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx,
1.70 yamt 705: win->cury, win->curx);
1.1 cgd 706: else {
1.5 cgd 707: if (win->flags & __LEAVEOK) {
1.43 blymn 708: curscr->cury = _cursesi_screen->ly;
709: curscr->curx = _cursesi_screen->lx;
1.4 mycroft 710: } else {
1.84 roy 711: domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx,
1.43 blymn 712: win->cury, win->curx);
1.23 jdc 713: curscr->cury = win->cury;
714: curscr->curx = win->curx;
1.1 cgd 715: }
716: }
1.23 jdc 717:
1.81 roy 718: cleanup:
1.28 mycroft 719: /* Don't leave the screen with attributes set. */
720: __unsetattr(0);
1.65 blymn 721: #ifdef DEBUG
722: #ifdef HAVE_WCHAR
723: {
724: int i, j;
725:
726: __CTRACE(__CTRACE_REFRESH,
727: "***********after*****************\n");
728: __CTRACE(__CTRACE_REFRESH,
729: "stdscr(%p)-curscr(%p)-__virtscr(%p)\n",
730: stdscr, curscr, _cursesi_screen->__virtscr);
731: for (i = 0; i < curscr->maxy; i++) {
732: for (j = 0; j < curscr->maxx; j++)
733: __CTRACE(__CTRACE_REFRESH,
734: "[%d,%d](%x,%x,%p)-(%x,%x,%p)\n",
735: i, j,
1.71 roy 736: curscr->alines[i]->line[j].ch,
737: curscr->alines[i]->line[j].attr,
738: curscr->alines[i]->line[j].nsp,
739: _cursesi_screen->__virtscr->alines[i]->line[j].ch,
740: _cursesi_screen->__virtscr->alines[i]->line[j].attr,
741: _cursesi_screen->__virtscr->alines[i]->line[j].nsp);
1.65 blymn 742: }
743: }
744: #endif /* HAVE_WCHAR */
745: #endif /* DEBUG */
1.60 christos 746: return fflush(_cursesi_screen->outfd) == EOF ? ERR : OK;
1.1 cgd 747: }
748:
1.91 roy 749: static void
750: putattr(__LDATA *nsp)
751: {
752: attr_t off, on;
753:
754: __CTRACE(__CTRACE_REFRESH,
755: "makech: have attr %08x, need attr %08x\n",
756: curscr->wattr
757: #ifndef HAVE_WCHAR
758: & __ATTRIBUTES
759: #else
760: & WA_ATTRIBUTES
761: #endif
762: , nsp->attr
763: #ifndef HAVE_WCHAR
764: & __ATTRIBUTES
765: #else
766: & WA_ATTRIBUTES
767: #endif
768: );
769:
770: off = (~nsp->attr & curscr->wattr)
771: #ifndef HAVE_WCHAR
772: & __ATTRIBUTES
773: #else
774: & WA_ATTRIBUTES
775: #endif
776: ;
777:
778: /*
779: * Unset attributes as appropriate. Unset first
780: * so that the relevant attributes can be reset
781: * (because 'me' unsets 'mb', 'md', 'mh', 'mk',
782: * 'mp' and 'mr'). Check to see if we also turn off
783: * standout, attributes and colour.
784: */
785: if (off & __TERMATTR && exit_attribute_mode != NULL) {
786: tputs(exit_attribute_mode, 0, __cputchar);
787: curscr->wattr &= __mask_me;
788: off &= __mask_me;
789: }
790:
791: /*
792: * Exit underscore mode if appropriate.
793: * Check to see if we also turn off standout,
794: * attributes and colour.
795: */
796: if (off & __UNDERSCORE && exit_underline_mode != NULL) {
797: tputs(exit_underline_mode, 0, __cputchar);
798: curscr->wattr &= __mask_ue;
799: off &= __mask_ue;
800: }
801:
802: /*
803: * Exit standout mode as appropriate.
804: * Check to see if we also turn off underscore,
805: * attributes and colour.
806: * XXX
807: * Should use uc if so/se not available.
808: */
809: if (off & __STANDOUT && exit_standout_mode != NULL) {
810: tputs(exit_standout_mode, 0, __cputchar);
811: curscr->wattr &= __mask_se;
812: off &= __mask_se;
813: }
814:
815: if (off & __ALTCHARSET && exit_alt_charset_mode != NULL) {
816: tputs(exit_alt_charset_mode, 0, __cputchar);
817: curscr->wattr &= ~__ALTCHARSET;
818: }
819:
820: /* Set/change colour as appropriate. */
821: if (__using_color)
822: __set_color(curscr, nsp->attr & __COLOR);
823:
824: on = (nsp->attr & ~curscr->wattr)
825: #ifndef HAVE_WCHAR
826: & __ATTRIBUTES
827: #else
828: & WA_ATTRIBUTES
829: #endif
830: ;
831:
832: /*
833: * Enter standout mode if appropriate.
834: */
835: if (on & __STANDOUT &&
836: enter_standout_mode != NULL &&
837: exit_standout_mode != NULL)
838: {
839: tputs(enter_standout_mode, 0, __cputchar);
840: curscr->wattr |= __STANDOUT;
841: }
842:
843: /*
844: * Enter underscore mode if appropriate.
845: * XXX
846: * Should use uc if us/ue not available.
847: */
848: if (on & __UNDERSCORE &&
849: enter_underline_mode != NULL &&
850: exit_underline_mode != NULL)
851: {
852: tputs(enter_underline_mode, 0, __cputchar);
853: curscr->wattr |= __UNDERSCORE;
854: }
855:
856: /*
857: * Set other attributes as appropriate.
858: */
859: if (exit_attribute_mode != NULL) {
860: if (on & __BLINK && enter_blink_mode != NULL)
861: {
862: tputs(enter_blink_mode, 0, __cputchar);
863: curscr->wattr |= __BLINK;
864: }
865: if (on & __BOLD && enter_bold_mode != NULL)
866: {
867: tputs(enter_bold_mode, 0, __cputchar);
868: curscr->wattr |= __BOLD;
869: }
870: if (on & __DIM && enter_dim_mode != NULL)
871: {
872: tputs(enter_dim_mode, 0, __cputchar);
873: curscr->wattr |= __DIM;
874: }
875: if (on & __BLANK && enter_secure_mode != NULL)
876: {
877: tputs(enter_secure_mode, 0, __cputchar);
878: curscr->wattr |= __BLANK;
879: }
880: if (on & __PROTECT && enter_protected_mode != NULL)
881: {
882: tputs(enter_protected_mode, 0, __cputchar);
883: curscr->wattr |= __PROTECT;
884: }
885: if (on & __REVERSE && enter_reverse_mode != NULL)
886: {
887: tputs(enter_reverse_mode, 0, __cputchar);
888: curscr->wattr |= __REVERSE;
889: }
890: #ifdef HAVE_WCHAR
891: if (on & WA_TOP && enter_top_hl_mode != NULL)
892: {
893: tputs(enter_top_hl_mode, 0, __cputchar);
894: curscr->wattr |= WA_TOP;
895: }
896: if (on & WA_LOW && enter_low_hl_mode != NULL)
897: {
898: tputs(enter_low_hl_mode, 0, __cputchar);
899: curscr->wattr |= WA_LOW;
900: }
901: if (on & WA_LEFT && enter_left_hl_mode != NULL)
902: {
903: tputs(enter_left_hl_mode, 0, __cputchar);
904: curscr->wattr |= WA_LEFT;
905: }
906: if (on & WA_RIGHT && enter_right_hl_mode != NULL)
907: {
908: tputs(enter_right_hl_mode, 0, __cputchar);
909: curscr->wattr |= WA_RIGHT;
910: }
911: if (on & WA_HORIZONTAL && enter_horizontal_hl_mode != NULL)
912: {
913: tputs(enter_horizontal_hl_mode, 0, __cputchar);
914: curscr->wattr |= WA_HORIZONTAL;
915: }
916: if (on & WA_VERTICAL && enter_vertical_hl_mode != NULL)
917: {
918: tputs(enter_vertical_hl_mode, 0, __cputchar);
919: curscr->wattr |= WA_VERTICAL;
920: }
921: #endif /* HAVE_WCHAR */
922: }
923:
924: /* Enter/exit altcharset mode as appropriate. */
925: if (on & __ALTCHARSET && enter_alt_charset_mode != NULL &&
926: exit_alt_charset_mode != NULL) {
927: tputs(enter_alt_charset_mode, 0, __cputchar);
928: curscr->wattr |= __ALTCHARSET;
929: }
930: }
931:
932: static void
933: putattr_out(__LDATA *nsp)
934: {
935:
936: if (underline_char &&
937: ((nsp->attr & __STANDOUT) || (nsp->attr & __UNDERSCORE)))
938: {
939: __cputchar('\b');
940: tputs(underline_char, 0, __cputchar);
941: }
942: }
943:
1.90 roy 944: static int
945: putch(__LDATA *nsp, __LDATA *csp, int wy, int wx)
946: {
947:
1.91 roy 948: if (csp != NULL)
949: putattr(nsp);
950:
1.90 roy 951: if (!_cursesi_screen->curwin && csp) {
952: csp->attr = nsp->attr;
953: csp->ch = nsp->ch;
954: #ifdef HAVE_WCHAR
955: if (_cursesi_copy_nsp(nsp->nsp, csp) == ERR)
956: return ERR;
957: #endif /* HAVE_WCHAR */
958: }
959:
960: #ifndef HAVE_WCHAR
961: __cputchar((int)nsp->ch);
962: #else
963: if (WCOL(*nsp) <= 0)
1.91 roy 964: goto out;
1.90 roy 965: __cputwchar((int)nsp->ch);
966: __CTRACE(__CTRACE_REFRESH,
967: "makech: (%d,%d)putwchar(0x%x)\n", wy, wx - 1, nsp->ch);
968:
969: /* Output non-spacing characters for the cell. */
970: __cursesi_putnsp(nsp->nsp, wy, wx);
1.91 roy 971: out:
1.90 roy 972: #endif /* HAVE_WCHAR */
973:
1.91 roy 974: if (csp != NULL)
975: putattr_out(nsp);
1.90 roy 976: return OK;
977: }
978:
979: static int
980: putchbr(__LDATA *nsp, __LDATA *csp, __LDATA *psp, int wy, int wx)
981: {
982: int error, cw, pcw;
983:
984: /* Can safely print to bottom right corner. */
985: if (!auto_right_margin)
986: return putch(nsp, csp, wy, wx);
987:
988: /* Disable auto margins temporarily. */
989: if (enter_am_mode && exit_am_mode) {
1.102 roy 990: tputs(exit_am_mode, 0, __cputchar);
991: error = putch(nsp, csp, wy, wx);
1.90 roy 992: tputs(enter_am_mode, 0, __cputchar);
993: return error;
994: }
995:
1.106 roy 996: /* We need to insert characters. */
1.90 roy 997: #ifdef HAVE_WCHAR
1.106 roy 998: cw = WCOL(*nsp);
999: pcw = WCOL(*psp);
1000: if (cw < 1 || pcw < 1)
1.90 roy 1001: return ERR; /* Nothing to insert */
1002:
1.106 roy 1003: /* When inserting a wide character, we need something other than
1.90 roy 1004: * insert_character. */
1005: if (pcw > 1 &&
1006: !(parm_ich != NULL ||
1007: (enter_insert_mode != NULL && exit_insert_mode != NULL)))
1008: return ERR;
1009: #else
1010: cw = pcw = 1;
1011: #endif /* HAVE_WCHAR */
1012:
1013: /* Write the corner character at wx - pcw. */
1014: __mvcur(wy, wx, wy, wx - pcw, 1);
1015: if (putch(nsp, csp, wy, wx) == ERR)
1016: return ERR;
1017:
1018: /* Move cursor back. */
1019: __mvcur(wy, wx - pcw + cw, wy, wx - cw, 1);
1020:
1.91 roy 1021: putattr(psp);
1022:
1.90 roy 1023: /* Enter insert mode. */
1024: if (pcw == 1 && insert_character != NULL)
1025: tputs(insert_character, 0, __cputchar);
1026: else if (parm_ich != NULL)
1027: tputs(tiparm(parm_ich, (long)pcw), 0, __cputchar);
1028: else if (enter_insert_mode != NULL && exit_insert_mode != NULL)
1029: tputs(enter_insert_mode, 0, __cputchar);
1030: else
1031: return ERR;
1032:
1033: /* Insert the old character back. */
1034: error = putch(psp, NULL, wy, wx - pcw);
1035:
1036: /* Exit insert mode. */
1037: if (insert_character != NULL || parm_ich != NULL)
1038: ;
1039: else if (enter_insert_mode != NULL && exit_insert_mode != NULL)
1040: tputs(exit_insert_mode, 0, __cputchar);
1041:
1.91 roy 1042: putattr_out(psp);
1043:
1.90 roy 1044: return error;
1045: }
1046:
1.1 cgd 1047: /*
1.4 mycroft 1048: * makech --
1049: * Make a change on the screen.
1.1 cgd 1050: */
1.4 mycroft 1051: static int
1.65 blymn 1052: makech(int wy)
1.1 cgd 1053: {
1.23 jdc 1054: WINDOW *win;
1.65 blymn 1055: static __LDATA blank;
1.90 roy 1056: __LDATA *nsp, *csp, *cp, *cep, *fsp;
1.78 blymn 1057: __LINE *wlp;
1.66 blymn 1058: size_t clsp, nlsp; /* Last space in lines. */
1.90 roy 1059: int lch, wx, chw;
1.72 roy 1060: const char *ce;
1.23 jdc 1061: attr_t lspc; /* Last space colour */
1.5 cgd 1062:
1.8 mikel 1063: #ifdef __GNUC__
1.23 jdc 1064: nlsp = lspc = 0; /* XXX gcc -Wuninitialized */
1.8 mikel 1065: #endif
1.43 blymn 1066: if (_cursesi_screen->curwin)
1.23 jdc 1067: win = curscr;
1068: else
1069: win = __virtscr;
1.65 blymn 1070: #ifdef HAVE_WCHAR
1.83 roy 1071: blank.ch = (wchar_t)btowc((int) win->bch);
1.65 blymn 1072: blank.attr = 0;
1073: if (_cursesi_copy_nsp(win->bnsp, &blank) == ERR)
1074: return ERR;
1.83 roy 1075: SET_WCOL(blank, 1);
1.65 blymn 1076: #endif /* HAVE_WCHAR */
1077: #ifdef DEBUG
1078: #if HAVE_WCHAR
1079: {
1080: int x;
1081: __LDATA *lp, *vlp;
1082:
1083: __CTRACE(__CTRACE_REFRESH,
1084: "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n",
1085: wy, curscr, __virtscr);
1086: for (x = 0; x < curscr->maxx; x++) {
1.71 roy 1087: lp = &curscr->alines[wy]->line[x];
1088: vlp = &__virtscr->alines[wy]->line[x];
1.65 blymn 1089: __CTRACE(__CTRACE_REFRESH,
1090: "[%d,%d](%x,%x,%x,%x,%p)-"
1091: "(%x,%x,%x,%x,%p)\n",
1092: wy, x, lp->ch, lp->attr,
1093: win->bch, win->battr, lp->nsp,
1094: vlp->ch, vlp->attr,
1095: win->bch, win->battr, vlp->nsp);
1096: }
1097: }
1098: #endif /* HAVE_WCHAR */
1099: #endif /* DEBUG */
1.5 cgd 1100: /* Is the cursor still on the end of the last line? */
1.71 roy 1101: if (wy > 0 && curscr->alines[wy - 1]->flags & __ISPASTEOL) {
1.84 roy 1102: domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx,
1.43 blymn 1103: _cursesi_screen->ly + 1, 0);
1104: _cursesi_screen->ly++;
1105: _cursesi_screen->lx = 0;
1.5 cgd 1106: }
1.78 blymn 1107: wlp = win->alines[wy];
1.71 roy 1108: wx = *win->alines[wy]->firstchp;
1.5 cgd 1109: if (wx < 0)
1110: wx = 0;
1.11 mrg 1111: else
1112: if (wx >= win->maxx)
1113: return (OK);
1.71 roy 1114: lch = *win->alines[wy]->lastchp;
1.1 cgd 1115: if (lch < 0)
1.83 roy 1116: return OK;
1.11 mrg 1117: else
1118: if (lch >= (int) win->maxx)
1119: lch = win->maxx - 1;
1.1 cgd 1120:
1.65 blymn 1121: if (_cursesi_screen->curwin) {
1.5 cgd 1122: csp = ␣
1.65 blymn 1123: __CTRACE(__CTRACE_REFRESH, "makech: csp is blank\n");
1124: } else {
1.71 roy 1125: csp = &curscr->alines[wy]->line[wx];
1.65 blymn 1126: __CTRACE(__CTRACE_REFRESH,
1127: "makech: csp is on curscr:(%d,%d)\n", wy, wx);
1128: }
1.1 cgd 1129:
1.90 roy 1130: nsp = fsp = &win->alines[wy]->line[wx];
1.65 blymn 1131: #ifdef DEBUG
1.83 roy 1132: if (_cursesi_screen->curwin)
1.65 blymn 1133: __CTRACE(__CTRACE_REFRESH,
1134: "makech: nsp is at curscr:(%d,%d)\n", wy, wx);
1135: else
1136: __CTRACE(__CTRACE_REFRESH,
1137: "makech: nsp is at __virtscr:(%d,%d)\n", wy, wx);
1138: #endif /* DEBUG */
1.72 roy 1139: if (clr_eol && !_cursesi_screen->curwin) {
1.71 roy 1140: cp = &win->alines[wy]->line[win->maxx - 1];
1.23 jdc 1141: lspc = cp->attr & __COLOR;
1.65 blymn 1142: #ifndef HAVE_WCHAR
1143: while (cp->ch == ' ' && cp->attr == lspc) /* XXX */
1.71 roy 1144: if (cp-- <= win->alines[wy]->line)
1.65 blymn 1145: break;
1146: #else
1147: while (cp->ch == ( wchar_t )btowc(( int )' ' )
1148: && ( cp->attr & WA_ATTRIBUTES ) == lspc)
1.71 roy 1149: if (cp-- <= win->alines[wy]->line)
1.1 cgd 1150: break;
1.65 blymn 1151: #endif /* HAVE_WCHAR */
1.71 roy 1152: if (win->alines[wy]->line > cp)
1.42 blymn 1153: nlsp = 0;
1.66 blymn 1154: else
1.71 roy 1155: nlsp = cp - win->alines[wy]->line;
1.1 cgd 1156: }
1.43 blymn 1157: if (!_cursesi_screen->curwin)
1.72 roy 1158: ce = clr_eol;
1.1 cgd 1159: else
1.4 mycroft 1160: ce = NULL;
1.1 cgd 1161:
1162: while (wx <= lch) {
1.98 uwe 1163: #ifndef HAVE_WCHAR
1.65 blymn 1164: __CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d\n", wx, lch);
1165: #else
1166: __CTRACE(__CTRACE_REFRESH, "makech: nsp=(%x,%x,%x,%x,%p)\n",
1167: nsp->ch, nsp->attr, win->bch, win->battr, nsp->nsp);
1168: __CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%x,%x,%p)\n",
1169: csp->ch, csp->attr, win->bch, win->battr, csp->nsp);
1.98 uwe 1170: #endif
1.78 blymn 1171: if (!(wlp->flags & __ISFORCED) &&
1.98 uwe 1172: #ifdef HAVE_WCHAR
1173: ((nsp->attr & __WCWIDTH) != __WCWIDTH) &&
1174: #endif
1175: celleq(nsp, csp))
1.83 roy 1176: {
1.65 blymn 1177: if (wx <= lch) {
1.98 uwe 1178: while (wx <= lch && celleq(nsp, csp)) {
1.65 blymn 1179: nsp++;
1180: if (!_cursesi_screen->curwin)
1181: ++csp;
1182: ++wx;
1183: }
1184: continue;
1185: }
1186: break;
1187: }
1.98 uwe 1188:
1.84 roy 1189: domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx);
1.5 cgd 1190:
1.64 jdc 1191: __CTRACE(__CTRACE_REFRESH, "makech: 1: wx = %d, ly= %d, "
1192: "lx = %d, newy = %d, newx = %d\n",
1.43 blymn 1193: wx, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx);
1194: _cursesi_screen->ly = wy;
1195: _cursesi_screen->lx = wx;
1.92 uwe 1196: while (wx <= lch &&
1.100 uwe 1197: ((wlp->flags & __ISFORCED) || !celleq(nsp, csp)))
1.83 roy 1198: {
1.99 uwe 1199: #ifndef HAVE_WCHAR
1200: if (ce != NULL && wx >= nlsp
1201: && nsp->ch == ' ' && nsp->attr == lspc)
1.65 blymn 1202: #else
1203: if (ce != NULL && wx >= nlsp
1.100 uwe 1204: && nsp->ch == (wchar_t)btowc((int)' ') /* XXX */
1205: && (nsp->attr & WA_ATTRIBUTES) == lspc)
1.99 uwe 1206: #endif
1.83 roy 1207: {
1.4 mycroft 1208: /* Check for clear to end-of-line. */
1.71 roy 1209: cep = &curscr->alines[wy]->line[win->maxx - 1];
1.65 blymn 1210: #ifndef HAVE_WCHAR
1211: while (cep->ch == ' ' && cep->attr == lspc) /* XXX */
1212: #else
1213: while (cep->ch == (wchar_t)btowc((int)' ')
1214: && (cep->attr & WA_ATTRIBUTES) == lspc)
1215: #endif /* HAVE_WCHAR */
1.5 cgd 1216: if (cep-- <= csp)
1.4 mycroft 1217: break;
1.78 blymn 1218: if (cep > (curscr->alines[wy]->line + win->begx * __LDATASIZE))
1219: clsp = cep - curscr->alines[wy]->line -
1.83 roy 1220: win->begx * __LDATASIZE;
1.78 blymn 1221: else
1222: clsp = 0;
1.64 jdc 1223: __CTRACE(__CTRACE_REFRESH,
1.67 veego 1224: "makech: clsp = %zu, nlsp = %zu\n",
1.20 jdc 1225: clsp, nlsp);
1.78 blymn 1226: __CTRACE(__CTRACE_REFRESH,
1227: "makech: line = %p, cep = %p, begx = %u\n",
1228: curscr->alines[wy]->line, cep, win->begx);
1.88 christos 1229: if (((clsp - nlsp >= strlen(ce) &&
1.20 jdc 1230: clsp < win->maxx * __LDATASIZE) ||
1231: wy == win->maxy - 1) &&
1.23 jdc 1232: (!(lspc & __COLOR) ||
1.83 roy 1233: ((lspc & __COLOR) && back_color_erase)))
1234: {
1.23 jdc 1235: __unsetattr(0);
1.47 jdc 1236: if (__using_color &&
1237: ((lspc & __COLOR) !=
1238: (curscr->wattr & __COLOR)))
1239: __set_color(curscr, lspc &
1240: __COLOR);
1.88 christos 1241: tputs(ce, 0, __cputchar);
1.43 blymn 1242: _cursesi_screen->lx = wx + win->begx;
1.5 cgd 1243: while (wx++ <= clsp) {
1.23 jdc 1244: csp->attr = lspc;
1.65 blymn 1245: #ifndef HAVE_WCHAR
1246: csp->ch = ' '; /* XXX */
1247: #else
1248: csp->ch = (wchar_t)btowc((int)' ');
1249: SET_WCOL( *csp, 1 );
1250: #endif /* HAVE_WCHAR */
1.113 mrg 1251: assert(csp != &blank);
1.5 cgd 1252: csp++;
1253: }
1.83 roy 1254: return OK;
1.1 cgd 1255: }
1.4 mycroft 1256: ce = NULL;
1257: }
1258:
1.90 roy 1259: #ifdef HAVE_WCHAR
1.106 roy 1260: chw = WCOL(*nsp);
1261: if (chw < 0)
1.107 roy 1262: chw = 0; /* match putch() */
1.90 roy 1263: #else
1264: chw = 1;
1265: #endif /* HAVE_WCHAR */
1266: if (wx + chw >= win->maxx &&
1.91 roy 1267: wy == win->maxy - 1 && !_cursesi_screen->curwin)
1268: {
1.89 roy 1269: if (win->flags & __ENDLINE)
1270: __unsetattr(1);
1271: if (!(win->flags & __SCROLLWIN)) {
1.90 roy 1272: int e;
1273:
1274: if (win->flags & __SCROLLOK)
1275: e = putch(nsp, csp, wy, wx);
1276: else
1277: e = putchbr(nsp, csp,
1278: nsp == fsp ? NULL : nsp - 1,
1279: wy, wx);
1280: if (e == ERR)
1281: return ERR;
1.7 cgd 1282: }
1.90 roy 1283: if (wx + chw < curscr->maxx) {
1.89 roy 1284: domvcur(win,
1285: _cursesi_screen->ly, wx,
1286: (int)(win->maxy - 1),
1287: (int)(win->maxx - 1));
1288: }
1289: _cursesi_screen->ly = win->maxy - 1;
1290: _cursesi_screen->lx = win->maxx - 1;
1291: return OK;
1.65 blymn 1292: }
1.90 roy 1293: if (wx + chw < win->maxx || wy < win->maxy - 1 ||
1.83 roy 1294: !(win->flags & __SCROLLWIN))
1295: {
1.90 roy 1296: if (putch(nsp, csp, wy, wx) == ERR)
1297: return ERR;
1.113 mrg 1298: if (!_cursesi_screen->curwin) {
1299: assert(csp != &blank);
1300: csp++;
1301: }
1.91 roy 1302: } else {
1303: putattr(nsp);
1304: putattr_out(nsp);
1.1 cgd 1305: }
1.90 roy 1306: wx += chw;
1.4 mycroft 1307: nsp++;
1.64 jdc 1308: __CTRACE(__CTRACE_REFRESH,
1309: "makech: 2: wx = %d, lx = %d\n",
1310: wx, _cursesi_screen->lx);
1.5 cgd 1311: }
1.43 blymn 1312: if (_cursesi_screen->lx == wx) /* If no change. */
1.4 mycroft 1313: break;
1.43 blymn 1314: _cursesi_screen->lx = wx;
1.72 roy 1315: if (_cursesi_screen->lx >= COLS && auto_right_margin)
1.43 blymn 1316: _cursesi_screen->lx = COLS - 1;
1.11 mrg 1317: else
1318: if (wx >= win->maxx) {
1.84 roy 1319: domvcur(win,
1320: _cursesi_screen->ly,
1.43 blymn 1321: _cursesi_screen->lx,
1322: _cursesi_screen->ly,
1.84 roy 1323: (int)(win->maxx - 1));
1.43 blymn 1324: _cursesi_screen->lx = win->maxx - 1;
1.11 mrg 1325: }
1.64 jdc 1326: __CTRACE(__CTRACE_REFRESH, "makech: 3: wx = %d, lx = %d\n",
1327: wx, _cursesi_screen->lx);
1.1 cgd 1328: }
1.65 blymn 1329: #ifdef DEBUG
1330: #if HAVE_WCHAR
1331: {
1332: int x;
1333: __LDATA *lp, *vlp;
1334:
1335: __CTRACE(__CTRACE_REFRESH,
1336: "makech-after: curscr(%p)-__virtscr(%p)\n",
1337: curscr, __virtscr );
1338: for (x = 0; x < curscr->maxx; x++) {
1.71 roy 1339: lp = &curscr->alines[wy]->line[x];
1340: vlp = &__virtscr->alines[wy]->line[x];
1.65 blymn 1341: __CTRACE(__CTRACE_REFRESH,
1342: "[%d,%d](%x,%x,%x,%x,%p)-"
1343: "(%x,%x,%x,%x,%p)\n",
1344: wy, x, lp->ch, lp->attr,
1345: win->bch, win->battr, lp->nsp,
1346: vlp->ch, vlp->attr,
1347: win->bch, win->battr, vlp->nsp);
1348: }
1349: }
1350: #endif /* HAVE_WCHAR */
1351: #endif /* DEBUG */
1.7 cgd 1352:
1.83 roy 1353: return OK;
1.1 cgd 1354: }
1355:
1356: /*
1.4 mycroft 1357: * domvcur --
1.19 jdc 1358: * Do a mvcur, leaving attributes if necessary.
1.1 cgd 1359: */
1.4 mycroft 1360: static void
1.110 blymn 1361: domvcur(WINDOW *win, int oy, int ox, int ny, int nx)
1.4 mycroft 1362: {
1.83 roy 1363:
1.112 rin 1364: __CTRACE(__CTRACE_REFRESH, "domvcur: (%d,%d)=>(%d,%d) win %p\n",
1.111 blymn 1365: oy, ox, ny, nx, win );
1.84 roy 1366:
1.23 jdc 1367: __unsetattr(1);
1.84 roy 1368:
1369: /* Don't move the cursor unless we need to. */
1370: if (oy == ny && ox == nx) {
1371: /* Check EOL. */
1372: if (!(win->alines[oy]->flags & __ISPASTEOL))
1373: return;
1374: }
1375:
1376: /* Clear EOL flags. */
1377: win->alines[oy]->flags &= ~__ISPASTEOL;
1378: win->alines[ny]->flags &= ~__ISPASTEOL;
1379:
1.5 cgd 1380: __mvcur(oy, ox, ny, nx, 1);
1381: }
1382:
1383: /*
1384: * Quickch() attempts to detect a pattern in the change of the window
1.7 cgd 1385: * in order to optimize the change, e.g., scroll n lines as opposed to
1.5 cgd 1386: * repainting the screen line by line.
1387: */
1388:
1.46 christos 1389: static __LDATA buf[128];
1.82 roy 1390: static unsigned int last_hash;
1.46 christos 1391: static size_t last_hash_len;
1392: #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
1393:
1.5 cgd 1394: static void
1.23 jdc 1395: quickch(void)
1.5 cgd 1396: {
1.23 jdc 1397: #define THRESH (int) __virtscr->maxy / 4
1.5 cgd 1398:
1.10 perry 1399: __LINE *clp, *tmp1, *tmp2;
1.11 mrg 1400: int bsize, curs, curw, starts, startw, i, j;
1401: int n, target, cur_period, bot, top, sc_region;
1.82 roy 1402: unsigned int blank_hash;
1.22 jdc 1403: attr_t bcolor;
1.5 cgd 1404:
1.8 mikel 1405: #ifdef __GNUC__
1.11 mrg 1406: curs = curw = starts = startw = 0; /* XXX gcc -Wuninitialized */
1.8 mikel 1407: #endif
1.7 cgd 1408: /*
1.5 cgd 1409: * Find how many lines from the top of the screen are unchanged.
1410: */
1.83 roy 1411: for (top = 0; top < __virtscr->maxy; top++) {
1.71 roy 1412: if (__virtscr->alines[top]->flags & __ISDIRTY &&
1413: (__virtscr->alines[top]->hash != curscr->alines[top]->hash ||
1.101 uwe 1414: !lineeq(__virtscr->alines[top]->line,
1415: curscr->alines[top]->line,
1416: (size_t) __virtscr->maxx)))
1.5 cgd 1417: break;
1418: else
1.71 roy 1419: __virtscr->alines[top]->flags &= ~__ISDIRTY;
1.83 roy 1420: }
1.11 mrg 1421: /*
1422: * Find how many lines from bottom of screen are unchanged.
1423: */
1.83 roy 1424: for (bot = __virtscr->maxy - 1; bot >= 0; bot--) {
1.71 roy 1425: if (__virtscr->alines[bot]->flags & __ISDIRTY &&
1426: (__virtscr->alines[bot]->hash != curscr->alines[bot]->hash ||
1.101 uwe 1427: !lineeq(__virtscr->alines[bot]->line,
1428: curscr->alines[bot]->line,
1429: (size_t) __virtscr->maxx)))
1.5 cgd 1430: break;
1431: else
1.71 roy 1432: __virtscr->alines[bot]->flags &= ~__ISDIRTY;
1.83 roy 1433: }
1.23 jdc 1434:
1435: /*
1436: * Work round an xterm bug where inserting lines causes all the
1437: * inserted lines to be covered with the background colour we
1438: * set on the first line (even if we unset it for subsequent
1439: * lines).
1440: */
1.71 roy 1441: bcolor = __virtscr->alines[min(top,
1.23 jdc 1442: __virtscr->maxy - 1)]->line[0].attr & __COLOR;
1443: for (i = top + 1, j = 0; i < bot; i++) {
1.71 roy 1444: if ((__virtscr->alines[i]->line[0].attr & __COLOR) != bcolor) {
1445: bcolor = __virtscr->alines[i]->line[__virtscr->maxx].
1.23 jdc 1446: attr & __COLOR;
1447: j = i - top;
1448: } else
1449: break;
1450: }
1451: top += j;
1.5 cgd 1452:
1453: #ifdef NO_JERKINESS
1454: /*
1455: * If we have a bottom unchanged region return. Scrolling the
1456: * bottom region up and then back down causes a screen jitter.
1457: * This will increase the number of characters sent to the screen
1458: * but it looks better.
1459: */
1.23 jdc 1460: if (bot < __virtscr->maxy - 1)
1.5 cgd 1461: return;
1.11 mrg 1462: #endif /* NO_JERKINESS */
1.5 cgd 1463:
1464: /*
1465: * Search for the largest block of text not changed.
1466: * Invariants of the loop:
1.23 jdc 1467: * - Startw is the index of the beginning of the examined block in
1468: * __virtscr.
1.11 mrg 1469: * - Starts is the index of the beginning of the examined block in
1.23 jdc 1470: * curscr.
1.7 cgd 1471: * - Curw is the index of one past the end of the exmined block in
1.23 jdc 1472: * __virtscr.
1473: * - Curs is the index of one past the end of the exmined block in
1.5 cgd 1474: * curscr.
1475: * - bsize is the current size of the examined block.
1.11 mrg 1476: */
1.23 jdc 1477:
1.5 cgd 1478: for (bsize = bot - top; bsize >= THRESH; bsize--) {
1479: for (startw = top; startw <= bot - bsize; startw++)
1.83 roy 1480: for (starts = top; starts <= bot - bsize; starts++) {
1.5 cgd 1481: for (curw = startw, curs = starts;
1.11 mrg 1482: curs < starts + bsize; curw++, curs++)
1.71 roy 1483: if (__virtscr->alines[curw]->hash !=
1484: curscr->alines[curs]->hash)
1.32 mycroft 1485: break;
1486: if (curs != starts + bsize)
1487: continue;
1488: for (curw = startw, curs = starts;
1.65 blymn 1489: curs < starts + bsize; curw++, curs++)
1.96 uwe 1490: if (!lineeq(__virtscr->alines[curw]->line,
1.101 uwe 1491: curscr->alines[curs]->line,
1492: (size_t) __virtscr->maxx))
1.5 cgd 1493: break;
1494: if (curs == starts + bsize)
1495: goto done;
1496: }
1497: }
1.11 mrg 1498: done:
1.22 jdc 1499:
1.5 cgd 1500: /* Did not find anything */
1.7 cgd 1501: if (bsize < THRESH)
1.5 cgd 1502: return;
1503:
1.64 jdc 1504: __CTRACE(__CTRACE_REFRESH, "quickch:bsize=%d, starts=%d, startw=%d, "
1505: "curw=%d, curs=%d, top=%d, bot=%d\n",
1.11 mrg 1506: bsize, starts, startw, curw, curs, top, bot);
1.5 cgd 1507:
1.7 cgd 1508: /*
1509: * Make sure that there is no overlap between the bottom and top
1.5 cgd 1510: * regions and the middle scrolled block.
1511: */
1512: if (bot < curs)
1513: bot = curs - 1;
1514: if (top > starts)
1515: top = starts;
1516:
1517: n = startw - starts;
1518:
1519: #ifdef DEBUG
1.64 jdc 1520: __CTRACE(__CTRACE_REFRESH, "#####################################\n");
1.11 mrg 1521: for (i = 0; i < curscr->maxy; i++) {
1.64 jdc 1522: __CTRACE(__CTRACE_REFRESH, "C: %d:", i);
1.71 roy 1523: __CTRACE(__CTRACE_REFRESH, " 0x%x \n", curscr->alines[i]->hash);
1.11 mrg 1524: for (j = 0; j < curscr->maxx; j++)
1.64 jdc 1525: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 1526: curscr->alines[i]->line[j].ch);
1.64 jdc 1527: __CTRACE(__CTRACE_REFRESH, "\n");
1528: __CTRACE(__CTRACE_REFRESH, " attr:");
1.11 mrg 1529: for (j = 0; j < curscr->maxx; j++)
1.64 jdc 1530: __CTRACE(__CTRACE_REFRESH, " %x",
1.71 roy 1531: curscr->alines[i]->line[j].attr);
1.64 jdc 1532: __CTRACE(__CTRACE_REFRESH, "\n");
1533: __CTRACE(__CTRACE_REFRESH, "W: %d:", i);
1534: __CTRACE(__CTRACE_REFRESH, " 0x%x \n",
1.71 roy 1535: __virtscr->alines[i]->hash);
1.64 jdc 1536: __CTRACE(__CTRACE_REFRESH, " 0x%x ",
1.71 roy 1537: __virtscr->alines[i]->flags);
1.23 jdc 1538: for (j = 0; j < __virtscr->maxx; j++)
1.64 jdc 1539: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 1540: __virtscr->alines[i]->line[j].ch);
1.64 jdc 1541: __CTRACE(__CTRACE_REFRESH, "\n");
1542: __CTRACE(__CTRACE_REFRESH, " attr:");
1.23 jdc 1543: for (j = 0; j < __virtscr->maxx; j++)
1.64 jdc 1544: __CTRACE(__CTRACE_REFRESH, " %x",
1.71 roy 1545: __virtscr->alines[i]->line[j].attr);
1.64 jdc 1546: __CTRACE(__CTRACE_REFRESH, "\n");
1.11 mrg 1547: }
1.7 cgd 1548: #endif
1549:
1.65 blymn 1550: #ifndef HAVE_WCHAR
1.46 christos 1551: if (buf[0].ch != ' ') {
1552: for (i = 0; i < BLANKSIZE; i++) {
1553: buf[i].ch = ' ';
1554: buf[i].attr = 0;
1555: }
1.5 cgd 1556: }
1.65 blymn 1557: #else
1.83 roy 1558: if (buf[0].ch != (wchar_t)btowc((int)curscr->bch )) {
1.65 blymn 1559: for (i = 0; i < BLANKSIZE; i++) {
1.83 roy 1560: buf[i].ch = (wchar_t)btowc((int)curscr->bch);
1.65 blymn 1561: if (_cursesi_copy_nsp(curscr->bnsp, &buf[i]) == ERR)
1562: return;
1563: buf[i].attr = 0;
1.83 roy 1564: SET_WCOL(buf[i], 1);
1.65 blymn 1565: }
1566: }
1567: #endif /* HAVE_WCHAR */
1.46 christos 1568:
1569: if (__virtscr->maxx != last_hash_len) {
1570: blank_hash = 0;
1571: for (i = __virtscr->maxx; i > BLANKSIZE; i -= BLANKSIZE) {
1.61 dsl 1572: blank_hash = __hash_more(buf, sizeof(buf), blank_hash);
1.46 christos 1573: }
1574: blank_hash = __hash_more((char *)(void *)buf,
1575: i * sizeof(buf[0]), blank_hash);
1576: /* cache result in static data - screen width doesn't change often */
1577: last_hash_len = __virtscr->maxx;
1578: last_hash = blank_hash;
1579: } else
1580: blank_hash = last_hash;
1.5 cgd 1581:
1582: /*
1583: * Perform the rotation to maintain the consistency of curscr.
1584: * This is hairy since we are doing an *in place* rotation.
1585: * Invariants of the loop:
1586: * - I is the index of the current line.
1587: * - Target is the index of the target of line i.
1588: * - Tmp1 points to current line (i).
1589: * - Tmp2 and points to target line (target);
1.7 cgd 1590: * - Cur_period is the index of the end of the current period.
1.5 cgd 1591: * (see below).
1592: *
1593: * There are 2 major issues here that make this rotation non-trivial:
1594: * 1. Scrolling in a scrolling region bounded by the top
1595: * and bottom regions determined (whose size is sc_region).
1.7 cgd 1596: * 2. As a result of the use of the mod function, there may be a
1.5 cgd 1597: * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
1598: * 0 to 2, which then causes all odd lines not to be rotated.
1.7 cgd 1599: * To remedy this, an index of the end ( = beginning) of the
1600: * current 'period' is kept, cur_period, and when it is reached,
1601: * the next period is started from cur_period + 1 which is
1.5 cgd 1602: * guaranteed not to have been reached since that would mean that
1603: * all records would have been reached. (think about it...).
1.7 cgd 1604: *
1.5 cgd 1605: * Lines in the rotation can have 3 attributes which are marked on the
1606: * line so that curscr is consistent with the visual screen.
1607: * 1. Not dirty -- lines inside the scrolled block, top region or
1608: * bottom region.
1.7 cgd 1609: * 2. Blank lines -- lines in the differential of the scrolling
1610: * region adjacent to top and bot regions
1.5 cgd 1611: * depending on scrolling direction.
1612: * 3. Dirty line -- all other lines are marked dirty.
1613: */
1614: sc_region = bot - top + 1;
1615: i = top;
1.71 roy 1616: tmp1 = curscr->alines[top];
1.5 cgd 1617: cur_period = top;
1618: for (j = top; j <= bot; j++) {
1619: target = (i - top + n + sc_region) % sc_region + top;
1.71 roy 1620: tmp2 = curscr->alines[target];
1621: curscr->alines[target] = tmp1;
1.5 cgd 1622: /* Mark block as clean and blank out scrolled lines. */
1.71 roy 1623: clp = curscr->alines[target];
1.64 jdc 1624: __CTRACE(__CTRACE_REFRESH,
1625: "quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1.11 mrg 1626: n, startw, curw, i, target);
1.7 cgd 1627: if ((target >= startw && target < curw) || target < top
1.83 roy 1628: || target > bot)
1629: {
1.64 jdc 1630: __CTRACE(__CTRACE_REFRESH, " notdirty\n");
1.71 roy 1631: __virtscr->alines[target]->flags &= ~__ISDIRTY;
1.11 mrg 1632: } else
1633: if ((n > 0 && target >= top && target < top + n) ||
1.83 roy 1634: (n < 0 && target <= bot && target > bot + n))
1635: {
1.65 blymn 1636: if (clp->hash != blank_hash ||
1.96 uwe 1637: !lineeq(clp->line, clp->line + 1,
1.97 uwe 1638: (__virtscr->maxx - 1)) ||
1.96 uwe 1639: !celleq(clp->line, buf))
1.83 roy 1640: {
1.65 blymn 1641: for (i = __virtscr->maxx;
1642: i > BLANKSIZE;
1.46 christos 1643: i -= BLANKSIZE) {
1.65 blymn 1644: (void) memcpy(clp->line + i -
1.46 christos 1645: BLANKSIZE, buf, sizeof(buf));
1646: }
1.115 rin 1647: (void)memcpy(clp->line, buf,
1648: i * sizeof(buf[0]));
1.64 jdc 1649: __CTRACE(__CTRACE_REFRESH,
1650: " blanked out: dirty\n");
1.11 mrg 1651: clp->hash = blank_hash;
1.35 mycroft 1652: __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1);
1.11 mrg 1653: } else {
1.64 jdc 1654: __CTRACE(__CTRACE_REFRESH,
1655: " -- blank line already: dirty\n");
1.35 mycroft 1656: __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1);
1.11 mrg 1657: }
1.5 cgd 1658: } else {
1.64 jdc 1659: __CTRACE(__CTRACE_REFRESH, " -- dirty\n");
1.115 rin 1660: __touchline(__virtscr, target, 0,
1661: (int)__virtscr->maxx - 1);
1.5 cgd 1662: }
1663: if (target == cur_period) {
1664: i = target + 1;
1.71 roy 1665: tmp1 = curscr->alines[i];
1.5 cgd 1666: cur_period = i;
1667: } else {
1668: tmp1 = tmp2;
1669: i = target;
1670: }
1671: }
1672: #ifdef DEBUG
1.64 jdc 1673: __CTRACE(__CTRACE_REFRESH, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
1.11 mrg 1674: for (i = 0; i < curscr->maxy; i++) {
1.64 jdc 1675: __CTRACE(__CTRACE_REFRESH, "C: %d:", i);
1.11 mrg 1676: for (j = 0; j < curscr->maxx; j++)
1.64 jdc 1677: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 1678: curscr->alines[i]->line[j].ch);
1.64 jdc 1679: __CTRACE(__CTRACE_REFRESH, "\n");
1680: __CTRACE(__CTRACE_REFRESH, "W: %d:", i);
1.23 jdc 1681: for (j = 0; j < __virtscr->maxx; j++)
1.64 jdc 1682: __CTRACE(__CTRACE_REFRESH, "%c",
1.71 roy 1683: __virtscr->alines[i]->line[j].ch);
1.64 jdc 1684: __CTRACE(__CTRACE_REFRESH, "\n");
1.11 mrg 1685: }
1.5 cgd 1686: #endif
1.23 jdc 1687: if (n != 0)
1688: scrolln(starts, startw, curs, bot, top);
1.5 cgd 1689: }
1690:
1691: /*
1.7 cgd 1692: * scrolln --
1693: * Scroll n lines, where n is starts - startw.
1.5 cgd 1694: */
1.11 mrg 1695: static void /* ARGSUSED */
1.83 roy 1696: scrolln(int starts, int startw, int curs, int bot, int top)
1.5 cgd 1697: {
1.11 mrg 1698: int i, oy, ox, n;
1.5 cgd 1699:
1700: oy = curscr->cury;
1701: ox = curscr->curx;
1702: n = starts - startw;
1703:
1.7 cgd 1704: /*
1705: * XXX
1706: * The initial tests that set __noqch don't let us reach here unless
1.41 jdc 1707: * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1.7 cgd 1708: * scrolling can only shift the entire scrolling region, not just a
1709: * part of it, which means that the quickch() routine is going to be
1.41 jdc 1710: * sadly disappointed in us if we don't have cs as well.
1.7 cgd 1711: *
1.41 jdc 1712: * If cs, ho and SF/sf are set, can use the scrolling region. Because
1713: * the cursor position after cs is undefined, we need ho which gives us
1.7 cgd 1714: * the ability to move to somewhere without knowledge of the current
1715: * location of the cursor. Still call __mvcur() anyway, to update its
1716: * idea of where the cursor is.
1717: *
1718: * When the scrolling region has been set, the cursor has to be at the
1719: * last line of the region to make the scroll happen.
1720: *
1721: * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1.41 jdc 1722: * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1.7 cgd 1723: * SF/SR. So, if we're scrolling almost all of the screen, try and use
1724: * AL/DL, otherwise use the scrolling region. The "almost all" is a
1725: * shameless hack for vi.
1726: */
1.5 cgd 1727: if (n > 0) {
1.72 roy 1728: if (change_scroll_region != NULL && cursor_home != NULL &&
1729: (parm_index != NULL ||
1730: ((parm_insert_line == NULL || parm_delete_line == NULL ||
1.41 jdc 1731: top > 3 || bot + 3 < __virtscr->maxy) &&
1.72 roy 1732: scroll_forward != NULL)))
1733: {
1.75 roy 1734: tputs(tiparm(change_scroll_region, top, bot),
1.72 roy 1735: 0, __cputchar);
1.7 cgd 1736: __mvcur(oy, ox, 0, 0, 1);
1.72 roy 1737: tputs(cursor_home, 0, __cputchar);
1.7 cgd 1738: __mvcur(0, 0, bot, 0, 1);
1.72 roy 1739: if (parm_index != NULL)
1.75 roy 1740: tputs(tiparm(parm_index, n),
1.72 roy 1741: 0, __cputchar);
1.7 cgd 1742: else
1743: for (i = 0; i < n; i++)
1.72 roy 1744: tputs(scroll_forward, 0, __cputchar);
1.75 roy 1745: tputs(tiparm(change_scroll_region,
1.83 roy 1746: 0, (int)__virtscr->maxy - 1), 0, __cputchar);
1.7 cgd 1747: __mvcur(bot, 0, 0, 0, 1);
1.72 roy 1748: tputs(cursor_home, 0, __cputchar);
1.7 cgd 1749: __mvcur(0, 0, oy, ox, 1);
1750: return;
1751: }
1752:
1753: /* Scroll up the block. */
1.72 roy 1754: if (parm_index != NULL && top == 0) {
1.7 cgd 1755: __mvcur(oy, ox, bot, 0, 1);
1.75 roy 1756: tputs(tiparm(parm_index, n), 0, __cputchar);
1.7 cgd 1757: } else
1.72 roy 1758: if (parm_delete_line != NULL) {
1.11 mrg 1759: __mvcur(oy, ox, top, 0, 1);
1.75 roy 1760: tputs(tiparm(parm_delete_line, n),
1.72 roy 1761: 0, __cputchar);
1.11 mrg 1762: } else
1.72 roy 1763: if (delete_line != NULL) {
1.11 mrg 1764: __mvcur(oy, ox, top, 0, 1);
1765: for (i = 0; i < n; i++)
1.83 roy 1766: tputs(delete_line, 0,
1767: __cputchar);
1.11 mrg 1768: } else
1.72 roy 1769: if (scroll_forward != NULL && top == 0) {
1.11 mrg 1770: __mvcur(oy, ox, bot, 0, 1);
1771: for (i = 0; i < n; i++)
1.72 roy 1772: tputs(scroll_forward, 0,
1.41 jdc 1773: __cputchar);
1.11 mrg 1774: } else
1775: abort();
1.5 cgd 1776:
1.7 cgd 1777: /* Push down the bottom region. */
1.5 cgd 1778: __mvcur(top, 0, bot - n + 1, 0, 1);
1.72 roy 1779: if (parm_insert_line != NULL)
1.75 roy 1780: tputs(tiparm(parm_insert_line, n), 0, __cputchar);
1.83 roy 1781: else {
1782: if (insert_line != NULL) {
1.11 mrg 1783: for (i = 0; i < n; i++)
1.72 roy 1784: tputs(insert_line, 0, __cputchar);
1.83 roy 1785: } else
1.11 mrg 1786: abort();
1.83 roy 1787: }
1.5 cgd 1788: __mvcur(bot - n + 1, 0, oy, ox, 1);
1789: } else {
1.7 cgd 1790: /*
1791: * !!!
1792: * n < 0
1793: *
1.41 jdc 1794: * If cs, ho and SR/sr are set, can use the scrolling region.
1.7 cgd 1795: * See the above comments for details.
1796: */
1.72 roy 1797: if (change_scroll_region != NULL && cursor_home != NULL &&
1798: (parm_rindex != NULL ||
1799: ((parm_insert_line == NULL || parm_delete_line == NULL ||
1800: top > 3 ||
1801: bot + 3 < __virtscr->maxy) && scroll_reverse != NULL)))
1802: {
1.75 roy 1803: tputs(tiparm(change_scroll_region, top, bot),
1.72 roy 1804: 0, __cputchar);
1.7 cgd 1805: __mvcur(oy, ox, 0, 0, 1);
1.72 roy 1806: tputs(cursor_home, 0, __cputchar);
1.7 cgd 1807: __mvcur(0, 0, top, 0, 1);
1808:
1.72 roy 1809: if (parm_rindex != NULL)
1.75 roy 1810: tputs(tiparm(parm_rindex, -n),
1.72 roy 1811: 0, __cputchar);
1.7 cgd 1812: else
1813: for (i = n; i < 0; i++)
1.72 roy 1814: tputs(scroll_reverse, 0, __cputchar);
1.75 roy 1815: tputs(tiparm(change_scroll_region,
1.73 roy 1816: 0, (int) __virtscr->maxy - 1), 0, __cputchar);
1.7 cgd 1817: __mvcur(top, 0, 0, 0, 1);
1.72 roy 1818: tputs(cursor_home, 0, __cputchar);
1.7 cgd 1819: __mvcur(0, 0, oy, ox, 1);
1820: return;
1821: }
1822:
1823: /* Preserve the bottom lines. */
1824: __mvcur(oy, ox, bot + n + 1, 0, 1);
1.72 roy 1825: if (parm_rindex != NULL && bot == __virtscr->maxy)
1.75 roy 1826: tputs(tiparm(parm_rindex, -n), 0, __cputchar);
1.83 roy 1827: else {
1.72 roy 1828: if (parm_delete_line != NULL)
1.75 roy 1829: tputs(tiparm(parm_delete_line, -n),
1.72 roy 1830: 0, __cputchar);
1.83 roy 1831: else {
1.72 roy 1832: if (delete_line != NULL)
1.11 mrg 1833: for (i = n; i < 0; i++)
1.72 roy 1834: tputs(delete_line,
1835: 0, __cputchar);
1.83 roy 1836: else {
1.72 roy 1837: if (scroll_reverse != NULL &&
1.41 jdc 1838: bot == __virtscr->maxy)
1.11 mrg 1839: for (i = n; i < 0; i++)
1.72 roy 1840: tputs(scroll_reverse, 0,
1.41 jdc 1841: __cputchar);
1.11 mrg 1842: else
1843: abort();
1.83 roy 1844: }
1845: }
1846: }
1.7 cgd 1847: /* Scroll the block down. */
1.5 cgd 1848: __mvcur(bot + n + 1, 0, top, 0, 1);
1.72 roy 1849: if (parm_insert_line != NULL)
1.75 roy 1850: tputs(tiparm(parm_insert_line, -n), 0, __cputchar);
1.5 cgd 1851: else
1.72 roy 1852: if (insert_line != NULL)
1.11 mrg 1853: for (i = n; i < 0; i++)
1.72 roy 1854: tputs(insert_line, 0, __cputchar);
1.11 mrg 1855: else
1856: abort();
1.5 cgd 1857: __mvcur(top, 0, oy, ox, 1);
1.19 jdc 1858: }
1859: }
1860:
1861: /*
1.23 jdc 1862: * __unsetattr --
1.19 jdc 1863: * Unset attributes on curscr. Leave standout, attribute and colour
1.41 jdc 1864: * modes if necessary (!ms). Always leave altcharset (xterm at least
1.19 jdc 1865: * ignores a cursor move if we don't).
1866: */
1.23 jdc 1867: void /* ARGSUSED */
1868: __unsetattr(int checkms)
1.19 jdc 1869: {
1870: int isms;
1871:
1.83 roy 1872: if (checkms) {
1873: if (!move_standout_mode)
1.19 jdc 1874: isms = 1;
1.83 roy 1875: else
1.19 jdc 1876: isms = 0;
1.83 roy 1877: } else
1.19 jdc 1878: isms = 1;
1.64 jdc 1879: __CTRACE(__CTRACE_REFRESH,
1880: "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1.72 roy 1881: checkms, move_standout_mode ? "TRUE" : "FALSE", curscr->wattr);
1.65 blymn 1882:
1.20 jdc 1883: /*
1.65 blymn 1884: * Don't leave the screen in standout mode (check against ms). Check
1.27 mycroft 1885: * to see if we also turn off underscore, attributes and colour.
1.20 jdc 1886: */
1.19 jdc 1887: if (curscr->wattr & __STANDOUT && isms) {
1.72 roy 1888: tputs(exit_standout_mode, 0, __cputchar);
1.41 jdc 1889: curscr->wattr &= __mask_se;
1.19 jdc 1890: }
1.20 jdc 1891: /*
1.41 jdc 1892: * Don't leave the screen in underscore mode (check against ms).
1.26 jdc 1893: * Check to see if we also turn off attributes. Assume that we
1894: * also turn off colour.
1.20 jdc 1895: */
1.19 jdc 1896: if (curscr->wattr & __UNDERSCORE && isms) {
1.72 roy 1897: tputs(exit_underline_mode, 0, __cputchar);
1.41 jdc 1898: curscr->wattr &= __mask_ue;
1.19 jdc 1899: }
1.20 jdc 1900: /*
1.41 jdc 1901: * Don't leave the screen with attributes set (check against ms).
1.26 jdc 1902: * Assume that also turn off colour.
1.20 jdc 1903: */
1904: if (curscr->wattr & __TERMATTR && isms) {
1.72 roy 1905: tputs(exit_attribute_mode, 0, __cputchar);
1.41 jdc 1906: curscr->wattr &= __mask_me;
1.19 jdc 1907: }
1.41 jdc 1908: /* Don't leave the screen with altcharset set (don't check ms). */
1.19 jdc 1909: if (curscr->wattr & __ALTCHARSET) {
1.72 roy 1910: tputs(exit_alt_charset_mode, 0, __cputchar);
1.19 jdc 1911: curscr->wattr &= ~__ALTCHARSET;
1912: }
1.41 jdc 1913: /* Don't leave the screen with colour set (check against ms). */
1.47 jdc 1914: if (__using_color && isms)
1915: __unset_color(curscr);
1.1 cgd 1916: }
1.65 blymn 1917:
1918: #ifdef HAVE_WCHAR
1919: /* compare two cells on screen, must have the same forground/background,
1920: * and the same sequence of non-spacing characters */
1.95 uwe 1921: static int
1922: celleq(__LDATA *x, __LDATA *y)
1.65 blymn 1923: {
1924: nschar_t *xnp = x->nsp, *ynp = y->nsp;
1.93 uwe 1925: int ret = ( x->ch == y->ch ) && ( x->attr == y->attr );
1.65 blymn 1926:
1.83 roy 1927: if (!ret)
1.65 blymn 1928: return 0;
1.83 roy 1929: if (!xnp && !ynp)
1.65 blymn 1930: return 1;
1.83 roy 1931: if ((xnp && !ynp) || (!xnp && ynp))
1.65 blymn 1932: return 0;
1933:
1.83 roy 1934: while (xnp && ynp) {
1935: if (xnp->ch != ynp->ch)
1.65 blymn 1936: return 0;
1937: xnp = xnp->next;
1938: ynp = ynp->next;
1939: }
1.83 roy 1940: return !xnp && !ynp;
1.65 blymn 1941: }
1942:
1943: /* compare two line segments */
1.95 uwe 1944: static int
1945: lineeq(__LDATA *xl, __LDATA *yl, size_t len)
1.65 blymn 1946: {
1947: int i = 0;
1948: __LDATA *xp = xl, *yp = yl;
1949:
1.83 roy 1950: for (i = 0; i < len; i++, xp++, yp++) {
1.95 uwe 1951: if (!celleq(xp, yp))
1.65 blymn 1952: return 0;
1953: }
1954: return 1;
1955: }
1956:
1957: /*
1958: * Output the non-spacing characters associated with the given character
1959: * cell to the screen.
1960: */
1961:
1962: void
1963: __cursesi_putnsp(nschar_t *nsp, const int wy, const int wx)
1964: {
1965: nschar_t *p;
1966:
1.66 blymn 1967: /* this shuts up gcc warnings about wx and wy not being used */
1968: if (wx > wy) {
1969: }
1970:
1.65 blymn 1971: p = nsp;
1972: while (p != NULL) {
1.83 roy 1973: __cputwchar((int)p->ch);
1.65 blymn 1974: __CTRACE(__CTRACE_REFRESH,
1.115 rin 1975: "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n",
1976: wy, wx - 1, p->ch);
1.65 blymn 1977: p = p->next;
1978: }
1979: }
1980:
1981: #endif /* HAVE_WCHAR */
CVSweb <webmaster@jp.NetBSD.org>