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