📄 window.c
字号:
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 + -