updated for version 7.0201
diff --git a/src/INSTALLmac.txt b/src/INSTALLmac.txt
index adb1ca1..1c4d773 100644
--- a/src/INSTALLmac.txt
+++ b/src/INSTALLmac.txt
@@ -36,13 +36,16 @@
  directory.  You can move this bundle (the Vim.app directory) anywhere
  you want, for example, /Applications.
 
+ You need at least Xcode 1.5 to compile Vim 7.0.
+
+
 1.2 X-Windows or Plain Text
 
  If you do not want the Carbon interface, you must explicitly tell
  configure to use a different GUI.
 
   cd ..
-  ./configure --enable-gui=gtk2
+  ./configure --disable-darwin --enable-gui=gtk2
   make; make install
 
  NOTE: The following GUI options are supported:
diff --git a/src/Makefile b/src/Makefile
index 2da7860..a4b7d20 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1510,6 +1510,8 @@
 	$(ALL_GUI_PRO) \
 	$(TCL_PRO)
 
+ICON_APP = gui_mac.icns
+
 PRO_MANUAL = os_amiga.pro os_msdos.pro os_win16.pro os_win32.pro \
 	os_mswin.pro os_beos.pro os_vms.pro os_riscos.pro $(PERL_PRO)
 
@@ -2131,6 +2133,10 @@
 	cp config.mk.dist $(SHADOWDIR)
 	mkdir $(SHADOWDIR)/xxd
 	cd $(SHADOWDIR)/xxd; ln -s ../../xxd/*.[ch] ../../xxd/Make* .
+	if test -f $(ICON_APP); then \
+		cd $(SHADOWDIR); \
+		ln -s ../$(ICON_APP) ../os_mac.rsr.hqx ../dehqx.py .; \
+	fi
 	mkdir $(SHADOWDIR)/testdir
 	cd $(SHADOWDIR)/testdir; ln -s ../../testdir/Makefile \
 				 ../../testdir/vimrc.unix \
@@ -2494,7 +2500,6 @@
 		-DAPP_VER=$(VERSION) -DICON_APP=$(ICON_APP)
 
 ### Icons
-ICON_APP = gui_mac.icns
 ICONS = $(RESDIR)/$(ICON_APP)
 
 # If you uncomment the following lines the *.icns in the src directory will be
diff --git a/src/edit.c b/src/edit.c
index 9224c58..cb78cd6 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -114,7 +114,6 @@
 static pos_T	  compl_startpos;
 static colnr_T	  compl_col = 0;	    /* column where the text starts
 					     * that is being completed */
-static int	  save_sm = -1;
 static char_u	  *compl_orig_text = NULL;  /* text as it was before
 					     * completion started */
 static int	  compl_cont_mode = 0;
@@ -2733,11 +2732,19 @@
     compl_pattern = NULL;
     vim_free(compl_leader);
     compl_leader = NULL;
-    save_sm = -1;
     edit_submode_extra = NULL;
 }
 
 /*
+ * Return TRUE when Insert completion is active.
+ */
+    int
+ins_compl_active()
+{
+    return compl_started;
+}
+
+/*
  * Delete one character before the cursor and show the subset of the matches
  * that match the word that is now before the cursor.
  * Returns TRUE if the work is done and another char to be got from the user.
@@ -3071,8 +3078,6 @@
 	    compl_matches = 0;
 	    msg_clr_cmdline();		/* necessary for "noshowmode" */
 	    ctrl_x_mode = 0;
-	    if (save_sm >= 0)
-		p_sm = save_sm;
 	    if (edit_submode != NULL)
 	    {
 		edit_submode = NULL;
@@ -3904,10 +3909,6 @@
     {
 	/* First time we hit ^N or ^P (in a row, I mean) */
 
-	/* Turn off 'sm' so we don't show matches with ^X^L */
-	save_sm = p_sm;
-	p_sm = FALSE;
-
 	did_ai = FALSE;
 #ifdef FEAT_SMARTINDENT
 	did_si = FALSE;
diff --git a/src/eval.c b/src/eval.c
index 8c7049b..b0202cd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -621,6 +621,7 @@
 static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tagfiles __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
@@ -6983,6 +6984,7 @@
     {"synIDattr",	2, 3, f_synIDattr},
     {"synIDtrans",	1, 1, f_synIDtrans},
     {"system",		1, 2, f_system},
+    {"tabpagenr",	0, 1, f_tabpagenr},
     {"tagfiles",	0, 0, f_tagfiles},
     {"taglist",		1, 1, f_taglist},
     {"tempname",	0, 0, f_tempname},
@@ -14868,6 +14870,40 @@
 }
 
 /*
+ * "tabpagenr()" function
+ */
+/* ARGSUSED */
+    static void
+f_tabpagenr(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    int		nr = 1;
+#ifdef FEAT_WINDOWS
+    tabpage_T	*tp;
+    char_u	*arg;
+
+    if (argvars[0].v_type != VAR_UNKNOWN)
+    {
+	arg = get_tv_string_chk(&argvars[0]);
+	nr = 0;
+	if (arg != NULL)
+	{
+	    if (STRCMP(arg, "$") == 0)
+		for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+		    ++nr;
+	    else
+		EMSG2(_(e_invexpr2), arg);
+	}
+    }
+    else
+	for (tp = first_tabpage; tp != curtab; tp = tp->tp_next)
+	    ++nr;
+#endif
+    rettv->vval.v_number = nr;
+}
+
+/*
  * "tagfiles()" function
  */
 /*ARGSUSED*/
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index d505bff..9ab8b88 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -884,6 +884,8 @@
 EX(CMD_tabedit,		"tabedit",	ex_tabedit,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_tabfind,		"tabfind",	ex_tabedit,
+			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|NEEDARG|TRLBAR),
+EX(CMD_tabnew,		"tabnew",	ex_tabedit,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_tabonly,		"tabonly",	ex_tabonly,
 			TRLBAR|CMDWIN),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 495d739..1a87886 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -6228,7 +6228,7 @@
     else
 # endif
 	if (first_tabpage->tp_next == NULL)
-	    EMSG(_("E999: Cannot close last tab page"));
+	    EMSG(_("E784: Cannot close last tab page"));
 	else
 	{
 	    if (eap->addr_count > 0)
@@ -6239,7 +6239,7 @@
 		    beep_flush();
 		    return;
 		}
-		if (tp->tp_topframe != topframe)
+		if (tp != curtab)
 		{
 		    tabpage_close_other(tp, eap->forceit);
 		    return;
@@ -6975,9 +6975,10 @@
 }
 
 /*
- * :tabedit [[+command] file]	open new Tab page with empty window
- * :tabedit [[+command] file]	open new Tab page and edit "file"
- * :tabfind [[+command] file]	open new Tab page and find "file"
+ * :tabedit			open new Tab page with empty window
+ * :tabedit [+command] file	open new Tab page and edit "file"
+ * :tabnew [[+command] file]	just like :tabedit
+ * :tabfind [+command] file	open new Tab page and find "file"
  */
     void
 ex_tabedit(eap)
@@ -10626,6 +10627,11 @@
 		eap->errmsg = e_trailing;
 		return;
 	    }
+	    if (*end != *p)
+	    {
+		EMSG2(_(e_invarg2), p);
+		return;
+	    }
 
 	    c = *end;
 	    *end = NUL;
diff --git a/src/fileio.c b/src/fileio.c
index 437a4b6..de101c8 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6960,8 +6960,10 @@
     {"SpellFileMissing",EVENT_SPELLFILEMISSING},
     {"StdinReadPost",	EVENT_STDINREADPOST},
     {"StdinReadPre",	EVENT_STDINREADPRE},
-    {"Syntax",		EVENT_SYNTAX},
     {"SwapExists",	EVENT_SWAPEXISTS},
+    {"Syntax",		EVENT_SYNTAX},
+    {"TabEnterPost",	EVENT_TABENTERPOST},
+    {"TabLeavePre",	EVENT_TABLEAVEPRE},
     {"TermChanged",	EVENT_TERMCHANGED},
     {"TermResponse",	EVENT_TERMRESPONSE},
     {"User",		EVENT_USER},
diff --git a/src/gui.c b/src/gui.c
index 4f18988..0047a26 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -3598,14 +3598,9 @@
      * have both a left and right scrollbar, and we drag one of them, we still
      * need to update the other one.
      */
-    if (       (gui.dragged_sb == SBAR_LEFT
-		|| gui.dragged_sb == SBAR_RIGHT)
-	    && (!gui.which_scrollbars[SBAR_LEFT]
-		|| !gui.which_scrollbars[SBAR_RIGHT])
-	    && !force)
-	return;
-
-    if (!force && (gui.dragged_sb == SBAR_LEFT || gui.dragged_sb == SBAR_RIGHT))
+    if (!force && (gui.dragged_sb == SBAR_LEFT || gui.dragged_sb == SBAR_RIGHT)
+	    && gui.which_scrollbars[SBAR_LEFT]
+	    && gui.which_scrollbars[SBAR_RIGHT])
     {
 	/*
 	 * If we have two scrollbars and one of them is being dragged, just
@@ -3618,7 +3613,6 @@
 		    gui.dragged_wp->w_scrollbars[0].value,
 		    gui.dragged_wp->w_scrollbars[0].size,
 		    gui.dragged_wp->w_scrollbars[0].max);
-	return;
     }
 
     /* avoid that moving components around generates events */
@@ -3628,6 +3622,12 @@
     {
 	if (wp->w_buffer == NULL)	/* just in case */
 	    continue;
+	/* Skip a scrollbar that is being dragged. */
+	if (!force && (gui.dragged_sb == SBAR_LEFT
+					     || gui.dragged_sb == SBAR_RIGHT)
+		&& gui.dragged_wp == wp)
+	    continue;
+
 #ifdef SCROLL_PAST_END
 	max = wp->w_buffer->b_ml.ml_line_count - 1;
 #else
@@ -3759,11 +3759,12 @@
 #endif
 	    sb->size = size;
 	    sb->max = max;
-	    if (gui.which_scrollbars[SBAR_LEFT] && gui.dragged_sb != SBAR_LEFT)
+	    if (gui.which_scrollbars[SBAR_LEFT]
+		    && (gui.dragged_sb != SBAR_LEFT || gui.dragged_wp != wp))
 		gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_LEFT],
 					    val, size, max);
 	    if (gui.which_scrollbars[SBAR_RIGHT]
-					&& gui.dragged_sb != SBAR_RIGHT)
+		    && (gui.dragged_sb != SBAR_RIGHT || gui.dragged_wp != wp))
 		gui_mch_set_scrollbar_thumb(&wp->w_scrollbars[SBAR_RIGHT],
 					    val, size, max);
 	}
diff --git a/src/main.c b/src/main.c
index 31c6f6f..3dc72e1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1710,15 +1710,6 @@
 #endif
 		break;
 
-#ifdef TARGET_API_MAC_OSX
-		/* For some reason on MacOS X, an argument like:
-		   -psn_0_10223617 is passed in when invoke from Finder
-		   or with the 'open' command */
-	    case 'p':
-		argv_idx = -1; /* bypass full -psn */
-		main_start_gui();
-		break;
-#endif
 	    case 'M':		/* "-M"  no changes or writing of files */
 		reset_modifiable();
 		/* FALLTHROUGH */
@@ -1743,6 +1734,17 @@
 		break;
 
 	    case 'p':		/* "-p[N]" open N tab pages */
+#ifdef TARGET_API_MAC_OSX
+		/* For some reason on MacOS X, an argument like:
+		   -psn_0_10223617 is passed in when invoke from Finder
+		   or with the 'open' command */
+		if (argv[0][argv_idx] == 's')
+		{
+		    argv_idx = -1; /* bypass full -psn */
+		    main_start_gui();
+		    break;
+		}
+#endif
 #ifdef FEAT_WINDOWS
 		/* default is 0: open window for each file */
 		parmp->window_count = get_number_arg((char_u *)argv[0],
diff --git a/src/misc1.c b/src/misc1.c
index bcc43da..97e4196 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2034,6 +2034,9 @@
 #ifdef FEAT_MBYTE
 	    && charlen == 1
 #endif
+#ifdef FEAT_INS_EXPAND
+	    && !ins_compl_active()
+#endif
        )
 	showmatch(c);
 
diff --git a/src/proto/edit.pro b/src/proto/edit.pro
index 3939efc..5434b1c 100644
--- a/src/proto/edit.pro
+++ b/src/proto/edit.pro
@@ -12,6 +12,7 @@
 void ins_compl_show_pum __ARGS((void));
 char_u *find_word_start __ARGS((char_u *ptr));
 char_u *find_word_end __ARGS((char_u *ptr));
+int ins_compl_active __ARGS((void));
 void ins_compl_check_keys __ARGS((int frequency));
 int get_literal __ARGS((void));
 void insertchar __ARGS((int c, int flags, int second_indent));
diff --git a/src/screen.c b/src/screen.c
index 928b1b0..f36ac81 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -2516,6 +2516,7 @@
     long	v;
 
     int		char_attr = 0;		/* attributes for next character */
+    int		attr_pri = FALSE;	/* char_attr has priority */
     int		area_highlighting = FALSE; /* Visual or incsearch highlighting
 					      in this line */
     int		attr = 0;		/* attributes for area highlighting */
@@ -2764,7 +2765,7 @@
     }
 
     /*
-     * handle 'insearch' and ":s///c" highlighting
+     * handle 'incsearch' and ":s///c" highlighting
      */
     else
 #endif /* FEAT_VISUAL */
@@ -3287,14 +3288,7 @@
 	    else if (area_attr != 0
 		    && (vcol == tocol
 			|| (noinvcur && (colnr_T)vcol == wp->w_virtcol)))
-#ifdef LINE_ATTR
-		area_attr = line_attr;		/* stop highlighting */
-	    else if (line_attr && ((fromcol == -10 && tocol == MAXCOL)
-					 || (vcol < fromcol || vcol > tocol)))
-		area_attr = line_attr;
-#else
 		area_attr = 0;			/* stop highlighting */
-#endif
 
 #ifdef FEAT_SEARCH_EXTRA
 	    if (!n_extra)
@@ -3370,33 +3364,40 @@
 	    }
 #endif
 
-	    if (area_attr != 0)
-		char_attr = area_attr;
-#ifdef FEAT_SYN_HL
-	    else if (search_attr == 0 && has_syntax)
-		char_attr = syntax_attr;
-#endif
-	    else
-		char_attr = search_attr;
-
 #ifdef FEAT_DIFF
-	    if (diff_hlf != (hlf_T)0 && n_extra == 0)
+	    if (diff_hlf != (hlf_T)0)
 	    {
 		if (diff_hlf == HLF_CHD && ptr - line >= change_start)
 		    diff_hlf = HLF_TXD;		/* changed text */
 		if (diff_hlf == HLF_TXD && ptr - line > change_end)
 		    diff_hlf = HLF_CHD;		/* changed line */
-		if (attr == 0 || area_attr != attr)
-		    area_attr = hl_attr(diff_hlf);
-		if (attr == 0 || char_attr != attr)
-		{
-		    if (search_attr != 0)
-			char_attr = search_attr;
-		    else
-			char_attr = hl_attr(diff_hlf);
-		}
+		line_attr = hl_attr(diff_hlf);
 	    }
 #endif
+
+	    /* Decide which of the highlight attributes to use. */
+	    attr_pri = TRUE;
+	    if (area_attr != 0)
+		char_attr = area_attr;
+	    else if (search_attr != 0)
+		char_attr = search_attr;
+#ifdef LINE_ATTR
+		/* Use line_attr when not in the Visual or 'incsearch' area
+		 * (area_attr may be 0 when "noinvcur" is set). */
+	    else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL)
+					|| (vcol < fromcol || vcol >= tocol)))
+		char_attr = line_attr;
+#endif
+	    else
+	    {
+		attr_pri = FALSE;
+#ifdef FEAT_SYN_HL
+		if (has_syntax)
+		    char_attr = syntax_attr;
+		else
+#endif
+		    char_attr = 0;
+	    }
 	}
 
 	/*
@@ -3727,7 +3728,7 @@
 		    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
 		    ptr = line + v;
 
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 			char_attr = syntax_attr;
 		    else
 			char_attr = hl_combine_attr(syntax_attr, char_attr);
@@ -3740,7 +3741,7 @@
 		if (has_spell && v >= word_end && v > cur_checked_col)
 		{
 		    spell_attr = 0;
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 			char_attr = syntax_attr;
 		    if (c != 0 && (!has_syntax || can_spell))
 		    {
@@ -3813,7 +3814,7 @@
 		}
 		if (spell_attr != 0)
 		{
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 			char_attr = hl_combine_attr(char_attr, spell_attr);
 		    else
 			char_attr = hl_combine_attr(spell_attr, char_attr);
@@ -3840,7 +3841,7 @@
 		if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ')
 		{
 		    c = lcs_trail;
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 		    {
 			n_attr = 1;
 			extra_attr = hl_attr(HLF_8);
@@ -3953,7 +3954,7 @@
 			c = ' ';
 		    lcs_eol_one = -1;
 		    --ptr;	    /* put it back at the NUL */
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 		    {
 			extra_attr = hl_attr(HLF_AT);
 			n_attr = 1;
@@ -3979,7 +3980,7 @@
 		    n_extra = byte2cells(c) - 1;
 		    c_extra = NUL;
 		    c = *p_extra++;
-		    if (area_attr == 0 && search_attr == 0)
+		    if (!attr_pri)
 		    {
 			n_attr = n_extra + 1;
 			extra_attr = hl_attr(HLF_8);
@@ -4042,8 +4043,7 @@
 	/* Don't override visual selection highlighting. */
 	if (n_attr > 0
 		&& draw_state == WL_LINE
-		&& (area_attr == 0 || char_attr != area_attr)
-		&& (search_attr == 0 || char_attr != search_attr))
+		&& !attr_pri)
 	    char_attr = extra_attr;
 
 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
@@ -4108,8 +4108,7 @@
 	    else
 		mb_utf8 = FALSE;	/* don't draw as UTF-8 */
 #endif
-	    if ((area_attr == 0 || char_attr != area_attr)
-		    && (search_attr == 0 || char_attr != search_attr))
+	    if (!attr_pri)
 	    {
 		saved_attr3 = char_attr; /* save current attr */
 		char_attr = hl_attr(HLF_AT); /* later copied to char_attr */
diff --git a/src/version.h b/src/version.h
index 80a3f61..e09294a 100644
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 17)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 17, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 18)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 18, compiled "
diff --git a/src/vim.h b/src/vim.h
index 9af9514..ef86e81 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -347,7 +347,7 @@
 /*
  * The characters and attributes cached for the screen.
  */
-#define schar_T	char_u
+typedef char_u schar_T;
 #ifdef FEAT_SYN_HL
 typedef unsigned short sattr_T;
 # define MAX_TYPENR 65535
@@ -1109,6 +1109,8 @@
     EVENT_SPELLFILEMISSING,	/* spell file missing */
     EVENT_CURSORMOVED,		/* cursor was moved */
     EVENT_CURSORMOVEDI,		/* cursor was moved in Insert mode */
+    EVENT_TABLEAVEPRE,		/* before leaving a tab page */
+    EVENT_TABENTERPOST,		/* after entering a tab page */
     NUM_EVENTS			/* MUST be the last one */
 };
 
diff --git a/src/window.c b/src/window.c
index 03cc56c..b117fe3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -46,7 +46,7 @@
 #if defined(FEAT_WINDOWS) || defined(PROTO)
 static tabpage_T *alloc_tabpage __ARGS((void));
 static void free_tabpage __ARGS((tabpage_T *tp));
-static void leave_tabpage __ARGS((tabpage_T *tp));
+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));
@@ -2282,15 +2282,15 @@
 {
     tabpage_T	*tp;
 
-    /* Use the next tab page if it exists. */
-    if (curtab->tp_next != NULL)
+    /* Use the next tab page if we are currently at the first one. */
+    if (curtab == first_tabpage)
 	return curtab->tp_next;
 
     /* Find the previous tab page. */
     for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next)
 	if (tp->tp_next == curtab)
-	    return tp;
-    return first_tabpage;
+	    break;
+    return tp;
 }
 
 /*
@@ -2963,7 +2963,11 @@
 	return FAIL;
 
     /* Remember the current windows in this Tab page. */
-    leave_tabpage(curtab);
+    if (leave_tabpage(NULL) == FAIL)
+    {
+	vim_free(newtp);
+	return FAIL;
+    }
     curtab = newtp;
 
     /* Create a new empty window. */
@@ -2985,12 +2989,7 @@
     }
 
     /* Failed, get back the previous Tab page */
-    topframe = tp->tp_topframe;
-    curwin = tp->tp_curwin;
-    prevwin = tp->tp_prevwin;
-    firstwin = tp->tp_firstwin;
-    lastwin = tp->tp_lastwin;
-    curtab = tp;
+    enter_tabpage(curtab, curbuf);
     return FAIL;
 }
 
@@ -3060,12 +3059,33 @@
 }
 
 /*
- * Prepare for leaving the current tab page "tp".
+ * Prepare for leaving the current tab page.
+ * When autocomands change "curtab" we don't leave the tab page and return
+ * FAIL.
+ * Careful: When OK is returned need to get a new tab page very very soon!
  */
-    static void
-leave_tabpage(tp)
-    tabpage_T	*tp;
+/*ARGSUSED*/
+    static int
+leave_tabpage(new_curbuf)
+    buf_T	*new_curbuf;	    /* what is going to be the new curbuf,
+				       NULL if unknown */
 {
+    tabpage_T	*tp = curtab;
+
+#ifdef FEAT_AUTOCMD
+    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_TABLEAVEPRE, NULL, NULL, FALSE, curbuf);
+    if (curtab != tp)
+	return FAIL;
+#endif
 #if defined(FEAT_GUI)
     /* Remove the scrollbars.  They may be added back later. */
     if (gui.in_use)
@@ -3079,6 +3099,7 @@
     tp->tp_old_Columns = Columns;
     firstwin = NULL;
     lastwin = NULL;
+    return OK;
 }
 
 /*
@@ -3100,6 +3121,8 @@
     prevwin = tp->tp_prevwin;
 
 #ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_TABENTERPOST, 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
@@ -3114,10 +3137,10 @@
     /* The tabpage line may have appeared or disappeared, may need to resize
      * the frames for that.  When the Vim window was resized need to update
      * frame sizes too. */
-    if (tp->tp_old_Rows != Rows || old_off != firstwin->w_winrow)
+    if (curtab->tp_old_Rows != Rows || old_off != firstwin->w_winrow)
 	shell_new_rows();
 #ifdef FEAT_VERTSPLIT
-    if (tp->tp_old_Columns != Columns && starting == 0)
+    if (curtab->tp_old_Columns != Columns && starting == 0)
 	shell_new_columns();	/* update window widths */
 #endif
 
@@ -3143,20 +3166,16 @@
 goto_tabpage(n)
     int	    n;
 {
-    tabpage_T	*otp = curtab;
     tabpage_T	*tp;
     int		i;
 
-    if (otp == NULL)
-	return;
-
     if (n == 0)
     {
 	/* No count, go to next tab page, wrap around end. */
-	if (otp->tp_next == NULL)
+	if (curtab->tp_next == NULL)
 	    tp = first_tabpage;
 	else
-	    tp = otp->tp_next;
+	    tp = curtab->tp_next;
     }
     else
     {
@@ -3171,8 +3190,13 @@
 	}
     }
 
-    leave_tabpage(otp);
-    enter_tabpage(tp, curbuf);
+    if (leave_tabpage(tp->tp_curwin->w_buffer) == OK)
+    {
+	if (valid_tabpage(tp))
+	    enter_tabpage(tp, curbuf);
+	else
+	    enter_tabpage(curtab, curbuf);
+    }
 }
 
 /*