changeset 692:a28f83d37113

updated for version 7.0208
author vimboss
date Mon, 27 Feb 2006 00:08:02 +0000
parents 8106f3da02d0
children 05dc93b9c61f
files runtime/doc/eval.txt runtime/doc/options.txt runtime/doc/tags src/Makefile src/auto/configure src/configure.in src/edit.c src/ex_getln.c src/feature.h src/globals.h src/gui_mac.c src/ops.c src/option.c src/option.h src/proto/eval.pro src/proto/gui.pro src/proto/normal.pro src/regexp.c src/search.c src/structs.h src/tag.c src/undo.c src/version.h src/workshop.c
diffstat 24 files changed, 538 insertions(+), 192 deletions(-) [+]
line wrap: on
line diff
--- 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 25
+*eval.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 26
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -767,7 +767,7 @@ expr6 +	 expr6 ..	Number addition or |Li
 expr6 -	 expr6 ..	Number subtraction			*expr--*
 expr6 .	 expr6 ..	String concatenation			*expr-.*
 
-For |List|s only "+" is possible and then both expr6 must be a list.  The
+For |Lists| 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*
@@ -1651,11 +1651,11 @@ reverse( {list})		List	reverse {list} in
 search( {pattern} [, {flags}])	Number	search for {pattern}
 searchdecl({name} [, {global} [, {thisblock}]])
 				Number  search for variable declaration
-searchpair( {start}, {middle}, {end} [, {flags} [, {skip}]])
+searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
 				Number	search for other end of start/end pair
-searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip}]])
+searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
 				List	search for other end of start/end pair
-searchpos( {pattern} [, {flags}])
+searchpos( {pattern} [, {flags} [, {stopline}]])
 				List	search for {pattern}
 server2client( {clientid}, {string})
 				Number	send reply string
@@ -1725,7 +1725,7 @@ add({list}, {expr})					*add()*
 			: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 |List|s.
+		item.  Use |extend()| to concatenate |Lists|.
 		Use |insert()| to add an item at another position.
 
 
@@ -2016,7 +2016,7 @@ copy({expr})	Make a copy of {expr}.  For
 		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 |List|s.  Also
+		changing an item changes the contents of both |Lists|.  Also
 		see |deepcopy()|.
 
 count({comp}, {expr} [, {ic} [, {start}]])			*count()*
@@ -2327,9 +2327,10 @@ expand({expr} [, {flag}])				*expand()*
 		getting the raw output of an external command.
 
 extend({expr1}, {expr2} [, {expr3}])			*extend()*
-		{expr1} and {expr2} must be both |List|s or both Dictionaries.
-
-		If they are |List|s: Append {expr2} to {expr1}.
+		{expr1} and {expr2} must be both |Lists| or both
+		|Dictionaries|.
+
+		If they are |Lists|: 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
@@ -2341,7 +2342,7 @@ extend({expr1}, {expr2} [, {expr3}])			*
 		two lists into a new list use the + operator: >
 			:let newlist = [1, 2, 3] + [4, 5]
 <
-		If they are Dictionaries:
+		If they are |Dictionaries|:
 		Add all entries from {expr2} to {expr1}.
 		If a key exists in both {expr1} and {expr2} then {expr3} is
 		used to decide what to do:
@@ -2486,7 +2487,7 @@ function({name})					*function()* *E700*
 
 
 garbagecollect()					*garbagecollect()*
-		Cleanup unused |List|s and Dictionaries that have circular
+		Cleanup unused |Lists| 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
@@ -3108,7 +3109,7 @@ insert({list}, {item} [, {idx}])			*inse
 			: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 |List|s.
+		item.  Use |extend()| to concatenate |Lists|.
 
 isdirectory({directory})				*isdirectory()*
 		The result is a Number, which is non-zero when a directory
@@ -3143,7 +3144,7 @@ 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.  |List|s and Dictionaries are
+<		String items are used as-is.  |Lists| and |Dictionaries| are
 		converted into a string like with |string()|.
 		The opposite function is |split()|.
 
@@ -3342,7 +3343,7 @@ mapcheck({name}[, {mode}])				*mapcheck(
 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, |List|s and Dictionaries are used as echoed.
+		String, |Lists| 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.
@@ -3807,7 +3808,7 @@ reverse({list})	Reverse the order of ite
 		If you want a list to remain unmodified make a copy first: >
 			:let revlist = reverse(copy(mylist))
 
-search({pattern} [, {flags}])				*search()*
+search({pattern} [, {flags} [, {stopline}]])			*search()*
 		Search for regexp pattern {pattern}.  The search starts at the
 		cursor position (you can use |cursor()| to set it).
 		{flags} is a String, which can contain these character flags:
@@ -3823,11 +3824,20 @@ search({pattern} [, {flags}])				*search
 		cursor is moved. The 's' flag cannot be combined with the 'n'
 		flag.
 
+		When the {stopline} argument is given then the search stops
+		after searching this line.  This is useful to restrict the
+		search to a range of lines.  Examples: >
+			let match = search('(', 'b', line("w0"))
+			let end = search('END', '', line("w$"))
+<		When {stopline} is used and it is not zero this also implies
+		that the search does not wrap around the end of the file.
+
 		When a match has been found its line number is returned.
 		The cursor will be positioned at the match, unless the 'n'
 		flag is used).
 		If there is no match a 0 is returned and the cursor doesn't
 		move.  No error message is given.
+		To get the column number too use |searchpos()|.
 
 		Example (goes over all files in the argument list): >
 		    :let n = 1
@@ -3865,7 +3875,7 @@ searchdecl({name} [, {global} [, {thisbl
 			endif
 <
 							*searchpair()*
-searchpair({start}, {middle}, {end} [, {flags} [, {skip}]])
+searchpair({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
 		Search for the match of a nested start-end pair.  This can be
 		used to find the "endif" that matches an "if", while other
 		if/endif pairs in between are ignored.
@@ -3900,6 +3910,8 @@ searchpair({start}, {middle}, {end} [, {
 		When evaluating {skip} causes an error the search is aborted
 		and -1 returned.
 
+		For {stopline} see |search()|.
+
 		The value of 'ignorecase' is used.  'magic' is ignored, the
 		patterns are used like it's on.
 
@@ -3944,7 +3956,7 @@ searchpair({start}, {middle}, {end} [, {
 	     \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')
 <
 							*searchpairpos()*
-searchpairpos({start}, {middle}, {end} [, {flags} [, {skip}]])
+searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
 		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
@@ -3955,8 +3967,8 @@ 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
+searchpos({pattern} [, {flags} [, {stopline}]])		*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,
@@ -4143,7 +4155,7 @@ 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, |List|s after Numbers.
+		Numbers sort after Strings, |Lists| 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
--- 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 25
+*options.txt*	For Vim version 7.0aa.  Last change: 2006 Feb 26
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2447,6 +2447,7 @@ A jump table for the options with a shor
 	When reading a file 'fileencoding' will be set from 'fileencodings'.
 	To read a file in a certain encoding it won't work by setting
 	'fileencoding', use the |++enc| argument.
+	For a new file the global value of 'fileencoding' is used.
 	Prepending "8bit-" and "2byte-" has no meaning here, they are ignored.
 	When the option is set, the value is converted to lowercase.  Thus
 	you can set it with uppercase values too.  '_' characters are
@@ -2496,9 +2497,11 @@ A jump table for the options with a shor
 	non-blank characters.
 	When the |++enc| argument is used then the value of 'fileencodings' is
 	not used.
-	Note that 'fileencodings' is not used for a new file, 'fileencoding'
-	is always empty then.  This means that a non-existing file may get a
-	different encoding than an empty file.
+	Note that 'fileencodings' is not used for a new file, the global value
+	of 'fileencoding' is used instead.  You can set it with: >
+		:setglobal fenc=iso-8859-2
+<	This means that a non-existing file may get a different encoding than
+	an empty file.
 	The special value "ucs-bom" can be used to check for a Unicode BOM
 	(Byte Order Mark) at the start of the file.  It must not be preceded
 	by "utf-8" or another Unicode encoding for this to work properly.
@@ -3317,10 +3320,14 @@ A jump table for the options with a shor
 'guitablabel' 'gtl'	string	(default empty)
 			global
 			{not in Vi}
+			{only available when compiled with GUI enabled and
+			with the +windows feature}
 	When nonempty describes the text to use in a label of the GUI tab
-	pages line.  When empty Vim will use a default label. See
+	pages line.  When empty Vim will use a default label.  See
 	|setting-guitablabel| for more info.
 
+	The format of this option is like that of 'statusline'.
+
 	Only used when the GUI tab pages line is displayed.  'e' must be
 	present in 'guioptions'.  For the non-GUI tab pages line 'tabline' is
 	used.
@@ -5089,7 +5096,7 @@ A jump table for the options with a shor
 			feature}
 	When this option is not empty, it determines the content of the ruler
 	string, as displayed for the 'ruler' option.
-	The format of this option, is like that of 'statusline'.
+	The format of this option is like that of 'statusline'.
 	The default ruler width is 17 characters.  To make the ruler 15
 	characters wide, put "%15(" at the start and "%)" at the end.
 	Example: >
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -5471,7 +5471,6 @@ hebrew	hebrew.txt	/*hebrew*
 hebrew.txt	hebrew.txt	/*hebrew.txt*
 help	various.txt	/*help*
 help-context	help.txt	/*help-context*
-help-tags	tags	1
 help-translated	various.txt	/*help-translated*
 help-xterm-window	various.txt	/*help-xterm-window*
 help.txt	help.txt	/*help.txt*
--- a/src/Makefile
+++ b/src/Makefile
@@ -354,7 +354,10 @@ CClink = $(CC)
 # DARWIN - detecting Mac OS X
 # Uncomment this line when you want to compile a Unix version of Vim on
 # Darwin.  None of the Mac specific options or files will be used.
+# You can also change the architecture supported, default is to test for both.
 #CONF_OPT_DARWIN = --disable-darwin
+#CONF_OPT_DARWIN = --with-mac-arch=i386
+#CONF_OPT_DARWIN = --with-mac-arch=ppc
 
 # PERL
 # Uncomment this when you want to include the Perl interface.
@@ -547,10 +550,6 @@ LINT_OPTIONS = -beprxzF
 #PROFILE_CFLAGS = -DEXITFREE
 #PROFILE_LIBS = -lccmalloc
 
-# MAC OS X platform
-MAC_OSX_ARCH = -arch ppc
-#MAC_OSX_ARCH = -arch i386
-
 #####################################################
 ###  Specific systems, check if yours is listed!  ### {{{
 #####################################################
@@ -1201,11 +1200,11 @@ PHOTONGUI_BUNDLE =
 # CARBON GUI
 CARBONGUI_SRC	= gui.c gui_mac.c
 CARBONGUI_OBJ	= objects/gui.o objects/gui_mac.o objects/pty.o
-CARBONGUI_DEFS	= -DFEAT_GUI_MAC $(MAC_OSX_ARCH) -fno-common -fpascal-strings \
+CARBONGUI_DEFS	= -DFEAT_GUI_MAC -fno-common -fpascal-strings \
 		  -Wall -Wno-unknown-pragmas \
 		  -mdynamic-no-pic -pipe
 CARBONGUI_IPATH	= -I. -Iproto
-CARBONGUI_LIBS_DIR = $(MAC_OSX_ARCH)
+CARBONGUI_LIBS_DIR =
 CARBONGUI_LIBS1	= -framework Carbon
 CARBONGUI_LIBS2	=
 CARBONGUI_INSTALL = install_macosx
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -876,6 +876,7 @@ Optional Features:
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-mac-arch=ARCH    intel, ppc or both
   --with-vim-name=NAME    what to call the Vim executable
   --with-ex-name=NAME     what to call the Ex executable
   --with-view-name=NAME   what to call the View executable
@@ -2864,11 +2865,149 @@ echo "${ECHO_T}no, Darwin support disabl
 echo "${ECHO_T}yes, Darwin support excluded" >&6
   fi
 
+  echo "$as_me:$LINENO: checking --with-mac-arch argument" >&5
+echo $ECHO_N "checking --with-mac-arch argument... $ECHO_C" >&6
+
+# Check whether --with-mac-arch or --without-mac-arch was given.
+if test "${with_mac_arch+set}" = set; then
+  withval="$with_mac_arch"
+  MACARCH="$withval"; echo "$as_me:$LINENO: result: $MACARCH" >&5
+echo "${ECHO_T}$MACARCH" >&6
+else
+  MACARCH="both"; echo "$as_me:$LINENO: result: Defaulting to $MACARCH" >&5
+echo "${ECHO_T}Defaulting to $MACARCH" >&6
+fi;
+
+  if test "x$MACARCH" = "xboth"; then
+    echo "$as_me:$LINENO: checking if both architectures are supported" >&5
+echo $ECHO_N "checking if both architectures are supported... $ECHO_C" >&6
+    save_cppflags="$CPPFLAGS"
+    save_ldflags="$LDFLAGS"
+    CPPFLAGS="$CPPFLAGS -arch i386 -arch ppc"
+    LDFLAGS="$LDFLAGS -arch i386 -arch ppc"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+	    echo "$as_me:$LINENO: checking if Intel architecture is supported" >&5
+echo $ECHO_N "checking if Intel architecture is supported... $ECHO_C" >&6
+	    CPPFLAGS="$save_cppflags -arch i386"
+	    LDFLAGS="$save_ldflags -arch i386"
+	    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; MACARCH="intel"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; MACARCH="ppc"
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+    CPPFLAGS="$save_cppflags"
+    LDFLAGS="$save_ldflags"
+  fi
+
+  case "$MACARCH" in
+    intel)	MAC_OSX_ARCH="-arch i386";;
+    both)	MAC_OSX_ARCH="-arch i386 -arch ppc";;
+    ppc)	MAC_OSX_ARCH="-arch ppc";;
+    *)		MAC_OSX_ARCH="";;
+  esac
+
+    if test "$MACARCH" = "intel" -o "$MACARCH" = "both"; then
+    CFLAGS=`echo "$CFLAGS" | sed 's/-O[23456789]/-O/'`
+  fi
+
+  CPPFLAGS="$CPPFLAGS $MAC_OSX_ARCH"
+  LDFLAGS="$LDFLAGS $MAC_OSX_ARCH"
+
   if test "$enable_darwin" = "yes"; then
     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 ppc"
+        CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp"
 
                 echo "$as_me:$LINENO: checking for ANSI C header files" >&5
 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
@@ -3256,6 +3395,7 @@ fi
       fi
     fi
   fi
+
 else
   echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6
--- a/src/configure.in
+++ b/src/configure.in
@@ -102,12 +102,51 @@ if test "`(uname) 2>/dev/null`" = Darwin
     AC_MSG_RESULT([yes, Darwin support excluded])
   fi
 
+  AC_MSG_CHECKING(--with-mac-arch argument)
+  AC_ARG_WITH(mac-arch, [  --with-mac-arch=ARCH    intel, ppc or both],
+	MACARCH="$withval"; AC_MSG_RESULT($MACARCH),
+	MACARCH="both"; AC_MSG_RESULT(Defaulting to $MACARCH))
+
+  if test "x$MACARCH" = "xboth"; then
+    AC_MSG_CHECKING(if both architectures are supported)
+    save_cppflags="$CPPFLAGS"
+    save_ldflags="$LDFLAGS"
+    CPPFLAGS="$CPPFLAGS -arch i386 -arch ppc"
+    LDFLAGS="$LDFLAGS -arch i386 -arch ppc"
+    AC_TRY_LINK([ ], [ ],
+	AC_MSG_RESULT(yes),
+	AC_MSG_RESULT(no)
+	    AC_MSG_CHECKING(if Intel architecture is supported)
+	    CPPFLAGS="$save_cppflags -arch i386"
+	    LDFLAGS="$save_ldflags -arch i386"
+	    AC_TRY_LINK([ ], [ ],
+		AC_MSG_RESULT(yes); MACARCH="intel",
+		AC_MSG_RESULT(no); MACARCH="ppc"))
+    CPPFLAGS="$save_cppflags"
+    LDFLAGS="$save_ldflags"
+  fi
+
+  case "$MACARCH" in
+    intel)	MAC_OSX_ARCH="-arch i386";;
+    both)	MAC_OSX_ARCH="-arch i386 -arch ppc";;
+    ppc)	MAC_OSX_ARCH="-arch ppc";;
+    *)		MAC_OSX_ARCH="";;
+  esac
+
+  dnl avoid a bug with -O2 for intel
+  if test "$MACARCH" = "intel" -o "$MACARCH" = "both"; then
+    CFLAGS=`echo "$CFLAGS" | sed 's/-O[[23456789]]/-O/'`
+  fi
+
+  CPPFLAGS="$CPPFLAGS $MAC_OSX_ARCH"
+  LDFLAGS="$LDFLAGS $MAC_OSX_ARCH"
+
   if test "$enable_darwin" = "yes"; then
     MACOSX=yes
     OS_EXTRA_SCR="os_macosx.c os_mac_conv.c";
     OS_EXTRA_OBJ="objects/os_macosx.o objects/os_mac_conv.o"
     dnl TODO: use -arch i386 on Intel machines
-    CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp -arch ppc"
+    CPPFLAGS="$CPPFLAGS -DMACOS_X_UNIX -I/Developer/Headers/FlatCarbon -no-cpp-precomp"
 
     dnl If Carbon is found, assume we don't want X11
     dnl unless it was specifically asked for (--with-x)
@@ -119,6 +158,7 @@ if test "`(uname) 2>/dev/null`" = Darwin
       fi
     fi
   fi
+
 else
   AC_MSG_RESULT(no)
 fi
--- a/src/edit.c
+++ b/src/edit.c
@@ -202,6 +202,9 @@ static int  ins_bs __ARGS((int c, int mo
 static void ins_mouse __ARGS((int c));
 static void ins_mousescroll __ARGS((int up));
 #endif
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+static void ins_tabline __ARGS((int c));
+#endif
 static void ins_left __ARGS((void));
 static void ins_home __ARGS((int c));
 static void ins_end __ARGS((int c));
@@ -1044,6 +1047,12 @@ doESCkey:
 	    ins_mousescroll(TRUE);
 	    break;
 #endif
+#ifdef FEAT_GUI_TABLINE
+	case K_TABLINE:
+	case K_TABMENU:
+	    ins_tabline(c);
+	    break;
+#endif
 
 	case K_IGNORE:	/* Something mapped to nothing */
 	    break;
@@ -3515,7 +3524,7 @@ ins_compl_get_exp(ini)
 		    found_new_match = searchit(NULL, ins_buf, pos,
 							      compl_direction,
 				 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
-								     RE_LAST);
+							RE_LAST, (linenr_T)0);
 		if (!compl_started)
 		{
 		    /* set "compl_started" even on fail */
@@ -7978,7 +7987,31 @@ ins_mousescroll(up)
 }
 #endif
 
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
+    void
+ins_tabline(c)
+    int		c;
+{
+    /* We will be leaving the current window, unless closing another tab. */
+    if (c != K_TABMENU || current_tabmenu != TABLINE_MENU_CLOSE
+		|| (current_tab != 0 && current_tab != tabpage_index(curtab)))
+    {
+	undisplay_dollar();
+	start_arrow(&curwin->w_cursor);
+# ifdef FEAT_CINDENT
+	can_cindent = TRUE;
+# endif
+    }
+
+    if (c == K_TABLINE)
+	goto_tabpage(current_tab);
+    else
+	handle_tabmenu();
+
+}
+#endif
+
+#if defined(FEAT_GUI) || defined(PROTO)
     void
 ins_scroll()
 {
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1224,21 +1224,21 @@ getcmdline(firstc, count, indent)
 # endif
 		    if (!mouse_has(MOUSE_COMMAND))
 			goto cmdline_not_changed;   /* Ignore mouse */
-#ifdef FEAT_CLIPBOARD
+# ifdef FEAT_CLIPBOARD
 		if (clip_star.available)
 		    cmdline_paste('*', TRUE);
 		else
-#endif
+# endif
 		    cmdline_paste(0, TRUE);
 		redrawcmd();
 		goto cmdline_changed;
 
-#ifdef FEAT_DND
+# ifdef FEAT_DND
 	case K_DROP:
 		cmdline_paste('~', TRUE);
 		redrawcmd();
 		goto cmdline_changed;
-#endif
+# endif
 
 	case K_LEFTDRAG:
 	case K_LEFTRELEASE:
@@ -1291,7 +1291,7 @@ getcmdline(firstc, count, indent)
 		    if (mouse_row <= cmdline_row + ccline.cmdspos / Columns
 				  && mouse_col < ccline.cmdspos % Columns + i)
 			break;
-#ifdef FEAT_MBYTE
+# ifdef FEAT_MBYTE
 		    if (has_mbyte)
 		    {
 			/* Count ">" for double-wide char that doesn't fit. */
@@ -1299,7 +1299,7 @@ getcmdline(firstc, count, indent)
 			ccline.cmdpos += (*mb_ptr2len)(ccline.cmdbuff
 							 + ccline.cmdpos) - 1;
 		    }
-#endif
+# endif
 		    ccline.cmdspos += i;
 		}
 		goto cmdline_not_changed;
@@ -1339,6 +1339,16 @@ getcmdline(firstc, count, indent)
 		}
 		goto cmdline_not_changed;
 #endif
+#ifdef FEAT_GUI_TABLINE
+	case K_TABLINE:
+	case K_TABMENU:
+		/* Don't want to change any tabs here.  Make sure the same tab
+		 * is still selected. */
+		if (gui_use_tabline())
+		    gui_mch_set_curtab(tabpage_index(curtab));
+		goto cmdline_not_changed;
+#endif
+
 	case K_SELECT:	    /* end of Select mode mapping - ignore */
 		goto cmdline_not_changed;
 
--- a/src/feature.h
+++ b/src/feature.h
@@ -1194,6 +1194,11 @@
 # define FEAT_BEVAL_TIP		/* balloon eval used for toolbar tooltip */
 #endif
 
+/* both Motif and Athena are X11 and share some code */
+#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
+# define FEAT_GUI_X11
+#endif
+
 #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG)
 /*
  * The following features are (currently) only used by Sun Visual WorkShop 6
--- a/src/globals.h
+++ b/src/globals.h
@@ -489,6 +489,10 @@ EXTERN VimClipboard clip_plus;	/* CLIPBO
 # else
 #  define clip_plus clip_star	/* there is only one clipboard */
 # endif
+EXTERN int	clip_unnamed INIT(= FALSE);
+EXTERN int	clip_autoselect INIT(= FALSE);
+EXTERN int	clip_autoselectml INIT(= FALSE);
+EXTERN regprog_T *clip_exclude_prog INIT(= NULL);
 #endif
 
 /*
--- a/src/gui_mac.c
+++ b/src/gui_mac.c
@@ -3394,8 +3394,6 @@ gui_mch_init_font(char_u *font_name, int
 	    kATSStyleNoAntiAliasing :
 	    kATSStyleNoOptions;
 
-	printf("BLA\n");
-
 	ATSUAttributeTag attribTags[] =
 	{
 	    kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
@@ -3426,7 +3424,6 @@ gui_mch_init_font(char_u *font_name, int
 #endif
 
     return OK;
-
 }
 
 /*
--- a/src/ops.c
+++ b/src/ops.c
@@ -3249,7 +3249,7 @@ do_put(regname, dir, count, flags)
 	if (flags & PUT_LINE_FORWARD)
 	{
 	    /* Must be "p" for a Visual block, put lines below the block. */
-	    curwin->w_cursor = curbuf->b_visual_end;
+	    curwin->w_cursor = curbuf->b_visual.vi_end;
 	    dir = FORWARD;
 	}
 	curbuf->b_op_start = curwin->w_cursor;	/* default for '[ mark */
--- a/src/option.c
+++ b/src/option.c
@@ -38,20 +38,61 @@
  * The options that are local to a window or buffer have "indir" set to one of
  * these values.  Special values:
  * PV_NONE: global option.
+ * PV_WIN is added: window-local option
+ * PV_BUF is added: buffer-local option
  * PV_BOTH is added: global option which also has a local value.
  */
 #define PV_BOTH 0x1000
+#define PV_WIN  0x2000
+#define PV_BUF  0x4000
+#define OPT_WIN(x)  (idopt_T)(PV_WIN + (int)(x))
+#define OPT_BUF(x)  (idopt_T)(PV_BUF + (int)(x))
 #define OPT_BOTH(x) (idopt_T)(PV_BOTH + (int)(x))
 
+/*
+ * "indir" values for buffer-local opions
+ */
+enum
+{
+    BV_AI = 0
+    , BV_AR
+#if defined(FEAT_QUICKFIX)
+    , BV_BH
+#endif
+    , BV_BIN
+    , BV_BL
+    , BV_COUNT	    /* must be the last one */
+};
+
+#define PV_AI		OPT_BUF(BV_AI)
+#define PV_AR		OPT_BOTH(OPT_BUF(BV_AR))
+#if defined(FEAT_QUICKFIX)
+# define PV_BH		OPT_BUF(BV_BH)
+#endif
+#define PV_BIN		OPT_BUF(BV_BIN)
+#define PV_BL		OPT_BUF(BV_BL)
+
+/*
+ * "indir" values for window-local options
+ */
+enum
+{
+    WV_LIST = 0
+#ifdef FEAT_ARABIC
+	, WV_ARAB
+#endif
+    , WV_COUNT	    /* must be the last one */
+};
+
+#define PV_LIST		OPT_WIN(WV_LIST)
+#ifdef FEAT_ARABIC
+# define PV_ARAB	OPT_WIN(WV_ARAB)
+#endif
+
+/* TODO: "indir" values for the rest */
 typedef enum
 {
     PV_NONE = 0
-    , PV_AI
-    , PV_AR
-    , PV_ARAB
-    , PV_BH
-    , PV_BIN
-    , PV_BL
     , PV_BOMB
     , PV_BT
     , PV_CI
@@ -100,7 +141,6 @@ typedef enum
     , PV_KP
     , PV_LBR
     , PV_LISP
-    , PV_LIST
     , PV_MA
     , PV_ML
     , PV_MOD
@@ -408,7 +448,7 @@ static struct vimoption
 			    (char_u *)NULL, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L}},
     {"autoread",    "ar",   P_BOOL|P_VI_DEF,
-			    (char_u *)&p_ar, OPT_BOTH(PV_AR),
+			    (char_u *)&p_ar, PV_AR,
 			    {(char_u *)FALSE, (char_u *)0L}},
     {"autowrite",   "aw",   P_BOOL|P_VI_DEF,
 			    (char_u *)&p_aw, PV_NONE,
@@ -4092,7 +4132,7 @@ do_set(arg, opt_flags)
 			 * with a local value the local value will be
 			 * reset, use the global value here. */
 			if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
-				&& (int)options[opt_idx].indir >= PV_BOTH)
+				&& ((int)options[opt_idx].indir & PV_BOTH))
 			    varp = options[opt_idx].var;
 
 			/* The old value is kept until we are sure that the
@@ -4189,7 +4229,7 @@ do_set(arg, opt_flags)
 
 			    /* When setting the local value of a global
 			     * option, the old value may be the global value. */
-			    if ((int)options[opt_idx].indir >= PV_BOTH
+			    if (((int)options[opt_idx].indir & PV_BOTH)
 						   && (opt_flags & OPT_LOCAL))
 				origval = *(char_u **)get_varp(
 							   &options[opt_idx]);
@@ -5035,7 +5075,7 @@ set_string_option_direct(name, opt_idx, 
 
 	/* When setting both values of a global option with a local value,
 	 * make the local value empty, so that the global value is used. */
-	if ((int)options[opt_idx].indir >= PV_BOTH && both)
+	if (((int)options[opt_idx].indir & PV_BOTH) && both)
 	{
 	    free_string_option(*varp);
 	    *varp = empty_option;
@@ -5088,7 +5128,7 @@ set_string_option(opt_idx, value, opt_fl
     {
 	varp = (char_u **)get_varp_scope(&(options[opt_idx]),
 		(opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
-		    ? ((int)options[opt_idx].indir >= PV_BOTH
+		    ? (((int)options[opt_idx].indir & PV_BOTH)
 			? OPT_GLOBAL : OPT_LOCAL)
 		    : opt_flags);
 	oldval = *varp;
@@ -6351,7 +6391,7 @@ did_set_string_option(opt_idx, varp, new
 	    options[opt_idx].flags &= ~P_ALLOCED;
 
 	if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0
-		&& (int)options[opt_idx].indir >= PV_BOTH)
+		&& ((int)options[opt_idx].indir & PV_BOTH))
 	{
 	    /* global option with local value set to use global value; free
 	     * the local value and make it empty */
@@ -8538,7 +8578,7 @@ get_varp_scope(p, opt_flags)
 	    return (char_u *)GLOBAL_WO(get_varp(p));
 	return p->var;
     }
-    if ((opt_flags & OPT_LOCAL) && (int)p->indir >= PV_BOTH)
+    if ((opt_flags & OPT_LOCAL) && ((int)p->indir & PV_BOTH))
     {
 	switch ((int)p->indir)
 	{
@@ -8550,7 +8590,7 @@ get_varp_scope(p, opt_flags)
 	    case OPT_BOTH(PV_EP):   return (char_u *)&(curbuf->b_p_ep);
 	    case OPT_BOTH(PV_KP):   return (char_u *)&(curbuf->b_p_kp);
 	    case OPT_BOTH(PV_PATH): return (char_u *)&(curbuf->b_p_path);
-	    case OPT_BOTH(PV_AR):   return (char_u *)&(curbuf->b_p_ar);
+	    case PV_AR:   return (char_u *)&(curbuf->b_p_ar);
 	    case OPT_BOTH(PV_TAGS): return (char_u *)&(curbuf->b_p_tags);
 #ifdef FEAT_FIND_ID
 	    case OPT_BOTH(PV_DEF):  return (char_u *)&(curbuf->b_p_def);
@@ -8591,7 +8631,7 @@ get_varp(p)
 				    ? (char_u *)&curbuf->b_p_kp : p->var;
 	case OPT_BOTH(PV_PATH):	return *curbuf->b_p_path != NUL
 				    ? (char_u *)&(curbuf->b_p_path) : p->var;
-	case OPT_BOTH(PV_AR):	return curbuf->b_p_ar >= 0
+	case PV_AR:	return curbuf->b_p_ar >= 0
 				    ? (char_u *)&(curbuf->b_p_ar) : p->var;
 	case OPT_BOTH(PV_TAGS):	return *curbuf->b_p_tags != NUL
 				    ? (char_u *)&(curbuf->b_p_tags) : p->var;
--- a/src/option.h
+++ b/src/option.h
@@ -10,15 +10,6 @@
  * option.h: definition of global variables for settable options
  */
 
-#ifndef EXTERN
-# define EXTERN extern
-# define INIT(x)
-#else
-# ifndef INIT
-#  define INIT(x) x
-# endif
-#endif
-
 /*
  * Default values for 'errorformat'.
  * The "%f|%l| %m" one is used for when the contents of the quickfix window is
@@ -379,10 +370,6 @@ EXTERN long	p_cwh;		/* 'cmdwinheight' */
 #endif
 #ifdef FEAT_CLIPBOARD
 EXTERN char_u	*p_cb;		/* 'clipboard' */
-EXTERN int	clip_unnamed INIT(= FALSE);
-EXTERN int	clip_autoselect INIT(= FALSE);
-EXTERN int	clip_autoselectml INIT(= FALSE);
-EXTERN regprog_T *clip_exclude_prog INIT(= NULL);
 #endif
 EXTERN long	p_ch;		/* 'cmdheight' */
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
@@ -515,6 +502,8 @@ EXTERN char_u	*p_mouseshape;	/* 'mousesh
 #endif
 #if defined(FEAT_GUI)
 EXTERN char_u	*p_go;		/* 'guioptions' */
+#endif
+#if defined(FEAT_GUI_TABLINE)
 EXTERN char_u	*p_gtl;		/* 'guitablabel' */
 #endif
 EXTERN char_u	*p_hf;		/* 'helpfile' */
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -54,7 +54,7 @@ char_u *get_dict_string __ARGS((dict_T *
 long get_dict_number __ARGS((dict_T *d, char_u *key));
 char_u *get_function_name __ARGS((expand_T *xp, int idx));
 char_u *get_expr_name __ARGS((expand_T *xp, int idx));
-long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos));
+long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop));
 void set_vim_var_nr __ARGS((int idx, long val));
 long get_vim_var_nr __ARGS((int idx));
 char_u *get_vim_var_str __ARGS((int idx));
--- a/src/proto/gui.pro
+++ b/src/proto/gui.pro
@@ -37,6 +37,7 @@ void gui_init_which_components __ARGS((c
 int gui_use_tabline __ARGS((void));
 void gui_update_tabline __ARGS((void));
 void get_tabline_label __ARGS((tabpage_T *tp));
+int send_tabline_event __ARGS((int nr));
 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/normal.pro
+++ b/src/proto/normal.pro
@@ -18,6 +18,7 @@ void do_check_scrollbind __ARGS((int che
 void check_scrollbind __ARGS((linenr_T topline_diff, long leftcol_diff));
 int find_decl __ARGS((char_u *ptr, int len, int locally, int thisblock, int searchflags));
 void scroll_redraw __ARGS((int up, long count));
+void handle_tabmenu __ARGS((void));
 void do_nv_ident __ARGS((int c1, int c2));
 int get_visual_text __ARGS((cmdarg_T *cap, char_u **pp, int *lenp));
 void start_selection __ARGS((void));
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -3861,17 +3861,17 @@ regmatch(scan)
 		}
 		else
 		{
-		    if (lt(curbuf->b_visual_start, curbuf->b_visual_end))
+		    if (lt(curbuf->b_visual.vi_start, curbuf->b_visual.vi_end))
 		    {
-			top = curbuf->b_visual_start;
-			bot = curbuf->b_visual_end;
+			top = curbuf->b_visual.vi_start;
+			bot = curbuf->b_visual.vi_end;
 		    }
 		    else
 		    {
-			top = curbuf->b_visual_end;
-			bot = curbuf->b_visual_start;
+			top = curbuf->b_visual.vi_end;
+			bot = curbuf->b_visual.vi_start;
 		    }
-		    mode = curbuf->b_visual_mode;
+		    mode = curbuf->b_visual.vi_mode;
 		}
 		lnum = reglnum + reg_firstlnum;
 		col = (colnr_T)(reginput - regline);
--- a/src/search.c
+++ b/src/search.c
@@ -496,7 +496,7 @@ last_pat_prog(regmatch)
  * subpattern plus one; one if there was none.
  */
     int
-searchit(win, buf, pos, dir, pat, count, options, pat_use)
+searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum)
     win_T	*win;		/* window to search in; can be NULL for a
 				   buffer without a window! */
     buf_T	*buf;
@@ -505,7 +505,8 @@ searchit(win, buf, pos, dir, pat, count,
     char_u	*pat;
     long	count;
     int		options;
-    int		pat_use;
+    int		pat_use;	/* which pattern to use when "pat" is empty */
+    linenr_T	stop_lnum;	/* stop after this line number when != 0 */
 {
     int		found;
     linenr_T	lnum;		/* no init to shut up Apollo cc */
@@ -586,6 +587,11 @@ searchit(win, buf, pos, dir, pat, count,
 	    for ( ; lnum > 0 && lnum <= buf->b_ml.ml_line_count;
 					   lnum += dir, at_first_line = FALSE)
 	    {
+		/* Stop after checking "stop_lnum", if it's set. */
+		if (stop_lnum != 0 && (dir == FORWARD
+				       ? lnum > stop_lnum : lnum < stop_lnum))
+		    break;
+
 		/*
 		 * Look for a match somewhere in line "lnum".
 		 */
@@ -842,10 +848,12 @@ searchit(win, buf, pos, dir, pat, count,
 	    at_first_line = FALSE;
 
 	    /*
-	     * Stop the search if wrapscan isn't set, after an interrupt,
-	     * after a match and after looping twice.
+	     * Stop the search if wrapscan isn't set, "stop_lnum" is
+	     * specified, after an interrupt, after a match and after looping
+	     * twice.
 	     */
-	    if (!p_ws || got_int || called_emsg || break_loop || found || loop)
+	    if (!p_ws || stop_lnum != 0 || got_int || called_emsg
+					       || break_loop || found || loop)
 		break;
 
 	    /*
@@ -1227,7 +1235,7 @@ do_search(oap, dirc, pat, count, options
 		       (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
 			+ SEARCH_MSG + SEARCH_START
 			+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
-		RE_LAST);
+		RE_LAST, (linenr_T)0);
 
 	if (dircp != NULL)
 	    *dircp = dirc;	/* restore second '/' or '?' for normal_cmd() */
@@ -3746,7 +3754,8 @@ again:
     {
 	if (do_searchpair((char_u *)"<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|\\_s\\=>\\)",
 		    (char_u *)"",
-		    (char_u *)"</[^>]*>", BACKWARD, (char_u *)"", 0, NULL) <= 0)
+		    (char_u *)"</[^>]*>", BACKWARD, (char_u *)"", 0,
+						      NULL, (linenr_T)0) <= 0)
 	{
 	    curwin->w_cursor = old_pos;
 	    goto theend;
@@ -3779,7 +3788,8 @@ again:
     sprintf((char *)spat, "<%.*s\\%%(\\_[^>]\\{-}[^/]>\\|>\\)\\c", len, p);
     sprintf((char *)epat, "</%.*s>\\c", len, p);
 
-    r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"", 0, NULL);
+    r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"",
+						       0, NULL, (linenr_T)0);
 
     vim_free(spat);
     vim_free(epat);
@@ -3959,8 +3969,8 @@ extend:
      * Move past the end of any white lines.
      */
     end_lnum = start_lnum;
-    while (linewhite(end_lnum) && end_lnum < curbuf->b_ml.ml_line_count)
-	    ++end_lnum;
+    while (end_lnum <= curbuf->b_ml.ml_line_count && linewhite(end_lnum))
+	++end_lnum;
 
     --end_lnum;
     i = count;
--- a/src/structs.h
+++ b/src/structs.h
@@ -242,6 +242,15 @@ typedef struct foldinfo
 				   line */
 } foldinfo_T;
 
+/* Structure to store info about the Visual area. */
+typedef struct
+{
+    pos_T	vi_start;	/* start pos of last VIsual */
+    pos_T	vi_end;		/* end position of last VIsual */
+    int		vi_mode;	/* VIsual_mode of last VIsual */
+    colnr_T	vi_curswant;	/* MAXCOL from w_curswant */
+} visualinfo_T;
+
 /*
  * stuctures used for undo
  */
@@ -270,6 +279,9 @@ struct u_header
 #endif
     int		uh_flags;	/* see below */
     pos_T	uh_namedm[NMARKS];	/* marks before undo/after redo */
+#ifdef FEAT_VISUAL
+    visualinfo_T uh_visual;	/* Visual areas before undo/after redo */
+#endif
 };
 
 /* values for uh_flags */
@@ -1169,13 +1181,10 @@ struct file_buffer
 
 #ifdef FEAT_VISUAL
     /* These variables are set when VIsual_active becomes FALSE */
-    pos_T	b_visual_start;	/* start pos of last VIsual */
-    pos_T	b_visual_end;	/* end position of last VIsual */
-    int		b_visual_mode;	/* VIsual_mode of last VIsual */
+    visualinfo_T b_visual;
 # ifdef FEAT_EVAL
-    int		b_visual_mode_eval;  /* b_visual_mode for visualmode() */
+    int		b_visual_mode_eval;  /* b_visual.vi_mode for visualmode() */
 # endif
-    colnr_T	b_visual_curswant;   /* MAXCOL from w_curswant */
 #endif
 
     pos_T	b_last_cursor;	/* cursor position when last unloading this
@@ -2228,3 +2237,16 @@ typedef struct
     char_u	*pum_extra;	/* extra menu text (may be truncated) */
     char_u	*pum_info;	/* extra info */
 } pumitem_T;
+
+/*
+ * Structure used for get_tagfname().
+ */
+typedef struct
+{
+    char_u	*tn_tags;	/* value of 'tags' when starting */
+    char_u	*tn_np;		/* current position in tn_tags */
+    int		tn_did_filefind_init;
+    int		tn_hf_idx;
+    void	*tn_search_ctx;
+} tagname_T;
+
--- a/src/tag.c
+++ b/src/tag.c
@@ -356,7 +356,11 @@ do_tag(tag, type, count, forceit, verbos
 		goto end_do_tag;
 	    }
 
-	    if (type == DT_TAG)
+	    if (type == DT_TAG
+#if defined(FEAT_QUICKFIX)
+		|| type == DT_LTAG
+#endif
+		)
 	    {
 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
 		if (g_do_tagpreview)
@@ -413,9 +417,6 @@ do_tag(tag, type, count, forceit, verbos
 		switch (type)
 		{
 		    case DT_FIRST: cur_match = count - 1; break;
-#ifdef FEAT_QUICKFIX
-		    case DT_LTAG: cur_match = 0; break;
-#endif
 		    case DT_SELECT:
 		    case DT_JUMP:
 #ifdef FEAT_CSCOPE
@@ -516,7 +517,11 @@ do_tag(tag, type, count, forceit, verbos
 	    if (type == DT_TAG && count > 0)
 		cur_match = count - 1;
 
-	    if (type == DT_SELECT || type == DT_JUMP)
+	    if (type == DT_SELECT || type == DT_JUMP
+#if defined(FEAT_QUICKFIX)
+		|| type == DT_LTAG
+#endif
+		)
 		cur_match = MAXCOL - 1;
 	    max_num_matches = cur_match + 1;
 
@@ -763,8 +768,7 @@ do_tag(tag, type, count, forceit, verbos
 		ask_for_selection = TRUE;
 	    }
 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
-	    else
-	    if (type == DT_LTAG)
+	    else if (type == DT_LTAG)
 	    {
 		list_T	*list;
 		char_u	tag_name[128 + 1];
@@ -826,6 +830,7 @@ do_tag(tag, type, count, forceit, verbos
 				;
 			    cmd_end = p;
 			}
+
 			/*
 			 * Now, cmd_end points to the character after the
 			 * command. Adjust it to point to the last
@@ -872,7 +877,7 @@ do_tag(tag, type, count, forceit, verbos
 
 			if (cmd[len - 1] == '$')
 			{
-			    /* 
+			    /*
 			     * Replace '$' at the end of the search pattern
 			     * with '\$'
 			     */
@@ -902,6 +907,8 @@ do_tag(tag, type, count, forceit, verbos
 		set_errorlist(curwin, list, ' ');
 
 		list_free(list);
+
+		cur_match = 0;		/* Jump to the first tag */
 	    }
 #endif
 
@@ -1258,6 +1265,7 @@ find_tags(pat, num_matches, matchesp, fl
     FILE       *fp;
     char_u     *lbuf;			/* line buffer */
     char_u     *tag_fname;		/* name of tag file */
+    tagname_T	tn;			/* info for get_tagfname() */
     int		first_file;		/* trying first tag file */
     tagptrs_T	tagp;
     int		did_open = FALSE;	/* did open a tag file */
@@ -1461,7 +1469,8 @@ find_tags(pat, num_matches, matchesp, fl
 #ifdef FEAT_CSCOPE
 	    use_cscope ||
 #endif
-		get_tagfname(first_file, tag_fname) == OK; first_file = FALSE)
+		get_tagfname(&tn, first_file, tag_fname) == OK;
+							   first_file = FALSE)
       {
 	/*
 	 * A file that doesn't exist is silently ignored.  Only when not a
@@ -2429,6 +2438,11 @@ line_read_in:
 
       } /* end of for-each-file loop */
 
+#ifdef FEAT_CSCOPE
+	if (!use_cscope)
+#endif
+	    tagname_free(&tn);
+
 #ifdef FEAT_TAG_BINS
       /* stop searching when already did a linear search, or when TAG_NOIC
        * used, and 'ignorecase' not set or already did case-ignore search */
@@ -2519,13 +2533,11 @@ found_tagfile_cb(fname, cookie)
 							   vim_strsave(fname);
 }
 
-static void	*search_ctx = NULL;
-
 #if defined(EXITFREE) || defined(PROTO)
     void
 free_tag_stuff()
 {
-    vim_findfile_cleanup(search_ctx);
+    ga_clear_strings(&tag_fnames);
     do_tag(NULL, DT_FREE, 0, 0, 0);
 }
 #endif
@@ -2537,16 +2549,17 @@ free_tag_stuff()
  * Return FAIL if no more tag file names, OK otherwise.
  */
     int
-get_tagfname(first, buf)
+get_tagfname(tnp, first, buf)
+    tagname_T	*tnp;	/* holds status info */
     int		first;	/* TRUE when first file name is wanted */
     char_u	*buf;	/* pointer to buffer of MAXPATHL chars */
 {
-    static char_u	*np = NULL;
-    static int		did_filefind_init;
-    static int		hf_idx = 0;
     char_u		*fname = NULL;
     char_u		*r_ptr;
 
+    if (first)
+	vim_memset(tnp, 0, sizeof(tagname_T));
+
     if (curbuf->b_help)
     {
 	/*
@@ -2573,101 +2586,108 @@ get_tagfname(first, buf)
 		    "doc/tags"
 #endif
 					      , TRUE, found_tagfile_cb, NULL);
-	    hf_idx = 0;
 	}
 
-	if (hf_idx >= tag_fnames.ga_len)
+	if (tnp->tn_hf_idx >= tag_fnames.ga_len)
 	{
 	    /* Not found in 'runtimepath', use 'helpfile', if it exists and
 	     * wasn't used yet, replacing "help.txt" with "tags". */
-	    if (hf_idx > tag_fnames.ga_len || *p_hf == NUL)
+	    if (tnp->tn_hf_idx > tag_fnames.ga_len || *p_hf == NUL)
 		return FAIL;
-	    ++hf_idx;
+	    ++tnp->tn_hf_idx;
 	    STRCPY(buf, p_hf);
 	    STRCPY(gettail(buf), "tags");
 	}
 	else
-	    vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[hf_idx++],
-								MAXPATHL - 1);
+	    vim_strncpy(buf, ((char_u **)(tag_fnames.ga_data))[
+					     tnp->tn_hf_idx++], MAXPATHL - 1);
 	return OK;
     }
 
     if (first)
     {
-	/* Init. */
-	if (*curbuf->b_p_tags != NUL)
-	    np = curbuf->b_p_tags;
-	else
-	    np = p_tags;
-	vim_findfile_free_visited(search_ctx);
-	did_filefind_init = FALSE;
+	/* Init.  We make a copy of 'tags', because autocommands may change
+	 * the value without notifying us. */
+	tnp->tn_tags = vim_strsave((*curbuf->b_p_tags != NUL)
+						 ? curbuf->b_p_tags : p_tags);
+	if (tnp->tn_tags == NULL)
+	    return FAIL;
+	tnp->tn_np = tnp->tn_tags;
     }
-    else
+
+    /*
+     * Loop until we have found a file name that can be used.
+     * There are two states:
+     * tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'.
+     * tnp->tn_did_filefind_init == TRUE: find next file in this part.
+     */
+    for (;;)
     {
-	if (np == NULL)
-	    return FAIL;	/* tried already (or bogus call) */
-
-	/*
-	 * Loop until we have found a file name that can be used.
-	 * There are two states:
-	 * did_filefind_init == FALSE: setup for next part in 'tags'.
-	 * did_filefind_init == TRUE: find next file in this part.
-	 */
-	for (;;)
+	if (tnp->tn_did_filefind_init)
 	{
-	    if (did_filefind_init)
+	    fname = vim_findfile(tnp->tn_search_ctx);
+	    if (fname != NULL)
+		break;
+
+	    tnp->tn_did_filefind_init = FALSE;
+	}
+	else
+	{
+	    char_u  *filename = NULL;
+
+	    /* Stop when used all parts of 'tags'. */
+	    if (*tnp->tn_np == NUL)
 	    {
-		fname = vim_findfile(search_ctx);
-		if (fname != NULL)
-		    break;
-
-		did_filefind_init = FALSE;
+		vim_findfile_cleanup(tnp->tn_search_ctx);
+		tnp->tn_search_ctx = NULL;
+		return FAIL;
 	    }
-	    else
-	    {
-		char_u  *filename = NULL;
-
-		/* Stop when used all parts of 'tags'. */
-		if (*np == NUL)
-		{
-		    vim_findfile_cleanup(search_ctx);
-		    search_ctx = NULL;
-		    return FAIL;
-		}
-
-		/*
-		 * Copy next file name into buf.
-		 */
-		buf[0] = NUL;
-		(void)copy_option_part(&np, buf, MAXPATHL - 1, " ,");
+
+	    /*
+	     * Copy next file name into buf.
+	     */
+	    buf[0] = NUL;
+	    (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
 
 #ifdef FEAT_PATH_EXTRA
-		r_ptr = vim_findfile_stopdir(buf);
+	    r_ptr = vim_findfile_stopdir(buf);
 #else
-		r_ptr = NULL;
+	    r_ptr = NULL;
 #endif
-		/* move the filename one char forward and truncate the
-		 * filepath with a NUL */
-		filename = gettail(buf);
-		mch_memmove(filename + 1, filename, STRLEN(filename) + 1);
-		*filename++ = NUL;
-
-		search_ctx = vim_findfile_init(buf, filename, r_ptr, 100,
-			FALSE, /* don't free visited list */
-			FALSE, /* we search for a file */
-			search_ctx, TRUE, curbuf->b_ffname);
-		if (search_ctx != NULL)
-		    did_filefind_init = TRUE;
-	    }
+	    /* move the filename one char forward and truncate the
+	     * filepath with a NUL */
+	    filename = gettail(buf);
+	    mch_memmove(filename + 1, filename, STRLEN(filename) + 1);
+	    *filename++ = NUL;
+
+	    tnp->tn_search_ctx = vim_findfile_init(buf, filename,
+		    r_ptr, 100,
+		    FALSE, /* don't free visited list */
+		    FALSE, /* we search for a file */
+		    tnp->tn_search_ctx, TRUE, curbuf->b_ffname);
+	    if (tnp->tn_search_ctx != NULL)
+		tnp->tn_did_filefind_init = TRUE;
 	}
-	STRCPY(buf, fname);
-	vim_free(fname);
     }
 
+    STRCPY(buf, fname);
+    vim_free(fname);
     return OK;
 }
 
 /*
+ * Free the contents of a tagname_T that was filled by get_tagfname().
+ */
+    void
+tagname_free(tnp)
+    tagname_T	*tnp;
+{
+    vim_free(tnp->tn_tags);
+    vim_findfile_cleanup(tnp->tn_search_ctx);
+    ga_clear_strings(&tag_fnames);
+}
+
+/*
  * Parse one line from the tags file. Find start/end of tag name, start/end of
  * file name and start of search pattern.
  *
--- a/src/undo.c
+++ b/src/undo.c
@@ -294,8 +294,12 @@ u_savecommon(top, bot, newbot)
 	uhp->uh_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
 		       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
 
-	/* save named marks for undo */
+	/* save named marks and Visual marks for undo */
 	mch_memmove(uhp->uh_namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
+#ifdef FEAT_VISUAL
+	uhp->uh_visual = curbuf->b_visual;
+#endif
+
 	curbuf->b_u_newhead = uhp;
 	if (curbuf->b_u_oldhead == NULL)
 	    curbuf->b_u_oldhead = uhp;
@@ -569,6 +573,9 @@ u_undoredo()
     int		old_flags;
     int		new_flags;
     pos_T	namedm[NMARKS];
+#ifdef FEAT_VISUAL
+    visualinfo_T visualinfo;
+#endif
     int		empty_buffer;		    /* buffer became empty */
 
     old_flags = curbuf->b_u_curhead->uh_flags;
@@ -580,6 +587,9 @@ u_undoredo()
      * save marks before undo/redo
      */
     mch_memmove(namedm, curbuf->b_namedm, sizeof(pos_T) * NMARKS);
+#ifdef FEAT_VISUAL
+    visualinfo = curbuf->b_visual;
+#endif
     curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
     curbuf->b_op_start.col = 0;
     curbuf->b_op_end.lnum = 0;
@@ -741,11 +751,18 @@ u_undoredo()
      * restore marks from before undo/redo
      */
     for (i = 0; i < NMARKS; ++i)
-	if (curbuf->b_u_curhead->uh_namedm[i].lnum)
+	if (curbuf->b_u_curhead->uh_namedm[i].lnum != 0)
 	{
 	    curbuf->b_namedm[i] = curbuf->b_u_curhead->uh_namedm[i];
 	    curbuf->b_u_curhead->uh_namedm[i] = namedm[i];
 	}
+#ifdef FEAT_VISUAL
+    if (curbuf->b_u_curhead->uh_visual.vi_start.lnum != 0)
+    {
+	curbuf->b_visual = curbuf->b_u_curhead->uh_visual;
+	curbuf->b_u_curhead->uh_visual = visualinfo;
+    }
+#endif
 
     /*
      * If the cursor is only off by one line, put it at the same position as
--- 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 25)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 25, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 26)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2006 Feb 26, compiled "
--- a/src/workshop.c
+++ b/src/workshop.c
@@ -1127,13 +1127,13 @@ workshop_get_positions(
     *curLine = curwin->w_cursor.lnum;
     *curCol = curwin->w_cursor.col;
 
-    if (curbuf->b_visual_mode == 'v' &&
-	    equalpos(curwin->w_cursor, curbuf->b_visual_end))
+    if (curbuf->b_visual.vi_mode == 'v' &&
+	    equalpos(curwin->w_cursor, curbuf->b_visual.vi_end))
     {
-	*selStartLine = curbuf->b_visual_start.lnum;
-	*selStartCol = curbuf->b_visual_start.col;
-	*selEndLine = curbuf->b_visual_end.lnum;
-	*selEndCol = curbuf->b_visual_end.col;
+	*selStartLine = curbuf->b_visual.vi_start.lnum;
+	*selStartCol = curbuf->b_visual.vi_start.col;
+	*selEndLine = curbuf->b_visual.vi_end.lnum;
+	*selEndCol = curbuf->b_visual.vi_end.col;
 	*selection = get_selection(curbuf);
 	if (*selection)
 	    *selLength = strlen(*selection);
@@ -1171,10 +1171,10 @@ get_selection(
     char	*new_sp;	/* temp pointer to new sp */
     int		 lnum;		/* line number we are appending */
 
-    if (buf->b_visual_mode == 'v')
+    if (buf->b_visual.vi_mode == 'v')
     {
-	start = &buf->b_visual_start;
-	end = &buf->b_visual_end;
+	start = &buf->b_visual.vi_start;
+	end = &buf->b_visual.vi_end;
 	if (start->lnum == end->lnum)
 	{
 	    /* selection is all on one line */