|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)ex_vadj.c 7.10 (Berkeley) 3/9/87";
9: #endif not lint
10:
11: #include "ex.h"
12: #include "ex_tty.h"
13: #include "ex_vis.h"
14:
15: /*
16: * Routines to deal with management of logical versus physical
17: * display, opening and redisplaying lines on the screen, and
18: * use of intelligent terminal operations. Routines to deal with
19: * screen cleanup after a change.
20: */
21:
22: /*
23: * Display a new line at physical line p, returning
24: * the depth of the newly displayed line. We may decide
25: * to expand the window on an intelligent terminal if it is
26: * less than a full screen by deleting a line above the top of the
27: * window before doing an insert line to keep all the good text
28: * on the screen in which case the line may actually end up
29: * somewhere other than line p.
30: */
31: vopen(tp, p)
32: line *tp;
33: int p;
34: {
35: register int cnt;
36: register struct vlinfo *vp, *vpc;
37:
38: #ifdef ADEBUG
39: if (trace != NULL)
40: tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p);
41: #endif
42: if (state != VISUAL) {
43: if (vcnt)
44: if (hold & HOLDROL)
45: vup1();
46: else
47: vclean();
48:
49: /*
50: * Forget all that we once knew.
51: */
52: vcnt = vcline = 0;
53: p = WBOT; LASTLINE = WBOT + 1;
54: state = bastate;
55: WTOP = basWTOP;
56: WLINES = basWLINES;
57: }
58: vpc = &vlinfo[vcline];
59: for (vp = &vlinfo[vcnt]; vp >= vpc; vp--)
60: vlcopy(vp[1], vp[0]);
61: vcnt++;
62: if (Pline == numbline)
63: /*
64: * Dirtying all the lines is rather inefficient
65: * internally, but number mode is used rarely
66: * and so its not worth optimizing.
67: */
68: vdirty(vcline+1, WECHO);
69: getline(*tp);
70:
71: /*
72: * If we are opening at the top of the window, can try a window
73: * expansion at the top.
74: */
75: if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ex_ZERO) {
76: cnt = p + vdepth() - LINE(1);
77: if (cnt > 0) {
78: p -= cnt;
79: if (p < ex_ZERO)
80: p = ex_ZERO;
81: WTOP = p;
82: WLINES = WBOT - WTOP + 1;
83: }
84: }
85: vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0;
86: cnt = vreopen(p, lineno(tp), vcline);
87: if (vcline + 1 == vcnt)
88: LINE(vcnt) = LINE(vcline) + cnt;
89: }
90:
91: /*
92: * Redisplay logical line l at physical line p with line number lineno.
93: */
94: vreopen(p, lineno, l)
95: int p, lineno, l;
96: {
97: register int d;
98: register struct vlinfo *vp = &vlinfo[l];
99:
100: d = vp->vdepth;
101: if (d == 0 || (vp->vflags & VDIRT))
102: vp->vdepth = d = vdepth();
103: vp->vliny = p, vp->vflags &= ~VDIRT;
104:
105: /*
106: * Try to win by making the screen larger rather than inserting
107: * a line and driving text off the bottom.
108: */
109: p = vglitchup(l, 0);
110:
111: /*
112: * BUG: Should consider using CE here to clear to end of line.
113: * As it stands we always strike over the current text.
114: * Since often the current text is the same as what
115: * we are overstriking with, it tends not to show.
116: * On the other hand if it is different and we end up
117: * spacing out a lot of text, we could have won with
118: * a CE. This is probably worthwhile at low speed
119: * only however, since clearly computation will be
120: * necessary to determine which way to go.
121: */
122: vigoto(p, 0);
123: pline(lineno);
124:
125: /*
126: * When we are typing part of a line for hardcopy open, don't
127: * want to type the '$' marking an end of line if in list mode.
128: */
129: if (hold & HOLDDOL)
130: return (d);
131: if (Put_char == listchar)
132: ex_putchar('$');
133:
134: /*
135: * Optimization of cursor motion may prevent screen rollup if the
136: * line has blanks/tabs at the end unless we force the cursor to appear
137: * on the last line segment.
138: */
139: if (vp->vliny + d - 1 > WBOT)
140: vcsync();
141:
142: /*
143: * Switch into hardcopy open mode if we are in one line (adm3)
144: * open mode and this line is now too long. If in hardcopy
145: * open mode, then call sethard to move onto the next line
146: * with appropriate positioning.
147: */
148: if (state == ONEOPEN) {
149: WCOLS = OCOLUMNS;
150: if (vdepth() > 1) {
151: WCOLS = TUBECOLS;
152: sethard();
153: } else
154: WCOLS = TUBECOLS;
155: } else if (state == HARDOPEN)
156: sethard();
157:
158: /*
159: * Unless we filled (completely) the last line we typed on,
160: * we have to clear to the end of the line
161: * in case stuff is left from before.
162: */
163: if (vp->vliny + d > destline) {
164: if (IN && destcol == WCOLS)
165: vigoto(vp->vliny + d - 1, 0);
166: vclreol();
167: }
168: return (d);
169: }
170:
171: /*
172: * Real work for winning growing of window at top
173: * when inserting in the middle of a partially full
174: * screen on an intelligent terminal. We have as argument
175: * the logical line number to be inserted after, and the offset
176: * from that line where the insert will go.
177: * We look at the picture of depths and positions, and if we can
178: * delete some (blank) lines from the top of the screen so that
179: * later inserts will not push stuff off the bottom.
180: */
181: vglitchup(l, o)
182: int l, o;
183: {
184: register struct vlinfo *vp = &vlinfo[l];
185: register int need;
186: register int p = vp->vliny;
187: short oldhold, oldheldech;
188: bool glitched = 0;
189:
190: if (l < vcnt - 1) {
191: need = p + vp->vdepth - (vp+1)->vliny;
192: if (need > 0) {
193: if (state == VISUAL && WTOP - ex_ZERO >= need && AL && DL) {
194: glitched++;
195: WTOP -= need;
196: WLINES = WBOT - WTOP + 1;
197: p -= need;
198: if (p + o == WTOP) {
199: vp->vliny = WTOP;
200: return (WTOP + o);
201: }
202: vdellin(WTOP, need, -1);
203: oldheldech = heldech;
204: oldhold = hold;
205: hold |= HOLDECH;
206: }
207: vinslin((vp+1)->vliny, need, l);
208: if (glitched) {
209: hold = oldhold;
210: heldech = oldheldech;
211: }
212: }
213: } else
214: vp[1].vliny = vp[0].vliny + vp->vdepth;
215: return (p + o);
216: }
217:
218: /*
219: * Insert cnt blank lines before line p,
220: * logically and (if supported) physically.
221: */
222: vinslin(p, cnt, l)
223: register int p, cnt;
224: int l;
225: {
226: register int i;
227: bool could = 1;
228:
229: #ifdef ADEBUG
230: if (trace)
231: tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
232: #endif
233: if (p + cnt > WBOT && CD) {
234: /*
235: * Really quick -- clear to end of screen.
236: */
237: cnt = WECHO + 1 - p;
238: vgoto(p, 0), vputp(CD, cnt);
239: vclrech(1);
240: vadjAL(p, cnt);
241: } else if (SR && p == WTOP && costSR < costAL) {
242: /*
243: * Use reverse scroll mode of the terminal, at
244: * the top of the window. Reverse linefeed works
245: * too, since we only use it from line WTOP.
246: */
247: for (i = cnt; i > 0; i--) {
248: vgoto(p, 0), vputp(SR, 0);
249: if (i > 1 && (hold & HOLDAT) == 0)
250: ex_putchar('@');
251: /*
252: * If we are at the top of the screen, and the
253: * terminal retains display above, then we
254: * should try to clear to end of line.
255: * Have to use CE since we don't remember what is
256: * actually on the line.
257: */
258: if (CE && (DA || p != 0))
259: vputp(CE, 1);
260: }
261: vadjAL(p, cnt);
262: } else if (AL) {
263: /*
264: * Use insert line.
265: */
266: vgoto(p, 0);
267: if (AL_PARM && (cnt>1 || *AL==0)) {
268: /* insert cnt lines. Should do @'s too. */
269: vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p);
270: }
271: else if (CS && *AL==0) {
272: /* vt100 change scrolling region to fake AL */
273: vputp(SC, 1);
274: vputp(tgoto(CS, LINES-1,p), 1);
275: vputp(RC, 1); /* CS homes stupid cursor */
276: for (i=cnt; i>0; i--)
277: vputp(SR, 1); /* should do @'s */
278: vputp(tgoto(CS, LINES-1,0), 1);
279: vputp(RC, 1); /* Once again put it back */
280: }
281: else {
282: vputp(AL, WECHO + 1 - p);
283: for (i = cnt - 1; i > 0; i--) {
284: vgoto(outline+1, 0);
285: vputp(AL, WECHO + 1 - outline);
286: if ((hold & HOLDAT) == 0)
287: ex_putchar('@');
288: }
289: }
290: vadjAL(p, cnt);
291: } else
292: could = 0;
293: vopenup(cnt, could, l);
294: }
295:
296: /*
297: * Logically open up after line l, cnt of them.
298: * We need to know if it was done ``physically'' since in this
299: * case we accept what the hardware gives us. If we have to do
300: * it ourselves (brute force) we will squish out @ lines in the process
301: * if this will save us work.
302: */
303: vopenup(cnt, could, l)
304: int cnt;
305: bool could;
306: {
307: register struct vlinfo *vc = &vlinfo[l + 1];
308: register struct vlinfo *ve = &vlinfo[vcnt];
309:
310: #ifdef ADEBUG
311: if (trace)
312: tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
313: #endif
314: if (could)
315: /*
316: * This will push @ lines down the screen,
317: * just as the hardware did. Since the default
318: * for intelligent terminals is to never have @
319: * lines on the screen, this should never happen,
320: * and the code makes no special effort to be nice in this
321: * case, e.g. squishing out the @ lines by delete lines
322: * before doing append lines.
323: */
324: for (; vc <= ve; vc++)
325: vc->vliny += cnt;
326: else {
327: /*
328: * Will have to clean up brute force eventually,
329: * so push the line data around as little as possible.
330: */
331: vc->vliny += cnt, vc->vflags |= VDIRT;
332: while (vc < ve) {
333: register int i = vc->vliny + vc->vdepth;
334:
335: vc++;
336: if (i <= vc->vliny)
337: break;
338: vc->vliny = i, vc->vflags |= VDIRT;
339: }
340: }
341: vscrap();
342: }
343:
344: /*
345: * Adjust data structure internally to account for insertion of
346: * blank lines on the screen.
347: */
348: vadjAL(p, cnt)
349: int p, cnt;
350: {
351: char *tlines[TUBELINES];
352: register int from, to;
353:
354: #ifdef ADEBUG
355: if (trace)
356: tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
357: #endif
358: copy(tlines, vtube, sizeof vtube); /*SASSIGN*/
359: for (from = p, to = p + cnt; to <= WECHO; from++, to++)
360: vtube[to] = tlines[from];
361: for (to = p; from <= WECHO; from++, to++) {
362: vtube[to] = tlines[from];
363: vclrbyte(vtube[to], WCOLS);
364: }
365: /*
366: * Have to clear the echo area since its contents aren't
367: * necessarily consistent with the rest of the display.
368: */
369: vclrech(0);
370: }
371:
372: /*
373: * Roll the screen up logically and physically
374: * so that line dl is the bottom line on the screen.
375: */
376: vrollup(dl)
377: int dl;
378: {
379: register int cnt;
380: register int dc = destcol;
381:
382: #ifdef ADEBUG
383: if (trace)
384: tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
385: #endif
386: cnt = dl - (splitw ? WECHO : WBOT);
387: if (splitw && (state == VISUAL || state == CRTOPEN))
388: holdupd = 1;
389: vmoveitup(cnt, 1);
390: vscroll(cnt);
391: destline = dl - cnt, destcol = dc;
392: }
393:
394: vup1()
395: {
396:
397: vrollup(WBOT + 1);
398: }
399:
400: /*
401: * Scroll the screen up cnt lines physically.
402: * If doclr is true, do a clear eol if the terminal
403: * has standout (to prevent it from scrolling up)
404: */
405: vmoveitup(cnt, doclr)
406: register int cnt;
407: bool doclr;
408: {
409:
410: if (cnt == 0)
411: return;
412: #ifdef ADEBUG
413: if (trace)
414: tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
415: #endif
416: if (doclr && (SO || SE))
417: vclrech(0);
418: if (SF) {
419: destline = WECHO;
420: destcol = (NONL ? 0 : outcol % WCOLS);
421: fgoto();
422: while (cnt > 0)
423: vputp(SF, 0), cnt--;
424: return;
425: }
426: destline = WECHO + cnt;
427: destcol = (NONL ? 0 : outcol % WCOLS);
428: fgoto();
429: if (state == ONEOPEN || state == HARDOPEN) {
430: outline = destline = 0;
431: vclrbyte(vtube[0], WCOLS);
432: }
433: }
434:
435: /*
436: * Scroll the screen up cnt lines logically.
437: */
438: vscroll(cnt)
439: register int cnt;
440: {
441: register int from, to;
442: char *tlines[TUBELINES];
443:
444: #ifdef ADEBUG
445: if (trace)
446: fprintf(trace, "vscroll(%d)\n", cnt);
447: #endif
448: if (cnt < 0 || cnt > TUBELINES)
449: error("Internal error: vscroll");
450: if (cnt == 0)
451: return;
452: copy(tlines, vtube, sizeof vtube);
453: for (to = ex_ZERO, from = ex_ZERO + cnt; to <= WECHO - cnt; to++, from++)
454: vtube[to] = tlines[from];
455: for (from = ex_ZERO; to <= WECHO; to++, from++) {
456: vtube[to] = tlines[from];
457: vclrbyte(vtube[to], WCOLS);
458: }
459: for (from = 0; from <= vcnt; from++)
460: LINE(from) -= cnt;
461: }
462:
463: /*
464: * Discard logical lines due to physical wandering off the screen.
465: */
466: vscrap()
467: {
468: register int i, j;
469:
470: #ifdef ADEBUG
471: if (trace)
472: tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
473: #endif
474: if (splitw)
475: return;
476: if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ex_ZERO) {
477: WTOP = LINE(0);
478: WLINES = WBOT - WTOP + 1;
479: }
480: for (j = 0; j < vcnt; j++)
481: if (LINE(j) >= WTOP) {
482: if (j == 0)
483: break;
484: /*
485: * Discard the first j physical lines off the top.
486: */
487: vcnt -= j, vcline -= j;
488: for (i = 0; i <= vcnt; i++)
489: vlcopy(vlinfo[i], vlinfo[i + j]);
490: break;
491: }
492: /*
493: * Discard lines off the bottom.
494: */
495: if (vcnt) {
496: for (j = 0; j <= vcnt; j++)
497: if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
498: vcnt = j;
499: break;
500: }
501: LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
502: }
503: #ifdef ADEBUG
504: if (trace)
505: tvliny();
506: #endif
507: /*
508: * May have no lines!
509: */
510: }
511:
512: /*
513: * Repaint the screen, with cursor at curs, aftern an arbitrary change.
514: * Handle notification on large changes.
515: */
516: vrepaint(curs)
517: char *curs;
518: {
519:
520: wdot = NOLINE;
521: /*
522: * In open want to notify first.
523: */
524: ignore(noteit(0));
525: vscrap();
526:
527: /*
528: * Deal with a totally useless display.
529: */
530: if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
531: register line *odol = dol;
532:
533: vcnt = 0;
534: if (holdupd)
535: if (state == VISUAL)
536: ignore(peekkey());
537: else
538: vup1();
539: holdupd = 0;
540: if (odol == zero)
541: fixzero();
542: vcontext(dot, '.');
543: ignore(noteit(1));
544: if (noteit(1) == 0 && odol == zero) {
545: CATCH
546: error("No lines in buffer");
547: ENDCATCH
548: linebuf[0] = 0;
549: splitw = 0;
550: }
551: vnline(curs);
552: return;
553: }
554:
555: /*
556: * Have some useful displayed text; refresh it.
557: */
558: getDOT();
559:
560: /*
561: * This is for boundary conditions in open mode.
562: */
563: if (FLAGS(0) & VDIRT)
564: vsync(WTOP);
565:
566: /*
567: * If the current line is after the last displayed line
568: * or the bottom of the screen, then special effort is needed
569: * to get it on the screen. We first try a redraw at the
570: * last line on the screen, hoping it will fill in where @
571: * lines are now. If this doesn't work, then roll it onto
572: * the screen.
573: */
574: if (vcline >= vcnt || LINE(vcline) > WBOT) {
575: short oldhold = hold;
576: hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
577: if (vcline >= vcnt) {
578: register int i = vcline - vcnt + 1;
579:
580: dot -= i;
581: vcline -= i;
582: vroll(i);
583: } else
584: vsyncCL();
585: } else
586: vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
587:
588: /*
589: * Notification on large change for visual
590: * has to be done last or we may lose
591: * the echo area with redisplay.
592: */
593: ignore(noteit(1));
594:
595: /*
596: * Finally. Move the cursor onto the current line.
597: */
598: vnline(curs);
599: }
600:
601: /*
602: * Fully cleanup the screen, leaving no @ lines except at end when
603: * line after last won't completely fit. The routine vsync is
604: * more conservative and much less work on dumb terminals.
605: */
606: vredraw(p)
607: register int p;
608: {
609: register int l;
610: register line *tp;
611: char temp[LBSIZE];
612: bool anydl = 0;
613: short oldhold = hold;
614:
615: #ifdef ADEBUG
616: if (trace)
617: tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
618: #endif
619: if (holdupd) {
620: holdupd = 3;
621: return;
622: }
623: if (state == HARDOPEN || splitw)
624: return;
625: if (p < 0 /* || p > WECHO */)
626: error("Internal error: vredraw");
627:
628: /*
629: * Trim the ragged edges (lines which are off the screen but
630: * not yet logically discarded), save the current line, and
631: * search for first logical line affected by the redraw.
632: */
633: vscrap();
634: CP(temp, linebuf);
635: l = 0;
636: tp = dot - vcline;
637: if (vcnt == 0)
638: LINE(0) = WTOP;
639: while (l < vcnt && LINE(l) < p)
640: l++, tp++;
641:
642: /*
643: * We hold off echo area clearing during the redraw in deference
644: * to a final clear of the echo area at the end if appropriate.
645: */
646: heldech = 0;
647: hold |= HOLDECH;
648: for (; l < vcnt && Peek_key != ATTN; l++) {
649: if (l == vcline)
650: strcLIN(temp);
651: else
652: getline(*tp);
653:
654: /*
655: * Delete junk between displayed lines.
656: */
657: if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
658: if (anydl == 0 && DB && CD) {
659: hold = oldhold;
660: vclrech(0);
661: anydl = 1;
662: hold |= HOLDECH;
663: heldech = 0;
664: }
665: vdellin(p, LINE(l) - p, l);
666: }
667:
668: /*
669: * If line image is not know to be up to date, then
670: * redisplay it; else just skip onward.
671: */
672: LINE(l) = p;
673: if (FLAGS(l) & VDIRT) {
674: DEPTH(l) = vdepth();
675: if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
676: vscrap();
677: break;
678: }
679: FLAGS(l) &= ~VDIRT;
680: ignore(vreopen(p, lineno(tp), l));
681: p = LINE(l) + DEPTH(l);
682: } else
683: p += DEPTH(l);
684: tp++;
685: }
686:
687: /*
688: * That takes care of lines which were already partially displayed.
689: * Now try to fill the rest of the screen with text.
690: */
691: if (state == VISUAL && p <= WBOT) {
692: int ovcline = vcline;
693:
694: vcline = l;
695: for (; tp <= dol && Peek_key != ATTN; tp++) {
696: getline(*tp);
697: if (p + vdepth() - 1 > WBOT)
698: break;
699: vopen(tp, p);
700: p += DEPTH(vcline);
701: vcline++;
702: }
703: vcline = ovcline;
704: }
705:
706: /*
707: * Thats all the text we can get on.
708: * Now rest of lines (if any) get either a ~ if they
709: * are past end of file, or an @ if the next line won't fit.
710: */
711: for (; p <= WBOT && Peek_key != ATTN; p++)
712: vclrlin(p, tp);
713: strcLIN(temp);
714: hold = oldhold;
715: if (heldech)
716: vclrech(0);
717: #ifdef ADEBUG
718: if (trace)
719: tvliny();
720: #endif
721: }
722:
723: /*
724: * Do the real work in deleting cnt lines starting at line p from
725: * the display. First affected line is line l.
726: */
727: vdellin(p, cnt, l)
728: int p, cnt, l;
729: {
730: register int i;
731:
732: if (cnt == 0)
733: return;
734: if (DL == NOSTR || cnt < 0) {
735: /*
736: * Can't do it; just remember that line l is munged.
737: */
738: FLAGS(l) |= VDIRT;
739: return;
740: }
741: #ifdef ADEBUG
742: if (trace)
743: tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
744: #endif
745: /*
746: * Send the deletes to the screen and then adjust logical
747: * and physical internal data structures.
748: */
749: vgoto(p, 0);
750: if (DL_PARM && (cnt>1 || *DL==0)) {
751: vputp(tgoto(DL_PARM, p, cnt), WECHO-p);
752: }
753: else if (CS && *DL==0) {
754: /* vt100: fake DL by changing scrolling region */
755: vputp(SC, 1); /* Save since CS homes stupid cursor */
756: vputp(tgoto(CS, LINES-1, p), 1);
757: vputp(tgoto(CM, 0, LINES-1), 1);/* Go to lower left corner */
758: for (i=0; i<cnt; i++) /* .. and scroll cnt times */
759: putch('\n'); /* should check NL too */
760: vputp(tgoto(CS, LINES-1, 0), 1);/* restore scrolling region */
761: vputp(RC, 1); /* put cursor back */
762: }
763: else {
764: for (i = 0; i < cnt; i++)
765: vputp(DL, WECHO - p);
766: }
767: vadjDL(p, cnt);
768: vcloseup(l, cnt);
769: }
770: /*
771: * Adjust internal physical screen image to account for deleted lines.
772: */
773: vadjDL(p, cnt)
774: int p, cnt;
775: {
776: char *tlines[TUBELINES];
777: register int from, to;
778:
779: #ifdef ADEBUG
780: if (trace)
781: tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
782: #endif
783: /*
784: * Would like to use structured assignment but early
785: * v7 compiler (released with phototypesetter for v6)
786: * can't hack it.
787: */
788: copy(tlines, vtube, sizeof vtube); /*SASSIGN*/
789: for (from = p + cnt, to = p; from <= WECHO; from++, to++)
790: vtube[to] = tlines[from];
791: for (from = p; to <= WECHO; from++, to++) {
792: vtube[to] = tlines[from];
793: vclrbyte(vtube[to], WCOLS);
794: }
795: }
796: /*
797: * Sync the screen, like redraw but more lazy and willing to leave
798: * @ lines on the screen. VsyncCL syncs starting at the current line.
799: * In any case, if the redraw option is set then all syncs map to redraws
800: * as if vsync didn't exist.
801: */
802: vsyncCL()
803: {
804:
805: vsync(LINE(vcline));
806: }
807:
808: vsync(p)
809: register int p;
810: {
811:
812: if (value(REDRAW))
813: vredraw(p);
814: else
815: vsync1(p);
816: }
817:
818: /*
819: * The guts of a sync. Similar to redraw but
820: * just less ambitous.
821: */
822: vsync1(p)
823: register int p;
824: {
825: register int l;
826: char temp[LBSIZE];
827: register struct vlinfo *vp = &vlinfo[0];
828: short oldhold = hold;
829:
830: #ifdef ADEBUG
831: if (trace)
832: tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
833: #endif
834: if (holdupd) {
835: if (holdupd < 3)
836: holdupd = 2;
837: return;
838: }
839: if (state == HARDOPEN || splitw)
840: return;
841: vscrap();
842: CP(temp, linebuf);
843: if (vcnt == 0)
844: LINE(0) = WTOP;
845: l = 0;
846: while (l < vcnt && vp->vliny < p)
847: l++, vp++;
848: heldech = 0;
849: hold |= HOLDECH;
850: while (p <= WBOT && Peek_key != ATTN) {
851: /*
852: * Want to put a line here if not in visual and first line
853: * or if there are lies left and this line starts before
854: * the current line, or if this line is piled under the
855: * next line (vreplace does this and we undo it).
856: */
857: if (l == 0 && state != VISUAL ||
858: (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
859: if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
860: if (l == vcline)
861: strcLIN(temp);
862: else
863: getline(dot[l - vcline]);
864: /*
865: * Be careful that a long line doesn't cause the
866: * screen to shoot up.
867: */
868: if (l != vcline && (vp->vflags & VDIRT)) {
869: vp->vdepth = vdepth();
870: vp->vflags &= ~VDIRT;
871: if (p + vp->vdepth - 1 > WBOT)
872: break;
873: }
874: ignore(vreopen(p, lineDOT() + (l - vcline), l));
875: }
876: p = vp->vliny + vp->vdepth;
877: vp++;
878: l++;
879: } else
880: /*
881: * A physical line between logical lines,
882: * so we settle for an @ at the beginning.
883: */
884: vclrlin(p, dot + (l - vcline)), p++;
885: }
886: strcLIN(temp);
887: hold = oldhold;
888: if (heldech)
889: vclrech(0);
890: }
891:
892: /*
893: * Subtract (logically) cnt physical lines from the
894: * displayed position of lines starting with line l.
895: */
896: vcloseup(l, cnt)
897: int l;
898: register int cnt;
899: {
900: register int i;
901:
902: #ifdef ADEBUG
903: if (trace)
904: tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
905: #endif
906: for (i = l + 1; i <= vcnt; i++)
907: LINE(i) -= cnt;
908: }
909:
910: /*
911: * Workhorse for rearranging line descriptors on changes.
912: * The idea here is that, starting with line l, cnt lines
913: * have been replaced with newcnt lines. All of these may
914: * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
915: * since we may be called from an undo after the screen has
916: * moved a lot. Thus we have to be careful.
917: *
918: * Many boundary conditions here.
919: */
920: vreplace(l, cnt, newcnt)
921: int l, cnt, newcnt;
922: {
923: register int from, to, i;
924: bool savenote = 0;
925:
926: #ifdef ADEBUG
927: if (trace) {
928: tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
929: tvliny();
930: }
931: #endif
932: if (l >= vcnt)
933: return;
934: if (l < 0) {
935: if (l + cnt < 0) {
936: /*
937: * Nothing on the screen is relevant.
938: * Settle for redrawing from scratch (later).
939: */
940: vcnt = 0;
941: return;
942: }
943: /*
944: * Normalize l to top of screen; the add is
945: * really a subtract from cnt since l is negative.
946: */
947: cnt += l;
948: l = 0;
949:
950: /*
951: * Unseen lines were affect so notify (later).
952: */
953: savenote++;
954: }
955:
956: /*
957: * These shouldn't happen
958: * but would cause great havoc.
959: */
960: if (cnt < 0)
961: cnt = 0;
962: if (newcnt < 0)
963: newcnt = 0;
964:
965: /*
966: * Surely worthy of note if more than report
967: * lines were changed.
968: */
969: if (cnt > value(REPORT) || newcnt > value(REPORT))
970: savenote++;
971:
972: /*
973: * Same number of lines affeted as on screen, and we
974: * can insert and delete lines. Thus we just type
975: * over them, since otherwise we will push them
976: * slowly off the screen, a clear lose.
977: */
978: if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
979: if (cnt > 1 && l + cnt > vcnt)
980: savenote++;
981: vdirty(l, newcnt);
982: } else {
983: /*
984: * Lines are going away, squish them out.
985: */
986: if (cnt > 0) {
987: /*
988: * If non-displayed lines went away,
989: * always notify.
990: */
991: if (cnt > 1 && l + cnt > vcnt)
992: savenote++;
993: if (l + cnt >= vcnt)
994: cnt = vcnt - l;
995: else
996: for (from = l + cnt, to = l; from <= vcnt; to++, from++)
997: vlcopy(vlinfo[to], vlinfo[from]);
998: vcnt -= cnt;
999: }
1000: /*
1001: * Open up space for new lines appearing.
1002: * All new lines are piled in the same place,
1003: * and will be unpiled by vredraw/vsync, which
1004: * inserts lines in front as it unpiles.
1005: */
1006: if (newcnt > 0) {
1007: /*
1008: * Newlines are appearing which may not show,
1009: * so notify (this is only approximately correct
1010: * when long lines are present).
1011: */
1012: if (newcnt > 1 && l + newcnt > vcnt + 1)
1013: savenote++;
1014:
1015: /*
1016: * If there will be more lines than fit, then
1017: * just throw way the rest of the stuff on the screen.
1018: */
1019: if (l + newcnt > WBOT && AL && DL) {
1020: vcnt = l;
1021: goto skip;
1022: }
1023: from = vcnt, to = vcnt + newcnt;
1024: i = TUBELINES - to;
1025: if (i < 0)
1026: from += i, to += i;
1027: vcnt = to;
1028: for (; from >= l; from--, to--)
1029: vlcopy(vlinfo[to], vlinfo[from]);
1030: for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
1031: LINE(to) = LINE(from);
1032: DEPTH(to) = 0;
1033: FLAGS(to) = VDIRT;
1034: }
1035: }
1036: }
1037: skip:
1038: if (Pline == numbline && cnt != newcnt)
1039: /*
1040: * When lines positions are shifted, the numbers
1041: * will be wrong.
1042: */
1043: vdirty(l, WECHO);
1044: if (!savenote)
1045: notecnt = 0;
1046: #ifdef ADEBUG
1047: if (trace)
1048: tvliny();
1049: #endif
1050: }
1051:
1052: /*
1053: * Start harcopy open.
1054: * Print an image of the line to the left of the cursor
1055: * under the full print of the line and position the cursor.
1056: * If we are in a scroll ^D within hardcopy open then all this
1057: * is suppressed.
1058: */
1059: sethard()
1060: {
1061:
1062: if (state == VISUAL)
1063: return;
1064: rubble = 0;
1065: state = HARDOPEN;
1066: if (hold & HOLDROL)
1067: return;
1068: vup1();
1069: LINE(0) = WBOT;
1070: if (Pline == numbline)
1071: vgoto(WBOT, 0), ex_printf("%6d ", lineDOT());
1072: }
1073:
1074: /*
1075: * Mark the lines starting at base for i lines
1076: * as dirty so that they will be checked for correct
1077: * display at next sync/redraw.
1078: */
1079: vdirty(base, i)
1080: register int base, i;
1081: {
1082: register int l;
1083:
1084: for (l = base; l < vcnt; l++) {
1085: if (--i < 0)
1086: return;
1087: FLAGS(l) |= VDIRT;
1088: }
1089: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.