|
|
1.1 ! root 1: /*************************************************************************** ! 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * ! 3: * is provided to you without charge, and with no warranty. You may give * ! 4: * away copies of JOVE, including sources, provided that this notice is * ! 5: * included in all the files. * ! 6: ***************************************************************************/ ! 7: ! 8: /* This creates/deletes/divides/grows/shrinks windows. */ ! 9: ! 10: #include "jove.h" ! 11: #include "termcap.h" ! 12: ! 13: private char onlyone[] = "You only have one window!", ! 14: toosmall[] = "Resulting window would be too small."; ! 15: ! 16: Window *curwind, ! 17: *fwind = 0; ! 18: ! 19: /* First line in a Window */ ! 20: ! 21: int ! 22: FLine(w) ! 23: register Window *w; ! 24: { ! 25: register Window *wp = fwind; ! 26: register int lineno = -1; ! 27: ! 28: do { ! 29: if (wp == w) ! 30: return lineno + 1; ! 31: lineno += wp->w_height; ! 32: wp = wp->w_next; ! 33: } while (wp != fwind); ! 34: complain("window?"); ! 35: /* NOTREACHED */ ! 36: } ! 37: ! 38: /* Delete `wp' from the screen. If it is the only window left ! 39: on the screen, then complain. It gives its body ! 40: to the next window if there is one, otherwise the previous ! 41: window gets the body. */ ! 42: ! 43: void ! 44: del_wind(wp) ! 45: register Window *wp; ! 46: { ! 47: register Window *prev = wp->w_prev; ! 48: ! 49: if (one_windp()) ! 50: complain(onlyone); ! 51: ! 52: wp->w_prev->w_next = wp->w_next; ! 53: wp->w_next->w_prev = wp->w_prev; ! 54: ! 55: if (fwind == wp) { ! 56: fwind = wp->w_next; ! 57: fwind->w_height += wp->w_height; ! 58: /* Here try to do something intelligent for redisplay() */ ! 59: SetTop(fwind, prev_line(fwind->w_top, wp->w_height)); ! 60: if (curwind == wp) ! 61: SetWind(fwind); ! 62: } else { ! 63: prev->w_height += wp->w_height; ! 64: if (curwind == wp) ! 65: SetWind(prev); ! 66: } ! 67: #ifdef MAC ! 68: RemoveScrollBar(wp); ! 69: Windchange++; ! 70: #endif ! 71: free((char *) wp); ! 72: } ! 73: ! 74: /* Divide the window WP N times, or at least once. Complains if WP is too ! 75: small to be split into that many pieces. It returns the new window. */ ! 76: ! 77: Window * ! 78: div_wind(wp, n) ! 79: register Window *wp; ! 80: { ! 81: register Window *new; ! 82: int amt; ! 83: ! 84: if (n < 1) ! 85: n = 1; ! 86: amt = wp->w_height / (n + 1); ! 87: if (amt < 2) ! 88: complain(toosmall); ! 89: ! 90: while (--n >= 0) { ! 91: new = (Window *) emalloc(sizeof (Window)); ! 92: new->w_flags = 0; ! 93: new->w_LRscroll = 0; ! 94: ! 95: new->w_height = amt; ! 96: wp->w_height -= amt; ! 97: ! 98: /* set the lines such that w_line is the center in ! 99: each Window */ ! 100: new->w_line = wp->w_line; ! 101: new->w_char = wp->w_char; ! 102: new->w_bufp = wp->w_bufp; ! 103: new->w_top = prev_line(new->w_line, HALF(new)); ! 104: ! 105: /* Link the new window into the list */ ! 106: new->w_prev = wp; ! 107: new->w_next = wp->w_next; ! 108: new->w_next->w_prev = new; ! 109: wp->w_next = new; ! 110: #ifdef MAC ! 111: new->w_control = 0; ! 112: #endif ! 113: } ! 114: #ifdef MAC ! 115: Windchange++; ! 116: #endif ! 117: return new; ! 118: } ! 119: ! 120: /* Initialze the first window setting the bounds to the size of the ! 121: screen. There is no buffer with this window. See parse for the ! 122: setting of this window. */ ! 123: ! 124: void ! 125: winit() ! 126: { ! 127: register Window *w; ! 128: ! 129: w = curwind = fwind = (Window *) emalloc(sizeof (Window)); ! 130: w->w_line = w->w_top = 0; ! 131: w->w_LRscroll = 0; ! 132: w->w_flags = 0; ! 133: w->w_char = 0; ! 134: w->w_next = w->w_prev = fwind; ! 135: w->w_height = ILI; ! 136: #ifdef MAC ! 137: w->w_control = 0; ! 138: Windchange++; ! 139: #endif ! 140: } ! 141: ! 142: /* Change to previous window. */ ! 143: ! 144: void ! 145: PrevWindow() ! 146: { ! 147: register Window *new = curwind->w_prev; ! 148: ! 149: if (Asking) ! 150: complain((char *) 0); ! 151: if (one_windp()) ! 152: complain(onlyone); ! 153: SetWind(new); ! 154: } ! 155: ! 156: /* Make NEW the current Window */ ! 157: ! 158: void ! 159: SetWind(new) ! 160: register Window *new; ! 161: { ! 162: if (!Asking) { /* can you say kludge? */ ! 163: curwind->w_line = curline; ! 164: curwind->w_char = curchar; ! 165: curwind->w_bufp = curbuf; ! 166: } ! 167: if (new == curwind) ! 168: return; ! 169: SetBuf(new->w_bufp); ! 170: if (!inlist(new->w_bufp->b_first, new->w_line)) { ! 171: new->w_line = curline; ! 172: new->w_char = curchar; ! 173: } ! 174: DotTo(new->w_line, new->w_char); ! 175: if (curchar > strlen(linebuf)) ! 176: new->w_char = curchar = strlen(linebuf); ! 177: curwind = new; ! 178: } ! 179: ! 180: /* delete the current window if it isn't the only one left */ ! 181: ! 182: void ! 183: DelCurWindow() ! 184: { ! 185: SetABuf(curwind->w_bufp); ! 186: del_wind(curwind); ! 187: } ! 188: ! 189: /* put the current line of `w' in the middle of the window */ ! 190: ! 191: void ! 192: CentWind(w) ! 193: register Window *w; ! 194: { ! 195: SetTop(w, prev_line(w->w_line, HALF(w))); ! 196: } ! 197: ! 198: int ScrollStep = 0; /* full scrolling */ ! 199: ! 200: /* Calculate the new topline of the window. If ScrollStep == 0 ! 201: it means we should center the current line in the window. */ ! 202: ! 203: void ! 204: CalcWind(w) ! 205: register Window *w; ! 206: { ! 207: register int up; ! 208: int scr_step; ! 209: Line *newtop; ! 210: ! 211: if (ScrollStep == 0) /* Means just center it */ ! 212: CentWind(w); ! 213: else { ! 214: up = inorder(w->w_line, 0, w->w_top, 0); ! 215: if (up == -1) { ! 216: CentWind(w); ! 217: return; ! 218: } ! 219: scr_step = (ScrollStep < 0) ? SIZE(w) + ScrollStep : ! 220: ScrollStep - 1; ! 221: if (up) /* point is above the screen */ ! 222: newtop = prev_line(w->w_line, scr_step); ! 223: else ! 224: newtop = prev_line(w->w_line, (SIZE(w) - 1 - scr_step)); ! 225: if (LineDist(newtop, w->w_top) >= SIZE(w) - 1) ! 226: CentWind(w); ! 227: else ! 228: SetTop(w, newtop); ! 229: } ! 230: } ! 231: ! 232: /* This is bound to C-X 4 [BTF]. To make the screen stay the ! 233: same we have to remember various things, like the current ! 234: top line in the current window. It's sorta gross, but it's ! 235: necessary because of the way this is implemented (i.e., in ! 236: terms of do_find(), do_select() which manipulate the windows. */ ! 237: ! 238: void ! 239: WindFind() ! 240: { ! 241: register Buffer *obuf = curbuf, ! 242: *nbuf; ! 243: Line *ltop = curwind->w_top; ! 244: Bufpos savedot; ! 245: extern void ! 246: FindTag(), ! 247: BufSelect(), ! 248: FindFile(); ! 249: ! 250: DOTsave(&savedot); ! 251: ! 252: switch (waitchar((int *) 0)) { ! 253: case 't': ! 254: case 'T': ! 255: ExecCmd((data_obj *) FindCmd(FindTag)); ! 256: break; ! 257: ! 258: case 'b': ! 259: case 'B': ! 260: ExecCmd((data_obj *) FindCmd(BufSelect)); ! 261: break; ! 262: ! 263: case 'f': ! 264: case 'F': ! 265: ExecCmd((data_obj *) FindCmd(FindFile)); ! 266: break; ! 267: ! 268: default: ! 269: complain("T: find-tag, F: find-file, B: select-buffer."); ! 270: } ! 271: ! 272: nbuf = curbuf; ! 273: SetBuf(obuf); ! 274: SetDot(&savedot); ! 275: SetTop(curwind, ltop); /* there! it's as if we did nothing */ ! 276: ! 277: if (one_windp()) ! 278: (void) div_wind(curwind, 1); ! 279: ! 280: tiewind(curwind->w_next, nbuf); ! 281: SetWind(curwind->w_next); ! 282: } ! 283: ! 284: /* Go into one window mode by deleting all the other windows */ ! 285: ! 286: void ! 287: OneWindow() ! 288: { ! 289: while (curwind->w_next != curwind) ! 290: del_wind(curwind->w_next); ! 291: } ! 292: ! 293: Window * ! 294: windbp(bp) ! 295: register Buffer *bp; ! 296: { ! 297: ! 298: register Window *wp = fwind; ! 299: ! 300: if (bp == 0) ! 301: return 0; ! 302: do { ! 303: if (wp->w_bufp == bp) ! 304: return wp; ! 305: wp = wp->w_next; ! 306: } while (wp != fwind); ! 307: return 0; ! 308: } ! 309: ! 310: /* Change window into the next window. Curwind becomes the new window. */ ! 311: ! 312: void ! 313: NextWindow() ! 314: { ! 315: register Window *new = curwind->w_next; ! 316: ! 317: if (Asking) ! 318: complain((char *) 0); ! 319: if (one_windp()) ! 320: complain(onlyone); ! 321: SetWind(new); ! 322: } ! 323: ! 324: /* Scroll the next Window */ ! 325: ! 326: void ! 327: PageNWind() ! 328: { ! 329: if (one_windp()) ! 330: complain(onlyone); ! 331: NextWindow(); ! 332: NextPage(); ! 333: PrevWindow(); ! 334: } ! 335: ! 336: Window * ! 337: w_nam_typ(name, type) ! 338: register char *name; ! 339: { ! 340: register Window *w; ! 341: register Buffer *b; ! 342: ! 343: b = buf_exists(name); ! 344: w = fwind; ! 345: if (b) do { ! 346: if (w->w_bufp == b) ! 347: return w; ! 348: } while ((w = w->w_next) != fwind); ! 349: ! 350: w = fwind; ! 351: do { ! 352: if (w->w_bufp->b_type == type) ! 353: return w; ! 354: } while ((w = w->w_next) != fwind); ! 355: ! 356: return 0; ! 357: } ! 358: ! 359: /* Put a window with the buffer `name' in it. Erase the buffer if ! 360: `clobber' is non-zero. */ ! 361: ! 362: void ! 363: pop_wind(name, clobber, btype) ! 364: register char *name; ! 365: { ! 366: register Window *wp; ! 367: register Buffer *newb; ! 368: ! 369: if (newb = buf_exists(name)) ! 370: btype = -1; /* if the buffer exists, don't change ! 371: it's type */ ! 372: if ((wp = w_nam_typ(name, btype)) == 0) { ! 373: if (one_windp()) ! 374: SetWind(div_wind(curwind, 1)); ! 375: else ! 376: PrevWindow(); ! 377: } else ! 378: SetWind(wp); ! 379: ! 380: newb = do_select((Window *) 0, name); ! 381: if (clobber) { ! 382: initlist(newb); ! 383: newb->b_modified = NO; ! 384: } ! 385: tiewind(curwind, newb); ! 386: if (btype != -1) ! 387: newb->b_type = btype; ! 388: SetBuf(newb); ! 389: } ! 390: ! 391: void ! 392: GrowWindow() ! 393: { ! 394: WindSize(curwind, abs(arg_value())); ! 395: } ! 396: ! 397: void ! 398: ShrWindow() ! 399: { ! 400: WindSize(curwind, -abs(arg_value())); ! 401: } ! 402: ! 403: /* Change the size of the window by inc. First arg is the window, ! 404: second is the increment. */ ! 405: ! 406: void ! 407: WindSize(w, inc) ! 408: register Window *w; ! 409: register int inc; ! 410: { ! 411: if (one_windp()) ! 412: complain(onlyone); ! 413: ! 414: if (inc == 0) ! 415: return; ! 416: else if (inc < 0) { /* Shrinking this Window. */ ! 417: if (w->w_height + inc < 2) ! 418: complain(toosmall); ! 419: w->w_height += inc; ! 420: w->w_prev->w_height -= inc; ! 421: } else /* Growing the window. */ ! 422: WindSize(w->w_next, -inc); ! 423: #ifdef MAC ! 424: Windchange++; ! 425: #endif ! 426: } ! 427: ! 428: /* Set the topline of the window, calculating its number in the buffer. ! 429: This is for numbering the lines only. */ ! 430: ! 431: void ! 432: SetTop(w, line) ! 433: Window *w; ! 434: register Line *line; ! 435: { ! 436: register Line *lp = w->w_bufp->b_first; ! 437: register int num = 0; ! 438: ! 439: w->w_top = line; ! 440: if (w->w_flags & W_NUMLINES) { ! 441: while (lp) { ! 442: num += 1; ! 443: if (line == lp) ! 444: break; ! 445: lp = lp->l_next; ! 446: } ! 447: w->w_topnum = num; ! 448: } ! 449: } ! 450: ! 451: void ! 452: WNumLines() ! 453: { ! 454: curwind->w_flags ^= W_NUMLINES; ! 455: SetTop(curwind, curwind->w_top); ! 456: } ! 457: ! 458: void ! 459: WVisSpace() ! 460: { ! 461: curwind->w_flags ^= W_VISSPACE; ! 462: ClAndRedraw(); ! 463: } ! 464: ! 465: /* Return the line number that `line' occupies in `windes' */ ! 466: ! 467: int ! 468: in_window(windes, line) ! 469: register Window *windes; ! 470: register Line *line; ! 471: { ! 472: register int i; ! 473: register Line *top = windes->w_top; ! 474: ! 475: for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next) ! 476: if (top == line) ! 477: return FLine(windes) + i; ! 478: return -1; ! 479: } ! 480: ! 481: void ! 482: SplitWind() ! 483: { ! 484: SetWind(div_wind(curwind, is_an_arg() ? (arg_value() - 1) : 1)); ! 485: } ! 486: ! 487: /* Goto the window with the named buffer. If no such window ! 488: exists, pop one and attach the buffer to it. */ ! 489: void ! 490: GotoWind() ! 491: { ! 492: extern Buffer *lastbuf; ! 493: char *bname; ! 494: Window *w; ! 495: ! 496: bname = ask_buf(lastbuf); ! 497: w = curwind->w_next; ! 498: do { ! 499: if (w->w_bufp->b_name == bname) { ! 500: SetABuf(curbuf); ! 501: SetWind(w); ! 502: return; ! 503: } ! 504: w = w->w_next; ! 505: } while (w != curwind); ! 506: SetABuf(curbuf); ! 507: pop_wind(bname, NO, -1); ! 508: } ! 509: ! 510: void ! 511: ScrollRight() ! 512: { ! 513: int amt = (is_an_arg() ? arg_value() : 10); ! 514: ! 515: if (curwind->w_LRscroll - amt < 0) ! 516: curwind->w_LRscroll = 0; ! 517: else ! 518: curwind->w_LRscroll -= amt; ! 519: UpdModLine = YES; ! 520: } ! 521: ! 522: void ! 523: ScrollLeft() ! 524: { ! 525: int amt = (is_an_arg() ? arg_value() : 10); ! 526: ! 527: curwind->w_LRscroll += amt; ! 528: UpdModLine = YES; ! 529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.