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