]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0965: using one window for executing autocommands is insufficient v9.0.0965
authorBram Moolenaar <Bram@vim.org>
Mon, 28 Nov 2022 18:51:43 +0000 (18:51 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 28 Nov 2022 18:51:43 +0000 (18:51 +0000)
Problem:    Using one window for executing autocommands is insufficient.
Solution:   Use up to five windows for executing autocommands.

28 files changed:
src/autocmd.c
src/buffer.c
src/bufwrite.c
src/channel.c
src/diff.c
src/eval.c
src/evalbuffer.c
src/evalvars.c
src/evalwindow.c
src/ex_cmds2.c
src/ex_docmd.c
src/fileio.c
src/globals.h
src/if_perl.xs
src/if_py_both.h
src/if_ruby.c
src/main.c
src/os_unix.c
src/os_win32.c
src/proto/autocmd.pro
src/quickfix.c
src/screen.c
src/structs.h
src/term.c
src/terminal.c
src/testdir/test_autocmd.vim
src/version.c
src/window.c

index 11dc707d74d2775e5a4fee16d83bf10a57f8998e..3a081281333c9fbac987a7e55c71655c866b7fa2 100644 (file)
@@ -629,27 +629,51 @@ do_augroup(char_u *arg, int del_group)
     }
 }
 
+    void
+autocmd_init(void)
+{
+    CLEAR_FIELD(aucmd_win);
+}
+
 #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)
+    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.
@@ -1438,8 +1462,16 @@ ex_doautoall(exarg_T *eap)
        if (buf->b_ml.ml_mfp == NULL || buf == curbuf)
            continue;
 
-       // find a window for this buffer and save some values
+       // 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,7 +1481,7 @@ ex_doautoall(exarg_T *eap)
            // 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);
+           do_modelines(is_aucmd_win(curwin) ? OPT_NOWIN : 0);
 
        // restore the current window
        aucmd_restbuf(&aco);
@@ -1490,8 +1522,9 @@ check_nomodeline(char_u **argp)
 /*
  * 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".
+ * 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,18 +1545,29 @@ aucmd_prepbuf(
            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)
+    // Allocate a window when needed.
+    win_T *auc_win = NULL;
+    int auc_idx = AUCMD_WIN_COUNT;
+    if (win == NULL)
     {
-       aucmd_win = win_alloc_popup_win();
-       if (aucmd_win == NULL)
-           win = curwin;
+       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;
     }
-    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;
@@ -1533,24 +1577,23 @@ aucmd_prepbuf(
        // 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;
+       aco->use_aucmd_win_idx = -1;
        curwin = win;
     }
     else
     {
-       // There is no window for "buf", use "aucmd_win".  To minimize the side
+       // 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 = TRUE;
-       aucmd_win_used = TRUE;
+       aco->use_aucmd_win_idx = auc_idx;
 
-       win_init_popup_win(aucmd_win, buf);
+       win_init_popup_win(auc_win, buf);
 
        aco->globaldir = globaldir;
        globaldir = NULL;
 
-       // Split the current window, put the aucmd_win in the upper half.
+       // 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,7 +1608,7 @@ aucmd_prepbuf(
 
        // no redrawing and don't set the window title
        ++RedrawingDisabled;
-       (void)win_split_ins(0, WSP_TOP, aucmd_win, 0);
+       (void)win_split_ins(0, WSP_TOP, auc_win, 0);
        --RedrawingDisabled;
        (void)win_comp_pos();   // recompute window positions
        p_ea = save_ea;
@@ -1573,7 +1616,7 @@ aucmd_prepbuf(
        p_acd = save_acd;
 #endif
        unblock_autocmds();
-       curwin = aucmd_win;
+       curwin = auc_win;
     }
     curbuf = buf;
     aco->new_curwin_id = curwin->w_id;
@@ -1595,24 +1638,26 @@ aucmd_restbuf(
     int            dummy;
     win_T   *save_curwin;
 
-    if (aco->use_aucmd_win)
+    if (aco->use_aucmd_win_idx >= 0)
     {
+       win_T *awp = aucmd_win[aco->use_aucmd_win_idx].auc_win;
+
        --curbuf->b_nwindows;
-       // Find "aucmd_win", it can't be closed, but it may be in another tab
+       // Find "awp", it can't be closed, but it may be in another tab
        // page. Do not trigger autocommands here.
        block_autocmds();
-       if (curwin != aucmd_win)
+       if (curwin != awp)
        {
            tabpage_T   *tp;
            win_T       *wp;
 
            FOR_ALL_TAB_WINDOWS(tp, wp)
            {
-               if (wp == aucmd_win)
+               if (wp == awp)
                {
                    if (tp != curtab)
                        goto_tabpage_tp(tp, TRUE, TRUE);
-                   win_goto(aucmd_win);
+                   win_goto(awp);
                    goto win_found;
                }
            }
@@ -1622,7 +1667,7 @@ win_found:
        // Remove the window and frame from the tree of frames.
        (void)winframe_remove(curwin, &dummy, NULL);
        win_remove(curwin, NULL);
-       aucmd_win_used = FALSE;
+       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,8 +1691,8 @@ win_found:
 #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
+       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,11 +1709,9 @@ win_found:
 #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);
+           // 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
index f99da25e888c4b2bd15accbfc3182fca2e0c8c3e..eba5dd2d579233806c8443b3d76ec92d731fb23c 100644 (file)
@@ -150,11 +150,15 @@ buffer_ensure_loaded(buf_T *buf)
     {
        aco_save_T      aco;
 
+       // Make sure the buffer is in a window.  If not then skip it.
        aucmd_prepbuf(&aco, buf);
-       if (swap_exists_action != SEA_READONLY)
-           swap_exists_action = SEA_NONE;
-       open_buffer(FALSE, NULL, 0);
-       aucmd_restbuf(&aco);
+       if (curbuf == buf)
+       {
+           if (swap_exists_action != SEA_READONLY)
+               swap_exists_action = SEA_NONE;
+           open_buffer(FALSE, NULL, 0);
+           aucmd_restbuf(&aco);
+       }
     }
 }
 #endif
@@ -361,21 +365,26 @@ open_buffer(
        {
            aco_save_T  aco;
 
-           // Go to the buffer that was opened.
+           // 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);
-           do_modelines(0);
-           curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
+           if (curbuf == old_curbuf.br_buf)
+           {
+               do_modelines(0);
+               curbuf->b_flags &= ~(BF_CHECK_RO | BF_NEVERLOADED);
 
-           if ((flags & READ_NOWINENTER) == 0)
+               if ((flags & READ_NOWINENTER) == 0)
 #ifdef FEAT_EVAL
-               apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE,
-                                                             curbuf, &retval);
+                   apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL,
+                                                      FALSE, curbuf, &retval);
 #else
-               apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
+                   apply_autocmds(EVENT_BUFWINENTER, NULL, NULL,
+                                                               FALSE, curbuf);
 #endif
 
-           // restore curwin/curbuf and a few other things
-           aucmd_restbuf(&aco);
+               // restore curwin/curbuf and a few other things
+               aucmd_restbuf(&aco);
+           }
        }
     }
 
@@ -5942,8 +5951,14 @@ buf_contents_changed(buf_T *buf)
        return TRUE;
     }
 
-    // set curwin/curbuf to buf and save a few things
+    // 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,
index 18448dcde47d5d87662d38fdcbcb68367b9a17b5..03a83b569a44fac079f1b030374b61dc322b977c 100644 (file)
@@ -802,8 +802,15 @@ buf_write(
        if (fname == buf->b_sfname)
            buf_fname_s = TRUE;
 
-       // set curwin/curbuf to buf and save a few things
+       // 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,23 +2599,26 @@ nofail:
 
        // 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);
 
-       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);
+           // restore curwin/curbuf and a few other things
+           aucmd_restbuf(&aco);
+       }
 
 #ifdef FEAT_EVAL
        if (aborting())     // autocmds may abort script processing
index 08b1ac86702186a79ea1c0a6d3bec918ce6cf077..4e6457546ae30d794e0639148595a2b63b2d8a4e 100644 (file)
@@ -2872,8 +2872,14 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
 
     buffer->b_p_ma = TRUE;
 
-    // set curbuf to be our buf, temporarily
+    // 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
index 80f1eb3368410691fd39b9e164ae916b79bb7e5c..88e3ec45337affda4879aabf3f543f9e64099c46 100644 (file)
@@ -2786,8 +2786,12 @@ ex_diffgetput(exarg_T *eap)
        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
+       // 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
index 84a7b262031674a5ad7585656d7ca655dcedc836..c43158a29a32abfacdb1fd8078ed5c2cfaf03b17 100644 (file)
@@ -5084,9 +5084,10 @@ garbage_collect(int testing)
     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);
+    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,
index 82a10d675c9279792d5bf98c8cb96d90c23a76af..e611c52e4ccb27ea6f99ddf95c30cfbddb75c659 100644 (file)
@@ -136,6 +136,8 @@ typedef struct {
  *
  * 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,7 +158,8 @@ change_other_buffer_prepare(cob_T *cob, buf_T *buf)
        // 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;
+       if (curbuf == buf)
+           cob->cob_using_aco = TRUE;
     }
 }
 
index 28516c172b04be60719eec54f920f2c7a7cd9a08..20223c8fe8d40867ea9189b68b4461cdc378167c 100644 (file)
@@ -4761,13 +4761,16 @@ f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED)
        {
            aco_save_T  aco;
 
-           // set curbuf to be our buf, temporarily
+           // 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);
 
-           set_option_from_tv(varname + 1, varp);
-
-           // reset notion of buffer
-           aucmd_restbuf(&aco);
+               // reset notion of buffer
+               aucmd_restbuf(&aco);
+           }
        }
        else
        {
index 3578669ae89bfd2f4cd615e8da735f3e7c65191e..f8c0c7acfd9cd4fa8036e15a008ebbc2cd95bf84 100644 (file)
@@ -1064,7 +1064,7 @@ f_win_gettype(typval_T *argvars, typval_T *rettv)
            return;
        }
     }
-    if (wp == aucmd_win)
+    if (is_aucmd_win(wp))
        rettv->vval.v_string = vim_strsave((char_u *)"autocmd");
 #if defined(FEAT_QUICKFIX)
     else if (wp->w_p_pvw)
index c13d354bc1c32121d405921c7661e74226ad812b..9c00b80b7a1f7320123a524f0fdca61623db3a62 100644 (file)
@@ -705,9 +705,12 @@ ex_listdo(exarg_T *eap)
                else
                {
                    aucmd_prepbuf(&aco, buf);
-                   apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
+                   if (curbuf == buf)
+                   {
+                       apply_autocmds(EVENT_SYNTAX, buf->b_p_syn,
                                                      buf->b_fname, TRUE, buf);
-                   aucmd_restbuf(&aco);
+                       aucmd_restbuf(&aco);
+                   }
                }
 
                // start over, in case autocommands messed things up.
index bb4a8316339bd3456ac1f0b0c94db8c0cde1f47e..218b7edd9b12a36199a4301394a77fcafea9805f 100644 (file)
@@ -6050,7 +6050,7 @@ ex_win_close(
     buf_T      *buf = win->w_buffer;
 
     // Never close the autocommand window.
-    if (win == aucmd_win)
+    if (is_aucmd_win(win))
     {
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return;
index 9916de8a63e714e9fe2cf9928f456da0868b981c..1ee08e21edba8111051f359572ad4dcba265f279 100644 (file)
@@ -4369,8 +4369,14 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options)
     int                flags = READ_NEW;
     int                prepped = OK;
 
-    // set curwin/curbuf for "buf" and save some things
+    // 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.
index d9207b940f70032b586271918b9843e9d53d817d..eadff43c990a809fe3efbbfdd90a041cf72d4264 100644 (file)
@@ -977,8 +977,18 @@ EXTERN win_T       *prevwin INIT(= NULL);  // previous window
 
 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
+// 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
index 34315be7196371e74cac6a64d897a7180dea4a8c..c69ed9ef1fb9b00f38d9d1ded06a8b17d69f7b8f 100644 (file)
@@ -1869,18 +1869,21 @@ Set(vimbuf, ...)
            {
                aco_save_T      aco;
 
-               /* set curwin/curbuf for "vimbuf" and save some things */
+               /* Set curwin/curbuf for "vimbuf" and save some things. */
                aucmd_prepbuf(&aco, vimbuf);
-
-               if (u_savesub(lnum) == OK)
+               if (curbuf == vimbuf)
                {
-                   ml_replace(lnum, (char_u *)line, TRUE);
-                   changed_bytes(lnum, 0);
-               }
+                   /* 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! */
+                   /* restore curwin/curbuf and a few other things */
+                   aucmd_restbuf(&aco);
+                   /* Careful: autocommands may have made "vimbuf" invalid! */
+               }
            }
        }
     }
@@ -1921,18 +1924,22 @@ Delete(vimbuf, ...)
 
                    /* set curwin/curbuf for "vimbuf" and save some things */
                    aucmd_prepbuf(&aco, vimbuf);
-
-                   if (u_savedel(lnum, 1) == OK)
+                   if (curbuf == vimbuf)
                    {
-                       ml_delete(lnum);
-                       check_cursor();
-                       deleted_lines_mark(lnum, 1L);
+                       /* 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! */
                    }
 
-                   /* restore curwin/curbuf and a few other things */
-                   aucmd_restbuf(&aco);
-                   /* Careful: autocommands may have made "vimbuf" invalid! */
-
                    update_curbuf(UPD_VALID);
                }
            }
@@ -1963,16 +1970,19 @@ Append(vimbuf, ...)
 
                /* set curwin/curbuf for "vimbuf" and save some things */
                aucmd_prepbuf(&aco, vimbuf);
-
-               if (u_inssub(lnum + 1) == OK)
+               if (curbuf == vimbuf)
                {
-                   ml_append(lnum, (char_u *)line, (colnr_T)0, FALSE);
-                   appended_lines_mark(lnum, 1L);
-               }
+                   /* 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! */
+                   /* restore curwin/curbuf and a few other things */
+                   aucmd_restbuf(&aco);
+                   /* Careful: autocommands may have made "vimbuf" invalid! */
+                   }
 
                update_curbuf(UPD_VALID);
            }
index d6cb13b831b3ff864674b9b4f9874cc772115010..0cde18d0512b50f0296cab4bcd8c6ae145ad195d 100644 (file)
@@ -5283,8 +5283,11 @@ BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
        VimTryStart();
        // Using aucmd_*: autocommands will be executed by rename_buffer
        aucmd_prepbuf(&aco, self->buf);
-       ren_ret = rename_buffer(val);
-       aucmd_restbuf(&aco);
+       if (curbuf == self->buf)
+       {
+           ren_ret = rename_buffer(val);
+           aucmd_restbuf(&aco);
+       }
        Py_XDECREF(todecref);
        if (VimTryEnd())
            return -1;
index 51cfff13de1ba8597c4bbad1e48cc1c592fe8fa8..b157bb83d6d0c1e16f11ef7cb1ee20ed04681091 100644 (file)
@@ -1371,21 +1371,24 @@ set_buffer_line(buf_T *buf, linenr_T n, VALUE str)
 
     if (n > 0 && n <= buf->b_ml.ml_line_count && line != NULL)
     {
-       // set curwin/curbuf for "buf" and save some things
+       // Set curwin/curbuf for "buf" and save some things.
        aucmd_prepbuf(&aco, buf);
-
-       if (u_savesub(n) == OK)
+       if (curbuf == buf)
        {
-           ml_replace(n, (char_u *)line, TRUE);
-           changed();
+           // 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
+               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!
+           // restore curwin/curbuf and a few other things
+           aucmd_restbuf(&aco);
+           // Careful: autocommands may have made "buf" invalid!
+       }
 
        update_curbuf(UPD_NOT_VALID);
     }
@@ -1415,23 +1418,26 @@ buffer_delete(VALUE self, VALUE num)
 
     if (n > 0 && n <= buf->b_ml.ml_line_count)
     {
-       // set curwin/curbuf for "buf" and save some things
+       // Set curwin/curbuf for "buf" and save some things.
        aucmd_prepbuf(&aco, buf);
-
-       if (u_savedel(n, 1) == OK)
+       if (curbuf == buf)
        {
-           ml_delete(n);
+           // 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);
+               // Changes to non-active buffers should properly refresh
+               //   SegPhault - 01/09/05
+               deleted_lines_mark(n, 1L);
 
-           changed();
-       }
+               changed();
+           }
 
-       // restore curwin/curbuf and a few other things
-       aucmd_restbuf(&aco);
-       // Careful: autocommands may have made "buf" invalid!
+           // restore curwin/curbuf and a few other things
+           aucmd_restbuf(&aco);
+           // Careful: autocommands may have made "buf" invalid!
+       }
 
        update_curbuf(UPD_NOT_VALID);
     }
@@ -1458,21 +1464,24 @@ buffer_append(VALUE self, VALUE num, VALUE str)
     {
        // set curwin/curbuf for "buf" and save some things
        aucmd_prepbuf(&aco, buf);
-
-       if (u_inssub(n + 1) == OK)
+       if (curbuf == buf)
        {
-           ml_append(n, (char_u *) line, (colnr_T) 0, FALSE);
+           // 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);
+               //  Changes to non-active buffers should properly refresh screen
+               //    SegPhault - 12/20/04
+               appended_lines_mark(n, 1L);
 
-           changed();
-       }
+               changed();
+           }
 
-       // restore curwin/curbuf and a few other things
-       aucmd_restbuf(&aco);
-       // Careful: autocommands may have made "buf" invalid!
+           // restore curwin/curbuf and a few other things
+           aucmd_restbuf(&aco);
+           // Careful: autocommands may have made "buf" invalid!
+       }
 
        update_curbuf(UPD_NOT_VALID);
     }
index ca28eca7232d6f65d5aadf1a79f624f1af6b74c5..db81a3f3cffd36f7473d0f27bd61140da64657e7 100644 (file)
@@ -123,6 +123,8 @@ main
 #endif
     params.window_count = -1;
 
+    autocmd_init();
+
 #ifdef FEAT_RUBY
     {
        int ruby_stack_start;
index fd6d35fedcfce1860fa2ccaf6f2a4abfe831f3cf..c43d9c172da8fab7c612266ff60d94b71b02de60 100644 (file)
@@ -4490,27 +4490,30 @@ mch_call_shell_terminal(
 
     // Find a window to make "buf" curbuf.
     aucmd_prepbuf(&aco, buf);
-
-    clear_oparg(&oa);
-    while (term_use_loop())
+    if (curbuf == buf)
     {
-       if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
+       // Only when managed to find a window for "buf",
+       clear_oparg(&oa);
+       while (term_use_loop())
        {
-           // 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)
+           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);
        }
-       else
-           normal_cmd(&oa, TRUE);
-    }
-    retval = job->jv_exitval;
-    ch_log(NULL, "system command finished");
+       retval = job->jv_exitval;
+       ch_log(NULL, "system command finished");
 
-    job_unref(job);
+       job_unref(job);
 
-    // restore curwin/curbuf and a few other things
-    aucmd_restbuf(&aco);
+       // 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.
index 4c97b31002a51b7c2a1182ca8365304667800ccf..acbc4cb7d067b2b85f6af0df431f939af2b68d5d 100644 (file)
@@ -4878,27 +4878,30 @@ mch_call_shell_terminal(
 
     // Find a window to make "buf" curbuf.
     aucmd_prepbuf(&aco, buf);
-
-    clear_oparg(&oa);
-    while (term_use_loop())
+    if (curbuf == buf)
     {
-       if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
+       // Only do this when a window was found for "buf".
+       clear_oparg(&oa);
+       while (term_use_loop())
        {
-           // 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)
+           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);
        }
-       else
-           normal_cmd(&oa, TRUE);
-    }
-    retval = job->jv_exitval;
-    ch_log(NULL, "system command finished");
+       retval = job->jv_exitval;
+       ch_log(NULL, "system command finished");
 
-    job_unref(job);
+       job_unref(job);
 
-    // restore curwin/curbuf and a few other things
-    aucmd_restbuf(&aco);
+       // 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);
index 1f55f2d27d46b34cc8105457b58efb0c59c51dfb..0b61989c06532ba6092973daedfa11b614c21132 100644 (file)
@@ -2,7 +2,9 @@
 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);
index 403c397d53f9e9d3576c8eb173e1a56ac0fd0890..e8716d26809a0b1040429279d352584c20dfb4e2 100644 (file)
@@ -4598,21 +4598,29 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
        // 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"
+       }
 
-       qf_update_win_titlevar(qi);
+       if (do_fill)
+       {
+           qf_update_win_titlevar(qi);
 
-       qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
-       ++CHANGEDTICK(buf);
+           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);
+           if (old_last == NULL)
+           {
+               (void)qf_win_pos_update(qi, 0);
 
-           // restore curwin/curbuf and a few other things
-           aucmd_restbuf(&aco);
+               // restore curwin/curbuf and a few other things
+               aucmd_restbuf(&aco);
+           }
        }
 
        // Only redraw when added lines are visible.  This avoids flickering
@@ -6395,12 +6403,15 @@ vgr_process_files(
                    // 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,
+                       apply_autocmds(EVENT_FILETYPE, buf->b_p_ft,
                                                     buf->b_fname, TRUE, buf);
 #endif
-                   do_modelines(OPT_NOWIN);
-                   aucmd_restbuf(&aco);
+                       do_modelines(OPT_NOWIN);
+                       aucmd_restbuf(&aco);
+                   }
                }
            }
        }
@@ -6593,40 +6604,43 @@ load_dummy_buffer(
 
        // 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))
+       if (curbuf == newbuf)
        {
-           failed = FALSE;
-           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))
            {
-               // 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;
+               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);
        }
 
-       // 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);
 
index 47288118c551f2f1f370f2a692f3b6e3f488e857..7c3a6d7b0660eaf8653ecb5d7a281b5c6f326ada 100644 (file)
@@ -2369,7 +2369,6 @@ screenalloc(int doclear)
     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;
@@ -2438,8 +2437,9 @@ retry:
      */
     FOR_ALL_TAB_WINDOWS(tp, wp)
        win_free_lsize(wp);
-    if (aucmd_win != NULL)
-       win_free_lsize(aucmd_win);
+    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,7 +2455,7 @@ retry:
     if (enc_utf8)
     {
        new_ScreenLinesUC = LALLOC_MULT(u8char_T, (Rows + 1) * Columns);
-       for (i = 0; i < p_mco; ++i)
+       for (int i = 0; i < p_mco; ++i)
            new_ScreenLinesC[i] = LALLOC_CLEAR_MULT(u8char_T,
                                                         (Rows + 1) * Columns);
     }
@@ -2482,9 +2482,14 @@ retry:
            goto give_up;
        }
     }
-    if (aucmd_win != NULL && aucmd_win->w_lines == NULL
-                                       && win_alloc_lines(aucmd_win) == FAIL)
-       outofmem = TRUE;
+    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,11 +2510,15 @@ retry:
 
 give_up:
 
-    for (i = 0; i < p_mco; ++i)
+    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 || i != p_mco))
+           || (enc_utf8 && (new_ScreenLinesUC == NULL || found_null))
            || (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
            || new_ScreenAttrs == NULL
            || new_ScreenCols == NULL
@@ -2534,7 +2543,7 @@ give_up:
        }
        VIM_CLEAR(new_ScreenLines);
        VIM_CLEAR(new_ScreenLinesUC);
-       for (i = 0; i < p_mco; ++i)
+       for (int i = 0; i < p_mco; ++i)
            VIM_CLEAR(new_ScreenLinesC[i]);
        VIM_CLEAR(new_ScreenLines2);
        VIM_CLEAR(new_ScreenAttrs);
@@ -2571,7 +2580,7 @@ give_up:
                {
                    (void)vim_memset(new_ScreenLinesUC + new_row * Columns,
                                       0, (size_t)Columns * sizeof(u8char_T));
-                   for (i = 0; i < p_mco; ++i)
+                   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,7 +2612,7 @@ give_up:
                        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)
+                       for (int i = 0; i < p_mco; ++i)
                            mch_memmove(new_ScreenLinesC[i]
                                                    + new_LineOffset[new_row],
                                ScreenLinesC[i] + LineOffset[old_row],
@@ -2636,7 +2645,7 @@ give_up:
     // NOTE: this may result in all pointers to become NULL.
     ScreenLines = new_ScreenLines;
     ScreenLinesUC = new_ScreenLinesUC;
-    for (i = 0; i < p_mco; ++i)
+    for (int i = 0; i < p_mco; ++i)
        ScreenLinesC[i] = new_ScreenLinesC[i];
     Screen_mco = p_mco;
     ScreenLines2 = new_ScreenLines2;
index f57fb85618553941b81c0eca20d9df2b7eaf9253..824de455689a963a068fc955cd348b16e0f113a7 100644 (file)
@@ -4160,7 +4160,7 @@ typedef int vimmenu_T;
 typedef struct
 {
     buf_T      *save_curbuf;       // saved curbuf
-    int                use_aucmd_win;      // using aucmd_win
+    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
index 237a3258ae68d142fbe46a856146d15be1edf476..b8869f9be86649727d1ed4a06f72b3622d4a284e 100644 (file)
@@ -2232,10 +2232,13 @@ set_termname(char_u *term)
                if (curbuf->b_ml.ml_mfp != NULL)
                {
                    aucmd_prepbuf(&aco, buf);
-                   apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
+                   if (curbuf == buf)
+                   {
+                       apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE,
                                                                      curbuf);
-                   // restore curwin/curbuf and a few other things
-                   aucmd_restbuf(&aco);
+                       // restore curwin/curbuf and a few other things
+                       aucmd_restbuf(&aco);
+                   }
                }
            }
        }
index d300c59a24d92ee00a14fd5f9965140fff324741..18f9c626026ff025cc5e50fa65c735c10c25e31b 100644 (file)
@@ -3560,15 +3560,18 @@ term_after_channel_closed(term_T *term)
            // ++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);
+           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);
index a0d83ecf355fead3a88db564dadb4772eb585fa8..593e56819c7a0a8547686571e78bbd924d908655 100644 (file)
@@ -4068,4 +4068,27 @@ func Test_autocmd_split_dummy()
   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
index e53ad971f0f0978a4492f3e03c7d7428d23cd124..8d51ea702a7d80449951b32abee3ac392da42e14 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    965,
 /**/
     964,
 /**/
index 869c985358a82be40046e24061654b8e695a35d9..24f25d65b78f3fbd272335221701b13129bd2479 100644 (file)
@@ -1362,7 +1362,7 @@ win_split_ins(
        win_equal(wp, TRUE,
                (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
                : dir == 'h' ? 'b' : 'v');
-    else if (*p_spk != 'c' && wp != aucmd_win)
+    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,7 +1962,7 @@ win_equal(
     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)
+    if (*p_spk != 'c' && !is_aucmd_win(next_curwin))
        win_fix_scroll(TRUE);
 }
 
@@ -2426,7 +2426,7 @@ close_windows(
 
 /*
  * Return TRUE if the current window is the only window that exists (ignoring
- * "aucmd_win").
+ * "aucmd_win[]").
  * Returns FALSE if there is a window, possibly in another tab page.
  */
     static int
@@ -2436,7 +2436,7 @@ last_window(void)
 }
 
 /*
- * Return TRUE if there is only one window other than "aucmd_win" in the
+ * Return TRUE if there is only one window other than "aucmd_win[]" in the
  * current tab page.
  */
     int
@@ -2447,7 +2447,7 @@ one_window(void)
 
     FOR_ALL_WINDOWS(wp)
     {
-       if (wp != aucmd_win)
+       if (!is_aucmd_win(wp))
        {
            if (seen_one)
                return FALSE;
@@ -2588,7 +2588,7 @@ win_close(win_T *win, int free_buf)
        emsg(_(e_cannot_close_autocmd_or_popup_window));
        return FAIL;
     }
-    if ((firstwin == aucmd_win || lastwin == aucmd_win) && one_window())
+    if ((is_aucmd_win(firstwin) || is_aucmd_win(lastwin)) && one_window())
     {
        emsg(_(e_cannot_close_window_only_autocmd_window_would_remain));
        return FAIL;
@@ -3292,11 +3292,12 @@ win_free_all(void)
     while (first_tabpage->tp_next != NULL)
        tabpage_close(TRUE);
 
-    if (aucmd_win != NULL)
-    {
-       (void)win_free_mem(aucmd_win, &dummy, NULL);
-       aucmd_win = NULL;
-    }
+    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,7 +5664,7 @@ win_free(
     int
 win_unlisted(win_T *wp)
 {
-    return wp == aucmd_win || WIN_IS_POPUP(wp);
+    return is_aucmd_win(wp) || WIN_IS_POPUP(wp);
 }
 
 #if defined(FEAT_PROP_POPUP) || defined(PROTO)
@@ -7257,7 +7258,7 @@ only_one_window(void)
 # ifdef FEAT_QUICKFIX
                    || wp->w_p_pvw
 # endif
-            ) || wp == curwin) && wp != aucmd_win)
+            ) || wp == curwin) && !is_aucmd_win(wp))
            ++count;
     return (count <= 1);
 }