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