• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Revisionf6d4c6a3b41ce8e304595819c3b68e1df6af6b6b (tree)
Time2022-11-19 20:45:04
AuthorBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Log Message

patch 9.0.0907: restoring window after WinScrolled may fail

Commit: https://github.com/vim/vim/commit/d63a85592cef0ee4f0fec5efe2f8d66b31f01f05
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 19 11:41:30 2022 +0000

patch 9.0.0907: restoring window after WinScrolled may fail
Problem: Restoring window after WinScrolled may fail.
Solution: Lock the window layout when triggering WinScrolled.

Change Summary

Incremental Difference

diff -r 500ebbee148d -r f6d4c6a3b41c src/errors.h
--- a/src/errors.h Sat Nov 19 12:00:05 2022 +0100
+++ b/src/errors.h Sat Nov 19 12:45:04 2022 +0100
@@ -3341,3 +3341,5 @@
33413341 #endif
33423342 EXTERN char e_cannot_change_user_commands_while_listing[]
33433343 INIT(= N_("E1311: Cannot change user commands while listing"));
3344+EXTERN char e_not_allowed_to_change_window_layout_in_this_autocmd[]
3345+ INIT(= N_("E1312: Not allowed to change the window layout in this autocmd"));
diff -r 500ebbee148d -r f6d4c6a3b41c src/ex_docmd.c
--- a/src/ex_docmd.c Sat Nov 19 12:00:05 2022 +0100
+++ b/src/ex_docmd.c Sat Nov 19 12:45:04 2022 +0100
@@ -6055,6 +6055,8 @@
60556055 emsg(_(e_cannot_close_autocmd_or_popup_window));
60566056 return;
60576057 }
6058+ if (window_layout_locked())
6059+ return;
60586060
60596061 need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
60606062 if (need_hide && !buf_hide(buf) && !forceit)
@@ -6227,7 +6229,7 @@
62276229 cmdwin_result = K_IGNORE;
62286230 else if (first_tabpage->tp_next == NULL)
62296231 emsg(_(e_cannot_close_last_tab_page));
6230- else
6232+ else if (!window_layout_locked())
62316233 {
62326234 tab_number = get_tabpage_arg(eap);
62336235 if (eap->errmsg == NULL)
@@ -6263,7 +6265,7 @@
62636265 cmdwin_result = K_IGNORE;
62646266 else if (first_tabpage->tp_next == NULL)
62656267 msg(_("Already only one tab page"));
6266- else
6268+ else if (!window_layout_locked())
62676269 {
62686270 tab_number = get_tabpage_arg(eap);
62696271 if (eap->errmsg == NULL)
@@ -6296,6 +6298,9 @@
62966298 void
62976299 tabpage_close(int forceit)
62986300 {
6301+ if (window_layout_locked())
6302+ return;
6303+
62996304 // First close all the windows but the current one. If that worked then
63006305 // close the last window in this tab, that will close it.
63016306 if (!ONE_WINDOW)
@@ -6341,14 +6346,15 @@
63416346 static void
63426347 ex_only(exarg_T *eap)
63436348 {
6344- win_T *wp;
6345- int wnr;
6349+ if (window_layout_locked())
6350+ return;
63466351 # ifdef FEAT_GUI
63476352 need_mouse_correct = TRUE;
63486353 # endif
63496354 if (eap->addr_count > 0)
63506355 {
6351- wnr = eap->line2;
6356+ win_T *wp;
6357+ int wnr = eap->line2;
63526358 for (wp = firstwin; --wnr > 0; )
63536359 {
63546360 if (wp->w_next == NULL)
@@ -6367,6 +6373,8 @@
63676373 // ":hide" or ":hide | cmd": hide current window
63686374 if (!eap->skip)
63696375 {
6376+ if (window_layout_locked())
6377+ return;
63706378 #ifdef FEAT_GUI
63716379 need_mouse_correct = TRUE;
63726380 #endif
diff -r 500ebbee148d -r f6d4c6a3b41c src/proto/window.pro
--- a/src/proto/window.pro Sat Nov 19 12:00:05 2022 +0100
+++ b/src/proto/window.pro Sat Nov 19 12:45:04 2022 +0100
@@ -1,4 +1,5 @@
11 /* window.c */
2+int window_layout_locked(void);
23 win_T *prevwin_curwin(void);
34 void do_window(int nchar, long Prenum, int xchar);
45 void get_wincmd_addr_type(char_u *arg, exarg_T *eap);
diff -r 500ebbee148d -r f6d4c6a3b41c src/version.c
--- a/src/version.c Sat Nov 19 12:00:05 2022 +0100
+++ b/src/version.c Sat Nov 19 12:45:04 2022 +0100
@@ -696,6 +696,8 @@
696696 static int included_patches[] =
697697 { /* Add new patch number below this line */
698698 /**/
699+ 907,
700+/**/
699701 906,
700702 /**/
701703 905,
diff -r 500ebbee148d -r f6d4c6a3b41c src/window.c
--- a/src/window.c Sat Nov 19 12:00:05 2022 +0100
+++ b/src/window.c Sat Nov 19 12:45:04 2022 +0100
@@ -84,6 +84,48 @@
8484 // autocommands mess up the window structure.
8585 static int split_disallowed = 0;
8686
87+// When non-zero closing a window is forbidden. Used to avoid that nasty
88+// autocommands mess up the window structure.
89+static int close_disallowed = 0;
90+
91+/*
92+ * Disallow changing the window layout (split window, close window, move
93+ * window). Resizing is still allowed.
94+ * Used for autocommands that temporarily use another window and need to
95+ * make sure the previously selected window is still there.
96+ * Must be matched with exactly one call to window_layout_unlock()!
97+ */
98+ static void
99+window_layout_lock(void)
100+{
101+ ++split_disallowed;
102+ ++close_disallowed;
103+}
104+
105+ static void
106+window_layout_unlock(void)
107+{
108+ --split_disallowed;
109+ --close_disallowed;
110+}
111+
112+/*
113+ * When the window layout cannot be changed give an error and return TRUE.
114+ */
115+ int
116+window_layout_locked(void)
117+{
118+ if (split_disallowed > 0 || close_disallowed > 0)
119+ {
120+ if (close_disallowed == 0)
121+ emsg(_(e_cannot_split_window_when_closing_buffer));
122+ else
123+ emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd));
124+ return TRUE;
125+ }
126+ return FALSE;
127+}
128+
87129 // #define WIN_DEBUG
88130 #ifdef WIN_DEBUG
89131 /*
@@ -2531,6 +2573,8 @@
25312573 emsg(_(e_cannot_close_last_window));
25322574 return FAIL;
25332575 }
2576+ if (window_layout_locked())
2577+ return FAIL;
25342578
25352579 if (win->w_closing || (win->w_buffer != NULL
25362580 && win->w_buffer->b_locked > 0))
@@ -2802,24 +2846,28 @@
28022846 void
28032847 may_trigger_winscrolled(void)
28042848 {
2805- win_T *wp = curwin;
28062849 static int recursive = FALSE;
2807- char_u winid[NUMBUFLEN];
28082850
28092851 if (recursive || !has_winscrolled())
28102852 return;
28112853
2854+ win_T *wp = curwin;
28122855 if (wp->w_last_topline != wp->w_topline
28132856 || wp->w_last_leftcol != wp->w_leftcol
28142857 || wp->w_last_skipcol != wp->w_skipcol
28152858 || wp->w_last_width != wp->w_width
28162859 || wp->w_last_height != wp->w_height)
28172860 {
2818- vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
2861+ // "curwin" may be different from the actual current window, make sure
2862+ // it can be restored.
2863+ window_layout_lock();
28192864
28202865 recursive = TRUE;
2866+ char_u winid[NUMBUFLEN];
2867+ vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
28212868 apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer);
28222869 recursive = FALSE;
2870+ window_layout_unlock();
28232871
28242872 // an autocmd may close the window, "wp" may be invalid now
28252873 if (win_valid_any_tab(wp))
@@ -4014,6 +4062,8 @@
40144062 emsg(_(e_invalid_in_cmdline_window));
40154063 return FAIL;
40164064 }
4065+ if (window_layout_locked())
4066+ return FAIL;
40174067
40184068 newtp = alloc_tabpage();
40194069 if (newtp == NULL)
Show on old repository browser