|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: #include "ex.h" ! 3: #include "ex_tty.h" ! 4: #include "ex_vis.h" ! 5: ! 6: /* ! 7: * Routines to adjust the window, showing specified lines ! 8: * in certain positions on the screen, and scrolling in both ! 9: * directions. Code here is very dependent on mode (open versus visual). ! 10: */ ! 11: ! 12: /* ! 13: * Move in a nonlocal way to line addr. ! 14: * If it isn't on screen put it in specified context. ! 15: * New position for cursor is curs. ! 16: * Like most routines here, we vsave(). ! 17: */ ! 18: vmoveto(addr, curs, context) ! 19: register line *addr; ! 20: char *curs; ! 21: char context; ! 22: { ! 23: ! 24: markit(addr); ! 25: vsave(); ! 26: vjumpto(addr, curs, context); ! 27: } ! 28: ! 29: /* ! 30: * Vjumpto is like vmoveto, but doesn't mark previous ! 31: * context or save linebuf as current line. ! 32: */ ! 33: vjumpto(addr, curs, context) ! 34: register line *addr; ! 35: char *curs; ! 36: char context; ! 37: { ! 38: ! 39: noteit(0); ! 40: if (context != 0) ! 41: vcontext(addr, context); ! 42: else ! 43: vshow(addr, NOLINE); ! 44: noteit(1); ! 45: vnline(curs); ! 46: } ! 47: ! 48: /* ! 49: * Go up or down cnt (negative is up) to new position curs. ! 50: */ ! 51: vupdown(cnt, curs) ! 52: register int cnt; ! 53: char *curs; ! 54: { ! 55: ! 56: if (cnt > 0) ! 57: vdown(cnt, 0, 0); ! 58: else if (cnt < 0) ! 59: vup(-cnt, 0, 0); ! 60: if (vcnt == 0) ! 61: vrepaint(curs); ! 62: else ! 63: vnline(curs); ! 64: } ! 65: ! 66: /* ! 67: * Go up cnt lines, afterwards preferring to be ind ! 68: * logical lines from the top of the screen. ! 69: * If scroll, then we MUST use a scroll. ! 70: * Otherwise clear and redraw if motion is far. ! 71: */ ! 72: vup(cnt, ind, scroll) ! 73: register int cnt, ind; ! 74: bool scroll; ! 75: { ! 76: register int i, tot; ! 77: ! 78: if (dot == one) { ! 79: beep(); ! 80: return; ! 81: } ! 82: vsave(); ! 83: i = lineDOT() - 1; ! 84: if (cnt > i) { ! 85: ind -= cnt - i; ! 86: if (ind < 0) ! 87: ind = 0; ! 88: cnt = i; ! 89: } ! 90: if (!scroll && cnt <= vcline) { ! 91: vshow(dot - cnt, NOLINE); ! 92: return; ! 93: } ! 94: cnt -= vcline, dot -= vcline, vcline = 0; ! 95: if (hold & HOLDWIG) ! 96: goto contxt; ! 97: if (state == VISUAL && !AL && !SR && ! 98: cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO) ! 99: goto okr; ! 100: tot = WECHO - ZERO; ! 101: if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) { ! 102: if (ind > basWLINES / 2) ! 103: ind = basWLINES / 3; ! 104: contxt: ! 105: vcontext(dot + ind - cnt, '.'); ! 106: return; ! 107: } ! 108: okr: ! 109: vrollR(cnt); ! 110: if (scroll) { ! 111: vcline += ind, dot += ind; ! 112: if (vcline >= vcnt) ! 113: dot -= vcline - vcnt + 1, vcline = vcnt - 1; ! 114: getDOT(); ! 115: } ! 116: } ! 117: ! 118: /* ! 119: * Like vup, but scrolling down. ! 120: */ ! 121: vdown(cnt, ind, scroll) ! 122: register int cnt, ind; ! 123: bool scroll; ! 124: { ! 125: register int i, tot; ! 126: ! 127: if (dot == dol) { ! 128: beep(); ! 129: return; ! 130: } ! 131: vsave(); ! 132: i = dol - dot; ! 133: if (cnt > i) { ! 134: ind -= cnt - i; ! 135: if (ind < 0) ! 136: ind = 0; ! 137: cnt = i; ! 138: } ! 139: i = vcnt - vcline - 1; ! 140: if (!scroll && cnt <= i) { ! 141: vshow(dot + cnt, NOLINE); ! 142: return; ! 143: } ! 144: cnt -= i, dot += i, vcline += i; ! 145: if (hold & HOLDWIG) ! 146: goto dcontxt; ! 147: if (!scroll) { ! 148: tot = WECHO - ZERO; ! 149: if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) { ! 150: dcontxt: ! 151: vcontext(dot + cnt, '.'); ! 152: return; ! 153: } ! 154: } ! 155: if (cnt > 0) ! 156: vroll(cnt); ! 157: if (state == VISUAL && scroll) { ! 158: vcline -= ind, dot -= ind; ! 159: if (vcline < 0) ! 160: dot -= vcline, vcline = 0; ! 161: getDOT(); ! 162: } ! 163: } ! 164: ! 165: /* ! 166: * Show line addr in context where on the screen. ! 167: * Work here is in determining new top line implied by ! 168: * this placement of line addr, since we always draw from the top. ! 169: */ ! 170: vcontext(addr, where) ! 171: register line *addr; ! 172: char where; ! 173: { ! 174: register line *top; ! 175: ! 176: getline(*addr); ! 177: if (state != VISUAL) ! 178: top = addr; ! 179: else switch (where) { ! 180: ! 181: case '^': ! 182: addr = vback(addr, basWLINES - vdepth()); ! 183: getline(*addr); ! 184: /* fall into ... */ ! 185: ! 186: case '-': ! 187: top = vback(addr, basWLINES - vdepth()); ! 188: getline(*addr); ! 189: break; ! 190: ! 191: case '.': ! 192: top = vback(addr, basWLINES / 2 - vdepth()); ! 193: getline(*addr); ! 194: break; ! 195: ! 196: default: ! 197: top = addr; ! 198: break; ! 199: } ! 200: if (state == ONEOPEN && LINE(0) == WBOT) ! 201: vup1(); ! 202: vcnt = vcline = 0; ! 203: vclean(); ! 204: if (state == CRTOPEN) ! 205: vup1(); ! 206: vshow(addr, top); ! 207: } ! 208: ! 209: /* ! 210: * Get a clean line. If we are in a hard open ! 211: * we may be able to reuse the line we are on ! 212: * if it is blank. This is a real win. ! 213: */ ! 214: vclean() ! 215: { ! 216: ! 217: if (state != VISUAL && state != CRTOPEN) { ! 218: destcol = 0; ! 219: if (!ateopr()) ! 220: vup1(); ! 221: vcnt = 0; ! 222: } ! 223: } ! 224: ! 225: /* ! 226: * Show line addr with the specified top line on the screen. ! 227: * Top may be 0; in this case have vcontext compute the top ! 228: * (and call us recursively). Eventually, we clear the screen ! 229: * (or its open mode equivalent) and redraw. ! 230: */ ! 231: vshow(addr, top) ! 232: line *addr, *top; ! 233: { ! 234: #ifndef CBREAK ! 235: register bool fried = 0; ! 236: #endif ! 237: register int cnt = addr - dot; ! 238: register int i = vcline + cnt; ! 239: short oldhold = hold; ! 240: ! 241: if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) { ! 242: dot = addr; ! 243: getDOT(); ! 244: vcline = i; ! 245: return; ! 246: } ! 247: if (state != VISUAL) { ! 248: dot = addr; ! 249: vopen(dot, WBOT); ! 250: return; ! 251: } ! 252: if (top == 0) { ! 253: vcontext(addr, '.'); ! 254: return; ! 255: } ! 256: dot = top; ! 257: #ifndef CBREAK ! 258: if (vcookit(2)) ! 259: fried++, vcook(); ! 260: #endif ! 261: oldhold = hold; ! 262: hold |= HOLDAT; ! 263: vclear(); ! 264: vreset(0); ! 265: vredraw(WTOP); ! 266: /* error if vcline >= vcnt ! */ ! 267: vcline = addr - top; ! 268: dot = addr; ! 269: getDOT(); ! 270: hold = oldhold; ! 271: vsync(LASTLINE); ! 272: #ifndef CBREAK ! 273: if (fried) ! 274: flusho(), vraw(); ! 275: #endif ! 276: } ! 277: ! 278: /* ! 279: * reset the state. ! 280: * If inecho then leave us at the beginning of the echo ! 281: * area; we are called this way in the middle of a :e escape ! 282: * from visual, e.g. ! 283: */ ! 284: vreset(inecho) ! 285: bool inecho; ! 286: { ! 287: ! 288: vcnt = vcline = 0; ! 289: WTOP = basWTOP; ! 290: WLINES = basWLINES; ! 291: if (inecho) ! 292: splitw = 1, vgoto(WECHO, 0); ! 293: } ! 294: ! 295: /* ! 296: * Starting from which line preceding tp uses almost (but not more ! 297: * than) cnt physical lines? ! 298: */ ! 299: line * ! 300: vback(tp, cnt) ! 301: register int cnt; ! 302: register line *tp; ! 303: { ! 304: register int d; ! 305: ! 306: if (cnt > 0) ! 307: for (; tp > one; tp--) { ! 308: getline(tp[-1]); ! 309: d = vdepth(); ! 310: if (d > cnt) ! 311: break; ! 312: cnt -= d; ! 313: } ! 314: return (tp); ! 315: } ! 316: ! 317: /* ! 318: * How much scrolling will it take to roll cnt lines starting at tp? ! 319: */ ! 320: vfit(tp, cnt) ! 321: register line *tp; ! 322: int cnt; ! 323: { ! 324: register int j; ! 325: ! 326: j = 0; ! 327: while (cnt > 0) { ! 328: cnt--; ! 329: getline(tp[cnt]); ! 330: j += vdepth(); ! 331: } ! 332: if (tp > dot) ! 333: j -= WBOT - LASTLINE; ! 334: return (j); ! 335: } ! 336: ! 337: /* ! 338: * Roll cnt lines onto the screen. ! 339: */ ! 340: vroll(cnt) ! 341: register int cnt; ! 342: { ! 343: #ifndef CBREAK ! 344: register bool fried = 0; ! 345: #endif ! 346: short oldhold = hold; ! 347: ! 348: #ifdef ADEBUG ! 349: if (trace) ! 350: tfixnl(), fprintf(trace, "vroll(%d)\n", cnt); ! 351: #endif ! 352: if (state != VISUAL) ! 353: hold |= HOLDAT|HOLDROL; ! 354: if (WBOT == WECHO) { ! 355: vcnt = 0; ! 356: if (state == ONEOPEN) ! 357: vup1(); ! 358: } ! 359: #ifndef CBREAK ! 360: if (vcookit(cnt)) ! 361: fried++, vcook(); ! 362: #endif ! 363: for (; cnt > 0 && Peekkey != ATTN; cnt--) { ! 364: dot++, vcline++; ! 365: vopen(dot, LASTLINE); ! 366: vscrap(); ! 367: } ! 368: hold = oldhold; ! 369: if (state == HARDOPEN) ! 370: sethard(); ! 371: vsyncCL(); ! 372: #ifndef CBREAK ! 373: if (fried) ! 374: flusho(), vraw(); ! 375: #endif ! 376: } ! 377: ! 378: /* ! 379: * Roll backwards (scroll up). ! 380: */ ! 381: vrollR(cnt) ! 382: register int cnt; ! 383: { ! 384: register bool fried = 0; ! 385: short oldhold = hold; ! 386: ! 387: #ifdef ADEBUG ! 388: if (trace) ! 389: tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT()); ! 390: #endif ! 391: #ifndef CBREAK ! 392: if (vcookit(cnt)) ! 393: fried++, vcook(); ! 394: #endif ! 395: if (WBOT == WECHO) ! 396: vcnt = 0; ! 397: heldech = 0; ! 398: hold |= HOLDAT|HOLDECH; ! 399: for (; cnt > 0 && Peekkey != ATTN; cnt--) { ! 400: dot--; ! 401: vopen(dot, WTOP); ! 402: vscrap(); ! 403: } ! 404: hold = oldhold; ! 405: if (heldech) ! 406: vclrech(0); ! 407: vsync(LINE(vcnt-1)); ! 408: #ifndef CBREAK ! 409: if (fried) ! 410: flusho(), vraw(); ! 411: #endif ! 412: } ! 413: ! 414: /* ! 415: * Go into cooked mode (allow interrupts) during ! 416: * a scroll if we are at less than 1200 baud and not ! 417: * a 'vi' command, of if we are in a 'vi' command and the ! 418: * scroll is more than 2 full screens. ! 419: * ! 420: * BUG: An interrupt during a scroll in this way ! 421: * dumps to command mode. ! 422: */ ! 423: vcookit(cnt) ! 424: register int cnt; ! 425: { ! 426: ! 427: return (cnt > 1 && (ospeed < B1200 && !initev || cnt > LINES * 2)); ! 428: } ! 429: ! 430: /* ! 431: * Determine displayed depth of current line. ! 432: */ ! 433: vdepth() ! 434: { ! 435: register int d; ! 436: ! 437: d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + IN) / WCOLS; ! 438: #ifdef ADEBUG ! 439: if (trace) ! 440: tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d); ! 441: #endif ! 442: return (d == 0 ? 1 : d); ! 443: } ! 444: ! 445: /* ! 446: * Move onto a new line, with cursor at position curs. ! 447: */ ! 448: vnline(curs) ! 449: char *curs; ! 450: { ! 451: ! 452: if (curs) ! 453: wcursor = curs; ! 454: else if (vmoving) ! 455: wcursor = vfindcol(vmovcol); ! 456: else ! 457: wcursor = vskipwh(linebuf); ! 458: cursor = linebuf; ! 459: vmove(); ! 460: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.