home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / newemacs / window.c < prev    next >
C/C++ Source or Header  |  1986-02-04  |  9KB  |  372 lines

  1. /*
  2.  * Window management.
  3.  * Some of the functions are internal,
  4.  * and some are attached to keys that the
  5.  * user actually types.
  6.  */
  7. #include    <stdio.h>
  8. #include    "ed.h"
  9.  
  10. /*
  11.  * Reposition dot in the current
  12.  * window to line "n". If the argument is
  13.  * positive, it is that line. If it is negative it
  14.  * is that line from the bottom. If it is 0 the window
  15.  * is centered (this is what the standard redisplay code
  16.  * does). With no argument it defaults to 1. Bound to
  17.  * M-!. Because of the default, it works like in
  18.  * Gosling.
  19.  */
  20. reposition(f, n)
  21. {
  22.     curwp->w_force = n;
  23.     curwp->w_flag |= WFFORCE;
  24.     return (TRUE);
  25. }
  26.  
  27. /*
  28.  * Refresh the screen. With no
  29.  * argument, it just does the refresh. With an
  30.  * argument it recenters "." in the current
  31.  * window. Bound to "C-L".
  32.  */
  33. refresh(f, n)
  34. {
  35.     if (f == FALSE)
  36.         sgarbf = TRUE;
  37.     else {
  38.         curwp->w_force = 0;        /* Center dot.        */
  39.         curwp->w_flag |= WFFORCE;
  40.     }
  41.     return (TRUE);
  42. }
  43.  
  44. /*
  45.  * The command make the next
  46.  * window (next => down the screen)
  47.  * the current window. There are no real
  48.  * errors, although the command does
  49.  * nothing if there is only 1 window on
  50.  * the screen. Bound to "C-X C-N".
  51.  */
  52. nextwind(f, n)
  53. {
  54.     register WINDOW    *wp;
  55.  
  56.     if (!(wp=curwp->w_wndp))
  57.         wp = wheadp;
  58.     curwp = wp;
  59.     curbp = wp->w_bufp;
  60.     return (TRUE);
  61. }
  62.  
  63. /*
  64.  * This command makes the previous
  65.  * window (previous => up the screen) the
  66.  * current window. There arn't any errors,
  67.  * although the command does not do a lot
  68.  * if there is 1 window.
  69.  */
  70. prevwind(f, n)
  71. {
  72.     register WINDOW    *wp1;
  73.     register WINDOW    *wp2;
  74.  
  75.     wp1 = wheadp;
  76.     wp2 = curwp;
  77.     if (wp1 == wp2)
  78.         wp2 = NULL;
  79.     while (wp1->w_wndp != wp2)
  80.         wp1 = wp1->w_wndp;
  81.     curwp = wp1;
  82.     curbp = wp1->w_bufp;
  83.     return (TRUE);
  84. }
  85.  
  86. /*
  87.  * This command moves the current
  88.  * window down by "arg" lines. Recompute
  89.  * the top line in the window. The move up and
  90.  * move down code is almost completely the same;
  91.  * most of the work has to do with reframing the
  92.  * window, and picking a new dot. We share the
  93.  * code by having "move down" just be an interface
  94.  * to "move up". Magic. Bound to "C-X C-N".
  95.  */
  96. mvdnwind(f, n)
  97. register int    n;
  98. {
  99.     return (mvupwind(f, -n));
  100. }
  101.  
  102. /*
  103.  * Move the current window up by "arg"
  104.  * lines. Recompute the new top line of the window.
  105.  * Look to see if "." is still on the screen. If it is,
  106.  * you win. If it isn't, then move "." to center it
  107.  * in the new framing of the window (this command does
  108.  * not really move "."; it moves the frame). Bound
  109.  * to "C-X C-P".
  110.  */
  111. mvupwind(f, n)
  112. register int    n;
  113. {
  114.     register LINE    *lp;
  115.     register int    i;
  116.  
  117.     lp = curwp->w_linep;
  118.     if (n < 0) {
  119.         while (n++ && lp!=curbp->b_linep)
  120.             lp = lforw(lp);
  121.     } else {
  122.         while (n-- && lback(lp)!=curbp->b_linep)
  123.             lp = lback(lp);
  124.     }
  125.     curwp->w_linep = lp;
  126.     curwp->w_flag |= WFHARD;        /* Mode line is OK.    */
  127.     for (i=0; i<curwp->w_ntrows; ++i) {
  128.         if (lp == curwp->w_dotp)
  129.             return (TRUE);
  130.         if (lp == curbp->b_linep)
  131.             break;
  132.         lp = lforw(lp);
  133.     }
  134.     lp = curwp->w_linep;
  135.     i  = curwp->w_ntrows/2;
  136.     while (i-- && lp!=curbp->b_linep)
  137.         lp = lforw(lp);
  138.     curwp->w_dotp  = lp;
  139.     curwp->w_doto  = 0;
  140.     return (TRUE);
  141. }
  142.  
  143. /*
  144.  * This command makes the current
  145.  * window the only window on the screen.
  146.  * Bound to "C-X 1". Try to set the framing
  147.  * so that "." does not have to move on
  148.  * the display. Some care has to be taken
  149.  * to keep the values of dot and mark
  150.  * in the buffer structures right if the
  151.  * distruction of a window makes a buffer
  152.  * become undisplayed.
  153.  */
  154. onlywind(f, n)
  155. {
  156.     register WINDOW    *wp;
  157.     register LINE    *lp;
  158.     register int    i;
  159.  
  160.     while (wheadp != curwp) {
  161.         wp = wheadp;
  162.         wheadp = wp->w_wndp;
  163.         if (!--wp->w_bufp->b_nwnd) {
  164.             wp->w_bufp->b_dotp  = wp->w_dotp;
  165.             wp->w_bufp->b_doto  = wp->w_doto;
  166.             wp->w_bufp->b_markp = wp->w_markp;
  167.             wp->w_bufp->b_marko = wp->w_marko;
  168.         }
  169.         free((char *) wp);
  170.     }
  171.     while (curwp->w_wndp) {
  172.         wp = curwp->w_wndp;
  173.         curwp->w_wndp = wp->w_wndp;
  174.         if (!--wp->w_bufp->b_nwnd) {
  175.             wp->w_bufp->b_dotp  = wp->w_dotp;
  176.             wp->w_bufp->b_doto  = wp->w_doto;
  177.             wp->w_bufp->b_markp = wp->w_markp;
  178.             wp->w_bufp->b_marko = wp->w_marko;
  179.         }
  180.         free((char *) wp);
  181.     }
  182.     lp = curwp->w_linep;
  183.     i  = curwp->w_toprow;
  184.     while (i && lback(lp)!=curbp->b_linep) {
  185.         --i;
  186.         lp = lback(lp);
  187.     }
  188.     curwp->w_toprow = 0;
  189.     curwp->w_ntrows = NROW-1;
  190.     curwp->w_linep  = lp;
  191.     curwp->w_flag  |= WFMODE|WFHARD;
  192.     return (TRUE);
  193. }
  194.  
  195. /*
  196.  * Split the current window. A window
  197.  * smaller than 3 lines cannot be split.
  198.  * The only other error that is possible is
  199.  * a "malloc" failure allocating the structure
  200.  * for the new window. Bound to "C-X 2".
  201.  */
  202. splitwind(f, n)
  203. {
  204.     register WINDOW    *wp;
  205.     register LINE    *lp;
  206.     register int    ntru;
  207.     register int    ntrl;
  208.     register int    ntrd;
  209.     register WINDOW    *wp1;
  210.     register WINDOW    *wp2;
  211.  
  212.     if (curwp->w_ntrows < 3) {
  213.         mlwrite("Cannot split a %d line window", curwp->w_ntrows);
  214.         return (FALSE);
  215.     }
  216.     if (!(wp = (WINDOW *) malloc(sizeof(WINDOW)))) {
  217.         mlwrite("Cannot allocate WINDOW block");
  218.         return (FALSE);
  219.     }
  220.     ++curbp->b_nwnd;            /* Displayed twice.    */
  221.     wp->w_bufp  = curbp;
  222.     wp->w_dotp  = curwp->w_dotp;
  223.     wp->w_doto  = curwp->w_doto;
  224.     wp->w_markp = curwp->w_markp;
  225.     wp->w_marko = curwp->w_marko;
  226.     wp->w_flag  = wp->w_force = 0;
  227.     ntru = (curwp->w_ntrows-1) / 2;        /* Upper size        */
  228.     ntrl = (curwp->w_ntrows-1) - ntru;    /* Lower size        */
  229.     lp = curwp->w_linep;
  230.     for (ntrd = 0; lp != curwp->w_dotp; ntrd++)
  231.         lp = lforw(lp);
  232.     lp = curwp->w_linep;
  233.     if (ntrd <= ntru) {            /* Old is upper window.    */
  234.         if (ntrd == ntru)        /* Hit mode line.    */
  235.             lp = lforw(lp);
  236.         curwp->w_ntrows = ntru;
  237.         wp->w_wndp = curwp->w_wndp;
  238.         curwp->w_wndp = wp;
  239.         wp->w_toprow = curwp->w_toprow+ntru+1;
  240.         wp->w_ntrows = ntrl;
  241.     } else {                /* Old is lower window    */
  242.         wp1 = NULL;
  243.         for (wp2 = wheadp; wp2 != curwp; wp2 = wp2->w_wndp) wp1 = wp2;
  244.         if (!wp1) wheadp = wp;
  245.         else wp1->w_wndp = wp;
  246.         wp->w_wndp   = curwp;
  247.         wp->w_toprow = curwp->w_toprow;
  248.         wp->w_ntrows = ntru++;
  249.         curwp->w_toprow += ntru;
  250.         curwp->w_ntrows  = ntrl;
  251.         while (ntru--) lp = lforw(lp);
  252.     }
  253.     curwp->w_linep = wp->w_linep = lp;    /* Adjust the top lines    */
  254.                         /* if necessary.    */
  255.     curwp->w_flag |= WFMODE|WFHARD;
  256.     wp->w_flag |= WFMODE|WFHARD;
  257.     return (TRUE);
  258. }
  259.  
  260. /*
  261.  * Enlarge the current window.
  262.  * Find the window that loses space. Make
  263.  * sure it is big enough. If so, hack the window
  264.  * descriptions, and ask redisplay to do all the
  265.  * hard work. You don't just set "force reframe"
  266.  * because dot would move. Bound to "C-X Z".
  267.  */
  268. enlargewind(f, n)
  269. {
  270.     register WINDOW    *adjwp;
  271.     register LINE    *lp;
  272.     register int    i;
  273.  
  274.     if (n < 0)
  275.         return (shrinkwind(f, -n));
  276.     if (!wheadp->w_wndp) {
  277.         mlwrite("Only one window");
  278.         return (FALSE);
  279.     }
  280.     if (!(adjwp=curwp->w_wndp)) {
  281.         for (adjwp=wheadp; adjwp->w_wndp!=curwp;adjwp=adjwp->w_wndp) {};
  282.     }
  283.     if (adjwp->w_ntrows <= n) {
  284.         mlwrite("Impossible change");
  285.         return (FALSE);
  286.     }
  287.     if (curwp->w_wndp == adjwp) {        /* Shrink below.    */
  288.         lp = adjwp->w_linep;
  289.         for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  290.             lp = lforw(lp);
  291.         adjwp->w_linep  = lp;
  292.         adjwp->w_toprow += n;
  293.     } else {                /* Shrink above.    */
  294.         lp = curwp->w_linep;
  295.         for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  296.             lp = lback(lp);
  297.         curwp->w_linep  = lp;
  298.         curwp->w_toprow -= n;
  299.     }
  300.     curwp->w_ntrows += n;
  301.     adjwp->w_ntrows -= n;
  302.     curwp->w_flag |= WFMODE|WFHARD;
  303.     adjwp->w_flag |= WFMODE|WFHARD;
  304.     return (TRUE);
  305. }
  306.  
  307. /*
  308.  * Shrink the current window.
  309.  * Find the window that gains space. Hack at
  310.  * the window descriptions. Ask the redisplay to
  311.  * do all the hard work. Bound to "C-X C-Z".
  312.  */
  313. shrinkwind(f, n)
  314. {
  315.     register WINDOW    *adjwp;
  316.     register LINE    *lp;
  317.     register int    i;
  318.  
  319.     if (n < 0)
  320.         return (enlargewind(f, -n));
  321.     if (!wheadp->w_wndp) {
  322.         mlwrite("Only one window");
  323.         return (FALSE);
  324.     }
  325.     if (!(adjwp=curwp->w_wndp)) {
  326.         for (adjwp=wheadp;adjwp->w_wndp!=curwp;adjwp=adjwp->w_wndp) {};
  327.     }
  328.     if (curwp->w_ntrows <= n) {
  329.         mlwrite("Impossible change");
  330.         return (FALSE);
  331.     }
  332.     if (curwp->w_wndp == adjwp) {        /* Grow below.        */
  333.         lp = adjwp->w_linep;
  334.         for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  335.             lp = lback(lp);
  336.         adjwp->w_linep  = lp;
  337.         adjwp->w_toprow -= n;
  338.     } else {                /* Grow above.        */
  339.         lp = curwp->w_linep;
  340.         for (i=0; i<n && lp!=curbp->b_linep; ++i)
  341.             lp = lforw(lp);
  342.         curwp->w_linep  = lp;
  343.         curwp->w_toprow += n;
  344.     }
  345.     curwp->w_ntrows -= n;
  346.     adjwp->w_ntrows += n;
  347.     curwp->w_flag |= WFMODE|WFHARD;
  348.     adjwp->w_flag |= WFMODE|WFHARD;
  349.     return (TRUE);
  350. }
  351.  
  352. /*
  353.  * Pick a window for a pop-up.
  354.  * Split the screen if there is only
  355.  * one window. Pick the uppermost window that
  356.  * isn't the current window. An LRU algorithm
  357.  * might be better. Return a pointer, or
  358.  * NULL on error.
  359.  */
  360. WINDOW    *
  361. wpopup()
  362. {
  363.     register WINDOW    *wp;
  364.  
  365.     if (!wheadp->w_wndp        /* Only 1 window    */
  366.     && splitwind(FALSE, 0) == FALSE)     /* and it won't split    */
  367.         return (NULL);
  368.     /* Find window to use    */
  369.     for (wp = wheadp; wp && wp==curwp; wp = wp->w_wndp) {};
  370.     return (wp);
  371. }
  372.