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