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