Submitted By: Matt Burgess (matthew at linuxfromscratch dot org)
Date: 2008-02-17
Initial Package Version: 7.1
Origin: Upstream
Upstream Status: Applied
Description: Contains patches 001-251 from upstream

diff -Naur vim71.orig/runtime/doc/Makefile vim71/runtime/doc/Makefile
--- vim71.orig/runtime/doc/Makefile	2006-11-07 20:59:05.000000000 +0000
+++ vim71/runtime/doc/Makefile	2008-02-14 21:07:34.000000000 +0000
@@ -301,7 +301,7 @@
 # Use Vim to generate the tags file.  Can only be used when Vim has been
 # compiled and installed.  Supports multiple languages.
 vimtags: $(DOCS)
-	$(VIMEXE) -u NONE -esX -c "helptags ." -c quit
+	$(VIMEXE) -u NONE -esX -c "helptags ++t ." -c quit
 
 # Use "doctags" to generate the tags file.  Only works for English!
 tags: doctags $(DOCS)
diff -Naur vim71.orig/runtime/doc/change.txt vim71/runtime/doc/change.txt
--- vim71.orig/runtime/doc/change.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/change.txt	2008-02-14 21:07:31.000000000 +0000
@@ -1571,6 +1571,10 @@
 			in their original order, right before the sorted
 			lines.
 
+			If {pattern} is empty (e.g. // is specified), the
+			last search pattern is used.  This allows trying out
+			a pattern first.
+
 Note that using ":sort" with ":global" doesn't sort the matching lines, it's
 quite useless.
 
diff -Naur vim71.orig/runtime/doc/cmdline.txt vim71/runtime/doc/cmdline.txt
--- vim71.orig/runtime/doc/cmdline.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/cmdline.txt	2008-02-14 21:07:34.000000000 +0000
@@ -1,4 +1,4 @@
-*cmdline.txt*   For Vim version 7.1.  Last change: 2006 Jul 18
+*cmdline.txt*   For Vim version 7.1.  Last change: 2008 Jan 04
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -316,7 +316,7 @@
 command-line is shown.  (Note: the shifted arrow keys do not work on all
 terminals)
 
-							*his* *:history*
+							*:his* *:history*
 :his[tory]	Print the history of last entered commands.
 		{not in Vi}
 		{not available when compiled without the |+cmdline_hist|
@@ -447,6 +447,11 @@
 
 To completely ignore files with some extension use 'wildignore'.
 
+To match only files that end at the end of the typed text append a "$".  For
+example, to match only files that end in ".c": >
+	:e *.c$
+This will not match a file ending in ".cpp".  Without the "$" it does match.
+
 The old value of an option can be obtained by hitting 'wildchar' just after
 the '='.  For example, typing 'wildchar' after ":set dir=" will insert the
 current value of 'dir'.  This overrules file name completion for the options
diff -Naur vim71.orig/runtime/doc/eval.txt vim71/runtime/doc/eval.txt
--- vim71.orig/runtime/doc/eval.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/eval.txt	2008-02-14 21:07:34.000000000 +0000
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.1.  Last change: 2007 May 11
+*eval.txt*      For Vim version 7.1.  Last change: 2008 Feb 13
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1401,10 +1401,24 @@
 		This is the screen column number, like with |virtcol()|.  The
 		value is zero when there was no mouse button click.
 
+					*v:operator* *operator-variable*
+v:operator	The last operator given in Normal mode.  This is a single
+		character except for commands starting with <g> or <z>,
+		in which case it is two characters.  Best used alongside
+		|v:prevcount| and |v:register|.  Useful if you want to cancel
+		Operator-pending mode and then use the operator, e.g.: >
+			:omap O <Esc>:call MyMotion(v:operator)<CR>
+<		The value remains set until another operator is entered, thus
+		don't expect it to be empty.
+		v:operator is not set for |:delete|, |:yank| or other Ex
+		commands.
+		Read-only.
+
 					*v:prevcount* *prevcount-variable*
 v:prevcount	The count given for the last but one Normal mode command.
 		This is the v:count value of the previous command.  Useful if
-		you want to cancel Visual mode and then use the count. >
+		you want to cancel Visual or Operator-pending mode and then
+		use the count, e.g.: >
 			:vmap % <Esc>:call MyFilter(v:prevcount)<CR>
 <		Read-only.
 
@@ -1557,6 +1571,7 @@
 changenr()			Number  current change number
 char2nr( {expr})		Number	ASCII value of first char in {expr}
 cindent( {lnum})		Number	C indent for line {lnum}
+clearmatches()			None	clear all matches
 col( {expr})			Number	column nr of cursor or mark
 complete({startcol}, {matches})	String  set Insert mode completion
 complete_add( {expr})		Number	add completion match
@@ -1602,7 +1617,7 @@
 foldtextresult( {lnum})		String	text for closed fold at {lnum}
 foreground( )			Number	bring the Vim window to the foreground
 function( {name})		Funcref reference to function {name}
-garbagecollect()		none	free memory, breaking cyclic references
+garbagecollect( [at_exit])	none	free memory, breaking cyclic references
 get( {list}, {idx} [, {def}])	any	get item {idx} from {list} or {def}
 get( {dict}, {key} [, {def}])	any	get item {key} from {dict} or {def}
 getbufline( {expr}, {lnum} [, {end}])
@@ -1622,6 +1637,7 @@
 getline( {lnum})		String	line {lnum} of current buffer
 getline( {lnum}, {end})		List	lines {lnum} to {end} of current buffer
 getloclist({nr})		List	list of location list items
+getmatches()			List	list of current matches
 getpos( {expr})			List	position of cursor, mark, etc.
 getqflist()			List	list of quickfix items
 getreg( [{regname} [, 1]])	String	contents of register
@@ -1676,7 +1692,10 @@
 				String	check for mappings matching {name}
 match( {expr}, {pat}[, {start}[, {count}]])
 				Number	position where {pat} matches in {expr}
+matchadd( {group}, {pattern}[, {priority}[, {id}]])
+				Number	highlight {pattern} with {group}
 matcharg( {nr})			List	arguments of |:match|
+matchdelete( {id})		Number	delete match identified by {id}
 matchend( {expr}, {pat}[, {start}[, {count}]])
 				Number	position where {pat} ends in {expr}
 matchlist( {expr}, {pat}[, {start}[, {count}]])
@@ -1714,14 +1733,15 @@
 repeat( {expr}, {count})	String	repeat {expr} {count} times
 resolve( {filename})		String	get filename a shortcut points to
 reverse( {list})		List	reverse {list} in-place
-search( {pattern} [, {flags}])	Number	search for {pattern}
+search( {pattern} [, {flags} [, {stopline} [, {timeout}]]])
+				Number	search for {pattern}
 searchdecl({name} [, {global} [, {thisblock}]])
 				Number  search for variable declaration
-searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
+searchpair( {start}, {middle}, {end} [, {flags} [, {skip} [...]]])
 				Number	search for other end of start/end pair
-searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
+searchpairpos( {start}, {middle}, {end} [, {flags} [, {skip} [...]]])
 				List	search for other end of start/end pair
-searchpos( {pattern} [, {flags} [, {stopline}]])
+searchpos( {pattern} [, {flags} [, {stopline} [, {timeout}]]])
 				List	search for {pattern}
 server2client( {clientid}, {string})
 				Number	send reply string
@@ -1731,6 +1751,7 @@
 setline( {lnum}, {line})	Number	set line {lnum} to {line}
 setloclist( {nr}, {list}[, {action}])
 				Number	modify location list using {list}
+setmatches( {list})		Number	restore a list of matches
 setpos( {expr}, {list})		none	set the {expr} position to {list}
 setqflist( {list}[, {action}])	Number	modify quickfix list using {list}
 setreg( {n}, {v}[, {opt}])	Number	set register to value and type
@@ -1765,6 +1786,7 @@
 synIDattr( {synID}, {what} [, {mode}])
 				String	attribute {what} of syntax ID {synID}
 synIDtrans( {synID})		Number	translated syntax ID of {synID}
+synstack({lnum}, {col})		List    stack of syntax IDs at {lnum} and {col}
 system( {expr} [, {input}])	String	output of shell command/filter {expr}
 tabpagebuflist( [{arg}])	List	list of buffer numbers in tab page
 tabpagenr( [{arg}])		Number	number of current or last tab page
@@ -2012,6 +2034,10 @@
 		feature, -1 is returned.
 		See |C-indenting|.
 
+clearmatches()						*clearmatches()*
+		Clears all matches previously defined by |matchadd()| and the
+		|:match| commands.
+
 							*col()*
 col({expr})	The result is a Number, which is the byte index of the column
 		position given with {expr}.  The accepted positions are:
@@ -2020,6 +2046,10 @@
 			    number of characters in the cursor line plus one)
 		    'x	    position of mark x (if the mark is not set, 0 is
 			    returned)
+		Additionally {expr} can be [lnum, col]: a |List| with the line
+		and column number. Most useful when the column is "$", to get
+		the las column of a specific line.  When "lnum" or "col" is
+		out of range then col() returns zero.
 		To get the line number use |line()|.  To get both use
 		|getpos()|.
 		For the screen column position use |virtcol()|.
@@ -2659,7 +2689,7 @@
 		{name} can be a user defined function or an internal function.
 
 
-garbagecollect()					*garbagecollect()*
+garbagecollect([at_exit])				*garbagecollect()*
 		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
@@ -2669,6 +2699,9 @@
 		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.
+		When the optional "at_exit" argument is one, garbage
+		collection will also be done when exiting Vim, if it wasn't
+		done before.  This is useful when checking for memory leaks.
 
 get({list}, {idx} [, {default}])			*get()*
 		Get item {idx} from |List| {list}.  When this item is not
@@ -2824,6 +2857,8 @@
 		given file {fname}.
 		If {fname} is a directory, 0 is returned.
 		If the file {fname} can't be found, -1 is returned.
+		If the size of {fname} is too big to fit in a Number then -2
+		is returned.
 
 getfontname([{name}])					*getfontname()*
 		Without an argument returns the name of the normal font being
@@ -2912,6 +2947,28 @@
 		returned.  For an invalid window number {nr}, an empty list is
 		returned. Otherwise, same as getqflist().
 
+getmatches()						*getmatches()*
+		Returns a |List| with all matches previously defined by
+		|matchadd()| and the |:match| commands.  |getmatches()| is
+		useful in combination with |setmatches()|, as |setmatches()|
+		can restore a list of matches saved by |getmatches()|.
+		Example: >
+			:echo getmatches()
+<			[{'group': 'MyGroup1', 'pattern': 'TODO',
+			'priority': 10, 'id': 1}, {'group': 'MyGroup2',
+			'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
+			:let m = getmatches()
+			:call clearmatches()
+			:echo getmatches()
+<			[] >
+			:call setmatches(m)
+			:echo getmatches()
+<			[{'group': 'MyGroup1', 'pattern': 'TODO',
+			'priority': 10, 'id': 1}, {'group': 'MyGroup2',
+			'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
+			:unlet m
+<
+
 getqflist()						*getqflist()*
 		Returns a list with all the current quickfix errors.  Each
 		list item is a dictionary with these entries:
@@ -3616,6 +3673,44 @@
 		the pattern.  'smartcase' is NOT used.  The matching is always
 		done like 'magic' is set and 'cpoptions' is empty.
 
+					*matchadd()* *E798* *E799* *E801*
+matchadd({group}, {pattern}[, {priority}[, {id}]])
+		Defines a pattern to be highlighted in the current window (a
+		"match").  It will be highlighted with {group}.  Returns an
+		identification number (ID), which can be used to delete the
+		match using |matchdelete()|.
+
+		The optional {priority} argument assigns a priority to the
+		match.  A match with a high priority will have its
+		highlighting overrule that of a match with a lower priority.
+		A priority is specified as an integer (negative numbers are no
+		exception).  If the {priority} argument is not specified, the
+		default priority is 10.  The priority of 'hlsearch' is zero,
+		hence all matches with a priority greater than zero will
+		overrule it.  Syntax highlighting (see 'syntax') is a separate
+		mechanism, and regardless of the chosen priority a match will
+		always overrule syntax highlighting.
+
+		The optional {id} argument allows the request for a specific
+		match ID.  If a specified ID is already taken, an error
+		message will appear and the match will not be added.  An ID
+		is specified as a positive integer (zero excluded).  IDs 1, 2
+		and 3 are reserved for |:match|, |:2match| and |:3match|,
+		respectively.  If the {id} argument is not specified,
+		|matchadd()| automatically chooses a free ID.
+
+		The number of matches is not limited, as it is the case with
+		the |:match| commands.
+
+		Example: >
+			:highlight MyGroup ctermbg=green guibg=green
+			:let m = matchadd("MyGroup", "TODO")
+<		Deletion of the pattern: >
+			:call matchdelete(m)
+
+<		A list of matches defined by |matchadd()| and |:match| are
+		available from |getmatches()|.  All matches can be deleted in
+		one operation by |clearmatches()|.
 
 matcharg({nr})							*matcharg()*
 		Selects the {nr} match item, as set with a |:match|,
@@ -3625,8 +3720,15 @@
 			The pattern used.
 		When {nr} is not 1, 2 or 3 returns an empty |List|.
 		When there is no match item set returns ['', ''].
-		This is usef to save and restore a |:match|.
-
+		This is useful to save and restore a |:match|.
+		Highlighting matches using the |:match| commands are limited
+		to three matches. |matchadd()| does not have this limitation.
+
+matchdelete({id})			       *matchdelete()* *E802* *E803*
+		Deletes a match with ID {id} previously defined by |matchadd()|
+		or one of the |:match| commands.  Returns 0 if succesfull,
+		otherwise -1.  See example for |matchadd()|.  All matches can
+		be deleted in one operation by |clearmatches()|.
 
 matchend({expr}, {pat}[, {start}[, {count}]])			*matchend()*
 		Same as match(), but return the index of first character after
@@ -4112,7 +4214,7 @@
 		If you want a list to remain unmodified make a copy first: >
 			:let revlist = reverse(copy(mylist))
 
-search({pattern} [, {flags} [, {stopline}]])			*search()*
+search({pattern} [, {flags} [, {stopline} [, {timeout}]]])	*search()*
 		Search for regexp pattern {pattern}.  The search starts at the
 		cursor position (you can use |cursor()| to set it).
 
@@ -4140,6 +4242,14 @@
 			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.
+		A zero value is equal to not giving the argument.
+
+		When the {timeout} argument is given the search stops when
+		more than this many milli seconds have passed.  Thus when
+		{timeout} is 500 the search stops after half a second.
+		The value must not be negative.  A zero value is like not
+		giving the argument.
+		{only available when compiled with the +reltime feature}
 
 		If there is no match a 0 is returned and the cursor doesn't
 		move.  No error message is given.
@@ -4202,7 +4312,8 @@
 			endif
 <
 							*searchpair()*
-searchpair({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
+searchpair({start}, {middle}, {end} [, {flags} [, {skip}
+				[, {stopline} [, {timeout}]]]])
 		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.
@@ -4237,7 +4348,7 @@
 		When evaluating {skip} causes an error the search is aborted
 		and -1 returned.
 
-		For {stopline} see |search()|.
+		For {stopline} and {timeout} see |search()|.
 
 		The value of 'ignorecase' is used.  'magic' is ignored, the
 		patterns are used like it's on.
@@ -4283,7 +4394,8 @@
 	     \ 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"')
 <
 							*searchpairpos()*
-searchpairpos({start}, {middle}, {end} [, {flags} [, {skip} [, {stopline}]]])
+searchpairpos({start}, {middle}, {end} [, {flags} [, {skip}
+				[, {stopline} [, {timeout}]]]])
 		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
@@ -4294,7 +4406,7 @@
 <
 		See |match-parens| for a bigger and more useful example.
 
-searchpos({pattern} [, {flags} [, {stopline}]])		*searchpos()*
+searchpos({pattern} [, {flags} [, {stopline} [, {timeout}]]])	*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
@@ -4379,7 +4491,13 @@
 		When {nr} is zero the current window is used. For a location
 		list window, the displayed location list is modified.  For an
 		invalid window number {nr}, -1 is returned.
-		Otherwise, same as setqflist().
+		Otherwise, same as |setqflist()|.
+		Also see |location-list|.
+
+setmatches({list})					*setmatches()*
+		Restores a list of matches saved by |getmatches()|.  Returns 0
+		if succesfull, otherwise -1.  All current matches are cleared
+		before the list is restored.  See example for |getmatches()|.
 
 							*setpos()*
 setpos({expr}, {list})
@@ -4405,6 +4523,9 @@
 		character.  E.g., a position within a <Tab> or after the last
 		character.
 
+		Returns 0 when the position could be set, -1 otherwise.
+		An error message is given if {expr} is invalid.
+
 		Also see |getpos()|
 
 		This does not restore the preferred column for moving
@@ -4845,6 +4966,20 @@
 		highlight the character.  Highlight links given with
 		":highlight link" are followed.
 
+synstack({lnum}, {col})					*synstack()*
+		Return a |List|, which is the stack of syntax items at the
+		position {lnum} and {col} in the current window.  Each item in
+		the List is an ID like what |synID()| returns.
+		The first item in the List is the outer region, following are
+		items contained in that one.  The last one is what |synID()|
+		returns, unless not the whole item is highlighted or it is a
+		transparent item.
+		This function is useful for debugging a syntax file.
+		Example that shows the syntax stack under the cursor: >
+			for id in synstack(line("."), col("."))
+			   echo synIDattr(id, "name")
+			endfor
+
 system({expr} [, {input}])				*system()* *E677*
 		Get the output of the shell command {expr}.
 		When {input} is given, this string is written to a file and
@@ -5022,14 +5157,12 @@
 		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.  When
-		"lnum" or "col" is out of range then virtcol() returns zero.
-		When 'virtualedit' is used it can be [lnum, col, off], where
+		For the byte position use |col()|.
+		For the use of {expr} see |col()|.
+		When 'virtualedit' is used {expr} can be [lnum, col, off], where
 		"off" is the offset in screen columns from the start of the
 		character.  E.g., a position within a <Tab> or after the last
 		character.
-		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'|
 		The accepted positions are:
diff -Naur vim71.orig/runtime/doc/gui_w32.txt vim71/runtime/doc/gui_w32.txt
--- vim71.orig/runtime/doc/gui_w32.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/gui_w32.txt	2008-02-14 21:07:32.000000000 +0000
@@ -1,4 +1,4 @@
-*gui_w32.txt*   For Vim version 7.1.  Last change: 2007 May 03
+*gui_w32.txt*   For Vim version 7.1.  Last change: 2007 Aug 14
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -53,6 +53,16 @@
 There is a specific version of gvim.exe that runs under the Win32s subsystem
 of Windows 3.1 or 3.11.  See |win32s|.
 
+
+Using Vim as a plugin					*gui-w32-windowid*
+
+When gvim starts up normally, it creates its own top level window.  If you
+pass Vim the command-line option |--windowid| with a decimal or hexadecimal
+value, Vim will create a window that is a child of the window with the given
+ID.  This enables Vim to act as a plugin in another application.  This really
+is a programmer's interface, and is of no use without a supporting application
+to spawn Vim correctly.
+
 ==============================================================================
 2. Vim as default editor				*vim-default-editor*
 
diff -Naur vim71.orig/runtime/doc/options.txt vim71/runtime/doc/options.txt
--- vim71.orig/runtime/doc/options.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/options.txt	2008-02-14 21:07:34.000000000 +0000
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.1.  Last change: 2007 May 11
+*options.txt*	For Vim version 7.1.  Last change: 2007 Aug 10
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2415,8 +2415,8 @@
 	When mixing vertically and horizontally split windows, a minimal size
 	is computed and some windows may be larger if there is room.  The
 	'eadirection' option tells in which direction the size is affected.
-	Changing the height of a window can be avoided by setting
-	'winfixheight'.
+	Changing the height and width of a window can be avoided by setting
+	'winfixheight' and 'winfixwidth', respectively.
 
 						*'equalprg'* *'ep'*
 'equalprg' 'ep'		string	(default "")
@@ -3618,6 +3618,7 @@
 	When you get bored looking at the highlighted matches, you can turn it
 	off with |:nohlsearch|.  As soon as you use a search command, the
 	highlighting comes back.
+	'redrawtime' specifies the maximum time spend on finding matches.
 	When the search pattern can match an end-of-line, Vim will try to
 	highlight all of the matched text.  However, this depends on where the
 	search starts.  This will be the first line in the window or the first
@@ -3851,6 +3852,10 @@
 	original position when no match is found and when pressing <Esc>.  You
 	still need to finish the search command with <Enter> to move the
 	cursor to the match.
+	When compiled with the |+reltime| feature Vim only searches for about
+	half a second.  With a complicated pattern and/or a lot of text the
+	match may not be found.  This is to avoid that Vim hangs while you
+	are typing the pattern.
 	The highlighting can be set with the 'i' flag in 'highlight'.
 	See also: 'hlsearch'.
 	CTRL-L can be used to add one character from after the current match
@@ -5185,6 +5190,18 @@
 	{not in Vi:}  When using the ":view" command the 'readonly' option is
 	set for the newly edited buffer.
 
+						*'redrawtime'* *'rdt'*
+'redrawtime' 'rdt'	number	(default 2000)
+			global
+			{not in Vi}
+			{only available when compiled with the |+reltime|
+			feature}
+	The time in milliseconds for redrawing the display.  This applies to
+	searching for patterns for 'hlsearch' and |:match| highlighting.
+	When redrawing takes more than this many milliseconds no further
+	matches will be highlighted.  This is used to avoid that Vim hangs
+	when using a very complicated pattern.
+
 						*'remap'* *'noremap'*
 'remap'			boolean	(default on)
 			global
diff -Naur vim71.orig/runtime/doc/pattern.txt vim71/runtime/doc/pattern.txt
--- vim71.orig/runtime/doc/pattern.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/pattern.txt	2008-02-14 21:07:32.000000000 +0000
@@ -1212,7 +1212,10 @@
 		{group} must exist at the moment this command is executed.
 
 		The {group} highlighting still applies when a character is
-		to be highlighted for 'hlsearch'.
+		to be highlighted for 'hlsearch', as the highlighting for
+		matches is given higher priority than that of 'hlsearch'.
+		Syntax highlighting (see 'syntax') is also overruled by
+		matches.
 
 		Note that highlighting the last used search pattern with
 		'hlsearch' is used in all windows, while the pattern defined
@@ -1226,8 +1229,15 @@
 		display you may get unexpected results.  That is because Vim
 		looks for a match in the line where redrawing starts.
 
-		Also see |matcharg()|, it returns the highlight group and
-		pattern of a previous :match command.
+		Also see |matcharg()|and |getmatches()|. The former returns
+		the highlight group and pattern of a previous |:match|
+		command.  The latter returns a list with highlight groups and
+		patterns defined by both |matchadd()| and |:match|.
+
+		Highlighting matches using |:match| are limited to three
+		matches (aside from |:match|, |:2match| and |:3match|are
+		available). |matchadd()| does not have this limitation and in
+		addition makes it possible to prioritize matches.
 
 		Another example, which highlights all characters in virtual
 		column 72 and more: >
diff -Naur vim71.orig/runtime/doc/pi_paren.txt vim71/runtime/doc/pi_paren.txt
--- vim71.orig/runtime/doc/pi_paren.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/pi_paren.txt	2008-02-14 21:07:32.000000000 +0000
@@ -12,8 +12,8 @@
 You can avoid loading this plugin by setting the "loaded_matchparen" variable: >
 	:let loaded_matchparen = 1
 
-The plugin installs CursorMoved autocommands to redefine the match
-highlighting.
+The plugin installs CursorMoved, CursorMovedI and WinEnter autocommands to
+redefine the match highlighting.
 
 To disable the plugin after it was loaded use this command: >
 
diff -Naur vim71.orig/runtime/doc/starting.txt vim71/runtime/doc/starting.txt
--- vim71.orig/runtime/doc/starting.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/starting.txt	2008-02-14 21:07:32.000000000 +0000
@@ -1,4 +1,4 @@
-*starting.txt*  For Vim version 7.1.  Last change: 2007 May 12
+*starting.txt*  For Vim version 7.1.  Last change: 2007 Aug 14
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -548,6 +548,11 @@
 		that it runs inside another window.  See |gui-gtk-socketid|
 		for details. {not in Vi}
 
+--windowid {id}						*--windowid*
+		Win32 GUI Vim only.  Make gvim try to use the window {id} as a
+		parent, so that it runs inside that window.  See
+		|gui-w32-windowid| for details. {not in Vi}
+
 --echo-wid						*--echo-wid*
 		GTK+ GUI Vim only.  Make gvim echo the Window ID on stdout,
 		which can be used to run gvim in a kpart widget.  The format
diff -Naur vim71.orig/runtime/doc/usr_41.txt vim71/runtime/doc/usr_41.txt
--- vim71.orig/runtime/doc/usr_41.txt	2007-05-12 10:18:48.000000000 +0000
+++ vim71/runtime/doc/usr_41.txt	2008-02-14 21:07:32.000000000 +0000
@@ -763,13 +763,22 @@
 	foldtextresult()	get the text displayed for a closed fold
 
 Syntax and highlighting:
+	clearmatches()		clear all matches defined by |matchadd()| and
+				the |:match| commands
+	getmatches()		get all matches defined by |matchadd()| and
+				the |:match| commands
 	hlexists()		check if a highlight group exists
 	hlID()			get ID of a highlight group
 	synID()			get syntax ID at a specific position
 	synIDattr()		get a specific attribute of a syntax ID
 	synIDtrans()		get translated syntax ID
 	diff_hlID()		get highlight ID for diff mode at a position
+	matchadd()		define a pattern to highlight (a "match")
 	matcharg()		get info about |:match| arguments
+	matchdelete()		delete a match defined by |matchadd()| or a
+				|:match| command
+	setmatches()		restore a list of matches saved by
+				|getmatches()|
 
 Spelling:
 	spellbadword()		locate badly spelled word at or after cursor
diff -Naur vim71.orig/runtime/doc/various.txt vim71/runtime/doc/various.txt
--- vim71.orig/runtime/doc/various.txt	2007-05-12 10:18:48.000000000 +0000
+++ vim71/runtime/doc/various.txt	2008-02-14 21:07:34.000000000 +0000
@@ -1,4 +1,4 @@
-*various.txt*   For Vim version 7.1.  Last change: 2007 Jan 14
+*various.txt*   For Vim version 7.1.  Last change: 2008 Jan 11
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -748,7 +748,8 @@
 
 					*:helpt* *:helptags*
 				*E154* *E150* *E151* *E152* *E153* *E670*
-:helpt[ags] {dir}	Generate the help tags file(s) for directory {dir}.
+:helpt[ags] [++t] {dir}
+			Generate the help tags file(s) for directory {dir}.
 			All "*.txt" and "*.??x" files in the directory are
 			scanned for a help tag definition in between stars.
 			The "*.??x" files are for translated docs, they
@@ -756,6 +757,9 @@
 			The generated tags files are sorted.
 			When there are duplicates an error message is given.
 			An existing tags file is silently overwritten.
+			The optional "++t" argument forces adding the
+			"help-tags" tag.  This is also done when the {dir} is
+			equal to $VIMRUNTIME/doc.
 			To rebuild the help tags in the runtime directory
 			(requires write permission there): >
 				:helptags $VIMRUNTIME/doc
diff -Naur vim71.orig/runtime/doc/vi_diff.txt vim71/runtime/doc/vi_diff.txt
--- vim71.orig/runtime/doc/vi_diff.txt	2007-05-12 10:18:49.000000000 +0000
+++ vim71/runtime/doc/vi_diff.txt	2008-02-14 21:07:32.000000000 +0000
@@ -1,4 +1,4 @@
-*vi_diff.txt*   For Vim version 7.1.  Last change: 2007 May 07
+*vi_diff.txt*   For Vim version 7.1.  Last change: 2007 Aug 14
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -827,6 +827,8 @@
 
 --socketid {id}		Vim: GTK window socket to run Vim in
 
+--windowid {id}		Vim: Win32 window ID to run Vim in
+
 --version	Vim: show version message and exit.
 
 -?		Vile: print usage summary and exit.
diff -Naur vim71.orig/runtime/doc/windows.txt vim71/runtime/doc/windows.txt
--- vim71.orig/runtime/doc/windows.txt	2007-05-12 10:18:49.000000000 +0000
+++ vim71/runtime/doc/windows.txt	2008-02-14 21:07:32.000000000 +0000
@@ -132,7 +132,8 @@
 		the same file.  Make new window N high (default is to use half
 		the height of the current window).  Reduces the current window
 		height to create room (and others, if the 'equalalways' option
-		is set and 'eadirection' isn't "hor").
+		is set, 'eadirection' isn't "hor", and one of them is higher
+		than the current or the new window).
 		Note: CTRL-S does not work on all terminals and might block
 		further input, use CTRL-Q to get going again.
 		Also see |++opt| and |+cmd|.
@@ -140,9 +141,13 @@
 CTRL-W CTRL-V						*CTRL-W_CTRL-V*
 CTRL-W v						*CTRL-W_v*
 :[N]vs[plit] [++opt] [+cmd] [file]			*:vs* *:vsplit*
-		Like |:split|, but split vertically.  If 'equalalways' is set
-		and 'eadirection' isn't "ver" the windows will be spread out
-		horizontally, unless a width was specified.
+		Like |:split|, but split vertically.  The windows will be
+		spread out horizontally if
+		1. a width was not specified,
+		2. 'equalalways' is set,
+		3. 'eadirection' isn't "ver", and
+		4. one of the other windows are wider than the current or new
+		   window.
 		Note: In other places CTRL-Q does the same as CTRL-V, but here
 		it doesn't!
 
diff -Naur vim71.orig/runtime/filetype.vim vim71/runtime/filetype.vim
--- vim71.orig/runtime/filetype.vim	2007-05-10 15:14:37.000000000 +0000
+++ vim71/runtime/filetype.vim	2008-02-14 21:07:31.000000000 +0000
@@ -1,7 +1,7 @@
 " Vim support file to detect file types
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2007 May 10
+" Last Change:	2007 May 15
 
 " Listen very carefully, I will say this only once
 if exists("did_load_filetypes")
@@ -1286,7 +1286,7 @@
 au BufNewFile,BufRead *.it,*.ih			setf ppwiz
 
 " Oracle Pro*C/C++
-au BufNewFile,BufRead .pc			setf proc
+au BufNewFile,BufRead *.pc			setf proc
 
 " Privoxy actions file
 au BufNewFile,BufRead *.action			setf privoxy
diff -Naur vim71.orig/runtime/menu.vim vim71/runtime/menu.vim
--- vim71.orig/runtime/menu.vim	2007-01-09 13:31:40.000000000 +0000
+++ vim71/runtime/menu.vim	2008-02-14 21:07:33.000000000 +0000
@@ -2,7 +2,7 @@
 " You can also use this as a start for your own set of menus.
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2007 Jan 09
+" Last Change:	2007 Nov 19
 
 " Note that ":an" (short for ":anoremenu") is often used to make a menu work
 " in all modes and avoid side effects from mappings defined by the user.
@@ -658,7 +658,6 @@
   let buf = 1
   while buf <= bufnr('$')
     if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf)
-					    \ && !getbufvar(buf, "&bufsecret")
       let s:bmenu_count = s:bmenu_count + 1
     endif
     let buf = buf + 1
@@ -671,7 +670,6 @@
   let buf = 1
   while buf <= bufnr('$')
     if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf)
-					    \ && !getbufvar(buf, "&bufsecret")
       call <SID>BMFilename(bufname(buf), buf)
     endif
     let buf = buf + 1
diff -Naur vim71.orig/runtime/plugin/matchparen.vim vim71/runtime/plugin/matchparen.vim
--- vim71.orig/runtime/plugin/matchparen.vim	2006-10-12 20:05:05.000000000 +0000
+++ vim71/runtime/plugin/matchparen.vim	2008-02-14 21:07:34.000000000 +0000
@@ -1,6 +1,6 @@
 " Vim plugin for showing matching parens
 " Maintainer:  Bram Moolenaar <Bram@vim.org>
-" Last Change: 2006 Oct 12
+" Last Change: 2008 Jan 06
 
 " Exit quickly when:
 " - this plugin was already loaded (or disabled)
@@ -13,7 +13,7 @@
 
 augroup matchparen
   " Replace all matchparen autocommands
-  autocmd! CursorMoved,CursorMovedI * call s:Highlight_Matching_Pair()
+  autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair()
 augroup END
 
 " Skip the rest if it was already done.
@@ -62,25 +62,37 @@
   " Figure out the arguments for searchpairpos().
   " Restrict the search to visible lines with "stopline".
   " And avoid searching very far (e.g., for closed folds and long lines)
+  " The "viewable" variables give a range in which we can scroll while keeping
+  " the cursor at the same position
+  " adjustedScrolloff accounts for very large numbers of scrolloff
+  let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2])
+  let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2])
+  let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2])
+  " one of these stoplines will be adjusted below, but the current values are
+  " minimal boundaries within the current window
+  let stoplinebottom = line('w$')
+  let stoplinetop = line('w0')
   if i % 2 == 0
     let s_flags = 'nW'
     let c2 = plist[i + 1]
     if has("byte_offset") && has("syntax_items") && &smc > 0
       let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2])
-      let stopline = min([line('w$'), byte2line(stopbyte)])
+      let stopline = min([bottom_viewable, byte2line(stopbyte)])
     else
-      let stopline = min([line('w$'), c_lnum + 100])
+      let stopline = min([bottom_viewable, c_lnum + 100])
     endif
+    let stoplinebottom = stopline
   else
     let s_flags = 'nbW'
     let c2 = c
     let c = plist[i - 1]
     if has("byte_offset") && has("syntax_items") && &smc > 0
       let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2])
-      let stopline = max([line('w0'), byte2line(stopbyte)])
+      let stopline = max([top_viewable, byte2line(stopbyte)])
     else
-      let stopline = max([line('w0'), c_lnum - 100])
+      let stopline = max([top_viewable, c_lnum - 100])
     endif
+    let stoplinetop = stopline
   endif
   if c == '['
     let c = '\['
@@ -99,14 +111,19 @@
 	\ '=~?  "string\\|character\\|singlequote\\|comment"'
   execute 'if' s_skip '| let s_skip = 0 | endif'
 
-  let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline)
+  try
+    " Limit the search time to 500 msec to avoid a hang on very long lines.
+    let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 500)
+  catch /E118/
+    let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline)
+  endtry
 
   if before > 0
     call winrestview(save_cursor)
   endif
 
   " If a match is found setup match highlighting.
-  if m_lnum > 0 && m_lnum >= line('w0') && m_lnum <= line('w$')
+  if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom 
     exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) .
 	  \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
     let w:paren_hl_on = 1
@@ -114,7 +131,8 @@
 endfunction
 
 " Define commands that will disable and enable the plugin.
-command! NoMatchParen 3match none | unlet! g:loaded_matchparen | au! matchparen
-command! DoMatchParen runtime plugin/matchparen.vim | doau CursorMoved
+command! NoMatchParen windo 3match none | unlet! g:loaded_matchparen |
+	  \ au! matchparen
+command! DoMatchParen runtime plugin/matchparen.vim | windo doau CursorMoved
 
 let &cpo = cpo_save
diff -Naur vim71.orig/src/Makefile vim71/src/Makefile
--- vim71.orig/src/Makefile	2007-05-12 11:57:13.000000000 +0000
+++ vim71/src/Makefile	2008-02-14 21:07:34.000000000 +0000
@@ -2559,8 +2559,11 @@
 #	-mkdir $(DESTDIR)$(prefix)/$(APPDIR)/bin
 	srcdir=`pwd`; $(MAKE) -f Makefile installruntime \
 		VIMEXE=$$srcdir/$(VIMTARGET) \
-		prefix=$(DESTDIR)$(prefix)/$(RESDIR)/vim \
-		VIMRTLOC=$(DESTDIR)$(prefix)/$(RESDIR)/vim/runtime
+		prefix=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR) \
+		exec_prefix=$(DESTDIR)$(prefix)/$(APPDIR)/Contents \
+		BINDIR=$(DESTDIR)$(prefix)/$(APPDIR)/Contents/MacOS \
+		VIMLOC=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR) \
+		VIMRTLOC=$(DESTDIR)$(prefix)/$(RESDIR)$(VIMDIR)/runtime
 # Put the link back.
 	ln -s `pwd`/../runtime $(RESDIR)/vim
 # Copy rgb.txt, Mac doesn't always have X11
diff -Naur vim71.orig/src/auto/configure vim71/src/auto/configure
--- vim71.orig/src/auto/configure	2007-05-12 11:49:09.000000000 +0000
+++ vim71/src/auto/configure	2008-02-14 21:07:34.000000000 +0000
@@ -3843,7 +3843,9 @@
   fi
 
   if test "X$vi_cv_path_mzscheme_pfx" != "X"; then
-    if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
+    if test "x$MACOSX" = "xyes"; then
+      MZSCHEME_LIBS="-framework PLT_MzScheme"
+    elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
       MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"
     else
       MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc"
@@ -4443,7 +4445,7 @@
   tclsh_name="$withval"; echo "$as_me:$LINENO: result: $tclsh_name" >&5
 echo "${ECHO_T}$tclsh_name" >&6
 else
-  tclsh_name="tclsh8.4"; echo "$as_me:$LINENO: result: no" >&5
+  tclsh_name="tclsh8.5"; echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6
 fi;
   # Extract the first word of "$tclsh_name", so it can be a program name with args.
@@ -4487,7 +4489,49 @@
 
 
 
-    if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then
+    if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.5"; then
+    tclsh_name="tclsh8.4"
+    # Extract the first word of "$tclsh_name", so it can be a program name with args.
+set dummy $tclsh_name; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_vi_cv_path_tcl+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $vi_cv_path_tcl in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_vi_cv_path_tcl="$vi_cv_path_tcl" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_vi_cv_path_tcl="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+vi_cv_path_tcl=$ac_cv_path_vi_cv_path_tcl
+
+if test -n "$vi_cv_path_tcl"; then
+  echo "$as_me:$LINENO: result: $vi_cv_path_tcl" >&5
+echo "${ECHO_T}$vi_cv_path_tcl" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  fi
+  if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then
     tclsh_name="tclsh8.2"
     # Extract the first word of "$tclsh_name", so it can be a program name with args.
 set dummy $tclsh_name; ac_word=$2
@@ -4647,6 +4691,7 @@
 echo $ECHO_N "checking for location of tclConfig.sh script... $ECHO_C" >&6
 	if test "x$MACOSX" != "xyes"; then
 	  tclcnf=`echo $tclinc | sed s/include/lib/g`
+	  tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
 	else
 	  	  tclcnf="/System/Library/Frameworks/Tcl.framework"
 	fi
@@ -4666,6 +4711,7 @@
 	  echo "$as_me:$LINENO: checking for Tcl library by myself" >&5
 echo $ECHO_N "checking for Tcl library by myself... $ECHO_C" >&6
 	  tcllib=`echo $tclinc | sed s/include/lib/g`
+	  tcllib="$tcllib `echo $tclinc | sed s/include/lib64/g`"
 	  for ext in .so .a ; do
 	    for ver in "" $tclver ; do
 	      for try in $tcllib ; do
@@ -10263,8 +10309,9 @@
 
 
 
+
 for ac_header in stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
-	termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \
+	termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \
 	iconv.h langinfo.h unistd.h stropts.h errno.h \
 	sys/resource.h sys/systeminfo.h locale.h \
 	sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
@@ -14212,7 +14259,7 @@
 echo "$as_me:$LINENO: checking how to run man with a section nr" >&5
 echo $ECHO_N "checking how to run man with a section nr... $ECHO_C" >&6
 MANDEF="man"
-(eval man -s 2 read) < /dev/null > /dev/null 2>&5 && MANDEF="man -s"
+(eval MANPAGER=cat PAGER=cat man -s 2 read) < /dev/null > /dev/null 2>&5 && MANDEF="man -s"
 echo "$as_me:$LINENO: result: $MANDEF" >&5
 echo "${ECHO_T}$MANDEF" >&6
 if test "$MANDEF" = "man -s"; then
diff -Naur vim71.orig/src/buffer.c vim71/src/buffer.c
--- vim71.orig/src/buffer.c	2007-05-10 15:25:59.000000000 +0000
+++ vim71/src/buffer.c	2008-02-14 21:07:33.000000000 +0000
@@ -171,6 +171,13 @@
 	    /* Put the cursor on the first line. */
 	    curwin->w_cursor.lnum = 1;
 	    curwin->w_cursor.col = 0;
+
+	    /* Set or reset 'modified' before executing autocommands, so that
+	     * it can be changed there. */
+	    if (!readonlymode && !bufempty())
+		changed();
+	    else if (retval != FAIL)
+		unchanged(curbuf, FALSE);
 #ifdef FEAT_AUTOCMD
 # ifdef FEAT_EVAL
 	    apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
@@ -194,16 +201,16 @@
     /* When reading stdin, the buffer contents always needs writing, so set
      * the changed flag.  Unless in readonly mode: "ls | gview -".
      * When interrupted and 'cpoptions' contains 'i' set changed flag. */
-    if ((read_stdin && !readonlymode && !bufempty())
+    if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
 #ifdef FEAT_AUTOCMD
 		|| modified_was_set	/* ":set modified" used in autocmd */
 # ifdef FEAT_EVAL
 		|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
 # endif
 #endif
-		|| (got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL))
+       )
 	changed();
-    else if (retval != FAIL)
+    else if (retval != FAIL && !read_stdin)
 	unchanged(curbuf, FALSE);
     save_file_ff(curbuf);		/* keep this fileformat */
 
@@ -495,6 +502,7 @@
     buf->b_start_eol = TRUE;
 #ifdef FEAT_MBYTE
     buf->b_p_bomb = FALSE;
+    buf->b_start_bomb = FALSE;
 #endif
     buf->b_ml.ml_mfp = NULL;
     buf->b_ml.ml_flags = ML_EMPTY;		/* empty buffer */
@@ -4167,29 +4175,35 @@
      * mess up the full path name, even though it starts with a '/'.
      * Also expand when there is ".." in the file name, try to remove it,
      * because "c:/src/../README" is equal to "c:/README".
+     * Similarly "c:/src//file" is equal to "c:/src/file".
      * For MS-Windows also expand names like "longna~1" to "longname".
      */
 #ifdef UNIX
     return FullName_save(fname, TRUE);
 #else
-    if (!vim_isAbsName(fname) || strstr((char *)fname, "..") != NULL
-#if defined(MSWIN) || defined(DJGPP)
+    if (!vim_isAbsName(fname)
+	    || strstr((char *)fname, "..") != NULL
+	    || strstr((char *)fname, "//") != NULL
+# ifdef BACKSLASH_IN_FILENAME
+	    || strstr((char *)fname, "\\\\") != NULL
+# endif
+# if defined(MSWIN) || defined(DJGPP)
 	    || vim_strchr(fname, '~') != NULL
-#endif
+# endif
 	    )
 	return FullName_save(fname, FALSE);
 
     fname = vim_strsave(fname);
 
-#ifdef USE_FNAME_CASE
-# ifdef USE_LONG_FNAME
+# ifdef USE_FNAME_CASE
+#  ifdef USE_LONG_FNAME
     if (USE_LONG_FNAME)
-# endif
+#  endif
     {
 	if (fname != NULL)
 	    fname_case(fname, 0);	/* set correct case for file name */
     }
-#endif
+# endif
 
     return fname;
 #endif
@@ -4253,12 +4267,12 @@
 do_arg_all(count, forceit, keep_tabs)
     int	count;
     int	forceit;		/* hide buffers in current windows */
-    int keep_tabs;		/* keep curren tabs, for ":tab drop file" */
+    int keep_tabs;		/* keep current tabs, for ":tab drop file" */
 {
     int		i;
     win_T	*wp, *wpnext;
     char_u	*opened;	/* array of flags for which args are open */
-    int		opened_len;	/* lenght of opened[] */
+    int		opened_len;	/* length of opened[] */
     int		use_firstwin = FALSE;	/* use first window for arglist */
     int		split_ret = OK;
     int		p_ea_save;
@@ -4853,7 +4867,7 @@
 	     */
 	    for (e = s; *e != ':' && *e != NUL; ++e)
 		if (e[0] == '\\' && e[1] == ':')
-		    STRCPY(e, e + 1);
+		    mch_memmove(e, e + 1, STRLEN(e));
 	    if (*e == NUL)
 		end = TRUE;
 
@@ -4938,10 +4952,7 @@
 	/* Expand "~/" in the file name at "line + 1" to a full path.
 	 * Then try shortening it by comparing with the current directory */
 	expand_env(xline, NameBuff, MAXPATHL);
-	mch_dirname(IObuff, IOSIZE);
-	sfname = shorten_fname(NameBuff, IObuff);
-	if (sfname == NULL)
-	    sfname = NameBuff;
+	sfname = shorten_fname1(NameBuff);
 
 	buf = buflist_new(NameBuff, sfname, (linenr_T)0, BLN_LISTED);
 	if (buf != NULL)	/* just in case... */
@@ -5507,11 +5518,11 @@
 
 #ifdef FEAT_AUTOCMD
     if (!aucmd)		    /* Don't trigger BufDelete autocommands here. */
-	++autocmd_block;
+	block_autocmds();
 #endif
     close_buffer(NULL, buf, DOBUF_WIPE);
 #ifdef FEAT_AUTOCMD
     if (!aucmd)
-	--autocmd_block;
+	unblock_autocmds();
 #endif
 }
diff -Naur vim71.orig/src/charset.c vim71/src/charset.c
--- vim71.orig/src/charset.c	2007-03-24 20:10:37.000000000 +0000
+++ vim71/src/charset.c	2008-02-14 21:07:32.000000000 +0000
@@ -207,7 +207,10 @@
 	    }
 	    while (c <= c2)
 	    {
-		if (!do_isalpha || isalpha(c)
+		/* Use the MB_ functions here, because isalpha() doesn't
+		 * work properly when 'encoding' is "latin1" and the locale is
+		 * "C".  */
+		if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c)
 #ifdef FEAT_FKMAP
 			|| (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
 #endif
@@ -929,6 +932,23 @@
 }
 
 /*
+ * return TRUE if 'c' is a valid file-name character or a wildcard character
+ * Assume characters above 0x100 are valid (multi-byte).
+ * Explicitly interpret ']' as a wildcard character as mch_has_wildcard("]")
+ * returns false.
+ */
+    int
+vim_isfilec_or_wc(c)
+    int c;
+{
+    char_u buf[2];
+
+    buf[0] = (char_u)c;
+    buf[1] = NUL;
+    return vim_isfilec(c) || c == ']' || mch_has_wildcard(buf);
+}
+
+/*
  * return TRUE if 'c' is a printable character
  * Assume characters above 0x100 are printable (multi-byte), except for
  * Unicode.
@@ -1898,7 +1918,7 @@
 {
     for ( ; *p; ++p)
 	if (rem_backslash(p))
-	    STRCPY(p, p + 1);
+	    mch_memmove(p, p + 1, STRLEN(p));
 }
 
 /*
diff -Naur vim71.orig/src/configure.in vim71/src/configure.in
--- vim71.orig/src/configure.in	2007-05-12 09:19:27.000000000 +0000
+++ vim71/src/configure.in	2008-02-14 21:07:34.000000000 +0000
@@ -423,7 +423,9 @@
   fi
 
   if test "X$vi_cv_path_mzscheme_pfx" != "X"; then
-    if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
+    if test "x$MACOSX" = "xyes"; then
+      MZSCHEME_LIBS="-framework PLT_MzScheme"
+    elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
       MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"
     else
       MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc"
@@ -757,15 +759,19 @@
 
 if test "$enable_tclinterp" = "yes"; then
 
-  dnl on FreeBSD tclsh is a silly script, look for tclsh8.[420]
+  dnl on FreeBSD tclsh is a silly script, look for tclsh8.[5420]
   AC_MSG_CHECKING(--with-tclsh argument)
   AC_ARG_WITH(tclsh, [  --with-tclsh=PATH       which tclsh to use (default: tclsh8.0)],
 	tclsh_name="$withval"; AC_MSG_RESULT($tclsh_name),
-	tclsh_name="tclsh8.4"; AC_MSG_RESULT(no))
+	tclsh_name="tclsh8.5"; AC_MSG_RESULT(no))
   AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
   AC_SUBST(vi_cv_path_tcl)
 
-  dnl when no specific version specified, also try 8.2 and 8.0
+  dnl when no specific version specified, also try 8.4, 8.2 and 8.0
+  if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.5"; then
+    tclsh_name="tclsh8.4"
+    AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
+  fi
   if test "X$vi_cv_path_tcl" = "X" -a $tclsh_name = "tclsh8.4"; then
     tclsh_name="tclsh8.2"
     AC_PATH_PROG(vi_cv_path_tcl, $tclsh_name)
@@ -808,6 +814,7 @@
 	AC_MSG_CHECKING(for location of tclConfig.sh script)
 	if test "x$MACOSX" != "xyes"; then
 	  tclcnf=`echo $tclinc | sed s/include/lib/g`
+	  tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
 	else
 	  dnl For Mac OS X 10.3, use the OS-provided framework location
 	  tclcnf="/System/Library/Frameworks/Tcl.framework"
@@ -828,6 +835,7 @@
 	  AC_MSG_RESULT(<not found>)
 	  AC_MSG_CHECKING(for Tcl library by myself)
 	  tcllib=`echo $tclinc | sed s/include/lib/g`
+	  tcllib="$tcllib `echo $tclinc | sed s/include/lib64/g`"
 	  for ext in .so .a ; do
 	    for ver in "" $tclver ; do
 	      for try in $tcllib ; do
@@ -2024,7 +2032,7 @@
 fi
 
 AC_CHECK_HEADERS(stdarg.h stdlib.h string.h sys/select.h sys/utsname.h \
-	termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h termio.h \
+	termcap.h fcntl.h sgtty.h sys/ioctl.h sys/time.h sys/types.h termio.h \
 	iconv.h langinfo.h unistd.h stropts.h errno.h \
 	sys/resource.h sys/systeminfo.h locale.h \
 	sys/stream.h sys/ptem.h termios.h libc.h sys/statfs.h \
@@ -2718,7 +2726,7 @@
 dnl Check how we can run man with a section number
 AC_MSG_CHECKING(how to run man with a section nr)
 MANDEF="man"
-(eval man -s 2 read) < /dev/null > /dev/null 2>&AC_FD_CC && MANDEF="man -s"
+(eval MANPAGER=cat PAGER=cat man -s 2 read) < /dev/null > /dev/null 2>&AC_FD_CC && MANDEF="man -s"
 AC_MSG_RESULT($MANDEF)
 if test "$MANDEF" = "man -s"; then
   AC_DEFINE(USEMAN_S)
diff -Naur vim71.orig/src/diff.c vim71/src/diff.c
--- vim71.orig/src/diff.c	2007-02-16 00:18:41.000000000 +0000
+++ vim71/src/diff.c	2008-02-14 21:07:34.000000000 +0000
@@ -791,6 +791,9 @@
     }
     mch_remove(tmp_orig);
 
+    /* force updating cursor position on screen */
+    curwin->w_valid_cursor.lnum = 0;
+
     diff_redraw(TRUE);
 
 theend:
@@ -840,11 +843,11 @@
 		    tmp_orig, tmp_new);
 	    append_redir(cmd, p_srr, tmp_diff);
 #ifdef FEAT_AUTOCMD
-	    ++autocmd_block;	/* Avoid ShellCmdPost stuff */
+	    block_autocmds();	/* Avoid ShellCmdPost stuff */
 #endif
 	    (void)call_shell(cmd, SHELL_FILTER|SHELL_SILENT|SHELL_DOOUT);
 #ifdef FEAT_AUTOCMD
-	    --autocmd_block;
+	    unblock_autocmds();
 #endif
 	    vim_free(cmd);
 	}
@@ -949,11 +952,11 @@
 # endif
 		eap->arg);
 #ifdef FEAT_AUTOCMD
-	++autocmd_block;	/* Avoid ShellCmdPost stuff */
+	block_autocmds();	/* Avoid ShellCmdPost stuff */
 #endif
 	(void)call_shell(buf, SHELL_FILTER | SHELL_COOKED);
 #ifdef FEAT_AUTOCMD
-	--autocmd_block;
+	unblock_autocmds();
 #endif
     }
 
@@ -1296,7 +1299,9 @@
 	    }
 	    else
 		/* second overlap of new block with existing block */
-		dp->df_count[idx_new] += count_new - count_orig;
+		dp->df_count[idx_new] += count_new - count_orig
+		    + dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]
+		    - (dp->df_lnum[idx_orig] + dp->df_count[idx_orig]);
 
 	    /* Adjust the size of the block to include all the lines to the
 	     * end of the existing block or the new diff, whatever ends last. */
@@ -1310,7 +1315,7 @@
 		    dp->df_count[idx_new] += -off;
 		off = 0;
 	    }
-	    for (i = idx_orig; i < idx_new + !notset; ++i)
+	    for (i = idx_orig; i < idx_new; ++i)
 		if (curtab->tp_diffbuf[i] != NULL)
 		    dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i]
 						       - dp->df_lnum[i] + off;
@@ -1625,14 +1630,16 @@
     win_T	*fromwin;
     win_T	*towin;
 {
-    buf_T	*buf = fromwin->w_buffer;
+    buf_T	*frombuf = fromwin->w_buffer;
     linenr_T	lnum = fromwin->w_topline;
-    int		idx;
+    int		fromidx;
+    int		toidx;
     diff_T	*dp;
+    int		max_count;
     int		i;
 
-    idx = diff_buf_idx(buf);
-    if (idx == DB_COUNT)
+    fromidx = diff_buf_idx(frombuf);
+    if (fromidx == DB_COUNT)
 	return;		/* safety check */
 
     if (curtab->tp_diff_invalid)
@@ -1642,42 +1649,72 @@
 
     /* search for a change that includes "lnum" in the list of diffblocks. */
     for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
-	if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
+	if (lnum <= dp->df_lnum[fromidx] + dp->df_count[fromidx])
 	    break;
     if (dp == NULL)
     {
 	/* After last change, compute topline relative to end of file; no
 	 * filler lines. */
 	towin->w_topline = towin->w_buffer->b_ml.ml_line_count
-					   - (buf->b_ml.ml_line_count - lnum);
+				       - (frombuf->b_ml.ml_line_count - lnum);
     }
     else
     {
 	/* Find index for "towin". */
-	i = diff_buf_idx(towin->w_buffer);
-	if (i == DB_COUNT)
+	toidx = diff_buf_idx(towin->w_buffer);
+	if (toidx == DB_COUNT)
 	    return;		/* safety check */
 
-	towin->w_topline = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
-	if (lnum >= dp->df_lnum[idx])
+	towin->w_topline = lnum + (dp->df_lnum[toidx] - dp->df_lnum[fromidx]);
+	if (lnum >= dp->df_lnum[fromidx])
 	{
-	    /* Inside a change: compute filler lines. */
-	    if (dp->df_count[i] == dp->df_count[idx])
+	    /* Inside a change: compute filler lines. With three or more
+	     * buffers we need to know the largest count. */
+	    max_count = 0;
+	    for (i = 0; i < DB_COUNT; ++i)
+		if (curtab->tp_diffbuf[i] != NULL
+					       && max_count < dp->df_count[i])
+		    max_count = dp->df_count[i];
+
+	    if (dp->df_count[toidx] == dp->df_count[fromidx])
+	    {
+		/* same number of lines: use same filler count */
 		towin->w_topfill = fromwin->w_topfill;
-	    else if (dp->df_count[i] > dp->df_count[idx])
+	    }
+	    else if (dp->df_count[toidx] > dp->df_count[fromidx])
 	    {
-		if (lnum == dp->df_lnum[idx] + dp->df_count[idx])
-		    towin->w_topline = dp->df_lnum[i] + dp->df_count[i]
-							 - fromwin->w_topfill;
+		if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
+		{
+		    /* more lines in towin and fromwin doesn't show diff
+		     * lines, only filler lines */
+		    if (max_count - fromwin->w_topfill >= dp->df_count[toidx])
+		    {
+			/* towin also only shows filler lines */
+			towin->w_topline = dp->df_lnum[toidx]
+						       + dp->df_count[toidx];
+			towin->w_topfill = fromwin->w_topfill;
+		    }
+		    else
+			/* towin still has some diff lines to show */
+			towin->w_topline = dp->df_lnum[toidx]
+					     + max_count - fromwin->w_topfill;
+		}
 	    }
-	    else
+	    else if (towin->w_topline >= dp->df_lnum[toidx]
+							+ dp->df_count[toidx])
 	    {
-		if (towin->w_topline >= dp->df_lnum[i] + dp->df_count[i])
+		/* less lines in towin and no diff lines to show: compute
+		 * filler lines */
+		towin->w_topline = dp->df_lnum[toidx] + dp->df_count[toidx];
+		if (diff_flags & DIFF_FILLER)
 		{
-		    if (diff_flags & DIFF_FILLER)
-			towin->w_topfill = dp->df_lnum[idx]
-						   + dp->df_count[idx] - lnum;
-		    towin->w_topline = dp->df_lnum[i] + dp->df_count[i];
+		    if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
+			/* fromwin is also out of diff lines */
+			towin->w_topfill = fromwin->w_topfill;
+		    else
+			/* fromwin has some diff lines */
+			towin->w_topfill = dp->df_lnum[fromidx]
+							   + max_count - lnum;
 		}
 	    }
 	}
diff -Naur vim71.orig/src/digraph.c vim71/src/digraph.c
--- vim71.orig/src/digraph.c	2006-05-02 18:24:04.000000000 +0000
+++ vim71/src/digraph.c	2008-02-14 21:07:34.000000000 +0000
@@ -1978,6 +1978,61 @@
 	{'f', 't', 0xfb05},
 	{'s', 't', 0xfb06},
 #      endif /* FEAT_MBYTE */
+
+	/* Vim 5.x compatible digraphs that don't conflict with the above */
+	{'~', '!', 161},	/* ¡ */
+	{'c', '|', 162},	/* ¢ */
+	{'$', '$', 163},	/* £ */
+	{'o', 'x', 164},	/* ¤ - currency symbol in ISO 8859-1 */
+	{'Y', '-', 165},	/* ¥ */
+	{'|', '|', 166},	/* ¦ */
+	{'c', 'O', 169},	/* © */
+	{'-', ',', 172},	/* ¬ */
+	{'-', '=', 175},	/* ¯ */
+	{'~', 'o', 176},	/* ° */
+	{'2', '2', 178},	/* ² */
+	{'3', '3', 179},	/* ³ */
+	{'p', 'p', 182},	/* ¶ */
+	{'~', '.', 183},	/* · */
+	{'1', '1', 185},	/* ¹ */
+	{'~', '?', 191},	/* ¿ */
+	{'A', '`', 192},	/* À */
+	{'A', '^', 194},	/* Â */
+	{'A', '~', 195},	/* Ã */
+	{'A', '"', 196},	/* Ä */
+	{'A', '@', 197},	/* Å */
+	{'E', '`', 200},	/* È */
+	{'E', '^', 202},	/* Ê */
+	{'E', '"', 203},	/* Ë */
+	{'I', '`', 204},	/* Ì */
+	{'I', '^', 206},	/* Î */
+	{'I', '"', 207},	/* Ï */
+	{'N', '~', 209},	/* Ñ */
+	{'O', '`', 210},	/* Ò */
+	{'O', '^', 212},	/* Ô */
+	{'O', '~', 213},	/* Õ */
+	{'/', '\\', 215},	/* × - multiplication symbol in ISO 8859-1 */
+	{'U', '`', 217},	/* Ù */
+	{'U', '^', 219},	/* Û */
+	{'I', 'p', 222},	/* Þ */
+	{'a', '`', 224},	/* à */
+	{'a', '^', 226},	/* â */
+	{'a', '~', 227},	/* ã */
+	{'a', '"', 228},	/* ä */
+	{'a', '@', 229},	/* å */
+	{'e', '`', 232},	/* è */
+	{'e', '^', 234},	/* ê */
+	{'e', '"', 235},	/* ë */
+	{'i', '`', 236},	/* ì */
+	{'i', '^', 238},	/* î */
+	{'n', '~', 241},	/* ñ */
+	{'o', '`', 242},	/* ò */
+	{'o', '^', 244},	/* ô */
+	{'o', '~', 245},	/* õ */
+	{'u', '`', 249},	/* ù */
+	{'u', '^', 251},	/* û */
+	{'y', '"', 255},	/* x XX */
+
 	{NUL, NUL, NUL}
        };
 
@@ -2028,7 +2083,7 @@
 
     ++no_mapping;
     ++allow_keys;
-    c = safe_vgetc();
+    c = plain_vgetc();
     --no_mapping;
     --allow_keys;
     if (c != ESC)		/* ESC cancels CTRL-K */
@@ -2050,7 +2105,7 @@
 #endif
 	++no_mapping;
 	++allow_keys;
-	cc = safe_vgetc();
+	cc = plain_vgetc();
 	--no_mapping;
 	--allow_keys;
 	if (cc != ESC)	    /* ESC cancels CTRL-K */
@@ -2349,8 +2404,10 @@
 
     if (*curbuf->b_p_keymap == NUL)
     {
-	/* Stop any active keymap and clear the table. */
+	/* Stop any active keymap and clear the table.  Also remove
+	 * b:keymap_name, as no keymap is active now. */
 	keymap_unload();
+	do_cmdline_cmd((char_u *)"unlet! b:keymap_name");
     }
     else
     {
@@ -2500,7 +2557,6 @@
 
     ga_clear(&curbuf->b_kmap_ga);
     curbuf->b_kmap_state &= ~KEYMAP_LOADED;
-    do_cmdline_cmd((char_u *)"unlet! b:keymap_name");
 #ifdef FEAT_WINDOWS
     status_redraw_curbuf();
 #endif
diff -Naur vim71.orig/src/edit.c vim71/src/edit.c
--- vim71.orig/src/edit.c	2007-05-07 19:43:55.000000000 +0000
+++ vim71/src/edit.c	2008-02-14 21:07:34.000000000 +0000
@@ -129,6 +129,7 @@
 
 static void ins_ctrl_x __ARGS((void));
 static int  has_compl_option __ARGS((int dict_opt));
+static int  ins_compl_accept_char __ARGS((int c));
 static int ins_compl_add __ARGS((char_u *str, int len, int icase, char_u *fname, char_u **cptext, int cdir, int flags, int adup));
 static int  ins_compl_equal __ARGS((compl_T *match, char_u *str, int len));
 static void ins_compl_longest_match __ARGS((compl_T *match));
@@ -549,7 +550,7 @@
 	i = showmode();
 
     if (!p_im && did_restart_edit == 0)
-	change_warning(i + 1);
+	change_warning(i == 0 ? 0 : i + 1);
 
 #ifdef CURSOR_SHAPE
     ui_cursor_shape();		/* may show different cursor shape */
@@ -702,10 +703,13 @@
 #endif
 
 	/*
-	 * Get a character for Insert mode.
+	 * Get a character for Insert mode.  Ignore K_IGNORE.
 	 */
 	lastc = c;			/* remember previous char for CTRL-D */
-	c = safe_vgetc();
+	do
+	{
+	    c = safe_vgetc();
+	} while (c == K_IGNORE);
 
 #ifdef FEAT_AUTOCMD
 	/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
@@ -754,8 +758,9 @@
 		    continue;
 		}
 
-		/* A printable, non-white character: Add to "compl_leader". */
-		if (vim_isprintc(c) && !vim_iswhite(c))
+		/* A non-white character that fits in with the current
+		 * completion: Add to "compl_leader". */
+		if (ins_compl_accept_char(c))
 		{
 		    ins_compl_addleader(c);
 		    continue;
@@ -775,7 +780,7 @@
 	/* Prepare for or stop CTRL-X mode.  This doesn't do completion, but
 	 * it does fix up the text when finishing completion. */
 	compl_get_longest = FALSE;
-	if (c != K_IGNORE && ins_compl_prep(c))
+	if (ins_compl_prep(c))
 	    continue;
 #endif
 
@@ -788,7 +793,7 @@
 	    ins_redraw(FALSE);
 	    ++no_mapping;
 	    ++allow_keys;
-	    c = safe_vgetc();
+	    c = plain_vgetc();
 	    --no_mapping;
 	    --allow_keys;
 	    if (c != Ctrl_N && c != Ctrl_G && c != Ctrl_O)
@@ -981,7 +986,7 @@
 #ifdef FEAT_NETBEANS_INTG
 	case K_F21:	/* NetBeans command */
 	    ++no_mapping;		/* don't map the next key hits */
-	    i = safe_vgetc();
+	    i = plain_vgetc();
 	    --no_mapping;
 	    netbeans_keycommand(i);
 	    break;
@@ -1453,6 +1458,14 @@
 # endif
 			     )
 	{
+# ifdef FEAT_SYN_HL
+	    /* Need to update the screen first, to make sure syntax
+	     * highlighting is correct after making a change (e.g., inserting
+	     * a "(".  The autocommand may also require a redraw, so it's done
+	     * again below, unfortunately. */
+	    if (syntax_present(curbuf) && must_redraw)
+		update_screen(0);
+# endif
 	    apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf);
 	    last_cursormoved = curwin->w_cursor;
 	}
@@ -1652,11 +1665,12 @@
  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
  */
     void
-change_indent(type, amount, round, replaced)
+change_indent(type, amount, round, replaced, call_changed_bytes)
     int		type;
     int		amount;
     int		round;
     int		replaced;	/* replaced character, put on replace stack */
+    int		call_changed_bytes;	/* call changed_bytes() */
 {
     int		vcol;
     int		last_vcol;
@@ -1713,7 +1727,7 @@
      * Set the new indent.  The cursor will be put on the first non-blank.
      */
     if (type == INDENT_SET)
-	(void)set_indent(amount, SIN_CHANGED);
+	(void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
     else
     {
 #ifdef FEAT_VREPLACE
@@ -1723,7 +1737,7 @@
 	if (State & VREPLACE_FLAG)
 	    State = INSERT;
 #endif
-	shift_line(type == INDENT_DEC, round, 1);
+	shift_line(type == INDENT_DEC, round, 1, call_changed_bytes);
 #ifdef FEAT_VREPLACE
 	State = save_State;
 #endif
@@ -2053,11 +2067,44 @@
 }
 
 /*
+ * Return TRUE when character "c" is part of the item currently being
+ * completed.  Used to decide whether to abandon complete mode when the menu
+ * is visible.
+ */
+    static int
+ins_compl_accept_char(c)
+    int c;
+{
+    if (ctrl_x_mode & CTRL_X_WANT_IDENT)
+	/* When expanding an identifier only accept identifier chars. */
+	return vim_isIDc(c);
+
+    switch (ctrl_x_mode)
+    {
+	case CTRL_X_FILES:
+	    /* When expanding file name only accept file name chars. But not
+	     * path separators, so that "proto/<Tab>" expands files in
+	     * "proto", not "proto/" as a whole */
+	    return vim_isfilec(c) && !vim_ispathsep(c);
+
+	case CTRL_X_CMDLINE:
+	case CTRL_X_OMNI:
+	    /* Command line and Omni completion can work with just about any
+	     * printable character, but do stop at white space. */
+	    return vim_isprintc(c) && !vim_iswhite(c);
+
+	case CTRL_X_WHOLE_LINE:
+	    /* For while line completion a space can be part of the line. */
+	    return vim_isprintc(c);
+    }
+    return vim_iswordc(c);
+}
+
+/*
  * This is like ins_compl_add(), but if 'ic' and 'inf' are set, then the
  * case of the originally typed text is used, and the case of the completed
  * text is inferred, ie this tries to work out what case you probably wanted
  * the rest of the word to be in -- webb
- * TODO: make this work for multi-byte characters.
  */
     int
 ins_compl_add_infercase(str, len, icase, fname, dir, flags)
@@ -2068,54 +2115,147 @@
     int		dir;
     int		flags;
 {
+    char_u	*p;
+    int		i, c;
+    int		actual_len;		/* Take multi-byte characters */
+    int		actual_compl_length;	/* into account. */
+    int		*wca;		        /* Wide character array. */
     int		has_lower = FALSE;
     int		was_letter = FALSE;
-    int		idx;
 
-    if (p_ic && curbuf->b_p_inf && len < IOSIZE)
+    if (p_ic && curbuf->b_p_inf && len > 0)
     {
-	/* Infer case of completed part -- webb */
-	/* Use IObuff, str would change text in buffer! */
-	vim_strncpy(IObuff, str, len);
+	/* Infer case of completed part. */
 
-	/* Rule 1: Were any chars converted to lower? */
-	for (idx = 0; idx < compl_length; ++idx)
+	/* Find actual length of completion. */
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
 	{
-	    if (islower(compl_orig_text[idx]))
+	    p = str;
+	    actual_len = 0;
+	    while (*p != NUL)
 	    {
-		has_lower = TRUE;
-		if (isupper(IObuff[idx]))
-		{
-		    /* Rule 1 is satisfied */
-		    for (idx = compl_length; idx < len; ++idx)
-			IObuff[idx] = TOLOWER_LOC(IObuff[idx]);
-		    break;
-		}
+		mb_ptr_adv(p);
+		++actual_len;
 	    }
 	}
+	else
+#endif
+	    actual_len = len;
 
-	/*
-	 * Rule 2: No lower case, 2nd consecutive letter converted to
-	 * upper case.
-	 */
-	if (!has_lower)
+	/* Find actual length of original text. */
+#ifdef FEAT_MBYTE
+	if (has_mbyte)
+	{
+	    p = compl_orig_text;
+	    actual_compl_length = 0;
+	    while (*p != NUL)
+	    {
+		mb_ptr_adv(p);
+		++actual_compl_length;
+	    }
+	}
+	else
+#endif
+	    actual_compl_length = compl_length;
+
+	/* Allocate wide character array for the completion and fill it. */
+	wca = (int *)alloc(actual_len * sizeof(int));
+	if (wca != NULL)
 	{
-	    for (idx = 0; idx < compl_length; ++idx)
+	    p = str;
+	    for (i = 0; i < actual_len; ++i)
+#ifdef FEAT_MBYTE
+		if (has_mbyte)
+		    wca[i] = mb_ptr2char_adv(&p);
+		else
+#endif
+		    wca[i] = *(p++);
+
+	    /* Rule 1: Were any chars converted to lower? */
+	    p = compl_orig_text;
+	    for (i = 0; i < actual_compl_length; ++i)
 	    {
-		if (was_letter && isupper(compl_orig_text[idx])
-						      && islower(IObuff[idx]))
+#ifdef FEAT_MBYTE
+		if (has_mbyte)
+		    c = mb_ptr2char_adv(&p);
+		else
+#endif
+		    c = *(p++);
+		if (MB_ISLOWER(c))
 		{
-		    /* Rule 2 is satisfied */
-		    for (idx = compl_length; idx < len; ++idx)
-			IObuff[idx] = TOUPPER_LOC(IObuff[idx]);
-		    break;
+		    has_lower = TRUE;
+		    if (MB_ISUPPER(wca[i]))
+		    {
+			/* Rule 1 is satisfied. */
+			for (i = actual_compl_length; i < actual_len; ++i)
+			    wca[i] = MB_TOLOWER(wca[i]);
+			break;
+		    }
+		}
+	    }
+
+	    /*
+	     * Rule 2: No lower case, 2nd consecutive letter converted to
+	     * upper case.
+	     */
+	    if (!has_lower)
+	    {
+		p = compl_orig_text;
+		for (i = 0; i < actual_compl_length; ++i)
+		{
+#ifdef FEAT_MBYTE
+		    if (has_mbyte)
+			c = mb_ptr2char_adv(&p);
+		    else
+#endif
+			c = *(p++);
+		    if (was_letter && MB_ISUPPER(c) && MB_ISLOWER(wca[i]))
+		    {
+			/* Rule 2 is satisfied. */
+			for (i = actual_compl_length; i < actual_len; ++i)
+			    wca[i] = MB_TOUPPER(wca[i]);
+			break;
+		    }
+		    was_letter = MB_ISLOWER(c) || MB_ISUPPER(c);
 		}
-		was_letter = isalpha(compl_orig_text[idx]);
 	    }
-	}
 
-	/* Copy the original case of the part we typed */
-	STRNCPY(IObuff, compl_orig_text, compl_length);
+	    /* Copy the original case of the part we typed. */
+	    p = compl_orig_text;
+	    for (i = 0; i < actual_compl_length; ++i)
+	    {
+#ifdef FEAT_MBYTE
+		if (has_mbyte)
+		    c = mb_ptr2char_adv(&p);
+		else
+#endif
+		    c = *(p++);
+		if (MB_ISLOWER(c))
+		    wca[i] = MB_TOLOWER(wca[i]);
+		else if (MB_ISUPPER(c))
+		    wca[i] = MB_TOUPPER(wca[i]);
+	    }
+
+	    /*
+	     * Generate encoding specific output from wide character array.
+	     * Multi-byte characters can occupy up to five bytes more than
+	     * ASCII characters, and we also need one byte for NUL, so stay
+	     * six bytes away from the edge of IObuff.
+	     */
+	    p = IObuff;
+	    i = 0;
+	    while (i < actual_len && (p - IObuff + 6) < IOSIZE)
+#ifdef FEAT_MBYTE
+		if (has_mbyte)
+		    p += (*mb_char2bytes)(wca[i++], p);
+		else
+#endif
+		    *(p++) = wca[i++];
+	    *p = NUL;
+
+	    vim_free(wca);
+	}
 
 	return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
 								flags, FALSE);
@@ -2842,6 +2982,7 @@
 			/*
 			 * Add the other matches on the line
 			 */
+			ptr = buf;
 			while (!got_int)
 			{
 			    /* Find start of the next word.  Skip white
@@ -2851,7 +2992,7 @@
 				break;
 			    wstart = ptr;
 
-			    /* Find end of the word and add it. */
+			    /* Find end of the word. */
 #ifdef FEAT_MBYTE
 			    if (has_mbyte)
 				/* Japanese words may have characters in
@@ -2868,9 +3009,12 @@
 			    else
 #endif
 				ptr = find_word_end(ptr);
-			    add_r = ins_compl_add_infercase(wstart,
-				    (int)(ptr - wstart),
-				    p_ic, files[i], *dir, 0);
+
+			    /* Add the word. Skip the regexp match. */
+			    if (wstart != regmatch->startp[0])
+				add_r = ins_compl_add_infercase(wstart,
+					(int)(ptr - wstart),
+					p_ic, files[i], *dir, 0);
 			}
 		    }
 		    if (add_r == OK)
@@ -3032,8 +3176,11 @@
     p = line + curwin->w_cursor.col;
     mb_ptr_back(line, p);
 
-    /* Stop completion when the whole word was deleted. */
-    if ((int)(p - line) - (int)compl_col <= 0)
+    /* Stop completion when the whole word was deleted.  For Omni completion
+     * allow the word to be deleted, we won't match everything. */
+    if ((int)(p - line) - (int)compl_col < 0
+	    || ((int)(p - line) - (int)compl_col == 0
+		&& (ctrl_x_mode & CTRL_X_OMNI) == 0))
 	return K_BS;
 
     /* Deleted more than what was used to find matches or didn't finish
@@ -3250,8 +3397,8 @@
     if (c != Ctrl_R && vim_is_ctrl_x_key(c))
 	edit_submode_extra = NULL;
 
-    /* Ignore end of Select mode mapping */
-    if (c == K_SELECT)
+    /* Ignore end of Select mode mapping and mouse scroll buttons. */
+    if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP)
 	return retval;
 
     /* Set "compl_get_longest" when finding the first matches. */
@@ -3927,7 +4074,7 @@
 		    found_new_match = searchit(NULL, ins_buf, pos,
 							      compl_direction,
 				 compl_pattern, 1L, SEARCH_KEEP + SEARCH_NFMSG,
-							RE_LAST, (linenr_T)0);
+						  RE_LAST, (linenr_T)0, NULL);
 		--msg_silent;
 		if (!compl_started)
 		{
@@ -4372,15 +4519,17 @@
 	else
 	{
 	    /* Need to get the character to have KeyTyped set.  We'll put it
-	     * back with vungetc() below. */
+	     * back with vungetc() below.  But skip K_IGNORE. */
 	    c = safe_vgetc();
+	    if (c != K_IGNORE)
+	    {
+		/* Don't interrupt completion when the character wasn't typed,
+		 * e.g., when doing @q to replay keys. */
+		if (c != Ctrl_R && KeyTyped)
+		    compl_interrupted = TRUE;
 
-	    /* Don't interrupt completion when the character wasn't typed,
-	     * e.g., when doing @q to replay keys. */
-	    if (c != Ctrl_R && KeyTyped)
-		compl_interrupted = TRUE;
-
-	    vungetc(c);
+		vungetc(c);
+	    }
 	}
     }
     if (compl_pending != 0 && !got_int)
@@ -4495,14 +4644,13 @@
 	curs_col = curwin->w_cursor.col;
 	compl_pending = 0;
 
-	/* if this same ctrl_x_mode has been interrupted use the text from
+	/* If this same ctrl_x_mode has been interrupted use the text from
 	 * "compl_startpos" to the cursor as a pattern to add a new word
 	 * instead of expand the one before the cursor, in word-wise if
-	 * "compl_startpos"
-	 * is not in the same line as the cursor then fix it (the line has
-	 * been split because it was longer than 'tw').  if SOL is set then
-	 * skip the previous pattern, a word at the beginning of the line has
-	 * been inserted, we'll look for that  -- Acevedo. */
+	 * "compl_startpos" is not in the same line as the cursor then fix it
+	 * (the line has been split because it was longer than 'tw').  if SOL
+	 * is set then skip the previous pattern, a word at the beginning of
+	 * the line has been inserted, we'll look for that  -- Acevedo. */
 	if ((compl_cont_status & CONT_INTRPT) == CONT_INTRPT
 					    && compl_cont_mode == ctrl_x_mode)
 	{
@@ -5128,10 +5276,7 @@
     i = 0;
     for (;;)
     {
-	do
-	    nc = safe_vgetc();
-	while (nc == K_IGNORE || nc == K_VER_SCROLLBAR
-						    || nc == K_HOR_SCROLLBAR);
+	nc = plain_vgetc();
 #ifdef FEAT_CMDL_INFO
 	if (!(State & CMDLINE)
 # ifdef FEAT_MBYTE
@@ -5782,7 +5927,7 @@
 	    {
 #ifdef FEAT_VREPLACE
 		if (State & VREPLACE_FLAG)
-		    change_indent(INDENT_SET, second_indent, FALSE, NUL);
+		    change_indent(INDENT_SET, second_indent, FALSE, NUL, TRUE);
 		else
 #endif
 		    (void)set_indent(second_indent, SIN_CHANGED);
@@ -6313,8 +6458,10 @@
 {
     vim_free(last_insert);
     last_insert = NULL;
+# ifdef FEAT_INS_EXPAND
     vim_free(compl_orig_text);
     compl_orig_text = NULL;
+# endif
 }
 #endif
 
@@ -6806,6 +6953,25 @@
     ++replace_stack_nr;
 }
 
+#if defined(FEAT_MBYTE) || defined(PROTO)
+/*
+ * Push a character onto the replace stack.  Handles a multi-byte character in
+ * reverse byte order, so that the first byte is popped off first.
+ * Return the number of bytes done (includes composing characters).
+ */
+    int
+replace_push_mb(p)
+    char_u *p;
+{
+    int l = (*mb_ptr2len)(p);
+    int j;
+
+    for (j = l - 1; j >= 0; --j)
+	replace_push(p[j]);
+    return l;
+}
+#endif
+
 #if 0
 /*
  * call replace_push(c) with replace_offset set to the first NUL.
@@ -7067,7 +7233,7 @@
 fixthisline(get_the_indent)
     int (*get_the_indent) __ARGS((void));
 {
-    change_indent(INDENT_SET, get_the_indent(), FALSE, 0);
+    change_indent(INDENT_SET, get_the_indent(), FALSE, 0, TRUE);
     if (linewhite(curwin->w_cursor.lnum))
 	did_ai = TRUE;	    /* delete the indent if the line stays empty */
 }
@@ -7215,6 +7381,8 @@
 		p = ml_get_curline();
 		if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30))
 		    return TRUE;
+		/* Need to get the line again after cin_islabel(). */
+		p = ml_get_curline();
 		if (curwin->w_cursor.col > 2
 			&& p[curwin->w_cursor.col - 1] == ':'
 			&& p[curwin->w_cursor.col - 2] == ':')
@@ -7477,7 +7645,7 @@
      * deleted when ESC is hit.
      */
     ++no_mapping;
-    regname = safe_vgetc();
+    regname = plain_vgetc();
 #ifdef FEAT_LANGMAP
     LANGMAP_ADJUST(regname, TRUE);
 #endif
@@ -7488,7 +7656,7 @@
 #ifdef FEAT_CMDL_INFO
 	add_to_showcmd_c(literally);
 #endif
-	regname = safe_vgetc();
+	regname = plain_vgetc();
 #ifdef FEAT_LANGMAP
 	LANGMAP_ADJUST(regname, TRUE);
 #endif
@@ -7579,7 +7747,7 @@
      * deleted when ESC is hit.
      */
     ++no_mapping;
-    c = safe_vgetc();
+    c = plain_vgetc();
     --no_mapping;
     switch (c)
     {
@@ -7998,7 +8166,8 @@
     /*
      * 0^D and ^^D: remove all indent.
      */
-    if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
+    if (c == Ctrl_D && (lastc == '0' || lastc == '^')
+						  && curwin->w_cursor.col > 0)
     {
 	--curwin->w_cursor.col;
 	(void)del_char(FALSE);		/* delete the '^' or '0' */
@@ -8007,10 +8176,10 @@
 	    replace_pop_ins();
 	if (lastc == '^')
 	    old_indent = get_indent();	/* remember curr. indent */
-	change_indent(INDENT_SET, 0, TRUE, 0);
+	change_indent(INDENT_SET, 0, TRUE, 0, TRUE);
     }
     else
-	change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0);
+	change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0, TRUE);
 
     if (did_ai && *skipwhite(ml_get_curline()) != NUL)
 	did_ai = FALSE;
@@ -8053,6 +8222,29 @@
     AppendCharToRedobuff(K_DEL);
 }
 
+static void ins_bs_one __ARGS((colnr_T *vcolp));
+
+/*
+ * Delete one character for ins_bs().
+ */
+    static void
+ins_bs_one(vcolp)
+    colnr_T	*vcolp;
+{
+    dec_cursor();
+    getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
+    if (State & REPLACE_FLAG)
+    {
+	/* Don't delete characters before the insert point when in
+	 * Replace mode */
+	if (curwin->w_cursor.lnum != Insstart.lnum
+		|| curwin->w_cursor.col >= Insstart.col)
+	    replace_do_bs();
+    }
+    else
+	(void)del_char(FALSE);
+}
+
 /*
  * Handle Backspace, delete-word and delete-line in Insert mode.
  * Return TRUE when backspace was actually used.
@@ -8274,6 +8466,7 @@
 	if (	   mode == BACKSPACE_CHAR
 		&& ((p_sta && in_indent)
 		    || (curbuf->b_p_sts != 0
+			&& curwin->w_cursor.col > 0
 			&& (*(ml_get_cursor() - 1) == TAB
 			    || (*(ml_get_cursor() - 1) == ' '
 				&& (!*inserted_space_p
@@ -8282,9 +8475,7 @@
 	    int		ts;
 	    colnr_T	vcol;
 	    colnr_T	want_vcol;
-#if 0
-	    int		extra = 0;
-#endif
+	    colnr_T	start_vcol;
 
 	    *inserted_space_p = FALSE;
 	    if (p_sta && in_indent)
@@ -8295,6 +8486,7 @@
 	     * 'showbreak' may get in the way, need to get the last column of
 	     * the previous character. */
 	    getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
+	    start_vcol = vcol;
 	    dec_cursor();
 	    getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
 	    inc_cursor();
@@ -8303,30 +8495,7 @@
 	    /* delete characters until we are at or before want_vcol */
 	    while (vcol > want_vcol
 		    && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
-	    {
-		dec_cursor();
-		getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
-		if (State & REPLACE_FLAG)
-		{
-		    /* Don't delete characters before the insert point when in
-		     * Replace mode */
-		    if (curwin->w_cursor.lnum != Insstart.lnum
-			    || curwin->w_cursor.col >= Insstart.col)
-		    {
-#if 0	/* what was this for?  It causes problems when sw != ts. */
-			if (State == REPLACE && (int)vcol < want_vcol)
-			{
-			    (void)del_char(FALSE);
-			    extra = 2;	/* don't pop too much */
-			}
-			else
-#endif
-			    replace_do_bs();
-		    }
-		}
-		else
-		    (void)del_char(FALSE);
-	    }
+		ins_bs_one(&vcol);
 
 	    /* insert extra spaces until we are at want_vcol */
 	    while (vcol < want_vcol)
@@ -8343,22 +8512,16 @@
 #endif
 		{
 		    ins_str((char_u *)" ");
-		    if ((State & REPLACE_FLAG) /* && extra <= 1 */)
-		    {
-#if 0
-			if (extra)
-			    replace_push_off(NUL);
-			else
-#endif
-			    replace_push(NUL);
-		    }
-#if 0
-		    if (extra == 2)
-			extra = 1;
-#endif
+		    if ((State & REPLACE_FLAG))
+			replace_push(NUL);
 		}
 		getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
 	    }
+
+	    /* If we are now back where we started delete one character.  Can
+	     * happen when using 'sts' and 'linebreak'. */
+	    if (vcol >= start_vcol)
+		ins_bs_one(&vcol);
 	}
 
 	/*
@@ -8461,6 +8624,14 @@
     if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == 0)
 	dollar_vcol = curwin->w_virtcol;
 
+#ifdef FEAT_FOLDING
+    /* When deleting a char the cursor line must never be in a closed fold.
+     * E.g., when 'foldmethod' is indent and deleting the first non-white
+     * char before a Tab. */
+    if (did_backspace)
+	foldOpenCursor();
+#endif
+
     return did_backspace;
 }
 
@@ -8518,15 +8689,16 @@
     int		up;
 {
     pos_T	tpos;
-# if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
-    win_T	*old_curwin;
+# if defined(FEAT_WINDOWS)
+    win_T	*old_curwin = curwin;
+# endif
+# ifdef FEAT_INS_EXPAND
+    int		did_scroll = FALSE;
 # endif
 
     tpos = curwin->w_cursor;
 
 # if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
-    old_curwin = curwin;
-
     /* Currently the mouse coordinates are only known in the GUI. */
     if (gui.in_use && mouse_row >= 0 && mouse_col >= 0)
     {
@@ -8543,10 +8715,23 @@
 # endif
 	undisplay_dollar();
 
-    if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
-	scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
-    else
-	scroll_redraw(up, 3L);
+# ifdef FEAT_INS_EXPAND
+    /* Don't scroll the window in which completion is being done. */
+    if (!pum_visible()
+#  if defined(FEAT_WINDOWS)
+	    || curwin != old_curwin
+#  endif
+	    )
+# endif
+    {
+	if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
+	    scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
+	else
+	    scroll_redraw(up, 3L);
+# ifdef FEAT_INS_EXPAND
+	did_scroll = TRUE;
+# endif
+    }
 
 # if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
     curwin->w_redr_status = TRUE;
@@ -8555,6 +8740,17 @@
     curbuf = curwin->w_buffer;
 # endif
 
+# ifdef FEAT_INS_EXPAND
+    /* The popup menu may overlay the window, need to redraw it.
+     * TODO: Would be more efficient to only redraw the windows that are
+     * overlapped by the popup menu. */
+    if (pum_visible() && did_scroll)
+    {
+	redraw_all_later(NOT_VALID);
+	ins_compl_show_pum();
+    }
+# endif
+
     if (!equalpos(curwin->w_cursor, tpos))
     {
 	start_arrow(&tpos);
@@ -9257,7 +9453,7 @@
      * mode message to be deleted when ESC is hit */
     ++no_mapping;
     ++allow_keys;
-    c = safe_vgetc();
+    c = plain_vgetc();
     --no_mapping;
     --allow_keys;
     if (IS_SPECIAL(c) || mod_mask)	    /* special key */
@@ -9289,7 +9485,7 @@
 	}
 	++no_mapping;
 	++allow_keys;
-	cc = safe_vgetc();
+	cc = plain_vgetc();
 	--no_mapping;
 	--allow_keys;
 	if (cc != ESC)
@@ -9443,7 +9639,7 @@
 	    curwin->w_cursor = old_pos;
 #ifdef FEAT_VREPLACE
 	    if (State & VREPLACE_FLAG)
-		change_indent(INDENT_SET, i, FALSE, NUL);
+		change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
 	    else
 #endif
 		(void)set_indent(i, SIN_CHANGED);
@@ -9472,7 +9668,7 @@
 		curwin->w_cursor = old_pos;
 	    }
 	    if (temp)
-		shift_line(TRUE, FALSE, 1);
+		shift_line(TRUE, FALSE, 1, TRUE);
 	}
     }
 
diff -Naur vim71.orig/src/eval.c vim71/src/eval.c
--- vim71.orig/src/eval.c	2007-05-07 19:47:32.000000000 +0000
+++ vim71/src/eval.c	2008-02-14 21:07:34.000000000 +0000
@@ -345,6 +345,7 @@
     {VV_NAME("mouse_win",	 VAR_NUMBER), 0},
     {VV_NAME("mouse_lnum",	 VAR_NUMBER), 0},
     {VV_NAME("mouse_col",	 VAR_NUMBER), 0},
+    {VV_NAME("operator",	 VAR_STRING), VV_RO},
 };
 
 /* shorthand */
@@ -369,17 +370,17 @@
 static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
 static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
 static char_u *skip_var_one __ARGS((char_u *arg));
-static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
-static void list_glob_vars __ARGS((void));
-static void list_buf_vars __ARGS((void));
-static void list_win_vars __ARGS((void));
+static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty, int *first));
+static void list_glob_vars __ARGS((int *first));
+static void list_buf_vars __ARGS((int *first));
+static void list_win_vars __ARGS((int *first));
 #ifdef FEAT_WINDOWS
-static void list_tab_vars __ARGS((void));
+static void list_tab_vars __ARGS((int *first));
 #endif
-static void list_vim_vars __ARGS((void));
-static void list_script_vars __ARGS((void));
-static void list_func_vars __ARGS((void));
-static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
+static void list_vim_vars __ARGS((int *first));
+static void list_script_vars __ARGS((int *first));
+static void list_func_vars __ARGS((int *first));
+static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg, int *first));
 static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
 static int check_changedtick __ARGS((char_u *arg));
 static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));
@@ -475,6 +476,7 @@
 static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
 #if defined(FEAT_INS_EXPAND)
 static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));
@@ -529,6 +531,7 @@
 static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
@@ -577,7 +580,9 @@
 static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_matchadd __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matcharg __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_matchdelete __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
@@ -618,6 +623,7 @@
 static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setloclist __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_setmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
@@ -645,6 +651,7 @@
 static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
@@ -672,7 +679,7 @@
 static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
 
 static int list2fpos __ARGS((typval_T *arg, pos_T *posp, int *fnump));
-static pos_T *var2fpos __ARGS((typval_T *varp, int lnum, int *fnum));
+static pos_T *var2fpos __ARGS((typval_T *varp, int dollar_lnum, int *fnum));
 static int get_env_len __ARGS((char_u **arg));
 static int get_id_len __ARGS((char_u **arg));
 static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
@@ -699,8 +706,8 @@
 static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
 static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
 static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
-static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
-static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
+static void list_one_var __ARGS((dictitem_T *v, char_u *prefix, int *first));
+static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string, int *first));
 static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
 static int var_check_ro __ARGS((int flags, char_u *name));
 static int var_check_fixed __ARGS((int flags, char_u *name));
@@ -992,20 +999,20 @@
     char_u	*value;
     int		value_len;
 {
-    size_t	len;
+    int		len;
 
     if (redir_lval == NULL)
 	return;
 
     if (value_len == -1)
-	len = STRLEN(value);	/* Append the entire string */
+	len = (int)STRLEN(value);	/* Append the entire string */
     else
-	len = value_len;	/* Append only "value_len" characters */
+	len = value_len;		/* Append only "value_len" characters */
 
-    if (ga_grow(&redir_ga, (int)len) == OK)
+    if (ga_grow(&redir_ga, len) == OK)
     {
 	mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len);
-	redir_ga.ga_len += (int)len;
+	redir_ga.ga_len += len;
     }
     else
 	var_redir_stop();
@@ -1313,7 +1320,6 @@
 {
     hashitem_T	*hi;
 
-    clear_tv(&vimvars[idx].vv_tv);
     vimvars[idx].vv_tv = *save_tv;
     if (vimvars[idx].vv_type == VAR_UNKNOWN)
     {
@@ -1357,7 +1363,6 @@
 
     if (p_verbose == 0)
 	--emsg_off;
-    vimvars[VV_VAL].vv_str = NULL;
     restore_vimvar(VV_VAL, &save_val);
 
     return list;
@@ -1411,7 +1416,8 @@
 }
 
 
-#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
+#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
+	|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
 /*
  * Call some vimL function and return the result in "*rettv".
  * Uses argv[argc] for the function arguments.
@@ -1484,6 +1490,7 @@
     return ret;
 }
 
+# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
 /*
  * Call vimL function "func" and return the result as a string.
  * Returns NULL when calling the function fails.
@@ -1506,8 +1513,9 @@
     clear_tv(&rettv);
     return retval;
 }
+# endif
 
-#if defined(FEAT_COMPL_FUNC) || defined(PROTO)
+# if defined(FEAT_COMPL_FUNC) || defined(PROTO)
 /*
  * Call vimL function "func" and return the result as a number.
  * Returns -1 when calling the function fails.
@@ -1530,7 +1538,7 @@
     clear_tv(&rettv);
     return retval;
 }
-#endif
+# endif
 
 /*
  * Call vimL function "func" and return the result as a list
@@ -1556,9 +1564,9 @@
 
     return rettv.vval.v_list;
 }
-
 #endif
 
+
 /*
  * Save the current function call pointer, and set it to NULL.
  * Used when executing autocommands and for ":source".
@@ -1691,6 +1699,7 @@
     int		semicolon = 0;
     char_u	op[2];
     char_u	*argend;
+    int		first = TRUE;
 
     argend = skip_var_list(arg, &var_count, &semicolon);
     if (argend == NULL)
@@ -1707,19 +1716,19 @@
 	    EMSG(_(e_invarg));
 	else if (!ends_excmd(*arg))
 	    /* ":let var1 var2" */
-	    arg = list_arg_vars(eap, arg);
+	    arg = list_arg_vars(eap, arg, &first);
 	else if (!eap->skip)
 	{
 	    /* ":let" */
-	    list_glob_vars();
-	    list_buf_vars();
-	    list_win_vars();
+	    list_glob_vars(&first);
+	    list_buf_vars(&first);
+	    list_win_vars(&first);
 #ifdef FEAT_WINDOWS
-	    list_tab_vars();
+	    list_tab_vars(&first);
 #endif
-	    list_script_vars();
-	    list_func_vars();
-	    list_vim_vars();
+	    list_script_vars(&first);
+	    list_func_vars(&first);
+	    list_vim_vars(&first);
 	}
 	eap->nextcmd = check_nextcmd(arg);
     }
@@ -1924,10 +1933,11 @@
  * If "empty" is TRUE also list NULL strings as empty strings.
  */
     static void
-list_hashtable_vars(ht, prefix, empty)
+list_hashtable_vars(ht, prefix, empty, first)
     hashtab_T	*ht;
     char_u	*prefix;
     int		empty;
+    int		*first;
 {
     hashitem_T	*hi;
     dictitem_T	*di;
@@ -1942,7 +1952,7 @@
 	    di = HI2DI(hi);
 	    if (empty || di->di_tv.v_type != VAR_STRING
 					   || di->di_tv.vval.v_string != NULL)
-		list_one_var(di, prefix);
+		list_one_var(di, prefix, first);
 	}
     }
 }
@@ -1951,32 +1961,38 @@
  * List global variables.
  */
     static void
-list_glob_vars()
+list_glob_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
+    list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
 }
 
 /*
  * List buffer variables.
  */
     static void
-list_buf_vars()
+list_buf_vars(first)
+    int *first;
 {
     char_u	numbuf[NUMBUFLEN];
 
-    list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
+    list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:",
+								 TRUE, first);
 
     sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
-    list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
+    list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
+							       numbuf, first);
 }
 
 /*
  * List window variables.
  */
     static void
-list_win_vars()
+list_win_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
+    list_hashtable_vars(&curwin->w_vars.dv_hashtab,
+						 (char_u *)"w:", TRUE, first);
 }
 
 #ifdef FEAT_WINDOWS
@@ -1984,9 +2000,11 @@
  * List tab page variables.
  */
     static void
-list_tab_vars()
+list_tab_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&curtab->tp_vars.dv_hashtab, (char_u *)"t:", TRUE);
+    list_hashtable_vars(&curtab->tp_vars.dv_hashtab,
+						 (char_u *)"t:", TRUE, first);
 }
 #endif
 
@@ -1994,39 +2012,44 @@
  * List Vim variables.
  */
     static void
-list_vim_vars()
+list_vim_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
+    list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
 }
 
 /*
  * List script-local variables, if there is a script.
  */
     static void
-list_script_vars()
+list_script_vars(first)
+    int *first;
 {
     if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
-	list_hashtable_vars(&SCRIPT_VARS(current_SID), (char_u *)"s:", FALSE);
+	list_hashtable_vars(&SCRIPT_VARS(current_SID),
+						(char_u *)"s:", FALSE, first);
 }
 
 /*
  * List function variables, if there is a function.
  */
     static void
-list_func_vars()
+list_func_vars(first)
+    int *first;
 {
     if (current_funccal != NULL)
 	list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
-						       (char_u *)"l:", FALSE);
+						(char_u *)"l:", FALSE, first);
 }
 
 /*
  * List variables in "arg".
  */
     static char_u *
-list_arg_vars(eap, arg)
+list_arg_vars(eap, arg, first)
     exarg_T	*eap;
     char_u	*arg;
+    int		*first;
 {
     int		error = FALSE;
     int		len;
@@ -2083,15 +2106,15 @@
 			{
 			    switch (*name)
 			    {
-				case 'g': list_glob_vars(); break;
-				case 'b': list_buf_vars(); break;
-				case 'w': list_win_vars(); break;
+				case 'g': list_glob_vars(first); break;
+				case 'b': list_buf_vars(first); break;
+				case 'w': list_win_vars(first); break;
 #ifdef FEAT_WINDOWS
-				case 't': list_tab_vars(); break;
+				case 't': list_tab_vars(first); break;
 #endif
-				case 'v': list_vim_vars(); break;
-				case 's': list_script_vars(); break;
-				case 'l': list_func_vars(); break;
+				case 'v': list_vim_vars(first); break;
+				case 's': list_script_vars(first); break;
+				case 'l': list_func_vars(first); break;
 				default:
 					  EMSG2(_("E738: Can't list variables for %s"), name);
 			    }
@@ -2108,7 +2131,9 @@
 			    *arg = NUL;
 			    list_one_var_a((char_u *)"",
 				    arg == arg_subsc ? name : name_start,
-				    tv.v_type, s == NULL ? (char_u *)"" : s);
+				    tv.v_type,
+				    s == NULL ? (char_u *)"" : s,
+				    first);
 			    *arg = c;
 			    vim_free(tf);
 			}
@@ -3383,6 +3408,7 @@
     hashtab_T	*ht;
     hashitem_T	*hi;
     char_u	*varname;
+    dictitem_T	*di;
 
     ht = find_var_ht(name, &varname);
     if (ht != NULL && *varname != NUL)
@@ -3390,9 +3416,9 @@
 	hi = hash_find(ht, varname);
 	if (!HASHITEM_EMPTY(hi))
 	{
-	    if (var_check_fixed(HI2DI(hi)->di_flags, name))
-		return FAIL;
-	    if (var_check_ro(HI2DI(hi)->di_flags, name))
+	    di = HI2DI(hi);
+	    if (var_check_fixed(di->di_flags, name)
+		    || var_check_ro(di->di_flags, name))
 		return FAIL;
 	    delete_var(ht, hi);
 	    return OK;
@@ -6105,6 +6131,7 @@
     /* Only do this once. */
     want_garbage_collect = FALSE;
     may_garbage_collect = FALSE;
+    garbage_collect_at_exit = FALSE;
 
     /*
      * 1. Go through all accessible variables and mark all lists and dicts
@@ -6681,7 +6708,7 @@
     dict_T	*d = NULL;
     typval_T	tvkey;
     typval_T	tv;
-    char_u	*key;
+    char_u	*key = NULL;
     dictitem_T	*item;
     char_u	*start = skipwhite(*arg + 1);
     char_u	buf[NUMBUFLEN];
@@ -6721,20 +6748,24 @@
 	    clear_tv(&tvkey);
 	    goto failret;
 	}
-	key = get_tv_string_buf_chk(&tvkey, buf);
-	if (key == NULL || *key == NUL)
+	if (evaluate)
 	{
-	    /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
-	    if (key != NULL)
-		EMSG(_(e_emptykey));
-	    clear_tv(&tvkey);
-	    goto failret;
+	    key = get_tv_string_buf_chk(&tvkey, buf);
+	    if (key == NULL || *key == NUL)
+	    {
+		/* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
+		if (key != NULL)
+		    EMSG(_(e_emptykey));
+		clear_tv(&tvkey);
+		goto failret;
+	    }
 	}
 
 	*arg = skipwhite(*arg + 1);
 	if (eval1(arg, &tv, evaluate) == FAIL)	/* recursive! */
 	{
-	    clear_tv(&tvkey);
+	    if (evaluate)
+		clear_tv(&tvkey);
 	    goto failret;
 	}
 	if (evaluate)
@@ -6794,7 +6825,7 @@
  * "numbuf" is used for a number.
  * Does not put quotes around strings, as ":echo" displays values.
  * When "copyID" is not NULL replace recursive lists and dicts with "...".
- * May return NULL;
+ * May return NULL.
  */
     static char_u *
 echo_string(tv, tofree, numbuf, copyID)
@@ -6879,7 +6910,7 @@
  * If the memory is allocated "tofree" is set to it, otherwise NULL.
  * "numbuf" is used for a number.
  * Puts quotes around strings, so that they can be parsed back by eval().
- * May return NULL;
+ * May return NULL.
  */
     static char_u *
 tv2string(tv, tofree, numbuf, copyID)
@@ -7043,6 +7074,7 @@
     {"changenr",	0, 0, f_changenr},
     {"char2nr",		1, 1, f_char2nr},
     {"cindent",		1, 1, f_cindent},
+    {"clearmatches",	0, 0, f_clearmatches},
     {"col",		1, 1, f_col},
 #if defined(FEAT_INS_EXPAND)
     {"complete",	2, 2, f_complete},
@@ -7082,7 +7114,7 @@
     {"foldtextresult",	1, 1, f_foldtextresult},
     {"foreground",	0, 0, f_foreground},
     {"function",	1, 1, f_function},
-    {"garbagecollect",	0, 0, f_garbagecollect},
+    {"garbagecollect",	0, 1, f_garbagecollect},
     {"get",		2, 3, f_get},
     {"getbufline",	2, 3, f_getbufline},
     {"getbufvar",	2, 2, f_getbufvar},
@@ -7099,6 +7131,7 @@
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
     {"getloclist",	1, 1, f_getqflist},
+    {"getmatches",	0, 0, f_getmatches},
     {"getpos",		1, 1, f_getpos},
     {"getqflist",	0, 0, f_getqflist},
     {"getreg",		0, 2, f_getreg},
@@ -7149,7 +7182,9 @@
     {"maparg",		1, 3, f_maparg},
     {"mapcheck",	1, 3, f_mapcheck},
     {"match",		2, 4, f_match},
+    {"matchadd",	2, 4, f_matchadd},
     {"matcharg",	1, 1, f_matcharg},
+    {"matchdelete",	1, 1, f_matchdelete},
     {"matchend",	2, 4, f_matchend},
     {"matchlist",	2, 4, f_matchlist},
     {"matchstr",	2, 4, f_matchstr},
@@ -7179,17 +7214,18 @@
     {"repeat",		2, 2, f_repeat},
     {"resolve",		1, 1, f_resolve},
     {"reverse",		1, 1, f_reverse},
-    {"search",		1, 3, f_search},
+    {"search",		1, 4, f_search},
     {"searchdecl",	1, 3, f_searchdecl},
-    {"searchpair",	3, 6, f_searchpair},
-    {"searchpairpos",	3, 6, f_searchpairpos},
-    {"searchpos",	1, 3, f_searchpos},
+    {"searchpair",	3, 7, f_searchpair},
+    {"searchpairpos",	3, 7, f_searchpairpos},
+    {"searchpos",	1, 4, f_searchpos},
     {"server2client",	2, 2, f_server2client},
     {"serverlist",	0, 0, f_serverlist},
     {"setbufvar",	3, 3, f_setbufvar},
     {"setcmdpos",	1, 1, f_setcmdpos},
     {"setline",		2, 2, f_setline},
     {"setloclist",	2, 3, f_setloclist},
+    {"setmatches",	1, 1, f_setmatches},
     {"setpos",		2, 2, f_setpos},
     {"setqflist",	1, 2, f_setqflist},
     {"setreg",		2, 3, f_setreg},
@@ -7217,6 +7253,7 @@
     {"synID",		3, 3, f_synID},
     {"synIDattr",	2, 3, f_synIDattr},
     {"synIDtrans",	1, 1, f_synIDtrans},
+    {"synstack",	2, 2, f_synstack},
     {"system",		1, 2, f_system},
     {"tabpagebuflist",	0, 1, f_tabpagebuflist},
     {"tabpagenr",	0, 1, f_tabpagenr},
@@ -8240,6 +8277,20 @@
 }
 
 /*
+ * "clearmatches()" function
+ */
+/*ARGSUSED*/
+    static void
+f_clearmatches(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    clear_matches(curwin);
+#endif
+}
+
+/*
  * "col(string)" function
  */
     static void
@@ -8682,7 +8733,7 @@
     static int		fnum = 0;
     static int		change_start = 0;
     static int		change_end = 0;
-    static hlf_T	hlID = 0;
+    static hlf_T	hlID = (hlf_T)0;
     int			filler_lines;
     int			col;
 
@@ -9339,15 +9390,16 @@
 {
     typval_T	rettv;
     char_u	*s;
+    int		retval = FAIL;
 
     copy_tv(tv, &vimvars[VV_VAL].vv_tv);
     s = expr;
     if (eval1(&s, &rettv, TRUE) == FAIL)
-	return FAIL;
+	goto theend;
     if (*s != NUL)  /* check for trailing chars after expr */
     {
 	EMSG2(_(e_invexpr2), s);
-	return FAIL;
+	goto theend;
     }
     if (map)
     {
@@ -9366,10 +9418,12 @@
 	/* On type error, nothing has been removed; return FAIL to stop the
 	 * loop.  The error message was given by get_tv_number_chk(). */
 	if (error)
-	    return FAIL;
+	    goto theend;
     }
+    retval = OK;
+theend:
     clear_tv(&vimvars[VV_VAL].vv_tv);
-    return OK;
+    return retval;
 }
 
 /*
@@ -9670,6 +9724,9 @@
     /* This is postponed until we are back at the toplevel, because we may be
      * using Lists and Dicts internally.  E.g.: ":echo [garbagecollect()]". */
     want_garbage_collect = TRUE;
+
+    if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1)
+	garbage_collect_at_exit = TRUE;
 }
 
 /*
@@ -9868,18 +9925,24 @@
 
     ++no_mapping;
     ++allow_keys;
-    if (argvars[0].v_type == VAR_UNKNOWN)
-	/* getchar(): blocking wait. */
-	n = safe_vgetc();
-    else if (get_tv_number_chk(&argvars[0], &error) == 1)
-	/* getchar(1): only check if char avail */
-	n = vpeekc();
-    else if (error || vpeekc() == NUL)
-	/* illegal argument or getchar(0) and no char avail: return zero */
-	n = 0;
-    else
-	/* getchar(0) and char avail: return char */
-	n = safe_vgetc();
+    for (;;)
+    {
+	if (argvars[0].v_type == VAR_UNKNOWN)
+	    /* getchar(): blocking wait. */
+	    n = safe_vgetc();
+	else if (get_tv_number_chk(&argvars[0], &error) == 1)
+	    /* getchar(1): only check if char avail */
+	    n = vpeekc();
+	else if (error || vpeekc() == NUL)
+	    /* illegal argument or getchar(0) and no char avail: return zero */
+	    n = 0;
+	else
+	    /* getchar(0) and char avail: return char */
+	    n = safe_vgetc();
+	if (n == K_IGNORE)
+	    continue;
+	break;
+    }
     --no_mapping;
     --allow_keys;
 
@@ -10136,7 +10199,13 @@
 	if (mch_isdir(fname))
 	    rettv->vval.v_number = 0;
 	else
+	{
 	    rettv->vval.v_number = (varnumber_T)st.st_size;
+
+	    /* non-perfect check for overflow */
+	    if ((off_t)rettv->vval.v_number != (off_t)st.st_size)
+		rettv->vval.v_number = -2;
+	}
     }
     else
 	  rettv->vval.v_number = -1;
@@ -10269,6 +10338,39 @@
 }
 
 /*
+ * "getmatches()" function
+ */
+/*ARGSUSED*/
+    static void
+f_getmatches(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    dict_T	*dict;
+    matchitem_T	*cur = curwin->w_match_head;
+
+    rettv->vval.v_number = 0;
+
+    if (rettv_list_alloc(rettv) == OK)
+    {
+	while (cur != NULL)
+	{
+	    dict = dict_alloc();
+	    if (dict == NULL)
+		return;
+	    dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
+	    dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
+	    dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
+	    dict_add_nr_str(dict, "id", (long)cur->id, NULL);
+	    list_append_dict(rettv->vval.v_list, dict);
+	    cur = cur->next;
+	}
+    }
+#endif
+}
+
+/*
  * "getpos(string)" function
  */
     static void
@@ -10290,7 +10392,8 @@
 	    list_append_number(l, (varnumber_T)0);
 	list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum
 							    : (varnumber_T)0);
-	list_append_number(l, (fp != NULL) ? (varnumber_T)fp->col + 1
+	list_append_number(l, (fp != NULL)
+		     ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1)
 							    : (varnumber_T)0);
 	list_append_number(l,
 #ifdef FEAT_VIRTUALEDIT
@@ -10785,6 +10888,9 @@
 	"gui_gtk2",
 # endif
 #endif
+#ifdef FEAT_GUI_GNOME
+	"gui_gnome",
+#endif
 #ifdef FEAT_GUI_MAC
 	"gui_mac",
 #endif
@@ -11471,14 +11577,12 @@
     char_u	*xp_arg = NULL;
 
     rettv->v_type = VAR_STRING;
+    rettv->vval.v_string = NULL;
 
 #ifdef NO_CONSOLE_INPUT
     /* While starting up, there is no place to enter text. */
     if (no_console_input())
-    {
-	rettv->vval.v_string = NULL;
 	return;
-    }
 #endif
 
     cmd_silent = FALSE;		/* Want to see the prompt. */
@@ -12439,6 +12543,44 @@
 }
 
 /*
+ * "matchadd()" function
+ */
+    static void
+f_matchadd(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    char_u	buf[NUMBUFLEN];
+    char_u	*grp = get_tv_string_buf_chk(&argvars[0], buf);	/* group */
+    char_u	*pat = get_tv_string_buf_chk(&argvars[1], buf);	/* pattern */
+    int		prio = 10;	/* default priority */
+    int		id = -1;
+    int		error = FALSE;
+
+    rettv->vval.v_number = -1;
+
+    if (grp == NULL || pat == NULL)
+	return;
+    if (argvars[2].v_type != VAR_UNKNOWN)
+    {
+	prio = get_tv_number_chk(&argvars[2], &error);
+	if (argvars[3].v_type != VAR_UNKNOWN)
+	    id = get_tv_number_chk(&argvars[3], &error);
+    }
+    if (error == TRUE)
+	return;
+    if (id >= 1 && id <= 3)
+    {
+	EMSGN("E798: ID is reserved for \":match\": %ld", id);
+	return;
+    }
+
+    rettv->vval.v_number = match_add(curwin, grp, pat, prio, id);
+#endif
+}
+
+/*
  * "matcharg()" function
  */
     static void
@@ -12449,20 +12591,42 @@
     if (rettv_list_alloc(rettv) == OK)
     {
 #ifdef FEAT_SEARCH_EXTRA
-	int	mi = get_tv_number(&argvars[0]);
+	int	    id = get_tv_number(&argvars[0]);
+	matchitem_T *m;
 
-	if (mi >= 1 && mi <= 3)
+	if (id >= 1 && id <= 3)
 	{
-	    list_append_string(rettv->vval.v_list,
-				 syn_id2name(curwin->w_match_id[mi - 1]), -1);
-	    list_append_string(rettv->vval.v_list,
-					     curwin->w_match_pat[mi - 1], -1);
+	    if ((m = (matchitem_T *)get_match(curwin, id)) != NULL)
+	    {
+		list_append_string(rettv->vval.v_list,
+						syn_id2name(m->hlg_id), -1);
+		list_append_string(rettv->vval.v_list, m->pattern, -1);
+	    }
+	    else
+	    {
+		list_append_string(rettv->vval.v_list, NUL, -1);
+		list_append_string(rettv->vval.v_list, NUL, -1);
+	    }
 	}
 #endif
     }
 }
 
 /*
+ * "matchdelete()" function
+ */
+    static void
+f_matchdelete(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    rettv->vval.v_number = match_delete(curwin,
+				       (int)get_tv_number(&argvars[0]), TRUE);
+#endif
+}
+
+/*
  * "matchend()" function
  */
     static void
@@ -13680,7 +13844,7 @@
 	    }
 	    /* Shorten "remain". */
 	    if (*q != NUL)
-		STRCPY(remain, q - 1);
+		mch_memmove(remain, q - 1, STRLEN(q - 1) + 1);
 	    else
 	    {
 		vim_free(remain);
@@ -13858,6 +14022,10 @@
     int		dir;
     int		retval = 0;	/* default: FAIL */
     long	lnum_stop = 0;
+    proftime_T	tm;
+#ifdef FEAT_RELTIME
+    long	time_limit = 0;
+#endif
     int		options = SEARCH_KEEP;
     int		subpatnum;
 
@@ -13871,15 +14039,27 @@
     if (flags & SP_END)
 	options |= SEARCH_END;
 
-    /* Optional extra argument: line number to stop searching. */
-    if (argvars[1].v_type != VAR_UNKNOWN
-	    && argvars[2].v_type != VAR_UNKNOWN)
+    /* Optional arguments: line number to stop searching and timeout. */
+    if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN)
     {
 	lnum_stop = get_tv_number_chk(&argvars[2], NULL);
 	if (lnum_stop < 0)
 	    goto theend;
+#ifdef FEAT_RELTIME
+	if (argvars[3].v_type != VAR_UNKNOWN)
+	{
+	    time_limit = get_tv_number_chk(&argvars[3], NULL);
+	    if (time_limit < 0)
+		goto theend;
+	}
+#endif
     }
 
+#ifdef FEAT_RELTIME
+    /* Set the time limit, if there is one. */
+    profile_setlimit(time_limit, &tm);
+#endif
+
     /*
      * This function does not accept SP_REPEAT and SP_RETCOUNT flags.
      * Check to make sure only those flags are set.
@@ -13895,7 +14075,7 @@
 
     pos = save_cursor = curwin->w_cursor;
     subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L,
-				     options, RE_SEARCH, (linenr_T)lnum_stop);
+				options, RE_SEARCH, (linenr_T)lnum_stop, &tm);
     if (subpatnum != FAIL)
     {
 	if (flags & SP_SUBPAT)
@@ -13919,6 +14099,8 @@
     /* If 'n' flag is used: restore cursor position. */
     if (flags & SP_NOMOVE)
 	curwin->w_cursor = save_cursor;
+    else
+	curwin->w_set_curswant = TRUE;
 theend:
     p_ws = save_p_ws;
 
@@ -13983,6 +14165,7 @@
     char_u	nbuf3[NUMBUFLEN];
     int		retval = 0;		/* default: FAIL */
     long	lnum_stop = 0;
+    long	time_limit = 0;
 
     /* Get the three pattern arguments: start, middle, end. */
     spat = get_tv_string_chk(&argvars[0]);
@@ -14006,6 +14189,10 @@
 	goto theend;
     }
 
+    /* Using 'r' implies 'W', otherwise it doesn't work. */
+    if (flags & SP_REPEAT)
+	p_ws = FALSE;
+
     /* Optional fifth argument: skip expression */
     if (argvars[3].v_type == VAR_UNKNOWN
 	    || argvars[4].v_type == VAR_UNKNOWN)
@@ -14018,13 +14205,21 @@
 	    lnum_stop = get_tv_number_chk(&argvars[5], NULL);
 	    if (lnum_stop < 0)
 		goto theend;
+#ifdef FEAT_RELTIME
+	    if (argvars[6].v_type != VAR_UNKNOWN)
+	    {
+		time_limit = get_tv_number_chk(&argvars[6], NULL);
+		if (time_limit < 0)
+		    goto theend;
+	    }
+#endif
 	}
     }
     if (skip == NULL)
 	goto theend;	    /* type error */
 
     retval = do_searchpair(spat, mpat, epat, dir, skip, flags,
-							match_pos, lnum_stop);
+					    match_pos, lnum_stop, time_limit);
 
 theend:
     p_ws = save_p_ws;
@@ -14076,7 +14271,8 @@
  * Returns 0 or -1 for no match,
  */
     long
-do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos, lnum_stop)
+do_searchpair(spat, mpat, epat, dir, skip, flags, match_pos,
+							lnum_stop, time_limit)
     char_u	*spat;	    /* start pattern */
     char_u	*mpat;	    /* middle pattern */
     char_u	*epat;	    /* end pattern */
@@ -14085,6 +14281,7 @@
     int		flags;	    /* SP_SETPCMARK and other SP_ values */
     pos_T	*match_pos;
     linenr_T	lnum_stop;  /* stop at this line if not zero */
+    long	time_limit; /* stop after this many msec */
 {
     char_u	*save_cpo;
     char_u	*pat, *pat2 = NULL, *pat3 = NULL;
@@ -14099,11 +14296,17 @@
     int		nest = 1;
     int		err;
     int		options = SEARCH_KEEP;
+    proftime_T	tm;
 
     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
     save_cpo = p_cpo;
     p_cpo = (char_u *)"";
 
+#ifdef FEAT_RELTIME
+    /* Set the time limit, if there is one. */
+    profile_setlimit(time_limit, &tm);
+#endif
+
     /* Make two search patterns: start/end (pat2, for in nested pairs) and
      * start/middle/end (pat3, for the top pair). */
     pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
@@ -14127,7 +14330,7 @@
     for (;;)
     {
 	n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
-					       options, RE_SEARCH, lnum_stop);
+					   options, RE_SEARCH, lnum_stop, &tm);
 	if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
 	    /* didn't find it or found the first match again: FAIL */
 	    break;
@@ -14146,6 +14349,9 @@
 	}
 	foundpos = pos;
 
+	/* clear the start flag to avoid getting stuck here */
+	options &= ~SEARCH_START;
+
 	/* If the skip pattern matches, ignore this match. */
 	if (*skip != NUL)
 	{
@@ -14498,6 +14704,66 @@
 }
 
 /*
+ * "setmatches()" function
+ */
+    static void
+f_setmatches(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SEARCH_EXTRA
+    list_T	*l;
+    listitem_T	*li;
+    dict_T	*d;
+
+    rettv->vval.v_number = -1;
+    if (argvars[0].v_type != VAR_LIST)
+    {
+	EMSG(_(e_listreq));
+	return;
+    }
+    if ((l = argvars[0].vval.v_list) != NULL)
+    {
+
+	/* To some extent make sure that we are dealing with a list from
+	 * "getmatches()". */
+	li = l->lv_first;
+	while (li != NULL)
+	{
+	    if (li->li_tv.v_type != VAR_DICT
+		    || (d = li->li_tv.vval.v_dict) == NULL)
+	    {
+		EMSG(_(e_invarg));
+		return;
+	    }
+	    if (!(dict_find(d, (char_u *)"group", -1) != NULL
+			&& dict_find(d, (char_u *)"pattern", -1) != NULL
+			&& dict_find(d, (char_u *)"priority", -1) != NULL
+			&& dict_find(d, (char_u *)"id", -1) != NULL))
+	    {
+		EMSG(_(e_invarg));
+		return;
+	    }
+	    li = li->li_next;
+	}
+
+	clear_matches(curwin);
+	li = l->lv_first;
+	while (li != NULL)
+	{
+	    d = li->li_tv.vval.v_dict;
+	    match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
+		    get_dict_string(d, (char_u *)"pattern", FALSE),
+		    (int)get_dict_number(d, (char_u *)"priority"),
+		    (int)get_dict_number(d, (char_u *)"id"));
+	    li = li->li_next;
+	}
+	rettv->vval.v_number = 0;
+    }
+#endif
+}
+
+/*
  * "setpos()" function
  */
 /*ARGSUSED*/
@@ -14510,24 +14776,31 @@
     int		fnum;
     char_u	*name;
 
+    rettv->vval.v_number = -1;
     name = get_tv_string_chk(argvars);
     if (name != NULL)
     {
 	if (list2fpos(&argvars[1], &pos, &fnum) == OK)
 	{
 	    --pos.col;
-	    if (name[0] == '.')		/* cursor */
+	    if (name[0] == '.' && name[1] == NUL)
 	    {
+		/* set cursor */
 		if (fnum == curbuf->b_fnum)
 		{
 		    curwin->w_cursor = pos;
 		    check_cursor();
+		    rettv->vval.v_number = 0;
 		}
 		else
 		    EMSG(_(e_invarg));
 	    }
-	    else if (name[0] == '\'')	/* mark */
-		(void)setmark_pos(name[1], &pos, fnum);
+	    else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL)
+	    {
+		/* set mark */
+		if (setmark_pos(name[1], &pos, fnum) == OK)
+		    rettv->vval.v_number = 0;
+	    }
 	    else
 		EMSG(_(e_invarg));
 	}
@@ -14785,6 +15058,10 @@
 
     p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
     p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
+    if (p1 == NULL)
+	p1 = (char_u *)"";
+    if (p2 == NULL)
+	p2 = (char_u *)"";
     if (item_compare_ic)
 	res = STRICMP(p1, p2);
     else
@@ -15274,7 +15551,8 @@
 
     rettv->v_type = VAR_STRING;
     rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 0);
-    if (tofree == NULL)
+    /* Make a copy if we have a value but it's not in allocate memory. */
+    if (rettv->vval.v_string != NULL && tofree == NULL)
 	rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
 }
 
@@ -15461,7 +15739,7 @@
 
     if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
 	    && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
-	id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL);
+	id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE);
 #endif
 
     rettv->vval.v_number = id;
@@ -15584,6 +15862,46 @@
 }
 
 /*
+ * "synstack(lnum, col)" function
+ */
+/*ARGSUSED*/
+    static void
+f_synstack(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+#ifdef FEAT_SYN_HL
+    long	lnum;
+    long	col;
+    int		i;
+    int		id;
+#endif
+
+    rettv->v_type = VAR_LIST;
+    rettv->vval.v_list = NULL;
+
+#ifdef FEAT_SYN_HL
+    lnum = get_tv_lnum(argvars);		/* -1 on type error */
+    col = get_tv_number(&argvars[1]) - 1;	/* -1 on type error */
+
+    if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
+	    && col >= 0 && col < (long)STRLEN(ml_get(lnum))
+	    && rettv_list_alloc(rettv) != FAIL)
+    {
+	(void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE);
+	for (i = 0; ; ++i)
+	{
+	    id = syn_get_stack_item(i);
+	    if (id < 0)
+		break;
+	    if (list_append_number(rettv->vval.v_list, id) == FAIL)
+		break;
+	}
+    }
+#endif
+}
+
+/*
  * "system()" function
  */
     static void
@@ -15599,7 +15917,7 @@
     FILE	*fd;
 
     if (check_restricted() || check_secure())
-	return;
+	goto done;
 
     if (argvars[1].v_type != VAR_UNKNOWN)
     {
@@ -15610,7 +15928,7 @@
 	if ((infile = vim_tempname('i')) == NULL)
 	{
 	    EMSG(_(e_notmp));
-	    return;
+	    goto done;
 	}
 
 	fd = mch_fopen((char *)infile, WRITEBIN);
@@ -16497,9 +16815,9 @@
  * Returns NULL when there is an error.
  */
     static pos_T *
-var2fpos(varp, lnum, fnum)
+var2fpos(varp, dollar_lnum, fnum)
     typval_T	*varp;
-    int		lnum;		/* TRUE when $ is last line */
+    int		dollar_lnum;	/* TRUE when $ is last line */
     int		*fnum;		/* set to fnum for '0, 'A, etc. */
 {
     char_u		*name;
@@ -16512,6 +16830,7 @@
 	list_T		*l;
 	int		len;
 	int		error = FALSE;
+	listitem_T	*li;
 
 	l = varp->vval.v_list;
 	if (l == NULL)
@@ -16527,6 +16846,14 @@
 	if (error)
 	    return NULL;
 	len = (long)STRLEN(ml_get(pos.lnum));
+
+	/* We accept "$" for the column number: last column. */
+	li = list_find(l, 1L);
+	if (li != NULL && li->li_tv.v_type == VAR_STRING
+		&& li->li_tv.vval.v_string != NULL
+		&& STRCMP(li->li_tv.vval.v_string, "$") == 0)
+	    pos.col = len + 1;
+
 	/* Accept a position up to the NUL after the line. */
 	if (pos.col == 0 || (int)pos.col > len + 1)
 	    return NULL;	/* invalid column number */
@@ -16559,7 +16886,7 @@
     pos.coladd = 0;
 #endif
 
-    if (name[0] == 'w' && lnum)
+    if (name[0] == 'w' && dollar_lnum)
     {
 	pos.col = 0;
 	if (name[1] == '0')		/* "w0": first visible line */
@@ -16577,7 +16904,7 @@
     }
     else if (name[0] == '$')		/* last column or line */
     {
-	if (lnum)
+	if (dollar_lnum)
 	{
 	    pos.lnum = curbuf->b_ml.ml_line_count;
 	    pos.col = 0;
@@ -17798,9 +18125,10 @@
  * List the value of one internal variable.
  */
     static void
-list_one_var(v, prefix)
+list_one_var(v, prefix, first)
     dictitem_T	*v;
     char_u	*prefix;
+    int		*first;
 {
     char_u	*tofree;
     char_u	*s;
@@ -17808,18 +18136,21 @@
 
     s = echo_string(&v->di_tv, &tofree, numbuf, ++current_copyID);
     list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
-						s == NULL ? (char_u *)"" : s);
+					 s == NULL ? (char_u *)"" : s, first);
     vim_free(tofree);
 }
 
     static void
-list_one_var_a(prefix, name, type, string)
+list_one_var_a(prefix, name, type, string, first)
     char_u	*prefix;
     char_u	*name;
     int		type;
     char_u	*string;
+    int		*first;  /* when TRUE clear rest of screen and set to FALSE */
 {
-    msg_attr(prefix, 0);    /* don't use msg(), it overwrites "v:statusmsg" */
+    /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
+    msg_start();
+    msg_puts(prefix);
     if (name != NULL)	/* "a:" vars don't have a name stored */
 	msg_puts(name);
     msg_putchar(' ');
@@ -17847,6 +18178,11 @@
 
     if (type == VAR_FUNC)
 	msg_puts((char_u *)"()");
+    if (*first)
+    {
+	msg_clr_eos();
+	*first = FALSE;
+    }
 }
 
 /*
@@ -19136,6 +19472,28 @@
 	goto theend;
     }
 
+    /* Check if the name is a Funcref.  If so, use the value. */
+    if (lv.ll_exp_name != NULL)
+    {
+	len = (int)STRLEN(lv.ll_exp_name);
+	name = deref_func_name(lv.ll_exp_name, &len);
+	if (name == lv.ll_exp_name)
+	    name = NULL;
+    }
+    else
+    {
+	len = (int)(end - *pp);
+	name = deref_func_name(*pp, &len);
+	if (name == *pp)
+	    name = NULL;
+    }
+    if (name != NULL)
+    {
+	name = vim_strsave(name);
+	*pp = end;
+	goto theend;
+    }
+
     if (lv.ll_exp_name != NULL)
     {
 	len = (int)STRLEN(lv.ll_exp_name);
@@ -19969,6 +20327,7 @@
 		char_u	buf[MSG_BUF_LEN];
 		char_u	numbuf2[NUMBUFLEN];
 		char_u	*tofree;
+		char_u	*s;
 
 		msg_puts((char_u *)"(");
 		for (i = 0; i < argcount; ++i)
@@ -19979,10 +20338,13 @@
 			msg_outnum((long)argvars[i].vval.v_number);
 		    else
 		    {
-			trunc_string(tv2string(&argvars[i], &tofree,
-					      numbuf2, 0), buf, MSG_BUF_CLEN);
-			msg_puts(buf);
-			vim_free(tofree);
+			s = tv2string(&argvars[i], &tofree, numbuf2, 0);
+			if (s != NULL)
+			{
+			    trunc_string(s, buf, MSG_BUF_CLEN);
+			    msg_puts(buf);
+			    vim_free(tofree);
+			}
 		    }
 		}
 		msg_puts((char_u *)")");
@@ -20060,14 +20422,18 @@
 	    char_u	buf[MSG_BUF_LEN];
 	    char_u	numbuf2[NUMBUFLEN];
 	    char_u	*tofree;
+	    char_u	*s;
 
 	    /* The value may be very long.  Skip the middle part, so that we
 	     * have some idea how it starts and ends. smsg() would always
 	     * truncate it at the end. */
-	    trunc_string(tv2string(fc.rettv, &tofree, numbuf2, 0),
-							   buf, MSG_BUF_CLEN);
-	    smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
-	    vim_free(tofree);
+	    s = tv2string(fc.rettv, &tofree, numbuf2, 0);
+	    if (s != NULL)
+	    {
+		trunc_string(s, buf, MSG_BUF_CLEN);
+		smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
+		vim_free(tofree);
+	    }
 	}
 	msg_puts((char_u *)"\n");   /* don't overwrite this either */
 
@@ -21034,14 +21400,27 @@
 	*usedlen += 2;
 	s = get_past_head(*fnamep);
 	while (tail > s && after_pathsep(s, tail))
-	    --tail;
+	    mb_ptr_back(*fnamep, tail);
 	*fnamelen = (int)(tail - *fnamep);
 #ifdef VMS
 	if (*fnamelen > 0)
 	    *fnamelen += 1; /* the path separator is part of the path */
 #endif
-	while (tail > s && !after_pathsep(s, tail))
-	    mb_ptr_back(*fnamep, tail);
+	if (*fnamelen == 0)
+	{
+	    /* Result is empty.  Turn it into "." to make ":cd %:h" work. */
+	    p = vim_strsave((char_u *)".");
+	    if (p == NULL)
+		return -1;
+	    vim_free(*bufp);
+	    *bufp = *fnamep = tail = p;
+	    *fnamelen = 1;
+	}
+	else
+	{
+	    while (tail > s && !after_pathsep(s, tail))
+		mb_ptr_back(*fnamep, tail);
+	}
     }
 
     /* ":8" - shortname  */
diff -Naur vim71.orig/src/ex_cmds.c vim71/src/ex_cmds.c
--- vim71.orig/src/ex_cmds.c	2007-05-07 19:41:01.000000000 +0000
+++ vim71/src/ex_cmds.c	2008-02-14 21:07:34.000000000 +0000
@@ -408,7 +408,11 @@
 		goto sortend;
 	    }
 	    *s = NUL;
-	    regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
+	    /* Use last search pattern if sort pattern is empty. */
+	    if (s == p + 1 && last_search_pat() != NULL)
+		regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
+	    else
+		regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
 	    if (regmatch.regprog == NULL)
 		goto sortend;
 	    p = s;		/* continue after the regexp */
@@ -1646,7 +1650,7 @@
 {
     vim_snprintf((char *)IObuff, IOSIZE, _("%sviminfo: %s in line: "),
 							     errnum, message);
-    STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
+    STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff) - 1);
     if (IObuff[STRLEN(IObuff) - 1] == '\n')
 	IObuff[STRLEN(IObuff) - 1] = NUL;
     emsg(IObuff);
@@ -1770,7 +1774,8 @@
 	 * overwrite a user's viminfo file after a "su root", with a
 	 * viminfo file that the user can't read.
 	 */
-	st_old.st_dev = st_old.st_ino = 0;
+	st_old.st_dev = 0;
+	st_old.st_ino = 0;
 	st_old.st_mode = 0600;
 	if (mch_stat((char *)fname, &st_old) == 0
 		&& getuid() != ROOT_UID
@@ -2727,6 +2732,9 @@
 		    && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
 		|| (buf->b_flags & BF_READERR))
 	    && !p_wa
+#ifdef FEAT_QUICKFIX
+	    && !bt_nofile(buf)
+#endif
 	    && vim_fexists(ffname))
     {
 	if (!eap->forceit && !eap->append)
@@ -2912,22 +2920,35 @@
 }
 
 /*
- * Check if a buffer is read-only.  Ask for overruling in a dialog.
- * Return TRUE and give an error message when the buffer is readonly.
+ * Check if a buffer is read-only (either 'readonly' option is set or file is
+ * read-only). Ask for overruling in a dialog. Return TRUE and give an error
+ * message when the buffer is readonly.
  */
     static int
 check_readonly(forceit, buf)
     int		*forceit;
     buf_T	*buf;
 {
-    if (!*forceit && buf->b_p_ro)
+    struct stat	st;
+
+    /* Handle a file being readonly when the 'readonly' option is set or when
+     * the file exists and permissions are read-only.
+     * We will send 0777 to check_file_readonly(), as the "perm" variable is
+     * important for device checks but not here. */
+    if (!*forceit && (buf->b_p_ro
+		|| (mch_stat((char *)buf->b_ffname, &st) >= 0
+		    && check_file_readonly(buf->b_ffname, 0777))))
     {
 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
 	if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL)
 	{
 	    char_u	buff[IOSIZE];
 
-	    dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
+	    if (buf->b_p_ro)
+		dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
+		    buf->b_fname);
+	    else
+		dialog_msg(buff, _("File permissions of \"%s\" are read-only.\nIt may still be possible to write it.\nDo you wish to try?"),
 		    buf->b_fname);
 
 	    if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES)
@@ -2941,9 +2962,14 @@
 	}
 	else
 #endif
+	if (buf->b_p_ro)
 	    EMSG(_(e_readonly));
+	else
+	    EMSG2(_("E505: \"%s\" is read-only (add ! to override)"),
+		    buf->b_fname);
 	return TRUE;
     }
+
     return FALSE;
 }
 
@@ -2952,7 +2978,7 @@
  * 'fnum' is the number of the file, if zero use ffname/sfname.
  *
  * Return 1 for "normal" error, 2 for "not written" error, 0 for success
- * -1 for succesfully opening another file.
+ * -1 for successfully opening another file.
  * 'lnum' is the line number for the cursor in the new file (if non-zero).
  */
     int
@@ -3367,7 +3393,7 @@
 		 * was in this window (or another window).  If not used
 		 * before, reset the local window options to the global
 		 * values.  Also restores old folding stuff. */
-		get_winopts(buf);
+		get_winopts(curbuf);
 #ifdef FEAT_SPELL
 		did_get_winopts = TRUE;
 #endif
@@ -3562,9 +3588,20 @@
 	curwin_init();
 
 #ifdef FEAT_FOLDING
-	/* It's like all lines in the buffer changed.  Need to update
-	 * automatic folding. */
+	/* It's possible that all lines in the buffer changed.  Need to update
+	 * automatic folding for all windows where it's used. */
+# ifdef FEAT_WINDOWS
+	{
+	    win_T	    *win;
+	    tabpage_T	    *tp;
+
+	    FOR_ALL_TAB_WINDOWS(tp, win)
+		if (win->w_buffer == curbuf)
+		    foldUpdateAll(win);
+	}
+# else
 	foldUpdateAll(curwin);
+# endif
 #endif
 
 	/* Change directories when the 'acd' option is set. */
@@ -3649,8 +3686,8 @@
 #ifdef FEAT_SPELL
     /* If the window options were changed may need to set the spell language.
      * Can only do this after the buffer has been properly setup. */
-    if (did_get_winopts && curwin->w_p_spell && *buf->b_p_spl != NUL)
-	did_set_spelllang(buf);
+    if (did_get_winopts && curwin->w_p_spell && *curbuf->b_p_spl != NUL)
+	did_set_spelllang(curbuf);
 #endif
 
     if (command == NULL)
@@ -3754,7 +3791,7 @@
 	    workshop_file_opened((char *)curbuf->b_ffname, curbuf->b_p_ro);
 # endif
 # ifdef FEAT_NETBEANS_INTG
-	if (usingNetbeans & ((flags & ECMD_SET_HELP) != ECMD_SET_HELP))
+	if (usingNetbeans && ((flags & ECMD_SET_HELP) != ECMD_SET_HELP))
 	    netbeans_file_opened(curbuf);
 # endif
     }
@@ -4163,7 +4200,6 @@
     linenr_T	old_line_count = curbuf->b_ml.ml_line_count;
     linenr_T	line2;
     long	nmatch;			/* number of lines in match */
-    linenr_T	sub_firstlnum;		/* nr of first sub line */
     char_u	*sub_firstline;		/* allocated copy of first sub line */
     int		endcolumn = FALSE;	/* cursor in last column when done */
     pos_T	old_cursor = curwin->w_cursor;
@@ -4175,11 +4211,6 @@
 	sub_nlines = 0;
     }
 
-#ifdef FEAT_FKMAP	/* reverse the flow of the Farsi characters */
-    if (p_altkeymap && curwin->w_p_rl)
-	lrF_sub(cmd);
-#endif
-
     if (eap->cmdidx == CMD_tilde)
 	which_pat = RE_LAST;	/* use last used regexp */
     else
@@ -4215,6 +4246,10 @@
 	}
 	else		/* find the end of the regexp */
 	{
+#ifdef FEAT_FKMAP	/* reverse the flow of the Farsi characters */
+	    if (p_altkeymap && curwin->w_p_rl)
+		lrF_sub(cmd);
+#endif
 	    which_pat = RE_LAST;	    /* use last used regexp */
 	    delimiter = *cmd++;		    /* remember delimiter character */
 	    pat = cmd;			    /* remember start of search pat */
@@ -4294,6 +4329,7 @@
 	do_error = TRUE;
 	do_print = FALSE;
 	do_count = FALSE;
+	do_number = FALSE;
 	do_ic = 0;
     }
     while (*cmd)
@@ -4410,8 +4446,8 @@
 #endif
 		); ++lnum)
     {
-	sub_firstlnum = lnum;
-	nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0);
+	nmatch = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
+							    (colnr_T)0, NULL);
 	if (nmatch)
 	{
 	    colnr_T	copycol;
@@ -4426,6 +4462,7 @@
 	    long	nmatch_tl = 0;	/* nr of lines matched below lnum */
 	    int		do_again;	/* do it again after joining lines */
 	    int		skip_match = FALSE;
+	    linenr_T	sub_firstlnum;	/* nr of first sub line */
 
 	    /*
 	     * The new text is build up step by step, to avoid too much
@@ -4445,8 +4482,10 @@
 	     *			far.
 	     * new_end		The new text, where to append new text.
 	     *
-	     * lnum		The line number where we were looking for the
-	     *			first match in the old line.
+	     * lnum		The line number where we found the start of
+	     *			the match.  Can be below the line we searched
+	     *			when there is a \n before a \zs in the
+	     *			pattern.
 	     * sub_firstlnum	The line number in the buffer where to look
 	     *			for a match.  Can be different from "lnum"
 	     *			when the pattern or substitute string contains
@@ -4464,18 +4503,13 @@
 	     *
 	     * The new text is built up in new_start[].  It has some extra
 	     * room to avoid using alloc()/free() too often.  new_start_len is
-	     * the lenght of the allocated memory at new_start.
+	     * the length of the allocated memory at new_start.
 	     *
 	     * Make a copy of the old line, so it won't be taken away when
 	     * updating the screen or handling a multi-line match.  The "old_"
 	     * pointers point into this copy.
 	     */
-	    sub_firstline = vim_strsave(ml_get(sub_firstlnum));
-	    if (sub_firstline == NULL)
-	    {
-		vim_free(new_start);
-		goto outofmem;
-	    }
+	    sub_firstlnum = lnum;
 	    copycol = 0;
 	    matchcol = 0;
 
@@ -4496,6 +4530,28 @@
 	     */
 	    for (;;)
 	    {
+		/* Advance "lnum" to the line where the match starts.  The
+		 * match does not start in the first line when there is a line
+		 * break before \zs. */
+		if (regmatch.startpos[0].lnum > 0)
+		{
+		    lnum += regmatch.startpos[0].lnum;
+		    sub_firstlnum += regmatch.startpos[0].lnum;
+		    nmatch -= regmatch.startpos[0].lnum;
+		    vim_free(sub_firstline);
+		    sub_firstline = NULL;
+		}
+
+		if (sub_firstline == NULL)
+		{
+		    sub_firstline = vim_strsave(ml_get(sub_firstlnum));
+		    if (sub_firstline == NULL)
+		    {
+			vim_free(new_start);
+			goto outofmem;
+		    }
+		}
+
 		/* Save the line number of the last change for the final
 		 * cursor position (just like Vi). */
 		curwin->w_cursor.lnum = lnum;
@@ -4538,6 +4594,7 @@
 		    {
 			matchcol = (colnr_T)STRLEN(sub_firstline);
 			nmatch = 1;
+			skip_match = TRUE;
 		    }
 		    sub_nsubs++;
 		    did_sub = TRUE;
@@ -4600,7 +4657,8 @@
 			    temp = RedrawingDisabled;
 			    RedrawingDisabled = 0;
 
-			    search_match_lines = regmatch.endpos[0].lnum;
+			    search_match_lines = regmatch.endpos[0].lnum
+						  - regmatch.startpos[0].lnum;
 			    search_match_endcol = regmatch.endpos[0].col;
 			    highlight_match = TRUE;
 
@@ -4635,7 +4693,7 @@
 #endif
 			    ++no_mapping;	/* don't map this key */
 			    ++allow_keys;	/* allow special keys */
-			    i = safe_vgetc();
+			    i = plain_vgetc();
 			    --allow_keys;
 			    --no_mapping;
 
@@ -4711,7 +4769,8 @@
 		 * 3. substitute the string.
 		 */
 		/* get length of substitution part */
-		sublen = vim_regsub_multi(&regmatch, sub_firstlnum,
+		sublen = vim_regsub_multi(&regmatch,
+				    sub_firstlnum - regmatch.startpos[0].lnum,
 				    sub, sub_firstline, FALSE, p_magic, TRUE);
 
 		/* When the match included the "$" of the last line it may
@@ -4781,7 +4840,8 @@
 		mch_memmove(new_end, sub_firstline + copycol, (size_t)i);
 		new_end += i;
 
-		(void)vim_regsub_multi(&regmatch, sub_firstlnum,
+		(void)vim_regsub_multi(&regmatch,
+				    sub_firstlnum - regmatch.startpos[0].lnum,
 					   sub, new_end, TRUE, p_magic, TRUE);
 		sub_nsubs++;
 		did_sub = TRUE;
@@ -4850,7 +4910,8 @@
 			    ++line2;
 			    /* move the cursor to the new line, like Vi */
 			    ++curwin->w_cursor.lnum;
-			    STRCPY(new_start, p1 + 1);	/* copy the rest */
+			    /* copy the rest */
+			    mch_memmove(new_start, p1 + 1, STRLEN(p1 + 1) + 1);
 			    p1 = new_start - 1;
 			}
 		    }
@@ -4869,10 +4930,13 @@
 skip:
 		/* We already know that we did the last subst when we are at
 		 * the end of the line, except that a pattern like
-		 * "bar\|\nfoo" may match at the NUL. */
+		 * "bar\|\nfoo" may match at the NUL.  "lnum" can be below
+		 * "line2" when there is a \zs in the pattern after a line
+		 * break. */
 		lastone = (skip_match
 			|| got_int
 			|| got_quit
+			|| lnum > line2
 			|| !(do_all || do_again)
 			|| (sub_firstline[matchcol] == NUL && nmatch <= 1
 					 && !re_multiline(regmatch.regprog)));
@@ -4887,12 +4951,16 @@
 		 * When asking the user we like to show the already replaced
 		 * text, but don't do it when "\<@=" or "\<@!" is used, it
 		 * changes what matches.
+		 * When the match starts below where we start searching also
+		 * need to replace the line first (using \zs after \n).
 		 */
 		if (lastone
 			|| (do_ask && !re_lookbehind(regmatch.regprog))
 			|| nmatch_tl > 0
 			|| (nmatch = vim_regexec_multi(&regmatch, curwin,
-				       curbuf, sub_firstlnum, matchcol)) == 0)
+							curbuf, sub_firstlnum,
+							 matchcol, NULL)) == 0
+			|| regmatch.startpos[0].lnum > 0)
 		{
 		    if (new_start != NULL)
 		    {
@@ -4956,13 +5024,20 @@
 		    }
 		    if (nmatch == -1 && !lastone)
 			nmatch = vim_regexec_multi(&regmatch, curwin, curbuf,
-						     sub_firstlnum, matchcol);
+					       sub_firstlnum, matchcol, NULL);
 
 		    /*
 		     * 5. break if there isn't another match in this line
 		     */
 		    if (nmatch <= 0)
+		    {
+			/* If the match found didn't start where we were
+			 * searching, do the next search in the line where we
+			 * found the match. */
+			if (nmatch == -1)
+			    lnum -= regmatch.startpos[0].lnum;
 			break;
+		    }
 		}
 
 		line_breakcheck();
@@ -5179,7 +5254,8 @@
     for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
     {
 	/* a match on this line? */
-	match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0);
+	match = vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
+							    (colnr_T)0, NULL);
 	if ((type == 'g' && match) || (type == 'v' && !match))
 	{
 	    ml_setmarked(lnum);
@@ -6018,7 +6094,7 @@
 }
 
 #if defined(FEAT_EX_EXTRA) || defined(PROTO)
-static void helptags_one __ARGS((char_u *dir, char_u *ext, char_u *lang));
+static void helptags_one __ARGS((char_u *dir, char_u *ext, char_u *lang, int add_help_tags));
 
 /*
  * ":helptags"
@@ -6033,12 +6109,26 @@
 #ifdef FEAT_MULTI_LANG
     char_u	lang[2];
 #endif
+    expand_T	xpc;
+    char_u	*dirname;
     char_u	ext[5];
     char_u	fname[8];
     int		filecount;
     char_u	**files;
+    int		add_help_tags = FALSE;
+
+    /* Check for ":helptags ++t {dir}". */
+    if (STRNCMP(eap->arg, "++t", 3) == 0 && vim_iswhite(eap->arg[3]))
+    {
+	add_help_tags = TRUE;
+	eap->arg = skipwhite(eap->arg + 3);
+    }
 
-    if (!mch_isdir(eap->arg))
+    ExpandInit(&xpc);
+    xpc.xp_context = EXPAND_DIRECTORIES;
+    dirname = ExpandOne(&xpc, eap->arg, NULL,
+			    WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
+    if (dirname == NULL || !mch_isdir(dirname))
     {
 	EMSG2(_("E150: Not a directory: %s"), eap->arg);
 	return;
@@ -6046,7 +6136,7 @@
 
 #ifdef FEAT_MULTI_LANG
     /* Get a list of all files in the directory. */
-    STRCPY(NameBuff, eap->arg);
+    STRCPY(NameBuff, dirname);
     add_pathsep(NameBuff);
     STRCAT(NameBuff, "*");
     if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
@@ -6054,6 +6144,7 @@
 	    || filecount == 0)
     {
 	EMSG2("E151: No match: %s", NameBuff);
+	vim_free(dirname);
 	return;
     }
 
@@ -6119,7 +6210,7 @@
 	    ext[1] = fname[5];
 	    ext[2] = fname[6];
 	}
-	helptags_one(eap->arg, ext, fname);
+	helptags_one(dirname, ext, fname, add_help_tags);
     }
 
     ga_clear(&ga);
@@ -6127,15 +6218,17 @@
 
 #else
     /* No language support, just use "*.txt" and "tags". */
-    helptags_one(eap->arg, (char_u *)".txt", (char_u *)"tags");
+    helptags_one(dirname, (char_u *)".txt", (char_u *)"tags", add_help_tags);
 #endif
+    vim_free(dirname);
 }
 
     static void
-helptags_one(dir, ext, tagfname)
-    char_u	*dir;	    /* doc directory */
-    char_u	*ext;	    /* suffix, ".txt", ".itx", ".frx", etc. */
-    char_u	*tagfname;    /* "tags" for English, "tags-it" for Italian. */
+helptags_one(dir, ext, tagfname, add_help_tags)
+    char_u	*dir;		/* doc directory */
+    char_u	*ext;		/* suffix, ".txt", ".itx", ".frx", etc. */
+    char_u	*tagfname;      /* "tags" for English, "tags-fr" for French. */
+    int		add_help_tags;  /* add "help-tags" tag */
 {
     FILE	*fd_tags;
     FILE	*fd;
@@ -6186,10 +6279,12 @@
     }
 
     /*
-     * If generating tags for "$VIMRUNTIME/doc" add the "help-tags" tag.
+     * If using the "++t" argument or generating tags for "$VIMRUNTIME/doc"
+     * add the "help-tags" tag.
      */
     ga_init2(&ga, (int)sizeof(char_u *), 100);
-    if (fullpathcmp((char_u *)"$VIMRUNTIME/doc", dir, FALSE) == FPC_SAME)
+    if (add_help_tags || fullpathcmp((char_u *)"$VIMRUNTIME/doc",
+						      dir, FALSE) == FPC_SAME)
     {
 	if (ga_grow(&ga, 1) == FAIL)
 	    got_int = TRUE;
@@ -6351,9 +6446,9 @@
 	for (i = 0; i < ga.ga_len; ++i)
 	{
 	    s = ((char_u **)ga.ga_data)[i];
-	    if (STRNCMP(s, "help-tags", 9) == 0)
+	    if (STRNCMP(s, "help-tags\t", 10) == 0)
 		/* help-tags entry was added in formatted form */
-		fprintf(fd_tags, (char *)s);
+		fputs((char *)s, fd_tags);
 	    else
 	    {
 		fprintf(fd_tags, "%s\t/*", s);
diff -Naur vim71.orig/src/ex_cmds.h vim71/src/ex_cmds.h
--- vim71.orig/src/ex_cmds.h	2007-03-07 20:53:27.000000000 +0000
+++ vim71/src/ex_cmds.h	2008-02-14 21:07:34.000000000 +0000
@@ -422,7 +422,7 @@
 EX(CMD_helpgrep,	"helpgrep",	ex_helpgrep,
 			EXTRA|NOTRLCOM|NEEDARG),
 EX(CMD_helptags,	"helptags",	ex_helptags,
-			NEEDARG|FILE1|TRLBAR|CMDWIN),
+			NEEDARG|FILES|TRLBAR|CMDWIN),
 EX(CMD_hardcopy,	"hardcopy",	ex_hardcopy,
 			RANGE|COUNT|EXTRA|TRLBAR|DFLALL|BANG),
 EX(CMD_highlight,	"highlight",	ex_highlight,
diff -Naur vim71.orig/src/ex_cmds2.c vim71/src/ex_cmds2.c
--- vim71.orig/src/ex_cmds2.c	2007-05-07 19:25:02.000000000 +0000
+++ vim71/src/ex_cmds2.c	2008-02-14 21:07:34.000000000 +0000
@@ -93,6 +93,8 @@
     int		save_emsg_silent = emsg_silent;
     int		save_redir_off = redir_off;
     tasave_T	typeaheadbuf;
+    int		typeahead_saved = FALSE;
+    int		save_ignore_script = 0;
 # ifdef FEAT_EX_EXTRA
     int		save_ex_normal_busy;
 # endif
@@ -159,18 +161,26 @@
 	 * This makes sure we get input from the user here and don't interfere
 	 * with the commands being executed.  Reset "ex_normal_busy" to avoid
 	 * the side effects of using ":normal". Save the stuff buffer and make
-	 * it empty. */
+	 * it empty. Set ignore_script to avoid reading from script input. */
 # ifdef FEAT_EX_EXTRA
 	save_ex_normal_busy = ex_normal_busy;
 	ex_normal_busy = 0;
 # endif
 	if (!debug_greedy)
+	{
 	    save_typeahead(&typeaheadbuf);
+	    typeahead_saved = TRUE;
+	    save_ignore_script = ignore_script;
+	    ignore_script = TRUE;
+	}
 
 	cmdline = getcmdline_prompt('>', NULL, 0, EXPAND_NOTHING, NULL);
 
-	if (!debug_greedy)
+	if (typeahead_saved)
+	{
 	    restore_typeahead(&typeaheadbuf);
+	    ignore_script = save_ignore_script;
+	}
 # ifdef FEAT_EX_EXTRA
 	ex_normal_busy = save_ex_normal_busy;
 # endif
@@ -885,19 +895,61 @@
     sprintf(buf, "%10.6lf", (double)tm->QuadPart / (double)fr.QuadPart);
 # else
     sprintf(buf, "%3ld.%06ld", (long)tm->tv_sec, (long)tm->tv_usec);
-#endif
+# endif
     return buf;
 }
 
-# endif  /* FEAT_PROFILE || FEAT_RELTIME */
+/*
+ * Put the time "msec" past now in "tm".
+ */
+    void
+profile_setlimit(msec, tm)
+    long	msec;
+    proftime_T	*tm;
+{
+    if (msec <= 0)   /* no limit */
+	profile_zero(tm);
+    else
+    {
+# ifdef WIN3264
+	LARGE_INTEGER   fr;
+
+	QueryPerformanceCounter(tm);
+	QueryPerformanceFrequency(&fr);
+	tm->QuadPart += (LONGLONG)((double)msec / 1000.0 * (double)fr.QuadPart);
+# else
+	long	    usec;
+
+	gettimeofday(tm, NULL);
+	usec = (long)tm->tv_usec + (long)msec * 1000;
+	tm->tv_usec = usec % 1000000L;
+	tm->tv_sec += usec / 1000000L;
+# endif
+    }
+}
 
-# if defined(FEAT_PROFILE) || defined(PROTO)
 /*
- * Functions for profiling.
+ * Return TRUE if the current time is past "tm".
  */
-static void script_do_profile __ARGS((scriptitem_T *si));
-static void script_dump_profile __ARGS((FILE *fd));
-static proftime_T prof_wait_time;
+    int
+profile_passed_limit(tm)
+    proftime_T	*tm;
+{
+    proftime_T	now;
+
+# ifdef WIN3264
+    if (tm->QuadPart == 0)  /* timer was not set */
+	return FALSE;
+    QueryPerformanceCounter(&now);
+    return (now.QuadPart > tm->QuadPart);
+# else
+    if (tm->tv_sec == 0)    /* timer was not set */
+	return FALSE;
+    gettimeofday(&now, NULL);
+    return (now.tv_sec > tm->tv_sec
+	    || (now.tv_sec == tm->tv_sec && now.tv_usec > tm->tv_usec));
+# endif
+}
 
 /*
  * Set the time in "tm" to zero.
@@ -914,6 +966,16 @@
 # endif
 }
 
+# endif  /* FEAT_PROFILE || FEAT_RELTIME */
+
+# if defined(FEAT_PROFILE) || defined(PROTO)
+/*
+ * Functions for profiling.
+ */
+static void script_do_profile __ARGS((scriptitem_T *si));
+static void script_dump_profile __ARGS((FILE *fd));
+static proftime_T prof_wait_time;
+
 /*
  * Add the time "tm2" to "tm".
  */
@@ -2827,11 +2889,14 @@
     if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL)
 	    && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp,
 							       FALSE, curbuf))
+    {
 # ifdef FEAT_EVAL
-	return aborting() ? FAIL : OK;
+	retval = aborting() ? FAIL : OK;
 # else
-	return OK;
+	retval = OK;
 # endif
+	goto theend;
+    }
 
     /* Apply SourcePre autocommands, they may get the file. */
     apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf);
diff -Naur vim71.orig/src/ex_docmd.c vim71/src/ex_docmd.c
--- vim71.orig/src/ex_docmd.c	2007-05-07 19:49:38.000000000 +0000
+++ vim71/src/ex_docmd.c	2008-02-14 21:07:34.000000000 +0000
@@ -133,6 +133,7 @@
 static void	get_flags __ARGS((exarg_T *eap));
 #if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
 	|| !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME)
+# define HAVE_EX_SCRIPT_NI
 static void	ex_script_ni __ARGS((exarg_T *eap));
 #endif
 static char_u	*invalid_range __ARGS((exarg_T *eap));
@@ -275,7 +276,6 @@
 static void	ex_swapname __ARGS((exarg_T *eap));
 static void	ex_syncbind __ARGS((exarg_T *eap));
 static void	ex_read __ARGS((exarg_T *eap));
-static void	ex_cd __ARGS((exarg_T *eap));
 static void	ex_pwd __ARGS((exarg_T *eap));
 static void	ex_equal __ARGS((exarg_T *eap));
 static void	ex_sleep __ARGS((exarg_T *eap));
@@ -372,7 +372,7 @@
 static char_u	*arg_all __ARGS((void));
 #ifdef FEAT_SESSION
 static int	makeopens __ARGS((FILE *fd, char_u *dirnow));
-static int	put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp));
+static int	put_view __ARGS((FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx));
 static void	ex_loadview __ARGS((exarg_T *eap));
 static char_u	*get_view_file __ARGS((int c));
 static int	did_lcd;	/* whether ":lcd" was produced for a session */
@@ -666,7 +666,7 @@
 		if (ex_pressedreturn)
 		{
 		    /* go up one line, to overwrite the ":<CR>" line, so the
-		     * output doensn't contain empty lines. */
+		     * output doesn't contain empty lines. */
 		    msg_row = prev_msg_row;
 		    if (prev_msg_row == Rows - 1)
 			msg_row--;
@@ -1741,7 +1741,9 @@
 	}
 
 	/* ignore comment and empty lines */
-	if (*ea.cmd == '"' || *ea.cmd == NUL)
+	if (*ea.cmd == '"')
+	    goto doend;
+	if (*ea.cmd == NUL)
 	{
 	    ex_pressedreturn = TRUE;
 	    goto doend;
@@ -2118,7 +2120,11 @@
 #ifdef FEAT_USR_CMDS
 	    !USER_CMDIDX(ea.cmdidx) &&
 #endif
-	    cmdnames[ea.cmdidx].cmd_func == ex_ni);
+	    (cmdnames[ea.cmdidx].cmd_func == ex_ni
+#ifdef HAVE_EX_SCRIPT_NI
+	     || cmdnames[ea.cmdidx].cmd_func == ex_script_ni
+#endif
+	     ));
 
 #ifndef FEAT_EVAL
     /*
@@ -2654,7 +2660,7 @@
 		errormsg = IObuff;
 	    }
 	    STRCAT(errormsg, ": ");
-	    STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff));
+	    STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff) - 1);
 	}
 	emsg(errormsg);
     }
@@ -2756,7 +2762,7 @@
 
     /*
      * Isolate the command and search for it in the command table.
-     * Exeptions:
+     * Exceptions:
      * - the 'k' command can directly be followed by any character.
      * - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
      *	    but :sre[wind] is another command, as are :scrip[tnames],
@@ -2957,6 +2963,57 @@
 #endif
 
 #if defined(FEAT_EVAL) || defined(PROTO)
+static struct cmdmod
+{
+    char	*name;
+    int		minlen;
+    int		has_count;  /* :123verbose  :3tab */
+} cmdmods[] = {
+    {"aboveleft", 3, FALSE},
+    {"belowright", 3, FALSE},
+    {"botright", 2, FALSE},
+    {"browse", 3, FALSE},
+    {"confirm", 4, FALSE},
+    {"hide", 3, FALSE},
+    {"keepalt", 5, FALSE},
+    {"keepjumps", 5, FALSE},
+    {"keepmarks", 3, FALSE},
+    {"leftabove", 5, FALSE},
+    {"lockmarks", 3, FALSE},
+    {"rightbelow", 6, FALSE},
+    {"sandbox", 3, FALSE},
+    {"silent", 3, FALSE},
+    {"tab", 3, TRUE},
+    {"topleft", 2, FALSE},
+    {"verbose", 4, TRUE},
+    {"vertical", 4, FALSE},
+};
+
+/*
+ * Return length of a command modifier (including optional count).
+ * Return zero when it's not a modifier.
+ */
+    int
+modifier_len(cmd)
+    char_u	*cmd;
+{
+    int		i, j;
+    char_u	*p = cmd;
+
+    if (VIM_ISDIGIT(*cmd))
+	p = skipwhite(skipdigits(cmd));
+    for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i)
+    {
+	for (j = 0; p[j] != NUL; ++j)
+	    if (p[j] != cmdmods[i].name[j])
+		break;
+	if (!isalpha(p[j]) && j >= cmdmods[i].minlen
+					&& (p == cmd || cmdmods[i].has_count))
+	    return j + (p - cmd);
+    }
+    return 0;
+}
+
 /*
  * Return > 0 if an Ex command "name" exists.
  * Return 2 if there is an exact match.
@@ -2971,30 +3028,6 @@
     int		i;
     int		j;
     char_u	*p;
-    static struct cmdmod
-    {
-	char	*name;
-	int	minlen;
-    } cmdmods[] = {
-	{"aboveleft", 3},
-	{"belowright", 3},
-	{"botright", 2},
-	{"browse", 3},
-	{"confirm", 4},
-	{"hide", 3},
-	{"keepalt", 5},
-	{"keepjumps", 5},
-	{"keepmarks", 3},
-	{"leftabove", 5},
-	{"lockmarks", 3},
-	{"rightbelow", 6},
-	{"sandbox", 3},
-	{"silent", 3},
-	{"tab", 3},
-	{"topleft", 2},
-	{"verbose", 4},
-	{"vertical", 4},
-    };
 
     /* Check command modifiers. */
     for (i = 0; i < sizeof(cmdmods) / sizeof(struct cmdmod); ++i)
@@ -3276,32 +3309,27 @@
 
     if (ea.argt & XFILE)
     {
-	int in_quote = FALSE;
-	char_u *bow = NULL;	/* Beginning of word */
+	int	c;
+	int	in_quote = FALSE;
+	char_u	*bow = NULL;	/* Beginning of word */
 
 	/*
 	 * Allow spaces within back-quotes to count as part of the argument
 	 * being expanded.
 	 */
 	xp->xp_pattern = skipwhite(arg);
-	for (p = xp->xp_pattern; *p; )
+	p = xp->xp_pattern;
+	while (*p != NUL)
 	{
-	    if (*p == '\\' && p[1] != NUL)
-		++p;
-#ifdef SPACE_IN_FILENAME
-	    else if (vim_iswhite(*p) && (!(ea.argt & NOSPC) || usefilter))
-#else
-	    else if (vim_iswhite(*p))
+#ifdef FEAT_MBYTE
+	    if (has_mbyte)
+		c = mb_ptr2char(p);
+	    else
 #endif
-	    {
-		p = skipwhite(p);
-		if (in_quote)
-		    bow = p;
-		else
-		    xp->xp_pattern = p;
-		--p;
-	    }
-	    else if (*p == '`')
+		c = *p;
+	    if (c == '\\' && p[1] != NUL)
+		++p;
+	    else if (c == '`')
 	    {
 		if (!in_quote)
 		{
@@ -3310,6 +3338,38 @@
 		}
 		in_quote = !in_quote;
 	    }
+	    /* An argument can contain just about everything, except
+	     * characters that end the command and white space. */
+	    else if (c == '|' || c == '\n' || c == '"' || (vim_iswhite(c)
+#ifdef SPACE_IN_FILENAME
+					 && (!(ea.argt & NOSPC) || usefilter)
+#endif
+		    ))
+	    {
+		while (*p != NUL)
+		{
+#ifdef FEAT_MBYTE
+		    if (has_mbyte)
+			c = mb_ptr2char(p);
+		    else
+#endif
+			c = *p;
+		    if (c == '`' || vim_isfilec_or_wc(c))
+			break;
+#ifdef FEAT_MBYTE
+		    if (has_mbyte)
+			len = (*mb_ptr2len)(p);
+		    else
+#endif
+			len = 1;
+		    mb_ptr_adv(p);
+		}
+		if (in_quote)
+		    bow = p;
+		else
+		    xp->xp_pattern = p;
+		p -= len;
+	    }
 	    mb_ptr_adv(p);
 	}
 
@@ -3401,14 +3461,13 @@
 	case CMD_windo:
 	    return arg;
 
-#ifdef FEAT_SEARCH_EXTRA
+#ifdef FEAT_CMDL_COMPL
+# ifdef FEAT_SEARCH_EXTRA
 	case CMD_match:
 	    if (*arg == NUL || !ends_excmd(*arg))
 	    {
-		/* Dummy call to clear variables. */
-		set_context_in_highlight_cmd(xp, (char_u *)"link n");
-		xp->xp_context = EXPAND_HIGHLIGHT;
-		xp->xp_pattern = arg;
+		/* also complete "None" */
+		set_context_in_echohl_cmd(xp, arg);
 		arg = skipwhite(skiptowhite(arg));
 		if (*arg != NUL)
 		{
@@ -3417,9 +3476,8 @@
 		}
 	    }
 	    return find_nextcmd(arg);
-#endif
+# endif
 
-#ifdef FEAT_CMDL_COMPL
 /*
  * All completion for the +cmdline_compl feature goes here.
  */
@@ -3617,8 +3675,7 @@
 	    break;
 
 	case CMD_echohl:
-	    xp->xp_context = EXPAND_HIGHLIGHT;
-	    xp->xp_pattern = arg;
+	    set_context_in_echohl_cmd(xp, arg);
 	    break;
 #endif
 	case CMD_highlight:
@@ -3874,7 +3931,8 @@
 				curwin->w_cursor.col = 0;
 			    searchcmdlen = 0;
 			    if (!do_search(NULL, c, cmd, 1L,
-				      SEARCH_HIS + SEARCH_MSG + SEARCH_START))
+					SEARCH_HIS + SEARCH_MSG + SEARCH_START,
+					NULL))
 			    {
 				curwin->w_cursor = pos;
 				cmd = NULL;
@@ -3923,7 +3981,7 @@
 					*cmd == '?' ? BACKWARD : FORWARD,
 					(char_u *)"", 1L,
 					SEARCH_MSG + SEARCH_START,
-						      i, (linenr_T)0) != FAIL)
+						i, (linenr_T)0, NULL) != FAIL)
 				lnum = pos.lnum;
 			    else
 			    {
@@ -3997,8 +4055,7 @@
 	eap->errmsg = (char_u *)N_("E319: Sorry, the command is not available in this version");
 }
 
-#if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
-	|| !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME)
+#ifdef HAVE_EX_SCRIPT_NI
 /*
  * Function called for script command which is Not Implemented.  NI!
  * Skips over ":perl <<EOF" constructs.
@@ -4376,7 +4433,7 @@
 			    || vim_strchr(eap->arg, '~') != NULL)
 		    {
 			expand_env_esc(eap->arg, NameBuff, MAXPATHL,
-								 TRUE, NULL);
+							    TRUE, TRUE, NULL);
 			has_wildcards = mch_has_wildcard(NameBuff);
 			p = NameBuff;
 		    }
@@ -4492,7 +4549,8 @@
 	    if (eap->argt & (USECTRLV | XFILE))
 		++p;		/* skip CTRL-V and next char */
 	    else
-		STRCPY(p, p + 1);	/* remove CTRL-V and skip next char */
+				/* remove CTRL-V and skip next char */
+		mch_memmove(p, p + 1, STRLEN(p));
 	    if (*p == NUL)		/* stop at NUL after CTRL-V */
 		break;
 	}
@@ -6650,7 +6708,7 @@
  * The list should be allocated using alloc(), as should each item in the
  * list. This function takes over responsibility for freeing the list.
  *
- * XXX The list is made into the arggument list. This is freed using
+ * XXX The list is made into the argument list. This is freed using
  * FreeWild(), which does a series of vim_free() calls, unless the two defines
  * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
  * routine _fnexplodefree() is used. This may cause problems, but as the drop
@@ -7070,7 +7128,7 @@
 			 : eap->addr_count == 0 ? 0
 					       : (int)eap->line2 + 1) != FAIL)
 	{
-	    do_exedit(eap, NULL);
+	    do_exedit(eap, old_curwin);
 
 	    /* set the alternate buffer for the window we came from */
 	    if (curwin != old_curwin
@@ -7743,6 +7801,7 @@
 free_cd_dir()
 {
     vim_free(prev_dir);
+    prev_dir = NULL;
 }
 #endif
 
@@ -7750,7 +7809,7 @@
 /*
  * ":cd", ":lcd", ":chdir" and ":lchdir".
  */
-    static void
+    void
 ex_cd(eap)
     exarg_T	*eap;
 {
@@ -7768,7 +7827,7 @@
 	if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged()
 							     && !eap->forceit)
 	{
-	    EMSG(_("E747: Cannot change directory, buffer is modifed (add ! to override)"));
+	    EMSG(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
 	    return;
 	}
 
@@ -8399,21 +8458,17 @@
 		    || *arg == '"')
 	    {
 		redir_reg = *arg++;
-		if (*arg == '>' && arg[1] == '>')
+		if (*arg == '>' && arg[1] == '>')  /* append */
 		    arg += 2;
-		else if ((*arg == NUL || (*arg == '>' && arg[1] == NUL)) &&
-			 (islower(redir_reg)
-# ifdef FEAT_CLIPBOARD
-			    || redir_reg == '*'
-			    || redir_reg == '+'
-# endif
-			    || redir_reg == '"'))
+		else
 		{
+		    /* Can use both "@a" and "@a>". */
 		    if (*arg == '>')
 			arg++;
-
-		    /* make register empty */
-		    write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
+		    /* Make register empty when not using @A-@Z and the
+		     * command is valid. */
+		    if (*arg == NUL && !isupper(redir_reg))
+			write_reg_contents(redir_reg, (char_u *)"", -1, FALSE);
 		}
 	    }
 	    if (*arg != NUL)
@@ -8710,7 +8765,8 @@
 	    }
 	    else
 	    {
-		failed |= (put_view(fd, curwin, !using_vdir, flagp) == FAIL);
+		failed |= (put_view(fd, curwin, !using_vdir, flagp,
+								 -1) == FAIL);
 	    }
 	    if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save")
 								      == FAIL)
@@ -9368,7 +9424,7 @@
     if (src > srcstart && src[-1] == '\\')
     {
 	*usedlen = 0;
-	STRCPY(src - 1, src);		/* remove backslash */
+	mch_memmove(src - 1, src, STRLEN(src) + 1);	/* remove backslash */
 	return NULL;
     }
 
@@ -9468,6 +9524,7 @@
 		    *errormsg = (char_u *)_("E495: no autocommand file name to substitute for \"<afile>\"");
 		    return NULL;
 		}
+		result = shorten_fname1(result);
 		break;
 
 	case SPEC_ABUF:		/* buffer number for autocommand */
@@ -9709,6 +9766,8 @@
     int		tabnr;
     win_T	*tab_firstwin;
     frame_T	*tab_topframe;
+    int		cur_arg_idx = 0;
+    int		next_arg_idx = 0;
 
     if (ssop_flags & SSOP_BUFFERS)
 	only_save_windows = FALSE;		/* Save ALL buffers */
@@ -9924,12 +9983,19 @@
 	{
 	    if (!ses_do_win(wp))
 		continue;
-	    if (put_view(fd, wp, wp != edited_win, &ssop_flags) == FAIL)
+	    if (put_view(fd, wp, wp != edited_win, &ssop_flags,
+							 cur_arg_idx) == FAIL)
 		return FAIL;
 	    if (nr > 1 && put_line(fd, "wincmd w") == FAIL)
 		return FAIL;
+	    next_arg_idx = wp->w_arg_idx;
 	}
 
+	/* The argument index in the first tab page is zero, need to set it in
+	 * each window.  For further tab pages it's the window where we do
+	 * "tabedit". */
+	cur_arg_idx = next_arg_idx;
+
 	/*
 	 * Restore cursor to the current window if it's not the first one.
 	 */
@@ -10138,11 +10204,13 @@
  * Caller must make sure 'scrolloff' is zero.
  */
     static int
-put_view(fd, wp, add_edit, flagp)
+put_view(fd, wp, add_edit, flagp, current_arg_idx)
     FILE	*fd;
     win_T	*wp;
     int		add_edit;	/* add ":edit" command to view */
     unsigned	*flagp;		/* vop_flags or ssop_flags */
+    int		current_arg_idx; /* current argument index of the window, use
+				  * -1 if unknown */
 {
     win_T	*save_curwin;
     int		f;
@@ -10172,10 +10240,10 @@
 
     /* Only when part of a session: restore the argument index.  Some
      * arguments may have been deleted, check if the index is valid. */
-    if (wp->w_arg_idx != 0 && wp->w_arg_idx <= WARGCOUNT(wp)
+    if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx <= WARGCOUNT(wp)
 						      && flagp == &ssop_flags)
     {
-	if (fprintf(fd, "%ldnext", (long)wp->w_arg_idx) < 0
+	if (fprintf(fd, "%ldargu", (long)wp->w_arg_idx + 1) < 0
 		|| put_eol(fd) == FAIL)
 	    return FAIL;
 	did_next = TRUE;
@@ -10816,12 +10884,13 @@
     exarg_T	*eap;
 {
     char_u	*p;
+    char_u	*g = NULL;
     char_u	*end;
     int		c;
-    int		mi;
+    int		id;
 
     if (eap->line2 <= 3)
-	mi = eap->line2 - 1;
+	id = eap->line2;
     else
     {
 	EMSG(e_invcmd);
@@ -10830,13 +10899,7 @@
 
     /* First clear any old pattern. */
     if (!eap->skip)
-    {
-	vim_free(curwin->w_match[mi].regprog);
-	curwin->w_match[mi].regprog = NULL;
-	vim_free(curwin->w_match_pat[mi]);
-	curwin->w_match_pat[mi] = NULL;
-	redraw_later(SOME_VALID);	/* always need a redraw */
-    }
+	match_delete(curwin, id, FALSE);
 
     if (ends_excmd(*eap->arg))
 	end = eap->arg;
@@ -10847,15 +10910,7 @@
     {
 	p = skiptowhite(eap->arg);
 	if (!eap->skip)
-	{
-	    curwin->w_match_id[mi] = syn_namen2id(eap->arg,
-							 (int)(p - eap->arg));
-	    if (curwin->w_match_id[mi] == 0)
-	    {
-		EMSG2(_(e_nogroup), eap->arg);
-		return;
-	    }
-	}
+	    g = vim_strnsave(eap->arg, (int)(p - eap->arg));
 	p = skipwhite(p);
 	if (*p == NUL)
 	{
@@ -10879,14 +10934,8 @@
 
 	    c = *end;
 	    *end = NUL;
-	    curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC);
-	    if (curwin->w_match[mi].regprog == NULL)
-	    {
-		EMSG2(_(e_invarg2), p);
-		*end = c;
-		return;
-	    }
-	    curwin->w_match_pat[mi] = vim_strsave(p + 1);
+	    match_add(curwin, g, p + 1, 10, id);
+	    vim_free(g);
 	    *end = c;
 	}
     }
diff -Naur vim71.orig/src/ex_eval.c vim71/src/ex_eval.c
--- vim71.orig/src/ex_eval.c	2007-05-07 19:47:50.000000000 +0000
+++ vim71/src/ex_eval.c	2008-02-14 21:07:33.000000000 +0000
@@ -1551,7 +1551,7 @@
 		}
 		save_cpo  = p_cpo;
 		p_cpo = (char_u *)"";
-		regmatch.regprog = vim_regcomp(pat, TRUE);
+		regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
 		regmatch.rm_ic = FALSE;
 		if (end != NULL)
 		    *end = save_char;
@@ -2269,9 +2269,18 @@
 has_loop_cmd(p)
     char_u	*p;
 {
-    p = skipwhite(p);
-    while (*p == ':')
-	p = skipwhite(p + 1);
+    int		len;
+
+    /* skip modifiers, white space and ':' */
+    for (;;)
+    {
+	while (*p == ' ' || *p == '\t' || *p == ':')
+	    ++p;
+	len = modifier_len(p);
+	if (len == 0)
+	    break;
+	p += len;
+    }
     if ((p[0] == 'w' && p[1] == 'h')
 	    || (p[0] == 'f' && p[1] == 'o' && p[2] == 'r'))
 	return TRUE;
diff -Naur vim71.orig/src/ex_getln.c vim71/src/ex_getln.c
--- vim71.orig/src/ex_getln.c	2007-05-07 19:47:23.000000000 +0000
+++ vim71/src/ex_getln.c	2008-02-14 21:07:34.000000000 +0000
@@ -268,7 +268,9 @@
     {
 	xpc.xp_context = ccline.xp_context;
 	xpc.xp_pattern = ccline.cmdbuff;
+# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
 	xpc.xp_arg = ccline.xp_arg;
+# endif
     }
 #endif
 
@@ -333,7 +335,14 @@
 	quit_more = FALSE;	/* reset after CTRL-D which had a more-prompt */
 
 	cursorcmd();		/* set the cursor on the right spot */
-	c = safe_vgetc();
+
+	/* Get a character.  Ignore K_IGNORE, it should not do anything, such
+	 * as stop completion. */
+	do
+	{
+	    c = safe_vgetc();
+	} while (c == K_IGNORE);
+
 	if (KeyTyped)
 	{
 	    some_key_typed = TRUE;
@@ -484,7 +493,8 @@
 	if (xpc.xp_context == EXPAND_MENUNAMES && p_wmnu)
 	{
 	    /* Hitting <Down> after "emenu Name.": complete submenu */
-	    if (ccline.cmdbuff[ccline.cmdpos - 1] == '.' && c == K_DOWN)
+	    if (c == K_DOWN && ccline.cmdpos > 0
+				  && ccline.cmdbuff[ccline.cmdpos - 1] == '.')
 		c = p_wc;
 	    else if (c == K_UP)
 	    {
@@ -533,9 +543,11 @@
 	    upseg[3] = PATHSEP;
 	    upseg[4] = NUL;
 
-	    if (ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
-		    && c == K_DOWN
-		    && (ccline.cmdbuff[ccline.cmdpos - 2] != '.'
+	    if (c == K_DOWN
+		    && ccline.cmdpos > 0
+		    && ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
+		    && (ccline.cmdpos < 3
+			|| ccline.cmdbuff[ccline.cmdpos - 2] != '.'
 			|| ccline.cmdbuff[ccline.cmdpos - 3] != '.'))
 	    {
 		/* go down a directory */
@@ -636,7 +648,7 @@
 	{
 	    ++no_mapping;
 	    ++allow_keys;
-	    c = safe_vgetc();
+	    c = plain_vgetc();
 	    --no_mapping;
 	    --allow_keys;
 	    /* CTRL-\ e doesn't work when obtaining an expression. */
@@ -730,8 +742,8 @@
 	    /* In Ex mode a backslash escapes a newline. */
 	    if (exmode_active
 		    && c != ESC
-		    && ccline.cmdpos > 0
 		    && ccline.cmdpos == ccline.cmdlen
+		    && ccline.cmdpos > 0
 		    && ccline.cmdbuff[ccline.cmdpos - 1] == '\\')
 	    {
 		if (c == K_KENTER)
@@ -1086,11 +1098,11 @@
 #endif
 		putcmdline('"', TRUE);
 		++no_mapping;
-		i = c = safe_vgetc();	/* CTRL-R <char> */
+		i = c = plain_vgetc();	/* CTRL-R <char> */
 		if (i == Ctrl_O)
 		    i = Ctrl_R;		/* CTRL-R CTRL-O == CTRL-R CTRL-R */
 		if (i == Ctrl_R)
-		    c = safe_vgetc();	/* CTRL-R CTRL-R <char> */
+		    c = plain_vgetc();	/* CTRL-R CTRL-R <char> */
 		--no_mapping;
 #ifdef FEAT_EVAL
 		/*
@@ -1181,10 +1193,10 @@
 	case K_LEFT:
 	case K_S_LEFT:
 	case K_C_LEFT:
+		if (ccline.cmdpos == 0)
+		    goto cmdline_not_changed;
 		do
 		{
-		    if (ccline.cmdpos == 0)
-			break;
 		    --ccline.cmdpos;
 #ifdef FEAT_MBYTE
 		    if (has_mbyte)	/* move to first byte of char */
@@ -1193,7 +1205,8 @@
 #endif
 		    ccline.cmdspos -= cmdline_charsize(ccline.cmdpos);
 		}
-		while ((c == K_S_LEFT || c == K_C_LEFT
+		while (ccline.cmdpos > 0
+			&& (c == K_S_LEFT || c == K_C_LEFT
 			       || (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)))
 			&& ccline.cmdbuff[ccline.cmdpos - 1] != ' ');
 #ifdef FEAT_MBYTE
@@ -1203,7 +1216,8 @@
 		goto cmdline_not_changed;
 
 	case K_IGNORE:
-		goto cmdline_not_changed;	/* Ignore mouse */
+		/* Ignore mouse event or ex_window() result. */
+		goto cmdline_not_changed;
 
 #ifdef FEAT_GUI_W32
 	    /* On Win32 ignore <M-F4>, we get it when closing the window was
@@ -1695,6 +1709,9 @@
 	if (p_is && !cmd_silent && (firstc == '/' || firstc == '?'))
 	{
 	    pos_T	end_pos;
+#ifdef FEAT_RELTIME
+	    proftime_T	tm;
+#endif
 
 	    /* if there is a character waiting, search and redraw later */
 	    if (char_avail())
@@ -1713,8 +1730,18 @@
 		cursor_off();		/* so the user knows we're busy */
 		out_flush();
 		++emsg_off;    /* So it doesn't beep if bad expr */
+#ifdef FEAT_RELTIME
+		/* Set the time limit to half a second. */
+		profile_setlimit(500L, &tm);
+#endif
 		i = do_search(NULL, firstc, ccline.cmdbuff, count,
-			SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK);
+			SEARCH_KEEP + SEARCH_OPT + SEARCH_NOOF + SEARCH_PEEK,
+#ifdef FEAT_RELTIME
+			&tm
+#else
+			NULL
+#endif
+			);
 		--emsg_off;
 		/* if interrupted while searching, behave like it failed */
 		if (got_int)
@@ -2090,11 +2117,11 @@
     garray_T	line_ga;
     char_u	*pend;
     int		startcol = 0;
-    int		c1;
+    int		c1 = 0;
     int		escaped = FALSE;	/* CTRL-V typed */
     int		vcol = 0;
     char_u	*p;
-    int		prev_char = 0;
+    int		prev_char;
 
     /* Switch cursor on now.  This avoids that it happens after the "\n", which
      * confuses the system function that computes tabstops. */
@@ -2147,6 +2174,7 @@
 
 	/* Get one character at a time.  Don't use inchar(), it can't handle
 	 * special characters. */
+	prev_char = c1;
 	c1 = vgetc();
 
 	/*
@@ -2204,7 +2232,6 @@
 redraw:
 		/* redraw the line */
 		msg_col = startcol;
-		windgoto(msg_row, msg_col);
 		vcol = 0;
 		for (p = (char_u *)line_ga.ga_data;
 			  p < (char_u *)line_ga.ga_data + line_ga.ga_len; ++p)
@@ -2223,6 +2250,7 @@
 		    }
 		}
 		msg_clr_eos();
+		windgoto(msg_row, msg_col);
 		continue;
 	    }
 
@@ -2268,7 +2296,6 @@
 	if (IS_SPECIAL(c1))
 	    c1 = '?';
 	((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1;
-	prev_char = c1;
 	if (c1 == '\n')
 	    msg_putchar('\n');
 	else if (c1 == TAB)
@@ -3311,6 +3338,10 @@
  * Return a pointer to alloced memory containing the new string.
  * Return NULL for failure.
  *
+ * "orig" is the originally expanded string, copied to allocated memory.  It
+ * should either be kept in orig_save or freed.  When "mode" is WILD_NEXT or
+ * WILD_PREV "orig" should be NULL.
+ *
  * Results are cached in xp->xp_files and xp->xp_numfiles, except when "mode"
  * is WILD_EXPAND_FREE or WILD_ALL.
  *
@@ -3344,6 +3375,7 @@
     char_u	*ss = NULL;
     static int	findex;
     static char_u *orig_save = NULL;	/* kept value of orig */
+    int		orig_saved = FALSE;
     int		i;
     long_u	len;
     int		non_suf_match;		/* number without matching suffix */
@@ -3395,7 +3427,7 @@
 	    return NULL;
     }
 
-/* free old names */
+    /* free old names */
     if (xp->xp_numfiles != -1 && mode != WILD_ALL && mode != WILD_LONGEST)
     {
 	FreeWild(xp->xp_numfiles, xp->xp_files);
@@ -3412,6 +3444,7 @@
     {
 	vim_free(orig_save);
 	orig_save = orig;
+	orig_saved = TRUE;
 
 	/*
 	 * Do the expansion.
@@ -3536,6 +3569,10 @@
     if (mode == WILD_EXPAND_FREE || mode == WILD_ALL)
 	ExpandCleanup(xp);
 
+    /* Free "orig" if it wasn't stored in "orig_save". */
+    if (!orig_saved)
+	vim_free(orig);
+
     return ss;
 }
 
@@ -4054,6 +4091,7 @@
 	     * ~ would be at the start of the file name, but not the tail.
 	     * $ could be anywhere in the tail.
 	     * ` could be anywhere in the file name.
+	     * When the name ends in '$' don't add a star, remove the '$'.
 	     */
 	    tail = gettail(retval);
 	    if ((*retval != '~' || tail != retval)
@@ -4061,6 +4099,8 @@
 		    && vim_strchr(tail, '$') == NULL
 		    && vim_strchr(retval, '`') == NULL)
 		retval[len++] = '*';
+	    else if (len > 0 && retval[len - 1] == '$')
+		--len;
 	    retval[len] = NUL;
 	}
     }
@@ -4148,13 +4188,19 @@
 
 #ifdef FEAT_EVAL
     if (ccline.cmdfirstc == '=')
+    {
+# ifdef FEAT_CMDL_COMPL
 	/* pass CMD_SIZE because there is no real command */
 	set_context_for_expression(xp, str, CMD_SIZE);
+# endif
+    }
     else if (ccline.input_fn)
     {
 	xp->xp_context = ccline.xp_context;
 	xp->xp_pattern = ccline.cmdbuff;
+# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
 	xp->xp_arg = ccline.xp_arg;
+# endif
     }
     else
 #endif
@@ -4295,10 +4341,11 @@
 			    && pat[i + 1] == '\\'
 			    && pat[i + 2] == '\\'
 			    && pat[i + 3] == ' ')
-			STRCPY(pat + i, pat + i + 3);
+			mch_memmove(pat + i, pat + i + 3,
+						     STRLEN(pat + i + 3) + 1);
 		    if (xp->xp_backslash == XP_BS_ONE
 			    && pat[i + 1] == ' ')
-			STRCPY(pat + i, pat + i + 1);
+			mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i));
 		}
 	}
 
@@ -4502,6 +4549,12 @@
     if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS)
 	sort_strings(*file, *num_file);
 
+#ifdef FEAT_CMDL_COMPL
+    /* Reset the variables used for special highlight names expansion, so that
+     * they don't show up when getting normal highlight names by ID. */
+    reset_expand_highlight();
+#endif
+
     return OK;
 }
 
@@ -4535,7 +4588,7 @@
     pat = vim_strsave(filepat);
     for (i = 0; pat[i]; ++i)
 	if (pat[i] == '\\' && pat[i + 1] == ' ')
-	    STRCPY(pat + i, pat + i + 1);
+	    mch_memmove(pat + i, pat + i + 1, STRLEN(pat + i));
 
     flags |= EW_FILE | EW_EXEC;
 
@@ -4615,7 +4668,7 @@
 static void * call_user_expand_func __ARGS((void *(*user_expand_func) __ARGS((char_u *, int, char_u **, int)), expand_T	*xp, int *num_file, char_u ***file));
 
 /*
- * call "user_expand_func()" to invoke a user defined VimL function and return
+ * Call "user_expand_func()" to invoke a user defined VimL function and return
  * the result (either a string or a List).
  */
     static void *
@@ -4637,11 +4690,22 @@
     *num_file = 0;
     *file = NULL;
 
-    keep = ccline.cmdbuff[ccline.cmdlen];
-    ccline.cmdbuff[ccline.cmdlen] = 0;
-    sprintf((char *)num, "%d", ccline.cmdpos);
+    if (ccline.cmdbuff == NULL)
+    {
+	/* Completion from Insert mode, pass fake arguments. */
+	keep = 0;
+	sprintf((char *)num, "%d", (int)STRLEN(xp->xp_pattern));
+	args[1] = xp->xp_pattern;
+    }
+    else
+    {
+	/* Completion on the command line, pass real arguments. */
+	keep = ccline.cmdbuff[ccline.cmdlen];
+	ccline.cmdbuff[ccline.cmdlen] = 0;
+	sprintf((char *)num, "%d", ccline.cmdpos);
+	args[1] = ccline.cmdbuff;
+    }
     args[0] = xp->xp_pattern;
-    args[1] = ccline.cmdbuff;
     args[2] = num;
 
     /* Save the cmdline, we don't know what the function may do. */
@@ -4654,8 +4718,8 @@
 
     ccline = save_ccline;
     current_SID = save_current_SID;
-
-    ccline.cmdbuff[ccline.cmdlen] = keep;
+    if (ccline.cmdbuff != NULL)
+	ccline.cmdbuff[ccline.cmdlen] = keep;
 
     return ret;
 }
@@ -5907,7 +5971,7 @@
 
 # ifdef FEAT_AUTOCMD
     /* Don't execute autocommands while creating the window. */
-    ++autocmd_block;
+    block_autocmds();
 # endif
     /* don't use a new tab page */
     cmdmod.tab = 0;
@@ -5916,6 +5980,9 @@
     if (win_split((int)p_cwh, WSP_BOT) == FAIL)
     {
 	beep_flush();
+# ifdef FEAT_AUTOCMD
+	unblock_autocmds();
+# endif
 	return K_IGNORE;
     }
     cmdwin_type = ccline.cmdfirstc;
@@ -5938,7 +6005,7 @@
 
 # ifdef FEAT_AUTOCMD
     /* Do execute autocommands for setting the filetype (load syntax). */
-    --autocmd_block;
+    unblock_autocmds();
 # endif
 
     /* Showing the prompt may have set need_wait_return, reset it. */
@@ -6092,7 +6159,7 @@
 
 # ifdef FEAT_AUTOCMD
 	/* Don't execute autocommands while deleting the window. */
-	++autocmd_block;
+	block_autocmds();
 # endif
 	wp = curwin;
 	bp = curbuf;
@@ -6104,7 +6171,7 @@
 	win_size_restore(&winsizes);
 
 # ifdef FEAT_AUTOCMD
-	--autocmd_block;
+	unblock_autocmds();
 # endif
     }
 
diff -Naur vim71.orig/src/feature.h vim71/src/feature.h
--- vim71.orig/src/feature.h	2007-05-07 19:33:19.000000000 +0000
+++ vim71/src/feature.h	2008-02-14 21:07:32.000000000 +0000
@@ -673,7 +673,7 @@
 # define ESC_CHG_TO_ENG_MODE		/* if defined, when ESC pressed,
 					 * turn to english mode
 					 */
-# if !defined(FEAT_XFONTSET) && defined(HAVE_X11)
+# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) && !defined(HAVE_GTK2)
 #  define FEAT_XFONTSET			/* Hangul input requires xfontset */
 # endif
 # if defined(FEAT_XIM) && !defined(LINT)
diff -Naur vim71.orig/src/fileio.c vim71/src/fileio.c
--- vim71.orig/src/fileio.c	2007-05-10 11:29:44.000000000 +0000
+++ vim71/src/fileio.c	2008-02-14 21:07:34.000000000 +0000
@@ -44,6 +44,10 @@
 /* Is there any system that doesn't have access()? */
 #define USE_MCH_ACCESS
 
+#if defined(sun) && defined(S_ISCHR)
+# define OPEN_CHR_FILES
+static int is_dev_fd_file(char_u *fname);
+#endif
 #ifdef FEAT_MBYTE
 static char_u *next_fenc __ARGS((char_u **pp));
 # ifdef FEAT_EVAL
@@ -110,7 +114,7 @@
 {
     int		bw_fd;		/* file descriptor */
     char_u	*bw_buf;	/* buffer with data to be written */
-    int		bw_len;	/* lenght of data */
+    int		bw_len;		/* length of data */
 #ifdef HAS_BW_FLAGS
     int		bw_flags;	/* FIO_ flags */
 #endif
@@ -217,11 +221,12 @@
 {
     int		fd = 0;
     int		newfile = (flags & READ_NEW);
-    int		set_options = newfile || (eap != NULL && eap->read_edit);
     int		check_readonly;
     int		filtering = (flags & READ_FILTER);
     int		read_stdin = (flags & READ_STDIN);
     int		read_buffer = (flags & READ_BUFFER);
+    int		set_options = newfile || read_buffer
+					   || (eap != NULL && eap->read_edit);
     linenr_T	read_buf_lnum = 1;	/* next line to read from curbuf */
     colnr_T	read_buf_col = 0;	/* next char to read from this line */
     char_u	c;
@@ -406,6 +411,10 @@
 # ifdef S_ISSOCK
 		      && !S_ISSOCK(perm)	    /* ... or socket */
 # endif
+# ifdef OPEN_CHR_FILES
+		      && !(S_ISCHR(perm) && is_dev_fd_file(fname))
+			/* ... or a character special file named /dev/fd/<n> */
+# endif
 						)
 	{
 	    if (S_ISDIR(perm))
@@ -424,7 +433,7 @@
 	 */
 	if (!p_odev && mch_nodetype(fname) == NODE_WRITABLE)
 	{
-	    filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option"), 0);
+	    filemess(curbuf, fname, (char_u *)_("is a device (disabled with 'opendevice' option)"), 0);
 	    msg_end();
 	    msg_scroll = msg_save;
 	    return FAIL;
@@ -642,10 +651,16 @@
 
     if (set_options)
     {
-	curbuf->b_p_eol = TRUE;
-	curbuf->b_start_eol = TRUE;
+	/* Don't change 'eol' if reading from buffer as it will already be
+	 * correctly set when reading stdin. */
+	if (!read_buffer)
+	{
+	    curbuf->b_p_eol = TRUE;
+	    curbuf->b_start_eol = TRUE;
+	}
 #ifdef FEAT_MBYTE
 	curbuf->b_p_bomb = FALSE;
+	curbuf->b_start_bomb = FALSE;
 #endif
     }
 
@@ -904,7 +919,10 @@
 	file_rewind = FALSE;
 #ifdef FEAT_MBYTE
 	if (set_options)
+	{
 	    curbuf->b_p_bomb = FALSE;
+	    curbuf->b_start_bomb = FALSE;
+	}
 	conv_error = 0;
 #endif
     }
@@ -1353,7 +1371,10 @@
 		    size -= blen;
 		    mch_memmove(ptr, ptr + blen, (size_t)size);
 		    if (set_options)
+		    {
 			curbuf->b_p_bomb = TRUE;
+			curbuf->b_start_bomb = TRUE;
+		    }
 		}
 
 		if (fio_flags == FIO_UCSBOM)
@@ -2265,6 +2286,13 @@
 	    }
 #  endif
 # endif
+# ifdef OPEN_CHR_FILES
+	    if (S_ISCHR(perm))			    /* or character special */
+	    {
+		STRCAT(IObuff, _("[character special]"));
+		c = TRUE;
+	    }
+# endif
 #endif
 	    if (curbuf->b_p_ro)
 	    {
@@ -2464,6 +2492,25 @@
     return OK;
 }
 
+#ifdef OPEN_CHR_FILES
+/*
+ * Returns TRUE if the file name argument is of the form "/dev/fd/\d\+",
+ * which is the name of files used for process substitution output by
+ * some shells on some operating systems, e.g., bash on SunOS.
+ * Do not accept "/dev/fd/[012]", opening these may hang Vim.
+ */
+    static int
+is_dev_fd_file(fname)
+    char_u	*fname;
+{
+    return (STRNCMP(fname, "/dev/fd/", 8) == 0
+	    && VIM_ISDIGIT(fname[8])
+	    && *skipdigits(fname + 9) == NUL
+	    && (fname[9] != NUL
+		|| (fname[8] != '0' && fname[8] != '1' && fname[8] != '2')));
+}
+#endif
+
 #ifdef FEAT_MBYTE
 
 /*
@@ -2734,6 +2781,32 @@
 #endif
 
 /*
+ * Return TRUE if a file appears to be read-only from the file permissions.
+ */
+    int
+check_file_readonly(fname, perm)
+    char_u	*fname;		/* full path to file */
+    int		perm;		/* known permissions on file */
+{
+#ifndef USE_MCH_ACCESS
+    int	    fd = 0;
+#endif
+
+    return (
+#ifdef USE_MCH_ACCESS
+# ifdef UNIX
+	(perm & 0222) == 0 ||
+# endif
+	mch_access((char *)fname, W_OK)
+#else
+	(fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
+					? TRUE : (close(fd), FALSE)
+#endif
+	);
+}
+
+
+/*
  * buf_write() - write to file "fname" lines "start" through "end"
  *
  * We do our own buffering here because fwrite() is so slow.
@@ -3142,7 +3215,8 @@
      * Get information about original file (if there is one).
      */
 #if defined(UNIX) && !defined(ARCHIE)
-    st_old.st_dev = st_old.st_ino = 0;
+    st_old.st_dev = 0;
+    st_old.st_ino = 0;
     perm = -1;
     if (mch_stat((char *)fname, &st_old) < 0)
 	newfile = TRUE;
@@ -3219,17 +3293,8 @@
 	 * Check if the file is really writable (when renaming the file to
 	 * make a backup we won't discover it later).
 	 */
-	file_readonly = (
-# ifdef USE_MCH_ACCESS
-#  ifdef UNIX
-		    (perm & 0222) == 0 ||
-#  endif
-		    mch_access((char *)fname, W_OK)
-# else
-		    (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
-						   ? TRUE : (close(fd), FALSE)
-# endif
-		    );
+	file_readonly = check_file_readonly(fname, (int)perm);
+
 	if (!forceit && file_readonly)
 	{
 	    if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
@@ -4193,7 +4258,8 @@
 	 * they don't it adds one.
 	 * With other RMS structures it works perfect without this fix.
 	 */
-	if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
+	if (buf->b_fab_rfm == FAB$C_VFC
+		|| ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
 	{
 	    int b2write;
 
@@ -5495,6 +5561,30 @@
 }
 #endif
 
+#if defined(FEAT_VIMINFO) || defined(FEAT_BROWSE) || \
+    defined(FEAT_QUICKFIX) || defined(FEAT_AUTOCMD) || defined(PROTO)
+/*
+ * Try to find a shortname by comparing the fullname with the current
+ * directory.
+ * Returns "full_path" or pointer into "full_path" if shortened.
+ */
+    char_u *
+shorten_fname1(full_path)
+    char_u	*full_path;
+{
+    char_u	dirname[MAXPATHL];
+    char_u	*p = full_path;
+
+    if (mch_dirname(dirname, MAXPATHL) == OK)
+    {
+	p = shorten_fname(full_path, dirname);
+	if (p == NULL || *p == NUL)
+	    p = full_path;
+    }
+    return p;
+}
+#endif
+
 /*
  * Try to find a shortname by comparing the fullname with the current
  * directory.
@@ -7107,6 +7197,7 @@
 
 static event_T	last_event;
 static int	last_group;
+static int	autocmd_blocked = 0;	/* block all autocmds */
 
 /*
  * Show the autocommands for one AutoPat.
@@ -8396,7 +8487,7 @@
      * Quickly return if there are no autocommands for this event or
      * autocommands are blocked.
      */
-    if (first_autopat[(int)event] == NULL || autocmd_block > 0)
+    if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
 	goto BYPASS_AU;
 
     /*
@@ -8461,6 +8552,8 @@
 
     /*
      * Set the file name to be used for <afile>.
+     * Make a copy to avoid that changing a buffer name or directory makes it
+     * invalid.
      */
     if (fname_io == NULL)
     {
@@ -8473,6 +8566,8 @@
     }
     else
 	autocmd_fname = fname_io;
+    if (autocmd_fname != NULL)
+	autocmd_fname = FullName_save(autocmd_fname, FALSE);
 
     /*
      * Set the buffer number to be used for <abuf>.
@@ -8655,6 +8750,7 @@
     vim_free(sourcing_name);
     sourcing_name = save_sourcing_name;
     sourcing_lnum = save_sourcing_lnum;
+    vim_free(autocmd_fname);
     autocmd_fname = save_autocmd_fname;
     autocmd_bufnr = save_autocmd_bufnr;
     autocmd_match = save_autocmd_match;
@@ -8710,6 +8806,40 @@
     return retval;
 }
 
+# ifdef FEAT_EVAL
+static char_u	*old_termresponse = NULL;
+# endif
+
+/*
+ * Block triggering autocommands until unblock_autocmd() is called.
+ * Can be used recursively, so long as it's symmetric.
+ */
+    void
+block_autocmds()
+{
+# ifdef FEAT_EVAL
+    /* Remember the value of v:termresponse. */
+    if (autocmd_blocked == 0)
+	old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
+# endif
+    ++autocmd_blocked;
+}
+
+    void
+unblock_autocmds()
+{
+    --autocmd_blocked;
+
+# ifdef FEAT_EVAL
+    /* When v:termresponse was set while autocommands were blocked, trigger
+     * the autocommands now.  Esp. useful when executing a shell command
+     * during startup (vimdiff). */
+    if (autocmd_blocked == 0
+		      && get_vim_var_str(VV_TERMRESPONSE) != old_termresponse)
+	apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, FALSE, curbuf);
+# endif
+}
+
 /*
  * Find next autocommand pattern that matches.
  */
diff -Naur vim71.orig/src/fold.c vim71/src/fold.c
--- vim71.orig/src/fold.c	2007-05-07 19:46:32.000000000 +0000
+++ vim71/src/fold.c	2008-02-14 21:07:34.000000000 +0000
@@ -858,7 +858,14 @@
 	    || foldmethodIsDiff(wp)
 #endif
 	    || foldmethodIsSyntax(wp))
+    {
+	int save_got_int = got_int;
+
+	/* reset got_int here, otherwise it won't work */
+	got_int = FALSE;
 	foldUpdateIEMS(wp, top, bot);
+	got_int |= save_got_int;
+    }
 }
 
 /* foldUpdateAll() {{{2 */
@@ -2669,6 +2676,7 @@
     if (fp->fd_len < flp->lnum - fp->fd_top)
     {
 	fp->fd_len = flp->lnum - fp->fd_top;
+	fp->fd_small = MAYBE;
 	fold_changed = TRUE;
     }
 
diff -Naur vim71.orig/src/getchar.c vim71/src/getchar.c
--- vim71.orig/src/getchar.c	2007-05-07 19:18:20.000000000 +0000
+++ vim71/src/getchar.c	2008-02-14 21:07:33.000000000 +0000
@@ -253,8 +253,9 @@
 	return;
     }
     else if (buf->bh_index != 0)
-	STRCPY(buf->bh_first.b_next->b_str,
-				 buf->bh_first.b_next->b_str + buf->bh_index);
+	mch_memmove(buf->bh_first.b_next->b_str,
+		    buf->bh_first.b_next->b_str + buf->bh_index,
+		    STRLEN(buf->bh_first.b_next->b_str + buf->bh_index) + 1);
     buf->bh_index = 0;
 
     if (buf->bh_space >= (int)slen)
@@ -1278,8 +1279,14 @@
     void
 free_typebuf()
 {
-    vim_free(typebuf.tb_buf);
-    vim_free(typebuf.tb_noremap);
+    if (typebuf.tb_buf == typebuf_init)
+	EMSG2(_(e_intern2), "Free typebuf 1");
+    else
+	vim_free(typebuf.tb_buf);
+    if (typebuf.tb_buf == noremapbuf_init)
+	EMSG2(_(e_intern2), "Free typebuf 2");
+    else
+	vim_free(typebuf.tb_noremap);
 }
 
 /*
@@ -1358,6 +1365,11 @@
 	EMSG(_(e_nesting));
 	return;
     }
+#ifdef FEAT_EVAL
+    if (ignore_script)
+	/* Not reading from script, also don't open one.  Warning message? */
+	return;
+#endif
 
     if (scriptin[curscript] != NULL)	/* already reading script */
 	++curscript;
@@ -1596,8 +1608,16 @@
 		continue;
 	    }
 #endif
-
 #ifdef FEAT_GUI
+	    /* Handle focus event here, so that the caller doesn't need to
+	     * know about it.  Return K_IGNORE so that we loop once (needed if
+	     * 'lazyredraw' is set). */
+	    if (c == K_FOCUSGAINED || c == K_FOCUSLOST)
+	    {
+		ui_focus_change(c == K_FOCUSGAINED);
+		c = K_IGNORE;
+	    }
+
 	    /* Translate K_CSI to CSI.  The special key is only used to avoid
 	     * it being recognized as the start of a special key. */
 	    if (c == K_CSI)
@@ -1741,6 +1761,22 @@
 }
 
 /*
+ * Like safe_vgetc(), but loop to handle K_IGNORE.
+ * Also ignore scrollbar events.
+ */
+    int
+plain_vgetc()
+{
+    int c;
+
+    do
+    {
+	c = safe_vgetc();
+    } while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR);
+    return c;
+}
+
+/*
  * Check if a character is available, such that vgetc() will not block.
  * If the next character is a special character or multi-byte, the returned
  * character is not valid!.
@@ -2321,7 +2357,7 @@
 						   current_menu->silent[idx]);
 				}
 			    }
-#endif /* FEAT_GUI */
+#endif /* FEAT_GUI && FEAT_MENU */
 			    continue;	/* try mapping again */
 			}
 
@@ -2837,11 +2873,15 @@
     undo_off = FALSE;		    /* restart undo now */
 
     /*
-     * first try script file
-     *	If interrupted: Stop reading script files.
+     * Get a character from a script file if there is one.
+     * If interrupted: Stop reading script files, close them all.
      */
     script_char = -1;
-    while (scriptin[curscript] != NULL && script_char < 0)
+    while (scriptin[curscript] != NULL && script_char < 0
+#ifdef FEAT_EVAL
+	    && !ignore_script
+#endif
+	    )
     {
 	if (got_int || (script_char = getc(scriptin[curscript])) < 0)
 	{
diff -Naur vim71.orig/src/globals.h vim71/src/globals.h
--- vim71.orig/src/globals.h	2007-05-07 19:44:26.000000000 +0000
+++ vim71/src/globals.h	2008-02-14 21:07:33.000000000 +0000
@@ -301,13 +301,17 @@
 #endif
 
 #ifdef FEAT_EVAL
-/* Garbage collection can only take place when we are sure there are no Lists
+/*
+ * Garbage collection can only take place when we are sure there are no Lists
  * or Dictionaries being used internally.  This is flagged with
  * "may_garbage_collect" when we are at the toplevel.
  * "want_garbage_collect" is set by the garbagecollect() function, which means
- * we do garbage collection before waiting for a char at the toplevel. */
+ * we do garbage collection before waiting for a char at the toplevel.
+ * "garbage_collect_at_exit" indicates garbagecollect(1) was called.
+ */
 EXTERN int	may_garbage_collect INIT(= FALSE);
 EXTERN int	want_garbage_collect INIT(= FALSE);
+EXTERN int	garbage_collect_at_exit INIT(= FALSE);
 
 /* ID of script being sourced or was sourced to define the current function. */
 EXTERN scid_T	current_SID INIT(= 0);
@@ -362,7 +366,6 @@
 EXTERN int	autocmd_busy INIT(= FALSE);	/* Is apply_autocmds() busy? */
 EXTERN int	autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */
 EXTERN int	autocmd_no_leave INIT(= FALSE); /* *Leave autocmds disabled */
-EXTERN int	autocmd_block INIT(= 0);	/* block all autocmds */
 EXTERN int	modified_was_set;		/* did ":set modified" */
 EXTERN int	did_filetype INIT(= FALSE);	/* FileType event found */
 EXTERN int	keep_filetype INIT(= FALSE);	/* value for did_filetype when
@@ -801,7 +804,7 @@
 EXTERN int (*mb_char2bytes) __ARGS((int c, char_u *buf)) INIT(= latin_char2bytes);
 EXTERN int (*mb_ptr2cells) __ARGS((char_u *p)) INIT(= latin_ptr2cells);
 EXTERN int (*mb_char2cells) __ARGS((int c)) INIT(= latin_char2cells);
-EXTERN int (*mb_off2cells) __ARGS((unsigned off)) INIT(= latin_off2cells);
+EXTERN int (*mb_off2cells) __ARGS((unsigned off, unsigned max_off)) INIT(= latin_off2cells);
 EXTERN int (*mb_ptr2char) __ARGS((char_u *p)) INIT(= latin_ptr2char);
 EXTERN int (*mb_head_off) __ARGS((char_u *base, char_u *p)) INIT(= latin_head_off);
 
@@ -876,7 +879,7 @@
 EXTERN int no_mapping INIT(= FALSE);	/* currently no mapping allowed */
 EXTERN int no_zero_mapping INIT(= 0);	/* mapping zero not allowed */
 EXTERN int allow_keys INIT(= FALSE);	/* allow key codes when no_mapping
-					     * is set */
+					 * is set */
 EXTERN int no_u_sync INIT(= 0);		/* Don't call u_sync() */
 
 EXTERN int restart_edit INIT(= 0);	/* call edit when next cmd finished */
@@ -951,6 +954,9 @@
 EXTERN int	ex_normal_busy INIT(= 0); /* recursiveness of ex_normal() */
 EXTERN int	ex_normal_lock INIT(= 0); /* forbid use of ex_normal() */
 #endif
+#ifdef FEAT_EVAL
+EXTERN int	ignore_script INIT(= FALSE);  /* ignore script input */
+#endif
 EXTERN int	stop_insert_mode;	/* for ":stopinsert" and 'insertmode' */
 
 EXTERN int	KeyTyped;		/* TRUE if user typed current char */
@@ -1252,6 +1258,14 @@
 EXTERN int	echo_wid_arg INIT(= FALSE);	/* --echo-wid argument */
 #endif
 
+#ifdef FEAT_GUI_W32
+/*
+ * The value of the --windowid argument.
+ * For embedding gvim inside another application.
+ */
+EXTERN int	win_socket_id INIT(= 0);
+#endif
+
 #if defined(FEAT_CLIENTSERVER) || defined(FEAT_EVAL)
 EXTERN int	typebuf_was_filled INIT(= FALSE); /* received text from client
 						     or from feedkeys() */
diff -Naur vim71.orig/src/gui.c vim71/src/gui.c
--- vim71.orig/src/gui.c	2007-05-07 19:50:55.000000000 +0000
+++ vim71/src/gui.c	2008-02-14 21:07:34.000000000 +0000
@@ -1080,7 +1080,8 @@
 		cur_width = gui.char_width;
 	    }
 #ifdef FEAT_MBYTE
-	    if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col) > 1)
+	    if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col,
+				    LineOffset[gui.row] + screen_Columns) > 1)
 	    {
 		/* Double wide character. */
 		if (shape_table[idx].shape != SHAPE_VER)
@@ -1159,7 +1160,7 @@
 #endif
 
 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
- 	|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC))
+	|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC))
     if (gui_has_tabline())
 	text_area_y += gui.tabline_height;
 #endif
@@ -1293,11 +1294,7 @@
     out_flush();
 
     gui.num_cols = (pixel_width - gui_get_base_width()) / gui.char_width;
-    gui.num_rows = (pixel_height - gui_get_base_height()
-#if !defined(FEAT_GUI_PHOTON) && !defined(FEAT_GUI_MSWIN)
-				    + (gui.char_height / 2)
-#endif
-					) / gui.char_height;
+    gui.num_rows = (pixel_height - gui_get_base_height()) / gui.char_height;
 
     gui_position_components(pixel_width);
 
@@ -3733,8 +3730,10 @@
     sb->value = value;
 
 #ifdef USE_ON_FLY_SCROLL
-    /* When not allowed to do the scrolling right now, return. */
-    if (dont_scroll || input_available())
+    /* When not allowed to do the scrolling right now, return.
+     * This also checked input_available(), but that causes the first click in
+     * a scrollbar to be ignored when Vim doesn't have focus. */
+    if (dont_scroll)
 	return;
 #endif
 #ifdef FEAT_INS_EXPAND
@@ -4213,7 +4212,19 @@
 #endif
 	    )
     {
-	redraw_win_later(wp, VALID);
+	int type = VALID;
+
+#ifdef FEAT_INS_EXPAND
+	if (pum_visible())
+	{
+	    type = NOT_VALID;
+	    wp->w_lines_valid = 0;
+	}
+#endif
+	/* Don't set must_redraw here, it may cause the popup menu to
+	 * disappear when losing focus after a scrollbar drag. */
+	if (wp->w_redr_type < type)
+	    wp->w_redr_type = type;
 	updateWindow(wp);   /* update window, status line, and cmdline */
     }
 
@@ -4518,7 +4529,18 @@
     xim_set_focus(in_focus);
 # endif
 
-    ui_focus_change(in_focus);
+    /* Put events in the input queue only when allowed.
+     * ui_focus_change() isn't called directly, because it invokes
+     * autocommands and that must not happen asynchronously. */
+    if (!hold_gui_events)
+    {
+	char_u  bytes[3];
+
+	bytes[0] = CSI;
+	bytes[1] = KS_EXTRA;
+	bytes[2] = in_focus ? (int)KE_FOCUSGAINED : (int)KE_FOCUSLOST;
+	add_to_input_buf(bytes, 3);
+    }
 #endif
 }
 
@@ -5026,7 +5048,7 @@
 	/* Search for the next match. */
 	i = msg_scroll;
 	do_search(NULL, down ? '/' : '?', ga.ga_data, 1L,
-						    SEARCH_MSG + SEARCH_MARK);
+					      SEARCH_MSG + SEARCH_MARK, NULL);
 	msg_scroll = i;	    /* don't let an error message set msg_scroll */
     }
 
@@ -5117,7 +5139,7 @@
 		p = vim_strsave_escaped(fnames[i], (char_u *)"\\ \t\"|");
 # endif
 		if (p != NULL)
-		    add_to_input_buf(p, (int)STRLEN(p));
+		    add_to_input_buf_csi(p, (int)STRLEN(p));
 		vim_free(p);
 		vim_free(fnames[i]);
 	    }
diff -Naur vim71.orig/src/gui.h vim71/src/gui.h
--- vim71.orig/src/gui.h	2007-05-07 19:50:58.000000000 +0000
+++ vim71/src/gui.h	2008-02-14 21:07:31.000000000 +0000
@@ -460,7 +460,6 @@
     WindowPtr	VimWindow;
     MenuHandle	MacOSHelpMenu;	    /* Help menu provided by the MacOS */
     int		MacOSHelpItems;	    /* Nr of help-items supplied by MacOS */
-    int		MacOSHaveCntxMenu;  /* Contextual menu available */
     WindowPtr	wid;		    /* Window id of text area */
     int		visibility;	    /* Is window partially/fully obscured? */
 #endif
diff -Naur vim71.orig/src/gui_gtk.c vim71/src/gui_gtk.c
--- vim71.orig/src/gui_gtk.c	2007-05-10 08:37:37.000000000 +0000
+++ vim71/src/gui_gtk.c	2008-02-14 21:07:33.000000000 +0000
@@ -53,8 +53,8 @@
 # ifdef bindtextdomain
 #  undef bindtextdomain
 # endif
-# ifdef bindtextdomain_codeset
-#  undef bindtextdomain_codeset
+# ifdef bind_textdomain_codeset
+#  undef bind_textdomain_codeset
 # endif
 # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
 #  define ENABLE_NLS	/* so the texts in the dialog boxes are translated */
@@ -1272,7 +1272,6 @@
     GtkWidget		*fc;
 #endif
     char_u		dirbuf[MAXPATHL];
-    char_u		*p;
 
 # ifdef HAVE_GTK2
     title = CONVERT_TO_UTF8(title);
@@ -1363,11 +1362,7 @@
 	return NULL;
 
     /* shorten the file name if possible */
-    mch_dirname(dirbuf, MAXPATHL);
-    p = shorten_fname(gui.browse_fname, dirbuf);
-    if (p == NULL)
-	p = gui.browse_fname;
-    return vim_strsave(p);
+    return vim_strsave(shorten_fname1(gui.browse_fname));
 }
 
 #if defined(HAVE_GTK2) || defined(PROTO)
@@ -1427,11 +1422,7 @@
 	return NULL;
 
     /* shorten the file name if possible */
-    mch_dirname(dirbuf, MAXPATHL);
-    p = shorten_fname(dirname, dirbuf);
-    if (p == NULL || *p == NUL)
-	p = dirname;
-    p = vim_strsave(p);
+    p = vim_strsave(shorten_fname1(dirname));
     g_free(dirname);
     return p;
 
@@ -1630,11 +1621,14 @@
  */
 /*ARGSUSED*/
     static int
-dlg_key_press_event(GtkWidget * widget, GdkEventKey * event, CancelData *data)
+dlg_key_press_event(GtkWidget *widget, GdkEventKey *event, CancelData *data)
 {
-    /* Ignore hitting Enter when there is no default button. */
-    if (data->ignore_enter && event->keyval == GDK_Return)
+    /* Ignore hitting Enter (or Space) when there is no default button. */
+    if (data->ignore_enter && (event->keyval == GDK_Return
+						     || event->keyval == ' '))
 	return TRUE;
+    else    /* A different key was pressed, return to normal behavior */
+	data->ignore_enter = FALSE;
 
     if (event->keyval != GDK_Escape && event->keyval != GDK_Return)
 	return FALSE;
@@ -2224,6 +2218,13 @@
 {
     DialogInfo *di = (DialogInfo *)data;
 
+    /* Ignore hitting Enter (or Space) when there is no default button. */
+    if (di->ignore_enter && (event->keyval == GDK_Return
+						     || event->keyval == ' '))
+	return TRUE;
+    else    /* A different key was pressed, return to normal behavior */
+	di->ignore_enter = FALSE;
+
     /* Close the dialog when hitting "Esc". */
     if (event->keyval == GDK_Escape)
     {
diff -Naur vim71.orig/src/gui_gtk_x11.c vim71/src/gui_gtk_x11.c
--- vim71.orig/src/gui_gtk_x11.c	2007-05-10 08:37:49.000000000 +0000
+++ vim71/src/gui_gtk_x11.c	2008-02-14 21:07:34.000000000 +0000
@@ -36,8 +36,8 @@
 # ifdef bindtextdomain
 #  undef bindtextdomain
 # endif
-# ifdef bindtextdomain_codeset
-#  undef bindtextdomain_codeset
+# ifdef bind_textdomain_codeset
+#  undef bind_textdomain_codeset
 # endif
 # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
 #  define ENABLE_NLS	/* so the texts in the dialog boxes are translated */
@@ -813,10 +813,15 @@
     if (blink_state == BLINK_NONE)
 	gui_mch_start_blink();
 
-    /* make sure keyboard input goes to the draw area (if this is focus for a window) */
+    /* make sure keyboard input goes to the draw area (if this is focus for a
+     * window) */
     if (widget != gui.drawarea)
 	gtk_widget_grab_focus(gui.drawarea);
 
+    /* make sure the input buffer is read */
+    if (gtk_main_level() > 0)
+	gtk_main_quit();
+
     return TRUE;
 }
 
@@ -829,6 +834,10 @@
     if (blink_state != BLINK_NONE)
 	gui_mch_stop_blink();
 
+    /* make sure the input buffer is read */
+    if (gtk_main_level() > 0)
+	gtk_main_quit();
+
     return TRUE;
 }
 
@@ -2188,8 +2197,10 @@
     escaped_filename = vim_strsave_escaped(filename, escape_chars);
     if (escaped_filename == NULL)
 	return FALSE;
-    mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename, NULL);
+    mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename,
+									NULL);
     vim_free(escaped_filename);
+
     /*
      * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
      * unpredictable effects when the session is saved automatically.  Also,
@@ -2199,7 +2210,7 @@
      */
     save_ssop_flags = ssop_flags;
     ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
-		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE);
+		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES);
 
     do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
     failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
@@ -3212,8 +3223,9 @@
 	{
 	    if (clicked_page == 0)
 	    {
-		/* Click after all tabs moves to next tab page. */
-		if (send_tabline_event(0) && gtk_main_level() > 0)
+		/* Click after all tabs moves to next tab page.  When "x" is
+		 * small guess it's the left button. */
+		if (send_tabline_event(x < 50 ? -1 : 0) && gtk_main_level() > 0)
 		    gtk_main_quit();
 	    }
 #ifndef HAVE_GTK2
@@ -4032,6 +4044,8 @@
 	unsigned int	w, h;
 	int		x = 0;
 	int		y = 0;
+	guint		pixel_width;
+	guint		pixel_height;
 
 	mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h);
 
@@ -4043,12 +4057,31 @@
 		p_window = h - 1;
 	    Rows = h;
 	}
+
+	pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width);
+	pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height);
+
+#ifdef HAVE_GTK2
+	pixel_width  += get_menu_tool_width();
+	pixel_height += get_menu_tool_height();
+#endif
+
 	if (mask & (XValue | YValue))
+	{
+	    int w, h;
+	    gui_mch_get_screen_dimensions(&w, &h);
+	    h += p_ghr + get_menu_tool_height();
+	    w += get_menu_tool_width();
+	    if (mask & XNegative)
+		x += w - pixel_width;
+	    if (mask & YNegative)
+		y += h - pixel_height;
 #ifdef HAVE_GTK2
 	    gtk_window_move(GTK_WINDOW(gui.mainwin), x, y);
 #else
 	    gtk_widget_set_uposition(gui.mainwin, x, y);
 #endif
+	}
 	vim_free(gui.geom);
 	gui.geom = NULL;
 
@@ -4059,14 +4092,6 @@
 	 */
 	if (gtk_socket_id != 0  &&  (mask & WidthValue || mask & HeightValue))
 	{
-	    guint pixel_width = (guint)(gui_get_base_width() + Columns * gui.char_width);
-	    guint pixel_height = (guint)(gui_get_base_height() + Rows * gui.char_height);
-
-#ifdef HAVE_GTK2
-	    pixel_width  += get_menu_tool_width();
-	    pixel_height += get_menu_tool_height();
-#endif
-
 	    update_window_manager_hints(pixel_width, pixel_height);
 	    init_window_hints_state = 1;
 	    g_timeout_add(1000, check_startup_plug_hints, NULL);
@@ -6635,6 +6660,7 @@
     unsigned	i;
     int		nbytes;
     char_u	*buffer;
+    time_t	start;
 
     for (i = 0; i < N_SELECTION_TARGETS; ++i)
     {
@@ -6645,7 +6671,11 @@
 			      cbd->gtk_sel_atom, target,
 			      (guint32)GDK_CURRENT_TIME);
 
-	while (received_selection == RS_NONE)
+	/* Hack: Wait up to three seconds for the selection.  A hang was
+	 * noticed here when using the netrw plugin combined with ":gui"
+	 * during the FocusGained event. */
+	start = time(NULL);
+	while (received_selection == RS_NONE && time(NULL) < start + 3)
 	    gtk_main();	/* wait for selection_received_cb */
 
 	if (received_selection != RS_FAIL)
diff -Naur vim71.orig/src/gui_motif.c vim71/src/gui_motif.c
--- vim71.orig/src/gui_motif.c	2007-05-07 19:20:24.000000000 +0000
+++ vim71/src/gui_motif.c	2008-02-14 21:07:34.000000000 +0000
@@ -3813,7 +3813,7 @@
 
     XtAddCallback(frdp->find, XmNactivateCallback,
 	    find_replace_callback,
-	    (XtPointer) (do_replace ? FRD_R_FINDNEXT : FRD_FINDNEXT));
+	    (do_replace ? (XtPointer)FRD_R_FINDNEXT : (XtPointer)FRD_FINDNEXT));
 
     if (do_replace)
     {
diff -Naur vim71.orig/src/gui_xmebw.c vim71/src/gui_xmebw.c
--- vim71.orig/src/gui_xmebw.c	2007-05-07 19:30:49.000000000 +0000
+++ vim71/src/gui_xmebw.c	2008-02-14 21:07:33.000000000 +0000
@@ -395,11 +395,15 @@
 
     /* Create the "highlight" pixmap. */
     color[4].pixel = eb->primitive.bottom_shadow_color;
+#ifdef XpmAllocColor /* SGI doesn't have it */
     attr.valuemask = XpmColorSymbols | XpmCloseness | XpmAllocColor;
+    attr.alloc_color = alloc_color;
+#else
+    attr.valuemask = XpmColorSymbols | XpmCloseness;
+#endif
     attr.closeness = 65535;	/* accuracy isn't crucial */
     attr.colorsymbols = color;
     attr.numsymbols = XtNumber(color);
-    attr.alloc_color = alloc_color;
 
     status = XpmCreatePixmapFromData(dpy, root, data, &pix, NULL, &attr);
     XpmFreeAttributes(&attr);
diff -Naur vim71.orig/src/hardcopy.c vim71/src/hardcopy.c
--- vim71.orig/src/hardcopy.c	2007-05-07 19:34:18.000000000 +0000
+++ vim71/src/hardcopy.c	2008-02-14 21:07:34.000000000 +0000
@@ -876,7 +876,7 @@
 	 */
 	if (psettings->do_syntax)
 	{
-	    id = syn_get_id(curwin, ppos->file_line, col, 1, NULL);
+	    id = syn_get_id(curwin, ppos->file_line, col, 1, NULL, FALSE);
 	    if (id > 0)
 		id = syn_get_final_id(id);
 	    else
diff -Naur vim71.orig/src/if_cscope.c vim71/src/if_cscope.c
--- vim71.orig/src/if_cscope.c	2007-03-11 14:29:57.000000000 +0000
+++ vim71/src/if_cscope.c	2008-02-14 21:07:32.000000000 +0000
@@ -24,11 +24,6 @@
     /* not UNIX, must be WIN32 */
 # include "vimio.h"
 # include <fcntl.h>
-# include <process.h>
-# define STDIN_FILENO    0
-# define STDOUT_FILENO   1
-# define STDERR_FILENO   2
-# define pipe(fds) _pipe(fds, 256, O_TEXT|O_NOINHERIT)
 #endif
 #include "if_cscope.h"
 
@@ -65,7 +60,7 @@
 static char *	    cs_parse_results __ARGS((int cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search));
 static char *	    cs_pathcomponents __ARGS((char *path));
 static void	    cs_print_tags_priv __ARGS((char **, char **, int));
-static int	    cs_read_prompt __ARGS((int ));
+static int	    cs_read_prompt __ARGS((int));
 static void	    cs_release_csp __ARGS((int, int freefnpp));
 static int	    cs_reset __ARGS((exarg_T *eap));
 static char *	    cs_resolve_file __ARGS((int, char *));
@@ -73,6 +68,8 @@
 
 
 static csinfo_T	    csinfo[CSCOPE_MAX_CONNECTIONS];
+static int	    eap_arg_len;    /* length of eap->arg, set in
+				       cs_lookup_cmd() */
 static cscmd_T	    cs_cmds[] =
 {
     { "add",	cs_add,
@@ -260,14 +257,7 @@
 
     if ((p = cs_manage_matches(NULL, NULL, -1, Get)) == NULL)
 	return TRUE;
-
-    if ((int)strlen(p) > size)
-    {
-	strncpy((char *)buf, p, size - 1);
-	buf[size] = '\0';
-    }
-    else
-	(void)strcpy((char *)buf, p);
+    vim_strncpy(buf, (char_u *)p, size - 1);
 
     return FALSE;
 } /* cs_fgets */
@@ -386,7 +376,7 @@
  * PRIVATE: cs_add
  *
  * add cscope database or a directory name (to look for cscope.out)
- * the the cscope connection list
+ * to the cscope connection list
  *
  * MAXPATHL 256
  */
@@ -509,7 +499,7 @@
 #if defined(UNIX)
     else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
 #else
-	/* substitute define S_ISREG from os_unix.h */
+	/* WIN32 - substitute define S_ISREG from os_unix.h */
     else if (((statbuf.st_mode) & S_IFMT) == S_IFREG)
 #endif
     {
@@ -722,17 +712,32 @@
 cs_create_connection(i)
     int i;
 {
-    int to_cs[2], from_cs[2], len;
-    char *prog, *cmd, *ppath = NULL;
-#ifndef UNIX
-    int in_save, out_save, err_save;
-    long_i ph;
-# ifdef FEAT_GUI
-    HWND activewnd = NULL;
-    HWND consolewnd = NULL;
+#ifdef UNIX
+    int		to_cs[2], from_cs[2];
+#endif
+    int		len;
+    char	*prog, *cmd, *ppath = NULL;
+#ifdef WIN32
+    int		fd;
+    SECURITY_ATTRIBUTES sa;
+    PROCESS_INFORMATION pi;
+    STARTUPINFO si;
+    BOOL	pipe_stdin = FALSE, pipe_stdout = FALSE;
+    HANDLE	stdin_rd, stdout_rd;
+    HANDLE	stdout_wr, stdin_wr;
+    BOOL	created;
+# ifdef __BORLANDC__
+#  define OPEN_OH_ARGTYPE long
+# else
+#  if (_MSC_VER >= 1300)
+#   define OPEN_OH_ARGTYPE intptr_t
+#  else
+#   define OPEN_OH_ARGTYPE long
+#  endif
 # endif
 #endif
 
+#if defined(UNIX)
     /*
      * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
      * from_cs[0] and writes to to_cs[1].
@@ -753,18 +758,12 @@
 	return CSCOPE_FAILURE;
     }
 
-#if defined(UNIX)
     switch (csinfo[i].pid = fork())
     {
     case -1:
 	(void)EMSG(_("E622: Could not fork for cscope"));
 	goto err_closing;
     case 0:				/* child: run cscope. */
-#else
-	in_save = dup(STDIN_FILENO);
-	out_save = dup(STDOUT_FILENO);
-	err_save = dup(STDERR_FILENO);
-#endif
 	if (dup2(to_cs[0], STDIN_FILENO) == -1)
 	    PERROR("cs_create_connection 1");
 	if (dup2(from_cs[1], STDOUT_FILENO) == -1)
@@ -773,15 +772,32 @@
 	    PERROR("cs_create_connection 3");
 
 	/* close unused */
-#if defined(UNIX)
 	(void)close(to_cs[1]);
 	(void)close(from_cs[0]);
 #else
-	/* On win32 we must close opposite ends because we are the parent */
-	(void)close(to_cs[0]);
-	to_cs[0] = -1;
-	(void)close(from_cs[1]);
-	from_cs[1] = -1;
+	/* WIN32 */
+	/* Create pipes to communicate with cscope */
+	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sa.bInheritHandle = TRUE;
+	sa.lpSecurityDescriptor = NULL;
+
+	if (!(pipe_stdin = CreatePipe(&stdin_rd, &stdin_wr, &sa, 0))
+		|| !(pipe_stdout = CreatePipe(&stdout_rd, &stdout_wr, &sa, 0)))
+	{
+	    (void)EMSG(_("E566: Could not create cscope pipes"));
+err_closing:
+	    if (pipe_stdin)
+	    {
+		CloseHandle(stdin_rd);
+		CloseHandle(stdin_wr);
+	    }
+	    if (pipe_stdout)
+	    {
+		CloseHandle(stdout_rd);
+		CloseHandle(stdout_wr);
+	    }
+	    return CSCOPE_FAILURE;
+	}
 #endif
 	/* expand the cscope exec for env var's */
 	if ((prog = (char *)alloc(MAXPATHL + 1)) == NULL)
@@ -789,6 +805,7 @@
 #ifdef UNIX
 	    return CSCOPE_FAILURE;
 #else
+	    /* WIN32 */
 	    goto err_closing;
 #endif
 	}
@@ -805,6 +822,7 @@
 #ifdef UNIX
 		return CSCOPE_FAILURE;
 #else
+		/* WIN32 */
 		goto err_closing;
 #endif
 	    }
@@ -823,6 +841,7 @@
 #ifdef UNIX
 	    return CSCOPE_FAILURE;
 #else
+	    /* WIN32 */
 	    goto err_closing;
 #endif
 	}
@@ -831,6 +850,7 @@
 #if defined(UNIX)
 	(void)sprintf(cmd, "exec %s -dl -f %s", prog, csinfo[i].fname);
 #else
+	/* WIN32 */
 	(void)sprintf(cmd, "%s -dl -f %s", prog, csinfo[i].fname);
 #endif
 	if (csinfo[i].ppath != NULL)
@@ -856,60 +876,6 @@
 	exit(127);
 	/* NOTREACHED */
     default:	/* parent. */
-#else
-# ifdef FEAT_GUI
-	activewnd = GetForegroundWindow(); /* on win9x cscope steals focus */
-	/* Dirty hack to hide annoying console window */
-	if (AllocConsole())
-	{
-	    char *title;
-	    title = (char *)alloc(1024);
-	    if (title == NULL)
-		FreeConsole();
-	    else
-	    {
-		GetConsoleTitle(title, 1024); /* save for future restore */
-		SetConsoleTitle(
-		    "GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS");
-		Sleep(40); /* as stated in MS KB we must wait 40 ms */
-		consolewnd = FindWindow(NULL,
-			"GVIMCS{5499421B-CBEF-45b0-85EF-38167FDEA5C5}GVIMCS");
-		if (consolewnd != NULL)
-		    ShowWindow(consolewnd, SW_HIDE);
-		SetConsoleTitle(title);
-		vim_free(title);
-	    }
-	}
-# endif
-	/* May be use &shell, &shellquote etc */
-# ifdef __BORLANDC__
-	/* BCC 5.5 uses a different function name for spawnlp */
-	ph = (long_i)spawnlp(P_NOWAIT, prog, cmd, NULL);
-# else
-	ph = (long_i)_spawnlp(_P_NOWAIT, prog, cmd, NULL);
-# endif
-	vim_free(prog);
-	vim_free(cmd);
-# ifdef FEAT_GUI
-	/* Dirty hack part two */
-	if (activewnd != NULL)
-	    /* restoring focus */
-	    SetForegroundWindow(activewnd);
-	if (consolewnd != NULL)
-	    FreeConsole();
-
-# endif
-	if (ph == -1)
-	{
-	    PERROR(_("cs_create_connection exec failed"));
-	    (void)EMSG(_("E623: Could not spawn cscope process"));
-	    goto err_closing;
-	}
-	/* else */
-	csinfo[i].pid = 0;
-	csinfo[i].hProc = (HANDLE)ph;
-
-#endif /* !UNIX */
 	/*
 	 * Save the file descriptors for later duplication, and
 	 * reopen as streams.
@@ -919,22 +885,54 @@
 	if ((csinfo[i].fr_fp = fdopen(from_cs[0], "r")) == NULL)
 	    PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
 
-#if defined(UNIX)
 	/* close unused */
 	(void)close(to_cs[0]);
 	(void)close(from_cs[1]);
 
 	break;
     }
+
 #else
-	/* restore stdhandles */
-    dup2(in_save, STDIN_FILENO);
-    dup2(out_save, STDOUT_FILENO);
-    dup2(err_save, STDERR_FILENO);
-    close(in_save);
-    close(out_save);
-    close(err_save);
-#endif
+    /* WIN32 */
+    /* Create a new process to run cscope and use pipes to talk with it */
+    GetStartupInfo(&si);
+    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_HIDE;  /* Hide child application window */
+    si.hStdOutput = stdout_wr;
+    si.hStdError  = stdout_wr;
+    si.hStdInput  = stdin_rd;
+    created = CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE,
+							NULL, NULL, &si, &pi);
+    vim_free(prog);
+    vim_free(cmd);
+
+    if (!created)
+    {
+	PERROR(_("cs_create_connection exec failed"));
+	(void)EMSG(_("E623: Could not spawn cscope process"));
+	goto err_closing;
+    }
+    /* else */
+    csinfo[i].pid = pi.dwProcessId;
+    csinfo[i].hProc = pi.hProcess;
+    CloseHandle(pi.hThread);
+
+    /* TODO - tidy up after failure to create files on pipe handles. */
+    if (((fd = _open_osfhandle((OPEN_OH_ARGTYPE)stdin_wr,
+						      _O_TEXT|_O_APPEND)) < 0)
+	    || ((csinfo[i].to_fp = _fdopen(fd, "w")) == NULL))
+	PERROR(_("cs_create_connection: fdopen for to_fp failed"));
+    if (((fd = _open_osfhandle((OPEN_OH_ARGTYPE)stdout_rd,
+						      _O_TEXT|_O_RDONLY)) < 0)
+	    || ((csinfo[i].fr_fp = _fdopen(fd, "r")) == NULL))
+	PERROR(_("cs_create_connection: fdopen for fr_fp failed"));
+
+    /* Close handles for file descriptors inherited by the cscope process */
+    CloseHandle(stdin_rd);
+    CloseHandle(stdout_wr);
+
+#endif /* !UNIX */
+
     return CSCOPE_SUCCESS;
 } /* cs_create_connection */
 
@@ -966,7 +964,7 @@
     }
 
     pat = opt + strlen(opt) + 1;
-    if (pat == NULL || (pat != NULL && pat[0] == '\0'))
+    if (pat >= (char *)eap->arg + eap_arg_len)
     {
 	cs_usage_msg(Find);
 	return FALSE;
@@ -1317,7 +1315,7 @@
 #else
 	    /* compare pathnames first */
 	    && ((fullpathcmp(csinfo[j].fname, fname, FALSE) & FPC_SAME)
-		/* if not Windows 9x, test index file atributes too */
+		/* if not Windows 9x, test index file attributes too */
 		|| (!mch_windows95()
 		    && csinfo[j].nVolume == bhfi.dwVolumeSerialNumber
 		    && csinfo[j].nIndexHigh == bhfi.nFileIndexHigh
@@ -1401,6 +1399,9 @@
     if (eap->arg == NULL)
 	return NULL;
 
+    /* Store length of eap->arg before it gets modified by strtok(). */
+    eap_arg_len = STRLEN(eap->arg);
+
     if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL)
 	return NULL;
 
@@ -2099,8 +2100,8 @@
 /*
  * PRIVATE: cs_release_csp
  *
- * does the actual free'ing for the cs ptr with an optional flag of whether
- * or not to free the filename.  called by cs_kill and cs_reset.
+ * Does the actual free'ing for the cs ptr with an optional flag of whether
+ * or not to free the filename.  Called by cs_kill and cs_reset.
  */
     static void
 cs_release_csp(i, freefnpp)
@@ -2118,10 +2119,13 @@
 	(void)fputs("q\n", csinfo[i].to_fp);
 	(void)fflush(csinfo[i].to_fp);
     }
-    /* give cscope chance to exit normally */
-    if (csinfo[i].hProc != NULL
-	    && WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT)
-	TerminateProcess(csinfo[i].hProc, 0);
+    if (csinfo[i].hProc != NULL)
+    {
+	/* Give cscope a chance to exit normally */
+	if (WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT)
+	    TerminateProcess(csinfo[i].hProc, 0);
+	CloseHandle(csinfo[i].hProc);
+    }
 #endif
 
     if (csinfo[i].fr_fp != NULL)
@@ -2195,7 +2199,7 @@
 	    cs_add_common(dblist[i], pplist[i], fllist[i]);
 	    if (p_csverbose)
 	    {
-		/* dont' use smsg_attr because want to display
+		/* don't use smsg_attr() because we want to display the
 		 * connection number in the same line as
 		 * "Added cscope database..."
 		 */
@@ -2304,6 +2308,21 @@
     return CSCOPE_SUCCESS;
 } /* cs_show */
 
+
+/*
+ * PUBLIC: cs_end
+ *
+ * Only called when VIM exits to quit any cscope sessions.
+ */
+    void
+cs_end()
+{
+    int i;
+
+    for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+	cs_release_csp(i, TRUE);
+}
+
 #endif	/* FEAT_CSCOPE */
 
 /* the end */
diff -Naur vim71.orig/src/if_cscope.h vim71/src/if_cscope.h
--- vim71.orig/src/if_cscope.h	2005-06-30 17:14:22.000000000 +0000
+++ vim71/src/if_cscope.h	2008-02-14 21:07:32.000000000 +0000
@@ -72,7 +72,7 @@
     ino_t	    st_ino;	/* inode number of cscope db */
 #else
 # if defined(WIN32)
-    int	    pid;	/* Can't get pid so set it to 0 ;) */
+    DWORD	    pid;	/* PID of the connected cscope process. */
     HANDLE	    hProc;	/* cscope process handle */
     DWORD	    nVolume;	/* Volume serial number, instead of st_dev */
     DWORD	    nIndexHigh;	/* st_ino has no meaning in the Windows */
diff -Naur vim71.orig/src/if_mzsch.c vim71/src/if_mzsch.c
--- vim71.orig/src/if_mzsch.c	2007-05-12 11:13:47.000000000 +0000
+++ vim71/src/if_mzsch.c	2008-02-14 21:07:31.000000000 +0000
@@ -308,6 +308,8 @@
 static Scheme_Config *(*dll_scheme_current_config)(void);
 static Scheme_Object *(*dll_scheme_char_string_to_byte_string)
     (Scheme_Object *s);
+static Scheme_Object *(*dll_scheme_char_string_to_path)
+    (Scheme_Object *s);
 # endif
 
 /* arrays are imported directly */
@@ -398,6 +400,8 @@
 #  define scheme_current_config dll_scheme_current_config
 #  define scheme_char_string_to_byte_string \
     dll_scheme_char_string_to_byte_string
+#  define scheme_char_string_to_path \
+    dll_scheme_char_string_to_path
 # endif
 
 typedef struct
@@ -498,6 +502,8 @@
     {"scheme_current_config", (void **)&dll_scheme_current_config},
     {"scheme_char_string_to_byte_string",
 	(void **)&dll_scheme_char_string_to_byte_string},
+    {"scheme_char_string_to_path",
+	(void **)&dll_scheme_char_string_to_path},
 # endif
     {NULL, NULL}};
 
@@ -773,7 +779,14 @@
 #ifdef MZSCHEME_COLLECTS
     /* setup 'current-library-collection-paths' parameter */
     scheme_set_param(scheme_config, MZCONFIG_COLLECTION_PATHS,
-	    scheme_make_pair(scheme_make_string(MZSCHEME_COLLECTS),
+	    scheme_make_pair(
+# if MZSCHEME_VERSION_MAJOR >= 299
+		scheme_char_string_to_path(
+		    scheme_byte_string_to_char_string(
+			scheme_make_byte_string(MZSCHEME_COLLECTS))),
+# else
+		scheme_make_string(MZSCHEME_COLLECTS),
+# endif
 		scheme_null));
 #endif
 #ifdef HAVE_SANDBOX
diff -Naur vim71.orig/src/if_perl.xs vim71/src/if_perl.xs
--- vim71.orig/src/if_perl.xs	2006-08-16 12:45:15.000000000 +0000
+++ vim71/src/if_perl.xs	2008-02-14 21:07:33.000000000 +0000
@@ -40,6 +40,28 @@
 #    define PERL_SUBVERSION SUBVERSION
 #endif
 
+/*
+ * Quoting Jan Dubois of Active State:
+ *    ActivePerl build 822 still identifies itself as 5.8.8 but already
+ *    contains many of the changes from the upcoming Perl 5.8.9 release.
+ *
+ * The changes include addition of two symbols (Perl_sv_2iv_flags,
+ * Perl_newXS_flags) not present in earlier releases.
+ *
+ * Jan Dubois suggested the following guarding scheme.
+ *
+ * Active State defined ACTIVEPERL_VERSION as a string in versions before
+ * 5.8.8; and so the comparison to 822 below needs to be guarded.
+ */
+#if (PERL_REVISION == 5) && (PERL_VERSION == 8) && (PERL_SUBVERSION >= 8)
+# if (ACTIVEPERL_VERSION >= 822) || (PERL_SUBVERSION >= 9)
+#  define PERL589_OR_LATER
+# endif
+#endif
+#if (PERL_REVISION == 5) && (PERL_VERSION >= 9)
+# define PERL589_OR_LATER
+#endif
+
 #ifndef pTHX
 #    define pTHX void
 #    define pTHX_
@@ -109,6 +131,10 @@
 # else
 #  define Perl_sv_catpvn dll_Perl_sv_catpvn
 # endif
+#ifdef PERL589_OR_LATER
+#  define Perl_sv_2iv_flags dll_Perl_sv_2iv_flags
+#  define Perl_newXS_flags dll_Perl_newXS_flags
+#endif
 # define Perl_sv_free dll_Perl_sv_free
 # define Perl_sv_isa dll_Perl_sv_isa
 # define Perl_sv_magic dll_Perl_sv_magic
@@ -192,6 +218,10 @@
 #else
 static void (*Perl_sv_catpvn)(pTHX_ SV*, const char*, STRLEN);
 #endif
+#ifdef PERL589_OR_LATER
+static IV (*Perl_sv_2iv_flags)(pTHX_ SV* sv, I32 flags);
+static CV * (*Perl_newXS_flags)(pTHX_ const char *name, XSUBADDR_t subaddr, const char *const filename, const char *const proto, U32 flags);
+#endif
 static void (*Perl_sv_free)(pTHX_ SV*);
 static int (*Perl_sv_isa)(pTHX_ SV*, const char*);
 static void (*Perl_sv_magic)(pTHX_ SV*, SV*, int, const char*, I32);
@@ -267,6 +297,10 @@
 #else
     {"Perl_sv_2pv", (PERL_PROC*)&Perl_sv_2pv},
 #endif
+#ifdef PERL589_OR_LATER
+    {"Perl_sv_2iv_flags", (PERL_PROC*)&Perl_sv_2iv_flags},
+    {"Perl_newXS_flags", (PERL_PROC*)&Perl_newXS_flags},
+#endif
     {"Perl_sv_bless", (PERL_PROC*)&Perl_sv_bless},
 #if (PERL_REVISION == 5) && (PERL_VERSION >= 8)
     {"Perl_sv_catpvn_flags", (PERL_PROC*)&Perl_sv_catpvn_flags},
@@ -411,13 +445,13 @@
     char *next;
     char *token = (char *)s;
 
-    while ((next = strchr(token, '\n')))
+    while ((next = strchr(token, '\n')) && !got_int)
     {
 	*next++ = '\0';			/* replace \n with \0 */
 	msg_attr((char_u *)token, attr);
 	token = next;
     }
-    if (*token)
+    if (*token && !got_int)
 	msg_attr((char_u *)token, attr);
 }
 
diff -Naur vim71.orig/src/if_ruby.c vim71/src/if_ruby.c
--- vim71.orig/src/if_ruby.c	2007-05-12 09:54:12.000000000 +0000
+++ vim71/src/if_ruby.c	2008-02-14 21:07:32.000000000 +0000
@@ -789,7 +789,7 @@
     return get_buffer_line(curbuf, curwin->w_cursor.lnum);
 }
 
-static VALUE set_current_line(VALUE str)
+static VALUE set_current_line(VALUE self, VALUE str)
 {
     return set_buffer_line(curbuf, curwin->w_cursor.lnum, str);
 }
diff -Naur vim71.orig/src/keymap.h vim71/src/keymap.h
--- vim71.orig/src/keymap.h	2006-08-22 11:38:38.000000000 +0000
+++ vim71/src/keymap.h	2008-02-14 21:07:32.000000000 +0000
@@ -254,6 +254,8 @@
     , KE_DROP		/* DnD data is available */
     , KE_CURSORHOLD	/* CursorHold event */
     , KE_NOP		/* doesn't do something */
+    , KE_FOCUSGAINED	/* focus gained */
+    , KE_FOCUSLOST	/* focus lost */
 };
 
 /*
@@ -445,6 +447,8 @@
 #define K_CMDWIN	TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
 
 #define K_DROP		TERMCAP2KEY(KS_EXTRA, KE_DROP)
+#define K_FOCUSGAINED	TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
+#define K_FOCUSLOST	TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
 
 #define K_CURSORHOLD	TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
 
diff -Naur vim71.orig/src/macros.h vim71/src/macros.h
--- vim71.orig/src/macros.h	2007-05-07 19:38:22.000000000 +0000
+++ vim71/src/macros.h	2008-02-14 21:07:32.000000000 +0000
@@ -54,10 +54,12 @@
 
 /*
  * toupper() and tolower() that use the current locale.
- * On some systems toupper()/tolower() only work on lower/uppercase characters
+ * On some systems toupper()/tolower() only work on lower/uppercase
+ * characters, first use islower() or isupper() then.
  * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
  * range 0 - 255.  toupper()/tolower() on some systems can't handle others.
- * Note: for UTF-8 use utf_toupper() and utf_tolower().
+ * Note: It is often better to use MB_TOLOWER() and MB_TOUPPER(), because many
+ * toupper() and tolower() implementations only work for ASCII.
  */
 #ifdef MSWIN
 #  define TOUPPER_LOC(c)	toupper_tab[(c) & 255]
diff -Naur vim71.orig/src/main.aap vim71/src/main.aap
--- vim71.orig/src/main.aap	2007-05-07 19:46:43.000000000 +0000
+++ vim71/src/main.aap	2008-02-14 21:07:33.000000000 +0000
@@ -56,9 +56,17 @@
     config {virtual} auto/config.h auto/config.aap :
                          auto/configure.aap configure.aap
                          config.arg config.h.in config.aap.in
+        # Use "uname -a" to detect the architecture of the system.
+        @ok, uname = redir_system('uname -a', 0)
+        @if string.find(uname, "i386") >= 0:
+        @   arch = "i386"
+        @else:
+        @   arch = "ppc"
+        :print Building for $arch system
+        config_args = `file2string("config.arg")`
         :sys CONFIG_STATUS=auto/config.status
-                ./configure.aap `file2string("config.arg")`
-                    --with-mac-arch=ppc
+                ./configure.aap $config_args
+                    --with-mac-arch=$arch
                     --cache-file=auto/config.cache
 
     # Configure arguments: create an empty "config.arg" file when its missing
@@ -433,11 +441,13 @@
         :print >> $target char_u *all_lflags = (char_u *)"$linkcmd";
         @if _no.get("COMPILEDBY"):
             who = $COMPILEDBY
-            where = ''
+            where =
         @else:
             :syseval whoami | :eval re.sub("\n", "", stdin) | :assign who
 
             :syseval hostname | :eval re.sub("\n", "", stdin) | :assign where
+        @who = string.replace(who, '"', '\\"')
+        @where = string.replace(where, '"', '\\"')
         :print >> $target char_u *compiled_user = (char_u *)"$who";
         :print >> $target char_u *compiled_sys = (char_u *)"$where";
 
@@ -1167,7 +1177,7 @@
         :symlink `os.getcwd()`/../runtime $RESDIR/vim/runtime
 # TODO: Create the vimtutor application.
 
-gui_bundle {virtual}: $(RESDIR) bundle-dir bundle-executable bundle-info
+gui_bundle {virtual}: $(RESDIR) bundle-dir bundle-executable bundle-info \
                         bundle-resource bundle-language
 
 bundle-dir {virtual}: $(APPDIR)/Contents $(VIMTARGET)
@@ -1187,7 +1197,7 @@
         :sys m4 $(M4FLAGSX) infplist.xml > $(APPDIR)/Contents/Info.plist
 
 bundle-resource {virtual}: bundle-dir bundle-rsrc
-    :copy {force} $(RSRC_DIR)/*.icns $(RESDIR)
+        :copy {force} $(RSRC_DIR)/*.icns $(RESDIR)
 
 ### Classic resources
 # Resource fork (in the form of a .rsrc file) for Classic Vim (Mac OS 9)
diff -Naur vim71.orig/src/main.c vim71/src/main.c
--- vim71.orig/src/main.c	2007-05-07 19:38:44.000000000 +0000
+++ vim71/src/main.c	2008-02-14 21:07:34.000000000 +0000
@@ -275,6 +275,7 @@
      *   -display or --display
      *   --server...
      *   --socketid
+     *   --windowid
      */
     early_arg_scan(&params);
 
@@ -954,7 +955,8 @@
     int		cmdwin;	    /* TRUE when working in the command-line window */
     int		noexmode;   /* TRUE when return on entering Ex mode */
 {
-    oparg_T	oa;	/* operator arguments */
+    oparg_T	oa;				/* operator arguments */
+    int		previous_got_int = FALSE;	/* "got_int" was TRUE */
 
 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
     /* Setup to catch a terminating error from the X server.  Just ignore
@@ -1015,12 +1017,32 @@
 		need_fileinfo = FALSE;
 	    }
 	}
-	if (got_int && !global_busy)
+
+	/* Reset "got_int" now that we got back to the main loop.  Except when
+	 * inside a ":g/pat/cmd" command, then the "got_int" needs to abort
+	 * the ":g" command.
+	 * For ":g/pat/vi" we reset "got_int" when used once.  When used
+	 * a second time we go back to Ex mode and abort the ":g" command. */
+	if (got_int)
 	{
-	    if (!quit_more)
-		(void)vgetc();		/* flush all buffers */
-	    got_int = FALSE;
+	    if (noexmode && global_busy && !exmode_active && previous_got_int)
+	    {
+		/* Typed two CTRL-C in a row: go back to ex mode as if "Q" was
+		 * used and keep "got_int" set, so that it aborts ":g". */
+		exmode_active = EXMODE_NORMAL;
+		State = NORMAL;
+	    }
+	    else if (!global_busy || !exmode_active)
+	    {
+		if (!quit_more)
+		    (void)vgetc();		/* flush all buffers */
+		got_int = FALSE;
+	    }
+	    previous_got_int = TRUE;
 	}
+	else
+	    previous_got_int = FALSE;
+
 	if (!exmode_active)
 	    msg_scroll = FALSE;
 	quit_more = FALSE;
@@ -1309,6 +1331,13 @@
 #ifdef FEAT_NETBEANS_INTG
     netbeans_end();
 #endif
+#ifdef FEAT_CSCOPE
+    cs_end();
+#endif
+#ifdef FEAT_EVAL
+    if (garbage_collect_at_exit)
+	garbage_collect();
+#endif
 
     mch_exit(exitval);
 }
@@ -1360,8 +1389,7 @@
 	p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
 	if (p != NULL && *p != NUL)
 	{
-	    STRCPY(NameBuff, p);
-	    STRCAT(NameBuff, "/lang");
+	    vim_snprintf((char *)NameBuff, MAXPATHL, "%s/lang", p);
 	    bindtextdomain(VIMPACKAGE, (char *)NameBuff);
 	}
 	if (mustfree)
@@ -1469,7 +1497,7 @@
  * Get the name of the display, before gui_prepare() removes it from
  * argv[].  Used for the xterm-clipboard display.
  *
- * Also find the --server... arguments and --socketid
+ * Also find the --server... arguments and --socketid and --windowid
  */
 /*ARGSUSED*/
     static void
@@ -1516,24 +1544,35 @@
 #  endif
 	}
 # endif
-# ifdef FEAT_GUI_GTK
+
+# if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)
+#  ifdef FEAT_GUI_W32
+	else if (STRICMP(argv[i], "--windowid") == 0)
+#  else
 	else if (STRICMP(argv[i], "--socketid") == 0)
+#  endif
 	{
-	    unsigned int    socket_id;
+	    unsigned int    id;
 	    int		    count;
 
 	    if (i == argc - 1)
 		mainerr_arg_missing((char_u *)argv[i]);
 	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
-		count = sscanf(&(argv[i + 1][2]), "%x", &socket_id);
+		count = sscanf(&(argv[i + 1][2]), "%x", &id);
 	    else
-		count = sscanf(argv[i+1], "%u", &socket_id);
+		count = sscanf(argv[i+1], "%u", &id);
 	    if (count != 1)
 		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
 	    else
-		gtk_socket_id = socket_id;
+#  ifdef FEAT_GUI_W32
+		win_socket_id = id;
+#  else
+		gtk_socket_id = id;
+#  endif
 	    i++;
 	}
+# endif
+# ifdef FEAT_GUI_GTK
 	else if (STRICMP(argv[i], "--echo-wid") == 0)
 	    echo_wid_arg = TRUE;
 # endif
@@ -1663,8 +1702,12 @@
 		    }
 		}
 #endif
-#ifdef FEAT_GUI_GTK
+#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_W32)
+# ifdef FEAT_GUI_GTK
 		else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
+# else
+		else if (STRNICMP(argv[0] + argv_idx, "windowid", 8) == 0)
+# endif
 		{
 		    /* already processed -- snatch the following arg */
 		    if (argc > 1)
@@ -1673,6 +1716,8 @@
 			++argv;
 		    }
 		}
+#endif
+#ifdef FEAT_GUI_GTK
 		else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
 		{
 		    /* already processed, skip */
@@ -1730,7 +1775,8 @@
 
 	    case 'F':		/* "-F" start in Farsi mode: rl + fkmap set */
 #ifdef FEAT_FKMAP
-		curwin->w_p_rl = p_fkmap = TRUE;
+		p_fkmap = TRUE;
+		set_option_value((char_u *)"rl", 1L, NULL, 0);
 #else
 		mch_errmsg(_(e_nofarsi));
 		mch_exit(2);
@@ -1747,7 +1793,8 @@
 
 	    case 'H':		/* "-H" start in Hebrew mode: rl + hkmap set */
 #ifdef FEAT_RIGHTLEFT
-		curwin->w_p_rl = p_hkmap = TRUE;
+		p_hkmap = TRUE;
+		set_option_value((char_u *)"rl", 1L, NULL, 0);
 #else
 		mch_errmsg(_(e_nohebrew));
 		mch_exit(2);
@@ -3036,7 +3083,7 @@
     main_msg(_("--remote-wait <files>  As --remote but wait for files to have been edited"));
     main_msg(_("--remote-wait-silent <files>  Same, don't complain if there is no server"));
 # ifdef FEAT_WINDOWS
-    main_msg(_("--remote-tab <files>  As --remote but open tab page for each file"));
+    main_msg(_("--remote-tab[-wait][-silent] <files>  As --remote but use tab page per file"));
 # endif
     main_msg(_("--remote-send <keys>\tSend <keys> to a Vim server and exit"));
     main_msg(_("--remote-expr <expr>\tEvaluate <expr> in a Vim server and print result"));
@@ -3100,6 +3147,7 @@
 #endif
 #ifdef FEAT_GUI_W32
     main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
+    main_msg(_("--windowid <HWND>\tOpen Vim inside another win32 widget"));
 #endif
 
 #ifdef FEAT_GUI_GNOME
@@ -3632,7 +3680,13 @@
 	mainerr_arg_missing((char_u *)filev[-1]);
     if (mch_dirname(cwd, MAXPATHL) != OK)
 	return NULL;
-    if ((p = vim_strsave_escaped_ext(cwd, PATH_ESC_CHARS, '\\', TRUE)) == NULL)
+    if ((p = vim_strsave_escaped_ext(cwd,
+#ifdef BACKSLASH_IN_FILENAME
+		    "",  /* rem_backslash() will tell what chars to escape */
+#else
+		    PATH_ESC_CHARS,
+#endif
+		    '\\', TRUE)) == NULL)
 	return NULL;
     ga_init2(&ga, 1, 100);
     ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
diff -Naur vim71.orig/src/mark.c vim71/src/mark.c
--- vim71.orig/src/mark.c	2007-05-07 19:28:01.000000000 +0000
+++ vim71/src/mark.c	2008-02-14 21:07:34.000000000 +0000
@@ -79,6 +79,12 @@
 	return OK;
     }
 
+    if (c == '"')
+    {
+	curbuf->b_last_cursor = *pos;
+	return OK;
+    }
+
     /* Allow setting '[ and '] for an autocommand that simulates reading a
      * file. */
     if (c == '[')
@@ -505,9 +511,24 @@
     {
 	/*
 	 * First expand "~/" in the file name to the home directory.
-	 * Try to shorten the file name.
+	 * Don't expand the whole name, it may contain other '~' chars.
 	 */
-	expand_env(fm->fname, NameBuff, MAXPATHL);
+	if (fm->fname[0] == '~' && (fm->fname[1] == '/'
+#ifdef BACKSLASH_IN_FILENAME
+		    || fm->fname[1] == '\\'
+#endif
+		    ))
+	{
+	    int len;
+
+	    expand_env((char_u *)"~/", NameBuff, MAXPATHL);
+	    len = STRLEN(NameBuff);
+	    vim_strncpy(NameBuff + len, fm->fname + 2, MAXPATHL - len - 1);
+	}
+	else
+	    vim_strncpy(NameBuff, fm->fname, MAXPATHL - 1);
+
+	/* Try to shorten the file name. */
 	mch_dirname(IObuff, IOSIZE);
 	p = shorten_fname(NameBuff, IObuff);
 
diff -Naur vim71.orig/src/mbyte.c vim71/src/mbyte.c
--- vim71.orig/src/mbyte.c	2007-05-07 19:47:09.000000000 +0000
+++ vim71/src/mbyte.c	2008-02-14 21:07:34.000000000 +0000
@@ -1310,20 +1310,26 @@
 /*
  * mb_off2cells() function pointer.
  * Return number of display cells for char at ScreenLines[off].
- * Caller must make sure "off" and "off + 1" are valid!
+ * We make sure that the offset used is less than "max_off".
  */
 /*ARGSUSED*/
     int
-latin_off2cells(off)
+latin_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
     return 1;
 }
 
     int
-dbcs_off2cells(off)
+dbcs_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
+    /* never check beyond end of the line */
+    if (off >= max_off)
+	return 1;
+
     /* Number of cells is equal to number of bytes, except for euc-jp when
      * the first byte is 0x8e. */
     if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
@@ -1332,10 +1338,11 @@
 }
 
     int
-utf_off2cells(off)
+utf_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
-    return ScreenLines[off + 1] == 0 ? 2 : 1;
+    return (off + 1 < max_off && ScreenLines[off + 1] == 0) ? 2 : 1;
 }
 
 /*
@@ -1635,7 +1642,7 @@
  * Get the length of UTF-8 byte sequence "p[size]".  Does not include any
  * following composing characters.
  * Returns 1 for "".
- * Returns 1 for an illegal byte sequence.
+ * Returns 1 for an illegal byte sequence (also in incomplete byte seq.).
  * Returns number > "size" for an incomplete byte sequence.
  */
     int
@@ -1645,13 +1652,14 @@
 {
     int		len;
     int		i;
+    int		m;
 
     if (*p == NUL)
 	return 1;
-    len = utf8len_tab[*p];
+    m = len = utf8len_tab[*p];
     if (len > size)
-	return len;	/* incomplete byte sequence. */
-    for (i = 1; i < len; ++i)
+	m = size;	/* incomplete byte sequence. */
+    for (i = 1; i < m; ++i)
 	if ((p[i] & 0xc0) != 0x80)
 	    return 1;
     return len;
@@ -2320,7 +2328,7 @@
 		/* Single byte: first check normally, then with ignore case. */
 		if (s1[i] != s2[i])
 		{
-		    cdiff = TOLOWER_LOC(s1[i]) - TOLOWER_LOC(s2[i]);
+		    cdiff = MB_TOLOWER(s1[i]) - MB_TOLOWER(s2[i]);
 		    if (cdiff != 0)
 			return cdiff;
 		}
@@ -2855,15 +2863,17 @@
 	    buf[m++] = K_SPECIAL;
 	    n += 2;
 	}
+	else if ((str[n] == K_SPECIAL
 # ifdef FEAT_GUI
-	else if (str[n] == CSI
+		    || str[n] == CSI
+# endif
+		 )
 		&& str[n + 1] == KS_EXTRA
 		&& str[n + 2] == (int)KE_CSI)
 	{
 	    buf[m++] = CSI;
 	    n += 2;
 	}
-# endif
 	else if (str[n] == K_SPECIAL
 # ifdef FEAT_GUI
 		|| str[n] == CSI
@@ -2899,12 +2909,8 @@
     if (composing_hangul)
 	return TRUE;
 #endif
-    if (enc_dbcs != 0)
-	return dbcs_off2cells(LineOffset[row] + col) > 1;
-    if (enc_utf8)
-	return (col + 1 < Columns
-		&& ScreenLines[LineOffset[row] + col + 1] == 0);
-    return FALSE;
+    return (*mb_off2cells)(LineOffset[row] + col,
+					LineOffset[row] + screen_Columns) > 1;
 }
 
 # if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
diff -Naur vim71.orig/src/message.c vim71/src/message.c
--- vim71.orig/src/message.c	2007-05-07 19:31:59.000000000 +0000
+++ vim71/src/message.c	2008-02-14 21:07:33.000000000 +0000
@@ -828,7 +828,7 @@
 		_("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
 		hl_attr(HLF_T));
 
-    for (p = first_msg_hist; p != NULL; p = p->next)
+    for (p = first_msg_hist; p != NULL && !got_int; p = p->next)
 	if (p->msg != NULL)
 	    msg_attr(p->msg, p->attr);
 
@@ -944,6 +944,7 @@
 		c = K_IGNORE;
 	    }
 #endif
+
 	    /*
 	     * Allow scrolling back in the messages.
 	     * Also accept scroll-down commands when messages fill the screen,
@@ -1840,9 +1841,10 @@
     char_u	*sb_str = str;
     int		sb_col = msg_col;
     int		wrap;
+    int		did_last_char;
 
     did_wait_return = FALSE;
-    while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen))
+    while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL)
     {
 	/*
 	 * We are at the end of the screen line when:
@@ -1878,7 +1880,7 @@
 		/* output postponed text */
 		t_puts(&t_col, t_s, s, attr);
 
-	    /* When no more prompt an no more room, truncate here */
+	    /* When no more prompt and no more room, truncate here */
 	    if (msg_no_more && lines_left == 0)
 		break;
 
@@ -1909,7 +1911,10 @@
 		else
 #endif
 		    msg_screen_putchar(*s++, attr);
+		did_last_char = TRUE;
 	    }
+	    else
+		did_last_char = FALSE;
 
 	    if (p_more)
 		/* store text for scrolling back */
@@ -1927,7 +1932,8 @@
 	     * If screen is completely filled and 'more' is set then wait
 	     * for a character.
 	     */
-	    --lines_left;
+	    if (lines_left > 0)
+		--lines_left;
 	    if (p_more && lines_left == 0 && State != HITRETURN
 					    && !msg_no_more && !exmode_active)
 	    {
@@ -1943,11 +1949,7 @@
 
 	    /* When we displayed a char in last column need to check if there
 	     * is still more. */
-	    if (*s >= ' '
-#ifdef FEAT_RIGHTLEFT
-		    && !cmdmsg_rl
-#endif
-	       )
+	    if (did_last_char)
 		continue;
 	}
 
@@ -2234,7 +2236,7 @@
 {
     msgchunk_T	*mp;
 
-    /* Only show somethign if there is more than one line, otherwise it looks
+    /* Only show something if there is more than one line, otherwise it looks
      * weird, typing a command without output results in one line. */
     mp = msg_sb_start(last_msgchunk);
     if (mp == NULL || mp->sb_prev == NULL)
@@ -2622,7 +2624,7 @@
 		}
 	    }
 
-	    if (scroll < 0 || (scroll == 0 && mp_last != NULL))
+	    if (scroll <= 0)
 	    {
 		/* displayed the requested text, more prompt again */
 		screen_fill((int)Rows - 1, (int)Rows, 0,
@@ -2848,6 +2850,15 @@
     }
     else if (State == HITRETURN || State == SETWSIZE)
     {
+	if (msg_row == Rows - 1)
+	{
+	    /* Avoid drawing the "hit-enter" prompt below the previous one,
+	     * overwrite it.  Esp. useful when regaining focus and a
+	     * FocusGained autocmd exists but didn't draw anything. */
+	    msg_didout = FALSE;
+	    msg_col = 0;
+	    msg_clr_eos();
+	}
 	hit_return_msg();
 	msg_row = Rows - 1;
     }
@@ -3456,11 +3467,11 @@
 		    /* advance to next hotkey and set default hotkey */
 #ifdef FEAT_MBYTE
 		    if (has_mbyte)
-			hotkp += (*mb_ptr2len)(hotkp);
+			hotkp += STRLEN(hotkp);
 		    else
 #endif
 			++hotkp;
-		    (void)copy_char(r + 1, hotkp, TRUE);
+		    hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL;
 		    if (dfltbutton)
 			--dfltbutton;
 
@@ -3493,7 +3504,7 @@
 			*msgp++ = (dfltbutton == 1) ? ']' : ')';
 
 			/* redefine hotkey */
-			(void)copy_char(r, hotkp, TRUE);
+			hotkp[copy_char(r, hotkp, TRUE)] = NUL;
 		    }
 		}
 		else
@@ -3519,8 +3530,6 @@
 	    *msgp++ = ':';
 	    *msgp++ = ' ';
 	    *msgp = NUL;
-	    mb_ptr_adv(hotkp);
-	    *hotkp = NUL;
 	}
 	else
 	{
@@ -3555,8 +3564,9 @@
 	    msgp = confirm_msg + 1 + STRLEN(message);
 	    hotkp = hotk;
 
-	    /* define first default hotkey */
-	    (void)copy_char(buttons, hotkp, TRUE);
+	    /* Define first default hotkey.  Keep the hotkey string NUL
+	     * terminated to avoid reading past the end. */
+	    hotkp[copy_char(buttons, hotkp, TRUE)] = NUL;
 
 	    /* Remember where the choices start, displaying starts here when
 	     * "hotkp" typed at the more prompt. */
diff -Naur vim71.orig/src/misc1.c vim71/src/misc1.c
--- vim71.orig/src/misc1.c	2007-05-07 19:49:03.000000000 +0000
+++ vim71/src/misc1.c	2008-02-14 21:07:34.000000000 +0000
@@ -90,7 +90,7 @@
  */
     int
 set_indent(size, flags)
-    int		size;
+    int		size;		    /* measured in spaces */
     int		flags;
 {
     char_u	*p;
@@ -98,12 +98,14 @@
     char_u	*oldline;
     char_u	*s;
     int		todo;
-    int		ind_len;
+    int		ind_len;	    /* measured in characters */
     int		line_len;
     int		doit = FALSE;
-    int		ind_done;
+    int		ind_done = 0;	    /* measured in spaces */
     int		tab_pad;
     int		retval = FALSE;
+    int		orig_char_len = -1; /* number of initial whitespace chars when
+				       'et' and 'pi' are both set */
 
     /*
      * First check if there is anything to do and compute the number of
@@ -116,8 +118,10 @@
     /* Calculate the buffer size for the new indent, and check to see if it
      * isn't already set */
 
-    /* if 'expandtab' isn't set: use TABs */
-    if (!curbuf->b_p_et)
+    /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and
+     * 'preserveindent' are set count the number of characters at the
+     * beginning of the line to be copied */
+    if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi))
     {
 	/* If 'preserveindent' is set then reuse as much as possible of
 	 * the existing indent structure for the new indent */
@@ -148,9 +152,14 @@
 		++p;
 	    }
 
+	    /* Set initial number of whitespace chars to copy if we are
+	     * preserving indent but expandtab is set */
+	    if (curbuf->b_p_et)
+		orig_char_len = ind_len;
+
 	    /* Fill to next tabstop with a tab, if possible */
 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
-	    if (todo >= tab_pad)
+	    if (todo >= tab_pad && orig_char_len == -1)
 	    {
 		doit = TRUE;
 		todo -= tab_pad;
@@ -193,13 +202,43 @@
     else
 	p = skipwhite(p);
     line_len = (int)STRLEN(p) + 1;
-    newline = alloc(ind_len + line_len);
-    if (newline == NULL)
-	return FALSE;
+
+    /* If 'preserveindent' and 'expandtab' are both set keep the original
+     * characters and allocate accordingly.  We will fill the rest with spaces
+     * after the if (!curbuf->b_p_et) below. */
+    if (orig_char_len != -1)
+    {
+	newline = alloc(orig_char_len + size - ind_done + line_len);
+	if (newline == NULL)
+	    return FALSE;
+	todo = size - ind_done;
+	ind_len = orig_char_len + todo;    /* Set total length of indent in
+					    * characters, which may have been
+					    * undercounted until now  */
+	p = oldline;
+	s = newline;
+	while (orig_char_len > 0)
+	{
+	    *s++ = *p++;
+	    orig_char_len--;
+	}
+
+	/* Skip over any additional white space (useful when newindent is less
+	 * than old) */
+	while (vim_iswhite(*p))
+	    ++p;
+
+    }
+    else
+    {
+	todo = size;
+	newline = alloc(ind_len + line_len);
+	if (newline == NULL)
+	    return FALSE;
+	s = newline;
+    }
 
     /* Put the characters in the new line. */
-    s = newline;
-    todo = size;
     /* if 'expandtab' isn't set: use TABs */
     if (!curbuf->b_p_et)
     {
@@ -398,7 +437,8 @@
     {
 	regmatch.rmm_ic = FALSE;
 	regmatch.rmm_maxcol = 0;
-	if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum, (colnr_T)0))
+	if (vim_regexec_multi(&regmatch, curwin, curbuf, lnum,
+							    (colnr_T)0, NULL))
 	{
 	    pos.lnum = regmatch.endpos[0].lnum + lnum;
 	    pos.col = regmatch.endpos[0].col;
@@ -553,7 +593,14 @@
 	replace_push(NUL);
 	p = saved_line + curwin->w_cursor.col;
 	while (*p != NUL)
-	    replace_push(*p++);
+	{
+#ifdef FEAT_MBYTE
+	    if (has_mbyte)
+		p += replace_push_mb(p);
+	    else
+#endif
+		replace_push(*p++);
+	}
 	saved_line[curwin->w_cursor.col] = NUL;
     }
 #endif
@@ -1320,8 +1367,8 @@
 	    newindent += (int)curbuf->b_p_sw;
 	}
 #endif
-	/* Copy the indent only if expand tab is disabled */
-	if (curbuf->b_p_ci && !curbuf->b_p_et)
+	/* Copy the indent */
+	if (curbuf->b_p_ci)
 	{
 	    (void)copy_indent(newindent, saved_line);
 
@@ -1876,7 +1923,6 @@
     int		charlen;
 {
     int		c = buf[0];
-    int		l, j;
 #endif
     int		newlen;		/* nr of bytes inserted */
     int		oldlen;		/* nr of bytes deleted (0 when not replacing) */
@@ -1978,13 +2024,11 @@
 	for (i = 0; i < oldlen; ++i)
 	{
 #ifdef FEAT_MBYTE
-	    l = (*mb_ptr2len)(oldp + col + i) - 1;
-	    for (j = l; j >= 0; --j)
-		replace_push(oldp[col + i + j]);
-	    i += l;
-#else
-	    replace_push(oldp[col + i]);
+	    if (has_mbyte)
+		i += replace_push_mb(oldp + col + i) - 1;
+	    else
 #endif
+		replace_push(oldp[col + i]);
 	}
     }
 
@@ -2226,13 +2270,16 @@
     /*
      * If the old line has been allocated the deletion can be done in the
      * existing line. Otherwise a new line has to be allocated
+     * Can't do this when using Netbeans, because we would need to invoke
+     * netbeans_removed(), which deallocates the line.  Let ml_replace() take
+     * care of notifiying Netbeans.
      */
-    was_alloced = ml_line_alloced();	    /* check if oldp was allocated */
 #ifdef FEAT_NETBEANS_INTG
-    if (was_alloced && usingNetbeans)
-	netbeans_removed(curbuf, lnum, col, count);
-    /* else is handled by ml_replace() */
+    if (usingNetbeans)
+	was_alloced = FALSE;
+    else
 #endif
+	was_alloced = ml_line_alloced();    /* check if oldp was allocated */
     if (was_alloced)
 	newp = oldp;			    /* use same allocated memory */
     else
@@ -2982,7 +3029,7 @@
 	if (direct)
 	    r = get_keystroke();
 	else
-	    r = safe_vgetc();
+	    r = plain_vgetc();
 	if (r == Ctrl_C || r == ESC)
 	    r = 'n';
 	msg_putchar(r);	    /* show what you typed */
@@ -3468,9 +3515,38 @@
 #endif
 
 /*
+ * Call expand_env() and store the result in an allocated string.
+ * This is not very memory efficient, this expects the result to be freed
+ * again soon.
+ */
+    char_u *
+expand_env_save(src)
+    char_u	*src;
+{
+    return expand_env_save_opt(src, FALSE);
+}
+
+/*
+ * Idem, but when "one" is TRUE handle the string as one file name, only
+ * expand "~" at the start.
+ */
+    char_u *
+expand_env_save_opt(src, one)
+    char_u	*src;
+    int		one;
+{
+    char_u	*p;
+
+    p = alloc(MAXPATHL);
+    if (p != NULL)
+	expand_env_esc(src, p, MAXPATHL, FALSE, one, NULL);
+    return p;
+}
+
+/*
  * Expand environment variable with path name.
  * "~/" is also expanded, using $HOME.	For Unix "~user/" is expanded.
- * Skips over "\ ", "\~" and "\$".
+ * Skips over "\ ", "\~" and "\$" (not for Win32 though).
  * If anything fails no expansion is done and dst equals src.
  */
     void
@@ -3479,15 +3555,16 @@
     char_u	*dst;		/* where to put the result */
     int		dstlen;		/* maximum length of the result */
 {
-    expand_env_esc(src, dst, dstlen, FALSE, NULL);
+    expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL);
 }
 
     void
-expand_env_esc(srcp, dst, dstlen, esc, startstr)
+expand_env_esc(srcp, dst, dstlen, esc, one, startstr)
     char_u	*srcp;		/* input string e.g. "$HOME/vim.hlp" */
     char_u	*dst;		/* where to put the result */
     int		dstlen;		/* maximum length of the result */
     int		esc;		/* escape spaces in expanded variables */
+    int		one;		/* "srcp" is one file name */
     char_u	*startstr;	/* start again after this (can be NULL) */
 {
     char_u	*src;
@@ -3728,6 +3805,8 @@
 	{
 	    /*
 	     * Recognize the start of a new name, for '~'.
+	     * Don't do this when "one" is TRUE, to avoid expanding "~" in
+	     * ":edit foo ~ foo".
 	     */
 	    at_start = FALSE;
 	    if (src[0] == '\\' && src[1] != NUL)
@@ -3735,7 +3814,7 @@
 		*dst++ = *src++;
 		--dstlen;
 	    }
-	    else if (src[0] == ' ' || src[0] == ',')
+	    else if ((src[0] == ' ' || src[0] == ',') && !one)
 		at_start = TRUE;
 	    *dst++ = *src++;
 	    --dstlen;
@@ -3902,7 +3981,7 @@
 	    /* remove trailing path separator */
 #ifndef MACOS_CLASSIC
 	    /* With MacOS path (with  colons) the final colon is required */
-	    /* to avoid confusion between absoulute and relative path */
+	    /* to avoid confusion between absolute and relative path */
 	    if (pend > p && after_pathsep(p, pend))
 		--pend;
 #endif
@@ -4032,23 +4111,6 @@
 }
 
 /*
- * Call expand_env() and store the result in an allocated string.
- * This is not very memory efficient, this expects the result to be freed
- * again soon.
- */
-    char_u *
-expand_env_save(src)
-    char_u	*src;
-{
-    char_u	*p;
-
-    p = alloc(MAXPATHL);
-    if (p != NULL)
-	expand_env(src, p, MAXPATHL);
-    return p;
-}
-
-/*
  * Our portable version of setenv.
  */
     void
@@ -4786,7 +4848,7 @@
 static int	cin_iswhileofdo __ARGS((char_u *, linenr_T, int));
 static int	cin_iswhileofdo_end __ARGS((int terminated, int	ind_maxparen, int ind_maxcomment));
 static int	cin_isbreak __ARGS((char_u *));
-static int	cin_is_cpp_baseclass __ARGS((char_u *line, colnr_T *col));
+static int	cin_is_cpp_baseclass __ARGS((colnr_T *col));
 static int	get_baseclass_amount __ARGS((int col, int ind_maxparen, int ind_maxcomment, int ind_cpp_baseclass));
 static int	cin_ends_in __ARGS((char_u *, char_u *, char_u *));
 static int	cin_skip2pos __ARGS((pos_T *trypos));
@@ -5551,13 +5613,13 @@
  * This is a lot of guessing.  Watch out for "cond ? func() : foo".
  */
     static int
-cin_is_cpp_baseclass(line, col)
-    char_u	*line;
+cin_is_cpp_baseclass(col)
     colnr_T	*col;	    /* return: column to align with */
 {
     char_u	*s;
     int		class_or_struct, lookfor_ctor_init, cpp_base_class;
     linenr_T	lnum = curwin->w_cursor.lnum;
+    char_u	*line = ml_get_curline();
 
     *col = 0;
 
@@ -5585,7 +5647,8 @@
      */
     while (lnum > 1)
     {
-	s = skipwhite(ml_get(lnum - 1));
+	line = ml_get(lnum - 1);
+	s = skipwhite(line);
 	if (*s == '#' || *s == NUL)
 	    break;
 	while (*s != NUL)
@@ -5602,7 +5665,8 @@
 	--lnum;
     }
 
-    s = cin_skipcomment(ml_get(lnum));
+    line = ml_get(lnum);
+    s = cin_skipcomment(line);
     for (;;)
     {
 	if (*s == NUL)
@@ -5610,7 +5674,10 @@
 	    if (lnum == curwin->w_cursor.lnum)
 		break;
 	    /* Continue in the cursor line. */
-	    s = cin_skipcomment(ml_get(++lnum));
+	    line = ml_get(++lnum);
+	    s = cin_skipcomment(line);
+	    if (*s == NUL)
+		continue;
 	}
 
 	if (s[0] == ':')
@@ -5625,7 +5692,7 @@
 	    else if (lookfor_ctor_init || class_or_struct)
 	    {
 		/* we have something found, that looks like the start of
-		 * cpp-base-class-declaration or contructor-initialization */
+		 * cpp-base-class-declaration or constructor-initialization */
 		cpp_base_class = TRUE;
 		lookfor_ctor_init = class_or_struct = FALSE;
 		*col = 0;
@@ -6082,7 +6149,7 @@
     pos_T	our_paren_pos;
     char_u	*start;
     int		start_brace;
-#define BRACE_IN_COL0		1	    /* '{' is in comumn 0 */
+#define BRACE_IN_COL0		1	    /* '{' is in column 0 */
 #define BRACE_AT_START		2	    /* '{' is at start of line */
 #define BRACE_AT_END		3	    /* '{' is at end of line */
     linenr_T	ourscope;
@@ -6305,7 +6372,7 @@
 		    if (curwin->w_cursor.lnum > 1)
 		    {
 			/* If the start comment string matches in the previous
-			 * line, use the indent of that line pluss offset.  If
+			 * line, use the indent of that line plus offset.  If
 			 * the middle comment string matches in the previous
 			 * line, use the indent of that line.  XXX */
 			look = skipwhite(ml_get(curwin->w_cursor.lnum - 1));
@@ -7079,7 +7146,7 @@
 		n = FALSE;
 		if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass > 0)
 		{
-		    n = cin_is_cpp_baseclass(l, &col);
+		    n = cin_is_cpp_baseclass(&col);
 		    l = ml_get_curline();
 		}
 		if (n)
@@ -7670,7 +7737,7 @@
 		n = FALSE;
 		if (ind_cpp_baseclass != 0 && theline[0] != '{')
 		{
-		    n = cin_is_cpp_baseclass(l, &col);
+		    n = cin_is_cpp_baseclass(&col);
 		    l = ml_get_curline();
 		}
 		if (n)
@@ -8158,7 +8225,7 @@
 
 		    if (*that && *that != ';') /* not a comment line */
 		    {
-			/* test *that != '(' to accomodate first let/do
+			/* test *that != '(' to accommodate first let/do
 			 * argument if it is more than one line */
 			if (!vi_lisp && *that != '(' && *that != '[')
 			    firsttry++;
@@ -8596,7 +8663,7 @@
     for (p = buf + wildoff; p < s; ++p)
 	if (rem_backslash(p))
 	{
-	    STRCPY(p, p + 1);
+	    mch_memmove(p, p + 1, STRLEN(p));
 	    --e;
 	    --s;
 	}
@@ -8897,7 +8964,7 @@
     for (p = buf + wildoff; p < s; ++p)
 	if (rem_backslash(p))
 	{
-	    STRCPY(p, p + 1);
+	    mch_memmove(p, p + 1, STRLEN(p));
 	    --e;
 	    --s;
 	}
@@ -9096,7 +9163,7 @@
 	     */
 	    if (vim_strpbrk(p, (char_u *)"$~") != NULL)
 	    {
-		p = expand_env_save(p);
+		p = expand_env_save_opt(p, TRUE);
 		if (p == NULL)
 		    p = pat[i];
 #ifdef UNIX
diff -Naur vim71.orig/src/misc2.c vim71/src/misc2.c
--- vim71.orig/src/misc2.c	2007-05-07 19:49:26.000000000 +0000
+++ vim71/src/misc2.c	2008-02-14 21:07:34.000000000 +0000
@@ -507,12 +507,17 @@
 	curwin->w_cursor.col = 0;
     else if (curwin->w_cursor.col >= len)
     {
-	/* Allow cursor past end-of-line in Insert mode, restarting Insert
-	 * mode or when in Visual mode and 'selection' isn't "old" */
+	/* Allow cursor past end-of-line when:
+	 * - in Insert mode or restarting Insert mode
+	 * - in Visual mode and 'selection' isn't "old"
+	 * - 'virtualedit' is set */
 	if ((State & INSERT) || restart_edit
 #ifdef FEAT_VISUAL
 		|| (VIsual_active && *p_sel != 'o')
 #endif
+#ifdef FEAT_VIRTUALEDIT
+		|| (ve_flags & VE_ONEMORE)
+#endif
 		|| virtual_active())
 	    curwin->w_cursor.col = len;
 	else
@@ -964,7 +969,6 @@
 {
     buf_T	*buf, *nextbuf;
     static int	entered = FALSE;
-    win_T	*win;
 
     /* When we cause a crash here it is caught and Vim tries to exit cleanly.
      * Don't try freeing everything again. */
@@ -972,15 +976,17 @@
 	return;
     entered = TRUE;
 
-    ++autocmd_block;	    /* don't want to trigger autocommands here */
+# ifdef FEAT_AUTOCMD
+    block_autocmds();	    /* don't want to trigger autocommands here */
+# endif
 
-#ifdef FEAT_WINDOWS
+# ifdef FEAT_WINDOWS
     /* close all tabs and windows */
     if (first_tabpage->tp_next != NULL)
 	do_cmdline_cmd((char_u *)"tabonly!");
     if (firstwin != lastwin)
 	do_cmdline_cmd((char_u *)"only!");
-#endif
+# endif
 
 # if defined(FEAT_SPELL)
     /* Free all spell info. */
@@ -1031,27 +1037,41 @@
     free_regexp_stuff();
     free_tag_stuff();
     free_cd_dir();
+# ifdef FEAT_EVAL
     set_expr_line(NULL);
+# endif
+# ifdef FEAT_DIFF
     diff_clear(curtab);
+# endif
     clear_sb_text();	      /* free any scrollback text */
 
     /* Free some global vars. */
     vim_free(username);
+# ifdef FEAT_CLIPBOARD
     vim_free(clip_exclude_prog);
+# endif
     vim_free(last_cmdline);
+# ifdef FEAT_CMDHIST
     vim_free(new_last_cmdline);
+# endif
     set_keep_msg(NULL, 0);
     vim_free(ff_expand_buffer);
 
     /* Clear cmdline history. */
     p_hi = 0;
+# ifdef FEAT_CMDHIST
     init_history();
+# endif
 
 #ifdef FEAT_QUICKFIX
-    qf_free_all(NULL);
-    /* Free all location lists */
-    FOR_ALL_WINDOWS(win)
-	qf_free_all(win);
+    {
+	win_T	*win;
+
+	qf_free_all(NULL);
+	/* Free all location lists */
+	FOR_ALL_WINDOWS(win)
+	    qf_free_all(win);
+    }
 #endif
 
     /* Close all script inputs. */
@@ -5922,7 +5942,11 @@
 {
     if (emsg_not_now())
 	return TRUE;		/* no error messages at the moment */
+#ifdef HAVE_STDARG_H
+    vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2);
+#else
     vim_snprintf((char *)IObuff, IOSIZE, (char *)s, (long_u)a1, (long_u)a2);
+#endif
     return emsg(IObuff);
 }
 
diff -Naur vim71.orig/src/netbeans.c vim71/src/netbeans.c
--- vim71.orig/src/netbeans.c	2007-05-07 19:51:36.000000000 +0000
+++ vim71/src/netbeans.c	2008-02-14 21:07:34.000000000 +0000
@@ -1204,6 +1204,54 @@
     return result;
 }
 
+/*
+ * Remove from "first" byte to "last" byte (inclusive), at line "lnum" of the
+ * current buffer.  Remove to end of line when "last" is MAXCOL.
+ */
+    static void
+nb_partialremove(linenr_T lnum, colnr_T first, colnr_T last)
+{
+    char_u *oldtext, *newtext;
+    int oldlen;
+    int lastbyte = last;
+
+    oldtext = ml_get(lnum);
+    oldlen = STRLEN(oldtext);
+    if (first >= (colnr_T)oldlen || oldlen == 0)  /* just in case */
+	return;
+    if (lastbyte >= oldlen)
+	lastbyte = oldlen - 1;
+    newtext = alloc(oldlen - (int)(lastbyte - first));
+    if (newtext != NULL)
+    {
+	mch_memmove(newtext, oldtext, first);
+	mch_memmove(newtext + first, oldtext + lastbyte + 1, STRLEN(oldtext + lastbyte + 1) + 1);
+	nbdebug(("    NEW LINE %d: %s\n", lnum, newtext));
+	ml_replace(lnum, newtext, FALSE);
+    }
+}
+
+/*
+ * Replace the "first" line with the concatenation of the "first" and
+ * the "other" line. The "other" line is not removed.
+ */
+    static void
+nb_joinlines(linenr_T first, linenr_T other)
+{
+    int len_first, len_other;
+    char_u *p;
+
+    len_first = STRLEN(ml_get(first));
+    len_other = STRLEN(ml_get(other));
+    p = alloc((unsigned)(len_first + len_other + 1));
+    if (p != NULL)
+    {
+      mch_memmove(p, ml_get(first), len_first);
+      mch_memmove(p + len_first, ml_get(other), len_other + 1);
+      ml_replace(first, p, FALSE);
+    }
+}
+
 #define SKIP_STOP 2
 #define streq(a,b) (strcmp(a,b) == 0)
 static int needupdate = 0;
@@ -1371,6 +1419,8 @@
 	    long count;
 	    pos_T first, last;
 	    pos_T *pos;
+	    pos_T *next;
+	    linenr_T del_from_lnum, del_to_lnum;  /* lines to be deleted as a whole */
 	    int oldFire = netbeansFireChanges;
 	    int oldSuppress = netbeansSuppressNoLines;
 	    int wasChanged;
@@ -1420,25 +1470,75 @@
 		}
 		last = *pos;
 		nbdebug(("    LAST POS: line %d, col %d\n", last.lnum, last.col));
-		curwin->w_cursor = first;
+		del_from_lnum = first.lnum;
+		del_to_lnum = last.lnum;
 		doupdate = 1;
 
-		/* keep part of first line */
-		if (first.lnum == last.lnum && first.col != last.col)
+		/* Get the position of the first byte after the deleted
+		 * section.  "next" is NULL when deleting to the end of the
+		 * file. */
+		next = off2pos(buf->bufp, off + count);
+
+		/* Remove part of the first line. */
+		if (first.col != 0 || (next != NULL && first.lnum == next->lnum))
 		{
-		    /* deletion is within one line */
-		    char_u *p = ml_get(first.lnum);
-		    mch_memmove(p + first.col, p + last.col + 1, STRLEN(p + last.col) + 1);
-		    nbdebug(("    NEW LINE %d: %s\n", first.lnum, p));
-		    ml_replace(first.lnum, p, TRUE);
+		    if (first.lnum != last.lnum
+			    || (next != NULL && first.lnum != next->lnum))
+		    {
+			/* remove to the end of the first line */
+			nb_partialremove(first.lnum, first.col,
+							     (colnr_T)MAXCOL);
+			if (first.lnum == last.lnum)
+			{
+			    /* Partial line to remove includes the end of
+			     * line.  Join the line with the next one, have
+			     * the next line deleted below. */
+			    nb_joinlines(first.lnum, next->lnum);
+			    del_to_lnum = next->lnum;
+			}
+		    }
+		    else
+		    {
+			/* remove within one line */
+			nb_partialremove(first.lnum, first.col, last.col);
+		    }
+		    ++del_from_lnum;  /* don't delete the first line */
 		}
 
-		if (first.lnum < last.lnum)
+		/* Remove part of the last line. */
+		if (first.lnum != last.lnum && next != NULL
+			&& next->col != 0 && last.lnum == next->lnum)
+		{
+		    nb_partialremove(last.lnum, 0, last.col);
+		    if (del_from_lnum > first.lnum)
+		    {
+			/* Join end of last line to start of first line; last
+			 * line is deleted below. */
+			nb_joinlines(first.lnum, last.lnum);
+		    }
+		    else
+			/* First line is deleted as a whole, keep the last
+			 * line. */
+			--del_to_lnum;
+		}
+
+		/* First is partial line; last line to remove includes
+		 * the end of line; join first line to line following last
+		 * line; line following last line is deleted below. */
+		if (first.lnum != last.lnum && del_from_lnum > first.lnum
+			&& next != NULL && last.lnum != next->lnum)
+		{
+		    nb_joinlines(first.lnum, next->lnum);
+		    del_to_lnum = next->lnum;
+		}
+
+		/* Delete whole lines if there are any. */
+		if (del_to_lnum >= del_from_lnum)
 		{
 		    int i;
 
 		    /* delete signs from the lines being deleted */
-		    for (i = first.lnum; i <= last.lnum; i++)
+		    for (i = del_from_lnum; i <= del_to_lnum; i++)
 		    {
 			int id = buf_findsign_id(buf->bufp, (linenr_T)i);
 			if (id > 0)
@@ -1450,10 +1550,15 @@
 			    nbdebug(("    No sign on line %d\n", i));
 		    }
 
-		    /* delete whole lines */
-		    nbdebug(("    Deleting lines %d through %d\n", first.lnum, last.lnum));
-		    del_lines(last.lnum - first.lnum + 1, FALSE);
+		    nbdebug(("    Deleting lines %d through %d\n", del_from_lnum, del_to_lnum));
+		    curwin->w_cursor.lnum = del_from_lnum;
+		    curwin->w_cursor.col = 0;
+		    del_lines(del_to_lnum - del_from_lnum + 1, FALSE);
 		}
+
+		/* Leave cursor at first deleted byte. */
+		curwin->w_cursor = first;
+		check_cursor_lnum();
 		buf->bufp->b_changed = wasChanged; /* logically unchanged */
 		netbeansFireChanges = oldFire;
 		netbeansSuppressNoLines = oldSuppress;
@@ -2374,8 +2479,7 @@
  * the current buffer as "buf".
  */
     static void
-nb_set_curbuf(buf)
-    buf_T *buf;
+nb_set_curbuf(buf_T *buf)
 {
     if (curbuf != buf && buf_jump_open_win(buf) == NULL)
 	set_curbuf(buf, DOBUF_GOTO);
diff -Naur vim71.orig/src/normal.c vim71/src/normal.c
--- vim71.orig/src/normal.c	2007-05-07 19:34:39.000000000 +0000
+++ vim71/src/normal.c	2008-02-14 21:07:34.000000000 +0000
@@ -141,12 +141,16 @@
 static void	nv_Undo __ARGS((cmdarg_T *cap));
 static void	nv_tilde __ARGS((cmdarg_T *cap));
 static void	nv_operator __ARGS((cmdarg_T *cap));
+#ifdef FEAT_EVAL
+static void	set_op_var __ARGS((int optype));
+#endif
 static void	nv_lineop __ARGS((cmdarg_T *cap));
 static void	nv_home __ARGS((cmdarg_T *cap));
 static void	nv_pipe __ARGS((cmdarg_T *cap));
 static void	nv_bck_word __ARGS((cmdarg_T *cap));
 static void	nv_wordcmd __ARGS((cmdarg_T *cap));
 static void	nv_beginline __ARGS((cmdarg_T *cap));
+static void	adjust_cursor __ARGS((oparg_T *oap));
 #ifdef FEAT_VISUAL
 static void	adjust_for_sel __ARGS((cmdarg_T *cap));
 static int	unadjust_for_sel __ARGS((void));
@@ -690,13 +694,20 @@
 		ca.count0 = ca.count0 * 10 + (c - '0');
 	    if (ca.count0 < 0)	    /* got too large! */
 		ca.count0 = 999999999L;
+#ifdef FEAT_EVAL
+	    /* Set v:count here, when called from main() and not a stuffed
+	     * command, so that v:count can be used in an expression mapping
+	     * right after the count. */
+	    if (toplevel && stuff_empty())
+		set_vcount(ca.count0, ca.count0 == 0 ? 1 : ca.count0);
+#endif
 	    if (ctrl_w)
 	    {
 		++no_mapping;
 		++allow_keys;		/* no mapping for nchar, but keys */
 	    }
 	    ++no_zero_mapping;		/* don't map zero here */
-	    c = safe_vgetc();
+	    c = plain_vgetc();
 #ifdef FEAT_LANGMAP
 	    LANGMAP_ADJUST(c, TRUE);
 #endif
@@ -721,7 +732,7 @@
 	    ca.count0 = 0;
 	    ++no_mapping;
 	    ++allow_keys;		/* no mapping for nchar, but keys */
-	    c = safe_vgetc();		/* get next character */
+	    c = plain_vgetc();		/* get next character */
 #ifdef FEAT_LANGMAP
 	    LANGMAP_ADJUST(c, TRUE);
 #endif
@@ -889,13 +900,18 @@
 
 	++no_mapping;
 	++allow_keys;		/* no mapping for nchar, but allow key codes */
+#ifdef FEAT_AUTOCMD
+	/* Don't generate a CursorHold event here, most commands can't handle
+	 * it, e.g., nv_replace(), nv_csearch(). */
+	did_cursorhold = TRUE;
+#endif
 	if (ca.cmdchar == 'g')
 	{
 	    /*
 	     * For 'g' get the next character now, so that we can check for
 	     * "gr", "g'" and "g`".
 	     */
-	    ca.nchar = safe_vgetc();
+	    ca.nchar = plain_vgetc();
 #ifdef FEAT_LANGMAP
 	    LANGMAP_ADJUST(ca.nchar, TRUE);
 #endif
@@ -952,7 +968,7 @@
 		im_set_active(TRUE);
 #endif
 
-	    *cp = safe_vgetc();
+	    *cp = plain_vgetc();
 
 	    if (langmap_active)
 	    {
@@ -1040,7 +1056,7 @@
 		}
 		if (c > 0)
 		{
-		    c = safe_vgetc();
+		    c = plain_vgetc();
 		    if (c != Ctrl_N && c != Ctrl_G)
 			vungetc(c);
 		    else
@@ -1059,7 +1075,7 @@
 	    while (enc_utf8 && lang && (c = vpeekc()) > 0
 				 && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1))
 	    {
-		c = safe_vgetc();
+		c = plain_vgetc();
 		if (!utf_iscomposing(c))
 		{
 		    vungetc(c);		/* it wasn't, put it back */
@@ -3755,7 +3771,8 @@
     extra_len = (int)STRLEN(p);
     overflow = old_len + extra_len - SHOWCMD_COLS;
     if (overflow > 0)
-	STRCPY(showcmd_buf, showcmd_buf + overflow);
+	mch_memmove(showcmd_buf, showcmd_buf + overflow,
+						      old_len - overflow + 1);
     STRCAT(showcmd_buf, p);
 
     if (char_avail())
@@ -4178,7 +4195,7 @@
     for (;;)
     {
 	t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD,
-				  pat, 1L, searchflags, RE_LAST, (linenr_T)0);
+			    pat, 1L, searchflags, RE_LAST, (linenr_T)0, NULL);
 	if (curwin->w_cursor.lnum >= old_pos.lnum)
 	    t = FAIL;	/* match after start is failure too */
 
@@ -4558,7 +4575,7 @@
 #endif
 	    ++no_mapping;
 	    ++allow_keys;   /* no mapping for nchar, but allow key codes */
-	    nchar = safe_vgetc();
+	    nchar = plain_vgetc();
 #ifdef FEAT_LANGMAP
 	    LANGMAP_ADJUST(nchar, TRUE);
 #endif
@@ -4916,7 +4933,7 @@
     case 'u':	/* "zug" and "zuw": undo "zg" and "zw" */
 		++no_mapping;
 		++allow_keys;   /* no mapping for nchar, but allow key codes */
-		nchar = safe_vgetc();
+		nchar = plain_vgetc();
 #ifdef FEAT_LANGMAP
 		LANGMAP_ADJUST(nchar, TRUE);
 #endif
@@ -5836,12 +5853,13 @@
 		/* When the NL before the first char has to be deleted we
 		 * put the cursor on the NUL after the previous line.
 		 * This is a very special case, be careful!
-		 * don't adjust op_end now, otherwise it won't work */
+		 * Don't adjust op_end now, otherwise it won't work. */
 		if (	   (cap->oap->op_type == OP_DELETE
 			    || cap->oap->op_type == OP_CHANGE)
 			&& !lineempty(curwin->w_cursor.lnum))
 		{
-		    ++curwin->w_cursor.col;
+		    if (*ml_get_cursor() != NUL)
+			++curwin->w_cursor.col;
 		    cap->retval |= CA_NO_ADJ_OP_END;
 		}
 		continue;
@@ -6075,7 +6093,7 @@
     curwin->w_set_curswant = TRUE;
 
     i = do_search(cap->oap, dir, pat, cap->count1,
-				 opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG);
+			   opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG, NULL);
     if (i == 0)
 	clearop(cap->oap);
     else
@@ -6379,7 +6397,7 @@
      */
     else if (cap->nchar == 'p' || cap->nchar == 'P')
     {
-	if (!checkclearopq(cap->oap))
+	if (!checkclearop(cap->oap))
 	{
 	    prep_redo_cmd(cap);
 	    do_put(cap->oap->regname,
@@ -6550,6 +6568,8 @@
 	clearopbeep(cap->oap);
     else
     {
+	/* Don't leave the cursor on the NUL past end of line. */
+	adjust_cursor(cap->oap);
 #ifdef FEAT_VIRTUALEDIT
 	curwin->w_cursor.coladd = 0;
 #endif
@@ -6662,6 +6682,13 @@
     else
 	had_ctrl_v = NUL;
 
+    /* Abort if the character is a special key. */
+    if (IS_SPECIAL(cap->nchar))
+    {
+	clearopbeep(cap->oap);
+	return;
+    }
+
 #ifdef FEAT_VISUAL
     /* Visual mode "r" */
     if (VIsual_active)
@@ -6688,11 +6715,9 @@
     }
 #endif
 
-    /*
-     * Check for a special key or not enough characters to replace.
-     */
+    /* Abort if not enough characters to replace. */
     ptr = ml_get_cursor();
-    if (IS_SPECIAL(cap->nchar) || STRLEN(ptr) < (unsigned)cap->count1
+    if (STRLEN(ptr) < (unsigned)cap->count1
 #ifdef FEAT_MBYTE
 	    || (has_mbyte && mb_charlen(ptr) < cap->count1)
 #endif
@@ -7155,6 +7180,9 @@
 	{
 	    cap->oap->start = curwin->w_cursor;
 	    cap->oap->op_type = OP_DELETE;
+#ifdef FEAT_EVAL
+	    set_op_var(OP_DELETE);
+#endif
 	    cap->count1 = 1;
 	    nv_dollar(cap);
 	    finish_op = TRUE;
@@ -8194,9 +8222,34 @@
     {
 	cap->oap->start = curwin->w_cursor;
 	cap->oap->op_type = op_type;
+#ifdef FEAT_EVAL
+	set_op_var(op_type);
+#endif
     }
 }
 
+#ifdef FEAT_EVAL
+/*
+ * Set v:operator to the characters for "optype".
+ */
+    static void
+set_op_var(optype)
+    int optype;
+{
+    char_u	opchars[3];
+
+    if (optype == OP_NOP)
+	set_vim_var_string(VV_OP, NULL, 0);
+    else
+    {
+	opchars[0] = get_op_char(optype);
+	opchars[1] = get_extra_op_char(optype);
+	opchars[2] = NUL;
+	set_vim_var_string(VV_OP, opchars, -1);
+    }
+}
+#endif
+
 /*
  * Handle linewise operator "dd", "yy", etc.
  *
@@ -8352,12 +8405,9 @@
     else
 	n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP);
 
-    /* Don't leave the cursor on the NUL past a line */
-    if (curwin->w_cursor.col && gchar_cursor() == NUL)
-    {
-	--curwin->w_cursor.col;
-	cap->oap->inclusive = TRUE;
-    }
+    /* Don't leave the cursor on the NUL past the end of line. */
+    if (n != FAIL)
+	adjust_cursor(cap->oap);
 
     if (n == FAIL && cap->oap->op_type == OP_NOP)
 	clearopbeep(cap->oap);
@@ -8374,6 +8424,39 @@
 }
 
 /*
+ * Used after a movement command: If the cursor ends up on the NUL after the
+ * end of the line, may move it back to the last character and make the motion
+ * inclusive.
+ */
+    static void
+adjust_cursor(oap)
+    oparg_T *oap;
+{
+    /* The cursor cannot remain on the NUL when:
+     * - the column is > 0
+     * - not in Visual mode or 'selection' is "o"
+     * - 'virtualedit' is not "all" and not "onemore".
+     */
+    if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL
+#ifdef FEAT_VISUAL
+		&& (!VIsual_active || *p_sel == 'o')
+#endif
+#ifdef FEAT_VIRTUALEDIT
+		&& !virtual_active() && (ve_flags & VE_ONEMORE) == 0
+#endif
+		)
+    {
+	--curwin->w_cursor.col;
+#ifdef FEAT_MBYTE
+	/* prevent cursor from moving on the trail byte */
+	if (has_mbyte)
+	    mb_adjust_cursor();
+#endif
+	oap->inclusive = TRUE;
+    }
+}
+
+/*
  * "0" and "^" commands.
  * cap->arg is the argument for beginline().
  */
diff -Naur vim71.orig/src/ops.c vim71/src/ops.c
--- vim71.orig/src/ops.c	2007-05-07 19:33:47.000000000 +0000
+++ vim71/src/ops.c	2008-02-14 21:07:34.000000000 +0000
@@ -258,7 +258,7 @@
 	    if (first_char != '#' || !preprocs_left())
 #endif
 	{
-	    shift_line(oap->op_type == OP_LSHIFT, p_sr, amount);
+	    shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, FALSE);
 	}
 	++curwin->w_cursor.lnum;
     }
@@ -321,10 +321,11 @@
  * leaves cursor on first blank in the line
  */
     void
-shift_line(left, round, amount)
+shift_line(left, round, amount, call_changed_bytes)
     int	left;
     int	round;
     int	amount;
+    int call_changed_bytes;	/* call changed_bytes() */
 {
     int		count;
     int		i, j;
@@ -363,10 +364,10 @@
     /* Set new indent */
 #ifdef FEAT_VREPLACE
     if (State & VREPLACE_FLAG)
-	change_indent(INDENT_SET, count, FALSE, NUL);
+	change_indent(INDENT_SET, count, FALSE, NUL, call_changed_bytes);
     else
 #endif
-	(void)set_indent(count, SIN_CHANGED);
+	(void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
 }
 
 #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
@@ -927,15 +928,16 @@
     int		name;
     int		copy;	/* make a copy, if FALSE make register empty. */
 {
-    static struct yankreg	*reg;
-    int				i;
+    struct yankreg	*reg;
+    int			i;
 
 #ifdef FEAT_CLIPBOARD
     /* When Visual area changed, may have to update selection.  Obtain the
      * selection too. */
-    if (name == '*' && clip_star.available && clip_isautosel())
+    if (name == '*' && clip_star.available)
     {
-	clip_update_selection();
+	if (clip_isautosel())
+	    clip_update_selection();
 	may_get_selection(name);
     }
 #endif
@@ -966,7 +968,7 @@
 }
 
 /*
- * Put "reg" into register "name".  Free any previous contents.
+ * Put "reg" into register "name".  Free any previous contents and "reg".
  */
     void
 put_register(name, reg)
@@ -976,6 +978,7 @@
     get_yank_register(name, 0);
     free_yank_all();
     *y_current = *(struct yankreg *)reg;
+    vim_free(reg);
 
 # ifdef FEAT_CLIPBOARD
     /* Send text written to clipboard register to the clipboard. */
@@ -2181,6 +2184,8 @@
 }
 #endif
 
+static int swapchars __ARGS((int op_type, pos_T *pos, int length));
+
 /*
  * Handle the (non-standard vi) tilde operator.  Also for "gu", "gU" and "g?".
  */
@@ -2191,9 +2196,8 @@
     pos_T		pos;
 #ifdef FEAT_VISUAL
     struct block_def	bd;
-    int			todo;
 #endif
-    int			did_change = 0;
+    int			did_change = FALSE;
 
     if (u_save((linenr_T)(oap->start.lnum - 1),
 				       (linenr_T)(oap->end.lnum + 1)) == FAIL)
@@ -2207,16 +2211,8 @@
 	{
 	    block_prep(oap, &bd, pos.lnum, FALSE);
 	    pos.col = bd.textcol;
-	    for (todo = bd.textlen; todo > 0; --todo)
-	    {
-# ifdef FEAT_MBYTE
-		if (has_mbyte)
-		    todo -= (*mb_ptr2len)(ml_get_pos(&pos)) - 1;
-# endif
-		did_change |= swapchar(oap->op_type, &pos);
-		if (inc(&pos) == -1)	    /* at end of file */
-		    break;
-	    }
+	    did_change = swapchars(oap->op_type, &pos, bd.textlen);
+
 # ifdef FEAT_NETBEANS_INTG
 	    if (usingNetbeans && did_change)
 	    {
@@ -2246,13 +2242,18 @@
 	else if (!oap->inclusive)
 	    dec(&(oap->end));
 
-	while (ltoreq(pos, oap->end))
-	{
-	    did_change |= swapchar(oap->op_type, &pos);
-	    if (inc(&pos) == -1)    /* at end of file */
-		break;
-	}
-
+	if (pos.lnum == oap->end.lnum)
+	    did_change = swapchars(oap->op_type, &pos,
+						  oap->end.col - pos.col + 1);
+	else
+	    for (;;)
+	    {
+		did_change |= swapchars(oap->op_type, &pos,
+				pos.lnum == oap->end.lnum ? oap->end.col + 1:
+					   (int)STRLEN(ml_get_pos(&pos)));
+		if (ltoreq(oap->end, pos) || inc(&pos) == -1)
+		    break;
+	    }
 	if (did_change)
 	{
 	    changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1,
@@ -2306,6 +2307,36 @@
 }
 
 /*
+ * Invoke swapchar() on "length" bytes at position "pos".
+ * "pos" is advanced to just after the changed characters.
+ * "length" is rounded up to include the whole last multi-byte character.
+ * Also works correctly when the number of bytes changes.
+ * Returns TRUE if some character was changed.
+ */
+    static int
+swapchars(op_type, pos, length)
+    int		op_type;
+    pos_T	*pos;
+    int		length;
+{
+    int todo;
+    int	did_change = 0;
+
+    for (todo = length; todo > 0; --todo)
+    {
+# ifdef FEAT_MBYTE
+	if (has_mbyte)
+	    /* we're counting bytes, not characters */
+	    todo -= (*mb_ptr2len)(ml_get_pos(pos)) - 1;
+# endif
+	did_change |= swapchar(op_type, pos);
+	if (inc(pos) == -1)    /* at end of file */
+	    break;
+    }
+    return did_change;
+}
+
+/*
  * If op_type == OP_UPPER: make uppercase,
  * if op_type == OP_LOWER: make lowercase,
  * if op_type == OP_ROT13: do rot13 encoding,
@@ -2327,7 +2358,8 @@
 	return FALSE;
 
 #ifdef FEAT_MBYTE
-    if (op_type == OP_UPPER && enc_latin1like && c == 0xdf)
+    if (op_type == OP_UPPER && c == 0xdf
+		      && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0))
     {
 	pos_T   sp = curwin->w_cursor;
 
@@ -2466,9 +2498,10 @@
 
     edit(NUL, FALSE, (linenr_T)count1);
 
-    /* if user has moved off this line, we don't know what to do, so do
-     * nothing */
-    if (curwin->w_cursor.lnum != oap->start.lnum)
+    /* If user has moved off this line, we don't know what to do, so do
+     * nothing.
+     * Also don't repeat the insert when Insert mode ended with CTRL-C. */
+    if (curwin->w_cursor.lnum != oap->start.lnum || got_int)
 	return;
 
     if (oap->block_mode)
@@ -2477,7 +2510,7 @@
 
 	/*
 	 * Spaces and tabs in the indent may have changed to other spaces and
-	 * tabs.  Get the starting column again and correct the lenght.
+	 * tabs.  Get the starting column again and correct the length.
 	 * Don't do this when "$" used, end-of-line will have changed.
 	 */
 	block_prep(oap, &bd2, oap->start.lnum, TRUE);
@@ -2534,7 +2567,9 @@
 #ifdef FEAT_VISUALEXTRA
     long		offset;
     linenr_T		linenr;
-    long		ins_len, pre_textlen = 0;
+    long		ins_len;
+    long		pre_textlen = 0;
+    long		pre_indent = 0;
     char_u		*firstline;
     char_u		*ins_text, *newp, *oldp;
     struct block_def	bd;
@@ -2579,7 +2614,9 @@
 						    || gchar_cursor() == NUL))
 	    coladvance_force(getviscol());
 # endif
-	pre_textlen = (long)STRLEN(ml_get(oap->start.lnum));
+	firstline = ml_get(oap->start.lnum);
+	pre_textlen = (long)STRLEN(firstline);
+	pre_indent = (long)(skipwhite(firstline) - firstline);
 	bd.textcol = curwin->w_cursor.col;
     }
 #endif
@@ -2595,16 +2632,26 @@
     /*
      * In Visual block mode, handle copying the new text to all lines of the
      * block.
+     * Don't repeat the insert when Insert mode ended with CTRL-C.
      */
-    if (oap->block_mode && oap->start.lnum != oap->end.lnum)
+    if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int)
     {
+	/* Auto-indenting may have changed the indent.  If the cursor was past
+	 * the indent, exclude that indent change from the inserted text. */
 	firstline = ml_get(oap->start.lnum);
-	/*
-	 * Subsequent calls to ml_get() flush the firstline data - take a
-	 * copy of the required bit.
-	 */
-	if ((ins_len = (long)STRLEN(firstline) - pre_textlen) > 0)
+	if (bd.textcol > (colnr_T)pre_indent)
+	{
+	    long new_indent = (long)(skipwhite(firstline) - firstline);
+
+	    pre_textlen += new_indent - pre_indent;
+	    bd.textcol += new_indent - pre_indent;
+	}
+
+	ins_len = (long)STRLEN(firstline) - pre_textlen;
+	if (ins_len > 0)
 	{
+	    /* Subsequent calls to ml_get() flush the firstline data - take a
+	     * copy of the inserted text.  */
 	    if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != NULL)
 	    {
 		vim_strncpy(ins_text, firstline + bd.textcol, (size_t)ins_len);
@@ -3404,7 +3451,9 @@
 
 #ifdef FEAT_VIRTUALEDIT
 	col += curwin->w_cursor.coladd;
-	if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0)
+	if (ve_flags == VE_ALL
+		&& (curwin->w_cursor.coladd > 0
+		    || endcol2 == curwin->w_cursor.col))
 	{
 	    if (dir == FORWARD && c == NUL)
 		++col;
diff -Naur vim71.orig/src/option.c vim71/src/option.c
--- vim71.orig/src/option.c	2007-05-01 11:26:10.000000000 +0000
+++ vim71/src/option.c	2008-02-14 21:07:34.000000000 +0000
@@ -427,6 +427,8 @@
 #define P_NOGLOB       0x100000L/* do not use local value for global vimrc */
 #define P_NFNAME       0x200000L/* only normal file name chars allowed */
 #define P_INSECURE     0x400000L/* option was set from a modeline */
+#define P_PRI_MKRC     0x800000L/* priority for :mkvimrc (setting option has
+				   side effects) */
 
 #define ISK_LATIN1  (char_u *)"@,48-57,_,192-255"
 
@@ -773,6 +775,8 @@
 			    {(char_u *)0L, (char_u *)0L}
 #endif
 			    },
+			    /* P_PRI_MKRC isn't needed here, optval_default()
+			     * always returns TRUE for 'compatible' */
     {"compatible",  "cp",   P_BOOL|P_RALL,
 			    (char_u *)&p_cp, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)FALSE}},
@@ -1515,7 +1519,7 @@
 			    {(char_u *)0L, (char_u *)0L}
 #endif
 			    },
-    {"keymap",	    "kmp",  P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME,
+    {"keymap",	    "kmp",  P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC,
 #ifdef FEAT_KEYMAP
 			    (char_u *)&p_keymap, PV_KMAP,
 			    {(char_u *)"", (char_u *)0L}
@@ -1836,7 +1840,7 @@
     {"paragraphs",  "para", P_STRING|P_VI_DEF,
 			    (char_u *)&p_para, PV_NONE,
 			    {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}},
-    {"paste",	    NULL,   P_BOOL|P_VI_DEF,
+    {"paste",	    NULL,   P_BOOL|P_VI_DEF|P_PRI_MKRC,
 			    (char_u *)&p_paste, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L}},
     {"pastetoggle", "pt",   P_STRING|P_VI_DEF,
@@ -1987,6 +1991,13 @@
     {"redraw",	    NULL,   P_BOOL|P_VI_DEF,
 			    (char_u *)NULL, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L}},
+    {"redrawtime",  "rdt",  P_NUM|P_VI_DEF,
+#ifdef FEAT_RELTIME
+			    (char_u *)&p_rdt, PV_NONE,
+#else
+			    (char_u *)NULL, PV_NONE,
+#endif
+			    {(char_u *)2000L, (char_u *)0L}},
     {"remap",	    NULL,   P_BOOL|P_VI_DEF,
 			    (char_u *)&p_remap, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)0L}},
@@ -4628,7 +4639,7 @@
 				    if ((!(flags & P_COMMA) || *s != ',')
 					    && vim_strchr(s + 1, *s) != NULL)
 				    {
-					STRCPY(s, s + 1);
+					mch_memmove(s, s + 1, STRLEN(s));
 					--s;
 				    }
 			    }
@@ -4992,7 +5003,7 @@
      * For 'spellsuggest' expand after "file:".
      */
     expand_env_esc(val, NameBuff, MAXPATHL,
-	    (char_u **)options[opt_idx].var == &p_tags,
+	    (char_u **)options[opt_idx].var == &p_tags, FALSE,
 #ifdef FEAT_SPELL
 	    (char_u **)options[opt_idx].var == &p_sps ? (char_u *)"file:" :
 #endif
@@ -5660,7 +5671,7 @@
     {
 	if (gvarp == &p_fenc)
 	{
-	    if (!curbuf->b_p_ma)
+	    if (!curbuf->b_p_ma && opt_flags != OPT_GLOBAL)
 		errmsg = e_modifiable;
 	    else if (vim_strchr(*varp, ',') != NULL)
 		/* No comma allowed in 'fileencoding'; catches confusing it
@@ -6348,7 +6359,7 @@
 		errmsg = check_stl_option(p_ruf);
 	}
 	/* check 'statusline' only if it doesn't start with "%!" */
-	else if (varp != &p_stl || s[0] != '%' || s[1] != '!')
+	else if (varp == &p_ruf || s[0] != '%' || s[1] != '!')
 	    errmsg = check_stl_option(s);
 	if (varp == &p_ruf && errmsg == NULL)
 	    comp_col();
@@ -7118,6 +7129,11 @@
     /* when 'endofline' is changed, redraw the window title */
     else if ((int *)varp == &curbuf->b_p_eol)
 	need_maketitle = TRUE;
+#ifdef FEAT_MBYTE
+    /* when 'bomb' is changed, redraw the window title */
+    else if ((int *)varp == &curbuf->b_p_bomb)
+	need_maketitle = TRUE;
+#endif
 #endif
 
     /* when 'bin' is set also set some other options */
@@ -7815,6 +7831,8 @@
 	    errmsg = e_positive;
 	    p_ch = 1;
 	}
+	if (p_ch > Rows - min_rows() + 1)
+	    p_ch = Rows - min_rows() + 1;
 
 	/* Only compute the new window layout when startup has been
 	 * completed. Otherwise the frame sizes may be wrong. */
@@ -8219,6 +8237,25 @@
 	    varp = get_varp(&options[opt_idx]);
 	    if (varp != NULL)	/* hidden option is not changed */
 	    {
+		if (number == 0 && string != NULL)
+		{
+		    int index;
+
+		    /* Either we are given a string or we are setting option
+		     * to zero. */
+		    for (index = 0; string[index] == '0'; ++index)
+			;
+		    if (string[index] != NUL || index == 0)
+		    {
+			/* There's another character after zeros or the string
+			 * is empty.  In both cases, we are trying to set a
+			 * num option using a string. */
+			EMSG3(_("E521: Number required: &%s = '%s'"),
+								name, string);
+			return;     /* do nothing as we hit an error */
+
+		    }
+		}
 		if (flags & P_NUM)
 		    (void)set_num_option(opt_idx, varp, number,
 							  NULL, 0, opt_flags);
@@ -8511,13 +8548,20 @@
     char_u		*varp_local = NULL;	/* fresh value */
     char		*cmd;
     int			round;
+    int			pri;
 
     /*
      * The options that don't have a default (terminal name, columns, lines)
      * are never written.  Terminal options are also not written.
+     * Do the loop over "options[]" twice: once for options with the
+     * P_PRI_MKRC flag and once without.
      */
-    for (p = &options[0]; !istermoption(p); p++)
-	if (!(p->flags & P_NO_MKRC) && !istermoption(p))
+    for (pri = 1; pri >= 0; --pri)
+    {
+      for (p = &options[0]; !istermoption(p); p++)
+	if (!(p->flags & P_NO_MKRC)
+		&& !istermoption(p)
+		&& ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0)))
 	{
 	    /* skip global option when only doing locals */
 	    if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL))
@@ -8613,6 +8657,7 @@
 		}
 	    }
 	}
+    }
     return OK;
 }
 
@@ -8715,6 +8760,8 @@
     char	*name;
     int		value;
 {
+    if (value < 0)	/* global/local option using global value */
+	return OK;
     if (fprintf(fd, "%s %s%s", cmd, value ? "" : "no", name) < 0
 	    || put_eol(fd) < 0)
 	return FAIL;
@@ -10585,6 +10632,8 @@
     buf->b_start_ffc = *buf->b_p_ff;
     buf->b_start_eol = buf->b_p_eol;
 #ifdef FEAT_MBYTE
+    buf->b_start_bomb = buf->b_p_bomb;
+
     /* Only use free/alloc when necessary, they take time. */
     if (buf->b_start_fenc == NULL
 			     || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0)
@@ -10598,13 +10647,17 @@
 /*
  * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value
  * from when editing started (save_file_ff() called).
- * Also when 'endofline' was changed and 'binary' is set.
+ * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was
+ * changed and 'binary' is not set.
  * Don't consider a new, empty buffer to be changed.
  */
     int
 file_ff_differs(buf)
     buf_T	*buf;
 {
+    /* In a buffer that was never loaded the options are not valid. */
+    if (buf->b_flags & BF_NEVERLOADED)
+	return FALSE;
     if ((buf->b_flags & BF_NEW)
 	    && buf->b_ml.ml_line_count == 1
 	    && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL)
@@ -10614,6 +10667,8 @@
     if (buf->b_p_bin && buf->b_start_eol != buf->b_p_eol)
 	return TRUE;
 #ifdef FEAT_MBYTE
+    if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb)
+	return TRUE;
     if (buf->b_start_fenc == NULL)
 	return (*buf->b_p_fenc != NUL);
     return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0);
diff -Naur vim71.orig/src/option.h vim71/src/option.h
--- vim71.orig/src/option.h	2007-05-07 19:23:03.000000000 +0000
+++ vim71/src/option.h	2008-02-14 21:07:34.000000000 +0000
@@ -633,6 +633,9 @@
 #ifdef FEAT_SEARCHPATH
 EXTERN char_u	*p_cdpath;	/* 'cdpath' */
 #endif
+#ifdef FEAT_RELTIME
+EXTERN long	p_rdt;		/* 'redrawtime' */
+#endif
 EXTERN int	p_remap;	/* 'remap' */
 EXTERN long	p_report;	/* 'report' */
 #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
diff -Naur vim71.orig/src/os_unix.c vim71/src/os_unix.c
--- vim71.orig/src/os_unix.c	2007-05-09 19:41:58.000000000 +0000
+++ vim71/src/os_unix.c	2008-02-14 21:07:34.000000000 +0000
@@ -195,6 +195,7 @@
 static int	show_shell_mess = TRUE;
 #endif
 static int	deadly_signal = 0;	    /* The signal we caught */
+static int	in_mch_delay = FALSE;	    /* sleeping in mch_delay() */
 
 static int curr_tmode = TMODE_COOK;	/* contains current terminal mode */
 
@@ -310,7 +311,7 @@
 }
 
 /*
- * mch_inchar(): low level input funcion.
+ * mch_inchar(): low level input function.
  * Get a characters from the keyboard.
  * Return the number of characters that are available.
  * If wtime == 0 do not wait for characters.
@@ -538,7 +539,9 @@
     if (ignoreinput)
     {
 	/* Go to cooked mode without echo, to allow SIGINT interrupting us
-	 * here */
+	 * here.  But we don't want QUIT to kill us (CTRL-\ used in a
+	 * shell may produce SIGQUIT). */
+	in_mch_delay = TRUE;
 	old_tmode = curr_tmode;
 	if (curr_tmode == TMODE_RAW)
 	    settmode(TMODE_SLEEP);
@@ -602,6 +605,7 @@
 #endif
 
 	settmode(old_tmode);
+	in_mch_delay = FALSE;
     }
     else
 	WaitForChar(msec);
@@ -753,7 +757,8 @@
     if (signal_stack != NULL)
     {
 # ifdef HAVE_SIGALTSTACK
-#  ifdef __APPLE__
+#  if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
+		|| MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
 	/* missing prototype.  Adding it to osdef?.h.in doesn't work, because
 	 * "struct sigaltstack" needs to be declared. */
 	extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
@@ -921,6 +926,14 @@
 #endif
 
 #ifdef SIGHASARG
+# ifdef SIGQUIT
+    /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
+     * interrupt us.  But in cooked mode we may also get SIGQUIT, e.g., when
+     * pressing CTRL-\, but we don't want Vim to exit then. */
+    if (in_mch_delay && sigarg == SIGQUIT)
+	SIGRETURN;
+# endif
+
     /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
      * here.  This avoids that a non-reentrant function is interrupted, e.g.,
      * free().  Calling free() again may then cause a crash. */
@@ -1566,18 +1579,19 @@
 #ifdef FEAT_XCLIPBOARD
     if (xterm_dpy != NULL && x11_window != 0)
     {
-	/* Checked it already. */
-	if (x11_display_from == XD_XTERM)
-	    return OK;
-
-	/*
-	 * If the X11 display was opened here before, for the window where Vim
-	 * was started, close that one now to avoid a memory leak.
-	 */
-	if (x11_display_from == XD_HERE && x11_display != NULL)
-	    XCloseDisplay(x11_display);
-	x11_display = xterm_dpy;
-	x11_display_from = XD_XTERM;
+	/* We may have checked it already, but Gnome terminal can move us to
+	 * another window, so we need to check every time. */
+	if (x11_display_from != XD_XTERM)
+	{
+	    /*
+	     * If the X11 display was opened here before, for the window where
+	     * Vim was started, close that one now to avoid a memory leak.
+	     */
+	    if (x11_display_from == XD_HERE && x11_display != NULL)
+		XCloseDisplay(x11_display);
+	    x11_display = xterm_dpy;
+	    x11_display_from = XD_XTERM;
+	}
 	if (test_x11_window(x11_display) == FAIL)
 	{
 	    /* probably bad $WINDOWID */
@@ -2420,7 +2434,7 @@
 /*
  * Set the case of the file name, if it already exists.  This will cause the
  * file name to remain exactly the same.
- * Only required for file systems where case is ingored and preserved.
+ * Only required for file systems where case is ignored and preserved.
  */
 /*ARGSUSED*/
     void
@@ -2499,7 +2513,13 @@
     if (stat((char *)name, &statb))
 #endif
 	return -1;
+#ifdef __INTERIX
+    /* The top bit makes the value negative, which means the file doesn't
+     * exist.  Remove the bit, we don't use it. */
+    return statb.st_mode & ~S_ADDACE;
+#else
     return statb.st_mode;
+#endif
 }
 
 /*
@@ -4646,7 +4666,7 @@
 	ret = poll(fds, nfd, towait);
 # ifdef FEAT_MZSCHEME
 	if (ret == 0 && mzquantum_used)
-	    /* MzThreads scheduling is required and timeout occured */
+	    /* MzThreads scheduling is required and timeout occurred */
 	    finished = FALSE;
 # endif
 
@@ -4794,7 +4814,7 @@
 #endif
 # ifdef FEAT_MZSCHEME
 	if (ret == 0 && mzquantum_used)
-	    /* loop if MzThreads must be scheduled and timeout occured */
+	    /* loop if MzThreads must be scheduled and timeout occurred */
 	    finished = FALSE;
 # endif
 
@@ -4938,6 +4958,9 @@
     char_u	*p;
     int		dir;
 #ifdef __EMX__
+    /*
+     * This is the OS/2 implementation.
+     */
 # define EXPL_ALLOC_INC	16
     char_u	**expl_files;
     size_t	files_alloced, files_free;
@@ -5048,20 +5071,26 @@
     return OK;
 
 #else /* __EMX__ */
-
+    /*
+     * This is the non-OS/2 implementation (really Unix).
+     */
     int		j;
     char_u	*tempname;
     char_u	*command;
     FILE	*fd;
     char_u	*buffer;
-#define STYLE_ECHO  0	    /* use "echo" to expand */
-#define STYLE_GLOB  1	    /* use "glob" to expand, for csh */
-#define STYLE_PRINT 2	    /* use "print -N" to expand, for zsh */
-#define STYLE_BT    3	    /* `cmd` expansion, execute the pattern directly */
+#define STYLE_ECHO	0	/* use "echo", the default */
+#define STYLE_GLOB	1	/* use "glob", for csh */
+#define STYLE_VIMGLOB	2	/* use "vimglob", for Posix sh */
+#define STYLE_PRINT	3	/* use "print -N", for zsh */
+#define STYLE_BT	4	/* `cmd` expansion, execute the pattern
+				 * directly */
     int		shell_style = STYLE_ECHO;
     int		check_spaces;
     static int	did_find_nul = FALSE;
     int		ampersent = FALSE;
+		/* vimglob() function to define for Posix shell */
+    static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo -n \"$1\"; echo; shift; done }; vimglob >";
 
     *num_file = 0;	/* default: no files found */
     *file = NULL;
@@ -5099,9 +5128,17 @@
 
     /*
      * Let the shell expand the patterns and write the result into the temp
-     * file.  if expanding `cmd` execute it directly.
-     * If we use csh, glob will work better than echo.
-     * If we use zsh, print -N will work better than glob.
+     * file.
+     * STYLE_BT:	NL separated
+     *	    If expanding `cmd` execute it directly.
+     * STYLE_GLOB:	NUL separated
+     *	    If we use *csh, "glob" will work better than "echo".
+     * STYLE_PRINT:	NL or NUL separated
+     *	    If we use *zsh, "print -N" will work better than "glob".
+     * STYLE_VIMGLOB:	NL separated
+     *	    If we use *sh*, we define "vimglob()".
+     * STYLE_ECHO:	space separated.
+     *	    A shell we don't know, stay safe and use "echo".
      */
     if (num_pat == 1 && *pat[0] == '`'
 	    && (len = STRLEN(pat[0])) > 2
@@ -5114,9 +5151,17 @@
 	else if (STRCMP(p_sh + len - 3, "zsh") == 0)
 	    shell_style = STYLE_PRINT;
     }
-
-    /* "unset nonomatch; print -N >" plus two is 29 */
+    if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
+								"sh") != NULL)
+	shell_style = STYLE_VIMGLOB;
+
+    /* Compute the length of the command.  We need 2 extra bytes: for the
+     * optional '&' and for the NUL.
+     * Worst case: "unset nonomatch; print -N >" plus two is 29 */
     len = STRLEN(tempname) + 29;
+    if (shell_style == STYLE_VIMGLOB)
+	len += STRLEN(sh_vimglob_func);
+
     for (i = 0; i < num_pat; ++i)
     {
 	/* Count the length of the patterns in the same way as they are put in
@@ -5175,16 +5220,20 @@
 	    STRCAT(command, "glob >");
 	else if (shell_style == STYLE_PRINT)
 	    STRCAT(command, "print -N >");
+	else if (shell_style == STYLE_VIMGLOB)
+	    STRCAT(command, sh_vimglob_func);
 	else
 	    STRCAT(command, "echo >");
     }
+
     STRCAT(command, tempname);
+
     if (shell_style != STYLE_BT)
 	for (i = 0; i < num_pat; ++i)
 	{
 	    /* When using system() always add extra quotes, because the shell
 	     * is started twice.  Otherwise put a backslash before special
-	     * characters, except insice ``. */
+	     * characters, except inside ``. */
 #ifdef USE_SYSTEM
 	    STRCAT(command, " \"");
 	    STRCAT(command, pat[i]);
@@ -5224,8 +5273,7 @@
     if (flags & EW_SILENT)
 	show_shell_mess = FALSE;
     if (ampersent)
-	STRCAT(command, "&");		/* put the '&' back after the
-					   redirection */
+	STRCAT(command, "&");		/* put the '&' after the redirection */
 
     /*
      * Using zsh -G: If a pattern has no matches, it is just deleted from
@@ -5257,7 +5305,7 @@
     show_shell_mess = TRUE;
     vim_free(command);
 
-    if (i)				/* mch_call_shell() failed */
+    if (i != 0)				/* mch_call_shell() failed */
     {
 	mch_remove(tempname);
 	vim_free(tempname);
@@ -5328,7 +5376,7 @@
     }
     vim_free(tempname);
 
-#if defined(__CYGWIN__) || defined(__CYGWIN32__)
+# if defined(__CYGWIN__) || defined(__CYGWIN32__)
     /* Translate <CR><NL> into <NL>.  Caution, buffer may contain NUL. */
     p = buffer;
     for (i = 0; i < len; ++i)
@@ -5351,7 +5399,7 @@
 	}
     }
     /* file names are separated with NL */
-    else if (shell_style == STYLE_BT)
+    else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
     {
 	buffer[len] = NUL;		/* make sure the buffer ends in NUL */
 	p = buffer;
@@ -5430,7 +5478,8 @@
     {
 	(*file)[i] = p;
 	/* Space or NL separates */
-	if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
+	if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
+					      || shell_style == STYLE_VIMGLOB)
 	{
 	    while (!(shell_style == STYLE_ECHO && *p == ' ')
 						   && *p != '\n' && *p != NUL)
@@ -5474,7 +5523,7 @@
 	{
 	    STRCPY(p, (*file)[i]);
 	    if (dir)
-		STRCAT(p, "/");	    /* add '/' to a directory name */
+		add_pathsep(p);	    /* add '/' to a directory name */
 	    (*file)[j++] = p;
 	}
     }
@@ -5668,7 +5717,7 @@
 	    /* gpm library tries to handling TSTP causes
 	     * problems. Anyways, we close connection to Gpm whenever
 	     * we are going to suspend or starting an external process
-	     * so we should'nt  have problem with this
+	     * so we shouldn't  have problem with this
 	     */
 	    signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
 	    return 1; /* succeed */
@@ -5682,7 +5731,7 @@
 
 /*
  * Closes connection to gpm
- * returns non-zero if connection succesfully closed
+ * returns non-zero if connection successfully closed
  */
     static void
 gpm_close()
@@ -6108,9 +6157,9 @@
     if (xterm_trace == 1)
     {
 	/* Get the hints just before tracking starts.  The font size might
-	 * have changed recently */
-	XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
-	if (!(got_hints & PResizeInc)
+	 * have changed recently. */
+	if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
+		|| !(got_hints & PResizeInc)
 		|| xterm_hints.width_inc <= 1
 		|| xterm_hints.height_inc <= 1)
 	{
diff -Naur vim71.orig/src/os_unix.h vim71/src/os_unix.h
--- vim71.orig/src/os_unix.h	2007-05-07 19:35:05.000000000 +0000
+++ vim71/src/os_unix.h	2008-02-14 21:07:31.000000000 +0000
@@ -508,6 +508,9 @@
 #if !defined(S_ISFIFO) && defined(S_IFIFO)
 # define	S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
 #endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+# define	S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
 
 /* Note: Some systems need both string.h and strings.h (Savage).  However,
  * some systems can't handle both, only use string.h in that case. */
diff -Naur vim71.orig/src/popupmnu.c vim71/src/popupmnu.c
--- vim71.orig/src/popupmnu.c	2007-03-24 20:07:39.000000000 +0000
+++ vim71/src/popupmnu.c	2008-02-14 21:07:32.000000000 +0000
@@ -75,7 +75,6 @@
 
     row = curwin->w_cline_row + W_WINROW(curwin);
     height = curwin->w_cline_height;
-    col = curwin->w_wcol + W_WINCOL(curwin) - curwin->w_leftcol;
 
     if (firstwin->w_p_pvw)
 	top_clear = firstwin->w_height;
@@ -167,6 +166,15 @@
     pum_base_width = max_width;
     pum_kind_width = kind_width;
 
+    /* Calculate column */
+#ifdef FEAT_RIGHTLEFT
+    if (curwin->w_p_rl)
+	col = W_WINCOL(curwin) + W_WIDTH(curwin) - curwin->w_wcol -
+							curwin->w_leftcol - 1;
+    else
+#endif
+	col = W_WINCOL(curwin) + curwin->w_wcol - curwin->w_leftcol;
+
     /* if there are more items than room we need a scrollbar */
     if (pum_height < size)
     {
@@ -179,11 +187,23 @@
     if (def_width < max_width)
 	def_width = max_width;
 
-    if (col < Columns - PUM_DEF_WIDTH || col < Columns - max_width)
+    if (((col < Columns - PUM_DEF_WIDTH || col < Columns - max_width)
+#ifdef FEAT_RIGHTLEFT
+		&& !curwin->w_p_rl)
+	    || (curwin->w_p_rl && (col > PUM_DEF_WIDTH || col > max_width)
+#endif
+       ))
     {
 	/* align pum column with "col" */
 	pum_col = col;
-	pum_width = Columns - pum_col - pum_scrollbar;
+
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_width = pum_col - pum_scrollbar + 1;
+	else
+#endif
+	    pum_width = Columns - pum_col - pum_scrollbar;
+
 	if (pum_width > max_width + kind_width + extra_width + 1
 						 && pum_width > PUM_DEF_WIDTH)
 	{
@@ -195,14 +215,24 @@
     else if (Columns < def_width)
     {
 	/* not enough room, will use what we have */
-	pum_col = 0;
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_col = Columns - 1;
+	else
+#endif
+	    pum_col = 0;
 	pum_width = Columns - 1;
     }
     else
     {
 	if (max_width > PUM_DEF_WIDTH)
 	    max_width = PUM_DEF_WIDTH;	/* truncate */
-	pum_col = Columns - max_width;
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_col = max_width - 1;
+	else
+#endif
+	    pum_col = Columns - max_width;
 	pum_width = max_width - pum_scrollbar;
     }
 
@@ -255,8 +285,16 @@
 	attr = (idx == pum_selected) ? attr_select : attr_norm;
 
 	/* prepend a space if there is room */
-	if (pum_col > 0)
-	    screen_putchar(' ', row, pum_col - 1, attr);
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	{
+	    if (pum_col < W_WINCOL(curwin) + W_WIDTH(curwin) - 1)
+		screen_putchar(' ', row, pum_col + 1, attr);
+	}
+	else
+#endif
+	    if (pum_col > 0)
+		screen_putchar(' ', row, pum_col - 1, attr);
 
 	/* Display each entry, use two spaces for a Tab.
 	 * Do this 3 times: For the main text, kind and extra info */
@@ -282,26 +320,67 @@
 		    {
 			/* Display the text that fits or comes before a Tab.
 			 * First convert it to printable characters. */
-			char_u *st;
-			int  saved = *p;
+			char_u	*st;
+			int	saved = *p;
 
 			*p = NUL;
 			st = transstr(s);
 			*p = saved;
-			if (st != NULL)
+#ifdef FEAT_RIGHTLEFT
+			if (curwin->w_p_rl)
 			{
-			    screen_puts_len(st, (int)STRLEN(st), row, col,
+			    if (st != NULL)
+			    {
+				char_u	*rt = reverse_text(st);
+				char_u	*rt_saved = rt;
+				int	len, j;
+
+				if (rt != NULL)
+				{
+				    len = STRLEN(rt);
+				    if (len > pum_width)
+				    {
+					for (j = pum_width; j < len; ++j)
+					    mb_ptr_adv(rt);
+					len = pum_width;
+				    }
+				    screen_puts_len(rt, len, row,
+							col - len + 1, attr);
+				    vim_free(rt_saved);
+				}
+				vim_free(st);
+			    }
+			    col -= width;
+			}
+			else
+#endif
+			{
+			    if (st != NULL)
+			    {
+				screen_puts_len(st, (int)STRLEN(st), row, col,
 									attr);
-			    vim_free(st);
+				vim_free(st);
+			    }
+			    col += width;
 			}
-			col += width;
 
 			if (*p != TAB)
 			    break;
 
 			/* Display two spaces for a Tab. */
-			screen_puts_len((char_u *)"  ", 2, row, col, attr);
-			col += 2;
+#ifdef FEAT_RIGHTLEFT
+			if (curwin->w_p_rl)
+			{
+			    screen_puts_len((char_u *)"  ", 2, row, col - 1,
+									attr);
+			    col -= 2;
+			}
+			else
+#endif
+			{
+			    screen_puts_len((char_u *)"  ", 2, row, col, attr);
+			    col += 2;
+			}
 			totwidth += 2;
 			s = NULL;	    /* start text at next char */
 			width = 0;
@@ -322,17 +401,44 @@
 					  && pum_array[idx].pum_extra == NULL)
 		    || pum_base_width + n >= pum_width)
 		break;
-	    screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
+#ifdef FEAT_RIGHTLEFT
+	    if (curwin->w_p_rl)
+	    {
+		screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
+						    col + 1, ' ', ' ', attr);
+		col = pum_col - pum_base_width - n + 1;
+	    }
+	    else
+#endif
+	    {
+		screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
 							      ' ', ' ', attr);
-	    col = pum_col + pum_base_width + n;
+		col = pum_col + pum_base_width + n;
+	    }
 	    totwidth = pum_base_width + n;
 	}
 
-	screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ',
+								    ' ', attr);
+	else
+#endif
+	    screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ',
+									attr);
 	if (pum_scrollbar > 0)
-	    screen_putchar(' ', row, pum_col + pum_width,
-		    i >= thumb_pos && i < thumb_pos + thumb_heigth
+	{
+#ifdef FEAT_RIGHTLEFT
+	    if (curwin->w_p_rl)
+		screen_putchar(' ', row, pum_col - pum_width,
+			i >= thumb_pos && i < thumb_pos + thumb_heigth
 						  ? attr_thumb : attr_scroll);
+	    else
+#endif
+		screen_putchar(' ', row, pum_col + pum_width,
+			i >= thumb_pos && i < thumb_pos + thumb_heigth
+						  ? attr_thumb : attr_scroll);
+	}
 
 	++row;
     }
@@ -466,7 +572,7 @@
 			set_option_value((char_u *)"bh", 0L,
 						 (char_u *)"wipe", OPT_LOCAL);
 			set_option_value((char_u *)"diff", 0L,
-						     (char_u *)"", OPT_LOCAL);
+							     NULL, OPT_LOCAL);
 		    }
 		}
 		if (res == OK)
diff -Naur vim71.orig/src/proto/charset.pro vim71/src/proto/charset.pro
--- vim71.orig/src/proto/charset.pro	2007-05-12 10:39:01.000000000 +0000
+++ vim71/src/proto/charset.pro	2008-02-14 21:07:32.000000000 +0000
@@ -21,6 +21,7 @@
 int vim_iswordp __ARGS((char_u *p));
 int vim_iswordc_buf __ARGS((char_u *p, buf_T *buf));
 int vim_isfilec __ARGS((int c));
+int vim_isfilec_or_wc __ARGS((int c));
 int vim_isprintc __ARGS((int c));
 int vim_isprintc_strict __ARGS((int c));
 int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col));
diff -Naur vim71.orig/src/proto/edit.pro vim71/src/proto/edit.pro
--- vim71.orig/src/proto/edit.pro	2007-05-12 10:39:05.000000000 +0000
+++ vim71/src/proto/edit.pro	2008-02-14 21:07:34.000000000 +0000
@@ -3,7 +3,7 @@
 void edit_putchar __ARGS((int c, int highlight));
 void edit_unputchar __ARGS((void));
 void display_dollar __ARGS((colnr_T col));
-void change_indent __ARGS((int type, int amount, int round, int replaced));
+void change_indent __ARGS((int type, int amount, int round, int replaced, int call_changed_bytes));
 void truncate_spaces __ARGS((char_u *line));
 void backspace_until_column __ARGS((int col));
 int vim_is_ctrl_x_key __ARGS((int c));
@@ -32,6 +32,7 @@
 char_u *get_last_insert __ARGS((void));
 char_u *get_last_insert_save __ARGS((void));
 void replace_push __ARGS((int c));
+int replace_push_mb __ARGS((char_u *p));
 void fixthisline __ARGS((int (*get_the_indent)(void)));
 void fix_indent __ARGS((void));
 int in_cinkeys __ARGS((int keytyped, int when, int line_is_empty));
diff -Naur vim71.orig/src/proto/eval.pro vim71/src/proto/eval.pro
--- vim71.orig/src/proto/eval.pro	2007-05-12 10:39:06.000000000 +0000
+++ vim71/src/proto/eval.pro	2008-02-14 21:07:34.000000000 +0000
@@ -54,7 +54,7 @@
 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, linenr_T lnum_stop));
+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, long time_limit));
 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));
diff -Naur vim71.orig/src/proto/ex_cmds2.pro vim71/src/proto/ex_cmds2.pro
--- vim71.orig/src/proto/ex_cmds2.pro	2007-05-12 10:39:09.000000000 +0000
+++ vim71/src/proto/ex_cmds2.pro	2008-02-14 21:07:34.000000000 +0000
@@ -14,6 +14,8 @@
 void profile_end __ARGS((proftime_T *tm));
 void profile_sub __ARGS((proftime_T *tm, proftime_T *tm2));
 char *profile_msg __ARGS((proftime_T *tm));
+void profile_setlimit __ARGS((long msec, proftime_T *tm));
+int profile_passed_limit __ARGS((proftime_T *tm));
 void profile_zero __ARGS((proftime_T *tm));
 void profile_add __ARGS((proftime_T *tm, proftime_T *tm2));
 void profile_self __ARGS((proftime_T *self, proftime_T *total, proftime_T *children));
diff -Naur vim71.orig/src/proto/ex_docmd.pro vim71/src/proto/ex_docmd.pro
--- vim71.orig/src/proto/ex_docmd.pro	2007-05-12 10:39:10.000000000 +0000
+++ vim71/src/proto/ex_docmd.pro	2008-02-14 21:07:33.000000000 +0000
@@ -5,6 +5,7 @@
 int getline_equal __ARGS((char_u *(*fgetline)(int, void *, int), void *cookie, char_u *(*func)(int, void *, int)));
 void *getline_cookie __ARGS((char_u *(*fgetline)(int, void *, int), void *cookie));
 int checkforcmd __ARGS((char_u **pp, char *cmd, int len));
+int modifier_len __ARGS((char_u *cmd));
 int cmd_exists __ARGS((char_u *name));
 char_u *set_one_cmd_context __ARGS((expand_T *xp, char_u *buff));
 char_u *skip_range __ARGS((char_u *cmd, int *ctx));
@@ -39,6 +40,7 @@
 void tabpage_new __ARGS((void));
 void do_exedit __ARGS((exarg_T *eap, win_T *old_curwin));
 void free_cd_dir __ARGS((void));
+void ex_cd __ARGS((exarg_T *eap));
 void do_sleep __ARGS((long msec));
 int vim_mkdir_emsg __ARGS((char_u *name, int prot));
 FILE *open_exfile __ARGS((char_u *fname, int forceit, char *mode));
diff -Naur vim71.orig/src/proto/fileio.pro vim71/src/proto/fileio.pro
--- vim71.orig/src/proto/fileio.pro	2007-05-12 10:39:14.000000000 +0000
+++ vim71/src/proto/fileio.pro	2008-02-14 21:07:33.000000000 +0000
@@ -2,9 +2,11 @@
 void filemess __ARGS((buf_T *buf, char_u *name, char_u *s, int attr));
 int readfile __ARGS((char_u *fname, char_u *sfname, linenr_T from, linenr_T lines_to_skip, linenr_T lines_to_read, exarg_T *eap, int flags));
 int prep_exarg __ARGS((exarg_T *eap, buf_T *buf));
+int check_file_readonly __ARGS((char_u *fname, int perm));
 int buf_write __ARGS((buf_T *buf, char_u *fname, char_u *sfname, linenr_T start, linenr_T end, exarg_T *eap, int append, int forceit, int reset_changed, int filtering));
 void msg_add_fname __ARGS((buf_T *buf, char_u *fname));
 void msg_add_lines __ARGS((int insert_space, long lnum, long nchars));
+char_u *shorten_fname1 __ARGS((char_u *full_path));
 char_u *shorten_fname __ARGS((char_u *full_path, char_u *dir_name));
 void shorten_fnames __ARGS((int force));
 void shorten_filenames __ARGS((char_u **fnames, int count));
@@ -39,6 +41,8 @@
 int trigger_cursorhold __ARGS((void));
 int has_cursormoved __ARGS((void));
 int has_cursormovedI __ARGS((void));
+void block_autocmds __ARGS((void));
+void unblock_autocmds __ARGS((void));
 int has_autocmd __ARGS((event_T event, char_u *sfname, buf_T *buf));
 char_u *get_augroup_name __ARGS((expand_T *xp, int idx));
 char_u *set_context_in_autocmd __ARGS((expand_T *xp, char_u *arg, int doautocmd));
diff -Naur vim71.orig/src/proto/getchar.pro vim71/src/proto/getchar.pro
--- vim71.orig/src/proto/getchar.pro	2007-05-12 10:39:16.000000000 +0000
+++ vim71/src/proto/getchar.pro	2008-02-14 21:07:32.000000000 +0000
@@ -38,6 +38,7 @@
 void updatescript __ARGS((int c));
 int vgetc __ARGS((void));
 int safe_vgetc __ARGS((void));
+int plain_vgetc __ARGS((void));
 int vpeekc __ARGS((void));
 int vpeekc_nomap __ARGS((void));
 int vpeekc_any __ARGS((void));
diff -Naur vim71.orig/src/proto/if_cscope.pro vim71/src/proto/if_cscope.pro
--- vim71.orig/src/proto/if_cscope.pro	2007-05-12 10:39:21.000000000 +0000
+++ vim71/src/proto/if_cscope.pro	2008-02-14 21:07:32.000000000 +0000
@@ -6,4 +6,5 @@
 void cs_free_tags __ARGS((void));
 void cs_print_tags __ARGS((void));
 int cs_connection __ARGS((int num, char_u *dbpath, char_u *ppath));
+void cs_end __ARGS((void));
 /* vim: set ft=c : */
diff -Naur vim71.orig/src/proto/mbyte.pro vim71/src/proto/mbyte.pro
--- vim71.orig/src/proto/mbyte.pro	2007-05-12 10:39:38.000000000 +0000
+++ vim71/src/proto/mbyte.pro	2008-02-14 21:07:32.000000000 +0000
@@ -12,9 +12,9 @@
 int utf_ptr2cells __ARGS((char_u *p));
 int dbcs_ptr2cells __ARGS((char_u *p));
 int latin_char2cells __ARGS((int c));
-int latin_off2cells __ARGS((unsigned off));
-int dbcs_off2cells __ARGS((unsigned off));
-int utf_off2cells __ARGS((unsigned off));
+int latin_off2cells __ARGS((unsigned off, unsigned max_off));
+int dbcs_off2cells __ARGS((unsigned off, unsigned max_off));
+int utf_off2cells __ARGS((unsigned off, unsigned max_off));
 int latin_ptr2char __ARGS((char_u *p));
 int utf_ptr2char __ARGS((char_u *p));
 int mb_ptr2char_adv __ARGS((char_u **pp));
diff -Naur vim71.orig/src/proto/misc1.pro vim71/src/proto/misc1.pro
--- vim71.orig/src/proto/misc1.pro	2007-05-12 10:39:34.000000000 +0000
+++ vim71/src/proto/misc1.pro	2008-02-14 21:07:33.000000000 +0000
@@ -48,10 +48,11 @@
 void vim_beep __ARGS((void));
 void init_homedir __ARGS((void));
 void free_homedir __ARGS((void));
+char_u *expand_env_save __ARGS((char_u *src));
+char_u *expand_env_save_opt __ARGS((char_u *src, int one));
 void expand_env __ARGS((char_u *src, char_u *dst, int dstlen));
-void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr));
+void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, int one, char_u *startstr));
 char_u *vim_getenv __ARGS((char_u *name, int *mustfree));
-char_u *expand_env_save __ARGS((char_u *src));
 void vim_setenv __ARGS((char_u *name, char_u *val));
 char_u *get_env_name __ARGS((expand_T *xp, int idx));
 void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one));
diff -Naur vim71.orig/src/proto/ops.pro vim71/src/proto/ops.pro
--- vim71.orig/src/proto/ops.pro	2007-05-12 10:39:40.000000000 +0000
+++ vim71/src/proto/ops.pro	2008-02-14 21:07:34.000000000 +0000
@@ -4,7 +4,7 @@
 int get_op_char __ARGS((int optype));
 int get_extra_op_char __ARGS((int optype));
 void op_shift __ARGS((oparg_T *oap, int curs_top, int amount));
-void shift_line __ARGS((int left, int round, int amount));
+void shift_line __ARGS((int left, int round, int amount, int call_changed_bytes));
 void op_reindent __ARGS((oparg_T *oap, int (*how)(void)));
 int get_expr_register __ARGS((void));
 void set_expr_line __ARGS((char_u *new_line));
diff -Naur vim71.orig/src/proto/regexp.pro vim71/src/proto/regexp.pro
--- vim71.orig/src/proto/regexp.pro	2007-05-12 10:39:48.000000000 +0000
+++ vim71/src/proto/regexp.pro	2008-02-14 21:07:34.000000000 +0000
@@ -1,13 +1,13 @@
 /* regexp.c */
-void free_regexp_stuff __ARGS((void));
 int re_multiline __ARGS((regprog_T *prog));
 int re_lookbehind __ARGS((regprog_T *prog));
 char_u *skip_regexp __ARGS((char_u *startp, int dirc, int magic, char_u **newp));
 regprog_T *vim_regcomp __ARGS((char_u *expr, int re_flags));
 int vim_regcomp_had_eol __ARGS((void));
+void free_regexp_stuff __ARGS((void));
 int vim_regexec __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
 int vim_regexec_nl __ARGS((regmatch_T *rmp, char_u *line, colnr_T col));
-long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col));
+long vim_regexec_multi __ARGS((regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm));
 reg_extmatch_T *ref_extmatch __ARGS((reg_extmatch_T *em));
 void unref_extmatch __ARGS((reg_extmatch_T *em));
 char_u *regtilde __ARGS((char_u *source, int magic));
diff -Naur vim71.orig/src/proto/search.pro vim71/src/proto/search.pro
--- vim71.orig/src/proto/search.pro	2007-05-12 10:39:50.000000000 +0000
+++ vim71/src/proto/search.pro	2008-02-14 21:07:34.000000000 +0000
@@ -1,6 +1,7 @@
 /* search.c */
 int search_regcomp __ARGS((char_u *pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch));
 char_u *get_search_pat __ARGS((void));
+char_u *reverse_text __ARGS((char_u *s));
 void save_search_patterns __ARGS((void));
 void restore_search_patterns __ARGS((void));
 void free_search_patterns __ARGS((void));
@@ -9,8 +10,8 @@
 void reset_search_dir __ARGS((void));
 void set_last_search_pat __ARGS((char_u *s, int idx, int magic, int setlast));
 void last_pat_prog __ARGS((regmmatch_T *regmatch));
-int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum));
-int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options));
+int searchit __ARGS((win_T *win, buf_T *buf, pos_T *pos, int dir, char_u *pat, long count, int options, int pat_use, linenr_T stop_lnum, proftime_T *tm));
+int do_search __ARGS((oparg_T *oap, int dirc, char_u *pat, long count, int options, proftime_T *tm));
 int search_for_exact_line __ARGS((buf_T *buf, pos_T *pos, int dir, char_u *pat));
 int searchc __ARGS((cmdarg_T *cap, int t_cmd));
 pos_T *findmatch __ARGS((oparg_T *oap, int initc));
diff -Naur vim71.orig/src/proto/syntax.pro vim71/src/proto/syntax.pro
--- vim71.orig/src/proto/syntax.pro	2007-05-12 10:39:52.000000000 +0000
+++ vim71/src/proto/syntax.pro	2008-02-14 21:07:34.000000000 +0000
@@ -4,13 +4,16 @@
 void syn_stack_apply_changes __ARGS((buf_T *buf));
 void syntax_end_parsing __ARGS((linenr_T lnum));
 int syntax_check_changed __ARGS((linenr_T lnum));
-int get_syntax_attr __ARGS((colnr_T col, int *can_spell));
+int get_syntax_attr __ARGS((colnr_T col, int *can_spell, int keep_state));
 void syntax_clear __ARGS((buf_T *buf));
 void ex_syntax __ARGS((exarg_T *eap));
 int syntax_present __ARGS((buf_T *buf));
+void reset_expand_highlight __ARGS((void));
+void set_context_in_echohl_cmd __ARGS((expand_T *xp, char_u *arg));
 void set_context_in_syntax_cmd __ARGS((expand_T *xp, char_u *arg));
 char_u *get_syntax_name __ARGS((expand_T *xp, int idx));
-int syn_get_id __ARGS((win_T *wp, long lnum, colnr_T col, int trans, int *spellp));
+int syn_get_id __ARGS((win_T *wp, long lnum, colnr_T col, int trans, int *spellp, int keep_state));
+int syn_get_stack_item __ARGS((int i));
 int syn_get_foldlevel __ARGS((win_T *wp, long lnum));
 void init_highlight __ARGS((int both, int reset));
 int load_colors __ARGS((char_u *name));
diff -Naur vim71.orig/src/proto/window.pro vim71/src/proto/window.pro
--- vim71.orig/src/proto/window.pro	2007-05-12 10:40:00.000000000 +0000
+++ vim71/src/proto/window.pro	2008-02-14 21:07:32.000000000 +0000
@@ -59,4 +59,8 @@
 int only_one_window __ARGS((void));
 void check_lnums __ARGS((int do_curwin));
 int win_hasvertsplit __ARGS((void));
+int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
+int match_delete __ARGS((win_T *wp, int id, int perr));
+void clear_matches __ARGS((win_T *wp));
+matchitem_T *get_match __ARGS((win_T *wp, int id));
 /* vim: set ft=c : */
diff -Naur vim71.orig/src/quickfix.c vim71/src/quickfix.c
--- vim71.orig/src/quickfix.c	2007-02-04 00:50:17.000000000 +0000
+++ vim71/src/quickfix.c	2008-02-14 21:07:34.000000000 +0000
@@ -1612,8 +1612,8 @@
 	}
 
 	/*
-	 * If there is only one window and is the quickfix window, create a new
-	 * one above the quickfix window.
+	 * If there is only one window and it is the quickfix window, create a
+	 * new one above the quickfix window.
 	 */
 	if (((firstwin == lastwin) && bt_quickfix(curbuf)) || !usable_win)
 	{
@@ -1803,7 +1803,8 @@
 	    /* Move the cursor to the first line in the buffer */
 	    save_cursor = curwin->w_cursor;
 	    curwin->w_cursor.lnum = 0;
-	    if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1, SEARCH_KEEP))
+	    if (!do_search(NULL, '/', qf_ptr->qf_pattern, (long)1,
+							   SEARCH_KEEP, NULL))
 		curwin->w_cursor = save_cursor;
 	}
 
@@ -2331,7 +2332,7 @@
 	    set_option_value((char_u *)"bt", 0L, (char_u *)"quickfix",
 								   OPT_LOCAL);
 	    set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
-	    set_option_value((char_u *)"diff", 0L, (char_u *)"", OPT_LOCAL);
+	    set_option_value((char_u *)"diff", 0L, NULL, OPT_LOCAL);
 	}
 
 	/* Only set the height when still in the same tab page and there is no
@@ -2972,6 +2973,7 @@
     regmmatch_T	regmatch;
     int		fcount;
     char_u	**fnames;
+    char_u	*fname;
     char_u	*s;
     char_u	*p;
     int		fi;
@@ -2981,6 +2983,7 @@
     buf_T	*buf;
     int		duplicate_name = FALSE;
     int		using_dummy;
+    int		redraw_for_dummy = FALSE;
     int		found_match;
     buf_T	*first_match_buf = NULL;
     time_t	seconds = 0;
@@ -2994,6 +2997,9 @@
     int		flags = 0;
     colnr_T	col;
     long	tomatch;
+    char_u	dirname_start[MAXPATHL];
+    char_u	dirname_now[MAXPATHL];
+    char_u	*target_dir = NULL;
 
     switch (eap->cmdidx)
     {
@@ -3068,17 +3074,23 @@
 	goto theend;
     }
 
+    /* Remember the current directory, because a BufRead autocommand that does
+     * ":lcd %:p:h" changes the meaning of short path names. */
+    mch_dirname(dirname_start, MAXPATHL);
+
     seconds = (time_t)0;
     for (fi = 0; fi < fcount && !got_int && tomatch > 0; ++fi)
     {
+	fname = shorten_fname1(fnames[fi]);
 	if (time(NULL) > seconds)
 	{
-	    /* Display the file name every second or so. */
+	    /* Display the file name every second or so, show the user we are
+	     * working on it. */
 	    seconds = time(NULL);
 	    msg_start();
-	    p = msg_strtrunc(fnames[fi], TRUE);
+	    p = msg_strtrunc(fname, TRUE);
 	    if (p == NULL)
-		msg_outtrans(fnames[fi]);
+		msg_outtrans(fname);
 	    else
 	    {
 		msg_outtrans(p);
@@ -3097,6 +3109,7 @@
 	    /* Remember that a buffer with this name already exists. */
 	    duplicate_name = (buf != NULL);
 	    using_dummy = TRUE;
+	    redraw_for_dummy = TRUE;
 
 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
 	    /* Don't do Filetype autocommands to avoid loading syntax and
@@ -3109,7 +3122,19 @@
 
 	    /* Load file into a buffer, so that 'fileencoding' is detected,
 	     * autocommands applied, etc. */
-	    buf = load_dummy_buffer(fnames[fi]);
+	    buf = load_dummy_buffer(fname);
+
+	    /* When autocommands changed directory: go back.  We assume it was
+	     * ":lcd %:p:h". */
+	    mch_dirname(dirname_now, MAXPATHL);
+	    if (STRCMP(dirname_start, dirname_now) != 0)
+	    {
+		exarg_T ea;
+
+		ea.arg = dirname_start;
+		ea.cmdidx = CMD_lcd;
+		ex_cd(&ea);
+	    }
 
 	    p_mls = save_mls;
 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
@@ -3123,7 +3148,7 @@
 	if (buf == NULL)
 	{
 	    if (!got_int)
-		smsg((char_u *)_("Cannot open file \"%s\""), fnames[fi]);
+		smsg((char_u *)_("Cannot open file \"%s\""), fname);
 	}
 	else
 	{
@@ -3135,11 +3160,12 @@
 	    {
 		col = 0;
 		while (vim_regexec_multi(&regmatch, curwin, buf, lnum,
-								     col) > 0)
+							       col, NULL) > 0)
 		{
+		    ;
 		    if (qf_add_entry(qi, &prevp,
 				NULL,       /* dir */
-				fnames[fi],
+				fname,
 				0,
 				ml_get_buf(buf,
 				     regmatch.startpos[0].lnum + lnum, FALSE),
@@ -3207,6 +3233,13 @@
 
 		if (buf != NULL)
 		{
+		    /* If the buffer is still loaded we need to use the
+		     * directory we jumped to below. */
+		    if (buf == first_match_buf
+			    && target_dir == NULL
+			    && STRCMP(dirname_start, dirname_now) != 0)
+			target_dir = vim_strsave(dirname_now);
+
 		    /* The buffer is still loaded, the Filetype autocommands
 		     * need to be done now, in that buffer.  And the modelines
 		     * need to be done (again).  But not the window-local
@@ -3243,12 +3276,41 @@
     if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
     {
 	if ((flags & VGR_NOJUMP) == 0)
+	{
+	    buf = curbuf;
 	    qf_jump(qi, 0, 0, eap->forceit);
+	    if (buf != curbuf)
+		/* If we jumped to another buffer redrawing will already be
+		 * taken care of. */
+		redraw_for_dummy = FALSE;
+
+	    /* Jump to the directory used after loading the buffer. */
+	    if (curbuf == first_match_buf && target_dir != NULL)
+	    {
+		exarg_T ea;
+
+		ea.arg = target_dir;
+		ea.cmdidx = CMD_lcd;
+		ex_cd(&ea);
+	    }
+	}
     }
     else
 	EMSG2(_(e_nomatch2), s);
 
+    /* If we loaded a dummy buffer into the current window, the autocommands
+     * may have messed up things, need to redraw and recompute folds. */
+    if (redraw_for_dummy)
+    {
+#ifdef FEAT_FOLDING
+	foldUpdateAll(curwin);
+#else
+	redraw_later(NOT_VALID);
+#endif
+    }
+
 theend:
+    vim_free(target_dir);
     vim_free(regmatch.regprog);
 }
 
diff -Naur vim71.orig/src/regexp.c vim71/src/regexp.c
--- vim71.orig/src/regexp.c	2007-05-07 19:50:03.000000000 +0000
+++ vim71/src/regexp.c	2008-02-14 21:07:34.000000000 +0000
@@ -378,14 +378,6 @@
 
 static char_u		*reg_prev_sub = NULL;
 
-#if defined(EXITFREE) || defined(PROTO)
-    void
-free_regexp_stuff()
-{
-    vim_free(reg_prev_sub);
-}
-#endif
-
 /*
  * REGEXP_INRANGE contains all characters which are always special in a []
  * range after '\'.
@@ -1288,8 +1280,7 @@
 }
 
 /*
- * regbranch - one alternative of an | operator
- *
+ * Handle one alternative of an | operator.
  * Implements the & operator.
  */
     static char_u *
@@ -1330,8 +1321,7 @@
 }
 
 /*
- * regbranch - one alternative of an | or & operator
- *
+ * Handle one alternative of an | or & operator.
  * Implements the concatenation operator.
  */
     static char_u *
@@ -1708,6 +1698,8 @@
       case Magic('|'):
       case Magic('&'):
       case Magic(')'):
+	if (one_exactly)
+	    EMSG_ONE_RET_NULL;
 	EMSG_RET_NULL(_(e_internal));	/* Supposed to be caught earlier. */
 	/* NOTREACHED */
 
@@ -2220,7 +2212,7 @@
 				break;
 			    case CLASS_LOWER:
 				for (cu = 1; cu <= 255; cu++)
-				    if (islower(cu))
+				    if (MB_ISLOWER(cu))
 					regc(cu);
 				break;
 			    case CLASS_PRINT:
@@ -2240,7 +2232,7 @@
 				break;
 			    case CLASS_UPPER:
 				for (cu = 1; cu <= 255; cu++)
-				    if (isupper(cu))
+				    if (MB_ISUPPER(cu))
 					regc(cu);
 				break;
 			    case CLASS_XDIGIT:
@@ -2770,7 +2762,8 @@
     {
 #ifdef FEAT_MBYTE
 	if (enc_utf8)
-	    prevchr_len += utf_char2len(mb_ptr2char(regparse + prevchr_len));
+	    /* exclude composing chars that mb_ptr2len does include */
+	    prevchr_len += utf_ptr2len(regparse + prevchr_len);
 	else if (has_mbyte)
 	    prevchr_len += (*mb_ptr2len)(regparse + prevchr_len);
 	else
@@ -3047,7 +3040,7 @@
 } save_se_T;
 
 static char_u	*reg_getline __ARGS((linenr_T lnum));
-static long	vim_regexec_both __ARGS((char_u *line, colnr_T col));
+static long	vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T *tm));
 static long	regtry __ARGS((regprog_T *prog, colnr_T col));
 static void	cleanup_subexpr __ARGS((void));
 #ifdef FEAT_SYN_HL
@@ -3105,7 +3098,7 @@
  * slow, we keep one allocated piece of memory and only re-allocate it when
  * it's too small.  It's freed in vim_regexec_both() when finished.
  */
-static char_u	*reg_tofree;
+static char_u	*reg_tofree = NULL;
 static unsigned	reg_tofreelen;
 
 /*
@@ -3205,12 +3198,39 @@
 } backpos_T;
 
 /*
- * regstack and backpos are used by regmatch().  They are kept over calls to
- * avoid invoking malloc() and free() often.
+ * "regstack" and "backpos" are used by regmatch().  They are kept over calls
+ * to avoid invoking malloc() and free() often.
+ * "regstack" is a stack with regitem_T items, sometimes preceded by regstar_T
+ * or regbehind_T.
+ * "backpos_T" is a table with backpos_T for BACK
+ */
+static garray_T	regstack = {0, 0, 0, 0, NULL};
+static garray_T	backpos = {0, 0, 0, 0, NULL};
+
+/*
+ * Both for regstack and backpos tables we use the following strategy of
+ * allocation (to reduce malloc/free calls):
+ * - Initial size is fairly small.
+ * - When needed, the tables are grown bigger (8 times at first, double after
+ *   that).
+ * - After executing the match we free the memory only if the array has grown.
+ *   Thus the memory is kept allocated when it's at the initial size.
+ * This makes it fast while not keeping a lot of memory allocated.
+ * A three times speed increase was observed when using many simple patterns.
  */
-static garray_T	regstack;	/* stack with regitem_T items, sometimes
-				   preceded by regstar_T or regbehind_T. */
-static garray_T	backpos;	/* table with backpos_T for BACK */
+#define REGSTACK_INITIAL	2048
+#define BACKPOS_INITIAL		64
+
+#if defined(EXITFREE) || defined(PROTO)
+    void
+free_regexp_stuff()
+{
+    ga_clear(&regstack);
+    ga_clear(&backpos);
+    vim_free(reg_tofree);
+    vim_free(reg_prev_sub);
+}
+#endif
 
 /*
  * Get pointer to the line "lnum", which is relative to "reg_firstlnum".
@@ -3264,7 +3284,7 @@
     ireg_icombine = FALSE;
 #endif
     ireg_maxcol = 0;
-    return (vim_regexec_both(line, col) != 0);
+    return (vim_regexec_both(line, col, NULL) != 0);
 }
 
 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \
@@ -3288,7 +3308,7 @@
     ireg_icombine = FALSE;
 #endif
     ireg_maxcol = 0;
-    return (vim_regexec_both(line, col) != 0);
+    return (vim_regexec_both(line, col, NULL) != 0);
 }
 #endif
 
@@ -3301,12 +3321,13 @@
  * match otherwise.
  */
     long
-vim_regexec_multi(rmp, win, buf, lnum, col)
+vim_regexec_multi(rmp, win, buf, lnum, col, tm)
     regmmatch_T	*rmp;
     win_T	*win;		/* window in which to search or NULL */
     buf_T	*buf;		/* buffer in which to search */
     linenr_T	lnum;		/* nr of line to start looking for match */
     colnr_T	col;		/* column to start looking for match */
+    proftime_T	*tm;		/* timeout limit or NULL */
 {
     long	r;
     buf_T	*save_curbuf = curbuf;
@@ -3326,7 +3347,7 @@
 
     /* Need to switch to buffer "buf" to make vim_iswordc() work. */
     curbuf = buf;
-    r = vim_regexec_both(NULL, col);
+    r = vim_regexec_both(NULL, col, tm);
     curbuf = save_curbuf;
 
     return r;
@@ -3336,24 +3357,36 @@
  * Match a regexp against a string ("line" points to the string) or multiple
  * lines ("line" is NULL, use reg_getline()).
  */
+/*ARGSUSED*/
     static long
-vim_regexec_both(line, col)
+vim_regexec_both(line, col, tm)
     char_u	*line;
     colnr_T	col;		/* column to start looking for match */
+    proftime_T	*tm;		/* timeout limit or NULL */
 {
     regprog_T	*prog;
     char_u	*s;
     long	retval = 0L;
 
-    reg_tofree = NULL;
-
-    /* Init the regstack empty.  Use an item size of 1 byte, since we push
-     * different things onto it.  Use a large grow size to avoid reallocating
-     * it too often. */
-    ga_init2(&regstack, 1, 10000);
-
-    /* Init the backpos table empty. */
-    ga_init2(&backpos, sizeof(backpos_T), 10);
+    /* Create "regstack" and "backpos" if they are not allocated yet.
+     * We allocate *_INITIAL amount of bytes first and then set the grow size
+     * to much bigger value to avoid many malloc calls in case of deep regular
+     * expressions.  */
+    if (regstack.ga_data == NULL)
+    {
+	/* Use an item size of 1 byte, since we push different things
+	 * onto the regstack. */
+	ga_init2(&regstack, 1, REGSTACK_INITIAL);
+	ga_grow(&regstack, REGSTACK_INITIAL);
+	regstack.ga_growsize = REGSTACK_INITIAL * 8;
+    }
+
+    if (backpos.ga_data == NULL)
+    {
+	ga_init2(&backpos, sizeof(backpos_T), BACKPOS_INITIAL);
+	ga_grow(&backpos, BACKPOS_INITIAL);
+	backpos.ga_growsize = BACKPOS_INITIAL * 8;
+    }
 
     if (REG_MULTI)
     {
@@ -3465,13 +3498,16 @@
 			(enc_utf8 && utf_fold(prog->regstart) == utf_fold(c)))
 			|| (c < 255 && prog->regstart < 255 &&
 #endif
-			    TOLOWER_LOC(prog->regstart) == TOLOWER_LOC(c)))))
+			    MB_TOLOWER(prog->regstart) == MB_TOLOWER(c)))))
 	    retval = regtry(prog, col);
 	else
 	    retval = 0;
     }
     else
     {
+#ifdef FEAT_RELTIME
+	int tm_count = 0;
+#endif
 	/* Messy cases:  unanchored match. */
 	while (!got_int)
 	{
@@ -3520,13 +3556,30 @@
 	    else
 #endif
 		++col;
+#ifdef FEAT_RELTIME
+	    /* Check for timeout once in a twenty times to avoid overhead. */
+	    if (tm != NULL && ++tm_count == 20)
+	    {
+		tm_count = 0;
+		if (profile_passed_limit(tm))
+		    break;
+	    }
+#endif
 	}
     }
 
 theend:
-    vim_free(reg_tofree);
-    ga_clear(&regstack);
-    ga_clear(&backpos);
+    /* Free "reg_tofree" when it's a bit big.
+     * Free regstack and backpos if they are bigger than their initial size. */
+    if (reg_tofreelen > 400)
+    {
+	vim_free(reg_tofree);
+	reg_tofree = NULL;
+    }
+    if (regstack.ga_maxlen > REGSTACK_INITIAL)
+	ga_clear(&regstack);
+    if (backpos.ga_maxlen > BACKPOS_INITIAL)
+	ga_clear(&backpos);
 
     return retval;
 }
@@ -3716,8 +3769,8 @@
 #define RA_MATCH	4	/* successful match */
 #define RA_NOMATCH	5	/* didn't match */
 
-  /* Init the regstack and backpos table empty.  They are initialized and
-   * freed in vim_regexec_both() to reduce malloc()/free() calls. */
+  /* Make "regstack" and "backpos" empty.  They are allocated and freed in
+   * vim_regexec_both() to reduce malloc()/free() calls. */
   regstack.ga_len = 0;
   backpos.ga_len = 0;
 
@@ -3809,11 +3862,11 @@
 	    break;
 
 	  case RE_BOF:
-	    /* Passing -1 to the getline() function provided for the search
-	     * should always return NULL if the current line is the first
-	     * line of the file. */
+	    /* We're not at the beginning of the file when below the first
+	     * line where we started, not at the start of the line or we
+	     * didn't start at the first line of the buffer. */
 	    if (reglnum != 0 || reginput != regline
-			|| (REG_MULTI && reg_getline((linenr_T)-1) != NULL))
+					  || (REG_MULTI && reg_firstlnum > 1))
 		status = RA_NOMATCH;
 	    break;
 
@@ -4200,7 +4253,7 @@
 #ifdef FEAT_MBYTE
 			    !enc_utf8 &&
 #endif
-			    TOLOWER_LOC(*opnd) != TOLOWER_LOC(*reginput))))
+			    MB_TOLOWER(*opnd) != MB_TOLOWER(*reginput))))
 		    status = RA_NOMATCH;
 		else if (*opnd == NUL)
 		{
@@ -4733,10 +4786,10 @@
 		    rst.nextb = *OPERAND(next);
 		    if (ireg_ic)
 		    {
-			if (isupper(rst.nextb))
-			    rst.nextb_ic = TOLOWER_LOC(rst.nextb);
+			if (MB_ISUPPER(rst.nextb))
+			    rst.nextb_ic = MB_TOLOWER(rst.nextb);
 			else
-			    rst.nextb_ic = TOUPPER_LOC(rst.nextb);
+			    rst.nextb_ic = MB_TOUPPER(rst.nextb);
 		    }
 		    else
 			rst.nextb_ic = rst.nextb;
@@ -5558,11 +5611,12 @@
 	    int	    cu, cl;
 
 	    /* This doesn't do a multi-byte character, because a MULTIBYTECODE
-	     * would have been used for it. */
+	     * would have been used for it.  It does handle single-byte
+	     * characters, such as latin1. */
 	    if (ireg_ic)
 	    {
-		cu = TOUPPER_LOC(*opnd);
-		cl = TOLOWER_LOC(*opnd);
+		cu = MB_TOUPPER(*opnd);
+		cl = MB_TOLOWER(*opnd);
 		while (count < maxcount && (*scan == cu || *scan == cl))
 		{
 		    count++;
@@ -6490,10 +6544,10 @@
 	cc = utf_fold(c);
     else
 #endif
-	 if (isupper(c))
-	cc = TOLOWER_LOC(c);
-    else if (islower(c))
-	cc = TOUPPER_LOC(c);
+	 if (MB_ISUPPER(c))
+	cc = MB_TOLOWER(c);
+    else if (MB_ISLOWER(c))
+	cc = MB_TOUPPER(c);
     else
 	return vim_strchr(s, c);
 
@@ -6637,9 +6691,9 @@
 		}
 	    }
 	    else if (magic)
-		STRCPY(p, p + 1);		/* remove '~' */
+		mch_memmove(p, p + 1, STRLEN(p));	/* remove '~' */
 	    else
-		STRCPY(p, p + 2);		/* remove '\~' */
+		mch_memmove(p, p + 2, STRLEN(p) - 1);	/* remove '\~' */
 	    --p;
 	}
 	else
@@ -7014,7 +7068,14 @@
 #ifdef FEAT_MBYTE
 			    if (has_mbyte)
 			    {
-				int l = mb_ptr2len(s) - 1;
+				int l;
+
+				/* Copy composing characters separately, one
+				 * at a time. */
+				if (enc_utf8)
+				    l = utf_ptr2len(s) - 1;
+				else
+				    l = mb_ptr2len(s) - 1;
 
 				s += l;
 				len -= l;
diff -Naur vim71.orig/src/screen.c vim71/src/screen.c
--- vim71.orig/src/screen.c	2007-05-07 19:27:53.000000000 +0000
+++ vim71/src/screen.c	2008-02-14 21:07:34.000000000 +0000
@@ -100,27 +100,7 @@
 static int	screen_cur_row, screen_cur_col;	/* last known cursor position */
 
 #ifdef FEAT_SEARCH_EXTRA
-/*
- * Struct used for highlighting 'hlsearch' matches for the last use search
- * pattern or a ":match" item.
- * For 'hlsearch' there is one pattern for all windows.  For ":match" there is
- * a different pattern for each window.
- */
-typedef struct
-{
-    regmmatch_T	rm;	/* points to the regexp program; contains last found
-			   match (may continue in next line) */
-    buf_T	*buf;	/* the buffer to search for a match */
-    linenr_T	lnum;	/* the line to search for a match */
-    int		attr;	/* attributes to be used for a match */
-    int		attr_cur; /* attributes currently active in win_line() */
-    linenr_T	first_lnum;	/* first lnum to search for multi-line pat */
-    colnr_T	startcol; /* in win_line() points to char where HL starts */
-    colnr_T	endcol;	 /* in win_line() points to char where HL ends */
-} match_T;
-
 static match_T search_hl;	/* used for 'hlsearch' highlight matching */
-static match_T match_hl[3];	/* used for ":match" highlight matching */
 #endif
 
 #ifdef FEAT_FOLDING
@@ -155,6 +135,7 @@
 static void redraw_custum_statusline __ARGS((win_T *wp));
 #endif
 #ifdef FEAT_SEARCH_EXTRA
+#define SEARCH_HL_PRIORITY 0
 static void start_search_hl __ARGS((void));
 static void end_search_hl __ARGS((void));
 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
@@ -350,6 +331,11 @@
     {
 	if (type < must_redraw)	    /* use maximal type */
 	    type = must_redraw;
+
+	/* must_redraw is reset here, so that when we run into some weird
+	 * reason to redraw while busy redrawing (e.g., asynchronous
+	 * scrolling), or update_topline() in win_update() will cause a
+	 * scroll, the screen will be redrawn later or in win_update(). */
 	must_redraw = 0;
     }
 
@@ -787,6 +773,7 @@
 					   w_topline got smaller a bit */
 #endif
 #ifdef FEAT_SEARCH_EXTRA
+    matchitem_T *cur;		/* points to the match list */
     int		top_to_mod = FALSE;    /* redraw above mod_top */
 #endif
 
@@ -848,22 +835,29 @@
 #endif
 
 #ifdef FEAT_SEARCH_EXTRA
-    /* Setup for ":match" and 'hlsearch' highlighting.  Disable any previous
+    /* Setup for match and 'hlsearch' highlighting.  Disable any previous
      * match */
-    for (i = 0; i < 3; ++i)
+    cur = wp->w_match_head;
+    while (cur != NULL)
     {
-	match_hl[i].rm = wp->w_match[i];
-	if (wp->w_match_id[i] == 0)
-	    match_hl[i].attr = 0;
-	else
-	    match_hl[i].attr = syn_id2attr(wp->w_match_id[i]);
-	match_hl[i].buf = buf;
-	match_hl[i].lnum = 0;
-	match_hl[i].first_lnum = 0;
+	cur->hl.rm = cur->match;
+	if (cur->hlg_id == 0)
+	    cur->hl.attr = 0;
+	else
+	    cur->hl.attr = syn_id2attr(cur->hlg_id);
+	cur->hl.buf = buf;
+	cur->hl.lnum = 0;
+	cur->hl.first_lnum = 0;
+# ifdef FEAT_RELTIME
+	/* Set the time limit to 'redrawtime'. */
+	profile_setlimit(p_rdt, &(cur->hl.tm));
+# endif
+	cur = cur->next;
     }
     search_hl.buf = buf;
     search_hl.lnum = 0;
     search_hl.first_lnum = 0;
+    /* time limit is set at the toplevel, for all windows */
 #endif
 
 #ifdef FEAT_LINEBREAK
@@ -923,19 +917,25 @@
 	     * change in one line may make the Search highlighting in a
 	     * previous line invalid.  Simple solution: redraw all visible
 	     * lines above the change.
-	     * Same for a ":match" pattern.
+	     * Same for a match pattern.
 	     */
 	    if (search_hl.rm.regprog != NULL
 					&& re_multiline(search_hl.rm.regprog))
 		top_to_mod = TRUE;
 	    else
-		for (i = 0; i < 3; ++i)
-		    if (match_hl[i].rm.regprog != NULL
-				      && re_multiline(match_hl[i].rm.regprog))
+	    {
+		cur = wp->w_match_head;
+		while (cur != NULL)
+		{
+		    if (cur->match.regprog != NULL
+					   && re_multiline(cur->match.regprog))
 		    {
 			top_to_mod = TRUE;
 			break;
 		    }
+		    cur = cur->next;
+		}
+	    }
 #endif
 	}
 #ifdef FEAT_FOLDING
@@ -1029,6 +1029,13 @@
 	    type = VALID;
     }
 
+    /* Trick: we want to avoid clearing the screen twice.  screenclear() will
+     * set "screen_cleared" to TRUE.  The special value MAYBE (which is still
+     * non-zero and thus not FALSE) will indicate that screenclear() was not
+     * called. */
+    if (screen_cleared)
+	screen_cleared = MAYBE;
+
     /*
      * If there are no changes on the screen that require a complete redraw,
      * handle three cases:
@@ -1230,7 +1237,11 @@
 	    mid_end = wp->w_height;
 	    if (lastwin == firstwin)
 	    {
-		screenclear();
+		/* Clear the screen when it was not done by win_del_lines() or
+		 * win_ins_lines() above, "screen_cleared" is FALSE or MAYBE
+		 * then. */
+		if (screen_cleared != TRUE)
+		    screenclear();
 #ifdef FEAT_WINDOWS
 		/* The screen was cleared, redraw the tab pages line. */
 		if (redraw_tabline)
@@ -1238,6 +1249,13 @@
 #endif
 	    }
 	}
+
+	/* When win_del_lines() or win_ins_lines() caused the screen to be
+	 * cleared (only happens for the first window) or when screenclear()
+	 * was called directly above, "must_redraw" will have been set to
+	 * NOT_VALID, need to reset it here to avoid redrawing twice. */
+	if (screen_cleared == TRUE)
+	    must_redraw = 0;
     }
     else
     {
@@ -2292,9 +2310,11 @@
 			prev_c = u8c;
 #endif
 		    /* Non-BMP character: display as ? or fullwidth ?. */
+#ifdef UNICODE16
 		    if (u8c >= 0x10000)
 			ScreenLinesUC[idx] = (cells == 2) ? 0xff1f : (int)'?';
 		    else
+#endif
 			ScreenLinesUC[idx] = u8c;
 		    for (i = 0; i < Screen_mco; ++i)
 		    {
@@ -2542,7 +2562,7 @@
 
     char_u	extra[18];		/* "%ld" and 'fdc' must fit in here */
     int		n_extra = 0;		/* number of extra chars */
-    char_u	*p_extra = NULL;	/* string of extra chars */
+    char_u	*p_extra = NULL;	/* string of extra chars, plus NUL */
     int		c_extra = NUL;		/* extra chars, all the same */
     int		extra_attr = 0;		/* attributes when n_extra != 0 */
     static char_u *at_end_str = (char_u *)""; /* used for p_extra when
@@ -2584,6 +2604,7 @@
     int		syntax_attr = 0;	/* attributes desired by syntax */
     int		has_syntax = FALSE;	/* this buffer has syntax highl. */
     int		save_did_emsg;
+    int		eol_hl_off = 0;		/* 1 if highlighted char after EOL */
 #endif
 #ifdef FEAT_SPELL
     int		has_spell = FALSE;	/* this buffer has spell checking */
@@ -2623,13 +2644,16 @@
 #if defined(FEAT_SIGNS) || (defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)) \
 	|| defined(FEAT_SYN_HL) || defined(FEAT_DIFF)
 # define LINE_ATTR
-    int		line_attr = 0;		/* atrribute for the whole line */
+    int		line_attr = 0;		/* attribute for the whole line */
 #endif
 #ifdef FEAT_SEARCH_EXTRA
-    match_T	*shl;			/* points to search_hl or match_hl */
-#endif
-#if defined(FEAT_SEARCH_EXTRA) || defined(FEAT_MBYTE)
-    int		i;
+    matchitem_T *cur;			/* points to the match list */
+    match_T	*shl;			/* points to search_hl or a match */
+    int		shl_flag;		/* flag to indicate whether search_hl
+					   has been processed or not */
+    int		prevcol_hl_flag;	/* flag to indicate whether prevcol
+					   equals startcol of search_hl or one
+					   of the matches */
 #endif
 #ifdef FEAT_ARABIC
     int		prev_c = 0;		/* previous Arabic character */
@@ -3016,18 +3040,25 @@
 	if (has_spell)
 	{
 	    int		len;
+	    colnr_T	linecol = (colnr_T)(ptr - line);
 	    hlf_T	spell_hlf = HLF_COUNT;
 
 	    pos = wp->w_cursor;
 	    wp->w_cursor.lnum = lnum;
-	    wp->w_cursor.col = (colnr_T)(ptr - line);
+	    wp->w_cursor.col = linecol;
 	    len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf);
+
+	    /* spell_move_to() may call ml_get() and make "line" invalid */
+	    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+	    ptr = line + linecol;
+
 	    if (len == 0 || (int)wp->w_cursor.col > ptr - line)
 	    {
 		/* no bad word found at line start, don't check until end of a
 		 * word */
 		spell_hlf = HLF_COUNT;
-		word_end = (int)(spell_to_word_end(ptr, wp->w_buffer) - line + 1);
+		word_end = (int)(spell_to_word_end(ptr, wp->w_buffer)
+								  - line + 1);
 	    }
 	    else
 	    {
@@ -3074,12 +3105,20 @@
 
 #ifdef FEAT_SEARCH_EXTRA
     /*
-     * Handle highlighting the last used search pattern and ":match".
-     * Do this for both search_hl and match_hl[3].
+     * Handle highlighting the last used search pattern and matches.
+     * Do this for both search_hl and the match list.
      */
-    for (i = 3; i >= 0; --i)
+    cur = wp->w_match_head;
+    shl_flag = FALSE;
+    while (cur != NULL || shl_flag == FALSE)
     {
-	shl = (i == 3) ? &search_hl : &match_hl[i];
+	if (shl_flag == FALSE)
+	{
+	    shl = &search_hl;
+	    shl_flag = TRUE;
+	}
+	else
+	    shl = &cur->hl;
 	shl->startcol = MAXCOL;
 	shl->endcol = MAXCOL;
 	shl->attr_cur = 0;
@@ -3122,6 +3161,8 @@
 		area_highlighting = TRUE;
 	    }
 	}
+	if (shl != &search_hl && cur != NULL)
+	    cur = cur->next;
     }
 #endif
 
@@ -3163,10 +3204,8 @@
 		if (cmdwin_type != 0 && wp == curwin)
 		{
 		    /* Draw the cmdline character. */
-		    *extra = cmdwin_type;
 		    n_extra = 1;
-		    p_extra = extra;
-		    c_extra = NUL;
+		    c_extra = cmdwin_type;
 		    char_attr = hl_attr(HLF_AT);
 		}
 	    }
@@ -3182,6 +3221,7 @@
 		    fill_foldcolumn(extra, wp, FALSE, lnum);
 		    n_extra = wp->w_p_fdc;
 		    p_extra = extra;
+		    p_extra[n_extra] = NUL;
 		    c_extra = NUL;
 		    char_attr = hl_attr(HLF_FC);
 		}
@@ -3388,13 +3428,24 @@
 		 * After end, check for start/end of next match.
 		 * When another match, have to check for start again.
 		 * Watch out for matching an empty string!
-		 * Do this first for search_hl, then for match_hl, so that
-		 * ":match" overrules 'hlsearch'.
+		 * Do this for 'search_hl' and the match list (ordered by
+		 * priority).
 		 */
 		v = (long)(ptr - line);
-		for (i = 3; i >= 0; --i)
-		{
-		    shl = (i == 3) ? &search_hl : &match_hl[i];
+		cur = wp->w_match_head;
+		shl_flag = FALSE;
+		while (cur != NULL || shl_flag == FALSE)
+		{
+		    if (shl_flag == FALSE
+			    && ((cur != NULL
+				    && cur->priority > SEARCH_HL_PRIORITY)
+				|| cur == NULL))
+		    {
+			shl = &search_hl;
+			shl_flag = TRUE;
+		    }
+		    else
+			shl = &cur->hl;
 		    while (shl->rm.regprog != NULL)
 		    {
 			if (shl->startcol != MAXCOL
@@ -3442,26 +3493,43 @@
 			}
 			break;
 		    }
+		    if (shl != &search_hl && cur != NULL)
+			cur = cur->next;
 		}
 
-		/* ":match" highlighting overrules 'hlsearch' */
-		for (i = 0; i <= 3; ++i)
-		    if (i == 3)
-			search_attr = search_hl.attr_cur;
-		    else if (match_hl[i].attr_cur != 0)
+		/* Use attributes from match with highest priority among
+		 * 'search_hl' and the match list. */
+		search_attr = search_hl.attr_cur;
+		cur = wp->w_match_head;
+		shl_flag = FALSE;
+		while (cur != NULL || shl_flag == FALSE)
+		{
+		    if (shl_flag == FALSE
+			    && ((cur != NULL
+				    && cur->priority > SEARCH_HL_PRIORITY)
+				|| cur == NULL))
 		    {
-			search_attr = match_hl[i].attr_cur;
-			break;
+			shl = &search_hl;
+			shl_flag = TRUE;
 		    }
+		    else
+			shl = &cur->hl;
+		    if (shl->attr_cur != 0)
+			search_attr = shl->attr_cur;
+		    if (shl != &search_hl && cur != NULL)
+			cur = cur->next;
+		}
 	    }
 #endif
 
 #ifdef FEAT_DIFF
 	    if (diff_hlf != (hlf_T)0)
 	    {
-		if (diff_hlf == HLF_CHD && ptr - line >= change_start)
+		if (diff_hlf == HLF_CHD && ptr - line >= change_start
+							      && n_extra == 0)
 		    diff_hlf = HLF_TXD;		/* changed text */
-		if (diff_hlf == HLF_TXD && ptr - line > change_end)
+		if (diff_hlf == HLF_TXD && ptr - line > change_end
+							      && n_extra == 0)
 		    diff_hlf = HLF_CHD;		/* changed line */
 		line_attr = hl_attr(diff_hlf);
 	    }
@@ -3496,9 +3564,11 @@
 	 * Get the next character to put on the screen.
 	 */
 	/*
-	 * The 'extra' array contains the extra stuff that is inserted to
-	 * represent special characters (non-printable stuff).  When all
-	 * characters are the same, c_extra is used.
+	 * The "p_extra" points to the extra stuff that is inserted to
+	 * represent special characters (non-printable stuff) and other
+	 * things.  When all characters are the same, c_extra is used.
+	 * "p_extra" must end in a NUL to avoid mb_ptr2len() reads past
+	 * "p_extra[n_extra]".
 	 * For the '$' of the 'list' option, n_extra == 1, p_extra == "".
 	 */
 	if (n_extra > 0)
@@ -3611,6 +3681,8 @@
 			 * Draw it as a space with a composing char. */
 			if (utf_iscomposing(mb_c))
 			{
+			    int i;
+
 			    for (i = Screen_mco - 1; i > 0; --i)
 				u8cc[i] = u8cc[i - 1];
 			    u8cc[0] = mb_c;
@@ -3621,13 +3693,18 @@
 		    if ((mb_l == 1 && c >= 0x80)
 			    || (mb_l >= 1 && mb_c == 0)
 			    || (mb_l > 1 && (!vim_isprintc(mb_c)
-							 || mb_c >= 0x10000)))
+# ifdef UNICODE16
+							 || mb_c >= 0x10000
+# endif
+							 )))
 		    {
 			/*
 			 * Illegal UTF-8 byte: display as <xx>.
 			 * Non-BMP character : display as ? or fullwidth ?.
 			 */
+# ifdef UNICODE16
 			if (mb_c < 0x10000)
+# endif
 			{
 			    transchar_hex(extra, mb_c);
 # ifdef FEAT_RIGHTLEFT
@@ -3635,11 +3712,13 @@
 				rl_mirror(extra);
 # endif
 			}
+# ifdef UNICODE16
 			else if (utf_char2cells(mb_c) != 2)
 			    STRCPY(extra, "?");
 			else
 			    /* 0xff1f in UTF-8: full-width '?' */
 			    STRCPY(extra, "\357\274\237");
+# endif
 
 			p_extra = extra;
 			c = *p_extra;
@@ -3752,10 +3831,8 @@
 		 * a '<' in the first column. */
 		if (n_skip > 0 && mb_l > 1)
 		{
-		    extra[0] = '<';
-		    p_extra = extra;
 		    n_extra = 1;
-		    c_extra = NUL;
+		    c_extra = '<';
 		    c = ' ';
 		    if (area_attr == 0 && search_attr == 0)
 		    {
@@ -3820,7 +3897,7 @@
 # ifdef FEAT_SPELL
 					       has_spell ? &can_spell :
 # endif
-					       NULL);
+					       NULL, FALSE);
 
 		    if (did_emsg)
 		    {
@@ -4248,20 +4325,39 @@
 	{
 #ifdef FEAT_SEARCH_EXTRA
 	    long prevcol = (long)(ptr - line) - (c == NUL);
+
+	    /* we're not really at that column when skipping some text */
+	    if ((long)(wp->w_p_wrap ? wp->w_skipcol : wp->w_leftcol) > prevcol)
+		++prevcol;
 #endif
 
 	    /* invert at least one char, used for Visual and empty line or
 	     * highlight match at end of line. If it's beyond the last
 	     * char on the screen, just overwrite that one (tricky!)  Not
 	     * needed when a '$' was displayed for 'list'. */
+#ifdef FEAT_SEARCH_EXTRA
+	    prevcol_hl_flag = FALSE;
+	    if (prevcol == (long)search_hl.startcol)
+		prevcol_hl_flag = TRUE;
+	    else
+	    {
+		cur = wp->w_match_head;
+		while (cur != NULL)
+		{
+		    if (prevcol == (long)cur->hl.startcol)
+		    {
+			prevcol_hl_flag = TRUE;
+			break;
+		    }
+		    cur = cur->next;
+		}
+	    }
+#endif
 	    if (lcs_eol == lcs_eol_one
 		    && ((area_attr != 0 && vcol == fromcol && c == NUL)
 #ifdef FEAT_SEARCH_EXTRA
 			/* highlight 'hlsearch' match at end of line */
-			|| ((prevcol == (long)search_hl.startcol
-				|| prevcol == (long)match_hl[0].startcol
-				|| prevcol == (long)match_hl[1].startcol
-				|| prevcol == (long)match_hl[2].startcol)
+			|| (prevcol_hl_flag == TRUE
 # if defined(LINE_ATTR)
 			    && did_line_attr <= 1
 # endif
@@ -4302,26 +4398,47 @@
 #ifdef FEAT_SEARCH_EXTRA
 		if (area_attr == 0)
 		{
-		    for (i = 0; i <= 3; ++i)
-		    {
-			if (i == 3)
-			    char_attr = search_hl.attr;
-			else if ((ptr - line) - 1 == (long)match_hl[i].startcol)
+		    /* Use attributes from match with highest priority among
+		     * 'search_hl' and the match list. */
+		    char_attr = search_hl.attr;
+		    cur = wp->w_match_head;
+		    shl_flag = FALSE;
+		    while (cur != NULL || shl_flag == FALSE)
+		    {
+			if (shl_flag == FALSE
+				&& ((cur != NULL
+					&& cur->priority > SEARCH_HL_PRIORITY)
+				    || cur == NULL))
 			{
-			    char_attr = match_hl[i].attr;
-			    break;
+			    shl = &search_hl;
+			    shl_flag = TRUE;
 			}
+			else
+			    shl = &cur->hl;
+			if ((ptr - line) - 1 == (long)shl->startcol)
+			    char_attr = shl->attr;
+			if (shl != &search_hl && cur != NULL)
+			    cur = cur->next;
 		    }
 		}
 #endif
 		ScreenAttrs[off] = char_attr;
 #ifdef FEAT_RIGHTLEFT
 		if (wp->w_p_rl)
+		{
 		    --col;
+		    --off;
+		}
 		else
 #endif
+		{
 		    ++col;
+		    ++off;
+		}
 		++vcol;
+#ifdef FEAT_SYN_HL
+		eol_hl_off = 1;
+#endif
 	    }
 	}
 
@@ -4331,6 +4448,14 @@
 	if (c == NUL)
 	{
 #ifdef FEAT_SYN_HL
+	    if (eol_hl_off > 0 && vcol - eol_hl_off == (long)wp->w_virtcol)
+	    {
+		/* highlight last char after line */
+		--col;
+		--off;
+		--vcol;
+	    }
+
 	    /* Highlight 'cursorcolumn' past end of the line. */
 	    if (wp->w_p_wrap)
 		v = wp->w_skipcol;
@@ -4341,7 +4466,7 @@
 
 		vcol = v + col - win_col_off(wp);
 	    if (wp->w_p_cuc
-		    && (int)wp->w_virtcol >= vcol
+		    && (int)wp->w_virtcol >= vcol - eol_hl_off
 		    && (int)wp->w_virtcol < W_WIDTH(wp) * (row - startrow + 1)
 									   + v
 		    && lnum != wp->w_cursor.lnum
@@ -4460,6 +4585,8 @@
 	    {
 		if (mb_utf8)
 		{
+		    int i;
+
 		    ScreenLinesUC[off] = mb_c;
 		    if ((c & 0xff) == 0)
 			ScreenLines[off] = 0x80;   /* avoid storing zero */
@@ -4548,7 +4675,7 @@
 
 	/*
 	 * At end of screen line and there is more to come: Display the line
-	 * so far.  If there is no more to display it is catched above.
+	 * so far.  If there is no more to display it is caught above.
 	 */
 	if ((
 #ifdef FEAT_RIGHTLEFT
@@ -4625,9 +4752,13 @@
 #endif
 #ifdef FEAT_MBYTE
 			 && !(has_mbyte
-			     && ((*mb_off2cells)(LineOffset[screen_row]) == 2
+			     && ((*mb_off2cells)(LineOffset[screen_row],
+				     LineOffset[screen_row] + screen_Columns)
+									  == 2
 				 || (*mb_off2cells)(LineOffset[screen_row - 1]
-							+ (int)Columns - 2) == 2))
+							+ (int)Columns - 2,
+				     LineOffset[screen_row] + screen_Columns)
+									== 2))
 #endif
 		   )
 		{
@@ -4787,6 +4918,10 @@
 {
     unsigned	    off_from;
     unsigned	    off_to;
+#ifdef FEAT_MBYTE
+    unsigned	    max_off_from;
+    unsigned	    max_off_to;
+#endif
     int		    col = 0;
 #if defined(FEAT_GUI) || defined(UNIX) || defined(FEAT_VERTSPLIT)
     int		    hl;
@@ -4813,6 +4948,10 @@
 
     off_from = (unsigned)(current_ScreenLine - ScreenLines);
     off_to = LineOffset[row] + coloff;
+#ifdef FEAT_MBYTE
+    max_off_from = off_from + screen_Columns;
+    max_off_to = LineOffset[row] + screen_Columns;
+#endif
 
 #ifdef FEAT_RIGHTLEFT
     if (rlflag)
@@ -4847,7 +4986,7 @@
     {
 #ifdef FEAT_MBYTE
 	if (has_mbyte && (col + 1 < endcol))
-	    char_cells = (*mb_off2cells)(off_from);
+	    char_cells = (*mb_off2cells)(off_from, max_off_from);
 	else
 	    char_cells = 1;
 #endif
@@ -4924,7 +5063,7 @@
 		 * ScreenLinesUC[] is sufficient. */
 		if (char_cells == 1
 			&& col + 1 < endcol
-			&& (*mb_off2cells)(off_to) > 1)
+			&& (*mb_off2cells)(off_to, max_off_to) > 1)
 		{
 		    /* Writing a single-cell character over a double-cell
 		     * character: need to redraw the next cell. */
@@ -4933,8 +5072,8 @@
 		}
 		else if (char_cells == 2
 			&& col + 2 < endcol
-			&& (*mb_off2cells)(off_to) == 1
-			&& (*mb_off2cells)(off_to + 1) > 1)
+			&& (*mb_off2cells)(off_to, max_off_to) == 1
+			&& (*mb_off2cells)(off_to + 1, max_off_to) > 1)
 		{
 		    /* Writing the second half of a double-cell character over
 		     * a double-cell character: need to redraw the second
@@ -4953,10 +5092,10 @@
 	     * char over the left halve of an existing one. */
 	    if (has_mbyte && col + char_cells == endcol
 		    && ((char_cells == 1
-			    && (*mb_off2cells)(off_to) > 1)
+			    && (*mb_off2cells)(off_to, max_off_to) > 1)
 			|| (char_cells == 2
-			    && (*mb_off2cells)(off_to) == 1
-			    && (*mb_off2cells)(off_to + 1) > 1)))
+			    && (*mb_off2cells)(off_to, max_off_to) == 1
+			    && (*mb_off2cells)(off_to + 1, max_off_to) > 1)))
 		clear_next = TRUE;
 #endif
 
@@ -5096,10 +5235,11 @@
 			/* find previous character by counting from first
 			 * column and get its width. */
 			unsigned off = LineOffset[row];
+			unsigned max_off = LineOffset[row] + screen_Columns;
 
 			while (off < off_to)
 			{
-			    prev_cells = (*mb_off2cells)(off);
+			    prev_cells = (*mb_off2cells)(off, max_off);
 			    off += prev_cells;
 			}
 		    }
@@ -5285,7 +5425,7 @@
 static int skip_status_match_char __ARGS((expand_T *xp, char_u *s));
 
 /*
- * Get the lenght of an item as it will be shown in the status line.
+ * Get the length of an item as it will be shown in the status line.
  */
     static int
 status_match_len(xp, s)
@@ -5351,7 +5491,7 @@
     int		row;
     char_u	*buf;
     int		len;
-    int		clen;		/* lenght in screen cells */
+    int		clen;		/* length in screen cells */
     int		fillchar;
     int		attr;
     int		i;
@@ -6103,6 +6243,7 @@
     char_u	*ptr = text;
     int		c;
 #ifdef FEAT_MBYTE
+    unsigned	max_off;
     int		mbyte_blen = 1;
     int		mbyte_cells = 1;
     int		u8c = 0;
@@ -6119,8 +6260,12 @@
 	return;
 
     off = LineOffset[row] + col;
-    while (*ptr != NUL && col < screen_Columns
-				      && (len < 0 || (int)(ptr - text) < len))
+#ifdef FEAT_MBYTE
+    max_off = LineOffset[row] + screen_Columns;
+#endif
+    while (col < screen_Columns
+	    && (len < 0 || (int)(ptr - text) < len)
+	    && *ptr != NUL)
     {
 	c = *ptr;
 #ifdef FEAT_MBYTE
@@ -6143,6 +6288,7 @@
 		else
 		    u8c = utfc_ptr2char(ptr, u8cc);
 		mbyte_cells = utf_char2cells(u8c);
+# ifdef UNICODE16
 		/* Non-BMP character: display as ? or fullwidth ?. */
 		if (u8c >= 0x10000)
 		{
@@ -6150,6 +6296,7 @@
 		    if (attr == 0)
 			attr = hl_attr(HLF_8);
 		}
+# endif
 # ifdef FEAT_ARABIC
 		if (p_arshape && !p_tbidi && ARABIC_CHAR(u8c))
 		{
@@ -6241,19 +6388,19 @@
 	    else if (has_mbyte
 		    && (len < 0 ? ptr[mbyte_blen] == NUL
 					     : ptr + mbyte_blen >= text + len)
-		    && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
+		    && ((mbyte_cells == 1 && (*mb_off2cells)(off, max_off) > 1)
 			|| (mbyte_cells == 2
-			    && (*mb_off2cells)(off) == 1
-			    && (*mb_off2cells)(off + 1) > 1)))
+			    && (*mb_off2cells)(off, max_off) == 1
+			    && (*mb_off2cells)(off + 1, max_off) > 1)))
 		clear_next_cell = TRUE;
 
 	    /* Make sure we never leave a second byte of a double-byte behind,
 	     * it confuses mb_off2cells(). */
 	    if (enc_dbcs
-		    && ((mbyte_cells == 1 && (*mb_off2cells)(off) > 1)
+		    && ((mbyte_cells == 1 && (*mb_off2cells)(off, max_off) > 1)
 			|| (mbyte_cells == 2
-			    && (*mb_off2cells)(off) == 1
-			    && (*mb_off2cells)(off + 1) > 1)))
+			    && (*mb_off2cells)(off, max_off) == 1
+			    && (*mb_off2cells)(off + 1, max_off) > 1)))
 		ScreenLines[off + mbyte_blen] = 0;
 #endif
 	    ScreenLines[off] = c;
@@ -6318,7 +6465,7 @@
 
 #ifdef FEAT_SEARCH_EXTRA
 /*
- * Prepare for 'searchhl' highlighting.
+ * Prepare for 'hlsearch' highlighting.
  */
     static void
 start_search_hl()
@@ -6327,11 +6474,15 @@
     {
 	last_pat_prog(&search_hl.rm);
 	search_hl.attr = hl_attr(HLF_L);
+# ifdef FEAT_RELTIME
+	/* Set the time limit to 'redrawtime'. */
+	profile_setlimit(p_rdt, &search_hl.tm);
+# endif
     }
 }
 
 /*
- * Clean up for 'searchhl' highlighting.
+ * Clean up for 'hlsearch' highlighting.
  */
     static void
 end_search_hl()
@@ -6351,18 +6502,28 @@
     win_T	*wp;
     linenr_T	lnum;
 {
-    match_T	*shl;		/* points to search_hl or match_hl */
+    matchitem_T *cur;		/* points to the match list */
+    match_T	*shl;		/* points to search_hl or a match */
+    int		shl_flag;	/* flag to indicate whether search_hl
+				   has been processed or not */
     int		n;
-    int		i;
 
     /*
      * When using a multi-line pattern, start searching at the top
      * of the window or just after a closed fold.
-     * Do this both for search_hl and match_hl[3].
+     * Do this both for search_hl and the match list.
      */
-    for (i = 3; i >= 0; --i)
+    cur = wp->w_match_head;
+    shl_flag = FALSE;
+    while (cur != NULL || shl_flag == FALSE)
     {
-	shl = (i == 3) ? &search_hl : &match_hl[i];
+	if (shl_flag == FALSE)
+	{
+	    shl = &search_hl;
+	    shl_flag = TRUE;
+	}
+	else
+	    shl = &cur->hl;
 	if (shl->rm.regprog != NULL
 		&& shl->lnum == 0
 		&& re_multiline(shl->rm.regprog))
@@ -6397,11 +6558,13 @@
 		}
 	    }
 	}
+	if (shl != &search_hl && cur != NULL)
+	    cur = cur->next;
     }
 }
 
 /*
- * Search for a next 'searchl' or ":match" match.
+ * Search for a next 'hlsearch' or match.
  * Uses shl->buf.
  * Sets shl->lnum and shl->rm contents.
  * Note: Assumes a previous match is always before "lnum", unless
@@ -6411,7 +6574,7 @@
     static void
 next_search_hl(win, shl, lnum, mincol)
     win_T	*win;
-    match_T	*shl;		/* points to search_hl or match_hl */
+    match_T	*shl;		/* points to search_hl or a match */
     linenr_T	lnum;
     colnr_T	mincol;		/* minimal column for a match */
 {
@@ -6440,6 +6603,14 @@
     called_emsg = FALSE;
     for (;;)
     {
+#ifdef FEAT_RELTIME
+	/* Stop searching after passing the time limit. */
+	if (profile_passed_limit(&(shl->tm)))
+	{
+	    shl->lnum = 0;		/* no match found in time */
+	    break;
+	}
+#endif
 	/* Three situations:
 	 * 1. No useful previous match: search from start of line.
 	 * 2. Not Vi compatible or empty match: continue at next character.
@@ -6473,13 +6644,19 @@
 	    matchcol = shl->rm.endpos[0].col;
 
 	shl->lnum = lnum;
-	nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol);
+	nmatched = vim_regexec_multi(&shl->rm, win, shl->buf, lnum, matchcol,
+#ifdef FEAT_RELTIME
+		&(shl->tm)
+#else
+		NULL
+#endif
+		);
 	if (called_emsg)
 	{
 	    /* Error while handling regexp: stop using this regexp. */
 	    if (shl == &search_hl)
 	    {
-		/* don't free the regprog in match_hl[], it's a copy */
+		/* don't free regprog in the match list, it's a copy */
 		vim_free(shl->rm.regprog);
 		no_hlsearch = TRUE;
 	    }
@@ -6827,6 +7004,9 @@
 {
     int		r, c;
     int		off;
+#ifdef FEAT_MBYTE
+    int		max_off;
+#endif
 
     /* Can't use ScreenLines unless initialized */
     if (ScreenLines == NULL)
@@ -6837,10 +7017,13 @@
     for (r = row; r < row + height; ++r)
     {
 	off = LineOffset[r];
+#ifdef FEAT_MBYTE
+	max_off = off + screen_Columns;
+#endif
 	for (c = col; c < col + width; ++c)
 	{
 #ifdef FEAT_MBYTE
-	    if (enc_dbcs != 0 && dbcs_off2cells(off + c) > 1)
+	    if (enc_dbcs != 0 && dbcs_off2cells(off + c, max_off) > 1)
 	    {
 		screen_char_2(off + c, r, c);
 		++c;
@@ -6850,7 +7033,7 @@
 	    {
 		screen_char(off + c, r, c);
 #ifdef FEAT_MBYTE
-		if (utf_off2cells(off + c) > 1)
+		if (utf_off2cells(off + c, max_off) > 1)
 		    ++c;
 #endif
 	    }
diff -Naur vim71.orig/src/search.c vim71/src/search.c
--- vim71.orig/src/search.c	2007-05-07 19:42:02.000000000 +0000
+++ vim71/src/search.c	2008-02-14 21:07:34.000000000 +0000
@@ -101,7 +101,6 @@
 static char_u	    *mr_pattern = NULL;	/* pattern used by search_regcomp() */
 #ifdef FEAT_RIGHTLEFT
 static int	    mr_pattern_alloced = FALSE; /* mr_pattern was allocated */
-static char_u	    *reverse_text __ARGS((char_u *s));
 #endif
 
 #ifdef FEAT_FIND_ID
@@ -228,12 +227,12 @@
     return mr_pattern;
 }
 
-#ifdef FEAT_RIGHTLEFT
+#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
 /*
  * Reverse text into allocated memory.
  * Returns the allocated string, NULL when out of memory.
  */
-    static char_u *
+    char_u *
 reverse_text(s)
     char_u *s;
 {
@@ -495,8 +494,9 @@
  * When FEAT_EVAL is defined, returns the index of the first matching
  * subpattern plus one; one if there was none.
  */
+/*ARGSUSED*/
     int
-searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum)
+searchit(win, buf, pos, dir, pat, count, options, pat_use, stop_lnum, tm)
     win_T	*win;		/* window to search in; can be NULL for a
 				   buffer without a window! */
     buf_T	*buf;
@@ -507,6 +507,7 @@
     int		options;
     int		pat_use;	/* which pattern to use when "pat" is empty */
     linenr_T	stop_lnum;	/* stop after this line number when != 0 */
+    proftime_T	*tm;		/* timeout limit or NULL */
 {
     int		found;
     linenr_T	lnum;		/* no init to shut up Apollo cc */
@@ -573,8 +574,12 @@
 	/*
 	 * Start searching in current line, unless searching backwards and
 	 * we're in column 0.
+	 * If we are searching backwards, in column 0, and not including the
+	 * current position, gain some efficiency by skipping back a line.
+	 * Otherwise begin the search in the current line.
 	 */
-	if (dir == BACKWARD && start_pos.col == 0)
+	if (dir == BACKWARD && start_pos.col == 0
+					     && (options & SEARCH_START) == 0)
 	{
 	    lnum = pos->lnum - 1;
 	    at_first_line = FALSE;
@@ -591,12 +596,23 @@
 		if (stop_lnum != 0 && (dir == FORWARD
 				       ? lnum > stop_lnum : lnum < stop_lnum))
 		    break;
+#ifdef FEAT_RELTIME
+		/* Stop after passing the "tm" time limit. */
+		if (tm != NULL && profile_passed_limit(tm))
+		    break;
+#endif
 
 		/*
 		 * Look for a match somewhere in line "lnum".
 		 */
 		nmatched = vim_regexec_multi(&regmatch, win, buf,
-							    lnum, (colnr_T)0);
+						      lnum, (colnr_T)0,
+#ifdef FEAT_RELTIME
+						      tm
+#else
+						      NULL
+#endif
+						      );
 		/* Abort searching on an error (e.g., out of stack). */
 		if (called_emsg)
 		    break;
@@ -605,9 +621,9 @@
 		    /* match may actually be in another line when using \zs */
 		    matchpos = regmatch.startpos[0];
 		    endpos = regmatch.endpos[0];
-# ifdef FEAT_EVAL
+#ifdef FEAT_EVAL
 		    submatch = first_submatch(&regmatch);
-# endif
+#endif
 		    /* Line me be past end of buffer for "\n\zs". */
 		    if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
 			ptr = (char_u *)"";
@@ -683,7 +699,13 @@
 			    if (ptr[matchcol] == NUL
 				    || (nmatched = vim_regexec_multi(&regmatch,
 					      win, buf, lnum + matchpos.lnum,
-					      matchcol)) == 0)
+					      matchcol,
+#ifdef FEAT_RELTIME
+					      tm
+#else
+					      NULL
+#endif
+					      )) == 0)
 			    {
 				match_ok = FALSE;
 				break;
@@ -789,7 +811,13 @@
 			    if (ptr[matchcol] == NUL
 				    || (nmatched = vim_regexec_multi(&regmatch,
 					      win, buf, lnum + matchpos.lnum,
-							      matchcol)) == 0)
+					      matchcol,
+#ifdef FEAT_RELTIME
+					      tm
+#else
+					      NULL
+#endif
+					    )) == 0)
 				break;
 
 			    /* Need to get the line pointer again, a
@@ -967,12 +995,13 @@
  * return 0 for failure, 1 for found, 2 for found and line offset added
  */
     int
-do_search(oap, dirc, pat, count, options)
+do_search(oap, dirc, pat, count, options, tm)
     oparg_T	    *oap;	/* can be NULL */
     int		    dirc;	/* '/' or '?' */
     char_u	   *pat;
     long	    count;
     int		    options;
+    proftime_T	    *tm;	/* timeout limit or NULL */
 {
     pos_T	    pos;	/* position of the last match */
     char_u	    *searchstr;
@@ -1246,7 +1275,7 @@
 		       (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS
 			+ SEARCH_MSG + SEARCH_START
 			+ ((pat != NULL && *pat == ';') ? 0 : SEARCH_NOOF))),
-		RE_LAST, (linenr_T)0);
+		RE_LAST, (linenr_T)0, tm);
 
 	if (dircp != NULL)
 	    *dircp = dirc;	/* restore second '/' or '?' for normal_cmd() */
@@ -1894,7 +1923,7 @@
     }
 
 #ifdef FEAT_RIGHTLEFT
-    /* This is just guessing: when 'rightleft' is set, search for a maching
+    /* This is just guessing: when 'rightleft' is set, search for a matching
      * paren/brace in the other direction. */
     if (curwin->w_p_rl && vim_strchr((char_u *)"()[]{}<>", initc) != NULL)
 	backwards = !backwards;
@@ -2124,6 +2153,9 @@
 			else if (!backwards)
 			    inquote = TRUE;
 		    }
+
+		    /* ml_get() only keeps one line, need to get linep again */
+		    linep = ml_get(pos.lnum);
 		}
 	    }
 	}
@@ -2313,7 +2345,9 @@
 #endif
     while ((p = vim_strchr(p, '/')) != NULL)
     {
-	if (p[1] == '/')
+	/* accept a double /, unless it's preceded with * and followed by *,
+	 * because * / / * is an end and start of a C comment */
+	if (p[1] == '/' && (p == line || p[-1] != '*' || p[2] != '*'))
 	    break;
 	++p;
     }
@@ -2795,7 +2829,7 @@
 	i = inc_cursor();
 	if (i == -1 || (i >= 1 && last_line)) /* started at last char in file */
 	    return FAIL;
-	if (i == 1 && eol && count == 0)      /* started at last char in line */
+	if (i >= 1 && eol && count == 0)      /* started at last char in line */
 	    return OK;
 
 	/*
@@ -3600,13 +3634,16 @@
     {
 	oap->start = start_pos;
 	oap->motion_type = MCHAR;
+	oap->inclusive = FALSE;
 	if (sol)
-	{
 	    incl(&curwin->w_cursor);
-	    oap->inclusive = FALSE;
-	}
-	else
+	else if (ltoreq(start_pos, curwin->w_cursor))
+	    /* Include the character under the cursor. */
 	    oap->inclusive = TRUE;
+	else
+	    /* End is before the start (no text in between <>, [], etc.): don't
+	     * operate on any text. */
+	    curwin->w_cursor = start_pos;
     }
 
     return OK;
@@ -3717,6 +3754,10 @@
     old_pos = curwin->w_cursor;
     old_end = curwin->w_cursor;		    /* remember where we started */
     old_start = old_end;
+#ifdef FEAT_VISUAL
+    if (!VIsual_active || *p_sel == 'e')
+#endif
+	decl(&old_end);			    /* old_end is inclusive */
 
     /*
      * If we start on "<aaa>" select that block.
@@ -3734,7 +3775,7 @@
 
 	if (in_html_tag(FALSE))
 	{
-	    /* cursor on start tag, move to just after it */
+	    /* cursor on start tag, move to its '>' */
 	    while (*ml_get_cursor() != '>')
 		if (inc_cursor() < 0)
 		    break;
@@ -3769,7 +3810,7 @@
 	if (do_searchpair((char_u *)"<[^ \t>/!]\\+\\%(\\_s\\_[^>]\\{-}[^/]>\\|$\\|\\_s\\=>\\)",
 		    (char_u *)"",
 		    (char_u *)"</[^>]*>", BACKWARD, (char_u *)"", 0,
-						      NULL, (linenr_T)0) <= 0)
+						  NULL, (linenr_T)0, 0L) <= 0)
 	{
 	    curwin->w_cursor = old_pos;
 	    goto theend;
@@ -3803,7 +3844,7 @@
     sprintf((char *)epat, "</%.*s>\\c", len, p);
 
     r = do_searchpair(spat, (char_u *)"", epat, FORWARD, (char_u *)"",
-						       0, NULL, (linenr_T)0);
+						    0, NULL, (linenr_T)0, 0L);
 
     vim_free(spat);
     vim_free(epat);
@@ -3838,7 +3879,7 @@
 	/* Exclude the start tag. */
 	curwin->w_cursor = start_pos;
 	while (inc_cursor() >= 0)
-	    if (*ml_get_cursor() == '>' && lt(curwin->w_cursor, end_pos))
+	    if (*ml_get_cursor() == '>')
 	    {
 		inc_cursor();
 		start_pos = curwin->w_cursor;
@@ -3860,7 +3901,11 @@
 #ifdef FEAT_VISUAL
     if (VIsual_active)
     {
-	if (*p_sel == 'e')
+	/* If the end is before the start there is no text between tags, select
+	 * the char under the cursor. */
+	if (lt(end_pos, start_pos))
+	    curwin->w_cursor = start_pos;
+	else if (*p_sel == 'e')
 	    ++curwin->w_cursor.col;
 	VIsual = start_pos;
 	VIsual_mode = 'v';
@@ -3872,7 +3917,15 @@
     {
 	oap->start = start_pos;
 	oap->motion_type = MCHAR;
-	oap->inclusive = TRUE;
+	if (lt(end_pos, start_pos))
+	{
+	    /* End is before the start: there is no text between tags; operate
+	     * on an empty area. */
+	    curwin->w_cursor = start_pos;
+	    oap->inclusive = FALSE;
+	}
+	else
+	    oap->inclusive = TRUE;
     }
     retval = OK;
 
diff -Naur vim71.orig/src/spell.c vim71/src/spell.c
--- vim71.orig/src/spell.c	2007-05-07 19:48:38.000000000 +0000
+++ vim71/src/spell.c	2008-02-14 21:07:34.000000000 +0000
@@ -2146,7 +2146,7 @@
 			{
 			    col = (int)(p - buf);
 			    (void)syn_get_id(wp, lnum, (colnr_T)col,
-						       FALSE, &can_spell);
+						    FALSE, &can_spell, FALSE);
 			    if (!can_spell)
 				attr = HLF_COUNT;
 			}
@@ -7829,7 +7829,7 @@
 # if (_MSC_VER <= 1200)
 /* This line is required for VC6 without the service pack.  Also see the
  * matching #pragma below. */
-/* # pragma optimize("", off) */
+ #  pragma optimize("", off)
 # endif
 #endif
 
@@ -7859,7 +7859,7 @@
 
 #ifdef _MSC_VER
 # if (_MSC_VER <= 1200)
-/* # pragma optimize("", on) */
+ #  pragma optimize("", on)
 # endif
 #endif
 
@@ -10343,7 +10343,7 @@
     curwin->w_cursor.lnum = 0;
     while (!got_int)
     {
-	if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP) == 0
+	if (do_search(NULL, '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
 						   || u_save_cursor() == FAIL)
 	    break;
 
@@ -12182,7 +12182,9 @@
 	    {
 		n = mb_cptr2len(p);
 		c = mb_ptr2char(p);
-		if (!soundfold && !spell_iswordp(p + n, curbuf))
+		if (p[n] == NUL)
+		    c2 = NUL;
+		else if (!soundfold && !spell_iswordp(p + n, curbuf))
 		    c2 = c; /* don't swap non-word char */
 		else
 		    c2 = mb_ptr2char(p + n);
@@ -12190,12 +12192,21 @@
 	    else
 #endif
 	    {
-		if (!soundfold && !spell_iswordp(p + 1, curbuf))
+		if (p[1] == NUL)
+		    c2 = NUL;
+		else if (!soundfold && !spell_iswordp(p + 1, curbuf))
 		    c2 = c; /* don't swap non-word char */
 		else
 		    c2 = p[1];
 	    }
 
+	    /* When the second character is NUL we can't swap. */
+	    if (c2 == NUL)
+	    {
+		sp->ts_state = STATE_REP_INI;
+		break;
+	    }
+
 	    /* When characters are identical, swap won't do anything.
 	     * Also get here if the second char is not a word character. */
 	    if (c == c2)
diff -Naur vim71.orig/src/structs.h vim71/src/structs.h
--- vim71.orig/src/structs.h	2007-05-07 19:50:49.000000000 +0000
+++ vim71/src/structs.h	2008-02-14 21:07:34.000000000 +0000
@@ -278,6 +278,9 @@
     linenr_T	ue_lcount;	/* linecount when u_save called */
     char_u	**ue_array;	/* array of lines in undo block */
     long	ue_size;	/* number of lines in ue_array */
+#ifdef U_DEBUG
+    int		ue_magic;	/* magic number to check allocation */
+#endif
 };
 
 struct u_header
@@ -300,6 +303,9 @@
     visualinfo_T uh_visual;	/* Visual areas before undo/after redo */
 #endif
     time_t	uh_time;	/* timestamp when the change was made */
+#ifdef U_DEBUG
+    int		uh_magic;	/* magic number to check allocation */
+#endif
 };
 
 /* values for uh_flags */
@@ -1453,6 +1459,7 @@
 #ifdef FEAT_MBYTE
     char_u	*b_start_fenc;	/* 'fileencoding' when edit started or NULL */
     int		b_bad_char;	/* "++bad=" argument when edit started or 0 */
+    int		b_start_bomb;	/* 'bomb' when it was read */
 #endif
 
 #ifdef FEAT_EVAL
@@ -1694,6 +1701,44 @@
 #define FR_COL	2	/* frame with a column of windows */
 
 /*
+ * Struct used for highlighting 'hlsearch' matches, matches defined by
+ * ":match" and matches defined by match functions.
+ * For 'hlsearch' there is one pattern for all windows.  For ":match" and the
+ * match functions there is a different pattern for each window.
+ */
+typedef struct
+{
+    regmmatch_T	rm;	/* points to the regexp program; contains last found
+			   match (may continue in next line) */
+    buf_T	*buf;	/* the buffer to search for a match */
+    linenr_T	lnum;	/* the line to search for a match */
+    int		attr;	/* attributes to be used for a match */
+    int		attr_cur; /* attributes currently active in win_line() */
+    linenr_T	first_lnum;	/* first lnum to search for multi-line pat */
+    colnr_T	startcol; /* in win_line() points to char where HL starts */
+    colnr_T	endcol;	 /* in win_line() points to char where HL ends */
+#ifdef FEAT_RELTIME
+    proftime_T	tm;	/* for a time limit */
+#endif
+} match_T;
+
+/*
+ * matchitem_T provides a linked list for storing match items for ":match" and
+ * the match functions.
+ */
+typedef struct matchitem matchitem_T;
+struct matchitem
+{
+    matchitem_T	*next;
+    int		id;	    /* match ID */
+    int		priority;   /* match priority */
+    char_u	*pattern;   /* pattern to highlight */
+    int		hlg_id;	    /* highlight group ID */
+    regmmatch_T	match;	    /* regexp program for pattern */
+    match_T	hl;	    /* struct for doing the actual highlighting */
+};
+
+/*
  * Structure which contains all information that belongs to a window
  *
  * All row numbers are relative to the start of the window, except w_winrow.
@@ -1934,9 +1979,8 @@
 #endif
 
 #ifdef FEAT_SEARCH_EXTRA
-    regmmatch_T	w_match[3];	    /* regexp programs for ":match" */
-    char_u	*(w_match_pat[3]);  /* patterns for ":match" */
-    int		w_match_id[3];	    /* highlight IDs for ":match" */
+    matchitem_T	*w_match_head;		/* head of match list */
+    int		w_next_match_id;	/* next match ID */
 #endif
 
     /*
diff -Naur vim71.orig/src/syntax.c vim71/src/syntax.c
--- vim71.orig/src/syntax.c	2007-05-07 19:42:55.000000000 +0000
+++ vim71/src/syntax.c	2008-02-14 21:07:34.000000000 +0000
@@ -66,8 +66,10 @@
 #define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
 
 #ifdef FEAT_CMDL_COMPL
-static int include_default = FALSE;	/* include "default" for expansion */
-static int include_link = FALSE;	/* include "link" for expansion */
+/* Flags to indicate an additional string for highlight name completion. */
+static int include_none = 0;	/* when 1 include "None" */
+static int include_default = 0;	/* when 1 include "default" */
+static int include_link = 0;	/* when 2 include "link" and "clear" */
 #endif
 
 /*
@@ -277,7 +279,8 @@
  */
 typedef struct state_item
 {
-    int		si_idx;			/* index of syntax pattern */
+    int		si_idx;			/* index of syntax pattern or
+					   KEYWORD_IDX */
     int		si_id;			/* highlight group ID for keywords */
     int		si_trans_id;		/* idem, transparancy removed */
     int		si_m_lnum;		/* lnum of the match */
@@ -369,13 +372,13 @@
 static int syn_stack_cleanup __ARGS((void));
 static void syn_stack_free_entry __ARGS((buf_T *buf, synstate_T *p));
 static synstate_T *syn_stack_find_entry __ARGS((linenr_T lnum));
-static synstate_T *store_current_state __ARGS((synstate_T *sp));
+static synstate_T *store_current_state __ARGS((void));
 static void load_current_state __ARGS((synstate_T *from));
 static void invalidate_current_state __ARGS((void));
 static int syn_stack_equal __ARGS((synstate_T *sp));
 static void validate_current_state __ARGS((void));
 static int syn_finish_line __ARGS((int syncing));
-static int syn_current_attr __ARGS((int syncing, int displaying, int *can_spell));
+static int syn_current_attr __ARGS((int syncing, int displaying, int *can_spell, int keep_state));
 static int did_match_already __ARGS((int idx, garray_T *gap));
 static stateitem_T *push_next_match __ARGS((stateitem_T *cur_si));
 static void check_state_ends __ARGS((void));
@@ -461,7 +464,7 @@
     synstate_T	*p;
     synstate_T	*last_valid = NULL;
     synstate_T	*last_min_valid = NULL;
-    synstate_T	*sp, *prev;
+    synstate_T	*sp, *prev = NULL;
     linenr_T	parsed_lnum;
     linenr_T	first_stored;
     int		dist;
@@ -499,7 +502,7 @@
 	if (!current_state_stored)
 	{
 	    ++current_lnum;
-	    (void)store_current_state(NULL);
+	    (void)store_current_state();
 	}
 
 	/*
@@ -555,7 +558,6 @@
 	dist = 999999;
     else
 	dist = syn_buf->b_ml.ml_line_count / (syn_buf->b_sst_len - Rows) + 1;
-    prev = syn_stack_find_entry(current_lnum);
     while (current_lnum < lnum)
     {
 	syn_start_line();
@@ -570,9 +572,13 @@
 	     * equal to the current state.  If so, then validate all saved
 	     * states that depended on a change before the parsed line. */
 	    if (prev == NULL)
+		prev = syn_stack_find_entry(current_lnum - 1);
+	    if (prev == NULL)
 		sp = syn_buf->b_sst_first;
 	    else
-		sp = prev->sst_next;
+		sp = prev;
+	    while (sp != NULL && sp->sst_lnum < current_lnum)
+		sp = sp->sst_next;
 	    if (sp != NULL
 		    && sp->sst_lnum == current_lnum
 		    && syn_stack_equal(sp))
@@ -598,7 +604,7 @@
 	    else if (prev == NULL
 			|| current_lnum == lnum
 			|| current_lnum >= prev->sst_lnum + dist)
-		prev = store_current_state(prev);
+		prev = store_current_state();
 	}
 
 	/* This can take a long time: break when CTRL-C pressed.  The current
@@ -835,9 +841,18 @@
 			    current_lnum = end_lnum;
 			    break;
 			}
-			spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]);
-			found_flags = spp->sp_flags;
-			found_match_idx = spp->sp_sync_idx;
+			if (cur_si->si_idx < 0)
+			{
+			    /* Cannot happen? */
+			    found_flags = 0;
+			    found_match_idx = KEYWORD_IDX;
+			}
+			else
+			{
+			    spp = &(SYN_ITEMS(syn_buf)[cur_si->si_idx]);
+			    found_flags = spp->sp_flags;
+			    found_match_idx = spp->sp_sync_idx;
+			}
 			found_current_lnum = current_lnum;
 			found_current_col = current_col;
 			found_m_endpos = cur_si->si_m_endpos;
@@ -1341,17 +1356,13 @@
  * The current state must be valid for the start of the current_lnum line!
  */
     static synstate_T *
-store_current_state(sp)
-    synstate_T	*sp;	/* at or before where state is to be saved or
-				   NULL */
+store_current_state()
 {
     int		i;
     synstate_T	*p;
     bufstate_T	*bp;
     stateitem_T	*cur_si;
-
-    if (sp == NULL)
-	sp = syn_stack_find_entry(current_lnum);
+    synstate_T	*sp = syn_stack_find_entry(current_lnum);
 
     /*
      * If the current state contains a start or end pattern that continues
@@ -1655,7 +1666,7 @@
 	     * Store the current state in b_sst_array[] for later use.
 	     */
 	    ++current_lnum;
-	    (void)store_current_state(NULL);
+	    (void)store_current_state();
 	}
     }
 
@@ -1679,7 +1690,7 @@
     {
 	while (!current_finished)
 	{
-	    (void)syn_current_attr(syncing, FALSE, NULL);
+	    (void)syn_current_attr(syncing, FALSE, NULL, FALSE);
 	    /*
 	     * When syncing, and found some item, need to check the item.
 	     */
@@ -1719,12 +1730,20 @@
  * done.
  */
     int
-get_syntax_attr(col, can_spell)
+get_syntax_attr(col, can_spell, keep_state)
     colnr_T	col;
     int		*can_spell;
+    int		keep_state;	/* keep state of char at "col" */
 {
     int	    attr = 0;
 
+    if (can_spell != NULL)
+	/* Default: Only do spelling when there is no @Spell cluster or when
+	 * ":syn spell toplevel" was used. */
+	*can_spell = syn_buf->b_syn_spell == SYNSPL_DEFAULT
+		    ? (syn_buf->b_spell_cluster_id == 0)
+		    : (syn_buf->b_syn_spell == SYNSPL_TOP);
+
     /* check for out of memory situation */
     if (syn_buf->b_sst_array == NULL)
 	return 0;
@@ -1749,7 +1768,8 @@
      */
     while (current_col <= col)
     {
-	attr = syn_current_attr(FALSE, TRUE, can_spell);
+	attr = syn_current_attr(FALSE, TRUE, can_spell,
+				     current_col == col ? keep_state : FALSE);
 	++current_col;
     }
 
@@ -1760,10 +1780,11 @@
  * Get syntax attributes for current_lnum, current_col.
  */
     static int
-syn_current_attr(syncing, displaying, can_spell)
+syn_current_attr(syncing, displaying, can_spell, keep_state)
     int		syncing;		/* When 1: called for syncing */
     int		displaying;		/* result will be displayed */
     int		*can_spell;		/* return: do spell checking */
+    int		keep_state;		/* keep syntax stack afterwards */
 {
     int		syn_id;
     lpos_T	endpos;		/* was: char_u *endp; */
@@ -2279,7 +2300,7 @@
 	 * may be for an empty match and a containing item might end in the
 	 * current column.
 	 */
-	if (!syncing)
+	if (!syncing && !keep_state)
 	{
 	    check_state_ends();
 	    if (current_state.ga_len > 0
@@ -2476,7 +2497,7 @@
 		if (current_state.ga_len == 0)
 		    break;
 
-		if (had_extend)
+		if (had_extend && keepend_level >= 0)
 		{
 		    syn_update_ends(FALSE);
 		    if (current_state.ga_len == 0)
@@ -2524,6 +2545,10 @@
     stateitem_T	*sip = &CUR_STATE(idx);
     synpat_T	*spp;
 
+    /* This should not happen... */
+    if (sip->si_idx < 0)
+	return;
+
     spp = &(SYN_ITEMS(syn_buf)[sip->si_idx]);
     if (sip->si_flags & HL_MATCH)
 	sip->si_id = spp->sp_syn_match_id;
@@ -2639,6 +2664,10 @@
     lpos_T	end_endpos;
     int		end_idx;
 
+    /* return quickly for a keyword */
+    if (sip->si_idx < 0)
+	return;
+
     /* Don't update when it's already done.  Can be a match of an end pattern
      * that started in a previous line.  Watch out: can also be a "keepend"
      * from a containing item. */
@@ -2751,6 +2780,10 @@
     char_u	*line;
     int		had_match = FALSE;
 
+    /* just in case we are invoked for a keyword */
+    if (idx < 0)
+	return;
+
     /*
      * Check for being called with a START pattern.
      * Can happen with a match that continues to the next line, because it
@@ -3064,7 +3097,7 @@
     colnr_T	col;
 {
     rmp->rmm_maxcol = syn_buf->b_p_smc;
-    if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col) > 0)
+    if (vim_regexec_multi(rmp, syn_win, syn_buf, lnum, col, NULL) > 0)
     {
 	rmp->startpos[0].lnum += lnum;
 	rmp->endpos[0].lnum += lnum;
@@ -3323,6 +3356,7 @@
     {
 	vim_free(SYN_ITEMS(buf)[i].sp_cont_list);
 	vim_free(SYN_ITEMS(buf)[i].sp_next_list);
+	vim_free(SYN_ITEMS(buf)[i].sp_syn.cont_in_list);
     }
 }
 
@@ -4460,8 +4494,8 @@
     current_syn_inc_tag = ++running_syn_inc_tag;
     prev_toplvl_grp = curbuf->b_syn_topgrp;
     curbuf->b_syn_topgrp = sgl_id;
-    if (source ? do_source(eap->arg, FALSE, FALSE) == FAIL
-				: source_runtime(eap->arg, DOSO_NONE) == FAIL)
+    if (source ? do_source(eap->arg, FALSE, DOSO_NONE) == FAIL
+				: source_runtime(eap->arg, TRUE) == FAIL)
 	EMSG2(_(e_notopen), eap->arg);
     curbuf->b_syn_topgrp = prev_toplvl_grp;
     current_syn_inc_tag = prev_syn_inc_tag;
@@ -5956,8 +5990,8 @@
 {
     return (buf->b_syn_patterns.ga_len != 0
 	    || buf->b_syn_clusters.ga_len != 0
-	    || curbuf->b_keywtab.ht_used > 0
-	    || curbuf->b_keywtab_ic.ht_used > 0);
+	    || buf->b_keywtab.ht_used > 0
+	    || buf->b_keywtab_ic.ht_used > 0);
 }
 
 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
@@ -5968,6 +6002,29 @@
     EXP_CASE	    /* expand ":syn case" arguments */
 } expand_what;
 
+/*
+ * Reset include_link, include_default, include_none to 0.
+ * Called when we are done expanding.
+ */
+    void
+reset_expand_highlight()
+{
+    include_link = include_default = include_none = 0;
+}
+
+/*
+ * Handle command line completion for :match and :echohl command: Add "None"
+ * as highlight group.
+ */
+    void
+set_context_in_echohl_cmd(xp, arg)
+    expand_T	*xp;
+    char_u	*arg;
+{
+    xp->xp_context = EXPAND_HIGHLIGHT;
+    xp->xp_pattern = arg;
+    include_none = 1;
+}
 
 /*
  * Handle command line completion for :syntax command.
@@ -5983,8 +6040,8 @@
     xp->xp_context = EXPAND_SYNTAX;
     expand_what = EXP_SUBCMD;
     xp->xp_pattern = arg;
-    include_link = FALSE;
-    include_default = FALSE;
+    include_link = 0;
+    include_default = 0;
 
     /* (part of) subcommand already typed */
     if (*arg != NUL)
@@ -6031,12 +6088,13 @@
  * Function called for expression evaluation: get syntax ID at file position.
  */
     int
-syn_get_id(wp, lnum, col, trans, spellp)
+syn_get_id(wp, lnum, col, trans, spellp, keep_state)
     win_T	*wp;
     long	lnum;
     colnr_T	col;
-    int		trans;	    /* remove transparancy */
-    int		*spellp;    /* return: can do spell checking */
+    int		trans;	     /* remove transparancy */
+    int		*spellp;     /* return: can do spell checking */
+    int		keep_state;  /* keep state of char at "col" */
 {
     /* When the position is not after the current position and in the same
      * line of the same buffer, need to restart parsing. */
@@ -6045,11 +6103,33 @@
 	    || col < current_col)
 	syntax_start(wp, lnum);
 
-    (void)get_syntax_attr(col, spellp);
+    (void)get_syntax_attr(col, spellp, keep_state);
 
     return (trans ? current_trans_id : current_id);
 }
 
+#if defined(FEAT_EVAL) || defined(PROTO)
+/*
+ * Return the syntax ID at position "i" in the current stack.
+ * The caller must have called syn_get_id() before to fill the stack.
+ * Returns -1 when "i" is out of range.
+ */
+    int
+syn_get_stack_item(i)
+    int i;
+{
+    if (i >= current_state.ga_len)
+    {
+	/* Need to invalidate the state, because we didn't properly finish it
+	 * for the last character, "keep_state" was TRUE. */
+	invalidate_current_state();
+	current_col = MAXCOL;
+	return -1;
+    }
+    return CUR_STATE(i).si_id;
+}
+#endif
+
 #if defined(FEAT_FOLDING) || defined(PROTO)
 /*
  * Function called to get folding level for line "lnum" in window "wp".
@@ -8479,7 +8559,7 @@
 syn_id2name(id)
     int		id;
 {
-    if (id <= 0 || id >= highlight_ga.ga_len)
+    if (id <= 0 || id > highlight_ga.ga_len)
 	return (char_u *)"";
     return HL_TABLE()[id - 1].sg_name;
 }
@@ -8949,7 +9029,7 @@
     return OK;
 }
 
-#ifdef FEAT_CMDL_COMPL
+#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
 
 static void highlight_list __ARGS((void));
 static void highlight_list_two __ARGS((int cnt, int attr));
@@ -8967,8 +9047,8 @@
     /* Default: expand group names */
     xp->xp_context = EXPAND_HIGHLIGHT;
     xp->xp_pattern = arg;
-    include_link = TRUE;
-    include_default = TRUE;
+    include_link = 2;
+    include_default = 1;
 
     /* (part of) subcommand already typed */
     if (*arg != NUL)
@@ -8976,7 +9056,7 @@
 	p = skiptowhite(arg);
 	if (*p != NUL)			/* past "default" or group name */
 	{
-	    include_default = FALSE;
+	    include_default = 0;
 	    if (STRNCMP("default", arg, p - arg) == 0)
 	    {
 		arg = skipwhite(p);
@@ -8985,7 +9065,7 @@
 	    }
 	    if (*p != NUL)			/* past group name */
 	    {
-		include_link = FALSE;
+		include_link = 0;
 		if (arg[1] == 'i' && arg[0] == 'N')
 		    highlight_list();
 		if (STRNCMP("link", arg, p - arg) == 0
@@ -9045,31 +9125,25 @@
     expand_T	*xp;
     int		idx;
 {
-    if (idx == highlight_ga.ga_len
 #ifdef FEAT_CMDL_COMPL
-	    && include_link
-#endif
-	    )
+    if (idx == highlight_ga.ga_len && include_none != 0)
+	return (char_u *)"none";
+    if (idx == highlight_ga.ga_len + include_none && include_default != 0)
+	return (char_u *)"default";
+    if (idx == highlight_ga.ga_len + include_none + include_default
+							 && include_link != 0)
 	return (char_u *)"link";
-    if (idx == highlight_ga.ga_len + 1
-#ifdef FEAT_CMDL_COMPL
-	    && include_link
-#endif
-	    )
+    if (idx == highlight_ga.ga_len + include_none + include_default + 1
+							 && include_link != 0)
 	return (char_u *)"clear";
-    if (idx == highlight_ga.ga_len + 2
-#ifdef FEAT_CMDL_COMPL
-	    && include_default
 #endif
-	    )
-	return (char_u *)"default";
     if (idx < 0 || idx >= highlight_ga.ga_len)
 	return NULL;
     return HL_TABLE()[idx].sg_name;
 }
 #endif
 
-#ifdef FEAT_GUI
+#if defined(FEAT_GUI) || defined(PROTO)
 /*
  * Free all the highlight group fonts.
  * Used when quitting for systems which need it.
diff -Naur vim71.orig/src/tag.c vim71/src/tag.c
--- vim71.orig/src/tag.c	2007-05-07 19:36:40.000000000 +0000
+++ vim71/src/tag.c	2008-02-14 21:07:34.000000000 +0000
@@ -3191,7 +3191,8 @@
 #endif
 	    save_lnum = curwin->w_cursor.lnum;
 	    curwin->w_cursor.lnum = 0;	/* start search before first line */
-	    if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options))
+	    if (do_search(NULL, pbuf[0], pbuf + 1, (long)1,
+							search_options, NULL))
 		retval = OK;
 	    else
 	    {
@@ -3203,7 +3204,7 @@
 		 */
 		p_ic = TRUE;
 		if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
-							      search_options))
+							search_options, NULL))
 		{
 		    /*
 		     * Failed to find pattern, take a guess: "^func  ("
@@ -3213,13 +3214,14 @@
 		    cc = *tagp.tagname_end;
 		    *tagp.tagname_end = NUL;
 		    sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
-		    if (!do_search(NULL, '/', pbuf, (long)1, search_options))
+		    if (!do_search(NULL, '/', pbuf, (long)1,
+							search_options, NULL))
 		    {
 			/* Guess again: "^char * \<func  (" */
 			sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
 								tagp.tagname);
 			if (!do_search(NULL, '/', pbuf, (long)1,
-							      search_options))
+							search_options, NULL))
 			    found = 0;
 		    }
 		    *tagp.tagname_end = cc;
diff -Naur vim71.orig/src/term.c vim71/src/term.c
--- vim71.orig/src/term.c	2007-05-07 19:39:11.000000000 +0000
+++ vim71/src/term.c	2008-02-14 21:07:32.000000000 +0000
@@ -4809,6 +4809,8 @@
 	    if (num_bytes == -1)
 		return -1;
 	    current_tab = (int)bytes[0];
+	    if (current_tab == 255)	/* -1 in a byte gives 255 */
+		current_tab = -1;
 	    slen += num_bytes;
 	}
 	else if (key_name[0] == (int)KS_TABMENU)
diff -Naur vim71.orig/src/termlib.c vim71/src/termlib.c
--- vim71.orig/src/termlib.c	2007-05-07 19:39:49.000000000 +0000
+++ vim71/src/termlib.c	2008-02-14 21:07:32.000000000 +0000
@@ -191,7 +191,7 @@
 	    lbuf[0] == '\t' &&
 	    lbuf[1] == ':')
 	{
-	    strcpy(lbuf, lbuf+2);
+	    mch_memmove(lbuf, lbuf + 2, strlen(lbuf + 2) + 1);
 	    llen -= 2;
 	}
 	if (lbuf[llen-2] == '\\')		/* and continuations */
diff -Naur vim71.orig/src/testdir/Makefile vim71/src/testdir/Makefile
--- vim71.orig/src/testdir/Makefile	2006-04-30 11:08:01.000000000 +0000
+++ vim71/src/testdir/Makefile	2008-02-14 21:07:33.000000000 +0000
@@ -1,9 +1,13 @@
 #
-# Makefile to run al tests for Vim
+# Makefile to run all tests for Vim
 #
 
 VIMPROG = ../vim
 
+# Uncomment this line for using valgrind.
+# The output goes into a file "valgrind.$PID" (sorry, no test number).
+# VALGRIND = valgrind --tool=memcheck --leak-check=yes --num-callers=15 --logfile=valgrind
+
 SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
 		test7.out test8.out test9.out test10.out test11.out \
 		test12.out  test13.out test14.out test15.out test17.out \
@@ -15,7 +19,8 @@
 		test43.out test44.out test45.out test46.out test47.out \
 		test48.out test49.out test51.out test52.out test53.out \
 		test54.out test55.out test56.out test57.out test58.out \
-		test59.out test60.out test61.out test62.out
+		test59.out test60.out test61.out test62.out test63.out \
+		test64.out
 
 SCRIPTS_GUI = test16.out
 
@@ -34,11 +39,11 @@
 $(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG)
 
 clean:
-	-rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* viminfo
+	-rm -rf *.out *.failed *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* valgrind.pid* viminfo
 
 test1.out: test1.in
 	-rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo
-	$(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+	$(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
 	@/bin/sh -c "if diff test.out $*.ok; \
 		then mv -f test.out $*.out; \
 		else echo; \
@@ -51,7 +56,7 @@
 	cp $*.ok test.ok
 	# Sleep a moment to avoid that the xterm title is messed up
 	@-sleep .2
-	-$(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+	-$(VALGRIND) $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
 	@/bin/sh -c "if test -f test.out; then\
 		  if diff test.out $*.ok; \
 		  then mv -f test.out $*.out; \
@@ -61,5 +66,9 @@
 		fi"
 	-rm -rf X* test.ok viminfo
 
+test49.out: test49.vim
+
+test60.out: test60.vim
+
 nolog:
 	-echo Test results: >test.log
diff -Naur vim71.orig/src/testdir/test14.in vim71/src/testdir/test14.in
--- vim71.orig/src/testdir/test14.in	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test14.in	2008-02-14 21:07:33.000000000 +0000
@@ -18,6 +18,7 @@
 : let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
 :endif
 :exe "normal " . tt
+:unlet tt
 :.w >>test.out
 :set vb
 /^Piece
diff -Naur vim71.orig/src/testdir/test26.in vim71/src/testdir/test26.in
--- vim71.orig/src/testdir/test26.in	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test26.in	2008-02-14 21:07:33.000000000 +0000
@@ -37,6 +37,7 @@
 :    endif
 :  endif
 :endwhile
+:unlet i j
 :'t,$w! test.out
 :qa!
 ENDTEST
diff -Naur vim71.orig/src/testdir/test34.in vim71/src/testdir/test34.in
--- vim71.orig/src/testdir/test34.in	2006-04-30 13:33:24.000000000 +0000
+++ vim71/src/testdir/test34.in	2008-02-14 21:07:33.000000000 +0000
@@ -52,7 +52,15 @@
 ---*---
 (one
 (two
-[(one again:$-5,$wq! test.out
+[(one again:$-5,$w! test.out
+:delfunc Table
+:delfunc Compute
+:delfunc Expr1
+:delfunc Expr2
+:delfunc ListItem
+:delfunc ListReset
+:unlet retval counter
+:q!
 ENDTEST
 
 here
diff -Naur vim71.orig/src/testdir/test39.in vim71/src/testdir/test39.in
--- vim71.orig/src/testdir/test39.in	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test39.in	2008-02-14 21:07:34.000000000 +0000
@@ -1,8 +1,10 @@
 
 Test Visual block mode commands
+And test "U" in Visual mode, also on German sharp S.
 
 STARTTEST
 :so small.vim
+:so mbyte.vim
 /^abcde
 :" Test shift-right of a block
 jlllljj>wlljlll>
@@ -14,7 +16,22 @@
 Gllllkkklllrq
 :" Test block-change
 G$khhhhhkkcmno
-:$-4,$wq! test.out
+:$-4,$w! test.out
+:" gUe must uppercase a whole word, also when ß changes to SS
+Gothe youtußeuu endYpk0wgUe
+:" gUfx must uppercase until x, inclusive.
+O- youßtußexu -0fogUfx
+:" VU must uppercase a whole line
+YpkVU
+:" same, when it's the last line in the buffer
+YPGi111VUddP
+:" Uppercase two lines
+Oblah di
+doh dutVkUj
+:" Uppercase part of two lines
+ddppi333k0i222fyllvjfuUk
+:/^the/,$w >> test.out
+:qa!
 ENDTEST
 
 abcdefghijklm
diff -Naur vim71.orig/src/testdir/test39.ok vim71/src/testdir/test39.ok
--- vim71.orig/src/testdir/test39.ok	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test39.ok	2008-02-14 21:07:34.000000000 +0000
@@ -3,3 +3,11 @@
 axyzqqqqef mno        ghijklm
 axyzqqqqefgmnoklm
 abcdqqqqijklm
+the YOUTUSSEUU end
+- yOUSSTUSSEXu -
+THE YOUTUSSEUU END
+111THE YOUTUSSEUU END
+BLAH DI
+DOH DUT
+222the yoUTUSSEUU END
+333THE YOUTUßeuu end
diff -Naur vim71.orig/src/testdir/test45.in vim71/src/testdir/test45.in
--- vim71.orig/src/testdir/test45.in	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test45.in	2008-02-14 21:07:33.000000000 +0000
@@ -55,6 +55,7 @@
 /kk$
 :call append("$", foldlevel("."))
 :/^last/+1,$w! test.out
+:delfun Flvl
 :qa!
 ENDTEST
 
diff -Naur vim71.orig/src/testdir/test47.in vim71/src/testdir/test47.in
--- vim71.orig/src/testdir/test47.in	2004-06-07 14:32:05.000000000 +0000
+++ vim71/src/testdir/test47.in	2008-02-14 21:07:33.000000000 +0000
@@ -34,6 +34,7 @@
 :call append("$", two)
 :call append("$", three)
 :$-2,$w! test.out
+:unlet one two three
 :qa!
 ENDTEST
 
diff -Naur vim71.orig/src/testdir/test49.in vim71/src/testdir/test49.in
--- vim71.orig/src/testdir/test49.in	2006-04-28 09:29:54.000000000 +0000
+++ vim71/src/testdir/test49.in	2008-02-14 21:07:33.000000000 +0000
@@ -1,13 +1,29 @@
 This is a test of the script language.
 
 If after adding a new test, the test output doesn't appear properly in
-test49.failed, try to add one ore more "G"s at the line before ENDTEST.
+test49.failed, try to add one ore more "G"s at the line ending in "test.out"
 
 STARTTEST
 :so small.vim
 :se nocp nomore viminfo+=nviminfo
 :so test49.vim
-GGGGGGGGGG"rp:.-,$wq! test.out
+GGGGGGGGGGGGGG"rp:.-,$w! test.out
+:"
+:" make valgrind happy
+:redir => funclist
+:silent func
+:redir END
+:for line in split(funclist, "\n")
+:  let name = matchstr(line, 'function \zs[A-Z]\w*\ze(')
+:  if name != ''
+:    exe "delfunc " . name
+:  endif
+:endfor
+:for v in keys(g:)
+:  silent! exe "unlet " . v
+:endfor
+:unlet v
+:qa!
 ENDTEST
 
 Results of test49.vim:
diff -Naur vim71.orig/src/testdir/test55.in vim71/src/testdir/test55.in
--- vim71.orig/src/testdir/test55.in	2006-10-15 14:07:05.000000000 +0000
+++ vim71/src/testdir/test55.in	2008-02-14 21:07:33.000000000 +0000
@@ -345,6 +345,10 @@
 :endfun
 :call Test(1, 2, [3, 4], {5: 6})  " This may take a while
 :"
+:delfunc Test
+:unlet dict
+:call garbagecollect(1)
+:"
 :/^start:/,$wq! test.out
 ENDTEST
 
diff -Naur vim71.orig/src/testdir/test56.in vim71/src/testdir/test56.in
--- vim71.orig/src/testdir/test56.in	2006-09-03 14:28:41.000000000 +0000
+++ vim71/src/testdir/test56.in	2008-02-14 21:07:33.000000000 +0000
@@ -17,5 +17,5 @@
 fun s:DoNothing()
   call append(line('$'), "nothing line")
 endfun
-nnoremap <buffer> _x	:call <SID>DoNothing()<bar>call <SID>DoLast()<cr>
+nnoremap <buffer> _x	:call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr>
 end:
diff -Naur vim71.orig/src/testdir/test58.in vim71/src/testdir/test58.in
--- vim71.orig/src/testdir/test58.in	2006-04-03 18:24:04.000000000 +0000
+++ vim71/src/testdir/test58.in	2008-02-14 21:07:33.000000000 +0000
@@ -86,6 +86,7 @@
 :$put =str
 `m]s:let [str, a] = spellbadword()
 :$put =str
+:unlet str a
 :"
 :" Postponed prefixes
 :call TestOne('2', '1')
@@ -100,6 +101,10 @@
 :" NOSLITSUGS
 :call TestOne('8', '8')
 :"
+:" clean up for valgrind
+:delfunc TestOne
+:set spl= enc=latin1
+:"
 gg:/^test output:/,$wq! test.out
 ENDTEST
 
diff -Naur vim71.orig/src/testdir/test59.in vim71/src/testdir/test59.in
--- vim71.orig/src/testdir/test59.in	2006-04-03 18:29:24.000000000 +0000
+++ vim71/src/testdir/test59.in	2008-02-14 21:07:33.000000000 +0000
@@ -90,6 +90,7 @@
 :$put =str
 `m]s:let [str, a] = spellbadword()
 :$put =str
+:unlet str a
 :"
 :" Postponed prefixes
 :call TestOne('2', '1')
@@ -101,6 +102,10 @@
 :call TestOne('6', '6')
 :call TestOne('7', '7')
 :"
+:" clean up for valgrind
+:delfunc TestOne
+:set spl= enc=latin1
+:"
 gg:/^test output:/,$wq! test.out
 ENDTEST
 
diff -Naur vim71.orig/src/testdir/test60.in vim71/src/testdir/test60.in
--- vim71.orig/src/testdir/test60.in	2006-05-05 18:41:18.000000000 +0000
+++ vim71/src/testdir/test60.in	2008-02-14 21:07:33.000000000 +0000
@@ -569,6 +569,9 @@
     redir END
 endfunction
 :call TestExists()
+:delfunc TestExists
+:delfunc RunTest
+:delfunc TestFuncArg
 :edit! test.out
 :set ff=unix
 :w
diff -Naur vim71.orig/src/testdir/test60.vim vim71/src/testdir/test60.vim
--- vim71.orig/src/testdir/test60.vim	2006-01-12 19:45:59.000000000 +0000
+++ vim71/src/testdir/test60.vim	2008-02-14 21:07:33.000000000 +0000
@@ -94,4 +94,5 @@
 else
     echo "FAILED"
 endif
+unlet str
 
diff -Naur vim71.orig/src/testdir/test62.in vim71/src/testdir/test62.in
--- vim71.orig/src/testdir/test62.in	2006-04-30 11:29:15.000000000 +0000
+++ vim71/src/testdir/test62.in	2008-02-14 21:07:33.000000000 +0000
@@ -7,6 +7,7 @@
 :let nr = tabpagenr()
 :q
 :call append(line('$'), 'tab page ' . nr)
+:unlet nr
 :"
 :" Open three tab pages and use ":tabdo"
 :0tabnew
@@ -23,6 +24,7 @@
 :q!
 :call append(line('$'), line1)
 :call append(line('$'), line2)
+:unlet line1 line2
 :"
 :"
 :/^Results/,$w! test.out
diff -Naur vim71.orig/src/testdir/test63.in vim71/src/testdir/test63.in
--- vim71.orig/src/testdir/test63.in	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test63.in	2008-02-14 21:07:33.000000000 +0000
@@ -0,0 +1,157 @@
+Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
+"matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
+
+STARTTEST
+:so small.vim
+:" --- Check that "matcharg()" returns the correct group and pattern if a match
+:" --- is defined.
+:let @r = "*** Test 1: "
+:highlight MyGroup1 ctermbg=red
+:highlight MyGroup2 ctermbg=green
+:highlight MyGroup3 ctermbg=blue
+:match MyGroup1 /TODO/
+:2match MyGroup2 /FIXME/
+:3match MyGroup3 /XXX/
+:if matcharg(1) == ['MyGroup1', 'TODO'] && matcharg(2) == ['MyGroup2', 'FIXME'] && matcharg(3) == ['MyGroup3', 'XXX']
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matcharg()" returns an empty list if the argument is not 1,
+:" --- 2 or 3 (only 0 and 4 are tested).
+:let @r .= "*** Test 2: "
+:if matcharg(0) == [] && matcharg(4) == []
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matcharg()" returns ['', ''] if a match is not defined.
+:let @r .= "*** Test 3: "
+:match
+:2match
+:3match
+:if matcharg(1) == ['', ''] && matcharg(2) == ['', ''] && matcharg(3) == ['', '']
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchadd()" and "getmatches()" agree on added matches and
+:" --- that default values apply.
+:let @r .= "*** Test 4: "
+:let m1 = matchadd("MyGroup1", "TODO")
+:let m2 = matchadd("MyGroup2", "FIXME", 42)
+:let m3 = matchadd("MyGroup3", "XXX", 60, 17)
+:if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 4}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 42, 'id': 5}, {'group': 'MyGroup3', 'pattern': 'XXX', 'priority': 60, 'id': 17}]
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchdelete()" deletes the matches defined in the previous
+:" --- test correctly.
+:let @r .= "*** Test 5: "
+:call matchdelete(m1)
+:call matchdelete(m2)
+:call matchdelete(m3)
+:unlet m1
+:unlet m2
+:unlet m3
+:if getmatches() == []
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchdelete()" returns 0 if successful and otherwise -1.
+:let @r .= "*** Test 6: "
+:let m = matchadd("MyGroup1", "TODO")
+:let r1 = matchdelete(m)
+:let r2 = matchdelete(42)
+:if r1 == 0 && r2 == -1
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:unlet m
+:unlet r1
+:unlet r2
+:" --- Check that "clearmatches()" clears all matches defined by ":match" and
+:" --- "matchadd()".
+:let @r .= "*** Test 7: "
+:let m1 = matchadd("MyGroup1", "TODO")
+:let m2 = matchadd("MyGroup2", "FIXME", 42)
+:let m3 = matchadd("MyGroup3", "XXX", 60, 17)
+:match MyGroup1 /COFFEE/
+:2match MyGroup2 /HUMPPA/
+:3match MyGroup3 /VIM/
+:call clearmatches()
+:if getmatches() == []
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:unlet m1
+:unlet m2
+:unlet m3
+:" --- Check that "setmatches()" restores a list of matches saved by
+:" --- "getmatches()" without changes. (Matches with equal priority must also
+:" --- remain in the same order.)
+:let @r .= "*** Test 8: "
+:let m1 = matchadd("MyGroup1", "TODO")
+:let m2 = matchadd("MyGroup2", "FIXME", 42)
+:let m3 = matchadd("MyGroup3", "XXX", 60, 17)
+:match MyGroup1 /COFFEE/
+:2match MyGroup2 /HUMPPA/
+:3match MyGroup3 /VIM/
+:let ml = getmatches()
+:call clearmatches()
+:call setmatches(ml)
+:if getmatches() == ml
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:call clearmatches()
+:unlet m1
+:unlet m2
+:unlet m3
+:unlet ml
+:" --- Check that "setmatches()" will not add two matches with the same ID. The
+:" --- expected behaviour (for now) is to add the first match but not the
+:" --- second and to return 0 (even though it is a matter of debate whether
+:" --- this can be considered successful behaviour).
+:let @r .= "*** Test 9: "
+:let r1 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 10, 'id': 1}])
+:if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}] && r1 == 0
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:call clearmatches()
+:unlet r1
+:" --- Check that "setmatches()" returns 0 if successful and otherwise -1.
+:" --- (A range of valid and invalid input values are tried out to generate the
+:" --- return values.)
+:let @r .= "*** Test 10: "
+:let rs1 = setmatches([])
+:let rs2 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])
+:call clearmatches()
+:let rf1 = setmatches(0)
+:let rf2 = setmatches([0])
+:let rf3 = setmatches([{'wrong key': 'wrong value'}])
+:if rs1 == 0 && rs2 == 0 && rf1 == -1 && rf2 == -1 && rf3 == -1
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:unlet rs1
+:unlet rs2
+:unlet rf1
+:unlet rf2
+:unlet rf3
+:highlight clear MyGroup1
+:highlight clear MyGroup2
+:highlight clear MyGroup3
+G"rp
+:/^Results/,$wq! test.out
+ENDTEST
+
+Results of test63:
diff -Naur vim71.orig/src/testdir/test63.ok vim71/src/testdir/test63.ok
--- vim71.orig/src/testdir/test63.ok	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test63.ok	2008-02-14 21:07:32.000000000 +0000
@@ -0,0 +1,11 @@
+Results of test63:
+*** Test 1: OK
+*** Test 2: OK
+*** Test 3: OK
+*** Test 4: OK
+*** Test 5: OK
+*** Test 6: OK
+*** Test 7: OK
+*** Test 8: OK
+*** Test 9: OK
+*** Test 10: OK
diff -Naur vim71.orig/src/testdir/test64.in vim71/src/testdir/test64.in
--- vim71.orig/src/testdir/test64.in	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test64.in	2008-02-14 21:07:33.000000000 +0000
@@ -0,0 +1,167 @@
+Test for regexp patterns.
+
+A pattern that gives the expected result produces OK, so that we know it was
+actually tried.
+
+STARTTEST
+:so small.vim
+:" tl is a List of Lists with:
+:"    regexp pattern
+:"    text to test the pattern on
+:"    expected match (optional)
+:"    expected submatch 1 (optional)
+:"    expected submatch 2 (optional)
+:"    etc.
+:"  When there is no match use only the first two items.
+:let tl = []
+:call add(tl, ['ab', 'aab', 'ab'])
+:call add(tl, ['b', 'abcdef', 'b'])
+:call add(tl, ['bc*', 'abccccdef', 'bcccc'])
+:call add(tl, ['bc\{-}', 'abccccdef', 'b'])
+:call add(tl, ['bc\{-}\(d\)', 'abccccdef', 'bccccd', 'd'])
+:call add(tl, ['bc*', 'abbdef', 'b'])
+:call add(tl, ['c*', 'ccc', 'ccc'])
+:call add(tl, ['bc*', 'abdef', 'b'])
+:call add(tl, ['c*', 'abdef', ''])
+:call add(tl, ['bc\+', 'abccccdef', 'bcccc'])
+:call add(tl, ['bc\+', 'abdef']) "no match
+:"
+:"operator \|
+:call add(tl, ['a\|ab', 'cabd', 'a']) "alternation is ordered
+:"
+:call add(tl, ['c\?', 'ccb', 'c'])
+:call add(tl, ['bc\?', 'abd', 'b'])
+:call add(tl, ['bc\?', 'abccd', 'bc'])
+:"
+:call add(tl, ['\va{1}', 'ab', 'a'])
+:"
+:call add(tl, ['\va{2}', 'aa', 'aa'])
+:call add(tl, ['\va{2}', 'caad', 'aa'])
+:call add(tl, ['\va{2}', 'aba'])
+:call add(tl, ['\va{2}', 'ab'])
+:call add(tl, ['\va{2}', 'abaa', 'aa'])
+:call add(tl, ['\va{2}', 'aaa', 'aa'])
+:"
+:call add(tl, ['\vb{1}', 'abca', 'b'])
+:call add(tl, ['\vba{2}', 'abaa', 'baa'])
+:call add(tl, ['\vba{3}', 'aabaac'])
+:"
+:call add(tl, ['\v(ab){1}', 'ab', 'ab', 'ab'])
+:call add(tl, ['\v(ab){1}', 'dabc', 'ab', 'ab'])
+:call add(tl, ['\v(ab){1}', 'acb'])
+:"
+:call add(tl, ['\v(ab){0,2}', 'acb', "", ""])
+:call add(tl, ['\v(ab){0,2}', 'ab', 'ab', 'ab'])
+:call add(tl, ['\v(ab){1,2}', 'ab', 'ab', 'ab'])
+:call add(tl, ['\v(ab){1,2}', 'ababc', 'abab', 'ab'])
+:call add(tl, ['\v(ab){2,4}', 'ababcab', 'abab', 'ab'])
+:call add(tl, ['\v(ab){2,4}', 'abcababa', 'abab', 'ab'])
+:"
+:call add(tl, ['\v(ab){2}', 'abab', 'abab', 'ab'])
+:call add(tl, ['\v(ab){2}', 'cdababe', 'abab', 'ab'])
+:call add(tl, ['\v(ab){2}', 'abac'])
+:call add(tl, ['\v(ab){2}', 'abacabab', 'abab', 'ab'])
+:call add(tl, ['\v((ab){2}){2}', 'abababab', 'abababab', 'abab', 'ab'])
+:call add(tl, ['\v((ab){2}){2}', 'abacabababab', 'abababab', 'abab', 'ab'])
+:"
+:call add(tl, ['\v(a{1}){1}', 'a', 'a', 'a'])
+:call add(tl, ['\v(a{2}){1}', 'aa', 'aa', 'aa'])
+:call add(tl, ['\v(a{2}){1}', 'aaac', 'aa', 'aa'])
+:call add(tl, ['\v(a{2}){1}', 'daaac', 'aa', 'aa'])
+:call add(tl, ['\v(a{1}){2}', 'daaac', 'aa', 'a'])
+:call add(tl, ['\v(a{1}){2}', 'aaa', 'aa', 'a'])
+:call add(tl, ['\v(a{2})+', 'adaac', 'aa', 'aa'])
+:call add(tl, ['\v(a{2})+', 'aa', 'aa', 'aa'])
+:call add(tl, ['\v(a{2}){1}', 'aa', 'aa', 'aa'])
+:call add(tl, ['\v(a{1}){2}', 'aa', 'aa', 'a'])
+:call add(tl, ['\v(a{1}){1}', 'a', 'a', 'a'])
+:call add(tl, ['\v(a{2}){2}', 'aaaa', 'aaaa', 'aa'])
+:call add(tl, ['\v(a{2}){2}', 'aaabaaaa', 'aaaa', 'aa'])
+:"
+:call add(tl, ['\v(a+){2}', 'dadaac', 'aa', 'a'])
+:call add(tl, ['\v(a{3}){2}', 'aaaaaaa', 'aaaaaa', 'aaa'])
+:"
+:call add(tl, ['\v(a{1,2}){2}', 'daaac', 'aaa', 'a'])
+:call add(tl, ['\v(a{1,3}){2}', 'daaaac', 'aaaa', 'a'])
+:call add(tl, ['\v(a{1,3}){2}', 'daaaaac', 'aaaaa', 'aa'])
+:call add(tl, ['\v(a{1,3}){3}', 'daac'])
+:call add(tl, ['\v(a{1,2}){2}', 'dac'])
+:call add(tl, ['\v(a+)+', 'daac', 'aa', 'aa'])
+:call add(tl, ['\v(a+)+', 'aaa', 'aaa', 'aaa'])
+:call add(tl, ['\v(a+){1,2}', 'aaa', 'aaa', 'aaa'])
+:call add(tl, ['\v(a+)(a+)', 'aaa', 'aaa', 'aa', 'a'])
+:call add(tl, ['\v(a{3})+', 'daaaac', 'aaa', 'aaa'])
+:call add(tl, ['\v(a|b|c)+', 'aacb', 'aacb', 'b'])
+:call add(tl, ['\v(a|b|c){2}', 'abcb', 'ab', 'b'])
+:call add(tl, ['\v(abc){2}', 'abcabd', ])
+:call add(tl, ['\v(abc){2}', 'abdabcabc','abcabc', 'abc'])
+:"
+:call add(tl, ['a*', 'cc', ''])
+:call add(tl, ['\v(a*)+', 'cc', ''])
+:call add(tl, ['\v((ab)+)+', 'ab', 'ab', 'ab', 'ab'])
+:call add(tl, ['\v(((ab)+)+)+', 'ab', 'ab', 'ab', 'ab', 'ab'])
+:call add(tl, ['\v(((ab)+)+)+', 'dababc', 'abab', 'abab', 'abab', 'ab'])
+:call add(tl, ['\v(a{0,2})+', 'cc', ''])
+:call add(tl, ['\v(a*)+', '', ''])
+:call add(tl, ['\v((a*)+)+', '', ''])
+:call add(tl, ['\v((ab)*)+', '', ''])
+:call add(tl, ['\va{1,3}', 'aab', 'aa'])
+:call add(tl, ['\va{2,3}', 'abaa', 'aa'])
+:"
+:call add(tl, ['\v((ab)+|c*)+', 'abcccaba', 'abcccab', '', 'ab'])
+:call add(tl, ['\v(a{2})|(b{3})', 'bbabbbb', 'bbb', '', 'bbb'])
+:call add(tl, ['\va{2}|b{2}', 'abab'])
+:call add(tl, ['\v(a)+|(c)+', 'bbacbaacbbb', 'a', 'a'])
+:call add(tl, ['\vab{2,3}c', 'aabbccccccccccccc', 'abbc'])
+:call add(tl, ['\vab{2,3}c', 'aabbbccccccccccccc', 'abbbc'])
+:call add(tl, ['\vab{2,3}cd{2,3}e', 'aabbbcddee', 'abbbcdde'])
+:call add(tl, ['\va(bc){2}d', 'aabcbfbc' ])
+:call add(tl, ['\va*a{2}', 'a', ])
+:call add(tl, ['\va*a{2}', 'aa', 'aa' ])
+:call add(tl, ['\va*a{2}', 'aaa', 'aaa' ])
+:call add(tl, ['\va*a{2}', 'bbbabcc', ])
+:call add(tl, ['\va*b*|a*c*', 'a', 'a'])
+:call add(tl, ['\va{1}b{1}|a{1}b{1}', ''])
+:"
+:"submatches
+:call add(tl, ['\v(a)', 'ab', 'a', 'a'])
+:call add(tl, ['\v(a)(b)', 'ab', 'ab', 'a', 'b'])
+:call add(tl, ['\v(ab)(b)(c)', 'abbc', 'abbc', 'ab', 'b', 'c'])
+:call add(tl, ['\v((a)(b))', 'ab', 'ab', 'ab', 'a', 'b'])
+:call add(tl, ['\v(a)|(b)', 'ab', 'a', 'a'])
+:"
+:call add(tl, ['\v(a*)+', 'aaaa', 'aaaa', ''])
+:call add(tl, ['x', 'abcdef'])
+:"
+:for t in tl
+:  let l = matchlist(t[1], t[0])
+:" check the match itself
+:  if len(l) == 0 && len(t) > 2
+:    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", did not match, expected: \"' . t[2] . '\"'
+:  elseif len(l) > 0 && len(t) == 2
+:    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected no match'
+:  elseif len(t) > 2 && l[0] != t[2]
+:    $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", match: \"' . l[0] . '\", expected: \"' . t[2] . '\"'
+:  else
+:    $put ='OK'
+:  endif
+:  if len(l) > 0
+:"   check all the nine submatches
+:    for i in range(1, 9)
+:      if len(t) <= i + 2
+:        let e = ''
+:      else
+:        let e = t[i + 2]
+:      endif
+:      if l[i] != e
+:        $put ='ERROR: pat: \"' . t[0] . '\", text: \"' . t[1] . '\", submatch ' . i . ': \"' . l[i] . '\", expected: \"' . e . '\"'
+:      endif
+:    endfor
+:    unlet i
+:  endif
+:endfor
+:unlet t tl e l
+:/^Results/,$wq! test.out
+ENDTEST
+
+Results of test64:
diff -Naur vim71.orig/src/testdir/test64.ok vim71/src/testdir/test64.ok
--- vim71.orig/src/testdir/test64.ok	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test64.ok	2008-02-14 21:07:33.000000000 +0000
@@ -0,0 +1,102 @@
+Results of test64:
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
diff -Naur vim71.orig/src/ui.c vim71/src/ui.c
--- vim71.orig/src/ui.c	2007-05-07 19:49:09.000000000 +0000
+++ vim71/src/ui.c	2008-02-14 21:07:32.000000000 +0000
@@ -1603,8 +1603,6 @@
 #if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) \
 	|| defined(FEAT_XCLIPBOARD) || defined(VMS) \
 	|| defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) \
-	|| (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
-		|| defined(FEAT_MENU))) \
 	|| defined(PROTO)
 /*
  * Add the given bytes to the input buffer
@@ -1630,7 +1628,9 @@
 }
 #endif
 
-#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \
+#if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \
+	|| defined(FEAT_GUI_MSWIN) \
+	|| defined(FEAT_GUI_MAC) \
 	|| (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \
 	|| (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
 		|| defined(FEAT_MENU))) \
diff -Naur vim71.orig/src/undo.c vim71/src/undo.c
--- vim71.orig/src/undo.c	2007-05-07 19:21:14.000000000 +0000
+++ vim71/src/undo.c	2008-02-14 21:07:34.000000000 +0000
@@ -76,6 +76,12 @@
  * buffer is unloaded.
  */
 
+/* Uncomment the next line for including the u_check() function.  This warns
+ * for errors in the debug information. */
+/* #define U_DEBUG 1 */
+#define UH_MAGIC 0x18dade	/* value for uh_magic when in use */
+#define UE_MAGIC 0xabc123	/* value for ue_magic when in use */
+
 #include "vim.h"
 
 /* See below: use malloc()/free() for memory management. */
@@ -113,6 +119,95 @@
  */
 static int	undo_undoes = FALSE;
 
+#ifdef U_DEBUG
+/*
+ * Check the undo structures for being valid.  Print a warning when something
+ * looks wrong.
+ */
+static int seen_b_u_curhead;
+static int seen_b_u_newhead;
+static int header_count;
+
+    static void
+u_check_tree(u_header_T *uhp,
+	u_header_T *exp_uh_next,
+	u_header_T *exp_uh_alt_prev)
+{
+    u_entry_T *uep;
+
+    if (uhp == NULL)
+	return;
+    ++header_count;
+    if (uhp == curbuf->b_u_curhead && ++seen_b_u_curhead > 1)
+    {
+	EMSG("b_u_curhead found twice (looping?)");
+	return;
+    }
+    if (uhp == curbuf->b_u_newhead && ++seen_b_u_newhead > 1)
+    {
+	EMSG("b_u_newhead found twice (looping?)");
+	return;
+    }
+
+    if (uhp->uh_magic != UH_MAGIC)
+	EMSG("uh_magic wrong (may be using freed memory)");
+    else
+    {
+	/* Check pointers back are correct. */
+	if (uhp->uh_next != exp_uh_next)
+	{
+	    EMSG("uh_next wrong");
+	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
+						   exp_uh_next, uhp->uh_next);
+	}
+	if (uhp->uh_alt_prev != exp_uh_alt_prev)
+	{
+	    EMSG("uh_alt_prev wrong");
+	    smsg((char_u *)"expected: 0x%x, actual: 0x%x",
+					   exp_uh_alt_prev, uhp->uh_alt_prev);
+	}
+
+	/* Check the undo tree at this header. */
+	for (uep = uhp->uh_entry; uep != NULL; uep = uep->ue_next)
+	{
+	    if (uep->ue_magic != UE_MAGIC)
+	    {
+		EMSG("ue_magic wrong (may be using freed memory)");
+		break;
+	    }
+	}
+
+	/* Check the next alt tree. */
+	u_check_tree(uhp->uh_alt_next, uhp->uh_next, uhp);
+
+	/* Check the next header in this branch. */
+	u_check_tree(uhp->uh_prev, uhp, NULL);
+    }
+}
+
+    void
+u_check(int newhead_may_be_NULL)
+{
+    seen_b_u_newhead = 0;
+    seen_b_u_curhead = 0;
+    header_count = 0;
+
+    u_check_tree(curbuf->b_u_oldhead, NULL, NULL);
+
+    if (seen_b_u_newhead == 0 && curbuf->b_u_oldhead != NULL
+	    && !(newhead_may_be_NULL && curbuf->b_u_newhead == NULL))
+	EMSGN("b_u_newhead invalid: 0x%x", curbuf->b_u_newhead);
+    if (curbuf->b_u_curhead != NULL && seen_b_u_curhead == 0)
+	EMSGN("b_u_curhead invalid: 0x%x", curbuf->b_u_curhead);
+    if (header_count != curbuf->b_u_numhead)
+    {
+	EMSG("b_u_numhead invalid");
+	smsg((char_u *)"expected: %ld, actual: %ld",
+			       (long)header_count, (long)curbuf->b_u_numhead);
+    }
+}
+#endif
+
 /*
  * Save the current line for both the "u" and "U" command.
  * Returns OK or FAIL.
@@ -243,6 +338,9 @@
     if (!undo_allowed())
 	return FAIL;
 
+#ifdef U_DEBUG
+    u_check(FALSE);
+#endif
 #ifdef FEAT_NETBEANS_INTG
     /*
      * Netbeans defines areas that cannot be modified.  Bail out here when
@@ -294,6 +392,9 @@
 	    uhp = (u_header_T *)U_ALLOC_LINE((unsigned)sizeof(u_header_T));
 	    if (uhp == NULL)
 		goto nomem;
+#ifdef U_DEBUG
+	    uhp->uh_magic = UH_MAGIC;
+#endif
 	}
 	else
 	    uhp = NULL;
@@ -316,8 +417,11 @@
 	{
 	    u_header_T	    *uhfree = curbuf->b_u_oldhead;
 
-	    /* If there is no branch only free one header. */
-	    if (uhfree->uh_alt_next == NULL)
+	    if (uhfree == old_curhead)
+		/* Can't reconnect the branch, delete all of it. */
+		u_freebranch(curbuf, uhfree, &old_curhead);
+	    else if (uhfree->uh_alt_next == NULL)
+		/* There is no branch, only free one header. */
 		u_freeheader(curbuf, uhfree, &old_curhead);
 	    else
 	    {
@@ -326,6 +430,9 @@
 		    uhfree = uhfree->uh_alt_next;
 		u_freebranch(curbuf, uhfree, &old_curhead);
 	    }
+#ifdef U_DEBUG
+	    u_check(TRUE);
+#endif
 	}
 
 	if (uhp == NULL)		/* no undo at all */
@@ -478,6 +585,9 @@
     uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
     if (uep == NULL)
 	goto nomem;
+#ifdef U_DEBUG
+    uep->ue_magic = UE_MAGIC;
+#endif
 
     uep->ue_size = size;
     uep->ue_top = top;
@@ -525,6 +635,9 @@
     curbuf->b_u_synced = FALSE;
     undo_undoes = FALSE;
 
+#ifdef U_DEBUG
+    u_check(FALSE);
+#endif
     return OK;
 
 nomem:
@@ -955,6 +1068,9 @@
     int		empty_buffer;		    /* buffer became empty */
     u_header_T	*curhead = curbuf->b_u_curhead;
 
+#ifdef U_DEBUG
+    u_check(FALSE);
+#endif
     old_flags = curhead->uh_flags;
     new_flags = (curbuf->b_changed ? UH_CHANGED : 0) +
 	       ((curbuf->b_ml.ml_flags & ML_EMPTY) ? UH_EMPTYBUF : 0);
@@ -1186,6 +1302,9 @@
     /* The timestamp can be the same for multiple changes, just use the one of
      * the undone/redone change. */
     curbuf->b_u_seq_time = curhead->uh_time;
+#ifdef U_DEBUG
+    u_check(FALSE);
+#endif
 }
 
 /*
@@ -1515,7 +1634,7 @@
 }
 
 /*
- * Free one header and its entry list and adjust the pointers.
+ * Free one header "uhp" and its entry list and adjust the pointers.
  */
     static void
 u_freeheader(buf, uhp, uhpp)
@@ -1523,6 +1642,8 @@
     u_header_T	    *uhp;
     u_header_T	    **uhpp;	/* if not NULL reset when freeing this header */
 {
+    u_header_T	    *uhap;
+
     /* When there is an alternate redo list free that branch completely,
      * because we can never go there. */
     if (uhp->uh_alt_next != NULL)
@@ -1540,7 +1661,8 @@
     if (uhp->uh_prev == NULL)
 	buf->b_u_newhead = uhp->uh_next;
     else
-	uhp->uh_prev->uh_next = uhp->uh_next;
+	for (uhap = uhp->uh_prev; uhap != NULL; uhap = uhap->uh_alt_next)
+	    uhap->uh_next = uhp->uh_next;
 
     u_freeentries(buf, uhp, uhpp);
 }
@@ -1556,6 +1678,14 @@
 {
     u_header_T	    *tofree, *next;
 
+    /* If this is the top branch we may need to use u_freeheader() to update
+     * all the pointers. */
+    if (uhp == buf->b_u_oldhead)
+    {
+	u_freeheader(buf, uhp, uhpp);
+	return;
+    }
+
     if (uhp->uh_alt_prev != NULL)
 	uhp->uh_alt_prev->uh_alt_next = NULL;
 
@@ -1585,6 +1715,8 @@
     /* Check for pointers to the header that become invalid now. */
     if (buf->b_u_curhead == uhp)
 	buf->b_u_curhead = NULL;
+    if (buf->b_u_newhead == uhp)
+	buf->b_u_newhead = NULL;  /* freeing the newest entry */
     if (uhpp != NULL && uhp == *uhpp)
 	*uhpp = NULL;
 
@@ -1594,6 +1726,9 @@
 	u_freeentry(uep, uep->ue_size);
     }
 
+#ifdef U_DEBUG
+    uhp->uh_magic = 0;
+#endif
     U_FREE_LINE((char_u *)uhp);
     --buf->b_u_numhead;
 }
@@ -1609,6 +1744,9 @@
     while (n > 0)
 	U_FREE_LINE(uep->ue_array[--n]);
     U_FREE_LINE((char_u *)uep->ue_array);
+#ifdef U_DEBUG
+    uep->ue_magic = 0;
+#endif
     U_FREE_LINE((char_u *)uep);
 }
 
@@ -1676,13 +1814,14 @@
     if (undo_off)
 	return;
 
-    if (curbuf->b_u_line_ptr == NULL ||
-			curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
+    if (curbuf->b_u_line_ptr == NULL
+			|| curbuf->b_u_line_lnum > curbuf->b_ml.ml_line_count)
     {
 	beep_flush();
 	return;
     }
-	/* first save the line for the 'u' command */
+
+    /* first save the line for the 'u' command */
     if (u_savecommon(curbuf->b_u_line_lnum - 1,
 				curbuf->b_u_line_lnum + 1, (linenr_T)0) == FAIL)
 	return;
@@ -1702,6 +1841,7 @@
 	curbuf->b_u_line_colnr = curwin->w_cursor.col;
     curwin->w_cursor.col = t;
     curwin->w_cursor.lnum = curbuf->b_u_line_lnum;
+    check_cursor_col();
 }
 
 /*
diff -Naur vim71.orig/src/version.c vim71/src/version.c
--- vim71.orig/src/version.c	2007-05-12 10:23:44.000000000 +0000
+++ vim71/src/version.c	2008-02-14 21:07:34.000000000 +0000
@@ -667,6 +667,508 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    251,
+/**/
+    250,
+/**/
+    249,
+/**/
+    248,
+/**/
+    247,
+/**/
+    246,
+/**/
+    245,
+/**/
+    244,
+/**/
+    243,
+/**/
+    242,
+/**/
+    241,
+/**/
+    240,
+/**/
+    239,
+/**/
+    238,
+/**/
+    237,
+/**/
+    236,
+/**/
+    235,
+/**/
+    234,
+/**/
+    233,
+/**/
+    232,
+/**/
+    231,
+/**/
+    230,
+/**/
+    229,
+/**/
+    228,
+/**/
+    227,
+/**/
+    226,
+/**/
+    225,
+/**/
+    224,
+/**/
+    223,
+/**/
+    222,
+/**/
+    221,
+/**/
+    220,
+/**/
+    219,
+/**/
+    218,
+/**/
+    217,
+/**/
+    216,
+/**/
+    215,
+/**/
+    214,
+/**/
+    213,
+/**/
+    212,
+/**/
+    211,
+/**/
+    210,
+/**/
+    209,
+/**/
+    208,
+/**/
+    207,
+/**/
+    206,
+/**/
+    205,
+/**/
+    204,
+/**/
+    203,
+/**/
+    202,
+/**/
+    201,
+/**/
+    200,
+/**/
+    199,
+/**/
+    198,
+/**/
+    197,
+/**/
+    196,
+/**/
+    195,
+/**/
+    194,
+/**/
+    193,
+/**/
+    192,
+/**/
+    191,
+/**/
+    190,
+/**/
+    189,
+/**/
+    188,
+/**/
+    187,
+/**/
+    186,
+/**/
+    185,
+/**/
+    184,
+/**/
+    183,
+/**/
+    182,
+/**/
+    181,
+/**/
+    180,
+/**/
+    179,
+/**/
+    178,
+/**/
+    177,
+/**/
+    176,
+/**/
+    175,
+/**/
+    174,
+/**/
+    173,
+/**/
+    172,
+/**/
+    171,
+/**/
+    170,
+/**/
+    169,
+/**/
+    168,
+/**/
+    167,
+/**/
+    166,
+/**/
+    165,
+/**/
+    164,
+/**/
+    163,
+/**/
+    162,
+/**/
+    161,
+/**/
+    160,
+/**/
+    159,
+/**/
+    158,
+/**/
+    157,
+/**/
+    156,
+/**/
+    155,
+/**/
+    154,
+/**/
+    153,
+/**/
+    152,
+/**/
+    151,
+/**/
+    150,
+/**/
+    149,
+/**/
+    148,
+/**/
+    147,
+/**/
+    146,
+/**/
+    145,
+/**/
+    144,
+/**/
+    143,
+/**/
+    142,
+/**/
+    141,
+/**/
+    140,
+/**/
+    139,
+/**/
+    138,
+/**/
+    137,
+/**/
+    136,
+/**/
+    135,
+/**/
+    134,
+/**/
+    133,
+/**/
+    132,
+/**/
+    131,
+/**/
+    130,
+/**/
+    129,
+/**/
+    128,
+/**/
+    127,
+/**/
+    126,
+/**/
+    125,
+/**/
+    124,
+/**/
+    123,
+/**/
+    122,
+/**/
+    121,
+/**/
+    120,
+/**/
+    119,
+/**/
+    118,
+/**/
+    117,
+/**/
+    116,
+/**/
+    115,
+/**/
+    114,
+/**/
+    113,
+/**/
+    112,
+/**/
+    111,
+/**/
+    110,
+/**/
+    109,
+/**/
+    108,
+/**/
+    107,
+/**/
+    106,
+/**/
+    105,
+/**/
+    104,
+/**/
+    103,
+/**/
+    102,
+/**/
+    101,
+/**/
+    100,
+/**/
+    99,
+/**/
+    98,
+/**/
+    97,
+/**/
+    96,
+/**/
+    95,
+/**/
+    94,
+/**/
+    93,
+/**/
+    92,
+/**/
+    91,
+/**/
+    90,
+/**/
+    89,
+/**/
+    88,
+/**/
+    87,
+/**/
+    86,
+/**/
+    85,
+/**/
+    84,
+/**/
+    83,
+/**/
+    82,
+/**/
+    81,
+/**/
+    80,
+/**/
+    79,
+/**/
+    78,
+/**/
+    77,
+/**/
+    76,
+/**/
+    75,
+/**/
+    74,
+/**/
+    73,
+/**/
+    72,
+/**/
+    71,
+/**/
+    70,
+/**/
+    69,
+/**/
+    68,
+/**/
+    67,
+/**/
+    66,
+/**/
+    65,
+/**/
+    64,
+/**/
+    63,
+/**/
+    62,
+/**/
+    61,
+/**/
+    60,
+/**/
+    59,
+/**/
+    58,
+/**/
+    57,
+/**/
+    56,
+/**/
+    55,
+/**/
+    54,
+/**/
+    53,
+/**/
+    52,
+/**/
+    51,
+/**/
+    50,
+/**/
+    49,
+/**/
+    48,
+/**/
+    47,
+/**/
+    46,
+/**/
+    45,
+/**/
+    44,
+/**/
+    43,
+/**/
+    42,
+/**/
+    41,
+/**/
+    40,
+/**/
+    39,
+/**/
+    38,
+/**/
+    37,
+/**/
+    36,
+/**/
+    35,
+/**/
+    34,
+/**/
+    33,
+/**/
+    32,
+/**/
+    31,
+/**/
+    30,
+/**/
+    29,
+/**/
+    28,
+/**/
+    27,
+/**/
+    26,
+/**/
+    25,
+/**/
+    24,
+/**/
+    23,
+/**/
+    22,
+/**/
+    21,
+/**/
+    20,
+/**/
+    19,
+/**/
+    18,
+/**/
+    17,
+/**/
+    16,
+/**/
+    15,
+/**/
+    14,
+/**/
+    13,
+/**/
+    12,
+/**/
+    11,
+/**/
+    10,
+/**/
+    9,
+/**/
+    8,
+/**/
+    7,
+/**/
+    6,
+/**/
+    5,
+/**/
+    4,
+/**/
+    3,
+/**/
+    2,
+/**/
+    1,
+/**/
     0
 };
 
@@ -1177,9 +1679,9 @@
 
     if (*mesg == ' ')
     {
-	vim_strncpy(modby, _("Modified by "), MODBY_LEN - 1);
+	vim_strncpy(modby, (char_u *)_("Modified by "), MODBY_LEN - 1);
 	l = STRLEN(modby);
-	vim_strncpy(modby + l, MODIFIED_BY, MODBY_LEN - l - 1);
+	vim_strncpy(modby + l, (char_u *)MODIFIED_BY, MODBY_LEN - l - 1);
 	mesg = modby;
     }
 #endif
diff -Naur vim71.orig/src/vim.h vim71/src/vim.h
--- vim71.orig/src/vim.h	2007-05-12 09:53:29.000000000 +0000
+++ vim71/src/vim.h	2008-02-14 21:07:34.000000000 +0000
@@ -1380,8 +1380,14 @@
 #endif
 
 #ifdef FEAT_MBYTE
-# define MB_STRICMP(d, s)	(has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL) : STRICMP((d), (s)))
-# define MB_STRNICMP(d, s, n)	(has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n)) : STRNICMP((d), (s), (n)))
+/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte
+ * encoding because mb_stricmp() takes care of all ascii and non-ascii
+ * encodings, including characters with umluats in latin1, etc., while
+ * STRICMP() only handles the system locale version, which often does not
+ * handle non-ascii properly. */
+
+# define MB_STRICMP(d, s)	mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL)
+# define MB_STRNICMP(d, s, n)	mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n))
 #else
 # define MB_STRICMP(d, s)	STRICMP((d), (s))
 # define MB_STRNICMP(d, s, n)	STRNICMP((d), (s), (n))
@@ -1544,6 +1550,16 @@
 # define MB_MAXBYTES	21
 #endif
 
+#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO)
+# ifdef WIN3264
+typedef LARGE_INTEGER proftime_T;
+# else
+typedef struct timeval proftime_T;
+# endif
+#else
+typedef int proftime_T;	    /* dummy for function prototypes */
+#endif
+
 /* Include option.h before structs.h, because the number of window-local and
  * buffer-local options is used there. */
 #include "option.h"	    /* options and default values */
@@ -1682,7 +1698,8 @@
 #define VV_MOUSE_WIN	49
 #define VV_MOUSE_LNUM   50
 #define VV_MOUSE_COL	51
-#define VV_LEN		52	/* number of v: vars */
+#define VV_OP		52
+#define VV_LEN		53	/* number of v: vars */
 
 #ifdef FEAT_CLIPBOARD
 
@@ -1755,16 +1772,6 @@
 # define stat(a,b) (access(a,0) ? -1 : stat(a,b))
 #endif
 
-#if (defined(FEAT_PROFILE) || defined(FEAT_RELTIME)) && !defined(PROTO)
-# ifdef WIN3264
-typedef LARGE_INTEGER proftime_T;
-# else
-typedef struct timeval proftime_T;
-# endif
-#else
-typedef int proftime_T;	    /* dummy for function prototypes */
-#endif
-
 #include "ex_cmds.h"	    /* Ex command defines */
 #include "proto.h"	    /* function prototypes */
 
diff -Naur vim71.orig/src/vimtutor vim71/src/vimtutor
--- vim71.orig/src/vimtutor	2004-06-07 14:32:27.000000000 +0000
+++ vim71/src/vimtutor	2008-02-14 21:07:31.000000000 +0000
@@ -39,18 +39,22 @@
 # remove the copy of the tutor on exit
 trap "rm -rf $TODELETE" 0 1 2 3 9 11 13 15
 
-# Vim could be called "vim" or "vi".  Also check for "vim6", for people who
-# have Vim 5.x installed as "vim" and Vim 6.0 as "vim6".
-testvim=`which vim6 2>/dev/null`
-if test -f "$testvim"; then
-	VIM=vim6
-else
-	testvim=`which vim`
+# Vim could be called "vim" or "vi".  Also check for "vimN", for people who
+# have Vim installed with its version number.
+# We anticipate up to a future Vim 8 version :-).
+seq="vim vim8 vim75 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi"
+for i in $seq; do
+	testvim=`which $i 2>/dev/null`
 	if test -f "$testvim"; then
-		VIM=vim
-	else
-		VIM=vi
+		VIM=$i
+		break
 	fi
+done
+
+# When no Vim version was found fall back to "vim", you'll get an error message
+# below.
+if test -z "$VIM"; then
+	VIM=vim
 fi
 
 # Use Vim to copy the tutor, it knows the value of $VIMRUNTIME
diff -Naur vim71.orig/src/window.c vim71/src/window.c
--- vim71.orig/src/window.c	2007-05-07 19:25:30.000000000 +0000
+++ vim71/src/window.c	2008-02-14 21:07:33.000000000 +0000
@@ -75,6 +75,7 @@
 static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
 
 #endif /* FEAT_WINDOWS */
+
 static win_T *win_alloc __ARGS((win_T *after));
 static void win_new_height __ARGS((win_T *, int));
 
@@ -583,7 +584,7 @@
 		++no_mapping;
 		++allow_keys;   /* no mapping for xchar, but allow key codes */
 		if (xchar == NUL)
-		    xchar = safe_vgetc();
+		    xchar = plain_vgetc();
 #ifdef FEAT_LANGMAP
 		LANGMAP_ADJUST(xchar, TRUE);
 #endif
@@ -732,7 +733,6 @@
     if (flags & WSP_VERT)
     {
 	layout = FR_ROW;
-	do_equal = (p_ea && new_size == 0 && *p_ead != 'v');
 
 	/*
 	 * Check if we are able to split the current window and compute its
@@ -769,16 +769,31 @@
 	 * instead, if possible. */
 	if (oldwin->w_p_wfw)
 	    win_setwidth_win(oldwin->w_width + new_size, oldwin);
+
+	/* Only make all windows the same width if one of them (except oldwin)
+	 * is wider than one of the split windows. */
+	if (!do_equal && p_ea && size == 0 && *p_ead != 'v'
+	   && oldwin->w_frame->fr_parent != NULL)
+	{
+	    frp = oldwin->w_frame->fr_parent->fr_child;
+	    while (frp != NULL)
+	    {
+		if (frp->fr_win != oldwin && frp->fr_win != NULL
+			&& (frp->fr_win->w_width > new_size
+			    || frp->fr_win->w_width > oldwin->w_width
+						   - new_size - STATUS_HEIGHT))
+		{
+		    do_equal = TRUE;
+		    break;
+		}
+		frp = frp->fr_next;
+	    }
+	}
     }
     else
 #endif
     {
 	layout = FR_COL;
-	do_equal = (p_ea && new_size == 0
-#ifdef FEAT_VERTSPLIT
-		&& *p_ead != 'h'
-#endif
-		);
 
 	/*
 	 * Check if we are able to split the current window and compute its
@@ -831,6 +846,29 @@
 	    if (need_status)
 		oldwin_height -= STATUS_HEIGHT;
 	}
+
+	/* Only make all windows the same height if one of them (except oldwin)
+	 * is higher than one of the split windows. */
+	if (!do_equal && p_ea && size == 0
+#ifdef FEAT_VERTSPLIT
+		&& *p_ead != 'h'
+#endif
+	   && oldwin->w_frame->fr_parent != NULL)
+	{
+	    frp = oldwin->w_frame->fr_parent->fr_child;
+	    while (frp != NULL)
+	    {
+		if (frp->fr_win != oldwin && frp->fr_win != NULL
+			&& (frp->fr_win->w_height > new_size
+			    || frp->fr_win->w_height > oldwin_height - new_size
+							      - STATUS_HEIGHT))
+		{
+		    do_equal = TRUE;
+		    break;
+		}
+		frp = frp->fr_next;
+	    }
+	}
     }
 
     /*
@@ -1253,7 +1291,7 @@
      * Don't execute autocommands while creating the windows.  Must do that
      * when putting the buffers in the windows.
      */
-    ++autocmd_block;
+    block_autocmds();
 #endif
 
     /* todo is number of windows left to create */
@@ -1275,7 +1313,7 @@
 	}
 
 #ifdef FEAT_AUTOCMD
-    --autocmd_block;
+    unblock_autocmds();
 #endif
 
     /* return actual number of windows */
@@ -2120,7 +2158,7 @@
 	if (wp->w_p_pvw || bt_quickfix(wp->w_buffer))
 	{
 	    /*
-	     * The cursor goes to the preview or the quickfix window, try
+	     * If the cursor goes to the preview or the quickfix window, try
 	     * finding another window to go to.
 	     */
 	    for (;;)
@@ -2307,7 +2345,6 @@
     frame_T	*frp, *frp2, *frp3;
     frame_T	*frp_close = win->w_frame;
     win_T	*wp;
-    int		old_size = 0;
 
     /*
      * If there is only one window there is nothing to remove.
@@ -2328,33 +2365,77 @@
     if (frp_close->fr_parent->fr_layout == FR_COL)
     {
 #endif
-	/* When 'winfixheight' is set, remember its old size and restore
-	 * it later (it's a simplistic solution...).  Don't do this if the
-	 * window will occupy the full height of the screen. */
-	if (frp2->fr_win != NULL
-		&& (frp2->fr_next != NULL || frp2->fr_prev != NULL)
-		&& frp2->fr_win->w_p_wfh)
-	    old_size = frp2->fr_win->w_height;
+	/* When 'winfixheight' is set, try to find another frame in the column
+	 * (as close to the closed frame as possible) to distribute the height
+	 * to. */
+	if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfh)
+	{
+	    frp = frp_close->fr_prev;
+	    frp3 = frp_close->fr_next;
+	    while (frp != NULL || frp3 != NULL)
+	    {
+		if (frp != NULL)
+		{
+		    if (frp->fr_win != NULL && !frp->fr_win->w_p_wfh)
+		    {
+			frp2 = frp;
+			wp = frp->fr_win;
+			break;
+		    }
+		    frp = frp->fr_prev;
+		}
+		if (frp3 != NULL)
+		{
+		    if (frp3->fr_win != NULL && !frp3->fr_win->w_p_wfh)
+		    {
+			frp2 = frp3;
+			wp = frp3->fr_win;
+			break;
+		    }
+		    frp3 = frp3->fr_next;
+		}
+	    }
+	}
 	frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
 			    frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
-	if (old_size != 0)
-	    win_setheight_win(old_size, frp2->fr_win);
 #ifdef FEAT_VERTSPLIT
 	*dirp = 'v';
     }
     else
     {
-	/* When 'winfixwidth' is set, remember its old size and restore
-	 * it later (it's a simplistic solution...).  Don't do this if the
-	 * window will occupy the full width of the screen. */
-	if (frp2->fr_win != NULL
-		&& (frp2->fr_next != NULL || frp2->fr_prev != NULL)
-		&& frp2->fr_win->w_p_wfw)
-	    old_size = frp2->fr_win->w_width;
+	/* When 'winfixwidth' is set, try to find another frame in the column
+	 * (as close to the closed frame as possible) to distribute the width
+	 * to. */
+	if (frp2->fr_win != NULL && frp2->fr_win->w_p_wfw)
+	{
+	    frp = frp_close->fr_prev;
+	    frp3 = frp_close->fr_next;
+	    while (frp != NULL || frp3 != NULL)
+	    {
+		if (frp != NULL)
+		{
+		    if (frp->fr_win != NULL && !frp->fr_win->w_p_wfw)
+		    {
+			frp2 = frp;
+			wp = frp->fr_win;
+			break;
+		    }
+		    frp = frp->fr_prev;
+		}
+		if (frp3 != NULL)
+		{
+		    if (frp3->fr_win != NULL && !frp3->fr_win->w_p_wfw)
+		    {
+			frp2 = frp3;
+			wp = frp3->fr_win;
+			break;
+		    }
+		    frp3 = frp3->fr_next;
+		}
+	    }
+	}
 	frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
 			    frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
-	if (old_size != 0)
-	    win_setwidth_win(old_size, frp2->fr_win);
 	*dirp = 'h';
     }
 #endif
@@ -3334,7 +3415,7 @@
      * Don't execute autocommands while creating the tab pages.  Must do that
      * when putting the buffers in the windows.
      */
-    ++autocmd_block;
+    block_autocmds();
 #endif
 
     for (todo = count - 1; todo > 0; --todo)
@@ -3342,7 +3423,7 @@
 	    break;
 
 #ifdef FEAT_AUTOCMD
-    --autocmd_block;
+    unblock_autocmds();
 #endif
 
     /* return actual number of tab pages */
@@ -4081,7 +4162,7 @@
 	/* Don't execute autocommands while the window is not properly
 	 * initialized yet.  gui_create_scrollbar() may trigger a FocusGained
 	 * event. */
-	++autocmd_block;
+	block_autocmds();
 #endif
 	/*
 	 * link the window in the window list
@@ -4126,7 +4207,11 @@
 	foldInitWin(newwin);
 #endif
 #ifdef FEAT_AUTOCMD
-	--autocmd_block;
+	unblock_autocmds();
+#endif
+#ifdef FEAT_SEARCH_EXTRA
+	newwin->w_match_head = NULL;
+	newwin->w_next_match_id = 4;
 #endif
     }
     return newwin;
@@ -4147,7 +4232,7 @@
 #ifdef FEAT_AUTOCMD
     /* Don't execute autocommands while the window is halfway being deleted.
      * gui_mch_destroy_scrollbar() may trigger a FocusGained event. */
-    ++autocmd_block;
+    block_autocmds();
 #endif
 
 #ifdef FEAT_MZSCHEME
@@ -4185,11 +4270,11 @@
 	vim_free(wp->w_tagstack[i].tagname);
 
     vim_free(wp->w_localdir);
+
 #ifdef FEAT_SEARCH_EXTRA
-    vim_free(wp->w_match[0].regprog);
-    vim_free(wp->w_match[1].regprog);
-    vim_free(wp->w_match[2].regprog);
+    clear_matches(wp);
 #endif
+
 #ifdef FEAT_JUMPLIST
     free_jumplist(wp);
 #endif
@@ -4210,7 +4295,7 @@
     vim_free(wp);
 
 #ifdef FEAT_AUTOCMD
-    --autocmd_block;
+    unblock_autocmds();
 #endif
 }
 
@@ -5438,6 +5523,7 @@
 		{
 		    EMSG(_(e_noroom));
 		    p_ch = old_p_ch;
+		    curtab->tp_ch_used = p_ch;
 		    cmdline_row = Rows - p_ch;
 		    break;
 		}
@@ -6174,3 +6260,175 @@
     return FALSE;
 }
 #endif
+
+#if defined(FEAT_SEARCH_EXTRA) || defined(PROTO)
+/*
+ * Add match to the match list of window 'wp'.  The pattern 'pat' will be
+ * highligted with the group 'grp' with priority 'prio'.
+ * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
+ * If no particular ID is desired, -1 must be specified for 'id'.
+ * Return ID of added match, -1 on failure.
+ */
+    int
+match_add(wp, grp, pat, prio, id)
+    win_T	*wp;
+    char_u	*grp;
+    char_u	*pat;
+    int		prio;
+    int		id;
+{
+    matchitem_T *cur;
+    matchitem_T *prev;
+    matchitem_T *m;
+    int		hlg_id;
+    regprog_T	*regprog;
+
+    if (*grp == NUL || *pat == NUL)
+	return -1;
+    if (id < -1 || id == 0)
+    {
+	EMSGN("E799: Invalid ID: %ld (must be greater than or equal to 1)", id);
+	return -1;
+    }
+    if (id != -1)
+    {
+	cur = wp->w_match_head;
+	while (cur != NULL)
+	{
+	    if (cur->id == id)
+	    {
+		EMSGN("E801: ID already taken: %ld", id);
+		return -1;
+	    }
+	    cur = cur->next;
+	}
+    }
+    if ((hlg_id = syn_namen2id(grp, STRLEN(grp))) == 0)
+    {
+	EMSG2(_(e_nogroup), grp);
+	return -1;
+    }
+    if ((regprog = vim_regcomp(pat, RE_MAGIC)) == NULL)
+    {
+	EMSG2(_(e_invarg2), pat);
+	return -1;
+    }
+
+    /* Find available match ID. */
+    while (id == -1)
+    {
+	cur = wp->w_match_head;
+	while (cur != NULL && cur->id != wp->w_next_match_id)
+	    cur = cur->next;
+	if (cur == NULL)
+	    id = wp->w_next_match_id;
+	wp->w_next_match_id++;
+    }
+
+    /* Build new match. */
+    m = (matchitem_T *)alloc(sizeof(matchitem_T));
+    m->id = id;
+    m->priority = prio;
+    m->pattern = vim_strsave(pat);
+    m->hlg_id = hlg_id;
+    m->match.regprog = regprog;
+    m->match.rmm_ic = FALSE;
+    m->match.rmm_maxcol = 0;
+
+    /* Insert new match.  The match list is in ascending order with regard to
+     * the match priorities. */
+    cur = wp->w_match_head;
+    prev = cur;
+    while (cur != NULL && prio >= cur->priority)
+    {
+	prev = cur;
+	cur = cur->next;
+    }
+    if (cur == prev)
+	wp->w_match_head = m;
+    else
+	prev->next = m;
+    m->next = cur;
+
+    redraw_later(SOME_VALID);
+    return id;
+}
+
+/*
+ * Delete match with ID 'id' in the match list of window 'wp'.
+ * Print error messages if 'perr' is TRUE.
+ */
+    int
+match_delete(wp, id, perr)
+    win_T	*wp;
+    int		id;
+    int		perr;
+{
+    matchitem_T *cur = wp->w_match_head;
+    matchitem_T *prev = cur;
+
+    if (id < 1)
+    {
+	if (perr == TRUE)
+	    EMSGN("E802: Invalid ID: %ld (must be greater than or equal to 1)",
+									  id);
+	return -1;
+    }
+    while (cur != NULL && cur->id != id)
+    {
+	prev = cur;
+	cur = cur->next;
+    }
+    if (cur == NULL)
+    {
+	if (perr == TRUE)
+	    EMSGN("E803: ID not found: %ld", id);
+	return -1;
+    }
+    if (cur == prev)
+	wp->w_match_head = cur->next;
+    else
+	prev->next = cur->next;
+    vim_free(cur->match.regprog);
+    vim_free(cur->pattern);
+    vim_free(cur);
+    redraw_later(SOME_VALID);
+    return 0;
+}
+
+/*
+ * Delete all matches in the match list of window 'wp'.
+ */
+    void
+clear_matches(wp)
+    win_T	*wp;
+{
+    matchitem_T *m;
+
+    while (wp->w_match_head != NULL)
+    {
+	m = wp->w_match_head->next;
+	vim_free(wp->w_match_head->match.regprog);
+	vim_free(wp->w_match_head->pattern);
+	vim_free(wp->w_match_head);
+	wp->w_match_head = m;
+    }
+    redraw_later(SOME_VALID);
+}
+
+/*
+ * Get match from ID 'id' in window 'wp'.
+ * Return NULL if match not found.
+ */
+    matchitem_T *
+get_match(wp, id)
+    win_T	*wp;
+    int		id;
+{
+    matchitem_T *cur = wp->w_match_head;
+
+    while (cur != NULL && cur->id != id)
+	cur = cur->next;
+    return cur;
+}
+#endif
diff -Naur vim71.orig/src/xxd/xxd.c vim71/src/xxd/xxd.c
--- vim71.orig/src/xxd/xxd.c	2007-05-07 19:41:57.000000000 +0000
+++ vim71/src/xxd/xxd.c	2008-02-14 21:07:33.000000000 +0000
@@ -212,7 +212,7 @@
 
 #define TRY_SEEK	/* attempt to use lseek, or skip forward by reading */
 #define COLS 256	/* change here, if you ever need more columns */
-#define LLEN (9 + (5*COLS-1)/2 + 2 + COLS)
+#define LLEN (11 + (9*COLS-1)/1 + COLS + 2)
 
 char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa;
 
@@ -590,7 +590,8 @@
       default:			octspergrp = 0; break;
       }
 
-  if (cols < 1 || (!hextype && (cols > COLS)))
+  if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS)
+							    && (cols > COLS)))
     {
       fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS);
       exit(1);
@@ -750,6 +751,7 @@
 	}
       if (ebcdic)
 	e = (e < 64) ? '.' : etoa64[e-64];
+      /* When changing this update definition of LLEN above. */
       l[11 + (grplen * cols - 1)/octspergrp + p] =
 #ifdef __MVS__
 	  (e >= 64)
