]> granicus.if.org Git - vim/commitdiff
patch 7.4.2312 v7.4.2312
authorBram Moolenaar <Bram@vim.org>
Sat, 3 Sep 2016 14:29:04 +0000 (16:29 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 3 Sep 2016 14:29:04 +0000 (16:29 +0200)
Problem:    Crash when autocommand moves to another tab. (Dominique Pelle)
Solution:   When navigating to another window halfway the :edit command go
            back to the right window.

src/buffer.c
src/ex_cmds.c
src/ex_docmd.c
src/ex_getln.c
src/proto/ex_getln.pro
src/testdir/test_tabpage.vim
src/version.c
src/window.c

index 4841f9ab2ddefcbb01fb5f6a623eea7f05ef1cd5..9270c39fc9f038fa36b13e8bcdc69283b2226980 100644 (file)
@@ -666,7 +666,8 @@ buf_clear_file(buf_T *buf)
 
 /*
  * buf_freeall() - free all things allocated for a buffer that are related to
- * the file.  flags:
+ * the file.  Careful: get here with "curwin" NULL when exiting.
+ * flags:
  * BFA_DEL       buffer is going to be deleted
  * BFA_WIPE      buffer is going to be wiped out
  * BFA_KEEP_UNDO  do not free undo information
@@ -677,7 +678,13 @@ buf_freeall(buf_T *buf, int flags)
 #ifdef FEAT_AUTOCMD
     int                is_curbuf = (buf == curbuf);
     bufref_T   bufref;
+# ifdef FEAT_WINDOWS
+    int                is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
+    win_T      *the_curwin = curwin;
+    tabpage_T  *the_curtab = curtab;
+# endif
 
+    /* Make sure the buffer isn't closed by autocommands. */
     buf->b_closing = TRUE;
     set_bufref(&bufref, buf);
     if (buf->b_ml.ml_mfp != NULL)
@@ -705,6 +712,19 @@ buf_freeall(buf_T *buf, int flags)
            return;
     }
     buf->b_closing = FALSE;
+
+# ifdef FEAT_WINDOWS
+    /* If the buffer was in curwin and the window has changed, go back to that
+     * window, if it still exists.  This avoids that ":edit x" triggering a
+     * "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
+    if (is_curwin && curwin != the_curwin &&  win_valid_any_tab(the_curwin))
+    {
+       block_autocmds();
+       goto_tabpage_win(the_curtab, the_curwin);
+       unblock_autocmds();
+    }
+# endif
+
 # ifdef FEAT_EVAL
     if (aborting())        /* autocmds may abort script processing */
        return;
index 1deb8a3689139161fe088ab529df4ae1dd7c8be2..61ab2ab125e744524a16a26e7a2292eb557e1fd9 100644 (file)
@@ -3935,25 +3935,28 @@ do_ecmd(
                auto_buf = TRUE;
            else
            {
+               win_T       *the_curwin = curwin;
+
+               /* Set the w_closing flag to avoid that autocommands close the
+                * window. */
+               the_curwin->w_closing = TRUE;
+
                if (curbuf == old_curbuf.br_buf)
 #endif
                    buf_copy_options(buf, BCO_ENTER);
 
-               /* close the link to the current buffer */
+               /* Close the link to the current buffer. This will set
+                * curwin->w_buffer to NULL. */
                u_sync(FALSE);
                close_buffer(oldwin, curbuf,
                               (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE);
 
 #ifdef FEAT_AUTOCMD
-               /* Autocommands may open a new window and leave oldwin open
-                * which leads to crashes since the above call sets
-                * oldwin->w_buffer to NULL. */
-               if (curwin != oldwin && oldwin != aucmd_win
-                            && win_valid(oldwin) && oldwin->w_buffer == NULL)
-                   win_close(oldwin, FALSE);
+               the_curwin->w_closing = FALSE;
 
 # ifdef FEAT_EVAL
-               if (aborting())     /* autocmds may abort script processing */
+               /* autocmds may abort script processing */
+               if (aborting() && curwin->w_buffer != NULL)
                {
                    vim_free(new_name);
                    goto theend;
index 866b347d64a4cc37f356734aece7f6020828331a..b568e46c3b5c5831215dc2282a1f9e5dd4b8223b 100644 (file)
@@ -2475,12 +2475,7 @@ do_one_cmd(
                && !IS_USER_CMDIDX(ea.cmdidx))
        {
            /* Command not allowed when editing the command line. */
-#ifdef FEAT_CMDWIN
-           if (cmdwin_type != 0)
-               errormsg = (char_u *)_(e_cmdwin);
-           else
-#endif
-               errormsg = (char_u *)_(e_secure);
+           errormsg = get_text_locked_msg();
            goto doend;
        }
 #ifdef FEAT_AUTOCMD
index 110a95afd68331a0e5344d9374b83a3dd6ec4e27..1627ee74f7c9a4815b9bd89842b7fc68a4572bae 100644 (file)
@@ -2132,13 +2132,18 @@ text_locked(void)
  */
     void
 text_locked_msg(void)
+{
+    EMSG(_(get_text_locked_msg()));
+}
+
+    char_u *
+get_text_locked_msg(void)
 {
 #ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
-       EMSG(_(e_cmdwin));
-    else
+       return e_cmdwin;
 #endif
-       EMSG(_(e_secure));
+    return e_secure;
 }
 
 #if defined(FEAT_AUTOCMD) || defined(PROTO)
index 581bfcebb4089aca7e73940dd1c79944d8e2e379..afc875c598520c2e055e97e2ea7a277677448724 100644 (file)
@@ -3,6 +3,7 @@ char_u *getcmdline(int firstc, long count, int indent);
 char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg);
 int text_locked(void);
 void text_locked_msg(void);
+char_u *get_text_locked_msg(void);
 int curbuf_locked(void);
 int allbuf_locked(void);
 char_u *getexline(int c, void *cookie, int indent);
index 7bdea0b18638f595b5327aa0a6fdb44a2912f2bb..0bf7d056de6bc123d55a67765f22b3bdd4928bda 100644 (file)
@@ -218,7 +218,7 @@ function Test_tabpage_with_tab_modifier()
   bw!
 endfunction
 
-func Test_tabnext_on_buf_unload()
+func Test_tabnext_on_buf_unload1()
   " This once caused a crash
   new
   tabedit
@@ -227,7 +227,19 @@ func Test_tabnext_on_buf_unload()
   q
 
   while tabpagenr('$') > 1
-    quit
+    bwipe!
+  endwhile
+endfunc
+
+func Test_tabnext_on_buf_unload2()
+  " This once caused a crash
+  tabedit
+  autocmd BufUnload <buffer> tabnext
+  file x
+  edit y
+
+  while tabpagenr('$') > 1
+    bwipe!
   endwhile
 endfunc
 
index ff7f236859d490d58e7740991be02a19d04366a6..df1de63e049f0dd67b4a2c181078b9947ab9dc74 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2312,
 /**/
     2311,
 /**/
index 2f3ec8c623dad2e70733d106ee4e487e1fdffd73..4f992711fe9dc9467fe9f16456a0fba5deea032f 100644 (file)
@@ -3912,12 +3912,7 @@ goto_tabpage(int n)
     if (text_locked())
     {
        /* Not allowed when editing the command line. */
-#ifdef FEAT_CMDWIN
-       if (cmdwin_type != 0)
-           EMSG(_(e_cmdwin));
-       else
-#endif
-           EMSG(_(e_secure));
+       text_locked_msg();
        return;
     }