home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d352 / mg.lha / MG / src.LZH / mg / window.c < prev    next >
C/C++ Source or Header  |  1990-05-23  |  9KB  |  373 lines

  1. /*
  2.  * Window handling.
  3.  */
  4. #include    "gosmacs.h"
  5.  
  6. #include    "def.h"
  7. #include    "line.h"
  8. #include    "buffer.h"
  9. #include    "window.h"
  10.  
  11. #ifdef    ANSI
  12. #include <stdlib.h>
  13. #endif
  14.  
  15. /*
  16.  * Reposition dot in the current window to line "n". If the argument is
  17.  * positive, it is that line. If it is negative it is that line from the
  18.  * bottom. If it is 0 the window is centered (this is what the standard
  19.  * redisplay code does).
  20.  */
  21. /* ARGSUSED */
  22. reposition(f, n)
  23. {
  24. #ifndef GOSMACS
  25.     if (f & FFUNIV)
  26.         curwp->w_force = curwp->w_ntrows / 2 + 1;
  27.     else if (f & FFARG)
  28.         curwp->w_force = (n >= 0 ? n + 1 : n);
  29.     if ((f & FFARG) == 0)
  30.         sgarbf = TRUE;
  31. #else
  32.     if ((f & FFUNIV) == 0)
  33.         curwp->w_force = n;
  34.     else {
  35.         register short  i = 1;
  36.         register struct line *lp = curwp->w_linep;
  37.  
  38.         while (lp != curwp->w_dotp) {
  39.             i += 1;
  40.             lp = lforw(lp);
  41.         }
  42.         sgarbf = TRUE;
  43.         curwp->w_force = i;
  44.     }
  45. #endif
  46.  
  47.     curwp->w_flag |= WFFORCE;
  48.     return TRUE;
  49. }
  50.  
  51. /*
  52.  * Refresh the display. A call is made to the "ttresize" entry in the
  53.  * terminal handler, which tries to reset "nrow" and "ncol". They will,
  54.  * however, never be set outside of the NROW or NCOL range. If the display
  55.  * changed size, arrange that everything is redone, then call "update" to fix
  56.  * the display. We do this so the new size can be displayed. In the normal
  57.  * case the call to "update" in "main.c" refreshes the screen, and all of the
  58.  * windows need not be recomputed. Note that when you get to the "display
  59.  * unusable" message, the screen will be messed up. If you make the window
  60.  * bigger again, and send another command, everything will get fixed!
  61.  */
  62. /* ARGSUSED */
  63. refresh(f, n)
  64. {
  65.     register struct window *wp;
  66.     register int    oldnrow;
  67.     register int    oldncol;
  68.  
  69.     oldnrow = nrow;
  70.     oldncol = ncol;
  71.     ttresize();
  72.     if (nrow != oldnrow || ncol != oldncol) {
  73.         wp = wheadp;    /* Find last.         */
  74.         while (wp->w_wndp != NULL)
  75.             wp = wp->w_wndp;
  76.         if (nrow < wp->w_toprow + 3) {    /* Check if too small.     */
  77.             ewprintf("Display unusable");
  78.             return (FALSE);
  79.         }
  80.         wp->w_ntrows = nrow - wp->w_toprow - 2;
  81.         sgarbf = TRUE;
  82.         update();
  83.         ewprintf("New size %d by %d", nrow, ncol);
  84.     } else
  85.         sgarbf = TRUE;
  86.     return TRUE;
  87. }
  88.  
  89. /*
  90.  * The command to make the next window (next => down the screen) the current
  91.  * window. There are no real errors, although the command does nothing if
  92.  * there is only 1 window on the screen.
  93.  */
  94. /* ARGSUSED */
  95. nextwind(f, n)
  96. {
  97.     register struct window *wp;
  98.  
  99.     if ((wp = curwp->w_wndp) == NULL)
  100.         wp = wheadp;
  101.     curwp = wp;
  102.     curbp = wp->w_bufp;
  103.     return TRUE;
  104. }
  105.  
  106. #ifdef    GOSMACS
  107. /* not in Gnu Emacs */
  108. /*
  109.  * This command makes the previous window (previous => up the screen) the
  110.  * current window. There arn't any errors, although the command does not do a
  111.  * lot if there is 1 window.
  112.  */
  113. /* ARGSUSED */
  114. prevwind(f, n)
  115. {
  116.     register struct window *wp1;
  117.     register struct window *wp2;
  118.  
  119.     wp1 = wheadp;
  120.     wp2 = curwp;
  121.     if (wp1 == wp2)
  122.         wp2 = NULL;
  123.     while (wp1->w_wndp != wp2)
  124.         wp1 = wp1->w_wndp;
  125.     curwp = wp1;
  126.     curbp = wp1->w_bufp;
  127.     return TRUE;
  128. }
  129. #endif
  130.  
  131. /*
  132.  * This command makes the current window the only window on the screen. Try
  133.  * to set the framing so that "." does not have to move on the display. Some
  134.  * care has to be taken to keep the values of dot and mark in the buffer
  135.  * structures right if the distruction of a window makes a buffer become
  136.  * undisplayed.
  137.  */
  138. /* ARGSUSED */
  139. onlywind(f, n)
  140. {
  141.     register struct window *wp;
  142.     register struct line *lp;
  143.     register int    i;
  144.  
  145.     while (wheadp != curwp) {
  146.         wp = wheadp;
  147.         wheadp = wp->w_wndp;
  148.         if (--wp->w_bufp->b_nwnd == 0) {
  149.             wp->w_bufp->b_dotp = wp->w_dotp;
  150.             wp->w_bufp->b_doto = wp->w_doto;
  151.             wp->w_bufp->b_markp = wp->w_markp;
  152.             wp->w_bufp->b_marko = wp->w_marko;
  153.         }
  154.         free((char *) wp);
  155.     }
  156.     while (curwp->w_wndp != NULL) {
  157.         wp = curwp->w_wndp;
  158.         curwp->w_wndp = wp->w_wndp;
  159.         if (--wp->w_bufp->b_nwnd == 0) {
  160.             wp->w_bufp->b_dotp = wp->w_dotp;
  161.             wp->w_bufp->b_doto = wp->w_doto;
  162.             wp->w_bufp->b_markp = wp->w_markp;
  163.             wp->w_bufp->b_marko = wp->w_marko;
  164.         }
  165.         free((char *) wp);
  166.     }
  167.     lp = curwp->w_linep;
  168.     i = curwp->w_toprow;
  169.     while (i != 0 && lback(lp) != curbp->b_linep) {
  170.         --i;
  171.         lp = lback(lp);
  172.     }
  173.     curwp->w_toprow = 0;
  174.     curwp->w_ntrows = nrow - 2;    /* 2 = mode, echo.     */
  175.     curwp->w_linep = lp;
  176.     curwp->w_flag |= WFMODE | WFHARD;
  177.     return TRUE;
  178. }
  179.  
  180. /*
  181.  * Split the current window. A window smaller than 3 lines cannot be split.
  182.  * The only other error that is possible is a "malloc" failure allocating the
  183.  * structure for the new window.
  184.  */
  185. /* ARGSUSED */
  186. splitwind(f, n)
  187. {
  188.     register struct window *wp;
  189.     register int    ntr;
  190.  
  191.     if (curwp->w_ntrows < 3) {
  192.         ewprintf("Cannot split a %d line window", curwp->w_ntrows);
  193.         return (FALSE);
  194.     }
  195.     if ((wp = (struct window *) malloc(sizeof(struct window))) == NULL) {
  196.         ewprintf("Can't get %d", sizeof(struct window));
  197.         return (FALSE);
  198.     }
  199.     ++curbp->b_nwnd;    /* Displayed twice.     */
  200.     /* Link in new window */
  201.     wp->w_wndp = curwp->w_wndp;
  202.     curwp->w_wndp = wp;
  203.  
  204.     /* Copy old values into new window */
  205.     wp->w_bufp = curbp;
  206.     wp->w_linep = curwp->w_linep;
  207.     wp->w_dotp = curwp->w_dotp;
  208.     wp->w_markp = curwp->w_markp;
  209.     wp->w_doto = curwp->w_doto;
  210.     wp->w_marko = curwp->w_marko;
  211.  
  212.     /* Get size of top (old) window, set sizes & top rows from it */
  213.     ntr = (curwp->w_ntrows - 1) / 2;
  214.     wp->w_toprow = curwp->w_toprow + ntr + 1;
  215.     wp->w_ntrows = (curwp->w_ntrows - 1) - ntr;
  216.     curwp->w_ntrows = ntr;
  217.  
  218.     wp->w_force = 0;
  219.     wp->w_flag = WFMODE | WFHARD;
  220.  
  221.     curwp->w_flag |= WFMODE | WFHARD;
  222.     return TRUE;
  223. }
  224.  
  225. /*
  226.  * Enlarge the current window. Find the window that loses space. Make sure it
  227.  * is big enough. If so, hack the window descriptions, and ask redisplay to
  228.  * do all the hard work. You don't just set "force reframe" because dot would
  229.  * move.
  230.  */
  231. /* ARGSUSED */
  232. enlargewind(f, n)
  233. {
  234.     register struct window *adjwp;
  235.     register struct line *lp;
  236.     register int    i;
  237.  
  238.     if (n < 0)
  239.         return shrinkwind(f, -n);
  240.     if (wheadp->w_wndp == NULL) {
  241.         ewprintf("Only one window");
  242.         return FALSE;
  243.     }
  244.     if ((adjwp = curwp->w_wndp) == NULL) {
  245.         adjwp = wheadp;
  246.         while (adjwp->w_wndp != curwp)
  247.             adjwp = adjwp->w_wndp;
  248.     }
  249.     if (adjwp->w_ntrows <= n) {
  250.         ewprintf("Impossible change");
  251.         return FALSE;
  252.     }
  253.     if (curwp->w_wndp == adjwp) {    /* Shrink below.     */
  254.         lp = adjwp->w_linep;
  255.         for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
  256.             lp = lforw(lp);
  257.         adjwp->w_linep = lp;
  258.         adjwp->w_toprow += n;
  259.     } else {        /* Shrink above.     */
  260.         lp = curwp->w_linep;
  261.         for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i)
  262.             lp = lback(lp);
  263.         curwp->w_linep = lp;
  264.         curwp->w_toprow -= n;
  265.     }
  266.     curwp->w_ntrows += n;
  267.     adjwp->w_ntrows -= n;
  268.     curwp->w_flag |= WFMODE | WFHARD;
  269.     adjwp->w_flag |= WFMODE | WFHARD;
  270.     return TRUE;
  271. }
  272.  
  273. /*
  274.  * Shrink the current window. Find the window that gains space. Hack at the
  275.  * window descriptions. Ask the redisplay to do all the hard work.
  276.  */
  277. shrinkwind(f, n)
  278. {
  279.     register struct window *adjwp;
  280.     register struct line *lp;
  281.     register int    i;
  282.  
  283.     if (n < 0)
  284.         return enlargewind(f, -n);
  285.     if (wheadp->w_wndp == NULL) {
  286.         ewprintf("Only one window");
  287.         return FALSE;
  288.     }
  289.     /*
  290.      * Bit of flakiness - KRANDOM means it was an internal call, and to
  291.      * be trusted implicitly about sizes.
  292.      */
  293.     if (!(f & FFRAND) && curwp->w_ntrows <= n) {
  294.         ewprintf("Impossible change");
  295.         return (FALSE);
  296.     }
  297.     if ((adjwp = curwp->w_wndp) == NULL) {
  298.         adjwp = wheadp;
  299.         while (adjwp->w_wndp != curwp)
  300.             adjwp = adjwp->w_wndp;
  301.     }
  302.     if (curwp->w_wndp == adjwp) {    /* Grow below.         */
  303.         lp = adjwp->w_linep;
  304.         for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i)
  305.             lp = lback(lp);
  306.         adjwp->w_linep = lp;
  307.         adjwp->w_toprow -= n;
  308.     } else {        /* Grow above.         */
  309.         lp = curwp->w_linep;
  310.         for (i = 0; i < n && lp != curbp->b_linep; ++i)
  311.             lp = lforw(lp);
  312.         curwp->w_linep = lp;
  313.         curwp->w_toprow += n;
  314.     }
  315.     curwp->w_ntrows -= n;
  316.     adjwp->w_ntrows += n;
  317.     curwp->w_flag |= WFMODE | WFHARD;
  318.     adjwp->w_flag |= WFMODE | WFHARD;
  319.     return (TRUE);
  320. }
  321.  
  322. /*
  323.  * Delete current window. Call shrink-window to do the screen updating, then
  324.  * throw away the window.
  325.  */
  326. /* ARGSUSED */
  327. delwind(f, n)
  328. {
  329.     register struct window *wp, *nwp;
  330.  
  331.     wp = curwp;        /* Cheap...         */
  332.     /* shrinkwind returning false means only one window... */
  333.     if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
  334.         return FALSE;
  335.     if (--wp->w_bufp->b_nwnd == 0) {
  336.         wp->w_bufp->b_dotp = wp->w_dotp;
  337.         wp->w_bufp->b_doto = wp->w_doto;
  338.         wp->w_bufp->b_markp = wp->w_markp;
  339.         wp->w_bufp->b_marko = wp->w_marko;
  340.     }
  341.     /* since shrinkwind did't crap out, we know we have a second window */
  342.     if (wp == wheadp)
  343.         wheadp = curwp = wp->w_wndp;
  344.     else if ((curwp = wp->w_wndp) == NULL)
  345.         curwp = wheadp;
  346.     curbp = curwp->w_bufp;
  347.     for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
  348.         if (nwp->w_wndp == wp) {
  349.             nwp->w_wndp = wp->w_wndp;
  350.             break;
  351.         }
  352.     free((char *) wp);
  353.     return TRUE;
  354. }
  355. /*
  356.  * Pick a window for a pop-up. Split the screen if there is only one window.
  357.  * Pick the uppermost window that isn't the current window. An LRU algorithm
  358.  * might be better. Return a pointer, or NULL on failure.
  359.  */
  360. struct window  *
  361. wpopup()
  362. {
  363.     register struct window *wp;
  364.  
  365.     if (wheadp->w_wndp == NULL
  366.         && splitwind(FFRAND, 0) == FALSE)
  367.         return NULL;
  368.     wp = wheadp;        /* Find window to use     */
  369.     while (wp != NULL && wp == curwp)
  370.         wp = wp->w_wndp;
  371.     return wp;
  372. }
  373.