home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_02 / window.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  23KB  |  877 lines

  1. /*
  2.  * Window management. Some of the functions are internal, and some are
  3.  * attached to keys that the user actually types.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include        "estruct.h"
  8. #include    "edef.h"
  9.  
  10. #if    ST520 & MEGAMAX
  11. overlay    "window"
  12. #endif
  13.  
  14. /*
  15.  * Reposition dot in the current window to line "n". If the argument is
  16.  * positive, it is that line. If it is negative it is that line from the
  17.  * bottom. If it is 0 the window is centered (this is what the standard
  18.  * redisplay code does). With no argument it defaults to 0. Bound to M-!.
  19.  */
  20. reposition(f, n)
  21.     {
  22.     if (f == FALSE)    /* default to 0 to center screen */
  23.     n = 0;
  24.     curwp->w_force = n;
  25.     curwp->w_flag |= WFFORCE;
  26.     return (TRUE);
  27.     }
  28.  
  29. /*
  30.  * Refresh the screen. With no argument, it just does the refresh. With an
  31.  * argument it recenters "." in the current window. Bound to "C-L".
  32.  */
  33. refresh(f, n)
  34.     {
  35.     if (f == FALSE)
  36.         sgarbf = TRUE;
  37.     else
  38.         {
  39.         curwp->w_force = 0;             /* Center dot. */
  40.         curwp->w_flag |= WFFORCE;
  41.         }
  42.  
  43.     return (TRUE);
  44.     }
  45.  
  46. /*
  47.  * The command make the next window (next => down the screen) the current
  48.  * window. There are no real errors, although the command does nothing if
  49.  * there is only 1 window on the screen. Bound to "C-X C-N".
  50.  *
  51.  * with an argument this command finds the <n>th window from the top
  52.  *
  53.  */
  54. nextwind(f, n)
  55.  
  56. int f, n;    /* default flag and numeric argument */
  57.  
  58. {
  59.     register WINDOW *wp;
  60.     register int nwindows;        /* total number of windows */
  61.  
  62.     if (f) {
  63.  
  64.         /* first count the # of windows */
  65.         wp = wheadp;
  66.         nwindows = 1;
  67.         while (wp->w_wndp != NULL) {
  68.             nwindows++;
  69.             wp = wp->w_wndp;
  70.         }
  71.  
  72.         /* if the argument is negative, it is the nth window
  73.            from the bottom of the screen            */
  74.         if (n < 0)
  75.             n = nwindows + n + 1;
  76.  
  77.         /* if an argument, give them that window from the top */
  78.         if (n > 0 && n <= nwindows) {
  79.             wp = wheadp;
  80.             while (--n)
  81.                 wp = wp->w_wndp;
  82.         } else {
  83.             mlwrite("Window number out of range");
  84.             return(FALSE);
  85.         }
  86.     } else
  87.         if ((wp = curwp->w_wndp) == NULL)
  88.             wp = wheadp;
  89.     curwp = wp;
  90.     curbp = wp->w_bufp;
  91.     upmode();
  92.     return (TRUE);
  93. }
  94.  
  95. /*
  96.  * This command makes the previous window (previous => up the screen) the
  97.  * current window. There arn't any errors, although the command does not do a
  98.  * lot if there is 1 window.
  99.  */
  100. prevwind(f, n)
  101. {
  102.     register WINDOW *wp1;
  103.     register WINDOW *wp2;
  104.  
  105.     /* if we have an argument, we mean the nth window from the bottom */
  106.     if (f)
  107.         return(nextwind(f, -n));
  108.  
  109.     wp1 = wheadp;
  110.     wp2 = curwp;
  111.  
  112.     if (wp1 == wp2)
  113.         wp2 = NULL;
  114.  
  115.     while (wp1->w_wndp != wp2)
  116.         wp1 = wp1->w_wndp;
  117.  
  118.     curwp = wp1;
  119.     curbp = wp1->w_bufp;
  120.     upmode();
  121.     return (TRUE);
  122. }
  123.  
  124. /*
  125.  * This command moves the current window down by "arg" lines. Recompute the
  126.  * top line in the window. The move up and move down code is almost completely
  127.  * the same; most of the work has to do with reframing the window, and picking
  128.  * a new dot. We share the code by having "move down" just be an interface to
  129.  * "move up". Magic. Bound to "C-X C-N".
  130.  */
  131. mvdnwind(f, n)
  132.  
  133. int n;
  134.  
  135. {
  136.     return (mvupwind(f, -n));
  137. }
  138.  
  139. /*
  140.  * Move the current window up by "arg" lines. Recompute the new top line of
  141.  * the window. Look to see if "." is still on the screen. If it is, you win.
  142.  * If it isn't, then move "." to center it in the new framing of the window
  143.  * (this command does not really move "."; it moves the frame). Bound to
  144.  * "C-X C-P".
  145.  */
  146. mvupwind(f, n)
  147.     int n;
  148.  
  149.     {
  150.     register LINE *lp;
  151.     register int i;
  152.  
  153.     lp = curwp->w_linep;
  154.  
  155.     if (n < 0)
  156.         {
  157.         while (n++ && lp!=curbp->b_linep)
  158.             lp = lforw(lp);
  159.         }
  160.     else
  161.         {
  162.         while (n-- && lback(lp)!=curbp->b_linep)
  163.             lp = lback(lp);
  164.         }
  165.  
  166.     curwp->w_linep = lp;
  167.     curwp->w_flag |= WFHARD;            /* Mode line is OK. */
  168.  
  169.     for (i = 0; i < curwp->w_ntrows; ++i)
  170.         {
  171.         if (lp == curwp->w_dotp)
  172.             return (TRUE);
  173.         if (lp == curbp->b_linep)
  174.             break;
  175.         lp = lforw(lp);
  176.         }
  177.  
  178.     lp = curwp->w_linep;
  179.     i  = curwp->w_ntrows/2;
  180.  
  181.     while (i-- && lp != curbp->b_linep)
  182.         lp = lforw(lp);
  183.  
  184.     curwp->w_dotp  = lp;
  185.     curwp->w_doto  = 0;
  186.     return (TRUE);
  187.     }
  188.  
  189. /*
  190.  * This command makes the current window the only window on the screen. Bound
  191.  * to "C-X 1". Try to set the framing so that "." does not have to move on the
  192.  * display. Some care has to be taken to keep the values of dot and mark in
  193.  * the buffer structures right if the distruction of a window makes a buffer
  194.  * become undisplayed.
  195.  */
  196. onlywind(f, n)
  197. {
  198.         register WINDOW *wp;
  199.         register LINE   *lp;
  200.         register int    i;
  201.  
  202.         while (wheadp != curwp) {
  203.                 wp = wheadp;
  204.                 wheadp = wp->w_wndp;
  205.                 if (--wp->w_bufp->b_nwnd == 0) {
  206.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  207.                         wp->w_bufp->b_doto  = wp->w_doto;
  208.                         wp->w_bufp->b_markp = wp->w_markp;
  209.                         wp->w_bufp->b_marko = wp->w_marko;
  210.                         wp->w_bufp->b_fcol  = wp->w_fcol;
  211.                 }
  212.                 free((char *) wp);
  213.         }
  214.         while (curwp->w_wndp != NULL) {
  215.                 wp = curwp->w_wndp;
  216.                 curwp->w_wndp = wp->w_wndp;
  217.                 if (--wp->w_bufp->b_nwnd == 0) {
  218.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  219.                         wp->w_bufp->b_doto  = wp->w_doto;
  220.                         wp->w_bufp->b_markp = wp->w_markp;
  221.                         wp->w_bufp->b_marko = wp->w_marko;
  222.                         wp->w_bufp->b_fcol  = wp->w_fcol;
  223.                 }
  224.                 free((char *) wp);
  225.         }
  226.         lp = curwp->w_linep;
  227.         i  = curwp->w_toprow;
  228.         while (i-- > 0 && lback(lp) != curbp->b_linep)
  229.                 lp = lback(lp);
  230.         curwp->w_toprow = 0;
  231.         curwp->w_ntrows = term.t_nrow - 1 - menuflag;
  232.         curwp->w_linep  = lp;
  233.         curwp->w_flag  |= WFMODE|WFHARD;
  234.         return (TRUE);
  235. }
  236.  
  237. /*
  238.  * Delete the current window, placing its space in the window above,
  239.  * or, if it is the top window, the window below. Bound to C-X 0.
  240.  */
  241.  
  242. delwind(f,n)
  243.  
  244. int f, n;    /* arguments are ignored for this command */
  245.  
  246. {
  247.     register WINDOW *wp;    /* window to recieve deleted space */
  248.     register WINDOW *lwp;    /* ptr window before curwp */
  249.     register int target;    /* target line to search for */
  250.         LINE   *lp;
  251.  
  252.     /* if there is only one window, don't delete it */
  253.     if (wheadp->w_wndp == NULL) {
  254.         mlwrite("Can not delete this window");
  255.         return(FALSE);
  256.     }
  257.  
  258.     /* find window before curwp in linked list */
  259.     wp = wheadp;
  260.     lwp = NULL;
  261.     while (wp != NULL) {
  262.         if (wp == curwp)
  263.             break;
  264.         lwp = wp;
  265.         wp = wp->w_wndp;
  266.     }
  267.  
  268.     /* find recieving window and give up our space */
  269.     wp = wheadp;
  270.     if (curwp->w_toprow == 0) {
  271.         /* find the next window down */
  272.         target = curwp->w_ntrows + 1;
  273.         while (wp != NULL) {
  274.             if (wp->w_toprow == target)
  275.                 break;
  276.             wp = wp->w_wndp;
  277.         }
  278.         if (wp == NULL)
  279.             return(FALSE);
  280.  
  281.         wp->w_toprow = 0;
  282.         wp->w_ntrows += target;
  283.  
  284.         /* change starting location to keep dot on same screen line */
  285.         lp = wp->w_linep;
  286.         while (target-- > 0 && lback(lp) != wp->w_bufp->b_linep)
  287.             lp = lback(lp);
  288.         wp->w_linep  = lp;
  289.     } else {
  290.         /* find the next window up */
  291.         target = curwp->w_toprow - 1;
  292.         while (wp != NULL) {
  293.             if ((wp->w_toprow + wp->w_ntrows) == target)
  294.                 break;
  295.             wp = wp->w_wndp;
  296.         }
  297.         if (wp == NULL)
  298.             return(FALSE);
  299.         wp->w_ntrows += 1 + curwp->w_ntrows;
  300.     }
  301.  
  302.     /* get rid of the current window */
  303.     if (--curwp->w_bufp->b_nwnd == 0) {
  304.         curwp->w_bufp->b_dotp = curwp->w_dotp;
  305.         curwp->w_bufp->b_doto = curwp->w_doto;
  306.         curwp->w_bufp->b_markp = curwp->w_markp;
  307.         curwp->w_bufp->b_marko = curwp->w_marko;
  308.                 curwp->w_bufp->b_fcol  = curwp->w_fcol;
  309.     }
  310.     if (lwp == NULL)
  311.         wheadp = curwp->w_wndp;
  312.     else
  313.         lwp->w_wndp = curwp->w_wndp;
  314.     free((char *)curwp);
  315.     curwp = wp;
  316.     wp->w_flag |= WFHARD;
  317.     curbp = wp->w_bufp;
  318.     upmode();
  319.     return(TRUE);
  320. }
  321.  
  322. /*
  323.  
  324. Split the current window.  A window smaller than 3 lines cannot be
  325. split.  An argument of 1 forces the cursor into the upper window, an
  326. argument of two forces the cursor to the lower window.  The only other
  327. error that is possible is a "malloc" failure allocating the structure
  328. for the new window.  Bound to "C-X 2".
  329.  
  330.  */
  331. splitwind(f, n)
  332.  
  333. int f, n;    /* default flag and numeric argument */
  334.  
  335. {
  336.         register WINDOW *wp;
  337.         register LINE   *lp;
  338.         register int    ntru;
  339.         register int    ntrl;
  340.         register int    ntrd;
  341.         register WINDOW *wp1;
  342.         register WINDOW *wp2;
  343.     char *malloc();
  344.  
  345.         if (curwp->w_ntrows < 3) {
  346.                 mlwrite("Cannot split a %d line window", curwp->w_ntrows);
  347.                 return (FALSE);
  348.         }
  349.         if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
  350.                 mlwrite("[OUT OF MEMORY]");
  351.                 return (FALSE);
  352.         }
  353.         ++curbp->b_nwnd;                        /* Displayed twice.    */
  354.     spltwp      = wp;            /* Leave a note        */
  355.         wp->w_bufp  = curbp;
  356.         wp->w_dotp  = curwp->w_dotp;
  357.         wp->w_doto  = curwp->w_doto;
  358.         wp->w_markp = curwp->w_markp;
  359.         wp->w_marko = curwp->w_marko;
  360.         wp->w_fcol  = curwp->w_fcol;
  361.         wp->w_flag  = 0;
  362.         wp->w_force = 0;
  363. #if    COLOR
  364.     /* set the colors of the new window */
  365.     wp->w_fcolor = gfcolor;
  366.     wp->w_bcolor = gbcolor;
  367. #endif
  368.         ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
  369.         ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
  370.         lp = curwp->w_linep;
  371.         ntrd = 0;
  372.         while (lp != curwp->w_dotp) {
  373.                 ++ntrd;
  374.                 lp = lforw(lp);
  375.         }
  376.         lp = curwp->w_linep;
  377.         if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
  378.                 /* Old is upper window. */
  379.                 if (ntrd == ntru)               /* Hit mode line.       */
  380.                         lp = lforw(lp);
  381.                 curwp->w_ntrows = ntru;
  382.                 wp->w_wndp = curwp->w_wndp;
  383.                 curwp->w_wndp = wp;
  384.                 wp->w_toprow = curwp->w_toprow+ntru+1;
  385.                 wp->w_ntrows = ntrl;
  386.         } else {                                /* Old is lower window  */
  387.                 wp1 = NULL;
  388.                 wp2 = wheadp;
  389.                 while (wp2 != curwp) {
  390.                         wp1 = wp2;
  391.                         wp2 = wp2->w_wndp;
  392.                 }
  393.                 if (wp1 == NULL)
  394.                         wheadp = wp;
  395.                 else
  396.                         wp1->w_wndp = wp;
  397.                 wp->w_wndp   = curwp;
  398.                 wp->w_toprow = curwp->w_toprow;
  399.                 wp->w_ntrows = ntru;
  400.                 ++ntru;                         /* Mode line.           */
  401.                 curwp->w_toprow += ntru;
  402.                 curwp->w_ntrows  = ntrl;
  403.                 while (ntru--)
  404.                         lp = lforw(lp);
  405.         }
  406.         curwp->w_linep = lp;                    /* Adjust the top lines */
  407.         wp->w_linep = lp;                       /* if necessary.        */
  408.         curwp->w_flag |= WFMODE|WFHARD;
  409.         wp->w_flag |= WFMODE|WFHARD;
  410.         return (TRUE);
  411. }
  412.  
  413. /*
  414.  * Enlarge the current window. Find the window that loses space. Make sure it
  415.  * is big enough. If so, hack the window descriptions, and ask redisplay to do
  416.  * all the hard work. You don't just set "force reframe" because dot would
  417.  * move. Bound to "C-X Z".
  418.  */
  419. enlargewind(f, n)
  420. {
  421.         register WINDOW *adjwp;
  422.         register LINE   *lp;
  423.         register int    i;
  424.  
  425.         if (n < 0)
  426.                 return (shrinkwind(f, -n));
  427.         if (wheadp->w_wndp == NULL) {
  428.                 mlwrite("Only one window");
  429.                 return (FALSE);
  430.         }
  431.         if ((adjwp=curwp->w_wndp) == NULL) {
  432.                 adjwp = wheadp;
  433.                 while (adjwp->w_wndp != curwp)
  434.                         adjwp = adjwp->w_wndp;
  435.         }
  436.         if (adjwp->w_ntrows <= n) {
  437.                 mlwrite("Impossible change");
  438.                 return (FALSE);
  439.         }
  440.         if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
  441.                 lp = adjwp->w_linep;
  442.                 for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  443.                         lp = lforw(lp);
  444.                 adjwp->w_linep  = lp;
  445.                 adjwp->w_toprow += n;
  446.         } else {                                /* Shrink above.        */
  447.                 lp = curwp->w_linep;
  448.                 for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  449.                         lp = lback(lp);
  450.                 curwp->w_linep  = lp;
  451.                 curwp->w_toprow -= n;
  452.         }
  453.         curwp->w_ntrows += n;
  454.         adjwp->w_ntrows -= n;
  455.         curwp->w_flag |= WFMODE|WFHARD;
  456.         adjwp->w_flag |= WFMODE|WFHARD;
  457.         return (TRUE);
  458. }
  459.  
  460. /*
  461.  * Shrink the current window. Find the window that gains space. Hack at the
  462.  * window descriptions. Ask the redisplay to do all the hard work. Bound to
  463.  * "C-X C-Z".
  464.  */
  465. shrinkwind(f, n)
  466. {
  467.         register WINDOW *adjwp;
  468.         register LINE   *lp;
  469.         register int    i;
  470.  
  471.         if (n < 0)
  472.                 return (enlargewind(f, -n));
  473.         if (wheadp->w_wndp == NULL) {
  474.                 mlwrite("Only one window");
  475.                 return (FALSE);
  476.         }
  477.         if ((adjwp=curwp->w_wndp) == NULL) {
  478.                 adjwp = wheadp;
  479.                 while (adjwp->w_wndp != curwp)
  480.                         adjwp = adjwp->w_wndp;
  481.         }
  482.         if (curwp->w_ntrows <= n) {
  483.                 mlwrite("Impossible change");
  484.                 return (FALSE);
  485.         }
  486.         if (curwp->w_wndp == adjwp) {           /* Grow below.          */
  487.                 lp = adjwp->w_linep;
  488.                 for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  489.                         lp = lback(lp);
  490.                 adjwp->w_linep  = lp;
  491.                 adjwp->w_toprow -= n;
  492.         } else {                                /* Grow above.          */
  493.                 lp = curwp->w_linep;
  494.                 for (i=0; i<n && lp!=curbp->b_linep; ++i)
  495.                         lp = lforw(lp);
  496.                 curwp->w_linep  = lp;
  497.                 curwp->w_toprow += n;
  498.         }
  499.         curwp->w_ntrows -= n;
  500.         adjwp->w_ntrows += n;
  501.         curwp->w_flag |= WFMODE|WFHARD;
  502.         adjwp->w_flag |= WFMODE|WFHARD;
  503.         return (TRUE);
  504. }
  505.  
  506. /*    Resize the current window to the requested size    */
  507.  
  508. resize(f, n)
  509.  
  510. int f, n;    /* default flag and numeric argument */
  511.  
  512. {
  513.     int clines;    /* current # of lines in window */
  514.     
  515.     /* must have a non-default argument, else ignore call */
  516.     if (f == FALSE)
  517.         return(TRUE);
  518.  
  519.     /* find out what to do */
  520.     clines = curwp->w_ntrows;
  521.  
  522.     /* already the right size? */
  523.     if (clines == n)
  524.         return(TRUE);
  525.  
  526.     return(enlargewind(TRUE, n - clines));
  527. }
  528.  
  529. /*
  530.  * Pick a window for a pop-up. Split the screen if there is only one window.
  531.  * Pick the uppermost window that isn't the current window. An LRU algorithm
  532.  * might be better. Return a pointer, or NULL on error.
  533.  */
  534. WINDOW  *
  535. wpopup()
  536. {
  537.         register WINDOW *wp;
  538.  
  539.         if (wheadp->w_wndp == NULL              /* Only 1 window        */
  540.         && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
  541.                 return (NULL);
  542.         wp = wheadp;                            /* Find window to use   */
  543.         while (wp!=NULL && wp==curwp)
  544.                 wp = wp->w_wndp;
  545.         return (wp);
  546. }
  547.  
  548. scrupnxt(f, n)        /* scroll the next window up (back) a page */
  549.  
  550. {
  551.     nextwind(FALSE, 1);
  552.     backpage(f, n);
  553.     prevwind(FALSE, 1);
  554. }
  555.  
  556. scrdwnxt(f, n)        /* scroll the next window down (forward) a page */
  557.  
  558. {
  559.     nextwind(FALSE, 1);
  560.     forwpage(f, n);
  561.     prevwind(FALSE, 1);
  562. }
  563.  
  564. savewnd(f, n)        /* save ptr to current window */
  565.  
  566. {
  567.     swindow = curwp;
  568.     return(TRUE);
  569. }
  570.  
  571. restwnd(f, n)        /* restore the saved screen */
  572.  
  573. {
  574.     register WINDOW *wp;
  575.  
  576.     /* find the window */
  577.     wp = wheadp;
  578.     while (wp != NULL) {
  579.         if (wp == swindow) {
  580.             curwp = wp;
  581.             curbp = wp->w_bufp;
  582.             upmode();
  583.             return (TRUE);
  584.         }
  585.         wp = wp->w_wndp;
  586.     }
  587.  
  588.     mlwrite("[No such window exists]");
  589.     return(FALSE);
  590. }
  591.  
  592. newsize(f, n)    /* resize the screen, re-writing the screen */
  593.  
  594. int f;    /* default flag */
  595. int n;    /* numeric argument */
  596.  
  597. {
  598.     WINDOW *wp;    /* current window being examined */
  599.     WINDOW *nextwp;    /* next window to scan */
  600.     WINDOW *lastwp;    /* last window scanned */
  601.     int lastline;    /* screen line of last line of current window */
  602.  
  603.     /* if the command defaults, assume the largest */
  604.     if (f == FALSE)
  605.         n = term.t_mrow + 1;
  606.  
  607.     /* make sure it's in range */
  608.     if (n < 3+menuflag || n > term.t_mrow + 1) {
  609.         mlwrite("%%Screen size out of range");
  610.         return(FALSE);
  611.     }
  612.  
  613.     if (term.t_nrow == n - 1)
  614.         return(TRUE);
  615.     else if (term.t_nrow < n - 1) {
  616.  
  617.         /* go to the last window */
  618.         wp = wheadp;
  619.         while (wp->w_wndp != NULL)
  620.             wp = wp->w_wndp;
  621.  
  622.         /* and enlarge it as needed */
  623.         wp->w_ntrows = n - wp->w_toprow - 2 - menuflag;
  624.         wp->w_flag |= WFHARD|WFMODE;
  625.  
  626.     } else {
  627.  
  628.         /* rebuild the window structure */
  629.         nextwp = wheadp;
  630.         wp = NULL;
  631.         lastwp = NULL;
  632.         while (nextwp != NULL) {
  633.             wp = nextwp;
  634.             nextwp = wp->w_wndp;
  635.     
  636.             /* get rid of it if it is too low */
  637.             if (wp->w_toprow > n - 2 - menuflag) {
  638.  
  639.                 /* save the point/mark if needed */
  640.                 if (--wp->w_bufp->b_nwnd == 0) {
  641.                     wp->w_bufp->b_dotp = wp->w_dotp;
  642.                     wp->w_bufp->b_doto = wp->w_doto;
  643.                     wp->w_bufp->b_markp = wp->w_markp;
  644.                     wp->w_bufp->b_marko = wp->w_marko;
  645.                                 wp->w_bufp->b_fcol  = wp->w_fcol;
  646.                 }
  647.     
  648.                 /* update curwp and lastwp if needed */
  649.                 if (wp == curwp)
  650.                     curwp = wheadp;
  651.                     curbp = curwp->w_bufp;
  652.                 if (lastwp != NULL)
  653.                     lastwp->w_wndp = NULL;
  654.  
  655.                 /* free the structure */
  656.                 free((char *)wp);
  657.                 wp = NULL;
  658.  
  659.             } else {
  660.                 /* need to change this window size? */
  661.                 lastline = wp->w_toprow + wp->w_ntrows - 1;
  662.                 if (lastline >= n - 2 - menuflag) {
  663.                     wp->w_ntrows = n - wp->w_toprow - 2 -
  664.                             menuflag;
  665.                     wp->w_flag |= WFHARD|WFMODE;
  666.                 }
  667.             }
  668.     
  669.             lastwp = wp;
  670.         }
  671.     }
  672.  
  673.     /* screen is garbage */
  674.     term.t_nrow = n - 1;
  675.     sgarbf = TRUE;
  676.     return(TRUE);
  677. }
  678.  
  679. newwidth(f, n)    /* resize the screen, re-writing the screen */
  680.  
  681. int f;    /* default flag */
  682. int n;    /* numeric argument */
  683.  
  684. {
  685.     register WINDOW *wp;
  686.  
  687.     /* if the command defaults, assume the largest */
  688.     if (f == FALSE)
  689.         n = term.t_mcol;
  690.  
  691.     /* make sure it's in range */
  692.     if (n < 10 || n > term.t_mcol) {
  693.         mlwrite("%%Screen width out of range");
  694.         return(FALSE);
  695.     }
  696.  
  697.     /* otherwise, just re-width it (no big deal) */
  698.     term.t_ncol = n;
  699.     term.t_margin = n / 10;
  700.     term.t_scrsiz = n - (term.t_margin * 2);
  701.  
  702.     /* force all windows to redraw */
  703.     wp = wheadp;
  704.     while (wp) {
  705.         wp->w_flag |= WFHARD | WFMOVE | WFMODE;
  706.         wp = wp->w_wndp;
  707.     }
  708.     sgarbf = TRUE;
  709.  
  710. #if    MENUS
  711.     menuinit();
  712. #endif
  713.  
  714.     return(TRUE);
  715. }
  716.  
  717. #if    CALLABLE
  718. /* free all windows */
  719. frallwindows()
  720. {
  721.     register WINDOW *wp;
  722.  
  723.     while(wheadp != NULL) {
  724.         wp = wheadp;
  725.         wheadp = wp->w_wndp;
  726.         --wp->w_bufp->b_nwnd;
  727.         free((char *) wp);
  728.     }
  729. }
  730. #endif
  731.  
  732. int getwpos()    /* get screen offset of current line in current window */
  733.  
  734. {
  735.     register int sline;    /* screen line from top of window */
  736.     register LINE *lp;    /* scannile line pointer */
  737.  
  738.     /* search down the line we want */
  739.     lp = curwp->w_linep;
  740.     sline = 1;
  741.     while (lp != curwp->w_dotp) {
  742.         ++sline;
  743.         lp = lforw(lp);
  744.     }
  745.  
  746.     /* and return the value */
  747.     return(sline);
  748. }
  749.  
  750. #if    DECEDT
  751. /*
  752.  * This command move dot down (or up) by "arg" lines.  If dot would go outside
  753.  * the middle third of the screen, it is forced back in and the entire
  754.  * window is scrolled up (or down).
  755.  */
  756. scdnwind(f, n)
  757.  
  758. int n;
  759.  
  760. {
  761.     register LINE *lp;
  762.     int row, top, bot, scroll;
  763.  
  764.     /* find where we are */
  765.  
  766.     lp = curwp->w_linep;
  767.     row = 1;
  768.     while (lp != curbp->b_linep && lp != curwp->w_dotp &&
  769.         row < curwp->w_ntrows) {
  770.     lp = lforw(lp);
  771.     ++row;
  772.     }
  773.  
  774.     /* find where we want to go */
  775.  
  776.     top = (curwp->w_ntrows + 2) / 3;
  777.     bot = curwp->w_ntrows + 1 - top;
  778.     scroll = 1;
  779.  
  780.     if (lp == curwp->w_dotp) {
  781.     row += n;
  782.     if (n < 0 && row < top) row = top;
  783.     else if (n > 0 && row > bot) row = bot;
  784.     else if (row < 1) row = 1;
  785.     else if (row > curwp->w_ntrows) row = curwp->w_ntrows;
  786.     else scroll = 0;
  787.     }
  788.     else if (n < 0) row = top;
  789.     else if (n > 0) row = bot;
  790.     else row = (top + bot) / 2;
  791.  
  792.     /* go there */
  793.  
  794.     lp = curwp->w_dotp;
  795.     if (n > 0) {
  796.     while (n-- && lp!=curbp->b_linep)
  797.         lp = lforw(lp);
  798.     }
  799.     else {
  800.     while (n++ && lback(lp)!=curbp->b_linep)
  801.         lp = lback(lp);
  802.     }
  803.  
  804.     /* flag this command as a line move */
  805.     thisflag |= CFCPCN;
  806.  
  807.     if (scroll) {
  808.     curwp->w_flag |= WFFORCE;
  809.     curwp->w_force = row;
  810.     }
  811.     if (lp != curwp->w_dotp) {
  812.     /* if the last command was not a line move,
  813.        reset the goal column */
  814.     if ((lastflag&CFCPCN) == 0) curgoal = getccol(FALSE);
  815.  
  816.     /* reset the current position */
  817.     curwp->w_doto  = getgoal(lp);
  818.     curwp->w_flag |= WFMOVE;
  819.     }
  820.     curwp->w_dotp = lp;
  821.     return (TRUE);
  822. }
  823.  
  824. /*
  825.  * This command move dot up (or down) by "arg" lines.
  826.  * It just calls scdnwind(f, n)
  827.  */
  828. scupwind(f, n)
  829. int n;
  830. {
  831.     return (scdnwind(f, -n));
  832. }
  833.  
  834. #endif
  835.  
  836. #if    AEDIT
  837. /*
  838.  * Scroll the entire window forward.
  839.  */
  840. scrlforw(f, n)
  841. {
  842.     register WINDOW *wp;
  843.     int saveoff;
  844.  
  845.     saveoff = curwp->w_fcol;
  846.     curwp->w_fcol += n;
  847.     if (curwp->w_fcol < 0) curwp->w_fcol = 0;
  848.  
  849.     if (curwp->w_fcol != saveoff) {
  850.     /* force all windows to redraw */
  851.     wp = wheadp;
  852.     while (wp) {
  853.         wp->w_flag |= WFHARD | WFMOVE | WFMODE;
  854.         wp = wp->w_wndp;
  855.     }
  856.     sgarbf = TRUE;
  857.     }
  858.     curwp->w_flag |= WFMOVE;
  859.     if (n < 0)    {
  860.     if (curwp->w_doto + n >= 0) curwp->w_doto += n;
  861.     else curwp->w_doto = 0;
  862.     }
  863.     else    {
  864.     if (curwp->w_doto + n <= llength(curwp->w_dotp)) curwp->w_doto += n;
  865.     else curwp->w_doto = llength(curwp->w_dotp);
  866.     }
  867.     return (TRUE);
  868. }
  869.  
  870. scrlback(f, n)
  871. {
  872.     return ( scrlforw(f, -n) );
  873. }
  874.  
  875. #endif
  876.  
  877.