|
|
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: /*
750: * Following line modified by Gershon Shamay. Reason - vi didn't work well
751: * in small windows (less than 6 lines). The code shouldn't have
752: * a hardwired number of lines, should just use the parameter LINES.
753: *
754: * vputp(tgoto(CM, 0,23), 1); /* Go to lower left corner
755: */
756:
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 && Peekkey != 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: 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), 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.