⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 window.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
/* vi:set ts=8 sts=4 sw=4:
 *
 * VIM - Vi IMproved	by Bram Moolenaar
 *
 * Do ":help uganda"  in Vim to read a list of people who contributed.
 * Do ":help credits" in Vim to see a list of people who contributed.
 */

#include "vim.h"

#ifdef FILE_IN_PATH
static char_u *find_file_in_path __ARGS((char_u *ptr, int len, int options, long count));
static char_u *find_file_in_wildcard_path __ARGS((char_u *path_so_far, char_u *wildcards, int level, long *countptr));
static int path_is_url __ARGS((char_u *p));
#endif
static void reset_VIsual __ARGS((void));
static int win_comp_pos __ARGS((void));
static void win_exchange __ARGS((long));
static void win_rotate __ARGS((int, int));
static void win_goto __ARGS((WIN *wp));
static void win_append __ARGS((WIN *, WIN *));
static void win_remove __ARGS((WIN *));
static void win_new_height __ARGS((WIN *, int));

static WIN	*prevwin = NULL;	/* previous window */

#define URL_SLASH	1		/* path_is_url() has found "://" */
#define URL_BACKSLASH	2		/* path_is_url() has found ":\\" */

/*
 * all CTRL-W window commands are handled here, called from normal_cmd().
 */
    void
do_window(nchar, Prenum)
    int		nchar;
    long	Prenum;
{
    long	Prenum1;
    WIN		*wp;
    int		xchar;
#if defined(FILE_IN_PATH) || defined(FIND_IN_PATH)
    char_u	*ptr;
#endif
#ifdef FIND_IN_PATH
    int		type = FIND_DEFINE;
    int		len;
#endif

    if (Prenum == 0)
	Prenum1 = 1;
    else
	Prenum1 = Prenum;

    switch (nchar)
    {
/* split current window in two parts */
    case 'S':
    case Ctrl('S'):
    case 's':	reset_VIsual();			/* stop Visual mode */
#ifdef USE_GUI
		need_mouse_correct = TRUE;
#endif
		win_split((int)Prenum, TRUE, FALSE);
		break;

/* split current window and edit alternate file */
    case K_CCIRCM:
    case '^':
		reset_VIsual();			/* stop Visual mode */
		stuffReadbuff((char_u *)":split #");
		if (Prenum)
		    stuffnumReadbuff(Prenum);	/* buffer number */
		stuffcharReadbuff('\n');
		break;

/* open new window */
    case Ctrl('N'):
    case 'n':	reset_VIsual();			/* stop Visual mode */
		stuffcharReadbuff(':');
		if (Prenum)
		    stuffnumReadbuff(Prenum);	    /* window height */
		stuffReadbuff((char_u *)"new\n");   /* it is ex_docmd.c */
		break;

/* quit current window */
    case Ctrl('Q'):
    case 'q':	reset_VIsual();			/* stop Visual mode */
		stuffReadbuff((char_u *)":quit\n"); /* it is ex_docmd.c */
		break;

/* close current window */
    case Ctrl('C'):
    case 'c':	reset_VIsual();			/* stop Visual mode */
		stuffReadbuff((char_u *)":close\n");	/* it is ex_docmd.c */
		break;

/* close all but current window */
    case Ctrl('O'):
    case 'o':	reset_VIsual();			/* stop Visual mode */
		stuffReadbuff((char_u *)":only\n"); /* it is ex_docmd.c */
		break;

/* cursor to next window */
    case 'j':
    case K_DOWN:
    case Ctrl('J'):
		for (wp = curwin; wp->w_next != NULL && Prenum1-- > 0;
							    wp = wp->w_next)
		    ;
		win_goto(wp);
		break;

/* cursor to next window with wrap around */
    case Ctrl('W'):
    case 'w':
/* cursor to previous window with wrap around */
    case 'W':
		if (lastwin == firstwin)	/* just one window */
		    beep_flush();
		else
		{
		    if (Prenum)			/* go to specified window */
		    {
			for (wp = firstwin; --Prenum > 0; )
			{
			    if (wp->w_next == NULL)
				break;
			    else
				wp = wp->w_next;
			}
		    }
		    else
		    {
			if (nchar == 'W')	    /* go to previous window */
			{
			    wp = curwin->w_prev;
			    if (wp == NULL)
				wp = lastwin;	    /* wrap around */
			}
			else			    /* go to next window */
			{
			    wp = curwin->w_next;
			    if (wp == NULL)
				wp = firstwin;	    /* wrap around */
			}
		    }
		    win_goto(wp);
		}
		break;

/* cursor to window above */
    case 'k':
    case K_UP:
    case Ctrl('K'):
		for (wp = curwin; wp->w_prev != NULL && Prenum1-- > 0;
							    wp = wp->w_prev)
		    ;
		win_goto(wp);
		break;

/* cursor to top window */
    case 't':
    case Ctrl('T'):
		wp = firstwin;
		win_goto(wp);
		break;

/* cursor to bottom window */
    case 'b':
    case Ctrl('B'):
		wp = lastwin;
		win_goto(wp);
		break;

/* cursor to last accessed (previous) window */
    case 'p':
    case Ctrl('P'):
		if (prevwin == NULL)
		    beep_flush();
		else
		{
		    wp = prevwin;
		    win_goto(wp);
		}
		break;

/* exchange current and next window */
    case 'x':
    case Ctrl('X'):
		win_exchange(Prenum);
		break;

/* rotate windows downwards */
    case Ctrl('R'):
    case 'r':	reset_VIsual();			/* stop Visual mode */
		win_rotate(FALSE, (int)Prenum1);    /* downwards */
		break;

/* rotate windows upwards */
    case 'R':	reset_VIsual();			/* stop Visual mode */
		win_rotate(TRUE, (int)Prenum1);	    /* upwards */
		break;

/* make all windows the same height */
    case '=':
#ifdef USE_GUI
		need_mouse_correct = TRUE;
#endif
		win_equal(NULL, TRUE);
		break;

/* increase current window height */
    case '+':
#ifdef USE_GUI
		need_mouse_correct = TRUE;
#endif
		win_setheight(curwin->w_height + (int)Prenum1);
		break;

/* decrease current window height */
    case '-':
#ifdef USE_GUI
		need_mouse_correct = TRUE;
#endif
		win_setheight(curwin->w_height - (int)Prenum1);
		break;

/* set current window height */
    case Ctrl('_'):
    case '_':
#ifdef USE_GUI
		need_mouse_correct = TRUE;
#endif
		win_setheight(Prenum ? (int)Prenum : 9999);
		break;

/* jump to tag and split window if tag exists */
    case ']':
    case Ctrl(']'):
		reset_VIsual();			/* stop Visual mode */
		if (Prenum)
		    postponed_split = Prenum;
		else
		    postponed_split = -1;
		stuffcharReadbuff(Ctrl(']'));
		break;

#ifdef FILE_IN_PATH
/* edit file name under cursor in a new window */
    case 'f':
    case Ctrl('F'):
		reset_VIsual();			/* stop Visual mode */
		ptr = file_name_at_cursor(FNAME_MESS|FNAME_HYP|FNAME_EXP,
								     Prenum1);
		if (ptr != NULL)
		{
#ifdef USE_GUI
		    need_mouse_correct = TRUE;
#endif
		    setpcmark();
		    if (win_split(0, FALSE, FALSE) == OK)
			(void)do_ecmd(0, ptr, NULL, NULL, (linenr_t)0,
								   ECMD_HIDE);
		    vim_free(ptr);
		}
		break;
#endif

#ifdef FIND_IN_PATH
/* Go to the first occurence of the identifier under cursor along path in a
 * new window -- webb
 */
    case 'i':			    /* Go to any match */
    case Ctrl('I'):
		type = FIND_ANY;
		/* FALLTHROUGH */
    case 'd':			    /* Go to definition, using p_def */
    case Ctrl('D'):
		if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
		    break;
		find_pattern_in_path(ptr, 0, len, TRUE,
			Prenum == 0 ? TRUE : FALSE, type,
			Prenum1, ACTION_SPLIT, (linenr_t)1, (linenr_t)MAXLNUM);
		curwin->w_set_curswant = TRUE;
		break;
#endif

/* CTRL-W g  extended commands */
    case 'g':
#ifdef USE_GUI_WIN32
		dont_scroll = TRUE;		/* disallow scrolling here */
#endif
		++no_mapping;
		++allow_keys;   /* no mapping for xchar, but allow key codes */
		xchar = vgetc();
#ifdef HAVE_LANGMAP
		LANGMAP_ADJUST(xchar, TRUE);
#endif
		--no_mapping;
		--allow_keys;
#ifdef SHOWCMD
		(void)add_to_showcmd(xchar);
#endif
		switch (xchar)
		{
		    case ']':
		    case Ctrl(']'):
			reset_VIsual();			/* stop Visual mode */
			if (Prenum)
			    postponed_split = Prenum;
			else
			    postponed_split = -1;
			stuffcharReadbuff('g');
			stuffcharReadbuff(xchar);
			break;

		    default:
			beep_flush();
			break;
		}
		break;

    default:	beep_flush();
		break;
    }
}

    static void
reset_VIsual()
{
    if (VIsual_active)
    {
	end_visual_mode();
	update_curbuf(NOT_VALID);	/* delete the inversion */
    }
    VIsual_reselect = FALSE;
}

/*
 * 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, req_room)
    int	    new_height;
    int	    redraw;
    int	    req_room;	    /* require enough room for new window */
{
    WIN		*wp;
    int		i;
    int		need_status;
    int		do_equal = (p_ea && new_height == 0);
    int		needed;
    int		available;
    int		curwin_height;

    /* 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 * p_wmh + STATUS_HEIGHT + need_status;
    if (req_room)
	needed += p_wh - p_wmh;
    if (p_ea)
    {
	for (wp = firstwin; wp != NULL; wp = wp->w_next)
	    if (wp != curwin)
	    {
		available += wp->w_height;
		needed += p_wmh;
	    }
    }
    if (available < needed)
    {
	EMSG(e_noroom);
	return FAIL;
    }
    curwin_height = curwin->w_height;
    if (need_status)
    {
	curwin->w_status_height = STATUS_HEIGHT;
	curwin_height -= STATUS_HEIGHT;
    }
    if (new_height == 0)
	new_height = curwin_height / 2;

    if (new_height > curwin_height - p_wmh - STATUS_HEIGHT)
	new_height = curwin_height - p_wmh - STATUS_HEIGHT;

    if (new_height < p_wmh)
	new_height = p_wmh;

    /* if it doesn't fit in the current window, need win_equal() */
    if (curwin_height - new_height - STATUS_HEIGHT < p_wmh)
	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
 */
    win_new_height(wp, new_height);
    win_new_height(curwin, curwin_height - (new_height + STATUS_HEIGHT));
    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_valid = 0;
    wp->w_curswant = curwin->w_curswant;
    wp->w_set_curswant = curwin->w_set_curswant;
    wp->w_topline = curwin->w_topline;
    wp->w_leftcol = curwin->w_leftcol;
    wp->w_pcmark = curwin->w_pcmark;
    wp->w_prev_pcmark = curwin->w_prev_pcmark;
    wp->w_alt_fnum = curwin->w_alt_fnum;
    wp->w_fraction = curwin->w_fraction;
    wp->w_prev_fraction_row = curwin->w_prev_fraction_row;

    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 = vim_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;

    if (need_status)
    {
	msg_row = Rows - 1;
	msg_col = sc_col;
	msg_clr_eos();	/* Old command/ruler may still be there -- webb */
	comp_col();
	msg_row = Rows - 1;
	msg_col = 0;	/* put position back at start of line */
    }
/*
 * make the new window the current window and redraw
 */
    if (do_equal)
	win_equal(wp, FALSE);
    win_enter(wp, FALSE);

    if (redraw)
	update_screen(NOT_VALID);
    else
	redraw_later(NOT_VALID);

    return OK;
}

/*
 * Check if "win" is a pointer to an existing window.
 */
    int
win_valid(win)
    WIN	    *win;
{
    WIN	    *wp;

    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	if (wp == win)
	    return TRUE;
    return FALSE;
}

/*
 * Return the number of windows.
 */
    int
win_count()
{
    WIN	    *wp;
    int	    count = 0;

    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	++count;
    return count;
}

/*
 * Make 'count' windows on the screen.
 * Return actual number of windows on the screen.
 * Must be called when there is just one window, filling the whole screen
 * (excluding the command line).
 */
    int
make_windows(count)
    int	    count;
{
    int	    maxcount;
    int	    todo;
    int	    p_sb_save;

/*
 * Each window needs at least 'winminheight' lines and a status line.
 * Add 4 lines for one window, otherwise we may end up with all zero-line
 * windows. Use value of 'winheight' if it is set
 */
    maxcount = (curwin->w_height + curwin->w_status_height
				  - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
    if (maxcount < 2)
	maxcount = 2;
    if (count > maxcount)
	count = maxcount;

    /*
     * add status line now, otherwise first window will be too big
     */
    if ((p_ls == 2 || (count > 1 && p_ls == 1)) && curwin->w_status_height == 0)
    {
	curwin->w_status_height = STATUS_HEIGHT;
	win_new_height(curwin, curwin->w_height - STATUS_HEIGHT);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -