Patch 9.0.0965
Problem:    Using one window for executing autocommands is insufficient.
Solution:   Use up to five windows for executing autocommands.
Files:      src/globals.h, src/structs.h, src/autocmd.c,
            src/proto/autocmd.pro, src/main.c, src/eval.c, src/evalwindow.c,
            src/ex_docmd.c, src/screen.c, src/terminal.c, src/window.c,
            src/buffer.c, src/bufwrite.c, src/channel.c, src/diff.c,
            src/evalbuffer.c, src/evalvars.c, src/ex_cmds2.c, src/fileio.c,
            src/if_ruby.c, src/os_unix.c, src/os_win32.c, src/quickfix.c,
            src/term.c, src/if_perl.xs, src/if_py_both.h,
            src/testdir/test_autocmd.vim


*** ../vim-9.0.0964/src/globals.h       2022-11-26 19:16:44.186717893 +0000
--- src/globals.h       2022-11-28 17:23:59.229580371 +0000
***************
*** 977,984 ****
  
  EXTERN win_T  *curwin;        // currently active window
  
! EXTERN win_T  *aucmd_win;     // window used in aucmd_prepbuf()
! EXTERN int    aucmd_win_used INIT(= FALSE);   // aucmd_win is being used
  
  #ifdef FEAT_PROP_POPUP
  EXTERN win_T    *first_popupwin;              // first global popup window
--- 977,994 ----
  
  EXTERN win_T  *curwin;        // currently active window
  
! // When executing autocommands for a buffer that is not in any window, a
! // special window is created to handle the side effects.  When autocommands
! // nest we may need more than one.  Allow for up to five, if more are needed
! // something crazy is happening.
! #define AUCMD_WIN_COUNT 5
! 
! typedef struct {
!   win_T       *auc_win;       // window used in aucmd_prepbuf()
!   int auc_win_used;   // this auc_win is being used
! } aucmdwin_T;
! 
! EXTERN aucmdwin_T aucmd_win[AUCMD_WIN_COUNT];
  
  #ifdef FEAT_PROP_POPUP
  EXTERN win_T    *first_popupwin;              // first global popup window
*** ../vim-9.0.0964/src/structs.h       2022-11-25 16:31:46.964606667 +0000
--- src/structs.h       2022-11-28 17:36:48.730226363 +0000
***************
*** 4160,4166 ****
  typedef struct
  {
      buf_T     *save_curbuf;       // saved curbuf
!     int               use_aucmd_win;      // using aucmd_win
      int               save_curwin_id;     // ID of saved curwin
      int               new_curwin_id;      // ID of new curwin
      int               save_prevwin_id;    // ID of saved prevwin
--- 4160,4166 ----
  typedef struct
  {
      buf_T     *save_curbuf;       // saved curbuf
!     int               use_aucmd_win_idx;  // index in aucmd_win[] if >= 0
      int               save_curwin_id;     // ID of saved curwin
      int               new_curwin_id;      // ID of new curwin
      int               save_prevwin_id;    // ID of saved prevwin
*** ../vim-9.0.0964/src/autocmd.c       2022-11-22 12:40:44.062427876 +0000
--- src/autocmd.c       2022-11-28 18:01:55.253554954 +0000
***************
*** 629,656 ****
      }
  }
  
  #if defined(EXITFREE) || defined(PROTO)
      void
  free_all_autocmds(void)
  {
-     int               i;
      char_u    *s;
  
      for (current_augroup = -1; current_augroup < augroups.ga_len;
                                                            ++current_augroup)
        do_autocmd(NULL, (char_u *)"", TRUE);
  
!     for (i = 0; i < augroups.ga_len; ++i)
      {
        s = ((char_u **)(augroups.ga_data))[i];
        if (s != get_deleted_augroup())
            vim_free(s);
      }
      ga_clear(&augroups);
  }
  #endif
  
  /*
   * Return the event number for event name "start".
   * Return NUM_EVENTS if the event name was not found.
   * Return a pointer to the next event name in "end".
--- 629,680 ----
      }
  }
  
+     void
+ autocmd_init(void)
+ {
+     CLEAR_FIELD(aucmd_win);
+ }
+ 
  #if defined(EXITFREE) || defined(PROTO)
      void
  free_all_autocmds(void)
  {
      char_u    *s;
  
      for (current_augroup = -1; current_augroup < augroups.ga_len;
                                                            ++current_augroup)
        do_autocmd(NULL, (char_u *)"", TRUE);
  
!     for (int i = 0; i < augroups.ga_len; ++i)
      {
        s = ((char_u **)(augroups.ga_data))[i];
        if (s != get_deleted_augroup())
            vim_free(s);
      }
      ga_clear(&augroups);
+ 
+     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
+       if (aucmd_win[i].auc_win_used)
+       {
+           aucmd_win[i].auc_win_used = FALSE;
+           win_remove(aucmd_win[i].auc_win, NULL);
+       }
  }
  #endif
  
  /*
+  * Return TRUE if "win" is an active entry in aucmd_win[].
+  */
+     int
+ is_aucmd_win(win_T *win)
+ {
+     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
+       if (aucmd_win[i].auc_win_used && aucmd_win[i].auc_win == win)
+           return TRUE;
+     return FALSE;
+ }
+ 
+ /*
   * Return the event number for event name "start".
   * Return NUM_EVENTS if the event name was not found.
   * Return a pointer to the next event name in "end".
***************
*** 1438,1445 ****
        if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
            continue;
  
!       // find a window for this buffer and save some values
        aucmd_prepbuf(&aco, buf);
        set_bufref(&bufref, buf);
  
        // execute the autocommands for this buffer
--- 1462,1477 ----
        if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
            continue;
  
!       // Find a window for this buffer and save some values.
        aucmd_prepbuf(&aco, buf);
+       if (curbuf != buf)
+       {
+           // Failed to find a window for this buffer.  Better not execute
+           // autocommands then.
+           retval = FAIL;
+           break;
+       }
+ 
        set_bufref(&bufref, buf);
  
        // execute the autocommands for this buffer
***************
*** 1449,1455 ****
            // Execute the modeline settings, but don't set window-local
            // options if we are using the current window for another
            // buffer.
!           do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
  
        // restore the current window
        aucmd_restbuf(&aco);
--- 1481,1487 ----
            // Execute the modeline settings, but don't set window-local
            // options if we are using the current window for another
            // buffer.
!           do_modelines(is_aucmd_win(curwin) ? OPT_NOWIN : 0);
  
        // restore the current window
        aucmd_restbuf(&aco);
***************
*** 1490,1497 ****
  /*
   * Prepare for executing autocommands for (hidden) buffer "buf".
   * Search for a visible window containing the current buffer.  If there isn't
!  * one then use "aucmd_win".
   * Set "curbuf" and "curwin" to match "buf".
   */
      void
  aucmd_prepbuf(
--- 1522,1530 ----
  /*
   * Prepare for executing autocommands for (hidden) buffer "buf".
   * Search for a visible window containing the current buffer.  If there isn't
!  * one then use an entry in "aucmd_win[]".
   * Set "curbuf" and "curwin" to match "buf".
+  * When this fails "curbuf" is not equal "buf".
   */
      void
  aucmd_prepbuf(
***************
*** 1512,1529 ****
            if (win->w_buffer == buf)
                break;
  
!     // Allocate "aucmd_win" when needed.  If this fails (out of memory) fall
!     // back to using the current window.
!     if (win == NULL && aucmd_win == NULL)
!     {
!       aucmd_win = win_alloc_popup_win();
!       if (aucmd_win == NULL)
!           win = curwin;
!     }
!     if (win == NULL && aucmd_win_used)
!       // Strange recursive autocommand, fall back to using the current
!       // window.  Expect a few side effects...
!       win = curwin;
  
      aco->save_curwin_id = curwin->w_id;
      aco->save_curbuf = curbuf;
--- 1545,1573 ----
            if (win->w_buffer == buf)
                break;
  
!     // Allocate a window when needed.
!     win_T *auc_win = NULL;
!     int auc_idx = AUCMD_WIN_COUNT;
!     if (win == NULL)
!     {
!       for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; ++auc_idx)
!           if (!aucmd_win[auc_idx].auc_win_used)
!           {
!               auc_win = win_alloc_popup_win();
!               if (auc_win != NULL)
!               {
!                   aucmd_win[auc_idx].auc_win = auc_win;
!                   aucmd_win[auc_idx].auc_win_used = TRUE;
!               }
!               break;
!           }
! 
!       // If this fails (out of memory or using all AUCMD_WIN_COUNT
!       // entries) then we can't reliable execute the autocmd, return with
!       // "curbuf" unequal "buf".
!       if (auc_win == NULL)
!           return;
!     }
  
      aco->save_curwin_id = curwin->w_id;
      aco->save_curbuf = curbuf;
***************
*** 1533,1556 ****
        // There is a window for "buf" in the current tab page, make it the
        // curwin.  This is preferred, it has the least side effects (esp. if
        // "buf" is curbuf).
!       aco->use_aucmd_win = FALSE;
        curwin = win;
      }
      else
      {
!       // There is no window for "buf", use "aucmd_win".  To minimize the side
        // effects, insert it in the current tab page.
        // Anything related to a window (e.g., setting folds) may have
        // unexpected results.
!       aco->use_aucmd_win = TRUE;
!       aucmd_win_used = TRUE;
  
!       win_init_popup_win(aucmd_win, buf);
  
        aco->globaldir = globaldir;
        globaldir = NULL;
  
!       // Split the current window, put the aucmd_win in the upper half.
        // We don't want the BufEnter or WinEnter autocommands.
        block_autocmds();
        make_snapshot(SNAP_AUCMD_IDX);
--- 1577,1599 ----
        // There is a window for "buf" in the current tab page, make it the
        // curwin.  This is preferred, it has the least side effects (esp. if
        // "buf" is curbuf).
!       aco->use_aucmd_win_idx = -1;
        curwin = win;
      }
      else
      {
!       // There is no window for "buf", use "auc_win".  To minimize the side
        // effects, insert it in the current tab page.
        // Anything related to a window (e.g., setting folds) may have
        // unexpected results.
!       aco->use_aucmd_win_idx = auc_idx;
  
!       win_init_popup_win(auc_win, buf);
  
        aco->globaldir = globaldir;
        globaldir = NULL;
  
!       // Split the current window, put the auc_win in the upper half.
        // We don't want the BufEnter or WinEnter autocommands.
        block_autocmds();
        make_snapshot(SNAP_AUCMD_IDX);
***************
*** 1565,1571 ****
  
        // no redrawing and don't set the window title
        ++RedrawingDisabled;
!       (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
        --RedrawingDisabled;
        (void)win_comp_pos();   // recompute window positions
        p_ea = save_ea;
--- 1608,1614 ----
  
        // no redrawing and don't set the window title
        ++RedrawingDisabled;
!       (void)win_split_ins(0, WSP_TOP, auc_win, 0);
        --RedrawingDisabled;
        (void)win_comp_pos();   // recompute window positions
        p_ea = save_ea;
***************
*** 1573,1579 ****
        p_acd = save_acd;
  #endif
        unblock_autocmds();
!       curwin = aucmd_win;
      }
      curbuf = buf;
      aco->new_curwin_id = curwin->w_id;
--- 1616,1622 ----
        p_acd = save_acd;
  #endif
        unblock_autocmds();
!       curwin = auc_win;
      }
      curbuf = buf;
      aco->new_curwin_id = curwin->w_id;
***************
*** 1595,1618 ****
      int           dummy;
      win_T   *save_curwin;
  
!     if (aco->use_aucmd_win)
      {
        --curbuf->b_nwindows;
!       // Find "aucmd_win", it can't be closed, but it may be in another tab
        // page. Do not trigger autocommands here.
        block_autocmds();
!       if (curwin != aucmd_win)
        {
            tabpage_T   *tp;
            win_T       *wp;
  
            FOR_ALL_TAB_WINDOWS(tp, wp)
            {
!               if (wp == aucmd_win)
                {
                    if (tp != curtab)
                        goto_tabpage_tp(tp, TRUE, TRUE);
!                   win_goto(aucmd_win);
                    goto win_found;
                }
            }
--- 1638,1663 ----
      int           dummy;
      win_T   *save_curwin;
  
!     if (aco->use_aucmd_win_idx >= 0)
      {
+       win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win;
+ 
        --curbuf->b_nwindows;
!       // Find "awp", it can't be closed, but it may be in another tab
        // page. Do not trigger autocommands here.
        block_autocmds();
!       if (curwin != awp)
        {
            tabpage_T   *tp;
            win_T       *wp;
  
            FOR_ALL_TAB_WINDOWS(tp, wp)
            {
!               if (wp == awp)
                {
                    if (tp != curtab)
                        goto_tabpage_tp(tp, TRUE, TRUE);
!                   win_goto(awp);
                    goto win_found;
                }
            }
***************
*** 1622,1628 ****
        // Remove the window and frame from the tree of frames.
        (void)winframe_remove(curwin, &dummy, NULL);
        win_remove(curwin, NULL);
!       aucmd_win_used = FALSE;
        last_status(FALSE);         // may need to remove last status line
  
        if (!valid_tabpage_win(curtab))
--- 1667,1673 ----
        // Remove the window and frame from the tree of frames.
        (void)winframe_remove(curwin, &dummy, NULL);
        win_remove(curwin, NULL);
!       aucmd_win[aco->use_aucmd_win_idx].auc_win_used = FALSE;
        last_status(FALSE);         // may need to remove last status line
  
        if (!valid_tabpage_win(curtab))
***************
*** 1646,1653 ****
  #endif
        prevwin = win_find_by_id(aco->save_prevwin_id);
  #ifdef FEAT_EVAL
!       vars_clear(&aucmd_win->w_vars->dv_hashtab);  // free all w: variables
!       hash_init(&aucmd_win->w_vars->dv_hashtab);   // re-use the hashtab
  #endif
        vim_free(globaldir);
        globaldir = aco->globaldir;
--- 1691,1698 ----
  #endif
        prevwin = win_find_by_id(aco->save_prevwin_id);
  #ifdef FEAT_EVAL
!       vars_clear(&awp->w_vars->dv_hashtab);  // free all w: variables
!       hash_init(&awp->w_vars->dv_hashtab);   // re-use the hashtab
  #endif
        vim_free(globaldir);
        globaldir = aco->globaldir;
***************
*** 1664,1674 ****
  #if defined(FEAT_GUI)
        if (gui.in_use)
        {
!           // Hide the scrollbars from the aucmd_win and update.
!           gui_mch_enable_scrollbar(
!                                  &aucmd_win->w_scrollbars[SBAR_LEFT], FALSE);
!           gui_mch_enable_scrollbar(
!                                 &aucmd_win->w_scrollbars[SBAR_RIGHT], FALSE);
            gui_may_update_scrollbars();
        }
  #endif
--- 1709,1717 ----
  #if defined(FEAT_GUI)
        if (gui.in_use)
        {
!           // Hide the scrollbars from the "awp" and update.
!           gui_mch_enable_scrollbar(&awp->w_scrollbars[SBAR_LEFT], FALSE);
!           gui_mch_enable_scrollbar(&awp->w_scrollbars[SBAR_RIGHT], FALSE);
            gui_may_update_scrollbars();
        }
  #endif
*** ../vim-9.0.0964/src/proto/autocmd.pro       2022-11-22 12:40:44.062427876 
+0000
--- src/proto/autocmd.pro       2022-11-28 17:47:53.893838235 +0000
***************
*** 2,8 ****
--- 2,10 ----
  void aubuflocal_remove(buf_T *buf);
  int au_has_group(char_u *name);
  void do_augroup(char_u *arg, int del_group);
+ void autocmd_init(void);
  void free_all_autocmds(void);
+ int is_aucmd_win(win_T *win);
  int check_ei(void);
  char_u *au_event_disable(char *what);
  void au_event_restore(char_u *old_ei);
*** ../vim-9.0.0964/src/main.c  2022-11-24 00:08:58.461010529 +0000
--- src/main.c  2022-11-28 17:12:18.551941151 +0000
***************
*** 123,128 ****
--- 123,130 ----
  #endif
      params.window_count = -1;
  
+     autocmd_init();
+ 
  #ifdef FEAT_RUBY
      {
        int ruby_stack_start;
*** ../vim-9.0.0964/src/eval.c  2022-11-18 22:14:04.798988157 +0000
--- src/eval.c  2022-11-28 17:39:42.506319536 +0000
***************
*** 5084,5092 ****
      FOR_ALL_TAB_WINDOWS(tp, wp)
        abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
                                                                  NULL, NULL);
!     if (aucmd_win != NULL)
!       abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID,
!                                                                 NULL, NULL);
  #ifdef FEAT_PROP_POPUP
      FOR_ALL_POPUPWINS(wp)
        abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
--- 5084,5093 ----
      FOR_ALL_TAB_WINDOWS(tp, wp)
        abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
                                                                  NULL, NULL);
!     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
!       if (aucmd_win[i].auc_win_used)
!           abort = abort || set_ref_in_item(
!                   &aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL);
  #ifdef FEAT_PROP_POPUP
      FOR_ALL_POPUPWINS(wp)
        abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
*** ../vim-9.0.0964/src/evalwindow.c    2022-11-18 22:14:04.798988157 +0000
--- src/evalwindow.c    2022-11-28 17:40:20.758338784 +0000
***************
*** 1064,1070 ****
            return;
        }
      }
!     if (wp == aucmd_win)
        rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
  #if defined(FEAT_QUICKFIX)
      else if (wp->w_p_pvw)
--- 1064,1070 ----
            return;
        }
      }
!     if (is_aucmd_win(wp))
        rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
  #if defined(FEAT_QUICKFIX)
      else if (wp->w_p_pvw)
*** ../vim-9.0.0964/src/ex_docmd.c      2022-11-19 13:14:05.737367072 +0000
--- src/ex_docmd.c      2022-11-28 17:40:46.126326544 +0000
***************
*** 6050,6056 ****
      buf_T     *buf = win->w_buffer;
  
      // Never close the autocommand window.
!     if (win == aucmd_win)
      {
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return;
--- 6050,6056 ----
      buf_T     *buf = win->w_buffer;
  
      // Never close the autocommand window.
!     if (is_aucmd_win(win))
      {
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return;
*** ../vim-9.0.0964/src/screen.c        2022-11-24 00:08:58.465010528 +0000
--- src/screen.c        2022-11-28 17:54:21.485646564 +0000
***************
*** 2369,2375 ****
      u8char_T      *new_ScreenLinesUC = NULL;
      u8char_T      *new_ScreenLinesC[MAX_MCO];
      schar_T       *new_ScreenLines2 = NULL;
-     int                   i;
      sattr_T       *new_ScreenAttrs;
      colnr_T       *new_ScreenCols;
      unsigned      *new_LineOffset;
--- 2369,2374 ----
***************
*** 2438,2445 ****
       */
      FOR_ALL_TAB_WINDOWS(tp, wp)
        win_free_lsize(wp);
!     if (aucmd_win != NULL)
!       win_free_lsize(aucmd_win);
  #ifdef FEAT_PROP_POPUP
      // global popup windows
      FOR_ALL_POPUPWINS(wp)
--- 2437,2445 ----
       */
      FOR_ALL_TAB_WINDOWS(tp, wp)
        win_free_lsize(wp);
!     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
!       if (aucmd_win[i].auc_win_used)
!           win_free_lsize(aucmd_win[i].auc_win);
  #ifdef FEAT_PROP_POPUP
      // global popup windows
      FOR_ALL_POPUPWINS(wp)
***************
*** 2455,2461 ****
      if (enc_utf8)
      {
        new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
!       for (i = 0; i < p_mco; ++i)
            new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
                                                         (Rows + 1) * Columns);
      }
--- 2455,2461 ----
      if (enc_utf8)
      {
        new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
!       for (int i = 0; i < p_mco; ++i)
            new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
                                                         (Rows + 1) * Columns);
      }
***************
*** 2482,2490 ****
            goto give_up;
        }
      }
!     if (aucmd_win != NULL && aucmd_win->w_lines == NULL
!                                       && win_alloc_lines(aucmd_win) == FAIL)
!       outofmem = TRUE;
  #ifdef FEAT_PROP_POPUP
      // global popup windows
      FOR_ALL_POPUPWINS(wp)
--- 2482,2495 ----
            goto give_up;
        }
      }
!     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
!       if (aucmd_win[i].auc_win_used
!               && aucmd_win[i].auc_win->w_lines == NULL
!               && win_alloc_lines(aucmd_win[i].auc_win) == FAIL)
!       {
!           outofmem = TRUE;
!           break;
!       }
  #ifdef FEAT_PROP_POPUP
      // global popup windows
      FOR_ALL_POPUPWINS(wp)
***************
*** 2505,2515 ****
  
  give_up:
  
!     for (i = 0; i < p_mco; ++i)
        if (new_ScreenLinesC[i] == NULL)
            break;
      if (new_ScreenLines == NULL
!           || (enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
            || (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
            || new_ScreenAttrs == NULL
            || new_ScreenCols == NULL
--- 2510,2524 ----
  
  give_up:
  
!     int found_null = FALSE;
!     for (int i = 0; i < p_mco; ++i)
        if (new_ScreenLinesC[i] == NULL)
+       {
+           found_null = TRUE;
            break;
+       }
      if (new_ScreenLines == NULL
!           || (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
            || (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
            || new_ScreenAttrs == NULL
            || new_ScreenCols == NULL
***************
*** 2534,2540 ****
        }
        VIM_CLEAR(new_ScreenLines);
        VIM_CLEAR(new_ScreenLinesUC);
!       for (i = 0; i < p_mco; ++i)
            VIM_CLEAR(new_ScreenLinesC[i]);
        VIM_CLEAR(new_ScreenLines2);
        VIM_CLEAR(new_ScreenAttrs);
--- 2543,2549 ----
        }
        VIM_CLEAR(new_ScreenLines);
        VIM_CLEAR(new_ScreenLinesUC);
!       for (int i = 0; i < p_mco; ++i)
            VIM_CLEAR(new_ScreenLinesC[i]);
        VIM_CLEAR(new_ScreenLines2);
        VIM_CLEAR(new_ScreenAttrs);
***************
*** 2571,2577 ****
                {
                    (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
                                       0, (size_t)Columns * sizeof(u8char_T));
!                   for (i = 0; i < p_mco; ++i)
                        (void)vim_memset(new_ScreenLinesC[i]
                                                          + new_row * Columns,
                                       0, (size_t)Columns * sizeof(u8char_T));
--- 2580,2586 ----
                {
                    (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
                                       0, (size_t)Columns * sizeof(u8char_T));
!                   for (int i = 0; i < p_mco; ++i)
                        (void)vim_memset(new_ScreenLinesC[i]
                                                          + new_row * Columns,
                                       0, (size_t)Columns * sizeof(u8char_T));
***************
*** 2603,2609 ****
                        mch_memmove(new_ScreenLinesUC + new_LineOffset[new_row],
                                ScreenLinesUC + LineOffset[old_row],
                                (size_t)len * sizeof(u8char_T));
!                       for (i = 0; i < p_mco; ++i)
                            mch_memmove(new_ScreenLinesC[i]
                                                    + new_LineOffset[new_row],
                                ScreenLinesC[i] + LineOffset[old_row],
--- 2612,2618 ----
                        mch_memmove(new_ScreenLinesUC + new_LineOffset[new_row],
                                ScreenLinesUC + LineOffset[old_row],
                                (size_t)len * sizeof(u8char_T));
!                       for (int i = 0; i < p_mco; ++i)
                            mch_memmove(new_ScreenLinesC[i]
                                                    + new_LineOffset[new_row],
                                ScreenLinesC[i] + LineOffset[old_row],
***************
*** 2636,2642 ****
      // NOTE: this may result in all pointers to become NULL.
      ScreenLines = new_ScreenLines;
      ScreenLinesUC = new_ScreenLinesUC;
!     for (i = 0; i < p_mco; ++i)
        ScreenLinesC[i] = new_ScreenLinesC[i];
      Screen_mco = p_mco;
      ScreenLines2 = new_ScreenLines2;
--- 2645,2651 ----
      // NOTE: this may result in all pointers to become NULL.
      ScreenLines = new_ScreenLines;
      ScreenLinesUC = new_ScreenLinesUC;
!     for (int i = 0; i < p_mco; ++i)
        ScreenLinesC[i] = new_ScreenLinesC[i];
      Screen_mco = p_mco;
      ScreenLines2 = new_ScreenLines2;
*** ../vim-9.0.0964/src/terminal.c      2022-11-25 16:31:46.968606662 +0000
--- src/terminal.c      2022-11-28 18:29:37.183398477 +0000
***************
*** 3560,3574 ****
            // ++close or term_finish == "close"
            ch_log(NULL, "terminal job finished, closing window");
            aucmd_prepbuf(&aco, term->tl_buffer);
!           // Avoid closing the window if we temporarily use it.
!           if (curwin == aucmd_win)
!               do_set_w_closing = TRUE;
!           if (do_set_w_closing)
!               curwin->w_closing = TRUE;
!           do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
!           if (do_set_w_closing)
!               curwin->w_closing = FALSE;
!           aucmd_restbuf(&aco);
  #ifdef FEAT_PROP_POPUP
            if (pwin != NULL)
                popup_close_with_retval(pwin, 0);
--- 3560,3577 ----
            // ++close or term_finish == "close"
            ch_log(NULL, "terminal job finished, closing window");
            aucmd_prepbuf(&aco, term->tl_buffer);
!           if (curbuf == term->tl_buffer)
!           {
!               // Avoid closing the window if we temporarily use it.
!               if (is_aucmd_win(curwin))
!                   do_set_w_closing = TRUE;
!               if (do_set_w_closing)
!                   curwin->w_closing = TRUE;
!               do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
!               if (do_set_w_closing)
!                   curwin->w_closing = FALSE;
!               aucmd_restbuf(&aco);
!           }
  #ifdef FEAT_PROP_POPUP
            if (pwin != NULL)
                popup_close_with_retval(pwin, 0);
*** ../vim-9.0.0964/src/window.c        2022-11-28 16:49:18.442868485 +0000
--- src/window.c        2022-11-28 17:47:21.633862191 +0000
***************
*** 1362,1368 ****
        win_equal(wp, TRUE,
                (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
                : dir == 'h' ? 'b' : 'v');
!     else if (*p_spk != 'c' && wp != aucmd_win)
        win_fix_scroll(FALSE);
  
      // Don't change the window height/width to 'winheight' / 'winwidth' if a
--- 1362,1368 ----
        win_equal(wp, TRUE,
                (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
                : dir == 'h' ? 'b' : 'v');
!     else if (*p_spk != 'c' && !is_aucmd_win(wp))
        win_fix_scroll(FALSE);
  
      // Don't change the window height/width to 'winheight' / 'winwidth' if a
***************
*** 1962,1968 ****
      win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
                      topframe, dir, 0, tabline_height(),
                                           (int)Columns, topframe->fr_height);
!     if (*p_spk != 'c' && next_curwin != aucmd_win)
        win_fix_scroll(TRUE);
  }
  
--- 1962,1968 ----
      win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
                      topframe, dir, 0, tabline_height(),
                                           (int)Columns, topframe->fr_height);
!     if (*p_spk != 'c' && !is_aucmd_win(next_curwin))
        win_fix_scroll(TRUE);
  }
  
***************
*** 2426,2432 ****
  
  /*
   * Return TRUE if the current window is the only window that exists (ignoring
!  * "aucmd_win").
   * Returns FALSE if there is a window, possibly in another tab page.
   */
      static int
--- 2426,2432 ----
  
  /*
   * Return TRUE if the current window is the only window that exists (ignoring
!  * "aucmd_win[]").
   * Returns FALSE if there is a window, possibly in another tab page.
   */
      static int
***************
*** 2436,2442 ****
  }
  
  /*
!  * Return TRUE if there is only one window other than "aucmd_win" in the
   * current tab page.
   */
      int
--- 2436,2442 ----
  }
  
  /*
!  * Return TRUE if there is only one window other than "aucmd_win[]" in the
   * current tab page.
   */
      int
***************
*** 2447,2453 ****
  
      FOR_ALL_WINDOWS(wp)
      {
!       if (wp != aucmd_win)
        {
            if (seen_one)
                return FALSE;
--- 2447,2453 ----
  
      FOR_ALL_WINDOWS(wp)
      {
!       if (!is_aucmd_win(wp))
        {
            if (seen_one)
                return FALSE;
***************
*** 2588,2594 ****
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return FAIL;
      }
!     if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
      {
        emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
        return FAIL;
--- 2588,2594 ----
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return FAIL;
      }
!     if ((is_aucmd_win(firstwin) || is_aucmd_win(lastwin)) && one_window())
      {
        emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
        return FAIL;
***************
*** 3292,3302 ****
      while (first_tabpage->tp_next != NULL)
        tabpage_close(TRUE);
  
!     if (aucmd_win != NULL)
!     {
!       (void)win_free_mem(aucmd_win, &dummy, NULL);
!       aucmd_win = NULL;
!     }
  
      while (firstwin != NULL)
        (void)win_free_mem(firstwin, &dummy, NULL);
--- 3292,3303 ----
      while (first_tabpage->tp_next != NULL)
        tabpage_close(TRUE);
  
!     for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
!       if (aucmd_win[i].auc_win_used)
!       {
!           (void)win_free_mem(aucmd_win[i].auc_win, &dummy, NULL);
!           aucmd_win[i].auc_win_used = FALSE;
!       }
  
      while (firstwin != NULL)
        (void)win_free_mem(firstwin, &dummy, NULL);
***************
*** 5663,5669 ****
      int
  win_unlisted(win_T *wp)
  {
!     return wp == aucmd_win || WIN_IS_POPUP(wp);
  }
  
  #if defined(FEAT_PROP_POPUP) || defined(PROTO)
--- 5664,5670 ----
      int
  win_unlisted(win_T *wp)
  {
!     return is_aucmd_win(wp) || WIN_IS_POPUP(wp);
  }
  
  #if defined(FEAT_PROP_POPUP) || defined(PROTO)
***************
*** 7257,7263 ****
  # ifdef FEAT_QUICKFIX
                    || wp->w_p_pvw
  # endif
!            ) || wp == curwin) && wp != aucmd_win)
            ++count;
      return (count <= 1);
  }
--- 7258,7264 ----
  # ifdef FEAT_QUICKFIX
                    || wp->w_p_pvw
  # endif
!            ) || wp == curwin) && !is_aucmd_win(wp))
            ++count;
      return (count <= 1);
  }
*** ../vim-9.0.0964/src/buffer.c        2022-11-25 16:31:46.964606667 +0000
--- src/buffer.c        2022-11-28 18:07:18.013530353 +0000
***************
*** 150,160 ****
      {
        aco_save_T      aco;
  
        aucmd_prepbuf(&aco, buf);
!       if (swap_exists_action != SEA_READONLY)
!           swap_exists_action = SEA_NONE;
!       open_buffer(FALSE, NULL, 0);
!       aucmd_restbuf(&aco);
      }
  }
  #endif
--- 150,164 ----
      {
        aco_save_T      aco;
  
+       // Make sure the buffer is in a window.  If not then skip it.
        aucmd_prepbuf(&aco, buf);
!       if (curbuf == buf)
!       {
!           if (swap_exists_action != SEA_READONLY)
!               swap_exists_action = SEA_NONE;
!           open_buffer(FALSE, NULL, 0);
!           aucmd_restbuf(&aco);
!       }
      }
  }
  #endif
***************
*** 361,381 ****
        {
            aco_save_T  aco;
  
!           // Go to the buffer that was opened.
            aucmd_prepbuf(&aco, old_curbuf.br_buf);
!           do_modelines(0);
!           curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
  
!           if ((flags & READ_NOWINENTER) == 0)
  #ifdef FEAT_EVAL
!               apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
!                                                             curbuf, &retval);
  #else
!               apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
  #endif
  
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
        }
      }
  
--- 365,390 ----
        {
            aco_save_T  aco;
  
!           // Go to the buffer that was opened, make sure it is in a window.
!           // If not then skip it.
            aucmd_prepbuf(&aco, old_curbuf.br_buf);
!           if (curbuf == old_curbuf.br_buf)
!           {
!               do_modelines(0);
!               curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
  
!               if ((flags & READ_NOWINENTER) == 0)
  #ifdef FEAT_EVAL
!                   apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL,
!                                                      FALSE, curbuf, &retval);
  #else
!                   apply_autocmds(EVENT_BUFWINENTER, NULL, NULL,
!                                                               FALSE, curbuf);
  #endif
  
!               // restore curwin/curbuf and a few other things
!               aucmd_restbuf(&aco);
!           }
        }
      }
  
***************
*** 5942,5949 ****
        return TRUE;
      }
  
!     // set curwin/curbuf to buf and save a few things
      aucmd_prepbuf(&aco, newbuf);
  
      if (ml_open(curbuf) == OK
            && readfile(buf->b_ffname, buf->b_fname,
--- 5951,5964 ----
        return TRUE;
      }
  
!     // Set curwin/curbuf to buf and save a few things.
      aucmd_prepbuf(&aco, newbuf);
+     if (curbuf != newbuf)
+     {
+       // Failed to find a window for "newbuf".
+       wipe_buffer(newbuf, FALSE);
+       return TRUE;
+     }
  
      if (ml_open(curbuf) == OK
            && readfile(buf->b_ffname, buf->b_fname,
*** ../vim-9.0.0964/src/bufwrite.c      2022-11-02 13:30:37.526314510 +0000
--- src/bufwrite.c      2022-11-28 18:12:05.305522374 +0000
***************
*** 802,809 ****
        if (fname == buf->b_sfname)
            buf_fname_s = TRUE;
  
!       // set curwin/curbuf to buf and save a few things
        aucmd_prepbuf(&aco, buf);
        set_bufref(&bufref, buf);
  
        if (append)
--- 802,816 ----
        if (fname == buf->b_sfname)
            buf_fname_s = TRUE;
  
!       // Set curwin/curbuf to buf and save a few things.
        aucmd_prepbuf(&aco, buf);
+       if (curbuf != buf)
+       {
+           // Could not find a window for "buf".  Doing more might cause
+           // problems, better bail out.
+           return FAIL;
+       }
+ 
        set_bufref(&bufref, buf);
  
        if (append)
***************
*** 2592,2614 ****
  
        // Apply POST autocommands.
        // Careful: The autocommands may call buf_write() recursively!
        aucmd_prepbuf(&aco, buf);
  
!       if (append)
!           apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
!                                                         FALSE, curbuf, eap);
!       else if (filtering)
!           apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
!                                                         FALSE, curbuf, eap);
!       else if (reset_changed && whole)
!           apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
!                                                         FALSE, curbuf, eap);
!       else
!           apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
!                                                         FALSE, curbuf, eap);
! 
!       // restore curwin/curbuf and a few other things
!       aucmd_restbuf(&aco);
  
  #ifdef FEAT_EVAL
        if (aborting())     // autocmds may abort script processing
--- 2599,2624 ----
  
        // Apply POST autocommands.
        // Careful: The autocommands may call buf_write() recursively!
+       // Only do this when a window was found for "buf".
        aucmd_prepbuf(&aco, buf);
+       if (curbuf == buf)
+       {
+           if (append)
+               apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
+                                                          FALSE, curbuf, eap);
+           else if (filtering)
+               apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
+                                                          FALSE, curbuf, eap);
+           else if (reset_changed && whole)
+               apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
+                                                          FALSE, curbuf, eap);
+           else
+               apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
+                                                          FALSE, curbuf, eap);
  
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
!       }
  
  #ifdef FEAT_EVAL
        if (aborting())     // autocmds may abort script processing
*** ../vim-9.0.0964/src/channel.c       2022-10-16 21:43:03.386665520 +0100
--- src/channel.c       2022-11-28 18:13:21.517521630 +0000
***************
*** 2872,2879 ****
  
      buffer->b_p_ma = TRUE;
  
!     // set curbuf to be our buf, temporarily
      aucmd_prepbuf(&aco, buffer);
  
      u_sync(TRUE);
      // ignore undo failure, undo is not very useful here
--- 2872,2885 ----
  
      buffer->b_p_ma = TRUE;
  
!     // Set curbuf to "buffer", temporarily.
      aucmd_prepbuf(&aco, buffer);
+     if (curbuf != buffer)
+     {
+       // Could not find a window for this buffer, the following might cause
+       // trouble, better bail out.
+       return;
+     }
  
      u_sync(TRUE);
      // ignore undo failure, undo is not very useful here
*** ../vim-9.0.0964/src/diff.c  2022-08-14 14:16:07.983582313 +0100
--- src/diff.c  2022-11-28 18:14:44.625513782 +0000
***************
*** 2786,2793 ****
        idx_to = idx_other;
        // Need to make the other buffer the current buffer to be able to make
        // changes in it.
!       // set curwin/curbuf to buf and save a few things
        aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
      }
  
      // May give the warning for a changed buffer here, which can trigger the
--- 2786,2797 ----
        idx_to = idx_other;
        // Need to make the other buffer the current buffer to be able to make
        // changes in it.
!       // Set curwin/curbuf to buf and save a few things.
        aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
+       if (curbuf != curtab->tp_diffbuf[idx_other])
+           // Could not find a window for this buffer, the rest is likely to
+           // fail.
+           goto theend;
      }
  
      // May give the warning for a changed buffer here, which can trigger the
*** ../vim-9.0.0964/src/evalbuffer.c    2022-11-27 19:45:45.706989832 +0000
--- src/evalbuffer.c    2022-11-28 18:18:26.628686202 +0000
***************
*** 136,141 ****
--- 136,143 ----
   *
   * Information is saved in "cob" and MUST be restored by calling
   * change_other_buffer_restore().
+  *
+  * If this fails then "curbuf" will not be equal to "buf".
   */
      static void
  change_other_buffer_prepare(cob_T *cob, buf_T *buf)
***************
*** 156,162 ****
        // curwin->w_buffer differ from "curbuf", use the autocmd window.
        curbuf = curwin->w_buffer;
        aucmd_prepbuf(&cob->cob_aco, buf);
!       cob->cob_using_aco = TRUE;
      }
  }
  
--- 158,165 ----
        // curwin->w_buffer differ from "curbuf", use the autocmd window.
        curbuf = curwin->w_buffer;
        aucmd_prepbuf(&cob->cob_aco, buf);
!       if (curbuf == buf)
!           cob->cob_using_aco = TRUE;
      }
  }
  
*** ../vim-9.0.0964/src/evalvars.c      2022-11-25 16:31:46.964606667 +0000
--- src/evalvars.c      2022-11-28 18:19:23.640519052 +0000
***************
*** 4761,4773 ****
        {
            aco_save_T  aco;
  
!           // set curbuf to be our buf, temporarily
            aucmd_prepbuf(&aco, buf);
  
!           set_option_from_tv(varname + 1, varp);
! 
!           // reset notion of buffer
!           aucmd_restbuf(&aco);
        }
        else
        {
--- 4761,4776 ----
        {
            aco_save_T  aco;
  
!           // Set curbuf to be our buf, temporarily.
            aucmd_prepbuf(&aco, buf);
+           if (curbuf == buf)
+           {
+               // Only when it worked to set "curbuf".
+               set_option_from_tv(varname + 1, varp);
  
!               // reset notion of buffer
!               aucmd_restbuf(&aco);
!           }
        }
        else
        {
*** ../vim-9.0.0964/src/ex_cmds2.c      2022-10-09 18:53:29.024591198 +0100
--- src/ex_cmds2.c      2022-11-28 18:19:48.764450172 +0000
***************
*** 705,713 ****
                else
                {
                    aucmd_prepbuf(&aco, buf);
!                   apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
                                                      buf->b_fname, TRUE, buf);
!                   aucmd_restbuf(&aco);
                }
  
                // start over, in case autocommands messed things up.
--- 705,716 ----
                else
                {
                    aucmd_prepbuf(&aco, buf);
!                   if (curbuf == buf)
!                   {
!                       apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
                                                      buf->b_fname, TRUE, buf);
!                       aucmd_restbuf(&aco);
!                   }
                }
  
                // start over, in case autocommands messed things up.
*** ../vim-9.0.0964/src/fileio.c        2022-11-01 20:33:39.991400397 +0000
--- src/fileio.c        2022-11-28 18:20:53.384285260 +0000
***************
*** 4369,4376 ****
      int               flags = READ_NEW;
      int               prepped = OK;
  
!     // set curwin/curbuf for "buf" and save some things
      aucmd_prepbuf(&aco, buf);
  
      // Unless reload_options is set, we only want to read the text from the
      // file, not reset the syntax highlighting, clear marks, diff status, etc.
--- 4369,4382 ----
      int               flags = READ_NEW;
      int               prepped = OK;
  
!     // Set curwin/curbuf for "buf" and save some things.
      aucmd_prepbuf(&aco, buf);
+     if (curbuf != buf)
+     {
+       // Failed to find a window for "buf", it is dangerous to continue,
+       // better bail out.
+       return;
+     }
  
      // Unless reload_options is set, we only want to read the text from the
      // file, not reset the syntax highlighting, clear marks, diff status, etc.
*** ../vim-9.0.0964/src/if_ruby.c       2022-11-25 16:31:46.968606662 +0000
--- src/if_ruby.c       2022-11-28 18:22:55.536015597 +0000
***************
*** 1371,1391 ****
  
      if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
      {
!       // set curwin/curbuf for "buf" and save some things
        aucmd_prepbuf(&aco, buf);
! 
!       if (u_savesub(n) == OK)
        {
!           ml_replace(n, (char_u *)line, TRUE);
!           changed();
  #ifdef SYNTAX_HL
!           syn_changed(n); // recompute syntax hl. for this line
  #endif
!       }
  
!       // restore curwin/curbuf and a few other things
!       aucmd_restbuf(&aco);
!       // Careful: autocommands may have made "buf" invalid!
  
        update_curbuf(UPD_NOT_VALID);
      }
--- 1371,1394 ----
  
      if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
      {
!       // Set curwin/curbuf for "buf" and save some things.
        aucmd_prepbuf(&aco, buf);
!       if (curbuf == buf)
        {
!           // Only when it worked to set "curbuf".
!           if (u_savesub(n) == OK)
!           {
!               ml_replace(n, (char_u *)line, TRUE);
!               changed();
  #ifdef SYNTAX_HL
!               syn_changed(n); // recompute syntax hl. for this line
  #endif
!           }
  
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
!           // Careful: autocommands may have made "buf" invalid!
!       }
  
        update_curbuf(UPD_NOT_VALID);
      }
***************
*** 1415,1438 ****
  
      if (n > 0 && n <= buf->b_ml.ml_line_count)
      {
!       // set curwin/curbuf for "buf" and save some things
        aucmd_prepbuf(&aco, buf);
! 
!       if (u_savedel(n, 1) == OK)
        {
!           ml_delete(n);
! 
!           // Changes to non-active buffers should properly refresh
!           //   SegPhault - 01/09/05
!           deleted_lines_mark(n, 1L);
! 
!           changed();
        }
  
-       // restore curwin/curbuf and a few other things
-       aucmd_restbuf(&aco);
-       // Careful: autocommands may have made "buf" invalid!
- 
        update_curbuf(UPD_NOT_VALID);
      }
      else
--- 1418,1444 ----
  
      if (n > 0 && n <= buf->b_ml.ml_line_count)
      {
!       // Set curwin/curbuf for "buf" and save some things.
        aucmd_prepbuf(&aco, buf);
!       if (curbuf == buf)
        {
!           // Only when it worked to set "curbuf".
!           if (u_savedel(n, 1) == OK)
!           {
!               ml_delete(n);
! 
!               // Changes to non-active buffers should properly refresh
!               //   SegPhault - 01/09/05
!               deleted_lines_mark(n, 1L);
! 
!               changed();
!           }
! 
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
!           // Careful: autocommands may have made "buf" invalid!
        }
  
        update_curbuf(UPD_NOT_VALID);
      }
      else
***************
*** 1458,1479 ****
      {
        // set curwin/curbuf for "buf" and save some things
        aucmd_prepbuf(&aco, buf);
! 
!       if (u_inssub(n + 1) == OK)
        {
!           ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
! 
!           //  Changes to non-active buffers should properly refresh screen
!           //    SegPhault - 12/20/04
!           appended_lines_mark(n, 1L);
! 
!           changed();
        }
  
-       // restore curwin/curbuf and a few other things
-       aucmd_restbuf(&aco);
-       // Careful: autocommands may have made "buf" invalid!
- 
        update_curbuf(UPD_NOT_VALID);
      }
      else
--- 1464,1488 ----
      {
        // set curwin/curbuf for "buf" and save some things
        aucmd_prepbuf(&aco, buf);
!       if (curbuf == buf)
        {
!           // Only when it worked to set "curbuf".
!           if (u_inssub(n + 1) == OK)
!           {
!               ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
! 
!               //  Changes to non-active buffers should properly refresh screen
!               //    SegPhault - 12/20/04
!               appended_lines_mark(n, 1L);
! 
!               changed();
!           }
! 
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
!           // Careful: autocommands may have made "buf" invalid!
        }
  
        update_curbuf(UPD_NOT_VALID);
      }
      else
*** ../vim-9.0.0964/src/os_unix.c       2022-11-25 15:09:30.710402884 +0000
--- src/os_unix.c       2022-11-28 18:24:30.511837561 +0000
***************
*** 4490,4516 ****
  
      // Find a window to make "buf" curbuf.
      aucmd_prepbuf(&aco, buf);
! 
!     clear_oparg(&oa);
!     while (term_use_loop())
      {
!       if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
        {
!           // If terminal_loop() returns OK we got a key that is handled
!           // in Normal model. We don't do redrawing anyway.
!           if (terminal_loop(TRUE) == OK)
                normal_cmd(&oa, TRUE);
        }
!       else
!           normal_cmd(&oa, TRUE);
!     }
!     retval = job->jv_exitval;
!     ch_log(NULL, "system command finished");
  
!     job_unref(job);
  
!     // restore curwin/curbuf and a few other things
!     aucmd_restbuf(&aco);
  
      // Only require pressing Enter when redrawing, to avoid that system() gets
      // the hit-enter prompt even though it didn't output anything.
--- 4490,4519 ----
  
      // Find a window to make "buf" curbuf.
      aucmd_prepbuf(&aco, buf);
!     if (curbuf == buf)
      {
!       // Only when managed to find a window for "buf",
!       clear_oparg(&oa);
!       while (term_use_loop())
        {
!           if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
!           {
!               // If terminal_loop() returns OK we got a key that is handled
!               // in Normal model. We don't do redrawing anyway.
!               if (terminal_loop(TRUE) == OK)
!                   normal_cmd(&oa, TRUE);
!           }
!           else
                normal_cmd(&oa, TRUE);
        }
!       retval = job->jv_exitval;
!       ch_log(NULL, "system command finished");
  
!       job_unref(job);
  
!       // restore curwin/curbuf and a few other things
!       aucmd_restbuf(&aco);
!     }
  
      // Only require pressing Enter when redrawing, to avoid that system() gets
      // the hit-enter prompt even though it didn't output anything.
*** ../vim-9.0.0964/src/os_win32.c      2022-11-23 22:28:03.552026184 +0000
--- src/os_win32.c      2022-11-28 18:25:11.999767140 +0000
***************
*** 4878,4904 ****
  
      // Find a window to make "buf" curbuf.
      aucmd_prepbuf(&aco, buf);
! 
!     clear_oparg(&oa);
!     while (term_use_loop())
      {
!       if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
        {
!           // If terminal_loop() returns OK we got a key that is handled
!           // in Normal model. We don't do redrawing anyway.
!           if (terminal_loop(TRUE) == OK)
                normal_cmd(&oa, TRUE);
        }
!       else
!           normal_cmd(&oa, TRUE);
!     }
!     retval = job->jv_exitval;
!     ch_log(NULL, "system command finished");
  
!     job_unref(job);
  
!     // restore curwin/curbuf and a few other things
!     aucmd_restbuf(&aco);
  
      wait_return(TRUE);
      do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
--- 4878,4907 ----
  
      // Find a window to make "buf" curbuf.
      aucmd_prepbuf(&aco, buf);
!     if (curbuf == buf)
      {
!       // Only do this when a window was found for "buf".
!       clear_oparg(&oa);
!       while (term_use_loop())
        {
!           if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
!           {
!               // If terminal_loop() returns OK we got a key that is handled
!               // in Normal model. We don't do redrawing anyway.
!               if (terminal_loop(TRUE) == OK)
!                   normal_cmd(&oa, TRUE);
!           }
!           else
                normal_cmd(&oa, TRUE);
        }
!       retval = job->jv_exitval;
!       ch_log(NULL, "system command finished");
  
!       job_unref(job);
  
!       // restore curwin/curbuf and a few other things
!       aucmd_restbuf(&aco);
!     }
  
      wait_return(TRUE);
      do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
*** ../vim-9.0.0964/src/quickfix.c      2022-11-13 12:54:46.718898500 +0000
--- src/quickfix.c      2022-11-28 18:28:02.135516484 +0000
***************
*** 4598,4618 ****
        // autocommands may cause trouble
        incr_quickfix_busy();
  
        if (old_last == NULL)
            // set curwin/curbuf to buf and save a few things
            aucmd_prepbuf(&aco, buf);
  
!       qf_update_win_titlevar(qi);
  
!       qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
!       ++CHANGEDTICK(buf);
  
!       if (old_last == NULL)
!       {
!           (void)qf_win_pos_update(qi, 0);
  
!           // restore curwin/curbuf and a few other things
!           aucmd_restbuf(&aco);
        }
  
        // Only redraw when added lines are visible.  This avoids flickering
--- 4598,4626 ----
        // autocommands may cause trouble
        incr_quickfix_busy();
  
+       int do_fill = TRUE;
        if (old_last == NULL)
+       {
            // set curwin/curbuf to buf and save a few things
            aucmd_prepbuf(&aco, buf);
+           if (curbuf != buf)
+               do_fill = FALSE;  // failed to find a window for "buf"
+       }
  
!       if (do_fill)
!       {
!           qf_update_win_titlevar(qi);
  
!           qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
!           ++CHANGEDTICK(buf);
  
!           if (old_last == NULL)
!           {
!               (void)qf_win_pos_update(qi, 0);
  
!               // restore curwin/curbuf and a few other things
!               aucmd_restbuf(&aco);
!           }
        }
  
        // Only redraw when added lines are visible.  This avoids flickering
***************
*** 6395,6406 ****
                    // need to be done (again).  But not the window-local
                    // options!
                    aucmd_prepbuf(&aco, buf);
  #if defined(FEAT_SYN_HL)
!                   apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
                                                     buf->b_fname, TRUE, buf);
  #endif
!                   do_modelines(OPT_NOWIN);
!                   aucmd_restbuf(&aco);
                }
            }
        }
--- 6403,6417 ----
                    // need to be done (again).  But not the window-local
                    // options!
                    aucmd_prepbuf(&aco, buf);
+                   if (curbuf == buf)
+                   {
  #if defined(FEAT_SYN_HL)
!                       apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
                                                     buf->b_fname, TRUE, buf);
  #endif
!                       do_modelines(OPT_NOWIN);
!                       aucmd_restbuf(&aco);
!                   }
                }
            }
        }
***************
*** 6593,6632 ****
  
        // set curwin/curbuf to buf and save a few things
        aucmd_prepbuf(&aco, newbuf);
  
!       // Need to set the filename for autocommands.
!       (void)setfname(curbuf, fname, NULL, FALSE);
! 
!       // Create swap file now to avoid the ATTENTION message.
!       check_need_swap(TRUE);
  
!       // Remove the "dummy" flag, otherwise autocommands may not
!       // work.
!       curbuf->b_flags &= ~BF_DUMMY;
! 
!       newbuf_to_wipe.br_buf = NULL;
!       readfile_result = readfile(fname, NULL,
!                   (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
!                   NULL, READ_NEW | READ_DUMMY);
!       --newbuf->b_locked;
!       if (readfile_result == OK
!               && !got_int
!               && !(curbuf->b_flags & BF_NEW))
!       {
!           failed = FALSE;
!           if (curbuf != newbuf)
            {
!               // Bloody autocommands changed the buffer!  Can happen when
!               // using netrw and editing a remote file.  Use the current
!               // buffer instead, delete the dummy one after restoring the
!               // window stuff.
!               set_bufref(&newbuf_to_wipe, newbuf);
!               newbuf = curbuf;
            }
        }
  
-       // restore curwin/curbuf and a few other things
-       aucmd_restbuf(&aco);
        if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
            wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
  
--- 6604,6646 ----
  
        // set curwin/curbuf to buf and save a few things
        aucmd_prepbuf(&aco, newbuf);
+       if (curbuf == newbuf)
+       {
+           // Need to set the filename for autocommands.
+           (void)setfname(curbuf, fname, NULL, FALSE);
  
!           // Create swap file now to avoid the ATTENTION message.
!           check_need_swap(TRUE);
  
!           // Remove the "dummy" flag, otherwise autocommands may not
!           // work.
!           curbuf->b_flags &= ~BF_DUMMY;
! 
!           newbuf_to_wipe.br_buf = NULL;
!           readfile_result = readfile(fname, NULL,
!                       (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
!                       NULL, READ_NEW | READ_DUMMY);
!           --newbuf->b_locked;
!           if (readfile_result == OK
!                   && !got_int
!                   && !(curbuf->b_flags & BF_NEW))
            {
!               failed = FALSE;
!               if (curbuf != newbuf)
!               {
!                   // Bloody autocommands changed the buffer!  Can happen when
!                   // using netrw and editing a remote file.  Use the current
!                   // buffer instead, delete the dummy one after restoring the
!                   // window stuff.
!                   set_bufref(&newbuf_to_wipe, newbuf);
!                   newbuf = curbuf;
!               }
            }
+ 
+           // restore curwin/curbuf and a few other things
+           aucmd_restbuf(&aco);
        }
  
        if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
            wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
  
*** ../vim-9.0.0964/src/term.c  2022-11-26 19:16:44.186717893 +0000
--- src/term.c  2022-11-28 18:28:32.775476943 +0000
***************
*** 2232,2241 ****
                if (curbuf->b_ml.ml_mfp != NULL)
                {
                    aucmd_prepbuf(&aco, buf);
!                   apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
                                                                      curbuf);
!                   // restore curwin/curbuf and a few other things
!                   aucmd_restbuf(&aco);
                }
            }
        }
--- 2232,2244 ----
                if (curbuf->b_ml.ml_mfp != NULL)
                {
                    aucmd_prepbuf(&aco, buf);
!                   if (curbuf == buf)
!                   {
!                       apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
                                                                      curbuf);
!                       // restore curwin/curbuf and a few other things
!                       aucmd_restbuf(&aco);
!                   }
                }
            }
        }
*** ../vim-9.0.0964/src/if_perl.xs      2022-11-14 15:31:04.041587447 +0000
--- src/if_perl.xs      2022-11-28 18:32:20.335223624 +0000
***************
*** 1869,1886 ****
            {
                aco_save_T      aco;
  
!               /* set curwin/curbuf for "vimbuf" and save some things */
                aucmd_prepbuf(&aco, vimbuf);
! 
!               if (u_savesub(lnum) == OK)
                {
!                   ml_replace(lnum, (char_u *)line, TRUE);
!                   changed_bytes(lnum, 0);
!               }
  
!               /* restore curwin/curbuf and a few other things */
!               aucmd_restbuf(&aco);
!               /* Careful: autocommands may have made "vimbuf" invalid! */
            }
        }
      }
--- 1869,1889 ----
            {
                aco_save_T      aco;
  
!               /* Set curwin/curbuf for "vimbuf" and save some things. */
                aucmd_prepbuf(&aco, vimbuf);
!               if (curbuf == vimbuf)
                {
!                   /* Only when a window was found. */
!                   if (u_savesub(lnum) == OK)
!                   {
!                       ml_replace(lnum, (char_u *)line, TRUE);
!                       changed_bytes(lnum, 0);
!                   }
  
!                   /* restore curwin/curbuf and a few other things */
!                   aucmd_restbuf(&aco);
!                   /* Careful: autocommands may have made "vimbuf" invalid! */
!               }
            }
        }
      }
***************
*** 1921,1938 ****
  
                    /* set curwin/curbuf for "vimbuf" and save some things */
                    aucmd_prepbuf(&aco, vimbuf);
! 
!                   if (u_savedel(lnum, 1) == OK)
                    {
!                       ml_delete(lnum);
!                       check_cursor();
!                       deleted_lines_mark(lnum, 1L);
                    }
  
-                   /* restore curwin/curbuf and a few other things */
-                   aucmd_restbuf(&aco);
-                   /* Careful: autocommands may have made "vimbuf" invalid! */
- 
                    update_curbuf(UPD_VALID);
                }
            }
--- 1924,1945 ----
  
                    /* set curwin/curbuf for "vimbuf" and save some things */
                    aucmd_prepbuf(&aco, vimbuf);
!                   if (curbuf == vimbuf)
                    {
!                       /* Only when a window was found. */
!                       if (u_savedel(lnum, 1) == OK)
!                       {
!                           ml_delete(lnum);
!                           check_cursor();
!                           deleted_lines_mark(lnum, 1L);
!                       }
! 
!                       /* restore curwin/curbuf and a few other things */
!                       aucmd_restbuf(&aco);
!                       /* Careful: autocommands may have made "vimbuf"
!                        * invalid! */
                    }
  
                    update_curbuf(UPD_VALID);
                }
            }
***************
*** 1963,1978 ****
  
                /* set curwin/curbuf for "vimbuf" and save some things */
                aucmd_prepbuf(&aco, vimbuf);
! 
!               if (u_inssub(lnum + 1) == OK)
                {
!                   ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
!                   appended_lines_mark(lnum, 1L);
!               }
  
!               /* restore curwin/curbuf and a few other things */
!               aucmd_restbuf(&aco);
!               /* Careful: autocommands may have made "vimbuf" invalid! */
  
                update_curbuf(UPD_VALID);
            }
--- 1970,1988 ----
  
                /* set curwin/curbuf for "vimbuf" and save some things */
                aucmd_prepbuf(&aco, vimbuf);
!               if (curbuf == vimbuf)
                {
!                   /* Only when a window for "vimbuf" was found. */
!                   if (u_inssub(lnum + 1) == OK)
!                   {
!                       ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
!                       appended_lines_mark(lnum, 1L);
!                   }
  
!                   /* restore curwin/curbuf and a few other things */
!                   aucmd_restbuf(&aco);
!                   /* Careful: autocommands may have made "vimbuf" invalid! */
!                   }
  
                update_curbuf(UPD_VALID);
            }
*** ../vim-9.0.0964/src/if_py_both.h    2022-11-25 16:31:46.968606662 +0000
--- src/if_py_both.h    2022-11-28 18:33:06.435179423 +0000
***************
*** 5283,5290 ****
        VimTryStart();
        // Using aucmd_*: autocommands will be executed by rename_buffer
        aucmd_prepbuf(&aco, self->buf);
!       ren_ret = rename_buffer(val);
!       aucmd_restbuf(&aco);
        Py_XDECREF(todecref);
        if (VimTryEnd())
            return -1;
--- 5283,5293 ----
        VimTryStart();
        // Using aucmd_*: autocommands will be executed by rename_buffer
        aucmd_prepbuf(&aco, self->buf);
!       if (curbuf == self->buf)
!       {
!           ren_ret = rename_buffer(val);
!           aucmd_restbuf(&aco);
!       }
        Py_XDECREF(todecref);
        if (VimTryEnd())
            return -1;
*** ../vim-9.0.0964/src/testdir/test_autocmd.vim        2022-11-25 
16:31:46.972606656 +0000
--- src/testdir/test_autocmd.vim        2022-11-28 17:06:57.506202897 +0000
***************
*** 4068,4071 ****
--- 4068,4094 ----
    call delete('Xerr')
  endfunc
  
+ " This was crashing because there was only one window to execute autocommands
+ " in.
+ func Test_autocmd_nested_setbufvar()
+   CheckFeature python3
+ 
+   set hidden
+   edit Xaaa
+   edit Xbbb
+   call setline(1, 'bar')
+   enew
+   au BufWriteCmd Xbbb ++nested call setbufvar('Xaaa', '&ft', 'foo') | bw! Xaaa
+   au FileType foo call py3eval('vim.current.buffer.options["cindent"]')
+   wall
+ 
+   au! BufWriteCmd
+   au! FileType foo
+   set nohidden
+   call delete('Xaaa')
+   call delete('Xbbb')
+   %bwipe!
+ endfunc
+ 
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-9.0.0964/src/version.c       2022-11-28 16:49:18.446868480 +0000
--- src/version.c       2022-11-28 17:03:08.590102217 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     965,
  /**/

-- 
Living in Hollywood is like living in a bowl of granola.  What ain't
fruits and nuts is flakes.

 /// 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/20221128185220.DB8E51C0A61%40moolenaar.net.

Raspunde prin e-mail lui