1: /* Copyright (c) 1981 Regents of the University of California */
   2: static char *sccsid = "@(#)ex_vadj.c	7.5	10/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:             putchar('\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: }

Defined functions

vadjAL defined in line 340; used 3 times
vadjDL defined in line 765; used 1 times
vcloseup defined in line 888; used 1 times
vdellin defined in line 719; used 2 times
vglitchup defined in line 173; used 2 times
vinslin defined in line 214; used 3 times
vopenup defined in line 295; used 1 times
vredraw defined in line 598; used 5 times
vreopen defined in line 86; used 6 times
vrollup defined in line 368; used 3 times
vscroll defined in line 430; used 1 times
vsync1 defined in line 814; used 3 times

Defined variables

sccsid defined in line 2; never used
Last modified: 1981-10-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2579
Valid CSS Valid XHTML 1.0 Strict