aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r--src/nvim/window.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 23779d1e7b..d07ae22c31 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -713,7 +713,7 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
}
switchwin_T switchwin;
- if (switch_win_noblock(&switchwin, win, tab, false) == FAIL) {
+ if (switch_win_noblock(&switchwin, win, tab, true) == FAIL) {
api_set_error(err,
kErrorTypeException,
"Failed to switch to window %d",
@@ -733,7 +733,7 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
// So do it now.
validate_cursor();
- restore_win_noblock(&switchwin, false);
+ restore_win_noblock(&switchwin, true);
if (noautocmd) {
unblock_autocmds();
}
@@ -928,6 +928,7 @@ static int check_split_disallowed(void)
// WSP_TOP: open window at the top-left of the screen (help window).
// WSP_BOT: open window at the bottom-right of the screen (quickfix window).
// WSP_HELP: creating the help window, keep layout snapshot
+// WSP_NOENTER: do not enter the new window or trigger WinNew autocommands
//
// return FAIL for failure, OK otherwise
int win_split(int size, int flags)
@@ -956,20 +957,20 @@ int win_split(int size, int flags)
clear_snapshot(curtab, SNAP_HELP_IDX);
}
- return win_split_ins(size, flags, NULL, 0);
+ return win_split_ins(size, flags, NULL, 0) == NULL ? FAIL : OK;
}
/// When "new_wp" is NULL: split the current window in two.
/// When "new_wp" is not NULL: insert this window at the far
/// top/left/right/bottom.
-/// @return FAIL for failure, OK otherwise
-int win_split_ins(int size, int flags, win_T *new_wp, int dir)
+/// @return NULL for failure, or pointer to new window
+win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir)
{
win_T *wp = new_wp;
// aucmd_win[] should always remain floating
if (new_wp != NULL && is_aucmd_win(new_wp)) {
- return FAIL;
+ return NULL;
}
win_T *oldwin;
@@ -985,22 +986,24 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
int need_status = 0;
int new_size = size;
bool new_in_layout = (new_wp == NULL || new_wp->w_floating);
+ bool vertical = flags & WSP_VERT;
+ bool toplevel = flags & (WSP_TOP | WSP_BOT);
// add a status line when p_ls == 1 and splitting the first window
if (one_nonfloat() && p_ls == 1 && oldwin->w_status_height == 0) {
if (oldwin->w_height <= p_wmh && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
need_status = STATUS_HEIGHT;
}
bool do_equal = false;
int oldwin_height = 0;
- const int layout = flags & WSP_VERT ? FR_ROW : FR_COL;
+ const int layout = vertical ? FR_ROW : FR_COL;
bool did_set_fraction = false;
- if (flags & WSP_VERT) {
+ if (vertical) {
// Check if we are able to split the current window and compute its
// width.
// Current window requires at least 1 space.
@@ -1011,7 +1014,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
int minwidth;
int available;
- if (flags & (WSP_BOT | WSP_TOP)) {
+ if (toplevel) {
minwidth = frame_minwidth(topframe, NOWIN);
available = topframe->fr_width;
needed += minwidth;
@@ -1039,7 +1042,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
if (available < needed && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
if (new_size == 0) {
new_size = oldwin->w_width / 2;
@@ -1092,7 +1095,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
int minheight;
int available;
- if (flags & (WSP_BOT | WSP_TOP)) {
+ if (toplevel) {
minheight = frame_minheight(topframe, NOWIN) + need_status;
available = topframe->fr_height;
needed += minheight;
@@ -1119,7 +1122,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
if (available < needed && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
oldwin_height = oldwin->w_height;
if (need_status) {
@@ -1182,7 +1185,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
&& ((flags & WSP_BOT)
|| (flags & WSP_BELOW)
|| (!(flags & WSP_ABOVE)
- && ((flags & WSP_VERT) ? p_spr : p_sb)))) {
+ && (vertical ? p_spr : p_sb)))) {
// new window below/right of current one
if (new_wp == NULL) {
wp = win_alloc(oldwin, false);
@@ -1199,7 +1202,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
if (new_wp == NULL) {
if (wp == NULL) {
- return FAIL;
+ return NULL;
}
new_frame(wp);
@@ -1218,9 +1221,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_T *curfrp;
// Reorganise the tree of frames to insert the new window.
- if (flags & (WSP_TOP | WSP_BOT)) {
- if ((topframe->fr_layout == FR_COL && (flags & WSP_VERT) == 0)
- || (topframe->fr_layout == FR_ROW && (flags & WSP_VERT) != 0)) {
+ if (toplevel) {
+ if ((topframe->fr_layout == FR_COL && !vertical)
+ || (topframe->fr_layout == FR_ROW && vertical)) {
curfrp = topframe->fr_child;
if (flags & WSP_BOT) {
while (curfrp->fr_next != NULL) {
@@ -1237,7 +1240,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
before = false;
} else if (flags & WSP_ABOVE) {
before = true;
- } else if (flags & WSP_VERT) {
+ } else if (vertical) {
before = !p_spr;
} else {
before = !p_sb;
@@ -1285,14 +1288,14 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
wp->w_fraction = oldwin->w_fraction;
- if (flags & WSP_VERT) {
+ if (vertical) {
wp->w_p_scr = curwin->w_p_scr;
if (need_status) {
win_new_height(oldwin, oldwin->w_height - 1);
oldwin->w_status_height = need_status;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
// set height and row of new window to full height
wp->w_winrow = tabline_height();
win_new_height(wp, curfrp->fr_height - (p_ls == 1 || p_ls == 2));
@@ -1316,7 +1319,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
wp->w_vsep_width = oldwin->w_vsep_width;
oldwin->w_vsep_width = 1;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
if (flags & WSP_BOT) {
frame_add_vsep(curfrp);
}
@@ -1338,7 +1341,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else {
const bool is_stl_global = global_stl_height() > 0;
// width and column of new window is same as current window
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
wp->w_wincol = 0;
win_new_width(wp, Columns);
wp->w_vsep_width = 0;
@@ -1359,7 +1362,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
wp->w_hsep_height = oldwin->w_hsep_height;
oldwin->w_hsep_height = is_stl_global ? 1 : 0;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
int new_fr_height = curfrp->fr_height - new_size;
if (is_stl_global) {
if (flags & WSP_BOT) {
@@ -1405,7 +1408,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_fix_height(oldwin);
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
win_comp_pos();
}
@@ -1426,7 +1429,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
// equalize the window sizes.
if (do_equal || dir != 0) {
- win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
+ win_equal(wp, true, vertical ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
} else if (!is_aucmd_win(wp)) {
win_fix_scroll(false);
}
@@ -1447,10 +1450,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
- // make the new window the current window
- win_enter_ext(wp, WEE_TRIGGER_NEW_AUTOCMDS | WEE_TRIGGER_ENTER_AUTOCMDS
- | WEE_TRIGGER_LEAVE_AUTOCMDS);
- if (flags & WSP_VERT) {
+ if (!(flags & WSP_NOENTER)) {
+ // make the new window the current window
+ win_enter_ext(wp, WEE_TRIGGER_NEW_AUTOCMDS | WEE_TRIGGER_ENTER_AUTOCMDS
+ | WEE_TRIGGER_LEAVE_AUTOCMDS);
+ }
+ if (vertical) {
p_wiw = i;
} else {
p_wh = i;
@@ -1461,7 +1466,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
oldwin->w_pos_changed = true;
}
- return OK;
+ return wp;
}
// Initialize window "newp" from window "oldp".
@@ -1557,7 +1562,7 @@ bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
/// Check if "win" is a pointer to an existing window in tabpage "tp".
///
/// @param win window to check
-static bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
+bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win == NULL) {
@@ -2485,7 +2490,7 @@ bool can_close_in_cmdwin(win_T *win, Error *err)
FUNC_ATTR_NONNULL_ALL
{
if (cmdwin_type != 0) {
- if (win == curwin) {
+ if (win == cmdwin_win) {
cmdwin_result = Ctrl_C;
return false;
} else if (win == cmdwin_old_curwin) {
@@ -2553,6 +2558,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
/// "abort_if_last" is passed to close_buffer(): abort closing if all other
/// windows are closed.
static void win_close_buffer(win_T *win, int action, bool abort_if_last)
+ FUNC_ATTR_NONNULL_ALL
{
// Free independent synblock before the buffer is freed.
if (win->w_buffer != NULL) {
@@ -2590,6 +2596,7 @@ static void win_close_buffer(win_T *win, int action, bool abort_if_last)
// Called by :quit, :close, :xit, :wq and findtag().
// Returns FAIL when the window was not closed.
int win_close(win_T *win, bool free_buf, bool force)
+ FUNC_ATTR_NONNULL_ALL
{
tabpage_T *prev_curtab = curtab;
frame_T *win_frame = win->w_floating ? NULL : win->w_frame->fr_parent;
@@ -2888,6 +2895,7 @@ static void do_autocmd_winclosed(win_T *win)
// Caller must check if buffer is hidden and whether the tabline needs to be
// updated.
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ALL
{
// Get here with win->w_buffer == NULL when win_close() detects the tab page
// changed.
@@ -2989,6 +2997,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
///
/// @return a pointer to the window that got the freed up space.
static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
win_T *wp;
tabpage_T *win_tp = tp == NULL ? curtab : tp;
@@ -3007,6 +3016,7 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
wp = firstwin;
}
} else {
+ assert(tp != curtab);
if (tabpage_win_valid(tp, tp->tp_prevwin) && tp->tp_prevwin != win) {
wp = tp->tp_prevwin;
} else {
@@ -3030,6 +3040,9 @@ void win_free_all(void)
{
// avoid an error for switching tabpage with the cmdline window open
cmdwin_type = 0;
+ cmdwin_buf = NULL;
+ cmdwin_win = NULL;
+ cmdwin_old_curwin = NULL;
while (first_tabpage->tp_next != NULL) {
tabpage_close(true);
@@ -3076,7 +3089,10 @@ void win_free_all(void)
///
/// @return a pointer to the window that got the freed up space.
win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1, 2)
{
+ assert(tp == NULL || tp != curtab);
+
// If there is only one window there is nothing to remove.
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
return NULL;
@@ -3223,7 +3239,10 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
/// @return a pointer to the frame that will receive the empty screen space that
/// is left over after "win" is closed.
static frame_T *win_altframe(win_T *win, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
+ assert(tp == NULL || tp != curtab);
+
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
return alt_tabpage()->tp_curwin->w_frame;
}
@@ -3287,6 +3306,7 @@ static tabpage_T *alt_tabpage(void)
// Find the left-upper window in frame "frp".
win_T *frame2win(frame_T *frp)
+ FUNC_ATTR_NONNULL_ALL
{
while (frp->fr_win == NULL) {
frp = frp->fr_child;
@@ -5139,7 +5159,10 @@ void win_append(win_T *after, win_T *wp)
///
/// @param tp tab page "win" is in, NULL for current
void win_remove(win_T *wp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
+ assert(tp == NULL || tp != curtab);
+
if (wp->w_prev != NULL) {
wp->w_prev->w_next = wp->w_next;
} else if (tp == NULL) {