New directory structure.
[unix-history] / usr / src / usr.bin / window / wwscroll.c
CommitLineData
577dff1e 1#ifndef lint
df7b254b 2static 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
14wwscroll(w, n)
15register struct ww *w;
f2a77fe1 16int 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 50wwscroll1(w, row1, row2, dir, leaveit)
577dff1e 51register struct ww *w;
19f9784c 52int row1, row2, dir;
b0d4d9e2 53int 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 {
213out:
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}