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: }

Defined functions

CentWind defined in line 191; used 6 times
DelCurWindow defined in line 182; used 4 times
FLine defined in line 21; used 5 times
GotoWind defined in line 489; used 4 times
GrowWindow defined in line 391; used 4 times
OneWindow defined in line 286; used 4 times
PageNWind defined in line 326; used 4 times
PrevWindow defined in line 144; used 6 times
ScrollLeft defined in line 522; used 2 times
ScrollRight defined in line 510; used 2 times
SetTop defined in line 431; used 13 times
ShrWindow defined in line 397; used 4 times
SplitWind defined in line 481; used 4 times
WNumLines defined in line 451; used 4 times
WVisSpace defined in line 458; used 4 times
WindFind defined in line 238; used 4 times
WindSize defined in line 406; used 6 times
del_wind defined in line 43; used 6 times
div_wind defined in line 77; used 6 times
w_nam_typ defined in line 336; used 3 times
windbp defined in line 293; used 5 times
winit defined in line 124; used 3 times

Defined variables

ScrollStep defined in line 198; used 9 times
curwind defined in line 16; used 89 times
fwind defined in line 17; used 41 times
onlyone defined in line 13; used 5 times
Last modified: 1988-03-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3689
Valid CSS Valid XHTML 1.0 Strict