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