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