xref: /dflybsd-src/usr.bin/window/xxflush.c (revision c6cf4f8f1ebc9e3fe2a8c566f08adfc86122c7bf)
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)xxflush.c	8.1 (Berkeley) 6/6/93
37  * $FreeBSD: src/usr.bin/window/xxflush.c,v 1.1.1.1.14.1 2001/05/17 09:45:02 obrien Exp $
38  * $DragonFly: src/usr.bin/window/xxflush.c,v 1.2 2003/06/17 04:29:34 dillon Exp $
39  */
40 
41 #include "ww.h"
42 #include "xx.h"
43 #include "tt.h"
44 
45 xxflush(intr)
46 	register intr;
47 {
48 	register struct xx *xp, *xq;
49 
50 	for (xp = xx_head; xp != 0 && !(intr && wwinterrupt()); xp = xq) {
51 		switch (xp->cmd) {
52 		case xc_move:
53 			if (xp->link == 0)
54 				(*tt.tt_move)(xp->arg0, xp->arg1);
55 			break;
56 		case xc_scroll:
57 			xxflush_scroll(xp);
58 			break;
59 		case xc_inschar:
60 			(*tt.tt_move)(xp->arg0, xp->arg1);
61 			tt.tt_nmodes = xp->arg3;
62 			(*tt.tt_inschar)(xp->arg2);
63 			break;
64 		case xc_insspace:
65 			(*tt.tt_move)(xp->arg0, xp->arg1);
66 			(*tt.tt_insspace)(xp->arg2);
67 			break;
68 		case xc_delchar:
69 			(*tt.tt_move)(xp->arg0, xp->arg1);
70 			(*tt.tt_delchar)(xp->arg2);
71 			break;
72 		case xc_clear:
73 			(*tt.tt_clear)();
74 			break;
75 		case xc_clreos:
76 			(*tt.tt_move)(xp->arg0, xp->arg1);
77 			(*tt.tt_clreos)();
78 			break;
79 		case xc_clreol:
80 			(*tt.tt_move)(xp->arg0, xp->arg1);
81 			(*tt.tt_clreol)();
82 			break;
83 		case xc_write:
84 			(*tt.tt_move)(xp->arg0, xp->arg1);
85 			tt.tt_nmodes = xp->arg3;
86 			(*tt.tt_write)(xp->buf, xp->arg2);
87 			break;
88 		}
89 		xq = xp->link;
90 		xxfree(xp);
91 	}
92 	if ((xx_head = xp) == 0) {
93 		xx_tail = 0;
94 		xxbufp = xxbuf;
95 	}
96 	ttflush();
97 }
98 
99 xxflush_scroll(xp)
100 	register struct xx *xp;
101 {
102 	register struct xx *xq;
103 
104  top:
105 	if (xp->arg0 == 0)
106 		return;
107 	/*
108 	 * We handle retain (da and db) by putting the burden on scrolling up,
109 	 * which is the less common operation.  It must ensure that
110 	 * text is not pushed below the screen, so scrolling down doesn't
111 	 * have to worry about it.
112 	 *
113 	 * Try scrolling region (or scrolling the whole screen) first.
114 	 * Can we assume "sr" doesn't push text below the screen
115 	 * so we don't have to worry about retain below?
116 	 * What about scrolling down with a newline?  It probably does
117 	 * push text above (with da).  Scrolling up would then have
118 	 * to take care of that.
119 	 * It's easy to be fool proof, but that slows things down.
120 	 * The current solution is to disallow tt_scroll_up if da or db is true
121 	 * but cs (scrolling region) is not.  Again, we sacrifice scrolling
122 	 * up in favor of scrolling down.  The idea is having scrolling regions
123 	 * probably means we can scroll (even the whole screen) with impunity.
124 	 * This lets us work efficiently on simple terminals (use newline
125 	 * on the bottom to scroll), on any terminal without retain, and
126 	 * on vt100 style scrolling regions (I think).
127 	 */
128 	if (xp->arg0 > 0) {
129 		if ((xq = xp->link) != 0 && xq->cmd == xc_scroll &&
130 		    xp->arg2 == xq->arg2 && xq->arg0 < 0) {
131 			if (xp->arg1 < xq->arg1) {
132 				if (xp->arg2 - xp->arg0 <= xq->arg1) {
133 					xq->arg0 = xp->arg0;
134 					xq->arg1 = xp->arg1;
135 					xq->arg2 = xp->arg2;
136 					return;
137 				}
138 				xp->arg2 = xq->arg1 + xp->arg0;
139 				xq->arg0 += xp->arg0;
140 				xq->arg1 = xp->arg2;
141 				if (xq->arg0 > 0)
142 					xq->arg1 -= xq->arg0;
143 				goto top;
144 			} else {
145 				if (xp->arg1 - xq->arg0 >= xp->arg2)
146 					return;
147 				xq->arg2 = xp->arg1 - xq->arg0;
148 				xp->arg0 += xq->arg0;
149 				xp->arg1 = xq->arg2;
150 				if (xp->arg0 < 0)
151 					xp->arg1 += xp->arg0;
152 				goto top;
153 			}
154 		}
155 		if (xp->arg0 > xp->arg2 - xp->arg1)
156 			xp->arg0 = xp->arg2 - xp->arg1;
157 		if (tt.tt_scroll_down) {
158 			if (tt.tt_scroll_top != xp->arg1 ||
159 			    tt.tt_scroll_bot != xp->arg2 - 1) {
160 				if (tt.tt_setscroll == 0)
161 					goto down;
162 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
163 			}
164 			tt.tt_scroll_down(xp->arg0);
165 		} else {
166 		down:
167 			(*tt.tt_move)(xp->arg1, 0);
168 			(*tt.tt_delline)(xp->arg0);
169 			if (xp->arg2 < tt.tt_nrow) {
170 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
171 				(*tt.tt_insline)(xp->arg0);
172 			}
173 		}
174 	} else {
175 		xp->arg0 = - xp->arg0;
176 		if (xp->arg0 > xp->arg2 - xp->arg1)
177 			xp->arg0 = xp->arg2 - xp->arg1;
178 		if (tt.tt_scroll_up) {
179 			if (tt.tt_scroll_top != xp->arg1 ||
180 			    tt.tt_scroll_bot != xp->arg2 - 1) {
181 				if (tt.tt_setscroll == 0)
182 					goto up;
183 				(*tt.tt_setscroll)(xp->arg1, xp->arg2 - 1);
184 			}
185 			tt.tt_scroll_up(xp->arg0);
186 		} else  {
187 		up:
188 			if (tt.tt_retain || xp->arg2 != tt.tt_nrow) {
189 				(*tt.tt_move)(xp->arg2 - xp->arg0, 0);
190 				(*tt.tt_delline)(xp->arg0);
191 			}
192 			(*tt.tt_move)(xp->arg1, 0);
193 			(*tt.tt_insline)(xp->arg0);
194 		}
195 	}
196 }
197