From 141182d6c6c06ad56413b81a518ba9b777a0cbe0 Mon Sep 17 00:00:00 2001 From: Colin Kennedy Date: Mon, 25 Dec 2023 20:41:09 -0800 Subject: vim-patch:9.1.0147: Cannot keep a buffer focused in a window Problem: Cannot keep a buffer focused in a window (Amit Levy) Solution: Add the 'winfixbuf' window-local option (Colin Kennedy) fixes: vim/vim#6445 closes: vim/vim#13903 https://github.com/vim/vim/commit/215703563757a4464907ead6fb9edaeb7f430bea N/A patch: vim-patch:58f1e5c0893a --- src/nvim/api/vim.c | 5 +++++ src/nvim/api/window.c | 6 ++++++ src/nvim/arglist.c | 10 +++++++++- src/nvim/buffer.c | 6 ++++++ src/nvim/buffer_defs.h | 2 ++ src/nvim/ex_cmds.c | 4 ++++ src/nvim/ex_cmds.lua | 2 +- src/nvim/ex_cmds2.c | 21 +++++++++++++++++++++ src/nvim/ex_docmd.c | 16 ++++++++++++++-- src/nvim/globals.h | 3 +++ src/nvim/insexpand.c | 2 +- src/nvim/normal.c | 7 ++++++- src/nvim/option.c | 2 ++ src/nvim/options.lua | 19 +++++++++++++++++++ src/nvim/quickfix.c | 33 +++++++++++++++++++++++++++++++-- src/nvim/search.c | 8 +++++--- src/nvim/tag.c | 8 ++++++++ src/nvim/window.c | 31 ++++++++++++++++++++++++++++++- 18 files changed, 173 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 84a2f24dbc..24ad7d5fbc 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -876,6 +876,11 @@ void nvim_set_current_buf(Buffer buffer, Error *err) return; } + if (curwin->w_p_wfb) { + api_set_error(err, kErrorTypeException, "%s", e_winfixbuf_cannot_go_to_buffer); + return; + } + try_start(); int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); if (!try_end(err) && result == FAIL) { diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index ed51eedf1b..1a80e9ea16 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -61,6 +61,12 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err) if (!win || !buf) { return; } + + if (win->w_p_wfb) { + api_set_error(err, kErrorTypeException, "%s", e_winfixbuf_cannot_go_to_buffer); + return; + } + if (win == cmdwin_win || win == cmdwin_old_curwin || buf == cmdwin_buf) { api_set_error(err, kErrorTypeException, "%s", e_cmdwin); return; diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index a02c22deae..4d493c9d03 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -623,6 +623,8 @@ void ex_argument(exarg_T *eap) /// Edit file "argn" of the argument lists. void do_argfile(exarg_T *eap, int argn) { + bool is_split_cmd = *eap->cmd == 's'; + int old_arg_idx = curwin->w_arg_idx; if (argn < 0 || argn >= ARGCOUNT) { @@ -637,10 +639,16 @@ void do_argfile(exarg_T *eap, int argn) return; } + if (!is_split_cmd + && (&ARGLIST[argn])->ae_fnum != curbuf->b_fnum + && !check_can_set_curbuf_forceit(eap->forceit)) { + return; + } + setpcmark(); // split window or create new tab page first - if (*eap->cmd == 's' || cmdmod.cmod_tab != 0) { + if (is_split_cmd || cmdmod.cmod_tab != 0) { if (win_split(0, 0) == FAIL) { return; } diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7154be36be..e141706edd 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1305,6 +1305,12 @@ int do_buffer(int action, int start, int dir, int count, int forceit) } return FAIL; } + + if (action == DOBUF_GOTO && buf != curbuf && !check_can_set_curbuf_forceit(forceit)) { + // disallow navigating to another buffer when 'winfixbuf' is applied + return FAIL; + } + if ((action == DOBUF_GOTO || action == DOBUF_SPLIT) && (buf->b_flags & BF_DUMMY)) { // disallow navigating to the dummy buffer semsg(_(e_nobufnr), count); diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1e5086309c..7f7300706c 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -139,6 +139,8 @@ typedef struct { #define w_ve_flags w_onebuf_opt.wo_ve_flags // flags for 'virtualedit' OptInt wo_nuw; #define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth' + int wo_wfb; +#define w_p_wfb w_onebuf_opt.wo_wfb // 'winfixbuf' int wo_wfh; #define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight' int wo_wfw; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 74ad8e95a2..14bd2b87e3 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2008,6 +2008,10 @@ static int check_readonly(int *forceit, buf_T *buf) /// GETFILE_OPEN_OTHER for successfully opening another file. int getfile(int fnum, char *ffname_arg, char *sfname_arg, bool setpm, linenr_T lnum, bool forceit) { + if (!check_can_set_curbuf_forceit(forceit)) { + return GETFILE_ERROR; + } + char *ffname = ffname_arg; char *sfname = sfname_arg; bool other; diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 1318eda5eb..e2196f99ec 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -812,7 +812,7 @@ module.cmds = { }, { command = 'drop', - flags = bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR), + flags = bit.bor(BANG, FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR), addr_type = 'ADDR_NONE', func = 'ex_drop', }, diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 8016e37ca7..3120868350 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -444,6 +444,27 @@ int buf_write_all(buf_T *buf, bool forceit) /// ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" void ex_listdo(exarg_T *eap) { + if (curwin->w_p_wfb) { + if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) && !eap->forceit) { + // Disallow :ldo if 'winfixbuf' is applied + semsg("%s", e_winfixbuf_cannot_go_to_buffer); + return; + } + + if (win_valid(prevwin)) { + // Change the current window to another because 'winfixbuf' is enabled + curwin = prevwin; + } else { + // Split the window, which will be 'nowinfixbuf', and set curwin to that + exarg_T new_eap = { + .cmdidx = CMD_split, + .cmd = "split", + .arg = "", + }; + ex_splitview(&new_eap); + } + } + char *save_ei = NULL; // Temporarily override SHM_OVER and SHM_OVERALL to avoid that file diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 2913f6d4e9..1b4e83d392 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5334,6 +5334,10 @@ static void ex_resize(exarg_T *eap) /// ":find [+command] " command. static void ex_find(exarg_T *eap) { + if (!check_can_set_curbuf_forceit(eap->forceit)) { + return; + } + char *file_to_find = NULL; char *search_ctx = NULL; char *fname = find_file_in_path(eap->arg, strlen(eap->arg), @@ -5364,6 +5368,14 @@ static void ex_find(exarg_T *eap) /// ":edit", ":badd", ":balt", ":visual". static void ex_edit(exarg_T *eap) { + // Exclude commands which keep the window's current buffer + if (eap->cmdidx != CMD_badd + && eap->cmdidx != CMD_balt + // All other commands must obey 'winfixbuf' / ! rules + && !check_can_set_curbuf_forceit(eap->forceit)) { + return; + } + do_exedit(eap, NULL); } @@ -6670,7 +6682,7 @@ static void ex_checkpath(exarg_T *eap) { find_pattern_in_path(NULL, 0, 0, false, false, CHECK_PATH, 1, eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW, - 1, (linenr_T)MAXLNUM); + 1, (linenr_T)MAXLNUM, eap->forceit); } /// ":psearch" @@ -6729,7 +6741,7 @@ static void ex_findpat(exarg_T *eap) if (!eap->skip) { find_pattern_in_path(eap->arg, 0, strlen(eap->arg), whole, !eap->forceit, *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, - n, action, eap->line1, eap->line2); + n, action, eap->line1, eap->line2, eap->forceit); } } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 113985cb52..aecb9d1116 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -971,6 +971,9 @@ EXTERN const char e_val_too_large[] INIT(= N_("E1510: Value too large: %s")); EXTERN const char e_undobang_cannot_redo_or_move_branch[] INIT(= N_("E5767: Cannot use :undo! to redo or move to a different undo branch")); +EXTERN const char e_winfixbuf_cannot_go_to_buffer[] +INIT(= N_("E1513: Cannot edit buffer. 'winfixbuf' is enabled")); + EXTERN const char e_trustfile[] INIT(= N_("E5570: Cannot update trust file: %s")); EXTERN const char e_unknown_option2[] INIT(= N_("E355: Unknown option: %s")); diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 41b964323e..d0cd24773f 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -3027,7 +3027,7 @@ static void get_next_include_file_completion(int compl_type) ((compl_type == CTRL_X_PATH_DEFINES && !(compl_cont_status & CONT_SOL)) ? FIND_DEFINE : FIND_ANY), - 1, ACTION_EXPAND, 1, MAXLNUM); + 1, ACTION_EXPAND, 1, MAXLNUM, false); } /// Get the next set of words matching "compl_pattern" in dictionary or diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f586ad6704..aae9621d4a 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3896,6 +3896,10 @@ static void nv_gotofile(cmdarg_T *cap) return; } + if (!check_can_set_curbuf_disabled()) { + return; + } + char *ptr = grab_file_name(cap->count1, &lnum); if (ptr != NULL) { @@ -4232,7 +4236,8 @@ static void nv_brackets(cmdarg_T *cap) (cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : 1), - MAXLNUM); + MAXLNUM, + false); xfree(ptr); curwin->w_set_curswant = true; } diff --git a/src/nvim/option.c b/src/nvim/option.c index 0ac65ed95d..fcc5b5eb06 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4629,6 +4629,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win) return &(win->w_p_rnu); case PV_NUW: return &(win->w_p_nuw); + case PV_WFB: + return &(win->w_p_wfb); case PV_WFH: return &(win->w_p_wfh); case PV_WFW: diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 72f9ff849d..5e8bc1361c 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -8406,6 +8406,8 @@ return { "split" when both are present. uselast If included, jump to the previously used window when jumping to errors with |quickfix| commands. + If a window has 'winfixbuf' enabled, 'switchbuf' is currently not + applied to the split window. ]=], expand_cb = 'expand_set_switchbuf', full_name = 'switchbuf', @@ -9816,6 +9818,23 @@ return { type = 'number', varname = 'p_window', }, + { + abbreviation = 'wfb', + defaults = { if_true = false }, + desc = [=[ + If enabled, the buffer and any window that displays it are paired. + For example, attempting to change the buffer with |:edit| will fail. + Other commands which change a window's buffer such as |:cnext| will + also skip any window with 'winfixbuf' enabled. However if a command + has an "!" option, a window can be forced to switch buffers. + ]=], + full_name = 'winfixbuf', + pv_name = 'p_wfb', + redraw = { 'current_window' }, + scope = { 'window' }, + short_desc = N_('pin a window to a specific buffer'), + type = 'boolean', + }, { abbreviation = 'wfh', defaults = { if_true = false }, diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 651ebc9f93..a88b781f32 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2699,7 +2699,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum) // Didn't find it, go to the window before the quickfix // window, unless 'switchbuf' contains 'uselast': in this case we // try to jump to the previously used window first. - if ((swb_flags & SWB_USELAST) && win_valid(prevwin)) { + if ((swb_flags & SWB_USELAST) && !prevwin->w_p_wfb && win_valid(prevwin)) { win = prevwin; } else if (altwin != NULL) { win = altwin; @@ -2714,6 +2714,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum) // Remember a usable window. if (altwin == NULL && !win->w_p_pvw + && !win->w_p_wfb && bt_normal(win->w_buffer)) { altwin = win; } @@ -2802,6 +2803,25 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int ECMD_HIDE + ECMD_SET_HELP, prev_winid == curwin->handle ? curwin : NULL); } else { + if (!forceit && curwin->w_p_wfb) { + if (qi->qfl_type == QFLT_LOCATION) { + // Location lists cannot split or reassign their window + // so 'winfixbuf' windows must fail + semsg("%s", e_winfixbuf_cannot_go_to_buffer); + return QF_ABORT; + } + + if (!win_valid(prevwin)) { + // Split the window, which will be 'nowinfixbuf', and set curwin to that + exarg_T new_eap = { + .cmdidx = CMD_split, + .cmd = "split", + .arg = "", + }; + ex_splitview(&new_eap); + } + } + retval = buflist_getfile(qf_ptr->qf_fnum, 1, GETF_SETMARK | GETF_SWITCH, forceit); } @@ -4297,6 +4317,11 @@ static void qf_jump_first(qf_info_T *qi, unsigned save_qfid, int forceit) if (qf_restore_list(qi, save_qfid) == FAIL) { return; } + + if (!check_can_set_curbuf_forceit(forceit)) { + return; + } + // Autocommands might have cleared the list, check for that if (!qf_list_empty(qf_get_curlist(qi))) { qf_jump(qi, 0, 0, forceit); @@ -5125,7 +5150,7 @@ void ex_cfile(exarg_T *eap) // This function is used by the :cfile, :cgetfile and :caddfile // commands. - // :cfile always creates a new quickfix list and jumps to the + // :cfile always creates a new quickfix list and may jump to the // first error. // :cgetfile creates a new quickfix list but doesn't jump to the // first error. @@ -5587,6 +5612,10 @@ theend: /// ":lvimgrepadd {pattern} file(s)" void ex_vimgrep(exarg_T *eap) { + if (!check_can_set_curbuf_forceit(eap->forceit)) { + return; + } + char *au_name = vgr_get_auname(eap->cmdidx); if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, curbuf->b_fname, true, curbuf)) { diff --git a/src/nvim/search.c b/src/nvim/search.c index 48e41c290d..2fea28ba7c 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -3564,8 +3564,10 @@ static char *get_line_and_copy(linenr_T lnum, char *buf) /// @param action What to do when we find it /// @param start_lnum first line to start searching /// @param end_lnum last line for searching +/// @param forceit If true, always switch to the found path void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool skip_comments, - int type, int count, int action, linenr_T start_lnum, linenr_T end_lnum) + int type, int count, int action, linenr_T start_lnum, linenr_T end_lnum, + int forceit) { SearchedFile *files; // Stack of included files SearchedFile *bigger; // When we need more space @@ -4025,7 +4027,7 @@ search_line: break; } if (!GETFILE_SUCCESS(getfile(curwin_save->w_buffer->b_fnum, NULL, - NULL, true, lnum, false))) { + NULL, true, lnum, forceit))) { break; // failed to jump to file } } else { @@ -4035,7 +4037,7 @@ search_line: check_cursor(); } else { if (!GETFILE_SUCCESS(getfile(0, files[depth].name, NULL, true, - files[depth].lnum, false))) { + files[depth].lnum, forceit))) { break; // failed to jump to file } // autocommands may have changed the lnum, we don't diff --git a/src/nvim/tag.c b/src/nvim/tag.c index ab5bfc6773..776498fa29 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -290,6 +290,10 @@ void set_buflocal_tfu_callback(buf_T *buf) /// @param verbose print "tag not found" message void do_tag(char *tag, int type, int count, int forceit, bool verbose) { + if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) { + return; + } + taggy_T *tagstack = curwin->w_tagstack; int tagstackidx = curwin->w_tagstackidx; int tagstacklen = curwin->w_tagstacklen; @@ -2784,6 +2788,10 @@ static char *tag_full_fname(tagptrs_T *tagp) /// @return OK for success, NOTAGFILE when file not found, FAIL otherwise. static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help) { + if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) { + return FAIL; + } + char *pbuf_end; char *tofree_fname = NULL; tagptrs_T tagp; diff --git a/src/nvim/window.c b/src/nvim/window.c index ff40a9adef..9f84713ee7 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -133,6 +133,35 @@ static void log_frame_layout(frame_T *frame) } #endif +/// Check if the current window is allowed to move to a different buffer. +/// +/// @return If the window has 'winfixbuf', or this function will return false. +bool check_can_set_curbuf_disabled(void) +{ + if (curwin->w_p_wfb) { + semsg("%s", e_winfixbuf_cannot_go_to_buffer); + return false; + } + + return true; +} + +/// Check if the current window is allowed to move to a different buffer. +/// +/// @param forceit If true, do not error. If false and 'winfixbuf' is enabled, error. +/// +/// @return If the window has 'winfixbuf', then forceit must be true +/// or this function will return false. +bool check_can_set_curbuf_forceit(int forceit) +{ + if (!forceit && curwin->w_p_wfb) { + semsg("%s", e_winfixbuf_cannot_go_to_buffer); + return false; + } + + return true; +} + /// @return the current window, unless in the cmdline window and "prevwin" is /// set, then return "prevwin". win_T *prevwin_curwin(void) @@ -597,7 +626,7 @@ wingotofile: ptr = xmemdupz(ptr, len); find_pattern_in_path(ptr, 0, len, true, Prenum == 0, - type, Prenum1, ACTION_SPLIT, 1, MAXLNUM); + type, Prenum1, ACTION_SPLIT, 1, MAXLNUM, false); xfree(ptr); curwin->w_set_curswant = true; break; -- cgit From e8bc23db62c37e91d0c277b4bddf652db6a9d5f1 Mon Sep 17 00:00:00 2001 From: Colin Kennedy Date: Mon, 4 Mar 2024 21:25:15 -0800 Subject: vim-patch:9.1.0149: null pointer member access when accessing 'winfixbuf' property Problem: qf_goto_win_with_qfl_file may check if prevwin has 'winfixbuf' set without checking if it's valid first. Solution: Reverse the condition. Add a test, a modeline, and a missing CheckFeature. (Searn Dewar) closes: vim/vim#14140 https://github.com/vim/vim/commit/5131f224da93f2e042a4b22545ef62b1b2ab8460 Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com> --- src/nvim/quickfix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index a88b781f32..3dd4e35f65 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2699,7 +2699,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum) // Didn't find it, go to the window before the quickfix // window, unless 'switchbuf' contains 'uselast': in this case we // try to jump to the previously used window first. - if ((swb_flags & SWB_USELAST) && !prevwin->w_p_wfb && win_valid(prevwin)) { + if ((swb_flags & SWB_USELAST) && win_valid(prevwin) && !prevwin->w_p_wfb) { win = prevwin; } else if (altwin != NULL) { win = altwin; -- cgit From 5931f2bc4ac319e5fa617b36cbe5305228125c11 Mon Sep 17 00:00:00 2001 From: Colin Kennedy Date: Tue, 5 Mar 2024 23:39:30 -0800 Subject: vim-patch:9.1.0150: Several minor 'winfixbuf' issues Problem: several minor 'winfixbuf' issues exist, mostly relating to the quickfix list Solution: address them and adjust tests. Retab and reflow a few things too. (Sean Dewar) Things touched include: - Replace the semsgs with gettext'd emsgs. - Handle window switching in ex_listdo properly, so curbuf and curwin are kept in-sync and trigger autocommands; handle those properly. - Don't change the list entry index in qf_jump_edit_buffer if we fail due to 'wfb' (achieved by returning FAIL; QF_ABORT should only be used if the list was changed). - Make qf_jump_edit_buffer actually switch to prevwin when using `:cXX` commands **outside** of the list window if 'wfb' is set in curwin. Handle autocommands properly in case they mess with the list. NOTE: previously, it seemed to split if 'wfb' was set, but do nothing and fail if prevwin is *valid*. This behaviour seemed strange, and maybe unintentional? Now it aligns more with what's described for the `:cXX` commands in the original PR description when used outside a list window, I think. - In both functions, only consider prevwin if 'wfb' isn't set for it; fallback to splitting otherwise. - Use win_split to split. Not sure if there was a specific reason for using ex_splitview. win_split is simpler and respects modifiers like :vertical that may have been used. Plus, its return value can be checked for setting opened_window in qf code (technically win_split_ins autocmds could immediately close it or change windows, in which the qf code might close some other window on failure; it's already the case elsewhere, though). closes: vim/vim#14142 https://github.com/vim/vim/commit/4bb505e28cac0389561fff78d8bbe0319c2bcf2f Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com> --- src/nvim/ex_cmds2.c | 25 ++++++++++++++----------- src/nvim/quickfix.c | 44 ++++++++++++++++++++++++++++++-------------- src/nvim/window.c | 4 ++-- 3 files changed, 46 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 3120868350..dacdb27b08 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -447,21 +447,24 @@ void ex_listdo(exarg_T *eap) if (curwin->w_p_wfb) { if ((eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) && !eap->forceit) { // Disallow :ldo if 'winfixbuf' is applied - semsg("%s", e_winfixbuf_cannot_go_to_buffer); + emsg(_(e_winfixbuf_cannot_go_to_buffer)); return; } - if (win_valid(prevwin)) { - // Change the current window to another because 'winfixbuf' is enabled - curwin = prevwin; - } else { + if (win_valid(prevwin) && !prevwin->w_p_wfb) { + // 'winfixbuf' is set; attempt to change to a window without it. + win_goto(prevwin); + } + if (curwin->w_p_wfb) { // Split the window, which will be 'nowinfixbuf', and set curwin to that - exarg_T new_eap = { - .cmdidx = CMD_split, - .cmd = "split", - .arg = "", - }; - ex_splitview(&new_eap); + win_split(0, 0); + + if (curwin->w_p_wfb) { + // Autocommands set 'winfixbuf' or sent us to another window + // with it set. Give up. + emsg(_(e_winfixbuf_cannot_go_to_buffer)); + return; + } } } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3dd4e35f65..28691914bb 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2699,7 +2699,8 @@ static void qf_goto_win_with_qfl_file(int qf_fnum) // Didn't find it, go to the window before the quickfix // window, unless 'switchbuf' contains 'uselast': in this case we // try to jump to the previously used window first. - if ((swb_flags & SWB_USELAST) && win_valid(prevwin) && !prevwin->w_p_wfb) { + if ((swb_flags & SWB_USELAST) && win_valid(prevwin) + && !prevwin->w_p_wfb) { win = prevwin; } else if (altwin != NULL) { win = altwin; @@ -2803,27 +2804,42 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int ECMD_HIDE + ECMD_SET_HELP, prev_winid == curwin->handle ? curwin : NULL); } else { - if (!forceit && curwin->w_p_wfb) { + int fnum = qf_ptr->qf_fnum; + + if (!forceit && curwin->w_p_wfb && curbuf->b_fnum != fnum) { if (qi->qfl_type == QFLT_LOCATION) { // Location lists cannot split or reassign their window // so 'winfixbuf' windows must fail - semsg("%s", e_winfixbuf_cannot_go_to_buffer); - return QF_ABORT; + emsg(_(e_winfixbuf_cannot_go_to_buffer)); + return FAIL; } - if (!win_valid(prevwin)) { - // Split the window, which will be 'nowinfixbuf', and set curwin to that - exarg_T new_eap = { - .cmdidx = CMD_split, - .cmd = "split", - .arg = "", - }; - ex_splitview(&new_eap); + if (win_valid(prevwin) && !prevwin->w_p_wfb + && !bt_quickfix(prevwin->w_buffer)) { + // 'winfixbuf' is set; attempt to change to a window without it + // that isn't a quickfix/location list window. + win_goto(prevwin); + } + if (curwin->w_p_wfb) { + // Split the window, which will be 'nowinfixbuf', and set curwin + // to that + if (win_split(0, 0) == OK) { + *opened_window = true; + } + if (curwin->w_p_wfb) { + // Autocommands set 'winfixbuf' or sent us to another window + // with it set. Give up, but don't return immediately, as + // they may have messed with the list. + emsg(_(e_winfixbuf_cannot_go_to_buffer)); + retval = FAIL; + } } } - retval = buflist_getfile(qf_ptr->qf_fnum, 1, - GETF_SETMARK | GETF_SWITCH, forceit); + if (retval == OK) { + retval = buflist_getfile(fnum, 1, + GETF_SETMARK | GETF_SWITCH, forceit); + } } // If a location list, check whether the associated window is still // present. diff --git a/src/nvim/window.c b/src/nvim/window.c index 9f84713ee7..521699f2f0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -139,7 +139,7 @@ static void log_frame_layout(frame_T *frame) bool check_can_set_curbuf_disabled(void) { if (curwin->w_p_wfb) { - semsg("%s", e_winfixbuf_cannot_go_to_buffer); + emsg(_(e_winfixbuf_cannot_go_to_buffer)); return false; } @@ -155,7 +155,7 @@ bool check_can_set_curbuf_disabled(void) bool check_can_set_curbuf_forceit(int forceit) { if (!forceit && curwin->w_p_wfb) { - semsg("%s", e_winfixbuf_cannot_go_to_buffer); + emsg(_(e_winfixbuf_cannot_go_to_buffer)); return false; } -- cgit From d71791a11a260ca81067d63d69b5970078fffb6d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 11 Mar 2024 11:25:00 +0800 Subject: vim-patch:9.1.0152: Coverity complains about ignoring return value Problem: Coverity complains about ignoring return value of win_split() (after v9.1.150) Solution: Check if win_split() failed, add winfixbuf.res to Makefile https://github.com/vim/vim/commit/af7ae8160041e2d17c56945381e9370e7178e596 Co-authored-by: Christian Brabandt --- src/nvim/ex_cmds2.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index dacdb27b08..732631b678 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -457,8 +457,9 @@ void ex_listdo(exarg_T *eap) } if (curwin->w_p_wfb) { // Split the window, which will be 'nowinfixbuf', and set curwin to that - win_split(0, 0); - + if (win_split(0, 0) == FAIL) { + return; // error message already given + } if (curwin->w_p_wfb) { // Autocommands set 'winfixbuf' or sent us to another window // with it set. Give up. -- cgit From 3b3511c4d9f1855d4240da0d844ce7875176c607 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 11 Mar 2024 11:26:02 +0800 Subject: vim-patch:9.1.0156: Make 'wfb' failing to split still report E1513 Problem: may not be clear why failing to split causes an ":Xdo" command to abort if 'wfb' is set. Solution: do not return immediately if win_split fails, so E1513 is still given. Expect both errors in the test. Also fix tests to pass CI. (Sean Dewar) closes: vim/vim#14152 https://github.com/vim/vim/commit/769eb2d0c3614f9ea6fffa82329558f1a4af384f Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com> --- src/nvim/ex_cmds2.c | 7 +++---- src/nvim/quickfix.c | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 732631b678..12687d0ea8 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -457,12 +457,11 @@ void ex_listdo(exarg_T *eap) } if (curwin->w_p_wfb) { // Split the window, which will be 'nowinfixbuf', and set curwin to that - if (win_split(0, 0) == FAIL) { - return; // error message already given - } + (void)win_split(0, 0); + if (curwin->w_p_wfb) { // Autocommands set 'winfixbuf' or sent us to another window - // with it set. Give up. + // with it set, or we failed to split the window. Give up. emsg(_(e_winfixbuf_cannot_go_to_buffer)); return; } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 28691914bb..0a4427f3c1 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2828,8 +2828,9 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int } if (curwin->w_p_wfb) { // Autocommands set 'winfixbuf' or sent us to another window - // with it set. Give up, but don't return immediately, as - // they may have messed with the list. + // with it set, or we failed to split the window. Give up, + // but don't return immediately, as they may have messed + // with the list. emsg(_(e_winfixbuf_cannot_go_to_buffer)); retval = FAIL; } -- cgit