|
|
1.1 root 1: /* Copyright (c) 1981 Regents of the University of California */
2: static char *sccsid = "@(#)ex_vadj.c 7.6 11/17/81";
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);
259: if (AL_PARM && (cnt>1 || *AL==0)) {
260: /* insert cnt lines. Should do @'s too. */
261: vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p);
262: }
263: else if (CS && *AL==0) {
264: /* vt100 change scrolling region to fake AL */
265: vputp(SC, 1);
266: vputp(tgoto(CS, LINES-1,p), 1);
267: vputp(RC, 1); /* CS homes stupid cursor */
268: for (i=cnt; i>0; i--)
269: vputp(SR, 1); /* should do @'s */
270: vputp(tgoto(CS, LINES-1,0), 1);
271: vputp(RC, 1); /* Once again put it back */
272: }
273: else {
274: vputp(AL, WECHO + 1 - p);
275: for (i = cnt - 1; i > 0; i--) {
276: vgoto(outline+1, 0);
277: vputp(AL, WECHO + 1 - outline);
278: if ((hold & HOLDAT) == 0)
279: putchar('@');
280: }
281: }
282: vadjAL(p, cnt);
283: } else
284: could = 0;
285: vopenup(cnt, could, l);
286: }
287:
288: /*
289: * Logically open up after line l, cnt of them.
290: * We need to know if it was done ``physically'' since in this
291: * case we accept what the hardware gives us. If we have to do
292: * it ourselves (brute force) we will squish out @ lines in the process
293: * if this will save us work.
294: */
295: vopenup(cnt, could, l)
296: int cnt;
297: bool could;
298: {
299: register struct vlinfo *vc = &vlinfo[l + 1];
300: register struct vlinfo *ve = &vlinfo[vcnt];
301:
302: #ifdef ADEBUG
303: if (trace)
304: tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
305: #endif
306: if (could)
307: /*
308: * This will push @ lines down the screen,
309: * just as the hardware did. Since the default
310: * for intelligent terminals is to never have @
311: * lines on the screen, this should never happen,
312: * and the code makes no special effort to be nice in this
313: * case, e.g. squishing out the @ lines by delete lines
314: * before doing append lines.
315: */
316: for (; vc <= ve; vc++)
317: vc->vliny += cnt;
318: else {
319: /*
320: * Will have to clean up brute force eventually,
321: * so push the line data around as little as possible.
322: */
323: vc->vliny += cnt, vc->vflags |= VDIRT;
324: while (vc < ve) {
325: register int i = vc->vliny + vc->vdepth;
326:
327: vc++;
328: if (i <= vc->vliny)
329: break;
330: vc->vliny = i, vc->vflags |= VDIRT;
331: }
332: }
333: vscrap();
334: }
335:
336: /*
337: * Adjust data structure internally to account for insertion of
338: * blank lines on the screen.
339: */
340: vadjAL(p, cnt)
341: int p, cnt;
342: {
343: char *tlines[TUBELINES];
344: register int from, to;
345:
346: #ifdef ADEBUG
347: if (trace)
348: tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
349: #endif
350: copy(tlines, vtube, sizeof vtube); /*SASSIGN*/
351: for (from = p, to = p + cnt; to <= WECHO; from++, to++)
352: vtube[to] = tlines[from];
353: for (to = p; from <= WECHO; from++, to++) {
354: vtube[to] = tlines[from];
355: vclrbyte(vtube[to], WCOLS);
356: }
357: /*
358: * Have to clear the echo area since its contents aren't
359: * necessarily consistent with the rest of the display.
360: */
361: vclrech(0);
362: }
363:
364: /*
365: * Roll the screen up logically and physically
366: * so that line dl is the bottom line on the screen.
367: */
368: vrollup(dl)
369: int dl;
370: {
371: register int cnt;
372: register int dc = destcol;
373:
374: #ifdef ADEBUG
375: if (trace)
376: tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
377: #endif
378: cnt = dl - (splitw ? WECHO : WBOT);
379: if (splitw && (state == VISUAL || state == CRTOPEN))
380: holdupd = 1;
381: vmoveitup(cnt, 1);
382: vscroll(cnt);
383: destline = dl - cnt, destcol = dc;
384: }
385:
386: vup1()
387: {
388:
389: vrollup(WBOT + 1);
390: }
391:
392: /*
393: * Scroll the screen up cnt lines physically.
394: * If doclr is true, do a clear eol if the terminal
395: * has standout (to prevent it from scrolling up)
396: */
397: vmoveitup(cnt, doclr)
398: register int cnt;
399: bool doclr;
400: {
401:
402: if (cnt == 0)
403: return;
404: #ifdef ADEBUG
405: if (trace)
406: tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
407: #endif
408: if (doclr && (SO || SE))
409: vclrech(0);
410: if (SF) {
411: destline = WECHO;
412: destcol = (NONL ? 0 : outcol % WCOLS);
413: fgoto();
414: while (cnt > 0)
415: vputp(SF, 0), cnt--;
416: return;
417: }
418: destline = WECHO + cnt;
419: destcol = (NONL ? 0 : outcol % WCOLS);
420: fgoto();
421: if (state == ONEOPEN || state == HARDOPEN) {
422: outline = destline = 0;
423: vclrbyte(vtube[0], WCOLS);
424: }
425: }
426:
427: /*
428: * Scroll the screen up cnt lines logically.
429: */
430: vscroll(cnt)
431: register int cnt;
432: {
433: register int from, to;
434: char *tlines[TUBELINES];
435:
436: #ifdef ADEBUG
437: if (trace)
438: fprintf(trace, "vscroll(%d)\n", cnt);
439: #endif
440: if (cnt < 0 || cnt > TUBELINES)
441: error("Internal error: vscroll");
442: if (cnt == 0)
443: return;
444: copy(tlines, vtube, sizeof vtube);
445: for (to = ZERO, from = ZERO + cnt; to <= WECHO - cnt; to++, from++)
446: vtube[to] = tlines[from];
447: for (from = ZERO; to <= WECHO; to++, from++) {
448: vtube[to] = tlines[from];
449: vclrbyte(vtube[to], WCOLS);
450: }
451: for (from = 0; from <= vcnt; from++)
452: LINE(from) -= cnt;
453: }
454:
455: /*
456: * Discard logical lines due to physical wandering off the screen.
457: */
458: vscrap()
459: {
460: register int i, j;
461:
462: #ifdef ADEBUG
463: if (trace)
464: tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
465: #endif
466: if (splitw)
467: return;
468: if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ZERO) {
469: WTOP = LINE(0);
470: WLINES = WBOT - WTOP + 1;
471: }
472: for (j = 0; j < vcnt; j++)
473: if (LINE(j) >= WTOP) {
474: if (j == 0)
475: break;
476: /*
477: * Discard the first j physical lines off the top.
478: */
479: vcnt -= j, vcline -= j;
480: for (i = 0; i <= vcnt; i++)
481: vlcopy(vlinfo[i], vlinfo[i + j]);
482: break;
483: }
484: /*
485: * Discard lines off the bottom.
486: */
487: if (vcnt) {
488: for (j = 0; j <= vcnt; j++)
489: if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
490: vcnt = j;
491: break;
492: }
493: LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
494: }
495: #ifdef ADEBUG
496: if (trace)
497: tvliny();
498: #endif
499: /*
500: * May have no lines!
501: */
502: }
503:
504: /*
505: * Repaint the screen, with cursor at curs, aftern an arbitrary change.
506: * Handle notification on large changes.
507: */
508: vrepaint(curs)
509: char *curs;
510: {
511:
512: wdot = NOLINE;
513: /*
514: * In open want to notify first.
515: */
516: noteit(0);
517: vscrap();
518:
519: /*
520: * Deal with a totally useless display.
521: */
522: if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
523: register line *odol = dol;
524:
525: vcnt = 0;
526: if (holdupd)
527: if (state == VISUAL)
528: ignore(peekkey());
529: else
530: vup1();
531: holdupd = 0;
532: if (odol == zero)
533: fixzero();
534: vcontext(dot, '.');
535: noteit(1);
536: if (noteit(1) == 0 && odol == zero) {
537: CATCH
538: error("No lines in buffer");
539: ENDCATCH
540: linebuf[0] = 0;
541: splitw = 0;
542: }
543: vnline(curs);
544: return;
545: }
546:
547: /*
548: * Have some useful displayed text; refresh it.
549: */
550: getDOT();
551:
552: /*
553: * This is for boundary conditions in open mode.
554: */
555: if (FLAGS(0) & VDIRT)
556: vsync(WTOP);
557:
558: /*
559: * If the current line is after the last displayed line
560: * or the bottom of the screen, then special effort is needed
561: * to get it on the screen. We first try a redraw at the
562: * last line on the screen, hoping it will fill in where @
563: * lines are now. If this doesn't work, then roll it onto
564: * the screen.
565: */
566: if (vcline >= vcnt || LINE(vcline) > WBOT) {
567: short oldhold = hold;
568: hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
569: if (vcline >= vcnt) {
570: register int i = vcline - vcnt + 1;
571:
572: dot -= i;
573: vcline -= i;
574: vroll(i);
575: } else
576: vsyncCL();
577: } else
578: vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
579:
580: /*
581: * Notification on large change for visual
582: * has to be done last or we may lose
583: * the echo area with redisplay.
584: */
585: noteit(1);
586:
587: /*
588: * Finally. Move the cursor onto the current line.
589: */
590: vnline(curs);
591: }
592:
593: /*
594: * Fully cleanup the screen, leaving no @ lines except at end when
595: * line after last won't completely fit. The routine vsync is
596: * more conservative and much less work on dumb terminals.
597: */
598: vredraw(p)
599: register int p;
600: {
601: register int l;
602: register line *tp;
603: char temp[LBSIZE];
604: bool anydl = 0;
605: short oldhold = hold;
606:
607: #ifdef ADEBUG
608: if (trace)
609: tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
610: #endif
611: if (holdupd) {
612: holdupd = 3;
613: return;
614: }
615: if (state == HARDOPEN || splitw)
616: return;
617: if (p < 0 /* || p > WECHO */)
618: error("Internal error: vredraw");
619:
620: /*
621: * Trim the ragged edges (lines which are off the screen but
622: * not yet logically discarded), save the current line, and
623: * search for first logical line affected by the redraw.
624: */
625: vscrap();
626: CP(temp, linebuf);
627: l = 0;
628: tp = dot - vcline;
629: if (vcnt == 0)
630: LINE(0) = WTOP;
631: while (l < vcnt && LINE(l) < p)
632: l++, tp++;
633:
634: /*
635: * We hold off echo area clearing during the redraw in deference
636: * to a final clear of the echo area at the end if appropriate.
637: */
638: heldech = 0;
639: hold |= HOLDECH;
640: for (; l < vcnt && Peekkey != ATTN; l++) {
641: if (l == vcline)
642: strcLIN(temp);
643: else
644: getline(*tp);
645:
646: /*
647: * Delete junk between displayed lines.
648: */
649: if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
650: if (anydl == 0 && DB && CD) {
651: hold = oldhold;
652: vclrech(0);
653: anydl = 1;
654: hold |= HOLDECH;
655: heldech = 0;
656: }
657: vdellin(p, LINE(l) - p, l);
658: }
659:
660: /*
661: * If line image is not know to be up to date, then
662: * redisplay it; else just skip onward.
663: */
664: LINE(l) = p;
665: if (FLAGS(l) & VDIRT) {
666: DEPTH(l) = vdepth();
667: if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
668: vscrap();
669: break;
670: }
671: FLAGS(l) &= ~VDIRT;
672: vreopen(p, lineno(tp), l);
673: p = LINE(l) + DEPTH(l);
674: } else
675: p += DEPTH(l);
676: tp++;
677: }
678:
679: /*
680: * That takes care of lines which were already partially displayed.
681: * Now try to fill the rest of the screen with text.
682: */
683: if (state == VISUAL && p <= WBOT) {
684: int ovcline = vcline;
685:
686: vcline = l;
687: for (; tp <= dol && Peekkey != ATTN; tp++) {
688: getline(*tp);
689: if (p + vdepth() - 1 > WBOT)
690: break;
691: vopen(tp, p);
692: p += DEPTH(vcline);
693: vcline++;
694: }
695: vcline = ovcline;
696: }
697:
698: /*
699: * Thats all the text we can get on.
700: * Now rest of lines (if any) get either a ~ if they
701: * are past end of file, or an @ if the next line won't fit.
702: */
703: for (; p <= WBOT && Peekkey != ATTN; p++)
704: vclrlin(p, tp);
705: strcLIN(temp);
706: hold = oldhold;
707: if (heldech)
708: vclrech(0);
709: #ifdef ADEBUG
710: if (trace)
711: tvliny();
712: #endif
713: }
714:
715: /*
716: * Do the real work in deleting cnt lines starting at line p from
717: * the display. First affected line is line l.
718: */
719: vdellin(p, cnt, l)
720: int p, cnt, l;
721: {
722: register int i;
723:
724: if (cnt == 0)
725: return;
726: if (DL == NOSTR || cnt < 0) {
727: /*
728: * Can't do it; just remember that line l is munged.
729: */
730: FLAGS(l) |= VDIRT;
731: return;
732: }
733: #ifdef ADEBUG
734: if (trace)
735: tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
736: #endif
737: /*
738: * Send the deletes to the screen and then adjust logical
739: * and physical internal data structures.
740: */
741: vgoto(p, 0);
742: if (DL_PARM && (cnt>1 || *DL==0)) {
743: vputp(tgoto(DL_PARM, p, cnt), WECHO-p);
744: }
745: else if (CS && *DL==0) {
746: /* vt100: fake DL by changing scrolling region */
747: vputp(SC, 1); /* Save since CS homes stupid cursor */
748: vputp(tgoto(CS, LINES-1, p), 1);
749: vputp(tgoto(CM, 0, 23), 1); /* Go to lower left corner */
750: for (i=0; i<cnt; i++) /* .. and scroll cnt times */
751: putch('\n'); /* should check NL too */
752: vputp(tgoto(CS, LINES-1, 0), 1);/* restore scrolling region */
753: vputp(RC, 1); /* put cursor back */
754: }
755: else {
756: for (i = 0; i < cnt; i++)
757: vputp(DL, WECHO - p);
758: }
759: vadjDL(p, cnt);
760: vcloseup(l, cnt);
761: }
762: /*
763: * Adjust internal physical screen image to account for deleted lines.
764: */
765: vadjDL(p, cnt)
766: int p, cnt;
767: {
768: char *tlines[TUBELINES];
769: register int from, to;
770:
771: #ifdef ADEBUG
772: if (trace)
773: tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
774: #endif
775: /*
776: * Would like to use structured assignment but early
777: * v7 compiler (released with phototypesetter for v6)
778: * can't hack it.
779: */
780: copy(tlines, vtube, sizeof vtube); /*SASSIGN*/
781: for (from = p + cnt, to = p; from <= WECHO; from++, to++)
782: vtube[to] = tlines[from];
783: for (from = p; to <= WECHO; from++, to++) {
784: vtube[to] = tlines[from];
785: vclrbyte(vtube[to], WCOLS);
786: }
787: }
788: /*
789: * Sync the screen, like redraw but more lazy and willing to leave
790: * @ lines on the screen. VsyncCL syncs starting at the current line.
791: * In any case, if the redraw option is set then all syncs map to redraws
792: * as if vsync didn't exist.
793: */
794: vsyncCL()
795: {
796:
797: vsync(LINE(vcline));
798: }
799:
800: vsync(p)
801: register int p;
802: {
803:
804: if (value(REDRAW))
805: vredraw(p);
806: else
807: vsync1(p);
808: }
809:
810: /*
811: * The guts of a sync. Similar to redraw but
812: * just less ambitous.
813: */
814: vsync1(p)
815: register int p;
816: {
817: register int l;
818: char temp[LBSIZE];
819: register struct vlinfo *vp = &vlinfo[0];
820: short oldhold = hold;
821:
822: #ifdef ADEBUG
823: if (trace)
824: tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
825: #endif
826: if (holdupd) {
827: if (holdupd < 3)
828: holdupd = 2;
829: return;
830: }
831: if (state == HARDOPEN || splitw)
832: return;
833: vscrap();
834: CP(temp, linebuf);
835: if (vcnt == 0)
836: LINE(0) = WTOP;
837: l = 0;
838: while (l < vcnt && vp->vliny < p)
839: l++, vp++;
840: heldech = 0;
841: hold |= HOLDECH;
842: while (p <= WBOT && Peekkey != ATTN) {
843: /*
844: * Want to put a line here if not in visual and first line
845: * or if there are lies left and this line starts before
846: * the current line, or if this line is piled under the
847: * next line (vreplace does this and we undo it).
848: */
849: if (l == 0 && state != VISUAL ||
850: (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
851: if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
852: if (l == vcline)
853: strcLIN(temp);
854: else
855: getline(dot[l - vcline]);
856: /*
857: * Be careful that a long line doesn't cause the
858: * screen to shoot up.
859: */
860: if (l != vcline && (vp->vflags & VDIRT)) {
861: vp->vdepth = vdepth();
862: vp->vflags &= ~VDIRT;
863: if (p + vp->vdepth - 1 > WBOT)
864: break;
865: }
866: vreopen(p, lineDOT() + (l - vcline), l);
867: }
868: p = vp->vliny + vp->vdepth;
869: vp++;
870: l++;
871: } else
872: /*
873: * A physical line between logical lines,
874: * so we settle for an @ at the beginning.
875: */
876: vclrlin(p, dot + (l - vcline)), p++;
877: }
878: strcLIN(temp);
879: hold = oldhold;
880: if (heldech)
881: vclrech(0);
882: }
883:
884: /*
885: * Subtract (logically) cnt physical lines from the
886: * displayed position of lines starting with line l.
887: */
888: vcloseup(l, cnt)
889: int l;
890: register int cnt;
891: {
892: register int i;
893:
894: #ifdef ADEBUG
895: if (trace)
896: tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
897: #endif
898: for (i = l + 1; i <= vcnt; i++)
899: LINE(i) -= cnt;
900: }
901:
902: /*
903: * Workhorse for rearranging line descriptors on changes.
904: * The idea here is that, starting with line l, cnt lines
905: * have been replaced with newcnt lines. All of these may
906: * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
907: * since we may be called from an undo after the screen has
908: * moved a lot. Thus we have to be careful.
909: *
910: * Many boundary conditions here.
911: */
912: vreplace(l, cnt, newcnt)
913: int l, cnt, newcnt;
914: {
915: register int from, to, i;
916: bool savenote = 0;
917:
918: #ifdef ADEBUG
919: if (trace) {
920: tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
921: tvliny();
922: }
923: #endif
924: if (l >= vcnt)
925: return;
926: if (l < 0) {
927: if (l + cnt < 0) {
928: /*
929: * Nothing on the screen is relevant.
930: * Settle for redrawing from scratch (later).
931: */
932: vcnt = 0;
933: return;
934: }
935: /*
936: * Normalize l to top of screen; the add is
937: * really a subtract from cnt since l is negative.
938: */
939: cnt += l;
940: l = 0;
941:
942: /*
943: * Unseen lines were affect so notify (later).
944: */
945: savenote++;
946: }
947:
948: /*
949: * These shouldn't happen
950: * but would cause great havoc.
951: */
952: if (cnt < 0)
953: cnt = 0;
954: if (newcnt < 0)
955: newcnt = 0;
956:
957: /*
958: * Surely worthy of note if more than report
959: * lines were changed.
960: */
961: if (cnt > value(REPORT) || newcnt > value(REPORT))
962: savenote++;
963:
964: /*
965: * Same number of lines affeted as on screen, and we
966: * can insert and delete lines. Thus we just type
967: * over them, since otherwise we will push them
968: * slowly off the screen, a clear lose.
969: */
970: if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
971: if (cnt > 1 && l + cnt > vcnt)
972: savenote++;
973: vdirty(l, newcnt);
974: } else {
975: /*
976: * Lines are going away, squish them out.
977: */
978: if (cnt > 0) {
979: /*
980: * If non-displayed lines went away,
981: * always notify.
982: */
983: if (cnt > 1 && l + cnt > vcnt)
984: savenote++;
985: if (l + cnt >= vcnt)
986: cnt = vcnt - l;
987: else
988: for (from = l + cnt, to = l; from <= vcnt; to++, from++)
989: vlcopy(vlinfo[to], vlinfo[from]);
990: vcnt -= cnt;
991: }
992: /*
993: * Open up space for new lines appearing.
994: * All new lines are piled in the same place,
995: * and will be unpiled by vredraw/vsync, which
996: * inserts lines in front as it unpiles.
997: */
998: if (newcnt > 0) {
999: /*
1000: * Newlines are appearing which may not show,
1001: * so notify (this is only approximately correct
1002: * when long lines are present).
1003: */
1004: if (newcnt > 1 && l + newcnt > vcnt + 1)
1005: savenote++;
1006:
1007: /*
1008: * If there will be more lines than fit, then
1009: * just throw way the rest of the stuff on the screen.
1010: */
1011: if (l + newcnt > WBOT && AL && DL) {
1012: vcnt = l;
1013: goto skip;
1014: }
1015: from = vcnt, to = vcnt + newcnt;
1016: i = TUBELINES - to;
1017: if (i < 0)
1018: from += i, to += i;
1019: vcnt = to;
1020: for (; from >= l; from--, to--)
1021: vlcopy(vlinfo[to], vlinfo[from]);
1022: for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
1023: LINE(to) = LINE(from);
1024: DEPTH(to) = 0;
1025: FLAGS(to) = VDIRT;
1026: }
1027: }
1028: }
1029: skip:
1030: if (Pline == numbline && cnt != newcnt)
1031: /*
1032: * When lines positions are shifted, the numbers
1033: * will be wrong.
1034: */
1035: vdirty(l, WECHO);
1036: if (!savenote)
1037: notecnt = 0;
1038: #ifdef ADEBUG
1039: if (trace)
1040: tvliny();
1041: #endif
1042: }
1043:
1044: /*
1045: * Start harcopy open.
1046: * Print an image of the line to the left of the cursor
1047: * under the full print of the line and position the cursor.
1048: * If we are in a scroll ^D within hardcopy open then all this
1049: * is suppressed.
1050: */
1051: sethard()
1052: {
1053:
1054: if (state == VISUAL)
1055: return;
1056: rubble = 0;
1057: state = HARDOPEN;
1058: if (hold & HOLDROL)
1059: return;
1060: vup1();
1061: LINE(0) = WBOT;
1062: if (Pline == numbline)
1063: vgoto(WBOT, 0), printf("%6d ", lineDOT());
1064: }
1065:
1066: /*
1067: * Mark the lines starting at base for i lines
1068: * as dirty so that they will be checked for correct
1069: * display at next sync/redraw.
1070: */
1071: vdirty(base, i)
1072: register int base, i;
1073: {
1074: register int l;
1075:
1076: for (l = base; l < vcnt; l++) {
1077: if (--i < 0)
1078: return;
1079: FLAGS(l) |= VDIRT;
1080: }
1081: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.