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
vadjAL defined in line 348; used 3 times
vadjDL defined in line 773; used 1 times
vcloseup defined in line 896; used 1 times
vdellin defined in line 727; used 2 times
vdirty defined in line 1079; used 10 times
vglitchup defined in line 181; used 2 times
vinslin defined in line 222; used 3 times
vopen defined in line 31; used 8 times
vopenup defined in line 303; used 1 times
vredraw defined in line 606; used 5 times
vreopen defined in line 94; used 6 times
vrollup defined in line 376; used 3 times
vscroll defined in line 438; used 1 times
vsync defined in line 808; used 7 times
vsync1 defined in line 822; used 3 times
vsyncCL defined in line 802; used 7 times

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: 4970
Valid CSS Valid XHTML 1.0 Strict