diff options
Diffstat (limited to 'lib/libcurses/refresh.c')
-rw-r--r-- | lib/libcurses/refresh.c | 344 |
1 files changed, 224 insertions, 120 deletions
diff --git a/lib/libcurses/refresh.c b/lib/libcurses/refresh.c index 1cd62f0..3271bd9 100644 --- a/lib/libcurses/refresh.c +++ b/lib/libcurses/refresh.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1981, 1993 + * Copyright (c) 1981, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,18 +32,19 @@ */ #ifndef lint -static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 7/20/93"; +static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94"; #endif /* not lint */ -#include <curses.h> #include <string.h> +#include "curses.h" + static int curwin; static short ly, lx; static void domvcur __P((int, int, int, int)); static int makech __P((WINDOW *, int)); -static void quickch __P((WINDOW *)); +static void quickch __P((WINDOW *)); static void scrolln __P((WINDOW *, int, int, int, int, int)); /* @@ -59,7 +60,7 @@ wrefresh(win) register int retval; register short wy; int dnum; - + /* Initialize loop parameters. */ ly = curscr->cury; lx = curscr->curx; @@ -70,8 +71,8 @@ wrefresh(win) for (wy = 0; wy < win->maxy; wy++) { wlp = win->lines[wy]; if (wlp->flags & __ISDIRTY) - wlp->hash = - __hash((char *) wlp->line, win->maxx * __LDATASIZE); + wlp->hash = __hash((char *)wlp->line, + win->maxx * __LDATASIZE); } if (win->flags & __CLEAROK || curscr->flags & __CLEAROK || curwin) { @@ -120,23 +121,23 @@ wrefresh(win) for (i = 0; i < curscr->maxy; i++) { __CTRACE("C: %d:", i); __CTRACE(" 0x%x \n", curscr->lines[i]->hash); - for (j = 0; j < curscr->maxx; j++) - __CTRACE("%c", + for (j = 0; j < curscr->maxx; j++) + __CTRACE("%c", curscr->lines[i]->line[j].ch); __CTRACE("\n"); - for (j = 0; j < curscr->maxx; j++) - __CTRACE("%x", + for (j = 0; j < curscr->maxx; j++) + __CTRACE("%x", curscr->lines[i]->line[j].attr); __CTRACE("\n"); __CTRACE("W: %d:", i); __CTRACE(" 0x%x \n", win->lines[i]->hash); __CTRACE(" 0x%x ", win->lines[i]->flags); - for (j = 0; j < win->maxx; j++) - __CTRACE("%c", + for (j = 0; j < win->maxx; j++) + __CTRACE("%c", win->lines[i]->line[j].ch); __CTRACE("\n"); - for (j = 0; j < win->maxx; j++) - __CTRACE("%x", + for (j = 0; j < win->maxx; j++) + __CTRACE("%x", win->lines[i]->line[j].attr); __CTRACE("\n"); } @@ -160,7 +161,7 @@ wrefresh(win) if (*win->lines[wy]->lastchp < win->maxx + win->ch_off) *win->lines[wy]->lastchp = win->ch_off; - if (*win->lines[wy]->lastchp < + if (*win->lines[wy]->lastchp < *win->lines[wy]->firstchp) { #ifdef DEBUG __CTRACE("wrefresh: line %d notdirty \n", wy); @@ -171,11 +172,11 @@ wrefresh(win) } #ifdef DEBUG - __CTRACE("\t%d\t%d\n", *win->lines[wy]->firstchp, + __CTRACE("\t%d\t%d\n", *win->lines[wy]->firstchp, *win->lines[wy]->lastchp); #endif } - + #ifdef DEBUG __CTRACE("refresh: ly=%d, lx=%d\n", ly, lx); #endif @@ -217,10 +218,10 @@ makech(win, wy) int wy; { static __LDATA blank = {' ', 0}; - register int nlsp, clsp; /* Last space in lines. */ - register int wx, lch, y; - register __LDATA *nsp, *csp, *cp, *cep; + __LDATA *nsp, *csp, *cp, *cep; u_int force; + int clsp, nlsp; /* Last space in lines. */ + int lch, wx, y; char *ce; /* Is the cursor still on the end of the last line? */ @@ -250,7 +251,7 @@ makech(win, wy) force = win->lines[wy]->flags & __FORCEPAINT; win->lines[wy]->flags &= ~__FORCEPAINT; if (CE && !curwin) { - for (cp = &win->lines[wy]->line[win->maxx - 1]; + for (cp = &win->lines[wy]->line[win->maxx - 1]; cp->ch == ' ' && cp->attr == 0; cp--) if (cp <= win->lines[wy]->line) break; @@ -269,16 +270,17 @@ makech(win, wy) __mvcur(0, 0, ly, lx, 1); } } + while (wx <= lch) { if (!force && memcmp(nsp, csp, sizeof(__LDATA)) == 0) { if (wx <= lch) { while (wx <= lch && - memcmp(nsp, csp, sizeof(__LDATA)) == 0) { - nsp++; - if (!curwin) - csp++; - ++wx; - } + memcmp(nsp, csp, sizeof(__LDATA)) == 0) { + nsp++; + if (!curwin) + ++csp; + ++wx; + } continue; } break; @@ -286,32 +288,34 @@ makech(win, wy) domvcur(ly, lx, y, wx + win->begx); #ifdef DEBUG - __CTRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d, force =%d\n", + __CTRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d, force =%d\n", wx, ly, lx, y, wx + win->begx, force); #endif ly = y; lx = wx + win->begx; - while ((force || memcmp(nsp, csp, sizeof(__LDATA)) != 0) + while ((force || memcmp(nsp, csp, sizeof(__LDATA)) != 0) && wx <= lch) { - if (ce != NULL && win->maxx + win->begx == - curscr->maxx && wx >= nlsp && nsp->ch == ' ') { + if (ce != NULL && + win->maxx + win->begx == curscr->maxx && + wx >= nlsp && nsp->ch == ' ' && nsp->attr == 0) { /* Check for clear to end-of-line. */ cep = &curscr->lines[wy]->line[win->maxx - 1]; while (cep->ch == ' ' && cep->attr == 0) if (cep-- <= csp) break; - clsp = cep - curscr->lines[wy]->line - + clsp = cep - curscr->lines[wy]->line - win->begx * __LDATASIZE; #ifdef DEBUG __CTRACE("makech: clsp = %d, nlsp = %d\n", clsp, nlsp); #endif - if ((clsp - nlsp >= strlen(CE) + if ((clsp - nlsp >= strlen(CE) && clsp < win->maxx * __LDATASIZE) || wy == win->maxy - 1) { -#ifdef DEBUG - __CTRACE("makech: using CE\n"); -#endif + if (curscr->flags & __WSTANDOUT) { + tputs(SE, 0, __cputchar); + curscr->flags &= ~__WSTANDOUT; + } tputs(CE, 0, __cputchar); lx = wx + win->begx; while (wx++ <= clsp) { @@ -324,17 +328,23 @@ makech(win, wy) ce = NULL; } - /* Enter/exit standout mode as appropriate. */ - if (SO && (nsp->attr & __STANDOUT) != - (curscr->flags & __WSTANDOUT)) { - if (nsp->attr & __STANDOUT) { + /* + * Enter/exit standout mode as appropriate. + * XXX + * Should use UC if SO/SE not available. + */ + if (nsp->attr & __STANDOUT) { + if (!(curscr->flags & __WSTANDOUT) && + SO != NULL && SE != NULL) { tputs(SO, 0, __cputchar); curscr->flags |= __WSTANDOUT; - } else { + } + } else + if (curscr->flags & __WSTANDOUT && + SE != NULL) { tputs(SE, 0, __cputchar); curscr->flags &= ~__WSTANDOUT; } - } wx++; if (wx >= win->maxx && wy == win->maxy - 1 && !curwin) @@ -355,21 +365,21 @@ makech(win, wy) putchar(nsp->ch); } if (wx + win->begx < curscr->maxx) { - domvcur(ly, wx + win->begx, + domvcur(ly, wx + win->begx, win->begy + win->maxy - 1, win->begx + win->maxx - 1); } ly = win->begy + win->maxy - 1; lx = win->begx + win->maxx - 1; return (OK); - } - if (wx < win->maxx || wy < win->maxy - 1 || + } + if (wx < win->maxx || wy < win->maxy - 1 || !(win->flags & __SCROLLWIN)) { if (!curwin) { csp->attr = nsp->attr; putchar(csp->ch = nsp->ch); csp++; - } else + } else putchar(nsp->ch); } #ifdef DEBUG @@ -398,6 +408,12 @@ makech(win, wy) __CTRACE("makech: 3: wx = %d, lx = %d\n", wx, lx); #endif } + + /* Don't leave the screen in standout mode. */ + if (curscr->flags & __WSTANDOUT) { + tputs(SE, 0, __cputchar); + curscr->flags &= ~__WSTANDOUT; + } return (OK); } @@ -419,7 +435,7 @@ domvcur(oy, ox, ny, nx) /* * Quickch() attempts to detect a pattern in the change of the window - * in order to optimize the change, e.g., scroll n lines as opposed to + * in order to optimize the change, e.g., scroll n lines as opposed to * repainting the screen line by line. */ @@ -435,26 +451,26 @@ quickch(win) __LDATA buf[1024]; u_int blank_hash; - /* + /* * Find how many lines from the top of the screen are unchanged. */ - for (top = 0; top < win->maxy; top++) + for (top = 0; top < win->maxy; top++) if (win->lines[top]->flags & __FORCEPAINT || - win->lines[top]->hash != curscr->lines[top]->hash - || memcmp(win->lines[top]->line, - curscr->lines[top]->line, + win->lines[top]->hash != curscr->lines[top]->hash + || memcmp(win->lines[top]->line, + curscr->lines[top]->line, win->maxx * __LDATASIZE) != 0) break; else win->lines[top]->flags &= ~__ISDIRTY; /* - * Find how many lines from bottom of screen are unchanged. + * Find how many lines from bottom of screen are unchanged. */ for (bot = win->maxy - 1; bot >= 0; bot--) if (win->lines[bot]->flags & __FORCEPAINT || - win->lines[bot]->hash != curscr->lines[bot]->hash - || memcmp(win->lines[bot]->line, - curscr->lines[bot]->line, + win->lines[bot]->hash != curscr->lines[bot]->hash + || memcmp(win->lines[bot]->line, + curscr->lines[bot]->line, win->maxx * __LDATASIZE) != 0) break; else @@ -475,16 +491,16 @@ quickch(win) * Search for the largest block of text not changed. * Invariants of the loop: * - Startw is the index of the beginning of the examined block in win. - * - Starts is the index of the beginning of the examined block in + * - Starts is the index of the beginning of the examined block in * curscr. * - Curs is the index of one past the end of the exmined block in win. - * - Curw is the index of one past the end of the exmined block in + * - Curw is the index of one past the end of the exmined block in * curscr. * - bsize is the current size of the examined block. */ for (bsize = bot - top; bsize >= THRESH; bsize--) { for (startw = top; startw <= bot - bsize; startw++) - for (starts = top; starts <= bot - bsize; + for (starts = top; starts <= bot - bsize; starts++) { for (curw = startw, curs = starts; curs < starts + bsize; curw++, curs++) @@ -492,8 +508,8 @@ quickch(win) __FORCEPAINT || (win->lines[curw]->hash != curscr->lines[curs]->hash || - memcmp(win->lines[curw]->line, - curscr->lines[curs]->line, + memcmp(win->lines[curw]->line, + curscr->lines[curs]->line, win->maxx * __LDATASIZE) != 0)) break; if (curs == starts + bsize) @@ -502,16 +518,16 @@ quickch(win) } done: /* Did not find anything */ - if (bsize < THRESH) + if (bsize < THRESH) return; #ifdef DEBUG - __CTRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n", + __CTRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n", bsize, starts, startw, curw, curs, top, bot); #endif - /* - * Make sure that there is no overlap between the bottom and top + /* + * Make sure that there is no overlap between the bottom and top * regions and the middle scrolled block. */ if (bot < curs) @@ -526,28 +542,28 @@ quickch(win) for (i = 0; i < curscr->maxy; i++) { __CTRACE("C: %d:", i); __CTRACE(" 0x%x \n", curscr->lines[i]->hash); - for (j = 0; j < curscr->maxx; j++) - __CTRACE("%c", + for (j = 0; j < curscr->maxx; j++) + __CTRACE("%c", curscr->lines[i]->line[j].ch); __CTRACE("\n"); - for (j = 0; j < curscr->maxx; j++) - __CTRACE("%x", + for (j = 0; j < curscr->maxx; j++) + __CTRACE("%x", curscr->lines[i]->line[j].attr); __CTRACE("\n"); __CTRACE("W: %d:", i); __CTRACE(" 0x%x \n", win->lines[i]->hash); __CTRACE(" 0x%x ", win->lines[i]->flags); - for (j = 0; j < win->maxx; j++) - __CTRACE("%c", + for (j = 0; j < win->maxx; j++) + __CTRACE("%c", win->lines[i]->line[j].ch); __CTRACE("\n"); - for (j = 0; j < win->maxx; j++) - __CTRACE("%x", + for (j = 0; j < win->maxx; j++) + __CTRACE("%x", win->lines[i]->line[j].attr); __CTRACE("\n"); } -#endif - +#endif + /* So we don't have to call __hash() each time */ for (i = 0; i < win->maxx; i++) { buf[i].ch = ' '; @@ -563,27 +579,27 @@ quickch(win) * - Target is the index of the target of line i. * - Tmp1 points to current line (i). * - Tmp2 and points to target line (target); - * - Cur_period is the index of the end of the current period. + * - Cur_period is the index of the end of the current period. * (see below). * * There are 2 major issues here that make this rotation non-trivial: * 1. Scrolling in a scrolling region bounded by the top * and bottom regions determined (whose size is sc_region). - * 2. As a result of the use of the mod function, there may be a + * 2. As a result of the use of the mod function, there may be a * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and * 0 to 2, which then causes all odd lines not to be rotated. - * To remedy this, an index of the end ( = beginning) of the - * current 'period' is kept, cur_period, and when it is reached, - * the next period is started from cur_period + 1 which is + * To remedy this, an index of the end ( = beginning) of the + * current 'period' is kept, cur_period, and when it is reached, + * the next period is started from cur_period + 1 which is * guaranteed not to have been reached since that would mean that * all records would have been reached. (think about it...). - * + * * Lines in the rotation can have 3 attributes which are marked on the * line so that curscr is consistent with the visual screen. * 1. Not dirty -- lines inside the scrolled block, top region or * bottom region. - * 2. Blank lines -- lines in the differential of the scrolling - * region adjacent to top and bot regions + * 2. Blank lines -- lines in the differential of the scrolling + * region adjacent to top and bot regions * depending on scrolling direction. * 3. Dirty line -- all other lines are marked dirty. */ @@ -601,7 +617,7 @@ quickch(win) __CTRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ", n, startw, curw, i, target); #endif - if ((target >= startw && target < curw) || target < top + if ((target >= startw && target < curw) || target < top || target > bot) { #ifdef DEBUG __CTRACE("-- notdirty"); @@ -609,7 +625,7 @@ quickch(win) win->lines[target]->flags &= ~__ISDIRTY; } else if ((n > 0 && target >= top && target < top + n) || (n < 0 && target <= bot && target > bot + n)) { - if (clp->hash != blank_hash || memcmp(clp->line, + if (clp->hash != blank_hash || memcmp(clp->line, buf, win->maxx * __LDATASIZE) !=0) { (void)memcpy(clp->line, buf, win->maxx * __LDATASIZE); @@ -646,14 +662,13 @@ quickch(win) __CTRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); for (i = 0; i < curscr->maxy; i++) { __CTRACE("C: %d:", i); - for (j = 0; j < curscr->maxx; j++) - __CTRACE("%c", + for (j = 0; j < curscr->maxx; j++) + __CTRACE("%c", curscr->lines[i]->line[j].ch); __CTRACE("\n"); __CTRACE("W: %d:", i); - for (j = 0; j < win->maxx; j++) - __CTRACE("%c", - win->lines[i]->line[j].ch); + for (j = 0; j < win->maxx; j++) + __CTRACE("%c", win->lines[i]->line[j].ch); __CTRACE("\n"); } #endif @@ -662,7 +677,7 @@ quickch(win) scrolln(win, starts, startw, curs, bot, top); /* * Need to repoint any subwindow lines to the rotated - * line structured. + * line structured. */ for (wp = win->nextp; wp != win; wp = wp->nextp) __set_subwin(win, wp); @@ -670,7 +685,8 @@ quickch(win) } /* - * Scrolln performs the scroll by n lines, where n is starts - startw. + * scrolln -- + * Scroll n lines, where n is starts - startw. */ static void scrolln(win, starts, startw, curs, bot, top) @@ -683,41 +699,129 @@ scrolln(win, starts, startw, curs, bot, top) ox = curscr->curx; n = starts - startw; + /* + * XXX + * The initial tests that set __noqch don't let us reach here unless + * we have either CS + HO + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr + * scrolling can only shift the entire scrolling region, not just a + * part of it, which means that the quickch() routine is going to be + * sadly disappointed in us if we don't have CS as well. + * + * If CS, HO and SF/sf are set, can use the scrolling region. Because + * the cursor position after CS is undefined, we need HO which gives us + * the ability to move to somewhere without knowledge of the current + * location of the cursor. Still call __mvcur() anyway, to update its + * idea of where the cursor is. + * + * When the scrolling region has been set, the cursor has to be at the + * last line of the region to make the scroll happen. + * + * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr + * or al/dl, and, some terminals have AL/DL, sf/sr, and CS, but not + * SF/SR. So, if we're scrolling almost all of the screen, try and use + * AL/DL, otherwise use the scrolling region. The "almost all" is a + * shameless hack for vi. + */ if (n > 0) { - __mvcur(oy, ox, top, 0, 1); - /* Scroll up the block */ - if (DL) - tputs(__tscroll(DL, n), 0, __cputchar); - else - for(i = 0; i < n; i++) - tputs(dl, 0, __cputchar); + if (CS != NULL && HO != NULL && (SF != NULL || + (AL == NULL || DL == NULL || + top > 3 || bot + 3 < win->maxy) && sf != NULL)) { + tputs(__tscroll(CS, top, bot + 1), 0, __cputchar); + __mvcur(oy, ox, 0, 0, 1); + tputs(HO, 0, __cputchar); + __mvcur(0, 0, bot, 0, 1); + if (SF != NULL) + tputs(__tscroll(SF, n, 0), 0, __cputchar); + else + for (i = 0; i < n; i++) + tputs(sf, 0, __cputchar); + tputs(__tscroll(CS, 0, win->maxy), 0, __cputchar); + __mvcur(bot, 0, 0, 0, 1); + tputs(HO, 0, __cputchar); + __mvcur(0, 0, oy, ox, 1); + return; + } - /* - * Push down the bottom region. - */ + /* Scroll up the block. */ + if (SF != NULL && top == 0) { + __mvcur(oy, ox, bot, 0, 1); + tputs(__tscroll(SF, n, 0), 0, __cputchar); + } else if (DL != NULL) { + __mvcur(oy, ox, top, 0, 1); + tputs(__tscroll(DL, n, 0), 0, __cputchar); + } else if (dl != NULL) { + __mvcur(oy, ox, top, 0, 1); + for (i = 0; i < n; i++) + tputs(dl, 0, __cputchar); + } else if (sf != NULL && top == 0) { + __mvcur(oy, ox, bot, 0, 1); + for (i = 0; i < n; i++) + tputs(sf, 0, __cputchar); + } else + abort(); + + /* Push down the bottom region. */ __mvcur(top, 0, bot - n + 1, 0, 1); - if (AL) - tputs(__tscroll(AL, n), 0, __cputchar); - else - for(i = 0; i < n; i++) + if (AL != NULL) + tputs(__tscroll(AL, n, 0), 0, __cputchar); + else if (al != NULL) + for (i = 0; i < n; i++) tputs(al, 0, __cputchar); + else + abort(); __mvcur(bot - n + 1, 0, oy, ox, 1); } else { - /* Preserve the bottom lines */ - __mvcur(oy, ox, bot + n + 1, 0, 1); /* n < 0 */ - if (DL) - tputs(__tscroll(DL, -n), 0, __cputchar); - else - for(i = n; i < 0; i++) - tputs(dl, 0, __cputchar); - __mvcur(bot + n + 1, 0, top, 0, 1); + /* + * !!! + * n < 0 + * + * If CS, HO and SR/sr are set, can use the scrolling region. + * See the above comments for details. + */ + if (CS != NULL && HO != NULL && (SR != NULL || + (AL == NULL || DL == NULL || + top > 3 || bot + 3 < win->maxy) && sr != NULL)) { + tputs(__tscroll(CS, top, bot + 1), 0, __cputchar); + __mvcur(oy, ox, 0, 0, 1); + tputs(HO, 0, __cputchar); + __mvcur(0, 0, top, 0, 1); + + if (SR != NULL) + tputs(__tscroll(SR, -n, 0), 0, __cputchar); + else + for (i = n; i < 0; i++) + tputs(sr, 0, __cputchar); + tputs(__tscroll(CS, 0, win->maxy), 0, __cputchar); + __mvcur(top, 0, 0, 0, 1); + tputs(HO, 0, __cputchar); + __mvcur(0, 0, oy, ox, 1); + return; + } - /* Scroll the block down */ - if (AL) - tputs(__tscroll(AL, -n), 0, __cputchar); + /* Preserve the bottom lines. */ + __mvcur(oy, ox, bot + n + 1, 0, 1); + if (SR != NULL && bot == win->maxy) + tputs(__tscroll(SR, -n, 0), 0, __cputchar); + else if (DL != NULL) + tputs(__tscroll(DL, -n, 0), 0, __cputchar); + else if (dl != NULL) + for (i = n; i < 0; i++) + tputs(dl, 0, __cputchar); + else if (sr != NULL && bot == win->maxy) + for (i = n; i < 0; i++) + tputs(sr, 0, __cputchar); else - for(i = n; i < 0; i++) + abort(); + + /* Scroll the block down. */ + __mvcur(bot + n + 1, 0, top, 0, 1); + if (AL != NULL) + tputs(__tscroll(AL, -n, 0), 0, __cputchar); + else if (al != NULL) + for (i = n; i < 0; i++) tputs(al, 0, __cputchar); + else + abort(); __mvcur(top, 0, oy, ox, 1); - } + } } |