xref: /csrg-svn/lib/libcurses/refresh.c (revision 56559)
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*56559Selan static char sccsid[] = "@(#)refresh.c	5.15 (Berkeley) 10/13/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 
1856378Selan int doqch = 1;
1956378Selan 
2055976Sbostic WINDOW *_win;
212261Sarnold 
2255976Sbostic static void	domvcur __P((int, int, int, int));
2355976Sbostic static int	makech __P((WINDOW *, int));
2456302Selan static void	quickch __P((WINDOW *));
25*56559Selan static void	scrolln __P((WINDOW *, int, int, int, int, int));
2655976Sbostic /*
2755976Sbostic  * wrefresh --
2855976Sbostic  *	Make the current screen look like "win" over the area coverd by
2955976Sbostic  *	win.
3055976Sbostic  */
3155976Sbostic int
322261Sarnold wrefresh(win)
3355976Sbostic 	register WINDOW *win;
342261Sarnold {
3556302Selan 	register LINE *wlp;
3655976Sbostic 	register int retval;
3755976Sbostic 	register short wy;
382261Sarnold 
3955976Sbostic 	/* Make sure were in visual state. */
4055976Sbostic 	if (__endwin) {
4155976Sbostic 		tputs(VS, 0, __cputchar);
4255976Sbostic 		tputs(TI, 0, __cputchar);
4355976Sbostic 		__endwin = 0;
442261Sarnold 	}
452287Sarnold 
4655976Sbostic 	/* Initialize loop parameters. */
472287Sarnold 
4856238Selan 	ly = curscr->cury;
4956238Selan 	lx = curscr->curx;
502287Sarnold 	wy = 0;
512287Sarnold 	_win = win;
522287Sarnold 	curwin = (win == curscr);
532287Sarnold 
5456378Selan 	if (!curwin)
5556378Selan 		for (wy = 0; wy < win->maxy; wy++) {
5656378Selan 			wlp = win->lines[wy];
5756378Selan 			if (wlp->flags & __ISDIRTY)
5856378Selan 				wlp->hash = __hash(wlp->line, win->maxx);
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 			}
722261Sarnold 			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",
9456238Selan 		    wy, win->lines[wy]->firstch, win->lines[wy]->lastch);
9555976Sbostic #endif
9656378Selan 		if (!curwin)
9756378Selan 			curscr->lines[wy]->hash = win->lines[wy]->hash;
9856238Selan 		if (win->lines[wy]->flags & __ISDIRTY)
992261Sarnold 			if (makech(win, wy) == ERR)
10055976Sbostic 				return (ERR);
10119893Sbloom 			else {
10256238Selan 				if (win->lines[wy]->firstch >= win->ch_off)
10356238Selan 					win->lines[wy]->firstch = win->maxx +
10456238Selan 					    win->ch_off;
10556238Selan 				if (win->lines[wy]->lastch < win->maxx +
10656238Selan 				    win->ch_off)
10756238Selan 					win->lines[wy]->lastch = win->ch_off;
10856238Selan 				if (win->lines[wy]->lastch <
10956238Selan 				    win->lines[wy]->firstch)
11056238Selan 					win->lines[wy]->flags &= ~__ISDIRTY;
11119893Sbloom 			}
11255976Sbostic #ifdef DEBUG
11356238Selan 		__TRACE("\t%d\t%d\n", win->lines[wy]->firstch,
11456238Selan 			win->lines[wy]->lastch);
11555976Sbostic #endif
1162261Sarnold 	}
11756238Selan 
11856302Selan #ifdef DEBUG
11956238Selan 	__TRACE("refresh: ly=%d, lx=%d\n", ly, lx);
12056302Selan #endif
12156472Selan 
12212358Sarnold 	if (win == curscr)
12356238Selan 		domvcur(ly, lx, win->cury, win->curx);
12419893Sbloom 	else {
12556238Selan 		if (win->flags & __LEAVEOK) {
12656238Selan 			curscr->cury = ly;
12756238Selan 			curscr->curx = lx;
12856238Selan 			ly -= win->begy;
12956238Selan 			lx -= win->begx;
13056238Selan 			if (ly >= 0 && ly < win->maxy && lx >= 0 &&
13156238Selan 			    lx < win->maxx) {
13256238Selan 				win->cury = ly;
13356238Selan 				win->curx = lx;
13455976Sbostic 			} else
13556238Selan 				win->cury = win->curx = 0;
13655976Sbostic 		} else {
13756238Selan 			domvcur(ly, lx, win->cury + win->begy,
13856238Selan 			    win->curx + win->begx);
13956238Selan 			curscr->cury = win->cury + win->begy;
14056238Selan 			curscr->curx = win->curx + win->begx;
14119893Sbloom 		}
1422261Sarnold 	}
1432287Sarnold 	retval = OK;
14455986Sbostic 
1452261Sarnold 	_win = NULL;
14655976Sbostic 	(void)fflush(stdout);
14755976Sbostic 	return (retval);
1482261Sarnold }
1492261Sarnold 
1502261Sarnold /*
15155976Sbostic  * makech --
15255976Sbostic  *	Make a change on the screen.
1532261Sarnold  */
15455976Sbostic static int
1552261Sarnold makech(win, wy)
15655976Sbostic 	register WINDOW *win;
15755976Sbostic 	int wy;
1582261Sarnold {
15955976Sbostic 	register int nlsp, clsp;		/* Last space in lines. */
16055976Sbostic 	register short wx, lch, y;
16155976Sbostic 	register char *nsp, *csp, *ce;
1622261Sarnold 
16356472Selan 	/* Is the cursor still on the end of the last line? */
16456472Selan 	if (wy > 0 && win->lines[wy - 1]->flags & __ISPASTEOL) {
16556551Selan 		win->lines[wy - 1]->flags &= ~__ISPASTEOL;
16656551Selan 		domvcur(ly, lx, ly + 1, 0);
16756551Selan 		ly++;
16856551Selan 		lx = 0;
16956551Selan 	}
17056238Selan 	if (!(win->lines[wy]->flags & __ISDIRTY))
17155976Sbostic 		return (OK);
17256238Selan 	wx = win->lines[wy]->firstch - win->ch_off;
17356238Selan 	if (wx >= win->maxx)
17456238Selan 		return (OK);
17519893Sbloom 	else if (wx < 0)
17619893Sbloom 		wx = 0;
17756238Selan 	lch = win->lines[wy]->lastch - win->ch_off;
17819893Sbloom 	if (lch < 0)
17955976Sbostic 		return (OK);
18056238Selan 	else if (lch >= win->maxx)
18156238Selan 		lch = win->maxx - 1;
18256238Selan 	y = wy + win->begy;
18319893Sbloom 
1842287Sarnold 	if (curwin)
1852287Sarnold 		csp = " ";
1862287Sarnold 	else
18756238Selan 		csp = &curscr->lines[wy + win->begy]->line[wx + win->begx];
18819893Sbloom 
18956238Selan 	nsp = &win->lines[wy]->line[wx];
1902287Sarnold 	if (CE && !curwin) {
19156238Selan 		for (ce = &win->lines[wy]->line[win->maxx - 1];
19256238Selan 		     *ce == ' '; ce--)
19356238Selan 			if (ce <= win->lines[wy]->line)
1942261Sarnold 				break;
19556238Selan 		nlsp = ce - win->lines[wy]->line;
1962261Sarnold 	}
1972287Sarnold 	if (!curwin)
1982287Sarnold 		ce = CE;
1992287Sarnold 	else
2002287Sarnold 		ce = NULL;
20119893Sbloom 
2022261Sarnold 	while (wx <= lch) {
20355986Sbostic 		if (*nsp == *csp) {
20455986Sbostic 			if (wx <= lch) {
20555986Sbostic 				while (*nsp == *csp && wx <= lch) {
20655986Sbostic 					nsp++;
20755986Sbostic 					if (!curwin)
20855986Sbostic 						csp++;
20955986Sbostic 					++wx;
21055986Sbostic 				}
21155986Sbostic 				continue;
21255986Sbostic 			}
21355986Sbostic 			break;
21455986Sbostic 		}
21556238Selan 		domvcur(ly, lx, y, wx + win->begx);
21656378Selan 
21755976Sbostic #ifdef DEBUG
21856378Selan 		__TRACE("makech: 1: wx = %d, ly= %d, lx = %d, newy = %d, newx = %d\n",
21956378Selan 		    wx, ly, lx, y, wx + win->begx);
22055976Sbostic #endif
22155986Sbostic 		ly = y;
22256238Selan 		lx = wx + win->begx;
22355986Sbostic 		while (*nsp != *csp && wx <= lch) {
22456378Selan #ifdef notdef
22556378Selan 			/* XXX
22656378Selan 			 * The problem with this code is that we can't count on
22756378Selan 			 * terminals wrapping around after the
22856378Selan 			 * last character on the previous line has been output
22956378Selan 			 * In effect, what then could happen is that the CE
23056378Selan 			 * clear the previous line and do nothing to the
23156378Selan 			 * next line.
23256378Selan 			 */
23355986Sbostic 			if (ce != NULL && wx >= nlsp && *nsp == ' ') {
23455986Sbostic 				/* Check for clear to end-of-line. */
23556238Selan 				ce = &curscr->lines[ly]->line[COLS - 1];
23655986Sbostic 				while (*ce == ' ')
23755986Sbostic 					if (ce-- <= csp)
23855986Sbostic 						break;
23956238Selan 				clsp = ce - curscr->lines[ly]->line -
24056238Selan 				       win->begx;
24155976Sbostic #ifdef DEBUG
24255986Sbostic 			__TRACE("makech: clsp = %d, nlsp = %d\n", clsp, nlsp);
24355976Sbostic #endif
24455986Sbostic 				if (clsp - nlsp >= strlen(CE) &&
24556238Selan 				    clsp < win->maxx) {
24655976Sbostic #ifdef DEBUG
24755986Sbostic 					__TRACE("makech: using CE\n");
24855976Sbostic #endif
24955986Sbostic 					tputs(CE, 0, __cputchar);
25056238Selan 					lx = wx + win->begx;
25155986Sbostic 					while (wx++ <= clsp)
25255986Sbostic 						*csp++ = ' ';
25355986Sbostic 					return (OK);
2542261Sarnold 				}
25555986Sbostic 				ce = NULL;
25655986Sbostic 			}
25756378Selan #endif
25855986Sbostic 
25955986Sbostic 			/* Enter/exit standout mode as appropriate. */
26056238Selan 			if (SO && (*nsp & __STANDOUT) !=
26156378Selan 			    (curscr->flags & __WSTANDOUT)) {
26256238Selan 				if (*nsp & __STANDOUT) {
26355986Sbostic 					tputs(SO, 0, __cputchar);
26456238Selan 					curscr->flags |= __WSTANDOUT;
26555986Sbostic 				} else {
26655986Sbostic 					tputs(SE, 0, __cputchar);
26756238Selan 					curscr->flags &= ~__WSTANDOUT;
2682261Sarnold 				}
26955986Sbostic 			}
27055986Sbostic 
27155986Sbostic 			wx++;
27256472Selan 			if (wx >= win->maxx && wy == win->maxy - 1 && !curwin)
27356238Selan 				if (win->flags & __SCROLLOK) {
27456238Selan 					if (curscr->flags & __WSTANDOUT
27556238Selan 					    && win->flags & __ENDLINE)
27655986Sbostic 						if (!MS) {
27755986Sbostic 							tputs(SE, 0,
27855986Sbostic 							    __cputchar);
27956238Selan 							curscr->flags &=
28056238Selan 							    ~__WSTANDOUT;
28155976Sbostic 						}
28255986Sbostic 					if (!curwin)
28355986Sbostic 						putchar((*csp = *nsp) & 0177);
28455986Sbostic 					else
28555986Sbostic 						putchar(*nsp & 0177);
28656378Selan #ifdef notdef
28756472Selan 					if (win->flags & __FULLWIN && !curwin)
28855986Sbostic 						scroll(curscr);
28956378Selan #endif
29056378Selan 					ly = win->begy + win->maxy - 1;
29156378Selan 					lx = win->begx + win->maxx - 1;
29255986Sbostic 					return (OK);
29355986Sbostic 				} else
29456238Selan 					if (win->flags & __SCROLLWIN) {
29555986Sbostic 						lx = --wx;
29655986Sbostic 						return (ERR);
29755986Sbostic 					}
29855986Sbostic 			if (!curwin)
29955986Sbostic 				putchar((*csp++ = *nsp) & 0177);
30055986Sbostic 			else
30155986Sbostic 				putchar(*nsp & 0177);
30256472Selan 
30355976Sbostic #ifdef DEBUG
30455986Sbostic 			__TRACE("makech: putchar(%c)\n", *nsp & 0177);
30555976Sbostic #endif
30656238Selan 			if (UC && (*nsp & __STANDOUT)) {
30755986Sbostic 				putchar('\b');
30855986Sbostic 				tputs(UC, 0, __cputchar);
3092261Sarnold 			}
31055986Sbostic 			nsp++;
31155986Sbostic 		}
31255976Sbostic #ifdef DEBUG
31355986Sbostic 		__TRACE("makech: 2: wx = %d, lx = %d\n", wx, lx);
31455976Sbostic #endif
31556238Selan 		if (lx == wx + win->begx)	/* If no change. */
31655986Sbostic 			break;
31756238Selan 		lx = wx + win->begx;
31855986Sbostic 		if (lx >= COLS && AM) {
31955986Sbostic 			/*
32055986Sbostic 			 * xn glitch: chomps a newline after auto-wrap.
32155986Sbostic 			 * we just feed it now and forget about it.
32255986Sbostic 			 */
32355986Sbostic 			if (XN) {
32456472Selan 				lx = 0;
32556472Selan 				ly++;
32655986Sbostic 				putchar('\n');
32755986Sbostic 				putchar('\r');
32856472Selan 			} else {
32956472Selan 				if (wy != LINES)
33056472Selan 					win->lines[wy]->flags |= __ISPASTEOL;
33156472Selan 				lx = COLS - 1;
33222789Smckusick 			}
33355986Sbostic 		}
33455976Sbostic #ifdef DEBUG
33555976Sbostic 		__TRACE("makech: 3: wx = %d, lx = %d\n", wx, lx);
33655976Sbostic #endif
3372261Sarnold 	}
33855976Sbostic 	return (OK);
33911736Sarnold }
34011736Sarnold 
34111736Sarnold /*
34255976Sbostic  * domvcur --
34355976Sbostic  *	Do a mvcur, leaving standout mode if necessary.
34411736Sarnold  */
34555976Sbostic static void
34611736Sarnold domvcur(oy, ox, ny, nx)
34755976Sbostic 	int oy, ox, ny, nx;
34855976Sbostic {
34956238Selan 	if (curscr->flags & __WSTANDOUT && !MS) {
35055976Sbostic 		tputs(SE, 0, __cputchar);
35156238Selan 		curscr->flags &= ~__WSTANDOUT;
3522261Sarnold 	}
35356378Selan #ifdef DEBUG
35456378Selan 	__TRACE("domvcur: oy=%d, ox=%d, ny=%d, nx=%d\n", oy, ox, ny, nx);
35556378Selan #endif
35611736Sarnold 	mvcur(oy, ox, ny, nx);
3572261Sarnold }
35856302Selan 
35956302Selan 
36056302Selan /*
36156302Selan  * Quickch() attempts to detect a pattern in the change of the window
36256552Selan  * in order to optimize the change, e.g., scroll n lines as opposed to
36356302Selan  * repainting the screen line by line.
36456302Selan  */
36556302Selan 
36656302Selan static void
36756302Selan quickch(win)
36856302Selan 	WINDOW *win;
36956302Selan {
37056378Selan #define THRESH		win->maxy / 4
37156302Selan 
37256378Selan 	register LINE *clp, *tmp1, *tmp2;
37356378Selan 	register int bsize, curs, curw, starts, startw, i, j;
374*56559Selan 	int n, target, remember, bot, top;
37556378Selan 	char buf[1024];
37656378Selan 	u_int blank_hash;
37756302Selan 
37856552Selan 	/*
37956552Selan 	 * Search for the largest block of text not changed.
38056552Selan          */
38156302Selan 	for (bsize = win->maxy; bsize >= THRESH; bsize--)
38256302Selan 		for (startw = 0; startw <= win->maxy - bsize; startw++)
38356302Selan 			for (starts = 0; starts <= win->maxy - bsize;
38456302Selan 			     starts++) {
38556302Selan 				for (curw = startw, curs = starts;
38656302Selan 				     curs < starts + bsize; curw++, curs++)
38756302Selan 					if (win->lines[curw]->hash !=
38856552Selan 					    curscr->lines[curs]->hash ||
38956552Selan 				            bcmp(&win->lines[curw],
390*56559Selan 					    &curscr->lines[curs],
391*56559Selan 					    win->maxx != 0))
39256302Selan 						break;
39356302Selan 				if (curs == starts + bsize)
39456302Selan 					goto done;
39556302Selan 			}
39656302Selan  done:
39756302Selan 	/* Did not find anything or block is in correct place already. */
39856302Selan 	if (bsize < THRESH || starts == startw)
39956302Selan 		return;
40056302Selan 
401*56559Selan 	/*
402*56559Selan 	 * Find how many lines from the top of the screen are unchanged.
403*56559Selan 	 */
404*56559Selan 	if (starts != 0) {
405*56559Selan 		for (top = 0; top < win->maxy; top++)
406*56559Selan 			if (win->lines[top]->hash != curscr->lines[top]->hash
407*56559Selan 			    || bcmp(&win->lines[top], &curscr->lines[top],
408*56559Selan 				 win->maxx) != 0)
409*56559Selan 				break;
410*56559Selan 	} else
411*56559Selan 		top = 0;
412*56559Selan 
413*56559Selan        /*
414*56559Selan 	* Find how many lines from bottom of screen are unchanged.
415*56559Selan 	*/
416*56559Selan 	if (curs != win->maxy) {
417*56559Selan 		for (bot = win->maxy - 1; bot >= 0; bot--)
418*56559Selan 			if (win->lines[bot]->hash != curscr->lines[bot]->hash
419*56559Selan 			    || bcmp(&win->lines[bot], &curscr->lines[bot],
420*56559Selan 				 win->maxx) != 0)
421*56559Selan 				break;
422*56559Selan 	} else
423*56559Selan 		bot = win->maxy - 1;
424*56559Selan 
42556302Selan #ifdef DEBUG
426*56559Selan 	__TRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n",
427*56559Selan 		bsize, starts, startw, curw, curs, top, bot);
42856302Selan #endif
42956378Selan 
430*56559Selan 	/*
431*56559Selan 	 * Make sure that there is no overlap between the bottom and top
432*56559Selan 	 * regions and the middle scrolled block.
433*56559Selan 	 */
434*56559Selan 	if (bot < curw)
435*56559Selan 		bot = curw - 1;
436*56559Selan 	if (top > startw)
437*56559Selan 		top = startw;
438*56559Selan 
439*56559Selan 	scrolln(win, starts, startw, curs, top, bot);
440*56559Selan 
44156378Selan 	n = startw - starts;
44256378Selan 
44356378Selan 	/* So we don't have to call __hash() each time */
44456378Selan 	(void)memset(buf, ' ', win->maxx);
44556378Selan 	blank_hash = __hash(buf, win->maxx);
44656378Selan 
44756378Selan 	/*
44856378Selan 	 * Perform the rotation to maintain the consistency of curscr.
44956378Selan 	 */
45056378Selan 	i = 0;
45156378Selan 	tmp1 = curscr->lines[0];
45256378Selan 	remember = 0;
45356378Selan 	for (j = 0; j < win->maxy; j++) {
45456378Selan 		target = (i + n + win->maxy) % win->maxy;
45556378Selan 		tmp2 = curscr->lines[target];
45656378Selan 		curscr->lines[target] = tmp1;
45756378Selan 		/* Mark block as clean and blank out scrolled lines. */
45856378Selan 		clp = curscr->lines[target];
45956472Selan #ifdef DEBUG
46056378Selan 		__TRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ",
46156378Selan 			n, startw, curw, i, target);
46256472Selan #endif
463*56559Selan 		if (target >= startw && target < curw || target < top ||
464*56559Selan 		    target > bot) {
46556472Selan #ifdef DEBUG
46656378Selan 			__TRACE("-- notdirty");
46756472Selan #endif
46856378Selan 			win->lines[target]->flags &= ~__ISDIRTY;
46956378Selan 		} else if ((n < 0 && target >= win->maxy + n) ||
47056378Selan 			 (n > 0 && target < n)) {
47156552Selan 			if (clp->hash != blank_hash ||
47256552Selan 			    bcmp(clp->line, buf, win->maxx) != 0) {
47356378Selan 				(void)memset(clp->line, ' ', win->maxx);
47456472Selan #ifdef DEBUG
47556378Selan 				__TRACE("-- memset");
47656472Selan #endif
47756378Selan 				clp->hash = blank_hash;
47856378Selan 			} else
47956472Selan #ifdef DEBUG
48056378Selan 				__TRACE(" -- nonmemset");
48156472Selan #endif
48256378Selan 			touchline(win, target, 0, win->maxx - 1);
48356378Selan 		} else {
48456472Selan #ifdef DEBUG
48556378Selan 			__TRACE(" -- just dirty");
48656472Selan #endif
48756378Selan 			touchline(win, target, 0, win->maxx - 1);
48856378Selan 		}
48956472Selan #ifdef DEBUG
49056378Selan 		__TRACE("\n");
49156472Selan #endif
49256378Selan 		if (target == remember) {
49356378Selan 			i = target + 1;
49456378Selan 			tmp1 = curscr->lines[i];
49556378Selan 			remember = i;
49656378Selan 		} else {
49756378Selan 			tmp1 = tmp2;
49856378Selan 			i = target;
49956378Selan 		}
50056302Selan 	}
50156472Selan #ifdef DEBUG
50256378Selan 	__TRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
50356378Selan 	for (i = 0; i < curscr->maxy; i++)
50456378Selan 		__TRACE("Q: %d: %.70s\n", i,
50556378Selan 	           curscr->lines[i]->line);
50656472Selan #endif
50756302Selan }
50856302Selan 
50956302Selan static void
510*56559Selan scrolln(win, starts, startw, curs, top, bot)
51156302Selan 	WINDOW *win;
512*56559Selan 	int starts, startw, curs, top, bot;
51356302Selan {
51456302Selan 	int i, oy, ox, n;
51556302Selan 
51656302Selan 	oy = curscr->cury;
51756302Selan 	ox = curscr->curx;
51856302Selan 	n = starts - startw;
51956302Selan 
52056302Selan 	if (n > 0) {
521*56559Selan 		mvcur(oy, ox, top, 0);
522*56559Selan 		/* Scroll up the block */
52356302Selan 		if (DL)
52456302Selan 			tputs(tscroll(DL, n), 0, __cputchar);
52556302Selan 		else
52656302Selan 			for(i = 0; i < n; i++)
52756302Selan 				tputs(dl, 0, __cputchar);
528*56559Selan 		/* Push back down the bottom region */
529*56559Selan 		if (bot < win->maxy - 1) {
530*56559Selan 			mvcur(top, 0, bot - n + 1, 0);
531*56559Selan 			if (AL)
532*56559Selan 				tputs(tscroll(AL, n), 0, __cputchar);
533*56559Selan 			else
534*56559Selan 				for(i = 0; i < n; i++)
535*56559Selan 					tputs(al, 0, __cputchar);
536*56559Selan 			mvcur(bot - n + 1, 0, oy, ox);
537*56559Selan 		} else
538*56559Selan 			mvcur(top, 0, oy, ox);
53956302Selan 	} else {
540*56559Selan 		/* Preserve the bottom lines. (Pull them up) */
541*56559Selan 		if (bot < win->maxy - 1) {
542*56559Selan 			mvcur(oy, ox, curs, 0);
543*56559Selan 			if (DL)
544*56559Selan 				tputs(tscroll(DL, -n), 0, __cputchar);
545*56559Selan 			else
546*56559Selan 			       	for(i = n; i < 0; i++)
547*56559Selan 					tputs(dl, 0, __cputchar);
548*56559Selan 			mvcur(curs, 0, starts, 0);
549*56559Selan 		} else
550*56559Selan 			mvcur(oy, ox, starts,  0);
55156302Selan 
55256302Selan 		/* Scroll the block down */
55356302Selan 		if (AL)
55456302Selan 			tputs(tscroll(AL, -n), 0, __cputchar);
55556302Selan 		else
55656302Selan 			for(i = n; i < 0; i++)
55756302Selan 				tputs(al, 0, __cputchar);
55856302Selan 		mvcur(starts, 0, oy, ox);
55956378Selan 	}
56056302Selan }
56156378Selan 
56256378Selan 
563