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