|
|
1.1 root 1: /* Copyright (c) 1981 Regents of the University of California */
2: static char *sccsid = "@(#)ex_vwind.c 7.1 7/8/81";
3: #include "ex.h"
4: #include "ex_tty.h"
5: #include "ex_vis.h"
6:
7: /*
8: * Routines to adjust the window, showing specified lines
9: * in certain positions on the screen, and scrolling in both
10: * directions. Code here is very dependent on mode (open versus visual).
11: */
12:
13: /*
14: * Move in a nonlocal way to line addr.
15: * If it isn't on screen put it in specified context.
16: * New position for cursor is curs.
17: * Like most routines here, we vsave().
18: */
19: vmoveto(addr, curs, context)
20: register line *addr;
21: char *curs;
22: char context;
23: {
24:
25: markit(addr);
26: vsave();
27: vjumpto(addr, curs, context);
28: }
29:
30: /*
31: * Vjumpto is like vmoveto, but doesn't mark previous
32: * context or save linebuf as current line.
33: */
34: vjumpto(addr, curs, context)
35: register line *addr;
36: char *curs;
37: char context;
38: {
39:
40: noteit(0);
41: if (context != 0)
42: vcontext(addr, context);
43: else
44: vshow(addr, NOLINE);
45: noteit(1);
46: vnline(curs);
47: }
48:
49: /*
50: * Go up or down cnt (negative is up) to new position curs.
51: */
52: vupdown(cnt, curs)
53: register int cnt;
54: char *curs;
55: {
56:
57: if (cnt > 0)
58: vdown(cnt, 0, 0);
59: else if (cnt < 0)
60: vup(-cnt, 0, 0);
61: if (vcnt == 0)
62: vrepaint(curs);
63: else
64: vnline(curs);
65: }
66:
67: /*
68: * Go up cnt lines, afterwards preferring to be ind
69: * logical lines from the top of the screen.
70: * If scroll, then we MUST use a scroll.
71: * Otherwise clear and redraw if motion is far.
72: */
73: vup(cnt, ind, scroll)
74: register int cnt, ind;
75: bool scroll;
76: {
77: register int i, tot;
78:
79: if (dot == one) {
80: beep();
81: return;
82: }
83: vsave();
84: i = lineDOT() - 1;
85: if (cnt > i) {
86: ind -= cnt - i;
87: if (ind < 0)
88: ind = 0;
89: cnt = i;
90: }
91: if (!scroll && cnt <= vcline) {
92: vshow(dot - cnt, NOLINE);
93: return;
94: }
95: cnt -= vcline, dot -= vcline, vcline = 0;
96: if (hold & HOLDWIG)
97: goto contxt;
98: if (state == VISUAL && !AL && !SR &&
99: cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
100: goto okr;
101: tot = WECHO - ZERO;
102: if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
103: if (ind > basWLINES / 2)
104: ind = basWLINES / 3;
105: contxt:
106: vcontext(dot + ind - cnt, '.');
107: return;
108: }
109: okr:
110: vrollR(cnt);
111: if (scroll) {
112: vcline += ind, dot += ind;
113: if (vcline >= vcnt)
114: dot -= vcline - vcnt + 1, vcline = vcnt - 1;
115: getDOT();
116: }
117: }
118:
119: /*
120: * Like vup, but scrolling down.
121: */
122: vdown(cnt, ind, scroll)
123: register int cnt, ind;
124: bool scroll;
125: {
126: register int i, tot;
127:
128: if (dot == dol) {
129: beep();
130: return;
131: }
132: vsave();
133: i = dol - dot;
134: if (cnt > i) {
135: ind -= cnt - i;
136: if (ind < 0)
137: ind = 0;
138: cnt = i;
139: }
140: i = vcnt - vcline - 1;
141: if (!scroll && cnt <= i) {
142: vshow(dot + cnt, NOLINE);
143: return;
144: }
145: cnt -= i, dot += i, vcline += i;
146: if (hold & HOLDWIG)
147: goto dcontxt;
148: if (!scroll) {
149: tot = WECHO - ZERO;
150: if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
151: dcontxt:
152: vcontext(dot + cnt, '.');
153: return;
154: }
155: }
156: if (cnt > 0)
157: vroll(cnt);
158: if (state == VISUAL && scroll) {
159: vcline -= ind, dot -= ind;
160: if (vcline < 0)
161: dot -= vcline, vcline = 0;
162: getDOT();
163: }
164: }
165:
166: /*
167: * Show line addr in context where on the screen.
168: * Work here is in determining new top line implied by
169: * this placement of line addr, since we always draw from the top.
170: */
171: vcontext(addr, where)
172: register line *addr;
173: char where;
174: {
175: register line *top;
176:
177: getline(*addr);
178: if (state != VISUAL)
179: top = addr;
180: else switch (where) {
181:
182: case '^':
183: addr = vback(addr, basWLINES - vdepth());
184: getline(*addr);
185: /* fall into ... */
186:
187: case '-':
188: top = vback(addr, basWLINES - vdepth());
189: getline(*addr);
190: break;
191:
192: case '.':
193: top = vback(addr, basWLINES / 2 - vdepth());
194: getline(*addr);
195: break;
196:
197: default:
198: top = addr;
199: break;
200: }
201: if (state == ONEOPEN && LINE(0) == WBOT)
202: vup1();
203: vcnt = vcline = 0;
204: vclean();
205: if (state == CRTOPEN)
206: vup1();
207: vshow(addr, top);
208: }
209:
210: /*
211: * Get a clean line. If we are in a hard open
212: * we may be able to reuse the line we are on
213: * if it is blank. This is a real win.
214: */
215: vclean()
216: {
217:
218: if (state != VISUAL && state != CRTOPEN) {
219: destcol = 0;
220: if (!ateopr())
221: vup1();
222: vcnt = 0;
223: }
224: }
225:
226: /*
227: * Show line addr with the specified top line on the screen.
228: * Top may be 0; in this case have vcontext compute the top
229: * (and call us recursively). Eventually, we clear the screen
230: * (or its open mode equivalent) and redraw.
231: */
232: vshow(addr, top)
233: line *addr, *top;
234: {
235: #ifndef CBREAK
236: register bool fried = 0;
237: #endif
238: register int cnt = addr - dot;
239: register int i = vcline + cnt;
240: short oldhold = hold;
241:
242: if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
243: dot = addr;
244: getDOT();
245: vcline = i;
246: return;
247: }
248: if (state != VISUAL) {
249: dot = addr;
250: vopen(dot, WBOT);
251: return;
252: }
253: if (top == 0) {
254: vcontext(addr, '.');
255: return;
256: }
257: dot = top;
258: #ifndef CBREAK
259: if (vcookit(2))
260: fried++, vcook();
261: #endif
262: oldhold = hold;
263: hold |= HOLDAT;
264: vclear();
265: vreset(0);
266: vredraw(WTOP);
267: /* error if vcline >= vcnt ! */
268: vcline = addr - top;
269: dot = addr;
270: getDOT();
271: hold = oldhold;
272: vsync(LASTLINE);
273: #ifndef CBREAK
274: if (fried)
275: flusho(), vraw();
276: #endif
277: }
278:
279: /*
280: * reset the state.
281: * If inecho then leave us at the beginning of the echo
282: * area; we are called this way in the middle of a :e escape
283: * from visual, e.g.
284: */
285: vreset(inecho)
286: bool inecho;
287: {
288:
289: vcnt = vcline = 0;
290: WTOP = basWTOP;
291: WLINES = basWLINES;
292: if (inecho)
293: splitw = 1, vgoto(WECHO, 0);
294: }
295:
296: /*
297: * Starting from which line preceding tp uses almost (but not more
298: * than) cnt physical lines?
299: */
300: line *
301: vback(tp, cnt)
302: register int cnt;
303: register line *tp;
304: {
305: register int d;
306:
307: if (cnt > 0)
308: for (; tp > one; tp--) {
309: getline(tp[-1]);
310: d = vdepth();
311: if (d > cnt)
312: break;
313: cnt -= d;
314: }
315: return (tp);
316: }
317:
318: /*
319: * How much scrolling will it take to roll cnt lines starting at tp?
320: */
321: vfit(tp, cnt)
322: register line *tp;
323: int cnt;
324: {
325: register int j;
326:
327: j = 0;
328: while (cnt > 0) {
329: cnt--;
330: getline(tp[cnt]);
331: j += vdepth();
332: }
333: if (tp > dot)
334: j -= WBOT - LASTLINE;
335: return (j);
336: }
337:
338: /*
339: * Roll cnt lines onto the screen.
340: */
341: vroll(cnt)
342: register int cnt;
343: {
344: #ifndef CBREAK
345: register bool fried = 0;
346: #endif
347: short oldhold = hold;
348:
349: #ifdef ADEBUG
350: if (trace)
351: tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
352: #endif
353: if (state != VISUAL)
354: hold |= HOLDAT|HOLDROL;
355: if (WBOT == WECHO) {
356: vcnt = 0;
357: if (state == ONEOPEN)
358: vup1();
359: }
360: #ifndef CBREAK
361: if (vcookit(cnt))
362: fried++, vcook();
363: #endif
364: for (; cnt > 0 && Peekkey != ATTN; cnt--) {
365: dot++, vcline++;
366: vopen(dot, LASTLINE);
367: vscrap();
368: }
369: hold = oldhold;
370: if (state == HARDOPEN)
371: sethard();
372: vsyncCL();
373: #ifndef CBREAK
374: if (fried)
375: flusho(), vraw();
376: #endif
377: }
378:
379: /*
380: * Roll backwards (scroll up).
381: */
382: vrollR(cnt)
383: register int cnt;
384: {
385: register bool fried = 0;
386: short oldhold = hold;
387:
388: #ifdef ADEBUG
389: if (trace)
390: tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
391: #endif
392: #ifndef CBREAK
393: if (vcookit(cnt))
394: fried++, vcook();
395: #endif
396: if (WBOT == WECHO)
397: vcnt = 0;
398: heldech = 0;
399: hold |= HOLDAT|HOLDECH;
400: for (; cnt > 0 && Peekkey != ATTN; cnt--) {
401: dot--;
402: vopen(dot, WTOP);
403: vscrap();
404: }
405: hold = oldhold;
406: if (heldech)
407: vclrech(0);
408: vsync(LINE(vcnt-1));
409: #ifndef CBREAK
410: if (fried)
411: flusho(), vraw();
412: #endif
413: }
414:
415: /*
416: * Go into cooked mode (allow interrupts) during
417: * a scroll if we are at less than 1200 baud and not
418: * a 'vi' command, of if we are in a 'vi' command and the
419: * scroll is more than 2 full screens.
420: *
421: * BUG: An interrupt during a scroll in this way
422: * dumps to command mode.
423: */
424: vcookit(cnt)
425: register int cnt;
426: {
427:
428: return (cnt > 1 && (ospeed < B1200 && !initev || cnt > LINES * 2));
429: }
430:
431: /*
432: * Determine displayed depth of current line.
433: */
434: vdepth()
435: {
436: register int d;
437:
438: d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + IN) / WCOLS;
439: #ifdef ADEBUG
440: if (trace)
441: tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
442: #endif
443: return (d == 0 ? 1 : d);
444: }
445:
446: /*
447: * Move onto a new line, with cursor at position curs.
448: */
449: vnline(curs)
450: char *curs;
451: {
452:
453: if (curs)
454: wcursor = curs;
455: else if (vmoving)
456: wcursor = vfindcol(vmovcol);
457: else
458: wcursor = vskipwh(linebuf);
459: cursor = linebuf;
460: vmove();
461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.