xref: /original-bsd/usr.bin/window/xxflush.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Edward Wang at The University of California, Berkeley.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)xxflush.c	8.1 (Berkeley) 06/06/93";
13 #endif /* not lint */
14 
15 #include "ww.h"
16 #include "xx.h"
17 #include "tt.h"
18 
19 xxflush(intr)
20 	register intr;
21 {
22 	register struct xx *xp, *xq;
23 
24 	for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) {
25 		switch (xp->cmd) {
26 		case xc_move:
27 			if (xp->link == 0)
28 				(*tt.tt_move)(xp->arg0, xp->arg1);
29 			break;
30 		case xc_scroll:
31 			xxflush_scroll(xp);
32 			break;
33 		case xc_inschar:
34 			(*tt.tt_move)(xp->arg0, xp->arg1);
35 			tt.tt_nmodes = xp->arg3;
36 			(*tt.tt_inschar)(xp->arg2);
37 			break;
38 		case xc_insspace:
39 			(*tt.tt_move)(xp->arg0, xp->arg1);
40 			(*tt.tt_insspace)(xp->arg2);
41 			break;
42 		case xc_delchar:
43 			(*tt.tt_move)(xp->arg0, xp->arg1);
44 			(*tt.tt_delchar)(xp->arg2);
45 			break;
46 		case xc_clear:
47 			(*tt.tt_clear)();
48 			break;
49 		case xc_clreos:
50 			(*tt.tt_move)(xp->arg0, xp->arg1);
51 			(*tt.tt_clreos)();
52 			break;
53 		case xc_clreol:
54 			(*tt.tt_move)(xp->arg0, xp->arg1);
55 			(*tt.tt_clreol)();
56 			break;
57 		case xc_write:
58 			(*tt.tt_move)(xp->arg0, xp->arg1);
59 			tt.tt_nmodes = xp->arg3;
60 			(*tt.tt_write)(xp->buf, xp->arg2);
61 			break;
62 		}
63 		xq = xp->link;
64 		xxfree(xp);
65 	}
66 	if ((xx_head = xp) == 0) {
67 		xx_tail = 0;
68 		xxbufp = xxbuf;
69 	}
70 	ttflush();
71 }
72 
73 xxflush_scroll(xp)
74 	register struct xx *xp;
75 {
76 	register struct xx *xq;
77 
78  top:
79 	if (xp->arg0 == 0)
80 		return;
81 	/*
82 	 * We handle retain (da and db) by putting the burden on scrolling up,
83 	 * which is the less common operation.  It must ensure that
84 	 * text is not pushed below the screen, so scrolling down doesn't
85 	 * have to worry about it.
86 	 *
87 	 * Try scrolling region (or scrolling the whole screen) first.
88 	 * Can we assume "sr" doesn't push text below the screen
89 	 * so we don't have to worry about retain below?
90 	 * What about scrolling down with a newline?  It probably does
91 	 * push text above (with da).  Scrolling up would then have
92 	 * to take care of that.
93 	 * It's easy to be fool proof, but that slows things down.
94 	 * The current solution is to disallow tt_scroll_up if da or db is true
95 	 * but cs (scrolling region) is not.  Again, we sacrifice scrolling
96 	 * up in favor of scrolling down.  The idea is having scrolling regions
97 	 * probably means we can scroll (even the whole screen) with impunity.
98 	 * This lets us work efficiently on simple terminals (use newline
99 	 * on the bottom to scroll), on any terminal without retain, and
100 	 * on vt100 style scrolling regions (I think).
101 	 */
102 	if (xp->arg0 > 0) {
103 		if ((xq = xp->link) != 0 && xq->cmd == xc_scroll &&
104 		    xp->arg2 == xq->arg2 && xq->arg0 < 0) {
105 			if (xp->arg1 < xq->arg1) {
106 				if (xp->arg2 - xp->arg0 <= xq->arg1) {
107 					xq->arg0 = xp->arg0;
108 					xq->arg1 = xp->arg1;
109 					xq->arg2 = xp->arg2;
110 					return;
111 				}
112 				xp->arg2 = xq->arg1 + xp->arg0;
113 				xq->arg0 += xp->arg0;
114 				xq->arg1 = xp->arg2;
115 				if (xq->arg0 > 0)
116 					xq->arg1 -= xq->arg0;
117 				goto top;
118 			} else {
119 				if (xp->arg1 - xq->arg0 >= xp->arg2)
120 					return;
121 				xq->arg2 = xp->arg1 - xq->arg0;
122 				xp->arg0 += xq->arg0;
123 				xp->arg1 = xq->arg2;
124 				if (xp->arg0 < 0)
125 					xp->arg1 += xp->arg0;
126 				goto top;
127 			}
128 		}
129 		if (xp->arg0 > xp->arg2 - xp->arg1)
130 			xp->arg0 = xp->arg2 - xp->arg1;
131 		if (tt.tt_scroll_down) {
132 			if (tt.tt_scroll_top != xp->arg1 ||
133 			    tt.tt_scroll_bot != xp->arg2 - 1) {
134 				if (tt.tt_setscroll == 0)
135 					goto down;
136 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
137 			}
138 			tt.tt_scroll_down(xp->arg0);
139 		} else {
140 		down:
141 			(*tt.tt_move)(xp->arg1, 0);
142 			(*tt.tt_delline)(xp->arg0);
143 			if (xp->arg2 < tt.tt_nrow) {
144 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
145 				(*tt.tt_insline)(xp->arg0);
146 			}
147 		}
148 	} else {
149 		xp->arg0 = - xp->arg0;
150 		if (xp->arg0 > xp->arg2 - xp->arg1)
151 			xp->arg0 = xp->arg2 - xp->arg1;
152 		if (tt.tt_scroll_up) {
153 			if (tt.tt_scroll_top != xp->arg1 ||
154 			    tt.tt_scroll_bot != xp->arg2 - 1) {
155 				if (tt.tt_setscroll == 0)
156 					goto up;
157 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
158 			}
159 			tt.tt_scroll_up(xp->arg0);
160 		} else  {
161 		up:
162 			if (tt.tt_retain || xp->arg2 != tt.tt_nrow) {
163 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
164 				(*tt.tt_delline)(xp->arg0);
165 			}
166 			(*tt.tt_move)(xp->arg1, 0);
167 			(*tt.tt_insline)(xp->arg0);
168 		}
169 	}
170 }
171