1: /************************************************************************* 2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is * 3: * provided to you without charge for use only on a licensed Unix * 4: * system. You may copy JOVE provided that this notice is included with * 5: * the copy. You may not sell copies of this program or versions * 6: * modified for use on microcomputer systems, unless the copies are * 7: * included with a Unix system distribution and the source is provided. * 8: *************************************************************************/ 9: 10: /* This creates/deletes/divides/grows/shrinks windows. */ 11: 12: #include "jove.h" 13: #include "termcap.h" 14: 15: static char onlyone[] = "You only have one window!", 16: toosmall[] = "Resulting window would be too small."; 17: 18: Window *curwind, 19: *fwind = 0; 20: 21: /* First line in a Window */ 22: 23: FLine(w) 24: register Window *w; 25: { 26: register Window *wp = fwind; 27: register int lineno = -1; 28: 29: do { 30: if (wp == w) 31: return lineno + 1; 32: lineno += wp->w_height; 33: wp = wp->w_next; 34: } while (wp != fwind); 35: complain("window?"); 36: /* NOTREACHED */ 37: } 38: 39: /* Delete `wp' from the screen. If it is the only window left 40: on the screen, then complain. It gives its body 41: to the next window if there is one, otherwise the previous 42: window gets the body. */ 43: 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: free((char *) wp); 68: } 69: 70: /* Divide the window WP N times, or at least once. Complains if WP is too 71: small to be split into that many pieces. It returns the new window. */ 72: 73: Window * 74: div_wind(wp, n) 75: register Window *wp; 76: { 77: register Window *new; 78: int amt; 79: 80: if (n < 1) 81: n = 1; 82: amt = wp->w_height / (n + 1); 83: if (amt < 2) 84: complain(toosmall); 85: 86: while (--n >= 0) { 87: new = (Window *) emalloc(sizeof (Window)); 88: new->w_visspace = new->w_numlines = 0; 89: 90: new->w_height = amt; 91: wp->w_height -= amt; 92: 93: /* set the lines such that w_line is the center in 94: each Window */ 95: new->w_line = wp->w_line; 96: new->w_char = wp->w_char; 97: new->w_bufp = wp->w_bufp; 98: new->w_top = prev_line(new->w_line, HALF(new)); 99: 100: /* Link the new window into the list */ 101: new->w_prev = wp; 102: new->w_next = wp->w_next; 103: new->w_next->w_prev = new; 104: wp->w_next = new; 105: } 106: return new; 107: } 108: 109: /* Initialze the first window setting the bounds to the size of the 110: screen. There is no buffer with this window. See parse for the 111: setting of this window. */ 112: 113: winit() 114: { 115: register Window *w; 116: 117: w = curwind = fwind = (Window *) emalloc(sizeof (Window)); 118: w->w_line = w->w_top = 0; 119: w->w_visspace = w->w_numlines = 0; 120: w->w_char = 0; 121: w->w_next = w->w_prev = fwind; 122: w->w_height = ILI; 123: } 124: 125: /* Change to previous window. */ 126: 127: PrevWindow() 128: { 129: register Window *new = curwind->w_prev; 130: 131: if (one_windp()) 132: complain(onlyone); 133: SetWind(new); 134: } 135: 136: /* Make NEW the current Window */ 137: 138: SetWind(new) 139: register Window *new; 140: { 141: if (!Asking){ /* can you say kludge? */ 142: curwind->w_line = curline; 143: curwind->w_char = curchar; 144: curwind->w_bufp = curbuf; 145: } 146: if (new == curwind) 147: return; 148: SetBuf(new->w_bufp); 149: if (!inlist(new->w_bufp->b_first, new->w_line)) { 150: new->w_line = curline; 151: new->w_char = curchar; 152: } 153: DotTo(new->w_line, new->w_char); 154: if (curchar > strlen(linebuf)) 155: new->w_char = curchar = strlen(linebuf); 156: curwind = new; 157: } 158: 159: /* Delete the current window if it isn't the only one left */ 160: 161: DelCurWindow() 162: { 163: del_wind(curwind); 164: } 165: 166: /* Put the current line of `w' in the middle of the window */ 167: 168: CentWind(w) 169: register Window *w; 170: { 171: SetTop(w, prev_line(w->w_line, HALF(w))); 172: } 173: 174: int ScrollStep = 0; /* Full scrolling */ 175: 176: /* Calculate the new topline of the screen. If ScrollStep == 0 177: it means we should center the current line in the window. */ 178: 179: CalcWind(w) 180: register Window *w; 181: { 182: register int up; 183: Line *newtop; 184: 185: if (ScrollStep == 0) /* Means just center it */ 186: CentWind(w); 187: else { 188: up = inorder(w->w_line, 0, w->w_top, 0); 189: if (up == -1) { 190: CentWind(w); 191: return; 192: } 193: if (up) /* Dot is above the screen */ 194: newtop = prev_line(w->w_line, min(ScrollStep - 1, HALF(w))); 195: else 196: newtop = prev_line(w->w_line, (SIZE(w) - 1) - 197: min(ScrollStep - 1, HALF(w))); 198: if (LineDist(newtop, w->w_top) >= SIZE(w) - 1) 199: CentWind(w); 200: else 201: SetTop(w, newtop); 202: } 203: } 204: 205: WindFind() 206: { 207: register Buffer *savebuf = curbuf; 208: Bufpos savedot; 209: extern int 210: FindTag(), 211: BufSelect(), 212: FindFile(); 213: 214: DOTsave(&savedot); 215: 216: switch (waitchar()) { 217: case 't': 218: case 'T': 219: ExecCmd((data_obj *) FindCmd(FindTag)); 220: break; 221: 222: case 'b': 223: case 'B': 224: ExecCmd((data_obj *) FindCmd(BufSelect)); 225: break; 226: 227: case 'f': 228: case 'F': 229: ExecCmd((data_obj *) FindCmd(FindFile)); 230: break; 231: 232: default: 233: complain("T: find-tag, F: find-file, B: select-buffer."); 234: } 235: 236: if (one_windp()) 237: (void) div_wind(curwind, 1); 238: 239: tiewind(curwind->w_next, curbuf); 240: SetBuf(savebuf); /* Back to original buffer */ 241: SetDot(&savedot); /* in original position */ 242: tiewind(curwind, curbuf); 243: SetWind(curwind->w_next); 244: } 245: 246: /* Go into one window mode by deleting all the other windows */ 247: 248: OneWindow() 249: { 250: while (curwind->w_next != curwind) 251: del_wind(curwind->w_next); 252: } 253: 254: Window * 255: windbp(bp) 256: register Buffer *bp; 257: { 258: 259: register Window *wp = fwind; 260: 261: if (bp == 0) 262: return 0; 263: do { 264: if (wp->w_bufp == bp) 265: return wp; 266: wp = wp->w_next; 267: } while (wp != fwind); 268: return 0; 269: } 270: 271: /* Look for a window containing a buffer whose name is `name' */ 272: 273: Window * 274: windlook(name) 275: register char *name; 276: { 277: return windbp(buf_exists(name)); 278: } 279: 280: /* Change window into the next window. Curwind becomes the new window. */ 281: 282: NextWindow() 283: { 284: register Window *new = curwind->w_next; 285: 286: if (one_windp()) 287: complain(onlyone); 288: SetWind(new); 289: } 290: 291: /* Scroll the next Window */ 292: 293: PageNWind() 294: { 295: if (one_windp()) 296: complain(onlyone); 297: NextWindow(); 298: NextPage(); 299: PrevWindow(); 300: } 301: 302: Window * 303: w_nam_typ(name, type) 304: register char *name; 305: { 306: register Window *w; 307: register Buffer *b; 308: 309: b = buf_exists(name); 310: w = fwind; 311: if (b) do { 312: if (w->w_bufp == b) 313: return w; 314: } while ((w = w->w_next) != fwind); 315: 316: w = fwind; 317: do { 318: if (w->w_bufp->b_type == type) 319: return w; 320: } while ((w = w->w_next) != fwind); 321: 322: return 0; 323: } 324: 325: /* Put a window with the buffer `name' in it. Erase the buffer if 326: `clobber' is non-zero. */ 327: 328: pop_wind(name, clobber, btype) 329: register char *name; 330: { 331: register Window *wp; 332: register Buffer *newb; 333: 334: if ((wp = w_nam_typ(name, btype)) == 0) { 335: if (one_windp()) 336: SetWind(div_wind(curwind, 1)); 337: else 338: PrevWindow(); 339: } else 340: SetWind(wp); 341: 342: newb = do_select((Window *) 0, name); 343: if (clobber) 344: initlist(newb); 345: tiewind(curwind, newb); 346: #ifdef IPROCS 347: if (newb->b_type != B_IPROCESS && btype != -1) 348: #else 349: if (btype != -1) 350: #endif 351: newb->b_type = btype; 352: SetBuf(newb); 353: } 354: 355: GrowWindow() 356: { 357: WindSize(curwind, abs(exp)); 358: } 359: 360: ShrWindow() 361: { 362: WindSize(curwind, -abs(exp)); 363: } 364: 365: /* Change the size of the window by inc. First arg is the window, 366: second is the increment. */ 367: 368: WindSize(w, inc) 369: register Window *w; 370: register int inc; 371: { 372: if (one_windp()) 373: complain(onlyone); 374: 375: if (inc == 0) 376: return; 377: else if (inc < 0) { /* Shrinking this Window. */ 378: if (w->w_height + inc < 2) 379: complain(toosmall); 380: w->w_height += inc; 381: w->w_prev->w_height -= inc; 382: } else /* Growing the window. */ 383: WindSize(w->w_next, -inc); 384: } 385: 386: /* Set the topline of the window, calculating its number in the buffer. 387: This is for numbering the lines only. */ 388: 389: SetTop(w, line) 390: Window *w; 391: register Line *line; 392: { 393: register Line *lp = w->w_bufp->b_first; 394: register int num = 0; 395: 396: w->w_top = line; 397: if (w->w_numlines) { 398: while (lp) { 399: num++; 400: if (line == lp) 401: break; 402: lp = lp->l_next; 403: } 404: w->w_topnum = num; 405: } 406: } 407: 408: WNumLines() 409: { 410: curwind->w_numlines = !curwind->w_numlines; 411: SetTop(curwind, curwind->w_top); 412: } 413: 414: WVisSpace() 415: { 416: curwind->w_visspace = !curwind->w_visspace; 417: ClAndRedraw(); 418: } 419: 420: /* Return the line number that `line' occupies in `windes' */ 421: 422: in_window(windes, line) 423: register Window *windes; 424: register Line *line; 425: { 426: register int i; 427: register Line *top = windes->w_top; 428: 429: for (i = 0; top && i < windes->w_height - 1; i++, top = top->l_next) 430: if (top == line) 431: return FLine(windes) + i; 432: return -1; 433: } 434: 435: SplitWind() 436: { 437: SetWind(div_wind(curwind, exp_p ? (exp - 1) : 1)); 438: }