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