home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / util / vim-3.0.lha / Vim / src / window.c < prev    next >
C/C++ Source or Header  |  1994-08-09  |  26KB  |  1,194 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. #include "vim.h"
  10. #include "globals.h"
  11. #include "proto.h"
  12. #include "param.h"
  13.  
  14. static int win_comp_pos __ARGS((void));
  15. static void win_exchange __ARGS((long));
  16. static void win_rotate __ARGS((int, int));
  17. static void win_append __ARGS((WIN *, WIN *));
  18. static void win_remove __ARGS((WIN *));
  19.  
  20. static WIN        *prevwin = NULL;        /* previous window */
  21.  
  22. /*
  23.  * all CTRL-W window commands are handled here, called from normal().
  24.  */
  25.     void
  26. do_window(nchar, Prenum)
  27.     int        nchar;
  28.     long    Prenum;
  29. {
  30.     long    Prenum1;
  31.     WIN        *wp;
  32.     char_u    *ptr;
  33.  
  34.     if (Prenum == 0)
  35.         Prenum1 = 1;
  36.     else
  37.         Prenum1 = Prenum;
  38.  
  39.     switch (nchar)
  40.     {
  41. /* split current window in two parts */
  42.     case 'S':
  43.     case Ctrl('S'):
  44.     case 's':    VIsual.lnum = 0;        /* stop Visual mode */
  45.                 win_split(Prenum, TRUE);
  46.                 break;
  47.  
  48. /* open new window */
  49.     case Ctrl('N'):
  50.     case 'n':    VIsual.lnum = 0;                    /* stop Visual mode */
  51.                 stuffcharReadbuff(':');
  52.                 if (Prenum)
  53.                     stuffnumReadbuff(Prenum);        /* window height */
  54.                 stuffReadbuff((char_u *)"new\n");    /* it is cmdline.c */
  55.                 break;
  56.  
  57. /* quit current window */
  58.     case Ctrl('Q'):
  59.     case 'q':    VIsual.lnum = 0;        /* stop Visual mode */
  60.                 stuffReadbuff((char_u *)":quit\n");    /* it is cmdline.c */
  61.                 break;
  62.  
  63. /* close current window */
  64.     case Ctrl('C'):
  65.     case 'c':    VIsual.lnum = 0;        /* stop Visual mode */
  66.                 stuffReadbuff((char_u *)":close\n");    /* it is cmdline.c */
  67.                 break;
  68.  
  69. /* close all but current window */
  70.     case Ctrl('O'):
  71.     case 'o':    VIsual.lnum = 0;        /* stop Visual mode */
  72.                 stuffReadbuff((char_u *)":only\n");    /* it is cmdline.c */
  73.                 break;
  74.  
  75. /* cursor to next window */
  76.     case 'j':
  77.     case K_DARROW:
  78.     case Ctrl('J'):
  79.                 VIsual.lnum = 0;        /* stop Visual mode */
  80.                 for (wp = curwin; wp->w_next != NULL && Prenum1-- > 0;
  81.                                                             wp = wp->w_next)
  82.                     ;
  83.                 win_enter(wp, TRUE);
  84.                 cursupdate();
  85.                 break;
  86.  
  87. /* cursor to next window with wrap around */
  88.     case Ctrl('W'):
  89.     case 'w':
  90.                 VIsual.lnum = 0;        /* stop Visual mode */
  91.                 if (lastwin == firstwin)        /* just one window */
  92.                     beep();
  93.                 else
  94.                 {
  95.                     if (Prenum)                    /* go to specified window */
  96.                     {
  97.                         for (wp = firstwin; --Prenum > 0; )
  98.                         {
  99.                             if (wp->w_next == NULL)
  100.                                 break;
  101.                             else
  102.                                 wp = wp->w_next;
  103.                         }
  104.                     }
  105.                     else                        /* go to next window */
  106.                     {
  107.                         wp = curwin->w_next;
  108.                         if (wp == NULL)
  109.                             wp = firstwin;        /* wrap around */
  110.                     }
  111.                     win_enter(wp, TRUE);
  112.                     cursupdate();
  113.                 }
  114.                 break;
  115.  
  116. /* cursor to window above */
  117.     case 'k':
  118.     case K_UARROW:
  119.     case Ctrl('K'):
  120.                 VIsual.lnum = 0;        /* stop Visual mode */
  121.                 for (wp = curwin; wp->w_prev != NULL && Prenum1-- > 0;
  122.                                                             wp = wp->w_prev)
  123.                     ;
  124.                 win_enter(wp, TRUE);
  125.                 cursupdate();
  126.                 break;
  127.  
  128. /* cursor to last accessed (previous) window */
  129.     case 'p':
  130.     case Ctrl('P'):
  131.                 VIsual.lnum = 0;        /* stop Visual mode */
  132.                 if (prevwin == NULL)
  133.                     beep();
  134.                 else
  135.                 {
  136.                     win_enter(prevwin, TRUE);
  137.                     cursupdate();
  138.                 }
  139.                 break;
  140.  
  141. /* exchange current and next window */
  142.     case 'x':
  143.     case Ctrl('X'):
  144.                 win_exchange(Prenum);
  145.                 break;
  146.  
  147. /* rotate windows downwards */
  148.     case Ctrl('R'):
  149.     case 'r':    VIsual.lnum = 0;                    /* stop Visual mode */
  150.                 win_rotate(FALSE, (int)Prenum1);    /* downwards */
  151.                 break;
  152.  
  153. /* rotate windows upwards */
  154.     case 'R':    VIsual.lnum = 0;                    /* stop Visual mode */
  155.                 win_rotate(TRUE, (int)Prenum1);        /* upwards */
  156.                 break;
  157.  
  158. /* make all windows the same height */
  159.     case '=':    win_equal(NULL, TRUE);
  160.                 break;
  161.  
  162. /* increase current window height */
  163.     case '+':    win_setheight(curwin->w_height + (int)Prenum1);
  164.                 break;
  165.  
  166. /* decrease current window height */
  167.     case '-':    win_setheight(curwin->w_height - (int)Prenum1);
  168.                 break;
  169.  
  170. /* set current window height */
  171.     case Ctrl('_'):
  172.     case '_':    win_setheight(Prenum ? (int)Prenum : 9999);
  173.                 break;
  174.  
  175. /* jump to tag and split window if tag exists */
  176.     case ']':
  177.     case Ctrl(']'):
  178.                 VIsual.lnum = 0;        /* stop Visual mode */
  179.                 postponed_split = TRUE;
  180.                 stuffcharReadbuff(Ctrl(']'));
  181.                 break;
  182.  
  183. /* edit file name under cursor in a new window */
  184.     case 'f':
  185.     case Ctrl('F'):
  186.                 VIsual.lnum = 0;        /* stop Visual mode */
  187.                 ptr = file_name_at_cursor();
  188.                 if (ptr == NULL)
  189.                     beep();
  190.                 else
  191.                 {
  192.                     stuffReadbuff((char_u *) ":split ");
  193.                     stuffReadbuff(ptr);
  194.                     stuffReadbuff((char_u *) "\n");
  195.                     free(ptr);
  196.                 }
  197.                 break;
  198.  
  199.     default:    beep();
  200.                 break;
  201.     }
  202. }
  203.  
  204. /*
  205.  * split the current window, implements CTRL-W s and :split
  206.  *
  207.  * new_height is the height for the new window, 0 to make half of current height
  208.  * redraw is TRUE when redraw now
  209.  *
  210.  * return FAIL for failure, OK otherwise
  211.  */
  212.     int
  213. win_split(new_height, redraw)
  214.     long    new_height;
  215.     int        redraw;
  216. {
  217.     WIN            *wp;
  218.     linenr_t    lnum;
  219.     int            h;
  220.     int            i;
  221.     int            need_status;
  222.     int            do_equal = (p_ea && new_height == 0);
  223.     int            needed;
  224.     int            available;
  225.     
  226.         /* add a status line when p_ls == 1 and splitting the first window */
  227.     if (lastwin == firstwin && p_ls == 1 && curwin->w_status_height == 0)
  228.         need_status = STATUS_HEIGHT;
  229.     else
  230.         need_status = 0;
  231.  
  232. /*
  233.  * check if we are able to split the current window and compute its height
  234.  */
  235.     available = curwin->w_height;
  236.      needed = 2 * MIN_ROWS + STATUS_HEIGHT + need_status;
  237.     if (p_ea)
  238.     {
  239.         for (wp = firstwin; wp != NULL; wp = wp->w_next)
  240.             if (wp != curwin)
  241.             {
  242.                 available += wp->w_height;
  243.                 needed += MIN_ROWS;
  244.             }
  245.     }
  246.      if (available < needed)
  247.     {
  248.         EMSG(e_noroom);
  249.         return FAIL;
  250.     }
  251.     if (need_status)
  252.     {
  253.         curwin->w_status_height = STATUS_HEIGHT;
  254.         curwin->w_height -= STATUS_HEIGHT;
  255.     }
  256.     if (new_height == 0)
  257.         new_height = curwin->w_height / 2;
  258.  
  259.     if (new_height > curwin->w_height - MIN_ROWS - STATUS_HEIGHT)
  260.         new_height = curwin->w_height - MIN_ROWS - STATUS_HEIGHT;
  261.  
  262.     if (new_height < MIN_ROWS)
  263.         new_height = MIN_ROWS;
  264.  
  265.         /* if it doesn't fit in the current window, need win_equal() */
  266.     if (curwin->w_height - new_height - STATUS_HEIGHT < MIN_ROWS)
  267.         do_equal = TRUE;
  268. /*
  269.  * allocate new window structure and link it in the window list
  270.  */
  271.     if (p_sb)        /* new window below current one */
  272.         wp = win_alloc(curwin);
  273.     else
  274.         wp = win_alloc(curwin->w_prev);
  275.     if (wp == NULL)
  276.         return FAIL;
  277. /*
  278.  * compute the new screen positions
  279.  */
  280.     wp->w_height = new_height;
  281.     win_comp_scroll(wp);
  282.     curwin->w_height -= new_height + STATUS_HEIGHT;
  283.     win_comp_scroll(curwin);
  284.     if (p_sb)        /* new window below current one */
  285.     {
  286.         wp->w_winpos = curwin->w_winpos + curwin->w_height + STATUS_HEIGHT;
  287.         wp->w_status_height = curwin->w_status_height;
  288.         curwin->w_status_height = STATUS_HEIGHT;
  289.     }
  290.     else            /* new window above current one */
  291.     {
  292.         wp->w_winpos = curwin->w_winpos;
  293.         wp->w_status_height = STATUS_HEIGHT;
  294.         curwin->w_winpos = wp->w_winpos + wp->w_height + STATUS_HEIGHT;
  295.     }
  296. /*
  297.  * make the contents of the new window the same as the current one
  298.  */
  299.     wp->w_buffer = curbuf;
  300.     curbuf->b_nwindows++;
  301.     wp->w_cursor = curwin->w_cursor;
  302.     wp->w_row = curwin->w_row;
  303.     wp->w_col = curwin->w_col;
  304.     wp->w_virtcol = curwin->w_virtcol;
  305.     wp->w_curswant = curwin->w_curswant;
  306.     wp->w_set_curswant = curwin->w_set_curswant;
  307.     wp->w_empty_rows = curwin->w_empty_rows;
  308.     wp->w_leftcol = curwin->w_leftcol;
  309.     wp->w_pcmark = curwin->w_pcmark;
  310.     wp->w_prev_pcmark = curwin->w_prev_pcmark;
  311.  
  312.     wp->w_arg_idx = curwin->w_arg_idx;
  313.     /*
  314.      * copy tagstack and options from existing window
  315.      */
  316.     for (i = 0; i < curwin->w_tagstacklen; i++)
  317.     {
  318.         wp->w_tagstack[i].fmark = curwin->w_tagstack[i].fmark;
  319.         wp->w_tagstack[i].tagname = strsave(curwin->w_tagstack[i].tagname);
  320.     }
  321.     wp->w_tagstackidx = curwin->w_tagstackidx;
  322.     wp->w_tagstacklen = curwin->w_tagstacklen;
  323.     win_copy_options(curwin, wp);
  324. /*
  325.  * Both windows need redrawing
  326.  */
  327.      wp->w_redr_type = NOT_VALID;
  328.     wp->w_redr_status = TRUE;
  329.      curwin->w_redr_type = NOT_VALID;
  330.     curwin->w_redr_status = TRUE;
  331. /*
  332.  * Cursor is put in middle of window in both windows
  333.  */
  334.     if (wp->w_height < curwin->w_height)    /* use smallest of two heights */
  335.         h = wp->w_height;
  336.     else
  337.         h = curwin->w_height;
  338.     h >>= 1;
  339.     for (lnum = wp->w_cursor.lnum; lnum > 1; --lnum)
  340.     {
  341.         h -= plines(lnum);
  342.         if (h <= 0)
  343.             break;
  344.     }
  345.     w