xref: /csrg-svn/usr.bin/window/xxflush.c (revision 39159)
138745Sedward /*
238745Sedward  * Copyright (c) 1989 Regents of the University of California.
338745Sedward  * All rights reserved.
438745Sedward  *
538745Sedward  * Redistribution and use in source and binary forms are permitted
638745Sedward  * provided that the above copyright notice and this paragraph are
738745Sedward  * duplicated in all such forms and that any documentation,
838745Sedward  * advertising materials, and other materials related to such
938745Sedward  * distribution and use acknowledge that the software was developed
1038745Sedward  * by the University of California, Berkeley.  The name of the
1138745Sedward  * University may not be used to endorse or promote products derived
1238745Sedward  * from this software without specific prior written permission.
1338745Sedward  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1438745Sedward  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1538745Sedward  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1638745Sedward  */
1738745Sedward 
1838745Sedward #ifndef lint
19*39159Sedward static char sccsid[] = "@(#)xxflush.c	3.4 (Berkeley) 09/15/89";
2038745Sedward #endif /* not lint */
2138745Sedward 
2238745Sedward #include "ww.h"
2338745Sedward #include "xx.h"
2438745Sedward #include "tt.h"
2538745Sedward 
2638745Sedward xxflush(intr)
2738745Sedward 	register intr;
2838745Sedward {
2938745Sedward 	register struct xx *xp, *xq;
3038745Sedward 
3138745Sedward 	for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) {
3238745Sedward 		switch (xp->cmd) {
3338745Sedward 		case xc_move:
3438745Sedward 			if (xp->link == 0)
3538745Sedward 				(*tt.tt_move)(xp->arg0, xp->arg1);
3638745Sedward 			break;
3738745Sedward 		case xc_scroll:
3838745Sedward 			xxflush_scroll(xp);
3938745Sedward 			break;
4038745Sedward 		case xc_inschar:
4138745Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
4238747Sedward 			tt.tt_nmodes = xp->arg3;
4338747Sedward 			(*tt.tt_inschar)(xp->arg2);
4438745Sedward 			break;
4538747Sedward 		case xc_insspace:
4638747Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
4738747Sedward 			(*tt.tt_insspace)(xp->arg2);
4838747Sedward 			break;
4938745Sedward 		case xc_delchar:
5038745Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
5138745Sedward 			(*tt.tt_delchar)(xp->arg2);
5238745Sedward 			break;
5338745Sedward 		case xc_clear:
5438745Sedward 			(*tt.tt_clear)();
5538745Sedward 			break;
5638745Sedward 		case xc_clreos:
5738745Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
5838745Sedward 			(*tt.tt_clreos)();
5938745Sedward 			break;
6038745Sedward 		case xc_clreol:
6138745Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
6238745Sedward 			(*tt.tt_clreol)();
6338745Sedward 			break;
6438745Sedward 		case xc_write:
6538745Sedward 			(*tt.tt_move)(xp->arg0, xp->arg1);
6638745Sedward 			tt.tt_nmodes = xp->arg3;
67*39159Sedward 			(*tt.tt_write)(xp->buf, xp->arg2);
6838745Sedward 			break;
6938745Sedward 		}
7038745Sedward 		xq = xp->link;
7138745Sedward 		xxfree(xp);
7238745Sedward 	}
7338745Sedward 	if ((xx_head = xp) == 0) {
7438745Sedward 		xx_tail = 0;
7538745Sedward 		xxbufp = xxbuf;
7638745Sedward 	}
77*39159Sedward 	(*tt.tt_flush)();
7838745Sedward }
7938745Sedward 
8038745Sedward xxflush_scroll(xp)
8138745Sedward 	register struct xx *xp;
8238745Sedward {
8338745Sedward 	register struct xx *xq;
8438745Sedward 
8538745Sedward  top:
8638745Sedward 	if (xp->arg0 == 0)
8738745Sedward 		return;
8838745Sedward 	/*
8938745Sedward 	 * We handle retain (da and db) by putting the burden on scrolling up,
9038745Sedward 	 * which is the less common operation.  It must ensure that
9138745Sedward 	 * text is not pushed below the screen, so scrolling down doesn't
9238745Sedward 	 * have to worry about it.
9338745Sedward 	 *
9438745Sedward 	 * Try scrolling region (or scrolling the whole screen) first.
9538745Sedward 	 * Can we assume "sr" doesn't push text below the screen
9638745Sedward 	 * so we don't have to worry about retain below?
9738745Sedward 	 * What about scrolling down with a newline?  It probably does
9838745Sedward 	 * push text above (with da).  Scrolling up would then have
9938745Sedward 	 * to take care of that.
10038745Sedward 	 * It's easy to be fool proof, but that slows things down.
10138745Sedward 	 * The current solution is to disallow tt_scroll_up if da or db is true
10238745Sedward 	 * but cs (scrolling region) is not.  Again, we sacrifice scrolling
10338745Sedward 	 * up in favor of scrolling down.  The idea is having scrolling regions
10438745Sedward 	 * probably means we can scroll (even the whole screen) with impunity.
10538745Sedward 	 * This lets us work efficiently on simple terminals (use newline
10638745Sedward 	 * on the bottom to scroll), on any terminal without retain, and
10738745Sedward 	 * on vt100 style scrolling regions (I think).
10838745Sedward 	 */
10938745Sedward 	if (xp->arg0 > 0) {
11038745Sedward 		if ((xq = xp->link) != 0 && xq->cmd == xc_scroll &&
11138745Sedward 		    xp->arg2 == xq->arg2 && xq->arg0 < 0) {
11238745Sedward 			if (xp->arg1 < xq->arg1) {
11338745Sedward 				if (xp->arg2 - xp->arg0 <= xq->arg1) {
11438745Sedward 					xq->arg0 = xp->arg0;
11538745Sedward 					xq->arg1 = xp->arg1;
11638745Sedward 					xq->arg2 = xp->arg2;
11738745Sedward 					return;
11838745Sedward 				}
11938745Sedward 				xp->arg2 = xq->arg1 + xp->arg0;
12038745Sedward 				xq->arg0 += xp->arg0;
12138745Sedward 				xq->arg1 = xp->arg2;
12238745Sedward 				if (xq->arg0 > 0)
12338745Sedward 					xq->arg1 -= xq->arg0;
12438745Sedward 				goto top;
12538745Sedward 			} else {
12638745Sedward 				if (xp->arg1 - xq->arg0 >= xp->arg2)
12738745Sedward 					return;
12838745Sedward 				xq->arg2 = xp->arg1 - xq->arg0;
12938745Sedward 				xp->arg0 += xq->arg0;
13038745Sedward 				xp->arg1 = xq->arg2;
13138745Sedward 				if (xp->arg0 < 0)
13238745Sedward 					xp->arg1 += xp->arg0;
13338745Sedward 				goto top;
13438745Sedward 			}
13538745Sedward 		}
13638745Sedward 		if (xp->arg0 > xp->arg2 - xp->arg1)
13738745Sedward 			xp->arg0 = xp->arg2 - xp->arg1;
13838745Sedward 		if (tt.tt_scroll_down) {
13938745Sedward 			if (tt.tt_scroll_top != xp->arg1 ||
14038745Sedward 			    tt.tt_scroll_bot != xp->arg2 - 1) {
14138745Sedward 				if (tt.tt_setscroll == 0)
14238745Sedward 					goto down;
14338745Sedward 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
14438745Sedward 			}
14538745Sedward 			tt.tt_scroll_down(xp->arg0);
14638745Sedward 		} else {
14738745Sedward 		down:
14838745Sedward 			(*tt.tt_move)(xp->arg1, 0);
14938745Sedward 			(*tt.tt_delline)(xp->arg0);
15038745Sedward 			if (xp->arg2 < tt.tt_nrow) {
15138745Sedward 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
15238745Sedward 				(*tt.tt_insline)(xp->arg0);
15338745Sedward 			}
15438745Sedward 		}
15538745Sedward 	} else {
15638745Sedward 		xp->arg0 = - xp->arg0;
15738745Sedward 		if (xp->arg0 > xp->arg2 - xp->arg1)
15838745Sedward 			xp->arg0 = xp->arg2 - xp->arg1;
15938745Sedward 		if (tt.tt_scroll_up) {
16038745Sedward 			if (tt.tt_scroll_top != xp->arg1 ||
16138745Sedward 			    tt.tt_scroll_bot != xp->arg2 - 1) {
16238745Sedward 				if (tt.tt_setscroll == 0)
16338745Sedward 					goto up;
16438745Sedward 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
16538745Sedward 			}
16638745Sedward 			tt.tt_scroll_up(xp->arg0);
16738745Sedward 		} else  {
16838745Sedward 		up:
16938745Sedward 			if (tt.tt_retain || xp->arg2 != tt.tt_nrow) {
17038745Sedward 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
17138745Sedward 				(*tt.tt_delline)(xp->arg0);
17238745Sedward 			}
17338745Sedward 			(*tt.tt_move)(xp->arg1, 0);
17438745Sedward 			(*tt.tt_insline)(xp->arg0);
17538745Sedward 		}
17638745Sedward 	}
17738745Sedward }
178