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

Defined functions

vadjAL defined in line 336; used 3 times
vadjDL defined in line 765; used 1 times
vcloseup defined in line 895; used 1 times
vdellin defined in line 734; used 2 times
vdirty defined in line 1080; used 9 times
vglitchup defined in line 184; used 2 times
vinslin defined in line 229; used 3 times
vopenup defined in line 291; used 1 times
vredraw defined in line 605; used 5 times
vreopen defined in line 91; used 6 times
vrollup defined in line 364; used 3 times
vscroll defined in line 429; used 1 times
vsync1 defined in line 814; used 3 times
Last modified: 1980-09-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2144
Valid CSS Valid XHTML 1.0 Strict