|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Edward Wang at The University of California, Berkeley.
7: *
8: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)wwscroll.c 3.24 (Berkeley) 6/6/90";
25: #endif /* not lint */
26:
27: #include "ww.h"
28: #include "tt.h"
29:
30: wwscroll(w, n)
31: register struct ww *w;
32: int n;
33: {
34: register dir;
35: register top;
36:
37: if (n == 0)
38: return;
39: dir = n < 0 ? -1 : 1;
40: top = w->ww_b.t - n;
41: if (top > w->ww_w.t)
42: top = w->ww_w.t;
43: else if (top + w->ww_b.nr < w->ww_w.b)
44: top = w->ww_w.b - w->ww_b.nr;
45: n = abs(top - w->ww_b.t);
46: if (n < w->ww_i.nr) {
47: while (--n >= 0) {
48: (void) wwscroll1(w, w->ww_i.t, w->ww_i.b, dir, 0);
49: w->ww_buf += dir;
50: w->ww_b.t -= dir;
51: w->ww_b.b -= dir;
52: }
53: } else {
54: w->ww_buf -= top - w->ww_b.t;
55: w->ww_b.t = top;
56: w->ww_b.b = top + w->ww_b.nr;
57: wwredrawwin(w);
58: }
59: }
60:
61: /*
62: * Scroll one line, between 'row1' and 'row2', in direction 'dir'.
63: * Don't adjust ww_scroll.
64: * And don't redraw 'leaveit' lines.
65: */
66: wwscroll1(w, row1, row2, dir, leaveit)
67: register struct ww *w;
68: int row1, row2, dir;
69: int leaveit;
70: {
71: register i;
72: int row1x, row2x;
73: int nvis;
74: int nvismax;
75: int scrolled = 0;
76:
77: /*
78: * See how many lines on the screen are affected.
79: * And calculate row1x, row2x, and left at the same time.
80: */
81: for (i = row1; i < row2 && w->ww_nvis[i] == 0; i++)
82: ;
83: if (i >= row2) /* can't do any fancy stuff */
84: goto out;
85: row1x = i;
86: for (i = row2 - 1; i >= row1 && w->ww_nvis[i] == 0; i--)
87: ;
88: if (i <= row1x)
89: goto out; /* just one line is easy */
90: row2x = i + 1;
91:
92: /*
93: * See how much of this window is visible.
94: */
95: nvismax = wwncol * (row2x - row1x);
96: nvis = 0;
97: for (i = row1x; i < row2x; i++)
98: nvis += w->ww_nvis[i];
99:
100: /*
101: * If it's a good idea to scroll and the terminal can, then do it.
102: */
103: if (nvis < nvismax / 2)
104: goto no_scroll; /* not worth it */
105: if ((dir > 0 ? tt.tt_scroll_down == 0 : tt.tt_scroll_up == 0) ||
106: (tt.tt_scroll_top != row1x || tt.tt_scroll_bot != row2x - 1) &&
107: tt.tt_setscroll == 0)
108: if (tt.tt_delline == 0 || tt.tt_insline == 0)
109: goto no_scroll;
110: xxscroll(dir, row1x, row2x);
111: scrolled = 1;
112: /*
113: * Fix up the old screen.
114: */
115: {
116: register union ww_char *tmp;
117: register union ww_char **cpp, **cqq;
118:
119: if (dir > 0) {
120: cpp = &wwos[row1x];
121: cqq = cpp + 1;
122: tmp = *cpp;
123: for (i = row2x - row1x; --i > 0;)
124: *cpp++ = *cqq++;
125: *cpp = tmp;
126: } else {
127: cpp = &wwos[row2x];
128: cqq = cpp - 1;
129: tmp = *cqq;
130: for (i = row2x - row1x; --i > 0;)
131: *--cpp = *--cqq;
132: *cqq = tmp;
133: }
134: for (i = wwncol; --i >= 0;)
135: tmp++->c_w = ' ';
136: }
137:
138: no_scroll:
139: /*
140: * Fix the new screen.
141: */
142: if (nvis == nvismax) {
143: /*
144: * Can shift whole lines.
145: */
146: if (dir > 0) {
147: {
148: register union ww_char *tmp;
149: register union ww_char **cpp, **cqq;
150:
151: cpp = &wwns[row1x];
152: cqq = cpp + 1;
153: tmp = *cpp;
154: for (i = row2x - row1x; --i > 0;)
155: *cpp++ = *cqq++;
156: *cpp = tmp;
157: }
158: if (scrolled) {
159: register char *p, *q;
160:
161: p = &wwtouched[row1x];
162: q = p + 1;
163: for (i = row2x - row1x; --i > 0;)
164: *p++ = *q++;
165: *p |= WWU_TOUCHED;
166: } else {
167: register char *p;
168:
169: p = &wwtouched[row1x];
170: for (i = row2x - row1x; --i >= 0;)
171: *p++ |= WWU_TOUCHED;
172: }
173: wwredrawwin1(w, row1, row1x, dir);
174: wwredrawwin1(w, row2x - 1, row2 - leaveit, dir);
175: } else {
176: {
177: register union ww_char *tmp;
178: register union ww_char **cpp, **cqq;
179:
180: cpp = &wwns[row2x];
181: cqq = cpp - 1;
182: tmp = *cqq;
183: for (i = row2x - row1x; --i > 0;)
184: *--cpp = *--cqq;
185: *cqq = tmp;
186: }
187: if (scrolled) {
188: register char *p, *q;
189:
190: p = &wwtouched[row2x];
191: q = p - 1;
192: for (i = row2x - row1x; --i > 0;)
193: *--p = *--q;
194: *q |= WWU_TOUCHED;
195: } else {
196: register char *p;
197:
198: p = &wwtouched[row1x];
199: for (i = row2x - row1x; --i >= 0;)
200: *p++ |= WWU_TOUCHED;
201: }
202: wwredrawwin1(w, row1 + leaveit, row1x + 1, dir);
203: wwredrawwin1(w, row2x, row2, dir);
204: }
205: } else {
206: if (scrolled) {
207: register char *p;
208:
209: p = &wwtouched[row1x];
210: for (i = row2x - row1x; --i >= 0;)
211: *p++ |= WWU_TOUCHED;
212: }
213: out:
214: if (dir > 0)
215: wwredrawwin1(w, row1, row2 - leaveit, dir);
216: else
217: wwredrawwin1(w, row1 + leaveit, row2, dir);
218: }
219: return scrolled;
220: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.