Commit | Line | Data |
---|---|---|
577dff1e | 1 | #ifndef lint |
b0d4d9e2 | 2 | static char *sccsid = "@(#)wwscroll.c 3.4 83/08/18"; |
577dff1e EW |
3 | #endif |
4 | ||
5 | #include "ww.h" | |
e908bfac | 6 | #include "tt.h" |
577dff1e | 7 | |
b0d4d9e2 EW |
8 | wwscroll(w, n) |
9 | register struct ww *w; | |
10 | register n; | |
11 | { | |
12 | int dir; | |
13 | register scroll; | |
14 | ||
15 | if (n == 0) | |
16 | return; | |
17 | dir = n < 0 ? -1 : 1; | |
18 | scroll = w->ww_scroll + n; | |
19 | if (scroll < 0) | |
20 | scroll = 0; | |
21 | else if (scroll > w->ww_nline - w->ww_w.nr) | |
22 | scroll = w->ww_nline - w->ww_w.nr; | |
23 | n = abs(scroll - w->ww_scroll); | |
24 | if (n < w->ww_w.nr) { | |
25 | while (--n >= 0) { | |
26 | wwscroll1(w, 0, w->ww_w.nr - 1, dir, 0); | |
27 | w->ww_scroll += dir; | |
28 | } | |
29 | } else { | |
30 | w->ww_scroll = scroll; | |
31 | wwredrawwin(w); | |
32 | } | |
33 | } | |
34 | ||
577dff1e | 35 | /* |
b0d4d9e2 | 36 | * Scroll one line, between 'srow' and 'erow', in direction 'dir'. |
577dff1e | 37 | * Don't adjust ww_scroll. |
b0d4d9e2 | 38 | * And don't redraw 'leaveit' lines. |
577dff1e EW |
39 | */ |
40 | wwscroll1(w, srow, erow, dir, leaveit) | |
41 | register struct ww *w; | |
42 | int srow, erow, dir; | |
b0d4d9e2 | 43 | int leaveit; |
577dff1e EW |
44 | { |
45 | register i; | |
b0d4d9e2 | 46 | int srow1, erow1; |
577dff1e EW |
47 | int nvis; |
48 | int nvismax; | |
49 | int deleted = 0; | |
50 | ||
51 | /* | |
52 | * See how many lines on the screen are affected. | |
53 | * And calculate srow, erow, and left at the same time. | |
54 | */ | |
55 | for (i = srow; i <= erow && w->ww_nvis[i] == 0; i++) | |
56 | ; | |
b0d4d9e2 | 57 | if ((srow1 = i) > erow) { |
577dff1e | 58 | /* can't do any fancy stuff */ |
b0d4d9e2 | 59 | erow1 = srow1 - 1; |
577dff1e EW |
60 | goto out; |
61 | } | |
62 | for (i = erow; i >= srow && w->ww_nvis[i] == 0; i--) | |
63 | ; | |
b0d4d9e2 | 64 | if ((erow1 = i) == srow1) |
577dff1e EW |
65 | goto out; /* just one line is easy */ |
66 | ||
67 | /* | |
68 | * See how much of this window is visible. | |
69 | */ | |
b0d4d9e2 | 70 | nvismax = wwncol * (erow1 - srow1 + 1); |
577dff1e | 71 | nvis = 0; |
b0d4d9e2 | 72 | for (i = srow1; i <= erow1; i++) |
577dff1e EW |
73 | nvis += w->ww_nvis[i]; |
74 | ||
75 | /* | |
76 | * If it's a good idea to use delete and insert line | |
77 | * and the terminal can, then do it. | |
78 | */ | |
79 | if (nvis > nvismax / 2 && tt.tt_delline && tt.tt_insline) { | |
80 | register union ww_char *tmp; | |
81 | register union ww_char **cpp, **cqq; | |
82 | ||
83 | if (dir > 0) { | |
b0d4d9e2 | 84 | (*tt.tt_move)(srow1 + w->ww_w.t, 0); |
577dff1e | 85 | (*tt.tt_delline)(); |
b0d4d9e2 EW |
86 | if (erow1 + w->ww_w.t != wwnrow - 1) { |
87 | (*tt.tt_move)(erow1 + w->ww_w.t, 0); | |
577dff1e EW |
88 | (*tt.tt_insline)(); |
89 | } | |
90 | /* | |
91 | * Fix up the old screen. | |
92 | */ | |
b0d4d9e2 | 93 | cpp = &wwos[srow1 + w->ww_w.t]; |
577dff1e EW |
94 | cqq = cpp + 1; |
95 | tmp = *cpp; | |
b0d4d9e2 | 96 | for (i = erow1 - srow1; --i >= 0;) |
577dff1e EW |
97 | *cpp++ = *cqq++; |
98 | *cpp = tmp; | |
99 | for (i = wwncol; --i >= 0;) | |
100 | tmp++->c_w = ' '; | |
101 | } else { | |
b0d4d9e2 EW |
102 | if (erow1 + w->ww_w.t != wwnrow - 1) { |
103 | (*tt.tt_move)(erow1 + w->ww_w.t, 0); | |
577dff1e EW |
104 | (*tt.tt_delline)(); |
105 | } | |
b0d4d9e2 | 106 | (*tt.tt_move)(srow1 + w->ww_w.t, 0); |
577dff1e EW |
107 | (*tt.tt_insline)(); |
108 | /* | |
109 | * Fix up the old screen. | |
110 | */ | |
b0d4d9e2 | 111 | cqq = &wwos[erow1 + w->ww_w.t]; |
577dff1e EW |
112 | cpp = cqq + 1; |
113 | tmp = *cqq; | |
b0d4d9e2 | 114 | for (i = erow1 - srow1; --i >= 0;) |
577dff1e EW |
115 | *--cpp = *--cqq; |
116 | *cqq = tmp; | |
117 | for (i = wwncol; --i >= 0;) | |
118 | tmp++->c_w = ' '; | |
119 | } | |
120 | deleted++; | |
121 | } | |
122 | ||
123 | /* | |
124 | * Fix the new screen. | |
125 | */ | |
126 | if (nvis == nvismax) { | |
127 | /* | |
128 | * Can shift whole lines. | |
129 | */ | |
577dff1e | 130 | if (dir > 0) { |
861cd1ed EW |
131 | { |
132 | register union ww_char *tmp; | |
133 | register union ww_char **cpp, **cqq; | |
134 | ||
b0d4d9e2 | 135 | cpp = &wwns[srow1 + w->ww_w.t]; |
861cd1ed EW |
136 | cqq = cpp + 1; |
137 | tmp = *cpp; | |
b0d4d9e2 | 138 | for (i = erow1 - srow1; --i >= 0;) |
861cd1ed EW |
139 | *cpp++ = *cqq++; |
140 | *cpp = tmp; | |
141 | } | |
142 | { | |
143 | register char *p, *q; | |
144 | ||
b0d4d9e2 | 145 | p = &wwtouched[srow1 + w->ww_w.t]; |
861cd1ed | 146 | q = p + 1; |
b0d4d9e2 | 147 | for (i = erow1 - srow1; --i >= 0;) |
861cd1ed EW |
148 | *p++ = *q++; |
149 | *p = 1; | |
150 | } | |
b0d4d9e2 EW |
151 | wwredrawwin1(w, srow, srow1 - 1, w->ww_scroll + dir); |
152 | wwredrawwin1(w, erow1, erow - leaveit, | |
577dff1e EW |
153 | w->ww_scroll + dir); |
154 | } else { | |
861cd1ed EW |
155 | { |
156 | register union ww_char *tmp; | |
157 | register union ww_char **cpp, **cqq; | |
158 | ||
b0d4d9e2 | 159 | cqq = &wwns[erow1 + w->ww_w.t]; |
861cd1ed EW |
160 | cpp = cqq + 1; |
161 | tmp = *cqq; | |
b0d4d9e2 | 162 | for (i = erow1 - srow1; --i >= 0;) |
861cd1ed EW |
163 | *--cpp = *--cqq; |
164 | *cqq = tmp; | |
165 | } | |
166 | { | |
167 | register char *p, *q; | |
168 | ||
b0d4d9e2 | 169 | q = &wwtouched[erow1 + w->ww_w.t]; |
861cd1ed | 170 | p = q + 1; |
b0d4d9e2 | 171 | for (i = erow1 - srow1; --i >= 0;) |
861cd1ed EW |
172 | *--p = *--q; |
173 | *q = 1; | |
174 | } | |
b0d4d9e2 | 175 | wwredrawwin1(w, srow + leaveit, srow1, |
577dff1e | 176 | w->ww_scroll + dir); |
b0d4d9e2 | 177 | wwredrawwin1(w, erow1 + 1, erow, w->ww_scroll + dir); |
577dff1e EW |
178 | } |
179 | } else { | |
180 | out: | |
181 | if (dir > 0) | |
182 | wwredrawwin1(w, srow, erow - leaveit, | |
183 | w->ww_scroll + dir); | |
184 | else | |
185 | wwredrawwin1(w, srow + leaveit, erow, | |
186 | w->ww_scroll + dir); | |
187 | } | |
188 | return deleted; | |
189 | } |