Loading ...
Sorry, an error occurred while loading the content.

Patch 7.3.551

Expand Messages
  • Bram Moolenaar
    Patch 7.3.551 Problem: When using :tablose a TabEnter autocommand is triggered too early. (Karthick) Solution: Don t trigger *Enter autocommands before
    Message 1 of 8 , Jun 13, 2012
    • 0 Attachment
      Patch 7.3.551
      Problem: When using :tablose a TabEnter autocommand is triggered too early.
      (Karthick)
      Solution: Don't trigger *Enter autocommands before closing the tab.
      (Christian Brabandt)
      Files: src/buffer.c, src/eval.c, src/ex_cmds2.c, src/fileio.c,
      src/proto/window.pro, src/window.c


      *** ../vim-7.3.550/src/buffer.c 2012-06-06 19:02:40.000000000 +0200
      --- src/buffer.c 2012-06-13 14:18:58.000000000 +0200
      ***************
      *** 4470,4476 ****
      * When the ":tab" modifier was used do this for all tab pages.
      */
      if (had_tab > 0)
      ! goto_tabpage_tp(first_tabpage);
      for (;;)
      {
      tpnext = curtab->tp_next;
      --- 4470,4476 ----
      * When the ":tab" modifier was used do this for all tab pages.
      */
      if (had_tab > 0)
      ! goto_tabpage_tp(first_tabpage, TRUE);
      for (;;)
      {
      tpnext = curtab->tp_next;
      ***************
      *** 4582,4588 ****
      if (!valid_tabpage(tpnext))
      tpnext = first_tabpage; /* start all over...*/
      # endif
      ! goto_tabpage_tp(tpnext);
      }

      /*
      --- 4582,4588 ----
      if (!valid_tabpage(tpnext))
      tpnext = first_tabpage; /* start all over...*/
      # endif
      ! goto_tabpage_tp(tpnext, TRUE);
      }

      /*
      ***************
      *** 4686,4698 ****
      if (last_curtab != new_curtab)
      {
      if (valid_tabpage(last_curtab))
      ! goto_tabpage_tp(last_curtab);
      if (win_valid(last_curwin))
      win_enter(last_curwin, FALSE);
      }
      /* to window with first arg */
      if (valid_tabpage(new_curtab))
      ! goto_tabpage_tp(new_curtab);
      if (win_valid(new_curwin))
      win_enter(new_curwin, FALSE);

      --- 4686,4698 ----
      if (last_curtab != new_curtab)
      {
      if (valid_tabpage(last_curtab))
      ! goto_tabpage_tp(last_curtab, TRUE);
      if (win_valid(last_curwin))
      win_enter(last_curwin, FALSE);
      }
      /* to window with first arg */
      if (valid_tabpage(new_curtab))
      ! goto_tabpage_tp(new_curtab, TRUE);
      if (win_valid(new_curwin))
      win_enter(new_curwin, FALSE);

      ***************
      *** 4744,4750 ****
      */
      #ifdef FEAT_WINDOWS
      if (had_tab > 0)
      ! goto_tabpage_tp(first_tabpage);
      for (;;)
      {
      #endif
      --- 4744,4750 ----
      */
      #ifdef FEAT_WINDOWS
      if (had_tab > 0)
      ! goto_tabpage_tp(first_tabpage, TRUE);
      for (;;)
      {
      #endif
      ***************
      *** 4784,4790 ****
      /* Without the ":tab" modifier only do the current tab page. */
      if (had_tab == 0 || tpnext == NULL)
      break;
      ! goto_tabpage_tp(tpnext);
      }
      #endif

      --- 4784,4790 ----
      /* Without the ":tab" modifier only do the current tab page. */
      if (had_tab == 0 || tpnext == NULL)
      break;
      ! goto_tabpage_tp(tpnext, TRUE);
      }
      #endif

      *** ../vim-7.3.550/src/eval.c 2012-06-06 16:29:06.000000000 +0200
      --- src/eval.c 2012-06-13 14:18:58.000000000 +0200
      ***************
      *** 16415,16421 ****
      if (tp != NULL && varname != NULL && varp != NULL)
      {
      save_curtab = curtab;
      ! goto_tabpage_tp(tp);

      tabvarname = alloc((unsigned)STRLEN(varname) + 3);
      if (tabvarname != NULL)
      --- 16415,16421 ----
      if (tp != NULL && varname != NULL && varp != NULL)
      {
      save_curtab = curtab;
      ! goto_tabpage_tp(tp, TRUE);

      tabvarname = alloc((unsigned)STRLEN(varname) + 3);
      if (tabvarname != NULL)
      ***************
      *** 16428,16434 ****

      /* Restore current tabpage */
      if (valid_tabpage(save_curtab))
      ! goto_tabpage_tp(save_curtab);
      }
      }

      --- 16428,16434 ----

      /* Restore current tabpage */
      if (valid_tabpage(save_curtab))
      ! goto_tabpage_tp(save_curtab, TRUE);
      }
      }

      ***************
      *** 16492,16498 ****
      /* set curwin to be our win, temporarily */
      save_curwin = curwin;
      save_curtab = curtab;
      ! goto_tabpage_tp(tp);
      if (!win_valid(win))
      return;
      curwin = win;
      --- 16492,16498 ----
      /* set curwin to be our win, temporarily */
      save_curwin = curwin;
      save_curtab = curtab;
      ! goto_tabpage_tp(tp, TRUE);
      if (!win_valid(win))
      return;
      curwin = win;
      ***************
      *** 16527,16533 ****
      /* Restore current tabpage and window, if still valid (autocomands can
      * make them invalid). */
      if (valid_tabpage(save_curtab))
      ! goto_tabpage_tp(save_curtab);
      if (win_valid(save_curwin))
      {
      curwin = save_curwin;
      --- 16527,16533 ----
      /* Restore current tabpage and window, if still valid (autocomands can
      * make them invalid). */
      if (valid_tabpage(save_curtab))
      ! goto_tabpage_tp(save_curtab, TRUE);
      if (win_valid(save_curwin))
      {
      curwin = save_curwin;
      *** ../vim-7.3.550/src/ex_cmds2.c 2012-04-25 17:32:14.000000000 +0200
      --- src/ex_cmds2.c 2012-06-13 14:18:58.000000000 +0200
      ***************
      *** 2476,2482 ****
      /* go to window "tp" */
      if (!valid_tabpage(tp))
      break;
      ! goto_tabpage_tp(tp);
      tp = tp->tp_next;
      }
      #endif
      --- 2476,2482 ----
      /* go to window "tp" */
      if (!valid_tabpage(tp))
      break;
      ! goto_tabpage_tp(tp, TRUE);
      tp = tp->tp_next;
      }
      #endif
      *** ../vim-7.3.550/src/fileio.c 2012-06-06 18:03:01.000000000 +0200
      --- src/fileio.c 2012-06-13 14:18:58.000000000 +0200
      ***************
      *** 8918,8924 ****
      if (wp == aucmd_win)
      {
      if (tp != curtab)
      ! goto_tabpage_tp(tp);
      win_goto(aucmd_win);
      goto win_found;
      }
      --- 8918,8924 ----
      if (wp == aucmd_win)
      {
      if (tp != curtab)
      ! goto_tabpage_tp(tp, TRUE);
      win_goto(aucmd_win);
      goto win_found;
      }
      *** ../vim-7.3.550/src/proto/window.pro 2012-02-22 14:58:24.000000000 +0100
      --- src/proto/window.pro 2012-06-13 14:23:06.000000000 +0200
      ***************
      *** 27,33 ****
      tabpage_T *find_tabpage __ARGS((int n));
      int tabpage_index __ARGS((tabpage_T *ftp));
      void goto_tabpage __ARGS((int n));
      ! void goto_tabpage_tp __ARGS((tabpage_T *tp));
      void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp));
      void tabpage_move __ARGS((int nr));
      void win_goto __ARGS((win_T *wp));
      --- 27,33 ----
      tabpage_T *find_tabpage __ARGS((int n));
      int tabpage_index __ARGS((tabpage_T *ftp));
      void goto_tabpage __ARGS((int n));
      ! void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_autocmds));
      void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp));
      void tabpage_move __ARGS((int nr));
      void win_goto __ARGS((win_T *wp));
      *** ../vim-7.3.550/src/window.c 2012-06-06 19:02:40.000000000 +0200
      --- src/window.c 2012-06-13 14:24:38.000000000 +0200
      ***************
      *** 45,51 ****
      #if defined(FEAT_WINDOWS) || defined(PROTO)
      static tabpage_T *alloc_tabpage __ARGS((void));
      static int leave_tabpage __ARGS((buf_T *new_curbuf));
      ! static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf));
      static void frame_fix_height __ARGS((win_T *wp));
      static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
      static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
      --- 45,51 ----
      #if defined(FEAT_WINDOWS) || defined(PROTO)
      static tabpage_T *alloc_tabpage __ARGS((void));
      static int leave_tabpage __ARGS((buf_T *new_curbuf));
      ! static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_autocmds));
      static void frame_fix_height __ARGS((win_T *wp));
      static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
      static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
      ***************
      *** 355,365 ****
      && valid_tabpage(oldtab))
      {
      newtab = curtab;
      ! goto_tabpage_tp(oldtab);
      if (curwin == wp)
      win_close(curwin, FALSE);
      if (valid_tabpage(newtab))
      ! goto_tabpage_tp(newtab);
      }
      }
      break;
      --- 355,365 ----
      && valid_tabpage(oldtab))
      {
      newtab = curtab;
      ! goto_tabpage_tp(oldtab, TRUE);
      if (curwin == wp)
      win_close(curwin, FALSE);
      if (valid_tabpage(newtab))
      ! goto_tabpage_tp(newtab, TRUE);
      }
      }
      break;
      ***************
      *** 2130,2137 ****
      * page and then close the window and the tab page. This avoids that
      * curwin and curtab are invalid while we are freeing memory, they may
      * be used in GUI events.
      */
      ! goto_tabpage_tp(alt_tabpage());
      redraw_tabline = TRUE;

      /* Safety check: Autocommands may have closed the window when jumping
      --- 2130,2139 ----
      * page and then close the window and the tab page. This avoids that
      * curwin and curtab are invalid while we are freeing memory, they may
      * be used in GUI events.
      + * Don't trigger autocommands yet, they may use wrong values, so do
      + * that below.
      */
      ! goto_tabpage_tp(alt_tabpage(), FALSE);
      redraw_tabline = TRUE;

      /* Safety check: Autocommands may have closed the window when jumping
      ***************
      *** 2144,2149 ****
      --- 2146,2157 ----
      if (h != tabline_height())
      shell_new_rows();
      }
      + /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
      + * that now. */
      + #ifdef FEAT_AUTOCMD
      + apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
      + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
      + #endif
      return TRUE;
      }
      return FALSE;
      ***************
      *** 3556,3562 ****
      }

      /* Failed, get back the previous Tab page */
      ! enter_tabpage(curtab, curbuf);
      return FAIL;
      }

      --- 3564,3570 ----
      }

      /* Failed, get back the previous Tab page */
      ! enter_tabpage(curtab, curbuf, TRUE);
      return FAIL;
      }

      ***************
      *** 3709,3719 ****
      /*
      * Start using tab page "tp".
      * Only to be used after leave_tabpage() or freeing the current tab page.
      */
      static void
      ! enter_tabpage(tp, old_curbuf)
      tabpage_T *tp;
      buf_T *old_curbuf UNUSED;
      {
      int old_off = tp->tp_firstwin->w_winrow;
      win_T *next_prevwin = tp->tp_prevwin;
      --- 3717,3729 ----
      /*
      * Start using tab page "tp".
      * Only to be used after leave_tabpage() or freeing the current tab page.
      + * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
      */
      static void
      ! enter_tabpage(tp, old_curbuf, trigger_autocmds)
      tabpage_T *tp;
      buf_T *old_curbuf UNUSED;
      + int trigger_autocmds;
      {
      int old_off = tp->tp_firstwin->w_winrow;
      win_T *next_prevwin = tp->tp_prevwin;
      ***************
      *** 3761,3769 ****
      #ifdef FEAT_AUTOCMD
      /* Apply autocommands after updating the display, when 'rows' and
      * 'columns' have been set correctly. */
      ! apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
      ! if (old_curbuf != curbuf)
      ! apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
      #endif

      redraw_all_later(CLEAR);
      --- 3771,3782 ----
      #ifdef FEAT_AUTOCMD
      /* Apply autocommands after updating the display, when 'rows' and
      * 'columns' have been set correctly. */
      ! if (trigger_autocmds)
      ! {
      ! apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
      ! if (old_curbuf != curbuf)
      ! apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
      ! }
      #endif

      redraw_all_later(CLEAR);
      ***************
      *** 3839,3845 ****
      }
      }

      ! goto_tabpage_tp(tp);

      #ifdef FEAT_GUI_TABLINE
      if (gui_use_tabline())
      --- 3852,3858 ----
      }
      }

      ! goto_tabpage_tp(tp, TRUE);

      #ifdef FEAT_GUI_TABLINE
      if (gui_use_tabline())
      ***************
      *** 3849,3859 ****

      /*
      * Go to tabpage "tp".
      * Note: doesn't update the GUI tab.
      */
      void
      ! goto_tabpage_tp(tp)
      tabpage_T *tp;
      {
      /* Don't repeat a message in another tab page. */
      set_keep_msg(NULL, 0);
      --- 3862,3874 ----

      /*
      * Go to tabpage "tp".
      + * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
      * Note: doesn't update the GUI tab.
      */
      void
      ! goto_tabpage_tp(tp, trigger_autocmds)
      tabpage_T *tp;
      + int trigger_autocmds;
      {
      /* Don't repeat a message in another tab page. */
      set_keep_msg(NULL, 0);
      ***************
      *** 3861,3869 ****
      if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK)
      {
      if (valid_tabpage(tp))
      ! enter_tabpage(tp, curbuf);
      else
      ! enter_tabpage(curtab, curbuf);
      }
      }

      --- 3876,3884 ----
      if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK)
      {
      if (valid_tabpage(tp))
      ! enter_tabpage(tp, curbuf, trigger_autocmds);
      else
      ! enter_tabpage(curtab, curbuf, trigger_autocmds);
      }
      }

      ***************
      *** 3876,3882 ****
      tabpage_T *tp;
      win_T *wp;
      {
      ! goto_tabpage_tp(tp);
      if (curtab == tp && win_valid(wp))
      {
      win_enter(wp, TRUE);
      --- 3891,3897 ----
      tabpage_T *tp;
      win_T *wp;
      {
      ! goto_tabpage_tp(tp, TRUE);
      if (curtab == tp && win_valid(wp))
      {
      win_enter(wp, TRUE);
      *** ../vim-7.3.550/src/version.c 2012-06-13 14:01:36.000000000 +0200
      --- src/version.c 2012-06-13 14:28:00.000000000 +0200
      ***************
      *** 716,717 ****
      --- 716,719 ----
      { /* Add new patch number below this line */
      + /**/
      + 551,
      /**/

      --
      Give a man a computer program and you give him a headache,
      but teach him to program computers and you give him the power
      to create headaches for others for the rest of his life...
      R. B. Forest

      /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
      /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
      \\\ an exciting new programming language -- http://www.Zimbu.org ///
      \\\ 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
    • ZyX
      This patch will trigger WinEnter events twice: vim -u NONE -N -S
      Message 2 of 8 , Apr 25, 2013
      • 0 Attachment
        This patch will trigger WinEnter events twice:

        vim -u NONE -N -S <(echo $'tabnew\nau WinEnter * :echom "HERE"\nredir! > /tmp/redir\ntabclose\nredir END\nqa')

        will show you two HERE strings in /tmp/redir (trigger_autocmds argument is not passed down to win_enter_ext). Strange nobody noticed it. It is also skipping BufEnter autocommads:

        vim -u NONE -N -S <(echo $'tabnew\nau BufEnter * :echom "HERE"\nredir! > /tmp/redir\ntabclose\nredir END\nqa')

        (tested on vim-7.3.905, but I believe this patch is the case). Found when exploring a way to not trigger autocommands for various set*var functions.

        --
        --
        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 vim_dev+unsubscribe@....
        For more options, visit https://groups.google.com/groups/opt_out.
      • ZyX
        ... % vim -u NONE -N -S
        Message 3 of 8 , Apr 25, 2013
        • 0 Attachment
          This also breaks the ordering: TabEnter is said to be launched after WinEnter, patch launches it before:

          >TabEnter Just after entering a tab page. |tab-page|
          > After triggering the WinEnter and before
          > triggering the BufEnter event.


          % vim -u NONE -N -S <(echo $'command -nargs=1 C :echom <q-args>|<args>\nau BufEnter * :echom "BUF"\nau TabEnter * :echom "TAB"\nau WinEnter * :echom "WIN"\nredir! > /tmp/redir\nC tabnew\nC tabnext\nC tabnext\nC tabclose\nredir END\nqa')
          % cat /tmp/redir

          tabnew
          TAB
          WIN
          BUF
          tabnext
          WIN
          TAB
          BUF
          tabnext
          WIN
          TAB
          BUF
          tabclose
          WIN
          TAB
          WIN

          Note that for tabnew ordering is also broken.

          --
          --
          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 vim_dev+unsubscribe@....
          For more options, visit https://groups.google.com/groups/opt_out.
        • ZyX
          Here is the patch. To be applied after applying patch with vim.**.options. I can split and/or rebase it if you need. # HG changeset patch # User ZyX
          Message 4 of 8 , Apr 25, 2013
          • 0 Attachment
            Here is the patch. To be applied after applying patch with vim.**.options. I can split and/or rebase it if you need.

            # HG changeset patch
            # User ZyX <kp-pav@...>
            # Date 1366951264 -14400
            # Branch python-extended-2
            # Node ID 66af9eddd748a888e3ccc0fc221fe80663d0186b
            # Parent 1ffc8d40ecea0d75d48612b828fd62d9e3669191
            Various tab and autocommands related fixes:

            - Do not launch autocommands for various set*var functions
            - Fix missing (BufEnter) autocommands on :tabclose
            - Fix duplicate (WinEnter) autocommands on :tabclose
            - Fix wrong ordering (TabEnter then WinEnter instead of the opposite) of
            autocommands on :tabclose and :tabnew

            diff -r 1ffc8d40ecea -r 66af9eddd748 runtime/doc/eval.txt
            --- a/runtime/doc/eval.txt Thu Apr 25 00:40:58 2013 +0400
            +++ b/runtime/doc/eval.txt Fri Apr 26 08:41:04 2013 +0400
            @@ -5320,8 +5320,6 @@
            |t:var|
            Note that the variable name without "t:" must be used.
            Tabs are numbered starting with one.
            - Vim briefly goes to the tab page {tabnr}, this may trigger
            - TabLeave and TabEnter autocommands.
            This function is not available in the |sandbox|.

            settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()*
            @@ -5334,8 +5332,6 @@
            doesn't work for a global or local buffer variable.
            For a local buffer option the global value is unchanged.
            Note that the variable name without "w:" must be used.
            - Vim briefly goes to the tab page {tabnr}, this may trigger
            - TabLeave and TabEnter autocommands.
            Examples: >
            :call settabwinvar(1, 1, "&list", 0)
            :call settabwinvar(3, 2, "myvar", "foobar")
            diff -r 1ffc8d40ecea -r 66af9eddd748 src/buffer.c
            --- a/src/buffer.c Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/buffer.c Fri Apr 26 08:41:04 2013 +0400
            @@ -4551,7 +4551,7 @@
            * When the ":tab" modifier was used do this for all tab pages.
            */
            if (had_tab > 0)
            - goto_tabpage_tp(first_tabpage, TRUE);
            + goto_tabpage_tp(first_tabpage, TRUE, TRUE);
            for (;;)
            {
            tpnext = curtab->tp_next;
            @@ -4663,7 +4663,7 @@
            if (!valid_tabpage(tpnext))
            tpnext = first_tabpage; /* start all over...*/
            # endif
            - goto_tabpage_tp(tpnext, TRUE);
            + goto_tabpage_tp(tpnext, TRUE, TRUE);
            }

            /*
            @@ -4767,13 +4767,13 @@
            if (last_curtab != new_curtab)
            {
            if (valid_tabpage(last_curtab))
            - goto_tabpage_tp(last_curtab, TRUE);
            + goto_tabpage_tp(last_curtab, TRUE, TRUE);
            if (win_valid(last_curwin))
            win_enter(last_curwin, FALSE);
            }
            /* to window with first arg */
            if (valid_tabpage(new_curtab))
            - goto_tabpage_tp(new_curtab, TRUE);
            + goto_tabpage_tp(new_curtab, TRUE, TRUE);
            if (win_valid(new_curwin))
            win_enter(new_curwin, FALSE);

            @@ -4825,7 +4825,7 @@
            */
            #ifdef FEAT_WINDOWS
            if (had_tab > 0)
            - goto_tabpage_tp(first_tabpage, TRUE);
            + goto_tabpage_tp(first_tabpage, TRUE, TRUE);
            for (;;)
            {
            #endif
            @@ -4865,7 +4865,7 @@
            /* Without the ":tab" modifier only do the current tab page. */
            if (had_tab == 0 || tpnext == NULL)
            break;
            - goto_tabpage_tp(tpnext, TRUE);
            + goto_tabpage_tp(tpnext, TRUE, TRUE);
            }
            #endif

            diff -r 1ffc8d40ecea -r 66af9eddd748 src/eval.c
            --- a/src/eval.c Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/eval.c Fri Apr 26 08:41:04 2013 +0400
            @@ -16604,7 +16604,7 @@
            if (tp != NULL && varname != NULL && varp != NULL)
            {
            save_curtab = curtab;
            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, FALSE, FALSE);

            tabvarname = alloc((unsigned)STRLEN(varname) + 3);
            if (tabvarname != NULL)
            @@ -16617,7 +16617,7 @@

            /* Restore current tabpage */
            if (valid_tabpage(save_curtab))
            - goto_tabpage_tp(save_curtab, TRUE);
            + goto_tabpage_tp(save_curtab, FALSE, FALSE);
            }
            }

            @@ -16654,7 +16654,7 @@
            /* set curwin to be our win, temporarily */
            *save_curwin = curwin;
            *save_curtab = curtab;
            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, FALSE, FALSE);
            if (!win_valid(win))
            return 1;
            curwin = win;
            @@ -16672,7 +16672,7 @@
            /* Restore current tabpage and window, if still valid (autocomands can
            * make them invalid). */
            if (valid_tabpage(save_curtab))
            - goto_tabpage_tp(save_curtab, TRUE);
            + goto_tabpage_tp(save_curtab, FALSE, FALSE);
            if (win_valid(save_curwin))
            {
            curwin = save_curwin;
            diff -r 1ffc8d40ecea -r 66af9eddd748 src/ex_cmds2.c
            --- a/src/ex_cmds2.c Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/ex_cmds2.c Fri Apr 26 08:41:04 2013 +0400
            @@ -2482,7 +2482,7 @@
            /* go to window "tp" */
            if (!valid_tabpage(tp))
            break;
            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, TRUE, TRUE);
            tp = tp->tp_next;
            }
            #endif
            diff -r 1ffc8d40ecea -r 66af9eddd748 src/fileio.c
            --- a/src/fileio.c Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/fileio.c Fri Apr 26 08:41:04 2013 +0400
            @@ -8934,7 +8934,7 @@
            if (wp == aucmd_win)
            {
            if (tp != curtab)
            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, TRUE, TRUE);
            win_goto(aucmd_win);
            goto win_found;
            }
            diff -r 1ffc8d40ecea -r 66af9eddd748 src/proto/window.pro
            --- a/src/proto/window.pro Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/proto/window.pro Fri Apr 26 08:41:04 2013 +0400
            @@ -27,7 +27,7 @@
            tabpage_T *find_tabpage __ARGS((int n));
            int tabpage_index __ARGS((tabpage_T *ftp));
            void goto_tabpage __ARGS((int n));
            -void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_autocmds));
            +void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds));
            void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp));
            void tabpage_move __ARGS((int nr));
            void win_goto __ARGS((win_T *wp));
            diff -r 1ffc8d40ecea -r 66af9eddd748 src/window.c
            --- a/src/window.c Thu Apr 25 00:40:58 2013 +0400
            +++ b/src/window.c Fri Apr 26 08:41:04 2013 +0400
            @@ -45,10 +45,10 @@
            #if defined(FEAT_WINDOWS) || defined(PROTO)
            static tabpage_T *alloc_tabpage __ARGS((void));
            static int leave_tabpage __ARGS((buf_T *new_curbuf));
            -static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_autocmds));
            +static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_autocmds, int trigger_leave_autocmds));
            static void frame_fix_height __ARGS((win_T *wp));
            static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
            -static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
            +static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin, int trigger_enter_autocmds, int trigger_leave_autocmds));
            static void win_free __ARGS((win_T *wp, tabpage_T *tp));
            static void frame_append __ARGS((frame_T *after, frame_T *frp));
            static void frame_insert __ARGS((frame_T *before, frame_T *frp));
            @@ -353,11 +353,11 @@
            && valid_tabpage(oldtab))
            {
            newtab = curtab;
            - goto_tabpage_tp(oldtab, TRUE);
            + goto_tabpage_tp(oldtab, TRUE, TRUE);
            if (curwin == wp)
            win_close(curwin, FALSE);
            if (valid_tabpage(newtab))
            - goto_tabpage_tp(newtab, TRUE);
            + goto_tabpage_tp(newtab, TRUE, TRUE);
            }
            }
            break;
            @@ -2124,6 +2124,7 @@
            {
            if (firstwin == lastwin)
            {
            + buf_T *old_curbuf;
            /*
            * Closing the last window in a tab page. First go to another tab
            * page and then close the window and the tab page. This avoids that
            @@ -2132,7 +2133,8 @@
            * Don't trigger autocommands yet, they may use wrong values, so do
            * that below.
            */
            - goto_tabpage_tp(alt_tabpage(), FALSE);
            + old_curbuf = curbuf;
            + goto_tabpage_tp(alt_tabpage(), FALSE, TRUE);
            redraw_tabline = TRUE;

            /* Safety check: Autocommands may have closed the window when jumping
            @@ -2148,8 +2150,10 @@
            /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
            * that now. */
            #ifdef FEAT_AUTOCMD
            + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
            - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            + if (old_curbuf != curbuf)
            + apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
            #endif
            return TRUE;
            }
            @@ -2341,7 +2345,7 @@
            win_comp_pos();
            if (close_curwin)
            {
            - win_enter_ext(wp, FALSE, TRUE);
            + win_enter_ext(wp, FALSE, TRUE, TRUE, TRUE);
            #ifdef FEAT_AUTOCMD
            if (other_buffer)
            /* careful: after this wp and win may be invalid! */
            @@ -3574,14 +3578,14 @@

            redraw_all_later(CLEAR);
            #ifdef FEAT_AUTOCMD
            + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
            - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            #endif
            return OK;
            }

            /* Failed, get back the previous Tab page */
            - enter_tabpage(curtab, curbuf, TRUE);
            + enter_tabpage(curtab, curbuf, TRUE, TRUE);
            return FAIL;
            }

            @@ -3734,13 +3738,15 @@
            /*
            * Start using tab page "tp".
            * Only to be used after leave_tabpage() or freeing the current tab page.
            - * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
            + * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
            + * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
            */
            static void
            -enter_tabpage(tp, old_curbuf, trigger_autocmds)
            +enter_tabpage(tp, old_curbuf, trigger_enter_autocmds, trigger_leave_autocmds)
            tabpage_T *tp;
            buf_T *old_curbuf UNUSED;
            - int trigger_autocmds UNUSED;
            + int trigger_enter_autocmds UNUSED;
            + int trigger_leave_autocmds UNUSED;
            {
            int old_off = tp->tp_firstwin->w_winrow;
            win_T *next_prevwin = tp->tp_prevwin;
            @@ -3753,7 +3759,7 @@
            /* We would like doing the TabEnter event first, but we don't have a
            * valid current window yet, which may break some commands.
            * This triggers autocommands, thus may make "tp" invalid. */
            - win_enter_ext(tp->tp_curwin, FALSE, TRUE);
            + win_enter_ext(tp->tp_curwin, FALSE, TRUE, trigger_enter_autocmds, trigger_leave_autocmds);
            prevwin = next_prevwin;

            last_status(FALSE); /* status line may appear or disappear */
            @@ -3788,7 +3794,7 @@
            #ifdef FEAT_AUTOCMD
            /* Apply autocommands after updating the display, when 'rows' and
            * 'columns' have been set correctly. */
            - if (trigger_autocmds)
            + if (trigger_enter_autocmds)
            {
            apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
            if (old_curbuf != curbuf)
            @@ -3869,7 +3875,7 @@
            }
            }

            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, TRUE, TRUE);

            #ifdef FEAT_GUI_TABLINE
            if (gui_use_tabline())
            @@ -3879,13 +3885,15 @@

            /*
            * Go to tabpage "tp".
            - * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
            + * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
            + * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
            * Note: doesn't update the GUI tab.
            */
            void
            -goto_tabpage_tp(tp, trigger_autocmds)
            +goto_tabpage_tp(tp, trigger_enter_autocmds, trigger_leave_autocmds)
            tabpage_T *tp;
            - int trigger_autocmds;
            + int trigger_enter_autocmds;
            + int trigger_leave_autocmds;
            {
            /* Don't repeat a message in another tab page. */
            set_keep_msg(NULL, 0);
            @@ -3893,9 +3901,9 @@
            if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK)
            {
            if (valid_tabpage(tp))
            - enter_tabpage(tp, curbuf, trigger_autocmds);
            + enter_tabpage(tp, curbuf, trigger_enter_autocmds, trigger_leave_autocmds);
            else
            - enter_tabpage(curtab, curbuf, trigger_autocmds);
            + enter_tabpage(curtab, curbuf, trigger_enter_autocmds, trigger_leave_autocmds);
            }
            }

            @@ -3908,7 +3916,7 @@
            tabpage_T *tp;
            win_T *wp;
            {
            - goto_tabpage_tp(tp, TRUE);
            + goto_tabpage_tp(tp, TRUE, TRUE);
            if (curtab == tp && win_valid(wp))
            {
            win_enter(wp, TRUE);
            @@ -4168,7 +4176,7 @@
            win_T *wp;
            int undo_sync;
            {
            - win_enter_ext(wp, undo_sync, FALSE);
            + win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE);
            }

            /*
            @@ -4177,10 +4185,12 @@
            * been closed and isn't valid.
            */
            static void
            -win_enter_ext(wp, undo_sync, curwin_invalid)
            +win_enter_ext(wp, undo_sync, curwin_invalid, trigger_enter_autocmds, trigger_leave_autocmds)
            win_T *wp;
            int undo_sync;
            int curwin_invalid;
            + int trigger_enter_autocmds UNUSED;
            + int trigger_leave_autocmds UNUSED;
            {
            #ifdef FEAT_AUTOCMD
            int other_buffer = FALSE;
            @@ -4190,7 +4200,7 @@
            return;

            #ifdef FEAT_AUTOCMD
            - if (!curwin_invalid)
            + if (!curwin_invalid && trigger_leave_autocmds)
            {
            /*
            * Be careful: If autocommands delete the window, return now.
            @@ -4259,9 +4269,12 @@
            }

            #ifdef FEAT_AUTOCMD
            - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            - if (other_buffer)
            - apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
            + if (trigger_enter_autocmds)
            + {
            + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
            + if (other_buffer)
            + apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
            + }
            #endif

            #ifdef FEAT_TITLE

            --
            --
            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 vim_dev+unsubscribe@....
            For more options, visit https://groups.google.com/groups/opt_out.
          • Bram Moolenaar
            ... Thanks for figuring this out. You had some nice examples for how to reproduce the problem you are fixing, how about turning those into a test? --
            Message 5 of 8 , Apr 26, 2013
            • 0 Attachment
              ZyX wrote:

              > Here is the patch. To be applied after applying patch with
              > vim.**.options. I can split and/or rebase it if you need.
              >
              > # HG changeset patch
              > # User ZyX <kp-pav@...>
              > # Date 1366951264 -14400
              > # Branch python-extended-2
              > # Node ID 66af9eddd748a888e3ccc0fc221fe80663d0186b
              > # Parent 1ffc8d40ecea0d75d48612b828fd62d9e3669191
              > Various tab and autocommands related fixes:
              >
              > - Do not launch autocommands for various set*var functions
              > - Fix missing (BufEnter) autocommands on :tabclose
              > - Fix duplicate (WinEnter) autocommands on :tabclose
              > - Fix wrong ordering (TabEnter then WinEnter instead of the opposite) of
              > autocommands on :tabclose and :tabnew

              Thanks for figuring this out. You had some nice examples for how to
              reproduce the problem you are fixing, how about turning those into a
              test?


              --
              hundred-and-one symptoms of being an internet addict:
              233. You start dreaming about web pages...in html.

              /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
              /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
              \\\ an exciting new programming language -- http://www.Zimbu.org ///
              \\\ 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 vim_dev+unsubscribe@....
              For more options, visit https://groups.google.com/groups/opt_out.
            • ZyX
              ... Updated patch: added tests, removed few autocommands left (BufLeave, TabLeave and WinLeave from leave_tabpage). Changes from the previous patch are here:
              Message 6 of 8 , Apr 26, 2013
              • 0 Attachment
                > Thanks for figuring this out. You had some nice examples for how to
                > reproduce the problem you are fixing, how about turning those into a
                > test?

                Updated patch: added tests, removed few autocommands left (BufLeave, TabLeave and WinLeave from leave_tabpage). Changes from the previous patch are here: https://bitbucket.org/ZyX_I/vim/changeset/86a5abc53a8e20a2f738cd5a099da82c8de48ce3.

                # HG changeset patch
                # User ZyX <kp-pav@...>
                # Date 1366986343 -14400
                # Branch python-extended-2
                # Node ID 869937c7f5d4cfb2a2a1b50ffb88b84db5eeea17
                # Parent 1ffc8d40ecea0d75d48612b828fd62d9e3669191
                Various tab and autocommands related fixes:

                - Do not launch autocommands for various set*var functions
                - Fix missing (BufEnter) autocommands on :tabclose
                - Fix duplicate (WinEnter) autocommands on :tabclose
                - Fix wrong ordering (TabEnter then WinEnter instead of the opposite) of
                autocommands on :tabclose and :tabnew

                diff -r 1ffc8d40ecea -r 869937c7f5d4 runtime/doc/eval.txt
                --- a/runtime/doc/eval.txt Thu Apr 25 00:40:58 2013 +0400
                +++ b/runtime/doc/eval.txt Fri Apr 26 18:25:43 2013 +0400
                @@ -5320,8 +5320,6 @@
                |t:var|
                Note that the variable name without "t:" must be used.
                Tabs are numbered starting with one.
                - Vim briefly goes to the tab page {tabnr}, this may trigger
                - TabLeave and TabEnter autocommands.
                This function is not available in the |sandbox|.

                settabwinvar({tabnr}, {winnr}, {varname}, {val}) *settabwinvar()*
                @@ -5334,8 +5332,6 @@
                doesn't work for a global or local buffer variable.
                For a local buffer option the global value is unchanged.
                Note that the variable name without "w:" must be used.
                - Vim briefly goes to the tab page {tabnr}, this may trigger
                - TabLeave and TabEnter autocommands.
                Examples: >
                :call settabwinvar(1, 1, "&list", 0)
                :call settabwinvar(3, 2, "myvar", "foobar")
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/buffer.c
                --- a/src/buffer.c Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/buffer.c Fri Apr 26 18:25:43 2013 +0400
                @@ -4551,7 +4551,7 @@
                * When the ":tab" modifier was used do this for all tab pages.
                */
                if (had_tab > 0)
                - goto_tabpage_tp(first_tabpage, TRUE);
                + goto_tabpage_tp(first_tabpage, TRUE, TRUE);
                for (;;)
                {
                tpnext = curtab->tp_next;
                @@ -4663,7 +4663,7 @@
                if (!valid_tabpage(tpnext))
                tpnext = first_tabpage; /* start all over...*/
                # endif
                - goto_tabpage_tp(tpnext, TRUE);
                + goto_tabpage_tp(tpnext, TRUE, TRUE);
                }

                /*
                @@ -4767,13 +4767,13 @@
                if (last_curtab != new_curtab)
                {
                if (valid_tabpage(last_curtab))
                - goto_tabpage_tp(last_curtab, TRUE);
                + goto_tabpage_tp(last_curtab, TRUE, TRUE);
                if (win_valid(last_curwin))
                win_enter(last_curwin, FALSE);
                }
                /* to window with first arg */
                if (valid_tabpage(new_curtab))
                - goto_tabpage_tp(new_curtab, TRUE);
                + goto_tabpage_tp(new_curtab, TRUE, TRUE);
                if (win_valid(new_curwin))
                win_enter(new_curwin, FALSE);

                @@ -4825,7 +4825,7 @@
                */
                #ifdef FEAT_WINDOWS
                if (had_tab > 0)
                - goto_tabpage_tp(first_tabpage, TRUE);
                + goto_tabpage_tp(first_tabpage, TRUE, TRUE);
                for (;;)
                {
                #endif
                @@ -4865,7 +4865,7 @@
                /* Without the ":tab" modifier only do the current tab page. */
                if (had_tab == 0 || tpnext == NULL)
                break;
                - goto_tabpage_tp(tpnext, TRUE);
                + goto_tabpage_tp(tpnext, TRUE, TRUE);
                }
                #endif

                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/eval.c
                --- a/src/eval.c Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/eval.c Fri Apr 26 18:25:43 2013 +0400
                @@ -16604,7 +16604,7 @@
                if (tp != NULL && varname != NULL && varp != NULL)
                {
                save_curtab = curtab;
                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, FALSE, FALSE);

                tabvarname = alloc((unsigned)STRLEN(varname) + 3);
                if (tabvarname != NULL)
                @@ -16617,7 +16617,7 @@

                /* Restore current tabpage */
                if (valid_tabpage(save_curtab))
                - goto_tabpage_tp(save_curtab, TRUE);
                + goto_tabpage_tp(save_curtab, FALSE, FALSE);
                }
                }

                @@ -16654,7 +16654,7 @@
                /* set curwin to be our win, temporarily */
                *save_curwin = curwin;
                *save_curtab = curtab;
                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, FALSE, FALSE);
                if (!win_valid(win))
                return 1;
                curwin = win;
                @@ -16672,7 +16672,7 @@
                /* Restore current tabpage and window, if still valid (autocomands can
                * make them invalid). */
                if (valid_tabpage(save_curtab))
                - goto_tabpage_tp(save_curtab, TRUE);
                + goto_tabpage_tp(save_curtab, FALSE, FALSE);
                if (win_valid(save_curwin))
                {
                curwin = save_curwin;
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/ex_cmds2.c
                --- a/src/ex_cmds2.c Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/ex_cmds2.c Fri Apr 26 18:25:43 2013 +0400
                @@ -2482,7 +2482,7 @@
                /* go to window "tp" */
                if (!valid_tabpage(tp))
                break;
                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, TRUE, TRUE);
                tp = tp->tp_next;
                }
                #endif
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/fileio.c
                --- a/src/fileio.c Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/fileio.c Fri Apr 26 18:25:43 2013 +0400
                @@ -8934,7 +8934,7 @@
                if (wp == aucmd_win)
                {
                if (tp != curtab)
                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, TRUE, TRUE);
                win_goto(aucmd_win);
                goto win_found;
                }
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/proto/window.pro
                --- a/src/proto/window.pro Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/proto/window.pro Fri Apr 26 18:25:43 2013 +0400
                @@ -27,7 +27,7 @@
                tabpage_T *find_tabpage __ARGS((int n));
                int tabpage_index __ARGS((tabpage_T *ftp));
                void goto_tabpage __ARGS((int n));
                -void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_autocmds));
                +void goto_tabpage_tp __ARGS((tabpage_T *tp, int trigger_enter_autocmds, int trigger_leave_autocmds));
                void goto_tabpage_win __ARGS((tabpage_T *tp, win_T *wp));
                void tabpage_move __ARGS((int nr));
                void win_goto __ARGS((win_T *wp));
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/testdir/test62.in
                --- a/src/testdir/test62.in Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/testdir/test62.in Fri Apr 26 18:25:43 2013 +0400
                @@ -120,6 +120,68 @@
                :endtry
                i =a

                :"
                +:" Test autocommands
                +:tabonly!
                +:let g:r=[]
                +:command -nargs=1 -bar C :call add(g:r, '=== ' . <q-args> . ' ===')|<args>
                +:function Test()
                + let hasau=has('autocmd')
                + if hasau
                + autocmd TabEnter * :call add(g:r, 'TabEnter')
                + autocmd WinEnter * :call add(g:r, 'WinEnter')
                + autocmd BufEnter * :call add(g:r, 'BufEnter')
                + autocmd TabLeave * :call add(g:r, 'TabLeave')
                + autocmd WinLeave * :call add(g:r, 'WinLeave')
                + autocmd BufLeave * :call add(g:r, 'BufLeave')
                + endif
                + let t:a='a'
                + C tab split
                + if !hasau
                + let g:r+=['WinLeave', 'TabLeave', 'WinEnter', 'TabEnter']
                + endif
                + let t:a='b'
                + C tabnew
                + if !hasau
                + let g:r+=['WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', 'BufLeave', 'BufEnter']
                + endif
                + let t:a='c'
                + call add(g:r, join(map(range(1, tabpagenr('$')), 'gettabvar(v:val, "a")')))
                + C call map(range(1, tabpagenr('$')), 'settabvar(v:val, "a", v:val*2)')
                + call add(g:r, join(map(range(1, tabpagenr('$')), 'gettabvar(v:val, "a")')))
                + let w:a='a'
                + C vsplit
                + if !hasau
                + let g:r+=['WinLeave', 'WinEnter']
                + endif
                + let w:a='a'
                + let tabn=tabpagenr()
                + let winr=range(1, winnr('$'))
                + C tabnext 1
                + if !hasau
                + let g:r+=['BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter']
                + endif
                + call add(g:r, join(map(copy(winr), 'gettabwinvar('.tabn.', v:val, "a")')))
                + C call map(copy(winr), 'settabwinvar('.tabn.', v:val, "a", v:val*2)')
                + call add(g:r, join(map(copy(winr), 'gettabwinvar('.tabn.', v:val, "a")')))
                + if hasau
                + augroup TabDestructive
                + autocmd TabEnter * :C tabnext 2 | C tabclose 3
                + augroup END
                + C tabnext 3
                + let g:r+=[tabpagenr().'/'.tabpagenr('$')]
                + autocmd! TabDestructive TabEnter
                + C tabnew
                + C tabnext 1
                + autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3
                + C tabnext 3
                + let g:r+=[tabpagenr().'/'.tabpagenr('$')]
                + else
                + let g:r+=["=== tabnext 3 ===","BufLeave","WinLeave","TabLeave","WinEnter","TabEnter","=== tabnext 2 ===","=== tabclose 3 ===","2/2","=== tabnew ===","WinLeave","TabLeave","WinEnter","TabEnter","BufLeave","BufEnter","=== tabnext 1 ===","BufLeave","WinLeave","TabLeave","WinEnter","TabEnter","BufEnter","=== tabnext 3 ===","BufLeave","WinLeave","TabLeave","WinEnter","TabEnter","=== tabnext 2 ===","BufLeave","WinLeave","TabLeave","WinEnter","TabEnter","=== tabnext 2 ===","=== tabclose 3 ===","BufEnter","=== tabclose 3 ===","2/2",]
                + endif
                +endfunction
                +:call Test()
                +:$ put =g:r
                +:"
                :"
                :/^Results/,$w! test.out
                :qa!
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/testdir/test62.ok
                --- a/src/testdir/test62.ok Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/testdir/test62.ok Fri Apr 26 18:25:43 2013 +0400
                @@ -18,3 +18,71 @@
                4
                6
                E474 caught.
                +=== tab split ===
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +=== tabnew ===
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +BufLeave
                +BufEnter
                +a b c
                +=== call map(range(1, tabpagenr('$')), 'settabvar(v:val, ===
                +a b c
                +=== vsplit ===
                +WinLeave
                +WinEnter
                +=== tabnext 1 ===
                +BufLeave
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +BufEnter
                +a a
                +=== call map(copy(winr), 'settabwinvar('.tabn.', v:val, ===
                +a a
                +=== tabnext 3 ===
                +BufLeave
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +=== tabnext 2 ===
                +=== tabclose 3 ===
                +2/2
                +=== tabnew ===
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +BufLeave
                +BufEnter
                +=== tabnext 1 ===
                +BufLeave
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +BufEnter
                +=== tabnext 3 ===
                +BufLeave
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +=== tabnext 2 ===
                +BufLeave
                +WinLeave
                +TabLeave
                +WinEnter
                +TabEnter
                +=== tabnext 2 ===
                +=== tabclose 3 ===
                +BufEnter
                +=== tabclose 3 ===
                +2/2
                diff -r 1ffc8d40ecea -r 869937c7f5d4 src/window.c
                --- a/src/window.c Thu Apr 25 00:40:58 2013 +0400
                +++ b/src/window.c Fri Apr 26 18:25:43 2013 +0400
                @@ -44,11 +44,11 @@
                static void new_frame __ARGS((win_T *wp));
                #if defined(FEAT_WINDOWS) || defined(PROTO)
                static tabpage_T *alloc_tabpage __ARGS((void));
                -static int leave_tabpage __ARGS((buf_T *new_curbuf));
                -static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_autocmds));
                +static int leave_tabpage __ARGS((buf_T *new_curbuf, int trigger_leave_autocmds));
                +static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf, int trigger_enter_autocmds, int trigger_leave_autocmds));
                static void frame_fix_height __ARGS((win_T *wp));
                static int frame_minheight __ARGS((frame_T *topfrp, win_T *next_curwin));
                -static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin));
                +static void win_enter_ext __ARGS((win_T *wp, int undo_sync, int no_curwin, int trigger_enter_autocmds, int trigger_leave_autocmds));
                static void win_free __ARGS((win_T *wp, tabpage_T *tp));
                static void frame_append __ARGS((frame_T *after, frame_T *frp));
                static void frame_insert __ARGS((frame_T *before, frame_T *frp));
                @@ -353,11 +353,11 @@
                && valid_tabpage(oldtab))
                {
                newtab = curtab;
                - goto_tabpage_tp(oldtab, TRUE);
                + goto_tabpage_tp(oldtab, TRUE, TRUE);
                if (curwin == wp)
                win_close(curwin, FALSE);
                if (valid_tabpage(newtab))
                - goto_tabpage_tp(newtab, TRUE);
                + goto_tabpage_tp(newtab, TRUE, TRUE);
                }
                }
                break;
                @@ -2124,6 +2124,7 @@
                {
                if (firstwin == lastwin)
                {
                + buf_T *old_curbuf;
                /*
                * Closing the last window in a tab page. First go to another tab
                * page and then close the window and the tab page. This avoids that
                @@ -2132,7 +2133,8 @@
                * Don't trigger autocommands yet, they may use wrong values, so do
                * that below.
                */
                - goto_tabpage_tp(alt_tabpage(), FALSE);
                + old_curbuf = curbuf;
                + goto_tabpage_tp(alt_tabpage(), FALSE, TRUE);
                redraw_tabline = TRUE;

                /* Safety check: Autocommands may have closed the window when jumping
                @@ -2148,8 +2150,10 @@
                /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
                * that now. */
                #ifdef FEAT_AUTOCMD
                + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
                - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                + if (old_curbuf != curbuf)
                + apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
                #endif
                return TRUE;
                }
                @@ -2341,7 +2345,7 @@
                win_comp_pos();
                if (close_curwin)
                {
                - win_enter_ext(wp, FALSE, TRUE);
                + win_enter_ext(wp, FALSE, TRUE, TRUE, TRUE);
                #ifdef FEAT_AUTOCMD
                if (other_buffer)
                /* careful: after this wp and win may be invalid! */
                @@ -3529,7 +3533,7 @@
                return FAIL;

                /* Remember the current windows in this Tab page. */
                - if (leave_tabpage(curbuf) == FAIL)
                + if (leave_tabpage(curbuf, TRUE) == FAIL)
                {
                vim_free(newtp);
                return FAIL;
                @@ -3574,14 +3578,14 @@

                redraw_all_later(CLEAR);
                #ifdef FEAT_AUTOCMD
                + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
                - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                #endif
                return OK;
                }

                /* Failed, get back the previous Tab page */
                - enter_tabpage(curtab, curbuf, TRUE);
                + enter_tabpage(curtab, curbuf, TRUE, TRUE);
                return FAIL;
                }

                @@ -3692,9 +3696,10 @@
                * Careful: When OK is returned need to get a new tab page very very soon!
                */
                static int
                -leave_tabpage(new_curbuf)
                +leave_tabpage(new_curbuf, trigger_leave_autocmds)
                buf_T *new_curbuf UNUSED; /* what is going to be the new curbuf,
                NULL if unknown */
                + int trigger_leave_autocmds UNUSED;
                {
                tabpage_T *tp = curtab;

                @@ -3702,18 +3707,21 @@
                reset_VIsual_and_resel(); /* stop Visual mode */
                #endif
                #ifdef FEAT_AUTOCMD
                - if (new_curbuf != curbuf)
                - {
                - apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
                + if (trigger_leave_autocmds)
                + {
                + if (new_curbuf != curbuf)
                + {
                + apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
                + if (curtab != tp)
                + return FAIL;
                + }
                + apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
                if (curtab != tp)
                return FAIL;
                - }
                - apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
                - if (curtab != tp)
                - return FAIL;
                - apply_autocmds(EVENT_TABLEAVE, NULL, NULL, FALSE, curbuf);
                - if (curtab != tp)
                - return FAIL;
                + apply_autocmds(EVENT_TABLEAVE, NULL, NULL, FALSE, curbuf);
                + if (curtab != tp)
                + return FAIL;
                + }
                #endif
                #if defined(FEAT_GUI)
                /* Remove the scrollbars. They may be added back later. */
                @@ -3734,13 +3742,15 @@
                /*
                * Start using tab page "tp".
                * Only to be used after leave_tabpage() or freeing the current tab page.
                - * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
                + * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
                + * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
                */
                static void
                -enter_tabpage(tp, old_curbuf, trigger_autocmds)
                +enter_tabpage(tp, old_curbuf, trigger_enter_autocmds, trigger_leave_autocmds)
                tabpage_T *tp;
                buf_T *old_curbuf UNUSED;
                - int trigger_autocmds UNUSED;
                + int trigger_enter_autocmds UNUSED;
                + int trigger_leave_autocmds UNUSED;
                {
                int old_off = tp->tp_firstwin->w_winrow;
                win_T *next_prevwin = tp->tp_prevwin;
                @@ -3753,7 +3763,7 @@
                /* We would like doing the TabEnter event first, but we don't have a
                * valid current window yet, which may break some commands.
                * This triggers autocommands, thus may make "tp" invalid. */
                - win_enter_ext(tp->tp_curwin, FALSE, TRUE);
                + win_enter_ext(tp->tp_curwin, FALSE, TRUE, trigger_enter_autocmds, trigger_leave_autocmds);
                prevwin = next_prevwin;

                last_status(FALSE); /* status line may appear or disappear */
                @@ -3788,7 +3798,7 @@
                #ifdef FEAT_AUTOCMD
                /* Apply autocommands after updating the display, when 'rows' and
                * 'columns' have been set correctly. */
                - if (trigger_autocmds)
                + if (trigger_enter_autocmds)
                {
                apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
                if (old_curbuf != curbuf)
                @@ -3869,7 +3879,7 @@
                }
                }

                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, TRUE, TRUE);

                #ifdef FEAT_GUI_TABLINE
                if (gui_use_tabline())
                @@ -3879,23 +3889,28 @@

                /*
                * Go to tabpage "tp".
                - * Only trigger *Enter autocommands when trigger_autocmds is TRUE.
                + * Only trigger *Enter autocommands when trigger_enter_autocmds is TRUE.
                + * Only trigger *Leave autocommands when trigger_leave_autocmds is TRUE.
                * Note: doesn't update the GUI tab.
                */
                void
                -goto_tabpage_tp(tp, trigger_autocmds)
                +goto_tabpage_tp(tp, trigger_enter_autocmds, trigger_leave_autocmds)
                tabpage_T *tp;
                - int trigger_autocmds;
                + int trigger_enter_autocmds;
                + int trigger_leave_autocmds;
                {
                /* Don't repeat a message in another tab page. */
                set_keep_msg(NULL, 0);

                - if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK)
                + if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer,
                + trigger_leave_autocmds) == OK)
                {
                if (valid_tabpage(tp))
                - enter_tabpage(tp, curbuf, trigger_autocmds);
                + enter_tabpage(tp, curbuf, trigger_enter_autocmds,
                + trigger_leave_autocmds);
                else
                - enter_tabpage(curtab, curbuf, trigger_autocmds);
                + enter_tabpage(curtab, curbuf, trigger_enter_autocmds,
                + trigger_leave_autocmds);
                }
                }

                @@ -3908,7 +3923,7 @@
                tabpage_T *tp;
                win_T *wp;
                {
                - goto_tabpage_tp(tp, TRUE);
                + goto_tabpage_tp(tp, TRUE, TRUE);
                if (curtab == tp && win_valid(wp))
                {
                win_enter(wp, TRUE);
                @@ -4168,7 +4183,7 @@
                win_T *wp;
                int undo_sync;
                {
                - win_enter_ext(wp, undo_sync, FALSE);
                + win_enter_ext(wp, undo_sync, FALSE, TRUE, TRUE);
                }

                /*
                @@ -4177,10 +4192,12 @@
                * been closed and isn't valid.
                */
                static void
                -win_enter_ext(wp, undo_sync, curwin_invalid)
                +win_enter_ext(wp, undo_sync, curwin_invalid, trigger_enter_autocmds, trigger_leave_autocmds)
                win_T *wp;
                int undo_sync;
                int curwin_invalid;
                + int trigger_enter_autocmds UNUSED;
                + int trigger_leave_autocmds UNUSED;
                {
                #ifdef FEAT_AUTOCMD
                int other_buffer = FALSE;
                @@ -4190,7 +4207,7 @@
                return;

                #ifdef FEAT_AUTOCMD
                - if (!curwin_invalid)
                + if (!curwin_invalid && trigger_leave_autocmds)
                {
                /*
                * Be careful: If autocommands delete the window, return now.
                @@ -4259,9 +4276,12 @@
                }

                #ifdef FEAT_AUTOCMD
                - apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                - if (other_buffer)
                - apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
                + if (trigger_enter_autocmds)
                + {
                + apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
                + if (other_buffer)
                + apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
                + }
                #endif

                #ifdef FEAT_TITLE

                --
                --
                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 vim_dev+unsubscribe@....
                For more options, visit https://groups.google.com/groups/opt_out.
              • Bram Moolenaar
                ... Wow, that was fast, thanks! Does this patch have to be applied before your part 6 patch? -- hundred-and-one symptoms of being an internet addict: 234.
                Message 7 of 8 , Apr 26, 2013
                • 0 Attachment
                  ZyX wrote:

                  > > Thanks for figuring this out. You had some nice examples for how to
                  > > reproduce the problem you are fixing, how about turning those into a
                  > > test?
                  >
                  > Updated patch: added tests, removed few autocommands left (BufLeave,
                  > TabLeave and WinLeave from leave_tabpage). Changes from the previous
                  > patch are here:
                  > https://bitbucket.org/ZyX_I/vim/changeset/86a5abc53a8e20a2f738cd5a099da82c8de48ce3.

                  Wow, that was fast, thanks!

                  Does this patch have to be applied before your "part 6" patch?


                  --
                  hundred-and-one symptoms of being an internet addict:
                  234. You started college as a chemistry major, and walk out four years
                  later as an Internet provider.

                  /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
                  /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
                  \\\ an exciting new programming language -- http://www.Zimbu.org ///
                  \\\ 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 vim_dev+unsubscribe@....
                  For more options, visit https://groups.google.com/groups/opt_out.
                • ZyX
                  ... Actually after. There will be conflicts where is now switch_win function otherwise. I can rebase this if you wish though. -- -- You received this message
                  Message 8 of 8 , Apr 26, 2013
                  • 0 Attachment
                    > Wow, that was fast, thanks!
                    >
                    > Does this patch have to be applied before your "part 6" patch?

                    Actually after. There will be conflicts where is now switch_win function otherwise. I can rebase this if you wish though.

                    --
                    --
                    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 vim_dev+unsubscribe@....
                    For more options, visit https://groups.google.com/groups/opt_out.
                  Your message has been successfully submitted and would be delivered to recipients shortly.