Patch 9.0.0907
Problem:    Restoring window after WinScrolled may fail.
Solution:   Lock the window layout when triggering WinScrolled.
Files:      src/window.c, src/proto/window.pro, src/errors.h, src/ex_docmd.c


*** ../vim-9.0.0906/src/window.c        2022-11-01 18:34:02.783964409 +0000
--- src/window.c        2022-11-19 11:25:22.357826785 +0000
***************
*** 84,89 ****
--- 84,131 ----
  // 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.
+  */
+     int
+ window_layout_locked(void)
+ {
+     if (split_disallowed > 0 || close_disallowed > 0)
+     {
+       if (close_disallowed == 0)
+           emsg(_(e_cannot_split_window_when_closing_buffer));
+       else
+           emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd));
+       return TRUE;
+     }
+     return FALSE;
+ }
+ 
  // #define WIN_DEBUG
  #ifdef WIN_DEBUG
  /*
***************
*** 2531,2536 ****
--- 2573,2580 ----
        emsg(_(e_cannot_close_last_window));
        return FAIL;
      }
+     if (window_layout_locked())
+       return FAIL;
  
      if (win->w_closing || (win->w_buffer != NULL
                                               && win->w_buffer->b_locked > 0))
***************
*** 2802,2825 ****
      void
  may_trigger_winscrolled(void)
  {
-     win_T         *wp = curwin;
      static int            recursive = FALSE;
-     char_u        winid[NUMBUFLEN];
  
      if (recursive || !has_winscrolled())
        return;
  
      if (wp->w_last_topline != wp->w_topline
            || wp->w_last_leftcol != wp->w_leftcol
            || wp->w_last_skipcol != wp->w_skipcol
            || wp->w_last_width != wp->w_width
            || wp->w_last_height != wp->w_height)
      {
!       vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
  
        recursive = TRUE;
        apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer);
        recursive = FALSE;
  
        // an autocmd may close the window, "wp" may be invalid now
        if (win_valid_any_tab(wp))
--- 2846,2873 ----
      void
  may_trigger_winscrolled(void)
  {
      static int            recursive = FALSE;
  
      if (recursive || !has_winscrolled())
        return;
  
+     win_T *wp = curwin;
      if (wp->w_last_topline != wp->w_topline
            || wp->w_last_leftcol != wp->w_leftcol
            || wp->w_last_skipcol != wp->w_skipcol
            || wp->w_last_width != wp->w_width
            || wp->w_last_height != wp->w_height)
      {
!       // "curwin" may be different from the actual current window, make sure
!       // it can be restored.
!       window_layout_lock();
  
        recursive = TRUE;
+       char_u winid[NUMBUFLEN];
+       vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
        apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer);
        recursive = FALSE;
+       window_layout_unlock();
  
        // an autocmd may close the window, "wp" may be invalid now
        if (win_valid_any_tab(wp))
***************
*** 4014,4019 ****
--- 4062,4069 ----
        emsg(_(e_invalid_in_cmdline_window));
        return FAIL;
      }
+     if (window_layout_locked())
+       return FAIL;
  
      newtp = alloc_tabpage();
      if (newtp == NULL)
*** ../vim-9.0.0906/src/proto/window.pro        2022-07-23 09:06:23.620970749 
+0100
--- src/proto/window.pro        2022-11-19 11:25:26.341827109 +0000
***************
*** 1,4 ****
--- 1,5 ----
  /* window.c */
+ int window_layout_locked(void);
  win_T *prevwin_curwin(void);
  void do_window(int nchar, long Prenum, int xchar);
  void get_wincmd_addr_type(char_u *arg, exarg_T *eap);
*** ../vim-9.0.0906/src/errors.h        2022-11-13 23:30:02.423807434 +0000
--- src/errors.h        2022-11-19 11:12:36.641489018 +0000
***************
*** 3341,3343 ****
--- 3341,3345 ----
  #endif
  EXTERN char e_cannot_change_user_commands_while_listing[]
        INIT(= N_("E1311: Cannot change user commands while listing"));
+ EXTERN char e_not_allowed_to_change_window_layout_in_this_autocmd[]
+       INIT(= N_("E1312: Not allowed to change the window layout in this 
autocmd"));
*** ../vim-9.0.0906/src/ex_docmd.c      2022-11-11 22:57:41.774304953 +0000
--- src/ex_docmd.c      2022-11-19 11:29:24.325833848 +0000
***************
*** 6055,6060 ****
--- 6055,6062 ----
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return;
      }
+     if (window_layout_locked())
+       return;
  
      need_hide = (bufIsChanged(buf) && buf->b_nwindows <= 1);
      if (need_hide && !buf_hide(buf) && !forceit)
***************
*** 6227,6233 ****
        cmdwin_result = K_IGNORE;
      else if (first_tabpage->tp_next == NULL)
        emsg(_(e_cannot_close_last_tab_page));
!     else
      {
        tab_number = get_tabpage_arg(eap);
        if (eap->errmsg == NULL)
--- 6229,6235 ----
        cmdwin_result = K_IGNORE;
      else if (first_tabpage->tp_next == NULL)
        emsg(_(e_cannot_close_last_tab_page));
!     else if (!window_layout_locked())
      {
        tab_number = get_tabpage_arg(eap);
        if (eap->errmsg == NULL)
***************
*** 6263,6269 ****
        cmdwin_result = K_IGNORE;
      else if (first_tabpage->tp_next == NULL)
        msg(_("Already only one tab page"));
!     else
      {
        tab_number = get_tabpage_arg(eap);
        if (eap->errmsg == NULL)
--- 6265,6271 ----
        cmdwin_result = K_IGNORE;
      else if (first_tabpage->tp_next == NULL)
        msg(_("Already only one tab page"));
!     else if (!window_layout_locked())
      {
        tab_number = get_tabpage_arg(eap);
        if (eap->errmsg == NULL)
***************
*** 6296,6301 ****
--- 6298,6306 ----
      void
  tabpage_close(int forceit)
  {
+     if (window_layout_locked())
+       return;
+ 
      // First close all the windows but the current one.  If that worked then
      // close the last window in this tab, that will close it.
      if (!ONE_WINDOW)
***************
*** 6341,6354 ****
      static void
  ex_only(exarg_T *eap)
  {
!     win_T   *wp;
!     int           wnr;
  # ifdef FEAT_GUI
      need_mouse_correct = TRUE;
  # endif
      if (eap->addr_count > 0)
      {
!       wnr = eap->line2;
        for (wp = firstwin; --wnr > 0; )
        {
            if (wp->w_next == NULL)
--- 6346,6360 ----
      static void
  ex_only(exarg_T *eap)
  {
!     if (window_layout_locked())
!       return;
  # ifdef FEAT_GUI
      need_mouse_correct = TRUE;
  # endif
      if (eap->addr_count > 0)
      {
!       win_T   *wp;
!       int     wnr = eap->line2;
        for (wp = firstwin; --wnr > 0; )
        {
            if (wp->w_next == NULL)
***************
*** 6367,6372 ****
--- 6373,6380 ----
      // ":hide" or ":hide | cmd": hide current window
      if (!eap->skip)
      {
+       if (window_layout_locked())
+           return;
  #ifdef FEAT_GUI
        need_mouse_correct = TRUE;
  #endif
*** ../vim-9.0.0906/src/version.c       2022-11-19 10:47:45.758339628 +0000
--- src/version.c       2022-11-19 11:03:29.545672203 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     907,
  /**/

-- 
>From "know your smileys":
 %      Bike accident.  A bit far-fetched, I suppose; although...
             o      _     _         _
     _o     /\_   _ \\o  (_)\__/o  (_)
   _< \_   _>(_) (_)/<_    \_| \   _|/' \/
  (_)>(_) (_)        (_)   (_)    (_)'  _\o_

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221119114200.DAE3E1C12B2%40moolenaar.net.

Raspunde prin e-mail lui