changeset 685:d7e33248b9c8 v7.0206

updated for version 7.0206
author vimboss
date Fri, 24 Feb 2006 23:53:04 +0000
parents a8caf7dd853d
children 473847b050f8
files runtime/doc/editing.txt runtime/doc/eval.txt runtime/doc/index.txt runtime/doc/map.txt runtime/doc/options.txt runtime/doc/tabpage.txt runtime/doc/tagsrch.txt runtime/doc/todo.txt runtime/doc/usr_08.txt runtime/doc/version7.txt runtime/doc/windows.txt src/Makefile src/auto/configure src/configure.in src/eval.c src/ex_cmds.h src/ex_cmds2.c src/ex_docmd.c src/feature.h src/globals.h src/gui.c src/gui.h src/gui_gtk_x11.c src/keymap.h src/main.c src/normal.c src/option.c src/option.h src/proto/gui.pro src/proto/gui_gtk_x11.pro src/proto/screen.pro src/proto/window.pro src/regexp.c src/screen.c src/search.c src/structs.h src/tag.c src/term.c src/version.h src/window.c
diffstat 40 files changed, 1098 insertions(+), 487 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1,4 +1,4 @@
-*editing.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 18
+*editing.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -819,7 +819,7 @@ USING THE ARGUMENT LIST
 			each file.
 			{not in Vi} {not available when compiled without the
 			|+listcmds| feature}
-			Also see |:windo| and |:bufdo|.
+			Also see |:windo|, |:tabdo| and |:bufdo|.
 
 Example: >
 	:args *.c
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 22
+*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -577,8 +577,8 @@ Expression syntax summary, from least to
 	etc.			As above, append ? for ignoring case, # for
 				matching case
 
-	expr5 is expr5		same List instance
-	expr5 isnot expr5	different List instance
+	expr5 is expr5		same |List| instance
+	expr5 isnot expr5	different |List| instance
 
 |expr5|	expr6 +	 expr6 ..	number addition or list concatenation
 	expr6 -	 expr6 ..	number subtraction
@@ -593,16 +593,16 @@ Expression syntax summary, from least to
 	+ expr7			unary plus
 
 
-|expr8|	expr8[expr1]		byte of a String or item of a List
-	expr8[expr1 : expr1]	substring of a String or sublist of a List
-	expr8.name		entry in a Dictionary
-	expr8(expr1, ...)	function call with Funcref variable
+|expr8|	expr8[expr1]		byte of a String or item of a |List|
+	expr8[expr1 : expr1]	substring of a String or sublist of a |List|
+	expr8.name		entry in a |Dictionary|
+	expr8(expr1, ...)	function call with |Funcref| variable
 
 |expr9| number			number constant
 	"string"		string constant, backslash is special
 	'string'		string constant, ' is doubled
-	[expr1, ...]		List
-	{expr1: expr1, ...}	Dictionary
+	[expr1, ...]		|List|
+	{expr1: expr1, ...}	|Dictionary|
 	&option			option value
 	(expr1)			nested expression
 	variable		internal variable
@@ -714,23 +714,23 @@ Examples:
 "abc" == "Abc"	  evaluates to 1 if 'ignorecase' is set, 0 otherwise
 
 							*E691* *E692*
-A List can only be compared with a List and only "equal", "not equal" and "is"
-can be used.  This compares the values of the list, recursively.  Ignoring
-case means case is ignored when comparing item values.
+A |List| can only be compared with a |List| and only "equal", "not equal" and
+"is" can be used.  This compares the values of the list, recursively.
+Ignoring case means case is ignored when comparing item values.
 
 							*E735* *E736*
-A Dictionary can only be compared with a Dictionary and only "equal", "not
-equal" and "is" can be used.  This compares the key/values of the Dictionary,
+A |Dictionary| can only be compared with a |Dictionary| and only "equal", "not
+equal" and "is" can be used.  This compares the key/values of the |Dictionary|
 recursively.  Ignoring case means case is ignored when comparing item values.
 
 							*E693* *E694*
-A Funcref can only be compared with a Funcref and only "equal" and "not equal"
-can be used.  Case is never ignored.
-
-When using "is" or "isnot" with a List this checks if the expressions are
-referring to the same List instance.  A copy of a List is different from the
-original List.  When using "is" without a List it is equivalent to using
-"equal", using "isnot" equivalent to using "not equal".  Except that a
+A |Funcref| can only be compared with a |Funcref| and only "equal" and "not
+equal" can be used.  Case is never ignored.
+
+When using "is" or "isnot" with a |List| this checks if the expressions are
+referring to the same |List| instance.  A copy of a |List| is different from
+the original |List|.  When using "is" without a |List| it is equivalent to
+using "equal", using "isnot" equivalent to using "not equal".  Except that a
 different type means the values are different.  "4 == '4'" is true, "4 is '4'"
 is false.
 
@@ -763,12 +763,12 @@ can be matched like an ordinary characte
 
 expr5 and expr6						*expr5* *expr6*
 ---------------
-expr6 +	 expr6 ..	Number addition or List concatenation	*expr-+*
+expr6 +	 expr6 ..	Number addition or |List| concatenation	*expr-+*
 expr6 -	 expr6 ..	Number subtraction			*expr--*
 expr6 .	 expr6 ..	String concatenation			*expr-.*
 
-For Lists only "+" is possible and then both expr6 must be a list.  The result
-is a new list with the two lists Concatenated.
+For |List|s only "+" is possible and then both expr6 must be a list.  The
+result is a new list with the two lists Concatenated.
 
 expr7 *	 expr7 ..	number multiplication			*expr-star*
 expr7 /	 expr7 ..	number division				*expr-/*
@@ -783,7 +783,7 @@ Note the difference between "+" and ".":
 When the righthand side of '/' is zero, the result is 0x7fffffff.
 When the righthand side of '%' is zero, the result is 0.
 
-None of these work for Funcrefs.
+None of these work for |Funcref|s.
 
 
 expr7							*expr7*
@@ -806,7 +806,7 @@ These three can be repeated and mixed.  
 
 expr8							*expr8*
 -----
-expr8[expr1]		item of String or List		*expr-[]* *E111*
+expr8[expr1]		item of String or |List|	*expr-[]* *E111*
 
 If expr8 is a Number or String this results in a String that contains the
 expr1'th single byte from expr8.  expr8 is used as a String, expr1 as a
@@ -821,13 +821,14 @@ If the length of the String is less than
 String.  A negative index always results in an empty string (reason: backwards
 compatibility).  Use [-1:] to get the last byte.
 
-If expr8 is a List then it results the item at index expr1.  See |list-index|
+If expr8 is a |List| then it results the item at index expr1.  See |list-index|
 for possible index values.  If the index is out of range this results in an
 error.  Example: >
 	:let item = mylist[-1]		" get last item
 
-Generally, if a List index is equal to or higher than the length of the List,
-or more negative than the length of the List, this results in an error.
+Generally, if a |List| index is equal to or higher than the length of the
+|List|, or more negative than the length of the |List|, this results in an
+error.
 
 
 expr8[expr1a : expr1b]	substring or sublist		*expr-[:]*
@@ -852,20 +853,22 @@ Examples: >
 	:let s = line(".")[4:]		" from the fifth byte to the end
 	:let s = s[:-3]			" remove last two bytes
 
-If expr8 is a List this results in a new List with the items indicated by the
-indexes expr1a and expr1b.  This works like with a String, as explained just
-above, except that indexes out of range cause an error.  Examples: >
+If expr8 is a |List| this results in a new |List| with the items indicated by
+the indexes expr1a and expr1b.  This works like with a String, as explained
+just above, except that indexes out of range cause an error.  Examples: >
 	:let l = mylist[:3]		" first four items
 	:let l = mylist[4:4]		" List with one item
 	:let l = mylist[:]		" shallow copy of a List
 
-Using expr8[expr1] or expr8[expr1a : expr1b] on a Funcref results in an error.
-
-
-expr8.name		entry in a Dictionary		*expr-entry*
-
-If expr8 is a Dictionary and it is followed by a dot, then the following name
-will be used as a key in the Dictionary.  This is just like: expr8[name].
+Using expr8[expr1] or expr8[expr1a : expr1b] on a |Funcref| results in an
+error.
+
+
+expr8.name		entry in a |Dictionary|		*expr-entry*
+
+If expr8 is a |Dictionary| and it is followed by a dot, then the following
+name will be used as a key in the |Dictionary|.  This is just like:
+expr8[name].
 
 The name must consist of alphanumeric characters, just like a variable name,
 but it may start with a number.  Curly braces cannot be used.
@@ -881,7 +884,7 @@ Note that the dot is also used for Strin
 always put spaces around the dot for String concatenation.
 
 
-expr8(expr1, ...)	Funcref function call
+expr8(expr1, ...)	|Funcref| function call
 
 When expr8 is a |Funcref| type variable, invoke the function it refers to.
 
@@ -1029,8 +1032,8 @@ specified by what is prepended:
 |function-argument|  a:	  Function argument (only inside a function).
 |vim-variable|       v:	  Global, predefined by Vim.
 
-The scope name by itself can be used as a Dictionary.  For example, to delete
-all script-local variables: >
+The scope name by itself can be used as a |Dictionary|.  For example, to
+delete all script-local variables: >
 	:for k in keys(s:)
 	:    unlet s:[k]
 	:endfor
@@ -1327,7 +1330,7 @@ v:insertmode	Used for the |InsertEnter| 
 			v	Virtual Replace mode
 
 						*v:key* *key-variable*
-v:key		Key of the current item of a Dictionary.  Only valid while
+v:key		Key of the current item of a |Dictionary|.  Only valid while
 		evaluating the expression used with |map()| and |filter()|.
 		Read-only.
 
@@ -1459,8 +1462,8 @@ v:throwpoint	The point where the excepti
 <		Output: "Exception from test.vim, line 2"
 
 						*v:val* *val-variable*
-v:val		Value of the current item of a List or Dictionary.  Only valid
-		while evaluating the expression used with |map()| and
+v:val		Value of the current item of a |List| or |Dictionary|.  Only
+		valid while evaluating the expression used with |map()| and
 		|filter()|.  Read-only.
 
 					*v:version* *version-variable*
@@ -1486,7 +1489,7 @@ See |function-list| for a list grouped b
 
 USAGE				RESULT	DESCRIPTION	~
 
-add( {list}, {item})		List	append {item} to List {list}
+add( {list}, {item})		List	append {item} to |List| {list}
 append( {lnum}, {string})	Number	append {string} below line {lnum}
 append( {lnum}, {list})		Number	append lines {list} below line {lnum}
 argc()				Number	number of files in the argument list
@@ -1595,9 +1598,9 @@ inputsecret( {prompt} [, {text}]) String
 insert( {list}, {item} [, {idx}]) List	insert {item} in {list} [before {idx}]
 isdirectory( {directory})	Number	TRUE if {directory} is a directory
 islocked( {expr})		Number	TRUE if {expr} is locked
-items( {dict})			List	List of key-value pairs in {dict}
+items( {dict})			List	key-value pairs in {dict}
 join( {list} [, {sep}])		String	join {list} items into one String
-keys( {dict})			List	List of keys in {dict}
+keys( {dict})			List	keys in {dict}
 len( {expr})			Number	the length of {expr}
 libcall( {lib}, {func}, {arg})	String	call {func} in library {lib} with {arg}
 libcallnr( {lib}, {func}, {arg})  Number  idem, but return a Number
@@ -1671,7 +1674,7 @@ spellbadword()			String	badly spelled wo
 spellsuggest( {word} [, {max} [, {capital}]])
 				List	spelling suggestions
 split( {expr} [, {pat} [, {keepempty}]])
-				List	make List from {pat} separated {expr}
+				List	make |List| from {pat} separated {expr}
 strftime( {format}[, {time}])	String	time in specified format
 stridx( {haystack}, {needle}[, {start}])
 				Number	index of {needle} in {haystack}
@@ -1702,7 +1705,7 @@ toupper( {expr})		String	the String {exp
 tr( {src}, {fromstr}, {tostr})	String	translate chars of {src} in {fromstr}
 					to chars in {tostr}
 type( {name})			Number	type of variable {name}
-values( {dict})			List	List of values in {dict}
+values( {dict})			List	values in {dict}
 virtcol( {expr})		Number	screen column of cursor or mark
 visualmode( [expr])		String	last visual mode used
 winbufnr( {nr})			Number	buffer number of window {nr}
@@ -1716,18 +1719,18 @@ writefile({list}, {fname} [, {binary}])
 				Number	write list of lines to file {fname}
 
 add({list}, {expr})					*add()*
-		Append the item {expr} to List {list}.  Returns the resulting
-		List.  Examples: >
+		Append the item {expr} to |List| {list}.  Returns the
+		resulting |List|.  Examples: >
 			:let alist = add([1, 2, 3], item)
 			:call add(mylist, "woodstock")
-<		Note that when {expr} is a List it is appended as a single
-		item.  Use |extend()| to concatenate Lists.
+<		Note that when {expr} is a |List| it is appended as a single
+		item.  Use |extend()| to concatenate |List|s.
 		Use |insert()| to add an item at another position.
 
 
 append({lnum}, {expr})					*append()*
-		When {expr} is a List: Append each item of the List as a text
-		line below line {lnum} in the current buffer.
+		When {expr} is a |List|: Append each item of the |List| as a
+		text line below line {lnum} in the current buffer.
 		Otherwise append {expr} as one text line below line {lnum} in
 		the current buffer.
 		{lnum} can be zero to insert a line before the first one.
@@ -1891,9 +1894,9 @@ byteidx({expr}, {nr})					*byteidx()*
 		is returned.
 
 call({func}, {arglist} [, {dict}])			*call()* *E699*
-		Call function {func} with the items in List {arglist} as
+		Call function {func} with the items in |List| {arglist} as
 		arguments.
-		{func} can either be a Funcref or the name of a function.
+		{func} can either be a |Funcref| or the name of a function.
 		a:firstline and a:lastline are set to the cursor line.
 		Returns the return value of the called function.
 		{dict} is for functions with the "dict" attribute.  It will be
@@ -2009,17 +2012,17 @@ confirm({msg} [, {choices} [, {default} 
 							*copy()*
 copy({expr})	Make a copy of {expr}.  For Numbers and Strings this isn't
 		different from using {expr} directly.
-		When {expr} is a List a shallow copy is created.  This means
-		that the original List can be changed without changing the
+		When {expr} is a |List| a shallow copy is created.  This means
+		that the original |List| can be changed without changing the
 		copy, and vise versa.  But the items are identical, thus
-		changing an item changes the contents of both Lists.  Also see
-		|deepcopy()|.
+		changing an item changes the contents of both |List|s.  Also
+		see |deepcopy()|.
 
 count({comp}, {expr} [, {ic} [, {start}]])			*count()*
 		Return the number of times an item with value {expr} appears
-		in List or Dictionary {comp}.
+		in |List| or |Dictionary| {comp}.
 		If {start} is given then start with the item with this index.
-		{start} can only be used with a List.
+		{start} can only be used with a |List|.
 		When {ic} is given and it's non-zero then case is ignored.
 
 
@@ -2080,16 +2083,16 @@ cursor({lnum}, {col})					*cursor()*
 deepcopy({expr}[, {noref}])				*deepcopy()* *E698*
 		Make a copy of {expr}.  For Numbers and Strings this isn't
 		different from using {expr} directly.
-		When {expr} is a List a full copy is created.  This means
-		that the original List can be changed without changing the
-		copy, and vise versa.  When an item is a List, a copy for it
+		When {expr} is a |List| a full copy is created.  This means
+		that the original |List| can be changed without changing the
+		copy, and vise versa.  When an item is a |List|, a copy for it
 		is made, recursively.  Thus changing an item in the copy does
-		not change the contents of the original List.
-		When {noref} is omitted or zero a contained List or Dictionary
-		is only copied once.  All references point to this single
-		copy.  With {noref} set to 1 every occurrence of a List or
-		Dictionary results in a new copy.  This also means that a
-		cyclic reference causes deepcopy() to fail.
+		not change the contents of the original |List|.
+		When {noref} is omitted or zero a contained |List| or
+		|Dictionary| is only copied once.  All references point to
+		this single copy.  With {noref} set to 1 every occurrence of a
+		|List| or |Dictionary| results in a new copy.  This also means
+		that a cyclic reference causes deepcopy() to fail.
 								*E724*
 		Nesting is possible up to 100 levels.  When there is an item
 		that refers back to a higher level making a deep copy with
@@ -2100,7 +2103,7 @@ delete({fname})							*delete()*
 		Deletes the file by the name {fname}.  The result is a Number,
 		which is 0 if the file was deleted successfully, and non-zero
 		when the deletion failed.
-		Use |remove()| to delete an item from a List.
+		Use |remove()| to delete an item from a |List|.
 
 							*did_filetype()*
 did_filetype()	Returns non-zero when autocommands are being executed and the
@@ -2135,10 +2138,10 @@ diff_hlID({lnum}, {col})				*diff_hlID()
 
 empty({expr})						*empty()*
 		Return the Number 1 if {expr} is empty, zero otherwise.
-		A List or Dictionary is empty when it does not have any items.
-		A Number is empty when its value is zero.
-		For a long List this is much faster then comparing the length
-		with zero.
+		A |List| or |Dictionary| is empty when it does not have any
+		items.  A Number is empty when its value is zero.
+		For a long |List| this is much faster then comparing the
+		length with zero.
 
 escape({string}, {chars})				*escape()*
 		Escape the characters in {chars} that occur in {string} with a
@@ -2151,7 +2154,7 @@ escape({string}, {chars})				*escape()*
 eval({string})	Evaluate {string} and return the result.  Especially useful to
 		turn the result of |string()| back into the original value.
 		This works for Numbers, Strings and composites of them.
-		Also works for Funcrefs that refer to existing functions.
+		Also works for |Funcref|s that refer to existing functions.
 
 eventhandler()						*eventhandler()*
 		Returns 1 when inside an event handler.  That is that Vim got
@@ -2195,9 +2198,9 @@ exists({expr})	The result is a Number, w
 					|user-functions|).
 			varname		internal variable (see
 					|internal-variables|).  Also works
-					for |curly-braces-names|, Dictionary
-					entries, List items, etc.  Beware that
-					this may cause functions to be
+					for |curly-braces-names|, |Dictionary|
+					entries, |List| items, etc.  Beware
+					that this may cause functions to be
 					invoked cause an error message for an
 					invalid expression.
 			:cmdname	Ex command: built-in command, user
@@ -2323,9 +2326,9 @@ expand({expr} [, {flag}])				*expand()*
 		getting the raw output of an external command.
 
 extend({expr1}, {expr2} [, {expr3}])			*extend()*
-		{expr1} and {expr2} must be both Lists or both Dictionaries.
-
-		If they are Lists: Append {expr2} to {expr1}.
+		{expr1} and {expr2} must be both |List|s or both Dictionaries.
+
+		If they are |List|s: Append {expr2} to {expr1}.
 		If {expr3} is given insert the items of {expr2} before item
 		{expr3} in {expr1}.  When {expr3} is zero insert before the
 		first item.  When {expr3} is equal to len({expr1}) then
@@ -2362,28 +2365,28 @@ filereadable({file})					*filereadable()
 
 
 filter({expr}, {string})					*filter()*
-		{expr} must be a List or a Dictionary.
+		{expr} must be a |List| or a |Dictionary|.
 		For each item in {expr} evaluate {string} and when the result
-		is zero remove the item from the List or Dictionary.
+		is zero remove the item from the |List| or |Dictionary|.
 		Inside {string} |v:val| has the value of the current item.
-		For a Dictionary |v:key| has the key of the current item.
+		For a |Dictionary| |v:key| has the key of the current item.
 		Examples: >
 			:call filter(mylist, 'v:val !~ "OLD"')
 <		Removes the items where "OLD" appears. >
 			:call filter(mydict, 'v:key >= 8')
 <		Removes the items with a key below 8. >
 			:call filter(var, 0)
-<		Removes all the items, thus clears the List or Dictionary.
+<		Removes all the items, thus clears the |List| or |Dictionary|.
 
 		Note that {string} is the result of expression and is then
 		used as an expression again.  Often it is good to use a
 		|literal-string| to avoid having to double backslashes.
 
-		The operation is done in-place.  If you want a List or
-		Dictionary to remain unmodified make a copy first: >
+		The operation is done in-place.  If you want a |List| or
+		|Dictionary| to remain unmodified make a copy first: >
 			:let l = filter(copy(mylist), 'v:val =~ "KEEP"')
 
-<		Returns {expr}, the List or Dictionary that was filtered.
+<		Returns {expr}, the |List| or |Dictionary| that was filtered.
 		When an error is encountered while evaluating {string} no
 		further items in {expr} are processed.
 
@@ -2477,35 +2480,35 @@ foreground()	Move the Vim window to the 
 
 
 function({name})					*function()* *E700*
-		Return a Funcref variable that refers to function {name}.
+		Return a |Funcref| variable that refers to function {name}.
 		{name} can be a user defined function or an internal function.
 
 
 garbagecollect()					*garbagecollect()*
-		Cleanup unused Lists and Dictionaries that have circular
+		Cleanup unused |List|s and Dictionaries that have circular
 		references.  There is hardly ever a need to invoke this
 		function, as it is automatically done when Vim runs out of
 		memory or is waiting for the user to press a key after
 		'updatetime'.  Items without circular references are always
 		freed when they become unused.
-		This is useful if you have deleted a very big List and/or
-		Dictionary with circular references in a script that runs for
-		a long time.
+		This is useful if you have deleted a very big |List| and/or
+		|Dictionary| with circular references in a script that runs
+		for a long time.
 
 get({list}, {idx} [, {default}])			*get()*
-		Get item {idx} from List {list}.  When this item is not
+		Get item {idx} from |List| {list}.  When this item is not
 		available return {default}.  Return zero when {default} is
 		omitted.
 get({dict}, {key} [, {default}])
-		Get item with key {key} from Dictionary {dict}.  When this
+		Get item with key {key} from |Dictionary| {dict}.  When this
 		item is not available return {default}.  Return zero when
 		{default} is omitted.
 
 							*getbufline()*
 getbufline({expr}, {lnum} [, {end}])
-		Return a List with the lines starting from {lnum} to {end}
-		(inclusive) in the buffer {expr}.  If {end} is omitted, a List
-		with only the line {lnum} is returned.
+		Return a |List| with the lines starting from {lnum} to {end}
+		(inclusive) in the buffer {expr}.  If {end} is omitted, a
+		|List| with only the line {lnum} is returned.
 
 		For the use of {expr}, see |bufname()| above.
 
@@ -2513,15 +2516,15 @@ getbufline({expr}, {lnum} [, {end}])
 		buffer.  Otherwise a number must be used.
 
 		When {lnum} is smaller than 1 or bigger than the number of
-		lines in the buffer, an empty List is returned.
+		lines in the buffer, an empty |List| is returned.
 
 		When {end} is greater than the number of lines in the buffer,
 		it is treated as {end} is set to the number of lines in the
-		buffer.  When {end} is before {lnum} an empty List is
+		buffer.  When {end} is before {lnum} an empty |List| is
 		returned.
 
 		This function works only for loaded buffers.  For unloaded and
-		non-existing buffers, an empty List is returned.
+		non-existing buffers, an empty |List| is returned.
 
 		Example: >
 			:let lines = getbufline(bufnr("myfile"), 1, "$")
@@ -2697,12 +2700,12 @@ getline({lnum} [, {end}])
 <		When {lnum} is smaller than 1 or bigger than the number of
 		lines in the buffer, an empty string is returned.
 
-		When {end} is given the result is a List where each item is a
-		line from the current buffer in the range {lnum} to {end},
+		When {end} is given the result is a |List| where each item is
+		a line from the current buffer in the range {lnum} to {end},
 		including line {end}.
 		{end} is used in the same way as {lnum}.
 		Non-existing lines are silently omitted.
-		When {end} is before {lnum} an empty List is returned.
+		When {end} is before {lnum} an empty |List| is returned.
 		Example: >
 			:let start = line('.')
 			:let end = search("^$") - 1
@@ -2829,8 +2832,8 @@ has({feature})	The result is a Number, w
 
 
 has_key({dict}, {key})					*has_key()*
-		The result is a Number, which is 1 if Dictionary {dict} has an
-		entry with key {key}.  Zero otherwise.
+		The result is a Number, which is 1 if |Dictionary| {dict} has
+		an entry with key {key}.  Zero otherwise.
 
 
 hasmapto({what} [, {mode}])				*hasmapto()*
@@ -2982,7 +2985,7 @@ indent({lnum})	The result is a Number, w
 
 
 index({list}, {expr} [, {start} [, {ic}]])			*index()*
-		Return the lowest index in List {list} where the item has a
+		Return the lowest index in |List| {list} where the item has a
 		value equal to {expr}.
 		If {start} is given then start looking at the item with index
 		{start} (may be negative for an item relative to the end).
@@ -3093,18 +3096,18 @@ inputsecret({prompt} [, {text}])			*inpu
 		NOTE: Command-line completion is not supported.
 
 insert({list}, {item} [, {idx}])			*insert()*
-		Insert {item} at the start of List {list}.
+		Insert {item} at the start of |List| {list}.
 		If {idx} is specified insert {item} before the item with index
 		{idx}.  If {idx} is zero it goes before the first item, just
 		like omitting {idx}.  A negative {idx} is also possible, see
 		|list-index|.  -1 inserts just before the last item.
-		Returns the resulting List.  Examples: >
+		Returns the resulting |List|.  Examples: >
 			:let mylist = insert([2, 3, 5], 1)
 			:call insert(mylist, 4, -1)
 			:call insert(mylist, 6, len(mylist))
 <		The last example can be done simpler with |add()|.
-		Note that when {item} is a List it is inserted as a single
-		item.  Use |extend()| to concatenate Lists.
+		Note that when {item} is a |List| it is inserted as a single
+		item.  Use |extend()| to concatenate |List|s.
 
 isdirectory({directory})				*isdirectory()*
 		The result is a Number, which is non-zero when a directory
@@ -3115,8 +3118,8 @@ isdirectory({directory})				*isdirectory
 islocked({expr})					*islocked()*
 		The result is a Number, which is non-zero when {expr} is the
 		name of a locked variable.
-		{expr} must be the name of a variable, List item or Dictionary
-		entry, not the variable itself!  Example: >
+		{expr} must be the name of a variable, |List| item or
+		|Dictionary| entry, not the variable itself!  Example: >
 			:let alist = [0, ['a', 'b'], 2, 3]
 			:lockvar 1 alist
 			:echo islocked('alist')		" 1
@@ -3126,9 +3129,10 @@ islocked({expr})					*islocked()*
 		message.  Use |exists()| to check for existance.
 
 items({dict})						*items()*
-		Return a List with all the key-value pairs of {dict}.  Each
-		List item is a list with two items: the key of a {dict} entry
-		and the value of this entry.  The List is in arbitrary order.
+		Return a |List| with all the key-value pairs of {dict}.  Each
+		|List| item is a list with two items: the key of a {dict}
+		entry and the value of this entry.  The |List| is in arbitrary
+		order.
 
 
 join({list} [, {sep}])					*join()*
@@ -3138,22 +3142,22 @@ join({list} [, {sep}])					*join()*
 		Note that {sep} is not added at the end.  You might want to
 		add it there too: >
 			let lines = join(mylist, "\n") . "\n"
-<		String items are used as-is.  Lists and Dictionaries are
+<		String items are used as-is.  |List|s and Dictionaries are
 		converted into a string like with |string()|.
 		The opposite function is |split()|.
 
 keys({dict})						*keys()*
-		Return a List with all the keys of {dict}.  The List is in
+		Return a |List| with all the keys of {dict}.  The |List| is in
 		arbitrary order.
 
 							*len()* *E701*
 len({expr})	The result is a Number, which is the length of the argument.
 		When {expr} is a String or a Number the length in bytes is
 		used, as with |strlen()|.
-		When {expr} is a List the number of items in the List is
+		When {expr} is a |List| the number of items in the |List| is
 		returned.
-		When {expr} is a Dictionary the number of entries in the
-		Dictionary is returned.
+		When {expr} is a |Dictionary| the number of entries in the
+		|Dictionary| is returned.
 		Otherwise an error is given.
 
 						*libcall()* *E364* *E368*
@@ -3259,11 +3263,11 @@ localtime()						*localtime()*
 
 
 map({expr}, {string})					*map()*
-		{expr} must be a List or a Dictionary.
+		{expr} must be a |List| or a |Dictionary|.
 		Replace each item in {expr} with the result of evaluating
 		{string}.
 		Inside {string} |v:val| has the value of the current item.
-		For a Dictionary |v:key| has the key of the current item.
+		For a |Dictionary| |v:key| has the key of the current item.
 		Example: >
 			:call map(mylist, '"> " . v:val . " <"')
 <		This puts "> " before and " <" after each item in "mylist".
@@ -3273,11 +3277,11 @@ map({expr}, {string})					*map()*
 		|literal-string| to avoid having to double backslashes.  You
 		still have to double ' quotes
 
-		The operation is done in-place.  If you want a List or
-		Dictionary to remain unmodified make a copy first: >
+		The operation is done in-place.  If you want a |List| or
+		|Dictionary| to remain unmodified make a copy first: >
 			:let tlist = map(copy(mylist), ' & . "\t"')
 
-<		Returns {expr}, the List or Dictionary that was filtered.
+<		Returns {expr}, the |List| or |Dictionary| that was filtered.
 		When an error is encountered while evaluating {string} no
 		further items in {expr} are processed.
 
@@ -3335,13 +3339,13 @@ mapcheck({name}[, {mode}])				*mapcheck(
 		mapping for "_v" or for "_vvv".
 
 match({expr}, {pat}[, {start}[, {count}]])			*match()*
-		When {expr} is a List then this returns the index of the first
-		item where {pat} matches.  Each item is used as a String,
-		Lists and Dictionaries are used as echoed.
+		When {expr} is a |List| then this returns the index of the
+		first item where {pat} matches.  Each item is used as a
+		String, |List|s and Dictionaries are used as echoed.
 		Otherwise, {expr} is used as a String.  The result is a
 		Number, which gives the index (byte offset) in {expr} where
 		{pat} matches.
-		A match at the first character or List item returns zero.
+		A match at the first character or |List| item returns zero.
 		If there is no match -1 is returned.
 		Example: >
 			:echo match("testing", "ing")	" results in 4
@@ -3359,10 +3363,10 @@ match({expr}, {pat}[, {start}[, {count}]
 		is found in a String the search for the next one starts on
 		character further.  Thus this example results in 1: >
 			echo match("testing", "..", 0, 2)
-<		In a List the search continues in the next item.
+<		In a |List| the search continues in the next item.
 
 		If {start} is given, the search starts from byte index
-		{start} in a String or item {start} in a List.
+		{start} in a String or item {start} in a |List|.
 		The result, however, is still the index counted from the
 		first character/item.  Example: >
 			:echo match("testing", "ing", 2)
@@ -3374,7 +3378,7 @@ match({expr}, {pat}[, {start}[, {count}]
 		For a String, if {start} < 0, it will be set to 0.  For a list
 		the index is counted from the end.
 		If {start} is out of range (> strlen({expr} for a String or
-		> len({expr} for a List) -1 is returned.
+		> len({expr} for a |List|) -1 is returned.
 
 		See |pattern| for the patterns that are accepted.
 		The 'ignorecase' option is used to set the ignore-caseness of
@@ -3398,10 +3402,10 @@ matchend({expr}, {pat}[, {start}[, {coun
 <		results in "7". >
 			:echo matchend("testing", "ing", 5)
 <		result is "-1".
-		When {expr} is a List the result is equal to match().
+		When {expr} is a |List| the result is equal to match().
 
 matchlist({expr}, {pat}[, {start}[, {count}]])			*matchlist()*
-		Same as match(), but return a List.  The first item in the
+		Same as match(), but return a |List|.  The first item in the
 		list is the matched string, same as what matchstr() would
 		return.  Following items are submatches, like "\1", "\2", etc.
 		in |:substitute|.
@@ -3417,20 +3421,20 @@ matchstr({expr}, {pat}[, {start}[, {coun
 <		results in "ing". >
 			:echo matchstr("testing", "ing", 5)
 <		result is "".
-		When {expr} is a List then the matching item is returned.
+		When {expr} is a |List| then the matching item is returned.
 		The type isn't changed, it's not necessarily a String.
 
 							*max()*
 max({list})	Return the maximum value of all items in {list}.
 		If {list} is not a list or one of the items in {list} cannot
 		be used as a Number this results in an error.
-		An empty List results in zero.
+		An empty |List| results in zero.
 
 							*min()*
 min({list})	Return the minumum value of all items in {list}.
 		If {list} is not a list or one of the items in {list} cannot
 		be used as a Number this results in an error.
-		An empty List results in zero.
+		An empty |List| results in zero.
 
 							*mkdir()* *E749*
 mkdir({name} [, {path} [, {prot}]])
@@ -3624,7 +3628,7 @@ pumvisible()						*pumvisible()*
 
 							*E726* *E727*
 range({expr} [, {max} [, {stride}]])				*range()*
-		Returns a List with Numbers:
+		Returns a |List| with Numbers:
 		- If only {expr} is specified: [0, 1, ..., {expr} - 1]
 		- If {max} is specified: [{expr}, {expr} + 1, ..., {max}]
 		- If {stride} is specified: [{expr}, {expr} + {stride}, ...,
@@ -3643,8 +3647,8 @@ range({expr} [, {max} [, {stride}]])				
 <
 							*readfile()*
 readfile({fname} [, {binary} [, {max}]])
-		Read file {fname} and return a List, each line of the file as
-		an item.  Lines broken at NL characters.  Macintosh files
+		Read file {fname} and return a |List|, each line of the file
+		as an item.  Lines broken at NL characters.  Macintosh files
 		separated with CR will result in a single long line (unless a
 		NL appears somewhere).
 		When {binary} is equal to "b" binary mode is used:
@@ -3748,7 +3752,7 @@ remote_send({server}, {string} [, {idvar
 		 \ 'server2client(expand("<client>"), "HELLO")<CR>')
 <
 remove({list}, {idx} [, {end}])				*remove()*
-		Without {end}: Remove the item at {idx} from List {list} and
+		Without {end}: Remove the item at {idx} from |List| {list} and
 		return it.
 		With {end}: Remove items from {idx} to {end} (inclusive) and
 		return a list with these items.  When {idx} points to the same
@@ -3777,7 +3781,7 @@ repeat({expr}, {count})					*repeat()*
 		result.  Example: >
 			:let seperator = repeat('-', 80)
 <		When {count} is zero or negative the result is empty.
-		When {expr} is a List the result is {expr} concatenated
+		When {expr} is a |List| the result is {expr} concatenated
 		{count} times.  Example: >
 			:let longlist = repeat(['a', 'b'], 3)
 <		Results in ['a', 'b', 'a', 'b', 'a', 'b'].
@@ -3940,9 +3944,9 @@ searchpair({start}, {middle}, {end} [, {
 <
 							*searchpairpos()*
 searchpairpos({start}, {middle}, {end} [, {flags} [, {skip}]])
-		Same as searchpair(), but returns a List with the line and
-		column position of the match. The first element of the List is
-		the line number and the second element is the byte index of
+		Same as searchpair(), but returns a |List| with the line and
+		column position of the match. The first element of the |List|
+		is the line number and the second element is the byte index of
 		the column position of the match.  If no match is found,
 		returns [0, 0].
 >
@@ -3951,11 +3955,11 @@ searchpairpos({start}, {middle}, {end} [
 		See |match-parens| for a bigger and more useful example.
 
 searchpos({pattern} [, {flags}])			*searchpos()*
-		Same as search(), but returns a List with the line and column
-		position of the match. The first element of the List is the
-		line number and the second element is the byte index of the
-		column position of the match. If no match is found, returns
-		[0, 0].
+		Same as search(), but returns a |List| with the line and
+		column position of the match. The first element of the |List|
+		is the line number and the second element is the byte index of
+		the column position of the match. If no match is found,
+		returns [0, 0].
 >
 			:let [lnum,col] = searchpos('mypattern', 'n')
 <
@@ -4015,7 +4019,7 @@ setline({lnum}, {line})					*setline()*
 		If this succeeds, 0 is returned.  If this fails (most likely
 		because {lnum} is invalid) 1 is returned.  Example: >
 			:call setline(5, strftime("%c"))
-<		When {line} is a List then line {lnum} and following lines
+<		When {line} is a |List| then line {lnum} and following lines
 		will be set to the items in the list.  Example: >
 			:call setline(5, ['aaa', 'bbb', 'ccc'])
 <		This is equivalent to: >
@@ -4138,11 +4142,11 @@ sort({list} [, {func}])					*sort()* *E7
 		want a list to remain unmodified make a copy first: >
 			:let sortedlist = sort(copy(mylist))
 <		Uses the string representation of each item to sort on.
-		Numbers sort after Strings, Lists after Numbers.
+		Numbers sort after Strings, |List|s after Numbers.
 		For sorting text in the current buffer use |:sort|.
 		When {func} is given and it is one then case is ignored.
-		When {func} is a Funcref or a function name, this function is
-		called to compare items.  The function is invoked with two
+		When {func} is a |Funcref| or a function name, this function
+		is called to compare items.  The function is invoked with two
 		items as argument and must return zero if they are equal, 1 if
 		the first one sorts after the second one, -1 if the first one
 		sorts before the second one.  Example: >
@@ -4189,7 +4193,7 @@ spellbadword([{sentence}])
 
 							*spellsuggest()*
 spellsuggest({word} [, {max} [, {capital}]])
-		Return a List with spelling suggestions to replace {word}.
+		Return a |List| with spelling suggestions to replace {word}.
 		When {max} is given up to this number of suggestions are
 		returned.  Otherwise up to 25 suggestions are returned.
 
@@ -4212,8 +4216,9 @@ spellsuggest({word} [, {max} [, {capital
 
 
 split({expr} [, {pattern} [, {keepempty}]])			*split()*
-		Make a List out of {expr}.  When {pattern} is omitted or empty
-		each white-separated sequence of characters becomes an item.
+		Make a |List| out of {expr}.  When {pattern} is omitted or
+		empty each white-separated sequence of characters becomes an
+		item.
 		Otherwise the string is split where {pattern} matches,
 		removing the matched characters.
 		When the first or last item is empty it is omitted, unless the
@@ -4454,7 +4459,7 @@ system({expr} [, {input}])				*system()*
 
 
 tabpagebuflist([{arg}])					*tabpagebuflist()*
-		The result is a List, where each item is the number of the
+		The result is a |List|, where each item is the number of the
 		buffer associated with each window in the current tab page.
 		{arg} specifies the number of tab page to be used.  When
 		omitted the current tab page is used.
@@ -4525,8 +4530,8 @@ taglist({expr})							*taglist()*
 		the tags file generated by the different ctags tools.
 
 							*tagfiles()*
-tagfiles()	Returns a List with the file names used to search for tags for
-		the current buffer.  This is the 'tags' option expanded.
+tagfiles()	Returns a |List| with the file names used to search for tags
+		for the current buffer.  This is the 'tags' option expanded.
 
 
 tempname()					*tempname()* *temp-file-name*
@@ -4581,8 +4586,8 @@ type({expr})	The result is a Number, dep
 			:if type(myvar) == type({})
 
 values({dict})						*values()*
-		Return a List with all the values of {dict}.  The List is in
-		arbitrary order.
+		Return a |List| with all the values of {dict}.  The |List| is
+		in arbitrary order.
 
 
 virtcol({expr})						*virtcol()*
@@ -4593,6 +4598,8 @@ virtcol({expr})						*virtcol()*
 		position, the returned Number will be the column at the end of
 		the <Tab>.  For example, for a <Tab> in column 1, with 'ts'
 		set to 8, it returns 8.
+		For the use of {expr} see |col()|.  Additionally you can use
+		[lnum, col]: a |List| with the line and column number.
 		For the byte position use |col()|.
 		When Virtual editing is active in the current mode, a position
 		beyond the end of the line can be returned. |'virtualedit'|
@@ -4688,7 +4695,7 @@ winwidth({nr})						*winwidth()*
 <
 							*writefile()*
 writefile({list}, {fname} [, {binary}])
-		Write List {list} to file {fname}.  Each list item is
+		Write |List| {list} to file {fname}.  Each list item is
 		separated with a NL.  Each list item must be a String or
 		Number.
 		When {binary} is equal to "b" binary mode is used: There will
@@ -4930,8 +4937,8 @@ instead of "s:" when the mapping is expa
 :fu[nction]		List all functions and their arguments.
 
 :fu[nction] {name}	List function {name}.
-			{name} can also be a Dictionary entry that is a
-			Funcref: >
+			{name} can also be a |Dictionary| entry that is a
+			|Funcref|: >
 				:function dict.init
 
 :fu[nction] /{pattern}	List functions with a name matching {pattern}.
@@ -4954,8 +4961,8 @@ See |:verbose-cmd| for more information.
 			must be made of alphanumeric characters and '_', and
 			must start with a capital or "s:" (see above).
 
-			{name} can also be a Dictionary entry that is a
-			Funcref: >
+			{name} can also be a |Dictionary| entry that is a
+			|Funcref|: >
 				:function dict.init(arg)
 <			"dict" must be an existing dictionary.  The entry
 			"init" is added if it didn't exist yet.  Otherwise [!]
@@ -4983,7 +4990,7 @@ See |:verbose-cmd| for more information.
 			abort as soon as an error is detected.
 
 			When the [dict] argument is added, the function must
-			be invoked through an entry in a Dictionary.  The
+			be invoked through an entry in a |Dictionary|.  The
 			local variable "self" will then be set to the
 			dictionary.  See |Dictionary-function|.
 
@@ -4996,8 +5003,8 @@ See |:verbose-cmd| for more information.
 
 					*:delf* *:delfunction* *E130* *E131*
 :delf[unction] {name}	Delete function {name}.
-			{name} can also be a Dictionary entry that is a
-			Funcref: >
+			{name} can also be a |Dictionary| entry that is a
+			|Funcref|: >
 				:delfunc dict.init
 <			This will remove the "init" entry from "dict".  The
 			function is deleted if there are no more references to
@@ -5026,14 +5033,14 @@ Up to 20 arguments can be given, separat
 arguments an argument "..." can be specified, which means that more arguments
 may optionally be following.  In the function the extra arguments can be used
 as "a:1", "a:2", etc.  "a:0" is set to the number of extra arguments (which
-can be 0).  "a:000" is set to a List that contains these arguments.  Note that
-"a:1" is the same as "a:000[0]".
+can be 0).  "a:000" is set to a |List| that contains these arguments.  Note
+that "a:1" is the same as "a:000[0]".
 								*E742*
 The a: scope and the variables in it cannot be changed, they are fixed.
-However, if a List or Dictionary is used, you can changes their contents.
-Thus you can pass a List to a function and have the function add an item to
-it.  If you want to make sure the function cannot change a List or Dictionary
-use |:lockvar|.
+However, if a |List| or |Dictionary| is used, you can changes their contents.
+Thus you can pass a |List| to a function and have the function add an item to
+it.  If you want to make sure the function cannot change a |List| or
+|Dictionary| use |:lockvar|.
 
 When not using "...", the number of arguments in a function call must be equal
 to the number of named arguments.  When using "...", the number of arguments
@@ -5269,8 +5276,8 @@ 7. Commands						*expression-commands*
 
 							*E711* *E719*
 :let {var-name}[{idx1}:{idx2}] = {expr1}		*E708* *E709* *E710*
-			Set a sequence of items in a List to the result of the
-			expression {expr1}, which must be a list with the
+			Set a sequence of items in a |List| to the result of
+			the expression {expr1}, which must be a list with the
 			correct number of items.
 			{idx1} can be omitted, zero is used instead.
 			{idx2} can be omitted, meaning the end of the list.
@@ -5345,11 +5352,11 @@ 7. Commands						*expression-commands*
 			(if there is one).  Works like |:setglobal|.
 
 :let [{name1}, {name2}, ...] = {expr1}		*:let-unpack* *E687* *E688*
-			{expr1} must evaluate to a List.  The first item in
+			{expr1} must evaluate to a |List|.  The first item in
 			the list is assigned to {name1}, the second item to
 			{name2}, etc.
 			The number of names must match the number of items in
-			the List.
+			the |List|.
 			Each name can be one of the items of the ":let"
 			command as mentioned above.
 			Example: >
@@ -5367,10 +5374,10 @@ 7. Commands						*expression-commands*
 :let [{name1}, {name2}, ...] += {expr1}
 :let [{name1}, {name2}, ...] -= {expr1}
 			Like above, but append/add/subtract the value for each
-			List item.
+			|List| item.
 
 :let [{name}, ..., ; {lastname}] = {expr1}
-			Like |:let-unpack| above, but the List may have more
+			Like |:let-unpack| above, but the |List| may have more
 			items than there are names.  A list of the remaining
 			items is assigned to {lastname}.  If there are no
 			remaining items {lastname} is set to an empty list.
@@ -5381,7 +5388,7 @@ 7. Commands						*expression-commands*
 :let [{name}, ..., ; {lastname}] += {expr1}
 :let [{name}, ..., ; {lastname}] -= {expr1}
 			Like above, but append/add/subtract the value for each
-			List item.
+			|List| item.
 							*E106*
 :let {var-name}	..	List the value of variable {var-name}.  Multiple
 			variable names may be given.  Special names recognized
@@ -5401,13 +5408,13 @@ 7. Commands						*expression-commands*
 :unl[et][!] {name} ...					*:unlet* *:unl* *E108*
 			Remove the internal variable {name}.  Several variable
 			names can be given, they are all removed.  The name
-			may also be a List or Dictionary item.
+			may also be a |List| or |Dictionary| item.
 			With [!] no error message is given for non-existing
 			variables.
-			One or more items from a List can be removed: >
+			One or more items from a |List| can be removed: >
 				:unlet list[3]	  " remove fourth item
 				:unlet list[3:]   " remove fourth item to last
-<			One item from a Dictionary can be removed at a time: >
+<			One item from a |Dictionary| can be removed at a time: >
 				:unlet dict['two']
 				:unlet dict.two
 
@@ -5422,28 +5429,30 @@ 7. Commands						*expression-commands*
 			If you try to change a locked variable you get an
 			error message: "E741: Value of {name} is locked"
 
-			[depth] is relevant when locking a List or Dictionary.
-			It specifies how deep the locking goes:
-				1	Lock the List or Dictionary itself,
+			[depth] is relevant when locking a |List| or
+			|Dictionary|.  It specifies how deep the locking goes:
+				1	Lock the |List| or |Dictionary| itself,
 					cannot add or remove items, but can
 					still change their values.
 				2	Also lock the values, cannot change
-					the items.  If an item is a List or
-					Dictionary, cannot add or remove
+					the items.  If an item is a |List| or
+					|Dictionary|, cannot add or remove
 					items, but can still change the
 					values.
-				3	Like 2 but for the List/Dictionary in
-					the List/Dictionary, one level deeper.
-			The default [depth] is 2, thus when {name} is a List
-			or Dictionary the values cannot be changed.
+				3	Like 2 but for the |List| /
+					|Dictionary| in the |List| /
+					|Dictionary|, one level deeper.
+			The default [depth] is 2, thus when {name} is a |List|
+			or |Dictionary| the values cannot be changed.
 								*E743*
 			For unlimited depth use [!] and omit [depth].
 			However, there is a maximum depth of 100 to catch
 			loops.
 
-			Note that when two variables refer to the same List
-			and you lock one of them, the List will also be locked
-			when used through the other variable.  Example: >
+			Note that when two variables refer to the same |List|
+			and you lock one of them, the |List| will also be
+			locked when used through the other variable.  Example:
+			>
 				:let l = [0, 1, 2, 3]
 				:let cl = l
 				:lockvar l
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1,4 +1,4 @@
-*index.txt*     For Vim version 7.0aa.  Last change: 2006 Feb 23
+*index.txt*     For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1446,11 +1446,14 @@ The commands are sorted on the non-optio
 |:tabclose|	:tabc[lose]	close current tab page
 |:tabedit|	:tabe[dit]	edit a file in a new tab page
 |:tabfind|	:tabf[ind]	find file in 'path', edit it in a new tab page
+|:tabfirst|	:tabfir[st]	got to first tab page
+|:tablast|	:tabl[ast]	got to last tab page
 |:tabmove|	:tabm[ove]	move tab page to other position
 |:tabnew|	:tabnew		edit a file in a new tab page
 |:tabnext|	:tabn[ext]	go to next tab page
 |:tabonly|	:tabo[nly]	close all tab pages except the current one
 |:tabprevious|	:tabp[revious]	go to previous tab page
+|:tabrewind|	:tabr[ewind]	got to first tab page
 |:tabs|		:tabs		list the tab pages and what they contain
 |:tab|		:tab		create new tab when opening new window
 |:tag|		:ta[g]		jump to tag
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -1,4 +1,4 @@
-*map.txt*       For Vim version 7.0aa.  Last change: 2006 Feb 10
+*map.txt*       For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -778,7 +778,7 @@ This does not work if 'cpoptions' includ
 You can even do more complicated things.  For example, to consume the space
 typed after an abbreviation: >
    func Eatchar(pat)
-      let c = nr2char(getchar())
+      let c = nr2char(getchar(0))
       return (c =~ a:pat) ? '' : c
    endfunc
    iabbr <silent> if if ()<Left><C-R>=Eatchar('\s')<CR>
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.0aa.  Last change: 2006 Feb 22
+*options.txt*	For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -3249,6 +3249,9 @@ A jump table for the options with a shor
 	  'c'	Use console dialogs instead of popup dialogs for simple
 		choices.
 
+	  'e'	Add tab pages when indicated with 'showtabpages'.  When 'e' is
+	  	missing a non-GUI tab pages line may be used.
+
 	  'f'	Foreground: Don't use fork() to detach the GUI from the shell
 		where it was started.  Use this for programs that wait for the
 		editor to finish (e.g., an e-mail program).  Alternatively you
--- a/runtime/doc/tabpage.txt
+++ b/runtime/doc/tabpage.txt
@@ -1,4 +1,4 @@
-*tabpage.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 23
+*tabpage.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -132,6 +132,12 @@ gT		Go to the previous tab page.  Wraps 
 {count}gT	Go {count} tab pages back.  Wraps around from the first one
 		to the last one.
 
+:tabr[ewind]			*:tabfir* *:tabfirst* *:tabr* *:tabrewind*
+:tabl[ast]	Go to the first tab page.
+
+							*:tabl* *:tablast*
+:tabl[ast]	Go to the last tab page.
+
 
 Other commands:
 							*:tabs*
@@ -147,6 +153,28 @@ REORDERING TAB PAGES:
 		make the current tab page the first one.  Without N the tab
 		page is made the last one.
 
+
+LOOPING OVER TAB PAGES:
+
+							*:tabd* *:tabdo*
+:tabd[o] {cmd}	Execute {cmd} in each tab page.
+		It works like doing this: >
+			:tabfirst
+			:{cmd}
+			:tabnext
+			:{cmd}
+			etc.
+<		This only operates in the current window of each tab page.
+		When an error is detected on one tab page, further tab pages
+		will not be visited.
+		The last tab page (or where an error occurred) becomes the
+		current tab page.
+		{cmd} can contain '|' to concatenate several commands.
+		{cmd} must not open or close tab pages or reorder them.
+		{not in Vi} {not available when compiled without the
+		|+listcmds| feature}
+		Also see |:windo|, |:argdo| and |:bufdo|.
+
 ==============================================================================
 3. Other items						*tab-page-other*
 
--- a/runtime/doc/tagsrch.txt
+++ b/runtime/doc/tagsrch.txt
@@ -1,4 +1,4 @@
-*tagsrch.txt*   For Vim version 7.0aa.  Last change: 2005 Oct 15
+*tagsrch.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -36,19 +36,26 @@ An easy way back is with the CTRL-T comm
 below.
 
 						*:ta* *:tag* *E426* *E429*
-:ta[g][!] {ident}	Jump to the definition of {ident}, using the
+:[count]ta[g][!] {ident}
+			Jump to the definition of {ident}, using the
 			information in the tags file(s).  Put {ident} in the
 			tag stack.  See |tag-!| for [!].
 			{ident} can be a regexp pattern, see |tag-regexp|.
-			When there are several matching tags for {ident}, the
-			first one is jumped to. |:tnext|.
+			When there are several matching tags for {ident}, jump
+			to the [count] one.  When [count] is omitted the
+			first one is jumped to. See |tag-matchlist| for
+			jumping to other matching tags.
 
 g<LeftMouse>						*g<LeftMouse>*
 <C-LeftMouse>					*<C-LeftMouse>* *CTRL-]*
 CTRL-]			Jump to the definition of the keyword under the
 			cursor.  Same as ":tag {ident}", where {ident} is the
-			keyword under or after cursor.  {Vi: identifier after
-			the cursor}
+			keyword under or after cursor.
+			When there are several matching tags for {ident}, jump
+			to the [count] one.  When no [count] is given the
+			first one is jumped to. See |tag-matchlist| for
+			jumping to other matching tags.
+			{Vi: identifier after the cursor}
 
 							*v_CTRL-]*
 {Visual}CTRL-]		Same as ":tag {ident}", where {ident} is the text that
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 23
+*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -30,17 +30,32 @@ be worked on, but only if you sponsor Vi
 							*known-bugs*
 -------------------- Known bugs and current work -----------------------
 
-:tablast
-:tabfirst
-Also support:
-    :tabdup	 split the tab with all its windows.
-    :tab ball    tab page for each buffer
-    :tab all     tab page for each argument
-    :tabdo cmd   ":tabdo windo cmd" should also work
+Fix for hlsearch getting stuck on multibyte char also in 6.4.  reportec by
+Yukihiro Nakadaira.
+
 
-In GUI: right click can popup a menu to close a specific tab.
-Option to put tab line at the left or right?  Need an option to specify its
-witdh.  It's like a separate window with ":tabs" output.
+Tab pages:
+-   GTK GUI implementation for the tab pages line:
+      /tmp/vim61_tab.patch.bz2
+    Window height can be wrong:
+	:set go-=e
+	resize to fill screen
+	:set go+=e
+    Add 'guitabitem' option?
+-   GUI implementation for the tab pages line for other systems.
+8   tab pages in the session file, if "tabpages" in 'sessionoptions'
+7   :tabdup	 duplicate the tab with all its windows.
+6   :tab ball    tab page for each buffer
+6   :tab all     tab page for each argument
+7   In GUI: right click can popup a menu to close a specific tab.
+7   Option to put tab line at the left or right?  Need an option to specify
+    its witdh.  It's like a separate window with ":tabs" output.
+7   Add local variables for each tab page?
+8   Add local options for each tab page?  E.g., 'diffopt' could differ between
+    tab pages.
+7   Add local highlighting for a tab page?
+
+Spelling: m'n -> no suggestion for "mijn"?
 
 Add an argument to search functions to stop at a certain line number.
     search('{', 'b', line('w0'))
@@ -49,15 +64,6 @@ Also start at a specified position?
 
 undo could remember the '< and '> marks.
 
-Support WINDOW TABS.  Works like several pages, each with their own split
-windows.  Let's call them "tab pages".
-    - line at top of frame with tabs.
-	Add 'tabtext' option, like 'statusline'.
-    - Need to be able to search the windows in inactive tabs, e.g. for the
-      quickfix window?
-    - docs:
-	Add info to the user manual somewhere.
-
 Crash with X command server (Ciaran McCreesh).
 
 Make virtcol([lnum, col]) work?
@@ -484,16 +490,6 @@ Patch for "paranoid mode" by Kevin Colli
 Check if file explorer can handle directory names and links with a single
 quote. (Nieko Maatjes, 2005 Jan 4)
 
-Future enhancements for tab pages:
-    - Add GUI Tabs for all systems.
-      Patch for GTK 1.2 passed on by Christian Michon, 2004 Jan 6.
-      Simple patch for GTK by Luis M (nov 7).
-    - ":tabsplit" makes a copy of the current tab page.
-    - Add local variables for each tab page?
-    - Add local options for each tab page?  E.g., 'diffopt' could differ
-      between tab pages.
-    - Add local highlighting for a tab page?
-
 
 Vi incompatibility:
 8   With undo/redo only marks in the changed lines should be changed.  Other
@@ -2074,7 +2070,6 @@ Tags:
 7   Can CTRL-] (jump to tag) include a following "." and "->" to restrict the
     number of possible matches? Check tags file for an item that has members.
     (Flemming Madsen)
-7   Count before CTRL-]: jump to N'th match
 8   Scope arguments for ":tag", e.g.: ":tag class:cPage open", like Elvis.
 8   When output of ":tselect" is long, getting the more-prompt, should be able
     to type the tag number directly.
--- a/runtime/doc/usr_08.txt
+++ b/runtime/doc/usr_08.txt
@@ -1,4 +1,4 @@
-*usr_08.txt*	For Vim version 7.0aa.  Last change: 2005 Apr 01
+*usr_08.txt*	For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 		     VIM USER MANUAL - by Bram Moolenaar
 
@@ -17,6 +17,7 @@ side by side.  All this is possible with
 |08.6|	Commands for all windows
 |08.7|	Viewing differences with vimdiff
 |08.8|	Various
+|08.9|  Tab pages
 
      Next chapter: |usr_09.txt|  Using the GUI
  Previous chapter: |usr_07.txt|  Editing more than one file
@@ -504,6 +505,95 @@ window is to appear:
 	:topleft {cmd}		at the top or left of the Vim window
 	:botright {cmd}		at the bottom or right of the Vim window
 
+
+==============================================================================
+*08.9*	Tab pages
+
+You will have noticed that windows never overlap.  That means you quickly run
+out of screen space.  The solution for this is called Tab pages.
+
+Assume you are editing "thisfile".  To create a new tab page use this command: >
+
+	:tabedit thatfile
+
+This will edit the file "thatfile" in a window that occupies the whole Vim
+window.  And you will notice a bar at the top with the two file names:
+
+	+----------------------------------+
+	|_thisfile_| thatfile ____________X|
+	|/* thatfile */  		   |
+	|that				   |
+	|that				   |
+	|~                                 |
+	|~                                 |
+	|~                                 |
+	|				   |
+	+----------------------------------+
+
+You now have two tab pages.  The first one has a window for "thisfile" and the
+second one a window for "thatfile".  It's like two pages that are on top of
+eachother, with a tab sticking out of each page showing the file name.
+
+Now use the mouse to click on "thisfile" in the top line.  The result is
+
+	+----------------------------------+
+	| thisfile |_thatfile_____________X|
+	|/* thisfile */  		   |
+	|this				   |
+	|this				   |
+	|~                                 |
+	|~                                 |
+	|~                                 |
+	|				   |
+	+----------------------------------+
+
+Thus you can switch between tab pages by clicking on the label in the top
+line.  If you don't have a mouse or don't want to use it, you can use the "gt"
+command.  Mnemonic: Goto Tab.
+
+Now let's create another tab page with the command: >
+
+	:tab split
+
+This makes a new tab page with one window that is editing the same buffer as
+the window we were in:
+
+	+-------------------------------------+
+	|_thisfile_| thisfile | _thatfile____X|
+	|/* thisfile */  		      |
+	|this				      |
+	|this				      |
+	|~                                    |
+	|~                                    |
+	|~                                    |
+	|				      |
+	+-------------------------------------+
+
+You can put ":tab" before any Ex command that opens a window.  The window will
+be opened in a new tab page.  Another example: >
+
+	:tab help gt
+
+Will show the help text for "gt" in a new tab page.
+
+A few more things you can do with tab pages:
+
+- click with the mouse in the space after the last label
+  	The next tab page will be selected, like with "gt".
+
+- click with the mouse on the "X" in the top right corner
+  	The current tab page will be closed.  Unless there are unsaved
+	changes in the current tab page.
+
+- double click with the mouse in the top line
+  	A new tab page will be created.
+
+- the "tabonly" command
+  	Closes all tab pages except the current one.  Unless there are unsaved
+	changes in other tab pages.
+
+For more information about tab pages see |tab-page|.
+
 ==============================================================================
 
 Next chapter: |usr_09.txt|  Using the GUI
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Feb 23
+*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1038,6 +1038,10 @@ made empty to avoid an endless redraw lo
 'tabline'.  ":verbose set statusline" will mention that it was set in an error
 handler.
 
+When there are several matching tags, the ":tag <name>" and CTRL-] commands
+jump to the [count] matching tag. (Yegappan Lakshmanan)
+
+
 ==============================================================================
 COMPILE TIME CHANGES					*compile-changes-7*
 
@@ -1740,4 +1744,9 @@ For a color terminal: When the Normal HL
 lighter, and another HL group specifies a color it might become light as well.
 Now reset bold if a HL group doesn't specify bold itself.
 
+When using 256 color xterm the color 255 would show up as color 0.  Use a
+short instead of a char to store the color number.
+
+ml_get errors when searching for "\n\zs" in an empty file.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -1,4 +1,4 @@
-*windows.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 23
+*windows.txt*   For Vim version 7.0aa.  Last change: 2006 Feb 24
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -629,7 +629,7 @@ 8. Do a command in all buffers or window
 				CTRL-W w
 				:{cmd}
 				etc.
-<			This only works in the current tab page.
+<			This only operates in the current tab page.
 			When an error is detected on one window, further
 			windows will not be visited.
 			The last window (or where an error occurred) becomes
@@ -638,7 +638,7 @@ 8. Do a command in all buffers or window
 			{cmd} must not open or close windows or reorder them.
 			{not in Vi} {not available when compiled without the
 			|+listcmds| feature}
-			Also see |:argdo| and |:bufdo|.
+			Also see |:tabdo|, |:argdo| and |:bufdo|.
 
 							*:bufdo*
 :bufdo[!] {cmd}		Execute {cmd} in each buffer in the buffer list.
@@ -664,7 +664,7 @@ 8. Do a command in all buffers or window
 			each buffer.
 			{not in Vi} {not available when compiled without the
 			|+listcmds| feature}
-			Also see |:argdo| and |:windo|.
+			Also see |:tabdo|, |:argdo| and |:windo|.
 
 Examples: >
 
--- a/src/Makefile
+++ b/src/Makefile
@@ -548,8 +548,8 @@ LINT_OPTIONS = -beprxzF
 #PROFILE_LIBS = -lccmalloc
 
 # MAC OS X platform
-#MAC_OSX_ARCH = -arch ppc
-MAC_OSX_ARCH = -arch i386 -arch ppc
+MAC_OSX_ARCH = -arch ppc
+#MAC_OSX_ARCH = -arch i386
 
 #####################################################
 ###  Specific systems, check if yours is listed!  ### {{{
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -2780,7 +2780,7 @@ if test -z "$CFLAGS"; then
   test "$GCC" = yes && CFLAGS="-O2 -fno-strength-reduce -Wall"
 fi
 if test "$GCC" = yes; then
-  gccversion=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\([0-9]\.[0-9.]*\).*$/\1/g'`
+  gccversion=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\(darwin.[^0-9]*\)*\([0-9]\.[0-9.]*\).*$/\2/g'`
     if test "$gccversion" = "3.0.1" -o "$gccversion" = "3.0.2" -o "$gccversion" = "4.0.1"; then
     echo 'GCC 34.0.12 has a bug in the optimizer, disabling "-O#"'
     CFLAGS=`echo "$CFLAGS" | sed 's/-O[23456789]/-O/'`
@@ -2868,7 +2868,7 @@ echo "${ECHO_T}yes, Darwin support exclu
     MACOSX=yes
     OS_EXTRA_SCR="os_macosx.c os_mac_conv.c";
     OS_EXTRA_OBJ="objects/os_macosx.o objects/os_mac_conv.o"
-    CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp"
+        CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp -arch ppc"
 
                 echo "$as_me:$LINENO: checking for ANSI C header files" >&5
 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
@@ -15087,7 +15087,7 @@ echo "$as_me:$LINENO: checking for GCC 3
 echo $ECHO_N "checking for GCC 3 or later... $ECHO_C" >&6
 DEPEND_CFLAGS_FILTER=
 if test "$GCC" = yes; then
-  gccmajor=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\([1-9]\)\.[0-9.]*.*$/\1/g'`
+  gccmajor=`"$CC" --version | sed -e '2,$d;s/^[^0-9]*\(darwin.[^0-9]*\)*\([1-9]\)\.[0-9].*$/\2/g'`
   if test "$gccmajor" -gt "2"; then
     DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'"
   fi
--- a/src/configure.in
+++ b/src/configure.in
@@ -29,7 +29,7 @@ if test -z "$CFLAGS"; then
   test "$GCC" = yes && CFLAGS="-O2 -fno-strength-reduce -Wall"
 fi
 if test "$GCC" = yes; then
-  gccversion=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\([[0-9]]\.[[0-9.]]*\).*$/\1/g'`
+  gccversion=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\(darwin.[[^0-9]]*\)*\([[0-9]]\.[[0-9.]]*\).*$/\2/g'`
   dnl version 4.0.1 was reported to cause trouble on Macintosh by Marcin Dalecki
   if test "$gccversion" = "3.0.1" -o "$gccversion" = "3.0.2" -o "$gccversion" = "4.0.1"; then
     echo 'GCC [34].0.[12] has a bug in the optimizer, disabling "-O#"'
@@ -106,7 +106,8 @@ if test "`(uname) 2>/dev/null`" = Darwin
     MACOSX=yes
     OS_EXTRA_SCR="os_macosx.c os_mac_conv.c";
     OS_EXTRA_OBJ="objects/os_macosx.o objects/os_mac_conv.o"
-    CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp -arch i386 -arch ppc"
+    dnl TODO: use -arch i386 on Intel machines
+    CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp -arch ppc"
 
     dnl If Carbon is found, assume we don't want X11
     dnl unless it was specifically asked for (--with-x)
@@ -2757,10 +2758,12 @@ fi
 dnl gcc 3.1 changed the meaning of -MM.  The only solution appears to be to
 dnl use "-isystem" instead of "-I" for all non-Vim include dirs.
 dnl But only when making dependencies, cproto and lint don't take "-isystem".
+dnl Mac gcc returns "powerpc-apple-darwin8-gcc-4.0.1 (GCC)...", need to allow
+dnl the number before the version number.
 AC_MSG_CHECKING(for GCC 3 or later)
 DEPEND_CFLAGS_FILTER=
 if test "$GCC" = yes; then
-  gccmajor=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\([[1-9]]\)\.[[0-9.]]*.*$/\1/g'`
+  gccmajor=`"$CC" --version | sed -e '2,$d;s/^[[^0-9]]*\(darwin.[[^0-9]]*\)*\([[1-9]]\)\.[[0-9]].*$/\2/g'`
   if test "$gccmajor" -gt "2"; then
     DEPEND_CFLAGS_FILTER="| sed 's+-I */+-isystem /+g'"
   fi
--- a/src/eval.c
+++ b/src/eval.c
@@ -14934,7 +14934,6 @@ f_tabpagenr(argvars, rettv)
 {
     int		nr = 1;
 #ifdef FEAT_WINDOWS
-    tabpage_T	*tp;
     char_u	*arg;
 
     if (argvars[0].v_type != VAR_UNKNOWN)
@@ -14944,15 +14943,13 @@ f_tabpagenr(argvars, rettv)
 	if (arg != NULL)
 	{
 	    if (STRCMP(arg, "$") == 0)
-		for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
-		    ++nr;
+		nr = tabpage_index(NULL);
 	    else
 		EMSG2(_(e_invexpr2), arg);
 	}
     }
     else
-	for (tp = first_tabpage; tp != curtab; tp = tp->tp_next)
-	    ++nr;
+	nr = tabpage_index(curtab);
 #endif
     rettv->vval.v_number = nr;
 }
@@ -15616,6 +15613,7 @@ f_writefile(argvars, rettv)
 
 /*
  * Translate a String variable into a position.
+ * Returns NULL when there is an error.
  */
     static pos_T *
 var2fpos(varp, lnum)
@@ -15626,6 +15624,39 @@ var2fpos(varp, lnum)
     static pos_T	pos;
     pos_T	*pp;
 
+    /* Argument can be [lnum, col]. */
+    if (varp->v_type == VAR_LIST)
+    {
+	list_T		*l;
+	listitem_T	*li;
+	int		len;
+
+	l = varp->vval.v_list;
+	if (l == NULL)
+	    return NULL;
+
+	/* Get the line number */
+	li = list_find(l, 0L);
+	if (li == NULL)
+	    return NULL;
+	pos.lnum = get_tv_number(&li->li_tv);
+	if (pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
+	    return NULL;	/* invalid line number */
+
+	/* Get the column number */
+	li = list_find(l, 1L);
+	if (li == NULL)
+	    return NULL;
+	pos.col = get_tv_number(&li->li_tv);
+	len = (long)STRLEN(ml_get(pos.lnum));
+	if (pos.col <= 0 || ((len == 0 && pos.col > 1)
+					       || (len > 0 && pos.col > len)))
+	    return NULL;	/* invalid column number */
+
+	pos.col--;
+	return &pos;
+    }
+
     name = get_tv_string_chk(varp);
     if (name == NULL)
 	return NULL;
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -881,22 +881,30 @@ EX(CMD_tab,		"tab",		ex_wrongmodifier,
 			NEEDARG|EXTRA|NOTRLCOM),
 EX(CMD_tabclose,	"tabclose",	ex_tabclose,
 			RANGE|NOTADR|COUNT|BANG|TRLBAR|CMDWIN),
+EX(CMD_tabdo,		"tabdo",	ex_listdo,
+			NEEDARG|EXTRA|NOTRLCOM),
 EX(CMD_tabedit,		"tabedit",	ex_splitview,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_tabfind,		"tabfind",	ex_splitview,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|NEEDARG|TRLBAR),
+EX(CMD_tabfirst,	"tabfirst",	ex_tabnext,
+			TRLBAR),
 EX(CMD_tabmove,		"tabmove",	ex_tabmove,
 			RANGE|NOTADR|COUNT|TRLBAR|ZEROR),
+EX(CMD_tablast,		"tablast",	ex_tabnext,
+			TRLBAR),
 EX(CMD_tabnext,		"tabnext",	ex_tabnext,
 			RANGE|NOTADR|COUNT|TRLBAR),
 EX(CMD_tabnew,		"tabnew",	ex_splitview,
 			BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR),
 EX(CMD_tabonly,		"tabonly",	ex_tabonly,
 			TRLBAR|CMDWIN),
-EX(CMD_tabprevious,	"tabprevious",	ex_tabprevious,
+EX(CMD_tabprevious,	"tabprevious",	ex_tabnext,
 			RANGE|NOTADR|COUNT|TRLBAR),
-EX(CMD_tabNext,		"tabNext",	ex_tabprevious,
+EX(CMD_tabNext,		"tabNext",	ex_tabnext,
 			RANGE|NOTADR|COUNT|TRLBAR),
+EX(CMD_tabrewind,	"tabrewind",	ex_tabnext,
+			TRLBAR),
 EX(CMD_tabs,		"tabs",		ex_tabs,
 			TRLBAR|CMDWIN),
 EX(CMD_tcl,		"tcl",		ex_tcl,
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -2155,7 +2155,7 @@ ex_argdelete(eap)
 }
 
 /*
- * ":argdo", ":windo", ":bufdo"
+ * ":argdo", ":windo", ":bufdo", ":tabdo"
  */
     void
 ex_listdo(eap)
@@ -2163,7 +2163,8 @@ ex_listdo(eap)
 {
     int		i;
 #ifdef FEAT_WINDOWS
-    win_T	*win;
+    win_T	*wp;
+    tabpage_T	*tp;
 #endif
     buf_T	*buf;
     int		next_fnum = 0;
@@ -2188,13 +2189,15 @@ ex_listdo(eap)
 #endif
 
     if (eap->cmdidx == CMD_windo
+	    || eap->cmdidx == CMD_tabdo
 	    || P_HID(curbuf)
 	    || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
     {
 	/* start at the first argument/window/buffer */
 	i = 0;
 #ifdef FEAT_WINDOWS
-	win = firstwin;
+	wp = firstwin;
+	tp = first_tabpage;
 #endif
 	/* set pcmark now */
 	if (eap->cmdidx == CMD_bufdo)
@@ -2229,11 +2232,19 @@ ex_listdo(eap)
 #ifdef FEAT_WINDOWS
 	    else if (eap->cmdidx == CMD_windo)
 	    {
-		/* go to window "win" */
-		if (!win_valid(win))
+		/* go to window "wp" */
+		if (!win_valid(wp))
 		    break;
-		win_goto(win);
-		win = curwin->w_next;
+		win_goto(wp);
+		wp = curwin->w_next;
+	    }
+	    else if (eap->cmdidx == CMD_tabdo)
+	    {
+		/* go to window "tp" */
+		if (!valid_tabpage(tp))
+		    break;
+		goto_tabpage_tp(tp);
+		tp = tp->tp_next;
 	    }
 #endif
 	    else if (eap->cmdidx == CMD_bufdo)
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -156,7 +156,6 @@ static void	ex_stag __ARGS((exarg_T *eap
 static void	ex_tabclose __ARGS((exarg_T *eap));
 static void	ex_tabonly __ARGS((exarg_T *eap));
 static void	ex_tabnext __ARGS((exarg_T *eap));
-static void	ex_tabprevious __ARGS((exarg_T *eap));
 static void	ex_tabmove __ARGS((exarg_T *eap));
 static void	ex_tabs __ARGS((exarg_T *eap));
 #else
@@ -167,7 +166,6 @@ static void	ex_tabs __ARGS((exarg_T *eap
 # define ex_splitview		ex_ni
 # define ex_stag		ex_ni
 # define ex_tabnext		ex_ni
-# define ex_tabprevious		ex_ni
 # define ex_tabmove		ex_ni
 # define ex_tabs		ex_ni
 # define ex_tabclose		ex_ni
@@ -1865,17 +1863,10 @@ do_one_cmd(cmdlinep, sourcing,
 	    case 't':	if (checkforcmd(&p, "tab", 3))
 			{
 #ifdef FEAT_WINDOWS
-			    tabpage_T	*tp;
-
 			    if (vim_isdigit(*ea.cmd))
 				cmdmod.tab = atoi((char *)ea.cmd) + 1;
 			    else
-			    {
-				cmdmod.tab = 2;
-				for (tp = first_tabpage; tp != curtab;
-							     tp = tp->tp_next)
-				    ++cmdmod.tab;
-			    }
+				cmdmod.tab = tabpage_index(curtab) + 1;
 			    ea.cmd = p;
 #endif
 			    continue;
@@ -6242,7 +6233,7 @@ ex_tabclose(eap)
     exarg_T	*eap;
 {
     tabpage_T	*tp;
-    int		h = tabpageline_height();
+    int		h = tabline_height();
 
 # ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
@@ -6271,7 +6262,7 @@ ex_tabclose(eap)
 		tabpage_close(eap->forceit);
 	}
 
-    if (h != tabpageline_height())
+    if (h != tabline_height())
 	shell_new_rows();
 }
 
@@ -6284,7 +6275,7 @@ ex_tabonly(eap)
 {
     tabpage_T	*tp;
     int		done;
-    int		h = tabpageline_height();
+    int		h = tabline_height();
 
 # ifdef FEAT_CMDWIN
     if (cmdwin_type != 0)
@@ -6314,7 +6305,7 @@ ex_tabonly(eap)
 	    }
 	}
 
-    if (h != tabpageline_height())
+    if (h != tabline_height())
 	shell_new_rows();
 }
 
@@ -7042,17 +7033,23 @@ tabpage_new()
 ex_tabnext(eap)
     exarg_T	*eap;
 {
-    goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2);
-}
-
-/*
- * :tabprevious and :tabNext command
- */
-    static void
-ex_tabprevious(eap)
-    exarg_T	*eap;
-{
-    goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2);
+    switch (eap->cmdidx)
+    {
+	case CMD_tabfirst:
+	case CMD_tabrewind:
+	    goto_tabpage(1);
+	    break;
+	case CMD_tablast:
+	    goto_tabpage(9999);
+	    break;
+	case CMD_tabprevious:
+	case CMD_tabNext:
+	    goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2);
+	    break;
+	default: /* CMD_tabnext */
+	    goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2);
+	    break;
+    }
 }
 
 /*
--- a/src/feature.h
+++ b/src/feature.h
@@ -730,6 +730,13 @@
 #endif
 
 /*
+ * GUI tabline
+ */
+#if defined(FEAT_GUI_GTK) && defined(HAVE_GTK2) && defined(FEAT_WINDOWS)
+# define FEAT_GUI_TABLINE
+#endif
+
+/*
  * +browse		":browse" command.
  */
 #if defined(FEAT_NORMAL) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC))
--- a/src/globals.h
+++ b/src/globals.h
@@ -435,6 +435,10 @@ EXTERN vimmenu_T	*current_menu;
 /* Set to TRUE after adding/removing menus to ensure they are updated */
 EXTERN int force_menu_update INIT(= FALSE);
 # endif
+# ifdef FEAT_GUI_TABLINE
+/* Tab in tab pages line just selected, set by check_termcode() */
+EXTERN int	    current_tab;
+# endif
 
 /* Scrollbar moved and new value, set by check_termcode() */
 EXTERN int	current_scrollbar;
--- a/src/gui.c
+++ b/src/gui.c
@@ -26,6 +26,9 @@ static int gui_screenstr __ARGS((int off
 static void gui_delete_lines __ARGS((int row, int count));
 static void gui_insert_lines __ARGS((int row, int count));
 static void fill_mouse_coord __ARGS((char_u *p, int col, int row));
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+static int gui_has_tabline __ARGS((void));
+#endif
 static void gui_do_scrollbar __ARGS((win_T *wp, int which, int enable));
 static colnr_T scroll_line_len __ARGS((linenr_T lnum));
 static void gui_update_horiz_scrollbar __ARGS((int));
@@ -1410,7 +1413,7 @@ gui_set_shellsize(mustset, fit_to_displa
     min_width = base_width + MIN_COLUMNS * gui.char_width;
     min_height = base_height + MIN_LINES * gui.char_height;
 # ifdef FEAT_WINDOWS
-    min_height += tabpageline_height() * gui.char_height;
+    min_height += tabline_height() * gui.char_height;
 # endif
 
     gui_mch_set_shellsize(width, height, min_width, min_height,
@@ -3081,7 +3084,7 @@ static int	prev_which_scrollbars[3] = {-
 
 /*
  * Set which components are present.
- * If "oldval" is not NULL, "oldval" is the previous value, the new * value is
+ * If "oldval" is not NULL, "oldval" is the previous value, the new value is
  * in p_go.
  */
 /*ARGSUSED*/
@@ -3096,6 +3099,10 @@ gui_init_which_components(oldval)
     static int	prev_toolbar = -1;
     int		using_toolbar = FALSE;
 #endif
+#ifdef FEAT_GUI_TABLINE
+    static int	prev_has_tabline = FALSE;
+    int		using_tabline;
+#endif
 #ifdef FEAT_FOOTER
     static int	prev_footer = -1;
     int		using_footer = FALSE;
@@ -3185,10 +3192,27 @@ gui_init_which_components(oldval)
 		/* Ignore options that are not supported */
 		break;
 	}
+
     if (gui.in_use)
     {
 	need_set_size = FALSE;
 	fix_size = FALSE;
+
+#ifdef FEAT_GUI_TABLINE
+	/* Update the tab line, it may appear or disappear. */
+	using_tabline = gui_has_tabline();
+	if (prev_has_tabline != using_tabline)
+	{
+	    prev_has_tabline = using_tabline;
+	    gui_update_tabline();
+	    need_set_size = TRUE;
+	    if (using_tabline)
+		fix_size = TRUE;
+	    if (!gui_use_tabline())
+		redraw_tabline = TRUE;    /* may draw non-GUI tab line */
+	}
+#endif
+
 	for (i = 0; i < 3; i++)
 	{
 	    if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
@@ -3281,6 +3305,82 @@ gui_init_which_components(oldval)
     }
 }
 
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+/*
+ * Return TRUE if the GUI is taking care of the tabline.
+ * It may still be hidden if 'showtabline' is zero.
+ */
+    int
+gui_use_tabline()
+{
+    return gui.in_use && vim_strchr(p_go, GO_TABLINE) != NULL;
+}
+
+/*
+ * Return TRUE if the GUI is showing the tabline.
+ * This uses 'showtabline'.
+ */
+    static int
+gui_has_tabline()
+{
+    if (!gui_use_tabline()
+	    || p_stal == 0
+	    || (p_stal == 1 && first_tabpage->tp_next == NULL))
+	return FALSE;
+    return TRUE;
+}
+
+/*
+ * Update the tabline.
+ * This may display/undisplay the tabline and update the labels.
+ */
+    void
+gui_update_tabline()
+{
+    int	    showit = gui_has_tabline();
+
+    if (!gui.starting && starting == 0)
+    {
+	gui_mch_show_tabline(showit);
+	if (showit != 0)
+	    gui_mch_update_tabline();
+    }
+}
+
+/*
+ * Get the label for tab page "tp" into NameBuff[].
+ */
+    void
+get_tabline_label(tp)
+    tabpage_T	*tp;
+{
+    int		modified = FALSE;
+    char_u	buf[40];
+    int		wincount;
+    win_T	*wp;
+
+    /* Get the buffer name into NameBuff[] */
+    get_trans_bufname(tp == curtab ? curbuf : tp->tp_curwin->w_buffer);
+
+    wp = (tp == curtab) ? firstwin : tp->tp_firstwin;
+    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 *)buf, sizeof(buf), "%d", wincount);
+	else
+	    buf[0] = NUL;
+	if (modified)
+	    STRCAT(buf, "+");
+	STRCAT(buf, " ");
+	mch_memmove(NameBuff + STRLEN(buf), NameBuff, STRLEN(NameBuff) + 1);
+	mch_memmove(NameBuff, buf, STRLEN(buf));
+    }
+}
+
+#endif
 
 /*
  * Scrollbar stuff:
--- a/src/gui.h
+++ b/src/gui.h
@@ -393,6 +393,7 @@ typedef struct Gui
     PangoContext     *text_context; /* the context used for all text */
     PangoFont	     *ascii_font;   /* cached font for ASCII strings */
     PangoGlyphString *ascii_glyphs; /* cached code point -> glyph map */
+    GtkWidget	*tabline;	    /* tab pages line handle */
 # endif
 
     GtkAccelGroup *accel_group;
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -2827,6 +2827,145 @@ delete_event_cb(GtkWidget *widget, GdkEv
     return TRUE;
 }
 
+#if defined(FEAT_MENU) || defined(FEAT_TOOLBAR) || defined(FEAT_GUI_TABLINE)
+    static int
+get_item_dimensions(GtkWidget *widget, GtkOrientation orientation)
+{
+    GtkOrientation item_orientation = GTK_ORIENTATION_HORIZONTAL;
+
+#ifdef FEAT_GUI_GNOME
+    if (using_gnome && widget != NULL)
+    {
+# ifdef HAVE_GTK2
+	BonoboDockItem *dockitem;
+
+	widget	 = gtk_widget_get_parent(widget);
+	dockitem = BONOBO_DOCK_ITEM(widget);
+
+	if (dockitem == NULL || dockitem->is_floating)
+	    return 0;
+	item_orientation = bonobo_dock_item_get_orientation(dockitem);
+# else
+	GnomeDockItem *dockitem;
+
+	widget	 = widget->parent;
+	dockitem = GNOME_DOCK_ITEM(widget);
+
+	if (dockitem == NULL || dockitem->is_floating)
+	    return 0;
+	item_orientation = gnome_dock_item_get_orientation(dockitem);
+# endif
+    }
+#endif
+    if (widget != NULL
+	    && item_orientation == orientation
+	    && GTK_WIDGET_REALIZED(widget)
+	    && GTK_WIDGET_VISIBLE(widget))
+    {
+	if (orientation == GTK_ORIENTATION_HORIZONTAL)
+	    return widget->allocation.height;
+	else
+	    return widget->allocation.width;
+    }
+    return 0;
+}
+#endif
+
+    static int
+get_menu_tool_width(void)
+{
+    int width = 0;
+
+#ifdef FEAT_GUI_GNOME /* these are never vertical without GNOME */
+# ifdef FEAT_MENU
+    width += get_item_dimensions(gui.menubar, GTK_ORIENTATION_VERTICAL);
+# endif
+# ifdef FEAT_TOOLBAR
+    width += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_VERTICAL);
+# endif
+# ifdef FEAT_GUI_TABLINE
+    width += get_item_dimensions(gui.tabline, GTK_ORIENTATION_VERTICAL);
+# endif
+#endif
+
+    return width;
+}
+
+    static int
+get_menu_tool_height(void)
+{
+    int height = 0;
+
+#ifdef FEAT_MENU
+    height += get_item_dimensions(gui.menubar, GTK_ORIENTATION_HORIZONTAL);
+#endif
+#ifdef FEAT_TOOLBAR
+    height += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_HORIZONTAL);
+#endif
+#ifdef FEAT_GUI_TABLINE
+    height += get_item_dimensions(gui.tabline, GTK_ORIENTATION_HORIZONTAL);
+#endif
+
+    return height;
+}
+
+    static void
+update_window_manager_hints(void)
+{
+    static int old_width  = 0;
+    static int old_height = 0;
+    static int old_char_width  = 0;
+    static int old_char_height = 0;
+
+    int width;
+    int height;
+
+    /* This also needs to be done when the main window isn't there yet,
+     * otherwise the hints don't work. */
+    width  = gui_get_base_width();
+    height = gui_get_base_height();
+# ifdef FEAT_MENU
+    height += tabline_height() * gui.char_height;
+# endif
+# ifdef HAVE_GTK2
+    width  += get_menu_tool_width();
+    height += get_menu_tool_height();
+# endif
+
+    /* Avoid an expose event when the size didn't change. */
+    if (width != old_width
+	    || height != old_height
+	    || gui.char_width != old_char_width
+	    || gui.char_height != old_char_height)
+    {
+	GdkGeometry	geometry;
+	GdkWindowHints	geometry_mask;
+
+	geometry.width_inc   = gui.char_width;
+	geometry.height_inc  = gui.char_height;
+	geometry.base_width  = width;
+	geometry.base_height = height;
+	geometry.min_width   = width  + MIN_COLUMNS * gui.char_width;
+	geometry.min_height  = height + MIN_LINES   * gui.char_height;
+	geometry_mask	     = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC
+			       |GDK_HINT_MIN_SIZE;
+# ifdef HAVE_GTK2
+	/* Using gui.formwin as geometry widget doesn't work as expected
+	 * with GTK+ 2 -- dunno why.  Presumably all the resizing hacks
+	 * in Vim confuse GTK+. */
+	gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.mainwin,
+				      &geometry, geometry_mask);
+# else
+	gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
+				      &geometry, geometry_mask);
+# endif
+	old_width  = width;
+	old_height = height;
+	old_char_width	= gui.char_width;
+	old_char_height = gui.char_height;
+    }
+}
+
 #ifdef FEAT_TOOLBAR
 
 # ifdef HAVE_GTK2
@@ -2920,6 +3059,122 @@ set_toolbar_style(GtkToolbar *toolbar)
 
 #endif /* FEAT_TOOLBAR */
 
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+static int ignore_tabline_evt = FALSE;
+
+/*
+ * Handle selecting one of the tabs.
+ */
+/*ARGSUSED*/
+    static void
+on_select_tab(
+	GtkNotebook	*notebook,
+	GtkNotebookPage *page,
+	gint		index,
+	gpointer	data)
+{
+    static char_u string[3];
+
+    if (!ignore_tabline_evt)
+    {
+	string[0] = CSI;
+	string[1] = KS_TABLINE;
+	string[2] = KE_FILLER;
+	add_to_input_buf(string, 3);
+	string[0] = index + 1;
+	add_to_input_buf_csi(string, 1);
+
+	if (gtk_main_level() > 0)
+	    gtk_main_quit();
+    }
+}
+
+/*
+ * Show or hide the tabline.
+ */
+    void
+gui_mch_show_tabline(int showit)
+{
+    if (gui.tabline == NULL)
+	return;
+
+    if (!showit != !gtk_notebook_get_show_tabs(GTK_NOTEBOOK(gui.tabline)))
+    {
+	gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), showit);
+	update_window_manager_hints();
+    }
+}
+
+/*
+ * Update the labels of the tabline.
+ */
+    void
+gui_mch_update_tabline(void)
+{
+    GtkWidget	    *page;
+    GtkWidget	    *label;
+    tabpage_T	    *tp;
+    int		    nr = 0;
+    int		    curtabidx = 0;
+
+    if (gui.tabline == NULL)
+	return;
+
+    ignore_tabline_evt = TRUE;
+
+    /* Add a label for each tab page.  They all contain the same text area. */
+    for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
+    {
+	if (tp == curtab)
+	    curtabidx = nr;
+
+	page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gui.tabline), nr);
+	if (page == NULL)
+	{
+	    /* Add notebook page */
+	    page = gtk_vbox_new(FALSE, 0);
+	    gtk_widget_show(page);
+	    label = gtk_label_new("-Empty-");
+	    gtk_widget_show(label);
+	    gtk_notebook_insert_page(GTK_NOTEBOOK(gui.tabline),
+		    page,
+		    label,
+		    nr++);
+	}
+
+	get_tabline_label(tp);
+	gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(gui.tabline), page,
+						     (const gchar *)NameBuff);
+    }
+
+    /* Remove any old labels. */
+    while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(gui.tabline), nr) != NULL)
+	gtk_notebook_remove_page(GTK_NOTEBOOK(gui.tabline), nr);
+
+    if (gtk_notebook_current_page(GTK_NOTEBOOK(gui.tabline)) != curtabidx)
+        gtk_notebook_set_page(GTK_NOTEBOOK(gui.tabline), curtabidx);
+
+    ignore_tabline_evt = FALSE;
+}
+
+/*
+ * Set the current tab to "nr".  First tab is 1.
+ */
+    void
+gui_mch_set_curtab(nr)
+    int		nr;
+{
+    if (gui.tabline == NULL)
+	return;
+
+    ignore_tabline_evt = TRUE;
+    if (gtk_notebook_current_page(GTK_NOTEBOOK(gui.tabline)) != nr - 1)
+        gtk_notebook_set_page(GTK_NOTEBOOK(gui.tabline), nr - 1);
+    ignore_tabline_evt = FALSE;
+}
+
+#endif /* FEAT_GUI_TABLINE */
+
 /*
  * Initialize the GUI.	Create all the windows, set up all the callbacks etc.
  * Returns OK for success, FAIL when the GUI can't be started.
@@ -3060,6 +3315,7 @@ gui_mch_init(void)
     gui.accel_group = gtk_accel_group_get_default();
 #endif
 
+    /* A vertical box holds the menubar, toolbar and main text window. */
     vbox = gtk_vbox_new(FALSE, 0);
 
 #ifdef FEAT_GUI_GNOME
@@ -3194,6 +3450,30 @@ gui_mch_init(void)
     }
 #endif /* FEAT_TOOLBAR */
 
+#ifdef FEAT_GUI_TABLINE
+    /* Use a Notebook for the tab pages labels.  The labels are hidden by
+     * default. */
+    gui.tabline = gtk_notebook_new();
+    gtk_widget_show(gui.tabline);
+    gtk_box_pack_start(GTK_BOX(vbox), gui.tabline, FALSE, FALSE, 0);
+    gtk_notebook_set_show_border(GTK_NOTEBOOK(gui.tabline), FALSE);
+    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), FALSE);
+
+    {
+	GtkWidget *page, *label;
+
+	/* Add the first tab. */
+	page = gtk_vbox_new(FALSE, 0);
+	gtk_widget_show(page);
+	gtk_container_add(GTK_CONTAINER(gui.tabline), page);
+	label = gtk_label_new("-Empty-");
+	gtk_widget_show(label);
+	gtk_notebook_set_tab_label(GTK_NOTEBOOK(gui.tabline), page, label);
+    }
+    gtk_signal_connect(GTK_OBJECT(gui.tabline), "switch_page",
+		       GTK_SIGNAL_FUNC(on_select_tab), NULL);
+#endif
+
     gui.formwin = gtk_form_new();
     gtk_container_border_width(GTK_CONTAINER(gui.formwin), 0);
     gtk_widget_set_events(gui.formwin, GDK_EXPOSURE_MASK);
@@ -3365,139 +3645,6 @@ gui_mch_new_colors(void)
     }
 }
 
-#if defined(FEAT_MENU) || defined(FEAT_TOOLBAR)
-    static int
-get_item_dimensions(GtkWidget *widget, GtkOrientation orientation)
-{
-    GtkOrientation item_orientation = GTK_ORIENTATION_HORIZONTAL;
-
-#ifdef FEAT_GUI_GNOME
-    if (using_gnome && widget != NULL)
-    {
-# ifdef HAVE_GTK2
-	BonoboDockItem *dockitem;
-
-	widget	 = gtk_widget_get_parent(widget);
-	dockitem = BONOBO_DOCK_ITEM(widget);
-
-	if (dockitem == NULL || dockitem->is_floating)
-	    return 0;
-	item_orientation = bonobo_dock_item_get_orientation(dockitem);
-# else
-	GnomeDockItem *dockitem;
-
-	widget	 = widget->parent;
-	dockitem = GNOME_DOCK_ITEM(widget);
-
-	if (dockitem == NULL || dockitem->is_floating)
-	    return 0;
-	item_orientation = gnome_dock_item_get_orientation(dockitem);
-# endif
-    }
-#endif
-    if (widget != NULL
-	    && item_orientation == orientation
-	    && GTK_WIDGET_REALIZED(widget)
-	    && GTK_WIDGET_VISIBLE(widget))
-    {
-	if (orientation == GTK_ORIENTATION_HORIZONTAL)
-	    return widget->allocation.height;
-	else
-	    return widget->allocation.width;
-    }
-    return 0;
-}
-#endif
-
-    static int
-get_menu_tool_width(void)
-{
-    int width = 0;
-
-#ifdef FEAT_GUI_GNOME /* these are never vertical without GNOME */
-# ifdef FEAT_MENU
-    width += get_item_dimensions(gui.menubar, GTK_ORIENTATION_VERTICAL);
-# endif
-# ifdef FEAT_TOOLBAR
-    width += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_VERTICAL);
-# endif
-#endif
-
-    return width;
-}
-
-    static int
-get_menu_tool_height(void)
-{
-    int height = 0;
-
-#ifdef FEAT_MENU
-    height += get_item_dimensions(gui.menubar, GTK_ORIENTATION_HORIZONTAL);
-#endif
-#ifdef FEAT_TOOLBAR
-    height += get_item_dimensions(gui.toolbar, GTK_ORIENTATION_HORIZONTAL);
-#endif
-
-    return height;
-}
-
-    static void
-update_window_manager_hints(void)
-{
-    static int old_width  = 0;
-    static int old_height = 0;
-    static int old_char_width  = 0;
-    static int old_char_height = 0;
-
-    int width;
-    int height;
-
-    /* This also needs to be done when the main window isn't there yet,
-     * otherwise the hints don't work. */
-    width  = gui_get_base_width();
-    height = gui_get_base_height();
-# ifdef FEAT_MENU
-    height += tabpageline_height() * gui.char_height;
-# endif
-# ifdef HAVE_GTK2
-    width  += get_menu_tool_width();
-    height += get_menu_tool_height();
-# endif
-
-    /* Avoid an expose event when the size didn't change. */
-    if (width != old_width
-	    || height != old_height
-	    || gui.char_width != old_char_width
-	    || gui.char_height != old_char_height)
-    {
-	GdkGeometry	geometry;
-	GdkWindowHints	geometry_mask;
-
-	geometry.width_inc   = gui.char_width;
-	geometry.height_inc  = gui.char_height;
-	geometry.base_width  = width;
-	geometry.base_height = height;
-	geometry.min_width   = width  + MIN_COLUMNS * gui.char_width;
-	geometry.min_height  = height + MIN_LINES   * gui.char_height;
-	geometry_mask	     = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC
-			       |GDK_HINT_MIN_SIZE;
-# ifdef HAVE_GTK2
-	/* Using gui.formwin as geometry widget doesn't work as expected
-	 * with GTK+ 2 -- dunno why.  Presumably all the resizing hacks
-	 * in Vim confuse GTK+. */
-	gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.mainwin,
-				      &geometry, geometry_mask);
-# else
-	gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
-				      &geometry, geometry_mask);
-# endif
-	old_width  = width;
-	old_height = height;
-	old_char_width	= gui.char_width;
-	old_char_height = gui.char_height;
-    }
-}
-
 /*
  * This signal informs us about the need to rearrange our sub-widgets.
  */
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -101,6 +101,9 @@
 /* Used for the qnx pterm mouse */
 #define KS_PTERM_MOUSE		241
 
+/* Used for click in a tab pages label. */
+#define KS_TABLINE		240
+
 /*
  * Filler used after KS_SPECIAL and others
  */
@@ -399,6 +402,8 @@ enum key_extra
 #define K_SELECT	TERMCAP2KEY(KS_SELECT, KE_FILLER)
 #define K_TEAROFF	TERMCAP2KEY(KS_TEAROFF, KE_FILLER)
 
+#define K_TABLINE	TERMCAP2KEY(KS_TABLINE, KE_FILLER)
+
 /*
  * Symbols for pseudo keys which are translated from the real key symbols
  * above.
--- a/src/main.c
+++ b/src/main.c
@@ -880,6 +880,18 @@ main
     mch_set_winsize_now();	    /* Allow winsize changes from now on */
 #endif
 
+#if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+    /* When tab pages were created, may need to update the tab pages line and
+     * scrollbars.  This is skipped while creating them. */
+    if (first_tabpage->tp_next != NULL)
+    {
+	out_flush();
+	gui_init_which_components(NULL);
+	gui_update_scrollbars(TRUE);
+    }
+    need_mouse_correct = TRUE;
+#endif
+
     /* If ":startinsert" command used, stuff a dummy command to be able to
      * call normal_cmd(), which will then start Insert mode. */
     if (restart_edit != 0)
--- a/src/normal.c
+++ b/src/normal.c
@@ -74,6 +74,9 @@ static void	nv_zet __ARGS((cmdarg_T *cap
 static void	nv_ver_scrollbar __ARGS((cmdarg_T *cap));
 static void	nv_hor_scrollbar __ARGS((cmdarg_T *cap));
 #endif
+#ifdef FEAT_GUI_TABLINE
+static void	nv_tabline __ARGS((cmdarg_T *cap));
+#endif
 static void	nv_exmode __ARGS((cmdarg_T *cap));
 static void	nv_colon __ARGS((cmdarg_T *cap));
 static void	nv_ctrlg __ARGS((cmdarg_T *cap));
@@ -418,6 +421,9 @@ static const struct nv_cmd
     {K_VER_SCROLLBAR, nv_ver_scrollbar, 0,		0},
     {K_HOR_SCROLLBAR, nv_hor_scrollbar, 0,		0},
 #endif
+#ifdef FEAT_GUI_TABLINE
+    {K_TABLINE, nv_tabline,	0,			0},
+#endif
 #ifdef FEAT_FKMAP
     {K_F8,	farsi_fkey,	0,			0},
     {K_F9,	farsi_fkey,	0,			0},
@@ -4977,6 +4983,22 @@ nv_hor_scrollbar(cap)
 }
 #endif
 
+#ifdef FEAT_GUI_TABLINE
+/*
+ * Click in GUI tab.
+ */
+    static void
+nv_tabline(cap)
+    cmdarg_T	*cap;
+{
+    if (cap->oap->op_type != OP_NOP)
+	clearopbeep(cap->oap);
+
+    /* Even if an operator was pending, we still want to jump tabs. */
+    goto_tabpage(current_tab);
+}
+#endif
+
 /*
  * "Q" command.
  */
@@ -5329,7 +5351,7 @@ nv_ident(cap)
 	    else if (g_cmd)
 		STRCPY(buf, "tj ");
 	    else
-		STRCPY(buf, "ta ");
+		sprintf((char *)buf, "%ldta ", cap->count0);
     }
 
     /*
--- a/src/option.c
+++ b/src/option.c
@@ -1099,9 +1099,9 @@ static struct vimoption
 #if defined(FEAT_GUI)
 			    (char_u *)&p_go, PV_NONE,
 # if defined(UNIX) && !defined(MACOS)
-			    {(char_u *)"agimrLtT", (char_u *)0L}
+			    {(char_u *)"aegimrLtT", (char_u *)0L}
 # else
-			    {(char_u *)"gmrLtT", (char_u *)0L}
+			    {(char_u *)"egmrLtT", (char_u *)0L}
 # endif
 #else
 			    (char_u *)NULL, PV_NONE,
--- a/src/option.h
+++ b/src/option.h
@@ -223,6 +223,7 @@
 #define GO_ASELML	'A'		/* autoselect modeless selection */
 #define GO_BOT		'b'		/* use bottom scrollbar */
 #define GO_CONDIALOG	'c'		/* use console dialog */
+#define GO_TABLINE	'e'		/* may show tabline */
 #define GO_FORG		'f'		/* start GUI in foreground */
 #define GO_GREY		'g'		/* use grey menu items */
 #define GO_HORSCROLL	'h'		/* flexible horizontal scrolling */
@@ -238,7 +239,7 @@
 #define GO_TOOLBAR	'T'		/* add toolbar */
 #define GO_FOOTER	'F'		/* add footer */
 #define GO_VERTICAL	'v'		/* arrange dialog buttons vertically */
-#define GO_ALL		"aAbcfFghilmMprtTv" /* all possible flags for 'go' */
+#define GO_ALL		"aAbcefFghilmMprtTv" /* all possible flags for 'go' */
 
 /* flags for 'comments' option */
 #define COM_NEST	'n'		/* comments strings nest */
--- a/src/proto/gui.pro
+++ b/src/proto/gui.pro
@@ -34,6 +34,9 @@ void gui_send_mouse_event __ARGS((int bu
 int gui_xy2colrow __ARGS((int x, int y, int *colp));
 void gui_menu_cb __ARGS((vimmenu_T *menu));
 void gui_init_which_components __ARGS((char_u *oldval));
+int gui_use_tabline __ARGS((void));
+void gui_update_tabline __ARGS((void));
+void get_tabline_label __ARGS((tabpage_T *tp));
 void gui_remove_scrollbars __ARGS((void));
 void gui_create_scrollbar __ARGS((scrollbar_T *sb, int type, win_T *wp));
 scrollbar_T *gui_find_scrollbar __ARGS((long ident));
--- a/src/proto/gui_gtk_x11.pro
+++ b/src/proto/gui_gtk_x11.pro
@@ -5,6 +5,9 @@ void gui_mch_set_blinking __ARGS((long w
 void gui_mch_stop_blink __ARGS((void));
 void gui_mch_start_blink __ARGS((void));
 int gui_mch_init_check __ARGS((void));
+void gui_mch_show_tabline __ARGS((int showit));
+void gui_mch_update_tabline __ARGS((void));
+void gui_mch_set_curtab __ARGS((int nr));
 int gui_mch_init __ARGS((void));
 void gui_mch_forked __ARGS((void));
 void gui_mch_new_colors __ARGS((void));
--- a/src/proto/screen.pro
+++ b/src/proto/screen.pro
@@ -42,6 +42,7 @@ int screen_ins_lines __ARGS((int off, in
 int screen_del_lines __ARGS((int off, int row, int line_count, int end, int force, win_T *wp));
 int showmode __ARGS((void));
 void unshowmode __ARGS((int force));
+void get_trans_bufname __ARGS((buf_T *buf));
 int redrawing __ARGS((void));
 int messaging __ARGS((void));
 void showruler __ARGS((int always));
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -19,7 +19,9 @@ int may_open_tabpage __ARGS((void));
 int make_tabpages __ARGS((int maxcount));
 int valid_tabpage __ARGS((tabpage_T *tpc));
 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 tabpage_move __ARGS((int nr));
 void win_goto __ARGS((win_T *wp));
 win_T *win_find_nr __ARGS((int winnr));
@@ -42,7 +44,7 @@ void win_drag_vsep_line __ARGS((win_T *d
 void win_comp_scroll __ARGS((win_T *wp));
 void command_height __ARGS((long old_p_ch));
 void last_status __ARGS((int morewin));
-int tabpageline_height __ARGS((void));
+int tabline_height __ARGS((void));
 char_u *grab_file_name __ARGS((long count, linenr_T *file_lnum));
 char_u *file_name_at_cursor __ARGS((int options, long count, linenr_T *file_lnum));
 char_u *file_name_in_line __ARGS((char_u *line, int col, int options, long count, char_u *rel_fname, linenr_T *file_lnum));
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -3861,8 +3861,16 @@ regmatch(scan)
 		}
 		else
 		{
-		    top = curbuf->b_visual_start;
-		    bot = curbuf->b_visual_end;
+		    if (lt(curbuf->b_visual_start, curbuf->b_visual_end))
+		    {
+			top = curbuf->b_visual_start;
+			bot = curbuf->b_visual_end;
+		    }
+		    else
+		    {
+			top = curbuf->b_visual_end;
+			bot = curbuf->b_visual_start;
+		    }
 		    mode = curbuf->b_visual_mode;
 		}
 		lnum = reglnum + reg_firstlnum;
@@ -5092,8 +5100,8 @@ regmatch(scan)
 			/* Tried first position already, advance. */
 			if (rp->rs_state == RS_STAR_LONG)
 			{
-			    /* Trying for longest matc, but couldn't or didn't
-			     * match -- back up one char. */
+			    /* Trying for longest match, but couldn't or
+			     * didn't match -- back up one char. */
 			    if (--rst->count < rst->minval)
 				break;
 			    if (reginput == regline)
@@ -5149,8 +5157,8 @@ regmatch(scan)
 	    break;
 	}
 
-	/* If we want to continue the inner loop or didn't pop a state contine
-	 * matching loop */
+	/* If we want to continue the inner loop or didn't pop a state
+	 * continue matching loop */
 	if (status == RA_CONT || rp == (regitem_T *)
 			     ((char *)regstack.ga_data + regstack.ga_len) - 1)
 	    break;
--- a/src/screen.c
+++ b/src/screen.c
@@ -5344,12 +5344,7 @@ win_redr_status(wp)
     {
 	fillchar = fillchar_status(&attr, wp == curwin);
 
-	if (buf_spname(wp->w_buffer) != NULL)
-	    STRCPY(NameBuff, buf_spname(wp->w_buffer));
-	else
-	    home_replace(wp->w_buffer, wp->w_buffer->b_fname, NameBuff,
-							      MAXPATHL, TRUE);
-	trans_characters(NameBuff, MAXPATHL);
+	get_trans_bufname(wp->w_buffer);
 	p = NameBuff;
 	len = (int)STRLEN(p);
 
@@ -6170,14 +6165,24 @@ next_search_hl(win, shl, lnum, mincol)
 	    matchcol = 0;
 	else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL
 		|| (shl->rm.endpos[0].lnum == 0
-		    && shl->rm.endpos[0].col == shl->rm.startpos[0].col))
-	{
-	    matchcol = shl->rm.startpos[0].col + 1;
-	    if (ml_get_buf(shl->buf, lnum, FALSE)[matchcol - 1] == NUL)
-	    {
+		    && shl->rm.endpos[0].col <= shl->rm.startpos[0].col))
+	{
+	    char_u	*ml = ml_get_buf(shl->buf, lnum, FALSE);
+
+	    matchcol = shl->rm.startpos[0].col;
+	    ml += matchcol;
+	    if (*ml == NUL)
+	    {
+		++matchcol;
 		shl->lnum = 0;
 		break;
 	    }
+#ifdef FEAT_MBYTE
+	    if (has_mbyte)
+		matchcol += mb_ptr2len(ml);
+	    else
+#endif
+		++matchcol;
 	}
 	else
 	    matchcol = shl->rm.endpos[0].col;
@@ -8577,7 +8582,16 @@ draw_tabline()
 
     redraw_tabline = FALSE;
 
-    if (tabpageline_height() < 1)
+#ifdef FEAT_GUI_TABLINE
+    /* When the GUI has the tabline then this always returns zero. */
+    if (gui_use_tabline())
+    {
+	gui_update_tabline();
+	return;
+    }
+#endif
+
+    if (tabline_height() < 1)
 	return;
 
 #if defined(FEAT_STL_OPT)
@@ -8670,12 +8684,8 @@ draw_tabline()
 	    room = scol - col + tabwidth - 1;
 	    if (room > 0)
 	    {
-		if (buf_spname(cwp->w_buffer) != NULL)
-		    STRCPY(NameBuff, buf_spname(cwp->w_buffer));
-		else
-		    home_replace(cwp->w_buffer, cwp->w_buffer->b_fname, NameBuff,
-								  MAXPATHL, TRUE);
-		trans_characters(NameBuff, MAXPATHL);
+		/* Get buffer name in NameBuff[] */
+		get_trans_bufname(cwp->w_buffer);
 		len = vim_strsize(NameBuff);
 		p = NameBuff;
 #ifdef FEAT_MBYTE
@@ -8719,6 +8729,21 @@ draw_tabline()
 	}
     }
 }
+
+/*
+ * Get buffer name for "buf" into NameBuff[].
+ * Takes care of special buffer names and translates special characters.
+ */
+    void
+get_trans_bufname(buf)
+    buf_T	*buf;
+{
+    if (buf_spname(buf) != NULL)
+	STRCPY(NameBuff, buf_spname(buf));
+    else
+	home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, TRUE);
+    trans_characters(NameBuff, MAXPATHL);
+}
 #endif
 
 #if defined(FEAT_WINDOWS) || defined(FEAT_WILDMENU) || defined(FEAT_STL_OPT)
--- a/src/search.c
+++ b/src/search.c
@@ -602,7 +602,11 @@ searchit(win, buf, pos, dir, pat, count,
 # ifdef FEAT_EVAL
 		    submatch = first_submatch(&regmatch);
 # endif
-		    ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
+		    /* Line me be past end of buffer for "\n\zs". */
+		    if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
+			ptr = (char_u *)"";
+		    else
+			ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
 
 		    /*
 		     * Forward search in the first line: match should be after
@@ -886,6 +890,15 @@ searchit(win, buf, pos, dir, pat, count,
 	return FAIL;
     }
 
+    /* A pattern like "\n\zs" may go past the last line. */
+    if (pos->lnum > buf->b_ml.ml_line_count)
+    {
+	pos->lnum = buf->b_ml.ml_line_count;
+	pos->col = STRLEN(ml_get_buf(buf, pos->lnum, FALSE));
+	if (pos->col > 0)
+	    --pos->col;
+    }
+
     return submatch + 1;
 }
 
--- a/src/structs.h
+++ b/src/structs.h
@@ -782,8 +782,9 @@ typedef struct attr_entry
 	} term;
 	struct
 	{
-	    char_u	    fg_color;	/* foreground color number */
-	    char_u	    bg_color;	/* background color number */
+	    /* These colors need to be > 8 bits to hold 256. */
+	    short_u	    fg_color;	/* foreground color number */
+	    short_u	    bg_color;	/* background color number */
 	} cterm;
 # ifdef FEAT_GUI
 	struct
--- a/src/tag.c
+++ b/src/tag.c
@@ -509,6 +509,13 @@ do_tag(tag, type, count, forceit, verbos
 		tagmatchname = vim_strsave(name);
 	    }
 
+	    /*
+	     * If a count is supplied to the ":tag <name>" command, then
+	     * jump to count'th matching tag.
+	     */
+	    if (type == DT_TAG && count > 0)
+		cur_match = count - 1;
+
 	    if (type == DT_SELECT || type == DT_JUMP)
 		cur_match = MAXCOL - 1;
 	    max_num_matches = cur_match + 1;
--- a/src/term.c
+++ b/src/term.c
@@ -4766,6 +4766,9 @@ check_termcode(max_offset, buf, buflen)
 	 * four bytes which are to be taken as a pointer to the vimmenu_T
 	 * structure.
 	 *
+	 * A tab line event is encodded as K_SPECIAL KS_TABLINE nr, where "nr"
+	 * is one byte with the tab index.
+	 *
 	 * A scrollbar event is K_SPECIAL, KS_VER_SCROLLBAR, KE_FILLER followed
 	 * by one byte representing the scrollbar number, and then four bytes
 	 * representing a long_u which is the new value of the scrollbar.
@@ -4786,6 +4789,16 @@ check_termcode(max_offset, buf, buflen)
 	    slen += num_bytes;
 	}
 # endif
+# ifdef FEAT_GUI_TABLINE
+	else if (key_name[0] == (int)KS_TABLINE)
+	{
+	    num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
+	    if (num_bytes == -1)
+		return -1;
+	    current_tab = (int)bytes[0];
+	    slen += num_bytes;
+	}
+# endif
 # ifndef USE_ON_FLY_SCROLL
 	else if (key_name[0] == (int)KS_VER_SCROLLBAR)
 	{
--- 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 23)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 23, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 24)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 24, compiled "
--- a/src/window.c
+++ b/src/window.c
@@ -86,7 +86,7 @@ static void win_new_height __ARGS((win_T
 #ifdef FEAT_WINDOWS
 static long p_ch_used = 1L;		/* value of 'cmdheight' when frame
 					   size was set */
-# define ROWS_AVAIL (Rows - p_ch - tabpageline_height())
+# define ROWS_AVAIL (Rows - p_ch - tabline_height())
 #else
 # define ROWS_AVAIL (Rows - p_ch)
 #endif
@@ -908,7 +908,7 @@ win_split_ins(size, flags, newwin, dir)
 	if (flags & (WSP_TOP | WSP_BOT))
 	{
 	    /* set height and row of new window to full height */
-	    wp->w_winrow = tabpageline_height();
+	    wp->w_winrow = tabline_height();
 	    wp->w_height = curfrp->fr_height - (p_ls > 0);
 	    wp->w_status_height = (p_ls > 0);
 	}
@@ -1543,7 +1543,7 @@ win_equal(next_curwin, current, dir)
 	dir = 'b';
 #endif
     win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
-		      topframe, dir, 0, tabpageline_height(),
+		      topframe, dir, 0, tabline_height(),
 					   (int)Columns, topframe->fr_height);
 }
 
@@ -1830,7 +1830,7 @@ close_windows(buf, keep_curwin)
 {
     win_T	*wp;
     tabpage_T   *tp, *nexttp;
-    int		h = tabpageline_height();
+    int		h = tabline_height();
 
     ++RedrawingDisabled;
 
@@ -1866,7 +1866,7 @@ close_windows(buf, keep_curwin)
 
     --RedrawingDisabled;
 
-    if (h != tabpageline_height())
+    if (h != tabline_height())
 	shell_new_rows();
 }
 
@@ -3041,7 +3041,7 @@ win_new_tabpage(after)
 	    tp->tp_next = newtp;
 	}
 	win_init_size();
-	firstwin->w_winrow = tabpageline_height();
+	firstwin->w_winrow = tabline_height();
 
 	newtp->tp_topframe = topframe;
 	last_status(FALSE);
@@ -3142,6 +3142,22 @@ find_tabpage(n)
 }
 
 /*
+ * Get index of tab page "tp".  First one has index 1.
+ * When not found returns number of tab pages.
+ */
+    int
+tabpage_index(ftp)
+    tabpage_T	*ftp;
+{
+    int		i = 1;
+    tabpage_T	*tp;
+
+    for (tp = first_tabpage; tp != NULL && tp != ftp; tp = tp->tp_next)
+	++i;
+    return i;
+}
+
+/*
  * Prepare for leaving the current tab page.
  * When autocomands change "curtab" we don't leave the tab page and return
  * FAIL.
@@ -3223,7 +3239,11 @@ enter_tabpage(tp, old_curbuf)
     /* 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 (curtab->tp_old_Rows != Rows || old_off != firstwin->w_winrow)
+    if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow
+#ifdef FEAT_GUI_TABLINE
+			    && !gui_use_tabline()
+#endif
+		))
 	shell_new_rows();
 #ifdef FEAT_VERTSPLIT
     if (curtab->tp_old_Columns != Columns && starting == 0)
@@ -3233,12 +3253,8 @@ enter_tabpage(tp, old_curbuf)
 #if defined(FEAT_GUI)
     /* When 'guioptions' includes 'L' or 'R' may have to remove or add
      * scrollbars.  Have to update them anyway. */
-    if (gui.in_use)
-    {
-	out_flush();
-	gui_init_which_components(NULL);
+    if (gui.in_use && starting == 0)
 	gui_update_scrollbars(TRUE);
-    }
     need_mouse_correct = TRUE;
 #endif
 
@@ -3247,6 +3263,7 @@ enter_tabpage(tp, old_curbuf)
 
 /*
  * Go to tab page "n".  For ":tab N" and "Ngt".
+ * When "n" is 9999 go to the last tab page.
  */
     void
 goto_tabpage(n)
@@ -3285,12 +3302,16 @@ goto_tabpage(n)
 	    ttp = tp;
 	}
     }
+    else if (n == 9999)
+    {
+	/* Go to last tab page. */
+	for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next)
+	    ;
+    }
     else
     {
 	/* Go to tab page "n". */
-	i = 0;
-	for (tp = first_tabpage; ++i != n && tp != NULL; tp = tp->tp_next)
-	    ;
+	tp = find_tabpage(n);
 	if (tp == NULL)
 	{
 	    beep_flush();
@@ -3298,6 +3319,22 @@ goto_tabpage(n)
 	}
     }
 
+    goto_tabpage_tp(tp);
+
+#ifdef FEAT_GUI_TABLINE
+    if (gui_use_tabline())
+	gui_mch_set_curtab(tabpage_index(tp));
+#endif
+}
+
+/*
+ * Go to tabpage "tp".
+ * Note: doesn't update the GUI tab.
+ */
+    void
+goto_tabpage_tp(tp)
+    tabpage_T	*tp;
+{
     if (tp != curtab && leave_tabpage(tp->tp_curwin->w_buffer) == OK)
     {
 	if (valid_tabpage(tp))
@@ -4071,7 +4108,7 @@ win_size_restore(gap)
     int
 win_comp_pos()
 {
-    int		row = tabpageline_height();
+    int		row = tabline_height();
     int		col = 0;
 
     frame_comp_pos(topframe, &row, &col);
@@ -5169,8 +5206,13 @@ last_status_rec(fr, statusline)
  * Return the number of lines used by the tab page line.
  */
     int
-tabpageline_height()
+tabline_height()
 {
+#ifdef FEAT_GUI_TABLINE
+    /* When the GUI has the tabline then this always returns zero. */
+    if (gui_use_tabline())
+	return 0;
+#endif
     switch (p_stal)
     {
 	case 0: return 0;
@@ -5516,7 +5558,7 @@ min_rows()
 	if (total < n)
 	    total = n;
     }
-    total += tabpageline_height();
+    total += tabline_height();
 #else
     total = 1;		/* at least one window should have a line! */
 #endif