12261Sarnold /* 234677Sbostic * Copyright (c) 1981 Regents of the University of California. 334677Sbostic * All rights reserved. 434677Sbostic * 542657Sbostic * %sccs.include.redist.c% 622791Smckusick */ 722791Smckusick 822791Smckusick #ifndef lint 9*59775Selan static char sccsid[] = "@(#)refresh.c 5.41 (Berkeley) 05/06/93"; 1034677Sbostic #endif /* not lint */ 1122791Smckusick 1255976Sbostic #include <curses.h> 1355986Sbostic #include <string.h> 142261Sarnold 1555976Sbostic static int curwin; 1655976Sbostic static short ly, lx; 172261Sarnold 1855976Sbostic WINDOW *_win; 192261Sarnold 2055976Sbostic static void domvcur __P((int, int, int, int)); 2155976Sbostic static int makech __P((WINDOW *, int)); 2256302Selan static void quickch __P((WINDOW *)); 2356559Selan static void scrolln __P((WINDOW *, int, int, int, int, int)); 2456648Selan 2555976Sbostic /* 2655976Sbostic * wrefresh -- 2755976Sbostic * Make the current screen look like "win" over the area coverd by 2855976Sbostic * win. 2955976Sbostic */ 3055976Sbostic int 312261Sarnold wrefresh(win) 3255976Sbostic register WINDOW *win; 332261Sarnold { 3456648Selan register __LINE *wlp; 3555976Sbostic register int retval; 3655976Sbostic register short wy; 3758019Selan int dnum; 3858019Selan 3955976Sbostic /* Initialize loop parameters. */ 4056238Selan ly = curscr->cury; 4156238Selan lx = curscr->curx; 422287Sarnold wy = 0; 432287Sarnold _win = win; 442287Sarnold curwin = (win == curscr); 452287Sarnold 4656378Selan if (!curwin) 4756378Selan for (wy = 0; wy < win->maxy; wy++) { 4856378Selan wlp = win->lines[wy]; 4956378Selan if (wlp->flags & __ISDIRTY) 5056648Selan wlp->hash = 5158192Selan __hash((char *) wlp->line, win->maxx * __LDATASIZE); 5256378Selan } 5356378Selan 5456238Selan if (win->flags & __CLEAROK || curscr->flags & __CLEAROK || curwin) { 5556238Selan if ((win->flags & __FULLWIN) || curscr->flags & __CLEAROK) { 5655976Sbostic tputs(CL, 0, __cputchar); 5712358Sarnold ly = 0; 5812358Sarnold lx = 0; 5912358Sarnold if (!curwin) { 6056238Selan curscr->flags &= ~__CLEAROK; 6156238Selan curscr->cury = 0; 6256238Selan curscr->curx = 0; 632287Sarnold werase(curscr); 6412358Sarnold } 6556651Selan __touchwin(win); 662261Sarnold } 6756238Selan win->flags &= ~__CLEAROK; 682261Sarnold } 692261Sarnold if (!CA) { 7056238Selan if (win->curx != 0) 7155976Sbostic putchar('\n'); 722287Sarnold if (!curwin) 732287Sarnold werase(curscr); 742261Sarnold } 7555976Sbostic #ifdef DEBUG 7655976Sbostic __TRACE("wrefresh: (%0.2o): curwin = %d\n", win, curwin); 7755976Sbostic __TRACE("wrefresh: \tfirstch\tlastch\n"); 7855976Sbostic #endif 7956302Selan 8056302Selan #ifndef NOQCH 8158019Selan if ((win->flags & __FULLWIN) && !curwin) { 8258019Selan /* 8358019Selan * Invoke quickch() only if more than a quarter of the lines 8458019Selan * in the window are dirty. 8558019Selan */ 8658019Selan for (wy = 0, dnum = 0; wy < win->maxy; wy++) 8758019Selan if (win->lines[wy]->flags & (__ISDIRTY | __FORCEPAINT)) 8858019Selan dnum++; 8958019Selan if (!__noqch && dnum > (int) win->maxy / 4) 9058019Selan quickch(win); 9158019Selan } 9256302Selan #endif 9356238Selan for (wy = 0; wy < win->maxy; wy++) { 9455976Sbostic #ifdef DEBUG 9555976Sbostic __TRACE("%d\t%d\t%d\n", 9656715Selan wy, *win->lines[wy]->firstchp, *win->lines[wy]->lastchp); 9755976Sbostic #endif 9856378Selan if (!curwin) 9956378Selan curscr->lines[wy]->hash = win->lines[wy]->hash; 10058369Selan if (win->lines[wy]->flags & (__ISDIRTY | __FORCEPAINT)) { 10157472Sbostic if (makech(win, wy) == ERR) 10257472Sbostic return (ERR); 10319893Sbloom else { 10456715Selan if (*win->lines[wy]->firstchp >= win->ch_off) 10556715Selan *win->lines[wy]->firstchp = win->maxx + 10656238Selan win->ch_off; 10756715Selan if (*win->lines[wy]->lastchp < win->maxx + 10856238Selan win->ch_off) 10956715Selan *win->lines[wy]->lastchp = win->ch_off; 11056715Selan if (*win->lines[wy]->lastchp < 11158034Selan *win->lines[wy]->firstchp) { 11258034Selan #ifdef DEBUG 11358034Selan __TRACE("wrefresh: line %d notdirty \n", wy); 11458034Selan #endif 11556238Selan win->lines[wy]->flags &= ~__ISDIRTY; 11658034Selan } 11719893Sbloom } 11858369Selan 11959774Selan } 12055976Sbostic #ifdef DEBUG 12156715Selan __TRACE("\t%d\t%d\n", *win->lines[wy]->firstchp, 12256715Selan *win->lines[wy]->lastchp); 12355976Sbostic #endif 1242261Sarnold } 12556238Selan 12656302Selan #ifdef DEBUG 12756238Selan __TRACE("refresh: ly=%d, lx=%d\n", ly, lx); 12856302Selan #endif 12956472Selan 13012358Sarnold if (win == curscr) 13156238Selan domvcur(ly, lx, win->cury, win->curx); 13219893Sbloom else { 13356238Selan if (win->flags & __LEAVEOK) { 13456238Selan curscr->cury = ly; 13556238Selan curscr->curx = lx; 13656238Selan ly -= win->begy; 13756238Selan lx -= win->begx; 13856238Selan if (ly >= 0 && ly < win->maxy && lx >= 0 && 13956238Selan lx < win->maxx) { 14056238Selan win->cury = ly; 14156238Selan win->curx = lx; 14255976Sbostic } else 14356238Selan win->cury = win->curx = 0; 14455976Sbostic } else { 14556238Selan domvcur(ly, lx, win->cury + win->begy, 14656238Selan win->curx + win->begx); 14756238Selan curscr->cury = win->cury + win->begy; 14856238Selan curscr->curx = win->curx + win->begx; 14919893Sbloom } 1502261Sarnold } 15157472Sbostic retval = OK; 15255986Sbostic 1532261Sarnold _win = NULL; 15455976Sbostic (void)fflush(stdout); 15555976Sbostic return (retval); 1562261Sarnold } 1572261Sarnold 1582261Sarnold /* 15955976Sbostic * makech -- 16055976Sbostic * Make a change on the screen. 1612261Sarnold */ 16255976Sbostic static int 1632261Sarnold makech(win, wy) 16455976Sbostic register WINDOW *win; 16555976Sbostic int wy; 1662261Sarnold { 167*59775Selan register int nlsp, clsp; /* Last space in lines. */ 16859352Selan register int wx, lch, y; 169*59775Selan register __LDATA *nsp, *csp, *cp, *cep; 17056651Selan u_int force; 17156648Selan char *ce; 17256648Selan __LDATA blank = {' ', 0}; 17356648Selan 17456472Selan /* Is the cursor still on the end of the last line? */ 17556472Selan if (wy > 0 && win->lines[wy - 1]->flags & __ISPASTEOL) { 17656551Selan domvcur(ly, lx, ly + 1, 0); 17756551Selan ly++; 17856551Selan lx = 0; 17956551Selan } 18056715Selan wx = *win->lines[wy]->firstchp - win->ch_off; 18159352Selan if (wx < 0) 18259352Selan wx = 0; 18359352Selan else if (wx >= win->maxx) 18457472Sbostic return (OK); 18556715Selan lch = *win->lines[wy]->lastchp - win->ch_off; 18619893Sbloom if (lch < 0) 18757472Sbostic return (OK); 18859352Selan else if (lch >= (int) win->maxx) 18956238Selan lch = win->maxx - 1; 19056238Selan y = wy + win->begy; 19119893Sbloom 1922287Sarnold if (curwin) 19356648Selan csp = ␣ 1942287Sarnold else 19556238Selan csp = &curscr->lines[wy + win->begy]->line[wx + win->begx]; 19619893Sbloom 19756238Selan nsp = &win->lines[wy]->line[wx]; 19856651Selan force = win->lines[wy]->flags & __FORCEPAINT; 19956651Selan win->lines[wy]->flags &= ~__FORCEPAINT; 2002287Sarnold if (CE && !curwin) { 20156648Selan for (cp = &win->lines[wy]->line[win->maxx - 1]; 20256648Selan cp->ch == ' ' && cp->attr == 0; cp--) 20356648Selan if (cp <= win->lines[wy]->line) 2042261Sarnold break; 20556648Selan nlsp = cp - win->lines[wy]->line; 2062261Sarnold } 2072287Sarnold if (!curwin) 2082287Sarnold ce = CE; 2092287Sarnold else 2102287Sarnold ce = NULL; 21119893Sbloom 21256651Selan if (force) { 21356651Selan if (CM) 21456651Selan tputs(tgoto(CM, lx, ly), 0, __cputchar); 21556651Selan else { 21656651Selan tputs(HO, 0, __cputchar); 21756651Selan mvcur(0, 0, ly, lx); 21856651Selan } 21956651Selan } 2202261Sarnold while (wx <= lch) { 22157956Selan if (!force && memcmp(nsp, csp, sizeof(__LDATA)) == 0) { 22255986Sbostic if (wx <= lch) { 22357956Selan while (memcmp(nsp, csp, sizeof(__LDATA)) == 0 && 22456648Selan wx <= lch) { 22556596Selan nsp++; 22656648Selan if (!curwin) 22756648Selan csp++; 22856648Selan ++wx; 22956648Selan } 23055986Sbostic continue; 23155986Sbostic } 23255986Sbostic break; 23355986Sbostic } 23456238Selan domvcur(ly, lx, y, wx + win->begx); 23556378Selan 23655976Sbostic #ifdef DEBUG 23756651Selan __TRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d, force =%d\n", 23856651Selan wx, ly, lx, y, wx + win->begx, force); 23955976Sbostic #endif 24055986Sbostic ly = y; 24156238Selan lx = wx + win->begx; 24257956Selan while ((force || memcmp(nsp, csp, sizeof(__LDATA)) != 0) 24356651Selan && wx <= lch) { 24455986Sbostic 245*59775Selan if (ce != NULL && win->maxx + win->begx == 246*59775Selan curscr->maxx && wx >= nlsp && nsp->ch == ' ') { 247*59775Selan /* Check for clear to end-of-line. */ 248*59775Selan cep = &curscr->lines[wy]->line[win->maxx - 1]; 249*59775Selan while (cep->ch == ' ' && cep->attr == 0) 250*59775Selan if (cep-- <= csp) 251*59775Selan break; 252*59775Selan clsp = cep - curscr->lines[wy]->line - 253*59775Selan win->begx * __LDATASIZE; 254*59775Selan #ifdef DEBUG 255*59775Selan __TRACE("makech: clsp = %d, nlsp = %d\n", clsp, nlsp); 256*59775Selan #endif 257*59775Selan if ((clsp - nlsp >= strlen(CE) 258*59775Selan && clsp < win->maxx * __LDATASIZE) || 259*59775Selan wy == win->maxy - 1) { 260*59775Selan #ifdef DEBUG 261*59775Selan __TRACE("makech: using CE\n"); 262*59775Selan #endif 263*59775Selan tputs(CE, 0, __cputchar); 264*59775Selan lx = wx + win->begx; 265*59775Selan while (wx++ <= clsp) { 266*59775Selan csp->ch = ' '; 267*59775Selan csp->attr = 0; 268*59775Selan csp++; 269*59775Selan } 270*59775Selan return (OK); 271*59775Selan } 272*59775Selan ce = NULL; 273*59775Selan } 274*59775Selan 27555986Sbostic /* Enter/exit standout mode as appropriate. */ 27656648Selan if (SO && (nsp->attr & __STANDOUT) != 27756378Selan (curscr->flags & __WSTANDOUT)) { 27856648Selan if (nsp->attr & __STANDOUT) { 27955986Sbostic tputs(SO, 0, __cputchar); 28056238Selan curscr->flags |= __WSTANDOUT; 28155986Sbostic } else { 28255986Sbostic tputs(SE, 0, __cputchar); 28356238Selan curscr->flags &= ~__WSTANDOUT; 2842261Sarnold } 28555986Sbostic } 28655986Sbostic 28755986Sbostic wx++; 28856472Selan if (wx >= win->maxx && wy == win->maxy - 1 && !curwin) 28956238Selan if (win->flags & __SCROLLOK) { 29056238Selan if (curscr->flags & __WSTANDOUT 29156238Selan && win->flags & __ENDLINE) 29255986Sbostic if (!MS) { 29355986Sbostic tputs(SE, 0, 29455986Sbostic __cputchar); 29556238Selan curscr->flags &= 29656238Selan ~__WSTANDOUT; 29755976Sbostic } 29859760Selan if (!(win->flags & __SCROLLWIN)) { 29959760Selan if (!curwin) { 30059760Selan csp->attr = nsp->attr; 30159760Selan putchar(csp->ch = nsp->ch); 30259760Selan } else 30359760Selan putchar(nsp->ch); 30459760Selan } 30556599Selan if (wx + win->begx < curscr->maxx) { 30656599Selan domvcur(ly, wx + win->begx, 30756599Selan win->begy + win->maxy - 1, 30856599Selan win->begx + win->maxx - 1); 30956599Selan } 31056378Selan ly = win->begy + win->maxy - 1; 31156378Selan lx = win->begx + win->maxx - 1; 31257472Sbostic return (OK); 31359760Selan } 31459760Selan if (wx < win->maxx || wy < win->maxy - 1 || 31559760Selan !(win->flags & __SCROLLWIN)) { 31659760Selan if (!curwin) { 31759760Selan csp->attr = nsp->attr; 31859760Selan putchar(csp->ch = nsp->ch); 31959760Selan csp++; 32059760Selan } else 32159760Selan putchar(nsp->ch); 32259760Selan } 32355976Sbostic #ifdef DEBUG 32456648Selan __TRACE("makech: putchar(%c)\n", nsp->ch & 0177); 32555976Sbostic #endif 32656648Selan if (UC && (nsp->attr & __STANDOUT)) { 32755986Sbostic putchar('\b'); 32855986Sbostic tputs(UC, 0, __cputchar); 3292261Sarnold } 33055986Sbostic nsp++; 33155976Sbostic #ifdef DEBUG 33255986Sbostic __TRACE("makech: 2: wx = %d, lx = %d\n", wx, lx); 33355976Sbostic #endif 33459760Selan } 33556238Selan if (lx == wx + win->begx) /* If no change. */ 33655986Sbostic break; 33756238Selan lx = wx + win->begx; 33859774Selan if (lx >= COLS && AM) 33958040Selan lx = COLS - 1; 34059774Selan else if (wx >= win->maxx) { 34156596Selan domvcur(ly, lx, ly, win->maxx + win->begx - 1); 34256596Selan lx = win->maxx + win->begx - 1; 34355986Sbostic } 34456596Selan 34555976Sbostic #ifdef DEBUG 34655976Sbostic __TRACE("makech: 3: wx = %d, lx = %d\n", wx, lx); 34755976Sbostic #endif 3482261Sarnold } 34957472Sbostic return (OK); 35011736Sarnold } 35111736Sarnold 35211736Sarnold /* 35355976Sbostic * domvcur -- 35455976Sbostic * Do a mvcur, leaving standout mode if necessary. 35511736Sarnold */ 35655976Sbostic static void 35711736Sarnold domvcur(oy, ox, ny, nx) 35855976Sbostic int oy, ox, ny, nx; 35955976Sbostic { 36056238Selan if (curscr->flags & __WSTANDOUT && !MS) { 36155976Sbostic tputs(SE, 0, __cputchar); 36256238Selan curscr->flags &= ~__WSTANDOUT; 3632261Sarnold } 36456596Selan 36511736Sarnold mvcur(oy, ox, ny, nx); 3662261Sarnold } 36756302Selan 36856302Selan /* 36956302Selan * Quickch() attempts to detect a pattern in the change of the window 37056552Selan * in order to optimize the change, e.g., scroll n lines as opposed to 37156302Selan * repainting the screen line by line. 37256302Selan */ 37356302Selan 37456302Selan static void 37556302Selan quickch(win) 37656302Selan WINDOW *win; 37756302Selan { 37858019Selan #define THRESH (int) win->maxy / 4 37956302Selan 38056648Selan register __LINE *clp, *tmp1, *tmp2; 38156378Selan register int bsize, curs, curw, starts, startw, i, j; 38256652Selan int n, target, cur_period, bot, top, sc_region; 38356648Selan __LDATA buf[1024]; 38456378Selan u_int blank_hash; 38556302Selan 38658019Selan /* 38758019Selan * Find how many lines from the top of the screen are unchanged. 38858019Selan */ 38958034Selan for (top = 0; top < win->maxy; top++) 39058019Selan if (win->lines[top]->flags & __FORCEPAINT || 39158019Selan win->lines[top]->hash != curscr->lines[top]->hash 39258019Selan || memcmp(win->lines[top]->line, 39358019Selan curscr->lines[top]->line, 39458019Selan win->maxx * __LDATASIZE) != 0) 39558019Selan break; 39658034Selan else 39758034Selan win->lines[top]->flags &= ~__ISDIRTY; 39858019Selan /* 39958019Selan * Find how many lines from bottom of screen are unchanged. 40058019Selan */ 40158019Selan for (bot = win->maxy - 1; bot >= 0; bot--) 40258019Selan if (win->lines[bot]->flags & __FORCEPAINT || 40358019Selan win->lines[bot]->hash != curscr->lines[bot]->hash 40458019Selan || memcmp(win->lines[bot]->line, 40558019Selan curscr->lines[bot]->line, 40658019Selan win->maxx * __LDATASIZE) != 0) 40758019Selan break; 40858034Selan else 40958034Selan win->lines[bot]->flags &= ~__ISDIRTY; 41058019Selan 41159352Selan #ifdef NO_JERKINESS 41256552Selan /* 41359062Selan * If we have a bottom unchanged region return. Scrolling the 41459062Selan * bottom region up and then back down causes a screen jitter. 41559062Selan * This will increase the number of characters sent to the screen 41659062Selan * but it looks better. 41759062Selan */ 41859062Selan if (bot < win->maxy - 1) 41959062Selan return; 42059352Selan #endif /* NO_JERKINESS */ 42159062Selan 42259062Selan /* 42356552Selan * Search for the largest block of text not changed. 42456652Selan * Invariants of the loop: 42556652Selan * - Startw is the index of the beginning of the examined block in win. 42656652Selan * - Starts is the index of the beginning of the examined block in 42756652Selan * curscr. 42856652Selan * - Curs is the index of one past the end of the exmined block in win. 42956652Selan * - Curw is the index of one past the end of the exmined block in 43056652Selan * curscr. 43156652Selan * - bsize is the current size of the examined block. 43256552Selan */ 43358019Selan for (bsize = bot - top; bsize >= THRESH; bsize--) { 43458019Selan for (startw = top; startw <= bot - bsize; startw++) 43558019Selan for (starts = top; starts <= bot - bsize; 43656302Selan starts++) { 43756302Selan for (curw = startw, curs = starts; 43856302Selan curs < starts + bsize; curw++, curs++) 43956651Selan if (win->lines[curw]->flags & 44056651Selan __FORCEPAINT || 44156651Selan (win->lines[curw]->hash != 44256552Selan curscr->lines[curs]->hash || 44357956Selan memcmp(win->lines[curw]->line, 44456648Selan curscr->lines[curs]->line, 44556651Selan win->maxx * __LDATASIZE) != 0)) 44656302Selan break; 44756302Selan if (curs == starts + bsize) 44856302Selan goto done; 44956302Selan } 45058019Selan } 45156302Selan done: 45256651Selan /* Did not find anything */ 45356651Selan if (bsize < THRESH) 45456302Selan return; 45556302Selan 45656302Selan #ifdef DEBUG 45756559Selan __TRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n", 45856559Selan bsize, starts, startw, curw, curs, top, bot); 45956302Selan #endif 46056378Selan 46156559Selan /* 46256559Selan * Make sure that there is no overlap between the bottom and top 46356559Selan * regions and the middle scrolled block. 46456559Selan */ 46556691Selan if (bot < curs) 46656691Selan bot = curs - 1; 46756691Selan if (top > starts) 46856691Selan top = starts; 46956559Selan 47056378Selan n = startw - starts; 47156378Selan 47256691Selan #ifdef DEBUG 47356691Selan __TRACE("#####################################\n"); 47456691Selan for (i = 0; i < curscr->maxy; i++) { 47556691Selan __TRACE("C: %d:", i); 47657356Selan __TRACE(" 0x%x \n", curscr->lines[i]->hash); 47756691Selan for (j = 0; j < curscr->maxx; j++) 47856691Selan __TRACE("%c", 47956691Selan curscr->lines[i]->line[j].ch); 48056691Selan __TRACE("\n"); 48157356Selan for (j = 0; j < curscr->maxx; j++) 48257356Selan __TRACE("%x", 48357356Selan curscr->lines[i]->line[j].attr); 48457356Selan __TRACE("\n"); 48556691Selan __TRACE("W: %d:", i); 48657356Selan __TRACE(" 0x%x \n", win->lines[i]->hash); 48757356Selan __TRACE(" 0x%x ", win->lines[i]->flags); 48856691Selan for (j = 0; j < win->maxx; j++) 48956691Selan __TRACE("%c", 49056691Selan win->lines[i]->line[j].ch); 49156691Selan __TRACE("\n"); 49257356Selan for (j = 0; j < win->maxx; j++) 49357356Selan __TRACE("%x", 49457356Selan win->lines[i]->line[j].attr); 49557356Selan __TRACE("\n"); 49656691Selan } 49756691Selan #endif 49856651Selan if (n != 0) 49956705Selan scrolln(win, starts, startw, curs, bot, top); 50058019Selan 50156378Selan /* So we don't have to call __hash() each time */ 50256648Selan for (i = 0; i < win->maxx; i++) { 50356648Selan buf[i].ch = ' '; 50456648Selan buf[i].attr = 0; 50556648Selan } 50658192Selan blank_hash = __hash((char *) buf, win->maxx * __LDATASIZE); 50756378Selan 50856378Selan /* 50956378Selan * Perform the rotation to maintain the consistency of curscr. 51056691Selan * This is hairy since we are doing an *in place* rotation. 51156652Selan * Invariants of the loop: 51256652Selan * - I is the index of the current line. 51356652Selan * - Target is the index of the target of line i. 51456652Selan * - Tmp1 points to current line (i). 51556652Selan * - Tmp2 and points to target line (target); 51656652Selan * - Cur_period is the index of the end of the current period. 51756652Selan * (see below). 51856652Selan * 51956652Selan * There are 2 major issues here that make this rotation non-trivial: 52056652Selan * 1. Scrolling in a scrolling region bounded by the top 52156652Selan * and bottom regions determined (whose size is sc_region). 52256652Selan * 2. As a result of the use of the mod function, there may be a 52356652Selan * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and 52456652Selan * 0 to 2, which then causes all odd lines not to be rotated. 52556652Selan * To remedy this, an index of the end ( = beginning) of the 52656652Selan * current 'period' is kept, cur_period, and when it is reached, 52756652Selan * the next period is started from cur_period + 1 which is 52856652Selan * guaranteed not to have been reached since that would mean that 52956652Selan * all records would have been reached. (think about it...). 53056652Selan * 53156652Selan * Lines in the rotation can have 3 attributes which are marked on the 53256652Selan * line so that curscr is consistent with the visual screen. 53356705Selan * 1. Not dirty -- lines inside the scrolled block, top region or 53456652Selan * bottom region. 53556705Selan * 2. Blank lines -- lines in the differential of the scrolling 53656705Selan * region adjacent to top and bot regions 53756705Selan * depending on scrolling direction. 53856652Selan * 3. Dirty line -- all other lines are marked dirty. 53956378Selan */ 54056648Selan sc_region = bot - top + 1; 54156648Selan i = top; 54256648Selan tmp1 = curscr->lines[top]; 54356652Selan cur_period = top; 54456648Selan for (j = top; j <= bot; j++) { 54556648Selan target = (i - top + n + sc_region) % sc_region + top; 54656378Selan tmp2 = curscr->lines[target]; 54756378Selan curscr->lines[target] = tmp1; 54856378Selan /* Mark block as clean and blank out scrolled lines. */ 54956378Selan clp = curscr->lines[target]; 55056472Selan #ifdef DEBUG 55156378Selan __TRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ", 55256378Selan n, startw, curw, i, target); 55356472Selan #endif 55456691Selan if ((target >= startw && target < curw) || target < top 55556691Selan || target > bot) { 55656472Selan #ifdef DEBUG 55756378Selan __TRACE("-- notdirty"); 55856472Selan #endif 55956378Selan win->lines[target]->flags &= ~__ISDIRTY; 56056705Selan } else if ((n > 0 && target >= top && target < top + n) || 56156705Selan (n < 0 && target <= bot && target > bot + n)) { 56257956Selan if (clp->hash != blank_hash || memcmp(clp->line, 56356648Selan buf, win->maxx * __LDATASIZE) !=0) { 56458041Selan (void)memcpy(clp->line, buf, 56556648Selan win->maxx * __LDATASIZE); 56656472Selan #ifdef DEBUG 56756648Selan __TRACE("-- blanked out: dirty"); 56856472Selan #endif 56956378Selan clp->hash = blank_hash; 57056652Selan __touchline(win, target, 0, win->maxx - 1, 0); 57156705Selan } else { 57256652Selan __touchline(win, target, 0, win->maxx - 1, 0); 57356472Selan #ifdef DEBUG 57456648Selan __TRACE(" -- blank line already: dirty"); 57556472Selan #endif 57656705Selan } 57756378Selan } else { 57856472Selan #ifdef DEBUG 57956648Selan __TRACE(" -- dirty"); 58056472Selan #endif 58156651Selan __touchline(win, target, 0, win->maxx - 1, 0); 58256378Selan } 58356472Selan #ifdef DEBUG 58456378Selan __TRACE("\n"); 58556472Selan #endif 58656652Selan if (target == cur_period) { 58756378Selan i = target + 1; 58856378Selan tmp1 = curscr->lines[i]; 58956652Selan cur_period = i; 59056378Selan } else { 59156378Selan tmp1 = tmp2; 59256378Selan i = target; 59356378Selan } 59456302Selan } 59556472Selan #ifdef DEBUG 59656648Selan __TRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); 59756648Selan for (i = 0; i < curscr->maxy; i++) { 59856691Selan __TRACE("C: %d:", i); 59956648Selan for (j = 0; j < curscr->maxx; j++) 60056648Selan __TRACE("%c", 60156648Selan curscr->lines[i]->line[j].ch); 60256648Selan __TRACE("\n"); 60356691Selan __TRACE("W: %d:", i); 60456691Selan for (j = 0; j < win->maxx; j++) 60556691Selan __TRACE("%c", 60656691Selan win->lines[i]->line[j].ch); 60756691Selan __TRACE("\n"); 60856648Selan } 60956472Selan #endif 61056302Selan } 61156302Selan 61256652Selan /* 61356652Selan * Scrolln performs the scroll by n lines, where n is starts - startw. 61456652Selan */ 61556302Selan static void 61656705Selan scrolln(win, starts, startw, curs, bot, top) 61756302Selan WINDOW *win; 61856705Selan int starts, startw, curs, bot, top; 61956302Selan { 62056302Selan int i, oy, ox, n; 62156302Selan 62256302Selan oy = curscr->cury; 62356302Selan ox = curscr->curx; 62456302Selan n = starts - startw; 62556302Selan 62656302Selan if (n > 0) { 62756559Selan mvcur(oy, ox, top, 0); 62856559Selan /* Scroll up the block */ 62956302Selan if (DL) 63057475Sbostic tputs(__tscroll(DL, n), 0, __cputchar); 63156302Selan else 63256302Selan for(i = 0; i < n; i++) 63356302Selan tputs(dl, 0, __cputchar); 63456652Selan 63556651Selan /* 63656652Selan * Push down the bottom region. 63756651Selan */ 63856705Selan mvcur(top, 0, bot - n + 1, 0); 63958019Selan if (AL) 64057475Sbostic tputs(__tscroll(AL, n), 0, __cputchar); 64156652Selan else 64256652Selan for(i = 0; i < n; i++) 64356652Selan tputs(al, 0, __cputchar); 64456705Selan mvcur(bot - n + 1, 0, oy, ox); 64556302Selan } else { 64656651Selan /* Preserve the bottom lines */ 64756705Selan mvcur(oy, ox, bot + n + 1, 0); /* n < 0 */ 64856652Selan if (DL) 64957475Sbostic tputs(__tscroll(DL, -n), 0, __cputchar); 65056652Selan else 65156652Selan for(i = n; i < 0; i++) 65256652Selan tputs(dl, 0, __cputchar); 65356705Selan mvcur(bot + n + 1, 0, top, 0); 65456302Selan 65556302Selan /* Scroll the block down */ 65658019Selan if (AL) 65757475Sbostic tputs(__tscroll(AL, -n), 0, __cputchar); 65856302Selan else 65956302Selan for(i = n; i < 0; i++) 66056302Selan tputs(al, 0, __cputchar); 66156705Selan mvcur(top, 0, oy, ox); 66256378Selan } 66356302Selan } 66456378Selan 66556378Selan 666