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

📄 window.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
    }

#ifdef AUTOCMD
/*
 * Don't execute autocommands while creating the windows.  Must do that
 * when putting the buffers in the windows.
 */
    ++autocmd_busy;
#endif

/*
 * set 'splitbelow' off for a moment, don't want that now
 */
    p_sb_save = p_sb;
    p_sb = FALSE;
	/* todo is number of windows left to create */
    for (todo = count - 1; todo > 0; --todo)
	if (win_split(curwin->w_height - (curwin->w_height - todo
				* STATUS_HEIGHT) / (todo + 1) - STATUS_HEIGHT,
							FALSE, FALSE) == FAIL)
	    break;
    p_sb = p_sb_save;

#ifdef AUTOCMD
    --autocmd_busy;
#endif

	/* return actual number of windows */
    return (count - todo);
}

/*
 * Exchange current and next window
 */
    static void
win_exchange(Prenum)
    long	Prenum;
{
    WIN	    *wp;
    WIN	    *wp2;
    int	    temp;

    if (lastwin == firstwin)	    /* just one window */
    {
	beep_flush();
	return;
    }

#ifdef USE_GUI
    need_mouse_correct = TRUE;
#endif

/*
 * find window to exchange with
 */
    if (Prenum)
    {
	wp = firstwin;
	while (wp != NULL && --Prenum > 0)
	    wp = wp->w_next;
    }
    else if (curwin->w_next != NULL)	/* Swap with next */
	wp = curwin->w_next;
    else    /* Swap last window with previous */
	wp = curwin->w_prev;

    if (wp == curwin || wp == NULL)
	return;

/*
 * 1. remove curwin from the list. Remember after which window it was in wp2
 * 2. insert curwin before wp in the list
 * if wp != wp2
 *    3. remove wp from the list
 *    4. insert wp after wp2
 * 5. exchange the status line height
 */
    wp2 = curwin->w_prev;
    win_remove(curwin);
    win_append(wp->w_prev, curwin);
    if (wp != wp2)
    {
	win_remove(wp);
	win_append(wp2, wp);
    }
    temp = curwin->w_status_height;
    curwin->w_status_height = wp->w_status_height;
    wp->w_status_height = temp;

    win_comp_pos();		/* recompute window positions */

    win_enter(wp, TRUE);
    update_screen(CLEAR);
}

/*
 * rotate windows: if upwards TRUE the second window becomes the first one
 *		   if upwards FALSE the first window becomes the second one
 */
    static void
win_rotate(upwards, count)
    int	    upwards;
    int	    count;
{
    WIN		 *wp;
    int		 height;

    if (firstwin == lastwin)		/* nothing to do */
    {
	beep_flush();
	return;
    }

#ifdef USE_GUI
    need_mouse_correct = TRUE;
#endif

    while (count--)
    {
	if (upwards)		/* first window becomes last window */
	{
	    wp = firstwin;
	    win_remove(wp);
	    win_append(lastwin, wp);
	    wp = lastwin->w_prev;	    /* previously last window */
	}
	else			/* last window becomes first window */
	{
	    wp = lastwin;
	    win_remove(lastwin);
	    win_append(NULL, wp);
	    wp = firstwin;		    /* previously last window */
	}
	    /* exchange status height of old and new last window */
	height = lastwin->w_status_height;
	lastwin->w_status_height = wp->w_status_height;
	wp->w_status_height = height;

	    /* recompute w_winpos for all windows */
	(void)win_comp_pos();
    }

    update_screen(CLEAR);
}

/*
 * Move window "win1" to below "win2" and make "win1" the current window.
 */
    void
win_move_after(win1, win2)
    WIN	*win1, *win2;
{
    int	    height;

    /* check if the arguments are reasonable */
    if (win1 == win2)
	return;

    /* check if there is something to do */
    if (win2->w_next != win1)
    {
	/* may need move the status line of the last window */
	if (win1 == lastwin)
	{
	    height = win1->w_prev->w_status_height;
	    win1->w_prev->w_status_height = win1->w_status_height;
	    win1->w_status_height = height;
	}
	else if (win2 == lastwin)
	{
	    height = win1->w_status_height;
	    win1->w_status_height = win2->w_status_height;
	    win2->w_status_height = height;
	}
	win_remove(win1);
	win_append(win2, win1);

	(void)win_comp_pos();	/* recompute w_winpos for all windows */
	redraw_later(NOT_VALID);
    }
    win_enter(win1, FALSE);
}

/*
 * Make all windows the same height.
 * 'next_curwin' will soon be the current window, make sure it has enough
 * rows.
 */
    void
win_equal(next_curwin, redraw)
    WIN	    *next_curwin;	    /* pointer to current window to be */
    int	    redraw;
{
    int	    total;
    int	    less;
    int	    wincount;
    int	    winpos;
    int	    temp;
    WIN	    *wp;
    int	    new_height;

/*
 * count the number of lines available
 */
    total = 0;
    wincount = 0;
    for (wp = firstwin; wp; wp = wp->w_next)
    {
	total += wp->w_height - p_wmh;
	wincount++;
    }

/*
 * If next_curwin given and 'winheight' set, make next_curwin p_wh lines.
 */
    less = 0;
    if (next_curwin != NULL)
    {
	if (p_wh - p_wmh > total)    /* all lines go to current window */
	    less = total;
	else
	{
	    less = p_wh - p_wmh - total / wincount;
	    if (less < 0)
		less = 0;
	}
    }

/*
 * spread the available lines over the windows
 */
    winpos = 0;
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
    {
	if (wp == next_curwin && less)
	{
	    less = 0;
	    temp = p_wh - p_wmh;
	    if (temp > total)
		temp = total;
	}
	else
	    temp = (total - less + ((unsigned)wincount >> 1)) / wincount;
	new_height = p_wmh + temp;
	if (wp->w_winpos != winpos || wp->w_height != new_height)
	{
	    wp->w_redr_type = NOT_VALID;
	    wp->w_redr_status = TRUE;
	}
	wp->w_winpos = winpos;
	win_new_height(wp, new_height);
	total -= temp;
	--wincount;
	winpos += wp->w_height + wp->w_status_height;
    }
    if (redraw)
	must_redraw = CLEAR;
}

/*
 * close all windows for buffer 'buf'
 */
    void
close_windows(buf)
    BUF	    *buf;
{
    WIN	    *win;

    ++RedrawingDisabled;
    for (win = firstwin; win != NULL && lastwin != firstwin; )
    {
	if (win->w_buffer == buf)
	{
	    close_window(win, FALSE);
	    win = firstwin;	    /* go back to the start */
	}
	else
	    win = win->w_next;
    }
    --RedrawingDisabled;
}

/*
 * close window "win"
 * If "free_buf" is TRUE related buffer may be freed.
 *
 * called by :quit, :close, :xit, :wq and findtag()
 */
    void
close_window(win, free_buf)
    WIN	    *win;
    int	    free_buf;
{
    WIN	    *wp;
#ifdef AUTOCMD
    int	    other_buffer = FALSE;
#endif

    if (lastwin == firstwin)
    {
	EMSG("Cannot close last window");
	return;
    }

#ifdef AUTOCMD
    if (win == curwin)
    {
	/*
	 * Guess which window is going to be the new current window.
	 * This may change because of the autocommands (sigh).
	 */
	if ((!p_sb && win->w_next != NULL) || win->w_prev == NULL)
	    wp = win->w_next;
	else
	    wp = win->w_prev;

	/*
	 * Be careful: If autocommands delete the window, return now.
	 */
	if (wp->w_buffer != curbuf)
	{
	    other_buffer = TRUE;
	    apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
	    if (!win_valid(win))
		return;
	}
	apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
	if (!win_valid(win))
	    return;
    }
#endif

/*
 * Remove the window.
 * if 'splitbelow' the free space goes to the window above it.
 * if 'nosplitbelow' the free space goes to the window below it.
 * This makes opening a window and closing it immediately keep the same window
 * layout.
 */
				    /* freed space goes to next window */
    if ((!p_sb && win->w_next != NULL) || win->w_prev == NULL)
    {
	wp = win->w_next;
	wp->w_winpos = win->w_winpos;
    }
    else			    /* freed space goes to previous window */
	wp = win->w_prev;
    win_new_height(wp, wp->w_height + win->w_height + win->w_status_height);

/*
 * Close the link to the buffer.
 */
    close_buffer(win, win->w_buffer, free_buf, FALSE);

    win_free(win);
    if (win == curwin)
	curwin = NULL;
    if (p_ea)
	win_equal(wp, FALSE);
    if (curwin == NULL)
    {
	win_enter(wp, FALSE);
#ifdef AUTOCMD
	if (other_buffer)
	    /* careful: after this wp and win may be invalid! */
	    apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
#endif
    }

    /*
     * if last window has status line now and we don't want one,
     * remove the status line
     */
    if (lastwin->w_status_height &&
			(p_ls == 0 || (p_ls == 1 && firstwin == lastwin)))
    {
	win_new_height(lastwin, lastwin->w_height + lastwin->w_status_height);
	lastwin->w_status_height = 0;
	comp_col();
    }

    update_screen(NOT_VALID);
}

/*
 * Close all windows except current one.
 * Buffers in the other windows become hidden if 'hidden' is set, or '!' is
 * used and the buffer was modified.
 *
 * Used by ":bdel" and ":only".
 */
    void
close_others(message, forceit)
    int	    message;
    int	    forceit;	    /* always hide all other windows */
{
    WIN	    *wp;
    WIN	    *nextwp;

    if (lastwin == firstwin)
    {
	if (message
#ifdef AUTOCMD
		    && !autocmd_busy
#endif
				    )
	    MSG("Already only one window");
	return;
    }

    for (wp = firstwin; wp != NULL; wp = nextwp)
    {
	nextwp = wp->w_next;
	if (wp == curwin)		/* don't close current window */
	    continue;

	/* Check if it's allowed to abandon this window */
	if (!can_abandon(wp->w_buffer, forceit))
	    continue;

	/* Close the link to the buffer. */
	close_buffer(wp, wp->w_buffer,
				 !p_hid && !buf_changed(wp->w_buffer), FALSE);

	/* Remove the window.  All lines go to previous or next window. */
	if (wp->w_prev != NULL)
	    win_new_height(wp->w_prev,
		   wp->w_prev->w_height + wp->w_height + wp->w_status_height);
	else
	{
	    win_new_height(wp->w_next,
		   wp->w_next->w_height + wp->w_height + wp->w_status_height);
	    wp->w_next->w_winpos = wp->w_winpos;
	}
	win_free(wp);
    }

    /*
     * If current window has a status line and we don't want one,
     * remove the status line.
     */
    if (lastwin != firstwin)
	EMSG("Other window contains changes");
    else if (curwin->w_status_height && p_ls != 2)
    {
	win_new_height(curwin, curwin->w_height + curwin->w_status_height);
	curwin->w_status_height = 0;
	comp_col();
    }
    if (message)
	update_screen(NOT_VALID);
}

/*
 * init the cursor in the window
 *
 * called when a new file is being edited
 */
    void
win_init(wp)
    WIN	    *wp;
{
    wp->w_redr_type = NOT_VALID;
    wp->w_cursor.lnum = 1;
    wp->w_curswant = wp->w_cursor.col = 0;
    wp->w_pcmark.lnum = 1;	/* pcmark not cleared but set to line 1 */
    wp->w_pcmark.col = 0;
    wp->w_prev_pcmark.lnum = 0;
    wp->w_prev_pcmark.col = 0;
    wp->w_topline = 1;
    wp->w_botline = 2;
#ifdef FKMAP
    if (curwin->w_p_rl)
	wp->w_p_pers = W_CONV + W_R_L;
    else
	wp->w_p_pers = W_CONV;
#endif
}

/*
 * Go to another window.
 * When jumping to another buffer, stop visual mode.  Do this before
 * changing windows so we can yank the selection into the '*' register.
 */
    static void
win_goto(wp)
    WIN	    *wp;
{
    if (wp->w_buffer != curbuf && VIsual_active)
    {
	end_visual_mode();
	redraw_curbuf_later(NOT_VALID);
    }
    VIsual_reselect = FALSE;
#ifdef USE_GUI
    need_mouse_correct = TRUE;
#endif
    win_enter(wp, TRUE);
}

/*
 * Go to window nr "winnr" (counting top to bottom).
 */
    WIN *
win_goto_nr(winnr)
    int	    winnr;
{
    WIN	    *wp;

    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	if (--winnr == 0)
	    break;
    return wp;
}

/*
 * Make window wp the current window.
 * Can be called when curwin == NULL, if curwin already has been closed.
 */
    void
win_enter(wp, undo_sync)
    WIN	    *wp;
    int	    undo_sync;
{
#ifdef AUTOCMD
    int		other_buffer = FALSE;
#endif

    if (wp == curwin)		/* nothing to do */
	return;

#ifdef AUTOCMD
    if (curwin != NULL)
    {
	/*
	 * Be careful: If autocommands delete the window, return now.
	 */
	if (wp->w_buffer != curbuf)
	{
	    apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
	    other_buffer = TRUE;
	    if (!win_valid(wp))
		return;
	}
	apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
	if (!win_valid(wp))
	    return;
    }
#endif

	/* sync undo before leaving the current buffer */
    if (undo_sync && curbuf != wp->w_buffer)
	u_sync();
	/* may have to copy the buffer options when 'cpo' contains 'S' */
    if (wp->w_buffer != curbuf)

⌨️ 快捷键说明

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