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