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 >
Wrap
C/C++ Source or Header
|
1994-08-09
|
26KB
|
1,194 lines
/* vi:ts=4:sw=4
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Read the file "credits.txt" for a list of people who contributed.
* Read the file "uganda.txt" for copying and usage conditions.
*/
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
static int win_comp_pos __ARGS((void));
static void win_exchange __ARGS((long));
static void win_rotate __ARGS((int, int));
static void win_append __ARGS((WIN *, WIN *));
static void win_remove __ARGS((WIN *));
static WIN *prevwin = NULL; /* previous window */
/*
* all CTRL-W window commands are handled here, called from normal().
*/
void
do_window(nchar, Prenum)
int nchar;
long Prenum;
{
long Prenum1;
WIN *wp;
char_u *ptr;
if (Prenum == 0)
Prenum1 = 1;
else
Prenum1 = Prenum;
switch (nchar)
{
/* split current window in two parts */
case 'S':
case Ctrl('S'):
case 's': VIsual.lnum = 0; /* stop Visual mode */
win_split(Prenum, TRUE);
break;
/* open new window */
case Ctrl('N'):
case 'n': VIsual.lnum = 0; /* stop Visual mode */
stuffcharReadbuff(':');
if (Prenum)
stuffnumReadbuff(Prenum); /* window height */
stuffReadbuff((char_u *)"new\n"); /* it is cmdline.c */
break;
/* quit current window */
case Ctrl('Q'):
case 'q': VIsual.lnum = 0; /* stop Visual mode */
stuffReadbuff((char_u *)":quit\n"); /* it is cmdline.c */
break;
/* close current window */
case Ctrl('C'):
case 'c': VIsual.lnum = 0; /* stop Visual mode */
stuffReadbuff((char_u *)":close\n"); /* it is cmdline.c */
break;
/* close all but current window */
case Ctrl('O'):
case 'o': VIsual.lnum = 0; /* stop Visual mode */
stuffReadbuff((char_u *)":only\n"); /* it is cmdline.c */
break;
/* cursor to next window */
case 'j':
case K_DARROW:
case Ctrl('J'):
VIsual.lnum = 0; /* stop Visual mode */
for (wp = curwin; wp->w_next != NULL && Prenum1-- > 0;
wp = wp->w_next)
;
win_enter(wp, TRUE);
cursupdate();
break;
/* cursor to next window with wrap around */
case Ctrl('W'):
case 'w':
VIsual.lnum = 0; /* stop Visual mode */
if (lastwin == firstwin) /* just one window */
beep();
else
{
if (Prenum) /* go to specified window */
{
for (wp = firstwin; --Prenum > 0; )
{
if (wp->w_next == NULL)
break;
else
wp = wp->w_next;
}
}
else /* go to next window */
{
wp = curwin->w_next;
if (wp == NULL)
wp = firstwin; /* wrap around */
}
win_enter(wp, TRUE);
cursupdate();
}
break;
/* cursor to window above */
case 'k':
case K_UARROW:
case Ctrl('K'):
VIsual.lnum = 0; /* stop Visual mode */
for (wp = curwin; wp->w_prev != NULL && Prenum1-- > 0;
wp = wp->w_prev)
;
win_enter(wp, TRUE);
cursupdate();
break;
/* cursor to last accessed (previous) window */
case 'p':
case Ctrl('P'):
VIsual.lnum = 0; /* stop Visual mode */
if (prevwin == NULL)
beep();
else
{
win_enter(prevwin, TRUE);
cursupdate();
}
break;
/* exchange current and next window */
case 'x':
case Ctrl('X'):
win_exchange(Prenum);
break;
/* rotate windows downwards */
case Ctrl('R'):
case 'r': VIsual.lnum = 0; /* stop Visual mode */
win_rotate(FALSE, (int)Prenum1); /* downwards */
break;
/* rotate windows upwards */
case 'R': VIsual.lnum = 0; /* stop Visual mode */
win_rotate(TRUE, (int)Prenum1); /* upwards */
break;
/* make all windows the same height */
case '=': win_equal(NULL, TRUE);
break;
/* increase current window height */
case '+': win_setheight(curwin->w_height + (int)Prenum1);
break;
/* decrease current window height */
case '-': win_setheight(curwin->w_height - (int)Prenum1);
break;
/* set current window height */
case Ctrl('_'):
case '_': win_setheight(Prenum ? (int)Prenum : 9999);
break;
/* jump to tag and split window if tag exists */
case ']':
case Ctrl(']'):
VIsual.lnum = 0; /* stop Visual mode */
postponed_split = TRUE;
stuffcharReadbuff(Ctrl(']'));
break;
/* edit file name under cursor in a new window */
case 'f':
case Ctrl('F'):
VIsual.lnum = 0; /* stop Visual mode */
ptr = file_name_at_cursor();
if (ptr == NULL)
beep();
else
{
stuffReadbuff((char_u *) ":split ");
stuffReadbuff(ptr);
stuffReadbuff((char_u *) "\n");
free(ptr);
}
break;
default: beep();
break;
}
}
/*
* split the current window, implements CTRL-W s and :split
*
* new_height is the height for the new window, 0 to make half of current height
* redraw is TRUE when redraw now
*
* return FAIL for failure, OK otherwise
*/
int
win_split(new_height, redraw)
long new_height;
int redraw;
{
WIN *wp;
linenr_t lnum;
int h;
int i;
int need_status;
int do_equal = (p_ea && new_height == 0);
int needed;
int available;
/* add a status line when p_ls == 1 and splitting the first window */
if (lastwin == firstwin && p_ls == 1 && curwin->w_status_height == 0)
need_status = STATUS_HEIGHT;
else
need_status = 0;
/*
* check if we are able to split the current window and compute its height
*/
available = curwin->w_height;
needed = 2 * MIN_ROWS + STATUS_HEIGHT + need_status;
if (p_ea)
{
for (wp = firstwin; wp != NULL; wp = wp->w_next)
if (wp != curwin)
{
available += wp->w_height;
needed += MIN_ROWS;
}
}
if (available < needed)
{
EMSG(e_noroom);
return FAIL;
}
if (need_status)
{
curwin->w_status_height = STATUS_HEIGHT;
curwin->w_height -= STATUS_HEIGHT;
}
if (new_height == 0)
new_height = curwin->w_height / 2;
if (new_height > curwin->w_height - MIN_ROWS - STATUS_HEIGHT)
new_height = curwin->w_height - MIN_ROWS - STATUS_HEIGHT;
if (new_height < MIN_ROWS)
new_height = MIN_ROWS;
/* if it doesn't fit in the current window, need win_equal() */
if (curwin->w_height - new_height - STATUS_HEIGHT < MIN_ROWS)
do_equal = TRUE;
/*
* allocate new window structure and link it in the window list
*/
if (p_sb) /* new window below current one */
wp = win_alloc(curwin);
else
wp = win_alloc(curwin->w_prev);
if (wp == NULL)
return FAIL;
/*
* compute the new screen positions
*/
wp->w_height = new_height;
win_comp_scroll(wp);
curwin->w_height -= new_height + STATUS_HEIGHT;
win_comp_scroll(curwin);
if (p_sb) /* new window below current one */
{
wp->w_winpos = curwin->w_winpos + curwin->w_height + STATUS_HEIGHT;
wp->w_status_height = curwin->w_status_height;
curwin->w_status_height = STATUS_HEIGHT;
}
else /* new window above current one */
{
wp->w_winpos = curwin->w_winpos;
wp->w_status_height = STATUS_HEIGHT;
curwin->w_winpos = wp->w_winpos + wp->w_height + STATUS_HEIGHT;
}
/*
* make the contents of the new window the same as the current one
*/
wp->w_buffer = curbuf;
curbuf->b_nwindows++;
wp->w_cursor = curwin->w_cursor;
wp->w_row = curwin->w_row;
wp->w_col = curwin->w_col;
wp->w_virtcol = curwin->w_virtcol;
wp->w_curswant = curwin->w_curswant;
wp->w_set_curswant = curwin->w_set_curswant;
wp->w_empty_rows = curwin->w_empty_rows;
wp->w_leftcol = curwin->w_leftcol;
wp->w_pcmark = curwin->w_pcmark;
wp->w_prev_pcmark = curwin->w_prev_pcmark;
wp->w_arg_idx = curwin->w_arg_idx;
/*
* copy tagstack and options from existing window
*/
for (i = 0; i < curwin->w_tagstacklen; i++)
{
wp->w_tagstack[i].fmark = curwin->w_tagstack[i].fmark;
wp->w_tagstack[i].tagname = strsave(curwin->w_tagstack[i].tagname);
}
wp->w_tagstackidx = curwin->w_tagstackidx;
wp->w_tagstacklen = curwin->w_tagstacklen;
win_copy_options(curwin, wp);
/*
* Both windows need redrawing
*/
wp->w_redr_type = NOT_VALID;
wp->w_redr_status = TRUE;
curwin->w_redr_type = NOT_VALID;
curwin->w_redr_status = TRUE;
/*
* Cursor is put in middle of window in both windows
*/
if (wp->w_height < curwin->w_height) /* use smallest of two heights */
h = wp->w_height;
else
h = curwin->w_height;
h >>= 1;
for (lnum = wp->w_cursor.lnum; lnum > 1; --lnum)
{
h -= plines(lnum);
if (h <= 0)
break;
}
w