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:  #6445
closes: #13903

Signed-off-by: Colin Kennedy <colinvfx@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Colin Kennedy
2024-03-03 16:16:47 +01:00
committed by Christian Brabandt
parent 353faa373e
commit 2157035637
29 changed files with 3336 additions and 31 deletions

View File

@ -1,4 +1,4 @@
*message.txt* For Vim version 9.1. Last change: 2023 Dec 20 *message.txt* For Vim version 9.1. Last change: 2024 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -122,6 +122,13 @@ wiped out a buffer which contains a mark or is referenced in another way.
You cannot have two buffers with exactly the same name. This includes the You cannot have two buffers with exactly the same name. This includes the
path leading to the file. path leading to the file.
*E1513* >
Cannot edit buffer. 'winfixbuf' is enabled
If a window has 'winfixbuf' enabled, you cannot change that window's current
buffer. You need to set 'nowinfixbuf' before continuing. You may use [!] to
force the window to switch buffers, if your command supports it.
*E72* *E72*
Close error on swap file ~ Close error on swap file ~

View File

@ -1,4 +1,4 @@
*options.txt* For Vim version 9.1. Last change: 2024 Feb 24 *options.txt* For Vim version 9.1. Last change: 2024 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -8021,6 +8021,8 @@ A jump table for the options with a short description can be found at |Q_op|.
"split" when both are present. "split" when both are present.
uselast If included, jump to the previously used window when uselast If included, jump to the previously used window when
jumping to errors with |quickfix| commands. jumping to errors with |quickfix| commands.
If a window has 'winfixbuf' enabled, 'switchbuf' is currently not
applied to the split window.
*'synmaxcol'* *'smc'* *'synmaxcol'* *'smc'*
'synmaxcol' 'smc' number (default 3000) 'synmaxcol' 'smc' number (default 3000)
@ -9471,6 +9473,15 @@ A jump table for the options with a short description can be found at |Q_op|.
Note: Do not confuse this with the height of the Vim window, use Note: Do not confuse this with the height of the Vim window, use
'lines' for that. 'lines' for that.
*'winfixbuf'*
'winfixbuf' 'wfb' boolean (default off)
local to window
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.
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'* *'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
'winfixheight' 'wfh' boolean (default off) 'winfixheight' 'wfh' boolean (default off)
local to window |local-noglobal| local to window |local-noglobal|

View File

@ -1,4 +1,4 @@
*quickref.txt* For Vim version 9.1. Last change: 2023 Dec 05 *quickref.txt* For Vim version 9.1. Last change: 2024 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -1005,6 +1005,7 @@ Short explanation of each option: *option-list*
'winaltkeys' 'wak' when the windows system handles ALT keys 'winaltkeys' 'wak' when the windows system handles ALT keys
'wincolor' 'wcr' window-local highlighting 'wincolor' 'wcr' window-local highlighting
'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B 'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B
'winfixbuf' 'wfb' keep window focused on a single buffer
'winfixheight' 'wfh' keep window height when opening/closing windows 'winfixheight' 'wfh' keep window height when opening/closing windows
'winfixwidth' 'wfw' keep window width when opening/closing windows 'winfixwidth' 'wfw' keep window width when opening/closing windows
'winheight' 'wh' minimum number of lines for the current window 'winheight' 'wh' minimum number of lines for the current window

View File

@ -1294,6 +1294,7 @@ $quote eval.txt /*$quote*
'winaltkeys' options.txt /*'winaltkeys'* 'winaltkeys' options.txt /*'winaltkeys'*
'wincolor' options.txt /*'wincolor'* 'wincolor' options.txt /*'wincolor'*
'window' options.txt /*'window'* 'window' options.txt /*'window'*
'winfixbuf' options.txt /*'winfixbuf'*
'winfixheight' options.txt /*'winfixheight'* 'winfixheight' options.txt /*'winfixheight'*
'winfixwidth' options.txt /*'winfixwidth'* 'winfixwidth' options.txt /*'winfixwidth'*
'winheight' options.txt /*'winheight'* 'winheight' options.txt /*'winheight'*
@ -4541,6 +4542,7 @@ E151 helphelp.txt /*E151*
E1510 change.txt /*E1510* E1510 change.txt /*E1510*
E1511 options.txt /*E1511* E1511 options.txt /*E1511*
E1512 options.txt /*E1512* E1512 options.txt /*E1512*
E1513 message.txt /*E1513*
E152 helphelp.txt /*E152* E152 helphelp.txt /*E152*
E153 helphelp.txt /*E153* E153 helphelp.txt /*E153*
E154 helphelp.txt /*E154* E154 helphelp.txt /*E154*

View File

@ -1,4 +1,4 @@
*tagsrch.txt* For Vim version 9.1. Last change: 2023 Feb 13 *tagsrch.txt* For Vim version 9.1. Last change: 2024 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -409,17 +409,22 @@ If the tag is in the current file this will always work. Otherwise the
performed actions depend on whether the current file was changed, whether a ! performed actions depend on whether the current file was changed, whether a !
is added to the command and on the 'autowrite' option: is added to the command and on the 'autowrite' option:
tag in file autowrite ~ tag in file autowrite ~
current file changed ! option action ~ current file changed ! winfixbuf option action ~
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
yes x x x goto tag yes x x no x goto tag
no no x x read other file, goto tag no no x no x read other file, goto tag
no yes yes x abandon current file, read other file, goto no yes yes no x abandon current file,
tag read other file, goto tag
no yes no on write current file, read other file, goto no yes no no on write current file,
tag read other file, goto tag
no yes no off fail no yes no no off fail
----------------------------------------------------------------------------- yes x yes x x goto tag
no no no yes x fail
no yes no yes x fail
no yes no yes on fail
no yes no yes off fail
-----------------------------------------------------------------------------
- If the tag is in the current file, the command will always work. - If the tag is in the current file, the command will always work.
- If the tag is in another file and the current file was not changed, the - If the tag is in another file and the current file was not changed, the
@ -435,6 +440,8 @@ current file changed ! option action ~
the changes, use the ":w" command and then use ":tag" without an argument. the changes, use the ":w" command and then use ":tag" without an argument.
This works because the tag is put on the stack anyway. If you want to lose This works because the tag is put on the stack anyway. If you want to lose
the changes you can use the ":tag!" command. the changes you can use the ":tag!" command.
- If the tag is in another file and the window includes 'winfixbuf', the
command will fail. If the tag is in the same file then it may succeed.
*tag-security* *tag-security*
Note that Vim forbids some commands, for security reasons. This works like Note that Vim forbids some commands, for security reasons. This works like

View File

@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2024 Feb 21 *version9.txt* For Vim version 9.1. Last change: 2024 Mar 03
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@ -41575,6 +41575,8 @@ Commands: ~
Options: ~ Options: ~
'winfixbuf' Keep buffer focused in a window
============================================================================== ==============================================================================
INCOMPATIBLE CHANGES *incompatible-9.2* INCOMPATIBLE CHANGES *incompatible-9.2*

View File

@ -482,6 +482,7 @@ if has("statusline")
call <SID>AddOption("statusline", gettext("alternate format to be used for a status line")) call <SID>AddOption("statusline", gettext("alternate format to be used for a status line"))
call <SID>OptionG("stl", &stl) call <SID>OptionG("stl", &stl)
endif endif
call append("$", "\t" .. s:local_to_window)
call <SID>AddOption("equalalways", gettext("make all windows the same size when adding/removing windows")) call <SID>AddOption("equalalways", gettext("make all windows the same size when adding/removing windows"))
call <SID>BinOptionG("ea", &ea) call <SID>BinOptionG("ea", &ea)
call <SID>AddOption("eadirection", gettext("in which direction 'equalalways' works: \"ver\", \"hor\" or \"both\"")) call <SID>AddOption("eadirection", gettext("in which direction 'equalalways' works: \"ver\", \"hor\" or \"both\""))
@ -490,6 +491,8 @@ call <SID>AddOption("winheight", gettext("minimal number of lines used for the c
call append("$", " \tset wh=" . &wh) call append("$", " \tset wh=" . &wh)
call <SID>AddOption("winminheight", gettext("minimal number of lines used for any window")) call <SID>AddOption("winminheight", gettext("minimal number of lines used for any window"))
call append("$", " \tset wmh=" . &wmh) call append("$", " \tset wmh=" . &wmh)
call <SID>AddOption("winfixbuf", gettext("keep window focused on a single buffer"))
call <SID>OptionG("wfb", &wfb)
call <SID>AddOption("winfixheight", gettext("keep the height of the window")) call <SID>AddOption("winfixheight", gettext("keep the height of the window"))
call append("$", "\t" .. s:local_to_window) call append("$", "\t" .. s:local_to_window)
call <SID>BinOptionL("wfh") call <SID>BinOptionL("wfh")

View File

@ -682,6 +682,7 @@ do_argfile(exarg_T *eap, int argn)
int other; int other;
char_u *p; char_u *p;
int old_arg_idx = curwin->w_arg_idx; int old_arg_idx = curwin->w_arg_idx;
int is_split_cmd = *eap->cmd == 's';
if (ERROR_IF_ANY_POPUP_WINDOW) if (ERROR_IF_ANY_POPUP_WINDOW)
return; return;
@ -697,13 +698,18 @@ do_argfile(exarg_T *eap, int argn)
return; return;
} }
if (!is_split_cmd
&& (&ARGLIST[argn])->ae_fnum != curbuf->b_fnum
&& !check_can_set_curbuf_forceit(eap->forceit))
return;
setpcmark(); setpcmark();
#ifdef FEAT_GUI #ifdef FEAT_GUI
need_mouse_correct = TRUE; need_mouse_correct = TRUE;
#endif #endif
// split window or create new tab page first // 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) if (win_split(0, 0) == FAIL)
return; return;

View File

@ -1370,6 +1370,13 @@ do_buffer_ext(
if ((flags & DOBUF_NOPOPUP) && bt_popup(buf) && !bt_terminal(buf)) if ((flags & DOBUF_NOPOPUP) && bt_popup(buf) && !bt_terminal(buf))
return OK; return OK;
#endif #endif
if (
action == DOBUF_GOTO
&& buf != curbuf
&& !check_can_set_curbuf_forceit((flags & DOBUF_FORCEIT) ? TRUE : FALSE))
// disallow navigating to another buffer when 'winfixbuf' is applied
return FAIL;
if ((action == DOBUF_GOTO || action == DOBUF_SPLIT) if ((action == DOBUF_GOTO || action == DOBUF_SPLIT)
&& (buf->b_flags & BF_DUMMY)) && (buf->b_flags & BF_DUMMY))
{ {

View File

@ -3607,3 +3607,5 @@ EXTERN char e_wrong_number_of_characters_for_field_str[]
INIT(= N_("E1511: Wrong number of characters for field \"%s\"")); INIT(= N_("E1511: Wrong number of characters for field \"%s\""));
EXTERN char e_wrong_character_width_for_field_str[] EXTERN char e_wrong_character_width_for_field_str[]
INIT(= N_("E1512: Wrong character width for field \"%s\"")); INIT(= N_("E1512: Wrong character width for field \"%s\""));
EXTERN char e_winfixbuf_cannot_go_to_buffer[]
INIT(= N_("E1513: Cannot edit buffer. 'winfixbuf' is enabled"));

View File

@ -2428,6 +2428,9 @@ getfile(
int retval; int retval;
char_u *free_me = NULL; char_u *free_me = NULL;
if (!check_can_set_curbuf_forceit(forceit))
return GETFILE_ERROR;
if (text_locked()) if (text_locked())
return GETFILE_ERROR; return GETFILE_ERROR;
if (curbuf_locked()) if (curbuf_locked())

View File

@ -521,7 +521,7 @@ EXCMD(CMD_doautoall, "doautoall", ex_doautoall,
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE), ADDR_NONE),
EXCMD(CMD_drop, "drop", ex_drop, EXCMD(CMD_drop, "drop", ex_drop,
EX_FILES|EX_CMDARG|EX_NEEDARG|EX_ARGOPT|EX_TRLBAR, EX_BANG|EX_FILES|EX_CMDARG|EX_NEEDARG|EX_ARGOPT|EX_TRLBAR,
ADDR_NONE), ADDR_NONE),
EXCMD(CMD_dsearch, "dsearch", ex_findpat, EXCMD(CMD_dsearch, "dsearch", ex_findpat,
EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK, EX_BANG|EX_RANGE|EX_DFLALL|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK,

View File

@ -457,6 +457,31 @@ ex_listdo(exarg_T *eap)
tabpage_T *tp; tabpage_T *tp;
buf_T *buf = curbuf; buf_T *buf = curbuf;
int next_fnum = 0; int next_fnum = 0;
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;
CLEAR_FIELD(new_eap);
new_eap.cmdidx = CMD_split;
new_eap.cmd = (char_u *)"split";
new_eap.arg = (char_u *)"";
ex_splitview(&new_eap);
}
}
#if defined(FEAT_SYN_HL) #if defined(FEAT_SYN_HL)
char_u *save_ei = NULL; char_u *save_ei = NULL;
#endif #endif

View File

@ -7164,6 +7164,9 @@ ex_resize(exarg_T *eap)
static void static void
ex_find(exarg_T *eap) ex_find(exarg_T *eap)
{ {
if (!check_can_set_curbuf_forceit(eap->forceit))
return;
char_u *fname; char_u *fname;
int count; int count;
char_u *file_to_find = NULL; char_u *file_to_find = NULL;
@ -7245,6 +7248,14 @@ ex_open(exarg_T *eap)
static void static void
ex_edit(exarg_T *eap) 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); do_exedit(eap, NULL);
} }
@ -9031,7 +9042,7 @@ ex_checkpath(exarg_T *eap)
{ {
find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L, find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW, eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
(linenr_T)1, (linenr_T)MAXLNUM); (linenr_T)1, (linenr_T)MAXLNUM, eap->forceit);
} }
#if defined(FEAT_QUICKFIX) #if defined(FEAT_QUICKFIX)
@ -9101,7 +9112,7 @@ ex_findpat(exarg_T *eap)
find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg), find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
whole, !eap->forceit, whole, !eap->forceit,
*eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
n, action, eap->line1, eap->line2); n, action, eap->line1, eap->line2, eap->forceit);
} }
#endif #endif

View File

@ -3407,7 +3407,7 @@ get_next_include_file_completion(int compl_type)
(compl_type == CTRL_X_PATH_DEFINES (compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL)) && !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND, ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
(linenr_T)1, (linenr_T)MAXLNUM); (linenr_T)1, (linenr_T)MAXLNUM, FALSE);
} }
#endif #endif

View File

@ -4073,6 +4073,9 @@ nv_gotofile(cmdarg_T *cap)
return; return;
#endif #endif
if (!check_can_set_curbuf_disabled())
return;
ptr = grab_file_name(cap->count1, &lnum); ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL) if (ptr != NULL)
@ -4475,7 +4478,8 @@ nv_brackets(cmdarg_T *cap)
SAFE_isupper(cap->nchar) ? ACTION_SHOW_ALL : SAFE_isupper(cap->nchar) ? ACTION_SHOW_ALL :
SAFE_islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO, SAFE_islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1, cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
(linenr_T)MAXLNUM); (linenr_T)MAXLNUM,
FALSE);
vim_free(ptr); vim_free(ptr);
curwin->w_set_curswant = TRUE; curwin->w_set_curswant = TRUE;
} }

View File

@ -6420,6 +6420,7 @@ get_varp(struct vimoption *p)
#ifdef FEAT_LINEBREAK #ifdef FEAT_LINEBREAK
case PV_NUW: return (char_u *)&(curwin->w_p_nuw); case PV_NUW: return (char_u *)&(curwin->w_p_nuw);
#endif #endif
case PV_WFB: return (char_u *)&(curwin->w_p_wfb);
case PV_WFH: return (char_u *)&(curwin->w_p_wfh); case PV_WFH: return (char_u *)&(curwin->w_p_wfh);
case PV_WFW: return (char_u *)&(curwin->w_p_wfw); case PV_WFW: return (char_u *)&(curwin->w_p_wfw);
#if defined(FEAT_QUICKFIX) #if defined(FEAT_QUICKFIX)

View File

@ -1309,6 +1309,7 @@ enum
#ifdef FEAT_STL_OPT #ifdef FEAT_STL_OPT
, WV_STL , WV_STL
#endif #endif
, WV_WFB
, WV_WFH , WV_WFH
, WV_WFW , WV_WFW
, WV_WRAP , WV_WRAP

View File

@ -215,6 +215,7 @@
# define PV_STL OPT_BOTH(OPT_WIN(WV_STL)) # define PV_STL OPT_BOTH(OPT_WIN(WV_STL))
#endif #endif
#define PV_UL OPT_BOTH(OPT_BUF(BV_UL)) #define PV_UL OPT_BOTH(OPT_BUF(BV_UL))
# define PV_WFB OPT_WIN(WV_WFB)
# define PV_WFH OPT_WIN(WV_WFH) # define PV_WFH OPT_WIN(WV_WFH)
# define PV_WFW OPT_WIN(WV_WFW) # define PV_WFW OPT_WIN(WV_WFW)
#define PV_WRAP OPT_WIN(WV_WRAP) #define PV_WRAP OPT_WIN(WV_WRAP)
@ -2850,6 +2851,9 @@ static struct vimoption options[] =
{"window", "wi", P_NUM|P_VI_DEF, {"window", "wi", P_NUM|P_VI_DEF,
(char_u *)&p_window, PV_NONE, did_set_window, NULL, (char_u *)&p_window, PV_NONE, did_set_window, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT}, {(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"winfixbuf", "wfb", P_BOOL|P_VI_DEF|P_RWIN,
(char_u *)VAR_WIN, PV_WFB, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
{"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT, {"winfixheight", "wfh", P_BOOL|P_VI_DEF|P_RSTAT,
(char_u *)VAR_WIN, PV_WFH, NULL, NULL, (char_u *)VAR_WIN, PV_WFH, NULL, NULL,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},

View File

@ -32,7 +32,7 @@ int check_linecomment(char_u *line);
void showmatch(int c); void showmatch(int c);
int current_search(long count, int forward); int current_search(long count, int forward);
int linewhite(linenr_T lnum); int linewhite(linenr_T lnum);
void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum); void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum, int forceit);
spat_T *get_spat(int idx); spat_T *get_spat(int idx);
int get_spat_last_idx(void); int get_spat_last_idx(void);
void f_searchcount(typval_T *argvars, typval_T *rettv); void f_searchcount(typval_T *argvars, typval_T *rettv);

View File

@ -1,4 +1,6 @@
/* window.c */ /* window.c */
int check_can_set_curbuf_disabled(void);
int check_can_set_curbuf_forceit(int forceit);
int window_layout_locked(enum CMD_index cmd); int window_layout_locked(enum CMD_index cmd);
win_T *prevwin_curwin(void); win_T *prevwin_curwin(void);
win_T *swbuf_goto_win_with_buf(buf_T *buf); win_T *swbuf_goto_win_with_buf(buf_T *buf);

View File

@ -3146,7 +3146,7 @@ qf_goto_win_with_qfl_file(int qf_fnum)
// Didn't find it, go to the window before the quickfix // Didn't find it, go to the window before the quickfix
// window, unless 'switchbuf' contains 'uselast': in this case we // window, unless 'switchbuf' contains 'uselast': in this case we
// try to jump to the previously used window first. // 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; win = prevwin;
else if (altwin != NULL) else if (altwin != NULL)
win = altwin; win = altwin;
@ -3158,7 +3158,7 @@ qf_goto_win_with_qfl_file(int qf_fnum)
} }
// Remember a usable window. // Remember a usable window.
if (altwin == NULL && !win->w_p_pvw && bt_normal(win->w_buffer)) if (altwin == NULL && !win->w_p_pvw && !win->w_p_wfb && bt_normal(win->w_buffer))
altwin = win; altwin = win;
} }
@ -3261,8 +3261,32 @@ qf_jump_edit_buffer(
prev_winid == curwin->w_id ? curwin : NULL); prev_winid == curwin->w_id ? curwin : NULL);
} }
else 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;
CLEAR_FIELD(new_eap);
new_eap.cmdidx = CMD_split;
new_eap.cmd = (char_u *)"split";
new_eap.arg = (char_u *)"";
ex_splitview(&new_eap);
}
}
retval = buflist_getfile(qf_ptr->qf_fnum, retval = buflist_getfile(qf_ptr->qf_fnum,
(linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit); (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
}
// If a location list, check whether the associated window is still // If a location list, check whether the associated window is still
// present. // present.
@ -4991,6 +5015,11 @@ qf_jump_first(qf_info_T *qi, int_u save_qfid, int forceit)
if (qf_restore_list(qi, save_qfid) == FAIL) if (qf_restore_list(qi, save_qfid) == FAIL)
return; return;
if (!check_can_set_curbuf_forceit(forceit))
return;
// Autocommands might have cleared the list, check for that. // Autocommands might have cleared the list, check for that.
if (!qf_list_empty(qf_get_curlist(qi))) if (!qf_list_empty(qf_get_curlist(qi)))
qf_jump(qi, 0, 0, forceit); qf_jump(qi, 0, 0, forceit);
@ -5907,7 +5936,7 @@ ex_cfile(exarg_T *eap)
// This function is used by the :cfile, :cgetfile and :caddfile // This function is used by the :cfile, :cgetfile and :caddfile
// commands. // 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. // first error.
// :cgetfile creates a new quickfix list but doesn't jump to the // :cgetfile creates a new quickfix list but doesn't jump to the
// first error. // first error.
@ -6497,6 +6526,9 @@ ex_vimgrep(exarg_T *eap)
char_u *au_name = NULL; char_u *au_name = NULL;
int status; int status;
if (!check_can_set_curbuf_forceit(eap->forceit))
return;
au_name = vgr_get_auname(eap->cmdidx); au_name = vgr_get_auname(eap->cmdidx);
if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name,
curbuf->b_fname, TRUE, curbuf)) curbuf->b_fname, TRUE, curbuf))
@ -6558,7 +6590,7 @@ ex_vimgrep(exarg_T *eap)
goto theend; goto theend;
} }
// Jump to first match. // Jump to first match if the current window is not 'winfixbuf'
if (!qf_list_empty(qf_get_curlist(qi))) if (!qf_list_empty(qf_get_curlist(qi)))
{ {
if ((args.flags & VGR_NOJUMP) == 0) if ((args.flags & VGR_NOJUMP) == 0)

View File

@ -3292,7 +3292,8 @@ find_pattern_in_path(
long count, long count,
int action, // What to do when we find it int action, // What to do when we find it
linenr_T start_lnum, // first line to start searching linenr_T start_lnum, // first line to start searching
linenr_T end_lnum) // last line for searching linenr_T end_lnum, // last line for searching
int forceit) // If true, always switch to the found path
{ {
SearchedFile *files; // Stack of included files SearchedFile *files; // Stack of included files
SearchedFile *bigger; // When we need more space SearchedFile *bigger; // When we need more space
@ -3829,7 +3830,7 @@ search_line:
break; break;
if (!GETFILE_SUCCESS(getfile( if (!GETFILE_SUCCESS(getfile(
curwin_save->w_buffer->b_fnum, NULL, curwin_save->w_buffer->b_fnum, NULL,
NULL, TRUE, lnum, FALSE))) NULL, TRUE, lnum, forceit)))
break; // failed to jump to file break; // failed to jump to file
} }
else else
@ -3842,7 +3843,7 @@ search_line:
{ {
if (!GETFILE_SUCCESS(getfile( if (!GETFILE_SUCCESS(getfile(
0, files[depth].name, NULL, TRUE, 0, files[depth].name, NULL, TRUE,
files[depth].lnum, FALSE))) files[depth].lnum, forceit)))
break; // failed to jump to file break; // failed to jump to file
// autocommands may have changed the lnum, we don't // autocommands may have changed the lnum, we don't
// want that here // want that here

View File

@ -246,6 +246,8 @@ typedef struct
long wo_nuw; long wo_nuw;
# define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth' # define w_p_nuw w_onebuf_opt.wo_nuw // 'numberwidth'
#endif #endif
int wo_wfb;
#define w_p_wfb w_onebuf_opt.wo_wfb // 'winfixbuf'
int wo_wfh; int wo_wfh;
# define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight' # define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight'
int wo_wfw; int wo_wfw;

View File

@ -289,6 +289,9 @@ do_tag(
static char_u **matches = NULL; static char_u **matches = NULL;
static int flags; static int flags;
if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit))
return FALSE;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (tfu_in_use) if (tfu_in_use)
{ {
@ -3705,6 +3708,9 @@ jumpto_tag(
size_t len; size_t len;
char_u *lbuf; char_u *lbuf;
if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit))
return FAIL;
// Make a copy of the line, it can become invalid when an autocommand calls // Make a copy of the line, it can become invalid when an autocommand calls
// back here recursively. // back here recursively.
len = matching_line_len(lbuf_arg) + 1; len = matching_line_len(lbuf_arg) + 1;

View File

@ -325,6 +325,7 @@ NEW_TESTS = \
test_window_cmd \ test_window_cmd \
test_window_id \ test_window_id \
test_windows_home \ test_windows_home \
test_winfixbuf \
test_wnext \ test_wnext \
test_wordcount \ test_wordcount \
test_writefile \ test_writefile \

File diff suppressed because it is too large Load Diff

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
147,
/**/ /**/
146, 146,
/**/ /**/

View File

@ -158,6 +158,37 @@ log_frame_layout(frame_T *frame)
} }
#endif #endif
/*
* Check if the current window is allowed to move to a different buffer.
* If the window has 'winfixbuf', this function will return FALSE.
*/
int
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.
* If the window has 'winfixbuf', then forceit must be TRUE or this function
* will return FALSE.
*/
int
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 * Return the current window, unless in the cmdline window and "prevwin" is
* set, then return "prevwin". * set, then return "prevwin".
@ -667,7 +698,7 @@ wingotofile:
find_pattern_in_path(ptr, 0, len, TRUE, find_pattern_in_path(ptr, 0, len, TRUE,
Prenum == 0 ? TRUE : FALSE, type, Prenum == 0 ? TRUE : FALSE, type,
Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM); Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM, FALSE);
vim_free(ptr); vim_free(ptr);
curwin->w_set_curswant = TRUE; curwin->w_set_curswant = TRUE;
break; break;