1: /* Copyright (c) 1981 Regents of the University of California */ 2: static char *sccsid = "@(#)ex_vadj.c 7.5 10/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: putchar('\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: }