]> git.saurik.com Git - apple/shell_cmds.git/blob - window/wwscroll.c
shell_cmds-34.tar.gz
[apple/shell_cmds.git] / window / wwscroll.c
1 /* $NetBSD: wwscroll.c,v 1.4 1997/11/21 08:37:48 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1983, 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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)wwscroll.c 8.1 (Berkeley) 6/6/93";
43 #else
44 __RCSID("$NetBSD: wwscroll.c,v 1.4 1997/11/21 08:37:48 lukem Exp $");
45 #endif
46 #endif /* not lint */
47
48 #include "ww.h"
49 #include "tt.h"
50 #include "xx.h"
51
52 void
53 wwscroll(w, n)
54 struct ww *w;
55 int n;
56 {
57 int dir;
58 int top;
59
60 if (n == 0)
61 return;
62 dir = n < 0 ? -1 : 1;
63 top = w->ww_b.t - n;
64 if (top > w->ww_w.t)
65 top = w->ww_w.t;
66 else if (top + w->ww_b.nr < w->ww_w.b)
67 top = w->ww_w.b - w->ww_b.nr;
68 n = abs(top - w->ww_b.t);
69 if (n < w->ww_i.nr) {
70 while (--n >= 0) {
71 (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0);
72 w->ww_buf += dir;
73 w->ww_b.t -= dir;
74 w->ww_b.b -= dir;
75 }
76 } else {
77 w->ww_buf -= top - w->ww_b.t;
78 w->ww_b.t = top;
79 w->ww_b.b = top + w->ww_b.nr;
80 wwredrawwin(w);
81 }
82 }
83
84 /*
85 * Scroll one line, between 'row1' and 'row2', in direction 'dir'.
86 * Don't adjust ww_scroll.
87 * And don't redraw 'leaveit' lines.
88 */
89 int
90 wwscroll1(w, row1, row2, dir, leaveit)
91 struct ww *w;
92 int row1, row2, dir;
93 int leaveit;
94 {
95 int i;
96 int row1x, row2x;
97 int nvis;
98 int nvismax;
99 int scrolled = 0;
100
101 /*
102 * See how many lines on the screen are affected.
103 * And calculate row1x, row2x, and left at the same time.
104 */
105 for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++)
106 ;
107 if (i >= row2) /* can't do any fancy stuff */
108 goto out;
109 row1x = i;
110 for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--)
111 ;
112 if (i <= row1x)
113 goto out; /* just one line is easy */
114 row2x = i + 1;
115
116 /*
117 * See how much of this window is visible.
118 */
119 nvismax = wwncol * (row2x - row1x);
120 nvis = 0;
121 for (i = row1x; i < row2x; i++)
122 nvis += w->ww_nvis[i];
123
124 /*
125 * If it's a good idea to scroll and the terminal can, then do it.
126 */
127 if (nvis < nvismax / 2)
128 goto no_scroll; /* not worth it */
129 if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) ||
130 ((tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) &&
131 tt.tt_setscroll == 0))
132 if (tt.tt_delline == 0 || tt.tt_insline == 0)
133 goto no_scroll;
134 xxscroll(dir, row1x, row2x);
135 scrolled = 1;
136 /*
137 * Fix up the old screen.
138 */
139 {
140 union ww_char *tmp;
141 union ww_char **cpp, **cqq;
142
143 if (dir > 0) {
144 cpp = &wwos[row1x];
145 cqq = cpp + 1;
146 tmp = *cpp;
147 for (i = row2x - row1x; --i > 0;)
148 *cpp++ = *cqq++;
149 *cpp = tmp;
150 } else {
151 cpp = &wwos[row2x];
152 cqq = cpp - 1;
153 tmp = *cqq;
154 for (i = row2x - row1x; --i > 0;)
155 *--cpp = *--cqq;
156 *cqq = tmp;
157 }
158 for (i = wwncol; --i >= 0;)
159 tmp++->c_w = ' ';
160 }
161
162 no_scroll:
163 /*
164 * Fix the new screen.
165 */
166 if (nvis == nvismax) {
167 /*
168 * Can shift whole lines.
169 */
170 if (dir > 0) {
171 {
172 union ww_char *tmp;
173 union ww_char **cpp, **cqq;
174
175 cpp = &wwns[row1x];
176 cqq = cpp + 1;
177 tmp = *cpp;
178 for (i = row2x - row1x; --i > 0;)
179 *cpp++ = *cqq++;
180 *cpp = tmp;
181 }
182 if (scrolled) {
183 char *p, *q;
184
185 p = &wwtouched[row1x];
186 q = p + 1;
187 for (i = row2x - row1x; --i > 0;)
188 *p++ = *q++;
189 *p |= WWU_TOUCHED;
190 } else {
191 char *p;
192
193 p = &wwtouched[row1x];
194 for (i = row2x - row1x; --i >= 0;)
195 *p++ |= WWU_TOUCHED;
196 }
197 wwredrawwin1(w, row1, row1x, dir);
198 wwredrawwin1(w, row2x - 1, row2 - leaveit, dir);
199 } else {
200 {
201 union ww_char *tmp;
202 union ww_char **cpp, **cqq;
203
204 cpp = &wwns[row2x];
205 cqq = cpp - 1;
206 tmp = *cqq;
207 for (i = row2x - row1x; --i > 0;)
208 *--cpp = *--cqq;
209 *cqq = tmp;
210 }
211 if (scrolled) {
212 char *p, *q;
213
214 p = &wwtouched[row2x];
215 q = p - 1;
216 for (i = row2x - row1x; --i > 0;)
217 *--p = *--q;
218 *q |= WWU_TOUCHED;
219 } else {
220 char *p;
221
222 p = &wwtouched[row1x];
223 for (i = row2x - row1x; --i >= 0;)
224 *p++ |= WWU_TOUCHED;
225 }
226 wwredrawwin1(w, row1 + leaveit, row1x + 1, dir);
227 wwredrawwin1(w, row2x, row2, dir);
228 }
229 } else {
230 if (scrolled) {
231 char *p;
232
233 p = &wwtouched[row1x];
234 for (i = row2x - row1x; --i >= 0;)
235 *p++ |= WWU_TOUCHED;
236 }
237 out:
238 if (dir > 0)
239 wwredrawwin1(w, row1, row2 - leaveit, dir);
240 else
241 wwredrawwin1(w, row1 + leaveit, row2, dir);
242 }
243 return scrolled;
244 }