Annotation of src/lib/libcurses/refresh.c, Revision 1.49
1.49 ! jdc 1: /* $NetBSD: refresh.c,v 1.48 2002/10/22 11:37:34 blymn 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.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
1.8 mikel 36: #include <sys/cdefs.h>
1.1 cgd 37: #ifndef lint
1.8 mikel 38: #if 0
1.7 cgd 39: static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94";
1.8 mikel 40: #else
1.49 ! jdc 41: __RCSID("$NetBSD: refresh.c,v 1.48 2002/10/22 11:37:34 blymn Exp $");
1.8 mikel 42: #endif
1.11 mrg 43: #endif /* not lint */
1.1 cgd 44:
1.38 matt 45: #include <stdlib.h>
1.4 mycroft 46: #include <string.h>
1.1 cgd 47:
1.7 cgd 48: #include "curses.h"
1.15 blymn 49: #include "curses_private.h"
1.7 cgd 50:
1.4 mycroft 51: static void domvcur __P((int, int, int, int));
1.23 jdc 52: static int makech __P((int));
53: static void quickch __P((void));
54: static void scrolln __P((int, int, int, int, int));
1.1 cgd 55:
1.17 blymn 56: #ifndef _CURSES_USE_MACROS
57:
58: /*
59: * refresh --
60: * Make the current screen look like "stdscr" over the area covered by
61: * stdscr.
62: */
63: int
64: refresh(void)
65: {
66: return wrefresh(stdscr);
67: }
68:
69: #endif
70:
1.4 mycroft 71: /*
1.23 jdc 72: * wnoutrefresh --
73: * Add the contents of "win" to the virtual window.
74: */
75: int
76: wnoutrefresh(WINDOW *win)
77: {
1.44 blymn 78: return _cursesi_wnoutrefresh(_cursesi_screen, win);
79: }
80:
81:
82: /*
83: * _cursesi_wnoutrefresh --
84: * Does the grunt work for wnoutrefresh to the given screen.
85: *
86: */
87: int
88: _cursesi_wnoutrefresh(SCREEN *screen, WINDOW *win)
89: {
1.45 blymn 90:
1.33 mycroft 91: short wy, wx, x_off;
92: __LINE *wlp, *vlp;
1.23 jdc 93:
94: #ifdef DEBUG
95: __CTRACE("wnoutrefresh: win %0.2o, flags 0x%08x\n", win, win->flags);
96: #endif
97:
1.44 blymn 98: if (screen->curwin)
1.23 jdc 99: return(OK);
1.44 blymn 100: screen->__virtscr->cury = win->cury + win->begy;
101: screen->__virtscr->curx = win->curx + win->begx;
1.23 jdc 102:
103: /* Copy the window flags from "win" to "__virtscr" */
1.33 mycroft 104: if (win->flags & __CLEAROK) {
105: if (win->flags & __FULLWIN)
1.44 blymn 106: screen->__virtscr->flags |= __CLEAROK;
1.23 jdc 107: win->flags &= ~__CLEAROK;
1.33 mycroft 108: }
1.44 blymn 109: screen->__virtscr->flags &= ~__LEAVEOK;
110: screen->__virtscr->flags |= win->flags;
1.23 jdc 111:
1.49 ! jdc 112: for (wy = 0; wy < win->maxy &&
! 113: wy < screen->__virtscr->maxy - win->begy; wy++) {
1.33 mycroft 114: wlp = win->lines[wy];
1.23 jdc 115: #ifdef DEBUG
116: __CTRACE("wnoutrefresh: wy %d\tf: %d\tl:%d\tflags %x\n", wy,
1.33 mycroft 117: *wlp->firstchp, *wlp->lastchp, wlp->flags);
1.23 jdc 118: #endif
1.35 mycroft 119: if ((wlp->flags & __ISDIRTY) == 0)
1.33 mycroft 120: continue;
1.44 blymn 121: vlp = screen->__virtscr->lines[wy + win->begy];
1.33 mycroft 122:
123: if (*wlp->firstchp < win->maxx + win->ch_off &&
124: *wlp->lastchp >= win->ch_off) {
1.23 jdc 125: /* Copy line from "win" to "__virtscr". */
1.49 ! jdc 126: for (wx = *wlp->firstchp - win->ch_off,
! 127: x_off = win->begx + *wlp->firstchp - win->ch_off;
! 128: wx <= *wlp->lastchp && wx < win->maxx &&
1.44 blymn 129: x_off < screen->__virtscr->maxx; wx++, x_off++) {
1.33 mycroft 130: vlp->line[x_off].attr = wlp->line[wx].attr;
1.36 jdc 131: if (wlp->line[wx].attr & __COLOR)
1.33 mycroft 132: vlp->line[x_off].attr |=
1.36 jdc 133: wlp->line[wx].battr & ~__COLOR;
134: else
135: vlp->line[x_off].attr |=
136: wlp->line[wx].battr;
1.33 mycroft 137: if (wlp->line[wx].ch == ' ' &&
138: wlp->line[wx].bch != ' ')
139: vlp->line[x_off].ch
140: = wlp->line[wx].bch;
1.23 jdc 141: else
1.33 mycroft 142: vlp->line[x_off].ch
143: = wlp->line[wx].ch;
1.23 jdc 144: }
145:
146: /* Set flags on "__virtscr" and unset on "win". */
1.33 mycroft 147: if (wlp->flags & __ISPASTEOL)
148: vlp->flags |= __ISPASTEOL;
1.23 jdc 149: else
1.33 mycroft 150: vlp->flags &= ~__ISPASTEOL;
151: if (wlp->flags & __ISDIRTY)
152: vlp->flags |= __ISDIRTY;
1.23 jdc 153:
154: #ifdef DEBUG
155: __CTRACE("win: firstch = %d, lastch = %d\n",
1.33 mycroft 156: *wlp->firstchp, *wlp->lastchp);
1.23 jdc 157: #endif
158: /* Set change pointers on "__virtscr". */
1.33 mycroft 159: if (*vlp->firstchp >
160: *wlp->firstchp + win->begx - win->ch_off)
161: *vlp->firstchp =
162: *wlp->firstchp + win->begx - win->ch_off;
163: if (*vlp->lastchp <
164: *wlp->lastchp + win->begx - win->ch_off)
165: *vlp->lastchp =
166: *wlp->lastchp + win->begx - win->ch_off;
1.23 jdc 167: #ifdef DEBUG
168: __CTRACE("__virtscr: firstch = %d, lastch = %d\n",
1.33 mycroft 169: *vlp->firstchp, *vlp->lastchp);
1.23 jdc 170: #endif
171:
172: /* Set change pointers on "win". */
1.33 mycroft 173: if (*wlp->firstchp >= win->ch_off)
174: *wlp->firstchp = win->maxx + win->ch_off;
175: if (*wlp->lastchp < win->maxx + win->ch_off)
176: *wlp->lastchp = win->ch_off;
177: if (*wlp->lastchp < *wlp->firstchp) {
1.23 jdc 178: #ifdef DEBUG
179: __CTRACE("wnoutrefresh: line %d notdirty\n",
180: wy);
181: #endif
1.33 mycroft 182: wlp->flags &= ~__ISDIRTY;
1.23 jdc 183: }
184: }
185: }
186:
187: return (OK);
188: }
189:
190: /*
1.4 mycroft 191: * wrefresh --
192: * Make the current screen look like "win" over the area coverd by
193: * win.
194: */
195: int
1.17 blymn 196: wrefresh(WINDOW *win)
1.1 cgd 197: {
1.44 blymn 198: int retval;
1.45 blymn 199:
1.44 blymn 200: _cursesi_screen->curwin = (win == _cursesi_screen->curscr);
1.43 blymn 201: if (!_cursesi_screen->curwin)
1.44 blymn 202: retval = _cursesi_wnoutrefresh(_cursesi_screen, win);
1.23 jdc 203: else
204: retval = OK;
205: if (retval == OK) {
206: retval = doupdate();
1.24 jdc 207: if (!win->flags & __LEAVEOK) {
208: win->cury = max(0, curscr->cury - win->begy);
209: win->curx = max(0, curscr->curx - win->begx);
210: }
1.23 jdc 211: }
1.43 blymn 212: _cursesi_screen->curwin = 0;
1.23 jdc 213: return(retval);
214: }
215:
216: /*
217: * doupdate --
218: * Make the current screen look like the virtual window "__virtscr".
219: */
220: int
221: doupdate(void)
222: {
223: WINDOW *win;
224: __LINE *wlp;
225: short wy;
226: int dnum;
1.9 phil 227:
228: /* Check if we need to restart ... */
1.43 blymn 229: if (_cursesi_screen->endwin)
1.9 phil 230: __restartwin();
1.7 cgd 231:
1.43 blymn 232: if (_cursesi_screen->curwin)
1.23 jdc 233: win = curscr;
234: else
1.44 blymn 235: win = _cursesi_screen->__virtscr;
1.23 jdc 236:
1.4 mycroft 237: /* Initialize loop parameters. */
1.43 blymn 238: _cursesi_screen->ly = curscr->cury;
239: _cursesi_screen->lx = curscr->curx;
1.1 cgd 240: wy = 0;
241:
1.43 blymn 242: if (!_cursesi_screen->curwin)
1.5 cgd 243: for (wy = 0; wy < win->maxy; wy++) {
244: wlp = win->lines[wy];
245: if (wlp->flags & __ISDIRTY)
1.12 christos 246: wlp->hash = __hash((char *)(void *)wlp->line,
1.48 blymn 247: (size_t) (win->maxx * __LDATASIZE));
1.5 cgd 248: }
249:
1.43 blymn 250: if ((win->flags & __CLEAROK) || (curscr->flags & __CLEAROK) ||
251: _cursesi_screen->curwin) {
1.23 jdc 252: if (curscr->wattr & __COLOR)
253: __unsetattr(0);
1.41 jdc 254: tputs(__tc_cl, 0, __cputchar);
1.43 blymn 255: _cursesi_screen->ly = 0;
256: _cursesi_screen->lx = 0;
257: if (!_cursesi_screen->curwin) {
1.23 jdc 258: curscr->flags &= ~__CLEAROK;
259: curscr->cury = 0;
260: curscr->curx = 0;
261: werase(curscr);
1.1 cgd 262: }
1.23 jdc 263: __touchwin(win);
1.5 cgd 264: win->flags &= ~__CLEAROK;
1.1 cgd 265: }
1.41 jdc 266: if (!__CA) {
1.5 cgd 267: if (win->curx != 0)
1.39 itojun 268: __cputchar('\n');
1.43 blymn 269: if (!_cursesi_screen->curwin)
1.1 cgd 270: werase(curscr);
271: }
1.4 mycroft 272: #ifdef DEBUG
1.43 blymn 273: __CTRACE("doupdate: (%0.2o): curwin = %d\n", win,
274: _cursesi_screen->curwin);
1.23 jdc 275: __CTRACE("doupdate: \tfirstch\tlastch\n");
1.5 cgd 276: #endif
277:
1.43 blymn 278: if (!_cursesi_screen->curwin) {
1.5 cgd 279: /*
280: * Invoke quickch() only if more than a quarter of the lines
281: * in the window are dirty.
282: */
283: for (wy = 0, dnum = 0; wy < win->maxy; wy++)
1.35 mycroft 284: if (win->lines[wy]->flags & __ISDIRTY)
1.5 cgd 285: dnum++;
286: if (!__noqch && dnum > (int) win->maxy / 4)
1.23 jdc 287: quickch();
1.5 cgd 288: }
289:
290: #ifdef DEBUG
1.11 mrg 291: {
292: int i, j;
293:
1.5 cgd 294: __CTRACE("#####################################\n");
295: for (i = 0; i < curscr->maxy; i++) {
296: __CTRACE("C: %d:", i);
297: __CTRACE(" 0x%x \n", curscr->lines[i]->hash);
1.7 cgd 298: for (j = 0; j < curscr->maxx; j++)
1.11 mrg 299: __CTRACE("%c", curscr->lines[i]->line[j].ch);
1.5 cgd 300: __CTRACE("\n");
1.14 simonb 301: __CTRACE(" attr:");
1.7 cgd 302: for (j = 0; j < curscr->maxx; j++)
1.43 blymn 303: __CTRACE(" %x",
304: curscr->lines[i]->line[j].attr);
1.5 cgd 305: __CTRACE("\n");
306: __CTRACE("W: %d:", i);
1.23 jdc 307: __CTRACE(" 0x%x \n", win->lines[i]->hash);
308: __CTRACE(" 0x%x ", win->lines[i]->flags);
309: for (j = 0; j < win->maxx; j++)
310: __CTRACE("%c", win->lines[i]->line[j].ch);
311: __CTRACE("\n");
312: __CTRACE(" attr:");
313: for (j = 0; j < win->maxx; j++)
314: __CTRACE(" %x",
315: win->lines[i]->line[j].attr);
316: __CTRACE("\n");
1.5 cgd 317: }
1.11 mrg 318: }
319: #endif /* DEBUG */
1.5 cgd 320:
321: for (wy = 0; wy < win->maxy; wy++) {
1.33 mycroft 322: wlp = win->lines[wy];
1.23 jdc 323: /* XXX: remove this debug */
1.4 mycroft 324: #ifdef DEBUG
1.23 jdc 325: __CTRACE("doupdate: wy %d\tf: %d\tl:%d\tflags %x\n", wy,
1.33 mycroft 326: *wlp->firstchp, *wlp->lastchp, wlp->flags);
1.4 mycroft 327: #endif
1.43 blymn 328: if (!_cursesi_screen->curwin)
1.33 mycroft 329: curscr->lines[wy]->hash = wlp->hash;
1.35 mycroft 330: if (wlp->flags & __ISDIRTY) {
1.23 jdc 331: if (makech(wy) == ERR)
1.4 mycroft 332: return (ERR);
1.1 cgd 333: else {
1.33 mycroft 334: if (*wlp->firstchp >= 0)
335: *wlp->firstchp = win->maxx;
336: if (*wlp->lastchp < win->maxx)
337: *wlp->lastchp = 0;
338: if (*wlp->lastchp < *wlp->firstchp) {
1.5 cgd 339: #ifdef DEBUG
1.23 jdc 340: __CTRACE("doupdate: line %d notdirty\n", wy);
1.5 cgd 341: #endif
1.33 mycroft 342: wlp->flags &= ~__ISDIRTY;
1.5 cgd 343: }
1.1 cgd 344: }
1.5 cgd 345:
346: }
1.4 mycroft 347: #ifdef DEBUG
1.33 mycroft 348: __CTRACE("\t%d\t%d\n", *wlp->firstchp, *wlp->lastchp);
1.4 mycroft 349: #endif
1.1 cgd 350: }
1.7 cgd 351:
1.5 cgd 352: #ifdef DEBUG
1.43 blymn 353: __CTRACE("doupdate: ly=%d, lx=%d\n", _cursesi_screen->ly,
354: _cursesi_screen->lx);
1.5 cgd 355: #endif
1.1 cgd 356:
1.43 blymn 357: if (_cursesi_screen->curwin)
358: domvcur(_cursesi_screen->ly, _cursesi_screen->lx,
359: (int) win->cury, (int) win->curx);
1.1 cgd 360: else {
1.5 cgd 361: if (win->flags & __LEAVEOK) {
1.43 blymn 362: curscr->cury = _cursesi_screen->ly;
363: curscr->curx = _cursesi_screen->lx;
1.4 mycroft 364: } else {
1.43 blymn 365: domvcur(_cursesi_screen->ly, _cursesi_screen->lx,
366: win->cury, win->curx);
1.23 jdc 367: curscr->cury = win->cury;
368: curscr->curx = win->curx;
1.1 cgd 369: }
370: }
1.23 jdc 371:
1.28 mycroft 372: /* Don't leave the screen with attributes set. */
373: __unsetattr(0);
1.43 blymn 374: (void) fflush(_cursesi_screen->outfd);
1.28 mycroft 375: return (OK);
1.1 cgd 376: }
377:
378: /*
1.4 mycroft 379: * makech --
380: * Make a change on the screen.
1.1 cgd 381: */
1.4 mycroft 382: static int
1.23 jdc 383: makech(wy)
1.11 mrg 384: int wy;
1.1 cgd 385: {
1.23 jdc 386: WINDOW *win;
1.34 mycroft 387: static __LDATA blank = {' ', 0, ' ', 0};
1.7 cgd 388: __LDATA *nsp, *csp, *cp, *cep;
1.11 mrg 389: int clsp, nlsp; /* Last space in lines. */
1.23 jdc 390: int lch, wx;
1.35 mycroft 391: char *ce;
1.23 jdc 392: attr_t lspc; /* Last space colour */
1.27 mycroft 393: attr_t off, on;
1.5 cgd 394:
1.8 mikel 395: #ifdef __GNUC__
1.23 jdc 396: nlsp = lspc = 0; /* XXX gcc -Wuninitialized */
1.8 mikel 397: #endif
1.43 blymn 398: if (_cursesi_screen->curwin)
1.23 jdc 399: win = curscr;
400: else
401: win = __virtscr;
1.5 cgd 402: /* Is the cursor still on the end of the last line? */
1.40 itojun 403: if (wy > 0 && curscr->lines[wy - 1]->flags & __ISPASTEOL) {
1.43 blymn 404: domvcur(_cursesi_screen->ly, _cursesi_screen->lx,
405: _cursesi_screen->ly + 1, 0);
406: _cursesi_screen->ly++;
407: _cursesi_screen->lx = 0;
1.5 cgd 408: }
1.23 jdc 409: wx = *win->lines[wy]->firstchp;
1.5 cgd 410: if (wx < 0)
411: wx = 0;
1.11 mrg 412: else
413: if (wx >= win->maxx)
414: return (OK);
1.23 jdc 415: lch = *win->lines[wy]->lastchp;
1.1 cgd 416: if (lch < 0)
1.4 mycroft 417: return (OK);
1.11 mrg 418: else
419: if (lch >= (int) win->maxx)
420: lch = win->maxx - 1;
1.1 cgd 421:
1.43 blymn 422: if (_cursesi_screen->curwin)
1.5 cgd 423: csp = ␣
1.1 cgd 424: else
1.23 jdc 425: csp = &curscr->lines[wy]->line[wx];
1.1 cgd 426:
1.5 cgd 427: nsp = &win->lines[wy]->line[wx];
1.43 blymn 428: if (__tc_ce && !_cursesi_screen->curwin) {
1.20 jdc 429: cp = &win->lines[wy]->line[win->maxx - 1];
1.23 jdc 430: lspc = cp->attr & __COLOR;
431: while (cp->ch == ' ' && cp->attr == lspc)
1.20 jdc 432: if (cp-- <= win->lines[wy]->line)
1.1 cgd 433: break;
1.5 cgd 434: nlsp = cp - win->lines[wy]->line;
1.42 blymn 435: if (nlsp < 0)
436: nlsp = 0;
1.1 cgd 437: }
1.43 blymn 438: if (!_cursesi_screen->curwin)
1.41 jdc 439: ce = __tc_ce;
1.1 cgd 440: else
1.4 mycroft 441: ce = NULL;
1.1 cgd 442:
443: while (wx <= lch) {
1.35 mycroft 444: if (memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
1.4 mycroft 445: if (wx <= lch) {
1.5 cgd 446: while (wx <= lch &&
1.7 cgd 447: memcmp(nsp, csp, sizeof(__LDATA)) == 0) {
448: nsp++;
1.43 blymn 449: if (!_cursesi_screen->curwin)
1.7 cgd 450: ++csp;
451: ++wx;
452: }
1.4 mycroft 453: continue;
454: }
455: break;
456: }
1.43 blymn 457: domvcur(_cursesi_screen->ly, _cursesi_screen->lx, wy, wx);
1.5 cgd 458:
1.4 mycroft 459: #ifdef DEBUG
1.35 mycroft 460: __CTRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d\n",
1.43 blymn 461: wx, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx);
1.4 mycroft 462: #endif
1.43 blymn 463: _cursesi_screen->ly = wy;
464: _cursesi_screen->lx = wx;
1.35 mycroft 465: while (memcmp(nsp, csp, sizeof(__LDATA)) != 0 && wx <= lch) {
1.7 cgd 466: if (ce != NULL &&
1.23 jdc 467: wx >= nlsp && nsp->ch == ' ' && nsp->attr == lspc) {
1.4 mycroft 468: /* Check for clear to end-of-line. */
1.5 cgd 469: cep = &curscr->lines[wy]->line[win->maxx - 1];
1.23 jdc 470: while (cep->ch == ' ' && cep->attr == lspc)
1.5 cgd 471: if (cep-- <= csp)
1.4 mycroft 472: break;
1.7 cgd 473: clsp = cep - curscr->lines[wy]->line -
1.11 mrg 474: win->begx * __LDATASIZE;
1.4 mycroft 475: #ifdef DEBUG
1.20 jdc 476: __CTRACE("makech: clsp = %d, nlsp = %d\n",
477: clsp, nlsp);
1.4 mycroft 478: #endif
1.41 jdc 479: if (((clsp - nlsp >= strlen(__tc_ce) &&
1.20 jdc 480: clsp < win->maxx * __LDATASIZE) ||
481: wy == win->maxy - 1) &&
1.23 jdc 482: (!(lspc & __COLOR) ||
1.41 jdc 483: ((lspc & __COLOR) && __tc_ut))) {
1.23 jdc 484: __unsetattr(0);
1.47 jdc 485: if (__using_color &&
486: ((lspc & __COLOR) !=
487: (curscr->wattr & __COLOR)))
488: __set_color(curscr, lspc &
489: __COLOR);
1.41 jdc 490: tputs(__tc_ce, 0, __cputchar);
1.43 blymn 491: _cursesi_screen->lx = wx + win->begx;
1.5 cgd 492: while (wx++ <= clsp) {
493: csp->ch = ' ';
1.23 jdc 494: csp->attr = lspc;
1.5 cgd 495: csp++;
496: }
1.4 mycroft 497: return (OK);
1.1 cgd 498: }
1.4 mycroft 499: ce = NULL;
500: }
501:
1.47 jdc 502: #ifdef DEBUG
503: __CTRACE("makech: have attributes %08x, need attributes %08x\n", curscr->wattr, nsp->attr);
504: #endif
1.27 mycroft 505:
506: off = ~nsp->attr & curscr->wattr;
1.16 jdc 507:
508: /*
1.11 mrg 509: * Unset attributes as appropriate. Unset first
510: * so that the relevant attributes can be reset
1.16 jdc 511: * (because 'me' unsets 'mb', 'md', 'mh', 'mk',
512: * 'mp' and 'mr'). Check to see if we also turn off
1.27 mycroft 513: * standout, attributes and colour.
1.11 mrg 514: */
1.41 jdc 515: if (off & __TERMATTR && __tc_me != NULL) {
516: tputs(__tc_me, 0, __cputchar);
517: curscr->wattr &= __mask_me;
518: off &= __mask_me;
1.11 mrg 519: }
520:
521: /*
522: * Exit underscore mode if appropriate.
1.27 mycroft 523: * Check to see if we also turn off standout,
524: * attributes and colour.
1.11 mrg 525: */
1.41 jdc 526: if (off & __UNDERSCORE && __tc_ue != NULL) {
527: tputs(__tc_ue, 0, __cputchar);
528: curscr->wattr &= __mask_ue;
529: off &= __mask_ue;
1.11 mrg 530: }
531:
532: /*
1.27 mycroft 533: * Exit standout mode as appropriate.
534: * Check to see if we also turn off underscore,
535: * attributes and colour.
1.7 cgd 536: * XXX
1.41 jdc 537: * Should use uc if so/se not available.
1.7 cgd 538: */
1.41 jdc 539: if (off & __STANDOUT && __tc_se != NULL) {
540: tputs(__tc_se, 0, __cputchar);
541: curscr->wattr &= __mask_se;
542: off &= __mask_se;
1.27 mycroft 543: }
544:
1.41 jdc 545: if (off & __ALTCHARSET && __tc_ae != NULL) {
546: tputs(__tc_ae, 0, __cputchar);
1.27 mycroft 547: curscr->wattr &= ~__ALTCHARSET;
548: }
549:
1.47 jdc 550: /* Set/change colour as appropriate. */
551: if (__using_color)
552: __set_color(curscr, nsp->attr & __COLOR);
553:
1.27 mycroft 554: on = nsp->attr & ~curscr->wattr;
555:
556: /*
557: * Enter standout mode if appropriate.
558: */
1.41 jdc 559: if (on & __STANDOUT && __tc_so != NULL && __tc_se
560: != NULL) {
561: tputs(__tc_so, 0, __cputchar);
1.27 mycroft 562: curscr->wattr |= __STANDOUT;
1.11 mrg 563: }
564:
565: /*
566: * Enter underscore mode if appropriate.
567: * XXX
1.41 jdc 568: * Should use uc if us/ue not available.
1.11 mrg 569: */
1.41 jdc 570: if (on & __UNDERSCORE && __tc_us != NULL &&
571: __tc_ue != NULL) {
572: tputs(__tc_us, 0, __cputchar);
1.15 blymn 573: curscr->wattr |= __UNDERSCORE;
1.11 mrg 574: }
575:
576: /*
577: * Set other attributes as appropriate.
578: */
1.41 jdc 579: if (__tc_me != NULL) {
580: if (on & __BLINK && __tc_mb != NULL) {
581: tputs(__tc_mb, 0, __cputchar);
1.27 mycroft 582: curscr->wattr |= __BLINK;
583: }
1.41 jdc 584: if (on & __BOLD && __tc_md != NULL) {
585: tputs(__tc_md, 0, __cputchar);
1.27 mycroft 586: curscr->wattr |= __BOLD;
587: }
1.41 jdc 588: if (on & __DIM && __tc_mh != NULL) {
589: tputs(__tc_mh, 0, __cputchar);
1.27 mycroft 590: curscr->wattr |= __DIM;
591: }
1.41 jdc 592: if (on & __BLANK && __tc_mk != NULL) {
593: tputs(__tc_mk, 0, __cputchar);
1.27 mycroft 594: curscr->wattr |= __BLANK;
595: }
1.41 jdc 596: if (on & __PROTECT && __tc_mp != NULL) {
597: tputs(__tc_mp, 0, __cputchar);
1.27 mycroft 598: curscr->wattr |= __PROTECT;
599: }
1.41 jdc 600: if (on & __REVERSE && __tc_mr != NULL) {
601: tputs(__tc_mr, 0, __cputchar);
1.27 mycroft 602: curscr->wattr |= __REVERSE;
603: }
1.15 blymn 604: }
605:
606: /* Enter/exit altcharset mode as appropriate. */
1.41 jdc 607: if (on & __ALTCHARSET && __tc_as != NULL &&
608: __tc_ae != NULL) {
609: tputs(__tc_as, 0, __cputchar);
1.27 mycroft 610: curscr->wattr |= __ALTCHARSET;
1.11 mrg 611: }
1.4 mycroft 612:
613: wx++;
1.23 jdc 614: if (wx >= win->maxx &&
1.43 blymn 615: wy == win->maxy - 1 && !_cursesi_screen->curwin)
1.5 cgd 616: if (win->flags & __SCROLLOK) {
1.28 mycroft 617: if (win->flags & __ENDLINE)
1.23 jdc 618: __unsetattr(1);
1.5 cgd 619: if (!(win->flags & __SCROLLWIN)) {
1.43 blymn 620: if (!_cursesi_screen->curwin) {
1.23 jdc 621: csp->attr = nsp->attr;
1.39 itojun 622: __cputchar((int)
1.23 jdc 623: (csp->ch =
624: nsp->ch));
1.5 cgd 625: } else
1.39 itojun 626: __cputchar((int) nsp->ch);
1.5 cgd 627: }
1.23 jdc 628: if (wx < curscr->maxx) {
1.43 blymn 629: domvcur(_cursesi_screen->ly, wx,
1.23 jdc 630: (int) (win->maxy - 1),
631: (int) (win->maxx - 1));
1.5 cgd 632: }
1.43 blymn 633: _cursesi_screen->ly = win->maxy - 1;
634: _cursesi_screen->lx = win->maxx - 1;
1.4 mycroft 635: return (OK);
1.7 cgd 636: }
637: if (wx < win->maxx || wy < win->maxy - 1 ||
1.5 cgd 638: !(win->flags & __SCROLLWIN)) {
1.43 blymn 639: if (!_cursesi_screen->curwin) {
1.23 jdc 640: csp->attr = nsp->attr;
1.39 itojun 641: __cputchar((int) (csp->ch = nsp->ch));
1.5 cgd 642: csp++;
1.7 cgd 643: } else
1.39 itojun 644: __cputchar((int) nsp->ch);
1.5 cgd 645: }
1.4 mycroft 646: #ifdef DEBUG
1.5 cgd 647: __CTRACE("makech: putchar(%c)\n", nsp->ch & 0177);
1.4 mycroft 648: #endif
1.41 jdc 649: if (__tc_uc && ((nsp->attr & __STANDOUT) ||
1.11 mrg 650: (nsp->attr & __UNDERSCORE))) {
1.39 itojun 651: __cputchar('\b');
1.41 jdc 652: tputs(__tc_uc, 0, __cputchar);
1.1 cgd 653: }
1.4 mycroft 654: nsp++;
655: #ifdef DEBUG
1.43 blymn 656: __CTRACE("makech: 2: wx = %d, lx = %d\n", wx, _cursesi_screen->lx);
1.4 mycroft 657: #endif
1.5 cgd 658: }
1.43 blymn 659: if (_cursesi_screen->lx == wx) /* If no change. */
1.4 mycroft 660: break;
1.43 blymn 661: _cursesi_screen->lx = wx;
662: if (_cursesi_screen->lx >= COLS && __tc_am)
663: _cursesi_screen->lx = COLS - 1;
1.11 mrg 664: else
665: if (wx >= win->maxx) {
1.43 blymn 666: domvcur(_cursesi_screen->ly,
667: _cursesi_screen->lx,
668: _cursesi_screen->ly,
669: (int) (win->maxx - 1));
670: _cursesi_screen->lx = win->maxx - 1;
1.11 mrg 671: }
1.4 mycroft 672: #ifdef DEBUG
1.43 blymn 673: __CTRACE("makech: 3: wx = %d, lx = %d\n", wx,
674: _cursesi_screen->lx);
1.4 mycroft 675: #endif
1.1 cgd 676: }
1.7 cgd 677:
1.4 mycroft 678: return (OK);
1.1 cgd 679: }
680:
681: /*
1.4 mycroft 682: * domvcur --
1.19 jdc 683: * Do a mvcur, leaving attributes if necessary.
1.1 cgd 684: */
1.4 mycroft 685: static void
1.1 cgd 686: domvcur(oy, ox, ny, nx)
1.11 mrg 687: int oy, ox, ny, nx;
1.4 mycroft 688: {
1.23 jdc 689: __unsetattr(1);
1.5 cgd 690: __mvcur(oy, ox, ny, nx, 1);
691: }
692:
693: /*
694: * Quickch() attempts to detect a pattern in the change of the window
1.7 cgd 695: * in order to optimize the change, e.g., scroll n lines as opposed to
1.5 cgd 696: * repainting the screen line by line.
697: */
698:
1.46 christos 699: static __LDATA buf[128];
700: static u_int last_hash;
701: static size_t last_hash_len;
702: #define BLANKSIZE (sizeof(buf) / sizeof(buf[0]))
703:
1.5 cgd 704: static void
1.23 jdc 705: quickch(void)
1.5 cgd 706: {
1.23 jdc 707: #define THRESH (int) __virtscr->maxy / 4
1.5 cgd 708:
1.10 perry 709: __LINE *clp, *tmp1, *tmp2;
1.11 mrg 710: int bsize, curs, curw, starts, startw, i, j;
711: int n, target, cur_period, bot, top, sc_region;
712: u_int blank_hash;
1.22 jdc 713: attr_t bcolor;
1.5 cgd 714:
1.8 mikel 715: #ifdef __GNUC__
1.11 mrg 716: curs = curw = starts = startw = 0; /* XXX gcc -Wuninitialized */
1.8 mikel 717: #endif
1.7 cgd 718: /*
1.5 cgd 719: * Find how many lines from the top of the screen are unchanged.
720: */
1.23 jdc 721: for (top = 0; top < __virtscr->maxy; top++)
1.35 mycroft 722: if (__virtscr->lines[top]->flags & __ISDIRTY &&
723: (__virtscr->lines[top]->hash != curscr->lines[top]->hash ||
724: memcmp(__virtscr->lines[top]->line,
1.32 mycroft 725: curscr->lines[top]->line,
1.35 mycroft 726: (size_t) __virtscr->maxx * __LDATASIZE) != 0))
1.5 cgd 727: break;
728: else
1.23 jdc 729: __virtscr->lines[top]->flags &= ~__ISDIRTY;
1.11 mrg 730: /*
731: * Find how many lines from bottom of screen are unchanged.
732: */
1.23 jdc 733: for (bot = __virtscr->maxy - 1; bot >= 0; bot--)
1.35 mycroft 734: if (__virtscr->lines[bot]->flags & __ISDIRTY &&
735: (__virtscr->lines[bot]->hash != curscr->lines[bot]->hash ||
736: memcmp(__virtscr->lines[bot]->line,
1.32 mycroft 737: curscr->lines[bot]->line,
1.35 mycroft 738: (size_t) __virtscr->maxx * __LDATASIZE) != 0))
1.5 cgd 739: break;
740: else
1.23 jdc 741: __virtscr->lines[bot]->flags &= ~__ISDIRTY;
742:
743: /*
744: * Work round an xterm bug where inserting lines causes all the
745: * inserted lines to be covered with the background colour we
746: * set on the first line (even if we unset it for subsequent
747: * lines).
748: */
749: bcolor = __virtscr->lines[min(top,
750: __virtscr->maxy - 1)]->line[0].attr & __COLOR;
751: for (i = top + 1, j = 0; i < bot; i++) {
752: if ((__virtscr->lines[i]->line[0].attr & __COLOR) != bcolor) {
753: bcolor = __virtscr->lines[i]->line[__virtscr->maxx].
754: attr & __COLOR;
755: j = i - top;
756: } else
757: break;
758: }
759: top += j;
1.5 cgd 760:
761: #ifdef NO_JERKINESS
762: /*
763: * If we have a bottom unchanged region return. Scrolling the
764: * bottom region up and then back down causes a screen jitter.
765: * This will increase the number of characters sent to the screen
766: * but it looks better.
767: */
1.23 jdc 768: if (bot < __virtscr->maxy - 1)
1.5 cgd 769: return;
1.11 mrg 770: #endif /* NO_JERKINESS */
1.5 cgd 771:
772: /*
773: * Search for the largest block of text not changed.
774: * Invariants of the loop:
1.23 jdc 775: * - Startw is the index of the beginning of the examined block in
776: * __virtscr.
1.11 mrg 777: * - Starts is the index of the beginning of the examined block in
1.23 jdc 778: * curscr.
1.7 cgd 779: * - Curw is the index of one past the end of the exmined block in
1.23 jdc 780: * __virtscr.
781: * - Curs is the index of one past the end of the exmined block in
1.5 cgd 782: * curscr.
783: * - bsize is the current size of the examined block.
1.11 mrg 784: */
1.23 jdc 785:
1.5 cgd 786: for (bsize = bot - top; bsize >= THRESH; bsize--) {
787: for (startw = top; startw <= bot - bsize; startw++)
1.7 cgd 788: for (starts = top; starts <= bot - bsize;
1.11 mrg 789: starts++) {
1.5 cgd 790: for (curw = startw, curs = starts;
1.11 mrg 791: curs < starts + bsize; curw++, curs++)
1.35 mycroft 792: if (__virtscr->lines[curw]->hash !=
793: curscr->lines[curs]->hash)
1.32 mycroft 794: break;
795: if (curs != starts + bsize)
796: continue;
797: for (curw = startw, curs = starts;
798: curs < starts + bsize; curw++, curs++)
799: if (memcmp(__virtscr->lines[curw]->line,
800: curscr->lines[curs]->line,
801: (size_t) __virtscr->maxx *
802: __LDATASIZE) != 0)
1.5 cgd 803: break;
804: if (curs == starts + bsize)
805: goto done;
806: }
807: }
1.11 mrg 808: done:
1.22 jdc 809:
1.5 cgd 810: /* Did not find anything */
1.7 cgd 811: if (bsize < THRESH)
1.5 cgd 812: return;
813:
814: #ifdef DEBUG
1.7 cgd 815: __CTRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n",
1.11 mrg 816: bsize, starts, startw, curw, curs, top, bot);
1.5 cgd 817: #endif
818:
1.7 cgd 819: /*
820: * Make sure that there is no overlap between the bottom and top
1.5 cgd 821: * regions and the middle scrolled block.
822: */
823: if (bot < curs)
824: bot = curs - 1;
825: if (top > starts)
826: top = starts;
827:
828: n = startw - starts;
829:
830: #ifdef DEBUG
1.11 mrg 831: __CTRACE("#####################################\n");
832: for (i = 0; i < curscr->maxy; i++) {
833: __CTRACE("C: %d:", i);
834: __CTRACE(" 0x%x \n", curscr->lines[i]->hash);
835: for (j = 0; j < curscr->maxx; j++)
836: __CTRACE("%c", curscr->lines[i]->line[j].ch);
837: __CTRACE("\n");
1.14 simonb 838: __CTRACE(" attr:");
1.11 mrg 839: for (j = 0; j < curscr->maxx; j++)
1.14 simonb 840: __CTRACE(" %x", curscr->lines[i]->line[j].attr);
1.11 mrg 841: __CTRACE("\n");
842: __CTRACE("W: %d:", i);
1.23 jdc 843: __CTRACE(" 0x%x \n", __virtscr->lines[i]->hash);
844: __CTRACE(" 0x%x ", __virtscr->lines[i]->flags);
845: for (j = 0; j < __virtscr->maxx; j++)
846: __CTRACE("%c", __virtscr->lines[i]->line[j].ch);
1.11 mrg 847: __CTRACE("\n");
1.14 simonb 848: __CTRACE(" attr:");
1.23 jdc 849: for (j = 0; j < __virtscr->maxx; j++)
850: __CTRACE(" %x", __virtscr->lines[i]->line[j].attr);
1.11 mrg 851: __CTRACE("\n");
852: }
1.7 cgd 853: #endif
854:
1.46 christos 855: if (buf[0].ch != ' ') {
856: for (i = 0; i < BLANKSIZE; i++) {
857: buf[i].ch = ' ';
858: buf[i].bch = ' ';
859: buf[i].attr = 0;
860: buf[i].battr = 0;
861: }
1.5 cgd 862: }
1.46 christos 863:
864: if (__virtscr->maxx != last_hash_len) {
865: blank_hash = 0;
866: for (i = __virtscr->maxx; i > BLANKSIZE; i -= BLANKSIZE) {
867: blank_hash = __hash_more((char *)(void *)buf, sizeof(buf),
868: blank_hash);
869: }
870: blank_hash = __hash_more((char *)(void *)buf,
871: i * sizeof(buf[0]), blank_hash);
872: /* cache result in static data - screen width doesn't change often */
873: last_hash_len = __virtscr->maxx;
874: last_hash = blank_hash;
875: } else
876: blank_hash = last_hash;
1.5 cgd 877:
878: /*
879: * Perform the rotation to maintain the consistency of curscr.
880: * This is hairy since we are doing an *in place* rotation.
881: * Invariants of the loop:
882: * - I is the index of the current line.
883: * - Target is the index of the target of line i.
884: * - Tmp1 points to current line (i).
885: * - Tmp2 and points to target line (target);
1.7 cgd 886: * - Cur_period is the index of the end of the current period.
1.5 cgd 887: * (see below).
888: *
889: * There are 2 major issues here that make this rotation non-trivial:
890: * 1. Scrolling in a scrolling region bounded by the top
891: * and bottom regions determined (whose size is sc_region).
1.7 cgd 892: * 2. As a result of the use of the mod function, there may be a
1.5 cgd 893: * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
894: * 0 to 2, which then causes all odd lines not to be rotated.
1.7 cgd 895: * To remedy this, an index of the end ( = beginning) of the
896: * current 'period' is kept, cur_period, and when it is reached,
897: * the next period is started from cur_period + 1 which is
1.5 cgd 898: * guaranteed not to have been reached since that would mean that
899: * all records would have been reached. (think about it...).
1.7 cgd 900: *
1.5 cgd 901: * Lines in the rotation can have 3 attributes which are marked on the
902: * line so that curscr is consistent with the visual screen.
903: * 1. Not dirty -- lines inside the scrolled block, top region or
904: * bottom region.
1.7 cgd 905: * 2. Blank lines -- lines in the differential of the scrolling
906: * region adjacent to top and bot regions
1.5 cgd 907: * depending on scrolling direction.
908: * 3. Dirty line -- all other lines are marked dirty.
909: */
910: sc_region = bot - top + 1;
911: i = top;
912: tmp1 = curscr->lines[top];
913: cur_period = top;
914: for (j = top; j <= bot; j++) {
915: target = (i - top + n + sc_region) % sc_region + top;
916: tmp2 = curscr->lines[target];
917: curscr->lines[target] = tmp1;
918: /* Mark block as clean and blank out scrolled lines. */
919: clp = curscr->lines[target];
920: #ifdef DEBUG
921: __CTRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ",
1.11 mrg 922: n, startw, curw, i, target);
1.5 cgd 923: #endif
1.7 cgd 924: if ((target >= startw && target < curw) || target < top
1.5 cgd 925: || target > bot) {
926: #ifdef DEBUG
1.22 jdc 927: __CTRACE("-- notdirty\n");
1.5 cgd 928: #endif
1.23 jdc 929: __virtscr->lines[target]->flags &= ~__ISDIRTY;
1.11 mrg 930: } else
931: if ((n > 0 && target >= top && target < top + n) ||
932: (n < 0 && target <= bot && target > bot + n)) {
933: if (clp->hash != blank_hash || memcmp(clp->line,
1.46 christos 934: clp->line + 1, (__virtscr->maxx - 1) *
935: __LDATASIZE) || memcmp(clp->line, buf,
936: __LDATASIZE)) {
937: for (i = __virtscr->maxx; i > BLANKSIZE;
938: i -= BLANKSIZE) {
939: (void)memcpy(clp->line + i -
940: BLANKSIZE, buf, sizeof(buf));
941: }
942: (void)memcpy(clp->line , buf, i *
943: sizeof(buf[0]));
1.11 mrg 944: #ifdef DEBUG
1.22 jdc 945: __CTRACE("-- blanked out: dirty\n");
1.11 mrg 946: #endif
947: clp->hash = blank_hash;
1.35 mycroft 948: __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1);
1.11 mrg 949: } else {
1.5 cgd 950: #ifdef DEBUG
1.22 jdc 951: __CTRACE(" -- blank line already: dirty\n");
1.5 cgd 952: #endif
1.35 mycroft 953: __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1);
1.11 mrg 954: }
1.5 cgd 955: } else {
956: #ifdef DEBUG
1.22 jdc 957: __CTRACE(" -- dirty\n");
1.5 cgd 958: #endif
1.35 mycroft 959: __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1);
1.5 cgd 960: }
961: if (target == cur_period) {
962: i = target + 1;
963: tmp1 = curscr->lines[i];
964: cur_period = i;
965: } else {
966: tmp1 = tmp2;
967: i = target;
968: }
969: }
970: #ifdef DEBUG
1.11 mrg 971: __CTRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
972: for (i = 0; i < curscr->maxy; i++) {
973: __CTRACE("C: %d:", i);
974: for (j = 0; j < curscr->maxx; j++)
975: __CTRACE("%c", curscr->lines[i]->line[j].ch);
976: __CTRACE("\n");
977: __CTRACE("W: %d:", i);
1.23 jdc 978: for (j = 0; j < __virtscr->maxx; j++)
979: __CTRACE("%c", __virtscr->lines[i]->line[j].ch);
1.11 mrg 980: __CTRACE("\n");
981: }
1.5 cgd 982: #endif
1.23 jdc 983: if (n != 0)
984: scrolln(starts, startw, curs, bot, top);
1.5 cgd 985: }
986:
987: /*
1.7 cgd 988: * scrolln --
989: * Scroll n lines, where n is starts - startw.
1.5 cgd 990: */
1.11 mrg 991: static void /* ARGSUSED */
1.23 jdc 992: scrolln(starts, startw, curs, bot, top)
1.11 mrg 993: int starts, startw, curs, bot, top;
1.5 cgd 994: {
1.11 mrg 995: int i, oy, ox, n;
1.5 cgd 996:
997: oy = curscr->cury;
998: ox = curscr->curx;
999: n = starts - startw;
1000:
1.7 cgd 1001: /*
1002: * XXX
1003: * The initial tests that set __noqch don't let us reach here unless
1.41 jdc 1004: * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr
1.7 cgd 1005: * scrolling can only shift the entire scrolling region, not just a
1006: * part of it, which means that the quickch() routine is going to be
1.41 jdc 1007: * sadly disappointed in us if we don't have cs as well.
1.7 cgd 1008: *
1.41 jdc 1009: * If cs, ho and SF/sf are set, can use the scrolling region. Because
1010: * the cursor position after cs is undefined, we need ho which gives us
1.7 cgd 1011: * the ability to move to somewhere without knowledge of the current
1012: * location of the cursor. Still call __mvcur() anyway, to update its
1013: * idea of where the cursor is.
1014: *
1015: * When the scrolling region has been set, the cursor has to be at the
1016: * last line of the region to make the scroll happen.
1017: *
1018: * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr
1.41 jdc 1019: * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not
1.7 cgd 1020: * SF/SR. So, if we're scrolling almost all of the screen, try and use
1021: * AL/DL, otherwise use the scrolling region. The "almost all" is a
1022: * shameless hack for vi.
1023: */
1.5 cgd 1024: if (n > 0) {
1.41 jdc 1025: if (__tc_cs != NULL && __tc_ho != NULL && (__tc_SF != NULL ||
1026: ((__tc_AL == NULL || __tc_DL == NULL ||
1027: top > 3 || bot + 3 < __virtscr->maxy) &&
1028: __tc_sf != NULL))) {
1029: tputs(__tscroll(__tc_cs, top, bot + 1), 0, __cputchar);
1.7 cgd 1030: __mvcur(oy, ox, 0, 0, 1);
1.41 jdc 1031: tputs(__tc_ho, 0, __cputchar);
1.7 cgd 1032: __mvcur(0, 0, bot, 0, 1);
1.41 jdc 1033: if (__tc_SF != NULL)
1034: tputs(__tscroll(__tc_SF, n, 0), 0, __cputchar);
1.7 cgd 1035: else
1036: for (i = 0; i < n; i++)
1.41 jdc 1037: tputs(__tc_sf, 0, __cputchar);
1038: tputs(__tscroll(__tc_cs, 0, (int) __virtscr->maxy), 0,
1039: __cputchar);
1.7 cgd 1040: __mvcur(bot, 0, 0, 0, 1);
1.41 jdc 1041: tputs(__tc_ho, 0, __cputchar);
1.7 cgd 1042: __mvcur(0, 0, oy, ox, 1);
1043: return;
1044: }
1045:
1046: /* Scroll up the block. */
1.41 jdc 1047: if (__tc_SF != NULL && top == 0) {
1.7 cgd 1048: __mvcur(oy, ox, bot, 0, 1);
1.41 jdc 1049: tputs(__tscroll(__tc_SF, n, 0), 0, __cputchar);
1.7 cgd 1050: } else
1.41 jdc 1051: if (__tc_DL != NULL) {
1.11 mrg 1052: __mvcur(oy, ox, top, 0, 1);
1.41 jdc 1053: tputs(__tscroll(__tc_DL, n, 0), 0, __cputchar);
1.11 mrg 1054: } else
1.41 jdc 1055: if (__tc_dl != NULL) {
1.11 mrg 1056: __mvcur(oy, ox, top, 0, 1);
1057: for (i = 0; i < n; i++)
1.41 jdc 1058: tputs(__tc_dl, 0, __cputchar);
1.11 mrg 1059: } else
1.41 jdc 1060: if (__tc_sf != NULL && top == 0) {
1.11 mrg 1061: __mvcur(oy, ox, bot, 0, 1);
1062: for (i = 0; i < n; i++)
1.41 jdc 1063: tputs(__tc_sf, 0,
1064: __cputchar);
1.11 mrg 1065: } else
1066: abort();
1.5 cgd 1067:
1.7 cgd 1068: /* Push down the bottom region. */
1.5 cgd 1069: __mvcur(top, 0, bot - n + 1, 0, 1);
1.41 jdc 1070: if (__tc_AL != NULL)
1071: tputs(__tscroll(__tc_AL, n, 0), 0, __cputchar);
1.5 cgd 1072: else
1.41 jdc 1073: if (__tc_al != NULL)
1.11 mrg 1074: for (i = 0; i < n; i++)
1.41 jdc 1075: tputs(__tc_al, 0, __cputchar);
1.11 mrg 1076: else
1077: abort();
1.5 cgd 1078: __mvcur(bot - n + 1, 0, oy, ox, 1);
1079: } else {
1.7 cgd 1080: /*
1081: * !!!
1082: * n < 0
1083: *
1.41 jdc 1084: * If cs, ho and SR/sr are set, can use the scrolling region.
1.7 cgd 1085: * See the above comments for details.
1086: */
1.41 jdc 1087: if (__tc_cs != NULL && __tc_ho != NULL && (__tc_SR != NULL ||
1088: ((__tc_AL == NULL || __tc_DL == NULL || top > 3 ||
1089: bot + 3 < __virtscr->maxy) && __tc_sr != NULL))) {
1090: tputs(__tscroll(__tc_cs, top, bot + 1), 0, __cputchar);
1.7 cgd 1091: __mvcur(oy, ox, 0, 0, 1);
1.41 jdc 1092: tputs(__tc_ho, 0, __cputchar);
1.7 cgd 1093: __mvcur(0, 0, top, 0, 1);
1094:
1.41 jdc 1095: if (__tc_SR != NULL)
1096: tputs(__tscroll(__tc_SR, -n, 0), 0, __cputchar);
1.7 cgd 1097: else
1098: for (i = n; i < 0; i++)
1.41 jdc 1099: tputs(__tc_sr, 0, __cputchar);
1100: tputs(__tscroll(__tc_cs, 0, (int) __virtscr->maxy), 0,
1101: __cputchar);
1.7 cgd 1102: __mvcur(top, 0, 0, 0, 1);
1.41 jdc 1103: tputs(__tc_ho, 0, __cputchar);
1.7 cgd 1104: __mvcur(0, 0, oy, ox, 1);
1105: return;
1106: }
1107:
1108: /* Preserve the bottom lines. */
1109: __mvcur(oy, ox, bot + n + 1, 0, 1);
1.41 jdc 1110: if (__tc_SR != NULL && bot == __virtscr->maxy)
1111: tputs(__tscroll(__tc_SR, -n, 0), 0, __cputchar);
1.5 cgd 1112: else
1.41 jdc 1113: if (__tc_DL != NULL)
1114: tputs(__tscroll(__tc_DL, -n, 0), 0, __cputchar);
1.11 mrg 1115: else
1.41 jdc 1116: if (__tc_dl != NULL)
1.11 mrg 1117: for (i = n; i < 0; i++)
1.41 jdc 1118: tputs(__tc_dl, 0, __cputchar);
1.11 mrg 1119: else
1.41 jdc 1120: if (__tc_sr != NULL &&
1121: bot == __virtscr->maxy)
1.11 mrg 1122: for (i = n; i < 0; i++)
1.41 jdc 1123: tputs(__tc_sr, 0,
1124: __cputchar);
1.11 mrg 1125: else
1126: abort();
1.7 cgd 1127:
1128: /* Scroll the block down. */
1.5 cgd 1129: __mvcur(bot + n + 1, 0, top, 0, 1);
1.41 jdc 1130: if (__tc_AL != NULL)
1131: tputs(__tscroll(__tc_AL, -n, 0), 0, __cputchar);
1.5 cgd 1132: else
1.41 jdc 1133: if (__tc_al != NULL)
1.11 mrg 1134: for (i = n; i < 0; i++)
1.41 jdc 1135: tputs(__tc_al, 0, __cputchar);
1.11 mrg 1136: else
1137: abort();
1.5 cgd 1138: __mvcur(top, 0, oy, ox, 1);
1.19 jdc 1139: }
1140: }
1141:
1142: /*
1.23 jdc 1143: * __unsetattr --
1.19 jdc 1144: * Unset attributes on curscr. Leave standout, attribute and colour
1.41 jdc 1145: * modes if necessary (!ms). Always leave altcharset (xterm at least
1.19 jdc 1146: * ignores a cursor move if we don't).
1147: */
1.23 jdc 1148: void /* ARGSUSED */
1149: __unsetattr(int checkms)
1.19 jdc 1150: {
1151: int isms;
1152:
1153: if (checkms)
1.41 jdc 1154: if (!__tc_ms) {
1.19 jdc 1155: isms = 1;
1156: } else {
1157: isms = 0;
1158: }
1159: else
1160: isms = 1;
1.20 jdc 1161: #ifdef DEBUG
1.41 jdc 1162: __CTRACE("__unsetattr: checkms = %d, ms = %s, wattr = %08x\n",
1163: checkms, __tc_ms ? "TRUE" : "FALSE", curscr->wattr);
1.20 jdc 1164: #endif
1.19 jdc 1165:
1.20 jdc 1166: /*
1.41 jdc 1167: * Don't leave the screen in standout mode (check against ms). Check
1.27 mycroft 1168: * to see if we also turn off underscore, attributes and colour.
1.20 jdc 1169: */
1.19 jdc 1170: if (curscr->wattr & __STANDOUT && isms) {
1.41 jdc 1171: tputs(__tc_se, 0, __cputchar);
1172: curscr->wattr &= __mask_se;
1.19 jdc 1173: }
1.20 jdc 1174: /*
1.41 jdc 1175: * Don't leave the screen in underscore mode (check against ms).
1.26 jdc 1176: * Check to see if we also turn off attributes. Assume that we
1177: * also turn off colour.
1.20 jdc 1178: */
1.19 jdc 1179: if (curscr->wattr & __UNDERSCORE && isms) {
1.41 jdc 1180: tputs(__tc_ue, 0, __cputchar);
1181: curscr->wattr &= __mask_ue;
1.19 jdc 1182: }
1.20 jdc 1183: /*
1.41 jdc 1184: * Don't leave the screen with attributes set (check against ms).
1.26 jdc 1185: * Assume that also turn off colour.
1.20 jdc 1186: */
1187: if (curscr->wattr & __TERMATTR && isms) {
1.41 jdc 1188: tputs(__tc_me, 0, __cputchar);
1189: curscr->wattr &= __mask_me;
1.19 jdc 1190: }
1.41 jdc 1191: /* Don't leave the screen with altcharset set (don't check ms). */
1.19 jdc 1192: if (curscr->wattr & __ALTCHARSET) {
1.41 jdc 1193: tputs(__tc_ae, 0, __cputchar);
1.19 jdc 1194: curscr->wattr &= ~__ALTCHARSET;
1195: }
1.41 jdc 1196: /* Don't leave the screen with colour set (check against ms). */
1.47 jdc 1197: if (__using_color && isms)
1198: __unset_color(curscr);
1.1 cgd 1199: }
CVSweb <webmaster@jp.NetBSD.org>