removed support for -r, -h, and rmail
[unix-history] / usr / src / usr.bin / window / wwscroll.c
CommitLineData
60de5df9 1/*
46e9ea25
KB
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
60de5df9
EW
11 */
12
46e9ea25 13#ifndef lint
16ea9636 14static char sccsid[] = "@(#)wwscroll.c 3.19 (Berkeley) %G%";
46e9ea25
KB
15#endif /* not lint */
16
577dff1e 17#include "ww.h"
e908bfac 18#include "tt.h"
577dff1e 19
b0d4d9e2
EW
20wwscroll(w, n)
21register struct ww *w;
f2a77fe1 22int n;
b0d4d9e2 23{
f2a77fe1
EW
24 register dir;
25 register top;
b0d4d9e2
EW
26
27 if (n == 0)
28 return;
29 dir = n < 0 ? -1 : 1;
f2a77fe1
EW
30 top = w->ww_b.t - n;
31 if (top > w->ww_w.t)
32 top = w->ww_w.t;
33 else if (top + w->ww_b.nr < w->ww_w.b)
34 top = w->ww_w.b - w->ww_b.nr;
35 n = abs(top - w->ww_b.t);
19f9784c 36 if (n < w->ww_i.nr) {
b0d4d9e2 37 while (--n >= 0) {
f2a77fe1
EW
38 (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0);
39 w->ww_buf += dir;
40 w->ww_b.t -= dir;
41 w->ww_b.b -= dir;
b0d4d9e2
EW
42 }
43 } else {
f2a77fe1
EW
44 w->ww_buf -= top - w->ww_b.t;
45 w->ww_b.t = top;
46 w->ww_b.b = top + w->ww_b.nr;
b0d4d9e2
EW
47 wwredrawwin(w);
48 }
49}
50
577dff1e 51/*
19f9784c 52 * Scroll one line, between 'row1' and 'row2', in direction 'dir'.
577dff1e 53 * Don't adjust ww_scroll.
b0d4d9e2 54 * And don't redraw 'leaveit' lines.
577dff1e 55 */
19f9784c 56wwscroll1(w, row1, row2, dir, leaveit)
577dff1e 57register struct ww *w;
19f9784c 58int row1, row2, dir;
b0d4d9e2 59int leaveit;
577dff1e
EW
60{
61 register i;
19f9784c 62 int row1x, row2x;
577dff1e
EW
63 int nvis;
64 int nvismax;
16ea9636
EW
65 int scrolled = 0;
66 int (*scroll_func)();
577dff1e
EW
67
68 /*
69 * See how many lines on the screen are affected.
19f9784c 70 * And calculate row1x, row2x, and left at the same time.
577dff1e 71 */
19f9784c 72 for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++)
577dff1e 73 ;
19f9784c 74 if (i >= row2) /* can't do any fancy stuff */
577dff1e 75 goto out;
19f9784c
EW
76 row1x = i;
77 for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--)
577dff1e 78 ;
19f9784c 79 if (i <= row1x)
577dff1e 80 goto out; /* just one line is easy */
19f9784c 81 row2x = i + 1;
577dff1e
EW
82
83 /*
84 * See how much of this window is visible.
85 */
19f9784c 86 nvismax = wwncol * (row2x - row1x);
577dff1e 87 nvis = 0;
19f9784c 88 for (i = row1x; i < row2x; i++)
577dff1e
EW
89 nvis += w->ww_nvis[i];
90
91 /*
05fb5c3b 92 * If it's a good idea to scroll and the terminal can, then do it.
16ea9636
EW
93 * We handle retain (da and db) by putting the burden on scrolling up,
94 * which is the less common operation. It must ensure that
95 * text is not pushed below the screen, so scrolling down doesn't
96 * have to worry about it.
577dff1e 97 */
16ea9636
EW
98 if (nvis < nvismax / 2)
99 goto no_scroll; /* not worth it */
100 /*
101 * Try scrolling region (or scrolling the whole screen) first.
102 * Can we assume "sr" doesn't push text below the screen
103 * so we don't have to worry about retain below?
104 * What about scrolling down with a newline? It probably does
105 * push text above (with da). Scrolling up would then have
106 * to take care of that.
107 * It's easy to be fool proof, but that slows things down.
108 * The current solution is to disallow tt_scroll_up if da or db is true
109 * but cs (scrolling region) is not. Again, we sacrifice scrolling
110 * up in favor of scrolling down. The idea is having scrolling regions
111 * probably means we can scroll (even the whole screen) with impunity.
112 * This lets us work efficiently on simple terminals (use newline
113 * on the bottom to scroll), on any terminal without retain, and
114 * on vt100 style scrolling regions (I think).
115 */
116 if (scroll_func = dir > 0 ? tt.tt_scroll_down : tt.tt_scroll_up) {
117 if (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1)
118 if (tt.tt_setscroll == 0)
119 scroll_func = 0;
120 else
121 (*tt.tt_setscroll)(row1x, row2x - 1);
122 if (scroll_func) {
123 (*scroll_func)();
124 goto did_scroll;
125 }
126 }
127 /*
128 * Try insert/delete line.
129 * Don't worry about retain when scrolling down,
130 * but do worry when scrolling up, for hp2621.
131 */
132 if (tt.tt_delline == 0 || tt.tt_insline == 0)
133 goto no_scroll;
134 if (dir > 0) {
135 (*tt.tt_move)(row1x, 0);
136 (*tt.tt_delline)();
137 if (row2x < wwnrow) {
138 (*tt.tt_move)(row2x - 1, 0);
05fb5c3b
EW
139 (*tt.tt_insline)();
140 }
16ea9636
EW
141 } else {
142 if (tt.tt_retain || row2x != wwnrow) {
143 (*tt.tt_move)(row2x - 1, 0);
144 (*tt.tt_delline)();
145 }
146 (*tt.tt_move)(row1x, 0);
147 (*tt.tt_insline)();
05fb5c3b 148 }
16ea9636
EW
149did_scroll:
150 scrolled = 1;
05fb5c3b
EW
151 /*
152 * Fix up the old screen.
153 */
16ea9636 154 {
05fb5c3b
EW
155 register union ww_char *tmp;
156 register union ww_char **cpp, **cqq;
157
158 if (dir > 0) {
f2a77fe1 159 cpp = &wwos[row1x];
577dff1e
EW
160 cqq = cpp + 1;
161 tmp = *cpp;
19f9784c 162 for (i = row2x - row1x; --i > 0;)
577dff1e
EW
163 *cpp++ = *cqq++;
164 *cpp = tmp;
577dff1e 165 } else {
f2a77fe1 166 cpp = &wwos[row2x];
19f9784c 167 cqq = cpp - 1;
577dff1e 168 tmp = *cqq;
19f9784c 169 for (i = row2x - row1x; --i > 0;)
577dff1e
EW
170 *--cpp = *--cqq;
171 *cqq = tmp;
577dff1e 172 }
f2a77fe1
EW
173 for (i = wwncol; --i >= 0;)
174 tmp++->c_w = ' ';
577dff1e
EW
175 }
176
16ea9636 177no_scroll:
577dff1e
EW
178 /*
179 * Fix the new screen.
180 */
181 if (nvis == nvismax) {
182 /*
183 * Can shift whole lines.
184 */
577dff1e 185 if (dir > 0) {
861cd1ed
EW
186 {
187 register union ww_char *tmp;
188 register union ww_char **cpp, **cqq;
189
f2a77fe1 190 cpp = &wwns[row1x];
861cd1ed
EW
191 cqq = cpp + 1;
192 tmp = *cpp;
19f9784c 193 for (i = row2x - row1x; --i > 0;)
861cd1ed
EW
194 *cpp++ = *cqq++;
195 *cpp = tmp;
196 }
16ea9636 197 if (scrolled) {
861cd1ed
EW
198 register char *p, *q;
199
f2a77fe1 200 p = &wwtouched[row1x];
861cd1ed 201 q = p + 1;
19f9784c 202 for (i = row2x - row1x; --i > 0;)
861cd1ed 203 *p++ = *q++;
04d70db4 204 *p |= WWU_TOUCHED;
26008571
EW
205 } else {
206 register char *p;
207
f2a77fe1 208 p = &wwtouched[row1x];
19f9784c 209 for (i = row2x - row1x; --i >= 0;)
04d70db4 210 *p++ |= WWU_MAJOR|WWU_TOUCHED;
861cd1ed 211 }
f2a77fe1
EW
212 wwredrawwin1(w, row1, row1x, dir);
213 wwredrawwin1(w, row2x - 1, row2 - leaveit, dir);
577dff1e 214 } else {
861cd1ed
EW
215 {
216 register union ww_char *tmp;
217 register union ww_char **cpp, **cqq;
218
f2a77fe1 219 cpp = &wwns[row2x];
19f9784c 220 cqq = cpp - 1;
861cd1ed 221 tmp = *cqq;
19f9784c 222 for (i = row2x - row1x; --i > 0;)
861cd1ed
EW
223 *--cpp = *--cqq;
224 *cqq = tmp;
225 }
16ea9636 226 if (scrolled) {
861cd1ed
EW
227 register char *p, *q;
228
f2a77fe1 229 p = &wwtouched[row2x];
19f9784c
EW
230 q = p - 1;
231 for (i = row2x - row1x; --i > 0;)
861cd1ed 232 *--p = *--q;
5360b004 233 *q |= WWU_TOUCHED;
26008571
EW
234 } else {
235 register char *p;
236
f2a77fe1 237 p = &wwtouched[row1x];
19f9784c 238 for (i = row2x - row1x; --i >= 0;)
5360b004 239 *p++ |= WWU_MAJOR|WWU_TOUCHED;
861cd1ed 240 }
f2a77fe1
EW
241 wwredrawwin1(w, row1 + leaveit, row1x + 1, dir);
242 wwredrawwin1(w, row2x, row2, dir);
577dff1e
EW
243 }
244 } else {
16ea9636 245 if (scrolled) {
5360b004
EW
246 register char *p;
247
248 p = &wwtouched[row1x];
249 for (i = row2x - row1x; --i >= 0;)
250 *p++ |= WWU_MAJOR|WWU_TOUCHED;
251 }
577dff1e
EW
252out:
253 if (dir > 0)
f2a77fe1 254 wwredrawwin1(w, row1, row2 - leaveit, dir);
577dff1e 255 else
f2a77fe1 256 wwredrawwin1(w, row1 + leaveit, row2, dir);
577dff1e 257 }
16ea9636 258 return scrolled;
577dff1e 259}