|
|
1.1 ! root 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: #ifndef lint ! 8: static char *sccsid = "@(#)ex_vadj.c 7.9 (Berkeley) 6/7/85"; ! 9: #endif not lint ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.