home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume14 / jove4.9 / part04 / wind.c < prev   
C/C++ Source or Header  |  1988-04-25  |  10KB  |  530 lines

  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. }
  530.