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*56715Selan static char sccsid[] = "@(#)refresh.c 5.23 (Berkeley) 11/11/92"; 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; 372261Sarnold 3855976Sbostic /* Make sure were in visual state. */ 3955976Sbostic if (__endwin) { 4055976Sbostic tputs(VS, 0, __cputchar); 4155976Sbostic tputs(TI, 0, __cputchar); 4255976Sbostic __endwin = 0; 432261Sarnold } 442287Sarnold 4555976Sbostic /* Initialize loop parameters. */ 462287Sarnold 4756238Selan ly = curscr->cury; 4856238Selan lx = curscr->curx; 492287Sarnold wy = 0; 502287Sarnold _win = win; 512287Sarnold curwin = (win == curscr); 522287Sarnold 5356378Selan if (!curwin) 5456378Selan for (wy = 0; wy < win->maxy; wy++) { 5556378Selan wlp = win->lines[wy]; 5656378Selan if (wlp->flags & __ISDIRTY) 5756648Selan wlp->hash = 5856648Selan __hash(wlp->line, win->maxx * __LDATASIZE); 5956378Selan } 6056378Selan 6156238Selan if (win->flags & __CLEAROK || curscr->flags & __CLEAROK || curwin) { 6256238Selan if ((win->flags & __FULLWIN) || curscr->flags & __CLEAROK) { 6355976Sbostic tputs(CL, 0, __cputchar); 6412358Sarnold ly = 0; 6512358Sarnold lx = 0; 6612358Sarnold if (!curwin) { 6756238Selan curscr->flags &= ~__CLEAROK; 6856238Selan curscr->cury = 0; 6956238Selan curscr->curx = 0; 702287Sarnold werase(curscr); 7112358Sarnold } 7256651Selan __touchwin(win); 732261Sarnold } 7456238Selan win->flags &= ~__CLEAROK; 752261Sarnold } 762261Sarnold if (!CA) { 7756238Selan if (win->curx != 0) 7855976Sbostic putchar('\n'); 792287Sarnold if (!curwin) 802287Sarnold werase(curscr); 812261Sarnold } 8255976Sbostic #ifdef DEBUG 8355976Sbostic __TRACE("wrefresh: (%0.2o): curwin = %d\n", win, curwin); 8455976Sbostic __TRACE("wrefresh: \tfirstch\tlastch\n"); 8555976Sbostic #endif 8656302Selan 8756302Selan #ifndef NOQCH 8856378Selan if (!__noqch && (win->flags & __FULLWIN) && !curwin) 8956302Selan quickch(win); 9056302Selan #endif 9156238Selan for (wy = 0; wy < win->maxy; wy++) { 9255976Sbostic #ifdef DEBUG 9355976Sbostic __TRACE("%d\t%d\t%d\n", 94*56715Selan wy, *win->lines[wy]->firstchp, *win->lines[wy]->lastchp); 9555976Sbostic #endif 9656378Selan if (!curwin) 9756378Selan curscr->lines[wy]->hash = win->lines[wy]->hash; 9856651Selan if (win->lines[wy]->flags & __ISDIRTY || 9956651Selan win->lines[wy]->flags & __FORCEPAINT) 1002261Sarnold if (makech(win, wy) == ERR) 10155976Sbostic return (ERR); 10219893Sbloom else { 103*56715Selan if (*win->lines[wy]->firstchp >= win->ch_off) 104*56715Selan *win->lines[wy]->firstchp = win->maxx + 10556238Selan win->ch_off; 106*56715Selan if (*win->lines[wy]->lastchp < win->maxx + 10756238Selan win->ch_off) 108*56715Selan *win->lines[wy]->lastchp = win->ch_off; 109*56715Selan if (*win->lines[wy]->lastchp < 110*56715Selan *win->lines[wy]->firstchp) 11156238Selan win->lines[wy]->flags &= ~__ISDIRTY; 11219893Sbloom } 11355976Sbostic #ifdef DEBUG 114*56715Selan __TRACE("\t%d\t%d\n", *win->lines[wy]->firstchp, 115*56715Selan *win->lines[wy]->lastchp); 11655976Sbostic #endif 1172261Sarnold } 11856238Selan 11956302Selan #ifdef DEBUG 12056238Selan __TRACE("refresh: ly=%d, lx=%d\n", ly, lx); 12156302Selan #endif 12256472Selan 12312358Sarnold if (win == curscr) 12456238Selan domvcur(ly, lx, win->cury, win->curx); 12519893Sbloom else { 12656238Selan if (win->flags & __LEAVEOK) { 12756238Selan curscr->cury = ly; 12856238Selan curscr->curx = lx; 12956238Selan ly -= win->begy; 13056238Selan lx -= win->begx; 13156238Selan if (ly >= 0 && ly < win->maxy && lx >= 0 && 13256238Selan lx < win->maxx) { 13356238Selan win->cury = ly; 13456238Selan win->curx = lx; 13555976Sbostic } else 13656238Selan win->cury = win->curx = 0; 13755976Sbostic } else { 13856238Selan domvcur(ly, lx, win->cury + win->begy, 13956238Selan win->curx + win->begx); 14056238Selan curscr->cury = win->cury + win->begy; 14156238Selan curscr->curx = win->curx + win->begx; 14219893Sbloom } 1432261Sarnold } 1442287Sarnold retval = OK; 14555986Sbostic 1462261Sarnold _win = NULL; 14755976Sbostic (void)fflush(stdout); 14855976Sbostic return (retval); 1492261Sarnold } 1502261Sarnold 1512261Sarnold /* 15255976Sbostic * makech -- 15355976Sbostic * Make a change on the screen. 1542261Sarnold */ 15555976Sbostic static int 1562261Sarnold makech(win, wy) 15755976Sbostic register WINDOW *win; 15855976Sbostic int wy; 1592261Sarnold { 16055976Sbostic register int nlsp, clsp; /* Last space in lines. */ 16155976Sbostic register short wx, lch, y; 16256648Selan register __LDATA *nsp, *csp, *cp; 16356651Selan u_int force; 16456648Selan char *ce; 16556648Selan __LDATA blank = {' ', 0}; 16656648Selan 16756472Selan /* Is the cursor still on the end of the last line? */ 16856472Selan if (wy > 0 && win->lines[wy - 1]->flags & __ISPASTEOL) { 16956551Selan win->lines[wy - 1]->flags &= ~__ISPASTEOL; 17056551Selan domvcur(ly, lx, ly + 1, 0); 17156551Selan ly++; 17256551Selan lx = 0; 17356551Selan } 17456238Selan if (!(win->lines[wy]->flags & __ISDIRTY)) 17555976Sbostic return (OK); 176*56715Selan wx = *win->lines[wy]->firstchp - win->ch_off; 17756238Selan if (wx >= win->maxx) 17856238Selan return (OK); 17919893Sbloom else if (wx < 0) 18019893Sbloom wx = 0; 181*56715Selan lch = *win->lines[wy]->lastchp - win->ch_off; 18219893Sbloom if (lch < 0) 18355976Sbostic return (OK); 18456238Selan else if (lch >= win->maxx) 18556238Selan lch = win->maxx - 1; 18656238Selan y = wy + win->begy; 18719893Sbloom 1882287Sarnold if (curwin) 18956648Selan csp = ␣ 1902287Sarnold else 19156238Selan csp = &curscr->lines[wy + win->begy]->line[wx + win->begx]; 19219893Sbloom 19356238Selan nsp = &win->lines[wy]->line[wx]; 19456651Selan force = win->lines[wy]->flags & __FORCEPAINT; 19556651Selan win->lines[wy]->flags &= ~__FORCEPAINT; 1962287Sarnold if (CE && !curwin) { 19756648Selan for (cp = &win->lines[wy]->line[win->maxx - 1]; 19856648Selan cp->ch == ' ' && cp->attr == 0; cp--) 19956648Selan if (cp <= win->lines[wy]->line) 2002261Sarnold break; 20156648Selan nlsp = cp - win->lines[wy]->line; 2022261Sarnold } 2032287Sarnold if (!curwin) 2042287Sarnold ce = CE; 2052287Sarnold else 2062287Sarnold ce = NULL; 20719893Sbloom 20856651Selan if (force) { 20956651Selan if (CM) 21056651Selan tputs(tgoto(CM, lx, ly), 0, __cputchar); 21156651Selan else { 21256651Selan tputs(HO, 0, __cputchar); 21356651Selan mvcur(0, 0, ly, lx); 21456651Selan } 21556651Selan } 2162261Sarnold while (wx <= lch) { 21756651Selan if (!force && bcmp(nsp, csp, sizeof(__LDATA)) == 0) { 21855986Sbostic if (wx <= lch) { 21956648Selan while (bcmp(nsp, csp, sizeof(__LDATA)) == 0 && 22056648Selan wx <= lch) { 22156596Selan nsp++; 22256648Selan if (!curwin) 22356648Selan csp++; 22456648Selan ++wx; 22556648Selan } 22655986Sbostic continue; 22755986Sbostic } 22855986Sbostic break; 22955986Sbostic } 23056238Selan domvcur(ly, lx, y, wx + win->begx); 23156378Selan 23255976Sbostic #ifdef DEBUG 23356651Selan __TRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d, force =%d\n", 23456651Selan wx, ly, lx, y, wx + win->begx, force); 23555976Sbostic #endif 23655986Sbostic ly = y; 23756238Selan lx = wx + win->begx; 23856651Selan while ((force || bcmp(nsp, csp, sizeof(__LDATA)) != 0) 23956651Selan && wx <= lch) { 24056378Selan #ifdef notdef 24156378Selan /* XXX 24256378Selan * The problem with this code is that we can't count on 24356378Selan * terminals wrapping around after the 24456378Selan * last character on the previous line has been output 24556378Selan * In effect, what then could happen is that the CE 24656378Selan * clear the previous line and do nothing to the 24756378Selan * next line. 24856378Selan */ 24956648Selan if (ce != NULL && wx >= nlsp && 25056648Selan nsp->ch == ' ') { 25155986Sbostic /* Check for clear to end-of-line. */ 25256596Selan ce = &curscr->lines[wy]->line[COLS - 1]; 25356648Selan while (ce->ch == ' ' && ce->attr = 0) 25455986Sbostic if (ce-- <= csp) 25555986Sbostic break; 25656596Selan clsp = ce - curscr->lines[wy]->line - 25756648Selan win->begx * __LDATASIZE; 25855976Sbostic #ifdef DEBUG 25955986Sbostic __TRACE("makech: clsp = %d, nlsp = %d\n", clsp, nlsp); 26055976Sbostic #endif 26156648Selan if (clsp - nlsp >= strlen(CE) 26256648Selan && clsp < win->maxx * __LDATASIZE) { 26355976Sbostic #ifdef DEBUG 26455986Sbostic __TRACE("makech: using CE\n"); 26555976Sbostic #endif 26655986Sbostic tputs(CE, 0, __cputchar); 26756238Selan lx = wx + win->begx; 26856596Selan while (wx++ <= clsp) { 26956648Selan csp->ch = ' '; 27056648Selan csp->attr = 0; 27156648Selan csp++; 27256596Selan } 27355986Sbostic return (OK); 2742261Sarnold } 27555986Sbostic ce = NULL; 27655986Sbostic } 27756378Selan #endif 27855986Sbostic 27955986Sbostic /* Enter/exit standout mode as appropriate. */ 28056648Selan if (SO && (nsp->attr & __STANDOUT) != 28156378Selan (curscr->flags & __WSTANDOUT)) { 28256648Selan if (nsp->attr & __STANDOUT) { 28355986Sbostic tputs(SO, 0, __cputchar); 28456238Selan curscr->flags |= __WSTANDOUT; 28555986Sbostic } else { 28655986Sbostic tputs(SE, 0, __cputchar); 28756238Selan curscr->flags &= ~__WSTANDOUT; 2882261Sarnold } 28955986Sbostic } 29055986Sbostic 29155986Sbostic wx++; 29256472Selan if (wx >= win->maxx && wy == win->maxy - 1 && !curwin) 29356238Selan if (win->flags & __SCROLLOK) { 29456238Selan if (curscr->flags & __WSTANDOUT 29556238Selan && win->flags & __ENDLINE) 29655986Sbostic if (!MS) { 29755986Sbostic tputs(SE, 0, 29855986Sbostic __cputchar); 29956238Selan curscr->flags &= 30056238Selan ~__WSTANDOUT; 30155976Sbostic } 30256596Selan if (!curwin) { 30356648Selan csp->attr = nsp->attr; 30456648Selan putchar(csp->ch = nsp->ch); 30556596Selan } else 30656648Selan putchar(nsp->ch); 30756648Selan #ifdef notdef /* XXX why is this here? */ 30856472Selan if (win->flags & __FULLWIN && !curwin) 30955986Sbostic scroll(curscr); 31056378Selan #endif 31156599Selan if (wx + win->begx < curscr->maxx) { 31256599Selan domvcur(ly, wx + win->begx, 31356599Selan win->begy + win->maxy - 1, 31456599Selan win->begx + win->maxx - 1); 31556599Selan } 31656378Selan ly = win->begy + win->maxy - 1; 31756378Selan lx = win->begx + win->maxx - 1; 31855986Sbostic return (OK); 31955986Sbostic } else 32056238Selan if (win->flags & __SCROLLWIN) { 32155986Sbostic lx = --wx; 32255986Sbostic return (ERR); 32355986Sbostic } 32456596Selan if (!curwin) { 32556648Selan csp->attr = nsp->attr; 32656648Selan putchar(csp->ch = nsp->ch); 32756648Selan csp++; 32856648Selan } else 32956648Selan putchar(nsp->ch); 33056472Selan 33155976Sbostic #ifdef DEBUG 33256648Selan __TRACE("makech: putchar(%c)\n", nsp->ch & 0177); 33355976Sbostic #endif 33456648Selan if (UC && (nsp->attr & __STANDOUT)) { 33555986Sbostic putchar('\b'); 33655986Sbostic tputs(UC, 0, __cputchar); 3372261Sarnold } 33855986Sbostic nsp++; 33955986Sbostic } 34055976Sbostic #ifdef DEBUG 34155986Sbostic __TRACE("makech: 2: wx = %d, lx = %d\n", wx, lx); 34255976Sbostic #endif 34356238Selan if (lx == wx + win->begx) /* If no change. */ 34455986Sbostic break; 34556238Selan lx = wx + win->begx; 34655986Sbostic if (lx >= COLS && AM) { 34755986Sbostic /* 34855986Sbostic * xn glitch: chomps a newline after auto-wrap. 34955986Sbostic * we just feed it now and forget about it. 35055986Sbostic */ 35155986Sbostic if (XN) { 35256472Selan lx = 0; 35356472Selan ly++; 35455986Sbostic putchar('\n'); 35555986Sbostic putchar('\r'); 35656472Selan } else { 35756472Selan if (wy != LINES) 35856472Selan win->lines[wy]->flags |= __ISPASTEOL; 35956472Selan lx = COLS - 1; 36022789Smckusick } 36156596Selan } else if (wx >= win->maxx) { 36256596Selan if (wy != win->maxy) 36356596Selan win->lines[wy]->flags |= __ISPASTEOL; 36456596Selan domvcur(ly, lx, ly, win->maxx + win->begx - 1); 36556596Selan lx = win->maxx + win->begx - 1; 36655986Sbostic } 36756596Selan 36855976Sbostic #ifdef DEBUG 36955976Sbostic __TRACE("makech: 3: wx = %d, lx = %d\n", wx, lx); 37055976Sbostic #endif 3712261Sarnold } 37255976Sbostic return (OK); 37311736Sarnold } 37411736Sarnold 37511736Sarnold /* 37655976Sbostic * domvcur -- 37755976Sbostic * Do a mvcur, leaving standout mode if necessary. 37811736Sarnold */ 37955976Sbostic static void 38011736Sarnold domvcur(oy, ox, ny, nx) 38155976Sbostic int oy, ox, ny, nx; 38255976Sbostic { 38356238Selan if (curscr->flags & __WSTANDOUT && !MS) { 38455976Sbostic tputs(SE, 0, __cputchar); 38556238Selan curscr->flags &= ~__WSTANDOUT; 3862261Sarnold } 38756596Selan 38811736Sarnold mvcur(oy, ox, ny, nx); 3892261Sarnold } 39056302Selan 39156302Selan /* 39256302Selan * Quickch() attempts to detect a pattern in the change of the window 39356552Selan * in order to optimize the change, e.g., scroll n lines as opposed to 39456302Selan * repainting the screen line by line. 39556302Selan */ 39656302Selan 397*56715Selan 39856302Selan static void 39956302Selan quickch(win) 40056302Selan WINDOW *win; 40156302Selan { 40256378Selan #define THRESH win->maxy / 4 40356302Selan 40456648Selan register __LINE *clp, *tmp1, *tmp2; 40556378Selan register int bsize, curs, curw, starts, startw, i, j; 40656652Selan int n, target, cur_period, bot, top, sc_region; 40756648Selan __LDATA buf[1024]; 40856378Selan u_int blank_hash; 40956302Selan 41056552Selan /* 41156552Selan * Search for the largest block of text not changed. 41256652Selan * Invariants of the loop: 41356652Selan * - Startw is the index of the beginning of the examined block in win. 41456652Selan * - Starts is the index of the beginning of the examined block in 41556652Selan * curscr. 41656652Selan * - Curs is the index of one past the end of the exmined block in win. 41756652Selan * - Curw is the index of one past the end of the exmined block in 41856652Selan * curscr. 41956652Selan * - bsize is the current size of the examined block. 42056552Selan */ 42156302Selan for (bsize = win->maxy; bsize >= THRESH; bsize--) 42256302Selan for (startw = 0; startw <= win->maxy - bsize; startw++) 42356302Selan for (starts = 0; starts <= win->maxy - bsize; 42456302Selan starts++) { 42556302Selan for (curw = startw, curs = starts; 42656302Selan curs < starts + bsize; curw++, curs++) 42756651Selan if (win->lines[curw]->flags & 42856651Selan __FORCEPAINT || 42956651Selan (win->lines[curw]->hash != 43056552Selan curscr->lines[curs]->hash || 43156648Selan bcmp(win->lines[curw]->line, 43256648Selan curscr->lines[curs]->line, 43356651Selan win->maxx * __LDATASIZE) != 0)) 43456302Selan break; 43556302Selan if (curs == starts + bsize) 43656302Selan goto done; 43756302Selan } 43856302Selan done: 43956651Selan /* Did not find anything */ 44056651Selan if (bsize < THRESH) 44156302Selan return; 44256302Selan 44356559Selan /* 44456559Selan * Find how many lines from the top of the screen are unchanged. 44556559Selan */ 44656559Selan if (starts != 0) { 44756559Selan for (top = 0; top < win->maxy; top++) 44856651Selan if (win->lines[top]->flags & __FORCEPAINT || 44956651Selan win->lines[top]->hash != curscr->lines[top]->hash 45056648Selan || bcmp(win->lines[top]->line, 45156648Selan curscr->lines[top]->line, 45256648Selan win->maxx * __LDATASIZE) != 0) 45356559Selan break; 45456559Selan } else 45556559Selan top = 0; 45656559Selan 45756559Selan /* 45856559Selan * Find how many lines from bottom of screen are unchanged. 45956559Selan */ 46056559Selan if (curs != win->maxy) { 46156559Selan for (bot = win->maxy - 1; bot >= 0; bot--) 46256651Selan if (win->lines[bot]->flags & __FORCEPAINT || 46356651Selan win->lines[bot]->hash != curscr->lines[bot]->hash 46456648Selan || bcmp(win->lines[bot]->line, 46556648Selan curscr->lines[bot]->line, 46656648Selan win->maxx * __LDATASIZE) != 0) 46756559Selan break; 46856559Selan } else 46956559Selan bot = win->maxy - 1; 47056559Selan 47156302Selan #ifdef DEBUG 47256559Selan __TRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n", 47356559Selan bsize, starts, startw, curw, curs, top, bot); 47456302Selan #endif 47556378Selan 47656559Selan /* 47756559Selan * Make sure that there is no overlap between the bottom and top 47856559Selan * regions and the middle scrolled block. 47956559Selan */ 48056691Selan if (bot < curs) 48156691Selan bot = curs - 1; 48256691Selan if (top > starts) 48356691Selan top = starts; 48456559Selan 48556378Selan n = startw - starts; 48656378Selan 48756691Selan #ifdef DEBUG 48856691Selan __TRACE("#####################################\n"); 48956691Selan for (i = 0; i < curscr->maxy; i++) { 49056691Selan __TRACE("C: %d:", i); 49156691Selan for (j = 0; j < curscr->maxx; j++) 49256691Selan __TRACE("%c", 49356691Selan curscr->lines[i]->line[j].ch); 49456691Selan __TRACE("\n"); 49556691Selan __TRACE("W: %d:", i); 49656691Selan for (j = 0; j < win->maxx; j++) 49756691Selan __TRACE("%c", 49856691Selan win->lines[i]->line[j].ch); 49956691Selan __TRACE("\n"); 50056691Selan } 50156691Selan #endif 50256651Selan if (n != 0) 50356705Selan scrolln(win, starts, startw, curs, bot, top); 50456651Selan 50556651Selan 50656378Selan /* So we don't have to call __hash() each time */ 50756648Selan for (i = 0; i < win->maxx; i++) { 50856648Selan buf[i].ch = ' '; 50956648Selan buf[i].attr = 0; 51056648Selan } 51156648Selan blank_hash = __hash(buf, win->maxx * __LDATASIZE); 51256378Selan 51356378Selan /* 51456378Selan * Perform the rotation to maintain the consistency of curscr. 51556691Selan * This is hairy since we are doing an *in place* rotation. 51656652Selan * Invariants of the loop: 51756652Selan * - I is the index of the current line. 51856652Selan * - Target is the index of the target of line i. 51956652Selan * - Tmp1 points to current line (i). 52056652Selan * - Tmp2 and points to target line (target); 52156652Selan * - Cur_period is the index of the end of the current period. 52256652Selan * (see below). 52356652Selan * 52456652Selan * There are 2 major issues here that make this rotation non-trivial: 52556652Selan * 1. Scrolling in a scrolling region bounded by the top 52656652Selan * and bottom regions determined (whose size is sc_region). 52756652Selan * 2. As a result of the use of the mod function, there may be a 52856652Selan * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and 52956652Selan * 0 to 2, which then causes all odd lines not to be rotated. 53056652Selan * To remedy this, an index of the end ( = beginning) of the 53156652Selan * current 'period' is kept, cur_period, and when it is reached, 53256652Selan * the next period is started from cur_period + 1 which is 53356652Selan * guaranteed not to have been reached since that would mean that 53456652Selan * all records would have been reached. (think about it...). 53556652Selan * 53656652Selan * Lines in the rotation can have 3 attributes which are marked on the 53756652Selan * line so that curscr is consistent with the visual screen. 53856705Selan * 1. Not dirty -- lines inside the scrolled block, top region or 53956652Selan * bottom region. 54056705Selan * 2. Blank lines -- lines in the differential of the scrolling 54156705Selan * region adjacent to top and bot regions 54256705Selan * depending on scrolling direction. 54356652Selan * 3. Dirty line -- all other lines are marked dirty. 54456378Selan */ 54556648Selan sc_region = bot - top + 1; 54656648Selan i = top; 54756648Selan tmp1 = curscr->lines[top]; 54856652Selan cur_period = top; 54956648Selan for (j = top; j <= bot; j++) { 55056648Selan target = (i - top + n + sc_region) % sc_region + top; 55156378Selan tmp2 = curscr->lines[target]; 55256378Selan curscr->lines[target] = tmp1; 55356378Selan /* Mark block as clean and blank out scrolled lines. */ 55456378Selan clp = curscr->lines[target]; 55556472Selan #ifdef DEBUG 55656378Selan __TRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ", 55756378Selan n, startw, curw, i, target); 55856472Selan #endif 55956691Selan if ((target >= startw && target < curw) || target < top 56056691Selan || target > bot) { 56156472Selan #ifdef DEBUG 56256378Selan __TRACE("-- notdirty"); 56356472Selan #endif 56456378Selan win->lines[target]->flags &= ~__ISDIRTY; 56556705Selan } else if ((n > 0 && target >= top && target < top + n) || 56656705Selan (n < 0 && target <= bot && target > bot + n)) { 56756648Selan if (clp->hash != blank_hash || bcmp(clp->line, 56856648Selan buf, win->maxx * __LDATASIZE) !=0) { 56956648Selan (void)bcopy(buf, clp->line, 57056648Selan win->maxx * __LDATASIZE); 57156472Selan #ifdef DEBUG 57256648Selan __TRACE("-- blanked out: dirty"); 57356472Selan #endif 57456378Selan clp->hash = blank_hash; 57556652Selan __touchline(win, target, 0, win->maxx - 1, 0); 57656705Selan } else { 57756652Selan __touchline(win, target, 0, win->maxx - 1, 0); 57856472Selan #ifdef DEBUG 57956648Selan __TRACE(" -- blank line already: dirty"); 58056472Selan #endif 58156705Selan } 58256378Selan } else { 58356472Selan #ifdef DEBUG 58456648Selan __TRACE(" -- dirty"); 58556472Selan #endif 58656651Selan __touchline(win, target, 0, win->maxx - 1, 0); 58756378Selan } 58856472Selan #ifdef DEBUG 58956378Selan __TRACE("\n"); 59056472Selan #endif 59156652Selan if (target == cur_period) { 59256378Selan i = target + 1; 59356378Selan tmp1 = curscr->lines[i]; 59456652Selan cur_period = i; 59556378Selan } else { 59656378Selan tmp1 = tmp2; 59756378Selan i = target; 59856378Selan } 59956302Selan } 60056472Selan #ifdef DEBUG 60156648Selan __TRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); 60256648Selan for (i = 0; i < curscr->maxy; i++) { 60356691Selan __TRACE("C: %d:", i); 60456648Selan for (j = 0; j < curscr->maxx; j++) 60556648Selan __TRACE("%c", 60656648Selan curscr->lines[i]->line[j].ch); 60756648Selan __TRACE("\n"); 60856691Selan __TRACE("W: %d:", i); 60956691Selan for (j = 0; j < win->maxx; j++) 61056691Selan __TRACE("%c", 61156691Selan win->lines[i]->line[j].ch); 61256691Selan __TRACE("\n"); 61356648Selan } 61456472Selan #endif 61556302Selan } 61656302Selan 61756652Selan /* 61856652Selan * Scrolln performs the scroll by n lines, where n is starts - startw. 61956652Selan */ 62056302Selan static void 62156705Selan scrolln(win, starts, startw, curs, bot, top) 62256302Selan WINDOW *win; 62356705Selan int starts, startw, curs, bot, top; 62456302Selan { 62556302Selan int i, oy, ox, n; 62656302Selan 62756302Selan oy = curscr->cury; 62856302Selan ox = curscr->curx; 62956302Selan n = starts - startw; 63056302Selan 63156302Selan if (n > 0) { 63256559Selan mvcur(oy, ox, top, 0); 63356559Selan /* Scroll up the block */ 63456302Selan if (DL) 63556302Selan tputs(tscroll(DL, n), 0, __cputchar); 63656302Selan else 63756302Selan for(i = 0; i < n; i++) 63856302Selan tputs(dl, 0, __cputchar); 63956652Selan 64056651Selan /* 64156652Selan * Push down the bottom region. 64256651Selan */ 64356705Selan mvcur(top, 0, bot - n + 1, 0); 64456652Selan if (AL) 64556652Selan tputs(tscroll(AL, n), 0, __cputchar); 64656652Selan else 64756652Selan for(i = 0; i < n; i++) 64856652Selan tputs(al, 0, __cputchar); 64956705Selan mvcur(bot - n + 1, 0, oy, ox); 65056302Selan } else { 65156651Selan /* Preserve the bottom lines */ 65256705Selan mvcur(oy, ox, bot + n + 1, 0); /* n < 0 */ 65356652Selan if (DL) 65456652Selan tputs(tscroll(DL, -n), 0, __cputchar); 65556652Selan else 65656652Selan for(i = n; i < 0; i++) 65756652Selan tputs(dl, 0, __cputchar); 65856705Selan mvcur(bot + n + 1, 0, top, 0); 65956302Selan 66056302Selan /* Scroll the block down */ 66156302Selan if (AL) 66256302Selan tputs(tscroll(AL, -n), 0, __cputchar); 66356302Selan else 66456302Selan for(i = n; i < 0; i++) 66556302Selan tputs(al, 0, __cputchar); 66656705Selan mvcur(top, 0, oy, ox); 66756378Selan } 66856302Selan } 66956378Selan 67056378Selan 671