fix ticket file ownership (look at this again later)
[unix-history] / usr / src / usr.bin / window / xxflush.c
CommitLineData
1cb6db79
EW
1/*
2 * Copyright (c) 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#ifndef lint
19static char sccsid[] = "@(#)xxflush.c 3.1 (Berkeley) %G%";
20#endif /* not lint */
21
22#include "ww.h"
23#include "xx.h"
24#include "tt.h"
25
26xxflush(intr)
27 register intr;
28{
29 register struct xx *xp, *xq;
30
31 for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) {
32 switch (xp->cmd) {
33 case xc_move:
34 if (xp->link == 0)
35 (*tt.tt_move)(xp->arg0, xp->arg1);
36 break;
37 case xc_scroll:
38 xxflush_scroll(xp);
39 break;
40 case xc_inschar:
41 if (xp->arg1 + xp->arg2 >= tt.tt_ncol)
42 break;
43 (*tt.tt_move)(xp->arg0, xp->arg1);
44 if (tt.tt_setinsert) {
45 tt.tt_nmodes = xp->arg3;
46 tt.tt_ninsert = 1;
47 (*tt.tt_write)(xp->buf, xp->arg2);
48 tt.tt_ninsert = 0;
49 } else
50 (*tt.tt_inschar)(xp->arg2);
51 break;
52 case xc_delchar:
53 if (xp->arg1 + xp->arg2 >= tt.tt_ncol)
54 break;
55 (*tt.tt_move)(xp->arg0, xp->arg1);
56 (*tt.tt_delchar)(xp->arg2);
57 break;
58 case xc_clear:
59 (*tt.tt_clear)();
60 break;
61 case xc_clreos:
62 (*tt.tt_move)(xp->arg0, xp->arg1);
63 (*tt.tt_clreos)();
64 break;
65 case xc_clreol:
66 (*tt.tt_move)(xp->arg0, xp->arg1);
67 (*tt.tt_clreol)();
68 break;
69 case xc_write:
70 (*tt.tt_move)(xp->arg0, xp->arg1);
71 tt.tt_nmodes = xp->arg3;
72 if (tt.tt_ntoken > 0)
73 xcwrite(xp->buf, xp->arg2, xp->buf - xxbuf);
74 else
75 (*tt.tt_write)(xp->buf, xp->arg2);
76 break;
77 }
78 xq = xp->link;
79 xxfree(xp);
80 }
81 if ((xx_head = xp) == 0) {
82 xx_tail = 0;
83 xxbufp = xxbuf;
84 if (tt.tt_ntoken > 0)
85 xcreset();
86 }
87 ttflush();
88}
89
90xxflush_scroll(xp)
91 register struct xx *xp;
92{
93 register struct xx *xq;
94
95 top:
96 if (xp->arg0 == 0)
97 return;
98 /*
99 * We handle retain (da and db) by putting the burden on scrolling up,
100 * which is the less common operation. It must ensure that
101 * text is not pushed below the screen, so scrolling down doesn't
102 * have to worry about it.
103 *
104 * Try scrolling region (or scrolling the whole screen) first.
105 * Can we assume "sr" doesn't push text below the screen
106 * so we don't have to worry about retain below?
107 * What about scrolling down with a newline? It probably does
108 * push text above (with da). Scrolling up would then have
109 * to take care of that.
110 * It's easy to be fool proof, but that slows things down.
111 * The current solution is to disallow tt_scroll_up if da or db is true
112 * but cs (scrolling region) is not. Again, we sacrifice scrolling
113 * up in favor of scrolling down. The idea is having scrolling regions
114 * probably means we can scroll (even the whole screen) with impunity.
115 * This lets us work efficiently on simple terminals (use newline
116 * on the bottom to scroll), on any terminal without retain, and
117 * on vt100 style scrolling regions (I think).
118 */
119 if (xp->arg0 > 0) {
120 if ((xq = xp->link) != 0 && xq->cmd == xc_scroll &&
121 xp->arg2 == xq->arg2 && xq->arg0 < 0) {
122 if (xp->arg1 < xq->arg1) {
123 if (xp->arg2 - xp->arg0 <= xq->arg1) {
124 xq->arg0 = xp->arg0;
125 xq->arg1 = xp->arg1;
126 xq->arg2 = xp->arg2;
127 return;
128 }
129 xp->arg2 = xq->arg1 + xp->arg0;
130 xq->arg0 += xp->arg0;
131 xq->arg1 = xp->arg2;
132 if (xq->arg0 > 0)
133 xq->arg1 -= xq->arg0;
134 goto top;
135 } else {
136 if (xp->arg1 - xq->arg0 >= xp->arg2)
137 return;
138 xq->arg2 = xp->arg1 - xq->arg0;
139 xp->arg0 += xq->arg0;
140 xp->arg1 = xq->arg2;
141 if (xp->arg0 < 0)
142 xp->arg1 += xp->arg0;
143 goto top;
144 }
145 }
146 if (xp->arg0 > xp->arg2 - xp->arg1)
147 xp->arg0 = xp->arg2 - xp->arg1;
148 if (tt.tt_scroll_down) {
149 if (tt.tt_scroll_top != xp->arg1 ||
150 tt.tt_scroll_bot != xp->arg2 - 1) {
151 if (tt.tt_setscroll == 0)
152 goto down;
153 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
154 }
155 tt.tt_scroll_down(xp->arg0);
156 } else {
157 down:
158 (*tt.tt_move)(xp->arg1, 0);
159 (*tt.tt_delline)(xp->arg0);
160 if (xp->arg2 < tt.tt_nrow) {
161 (*tt.tt_move)(xp->arg2 - xp->arg0, 0);
162 (*tt.tt_insline)(xp->arg0);
163 }
164 }
165 } else {
166 xp->arg0 = - xp->arg0;
167 if (xp->arg0 > xp->arg2 - xp->arg1)
168 xp->arg0 = xp->arg2 - xp->arg1;
169 if (tt.tt_scroll_up) {
170 if (tt.tt_scroll_top != xp->arg1 ||
171 tt.tt_scroll_bot != xp->arg2 - 1) {
172 if (tt.tt_setscroll == 0)
173 goto up;
174 (*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
175 }
176 tt.tt_scroll_up(xp->arg0);
177 } else {
178 up:
179 if (tt.tt_retain || xp->arg2 != tt.tt_nrow) {
180 (*tt.tt_move)(xp->arg2 - xp->arg0, 0);
181 (*tt.tt_delline)(xp->arg0);
182 }
183 (*tt.tt_move)(xp->arg1, 0);
184 (*tt.tt_insline)(xp->arg0);
185 }
186 }
187}