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
xxflush(intr)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
xxflush_scroll(xp)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