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