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*59062Selan static char sccsid[] = "@(#)refresh.c 5.37 (Berkeley) 04/13/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 11958369Selan } else 12058369Selan win->lines[wy]->flags &= ~__ISPASTEOL; 12155976Sbostic #ifdef DEBUG 12256715Selan __TRACE("\t%d\t%d\n", *win->lines[wy]->firstchp, 12356715Selan *win->lines[wy]->lastchp); 12455976Sbostic #endif 1252261Sarnold } 12656238Selan 12756302Selan #ifdef DEBUG 12856238Selan __TRACE("refresh: ly=%d, lx=%d\n", ly, lx); 12956302Selan #endif 13056472Selan 13112358Sarnold if (win == curscr) 13256238Selan domvcur(ly, lx, win->cury, win->curx); 13319893Sbloom else { 13456238Selan if (win->flags & __LEAVEOK) { 13556238Selan curscr->cury = ly; 13656238Selan curscr->curx = lx; 13756238Selan ly -= win->begy; 13856238Selan lx -= win->begx; 13956238Selan if (ly >= 0 && ly < win->maxy && lx >= 0 && 14056238Selan lx < win->maxx) { 14156238Selan win->cury = ly; 14256238Selan win->curx = lx; 14355976Sbostic } else 14456238Selan win->cury = win->curx = 0; 14555976Sbostic } else { 14656238Selan domvcur(ly, lx, win->cury + win->begy, 14756238Selan win->curx + win->begx); 14856238Selan curscr->cury = win->cury + win->begy; 14956238Selan curscr->curx = win->curx + win->begx; 15019893Sbloom } 1512261Sarnold } 15257472Sbostic retval = OK; 15355986Sbostic 1542261Sarnold _win = NULL; 15555976Sbostic (void)fflush(stdout); 15655976Sbostic return (retval); 1572261Sarnold } 1582261Sarnold 1592261Sarnold /* 16055976Sbostic * makech -- 16155976Sbostic * Make a change on the screen. 1622261Sarnold */ 16355976Sbostic static int 1642261Sarnold makech(win, wy) 16555976Sbostic register WINDOW *win; 16655976Sbostic int wy; 1672261Sarnold { 16858049Selan register int nlsp; /* Last space in lines. */ 16955976Sbostic register short wx, lch, y; 17056648Selan register __LDATA *nsp, *csp, *cp; 17156651Selan u_int force; 17256648Selan char *ce; 17356648Selan __LDATA blank = {' ', 0}; 17456648Selan 17556472Selan /* Is the cursor still on the end of the last line? */ 17656472Selan if (wy > 0 && win->lines[wy - 1]->flags & __ISPASTEOL) { 17756551Selan win->lines[wy - 1]->flags &= ~__ISPASTEOL; 17856551Selan domvcur(ly, lx, ly + 1, 0); 17956551Selan ly++; 18056551Selan lx = 0; 18156551Selan } 18256238Selan if (!(win->lines[wy]->flags & __ISDIRTY)) 18357472Sbostic return (OK); 18456715Selan wx = *win->lines[wy]->firstchp - win->ch_off; 18556238Selan if (wx >= win->maxx) 18657472Sbostic return (OK); 18719893Sbloom else if (wx < 0) 18819893Sbloom wx = 0; 18956715Selan lch = *win->lines[wy]->lastchp - win->ch_off; 19019893Sbloom if (lch < 0) 19157472Sbostic return (OK); 19256238Selan else if (lch >= win->maxx) 19356238Selan lch = win->maxx - 1; 19456238Selan y = wy + win->begy; 19519893Sbloom 1962287Sarnold if (curwin) 19756648Selan csp = ␣ 1982287Sarnold else 19956238Selan csp = &curscr->lines[wy + win->begy]->line[wx + win->begx]; 20019893Sbloom 20156238Selan nsp = &win->lines[wy]->line[wx]; 20256651Selan force = win->lines[wy]->flags & __FORCEPAINT; 20356651Selan win->lines[wy]->flags &= ~__FORCEPAINT; 2042287Sarnold if (CE && !curwin) { 20556648Selan for (cp = &win->lines[wy]->line[win->maxx - 1]; 20656648Selan cp->ch == ' ' && cp->attr == 0; cp--) 20756648Selan if (cp <= win->lines[wy]->line) 2082261Sarnold break; 20956648Selan nlsp = cp - win->lines[wy]->line; 2102261Sarnold } 2112287Sarnold if (!curwin) 2122287Sarnold ce = CE; 2132287Sarnold else 2142287Sarnold ce = NULL; 21519893Sbloom 21656651Selan if (force) { 21756651Selan if (CM) 21856651Selan tputs(tgoto(CM, lx, ly), 0, __cputchar); 21956651Selan else { 22056651Selan tputs(HO, 0, __cputchar); 22156651Selan mvcur(0, 0, ly, lx); 22256651Selan } 22356651Selan } 2242261Sarnold while (wx <= lch) { 22557956Selan if (!force && memcmp(nsp, csp, sizeof(__LDATA)) == 0) { 22655986Sbostic if (wx <= lch) { 22757956Selan while (memcmp(nsp, csp, sizeof(__LDATA)) == 0 && 22856648Selan wx <= lch) { 22956596Selan nsp++; 23056648Selan if (!curwin) 23156648Selan csp++; 23256648Selan ++wx; 23356648Selan } 23455986Sbostic continue; 23555986Sbostic } 23655986Sbostic break; 23755986Sbostic } 23856238Selan domvcur(ly, lx, y, wx + win->begx); 23956378Selan 24055976Sbostic #ifdef DEBUG 24156651Selan __TRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d, force =%d\n", 24256651Selan wx, ly, lx, y, wx + win->begx, force); 24355976Sbostic #endif 24455986Sbostic ly = y; 24556238Selan lx = wx + win->begx; 24657956Selan while ((force || memcmp(nsp, csp, sizeof(__LDATA)) != 0) 24756651Selan && wx <= lch) { 24855986Sbostic 24955986Sbostic /* Enter/exit standout mode as appropriate. */ 25056648Selan if (SO && (nsp->attr & __STANDOUT) != 25156378Selan (curscr->flags & __WSTANDOUT)) { 25256648Selan if (nsp->attr & __STANDOUT) { 25355986Sbostic tputs(SO, 0, __cputchar); 25456238Selan curscr->flags |= __WSTANDOUT; 25555986Sbostic } else { 25655986Sbostic tputs(SE, 0, __cputchar); 25756238Selan curscr->flags &= ~__WSTANDOUT; 2582261Sarnold } 25955986Sbostic } 26055986Sbostic 26155986Sbostic wx++; 26256472Selan if (wx >= win->maxx && wy == win->maxy - 1 && !curwin) 26356238Selan if (win->flags & __SCROLLOK) { 26456238Selan if (curscr->flags & __WSTANDOUT 26556238Selan && win->flags & __ENDLINE) 26655986Sbostic if (!MS) { 26755986Sbostic tputs(SE, 0, 26855986Sbostic __cputchar); 26956238Selan curscr->flags &= 27056238Selan ~__WSTANDOUT; 27155976Sbostic } 27256596Selan if (!curwin) { 27356648Selan csp->attr = nsp->attr; 27456648Selan putchar(csp->ch = nsp->ch); 27556596Selan } else 27656648Selan putchar(nsp->ch); 27758040Selan 27856599Selan if (wx + win->begx < curscr->maxx) { 27956599Selan domvcur(ly, wx + win->begx, 28056599Selan win->begy + win->maxy - 1, 28156599Selan win->begx + win->maxx - 1); 28256599Selan } 28356378Selan ly = win->begy + win->maxy - 1; 28456378Selan lx = win->begx + win->maxx - 1; 28557472Sbostic return (OK); 28655986Sbostic } else 28756238Selan if (win->flags & __SCROLLWIN) { 28855986Sbostic lx = --wx; 28957472Sbostic return (ERR); 29055986Sbostic } 29156596Selan if (!curwin) { 29256648Selan csp->attr = nsp->attr; 29356648Selan putchar(csp->ch = nsp->ch); 29456648Selan csp++; 29556648Selan } else 29656648Selan putchar(nsp->ch); 29756472Selan 29855976Sbostic #ifdef DEBUG 29956648Selan __TRACE("makech: putchar(%c)\n", nsp->ch & 0177); 30055976Sbostic #endif 30156648Selan if (UC && (nsp->attr & __STANDOUT)) { 30255986Sbostic putchar('\b'); 30355986Sbostic tputs(UC, 0, __cputchar); 3042261Sarnold } 30555986Sbostic nsp++; 30655986Sbostic } 30755976Sbostic #ifdef DEBUG 30855986Sbostic __TRACE("makech: 2: wx = %d, lx = %d\n", wx, lx); 30955976Sbostic #endif 31056238Selan if (lx == wx + win->begx) /* If no change. */ 31155986Sbostic break; 31256238Selan lx = wx + win->begx; 31355986Sbostic if (lx >= COLS && AM) { 31458040Selan if (wy != LINES) 31558040Selan win->lines[wy]->flags |= __ISPASTEOL; 31658040Selan lx = COLS - 1; 31756596Selan } else if (wx >= win->maxx) { 31856596Selan if (wy != win->maxy) 31956596Selan win->lines[wy]->flags |= __ISPASTEOL; 32056596Selan domvcur(ly, lx, ly, win->maxx + win->begx - 1); 32156596Selan lx = win->maxx + win->begx - 1; 32255986Sbostic } 32356596Selan 32455976Sbostic #ifdef DEBUG 32555976Sbostic __TRACE("makech: 3: wx = %d, lx = %d\n", wx, lx); 32655976Sbostic #endif 3272261Sarnold } 32857472Sbostic return (OK); 32911736Sarnold } 33011736Sarnold 33111736Sarnold /* 33255976Sbostic * domvcur -- 33355976Sbostic * Do a mvcur, leaving standout mode if necessary. 33411736Sarnold */ 33555976Sbostic static void 33611736Sarnold domvcur(oy, ox, ny, nx) 33755976Sbostic int oy, ox, ny, nx; 33855976Sbostic { 33956238Selan if (curscr->flags & __WSTANDOUT && !MS) { 34055976Sbostic tputs(SE, 0, __cputchar); 34156238Selan curscr->flags &= ~__WSTANDOUT; 3422261Sarnold } 34356596Selan 34411736Sarnold mvcur(oy, ox, ny, nx); 3452261Sarnold } 34656302Selan 34756302Selan /* 34856302Selan * Quickch() attempts to detect a pattern in the change of the window 34956552Selan * in order to optimize the change, e.g., scroll n lines as opposed to 35056302Selan * repainting the screen line by line. 35156302Selan */ 35256302Selan 35356302Selan static void 35456302Selan quickch(win) 35556302Selan WINDOW *win; 35656302Selan { 35758019Selan #define THRESH (int) win->maxy / 4 35856302Selan 35956648Selan register __LINE *clp, *tmp1, *tmp2; 36056378Selan register int bsize, curs, curw, starts, startw, i, j; 36156652Selan int n, target, cur_period, bot, top, sc_region; 36256648Selan __LDATA buf[1024]; 36356378Selan u_int blank_hash; 36456302Selan 36558019Selan /* 36658019Selan * Find how many lines from the top of the screen are unchanged. 36758019Selan */ 36858034Selan for (top = 0; top < win->maxy; top++) 36958019Selan if (win->lines[top]->flags & __FORCEPAINT || 37058019Selan win->lines[top]->hash != curscr->lines[top]->hash 37158019Selan || memcmp(win->lines[top]->line, 37258019Selan curscr->lines[top]->line, 37358019Selan win->maxx * __LDATASIZE) != 0) 37458019Selan break; 37558034Selan else 37658034Selan win->lines[top]->flags &= ~__ISDIRTY; 37758019Selan /* 37858019Selan * Find how many lines from bottom of screen are unchanged. 37958019Selan */ 38058019Selan for (bot = win->maxy - 1; bot >= 0; bot--) 38158019Selan if (win->lines[bot]->flags & __FORCEPAINT || 38258019Selan win->lines[bot]->hash != curscr->lines[bot]->hash 38358019Selan || memcmp(win->lines[bot]->line, 38458019Selan curscr->lines[bot]->line, 38558019Selan win->maxx * __LDATASIZE) != 0) 38658019Selan break; 38758034Selan else 38858034Selan win->lines[bot]->flags &= ~__ISDIRTY; 38958019Selan 390*59062Selan 39156552Selan /* 392*59062Selan * If we have a bottom unchanged region return. Scrolling the 393*59062Selan * bottom region up and then back down causes a screen jitter. 394*59062Selan * This will increase the number of characters sent to the screen 395*59062Selan * but it looks better. 396*59062Selan */ 397*59062Selan if (bot < win->maxy - 1) 398*59062Selan return; 399*59062Selan 400*59062Selan /* 40156552Selan * Search for the largest block of text not changed. 40256652Selan * Invariants of the loop: 40356652Selan * - Startw is the index of the beginning of the examined block in win. 40456652Selan * - Starts is the index of the beginning of the examined block in 40556652Selan * curscr. 40656652Selan * - Curs is the index of one past the end of the exmined block in win. 40756652Selan * - Curw is the index of one past the end of the exmined block in 40856652Selan * curscr. 40956652Selan * - bsize is the current size of the examined block. 41056552Selan */ 41158019Selan for (bsize = bot - top; bsize >= THRESH; bsize--) { 41258019Selan for (startw = top; startw <= bot - bsize; startw++) 41358019Selan for (starts = top; starts <= bot - bsize; 41456302Selan starts++) { 41556302Selan for (curw = startw, curs = starts; 41656302Selan curs < starts + bsize; curw++, curs++) 41756651Selan if (win->lines[curw]->flags & 41856651Selan __FORCEPAINT || 41956651Selan (win->lines[curw]->hash != 42056552Selan curscr->lines[curs]->hash || 42157956Selan memcmp(win->lines[curw]->line, 42256648Selan curscr->lines[curs]->line, 42356651Selan win->maxx * __LDATASIZE) != 0)) 42456302Selan break; 42556302Selan if (curs == starts + bsize) 42656302Selan goto done; 42756302Selan } 42858019Selan } 42956302Selan done: 43056651Selan /* Did not find anything */ 43156651Selan if (bsize < THRESH) 43256302Selan return; 43356302Selan 43456302Selan #ifdef DEBUG 43556559Selan __TRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n", 43656559Selan bsize, starts, startw, curw, curs, top, bot); 43756302Selan #endif 43856378Selan 43956559Selan /* 44056559Selan * Make sure that there is no overlap between the bottom and top 44156559Selan * regions and the middle scrolled block. 44256559Selan */ 44356691Selan if (bot < curs) 44456691Selan bot = curs - 1; 44556691Selan if (top > starts) 44656691Selan top = starts; 44756559Selan 44856378Selan n = startw - starts; 44956378Selan 45056691Selan #ifdef DEBUG 45156691Selan __TRACE("#####################################\n"); 45256691Selan for (i = 0; i < curscr->maxy; i++) { 45356691Selan __TRACE("C: %d:", i); 45457356Selan __TRACE(" 0x%x \n", curscr->lines[i]->hash); 45556691Selan for (j = 0; j < curscr->maxx; j++) 45656691Selan __TRACE("%c", 45756691Selan curscr->lines[i]->line[j].ch); 45856691Selan __TRACE("\n"); 45957356Selan for (j = 0; j < curscr->maxx; j++) 46057356Selan __TRACE("%x", 46157356Selan curscr->lines[i]->line[j].attr); 46257356Selan __TRACE("\n"); 46356691Selan __TRACE("W: %d:", i); 46457356Selan __TRACE(" 0x%x \n", win->lines[i]->hash); 46557356Selan __TRACE(" 0x%x ", win->lines[i]->flags); 46656691Selan for (j = 0; j < win->maxx; j++) 46756691Selan __TRACE("%c", 46856691Selan win->lines[i]->line[j].ch); 46956691Selan __TRACE("\n"); 47057356Selan for (j = 0; j < win->maxx; j++) 47157356Selan __TRACE("%x", 47257356Selan win->lines[i]->line[j].attr); 47357356Selan __TRACE("\n"); 47456691Selan } 47556691Selan #endif 47656651Selan if (n != 0) 47756705Selan scrolln(win, starts, startw, curs, bot, top); 47858019Selan 47956378Selan /* So we don't have to call __hash() each time */ 48056648Selan for (i = 0; i < win->maxx; i++) { 48156648Selan buf[i].ch = ' '; 48256648Selan buf[i].attr = 0; 48356648Selan } 48458192Selan blank_hash = __hash((char *) buf, win->maxx * __LDATASIZE); 48556378Selan 48656378Selan /* 48756378Selan * Perform the rotation to maintain the consistency of curscr. 48856691Selan * This is hairy since we are doing an *in place* rotation. 48956652Selan * Invariants of the loop: 49056652Selan * - I is the index of the current line. 49156652Selan * - Target is the index of the target of line i. 49256652Selan * - Tmp1 points to current line (i). 49356652Selan * - Tmp2 and points to target line (target); 49456652Selan * - Cur_period is the index of the end of the current period. 49556652Selan * (see below). 49656652Selan * 49756652Selan * There are 2 major issues here that make this rotation non-trivial: 49856652Selan * 1. Scrolling in a scrolling region bounded by the top 49956652Selan * and bottom regions determined (whose size is sc_region). 50056652Selan * 2. As a result of the use of the mod function, there may be a 50156652Selan * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and 50256652Selan * 0 to 2, which then causes all odd lines not to be rotated. 50356652Selan * To remedy this, an index of the end ( = beginning) of the 50456652Selan * current 'period' is kept, cur_period, and when it is reached, 50556652Selan * the next period is started from cur_period + 1 which is 50656652Selan * guaranteed not to have been reached since that would mean that 50756652Selan * all records would have been reached. (think about it...). 50856652Selan * 50956652Selan * Lines in the rotation can have 3 attributes which are marked on the 51056652Selan * line so that curscr is consistent with the visual screen. 51156705Selan * 1. Not dirty -- lines inside the scrolled block, top region or 51256652Selan * bottom region. 51356705Selan * 2. Blank lines -- lines in the differential of the scrolling 51456705Selan * region adjacent to top and bot regions 51556705Selan * depending on scrolling direction. 51656652Selan * 3. Dirty line -- all other lines are marked dirty. 51756378Selan */ 51856648Selan sc_region = bot - top + 1; 51956648Selan i = top; 52056648Selan tmp1 = curscr->lines[top]; 52156652Selan cur_period = top; 52256648Selan for (j = top; j <= bot; j++) { 52356648Selan target = (i - top + n + sc_region) % sc_region + top; 52456378Selan tmp2 = curscr->lines[target]; 52556378Selan curscr->lines[target] = tmp1; 52656378Selan /* Mark block as clean and blank out scrolled lines. */ 52756378Selan clp = curscr->lines[target]; 52856472Selan #ifdef DEBUG 52956378Selan __TRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ", 53056378Selan n, startw, curw, i, target); 53156472Selan #endif 53256691Selan if ((target >= startw && target < curw) || target < top 53356691Selan || target > bot) { 53456472Selan #ifdef DEBUG 53556378Selan __TRACE("-- notdirty"); 53656472Selan #endif 53756378Selan win->lines[target]->flags &= ~__ISDIRTY; 53856705Selan } else if ((n > 0 && target >= top && target < top + n) || 53956705Selan (n < 0 && target <= bot && target > bot + n)) { 54057956Selan if (clp->hash != blank_hash || memcmp(clp->line, 54156648Selan buf, win->maxx * __LDATASIZE) !=0) { 54258041Selan (void)memcpy(clp->line, buf, 54356648Selan win->maxx * __LDATASIZE); 54456472Selan #ifdef DEBUG 54556648Selan __TRACE("-- blanked out: dirty"); 54656472Selan #endif 54756378Selan clp->hash = blank_hash; 54856652Selan __touchline(win, target, 0, win->maxx - 1, 0); 54956705Selan } else { 55056652Selan __touchline(win, target, 0, win->maxx - 1, 0); 55156472Selan #ifdef DEBUG 55256648Selan __TRACE(" -- blank line already: dirty"); 55356472Selan #endif 55456705Selan } 55556378Selan } else { 55656472Selan #ifdef DEBUG 55756648Selan __TRACE(" -- dirty"); 55856472Selan #endif 55956651Selan __touchline(win, target, 0, win->maxx - 1, 0); 56056378Selan } 56156472Selan #ifdef DEBUG 56256378Selan __TRACE("\n"); 56356472Selan #endif 56456652Selan if (target == cur_period) { 56556378Selan i = target + 1; 56656378Selan tmp1 = curscr->lines[i]; 56756652Selan cur_period = i; 56856378Selan } else { 56956378Selan tmp1 = tmp2; 57056378Selan i = target; 57156378Selan } 57256302Selan } 57356472Selan #ifdef DEBUG 57456648Selan __TRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); 57556648Selan for (i = 0; i < curscr->maxy; i++) { 57656691Selan __TRACE("C: %d:", i); 57756648Selan for (j = 0; j < curscr->maxx; j++) 57856648Selan __TRACE("%c", 57956648Selan curscr->lines[i]->line[j].ch); 58056648Selan __TRACE("\n"); 58156691Selan __TRACE("W: %d:", i); 58256691Selan for (j = 0; j < win->maxx; j++) 58356691Selan __TRACE("%c", 58456691Selan win->lines[i]->line[j].ch); 58556691Selan __TRACE("\n"); 58656648Selan } 58756472Selan #endif 58856302Selan } 58956302Selan 59056652Selan /* 59156652Selan * Scrolln performs the scroll by n lines, where n is starts - startw. 59256652Selan */ 59356302Selan static void 59456705Selan scrolln(win, starts, startw, curs, bot, top) 59556302Selan WINDOW *win; 59656705Selan int starts, startw, curs, bot, top; 59756302Selan { 59856302Selan int i, oy, ox, n; 59956302Selan 60056302Selan oy = curscr->cury; 60156302Selan ox = curscr->curx; 60256302Selan n = starts - startw; 60356302Selan 60456302Selan if (n > 0) { 60556559Selan mvcur(oy, ox, top, 0); 60656559Selan /* Scroll up the block */ 60756302Selan if (DL) 60857475Sbostic tputs(__tscroll(DL, n), 0, __cputchar); 60956302Selan else 61056302Selan for(i = 0; i < n; i++) 61156302Selan tputs(dl, 0, __cputchar); 61256652Selan 61356651Selan /* 61456652Selan * Push down the bottom region. 61556651Selan */ 61656705Selan mvcur(top, 0, bot - n + 1, 0); 61758019Selan if (AL) 61857475Sbostic tputs(__tscroll(AL, n), 0, __cputchar); 61956652Selan else 62056652Selan for(i = 0; i < n; i++) 62156652Selan tputs(al, 0, __cputchar); 62256705Selan mvcur(bot - n + 1, 0, oy, ox); 62356302Selan } else { 62456651Selan /* Preserve the bottom lines */ 62556705Selan mvcur(oy, ox, bot + n + 1, 0); /* n < 0 */ 62656652Selan if (DL) 62757475Sbostic tputs(__tscroll(DL, -n), 0, __cputchar); 62856652Selan else 62956652Selan for(i = n; i < 0; i++) 63056652Selan tputs(dl, 0, __cputchar); 63156705Selan mvcur(bot + n + 1, 0, top, 0); 63256302Selan 63356302Selan /* Scroll the block down */ 63458019Selan if (AL) 63557475Sbostic tputs(__tscroll(AL, -n), 0, __cputchar); 63656302Selan else 63756302Selan for(i = n; i < 0; i++) 63856302Selan tputs(al, 0, __cputchar); 63956705Selan mvcur(top, 0, oy, ox); 64056378Selan } 64156302Selan } 64256378Selan 64356378Selan 644