updated for version 7.0199
diff --git a/src/auto/configure b/src/auto/configure
index 794fd8f..05897e2 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -15088,7 +15088,7 @@
 DEPEND_CFLAGS_FILTER=
 if test "$GCC" = yes; then
   gccmajor=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\([1-9]\)\.[0-9.]*.*$/\1/g'`
-  if test "$gccmajor" > "2"; then
+  if test "$gccmajor" -gt "2"; then
     DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'"
   fi
 fi
diff --git a/src/buffer.c b/src/buffer.c
index eb8799c..28ed6b9 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1062,21 +1062,7 @@
 
 	    /* Close any other windows on this buffer, then make it empty. */
 #ifdef FEAT_WINDOWS
-	    {
-		win_T	*wp, *nextwp;
-
-		for (wp = firstwin; wp != NULL; wp = nextwp)
-		{
-		    nextwp = wp->w_next;
-		    if (wp != curwin && wp->w_buffer == buf)
-		    {
-			/* Start all over, autocommands may change the window
-			 * layout. */
-			nextwp = firstwin;
-			win_close(wp, FALSE);
-		    }
-		}
-	    }
+	    close_windows(buf, TRUE);
 #endif
 	    setpcmark();
 	    retval = do_ecmd(0, NULL, NULL, NULL, ECMD_ONE,
@@ -1095,9 +1081,11 @@
 #ifdef FEAT_WINDOWS
 	/*
 	 * If the deleted buffer is the current one, close the current window
-	 * (unless it's the only window).
+	 * (unless it's the only window).  Repeat this so long as we end up in
+	 * a window with this buffer.
 	 */
-	while (buf == curbuf && firstwin != lastwin)
+	while (buf == curbuf
+		   && (firstwin != lastwin || first_tabpage->tp_next != NULL))
 	    win_close(curwin, FALSE);
 #endif
 
@@ -1107,7 +1095,7 @@
 	if (buf != curbuf)
 	{
 #ifdef FEAT_WINDOWS
-	    close_windows(buf);
+	    close_windows(buf, FALSE);
 #endif
 	    if (buf != curbuf && buf_valid(buf) && buf->b_nwindows <= 0)
 		close_buffer(NULL, buf, action);
@@ -1317,7 +1305,7 @@
     {
 #ifdef FEAT_WINDOWS
 	if (unload)
-	    close_windows(prevbuf);
+	    close_windows(prevbuf, FALSE);
 #endif
 #if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
 	if (buf_valid(prevbuf) && !aborting())
@@ -4707,6 +4695,7 @@
     buf_T	*buf;
 #ifdef FEAT_WINDOWS
     win_T	*win;
+    tabpage_T	*tp;
 #endif
     char_u	*line;
     int		max_buffers;
@@ -4723,7 +4712,7 @@
 	return;
 
 #ifdef FEAT_WINDOWS
-    for (win = firstwin; win != NULL; win = win->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, win)
 	set_last_cursor(win);
 #else
     set_last_cursor(curwin);
diff --git a/src/configure.in b/src/configure.in
index 04001de..4324101 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -2761,7 +2761,7 @@
 DEPEND_CFLAGS_FILTER=
 if test "$GCC" = yes; then
   gccmajor=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\([[1-9]]\)\.[[0-9.]]*.*$/\1/g'`
-  if test "$gccmajor" > "2"; then
+  if test "$gccmajor" -gt "2"; then
     DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'"
   fi
 fi
diff --git a/src/diff.c b/src/diff.c
index 22e18f3..7c5bbd3 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1075,6 +1075,7 @@
 
 /*
  * Set options not to show diffs.  For the current window or all windows.
+ * Only in the current tab page.
  */
     void
 ex_diffoff(eap)
diff --git a/src/eval.c b/src/eval.c
index 6ec0975..d29f1a4 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -15509,11 +15509,13 @@
 	pos.col = 0;
 	if (name[1] == '0')		/* "w0": first visible line */
 	{
+	    update_topline();
 	    pos.lnum = curwin->w_topline;
 	    return &pos;
 	}
 	else if (name[1] == '$')	/* "w$": last visible line */
 	{
+	    validate_botline();
 	    pos.lnum = curwin->w_botline - 1;
 	    return &pos;
 	}
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 8a7999f..0e671c8 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -1761,8 +1761,9 @@
 {
 #ifdef FEAT_WINDOWS
     win_T	*win;
+    tabpage_T	*tp;
 
-    for (win = firstwin; win != NULL; win = win->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, win)
 	if (win->w_alist == curwin->w_alist)
 	    check_arg_idx(win);
 #else
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index e87bb6f..195f19d 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -148,7 +148,7 @@
 static void	ex_quit_all __ARGS((exarg_T *eap));
 #ifdef FEAT_WINDOWS
 static void	ex_close __ARGS((exarg_T *eap));
-static void	ex_win_close __ARGS((int forceit, win_T *win));
+static void	ex_win_close __ARGS((int forceit, win_T *win, tabpage_T *tp));
 static void	ex_only __ARGS((exarg_T *eap));
 static void	ex_all __ARGS((exarg_T *eap));
 static void	ex_resize __ARGS((exarg_T *eap));
@@ -6144,7 +6144,7 @@
     else
 # endif
 	if (!text_locked())
-	    ex_win_close(eap->forceit, curwin);
+	    ex_win_close(eap->forceit, curwin, NULL);
 }
 
 #ifdef FEAT_QUICKFIX
@@ -6160,16 +6160,21 @@
     for (win = firstwin; win != NULL; win = win->w_next)
 	if (win->w_p_pvw)
 	{
-	    ex_win_close(eap->forceit, win);
+	    ex_win_close(eap->forceit, win, NULL);
 	    break;
 	}
 }
 #endif
 
+/*
+ * Close window "win" and take care of handling closing the last window for a
+ * modified buffer.
+ */
     static void
-ex_win_close(forceit, win)
+ex_win_close(forceit, win, tp)
     int		forceit;
     win_T	*win;
+    tabpage_T	*tp;		/* NULL or the tab page "win" is in */
 {
     int		need_hide;
     buf_T	*buf = win->w_buffer;
@@ -6196,39 +6201,93 @@
 #ifdef FEAT_GUI
     need_mouse_correct = TRUE;
 #endif
+
     /* free buffer when not hiding it or when it's a scratch buffer */
-    win_close(win, !need_hide && !P_HID(buf));
+    if (tp == NULL)
+	win_close(win, !need_hide && !P_HID(buf));
+    else
+	win_close_othertab(win, !need_hide && !P_HID(buf), tp);
 }
 
 /*
- * ":tabclose": close current tab page, unless it is the last one
+ * ":tabclose": close current tab page, unless it is the last one.
+ * ":tabclose N": close tab page N.
  */
     static void
 ex_tabclose(eap)
     exarg_T	*eap;
 {
+    tabpage_T	*tp;
+
 # ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
 	cmdwin_result = K_IGNORE;
     else
 # endif
-	if (!text_locked())
+	if (first_tabpage->tp_next == NULL)
+	    EMSG(_("E999: Cannot close last tab page"));
+	else
 	{
-	    if (first_tabpage->tp_next == NULL)
-		EMSG(_("E999: Cannot close last tab page"));
-	    else
+	    if (eap->addr_count > 0)
 	    {
-		/* First close all the windows but the current one.  If that
-		 * worked then close the last window in this tab, that will
-		 * close it. */
-		ex_only(eap);
-		if (lastwin == firstwin)
-		    ex_win_close(eap->forceit, curwin);
+		tp = find_tabpage((int)eap->line2);
+		if (tp == NULL)
+		{
+		    beep_flush();
+		    return;
+		}
+		if (tp->tp_topframe != topframe)
+		{
+		    tabpage_close_other(tp, eap->forceit);
+		    return;
+		}
 	    }
+	    if (!text_locked())
+		tabpage_close(eap->forceit);
 	}
 }
 
 /*
+ * Close the current tab page.
+ */
+    void
+tabpage_close(forceit)
+    int	    forceit;
+{
+    /* First close all the windows but the current one.  If that worked then
+     * close the last window in this tab, that will close it. */
+    close_others(TRUE, forceit);
+    if (lastwin == firstwin)
+	ex_win_close(forceit, curwin, NULL);
+# ifdef FEAT_GUI
+    need_mouse_correct = TRUE;
+# endif
+}
+
+/*
+ * Close tab page "tp", which is not the current tab page.
+ * Note that autocommands may make "tp" invalid.
+ */
+    void
+tabpage_close_other(tp, forceit)
+    tabpage_T	*tp;
+    int		forceit;
+{
+    int		done = 0;
+
+    /* Limit to 1000 windows, autocommands may add a window while we close
+     * one.  OK, so I'm paranoid... */
+    while (++done < 1000)
+    {
+	ex_win_close(forceit, tp->tp_firstwin, tp);
+
+	/* Autocommands may delete the tab page under our fingers. */
+	if (!valid_tabpage(tp))
+	    break;
+    }
+}
+
+/*
  * ":only".
  */
     static void
@@ -6689,13 +6748,14 @@
     int		i;
 # ifdef FEAT_WINDOWS
     win_T	*wp;
+    tabpage_T	*tp;
 # endif
 
     for (i = 0; i < GARGCOUNT; ++i)
 	if (GARGLIST[i].ae_fname != NULL)
 	    slash_adjust(GARGLIST[i].ae_fname);
 # ifdef FEAT_WINDOWS
-    for (wp = firstwin; wp != NULL; wp = wp->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, wp)
 	if (wp->w_alist != &global_alist)
 	    for (i = 0; i < WARGCOUNT(wp); ++i)
 		if (WARGLIST(wp)[i].ae_fname != NULL)
@@ -6925,7 +6985,8 @@
 # ifdef FEAT_SCROLLBIND
 	curwin->w_p_scb = FALSE;
 # endif
-	do_exedit(eap, NULL);
+	if (*eap->arg != NUL)
+	    do_exedit(eap, NULL);
     }
 
 # ifdef FEAT_BROWSE
diff --git a/src/globals.h b/src/globals.h
index 57d7d09..c6409b9 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -42,7 +42,7 @@
 EXTERN schar_T	*ScreenLines INIT(= NULL);
 EXTERN sattr_T	*ScreenAttrs INIT(= NULL);
 EXTERN unsigned	*LineOffset INIT(= NULL);
-EXTERN char_u	*LineWraps INIT(= NULL);
+EXTERN char_u	*LineWraps INIT(= NULL);	/* line wraps to next line */
 
 #ifdef FEAT_MBYTE
 /*
@@ -61,6 +61,10 @@
 EXTERN schar_T	*ScreenLines2 INIT(= NULL);
 #endif
 
+#ifdef FEAT_WINDOWS
+EXTERN char_u	*TabPageIdxs INIT(= NULL);	/* indexes for tab page line */
+#endif
+
 EXTERN int	screen_Rows INIT(= 0);	    /* actual size of ScreenLines[] */
 EXTERN int	screen_Columns INIT(= 0);   /* actual size of ScreenLines[] */
 
@@ -482,6 +486,10 @@
 EXTERN win_T	*prevwin INIT(= NULL);	/* previous window */
 # define W_NEXT(wp) ((wp)->w_next)
 # define FOR_ALL_WINDOWS(wp) for (wp = firstwin; wp != NULL; wp = wp->w_next)
+#define FOR_ALL_TAB_WINDOWS(tp, wp) \
+    for ((tp) = first_tabpage; (tp) != NULL; (tp) = (tp)->tp_next) \
+	for ((wp) = ((tp)->tp_topframe == topframe) \
+		? firstwin : (tp)->tp_firstwin; (wp); (wp) = (wp)->w_next)
 #else
 # define firstwin curwin
 # define lastwin curwin
diff --git a/src/if_mzsch.c b/src/if_mzsch.c
index 4d5bb32..9eb524a 100644
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -1423,7 +1423,8 @@
     win_T   *w;
     int	    n = 0;
 
-    for (w = firstwin; w; w = w->w_next) ++n;
+    for (w = firstwin; w != NULL; w = w->w_next)
+	++n;
     return scheme_make_integer(n);
 }
 
@@ -1439,7 +1440,7 @@
     buf = get_buffer_arg(prim->name, 0, argc, argv);
     list = scheme_null;
 
-    for (w = firstwin; w; w = w->w_next)
+    for (w = firstwin; w != NULL; w = w->w_next)
         if (w->w_buffer == buf->buf)
 	    list = scheme_make_pair(window_new(w), list);
 
@@ -1500,7 +1501,7 @@
     if (fnum < 1)
 	scheme_signal_error(_("window index is out of range"));
 
-    for (win = firstwin; win; win = win->w_next, --fnum)
+    for (win = firstwin; win != NULL; win = win->w_next, --fnum)
         if (fnum == 1)	    /* to be 1-based */
 	    return window_new(win);
 
diff --git a/src/if_python.c b/src/if_python.c
index d0ce401..dbbe602 100644
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -2160,7 +2160,7 @@
     win_T	*w = firstwin;
     int		n = 0;
 
-    while (w)
+    while (w != NULL)
     {
 	++n;
 	w = W_NEXT(w);
@@ -2175,7 +2175,7 @@
 {
     win_T *w;
 
-    for (w = firstwin; w; w = W_NEXT(w), --n)
+    for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
 	if (n == 0)
 	    return WindowNew(w);
 
diff --git a/src/if_ruby.c b/src/if_ruby.c
index f09b220..bacd6c7 100644
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -726,7 +726,7 @@
     win_T	*w;
     int n = 0;
 
-    for (w = firstwin; w; w = w->w_next)
+    for (w = firstwin; w != NULL; w = w->w_next)
 	n++;
     return INT2NUM(n);
 #else
diff --git a/src/main.c b/src/main.c
index 81e41b6..1a71be9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1133,6 +1133,7 @@
 #ifdef FEAT_AUTOCMD
     buf_T	*buf;
     win_T	*wp;
+    tabpage_T	*tp, *next_tp;
 #endif
 
     exiting = TRUE;
@@ -1160,23 +1161,28 @@
 
 #ifdef FEAT_AUTOCMD
     /* Trigger BufWinLeave for all windows, but only once per buffer. */
-    for (wp = firstwin; wp != NULL; )
+# if defined FEAT_WINDOWS
+    for (tp = first_tabpage; tp != NULL; tp = next_tp)
     {
-	buf = wp->w_buffer;
-	if (buf->b_changedtick != -1)
+	next_tp = tp->tp_next;
+	for (wp = (tp->tp_topframe == topframe)
+		    ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next)
 	{
-	    apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
+	    buf = wp->w_buffer;
+	    if (buf->b_changedtick != -1)
+	    {
+		apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
 								  FALSE, buf);
-	    buf->b_changedtick = -1;	/* note that we did it already */
-	    wp = firstwin;		/* restart, window may be closed */
+		buf->b_changedtick = -1;    /* note that we did it already */
+		/* start all over, autocommands may mess up the lists */
+		next_tp = first_tabpage;
+		break;
+	    }
 	}
-# ifdef FEAT_WINDOWS
-	else
-	    wp = wp->w_next;
-# else
-	break;
-# endif
     }
+# else
+    apply_autocmds(EVENT_BUFWINLEAVE, curbuf, curbuf->b_fname, FALSE, curbuf);
+# endif
 
     /* Trigger BufUnload for buffers that are loaded */
     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
diff --git a/src/mark.c b/src/mark.c
index f077b11..193d768 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -1500,11 +1500,12 @@
     int		i;
 #ifdef FEAT_WINDOWS
     win_T	*win;
+    tabpage_T	*tp;
 
     /*
      * Set b_last_cursor for the all buffers that have a window.
      */
-    for (win = firstwin; win != NULL; win = win->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, win)
 	set_last_cursor(win);
 #else
 	set_last_cursor(curwin);
diff --git a/src/misc1.c b/src/misc1.c
index 300aeff..fc56c91 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -2458,6 +2458,7 @@
 	ml_setflags(curbuf);
 #ifdef FEAT_WINDOWS
 	check_status(curbuf);
+	redraw_tabpage = TRUE;
 #endif
 #ifdef FEAT_TITLE
 	need_maketitle = TRUE;	    /* set window title later */
@@ -2847,6 +2848,7 @@
 	    save_file_ff(buf);
 #ifdef FEAT_WINDOWS
 	check_status(buf);
+	redraw_tabpage = TRUE;
 #endif
 #ifdef FEAT_TITLE
 	need_maketitle = TRUE;	    /* set window title later */
diff --git a/src/misc2.c b/src/misc2.c
index 328bdf2..2ff4d5c 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -2790,7 +2790,9 @@
 	set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
 							OPT_FREE | opt_flags);
 #ifdef FEAT_WINDOWS
+    /* This may cause the buffer to become (un)modified. */
     check_status(curbuf);
+    redraw_tabpage = TRUE;
 #endif
 #ifdef FEAT_TITLE
     need_maketitle = TRUE;	    /* set window title later */
diff --git a/src/normal.c b/src/normal.c
index d4001b4..d910bbe 100644
--- a/src/normal.c
+++ b/src/normal.c
@@ -2421,6 +2421,37 @@
 
     start_visual.lnum = 0;
 
+#ifdef FEAT_WINDOWS
+    /* Check for clicking in the tab page line. */
+    if (mouse_row == 0 && firstwin->w_winrow > 0)
+    {
+	got_click = FALSE;	/* ignore mouse-up and drag events */
+
+	/* click in last column closes the current tab page. */
+	if (mouse_col == Columns - 1 && first_tabpage->tp_next != NULL)
+	{
+	    tabpage_close(FALSE);
+	    return TRUE;
+	}
+
+	/* click in a tab selects that tab page */
+	if (is_click
+# ifdef FEAT_CMDWIN
+		&& cmdwin_type == 0
+# endif
+		&& mouse_col < Columns && TabPageIdxs[mouse_col] != 0xff)
+	{
+	    goto_tabpage(TabPageIdxs[mouse_col]);
+
+	    /* It's like clicking on the status line of a window. */
+	    if (curwin != old_curwin)
+		end_visual_mode();
+	    return TRUE;
+	}
+	return FALSE;
+    }
+#endif
+
     /*
      * When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
      * right button up   -> pop-up menu
diff --git a/src/option.c b/src/option.c
index 25ddafb..e955f7f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2653,6 +2653,7 @@
 
 static void set_option_default __ARGS((int, int opt_flags, int compatible));
 static void set_options_default __ARGS((int opt_flags));
+static char_u *term_bg_default __ARGS((void));
 static void did_set_option __ARGS((int opt_idx, int opt_flags, int new_value));
 static char_u *illegal_char __ARGS((char_u *, int));
 static int string_to_key __ARGS((char_u *arg));
@@ -3200,6 +3201,7 @@
     int		i;
 #ifdef FEAT_WINDOWS
     win_T	*wp;
+    tabpage_T	*tp;
 #endif
 
     for (i = 0; !istermoption(&options[i]); i++)
@@ -3208,7 +3210,7 @@
 
 #ifdef FEAT_WINDOWS
     /* The 'scroll' option must be computed for all windows. */
-    for (wp = firstwin; wp != NULL; wp = wp->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, wp)
 	win_comp_scroll(wp);
 #else
 	win_comp_scroll(curwin);
@@ -3306,39 +3308,20 @@
 	p_window = Rows - 1;
     set_number_default("window", Rows - 1);
 
+    /* For DOS console the default is always black. */
 #if !((defined(MSDOS) || defined(OS2) || defined(WIN3264)) && !defined(FEAT_GUI))
+    /*
+     * If 'background' wasn't set by the user, try guessing the value,
+     * depending on the terminal name.  Only need to check for terminals
+     * with a dark background, that can handle color.
+     */
+    idx = findoption((char_u *)"bg");
+    if (!(options[idx].flags & P_WAS_SET) && *term_bg_default() == 'd')
     {
-	char_u	*p;
-
-	/*
-	 * If 'background' wasn't set by the user, try guessing the value,
-	 * depending on the terminal name.  Only need to check for terminals
-	 * with a dark background, that can handle color.  Recognized are:
-	 * "linux"	    Linux console
-	 * "screen.linux"   Linux console with screen
-	 * "cygwin"	    Cygwin shell
-	 * "putty"	    Putty program
-	 * We also check the COLORFGBG environment variable, which is set by
-	 * rxvt and derivatives. This variable contains either two or three
-	 * values separated by semicolons; we want the last value in either
-	 * case. If this value is 0-6 or 8, our background is dark.
-	 */
-	idx = findoption((char_u *)"bg");
-	if (!(options[idx].flags & P_WAS_SET)
-		&& (STRCMP(T_NAME, "linux") == 0
-		    || STRCMP(T_NAME, "screen.linux") == 0
-		    || STRCMP(T_NAME, "cygwin") == 0
-		    || STRCMP(T_NAME, "putty") == 0
-		    || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
-			&& (p = vim_strrchr(p, ';')) != NULL
-			&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
-			&& p[2] == NUL)))
-	{
-	    set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE);
-	    /* don't mark it as set, when starting the GUI it may be
-	     * changed again */
-	    options[idx].flags &= ~P_WAS_SET;
-	}
+	set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE);
+	/* don't mark it as set, when starting the GUI it may be
+	 * changed again */
+	options[idx].flags &= ~P_WAS_SET;
     }
 #endif
 
@@ -3354,6 +3337,40 @@
 }
 
 /*
+ * Return "dark" or "light" depending on the kind of terminal.
+ * This is just guessing!  Recognized are:
+ * "linux"	    Linux console
+ * "screen.linux"   Linux console with screen
+ * "cygwin"	    Cygwin shell
+ * "putty"	    Putty program
+ * We also check the COLORFGBG environment variable, which is set by
+ * rxvt and derivatives. This variable contains either two or three
+ * values separated by semicolons; we want the last value in either
+ * case. If this value is 0-6 or 8, our background is dark.
+ */
+    static char_u *
+term_bg_default()
+{
+    char_u	*p;
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN3264)
+    /* DOS console nearly always black */
+    return (char_u *)"dark";
+#else
+    if (STRCMP(T_NAME, "linux") == 0
+	    || STRCMP(T_NAME, "screen.linux") == 0
+	    || STRCMP(T_NAME, "cygwin") == 0
+	    || STRCMP(T_NAME, "putty") == 0
+	    || ((p = mch_getenv((char_u *)"COLORFGBG")) != NULL
+		&& (p = vim_strrchr(p, ';')) != NULL
+		&& ((p[1] >= '0' && p[1] <= '6') || p[1] == '8')
+		&& p[2] == NUL))
+	return (char_u *)"dark";
+    return (char_u *)"light";
+#endif
+}
+
+/*
  * Initialize the options, part three: After reading the .vimrc
  */
     void
@@ -4071,8 +4088,7 @@
 				    newval = gui_bg_default();
 				else
 #endif
-				    if (STRCMP(T_NAME, "linux") == 0)
-					newval = (char_u *)"dark";
+				    newval = term_bg_default();
 			    }
 
 			    /* expand environment variables and ~ (since the
diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro
index a6998cf..a171e97 100644
--- a/src/proto/ex_docmd.pro
+++ b/src/proto/ex_docmd.pro
@@ -23,6 +23,8 @@
 char_u *get_user_cmd_complete __ARGS((expand_T *xp, int idx));
 int parse_compl_arg __ARGS((char_u *value, int vallen, int *complp, long *argt, char_u **compl_arg));
 void not_exiting __ARGS((void));
+void tabpage_close __ARGS((int forceit));
+void tabpage_close_other __ARGS((tabpage_T *tp, int forceit));
 void handle_drop __ARGS((int filec, char_u **filev, int split));
 void alist_clear __ARGS((alist_T *al));
 void alist_init __ARGS((alist_T *al));
diff --git a/src/proto/window.pro b/src/proto/window.pro
index 0ff745a..ae6aa63 100644
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -6,15 +6,18 @@
 int make_windows __ARGS((int count, int vertical));
 void win_move_after __ARGS((win_T *win1, win_T *win2));
 void win_equal __ARGS((win_T *next_curwin, int current, int dir));
-void close_windows __ARGS((buf_T *buf));
+void close_windows __ARGS((buf_T *buf, int keep_curwin));
 int last_window __ARGS((void));
 void win_close __ARGS((win_T *win, int free_buf));
+void win_close_othertab __ARGS((win_T *win, int free_buf, tabpage_T *tp));
 void win_free_all __ARGS((void));
 void close_others __ARGS((int message, int forceit));
 void win_init __ARGS((win_T *wp));
 int win_alloc_first __ARGS((void));
 void win_init_size __ARGS((void));
 int win_new_tabpage __ARGS((void));
+int valid_tabpage __ARGS((tabpage_T *tpc));
+tabpage_T *find_tabpage __ARGS((int n));
 void goto_tabpage __ARGS((int n));
 void win_goto __ARGS((win_T *wp));
 win_T *win_find_nr __ARGS((int winnr));
diff --git a/src/screen.c b/src/screen.c
index 9005efa..f9ed5e1 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -6742,6 +6742,10 @@
     sattr_T	    *new_ScreenAttrs;
     unsigned	    *new_LineOffset;
     char_u	    *new_LineWraps;
+#ifdef FEAT_WINDOWS
+    char_u	    *new_TabPageIdxs;
+    tabpage_T	    *tp;
+#endif
     static int	    entered = FALSE;		/* avoid recursiveness */
     static int	    did_outofmem_msg = FALSE;	/* did outofmem message */
 
@@ -6788,10 +6792,10 @@
      * size is wrong.
      */
 #ifdef FEAT_WINDOWS
-    for (wp = firstwin; wp; wp = wp->w_next)
+    FOR_ALL_TAB_WINDOWS(tp, wp)
 	win_free_lsize(wp);
 #else
-	win_free_lsize(curwin);
+    win_free_lsize(curwin);
 #endif
 
     new_ScreenLines = (schar_T *)lalloc((long_u)(
@@ -6815,6 +6819,9 @@
     new_LineOffset = (unsigned *)lalloc((long_u)(
 					 Rows * sizeof(unsigned)), FALSE);
     new_LineWraps = (char_u *)lalloc((long_u)(Rows * sizeof(char_u)), FALSE);
+#ifdef FEAT_WINDOWS
+    new_TabPageIdxs = (char_u *)lalloc((long_u)(Columns * sizeof(char_u)), FALSE);
+#endif
 
     FOR_ALL_WINDOWS(wp)
     {
@@ -6836,6 +6843,9 @@
 	    || new_ScreenAttrs == NULL
 	    || new_LineOffset == NULL
 	    || new_LineWraps == NULL
+#ifdef FEAT_WINDOWS
+	    || new_TabPageIdxs == NULL
+#endif
 	    || outofmem)
     {
 	if (ScreenLines != NULL || !did_outofmem_msg)
@@ -6865,6 +6875,10 @@
 	new_LineOffset = NULL;
 	vim_free(new_LineWraps);
 	new_LineWraps = NULL;
+#ifdef FEAT_WINDOWS
+	vim_free(new_TabPageIdxs);
+	new_TabPageIdxs = NULL;
+#endif
     }
     else
     {
@@ -6956,6 +6970,9 @@
     ScreenAttrs = new_ScreenAttrs;
     LineOffset = new_LineOffset;
     LineWraps = new_LineWraps;
+#ifdef FEAT_WINDOWS
+    TabPageIdxs = new_TabPageIdxs;
+#endif
 
     /* It's important that screen_Rows and screen_Columns reflect the actual
      * size of ScreenLines[].  Set them before calling anything. */
@@ -7005,6 +7022,9 @@
     vim_free(ScreenAttrs);
     vim_free(LineOffset);
     vim_free(LineWraps);
+#ifdef FEAT_WINDOWS
+    vim_free(TabPageIdxs);
+#endif
 }
 
     void
@@ -8443,9 +8463,13 @@
     tabpage_T	*tp;
     int		tabwidth;
     int		col = 0;
+    int		scol;
     int		had_current = FALSE;
     int		attr;
     win_T	*wp;
+    win_T	*cwp;
+    int		wincount;
+    int		modified;
     int		c;
     int		len;
     int		attr_sel = hl_attr(HLF_TPS);
@@ -8460,13 +8484,16 @@
     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
 	++tabcount;
 
-    tabwidth = Columns / tabcount;
+    tabwidth = (Columns - 1 + tabcount / 2) / tabcount;
     if (tabwidth < 6)
 	tabwidth = 6;
 
     attr = attr_nosel;
-    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+    tabcount = 0;
+    for (tp = first_tabpage; tp != NULL && col < Columns; tp = tp->tp_next)
     {
+	scol = col;
+
 	if (tp->tp_topframe == topframe)
 	{
 	    c = '/';
@@ -8486,21 +8513,55 @@
 	screen_putchar(' ', 0, col++, attr);
 
 	if (tp->tp_topframe == topframe)
-	    wp = curwin;
+	{
+	    cwp = curwin;
+	    wp = firstwin;
+	}
 	else
-	    wp = tp->tp_curwin;
-	if (buf_spname(wp->w_buffer) != NULL)
-	    STRCPY(NameBuff, buf_spname(wp->w_buffer));
+	{
+	    cwp = tp->tp_curwin;
+	    wp = tp->tp_firstwin;
+	}
+
+	modified = FALSE;
+	for (wincount = 0; wp != NULL; wp = wp->w_next, ++wincount)
+	    if (bufIsChanged(wp->w_buffer))
+		modified = TRUE;
+	if (modified || wincount > 1)
+	{
+	    if (wincount > 1)
+	    {
+		vim_snprintf((char *)NameBuff, MAXPATHL, "#%d", wincount);
+		len = STRLEN(NameBuff);
+		screen_puts_len(NameBuff, len, 0, col, attr);
+		col += len;
+	    }
+	    if (modified)
+		screen_puts_len((char_u *)"+", 2, 0, col++, attr);
+	    screen_putchar(' ', 0, col++, attr);
+	}
+
+	if (buf_spname(cwp->w_buffer) != NULL)
+	    STRCPY(NameBuff, buf_spname(cwp->w_buffer));
 	else
-	    home_replace(wp->w_buffer, wp->w_buffer->b_fname, NameBuff,
+	    home_replace(cwp->w_buffer, cwp->w_buffer->b_fname, NameBuff,
 							      MAXPATHL, TRUE);
 	trans_characters(NameBuff, MAXPATHL);
 	len = STRLEN(NameBuff);
-	if (len > tabwidth) /* TODO: multi-byte chars */
-	    len = tabwidth;
-	screen_puts_len(NameBuff, len, 0, col, attr);
-	col += len;
+	if (len > scol - col + tabwidth - 1) /* TODO: multi-byte chars */
+	    len = scol - col + tabwidth - 1;
+	if (len > 0)
+	{
+	    screen_puts_len(NameBuff, len, 0, col, attr);
+	    col += len;
+	}
 	screen_putchar(' ', 0, col++, attr);
+
+	/* Store the tab page number in TabPageIdxs[], so that jump_to_mouse()
+	 * knows where each one is. */
+	++tabcount;
+	while (scol < col)
+	    TabPageIdxs[scol++] = tabcount;
     }
 
     if (t_colors < 8)
@@ -8511,6 +8572,14 @@
     else
 	c = ' ';
     screen_fill(0, 1, col, (int)Columns, c, c, attr_fill);
+
+    /* Put an "X" for closing the current tab if there are several. */
+    if (first_tabpage->tp_next != NULL)
+	screen_putchar('X', 0, (int)Columns - 1, attr_nosel);
+
+    /* Clicking outside of tabs has no effect. */
+    while (scol < Columns)
+	TabPageIdxs[scol++] = 0xff;
 }
 #endif
 
diff --git a/src/structs.h b/src/structs.h
index 893b826..6153099 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1558,6 +1558,7 @@
     tabpage_T	    *tp_next;	    /* next tabpage or NULL */
     frame_T	    *tp_topframe;   /* topframe for the windows */
     win_T	    *tp_curwin;	    /* current window in this Tab page */
+    win_T	    *tp_prevwin;    /* previous window in this Tab page */
     win_T	    *tp_firstwin;   /* first window in this Tab page */
     win_T	    *tp_lastwin;    /* last window in this Tab page */
     long	    tp_old_Rows;    /* Rows when Tab page was left */
diff --git a/src/version.h b/src/version.h
index 0f561bc..b00a9a1 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 15)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 15, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 16)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 16, compiled "
diff --git a/src/window.c b/src/window.c
index 116a5fc..927c7a1 100644
--- a/src/window.c
+++ b/src/window.c
@@ -25,9 +25,9 @@
 static void win_rotate __ARGS((int, int));
 static void win_totop __ARGS((int size, int flags));
 static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height));
-static win_T *win_free_mem __ARGS((win_T *win, int *dirp));
-static win_T *winframe_remove __ARGS((win_T *win, int *dirp));
-static frame_T *win_altframe __ARGS((win_T *win));
+static win_T *win_free_mem __ARGS((win_T *win, int *dirp, tabpage_T *tp));
+static win_T *winframe_remove __ARGS((win_T *win, int *dirp, tabpage_T *tp));
+static frame_T *win_altframe __ARGS((win_T *win, tabpage_T *tp));
 static tabpage_T *alt_tabpage __ARGS((void));
 static win_T *frame2win __ARGS((frame_T *frp));
 static int frame_has_win __ARGS((frame_T *frp, win_T *wp));
@@ -49,9 +49,9 @@
 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_free __ARGS((win_T *wp));
+static void win_free __ARGS((win_T *wp, tabpage_T *tp));
 static void win_append __ARGS((win_T *, win_T *));
-static void win_remove __ARGS((win_T *));
+static void win_remove __ARGS((win_T *, 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));
 static void frame_remove __ARGS((frame_T *frp));
@@ -1262,14 +1262,14 @@
     frp2 = curwin->w_frame->fr_prev;
     if (wp->w_prev != curwin)
     {
-	win_remove(curwin);
+	win_remove(curwin, NULL);
 	frame_remove(curwin->w_frame);
 	win_append(wp->w_prev, curwin);
 	frame_insert(frp, curwin->w_frame);
     }
     if (wp != wp2)
     {
-	win_remove(wp);
+	win_remove(wp, NULL);
 	frame_remove(wp->w_frame);
 	win_append(wp2, wp);
 	if (frp2 == NULL)
@@ -1353,7 +1353,7 @@
 	    /* remove first window/frame from the list */
 	    frp = curwin->w_frame->fr_parent->fr_child;
 	    wp1 = frp->fr_win;
-	    win_remove(wp1);
+	    win_remove(wp1, NULL);
 	    frame_remove(frp);
 
 	    /* find last frame and append removed window/frame after it */
@@ -1372,7 +1372,7 @@
 		;
 	    wp1 = frp->fr_win;
 	    wp2 = wp1->w_prev;		    /* will become last window */
-	    win_remove(wp1);
+	    win_remove(wp1, NULL);
 	    frame_remove(frp);
 
 	    /* append the removed window/frame before the first in the list */
@@ -1419,8 +1419,8 @@
     }
 
     /* Remove the window and frame from the tree of frames. */
-    (void)winframe_remove(curwin, &dir);
-    win_remove(curwin);
+    (void)winframe_remove(curwin, &dir, NULL);
+    win_remove(curwin, NULL);
     last_status(FALSE);	    /* may need to remove last status line */
     (void)win_comp_pos();   /* recompute window positions */
 
@@ -1486,7 +1486,7 @@
 	    win1->w_vsep_width = 0;
 #endif
 	}
-	win_remove(win1);
+	win_remove(win1, NULL);
 	frame_remove(win1->w_frame);
 	win_append(win2, win1);
 	frame_append(win2->w_frame, win1->w_frame);
@@ -1797,23 +1797,50 @@
  * close all windows for buffer 'buf'
  */
     void
-close_windows(buf)
+close_windows(buf, keep_curwin)
     buf_T	*buf;
+    int		keep_curwin;	    /* don't close "curwin" */
 {
-    win_T	*win;
+    win_T	*wp;
+    tabpage_T   *tp, *nexttp;
+    int		h = tabpageline_height();
 
     ++RedrawingDisabled;
-    for (win = firstwin; win != NULL && lastwin != firstwin; )
+
+    for (wp = firstwin; wp != NULL && lastwin != firstwin; )
     {
-	if (win->w_buffer == buf)
+	if (wp->w_buffer == buf && (!keep_curwin || wp != curwin))
 	{
-	    win_close(win, FALSE);
-	    win = firstwin;	    /* go back to the start */
+	    win_close(wp, FALSE);
+
+	    /* Start all over, autocommands may change the window layout. */
+	    wp = firstwin;
 	}
 	else
-	    win = win->w_next;
+	    wp = wp->w_next;
     }
+
+    /* Also check windows in other tab pages. */
+    for (tp = first_tabpage; tp != NULL; tp = nexttp)
+    {
+	nexttp = tp->tp_next;
+	if (tp->tp_topframe != topframe)
+	    for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
+		if (wp->w_buffer == buf)
+		{
+		    win_close_othertab(wp, FALSE, tp);
+
+		    /* Start all over, the tab page may be closed and
+		     * autocommands may change the window layout. */
+		    nexttp = first_tabpage;
+		    break;
+		}
+    }
+
     --RedrawingDisabled;
+
+    if (h != tabpageline_height())
+	shell_new_rows();
 }
 
 /*
@@ -1827,7 +1854,7 @@
 }
 
 /*
- * close window "win"
+ * Close window "win".
  * If "free_buf" is TRUE related buffer may be unloaded.
  *
  * called by :quit, :close, :xit, :wq and findtag()
@@ -1866,7 +1893,7 @@
 	 * Guess which window is going to be the new current window.
 	 * This may change because of the autocommands (sigh).
 	 */
-	wp = frame2win(win_altframe(win));
+	wp = frame2win(win_altframe(win, NULL));
 
 	/*
 	 * Be careful: If autocommands delete the window, return now.
@@ -1899,7 +1926,7 @@
 	return;
 
     /* Free the memory used for the window. */
-    wp = win_free_mem(win, &dir);
+    wp = win_free_mem(win, &dir, NULL);
 
     /* When closing the last window in a tab page go to another tab page. */
     if (wp == NULL)
@@ -2004,13 +2031,70 @@
 }
 
 /*
+ * Close window "win" in tab page "tp", which is not the current tab page.
+ * This may be the last window ih that tab page and result in closing the tab,
+ * thus "tp" may become invalid!
+ * Called must check if buffer is hidden.
+ */
+    void
+win_close_othertab(win, free_buf, tp)
+    win_T	*win;
+    int		free_buf;
+    tabpage_T	*tp;
+{
+    win_T	*wp;
+    int		dir;
+    tabpage_T   *ptp = NULL;
+
+    /* Close the link to the buffer. */
+    close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0);
+
+    /* Careful: Autocommands may have closed the tab page or made it the
+     * current tab page.  */
+    for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next)
+	;
+    if (ptp == NULL || tp->tp_topframe == topframe)
+	return;
+
+    /* Autocommands may have closed the window already. */
+    for (wp = tp->tp_firstwin; wp != NULL && wp != win; wp = wp->w_next)
+	;
+    if (wp == NULL)
+	return;
+
+    /* Free the memory used for the window. */
+    wp = win_free_mem(win, &dir, tp);
+
+    /* When closing the last window in a tab page remove the tab page. */
+    if (wp == NULL)
+    {
+	if (tp == first_tabpage)
+	    first_tabpage = tp->tp_next;
+	else
+	{
+	    for (ptp = first_tabpage; ptp != NULL && ptp->tp_next != tp;
+							   ptp = ptp->tp_next)
+		;
+	    if (ptp == NULL)
+	    {
+		EMSG2(_(e_intern2), "win_close_othertab()");
+		return;
+	    }
+	    ptp->tp_next = tp->tp_next;
+	}
+	vim_free(tp);
+    }
+}
+
+/*
  * Free the memory used for a window.
  * Returns a pointer to the window that got the freed up space.
  */
     static win_T *
-win_free_mem(win, dirp)
+win_free_mem(win, dirp, tp)
     win_T	*win;
     int		*dirp;		/* set to 'v' or 'h' for direction if 'ea' */
+    tabpage_T	*tp;		/* tab page "win" is in, NULL for current */
 {
     frame_T	*frp;
     win_T	*wp;
@@ -2024,13 +2108,9 @@
 
     /* Remove the window and its frame from the tree of frames. */
     frp = win->w_frame;
-    if (firstwin == lastwin)
-	/* Last window in a tab page. */
-	wp = NULL;
-    else
-	wp = winframe_remove(win, dirp);
+    wp = winframe_remove(win, dirp, tp);
     vim_free(frp);
-    win_free(win);
+    win_free(win, tp);
 
     return wp;
 }
@@ -2041,8 +2121,13 @@
 {
     int		dummy;
 
+# ifdef FEAT_WINDOWS
+    while (first_tabpage->tp_next != NULL)
+	tabpage_close(TRUE);
+# endif
+
     while (firstwin != NULL)
-	(void)win_free_mem(firstwin, &dummy);
+	(void)win_free_mem(firstwin, &dummy, NULL);
 }
 #endif
 
@@ -2052,9 +2137,10 @@
  */
 /*ARGSUSED*/
     static win_T *
-winframe_remove(win, dirp)
+winframe_remove(win, dirp, tp)
     win_T	*win;
     int		*dirp;		/* set to 'v' or 'h' for direction if 'ea' */
+    tabpage_T	*tp;		/* tab page "win" is in, NULL for current */
 {
     frame_T	*frp, *frp2, *frp3;
     frame_T	*frp_close = win->w_frame;
@@ -2062,12 +2148,15 @@
     int		old_height = 0;
 
     /*
+     * If there is only one window there is nothing to remove.
+     */
+    if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
+	return NULL;
+
+    /*
      * Remove the window from its frame.
      */
-    frp2 = win_altframe(win);
-    if (frp2 == NULL)
-	return NULL;	    /* deleted the last frame */
-
+    frp2 = win_altframe(win, tp);
     wp = frame2win(frp2);
 
     /* Remove this frame from the list of frames. */
@@ -2160,13 +2249,14 @@
  * layout.
  */
     static frame_T *
-win_altframe(win)
+win_altframe(win, tp)
     win_T	*win;
+    tabpage_T	*tp;		/* tab page "win" is in, NULL for current */
 {
     frame_T	*frp;
     int		b;
 
-    if (firstwin == lastwin)
+    if (tp == NULL ? firstwin == lastwin : tp->tp_firstwin == tp->tp_lastwin)
 	/* Last window in this tab page, will go to next tab page. */
 	return alt_tabpage()->tp_curwin->w_frame;
 
@@ -2861,6 +2951,7 @@
 	firstwin->w_winrow = tabpageline_height();
 
 	newtp->tp_topframe = topframe;
+	last_status(FALSE);
 	redraw_all_later(CLEAR);
 	return OK;
     }
@@ -2868,6 +2959,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;
     return FAIL;
@@ -2890,6 +2982,36 @@
 }
 
 /*
+ * Return TRUE when "tpc" points to a valid tab page.
+ */
+    int
+valid_tabpage(tpc)
+    tabpage_T	*tpc;
+{
+    tabpage_T	*tp;
+
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+	if (tp == tpc)
+	    return TRUE;
+    return FALSE;
+}
+
+/*
+ * Find tab page "n" (first one is 1).  Returns NULL when not found.
+ */
+    tabpage_T *
+find_tabpage(n)
+    int		n;
+{
+    tabpage_T	*tp;
+    int		i = 1;
+
+    for (tp = first_tabpage; tp != NULL && i != n; tp = tp->tp_next)
+	++i;
+    return tp;
+}
+
+/*
  * Prepare for leaving the current tab page "tp".
  */
     static void
@@ -2902,6 +3024,7 @@
 	gui_remove_scrollbars();
 #endif
     tp->tp_curwin = curwin;
+    tp->tp_prevwin = prevwin;
     tp->tp_firstwin = firstwin;
     tp->tp_lastwin = lastwin;
     tp->tp_old_Rows = Rows;
@@ -2925,6 +3048,7 @@
     lastwin = tp->tp_lastwin;
     topframe = tp->tp_topframe;
     win_enter_ext(tp->tp_curwin, FALSE, TRUE);
+    prevwin = tp->tp_prevwin;
 
 #ifdef FEAT_AUTOCMD
     if (old_curbuf != curbuf)
@@ -2985,12 +3109,13 @@
     {
 	/* Go to tab page "n". */
 	i = 0;
-	for (tp = first_tabpage; ++i != n; tp = tp->tp_next)
-	    if (tp == NULL)
-	    {
-		beep_flush();
-		return;
-	    }
+	for (tp = first_tabpage; ++i != n && tp != NULL; tp = tp->tp_next)
+	    ;
+	if (tp == NULL)
+	{
+	    beep_flush();
+	    return;
+	}
     }
 
     leave_tabpage(otp);
@@ -3418,8 +3543,9 @@
  * remove window 'wp' from the window list and free the structure
  */
     static void
-win_free(wp)
+win_free(wp, tp)
     win_T	*wp;
+    tabpage_T	*tp;		/* tab page "win" is in, NULL for current */
 {
     int		i;
 
@@ -3478,7 +3604,7 @@
     }
 #endif /* FEAT_GUI */
 
-    win_remove(wp);
+    win_remove(wp, tp);
     vim_free(wp);
 }
 
@@ -3512,17 +3638,22 @@
  * Remove a window from the window list.
  */
     static void
-win_remove(wp)
+win_remove(wp, tp)
     win_T	*wp;
+    tabpage_T	*tp;		/* tab page "win" is in, NULL for current */
 {
     if (wp->w_prev != NULL)
 	wp->w_prev->w_next = wp->w_next;
-    else
+    else if (tp == NULL)
 	firstwin = wp->w_next;
+    else
+	tp->tp_firstwin = wp->w_next;
     if (wp->w_next != NULL)
 	wp->w_next->w_prev = wp->w_prev;
-    else
+    else if (tp == NULL)
 	lastwin = wp->w_prev;
+    else
+	tp->tp_lastwin = wp->w_prev;
 }
 
 /*
@@ -3600,6 +3731,7 @@
 
 /*
  * Called from win_new_shellsize() after Rows changed.
+ * This only does the current tab page, others must be done when made active.
  */
     void
 shell_new_rows()
@@ -5115,16 +5247,27 @@
 min_rows()
 {
     int		total;
+#ifdef FEAT_WINDOWS
+    tabpage_T	*tp;
+    int		n;
+#endif
 
     if (firstwin == NULL)	/* not initialized yet */
 	return MIN_LINES;
 
-    total = 1;		/* count the room for the command line */
 #ifdef FEAT_WINDOWS
-    total += frame_minheight(topframe, NULL);
+    total = 0;
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
+    {
+	n = frame_minheight(tp->tp_topframe, NULL);
+	if (total < n)
+	    total = n;
+    }
+    total += tabpageline_height();
 #else
-    total += 1;		/* at least one window should have a line! */
+    total = 1;		/* at least one window should have a line! */
 #endif
+    total += 1;		/* count the room for the command line */
     return total;
 }
 
@@ -5169,7 +5312,9 @@
     win_T	*wp;
 
 #ifdef FEAT_WINDOWS
-    for (wp = firstwin; wp != NULL; wp = wp->w_next)
+    tabpage_T	*tp;
+
+    FOR_ALL_TAB_WINDOWS(tp, wp)
 	if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf)
 #else
     wp = curwin;