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

📄 window.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
	buf_copy_options(curbuf, wp->w_buffer, BCO_ENTER | BCO_NOHELP);
    if (curwin != NULL)
    {
	prevwin = curwin;	/* remember for CTRL-W p */
	curwin->w_redr_status = TRUE;
    }
    curwin = wp;
    curbuf = wp->w_buffer;
    adjust_cursor();
    changed_line_abv_curs();	/* assume cursor position needs updating */

#ifdef AUTOCMD
    apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
    if (other_buffer)
	apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
#endif

    maketitle();
    curwin->w_redr_status = TRUE;

	    /* set window height to desired minimal value */
    if (curwin->w_height < p_wh)
	win_setheight((int)p_wh);
#ifdef USE_MOUSE
    setmouse();			/* in case jumped to/from help buffer */
#endif
}

/*
 * allocate a window structure and link it in the window list
 */
    WIN *
win_alloc(after)
    WIN	    *after;
{
    WIN	    *newwin;

    /*
     * allocate window structure and linesizes arrays
     */
    newwin = (WIN *)alloc_clear((unsigned)sizeof(WIN));
    if (newwin != NULL && win_alloc_lsize(newwin) == FAIL)
    {
	vim_free(newwin);
	newwin = NULL;
    }

    if (newwin != NULL)
    {
	/*
	 * link the window in the window list
	 */
	win_append(after, newwin);

	/* position the display and the cursor at the top of the file. */
	newwin->w_topline = 1;
	newwin->w_botline = 2;
	newwin->w_cursor.lnum = 1;

	/* We won't calculate w_fraction until resizing the window */
	newwin->w_fraction = 0;
	newwin->w_prev_fraction_row = -1;

#ifdef USE_GUI
	if (gui.in_use)
	{
	    gui_create_scrollbar(&newwin->w_scrollbars[SBAR_LEFT], newwin);
	    gui_create_scrollbar(&newwin->w_scrollbars[SBAR_RIGHT], newwin);
	}
#endif
#ifdef WANT_EVAL
	var_init(&newwin->w_vars);	    /* init internal variables */
#endif
    }
    return newwin;
}

/*
 * remove window 'wp' from the window list and free the structure
 */
    void
win_free(wp)
    WIN	    *wp;
{
    int	    i;

#ifdef HAVE_PERL_INTERP
    perl_win_free(wp);
#endif

#ifdef HAVE_PYTHON
    python_window_free(wp);
#endif

#ifdef HAVE_TCL
    tcl_window_free(wp);
#endif

#ifdef WANT_EVAL
    var_clear(&wp->w_vars);	    /* free all internal variables */
#endif

    if (prevwin == wp)
	prevwin = NULL;
    win_free_lsize(wp);

    for (i = 0; i < wp->w_tagstacklen; ++i)
	vim_free(wp->w_tagstack[i].tagname);

#ifdef USE_GUI
    if (gui.in_use)
    {
	gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_LEFT]);
	gui_mch_destroy_scrollbar(&wp->w_scrollbars[SBAR_RIGHT]);
    }
#endif /* USE_GUI */

    win_remove(wp);
    vim_free(wp);
}

    static void
win_append(after, wp)
    WIN	    *after, *wp;
{
    WIN	    *before;

    if (after == NULL)	    /* after NULL is in front of the first */
	before = firstwin;
    else
	before = after->w_next;

    wp->w_next = before;
    wp->w_prev = after;
    if (after == NULL)
	firstwin = wp;
    else
	after->w_next = wp;
    if (before == NULL)
	lastwin = wp;
    else
	before->w_prev = wp;
}

/*
 * remove window from the window list
 */
    static void
win_remove(wp)
    WIN	    *wp;
{
    if (wp->w_prev)
	wp->w_prev->w_next = wp->w_next;
    else
	firstwin = wp->w_next;
    if (wp->w_next)
	wp->w_next->w_prev = wp->w_prev;
    else
	lastwin = wp->w_prev;
}

/*
 * allocate lsize arrays for a window
 * return FAIL for failure, OK for success
 */
    int
win_alloc_lsize(wp)
    WIN	    *wp;
{
    wp->w_lsize_valid = 0;
    wp->w_lsize_lnum = (linenr_t *)alloc((unsigned)(Rows * sizeof(linenr_t)));
    wp->w_lsize = alloc((unsigned)Rows);
    if (wp->w_lsize_lnum == NULL || wp->w_lsize == NULL)
    {
	win_free_lsize(wp);	/* one of the two may have worked */
	return FAIL;
    }
    return OK;
}

/*
 * free lsize arrays for a window
 */
    void
win_free_lsize(wp)
    WIN	    *wp;
{
    vim_free(wp->w_lsize_lnum);
    vim_free(wp->w_lsize);
    wp->w_lsize_lnum = NULL;
    wp->w_lsize = NULL;
}

/*
 * call this fuction whenever Rows changes value
 */
    void
screen_new_rows()
{
    WIN	    *wp;
    int	    extra_lines;

    if (firstwin == NULL)	/* not initialized yet */
	return;
/*
 * the number of extra lines is the difference between the position where
 * the command line should be and where it is now
 */
    extra_lines = Rows - p_ch -
	   (lastwin->w_winpos + lastwin->w_height + lastwin->w_status_height);
    if (extra_lines < 0)			/* reduce windows height */
    {
	for (wp = lastwin; wp; wp = wp->w_prev)
	{
	    if (wp->w_height - p_wmh < -extra_lines)
	    {
		extra_lines += wp->w_height - p_wmh;
		win_new_height(wp, (int)p_wmh);
	    }
	    else
	    {
		win_new_height(wp, wp->w_height + extra_lines);
		break;
	    }
	}
	(void)win_comp_pos();		    /* compute w_winpos */
    }
    else if (extra_lines > 0)		    /* increase height of last window */
	win_new_height(lastwin, lastwin->w_height + extra_lines);

    compute_cmdrow();

    if (p_ea)
	win_equal(curwin, FALSE);
}

/*
 * update the w_winpos field for all windows
 * returns the row just after the last window
 */
    static int
win_comp_pos()
{
    WIN	    *wp;
    int	    row;

    row = 0;
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
    {
	if (wp->w_winpos != row)	/* if position changes, redraw */
	{
	    wp->w_winpos = row;
	    wp->w_redr_type = NOT_VALID;
	    wp->w_redr_status = TRUE;
	}
	row += wp->w_height + wp->w_status_height;
    }
    return row;
}

/*
 * set current window height
 */
    void
win_setheight(height)
    int	    height;
{
    WIN	    *wp;
    int	    room;		/* total number of lines available */
    int	    take;		/* number of lines taken from other windows */
    int	    room_cmdline;	/* lines available from cmdline */
    int	    row;
    int	    run;

    if (p_wmh == 0)
    {
	/* Always keep current window at least one line high, even when
	 * 'winminheight' is zero */
	if (height == 0)	/* need at least one line */
	{
	    height = 1;
	    room = 1;
	}
	else
	    room = p_wmh;	/* count 'winminheight' for the curr. window */
    }
    else
    {
	if (height < p_wmh)	/* need at least some lines */
	    height = p_wmh;
	room = p_wmh;		/* count 'winminheight' for the curr. window */
    }

/*
 * compute the room we have from all the windows
 */
    room_cmdline = Rows - p_ch;
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
    {
	room += wp->w_height - p_wmh;
	room_cmdline -= wp->w_height + wp->w_status_height;
    }
/*
 * limit new height to the room available
 */
    if (height > room + room_cmdline)	    /* can't make it that large */
	height = room + room_cmdline;	    /* use all available room */
/*
 * compute the number of lines we will take from the windows (can be negative)
 */
    take = height - curwin->w_height;
    if (take == 0)			    /* no change, nothing to do */
	return;

    if (take > 0)
    {
	take -= room_cmdline;		    /* use lines from cmdline first */
	if (take < 0)
	    take = 0;
    }
/*
 * set the current window to the new height
 */
    win_new_height(curwin, height);

/*
 * First take lines from the windows below the current window.
 * If that is not enough, takes lines from windows above the current window.
 */
    for (run = 0; run < 2; ++run)
    {
	if (run == 0)
	    wp = curwin->w_next;	/* 1st run: start with next window */
	else
	    wp = curwin->w_prev;	/* 2nd run: start with prev window */
	while (wp != NULL && take != 0)
	{
	    if (wp->w_height - take < p_wmh)
	    {
		take -= wp->w_height - p_wmh;
		win_new_height(wp, (int)p_wmh);
	    }
	    else
	    {
		win_new_height(wp, wp->w_height - take);
		take = 0;
	    }
	    if (run == 0)
		wp = wp->w_next;
	    else
		wp = wp->w_prev;
	}
    }

/* recompute the window positions */
    row = win_comp_pos();

/*
 * If there is extra space created between the last window and the command line,
 * clear it.
 */
    if (full_screen && msg_scrolled == 0)
	screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
    cmdline_row = row;

    update_screen(NOT_VALID);
}

/*
 * Check 'winminheight' for a valid value.
 */
    void
win_setminheight()
{
    int		room;
    int		first = TRUE;
    WIN		*wp;

    /* loop until there is a 'winminheight' that is possible */
    while (p_wmh > 0)
    {
	room = -p_wh;
	for (wp = firstwin; wp != NULL; wp = wp->w_next)
	    room += wp->w_height - p_wmh;
	if (room >= 0)
	    break;
	--p_wmh;
	if (first)
	{
	    EMSG(e_noroom);
	    first = FALSE;
	}
    }
}

#ifdef USE_MOUSE

    void
win_drag_status_line(offset)
    int	    offset;
{
    WIN	    *wp;
    int	    room;
    int	    row;
    int	    up;		/* if TRUE, drag status line up, otherwise down */

    if (offset < 0)
    {
	up = TRUE;
	offset = -offset;
    }
    else
	up = FALSE;

    if (up) /* drag up */
    {
	if (p_wmh == 0)
	    room = -1;	/* current window should be at least one line */
	else
	    room = 0;
	for (wp = curwin; wp != NULL && room < offset; wp = wp->w_prev)
	    room += wp->w_height - p_wmh;
	wp = curwin->w_next;		    /* put wp at window that grows */
    }
    else    /* drag down */
    {
	/*
	 * Only dragging the last status line can reduce p_ch.
	 */
	room = Rows - cmdline_row;
	if (curwin->w_next == NULL)
	    room -= 1;
	else
	    room -= p_ch;
	for (wp = curwin->w_next; wp != NULL && room < offset; wp = wp->w_next)
	    room += wp->w_height - p_wmh;
	wp = curwin;			    /* put wp at window that grows */
    }

    if (room < offset)	    /* Not enough room */
	offset = room;	    /* Move as far as we can */
    if (offset <= 0)
	return;

    if (wp != NULL)	    /* grow window wp by offset lines */
	win_new_height(wp, wp->w_height + offset);

    if (up)
	wp = curwin;		    /* current window gets smaller */
    else
	wp = curwin->w_next;	    /* next window gets smaller */

    while (wp != NULL && offset > 0)
    {
	if (wp->w_height - offset <= p_wmh)
	{
	    offset -= wp->w_height - p_wmh;
	    if (wp == curwin && p_wmh == 0)
	    {
		win_new_height(wp, 1);
		offset += 1;
	    }
	    else
		win_new_height(wp, (int)p_wmh);
	}
	else
	{
	    win_new_height(wp, wp->w_height - offset);
	    offset = 0;
	}
	if (up)
	    wp = wp->w_prev;
	else
	    wp = wp->w_next;
    }
    row = win_comp_pos();
    screen_fill(row, cmdline_row, 0, (int)Columns, ' ', ' ', 0);
    cmdline_row = row;
    p_ch = Rows - cmdline_row;
    update_screen(NOT_VALID);
    showmode();
}
#endif /* USE_MOUSE */

/*
 * Set new window height.
 */
    static void
win_new_height(wp, height)
    WIN	    *wp;
    int	    height;
{
    linenr_t	lnum;
    int		sline, line_size;
#define FRACTION_MULT	16384L

    if (wp->w_wrow != wp->w_prev_fraction_row && wp->w_height > 0)
	wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT
				    + FRACTION_MULT / 2) / (long)wp->w_height;

    wp->w_height = height;
    wp->w_skipcol = 0;

    lnum = wp->w_cursor.lnum;
    if (lnum < 1)		/* can happen when starting up */
	lnum = 1;
    wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L) / FRACTION_MULT;
    line_size = plines_win_col(wp, lnum, (long)(wp->w_cursor.col)) - 1;
    sline = wp->w_wrow - line_size;
    if (sline < 0)
    {
	/*
	 * Cursor line would go off top of screen if w_wrow was this high.
	 */
	wp->w_wrow = line_size;
    }
    else
    {
	while (sline > 0 && lnum > 1)
	    sline -= (line_size = plines_win(wp, --lnum));
	if (sline < 0)
	{
	    /*
	     * Line we want at top would go off top of screen.	Use next line
	     * instead.
	     */
	    lnum++;
	    wp->w_wrow -= line_size + sline;
	}
	else if (sline > 0)
	{
	    /* First line of file reached, use that as topline. */
	    lnum = 1;
	    wp->w_wrow -= sline;
	}
    }
    set_topline(wp, lnum);
    if (wp == curwin)
    {
	if (p_so)
	    update_topline();
	curs_columns(FALSE);	    /* validate w_wrow */
    }
    wp->w_prev_fraction_row = wp->w_wrow;

    win_comp_scroll(wp);
    if (wp->w_redr_type < NOT_VALID)
	wp->w_redr_type = NOT_VALID;
    wp->w_redr_status = TRUE;
    invalidate_botline_win(wp);
}

    void
win_comp_scroll(wp)
    WIN	    *wp;

⌨️ 快捷键说明

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