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