mirror of
https://github.com/neovim/neovim.git
synced 2026-04-02 05:39:26 +00:00
vim-patch:partial:9.0.0907: restoring window after WinScrolled may fail
Problem: Restoring window after WinScrolled may fail.
Solution: Lock the window layout when triggering WinScrolled.
d63a85592c
Only check close_disallowed in window_layout_locked() for now.
Also don't check window_layout_locked() when closing a floating window,
as it's not checked when creating a floating window.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -195,6 +195,8 @@ EXTERN const char e_stray_closing_curly_str[]
|
||||
INIT(= N_("E1278: Stray '}' without a matching '{': %s"));
|
||||
EXTERN const char e_missing_close_curly_str[]
|
||||
INIT(= N_("E1279: Missing '}': %s"));
|
||||
EXTERN const char e_not_allowed_to_change_window_layout_in_this_autocmd[]
|
||||
INIT(= N_("E1312: Not allowed to change the window layout in this autocmd"));
|
||||
|
||||
EXTERN const char e_val_too_large[] INIT(= N_("E1510: Value too large: %s"));
|
||||
|
||||
|
||||
@@ -5033,6 +5033,9 @@ void ex_win_close(int forceit, win_T *win, tabpage_T *tp)
|
||||
emsg(_(e_autocmd_close));
|
||||
return;
|
||||
}
|
||||
if (!win->w_floating && window_layout_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf_T *buf = win->w_buffer;
|
||||
|
||||
@@ -5074,6 +5077,10 @@ static void ex_tabclose(exarg_T *eap)
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_layout_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tab_number = get_tabpage_arg(eap);
|
||||
if (eap->errmsg != NULL) {
|
||||
return;
|
||||
@@ -5105,6 +5112,10 @@ static void ex_tabonly(exarg_T *eap)
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_layout_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tab_number = get_tabpage_arg(eap);
|
||||
if (eap->errmsg != NULL) {
|
||||
return;
|
||||
@@ -5175,9 +5186,12 @@ void tabpage_close_other(tabpage_T *tp, int forceit)
|
||||
/// ":only".
|
||||
static void ex_only(exarg_T *eap)
|
||||
{
|
||||
win_T *wp;
|
||||
if (window_layout_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (eap->addr_count > 0) {
|
||||
win_T *wp;
|
||||
linenr_T wnr = eap->line2;
|
||||
for (wp = firstwin; --wnr > 0;) {
|
||||
if (wp->w_next == NULL) {
|
||||
@@ -5185,11 +5199,9 @@ static void ex_only(exarg_T *eap)
|
||||
}
|
||||
wp = wp->w_next;
|
||||
}
|
||||
} else {
|
||||
wp = curwin;
|
||||
}
|
||||
if (wp != curwin) {
|
||||
win_goto(wp);
|
||||
if (wp != curwin) {
|
||||
win_goto(wp);
|
||||
}
|
||||
}
|
||||
close_others(true, eap->forceit);
|
||||
}
|
||||
@@ -5201,11 +5213,11 @@ static void ex_hide(exarg_T *eap)
|
||||
return;
|
||||
}
|
||||
|
||||
win_T *win = NULL;
|
||||
if (eap->addr_count == 0) {
|
||||
win_close(curwin, false, eap->forceit); // don't free buffer
|
||||
win = curwin;
|
||||
} else {
|
||||
int winnr = 0;
|
||||
win_T *win = NULL;
|
||||
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
winnr++;
|
||||
@@ -5217,8 +5229,13 @@ static void ex_hide(exarg_T *eap)
|
||||
if (win == NULL) {
|
||||
win = lastwin;
|
||||
}
|
||||
win_close(win, false, eap->forceit);
|
||||
}
|
||||
|
||||
if (!win->w_floating && window_layout_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
win_close(win, false, eap->forceit); // don't free buffer
|
||||
}
|
||||
|
||||
/// ":stop" and ":suspend": Suspend Vim.
|
||||
|
||||
@@ -108,6 +108,38 @@ static char *m_onlyone = N_("Already only one window");
|
||||
/// autocommands mess up the window structure.
|
||||
static int split_disallowed = 0;
|
||||
|
||||
/// When non-zero closing a window is forbidden. Used to avoid that nasty
|
||||
/// autocommands mess up the window structure.
|
||||
static int close_disallowed = 0;
|
||||
|
||||
/// Disallow changing the window layout (split window, close window, move
|
||||
/// window). Resizing is still allowed.
|
||||
/// Used for autocommands that temporarily use another window and need to
|
||||
/// make sure the previously selected window is still there.
|
||||
/// Must be matched with exactly one call to window_layout_unlock()!
|
||||
static void window_layout_lock(void)
|
||||
{
|
||||
split_disallowed++;
|
||||
close_disallowed++;
|
||||
}
|
||||
|
||||
static void window_layout_unlock(void)
|
||||
{
|
||||
split_disallowed--;
|
||||
close_disallowed--;
|
||||
}
|
||||
|
||||
/// When the window layout cannot be changed give an error and return true.
|
||||
bool window_layout_locked(void)
|
||||
{
|
||||
// if (split_disallowed > 0 || close_disallowed > 0) {
|
||||
if (close_disallowed > 0) {
|
||||
emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// #define WIN_DEBUG
|
||||
#ifdef WIN_DEBUG
|
||||
/// Call this method to log the current window layout.
|
||||
@@ -2739,6 +2771,9 @@ int win_close(win_T *win, bool free_buf, bool force)
|
||||
emsg(_(e_cannot_close_last_window));
|
||||
return FAIL;
|
||||
}
|
||||
if (!win->w_floating && window_layout_locked()) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (win_locked(win)
|
||||
|| (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) {
|
||||
@@ -4315,6 +4350,9 @@ int win_new_tabpage(int after, char *filename)
|
||||
emsg(_(e_cmdwin));
|
||||
return FAIL;
|
||||
}
|
||||
if (window_layout_locked()) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
tabpage_T *newtp = alloc_tabpage();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user