diff options
Diffstat (limited to 'src/nvim/window.c')
-rw-r--r-- | src/nvim/window.c | 89 |
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) { |