Commit | Line | Data |
---|---|---|
577dff1e | 1 | #ifndef lint |
df7b254b | 2 | static char sccsid[] = "@(#)wwscroll.c 3.14 %G%"; |
577dff1e EW |
3 | #endif |
4 | ||
60de5df9 EW |
5 | /* |
6 | * Copyright (c) 1983 Regents of the University of California, | |
7 | * All rights reserved. Redistribution permitted subject to | |
8 | * the terms of the Berkeley Software License Agreement. | |
9 | */ | |
10 | ||
577dff1e | 11 | #include "ww.h" |
e908bfac | 12 | #include "tt.h" |
577dff1e | 13 | |
b0d4d9e2 EW |
14 | wwscroll(w, n) |
15 | register struct ww *w; | |
f2a77fe1 | 16 | int n; |
b0d4d9e2 | 17 | { |
f2a77fe1 EW |
18 | register dir; |
19 | register top; | |
b0d4d9e2 EW |
20 | |
21 | if (n == 0) | |
22 | return; | |
23 | dir = n < 0 ? -1 : 1; | |
f2a77fe1 EW |
24 | top = w->ww_b.t - n; |
25 | if (top > w->ww_w.t) | |
26 | top = w->ww_w.t; | |
27 | else if (top + w->ww_b.nr < w->ww_w.b) | |
28 | top = w->ww_w.b - w->ww_b.nr; | |
29 | n = abs(top - w->ww_b.t); | |
19f9784c | 30 | if (n < w->ww_i.nr) { |
b0d4d9e2 | 31 | while (--n >= 0) { |
f2a77fe1 EW |
32 | (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0); |
33 | w->ww_buf += dir; | |
34 | w->ww_b.t -= dir; | |
35 | w->ww_b.b -= dir; | |
b0d4d9e2 EW |
36 | } |
37 | } else { | |
f2a77fe1 EW |
38 | w->ww_buf -= top - w->ww_b.t; |
39 | w->ww_b.t = top; | |
40 | w->ww_b.b = top + w->ww_b.nr; | |
b0d4d9e2 EW |
41 | wwredrawwin(w); |
42 | } | |
43 | } | |
44 | ||
577dff1e | 45 | /* |
19f9784c | 46 | * Scroll one line, between 'row1' and 'row2', in direction 'dir'. |
577dff1e | 47 | * Don't adjust ww_scroll. |
b0d4d9e2 | 48 | * And don't redraw 'leaveit' lines. |
577dff1e | 49 | */ |
19f9784c | 50 | wwscroll1(w, row1, row2, dir, leaveit) |
577dff1e | 51 | register struct ww *w; |
19f9784c | 52 | int row1, row2, dir; |
b0d4d9e2 | 53 | int leaveit; |
577dff1e EW |
54 | { |
55 | register i; | |
19f9784c | 56 | int row1x, row2x; |
577dff1e EW |
57 | int nvis; |
58 | int nvismax; | |
59 | int deleted = 0; | |
60 | ||
61 | /* | |
62 | * See how many lines on the screen are affected. | |
19f9784c | 63 | * And calculate row1x, row2x, and left at the same time. |
577dff1e | 64 | */ |
19f9784c | 65 | for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++) |
577dff1e | 66 | ; |
19f9784c | 67 | if (i >= row2) /* can't do any fancy stuff */ |
577dff1e | 68 | goto out; |
19f9784c EW |
69 | row1x = i; |
70 | for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--) | |
577dff1e | 71 | ; |
19f9784c | 72 | if (i <= row1x) |
577dff1e | 73 | goto out; /* just one line is easy */ |
19f9784c | 74 | row2x = i + 1; |
577dff1e EW |
75 | |
76 | /* | |
77 | * See how much of this window is visible. | |
78 | */ | |
19f9784c | 79 | nvismax = wwncol * (row2x - row1x); |
577dff1e | 80 | nvis = 0; |
19f9784c | 81 | for (i = row1x; i < row2x; i++) |
577dff1e EW |
82 | nvis += w->ww_nvis[i]; |
83 | ||
84 | /* | |
85 | * If it's a good idea to use delete and insert line | |
86 | * and the terminal can, then do it. | |
87 | */ | |
88 | if (nvis > nvismax / 2 && tt.tt_delline && tt.tt_insline) { | |
89 | register union ww_char *tmp; | |
90 | register union ww_char **cpp, **cqq; | |
91 | ||
f925dc2b | 92 | /* |
df7b254b EW |
93 | * Don't worry about retain when scrolling down, |
94 | * but do worry when scrolling up, for hp2621. | |
f925dc2b | 95 | */ |
577dff1e | 96 | if (dir > 0) { |
df7b254b EW |
97 | /* |
98 | * We're going to assume that a line feed at the | |
99 | * bottom of the screen will cause a scroll, unless | |
100 | * "ns" is set. This should work at least 99% | |
101 | * of the time. At any rate, vi seems to do it. | |
102 | */ | |
103 | if (tt.tt_noscroll || row1x != 0 || row2x != wwnrow) { | |
104 | (*tt.tt_move)(row1x, 0); | |
105 | (*tt.tt_delline)(); | |
106 | if (row2x < wwnrow) { | |
107 | (*tt.tt_move)(row2x - 1, 0); | |
108 | (*tt.tt_insline)(); | |
109 | } | |
110 | } else { | |
111 | if (tt.tt_row != wwnrow - 1) | |
112 | (*tt.tt_move)(wwnrow - 1, 0); | |
113 | ttputc('\n'); | |
577dff1e EW |
114 | } |
115 | /* | |
116 | * Fix up the old screen. | |
117 | */ | |
f2a77fe1 | 118 | cpp = &wwos[row1x]; |
577dff1e EW |
119 | cqq = cpp + 1; |
120 | tmp = *cpp; | |
19f9784c | 121 | for (i = row2x - row1x; --i > 0;) |
577dff1e EW |
122 | *cpp++ = *cqq++; |
123 | *cpp = tmp; | |
577dff1e | 124 | } else { |
f2a77fe1 EW |
125 | if (tt.tt_retain || row2x != wwnrow) { |
126 | (*tt.tt_move)(row2x - 1, 0); | |
577dff1e EW |
127 | (*tt.tt_delline)(); |
128 | } | |
f2a77fe1 | 129 | (*tt.tt_move)(row1x, 0); |
577dff1e EW |
130 | (*tt.tt_insline)(); |
131 | /* | |
132 | * Fix up the old screen. | |
133 | */ | |
f2a77fe1 | 134 | cpp = &wwos[row2x]; |
19f9784c | 135 | cqq = cpp - 1; |
577dff1e | 136 | tmp = *cqq; |
19f9784c | 137 | for (i = row2x - row1x; --i > 0;) |
577dff1e EW |
138 | *--cpp = *--cqq; |
139 | *cqq = tmp; | |
577dff1e | 140 | } |
f2a77fe1 EW |
141 | for (i = wwncol; --i >= 0;) |
142 | tmp++->c_w = ' '; | |
577dff1e EW |
143 | deleted++; |
144 | } | |
145 | ||
146 | /* | |
147 | * Fix the new screen. | |
148 | */ | |
149 | if (nvis == nvismax) { | |
150 | /* | |
151 | * Can shift whole lines. | |
152 | */ | |
577dff1e | 153 | if (dir > 0) { |
861cd1ed EW |
154 | { |
155 | register union ww_char *tmp; | |
156 | register union ww_char **cpp, **cqq; | |
157 | ||
f2a77fe1 | 158 | cpp = &wwns[row1x]; |
861cd1ed EW |
159 | cqq = cpp + 1; |
160 | tmp = *cpp; | |
19f9784c | 161 | for (i = row2x - row1x; --i > 0;) |
861cd1ed EW |
162 | *cpp++ = *cqq++; |
163 | *cpp = tmp; | |
164 | } | |
26008571 | 165 | if (deleted) { |
861cd1ed EW |
166 | register char *p, *q; |
167 | ||
f2a77fe1 | 168 | p = &wwtouched[row1x]; |
861cd1ed | 169 | q = p + 1; |
19f9784c | 170 | for (i = row2x - row1x; --i > 0;) |
861cd1ed | 171 | *p++ = *q++; |
04d70db4 | 172 | *p |= WWU_TOUCHED; |
26008571 EW |
173 | } else { |
174 | register char *p; | |
175 | ||
f2a77fe1 | 176 | p = &wwtouched[row1x]; |
19f9784c | 177 | for (i = row2x - row1x; --i >= 0;) |
04d70db4 | 178 | *p++ |= WWU_MAJOR|WWU_TOUCHED; |
861cd1ed | 179 | } |
f2a77fe1 EW |
180 | wwredrawwin1(w, row1, row1x, dir); |
181 | wwredrawwin1(w, row2x - 1, row2 - leaveit, dir); | |
577dff1e | 182 | } else { |
861cd1ed EW |
183 | { |
184 | register union ww_char *tmp; | |
185 | register union ww_char **cpp, **cqq; | |
186 | ||
f2a77fe1 | 187 | cpp = &wwns[row2x]; |
19f9784c | 188 | cqq = cpp - 1; |
861cd1ed | 189 | tmp = *cqq; |
19f9784c | 190 | for (i = row2x - row1x; --i > 0;) |
861cd1ed EW |
191 | *--cpp = *--cqq; |
192 | *cqq = tmp; | |
193 | } | |
26008571 | 194 | if (deleted) { |
861cd1ed EW |
195 | register char *p, *q; |
196 | ||
f2a77fe1 | 197 | p = &wwtouched[row2x]; |
19f9784c EW |
198 | q = p - 1; |
199 | for (i = row2x - row1x; --i > 0;) | |
861cd1ed | 200 | *--p = *--q; |
04d70db4 | 201 | *q |= WWU_MAJOR|WWU_TOUCHED; |
26008571 EW |
202 | } else { |
203 | register char *p; | |
204 | ||
f2a77fe1 | 205 | p = &wwtouched[row1x]; |
19f9784c | 206 | for (i = row2x - row1x; --i >= 0;) |
04d70db4 | 207 | *p++ |= WWU_TOUCHED; |
861cd1ed | 208 | } |
f2a77fe1 EW |
209 | wwredrawwin1(w, row1 + leaveit, row1x + 1, dir); |
210 | wwredrawwin1(w, row2x, row2, dir); | |
577dff1e EW |
211 | } |
212 | } else { | |
213 | out: | |
214 | if (dir > 0) | |
f2a77fe1 | 215 | wwredrawwin1(w, row1, row2 - leaveit, dir); |
577dff1e | 216 | else |
f2a77fe1 | 217 | wwredrawwin1(w, row1 + leaveit, row2, dir); |
577dff1e EW |
218 | } |
219 | return deleted; | |
220 | } |