# 2.11BSD#431 - /usr/src/ucb/ex/ex_vadj.c

##### Functions

    sethard           X
    vadjAL            X
    vadjDL            X
    vcloseup          X
    vdellin           X
    vdirty            X
    vglitchup         X
    vinslin           X
    vmoveitup         X
    vopen             X
    vopenup           X
    vredraw           X
    vreopen           X
    vrepaint          X
    vreplace          X
    vrollup           X
    vscrap            X
    vscroll           X
    vsync             X
    vsync1            X
    vsyncCL           X
    vup1              X

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

#### Defined functions

sethard defined in line 1059; used 5 times

- in line 152-156(2)
- in /usr/src/ucb/ex/ex_vops.c line 326
- in /usr/src/ucb/ex/ex_vput.c line 63
- in /usr/src/ucb/ex/ex_vwind.c line 379

vadjAL defined in line 348; used 3 times

- in line 240, 261, 290

vadjDL defined in line 773; used 1 times

- in line 767

vcloseup defined in line 896; used 1 times

- in line 768

vdellin defined in line 727; used 2 times

- in line 202, 665

vdirty defined in line 1079; used 10 times

- in line 68, 981, 1043
- in /usr/src/ucb/ex/ex_subr.c line 934
- in /usr/src/ucb/ex/ex_vmain.c line 199, 1067
- in /usr/src/ucb/ex/ex_vops.c line 60, 104, 160, 754

vglitchup defined in line 181; used 2 times

- in line 109
- in /usr/src/ucb/ex/ex_vput.c line 723

vinslin defined in line 222; used 3 times

- in line 207
- in /usr/src/ucb/ex/ex_vops.c line 670
- in /usr/src/ucb/ex/ex_vput.c line 529

vmoveitup defined in line 405; used 5 times

- in line 389
- in /usr/src/ucb/ex/ex_cmds2.c line 547
- in /usr/src/ucb/ex/ex_v.c line 128
- in /usr/src/ucb/ex/ex_vget.c line 325
- in /usr/src/ucb/ex/ex_vmain.c line 1232

vopen defined in line 31; used 8 times

- in line 699
- in /usr/src/ucb/ex/ex_vops.c line 143, 548, 677
- in /usr/src/ucb/ex/ex_vops2.c line 365
- in /usr/src/ucb/ex/ex_vwind.c line 258, 374, 410

vopenup defined in line 303; used 1 times

- in line 293

vredraw defined in line 606; used 5 times

- in line 576, 813
- in /usr/src/ucb/ex/ex_vmain.c line 93, 212
- in /usr/src/ucb/ex/ex_vwind.c line 274

vreopen defined in line 94; used 6 times

- in line 86, 680, 874
- in /usr/src/ucb/ex/ex_vops.c line 331, 401
- in /usr/src/ucb/ex/ex_vops2.c line 297

vrepaint defined in line 516; used 16 times

- in /usr/src/ucb/ex/ex_subr.c line 935
- in /usr/src/ucb/ex/ex_vmain.c line 91, 222, 258, 497, 668, 827, 1068
- in /usr/src/ucb/ex/ex_vops.c line 123, 379, 565, 715, 744, 773, 916
- in /usr/src/ucb/ex/ex_vwind.c line 70

vreplace defined in line 920; used 8 times

- in /usr/src/ucb/ex/ex_io.c line 482
- in /usr/src/ucb/ex/ex_vmain.c line 492, 814
- in /usr/src/ucb/ex/ex_vops.c line 106, 376, 508, 712, 767

vrollup defined in line 376; used 3 times

- in line 397
- in /usr/src/ucb/ex/ex_vput.c line 342, 1071

vscrap defined in line 466; used 10 times

- in line 341, 525, 633, 676, 841
- in /usr/src/ucb/ex/ex_vget.c line 225
- in /usr/src/ucb/ex/ex_vops.c line 683
- in /usr/src/ucb/ex/ex_vops2.c line 367
- in /usr/src/ucb/ex/ex_vwind.c line 375, 411

vscroll defined in line 438; used 1 times

- in line 390

vsync defined in line 808; used 7 times

- in line 564, 586, 805
- in /usr/src/ucb/ex/ex_vmain.c line 95
- in /usr/src/ucb/ex/ex_vput.c line 728
- in /usr/src/ucb/ex/ex_vwind.c line 280, 416

vsync1 defined in line 822; used 3 times

- in line 815
- in /usr/src/ucb/ex/ex_vops.c line 685
- in /usr/src/ucb/ex/ex_vops2.c line 369

vsyncCL defined in line 802; used 7 times

- in line 584
- in /usr/src/ucb/ex/ex_vops.c line 61, 161, 402, 549
- in /usr/src/ucb/ex/ex_vops2.c line 385
- in /usr/src/ucb/ex/ex_vwind.c line 380

vup1 defined in line 394; used 11 times

- in line 45, 538, 1068
- in /usr/src/ucb/ex/ex_vget.c line 342
- in /usr/src/ucb/ex/ex_vmain.c line 1037
- in /usr/src/ucb/ex/ex_voper.c line 702
- in /usr/src/ucb/ex/ex_vput.c line 732
- in /usr/src/ucb/ex/ex_vwind.c line 210-214(2), 229, 366

#### Defined variables

sccsid defined in line 8; never used

Last modified: 1991-09-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2760 |