Submitted By: Jim Gifford (jim at linuxfromscratch dot org)
Date: 06-18-2008
Initial Package Version: 7.1
Origin: Upstream
Upstream Status: Applied
Description: Contains all upstream patches up to 7.1.315
             The following patches were skipped
             003 007 041 065 070 072 080 088 091 092 124 126 128 129 134 146 158 168 196 204 275 278 280 282 283 285 312

diff -Naur vim71.orig/Filelist vim71/Filelist
--- vim71.orig/Filelist	2007-05-06 11:00:23.000000000 -0400
+++ vim71/Filelist	2008-06-18 06:56:41.000000000 -0400
@@ -193,6 +193,7 @@
 		src/vim_icon.xbm \
 		src/vim_mask.xbm \
 		src/vimtutor \
+		src/gvimtutor \
 		src/which.sh \
 		src/workshop.c \
 		src/workshop.h \
diff -Naur vim71.orig/runtime/autoload/gzip.vim vim71/runtime/autoload/gzip.vim
--- vim71.orig/runtime/autoload/gzip.vim	2007-05-10 07:40:14.000000000 -0400
+++ vim71/runtime/autoload/gzip.vim	2008-06-18 06:56:50.000000000 -0400
@@ -1,6 +1,6 @@
 " Vim autoload file for editing compressed files.
 " Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2007 May 10
+" Last Change: 2008 May 29
 
 " These functions are used by the gzip plugin.
 
@@ -73,8 +73,15 @@
   let empty = line("'[") == 1 && line("']") == line("$")
   let tmp = tempname()
   let tmpe = tmp . "." . expand("<afile>:e")
+  if exists('*fnameescape')
+    let tmp_esc = fnameescape(tmp)
+    let tmpe_esc = fnameescape(tmpe)
+  else
+    let tmp_esc = escape(tmp, ' ')
+    let tmpe_esc = escape(tmpe, ' ')
+  endif
   " write the just read lines to a temp file "'[,']w tmp.gz"
-  execute "silent '[,']w " . escape(tmpe, ' ')
+  execute "silent '[,']w " . tmpe_esc
   " uncompress the temp file: call system("gzip -dn tmp.gz")
   call system(a:cmd . " " . s:escape(tmpe))
   if !filereadable(tmp)
@@ -95,12 +102,12 @@
     setlocal nobin
     if exists(":lockmarks")
       if empty
-	execute "silent lockmarks " . l . "r ++edit " . tmp
+	execute "silent lockmarks " . l . "r ++edit " . tmp_esc
       else
-	execute "silent lockmarks " . l . "r " . tmp
+	execute "silent lockmarks " . l . "r " . tmp_esc
       endif
     else
-      execute "silent " . l . "r " . tmp
+      execute "silent " . l . "r " . tmp_esc
     endif
 
     " if buffer became empty, delete trailing blank line
@@ -110,8 +117,8 @@
     endif
     " delete the temp file and the used buffers
     call delete(tmp)
-    silent! exe "bwipe " . tmp
-    silent! exe "bwipe " . tmpe
+    silent! exe "bwipe " . tmp_esc
+    silent! exe "bwipe " . tmpe_esc
   endif
 
   " Restore saved option values.
@@ -124,10 +131,15 @@
 
   " When uncompressed the whole buffer, do autocommands
   if ok && empty
+    if exists('*fnameescape')
+      let fname = fnameescape(expand("%:r"))
+    else
+      let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
+    endif
     if &verbose >= 8
-      execute "doau BufReadPost " . expand("%:r")
+      execute "doau BufReadPost " . fname
     else
-      execute "silent! doau BufReadPost " . expand("%:r")
+      execute "silent! doau BufReadPost " . fname
     endif
   endif
 endfun
diff -Naur vim71.orig/runtime/doc/Makefile vim71/runtime/doc/Makefile
--- vim71.orig/runtime/doc/Makefile	2006-11-07 15:59:05.000000000 -0500
+++ vim71/runtime/doc/Makefile	2008-06-18 06:55:02.000000000 -0400
@@ -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 06:18:46.000000000 -0400
+++ vim71/runtime/doc/change.txt	2008-06-18 06:51:08.000000000 -0400
@@ -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 06:18:46.000000000 -0400
+++ vim71/runtime/doc/cmdline.txt	2008-06-18 06:54:39.000000000 -0400
@@ -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 06:18:46.000000000 -0400
+++ vim71/runtime/doc/eval.txt	2008-06-18 06:56:43.000000000 -0400
@@ -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 May 28
 
 
 		  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
@@ -1594,6 +1609,7 @@
 				String	find directory {name} in {path}
 findfile( {name}[, {path}[, {count}]])
 				String	find file {name} in {path}
+fnameescape( {fname})		String	escape special characters in {fname}
 fnamemodify( {fname}, {mods})	String	modify file name
 foldclosed( {lnum})		Number	first line of fold at {lnum} if closed
 foldclosedend( {lnum})		Number	last line of fold at {lnum} if closed
@@ -1602,7 +1618,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 +1638,8 @@
 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
+getpid()			Number	process ID of Vim
 getpos( {expr})			List	position of cursor, mark, etc.
 getqflist()			List	list of quickfix items
 getreg( [{regname} [, 1]])	String	contents of register
@@ -1676,7 +1694,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 +1735,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 +1753,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 +1788,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 +2036,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 +2048,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()|.
@@ -2589,6 +2621,19 @@
 <		Searches from the directory of the current file upwards until
 		it finds the file "tags.vim".
 
+fnameescape({string})					*fnameescape()*
+		Escape {string} for use as file name command argument.  All
+		characters that have a special meaning, such as '%' and '|'
+		are escaped with a backslash.
+		For most systems the characters escaped are "".  For systems
+		where a backslash appears in a filename, it depends on the
+		value of 'isfname'.
+		Example: >
+			:let fname = 'some str%nge|name'
+			:exe "edit " . fnameescape(fname)
+<		results in executing: >
+			edit some\ str\%nge\|name
+
 fnamemodify({fname}, {mods})				*fnamemodify()*
 		Modify file name {fname} according to {mods}.  {mods} is a
 		string of characters like it is used for file names on the
@@ -2659,7 +2704,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 +2714,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 +2872,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 +2962,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 +3688,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 +3735,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
@@ -3731,6 +3848,10 @@
 		characters.  nr2char(0) is a real NUL and terminates the
 		string, thus results in an empty string.
 
+							*getpid()*
+getpid()	Return a Number which is the process ID of the Vim process.
+		On Unix this is a unique number.  On MS-DOS it's always zero.
+
 							*getpos()*
 getpos({expr})	Get the position for {expr}.  For possible values of {expr}
 		see |line()|.
@@ -4112,7 +4233,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 +4261,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 +4331,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 +4367,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 +4413,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 +4425,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 +4510,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 +4542,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 +4985,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 +5176,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/options.txt vim71/runtime/doc/options.txt
--- vim71.orig/runtime/doc/options.txt	2007-05-12 06:18:47.000000000 -0400
+++ vim71/runtime/doc/options.txt	2008-06-18 06:56:16.000000000 -0400
@@ -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: 2008 Feb 24
 
 
 		  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
@@ -4873,7 +4878,7 @@
 	|autocmd-osfiletypes|
 
 						*'paragraphs'* *'para'*
-'paragraphs' 'para'	string	(default "IPLPPPQPP LIpplpipbp")
+'paragraphs' 'para'	string	(default "IPLPPPQPP TPHPLIPpLpItpplpipbp")
 			global
 	Specifies the nroff macros that separate paragraphs.  These are pairs
 	of two letters (see |object-motions|).
@@ -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 06:18:47.000000000 -0400
+++ vim71/runtime/doc/pattern.txt	2008-06-18 06:51:23.000000000 -0400
@@ -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 06:18:47.000000000 -0400
+++ vim71/runtime/doc/pi_paren.txt	2008-06-18 06:52:15.000000000 -0400
@@ -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/usr_41.txt vim71/runtime/doc/usr_41.txt
--- vim71.orig/runtime/doc/usr_41.txt	2007-05-12 06:18:48.000000000 -0400
+++ vim71/runtime/doc/usr_41.txt	2008-06-18 06:51:23.000000000 -0400
@@ -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 06:18:48.000000000 -0400
+++ vim71/runtime/doc/various.txt	2008-06-18 06:55:02.000000000 -0400
@@ -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/vimtutor.1 vim71/runtime/doc/vimtutor.1
--- vim71.orig/runtime/doc/vimtutor.1	2004-06-07 10:32:40.000000000 -0400
+++ vim71/runtime/doc/vimtutor.1	2008-06-18 06:56:38.000000000 -0400
@@ -3,7 +3,7 @@
 vimtutor \- the Vim tutor
 .SH SYNOPSIS
 .br
-.B vimtutor [language]
+.B vimtutor [-g] [language]
 .SH DESCRIPTION
 .B Vimtutor
 starts the
@@ -18,6 +18,9 @@
 .B Vim
 commands.
 .PP
+The optional argument -g starts vimtutor with gvim rather than vim, if the
+GUI version of vim is available, or falls back to Vim if gvim is not found.
+.PP
 The optional [language] argument is the two-letter name of a language, like
 "it" or "es".
 If the [language] argument is missing, the language of the current locale will
diff -Naur vim71.orig/runtime/doc/windows.txt vim71/runtime/doc/windows.txt
--- vim71.orig/runtime/doc/windows.txt	2007-05-12 06:18:49.000000000 -0400
+++ vim71/runtime/doc/windows.txt	2008-06-18 06:51:59.000000000 -0400
@@ -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 11:14:37.000000000 -0400
+++ vim71/runtime/filetype.vim	2008-06-18 06:56:44.000000000 -0400
@@ -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")
@@ -16,20 +16,23 @@
 augroup filetypedetect
 
 " Ignored extensions
+if exists("*fnameescape")
 au BufNewFile,BufRead ?\+.orig,?\+.bak,?\+.old,?\+.new,?\+.rpmsave,?\+.rpmnew
-	\ exe "doau filetypedetect BufRead " . expand("<afile>:r")
+	\ exe "doau filetypedetect BufRead " . fnameescape(expand("<afile>:r"))
 au BufNewFile,BufRead *~
 	\ let s:name = expand("<afile>") |
 	\ let s:short = substitute(s:name, '\~$', '', '') |
 	\ if s:name != s:short && s:short != "" |
-	\   exe "doau filetypedetect BufRead " . s:short |
+	\   exe "doau filetypedetect BufRead " . fnameescape(s:short) |
 	\ endif |
-	\ unlet s:name |
-	\ unlet s:short
+	\ unlet s:name s:short
 au BufNewFile,BufRead ?\+.in
 	\ if expand("<afile>:t") != "configure.in" |
-	\   exe "doau filetypedetect BufRead " . expand("<afile>:r") |
+	\   exe "doau filetypedetect BufRead " . fnameescape(expand("<afile>:r")) |
 	\ endif
+elseif &verbose > 0
+  echomsg "Warning: some filetypes will not be recognized because this version of Vim does not have fnameescape()"
+endif
 
 " Pattern used to match file names which should not be inspected.
 " Currently finds compressed files.
@@ -187,7 +190,7 @@
   let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
 	\" ".getline(5)." "
   if head =~ '\sasmsyntax=\S\+\s'
-    let b:asmsyntax = substitute(head, '.*\sasmsyntax=\(\S\+\)\s.*','\1', "")
+    let b:asmsyntax = substitute(head, '.*\sasmsyntax=\([a-zA-Z0-9]\+\)\s.*','\1', "")
   elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
     let b:asmsyntax = "vmasm"
   endif
@@ -1286,7 +1289,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/indent.vim vim71/runtime/indent.vim
--- vim71.orig/runtime/indent.vim	2006-02-01 03:54:35.000000000 -0500
+++ vim71/runtime/indent.vim	2008-06-18 06:55:58.000000000 -0400
@@ -1,7 +1,7 @@
 " Vim support file to switch on loading indent files for file types
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2005 Mar 28
+" Last Change:	2008 Feb 22
 
 if exists("did_indent_on")
   finish
@@ -15,11 +15,17 @@
       exe b:undo_indent
       unlet! b:undo_indent b:did_indent
     endif
-    if expand("<amatch>") != ""
+    let s = expand("<amatch>")
+    if s != ""
       if exists("b:did_indent")
 	unlet b:did_indent
       endif
-      runtime! indent/<amatch>.vim
+
+      " When there is a dot it is used to separate filetype names.  Thus for
+      " "aaa.bbb" load "indent/aaa.vim" and then "indent/bbb.vim".
+      for name in split(s, '\.')
+	exe 'runtime! indent/' . name . '.vim'
+      endfor
     endif
   endfunc
 augroup END
diff -Naur vim71.orig/runtime/menu.vim vim71/runtime/menu.vim
--- vim71.orig/runtime/menu.vim	2007-01-09 08:31:40.000000000 -0500
+++ vim71/runtime/menu.vim	2008-06-18 06:53:55.000000000 -0400
@@ -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/optwin.vim vim71/runtime/optwin.vim
--- vim71.orig/runtime/optwin.vim	2006-10-10 17:06:34.000000000 -0400
+++ vim71/runtime/optwin.vim	2008-06-18 06:56:54.000000000 -0400
@@ -1,7 +1,7 @@
 " These commands create the option window.
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2006 Oct 10
+" Last Change:	2008 May 12
 
 " If there already is an option window, jump to that one.
 if bufwinnr("option-window") > 0
@@ -147,7 +147,7 @@
 
 " Open the window
 new option-window
-setlocal ts=15 tw=0
+setlocal ts=15 tw=0 noro
 
 " Insert help and a "set" command for each option.
 call append(0, '" Each "set" line shows the current value of an option (on the left).')
@@ -350,6 +350,10 @@
 call append("$", " \tset lines=" . &lines)
 call append("$", "lazyredraw\tdon't redraw while executing macros")
 call <SID>BinOptionG("lz", &lz)
+if has("reltime")
+  call append("$", "redrawtime\ttimeout for 'hlsearch' and :match highlighting in msec")
+  call append("$", " \tset rdt=" . &rdt)
+endif
 call append("$", "writedelay\tdelay in msec for each char written to the display")
 call append("$", "\t(for debugging)")
 call append("$", " \tset wd=" . &wd)
diff -Naur vim71.orig/runtime/plugin/matchparen.vim vim71/runtime/plugin/matchparen.vim
--- vim71.orig/runtime/plugin/matchparen.vim	2006-10-12 16:05:05.000000000 -0400
+++ vim71/runtime/plugin/matchparen.vim	2008-06-18 06:56:05.000000000 -0400
@@ -1,6 +1,6 @@
 " Vim plugin for showing matching parens
 " Maintainer:  Bram Moolenaar <Bram@vim.org>
-" Last Change: 2006 Oct 12
+" Last Change: 2008 Feb 27
 
 " 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.
@@ -34,7 +34,8 @@
   endif
 
   " Avoid that we remove the popup menu.
-  if pumvisible()
+  " Return when there are no colors (looks like the cursor jumps).
+  if pumvisible() || (&t_Co < 8 && !has("gui_running"))
     return
   endif
 
@@ -60,27 +61,13 @@
   endif
 
   " 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)
   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)])
-    else
-      let stopline = min([line('w$'), c_lnum + 100])
-    endif
   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)])
-    else
-      let stopline = max([line('w0'), c_lnum - 100])
-    endif
   endif
   if c == '['
     let c = '\['
@@ -99,14 +86,56 @@
 	\ '=~?  "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)
+  " Limit the search to lines visible in the window.
+  let stoplinebottom = line('w$')
+  let stoplinetop = line('w0')
+  if i % 2 == 0
+    let stopline = stoplinebottom
+  else
+    let stopline = stoplinetop
+  endif
+
+  try
+    " Limit the search time to 300 msec to avoid a hang on very long lines.
+    " This fails when a timeout is not supported.
+    let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 300)
+  catch /E118/
+    " Can't use the timeout, restrict the stopline a bit more to avoid taking
+    " a long time on 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
+    if i % 2 == 0
+      if has("byte_offset") && has("syntax_items") && &smc > 0
+	let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2])
+	let stopline = min([bottom_viewable, byte2line(stopbyte)])
+      else
+	let stopline = min([bottom_viewable, c_lnum + 100])
+      endif
+      let stoplinebottom = stopline
+    else
+      if has("byte_offset") && has("syntax_items") && &smc > 0
+	let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2])
+	let stopline = max([top_viewable, byte2line(stopbyte)])
+      else
+	let stopline = max([top_viewable, c_lnum - 100])
+      endif
+      let stoplinetop = stopline
+    endif
+    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 +143,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 07:57:13.000000000 -0400
+++ vim71/src/Makefile	2008-06-18 06:56:55.000000000 -0400
@@ -545,7 +545,7 @@
 # For unknown reasons adding "-lc" fixes a linking problem with GCC.  That's
 # probably a bug in the "-pg" implementation.
 # Need to recompile everything after changing this: "make clean" "make".
-#PROFILE_CFLAGS = -pg -g
+#PROFILE_CFLAGS = -pg -g -DWE_ARE_PROFILING
 #PROFILE_LIBS = -pg
 #PROFILE_LIBS = -pg -lc
 
@@ -780,6 +780,8 @@
 # 1) make config
 # 2) edit auto/config.mk, add -n32 to LDFLAGS
 # 3) make
+#
+#Alternatively: use -o32 instead of -n32.
 ###
 
 ### (C)  On SCO Unix v3.2.5 (and probably other versions) the termcap library,
@@ -1074,7 +1076,7 @@
 # default vi editor, it will create a link from vi to Vim when doing
 # "make install".  An existing file will be overwritten!
 # When not using it, some make programs can't handle an undefined $(LINKIT).
-#LINKIT = -ln -f -s $(BINDIR)/$(VIMTARGET) /usr/bin/vi
+#LINKIT = ln -f -s $(DEST_BIN)/$(VIMTARGET) $(DESTDIR)/usr/bin/vi
 LINKIT = @echo >/dev/null
 
 ###
@@ -1290,6 +1292,9 @@
 
 DEPEND_CFLAGS = -DPROTO -DDEPEND -DFEAT_GUI $(LINT_CFLAGS)
 
+# If you have problems with flags that cproto doesn't support, and you are
+# using GNU make, you can try using the other line to filter out arguments.
+#PFLAGS = $(PROTO_FLAGS) -DPROTO $(filter -D% -I%, $(LINT_CFLAGS))
 PFLAGS = $(PROTO_FLAGS) -DPROTO $(LINT_CFLAGS)
 
 ALL_LIB_DIRS = $(GUI_LIBS_DIR) $(X_LIBS_DIR)
@@ -1867,6 +1872,8 @@
 installtutorbin: $(DEST_VIM)
 	$(INSTALL_DATA) vimtutor $(DEST_BIN)/$(VIMNAME)tutor
 	chmod $(SCRIPTMOD) $(DEST_BIN)/$(VIMNAME)tutor
+	$(INSTALL_DATA) gvimtutor $(DEST_BIN)/$(GVIMNAME)tutor
+	chmod $(SCRIPTMOD) $(DEST_BIN)/$(GVIMNAME)tutor
 
 installtutor: $(DEST_RT) $(DEST_TUTOR)
 	-$(INSTALL_DATA) $(TUTORSOURCE)/README* $(TUTORSOURCE)/tutor* $(DEST_TUTOR)
@@ -2075,6 +2082,7 @@
 uninstall: uninstall_runtime
 	-rm -f $(DEST_BIN)/$(VIMTARGET)
 	-rm -f $(DEST_BIN)/vimtutor
+	-rm -f $(DEST_BIN)/gvimtutor
 	-rm -f $(DEST_BIN)/$(EXTARGET) $(DEST_BIN)/$(VIEWTARGET)
 	-rm -f $(DEST_BIN)/$(GVIMTARGET) $(DEST_BIN)/$(GVIEWTARGET)
 	-rm -f $(DEST_BIN)/$(RVIMTARGET) $(DEST_BIN)/$(RVIEWTARGET)
@@ -2171,7 +2179,7 @@
 
 shadow:	runtime pixmaps
 	mkdir $(SHADOWDIR)
-	cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../vimtutor ../mkinstalldirs .
+	cd $(SHADOWDIR); ln -s ../*.[ch] ../*.in ../*.sh ../*.xs ../*.xbm ../toolcheck ../proto ../po ../vimtutor ../gvimtutor ../mkinstalldirs .
 	mkdir $(SHADOWDIR)/auto
 	cd $(SHADOWDIR)/auto; ln -s ../../auto/configure .
 	cd $(SHADOWDIR); rm -f auto/link.sed
@@ -2190,7 +2198,7 @@
 	cd $(SHADOWDIR)/testdir; ln -s ../../testdir/Makefile \
 				 ../../testdir/vimrc.unix \
 				 ../../testdir/*.in \
-				 ../../testdir/unix.vim \
+				 ../../testdir/*.vim \
 				 ../../testdir/*.ok .
 
 # Link needed for doing "make install" in a shadow directory.
@@ -2559,8 +2567,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 07:49:09.000000000 -0400
+++ vim71/src/auto/configure	2008-06-18 06:56:39.000000000 -0400
@@ -845,6 +845,7 @@
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --disable-darwin        Disable Darwin (Mac OS X) support.
+  --disable-selinux	  Don't check for SELinux support.
   --disable-xsmp          Disable XSMP session management
   --disable-xsmp-interact Disable XSMP interaction
   --enable-mzschemeinterp   Include MzScheme interpreter.
@@ -3611,6 +3612,94 @@
 esac
 fi
 
+echo "$as_me:$LINENO: checking --disable-selinux argument" >&5
+echo $ECHO_N "checking --disable-selinux argument... $ECHO_C" >&6
+# Check whether --enable-selinux or --disable-selinux was given.
+if test "${enable_selinux+set}" = set; then
+  enableval="$enable_selinux"
+
+else
+  enable_selinux="yes"
+fi;
+if test "$enable_selinux" = "yes"; then
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
+echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6
+if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char is_selinux_enabled ();
+int
+main ()
+{
+is_selinux_enabled ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_selinux_is_selinux_enabled=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_selinux_is_selinux_enabled=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5
+echo "${ECHO_T}$ac_cv_lib_selinux_is_selinux_enabled" >&6
+if test $ac_cv_lib_selinux_is_selinux_enabled = yes; then
+  LIBS="$LIBS -lselinux"
+	   cat >>confdefs.h <<\_ACEOF
+#define HAVE_SELINUX 1
+_ACEOF
+
+fi
+
+else
+   echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+fi
 
 
 echo "$as_me:$LINENO: checking --with-features argument" >&5
@@ -3843,7 +3932,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 +4534,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 +4578,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
@@ -4625,10 +4758,11 @@
       echo "$as_me:$LINENO: checking for location of Tcl include" >&5
 echo $ECHO_N "checking for location of Tcl include... $ECHO_C" >&6
       if test "x$MACOSX" != "xyes"; then
-	tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include"
+	tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include /usr/include/tcl$tclver"
       else
 		tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
       fi
+      TCL_INC=
       for try in $tclinc; do
 	if test -f "$try/tcl.h"; then
 	  echo "$as_me:$LINENO: result: $try/tcl.h" >&5
@@ -4647,6 +4781,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 +4801,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 +10399,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 +14349,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 11:25:59.000000000 -0400
+++ vim71/src/buffer.c	2008-06-18 06:56:11.000000000 -0400
@@ -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
@@ -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;
 
@@ -4898,7 +4912,7 @@
     return retval;
 }
 
-#ifdef FEAT_VIMINFO
+#if defined(FEAT_VIMINFO) || defined(PROTO)
     int
 read_viminfo_bufferlist(virp, writing)
     vir_T	*virp;
@@ -5022,13 +5036,14 @@
 #if defined(FEAT_QUICKFIX) && defined(FEAT_WINDOWS)
     if (bt_quickfix(buf))
     {
-	win_T	*win;
+	win_T	    *win = NULL;
+	tabpage_T   *tp;
 
 	/*
 	 * For location list window, w_llist_ref points to the location list.
 	 * For quickfix window, w_llist_ref is NULL.
 	 */
-	FOR_ALL_WINDOWS(win)
+	FOR_ALL_TAB_WINDOWS(tp, win)
 	    if (win->w_buffer == buf)
 		break;
 	if (win != NULL && win->w_llist_ref != NULL)
@@ -5507,11 +5522,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 16:10:37.000000000 -0400
+++ vim71/src/charset.c	2008-06-18 06:55:55.000000000 -0400
@@ -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.
@@ -1270,7 +1290,8 @@
 		    /* If a double-cell char doesn't fit at the end of a line
 		     * it wraps to the next line, it's like this char is three
 		     * cells wide. */
-		    if (incr == 2 && wp->w_p_wrap && in_win_border(wp, vcol))
+		    if (incr == 2 && wp->w_p_wrap && MB_BYTE2LEN(*ptr) > 1
+			    && in_win_border(wp, vcol))
 		    {
 			++incr;
 			head = 1;
@@ -1898,7 +1919,7 @@
 {
     for ( ; *p; ++p)
 	if (rem_backslash(p))
-	    STRCPY(p, p + 1);
+	    mch_memmove(p, p + 1, STRLEN(p));
 }
 
 /*
diff -Naur vim71.orig/src/config.h.in vim71/src/config.h.in
--- vim71.orig/src/config.h.in	2007-04-26 10:40:34.000000000 -0400
+++ vim71/src/config.h.in	2008-06-18 06:56:39.000000000 -0400
@@ -155,6 +155,7 @@
 #undef HAVE_READLINK
 #undef HAVE_RENAME
 #undef HAVE_SELECT
+#undef HAVE_SELINUX
 #undef HAVE_SETENV
 #undef HAVE_SETPGID
 #undef HAVE_SETSID
diff -Naur vim71.orig/src/configure.in vim71/src/configure.in
--- vim71.orig/src/configure.in	2007-05-12 05:19:27.000000000 -0400
+++ vim71/src/configure.in	2008-06-18 06:56:39.000000000 -0400
@@ -299,6 +299,19 @@
 esac
 fi
 
+dnl Link with -lselinux for SELinux stuff; if not found
+AC_MSG_CHECKING(--disable-selinux argument)
+AC_ARG_ENABLE(selinux,
+	[  --disable-selinux	  Don't check for SELinux support.],
+	, enable_selinux="yes")
+if test "$enable_selinux" = "yes"; then
+  AC_MSG_RESULT(no)
+  AC_CHECK_LIB(selinux, is_selinux_enabled,
+	  [LIBS="$LIBS -lselinux"
+	   AC_DEFINE(HAVE_SELINUX)])
+else
+   AC_MSG_RESULT(yes)
+fi
 
 dnl Check user requested features.
 
@@ -423,7 +436,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 +772,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)
@@ -788,11 +807,12 @@
 
       AC_MSG_CHECKING(for location of Tcl include)
       if test "x$MACOSX" != "xyes"; then
-	tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/include"
+	tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver"
       else
 	dnl For Mac OS X 10.3, use the OS-provided framework location
 	tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
       fi
+      TCL_INC=
       for try in $tclinc; do
 	if test -f "$try/tcl.h"; then
 	  AC_MSG_RESULT($try/tcl.h)
@@ -808,6 +828,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 +849,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 +2046,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 +2740,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-15 19:18:41.000000000 -0500
+++ vim71/src/diff.c	2008-06-18 06:55:22.000000000 -0400
@@ -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 14:24:04.000000000 -0400
+++ vim71/src/digraph.c	2008-06-18 06:54:32.000000000 -0400
@@ -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 15:43:55.000000000 -0400
+++ vim71/src/edit.c	2008-06-18 06:56:15.000000000 -0400
@@ -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
@@ -5346,7 +5491,7 @@
 #if defined(FEAT_EVAL)
 	int do_internal = TRUE;
 
-	if (*curbuf->b_p_fex != NUL)
+	if (*curbuf->b_p_fex != NUL && (flags & INSCHAR_NO_FEX) == 0)
 	{
 	    do_internal = (fex_format(curwin->w_cursor.lnum, 1L, c) != 0);
 	    /* It may be required to save for undo again, e.g. when setline()
@@ -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);
@@ -5912,7 +6057,7 @@
      * be adjusted for the text formatting.
      */
     saved_cursor = pos;
-    format_lines((linenr_T)-1);
+    format_lines((linenr_T)-1, FALSE);
     curwin->w_cursor = saved_cursor;
     saved_cursor.lnum = 0;
 
@@ -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 15:47:32.000000000 -0400
+++ vim71/src/eval.c	2008-06-18 06:56:49.000000000 -0400
@@ -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));
@@ -505,6 +507,7 @@
 static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_fnameescape __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
@@ -529,6 +532,8 @@
 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_getpid __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 +582,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 +625,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 +653,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 +681,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 +708,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 +1001,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 +1322,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 +1365,6 @@
 
     if (p_verbose == 0)
 	--emsg_off;
-    vimvars[VV_VAL].vv_str = NULL;
     restore_vimvar(VV_VAL, &save_val);
 
     return list;
@@ -1411,7 +1418,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 +1492,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 +1515,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 +1540,7 @@
     clear_tv(&rettv);
     return retval;
 }
-#endif
+# endif
 
 /*
  * Call vimL function "func" and return the result as a list
@@ -1556,9 +1566,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 +1701,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 +1718,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 +1935,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 +1954,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 +1963,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 +2002,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 +2014,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 +2108,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 +2133,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 +3410,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 +3418,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 +6133,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 +6710,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 +6750,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 +6827,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 +6912,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 +7076,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},
@@ -7074,6 +7108,7 @@
     {"filter",		2, 2, f_filter},
     {"finddir",		1, 3, f_finddir},
     {"findfile",	1, 3, f_findfile},
+    {"fnameescape",	1, 1, f_fnameescape},
     {"fnamemodify",	2, 2, f_fnamemodify},
     {"foldclosed",	1, 1, f_foldclosed},
     {"foldclosedend",	1, 1, f_foldclosedend},
@@ -7082,7 +7117,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 +7134,8 @@
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
     {"getloclist",	1, 1, f_getqflist},
+    {"getmatches",	0, 0, f_getmatches},
+    {"getpid",		0, 0, f_getpid},
     {"getpos",		1, 1, f_getpos},
     {"getqflist",	0, 0, f_getqflist},
     {"getreg",		0, 2, f_getreg},
@@ -7149,7 +7186,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 +7218,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 +7257,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 +8281,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 +8737,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;
 
@@ -9152,13 +9207,13 @@
     rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
 }
 
-static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
+static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int find_what));
 
     static void
-findfilendir(argvars, rettv, dir)
+findfilendir(argvars, rettv, find_what)
     typval_T	*argvars;
     typval_T	*rettv;
-    int		dir;
+    int		find_what;
 {
 #ifdef FEAT_SEARCHPATH
     char_u	*fname;
@@ -9203,8 +9258,11 @@
 		vim_free(fresult);
 	    fresult = find_file_in_path_option(first ? fname : NULL,
 					       first ? (int)STRLEN(fname) : 0,
-					0, first, path, dir, curbuf->b_ffname,
-					dir ? (char_u *)"" : curbuf->b_p_sua);
+					0, first, path,
+					find_what,
+					curbuf->b_ffname,
+					find_what == FINDFILE_DIR
+					    ? (char_u *)"" : curbuf->b_p_sua);
 	    first = FALSE;
 
 	    if (fresult != NULL && rettv->v_type == VAR_LIST)
@@ -9339,15 +9397,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 +9425,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;
 }
 
 /*
@@ -9391,7 +9452,7 @@
     typval_T	*argvars;
     typval_T	*rettv;
 {
-    findfilendir(argvars, rettv, TRUE);
+    findfilendir(argvars, rettv, FINDFILE_DIR);
 }
 
 /*
@@ -9402,7 +9463,20 @@
     typval_T	*argvars;
     typval_T	*rettv;
 {
-    findfilendir(argvars, rettv, FALSE);
+    findfilendir(argvars, rettv, FINDFILE_FILE);
+}
+
+/*
+ * "fnameescape({string})" function
+ */
+    static void
+f_fnameescape(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_string = vim_strsave_fnameescape(
+					   get_tv_string(&argvars[0]), FALSE);
+    rettv->v_type = VAR_STRING;
 }
 
 /*
@@ -9670,6 +9744,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 +9945,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 +10219,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 +10358,51 @@
 }
 
 /*
+ * "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
+}
+
+/*
+ * "getpid()" function
+ */
+/*ARGSUSED*/
+    static void
+f_getpid(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    rettv->vval.v_number = mch_get_pid();
+}
+
+/*
  * "getpos(string)" function
  */
     static void
@@ -10290,7 +10424,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 +10920,9 @@
 	"gui_gtk2",
 # endif
 #endif
+#ifdef FEAT_GUI_GNOME
+	"gui_gnome",
+#endif
 #ifdef FEAT_GUI_MAC
 	"gui_mac",
 #endif
@@ -11471,14 +11609,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 +12575,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 +12623,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 +13876,7 @@
 	    }
 	    /* Shorten "remain". */
 	    if (*q != NUL)
-		STRCPY(remain, q - 1);
+		mch_memmove(remain, q - 1, STRLEN(q - 1) + 1);
 	    else
 	    {
 		vim_free(remain);
@@ -13773,6 +13969,7 @@
 	rettv->vval.v_list = l;
 	rettv->v_type = VAR_LIST;
 	++l->lv_refcount;
+	l->lv_idx = l->lv_len - l->lv_idx - 1;
     }
 }
 
@@ -13858,6 +14055,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 +14072,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 +14108,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 +14132,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 +14198,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 +14222,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 +14238,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 +14304,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 +14314,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 +14329,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 +14363,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 +14382,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)
 	{
@@ -14439,6 +14678,8 @@
 	appended_lines_mark(lcount, added);
 }
 
+static void set_qf_ll_list __ARGS((win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv));
+
 /*
  * Used by "setqflist()" and "setloclist()" functions
  */
@@ -14498,6 +14739,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 +14811,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 +15093,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
@@ -14906,7 +15218,7 @@
 	    if (!item_compare_func_err)
 	    {
 		/* Clear the List and append the items in the sorted order. */
-		l->lv_first = l->lv_last = NULL;
+		l->lv_first = l->lv_last = l->lv_idx_item = NULL;
 		l->lv_len = 0;
 		for (i = 0; i < len; ++i)
 		    list_append(l, ptrs[i]);
@@ -15274,7 +15586,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 +15774,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 +15897,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 +15952,7 @@
     FILE	*fd;
 
     if (check_restricted() || check_secure())
-	return;
+	goto done;
 
     if (argvars[1].v_type != VAR_UNKNOWN)
     {
@@ -15610,7 +15963,7 @@
 	if ((infile = vim_tempname('i')) == NULL)
 	{
 	    EMSG(_(e_notmp));
-	    return;
+	    goto done;
 	}
 
 	fd = mch_fopen((char *)infile, WRITEBIN);
@@ -16497,9 +16850,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 +16865,7 @@
 	list_T		*l;
 	int		len;
 	int		error = FALSE;
+	listitem_T	*li;
 
 	l = varp->vval.v_list;
 	if (l == NULL)
@@ -16527,6 +16881,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 +16921,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 +16939,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 +18160,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 +18171,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 +18213,11 @@
 
     if (type == VAR_FUNC)
 	msg_puts((char_u *)"()");
+    if (*first)
+    {
+	msg_clr_eos();
+	*first = FALSE;
+    }
 }
 
 /*
@@ -19136,6 +19507,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 +20362,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 +20373,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 +20457,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 */
 
@@ -20667,8 +21068,12 @@
 static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
 
 /*
- * Get the short pathname of a file.
- * Returns 1 on success. *fnamelen is 0 for nonexistent path.
+ * Get the short path (8.3) for the filename in "fnamep".
+ * Only works for a valid file name.
+ * When the path gets longer "fnamep" is changed and the allocated buffer
+ * is put in "bufp".
+ * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path.
+ * Returns OK on success, FAIL on failure.
  */
     static int
 get_short_pathname(fnamep, bufp, fnamelen)
@@ -20676,36 +21081,44 @@
     char_u	**bufp;
     int		*fnamelen;
 {
-    int		l,len;
+    int		l, len;
     char_u	*newbuf;
 
     len = *fnamelen;
-
     l = GetShortPathName(*fnamep, *fnamep, len);
     if (l > len - 1)
     {
 	/* If that doesn't work (not enough space), then save the string
-	 * and try again with a new buffer big enough
-	 */
+	 * and try again with a new buffer big enough. */
 	newbuf = vim_strnsave(*fnamep, l);
 	if (newbuf == NULL)
-	    return 0;
+	    return FAIL;
 
 	vim_free(*bufp);
 	*fnamep = *bufp = newbuf;
 
-	l = GetShortPathName(*fnamep,*fnamep,l+1);
-
-	/* Really should always succeed, as the buffer is big enough */
+	/* Really should always succeed, as the buffer is big enough. */
+	l = GetShortPathName(*fnamep, *fnamep, l+1);
     }
 
     *fnamelen = l;
-    return 1;
+    return OK;
 }
 
 /*
- * Create a short path name.  Returns the length of the buffer it needs.
- * Doesn't copy over the end of the buffer passed in.
+ * Get the short path (8.3) for the filename in "fname". The converted
+ * path is returned in "bufp".
+ *
+ * Some of the directories specified in "fname" may not exist. This function
+ * will shorten the existing directories at the beginning of the path and then
+ * append the remaining non-existing path.
+ *
+ * fname - Pointer to the filename to shorten.  On return, contains the
+ *         pointer to the shortened pathname
+ * bufp -  Pointer to an allocated buffer for the filename.
+ * fnamelen - Length of the filename pointed to by fname
+ *
+ * Returns OK on success (or nothing done) and FAIL on failure (out of memory).
  */
     static int
 shortpath_for_invalid_fname(fname, bufp, fnamelen)
@@ -20713,85 +21126,106 @@
     char_u	**bufp;
     int		*fnamelen;
 {
-    char_u	*s, *p, *pbuf2, *pbuf3;
+    char_u	*short_fname, *save_fname, *pbuf_unused;
+    char_u	*endp, *save_endp;
     char_u	ch;
-    int		len, len2, plen, slen;
+    int		old_len, len;
+    int		new_len, sfx_len;
+    int		retval = OK;
 
     /* Make a copy */
-    len2 = *fnamelen;
-    pbuf2 = vim_strnsave(*fname, len2);
-    pbuf3 = NULL;
-
-    s = pbuf2 + len2 - 1; /* Find the end */
-    slen = 1;
-    plen = len2;
-
-    if (after_pathsep(pbuf2, s + 1))
-    {
-	--s;
-	++slen;
-	--plen;
-    }
+    old_len = *fnamelen;
+    save_fname = vim_strnsave(*fname, old_len);
+    pbuf_unused = NULL;
+    short_fname = NULL;
 
-    do
+    endp = save_fname + old_len - 1; /* Find the end of the copy */
+    save_endp = endp;
+
+    /*
+     * Try shortening the supplied path till it succeeds by removing one
+     * directory at a time from the tail of the path.
+     */
+    len = 0;
+    for (;;)
     {
-	/* Go back one path-separator */
-	while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
-	{
-	    --s;
-	    ++slen;
-	    --plen;
-	}
-	if (s <= pbuf2)
-	    break;
+	/* go back one path-separator */
+	while (endp > save_fname && !after_pathsep(save_fname, endp + 1))
+	    --endp;
+	if (endp <= save_fname)
+	    break;		/* processed the complete path */
 
-	/* Remember the character that is about to be splatted */
-	ch = *s;
-	*s = 0; /* get_short_pathname requires a null-terminated string */
-
-	/* Try it in situ */
-	p = pbuf2;
-	if (!get_short_pathname(&p, &pbuf3, &plen))
+	/*
+	 * Replace the path separator with a NUL and try to shorten the
+	 * resulting path.
+	 */
+	ch = *endp;
+	*endp = 0;
+	short_fname = save_fname;
+	len = STRLEN(short_fname) + 1;
+	if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL)
 	{
-	    vim_free(pbuf2);
-	    return -1;
+	    retval = FAIL;
+	    goto theend;
 	}
-	*s = ch;    /* Preserve the string */
-    } while (plen == 0);
+	*endp = ch;	/* preserve the string */
 
-    if (plen > 0)
+	if (len > 0)
+	    break;	/* successfully shortened the path */
+
+	/* failed to shorten the path. Skip the path separator */
+	--endp;
+    }
+
+    if (len > 0)
     {
-	/* Remember the length of the new string.  */
-	*fnamelen = len = plen + slen;
+	/*
+	 * Succeeded in shortening the path. Now concatenate the shortened
+	 * path with the remaining path at the tail.
+	 */
+
+	/* Compute the length of the new path. */
+	sfx_len = (int)(save_endp - endp) + 1;
+	new_len = len + sfx_len;
+
+	*fnamelen = new_len;
 	vim_free(*bufp);
-	if (len > len2)
+	if (new_len > old_len)
 	{
-	    /* If there's not enough space in the currently allocated string,
-	     * then copy it to a buffer big enough.
-	     */
-	    *fname= *bufp = vim_strnsave(p, len);
+	    /* There is not enough space in the currently allocated string,
+	     * copy it to a buffer big enough. */
+	    *fname = *bufp = vim_strnsave(short_fname, new_len);
 	    if (*fname == NULL)
-		return -1;
+	    {
+		retval = FAIL;
+		goto theend;
+	    }
 	}
 	else
 	{
-	    /* Transfer pbuf2 to being the main buffer  (it's big enough) */
-	    *fname = *bufp = pbuf2;
-	    if (p != pbuf2)
-		strncpy(*fname, p, plen);
-	    pbuf2 = NULL;
-	}
-	/* Concat the next bit */
-	strncpy(*fname + plen, s, slen);
-	(*fname)[len] = '\0';
+	    /* Transfer short_fname to the main buffer (it's big enough),
+	     * unless get_short_pathname() did its work in-place. */
+	    *fname = *bufp = save_fname;
+	    if (short_fname != save_fname)
+		vim_strncpy(save_fname, short_fname, len);
+	    save_fname = NULL;
+	}
+
+	/* concat the not-shortened part of the path */
+	vim_strncpy(*fname + len, endp, sfx_len);
+	(*fname)[new_len] = NUL;
     }
-    vim_free(pbuf3);
-    vim_free(pbuf2);
-    return 0;
+
+theend:
+    vim_free(pbuf_unused);
+    vim_free(save_fname);
+
+    return retval;
 }
 
 /*
  * Get a pathname for a partial path.
+ * Returns OK for success, FAIL for failure.
  */
     static int
 shortpath_for_partial(fnamep, bufp, fnamelen)
@@ -20821,8 +21255,8 @@
 
     len = tflen = (int)STRLEN(tfname);
 
-    if (!get_short_pathname(&tfname, &pbuf, &len))
-	return -1;
+    if (get_short_pathname(&tfname, &pbuf, &len) == FAIL)
+	return FAIL;
 
     if (len == 0)
     {
@@ -20831,8 +21265,8 @@
 	 * there's not a lot of point in guessing what it might be.
 	 */
 	len = tflen;
-	if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
-	    return -1;
+	if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL)
+	    return FAIL;
     }
 
     /* Count the paths backward to find the beginning of the desired string. */
@@ -20856,7 +21290,7 @@
 	if (p >= tfname)
 	    *p = '~';
 	else
-	    return -1;
+	    return FAIL;
     }
     else
 	++p;
@@ -20867,7 +21301,7 @@
     *bufp = pbuf;
     *fnamep = p;
 
-    return 0;
+    return OK;
 }
 #endif /* WIN3264 */
 
@@ -20875,7 +21309,7 @@
  * Adjust a filename, according to a string of modifiers.
  * *fnamep must be NUL terminated when called.  When returning, the length is
  * determined by *fnamelen.
- * Returns valid flags.
+ * Returns VALID_ flags or -1 for failure.
  * When there is an error, *fnamep is set to NULL.
  */
     int
@@ -21034,14 +21468,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  */
@@ -21074,7 +21521,7 @@
 	 */
 	if (!has_fullname && !vim_isAbsName(*fnamep))
 	{
-	    if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
+	    if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL)
 		return -1;
 	}
 	else
@@ -21084,7 +21531,7 @@
 	    /* Simple case, already have the full-name
 	     * Nearly always shorter, so try first time. */
 	    l = *fnamelen;
-	    if (!get_short_pathname(fnamep, bufp, &l))
+	    if (get_short_pathname(fnamep, bufp, &l) == FAIL)
 		return -1;
 
 	    if (l == 0)
@@ -21092,7 +21539,7 @@
 		/* Couldn't find the filename.. search the paths.
 		 */
 		l = *fnamelen;
-		if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
+		if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL)
 		    return -1;
 	    }
 	    *fnamelen = l;
diff -Naur vim71.orig/src/ex_cmds.c vim71/src/ex_cmds.c
--- vim71.orig/src/ex_cmds.c	2007-05-07 15:41:01.000000000 -0400
+++ vim71/src/ex_cmds.c	2008-06-18 06:56:36.000000000 -0400
@@ -365,6 +365,10 @@
     int		sort_oct;		/* sort on octal number */
     int		sort_hex;		/* sort on hex number */
 
+    /* Sorting one line is really quick! */
+    if (count <= 1)
+	return;
+
     if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
 	return;
     sortbuf1 = NULL;
@@ -408,7 +412,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 */
@@ -1152,6 +1160,7 @@
     if (!do_out)
 	msg_putchar('\n');
 
+    /* Create the shell command in allocated memory. */
     cmd_buf = make_filter_cmd(cmd, itmp, otmp);
     if (cmd_buf == NULL)
 	goto filterend;
@@ -1172,7 +1181,10 @@
     if (do_out)
     {
 	if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
+	{
+	    vim_free(cmd_buf);
 	    goto error;
+	}
 	redraw_curbuf_later(VALID);
     }
     read_linecount = curbuf->b_ml.ml_line_count;
@@ -1646,7 +1658,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 +1782,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 +2740,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 +2928,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 +2970,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 +2986,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 +3401,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 +3596,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 +3694,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 +3799,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 +4208,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 +4219,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 +4254,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 +4337,7 @@
 	do_error = TRUE;
 	do_print = FALSE;
 	do_count = FALSE;
+	do_number = FALSE;
 	do_ic = 0;
     }
     while (*cmd)
@@ -4410,8 +4454,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,11 +4470,12 @@
 	    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
 	     * copying.  There are these pieces:
-	     * sub_firstline	The old text, unmodifed.
+	     * sub_firstline	The old text, unmodified.
 	     * copycol		Column in the old text where we started
 	     *			looking for a match; from here old text still
 	     *			needs to be copied to the new text.
@@ -4445,8 +4490,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 +4511,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 +4538,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 +4602,7 @@
 		    {
 			matchcol = (colnr_T)STRLEN(sub_firstline);
 			nmatch = 1;
+			skip_match = TRUE;
 		    }
 		    sub_nsubs++;
 		    did_sub = TRUE;
@@ -4600,7 +4665,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 +4701,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 +4777,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 +4848,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 +4918,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 +4938,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 +4959,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 +5032,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 +5262,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 +6102,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 +6117,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 +6144,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 +6152,7 @@
 	    || filecount == 0)
     {
 	EMSG2("E151: No match: %s", NameBuff);
+	vim_free(dirname);
 	return;
     }
 
@@ -6119,7 +6218,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 +6226,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 +6287,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 +6454,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 15:53:27.000000000 -0500
+++ vim71/src/ex_cmds.h	2008-06-18 06:55:02.000000000 -0400
@@ -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 15:25:02.000000000 -0400
+++ vim71/src/ex_cmds2.c	2008-06-18 06:55:20.000000000 -0400
@@ -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 15:49:38.000000000 -0400
+++ vim71/src/ex_docmd.c	2008-06-18 06:56:06.000000000 -0400
@@ -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));
@@ -372,7 +373,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 +667,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 +1742,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 +2121,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 +2661,7 @@
 		errormsg = IObuff;
 	    }
 	    STRCAT(errormsg, ": ");
-	    STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff));
+	    STRNCAT(errormsg, *cmdlinep, IOSIZE - STRLEN(IObuff) - 1);
 	}
 	emsg(errormsg);
     }
@@ -2756,7 +2763,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 +2964,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 +3029,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 +3310,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 +3339,39 @@
 		}
 		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
+		    ))
+	    {
+		len = 0;  /* avoid getting stuck when space is in 'isfname' */
+		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 +3463,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 +3478,8 @@
 		}
 	    }
 	    return find_nextcmd(arg);
-#endif
+# endif
 
-#ifdef FEAT_CMDL_COMPL
 /*
  * All completion for the +cmdline_compl feature goes here.
  */
@@ -3617,8 +3677,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 +3933,7 @@
 				curwin->w_cursor.col = 0;
 			    searchcmdlen = 0;
 			    if (!do_search(NULL, c, cmd, 1L,
-				      SEARCH_HIS + SEARCH_MSG + SEARCH_START))
+					       SEARCH_HIS | SEARCH_MSG, NULL))
 			    {
 				curwin->w_cursor = pos;
 				cmd = NULL;
@@ -3921,9 +3980,8 @@
 				pos.col = 0;
 			    if (searchit(curwin, curbuf, &pos,
 					*cmd == '?' ? BACKWARD : FORWARD,
-					(char_u *)"", 1L,
-					SEARCH_MSG + SEARCH_START,
-						      i, (linenr_T)0) != FAIL)
+					(char_u *)"", 1L, SEARCH_MSG,
+						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
 
@@ -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 15:47:50.000000000 -0400
+++ vim71/src/ex_eval.c	2008-06-18 06:53:54.000000000 -0400
@@ -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 15:47:23.000000000 -0400
+++ vim71/src/ex_getln.c	2008-06-18 06:56:47.000000000 -0400
@@ -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;
 }
 
@@ -3620,20 +3657,9 @@
 		    }
 		}
 #ifdef BACKSLASH_IN_FILENAME
-		{
-		    char_u	buf[20];
-		    int		j = 0;
-
-		    /* Don't escape '[' and '{' if they are in 'isfname'. */
-		    for (p = PATH_ESC_CHARS; *p != NUL; ++p)
-			if ((*p != '[' && *p != '{') || !vim_isfilec(*p))
-			    buf[j++] = *p;
-		    buf[j] = NUL;
-		    p = vim_strsave_escaped(files[i], buf);
-		}
+		p = vim_strsave_fnameescape(files[i], FALSE);
 #else
-		p = vim_strsave_escaped(files[i],
-			     xp->xp_shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
+		p = vim_strsave_fnameescape(files[i], xp->xp_shell);
 #endif
 		if (p != NULL)
 		{
@@ -3673,6 +3699,32 @@
 }
 
 /*
+ * Escape special characters in "fname" for when used as a file name argument
+ * after a Vim command, or, when "shell" is non-zero, a shell command.
+ * Returns the result in allocated memory.
+ */
+    char_u *
+vim_strsave_fnameescape(fname, shell)
+    char_u *fname;
+    int    shell;
+{
+#ifdef BACKSLASH_IN_FILENAME
+    char_u	buf[20];
+    int		j = 0;
+    char_u	*p;
+
+    /* Don't escape '[' and '{' if they are in 'isfname'. */
+    for (p = PATH_ESC_CHARS; *p != NUL; ++p)
+	if ((*p != '[' && *p != '{') || !vim_isfilec(*p))
+	    buf[j++] = *p;
+    buf[j] = NUL;
+    return vim_strsave_escaped(fname, buf);
+#else
+    return vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
+#endif
+}
+
+/*
  * Put a backslash before the file name in "pp", which is in allocated memory.
  */
     static void
@@ -4054,6 +4106,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 +4114,8 @@
 		    && vim_strchr(tail, '$') == NULL
 		    && vim_strchr(retval, '`') == NULL)
 		retval[len++] = '*';
+	    else if (len > 0 && retval[len - 1] == '$')
+		--len;
 	    retval[len] = NUL;
 	}
     }
@@ -4148,13 +4203,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 +4356,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 +4564,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 +4603,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 +4683,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 +4705,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 +4733,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 +5986,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 +5995,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 +6020,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 +6174,7 @@
 
 # ifdef FEAT_AUTOCMD
 	/* Don't execute autocommands while deleting the window. */
-	++autocmd_block;
+	block_autocmds();
 # endif
 	wp = curwin;
 	bp = curbuf;
@@ -6104,7 +6186,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 15:33:19.000000000 -0400
+++ vim71/src/feature.h	2008-06-18 06:51:34.000000000 -0400
@@ -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 07:29:44.000000000 -0400
+++ vim71/src/fileio.c	2008-06-18 06:56:56.000000000 -0400
@@ -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
@@ -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
     }
@@ -1270,12 +1288,49 @@
 #ifdef FEAT_MBYTE
 		    else if (conv_restlen > 0)
 		    {
-			/* Reached end-of-file but some trailing bytes could
-			 * not be converted.  Truncated file? */
-			if (conv_error == 0)
-			    conv_error = linecnt;
-			if (bad_char_behavior != BAD_DROP)
+			/*
+			 * Reached end-of-file but some trailing bytes could
+			 * not be converted.  Truncated file?
+			 */
+
+			/* When we did a conversion report an error. */
+			if (fio_flags != 0
+# ifdef USE_ICONV
+				|| iconv_fd != (iconv_t)-1
+# endif
+			   )
 			{
+			    if (conv_error == 0)
+				conv_error = curbuf->b_ml.ml_line_count
+								- linecnt + 1;
+			}
+			/* Remember the first linenr with an illegal byte */
+			else if (illegal_byte == 0)
+			    illegal_byte = curbuf->b_ml.ml_line_count
+								- linecnt + 1;
+			if (bad_char_behavior == BAD_DROP)
+			{
+			    *(ptr - conv_restlen) = NUL;
+			    conv_restlen = 0;
+			}
+			else
+			{
+			    /* Replace the trailing bytes with the replacement
+			     * character if we were converting; if we weren't,
+			     * leave the UTF8 checking code to do it, as it
+			     * works slightly differently. */
+			    if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
+# ifdef USE_ICONV
+				    || iconv_fd != (iconv_t)-1
+# endif
+			       ))
+			    {
+				while (conv_restlen > 0)
+				{
+				    *(--ptr) = bad_char_behavior;
+				    --conv_restlen;
+				}
+			    }
 			    fio_flags = 0;	/* don't convert this */
 # ifdef USE_ICONV
 			    if (iconv_fd != (iconv_t)-1)
@@ -1284,20 +1339,6 @@
 				iconv_fd = (iconv_t)-1;
 			    }
 # endif
-			    if (bad_char_behavior == BAD_KEEP)
-			    {
-				/* Keep the trailing bytes as-is. */
-				size = conv_restlen;
-				ptr -= conv_restlen;
-			    }
-			    else
-			    {
-				/* Replace the trailing bytes with the
-				 * replacement character. */
-				size = 1;
-				*--ptr = bad_char_behavior;
-			    }
-			    conv_restlen = 0;
 			}
 		    }
 #endif
@@ -1353,7 +1394,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)
@@ -1376,6 +1420,11 @@
 		    goto retry;
 		}
 	    }
+
+	    /* Include not converted bytes. */
+	    ptr -= conv_restlen;
+	    size += conv_restlen;
+	    conv_restlen = 0;
 #endif
 	    /*
 	     * Break here for a read error or end-of-file.
@@ -1385,11 +1434,6 @@
 
 #ifdef FEAT_MBYTE
 
-	    /* Include not converted bytes. */
-	    ptr -= conv_restlen;
-	    size += conv_restlen;
-	    conv_restlen = 0;
-
 # ifdef USE_ICONV
 	    if (iconv_fd != (iconv_t)-1)
 	    {
@@ -1851,12 +1895,12 @@
 		size = (long)((ptr + real_size) - dest);
 		ptr = dest;
 	    }
-	    else if (enc_utf8 && conv_error == 0 && !curbuf->b_p_bin)
+	    else if (enc_utf8 && !curbuf->b_p_bin)
 	    {
-		/* Reading UTF-8: Check if the bytes are valid UTF-8.
-		 * Need to start before "ptr" when part of the character was
-		 * read in the previous read() call. */
-		for (p = ptr - utf_head_off(buffer, ptr); ; ++p)
+		int  incomplete_tail = FALSE;
+
+		/* Reading UTF-8: Check if the bytes are valid UTF-8. */
+		for (p = ptr; ; ++p)
 		{
 		    int	 todo = (int)((ptr + size) - p);
 		    int	 l;
@@ -1870,43 +1914,56 @@
 			 * read() will get the next bytes, we'll check it
 			 * then. */
 			l = utf_ptr2len_len(p, todo);
-			if (l > todo)
+			if (l > todo && !incomplete_tail)
 			{
-			    /* Incomplete byte sequence, the next read()
-			     * should get them and check the bytes. */
-			    p += todo;
-			    break;
+			    /* Avoid retrying with a different encoding when
+			     * a truncated file is more likely, or attempting
+			     * to read the rest of an incomplete sequence when
+			     * we have already done so. */
+			    if (p > ptr || filesize > 0)
+				incomplete_tail = TRUE;
+			    /* Incomplete byte sequence, move it to conv_rest[]
+			     * and try to read the rest of it, unless we've
+			     * already done so. */
+			    if (p > ptr)
+			    {
+				conv_restlen = todo;
+				mch_memmove(conv_rest, p, conv_restlen);
+				size -= conv_restlen;
+				break;
+			    }
 			}
-			if (l == 1)
+			if (l == 1 || l > todo)
 			{
 			    /* Illegal byte.  If we can try another encoding
-			     * do that. */
-			    if (can_retry)
+			     * do that, unless at EOF where a truncated
+			     * file is more likely than a conversion error. */
+			    if (can_retry && !incomplete_tail)
 				break;
-
-			    /* Remember the first linenr with an illegal byte */
-			    if (illegal_byte == 0)
-				illegal_byte = readfile_linenr(linecnt, ptr, p);
 # ifdef USE_ICONV
 			    /* When we did a conversion report an error. */
 			    if (iconv_fd != (iconv_t)-1 && conv_error == 0)
 				conv_error = readfile_linenr(linecnt, ptr, p);
 # endif
+			    /* Remember the first linenr with an illegal byte */
+			    if (conv_error == 0 && illegal_byte == 0)
+				illegal_byte = readfile_linenr(linecnt, ptr, p);
 
 			    /* Drop, keep or replace the bad byte. */
 			    if (bad_char_behavior == BAD_DROP)
 			    {
-				mch_memmove(p, p+1, todo - 1);
+				mch_memmove(p, p + 1, todo - 1);
 				--p;
 				--size;
 			    }
 			    else if (bad_char_behavior != BAD_KEEP)
 				*p = bad_char_behavior;
 			}
-			p += l - 1;
+			else
+			    p += l - 1;
 		    }
 		}
-		if (p < ptr + size)
+		if (p < ptr + size && !incomplete_tail)
 		{
 		    /* Detected a UTF-8 error. */
 rewind_retry:
@@ -2265,6 +2322,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 +2528,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 +2817,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 +3251,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 +3329,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)
@@ -3586,6 +3687,9 @@
 						)
 			    mch_setperm(backup,
 					  (perm & 0707) | ((perm & 07) << 3));
+# ifdef HAVE_SELINUX
+			mch_copy_sec(fname, backup);
+# endif
 #endif
 
 			/*
@@ -3622,6 +3726,9 @@
 #ifdef HAVE_ACL
 			mch_set_acl(backup, acl);
 #endif
+#ifdef HAVE_SELINUX
+			mch_copy_sec(fname, backup);
+#endif
 			break;
 		    }
 		}
@@ -4243,6 +4350,12 @@
     }
 #endif
 
+#ifdef HAVE_SELINUX
+    /* Probably need to set the security context. */
+    if (!backup_copy)
+	mch_copy_sec(backup, wfname);
+#endif
+
 #ifdef UNIX
     /* When creating a new file, set its owner/group to that of the original
      * file.  Get the new device and inode number. */
@@ -5448,10 +5561,11 @@
     else if (p[0] == 0xfe && p[1] == 0xff
 	    && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
     {
-	if (flags == FIO_UTF16)
-	    name = "utf-16";	/* FE FF */
-	else
+	/* Default to utf-16, it works also for ucs-2 text. */
+	if (flags == FIO_UCS2)
 	    name = "ucs-2";	/* FE FF */
+	else
+	    name = "utf-16";	/* FE FF */
     }
     else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
 	    && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
@@ -5495,6 +5609,8 @@
 }
 #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.
@@ -5548,6 +5664,7 @@
 	p = NULL;
     return p;
 }
+#endif
 
 /*
  * Shorten filenames for all buffers.
@@ -7107,6 +7224,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 +8514,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 +8579,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 +8593,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 +8777,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 +8833,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.
  */
@@ -9108,7 +9265,7 @@
     aco_save_T	*aco;		/* structure to save values in */
     buf_T	*buf;		/* new curbuf */
 {
-    aco->save_buf = buf;
+    aco->save_buf = curbuf;
     curbuf = buf;
     curwin->w_buffer = buf;
 }
diff -Naur vim71.orig/src/fold.c vim71/src/fold.c
--- vim71.orig/src/fold.c	2007-05-07 15:46:32.000000000 -0400
+++ vim71/src/fold.c	2008-06-18 06:56:03.000000000 -0400
@@ -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 */
@@ -2300,7 +2307,7 @@
 
     /* If some fold changed, need to redraw and position cursor. */
     if (fold_changed && wp->w_p_fen)
-	changed_window_setting();
+	changed_window_setting_win(wp);
 
     /* If we updated folds past "bot", need to redraw more lines.  Don't do
      * this in other situations, the changed lines will be redrawn anyway and
@@ -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 15:18:20.000000000 -0400
+++ vim71/src/getchar.c	2008-06-18 06:54:12.000000000 -0400
@@ -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 15:44:26.000000000 -0400
+++ vim71/src/globals.h	2008-06-18 06:54:12.000000000 -0400
@@ -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);
 
@@ -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 */
diff -Naur vim71.orig/src/gui.c vim71/src/gui.c
--- vim71.orig/src/gui.c	2007-05-07 15:50:55.000000000 -0400
+++ vim71/src/gui.c	2008-06-18 06:56:40.000000000 -0400
@@ -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
 }
 
@@ -4833,6 +4855,15 @@
 {
     update_topline();
     validate_cursor();
+#ifdef FEAT_AUTOCMD
+    /* Trigger CursorMoved if the cursor moved. */
+    if (!finish_op && has_cursormoved()
+	    && !equalpos(last_cursormoved, curwin->w_cursor))
+    {
+	apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, FALSE, curbuf);
+	last_cursormoved = curwin->w_cursor;
+    }
+#endif
     update_screen(0);	/* may need to update the screen */
     setcursor();
     out_flush();		/* make sure output has been written */
@@ -5026,7 +5057,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 +5148,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_gtk.c vim71/src/gui_gtk.c
--- vim71.orig/src/gui_gtk.c	2007-05-10 04:37:37.000000000 -0400
+++ vim71/src/gui_gtk.c	2008-06-18 06:52:00.000000000 -0400
@@ -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 */
@@ -1630,11 +1630,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 +2227,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 04:37:49.000000000 -0400
+++ vim71/src/gui_gtk_x11.c	2008-06-18 06:54:51.000000000 -0400
@@ -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 15:20:24.000000000 -0400
+++ vim71/src/gui_motif.c	2008-06-18 06:55:26.000000000 -0400
@@ -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 15:30:49.000000000 -0400
+++ vim71/src/gui_xmebw.c	2008-06-18 06:53:43.000000000 -0400
@@ -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/gvimtutor vim71/src/gvimtutor
--- vim71.orig/src/gvimtutor	1969-12-31 19:00:00.000000000 -0500
+++ vim71/src/gvimtutor	2008-06-18 06:56:38.000000000 -0400
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Start GUI Vim on a copy of the tutor file.
+
+# Usage: gvimtutor [xx]
+# See vimtutor for usage.
+
+exec `dirname $0`/vimtutor -g "$@"
diff -Naur vim71.orig/src/hardcopy.c vim71/src/hardcopy.c
--- vim71.orig/src/hardcopy.c	2007-05-07 15:34:18.000000000 -0400
+++ vim71/src/hardcopy.c	2008-06-18 06:55:04.000000000 -0400
@@ -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 10:29:57.000000000 -0400
+++ vim71/src/if_cscope.c	2008-06-18 06:56:33.000000000 -0400
@@ -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;
 
@@ -2095,21 +2096,30 @@
     return CSCOPE_SUCCESS;
 }
 
+#if defined(UNIX) && defined(SIGALRM)
+/*
+ * Used to catch and ignore SIGALRM below.
+ */
+/* ARGSUSED */
+    static RETSIGTYPE
+sig_handler SIGDEFARG(sigarg)
+{
+    /* do nothing */
+    SIGRETURN;
+}
+#endif
 
 /*
  * 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)
     int i;
     int freefnpp;
 {
-#if defined(UNIX)
-    int pstat;
-#else
     /*
      * Trying to exit normally (not sure whether it is fit to UNIX cscope
      */
@@ -2118,10 +2128,95 @@
 	(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 defined(UNIX)
+    {
+	int waitpid_errno;
+	int pstat;
+	pid_t pid;
+
+# if defined(HAVE_SIGACTION)
+	struct sigaction sa, old;
+
+	/* Use sigaction() to limit the waiting time to two seconds. */
+	sigemptyset(&sa.sa_mask);
+	sa.sa_handler = sig_handler;
+	sa.sa_flags = SA_NODEFER;
+	sigaction(SIGALRM, &sa, &old);
+	alarm(2); /* 2 sec timeout */
+
+	/* Block until cscope exits or until timer expires */
+	pid = waitpid(csinfo[i].pid, &pstat, 0);
+	waitpid_errno = errno;
+
+	/* cancel pending alarm if still there and restore signal */
+	alarm(0);
+	sigaction(SIGALRM, &old, NULL);
+# else
+	int waited;
+
+	/* Can't use sigaction(), loop for two seconds.  First yield the CPU
+	 * to give cscope a chance to exit quickly. */
+	sleep(0);
+	for (waited = 0; waited < 40; ++waited)
+	{
+	    pid = waitpid(csinfo[i].pid, &pstat, WNOHANG);
+	    waitpid_errno = errno;
+	    if (pid != 0)
+		break;  /* break unless the process is still running */
+	    mch_delay(50L, FALSE); /* sleep 50 ms */
+	}
+# endif
+	/*
+	 * If the cscope process is still running: kill it.
+	 * Safety check: If the PID would be zero here, the entire X session
+	 * would be killed.  -1 and 1 are dangerous as well.
+	 */
+	if (pid < 0 && csinfo[i].pid > 1)
+	{
+# ifdef ECHILD
+	    int alive = TRUE;
+
+	    if (waitpid_errno == ECHILD)
+	    {
+		/*
+		 * When using 'vim -g', vim is forked and cscope process is
+		 * no longer a child process but a sibling.  So waitpid()
+		 * fails with errno being ECHILD (No child processes).
+		 * Don't send SIGKILL to cscope immediately but wait
+		 * (polling) for it to exit normally as result of sending
+		 * the "q" command, hence giving it a chance to clean up
+		 * its temporary files.
+		 */
+		int waited;
+
+		sleep(0);
+		for (waited = 0; waited < 40; ++waited)
+		{
+		    /* Check whether cscope process is still alive */
+		    if (kill(csinfo[i].pid, 0) != 0)
+		    {
+			alive = FALSE; /* cscope process no longer exists */
+			break;
+		    }
+		    mch_delay(50L, FALSE); /* sleep 50ms */
+		}
+	    }
+	    if (alive)
+# endif
+	    {
+		kill(csinfo[i].pid, SIGKILL);
+		(void)waitpid(csinfo[i].pid, &pstat, 0);
+	    }
+	}
+    }
+#else  /* !UNIX */
+    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)
@@ -2129,18 +2224,6 @@
     if (csinfo[i].to_fp != NULL)
 	(void)fclose(csinfo[i].to_fp);
 
-    /*
-     * Safety check: If the PID would be zero here, the entire X session would
-     * be killed.  -1 and 1 are dangerous as well.
-     */
-#if defined(UNIX)
-    if (csinfo[i].pid > 1)
-    {
-	kill(csinfo[i].pid, SIGTERM);
-	(void)waitpid(csinfo[i].pid, &pstat, 0);
-    }
-#endif
-
     if (freefnpp)
     {
 	vim_free(csinfo[i].fname);
@@ -2195,7 +2278,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 +2387,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 13:14:22.000000000 -0400
+++ vim71/src/if_cscope.h	2008-06-18 06:52:38.000000000 -0400
@@ -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 07:13:47.000000000 -0400
+++ vim71/src/if_mzsch.c	2008-06-18 06:51:00.000000000 -0400
@@ -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 08:45:15.000000000 -0400
+++ vim71/src/if_perl.xs	2008-06-18 06:53:25.000000000 -0400
@@ -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_python.c vim71/src/if_python.c
--- vim71.orig/src/if_python.c	2007-03-06 17:00:53.000000000 -0500
+++ vim71/src/if_python.c	2008-06-18 06:56:52.000000000 -0400
@@ -38,6 +38,8 @@
 # undef HAVE_STDARG_H	/* Python's config.h defines it as well. */
 #endif
 
+#define PY_SSIZE_T_CLEAN
+
 #include <Python.h>
 #if defined(MACOS) && !defined(MACOS_X_UNIX)
 # include "macglue.h"
@@ -55,6 +57,22 @@
 # define PySequenceMethods int
 #endif
 
+#if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000
+# define PyInt Py_ssize_t
+# define PyInquiry lenfunc
+# define PyIntArgFunc ssizeargfunc
+# define PyIntIntArgFunc ssizessizeargfunc
+# define PyIntObjArgProc ssizeobjargproc
+# define PyIntIntObjArgProc ssizessizeobjargproc
+#else
+# define PyInt int
+# define PyInquiry inquiry
+# define PyIntArgFunc intargfunc
+# define PyIntIntArgFunc intintargfunc
+# define PyIntObjArgProc intobjargproc
+# define PyIntIntObjArgProc intintobjargproc
+#endif
+
 /* Parser flags */
 #define single_input	256
 #define file_input	257
@@ -150,11 +168,11 @@
 static long(*dll_PyInt_AsLong)(PyObject *);
 static PyObject*(*dll_PyInt_FromLong)(long);
 static PyTypeObject* dll_PyInt_Type;
-static PyObject*(*dll_PyList_GetItem)(PyObject *, int);
+static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt);
 static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *);
-static PyObject*(*dll_PyList_New)(int size);
-static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *);
-static int(*dll_PyList_Size)(PyObject *);
+static PyObject*(*dll_PyList_New)(PyInt size);
+static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *);
+static PyInt(*dll_PyList_Size)(PyObject *);
 static PyTypeObject* dll_PyList_Type;
 static PyObject*(*dll_PyImport_ImportModule)(const char *);
 static PyObject*(*dll_PyDict_New)(void);
@@ -163,8 +181,8 @@
 static int(*dll_PyRun_SimpleString)(char *);
 static char*(*dll_PyString_AsString)(PyObject *);
 static PyObject*(*dll_PyString_FromString)(const char *);
-static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int);
-static int(*dll_PyString_Size)(PyObject *);
+static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt);
+static PyInt(*dll_PyString_Size)(PyObject *);
 static PyTypeObject* dll_PyString_Type;
 static int(*dll_PySys_SetObject)(char *, PyObject *);
 static int(*dll_PySys_SetArgv)(int, char **);
@@ -367,10 +385,10 @@
  * ----------------------------------------------
  */
 static PyObject *GetBufferLine(buf_T *, int);
-static PyObject *GetBufferLineList(buf_T *, int, int);
+static PyObject *GetBufferLineList(buf_T *, PyInt, PyInt);
 
 static int SetBufferLine(buf_T *, int, PyObject *, int *);
-static int SetBufferLineList(buf_T *, int, int, PyObject *, int *);
+static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, int *);
 static int InsertBufferLines(buf_T *, int, PyObject *, int *);
 
 static PyObject *LineToString(const char *);
@@ -773,8 +791,8 @@
     static PyObject *
 OutputWritelines(PyObject *self, PyObject *args)
 {
-    int n;
-    int i;
+    PyInt n;
+    PyInt i;
     PyObject *list;
     int error = ((OutputObject *)(self))->error;
 
@@ -986,11 +1004,11 @@
 static PyObject *BufferGetattr(PyObject *, char *);
 static PyObject *BufferRepr(PyObject *);
 
-static int BufferLength(PyObject *);
-static PyObject *BufferItem(PyObject *, int);
-static PyObject *BufferSlice(PyObject *, int, int);
-static int BufferAssItem(PyObject *, int, PyObject *);
-static int BufferAssSlice(PyObject *, int, int, PyObject *);
+static PyInt BufferLength(PyObject *);
+static PyObject *BufferItem(PyObject *, PyInt);
+static PyObject *BufferSlice(PyObject *, PyInt, PyInt);
+static PyInt BufferAssItem(PyObject *, PyInt, PyObject *);
+static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *);
 
 static PyObject *BufferAppend(PyObject *, PyObject *);
 static PyObject *BufferMark(PyObject *, PyObject *);
@@ -1017,11 +1035,11 @@
 static PyObject *RangeGetattr(PyObject *, char *);
 static PyObject *RangeRepr(PyObject *);
 
-static int RangeLength(PyObject *);
-static PyObject *RangeItem(PyObject *, int);
-static PyObject *RangeSlice(PyObject *, int, int);
-static int RangeAssItem(PyObject *, int, PyObject *);
-static int RangeAssSlice(PyObject *, int, int, PyObject *);
+static PyInt RangeLength(PyObject *);
+static PyObject *RangeItem(PyObject *, PyInt);
+static PyObject *RangeSlice(PyObject *, PyInt, PyInt);
+static PyInt RangeAssItem(PyObject *, PyInt, PyObject *);
+static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *);
 
 static PyObject *RangeAppend(PyObject *, PyObject *);
 
@@ -1029,15 +1047,15 @@
  * -------------------------------------------
  */
 
-static int WinListLength(PyObject *);
-static PyObject *WinListItem(PyObject *, int);
+static PyInt WinListLength(PyObject *);
+static PyObject *WinListItem(PyObject *, PyInt);
 
 /* Buffer list type - Implementation functions
  * -------------------------------------------
  */
 
-static int BufListLength(PyObject *);
-static PyObject *BufListItem(PyObject *, int);
+static PyInt BufListLength(PyObject *);
+static PyObject *BufListItem(PyObject *, PyInt);
 
 /* Current objects type - Implementation functions
  * -----------------------------------------------
@@ -1130,6 +1148,16 @@
 	result = Py_BuildValue("s", buf);
 	PyDict_SetItemString(lookupDict, ptrBuf, result);
     }
+#ifdef FEAT_FLOAT
+    else if (our_tv->v_type == VAR_FLOAT)
+    {
+	char buf[NUMBUFLEN];
+
+	sprintf(buf, "%f", our_tv->vval.v_float);
+	result = Py_BuildValue("s", buf);
+	PyDict_SetItemString(lookupDict, ptrBuf, result);
+    }
+#endif
     else if (our_tv->v_type == VAR_LIST)
     {
 	list_T		*list = our_tv->vval.v_list;
@@ -1245,7 +1273,7 @@
 }
 
     static PyObject *
-RBItem(BufferObject *self, int n, int start, int end)
+RBItem(BufferObject *self, PyInt n, int start, int end)
 {
     if (CheckBuffer(self))
 	return NULL;
@@ -1260,9 +1288,9 @@
 }
 
     static PyObject *
-RBSlice(BufferObject *self, int lo, int hi, int start, int end)
+RBSlice(BufferObject *self, PyInt lo, PyInt hi, int start, int end)
 {
-    int size;
+    PyInt size;
 
     if (CheckBuffer(self))
 	return NULL;
@@ -1283,8 +1311,8 @@
     return GetBufferLineList(self->buf, lo+start, hi+start);
 }
 
-    static int
-RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end)
+    static PyInt
+RBAssItem(BufferObject *self, PyInt n, PyObject *val, int start, int end, int *new_end)
 {
     int len_change;
 
@@ -1306,8 +1334,8 @@
     return 0;
 }
 
-    static int
-RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end)
+    static PyInt
+RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, int start, int end, int *new_end)
 {
     int size;
     int len_change;
@@ -1384,13 +1412,13 @@
 };
 
 static PySequenceMethods BufferAsSeq = {
-    (inquiry)		BufferLength,	    /* sq_length,    len(x)   */
+    (PyInquiry)		BufferLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0, /* BufferConcat, */	     /* sq_concat,    x+y      */
-    (intargfunc)	0, /* BufferRepeat, */	     /* sq_repeat,    x*n      */
-    (intargfunc)	BufferItem,	    /* sq_item,      x[i]     */
-    (intintargfunc)	BufferSlice,	    /* sq_slice,     x[i:j]   */
-    (intobjargproc)	BufferAssItem,	    /* sq_ass_item,  x[i]=v   */
-    (intintobjargproc)	BufferAssSlice,     /* sq_ass_slice, x[i:j]=v */
+    (PyIntArgFunc)	0, /* BufferRepeat, */	     /* sq_repeat,    x*n      */
+    (PyIntArgFunc)	BufferItem,	    /* sq_item,      x[i]     */
+    (PyIntIntArgFunc)	BufferSlice,	    /* sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)	BufferAssItem,	    /* sq_ass_item,  x[i]=v   */
+    (PyIntIntObjArgProc)	BufferAssSlice,     /* sq_ass_slice, x[i:j]=v */
 };
 
 static PyTypeObject BufferType = {
@@ -1516,7 +1544,7 @@
 
 /******************/
 
-    static int
+    static PyInt
 BufferLength(PyObject *self)
 {
     /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
@@ -1527,29 +1555,29 @@
 }
 
     static PyObject *
-BufferItem(PyObject *self, int n)
+BufferItem(PyObject *self, PyInt n)
 {
     return RBItem((BufferObject *)(self), n, 1,
 		  (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
 }
 
     static PyObject *
-BufferSlice(PyObject *self, int lo, int hi)
+BufferSlice(PyObject *self, PyInt lo, PyInt hi)
 {
     return RBSlice((BufferObject *)(self), lo, hi, 1,
 		   (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
 }
 
-    static int
-BufferAssItem(PyObject *self, int n, PyObject *val)
+    static PyInt
+BufferAssItem(PyObject *self, PyInt n, PyObject *val)
 {
     return RBAssItem((BufferObject *)(self), n, val, 1,
 		     (int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
 		     NULL);
 }
 
-    static int
-BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val)
+    static PyInt
+BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
 {
     return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
 		      (int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
@@ -1627,13 +1655,13 @@
 };
 
 static PySequenceMethods RangeAsSeq = {
-    (inquiry)		RangeLength,	    /* sq_length,    len(x)   */
+    (PyInquiry)		RangeLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0, /* RangeConcat, */	     /* sq_concat,    x+y      */
-    (intargfunc)	0, /* RangeRepeat, */	     /* sq_repeat,    x*n      */
-    (intargfunc)	RangeItem,	    /* sq_item,      x[i]     */
-    (intintargfunc)	RangeSlice,	    /* sq_slice,     x[i:j]   */
-    (intobjargproc)	RangeAssItem,	    /* sq_ass_item,  x[i]=v   */
-    (intintobjargproc)	RangeAssSlice,	    /* sq_ass_slice, x[i:j]=v */
+    (PyIntArgFunc)	0, /* RangeRepeat, */	     /* sq_repeat,    x*n      */
+    (PyIntArgFunc)	RangeItem,	    /* sq_item,      x[i]     */
+    (PyIntIntArgFunc)	RangeSlice,	    /* sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)	RangeAssItem,	    /* sq_ass_item,  x[i]=v   */
+    (PyIntIntObjArgProc)	RangeAssSlice,	    /* sq_ass_slice, x[i:j]=v */
 };
 
 static PyTypeObject RangeType = {
@@ -1738,7 +1766,7 @@
 
 /****************/
 
-    static int
+    static PyInt
 RangeLength(PyObject *self)
 {
     /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
@@ -1749,7 +1777,7 @@
 }
 
     static PyObject *
-RangeItem(PyObject *self, int n)
+RangeItem(PyObject *self, PyInt n)
 {
     return RBItem(((RangeObject *)(self))->buf, n,
 		  ((RangeObject *)(self))->start,
@@ -1757,15 +1785,15 @@
 }
 
     static PyObject *
-RangeSlice(PyObject *self, int lo, int hi)
+RangeSlice(PyObject *self, PyInt lo, PyInt hi)
 {
     return RBSlice(((RangeObject *)(self))->buf, lo, hi,
 		   ((RangeObject *)(self))->start,
 		   ((RangeObject *)(self))->end);
 }
 
-    static int
-RangeAssItem(PyObject *self, int n, PyObject *val)
+    static PyInt
+RangeAssItem(PyObject *self, PyInt n, PyObject *val)
 {
     return RBAssItem(((RangeObject *)(self))->buf, n, val,
 		     ((RangeObject *)(self))->start,
@@ -1773,8 +1801,8 @@
 		     &((RangeObject *)(self))->end);
 }
 
-    static int
-RangeAssSlice(PyObject *self, int lo, int hi, PyObject *val)
+    static PyInt
+RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
 {
     return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val,
 		      ((RangeObject *)(self))->start,
@@ -1801,13 +1829,13 @@
 BufListObject;
 
 static PySequenceMethods BufListAsSeq = {
-    (inquiry)		BufListLength,	    /* sq_length,    len(x)   */
+    (PyInquiry)		BufListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* sq_concat,    x+y      */
-    (intargfunc)	0,		    /* sq_repeat,    x*n      */
-    (intargfunc)	BufListItem,	    /* sq_item,      x[i]     */
-    (intintargfunc)	0,		    /* sq_slice,     x[i:j]   */
-    (intobjargproc)	0,		    /* sq_ass_item,  x[i]=v   */
-    (intintobjargproc)	0,		    /* sq_ass_slice, x[i:j]=v */
+    (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
+    (PyIntArgFunc)	BufListItem,	    /* sq_item,      x[i]     */
+    (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
+    (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
 };
 
 static PyTypeObject BufListType = {
@@ -1837,7 +1865,7 @@
  */
 
 /*ARGSUSED*/
-    static int
+    static PyInt
 BufListLength(PyObject *self)
 {
     buf_T	*b = firstbuf;
@@ -1854,7 +1882,7 @@
 
 /*ARGSUSED*/
     static PyObject *
-BufListItem(PyObject *self, int n)
+BufListItem(PyObject *self, PyInt n)
 {
     buf_T *b;
 
@@ -2119,13 +2147,13 @@
 WinListObject;
 
 static PySequenceMethods WinListAsSeq = {
-    (inquiry)		WinListLength,	    /* sq_length,    len(x)   */
+    (PyInquiry)		WinListLength,	    /* sq_length,    len(x)   */
     (binaryfunc)	0,		    /* sq_concat,    x+y      */
-    (intargfunc)	0,		    /* sq_repeat,    x*n      */
-    (intargfunc)	WinListItem,	    /* sq_item,      x[i]     */
-    (intintargfunc)	0,		    /* sq_slice,     x[i:j]   */
-    (intobjargproc)	0,		    /* sq_ass_item,  x[i]=v   */
-    (intintobjargproc)	0,		    /* sq_ass_slice, x[i:j]=v */
+    (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
+    (PyIntArgFunc)	WinListItem,	    /* sq_item,      x[i]     */
+    (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
+    (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
+    (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
 };
 
 static PyTypeObject WinListType = {
@@ -2154,7 +2182,7 @@
 /* Window list object - Implementation
  */
 /*ARGSUSED*/
-    static int
+    static PyInt
 WinListLength(PyObject *self)
 {
     win_T	*w = firstwin;
@@ -2171,7 +2199,7 @@
 
 /*ARGSUSED*/
     static PyObject *
-WinListItem(PyObject *self, int n)
+WinListItem(PyObject *self, PyInt n)
 {
     win_T *w;
 
@@ -2351,10 +2379,10 @@
  * including, hi. The list is returned as a Python list of string objects.
  */
     static PyObject *
-GetBufferLineList(buf_T *buf, int lo, int hi)
+GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
 {
-    int i;
-    int n = hi - lo;
+    PyInt i;
+    PyInt n = hi - lo;
     PyObject *list = PyList_New(n);
 
     if (list == NULL)
@@ -2517,7 +2545,7 @@
  * is set to the change in the buffer length.
  */
     static int
-SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change)
+SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, int *len_change)
 {
     /* First of all, we check the thpe of the supplied Python object.
      * There are three cases:
@@ -2527,8 +2555,8 @@
      */
     if (list == Py_None || list == NULL)
     {
-	int	i;
-	int	n = hi - lo;
+	PyInt	i;
+	PyInt	n = hi - lo;
 	buf_T	*savebuf = curbuf;
 
 	PyErr_Clear();
@@ -2564,9 +2592,9 @@
     }
     else if (PyList_Check(list))
     {
-	int	i;
-	int	new_len = PyList_Size(list);
-	int	old_len = hi - lo;
+	PyInt	i;
+	PyInt	new_len = PyList_Size(list);
+	PyInt	old_len = hi - lo;
 	int	extra = 0;	/* lines added to text, can be negative */
 	char	**array;
 	buf_T	*savebuf;
@@ -2745,8 +2773,8 @@
     }
     else if (PyList_Check(lines))
     {
-	int	i;
-	int	size = PyList_Size(lines);
+	PyInt	i;
+	PyInt	size = PyList_Size(lines);
 	char	**array;
 	buf_T	*savebuf;
 
@@ -2831,7 +2859,7 @@
 LineToString(const char *str)
 {
     PyObject *result;
-    int len = strlen(str);
+    PyInt len = strlen(str);
     char *p;
 
     /* Allocate an Python string object, with uninitialised contents. We
@@ -2871,8 +2899,8 @@
 {
     const char *str;
     char *save;
-    int len;
-    int i;
+    PyInt len;
+    PyInt i;
     char *p;
 
     if (obj == NULL || !PyString_Check(obj))
diff -Naur vim71.orig/src/if_ruby.c vim71/src/if_ruby.c
--- vim71.orig/src/if_ruby.c	2007-05-12 05:54:12.000000000 -0400
+++ vim71/src/if_ruby.c	2008-06-18 06:52:39.000000000 -0400
@@ -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 07:38:38.000000000 -0400
+++ vim71/src/keymap.h	2008-06-18 06:52:31.000000000 -0400
@@ -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 15:38:22.000000000 -0400
+++ vim71/src/macros.h	2008-06-18 06:52:12.000000000 -0400
@@ -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 15:46:43.000000000 -0400
+++ vim71/src/main.aap	2008-06-18 06:54:11.000000000 -0400
@@ -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 15:38:44.000000000 -0400
+++ vim71/src/main.c	2008-06-18 06:55:10.000000000 -0400
@@ -954,7 +954,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 +1016,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 +1330,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 +1388,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)
@@ -1730,7 +1757,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 +1775,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 +3065,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"));
@@ -3632,7 +3661,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 15:28:01.000000000 -0400
+++ vim71/src/mark.c	2008-06-18 06:55:40.000000000 -0400
@@ -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 15:47:09.000000000 -0400
+++ vim71/src/mbyte.c	2008-06-18 06:56:57.000000000 -0400
@@ -360,6 +360,12 @@
     {"ucs4be",		IDX_UCS4},
     {"ucs-4be",		IDX_UCS4},
     {"ucs4le",		IDX_UCS4LE},
+    {"utf32",		IDX_UCS4},
+    {"utf-32",		IDX_UCS4},
+    {"utf32be",		IDX_UCS4},
+    {"utf-32be",	IDX_UCS4},
+    {"utf32le",		IDX_UCS4LE},
+    {"utf-32le",	IDX_UCS4LE},
     {"932",		IDX_CP932},
     {"949",		IDX_CP949},
     {"936",		IDX_CP936},
@@ -1310,20 +1316,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 +1344,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 +1648,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 +1658,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;
@@ -1959,8 +1973,10 @@
 	{0x205f, 0x205f, 0},
 	{0x2060, 0x27ff, 1},		/* punctuation and symbols */
 	{0x2070, 0x207f, 0x2070},	/* superscript */
-	{0x2080, 0x208f, 0x2080},	/* subscript */
-	{0x2983, 0x2998, 1},
+	{0x2080, 0x2094, 0x2080},	/* subscript */
+	{0x20a0, 0x27ff, 1},		/* all kinds of symbols */
+	{0x2800, 0x28ff, 0x2800},	/* braille */
+	{0x2900, 0x2998, 1},		/* arrows, brackets, etc. */
 	{0x29d8, 0x29db, 1},
 	{0x29fc, 0x29fd, 1},
 	{0x3000, 0x3000, 0},		/* ideographic space */
@@ -2320,7 +2336,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 +2871,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 +2917,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) \
@@ -5506,13 +5520,13 @@
     preedit_caret_cb.callback = (XIMProc)preedit_caret_cbproc;
     preedit_done_cb.callback = (XIMProc)preedit_done_cbproc;
     preedit_attr
-	= XVaCreateNestedList (0,
+	 = XVaCreateNestedList(0,
 			       XNPreeditStartCallback, &preedit_start_cb,
 			       XNPreeditDrawCallback, &preedit_draw_cb,
 			       XNPreeditCaretCallback, &preedit_caret_cb,
 			       XNPreeditDoneCallback, &preedit_done_cb,
-			       0);
-    XSetICValues (xxic, XNPreeditAttributes, preedit_attr, 0);
+			       NULL);
+    XSetICValues(xxic, XNPreeditAttributes, preedit_attr, NULL);
     XFree(preedit_attr);
 }
 
@@ -5522,7 +5536,8 @@
 {
 #ifdef USE_X11R6_XIM
     /* don't change the input context when we call reset */
-    XSetICValues(((GdkICPrivate*)ic)->xic, XNResetState, XIMPreserveState, 0);
+    XSetICValues(((GdkICPrivate *)ic)->xic, XNResetState, XIMPreserveState,
+									NULL);
 #endif
 }
 
diff -Naur vim71.orig/src/memfile.c vim71/src/memfile.c
--- vim71.orig/src/memfile.c	2007-05-11 13:50:12.000000000 -0400
+++ vim71/src/memfile.c	2008-06-18 06:56:39.000000000 -0400
@@ -1346,5 +1346,10 @@
 	mfp->mf_ffname = NULL;
     }
     else
+    {
+#ifdef HAVE_SELINUX
+	mch_copy_sec(fname, mfp->mf_fname);
+#endif
 	mch_hide(mfp->mf_fname);    /* try setting the 'hidden' flag */
+    }
 }
diff -Naur vim71.orig/src/message.c vim71/src/message.c
--- vim71.orig/src/message.c	2007-05-07 15:31:59.000000000 -0400
+++ vim71/src/message.c	2008-06-18 06:53:52.000000000 -0400
@@ -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 15:49:03.000000000 -0400
+++ vim71/src/misc1.c	2008-06-18 06:55:59.000000000 -0400
@@ -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));
@@ -6827,6 +6894,7 @@
 			if (trypos != NULL)
 			{
 			    curwin->w_cursor.lnum = trypos->lnum + 1;
+			    curwin->w_cursor.col = 0;
 			    continue;
 			}
 
@@ -6887,6 +6955,7 @@
 			    if (trypos != NULL)
 			    {
 				curwin->w_cursor.lnum = trypos->lnum + 1;
+				curwin->w_cursor.col = 0;
 				continue;
 			    }
 			}
@@ -6924,6 +6993,7 @@
 		if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
 		{
 		    curwin->w_cursor.lnum = trypos->lnum + 1;
+		    curwin->w_cursor.col = 0;
 		    continue;
 		}
 
@@ -7047,7 +7117,10 @@
 		{
 		    if (find_last_paren(l, '{', '}') && (trypos =
 				    find_start_brace(ind_maxcomment)) != NULL)
+		    {
 			curwin->w_cursor.lnum = trypos->lnum + 1;
+			curwin->w_cursor.col = 0;
+		    }
 		    continue;
 		}
 
@@ -7079,7 +7152,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)
@@ -7163,11 +7236,12 @@
 			 *     case xx:  if ( asdf &&
 			 *			asdf)
 			 */
-			curwin->w_cursor.lnum = trypos->lnum;
+			curwin->w_cursor = *trypos;
 			l = ml_get_curline();
 			if (cin_iscase(l) || cin_isscopedecl(l))
 			{
 			    ++curwin->w_cursor.lnum;
+			    curwin->w_cursor.col = 0;
 			    continue;
 			}
 		    }
@@ -7187,6 +7261,7 @@
 			    if (*l == NUL || l[STRLEN(l) - 1] != '\\')
 				break;
 			    --curwin->w_cursor.lnum;
+			    curwin->w_cursor.col = 0;
 			}
 		    }
 
@@ -7520,11 +7595,12 @@
 			     *	   case xx:  if ( asdf &&
 			     *			    asdf)
 			     */
-			    curwin->w_cursor.lnum = trypos->lnum;
+			    curwin->w_cursor = *trypos;
 			    l = ml_get_curline();
 			    if (cin_iscase(l) || cin_isscopedecl(l))
 			    {
 				++curwin->w_cursor.lnum;
+				curwin->w_cursor.col = 0;
 				continue;
 			    }
 			}
@@ -7585,13 +7661,14 @@
 				&& (trypos = find_start_brace(ind_maxcomment))
 							    != NULL) /* XXX */
 			{
-			    curwin->w_cursor.lnum = trypos->lnum;
+			    curwin->w_cursor = *trypos;
 			    /* if not "else {" check for terminated again */
 			    /* but skip block for "} else {" */
 			    l = cin_skipcomment(ml_get_curline());
 			    if (*l == '}' || !cin_iselse(l))
 				goto term_again;
 			    ++curwin->w_cursor.lnum;
+			    curwin->w_cursor.col = 0;
 			}
 		    }
 		}
@@ -7660,6 +7737,7 @@
 		if ((trypos = find_start_comment(ind_maxcomment)) != NULL)
 		{
 		    curwin->w_cursor.lnum = trypos->lnum + 1;
+		    curwin->w_cursor.col = 0;
 		    continue;
 		}
 
@@ -7670,7 +7748,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)
@@ -7710,7 +7788,7 @@
 		    if (find_last_paren(l, '(', ')')
 			    && (trypos = find_match_paren(ind_maxparen,
 						     ind_maxcomment)) != NULL)
-			curwin->w_cursor.lnum = trypos->lnum;
+			curwin->w_cursor = *trypos;
 
 		    /* For a line ending in ',' that is a continuation line go
 		     * back to the first line with a backslash:
@@ -7724,6 +7802,7 @@
 			if (*l == NUL || l[STRLEN(l) - 1] != '\\')
 			    break;
 			--curwin->w_cursor.lnum;
+			curwin->w_cursor.col = 0;
 		    }
 
 		    amount = get_indent();	    /* XXX */
@@ -7797,7 +7876,7 @@
 
 		if ((trypos = find_match_paren(ind_maxparen,
 						     ind_maxcomment)) != NULL)
-		    curwin->w_cursor.lnum = trypos->lnum;
+		    curwin->w_cursor = *trypos;
 		amount = get_indent();	    /* XXX */
 		break;
 	    }
@@ -8158,7 +8237,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 +8675,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 +8976,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 +9175,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 15:49:26.000000000 -0400
+++ vim71/src/misc2.c	2008-06-18 06:56:31.000000000 -0400
@@ -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
@@ -746,7 +751,7 @@
 #endif
 
 /*
- * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
+ * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc().
  * Use lalloc for larger blocks.
  */
     char_u *
@@ -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. */
@@ -1062,7 +1082,11 @@
     win_free_all();
 #endif
 
-    /* Free all buffers. */
+    /* Free all buffers.  Reset 'autochdir' to avoid accessing things that
+     * were freed already. */
+#ifdef FEAT_AUTOCHDIR
+    p_acd = FALSE;
+#endif
     for (buf = firstbuf; buf != NULL; )
     {
 	nextbuf = buf->b_next;
@@ -3757,9 +3781,9 @@
     char_u		ffs_filearray_cur;   /* needed for partly handled dirs */
 
     /* to store status of partly handled directories
-     * 0: we work the on this directory for the first time
+     * 0: we work on this directory for the first time
      * 1: this directory was partly searched in an earlier step
-    */
+     */
     int			ffs_stage;
 
     /* How deep are we in the directory tree?
@@ -3828,6 +3852,7 @@
  * Set the default maximum depth.
  */
 #define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
+
 /*
  * The search context:
  *   ffsc_stack_ptr:	the stack for the dirs to search
@@ -3842,7 +3867,7 @@
  *   ffsc_wc_path:	the part of the given path containing wildcards
  *   ffsc_level:	how many levels of dirs to search downwards
  *   ffsc_stopdirs_v:	array of stop directories for upward search
- *   ffsc_need_dir:	TRUE if we search for a directory
+ *   ffsc_find_what:	FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE
  */
 typedef struct ff_search_ctx_T
 {
@@ -3859,11 +3884,9 @@
      int			ffsc_level;
      char_u			**ffsc_stopdirs_v;
 #endif
-     int			ffsc_need_dir;
+     int			ffsc_find_what;
 } ff_search_ctx_T;
 
-static ff_search_ctx_T *ff_search_ctx = NULL;
-
 /* locally needed functions */
 #ifdef FEAT_PATH_EXTRA
 static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *));
@@ -3877,10 +3900,10 @@
 static int ff_wc_equal __ARGS((char_u *s1, char_u *s2));
 #endif
 
-static void ff_push __ARGS((ff_stack_T *));
-static ff_stack_T * ff_pop __ARGS((void));
-static void ff_clear __ARGS((void));
-static void ff_free_stack_element __ARGS((ff_stack_T *));
+static void ff_push __ARGS((ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr));
+static ff_stack_T *ff_pop __ARGS((ff_search_ctx_T *search_ctx));
+static void ff_clear __ARGS((ff_search_ctx_T *search_ctx));
+static void ff_free_stack_element __ARGS((ff_stack_T *stack_ptr));
 #ifdef FEAT_PATH_EXTRA
 static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int));
 #else
@@ -3941,6 +3964,9 @@
  * not related to restricts given to the '**' wildcard. If 'level' is 100
  * and you use '**200' vim_findfile() will stop after 100 levels.
  *
+ * 'filename' cannot contain wildcards!  It is used as-is, no backslashes to
+ * escape special characters.
+ *
  * If 'stopdirs' is not NULL and nothing is found downward, the search is
  * restarted on the next higher directory level. This is repeated until the
  * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the
@@ -3960,74 +3986,74 @@
  * The list of visited files/dirs can also be cleared with the function
  * vim_findfile_free_visited().
  *
- * Set the parameter 'need_dir' to TRUE if you want to search for a directory
- * instead of a file.
+ * Set the parameter 'find_what' to FINDFILE_DIR if you want to search for
+ * directories only, FINDFILE_FILE for files only, FINDFILE_BOTH for both.
  *
  * A search context returned by a previous call to vim_findfile_init() can be
- * passed in the parameter 'search_ctx'. This context is than reused and
- * reinitialized with the new parameters. The list of already viseted
+ * passed in the parameter "search_ctx_arg".  This context is reused and
+ * reinitialized with the new parameters.  The list of already visited
  * directories from this context is only deleted if the parameter
- * 'free_visited' is true. Be aware that the passed search_context is freed if
- * the reinitialization fails.
+ * "free_visited" is true.  Be aware that the passed "search_ctx_arg" is freed
+ * if the reinitialization fails.
  *
- * If you don't have a search context from a previous call 'search_ctx' must be
- * NULL.
+ * If you don't have a search context from a previous call "search_ctx_arg"
+ * must be NULL.
  *
  * This function silently ignores a few errors, vim_findfile() will have
  * limited functionality then.
  */
 /*ARGSUSED*/
     void *
-vim_findfile_init(path, filename, stopdirs, level, free_visited, need_dir,
-						search_ctx, tagfile, rel_fname)
+vim_findfile_init(path, filename, stopdirs, level, free_visited, find_what,
+					   search_ctx_arg, tagfile, rel_fname)
     char_u	*path;
     char_u	*filename;
     char_u	*stopdirs;
     int		level;
     int		free_visited;
-    int		need_dir;
-    void	*search_ctx;
+    int		find_what;
+    void	*search_ctx_arg;
     int		tagfile;
     char_u	*rel_fname;	/* file name to use for "." */
 {
 #ifdef FEAT_PATH_EXTRA
-    char_u	*wc_part;
+    char_u		*wc_part;
 #endif
-    ff_stack_T	*sptr;
+    ff_stack_T		*sptr;
+    ff_search_ctx_T	*search_ctx;
 
     /* If a search context is given by the caller, reuse it, else allocate a
      * new one.
      */
-    if (search_ctx != NULL)
-	ff_search_ctx = search_ctx;
+    if (search_ctx_arg != NULL)
+	search_ctx = search_ctx_arg;
     else
     {
-	ff_search_ctx = (ff_search_ctx_T*)alloc(
-					   (unsigned)sizeof(ff_search_ctx_T));
-	if (ff_search_ctx == NULL)
+	search_ctx = (ff_search_ctx_T*)alloc((unsigned)sizeof(ff_search_ctx_T));
+	if (search_ctx == NULL)
 	    goto error_return;
-	memset(ff_search_ctx, 0, sizeof(ff_search_ctx_T));
+	memset(search_ctx, 0, sizeof(ff_search_ctx_T));
     }
+    search_ctx->ffsc_find_what = find_what;
 
     /* clear the search context, but NOT the visited lists */
-    ff_clear();
+    ff_clear(search_ctx);
 
     /* clear visited list if wanted */
     if (free_visited == TRUE)
-	vim_findfile_free_visited(ff_search_ctx);
+	vim_findfile_free_visited(search_ctx);
     else
     {
 	/* Reuse old visited lists. Get the visited list for the given
 	 * filename. If no list for the current filename exists, creates a new
-	 * one.
-	 */
-	ff_search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
-				     &ff_search_ctx->ffsc_visited_lists_list);
-	if (ff_search_ctx->ffsc_visited_list == NULL)
+	 * one. */
+	search_ctx->ffsc_visited_list = ff_get_visited_list(filename,
+					&search_ctx->ffsc_visited_lists_list);
+	if (search_ctx->ffsc_visited_list == NULL)
 	    goto error_return;
-	ff_search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename,
-				 &ff_search_ctx->ffsc_dir_visited_lists_list);
-	if (ff_search_ctx->ffsc_dir_visited_list == NULL)
+	search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename,
+				    &search_ctx->ffsc_dir_visited_lists_list);
+	if (search_ctx->ffsc_dir_visited_list == NULL)
 	    goto error_return;
     }
 
@@ -4051,12 +4077,11 @@
 	{
 	    /* Make the start dir an absolute path name. */
 	    vim_strncpy(ff_expand_buffer, rel_fname, len);
-	    ff_search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer,
-								       FALSE);
+	    search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE);
 	}
 	else
-	    ff_search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
-	if (ff_search_ctx->ffsc_start_dir == NULL)
+	    search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
+	if (search_ctx->ffsc_start_dir == NULL)
 	    goto error_return;
 	if (*++path != NUL)
 	    ++path;
@@ -4081,8 +4106,8 @@
 	if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL)
 	    goto error_return;
 
-	ff_search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
-	if (ff_search_ctx->ffsc_start_dir == NULL)
+	search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
+	if (search_ctx->ffsc_start_dir == NULL)
 	    goto error_return;
 
 #ifdef BACKSLASH_IN_FILENAME
@@ -4090,8 +4115,8 @@
 	 * directory (but not for "//machine/dir").  Only use the drive name. */
 	if ((*path == '/' || *path == '\\')
 		&& path[1] != path[0]
-		&& ff_search_ctx->ffsc_start_dir[1] == ':')
-	    ff_search_ctx->ffsc_start_dir[2] = NUL;
+		&& search_ctx->ffsc_start_dir[1] == ':')
+	    search_ctx->ffsc_start_dir[2] = NUL;
 #endif
     }
 
@@ -4101,7 +4126,7 @@
      * If this fails (mem allocation), there is no upward search at all or a
      * stop directory is not recognized -> continue silently.
      * If stopdirs just contains a ";" or is empty,
-     * ff_search_ctx->ffsc_stopdirs_v will only contain a  NULL pointer. This
+     * search_ctx->ffsc_stopdirs_v will only contain a  NULL pointer. This
      * is handled as unlimited upward search.  See function
      * ff_path_in_stoplist() for details.
      */
@@ -4114,10 +4139,10 @@
 	    walker++;
 
 	dircount = 1;
-	ff_search_ctx->ffsc_stopdirs_v =
-	    (char_u **)alloc((unsigned)sizeof(char_u *));
+	search_ctx->ffsc_stopdirs_v =
+				 (char_u **)alloc((unsigned)sizeof(char_u *));
 
-	if (ff_search_ctx->ffsc_stopdirs_v != NULL)
+	if (search_ctx->ffsc_stopdirs_v != NULL)
 	{
 	    do
 	    {
@@ -4125,37 +4150,37 @@
 		void	*ptr;
 
 		helper = walker;
-		ptr = vim_realloc(ff_search_ctx->ffsc_stopdirs_v,
+		ptr = vim_realloc(search_ctx->ffsc_stopdirs_v,
 					   (dircount + 1) * sizeof(char_u *));
 		if (ptr)
-		    ff_search_ctx->ffsc_stopdirs_v = ptr;
+		    search_ctx->ffsc_stopdirs_v = ptr;
 		else
 		    /* ignore, keep what we have and continue */
 		    break;
 		walker = vim_strchr(walker, ';');
 		if (walker)
 		{
-		    ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
-			vim_strnsave(helper, (int)(walker - helper));
+		    search_ctx->ffsc_stopdirs_v[dircount-1] =
+				 vim_strnsave(helper, (int)(walker - helper));
 		    walker++;
 		}
 		else
 		    /* this might be "", which means ascent till top
 		     * of directory tree.
 		     */
-		    ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
-			vim_strsave(helper);
+		    search_ctx->ffsc_stopdirs_v[dircount-1] =
+							  vim_strsave(helper);
 
 		dircount++;
 
 	    } while (walker != NULL);
-	    ff_search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
+	    search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
 	}
     }
 #endif
 
 #ifdef FEAT_PATH_EXTRA
-    ff_search_ctx->ffsc_level = level;
+    search_ctx->ffsc_level = level;
 
     /* split into:
      *  -fix path
@@ -4169,8 +4194,7 @@
 	char	*errpt;
 
 	/* save the fix part of the path */
-	ff_search_ctx->ffsc_fix_path = vim_strnsave(path,
-						       (int)(wc_part - path));
+	search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path));
 
 	/*
 	 * copy wc_path and add restricts to the '**' wildcard.
@@ -4209,47 +4233,47 @@
 		ff_expand_buffer[len++] = *wc_part++;
 	}
 	ff_expand_buffer[len] = NUL;
-	ff_search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer);
+	search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer);
 
-	if (ff_search_ctx->ffsc_wc_path == NULL)
+	if (search_ctx->ffsc_wc_path == NULL)
 	    goto error_return;
     }
     else
 #endif
-	ff_search_ctx->ffsc_fix_path = vim_strsave(path);
+	search_ctx->ffsc_fix_path = vim_strsave(path);
 
-    if (ff_search_ctx->ffsc_start_dir == NULL)
+    if (search_ctx->ffsc_start_dir == NULL)
     {
 	/* store the fix part as startdir.
 	 * This is needed if the parameter path is fully qualified.
 	 */
-	ff_search_ctx->ffsc_start_dir = vim_strsave(ff_search_ctx->ffsc_fix_path);
-	if (ff_search_ctx->ffsc_start_dir)
-	    ff_search_ctx->ffsc_fix_path[0] = NUL;
+	search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path);
+	if (search_ctx->ffsc_start_dir)
+	    search_ctx->ffsc_fix_path[0] = NUL;
     }
 
     /* create an absolute path */
-    STRCPY(ff_expand_buffer, ff_search_ctx->ffsc_start_dir);
+    STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir);
     add_pathsep(ff_expand_buffer);
-    STRCAT(ff_expand_buffer, ff_search_ctx->ffsc_fix_path);
+    STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path);
     add_pathsep(ff_expand_buffer);
 
     sptr = ff_create_stack_element(ff_expand_buffer,
 #ifdef FEAT_PATH_EXTRA
-	    ff_search_ctx->ffsc_wc_path,
+	    search_ctx->ffsc_wc_path,
 #endif
 	    level, 0);
 
     if (sptr == NULL)
 	goto error_return;
 
-    ff_push(sptr);
+    ff_push(search_ctx, sptr);
 
-    ff_search_ctx->ffsc_file_to_search = vim_strsave(filename);
-    if (ff_search_ctx->ffsc_file_to_search == NULL)
+    search_ctx->ffsc_file_to_search = vim_strsave(filename);
+    if (search_ctx->ffsc_file_to_search == NULL)
 	goto error_return;
 
-    return ff_search_ctx;
+    return search_ctx;
 
 error_return:
     /*
@@ -4257,7 +4281,7 @@
      * Even when the caller gave us a (perhaps valid) context we free it here,
      * as we might have already destroyed it.
      */
-    vim_findfile_cleanup(ff_search_ctx);
+    vim_findfile_cleanup(search_ctx);
     return NULL;
 }
 
@@ -4294,7 +4318,9 @@
 }
 #endif
 
-/* Clean up the given search context. Can handle a NULL pointer */
+/*
+ * Clean up the given search context. Can handle a NULL pointer.
+ */
     void
 vim_findfile_cleanup(ctx)
     void	*ctx;
@@ -4302,12 +4328,9 @@
     if (ctx == NULL)
 	return;
 
-    ff_search_ctx = ctx;
-
     vim_findfile_free_visited(ctx);
-    ff_clear();
+    ff_clear(ctx);
     vim_free(ctx);
-    ff_search_ctx = NULL;
 }
 
 /*
@@ -4323,15 +4346,15 @@
  * top of the list).
  */
     char_u *
-vim_findfile(search_ctx)
-    void	*search_ctx;
+vim_findfile(search_ctx_arg)
+    void	*search_ctx_arg;
 {
     char_u	*file_path;
 #ifdef FEAT_PATH_EXTRA
     char_u	*rest_of_wildcards;
     char_u	*path_end = NULL;
 #endif
-    ff_stack_T	*ctx;
+    ff_stack_T	*stackp;
 #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA)
     int		len;
 #endif
@@ -4340,11 +4363,12 @@
 #ifdef FEAT_SEARCHPATH
     char_u	*suf;
 #endif
+    ff_search_ctx_T *search_ctx;
 
-    if (search_ctx == NULL)
+    if (search_ctx_arg == NULL)
 	return NULL;
 
-    ff_search_ctx = (ff_search_ctx_T*)search_ctx;
+    search_ctx = (ff_search_ctx_T *)search_ctx_arg;
 
     /*
      * filepath is used as buffer for various actions and as the storage to
@@ -4355,8 +4379,9 @@
 
 #ifdef FEAT_PATH_EXTRA
     /* store the end of the start dir -- needed for upward search */
-    if (ff_search_ctx->ffsc_start_dir != NULL)
-	path_end = &ff_search_ctx->ffsc_start_dir[STRLEN(ff_search_ctx->ffsc_start_dir)];
+    if (search_ctx->ffsc_start_dir != NULL)
+	path_end = &search_ctx->ffsc_start_dir[
+					  STRLEN(search_ctx->ffsc_start_dir)];
 #endif
 
 #ifdef FEAT_PATH_EXTRA
@@ -4373,8 +4398,8 @@
 		break;
 
 	    /* get directory to work on from stack */
-	    ctx = ff_pop();
-	    if (ctx == NULL)
+	    stackp = ff_pop(search_ctx);
+	    if (stackp == NULL)
 		break;
 
 	    /*
@@ -4394,14 +4419,14 @@
 	     *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
 	     *
 	     * This check is only needed for directories we work on for the
-	     * first time (hence ctx->ff_filearray == NULL)
+	     * first time (hence stackp->ff_filearray == NULL)
 	     */
-	    if (ctx->ffs_filearray == NULL
-		    && ff_check_visited(&ff_search_ctx->ffsc_dir_visited_list
+	    if (stackp->ffs_filearray == NULL
+		    && ff_check_visited(&search_ctx->ffsc_dir_visited_list
 							  ->ffvl_visited_list,
-			ctx->ffs_fix_path
+			stackp->ffs_fix_path
 #ifdef FEAT_PATH_EXTRA
-			, ctx->ffs_wc_path
+			, stackp->ffs_wc_path
 #endif
 			) == FAIL)
 	    {
@@ -4410,13 +4435,13 @@
 		{
 		    verbose_enter_scroll();
 		    smsg((char_u *)"Already Searched: %s (%s)",
-					   ctx->ffs_fix_path, ctx->ffs_wc_path);
+				   stackp->ffs_fix_path, stackp->ffs_wc_path);
 		    /* don't overwrite this either */
 		    msg_puts((char_u *)"\n");
 		    verbose_leave_scroll();
 		}
 #endif
-		ff_free_stack_element(ctx);
+		ff_free_stack_element(stackp);
 		continue;
 	    }
 #ifdef FF_VERBOSE
@@ -4424,7 +4449,7 @@
 	    {
 		verbose_enter_scroll();
 		smsg((char_u *)"Searching: %s (%s)",
-					 ctx->ffs_fix_path, ctx->ffs_wc_path);
+				   stackp->ffs_fix_path, stackp->ffs_wc_path);
 		/* don't overwrite this either */
 		msg_puts((char_u *)"\n");
 		verbose_leave_scroll();
@@ -4432,9 +4457,9 @@
 #endif
 
 	    /* check depth */
-	    if (ctx->ffs_level <= 0)
+	    if (stackp->ffs_level <= 0)
 	    {
-		ff_free_stack_element(ctx);
+		ff_free_stack_element(stackp);
 		continue;
 	    }
 
@@ -4446,7 +4471,7 @@
 	     * and all possible expands are returned in one array. We use this
 	     * to handle the expansion of '**' into an empty string.
 	     */
-	    if (ctx->ffs_filearray == NULL)
+	    if (stackp->ffs_filearray == NULL)
 	    {
 		char_u *dirptrs[2];
 
@@ -4457,19 +4482,19 @@
 		dirptrs[1] = NULL;
 
 		/* if we have a start dir copy it in */
-		if (!vim_isAbsName(ctx->ffs_fix_path)
-			&& ff_search_ctx->ffsc_start_dir)
+		if (!vim_isAbsName(stackp->ffs_fix_path)
+						&& search_ctx->ffsc_start_dir)
 		{
-		    STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
+		    STRCPY(file_path, search_ctx->ffsc_start_dir);
 		    add_pathsep(file_path);
 		}
 
 		/* append the fix part of the search path */
-		STRCAT(file_path, ctx->ffs_fix_path);
+		STRCAT(file_path, stackp->ffs_fix_path);
 		add_pathsep(file_path);
 
 #ifdef FEAT_PATH_EXTRA
-		rest_of_wildcards = ctx->ffs_wc_path;
+		rest_of_wildcards = stackp->ffs_wc_path;
 		if (*rest_of_wildcards != NUL)
 		{
 		    len = (int)STRLEN(file_path);
@@ -4496,11 +4521,11 @@
 			else
 			    rest_of_wildcards += 3;
 
-			if (ctx->ffs_star_star_empty == 0)
+			if (stackp->ffs_star_star_empty == 0)
 			{
 			    /* if not done before, expand '**' to empty */
-			    ctx->ffs_star_star_empty = 1;
-			    dirptrs[1] = ctx->ffs_fix_path;
+			    stackp->ffs_star_star_empty = 1;
+			    dirptrs[1] = stackp->ffs_fix_path;
 			}
 		    }
 
@@ -4527,30 +4552,31 @@
 		 */
 		if (path_with_url(dirptrs[0]))
 		{
-		    ctx->ffs_filearray = (char_u **)
+		    stackp->ffs_filearray = (char_u **)
 					      alloc((unsigned)sizeof(char *));
-		    if (ctx->ffs_filearray != NULL
-			    && (ctx->ffs_filearray[0]
+		    if (stackp->ffs_filearray != NULL
+			    && (stackp->ffs_filearray[0]
 				= vim_strsave(dirptrs[0])) != NULL)
-			ctx->ffs_filearray_size = 1;
+			stackp->ffs_filearray_size = 1;
 		    else
-			ctx->ffs_filearray_size = 0;
+			stackp->ffs_filearray_size = 0;
 		}
 		else
 		    expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
-			    &ctx->ffs_filearray_size,
-			    &ctx->ffs_filearray,
+			    &stackp->ffs_filearray_size,
+			    &stackp->ffs_filearray,
 			    EW_DIR|EW_ADDSLASH|EW_SILENT);
 
-		ctx->ffs_filearray_cur = 0;
-		ctx->ffs_stage = 0;
+		stackp->ffs_filearray_cur = 0;
+		stackp->ffs_stage = 0;
 	    }
 #ifdef FEAT_PATH_EXTRA
 	    else
-		rest_of_wildcards = &ctx->ffs_wc_path[STRLEN(ctx->ffs_wc_path)];
+		rest_of_wildcards = &stackp->ffs_wc_path[
+						 STRLEN(stackp->ffs_wc_path)];
 #endif
 
-	    if (ctx->ffs_stage == 0)
+	    if (stackp->ffs_stage == 0)
 	    {
 		/* this is the first time we work on this directory */
 #ifdef FEAT_PATH_EXTRA
@@ -4561,18 +4587,18 @@
 		     * we don't have further wildcards to expand, so we have to
 		     * check for the final file now
 		     */
-		    for (i = ctx->ffs_filearray_cur;
-					     i < ctx->ffs_filearray_size; ++i)
+		    for (i = stackp->ffs_filearray_cur;
+					  i < stackp->ffs_filearray_size; ++i)
 		    {
-			if (!path_with_url(ctx->ffs_filearray[i])
-					 && !mch_isdir(ctx->ffs_filearray[i]))
+			if (!path_with_url(stackp->ffs_filearray[i])
+				      && !mch_isdir(stackp->ffs_filearray[i]))
 			    continue;   /* not a directory */
 
 			/* prepare the filename to be checked for existance
 			 * below */
-			STRCPY(file_path, ctx->ffs_filearray[i]);
+			STRCPY(file_path, stackp->ffs_filearray[i]);
 			add_pathsep(file_path);
-			STRCAT(file_path, ff_search_ctx->ffsc_file_to_search);
+			STRCAT(file_path, search_ctx->ffsc_file_to_search);
 
 			/*
 			 * Try without extra suffix and then with suffixes
@@ -4586,12 +4612,15 @@
 			{
 			    /* if file exists and we didn't already find it */
 			    if ((path_with_url(file_path)
-					|| (mch_getperm(file_path) >= 0
-					    && (!ff_search_ctx->ffsc_need_dir
-						|| mch_isdir(file_path))))
+				  || (mch_getperm(file_path) >= 0
+				      && (search_ctx->ffsc_find_what
+							      == FINDFILE_BOTH
+					  || ((search_ctx->ffsc_find_what
+							      == FINDFILE_DIR)
+						   == mch_isdir(file_path)))))
 #ifndef FF_VERBOSE
 				    && (ff_check_visited(
-					    &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
+					    &search_ctx->ffsc_visited_list->ffvl_visited_list,
 					    file_path
 #ifdef FEAT_PATH_EXTRA
 					    , (char_u *)""
@@ -4602,7 +4631,7 @@
 			    {
 #ifdef FF_VERBOSE
 				if (ff_check_visited(
-					    &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
+					    &search_ctx->ffsc_visited_list->ffvl_visited_list,
 					    file_path
 #ifdef FEAT_PATH_EXTRA
 					    , (char_u *)""
@@ -4623,8 +4652,8 @@
 #endif
 
 				/* push dir to examine rest of subdirs later */
-				ctx->ffs_filearray_cur = i + 1;
-				ff_push(ctx);
+				stackp->ffs_filearray_cur = i + 1;
+				ff_push(search_ctx, stackp);
 
 				simplify_filename(file_path);
 				if (mch_dirname(ff_expand_buffer, MAXPATHL)
@@ -4666,19 +4695,22 @@
 		     * still wildcards left, push the directories for further
 		     * search
 		     */
-		    for (i = ctx->ffs_filearray_cur;
-					     i < ctx->ffs_filearray_size; ++i)
+		    for (i = stackp->ffs_filearray_cur;
+					  i < stackp->ffs_filearray_size; ++i)
 		    {
-			if (!mch_isdir(ctx->ffs_filearray[i]))
+			if (!mch_isdir(stackp->ffs_filearray[i]))
 			    continue;	/* not a directory */
 
-			ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
-				      rest_of_wildcards, ctx->ffs_level - 1, 0));
+			ff_push(search_ctx,
+				ff_create_stack_element(
+						     stackp->ffs_filearray[i],
+						     rest_of_wildcards,
+						     stackp->ffs_level - 1, 0));
 		    }
 		}
 #endif
-		ctx->ffs_filearray_cur = 0;
-		ctx->ffs_stage = 1;
+		stackp->ffs_filearray_cur = 0;
+		stackp->ffs_stage = 1;
 	    }
 
 #ifdef FEAT_PATH_EXTRA
@@ -4686,23 +4718,25 @@
 	     * if wildcards contains '**' we have to descent till we reach the
 	     * leaves of the directory tree.
 	     */
-	    if (STRNCMP(ctx->ffs_wc_path, "**", 2) == 0)
+	    if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0)
 	    {
-		for (i = ctx->ffs_filearray_cur;
-					     i < ctx->ffs_filearray_size; ++i)
+		for (i = stackp->ffs_filearray_cur;
+					  i < stackp->ffs_filearray_size; ++i)
 		{
-		    if (fnamecmp(ctx->ffs_filearray[i], ctx->ffs_fix_path) == 0)
+		    if (fnamecmp(stackp->ffs_filearray[i],
+						   stackp->ffs_fix_path) == 0)
 			continue; /* don't repush same directory */
-		    if (!mch_isdir(ctx->ffs_filearray[i]))
+		    if (!mch_isdir(stackp->ffs_filearray[i]))
 			continue;   /* not a directory */
-		    ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
-				ctx->ffs_wc_path, ctx->ffs_level - 1, 1));
+		    ff_push(search_ctx,
+			    ff_create_stack_element(stackp->ffs_filearray[i],
+				stackp->ffs_wc_path, stackp->ffs_level - 1, 1));
 		}
 	    }
 #endif
 
 	    /* we are done with the current directory */
-	    ff_free_stack_element(ctx);
+	    ff_free_stack_element(stackp);
 
 	}
 
@@ -4710,40 +4744,40 @@
 	/* If we reached this, we didn't find anything downwards.
 	 * Let's check if we should do an upward search.
 	 */
-	if (ff_search_ctx->ffsc_start_dir
-		&& ff_search_ctx->ffsc_stopdirs_v != NULL && !got_int)
+	if (search_ctx->ffsc_start_dir
+		&& search_ctx->ffsc_stopdirs_v != NULL && !got_int)
 	{
 	    ff_stack_T  *sptr;
 
 	    /* is the last starting directory in the stop list? */
-	    if (ff_path_in_stoplist(ff_search_ctx->ffsc_start_dir,
-		       (int)(path_end - ff_search_ctx->ffsc_start_dir),
-		       ff_search_ctx->ffsc_stopdirs_v) == TRUE)
+	    if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
+		       (int)(path_end - search_ctx->ffsc_start_dir),
+		       search_ctx->ffsc_stopdirs_v) == TRUE)
 		break;
 
 	    /* cut of last dir */
-	    while (path_end > ff_search_ctx->ffsc_start_dir
-		    && vim_ispathsep(*path_end))
+	    while (path_end > search_ctx->ffsc_start_dir
+						  && vim_ispathsep(*path_end))
 		path_end--;
-	    while (path_end > ff_search_ctx->ffsc_start_dir
-		    && !vim_ispathsep(path_end[-1]))
+	    while (path_end > search_ctx->ffsc_start_dir
+					      && !vim_ispathsep(path_end[-1]))
 		path_end--;
 	    *path_end = 0;
 	    path_end--;
 
-	    if (*ff_search_ctx->ffsc_start_dir == 0)
+	    if (*search_ctx->ffsc_start_dir == 0)
 		break;
 
-	    STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
+	    STRCPY(file_path, search_ctx->ffsc_start_dir);
 	    add_pathsep(file_path);
-	    STRCAT(file_path, ff_search_ctx->ffsc_fix_path);
+	    STRCAT(file_path, search_ctx->ffsc_fix_path);
 
 	    /* create a new stack entry */
 	    sptr = ff_create_stack_element(file_path,
-		    ff_search_ctx->ffsc_wc_path, ff_search_ctx->ffsc_level, 0);
+		    search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0);
 	    if (sptr == NULL)
 		break;
-	    ff_push(sptr);
+	    ff_push(search_ctx, sptr);
 	}
 	else
 	    break;
@@ -4759,16 +4793,17 @@
  * Can handle it if the passed search_context is NULL;
  */
     void
-vim_findfile_free_visited(search_ctx)
-    void	*search_ctx;
+vim_findfile_free_visited(search_ctx_arg)
+    void	*search_ctx_arg;
 {
-    if (search_ctx == NULL)
-	return;
+    ff_search_ctx_T *search_ctx;
 
-    ff_search_ctx = (ff_search_ctx_T *)search_ctx;
+    if (search_ctx_arg == NULL)
+	return;
 
-    vim_findfile_free_visited_list(&ff_search_ctx->ffsc_visited_lists_list);
-    vim_findfile_free_visited_list(&ff_search_ctx->ffsc_dir_visited_lists_list);
+    search_ctx = (ff_search_ctx_T *)search_ctx_arg;
+    vim_findfile_free_visited_list(&search_ctx->ffsc_visited_lists_list);
+    vim_findfile_free_visited_list(&search_ctx->ffsc_dir_visited_lists_list);
 }
 
     static void
@@ -5083,33 +5118,35 @@
 }
 
 /*
- * push a dir on the directory stack
+ * Push a dir on the directory stack.
  */
     static void
-ff_push(ctx)
-    ff_stack_T *ctx;
+ff_push(search_ctx, stack_ptr)
+    ff_search_ctx_T *search_ctx;
+    ff_stack_T	    *stack_ptr;
 {
     /* check for NULL pointer, not to return an error to the user, but
      * to prevent a crash */
-    if (ctx != NULL)
+    if (stack_ptr != NULL)
     {
-	ctx->ffs_prev   = ff_search_ctx->ffsc_stack_ptr;
-	ff_search_ctx->ffsc_stack_ptr = ctx;
+	stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr;
+	search_ctx->ffsc_stack_ptr = stack_ptr;
     }
 }
 
 /*
- * pop a dir from the directory stack
- * returns NULL if stack is empty
+ * Pop a dir from the directory stack.
+ * Returns NULL if stack is empty.
  */
     static ff_stack_T *
-ff_pop()
+ff_pop(search_ctx)
+    ff_search_ctx_T *search_ctx;
 {
     ff_stack_T  *sptr;
 
-    sptr = ff_search_ctx->ffsc_stack_ptr;
-    if (ff_search_ctx->ffsc_stack_ptr != NULL)
-	ff_search_ctx->ffsc_stack_ptr = ff_search_ctx->ffsc_stack_ptr->ffs_prev;
+    sptr = search_ctx->ffsc_stack_ptr;
+    if (search_ctx->ffsc_stack_ptr != NULL)
+	search_ctx->ffsc_stack_ptr = search_ctx->ffsc_stack_ptr->ffs_prev;
 
     return sptr;
 }
@@ -5118,62 +5155,63 @@
  * free the given stack element
  */
     static void
-ff_free_stack_element(ctx)
-    ff_stack_T  *ctx;
+ff_free_stack_element(stack_ptr)
+    ff_stack_T  *stack_ptr;
 {
     /* vim_free handles possible NULL pointers */
-    vim_free(ctx->ffs_fix_path);
+    vim_free(stack_ptr->ffs_fix_path);
 #ifdef FEAT_PATH_EXTRA
-    vim_free(ctx->ffs_wc_path);
+    vim_free(stack_ptr->ffs_wc_path);
 #endif
 
-    if (ctx->ffs_filearray != NULL)
-	FreeWild(ctx->ffs_filearray_size, ctx->ffs_filearray);
+    if (stack_ptr->ffs_filearray != NULL)
+	FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray);
 
-    vim_free(ctx);
+    vim_free(stack_ptr);
 }
 
 /*
- * clear the search context
+ * Clear the search context, but NOT the visited list.
  */
     static void
-ff_clear()
+ff_clear(search_ctx)
+    ff_search_ctx_T *search_ctx;
 {
     ff_stack_T   *sptr;
 
     /* clear up stack */
-    while ((sptr = ff_pop()) != NULL)
+    while ((sptr = ff_pop(search_ctx)) != NULL)
 	ff_free_stack_element(sptr);
 
-    vim_free(ff_search_ctx->ffsc_file_to_search);
-    vim_free(ff_search_ctx->ffsc_start_dir);
-    vim_free(ff_search_ctx->ffsc_fix_path);
+    vim_free(search_ctx->ffsc_file_to_search);
+    vim_free(search_ctx->ffsc_start_dir);
+    vim_free(search_ctx->ffsc_fix_path);
 #ifdef FEAT_PATH_EXTRA
-    vim_free(ff_search_ctx->ffsc_wc_path);
+    vim_free(search_ctx->ffsc_wc_path);
 #endif
 
 #ifdef FEAT_PATH_EXTRA
-    if (ff_search_ctx->ffsc_stopdirs_v != NULL)
+    if (search_ctx->ffsc_stopdirs_v != NULL)
     {
 	int  i = 0;
 
-	while (ff_search_ctx->ffsc_stopdirs_v[i] != NULL)
+	while (search_ctx->ffsc_stopdirs_v[i] != NULL)
 	{
-	    vim_free(ff_search_ctx->ffsc_stopdirs_v[i]);
+	    vim_free(search_ctx->ffsc_stopdirs_v[i]);
 	    i++;
 	}
-	vim_free(ff_search_ctx->ffsc_stopdirs_v);
+	vim_free(search_ctx->ffsc_stopdirs_v);
     }
-    ff_search_ctx->ffsc_stopdirs_v = NULL;
+    search_ctx->ffsc_stopdirs_v = NULL;
 #endif
 
     /* reset everything */
-    ff_search_ctx->ffsc_file_to_search	= NULL;
-    ff_search_ctx->ffsc_start_dir	= NULL;
-    ff_search_ctx->ffsc_fix_path	= NULL;
+    search_ctx->ffsc_file_to_search = NULL;
+    search_ctx->ffsc_start_dir = NULL;
+    search_ctx->ffsc_fix_path = NULL;
 #ifdef FEAT_PATH_EXTRA
-    ff_search_ctx->ffsc_wc_path		= NULL;
-    ff_search_ctx->ffsc_level		= 0;
+    search_ctx->ffsc_wc_path = NULL;
+    search_ctx->ffsc_level = 0;
 #endif
 }
 
@@ -5222,7 +5260,7 @@
 
 #if defined(FEAT_SEARCHPATH) || defined(PROTO)
 /*
- * Find the file name "ptr[len]" in the path.
+ * Find the file name "ptr[len]" in the path.  Also finds directory names.
  *
  * On the first call set the parameter 'first' to TRUE to initialize
  * the search.  For repeating calls to FALSE.
@@ -5256,7 +5294,7 @@
 {
     return find_file_in_path_option(ptr, len, options, first,
 	    *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
-	    FALSE, rel_fname, curbuf->b_p_sua);
+	    FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
 }
 
 static char_u	*ff_file_to_find = NULL;
@@ -5289,17 +5327,17 @@
     char_u	*rel_fname;	/* file name searching relative to */
 {
     return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
-					       TRUE, rel_fname, (char_u *)"");
+				       FINDFILE_DIR, rel_fname, (char_u *)"");
 }
 
     char_u *
-find_file_in_path_option(ptr, len, options, first, path_option, need_dir, rel_fname, suffixes)
+find_file_in_path_option(ptr, len, options, first, path_option, find_what, rel_fname, suffixes)
     char_u	*ptr;		/* file name */
     int		len;		/* length of file name */
     int		options;
     int		first;		/* use count'th matching file name */
     char_u	*path_option;	/* p_path or p_cdpath */
-    int		need_dir;	/* looking for directory name */
+    int		find_what;	/* FINDFILE_FILE, _DIR or _BOTH */
     char_u	*rel_fname;	/* file name we are looking relative to. */
     char_u	*suffixes;	/* list of suffixes, 'suffixesadd' option */
 {
@@ -5401,12 +5439,14 @@
 #ifdef DJGPP
 			    /* "C:" by itself will fail for mch_getperm(),
 			     * assume it's always valid. */
-			    (need_dir && NameBuff[0] != NUL
+			    (find_what != FINDFILE_FILE && NameBuff[0] != NUL
 				  && NameBuff[1] == ':'
 				  && NameBuff[2] == NUL) ||
 #endif
 			    (mch_getperm(NameBuff) >= 0
-				       && (!need_dir || mch_isdir(NameBuff))))
+			     && (find_what == FINDFILE_BOTH
+				 || ((find_what == FINDFILE_DIR)
+						    == mch_isdir(NameBuff)))))
 		    {
 			file_name = vim_strsave(NameBuff);
 			goto theend;
@@ -5437,9 +5477,7 @@
 	{
 	    if (did_findfile_init)
 	    {
-		ff_search_ctx->ffsc_need_dir = need_dir;
 		file_name = vim_findfile(fdip_search_ctx);
-		ff_search_ctx->ffsc_need_dir = FALSE;
 		if (file_name != NULL)
 		    break;
 
@@ -5472,7 +5510,7 @@
 		r_ptr = NULL;
 #endif
 		fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
-					    r_ptr, 100, FALSE, TRUE,
+					    r_ptr, 100, FALSE, find_what,
 					   fdip_search_ctx, FALSE, rel_fname);
 		if (fdip_search_ctx != NULL)
 		    did_findfile_init = TRUE;
@@ -5484,7 +5522,7 @@
     {
 	if (first == TRUE)
 	{
-	    if (need_dir)
+	    if (find_what == FINDFILE_DIR)
 		EMSG2(_("E344: Can't find directory \"%s\" in cdpath"),
 			ff_file_to_find);
 	    else
@@ -5493,7 +5531,7 @@
 	}
 	else
 	{
-	    if (need_dir)
+	    if (find_what == FINDFILE_DIR)
 		EMSG2(_("E346: No more directory \"%s\" found in cdpath"),
 			ff_file_to_find);
 	    else
@@ -5922,7 +5960,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 15:51:36.000000000 -0400
+++ vim71/src/netbeans.c	2008-06-18 06:57:00.000000000 -0400
@@ -16,6 +16,10 @@
  * See ":help netbeans-protocol" for explanation.
  */
 
+#if defined(MSDOS) || defined(MSWIN)
+# include "vimio.h"	/* for mch_open(), must be before vim.h */
+#endif
+
 #include "vim.h"
 
 #if defined(FEAT_NETBEANS_INTG) || defined(PROTO)
@@ -1204,6 +1208,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 +1423,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 +1474,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 +1554,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;
@@ -1869,13 +1978,16 @@
 	}
 	else if (streq((char *)cmd, "setModified"))
 	{
+	    int prev_b_changed;
+
 	    if (buf == NULL || buf->bufp == NULL)
 	    {
 /*		EMSG("E646: null bufp in setModified"); */
 		return FAIL;
 	    }
+	    prev_b_changed = buf->bufp->b_changed;
 	    if (streq((char *)args, "T"))
-		buf->bufp->b_changed = 1;
+		buf->bufp->b_changed = TRUE;
 	    else
 	    {
 		struct stat	st;
@@ -1885,9 +1997,20 @@
 		if (buf->bufp->b_ffname != NULL
 			&& mch_stat((char *)buf->bufp->b_ffname, &st) >= 0)
 		    buf_store_time(buf->bufp, &st, buf->bufp->b_ffname);
-		buf->bufp->b_changed = 0;
+		buf->bufp->b_changed = FALSE;
 	    }
 	    buf->modified = buf->bufp->b_changed;
+	    if (prev_b_changed != buf->bufp->b_changed)
+	    {
+#ifdef FEAT_WINDOWS
+		check_status(buf->bufp);
+		redraw_tabline = TRUE;
+#endif
+#ifdef FEAT_TITLE
+		maketitle();
+#endif
+		update_screen(0);
+	    }
 /* =====================================================================*/
 	}
 	else if (streq((char *)cmd, "setModtime"))
@@ -2374,8 +2497,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 15:34:39.000000000 -0400
+++ vim71/src/normal.c	2008-06-18 06:56:27.000000000 -0400
@@ -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.
  *
@@ -8292,6 +8345,7 @@
     int		n;
     int		word_end;
     int		flag = FALSE;
+    pos_T	startpos = curwin->w_cursor;
 
     /*
      * Set inclusive for the "E" and "e" command.
@@ -8352,12 +8406,10 @@
     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. Unless we
+     * didn't move it forward. */
+    if (lt(startpos, curwin->w_cursor))
+	adjust_cursor(cap->oap);
 
     if (n == FAIL && cap->oap->op_type == OP_NOP)
 	clearopbeep(cap->oap);
@@ -8374,6 +8426,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 15:33:47.000000000 -0400
+++ vim71/src/ops.c	2008-06-18 06:56:15.000000000 -0400
@@ -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)
@@ -691,6 +692,7 @@
 	    }
 	}
 	++curwin->w_cursor.lnum;
+	curwin->w_cursor.col = 0;  /* make sure it's valid */
     }
 
     /* put cursor on first non-blank of indented line */
@@ -927,15 +929,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 +969,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 +979,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 +2185,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 +2197,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 +2212,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 +2243,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 +2308,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 +2359,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 +2499,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 +2511,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 +2568,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 +2615,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 +2633,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 +3452,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;
@@ -4330,7 +4380,7 @@
     if (keep_cursor)
 	saved_cursor = oap->cursor_start;
 
-    format_lines(oap->line_count);
+    format_lines(oap->line_count, keep_cursor);
 
     /*
      * Leave the cursor at the first non-blank of the last formatted line.
@@ -4445,8 +4495,9 @@
  * first line.
  */
     void
-format_lines(line_count)
+format_lines(line_count, avoid_fex)
     linenr_T	line_count;
+    int		avoid_fex;		/* don't use 'formatexpr' */
 {
     int		max_len;
     int		is_not_par;		/* current line not part of parag. */
@@ -4616,7 +4667,7 @@
 #ifdef FEAT_COMMENTS
 			+ (do_comments ? INSCHAR_DO_COM : 0)
 #endif
-			, second_indent);
+			+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
 		State = old_State;
 		p_smd = smd_save;
 		second_indent = -1;
diff -Naur vim71.orig/src/option.c vim71/src/option.c
--- vim71.orig/src/option.c	2007-05-01 07:26:10.000000000 -0400
+++ vim71/src/option.c	2008-06-18 06:57:01.000000000 -0400
@@ -243,7 +243,8 @@
 /* WV_ and BV_ values get typecasted to this for the "indir" field */
 typedef enum
 {
-    PV_NONE = 0
+    PV_NONE = 0,
+    PV_MAXVAL = 0xffff    /* to avoid warnings for value out of range */
 } idopt_T;
 
 /*
@@ -427,6 +428,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 +776,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 +1520,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}
@@ -1835,8 +1840,9 @@
 			    },
     {"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,
+			    {(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp",
+				(char_u *)0L}},
+    {"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 +1993,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 +4641,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 +5005,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 +5673,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 +6361,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 +7131,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 +7833,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 +8239,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 +8550,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 +8659,7 @@
 		}
 	    }
 	}
+    }
     return OK;
 }
 
@@ -8667,7 +8714,7 @@
 	{
 	    s = *valuep;
 	    while (*s != NUL)
-		if (fputs((char *)str2special(&s, FALSE), fd) < 0)
+		if (put_escstr(fd, str2special(&s, FALSE), 2) == FAIL)
 		    return FAIL;
 	}
 	else if (expand)
@@ -8715,6 +8762,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 +10634,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 +10649,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 +10669,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 15:23:03.000000000 -0400
+++ vim71/src/option.h	2008-06-18 06:55:25.000000000 -0400
@@ -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 15:41:58.000000000 -0400
+++ vim71/src/os_unix.c	2008-06-18 06:56:39.000000000 -0400
@@ -45,6 +45,11 @@
 # include <X11/SM/SMlib.h>
 #endif
 
+#ifdef HAVE_SELINUX
+# include <selinux/selinux.h>
+static int selinux_enabled = -1;
+#endif
+
 /*
  * Use this prototype for select, some include files have a wrong prototype
  */
@@ -195,6 +200,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 */
 
@@ -268,8 +274,9 @@
 #ifdef SIGVTALRM
     {SIGVTALRM,	    "VTALRM",	TRUE},
 #endif
-#if defined(SIGPROF) && !defined(FEAT_MZSCHEME)
-    /* MzScheme uses SIGPROF for its own needs */
+#if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
+    /* MzScheme uses SIGPROF for its own needs; On Linux with profiling
+     * this makes Vim exit.  WE_ARE_PROFILING is defined in Makefile.  */
     {SIGPROF,	    "PROF",	TRUE},
 #endif
 #ifdef SIGXCPU
@@ -310,7 +317,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 +545,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 +611,7 @@
 #endif
 
 	settmode(old_tmode);
+	in_mch_delay = FALSE;
     }
     else
 	WaitForChar(msec);
@@ -753,7 +763,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 +932,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 +1585,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 +2440,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 +2519,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
 }
 
 /*
@@ -2536,6 +2562,62 @@
 } vim_acl_solaris_T;
 # endif
 
+#if defined(HAVE_SELINUX) || defined(PROTO)
+/*
+ * Copy security info from "from_file" to "to_file".
+ */
+    void
+mch_copy_sec(from_file, to_file)
+    char_u	*from_file;
+    char_u	*to_file;
+{
+    if (from_file == NULL)
+	return;
+
+    if (selinux_enabled == -1)
+	selinux_enabled = is_selinux_enabled();
+
+    if (selinux_enabled > 0)
+    {
+	security_context_t from_context = NULL;
+	security_context_t to_context = NULL;
+
+	if (getfilecon((char *)from_file, &from_context) < 0)
+	{
+	    /* If the filesystem doesn't support extended attributes,
+	       the original had no special security context and the
+	       target cannot have one either.  */
+	    if (errno == EOPNOTSUPP)
+		return;
+
+	    MSG_PUTS(_("\nCould not get security context for "));
+	    msg_outtrans(from_file);
+	    msg_putchar('\n');
+	    return;
+	}
+	if (getfilecon((char *)to_file, &to_context) < 0)
+	{
+	    MSG_PUTS(_("\nCould not get security context for "));
+	    msg_outtrans(to_file);
+	    msg_putchar('\n');
+	    freecon (from_context);
+	    return ;
+	}
+	if (strcmp(from_context, to_context) != 0)
+	{
+	    if (setfilecon((char *)to_file, from_context) < 0)
+	    {
+		MSG_PUTS(_("\nCould not set security context for "));
+		msg_outtrans(to_file);
+		msg_putchar('\n');
+	    }
+	}
+	freecon(to_context);
+	freecon(from_context);
+    }
+}
+#endif /* HAVE_SELINUX */
+
 /*
  * Return a pointer to the ACL of file "fname" in allocated memory.
  * Return NULL if the ACL is not available for whatever reason.
@@ -4646,7 +4728,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 +4876,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 +5020,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 +5133,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 +5190,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 +5213,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 +5282,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 +5335,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 +5367,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 +5438,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 +5461,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 +5540,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 +5585,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 +5779,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 +5793,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 +6219,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 15:35:05.000000000 -0400
+++ vim71/src/os_unix.h	2008-06-18 06:51:07.000000000 -0400
@@ -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 16:07:39.000000000 -0400
+++ vim71/src/popupmnu.c	2008-06-18 06:51:46.000000000 -0400
@@ -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 06:39:01.000000000 -0400
+++ vim71/src/proto/charset.pro	2008-06-18 06:52:16.000000000 -0400
@@ -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 06:39:05.000000000 -0400
+++ vim71/src/proto/edit.pro	2008-06-18 06:55:19.000000000 -0400
@@ -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 06:39:06.000000000 -0400
+++ vim71/src/proto/eval.pro	2008-06-18 06:54:54.000000000 -0400
@@ -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 06:39:09.000000000 -0400
+++ vim71/src/proto/ex_cmds2.pro	2008-06-18 06:54:54.000000000 -0400
@@ -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 06:39:10.000000000 -0400
+++ vim71/src/proto/ex_docmd.pro	2008-06-18 06:53:54.000000000 -0400
@@ -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));
diff -Naur vim71.orig/src/proto/ex_getln.pro vim71/src/proto/ex_getln.pro
--- vim71.orig/src/proto/ex_getln.pro	2007-05-12 06:39:13.000000000 -0400
+++ vim71/src/proto/ex_getln.pro	2008-06-18 06:56:43.000000000 -0400
@@ -24,6 +24,7 @@
 void ExpandInit __ARGS((expand_T *xp));
 void ExpandCleanup __ARGS((expand_T *xp));
 void ExpandEscape __ARGS((expand_T *xp, char_u *str, int numfiles, char_u **files, int options));
+char_u *vim_strsave_fnameescape __ARGS((char_u *fname, int shell));
 void tilde_replace __ARGS((char_u *orig_pat, int num_files, char_u **files));
 char_u *sm_gettail __ARGS((char_u *s));
 char_u *addstar __ARGS((char_u *fname, int len, int context));
diff -Naur vim71.orig/src/proto/fileio.pro vim71/src/proto/fileio.pro
--- vim71.orig/src/proto/fileio.pro	2007-05-12 06:39:14.000000000 -0400
+++ vim71/src/proto/fileio.pro	2008-06-18 06:53:09.000000000 -0400
@@ -2,6 +2,7 @@
 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));
@@ -39,6 +40,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 06:39:16.000000000 -0400
+++ vim71/src/proto/getchar.pro	2008-06-18 06:52:43.000000000 -0400
@@ -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 06:39:21.000000000 -0400
+++ vim71/src/proto/if_cscope.pro	2008-06-18 06:52:38.000000000 -0400
@@ -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 06:39:38.000000000 -0400
+++ vim71/src/proto/mbyte.pro	2008-06-18 06:52:29.000000000 -0400
@@ -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 06:39:34.000000000 -0400
+++ vim71/src/proto/misc1.pro	2008-06-18 06:53:06.000000000 -0400
@@ -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 06:39:40.000000000 -0400
+++ vim71/src/proto/ops.pro	2008-06-18 06:56:15.000000000 -0400
@@ -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));
@@ -41,7 +41,7 @@
 void op_format __ARGS((oparg_T *oap, int keep_cursor));
 void op_formatexpr __ARGS((oparg_T *oap));
 int fex_format __ARGS((linenr_T lnum, long count, int c));
-void format_lines __ARGS((linenr_T line_count));
+void format_lines __ARGS((linenr_T line_count, int avoid_fex));
 int paragraph_start __ARGS((linenr_T lnum));
 int do_addsub __ARGS((int command, linenr_T Prenum1));
 int read_viminfo_register __ARGS((vir_T *virp, int force));
diff -Naur vim71.orig/src/proto/os_unix.pro vim71/src/proto/os_unix.pro
--- vim71.orig/src/proto/os_unix.pro	2007-05-12 06:39:43.000000000 -0400
+++ vim71/src/proto/os_unix.pro	2008-06-18 06:56:39.000000000 -0400
@@ -34,6 +34,7 @@
 void fname_case __ARGS((char_u *name, int len));
 long mch_getperm __ARGS((char_u *name));
 int mch_setperm __ARGS((char_u *name, long perm));
+void mch_copy_sec __ARGS((char_u *from_file, char_u *to_file));
 vim_acl_T mch_get_acl __ARGS((char_u *fname));
 void mch_set_acl __ARGS((char_u *fname, vim_acl_T aclent));
 void mch_free_acl __ARGS((vim_acl_T aclent));
diff -Naur vim71.orig/src/proto/regexp.pro vim71/src/proto/regexp.pro
--- vim71.orig/src/proto/regexp.pro	2007-05-12 06:39:48.000000000 -0400
+++ vim71/src/proto/regexp.pro	2008-06-18 06:55:25.000000000 -0400
@@ -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 06:39:50.000000000 -0400
+++ vim71/src/proto/search.pro	2008-06-18 06:55:25.000000000 -0400
@@ -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 06:39:52.000000000 -0400
+++ vim71/src/proto/syntax.pro	2008-06-18 06:55:04.000000000 -0400
@@ -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 06:40:00.000000000 -0400
+++ vim71/src/proto/window.pro	2008-06-18 06:51:23.000000000 -0400
@@ -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-03 19:50:17.000000000 -0500
+++ vim71/src/quickfix.c	2008-06-18 06:56:25.000000000 -0400
@@ -106,7 +106,9 @@
 
 static int	qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast));
 static void	qf_new_list __ARGS((qf_info_T *qi));
+static void	ll_free_all __ARGS((qf_info_T **pqi));
 static int	qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid));
+static qf_info_T *ll_new_list __ARGS((void));
 static void	qf_msg __ARGS((qf_info_T *qi));
 static void	qf_free __ARGS((qf_info_T *qi, int idx));
 static char_u	*qf_types __ARGS((int, int));
@@ -1612,8 +1614,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 +1805,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 +2334,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
@@ -2981,6 +2984,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;
@@ -3097,6 +3101,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
@@ -3135,7 +3140,7 @@
 	    {
 		col = 0;
 		while (vim_regexec_multi(&regmatch, curwin, buf, lnum,
-								     col) > 0)
+							       col, NULL) > 0)
 		{
 		    if (qf_add_entry(qi, &prevp,
 				NULL,       /* dir */
@@ -3243,11 +3248,29 @@
     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;
+	}
     }
     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(regmatch.regprog);
 }
diff -Naur vim71.orig/src/regexp.c vim71/src/regexp.c
--- vim71.orig/src/regexp.c	2007-05-07 15:50:03.000000000 -0400
+++ vim71/src/regexp.c	2008-06-18 06:57:02.000000000 -0400
@@ -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
@@ -3046,13 +3039,25 @@
     } se_u;
 } save_se_T;
 
+/* used for BEHIND and NOBEHIND matching */
+typedef struct regbehind_S
+{
+    regsave_T	save_after;
+    regsave_T	save_behind;
+    int		save_need_clear_subexpr;
+    save_se_T   save_start[NSUBEXP];
+    save_se_T   save_end[NSUBEXP];
+} regbehind_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
 static void	cleanup_zsubexpr __ARGS((void));
 #endif
+static void	save_subexpr __ARGS((regbehind_T *bp));
+static void	restore_subexpr __ARGS((regbehind_T *bp));
 static void	reg_nextline __ARGS((void));
 static void	reg_save __ARGS((regsave_T *save, garray_T *gap));
 static void	reg_restore __ARGS((regsave_T *save, garray_T *gap));
@@ -3105,7 +3110,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;
 
 /*
@@ -3173,19 +3178,12 @@
 	save_se_T  sesave;
 	regsave_T  regsave;
     } rs_un;			/* room for saving reginput */
-    short	rs_no;		/* submatch nr */
+    short	rs_no;		/* submatch nr or BEHIND/NOBEHIND */
 } regitem_T;
 
 static regitem_T *regstack_push __ARGS((regstate_T state, char_u *scan));
 static void regstack_pop __ARGS((char_u **scan));
 
-/* used for BEHIND and NOBEHIND matching */
-typedef struct regbehind_S
-{
-    regsave_T	save_after;
-    regsave_T	save_behind;
-} regbehind_T;
-
 /* used for STAR, PLUS and BRACE_SIMPLE matching */
 typedef struct regstar_S
 {
@@ -3205,12 +3203,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 +3289,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 +3313,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 +3326,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 +3352,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 +3362,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 +3503,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 +3561,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 +3774,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 +3867,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 +4258,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 +4791,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;
@@ -4835,6 +4893,10 @@
 		    status = RA_FAIL;
 		else
 		{
+		    /* Need to save the subexpr to be able to restore them
+		     * when there is a match but we don't use it. */
+		    save_subexpr(((regbehind_T *)rp) - 1);
+
 		    rp->rs_no = op;
 		    reg_save(&rp->rs_un.regsave, &backpos);
 		    /* First try if what follows matches.  If it does then we
@@ -5065,15 +5127,20 @@
 		    reg_restore(&(((regbehind_T *)rp) - 1)->save_after,
 								    &backpos);
 		else
-		    /* But we didn't want a match. */
+		{
+		    /* But we didn't want a match.  Need to restore the
+		     * subexpr, because what follows matched, so they have
+		     * been set. */
 		    status = RA_NOMATCH;
+		    restore_subexpr(((regbehind_T *)rp) - 1);
+		}
 		regstack_pop(&scan);
 		regstack.ga_len -= sizeof(regbehind_T);
 	    }
 	    else
 	    {
-		/* No match: Go back one character.  May go to previous
-		 * line once. */
+		/* No match or a match that doesn't end where we want it: Go
+		 * back one character.  May go to previous line once. */
 		no = OK;
 		if (REG_MULTI)
 		{
@@ -5107,6 +5174,13 @@
 		    /* Advanced, prepare for finding match again. */
 		    reg_restore(&rp->rs_un.regsave, &backpos);
 		    scan = OPERAND(rp->rs_scan);
+		    if (status == RA_MATCH)
+		    {
+			/* We did match, so subexpr may have been changed,
+			 * need to restore them for the next try. */
+			status = RA_NOMATCH;
+			restore_subexpr(((regbehind_T *)rp) - 1);
+		    }
 		}
 		else
 		{
@@ -5119,7 +5193,16 @@
 			status = RA_MATCH;
 		    }
 		    else
-			status = RA_NOMATCH;
+		    {
+			/* We do want a proper match.  Need to restore the
+			 * subexpr if we had a match, because they may have
+			 * been set. */
+			if (status == RA_MATCH)
+			{
+			    status = RA_NOMATCH;
+			    restore_subexpr(((regbehind_T *)rp) - 1);
+			}
+		    }
 		    regstack_pop(&scan);
 		    regstack.ga_len -= sizeof(regbehind_T);
 		}
@@ -5558,11 +5641,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++;
@@ -5766,6 +5850,66 @@
 #endif
 
 /*
+ * Save the current subexpr to "bp", so that they can be restored
+ * later by restore_subexpr().
+ */
+    static void
+save_subexpr(bp)
+    regbehind_T *bp;
+{
+    int i;
+
+    /* When "need_clear_subexpr" is set we don't need to save the values, only
+     * remember that this flag needs to be set again when restoring. */
+    bp->save_need_clear_subexpr = need_clear_subexpr;
+    if (!need_clear_subexpr)
+    {
+	for (i = 0; i < NSUBEXP; ++i)
+	{
+	    if (REG_MULTI)
+	    {
+		bp->save_start[i].se_u.pos = reg_startpos[i];
+		bp->save_end[i].se_u.pos = reg_endpos[i];
+	    }
+	    else
+	    {
+		bp->save_start[i].se_u.ptr = reg_startp[i];
+		bp->save_end[i].se_u.ptr = reg_endp[i];
+	    }
+	}
+    }
+}
+
+/*
+ * Restore the subexpr from "bp".
+ */
+    static void
+restore_subexpr(bp)
+    regbehind_T *bp;
+{
+    int i;
+
+    /* Only need to restore saved values when they are not to be cleared. */
+    need_clear_subexpr = bp->save_need_clear_subexpr;
+    if (!need_clear_subexpr)
+    {
+	for (i = 0; i < NSUBEXP; ++i)
+	{
+	    if (REG_MULTI)
+	    {
+		reg_startpos[i] = bp->save_start[i].se_u.pos;
+		reg_endpos[i] = bp->save_end[i].se_u.pos;
+	    }
+	    else
+	    {
+		reg_startp[i] = bp->save_start[i].se_u.ptr;
+		reg_endp[i] = bp->save_end[i].se_u.ptr;
+	    }
+	}
+    }
+}
+
+/*
  * Advance reglnum, regline and reginput to the next line.
  */
     static void
@@ -6490,10 +6634,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 +6781,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 +7158,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 15:27:53.000000000 -0400
+++ vim71/src/screen.c	2008-06-18 06:56:45.000000000 -0400
@@ -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
@@ -4402,7 +4527,7 @@
 #endif
 		    col == W_WIDTH(wp) - 1)
 		&& (*ptr != NUL
-		    || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str)
+		    || (wp->w_p_list && lcs_eol_one > 0)
 		    || (n_extra && (c_extra != NUL || *p_extra != NUL))))
 	{
 	    c = lcs_ext;
@@ -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
 	    }
@@ -7862,9 +8045,13 @@
 	windgoto(W_WINROW(curwin) + curwin->w_wrow,
 		W_WINCOL(curwin) + (
 #ifdef FEAT_RIGHTLEFT
+		/* With 'rightleft' set and the cursor on a double-wide
+		 * character, position it on the leftmost column. */
 		curwin->w_p_rl ? ((int)W_WIDTH(curwin) - curwin->w_wcol - (
 # ifdef FEAT_MBYTE
-			has_mbyte ? (*mb_ptr2cells)(ml_get_cursor()) :
+			(has_mbyte
+			   && (*mb_ptr2cells)(ml_get_cursor()) == 2
+			   && vim_isprintc(gchar_cursor())) ? 2 :
 # endif
 			1)) :
 #endif
@@ -9170,6 +9357,11 @@
        )
 	maketitle();
 #endif
+#ifdef FEAT_WINDOWS
+    /* Redraw the tab pages line if needed. */
+    if (redraw_tabline)
+	draw_tabline();
+#endif
 }
 
 #ifdef FEAT_CMDL_INFO
diff -Naur vim71.orig/src/search.c vim71/src/search.c
--- vim71.orig/src/search.c	2007-05-07 15:42:02.000000000 -0400
+++ vim71/src/search.c	2008-06-18 06:56:06.000000000 -0400
@@ -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 */
@@ -537,7 +538,10 @@
 	return FAIL;
     }
 
-    if (options & SEARCH_START)
+    /* When not accepting a match at the start position set "extra_col" to a
+     * non-zero value.  Don't do that when starting at MAXCOL, since MAXCOL +
+     * 1 is zero. */
+    if ((options & SEARCH_START) || pos->col == MAXCOL)
 	extra_col = 0;
 #ifdef FEAT_MBYTE
     /* Watch out for the "col" being MAXCOL - 2, used in a closed fold. */
@@ -573,8 +577,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 +599,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,10 +624,10 @@
 		    /* 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
-		    /* Line me be past end of buffer for "\n\zs". */
+#endif
+		    /* "lnum" may be past end of buffer for "\n\zs". */
 		    if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
 			ptr = (char_u *)"";
 		    else
@@ -683,7 +702,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 +814,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
@@ -805,21 +836,38 @@
 			    continue;
 		    }
 
-		    if (options & SEARCH_END && !(options & SEARCH_NOOF))
+		    /* With the SEARCH_END option move to the last character
+		     * of the match.  Don't do it for an empty match, end
+		     * should be same as start then. */
+		    if (options & SEARCH_END && !(options & SEARCH_NOOF)
+			    && !(matchpos.lnum == endpos.lnum
+				&& matchpos.col == endpos.col))
 		    {
+			/* For a match in the first column, set the position
+			 * on the NUL in the previous line. */
 			pos->lnum = lnum + endpos.lnum;
-			pos->col = endpos.col - 1;
-#ifdef FEAT_MBYTE
-			if (has_mbyte)
+			pos->col = endpos.col;
+			if (endpos.col == 0)
 			{
-			    /* 'e' offset may put us just below the last line */
-			    if (pos->lnum > buf->b_ml.ml_line_count)
-				ptr = (char_u *)"";
-			    else
-				ptr = ml_get_buf(buf, pos->lnum, FALSE);
-			    pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
+			    if (pos->lnum > 1)  /* just in case */
+			    {
+				--pos->lnum;
+				pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
+							   pos->lnum, FALSE));
+			    }
 			}
+			else
+			{
+			    --pos->col;
+#ifdef FEAT_MBYTE
+			    if (has_mbyte
+				    && pos->lnum <= buf->b_ml.ml_line_count)
+			    {
+				ptr = ml_get_buf(buf, pos->lnum, FALSE);
+				pos->col -= (*mb_head_off)(ptr, ptr + pos->col);
+			    }
 #endif
+			}
 		    }
 		    else
 		    {
@@ -967,12 +1015,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 +1295,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 +1943,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 +2173,9 @@
 			else if (!backwards)
 			    inquote = TRUE;
 		    }
+
+		    /* ml_get() only keeps one line, need to get linep again */
+		    linep = ml_get(pos.lnum);
 		}
 	    }
 	}
@@ -2313,7 +2365,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 +2849,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 +3654,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 +3774,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 +3795,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 +3830,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 +3864,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 +3899,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 +3921,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 +3937,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 15:48:38.000000000 -0400
+++ vim71/src/spell.c	2008-06-18 06:56:35.000000000 -0400
@@ -753,6 +753,7 @@
 static int spell_iswordp __ARGS((char_u *p, buf_T *buf));
 static int spell_iswordp_nmw __ARGS((char_u *p));
 #ifdef FEAT_MBYTE
+static int spell_mb_isword_class __ARGS((int cl));
 static int spell_iswordp_w __ARGS((int *p, buf_T *buf));
 #endif
 static int write_spell_prefcond __ARGS((FILE *fd, garray_T *gap));
@@ -2146,7 +2147,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;
 			}
@@ -2268,6 +2269,8 @@
 /*
  * For spell checking: concatenate the start of the following line "line" into
  * "buf", blanking-out special characters.  Copy less then "maxlen" bytes.
+ * Keep the blanks at the start of the next line, this is used in win_line()
+ * to skip those bytes if the word was OK.
  */
     void
 spell_cat_line(buf, line, maxlen)
@@ -2284,12 +2287,14 @@
 
     if (*p != NUL)
     {
-	*buf = ' ';
-	vim_strncpy(buf + 1, line, maxlen - 2);
-	n = (int)(p - line);
-	if (n >= maxlen)
-	    n = maxlen - 1;
-	vim_memset(buf + 1, ' ', n);
+	/* Only worth concatenating if there is something else than spaces to
+	 * concatenate. */
+	n = (int)(p - line) + 1;
+	if (n < maxlen - 1)
+	{
+	    vim_memset(buf, ' ', n);
+	    vim_strncpy(buf +  n, p, maxlen - 1 - n);
+	}
     }
 }
 
@@ -7829,7 +7834,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 +7864,7 @@
 
 #ifdef _MSC_VER
 # if (_MSC_VER <= 1200)
-/* # pragma optimize("", on) */
+ #  pragma optimize("", on)
 # endif
 #endif
 
@@ -9785,7 +9790,7 @@
 
 	c = mb_ptr2char(s);
 	if (c > 255)
-	    return mb_get_class(s) >= 2;
+	    return spell_mb_isword_class(mb_get_class(s));
 	return spelltab.st_isw[c];
     }
 #endif
@@ -9808,7 +9813,7 @@
     {
 	c = mb_ptr2char(p);
 	if (c > 255)
-	    return mb_get_class(p) >= 2;
+	    return spell_mb_isword_class(mb_get_class(p));
 	return spelltab.st_isw[c];
     }
 #endif
@@ -9817,6 +9822,18 @@
 
 #ifdef FEAT_MBYTE
 /*
+ * Return TRUE if word class indicates a word character.
+ * Only for characters above 255.
+ * Unicode subscript and superscript are not considered word characters.
+ */
+    static int
+spell_mb_isword_class(cl)
+    int cl;
+{
+    return cl >= 2 && cl != 0x2070 && cl != 0x2080;
+}
+
+/*
  * Return TRUE if "p" points to a word character.
  * Wide version of spell_iswordp().
  */
@@ -9837,7 +9854,7 @@
     if (*s > 255)
     {
 	if (enc_utf8)
-	    return utf_class(*s) >= 2;
+	    return spell_mb_isword_class(utf_class(*s));
 	if (enc_dbcs)
 	    return dbcs_class((unsigned)*s >> 8, *s & 0xff) >= 2;
 	return 0;
@@ -10343,7 +10360,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 +12199,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 +12209,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 15:50:49.000000000 -0400
+++ vim71/src/structs.h	2008-06-18 06:55:25.000000000 -0400
@@ -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 15:42:55.000000000 -0400
+++ vim71/src/syntax.c	2008-06-18 06:55:25.000000000 -0400
@@ -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 15:36:40.000000000 -0400
+++ vim71/src/tag.c	2008-06-18 06:55:50.000000000 -0400
@@ -2669,8 +2669,8 @@
 
 	    tnp->tn_search_ctx = vim_findfile_init(buf, filename,
 		    r_ptr, 100,
-		    FALSE, /* don't free visited list */
-		    FALSE, /* we search for a file */
+		    FALSE,         /* don't free visited list */
+		    FINDFILE_FILE, /* we search for a file */
 		    tnp->tn_search_ctx, TRUE, curbuf->b_ffname);
 	    if (tnp->tn_search_ctx != NULL)
 		tnp->tn_did_filefind_init = TRUE;
@@ -2691,6 +2691,7 @@
 {
     vim_free(tnp->tn_tags);
     vim_findfile_cleanup(tnp->tn_search_ctx);
+    tnp->tn_search_ctx = NULL;
     ga_clear_strings(&tag_fnames);
 }
 
@@ -3191,7 +3192,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 +3205,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 +3215,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 15:39:11.000000000 -0400
+++ vim71/src/term.c	2008-06-18 06:56:02.000000000 -0400
@@ -4050,15 +4050,17 @@
 	{
 	    /* Check for xterm version string: "<Esc>[>{x};{vers};{y}c".  Also
 	     * eat other possible responses to t_RV, rxvt returns
-	     * "<Esc>[?1;2c".  Also accept CSI instead of <Esc>[. */
+	     * "<Esc>[?1;2c".  Also accept CSI instead of <Esc>[.
+	     * mrxvt has been reported to have "+" in the version. Assume
+	     * the escape sequence ends with a letter or one of "{|}~". */
 	    if (*T_CRV != NUL && ((tp[0] == ESC && tp[1] == '[' && len >= 3)
 					       || (tp[0] == CSI && len >= 2)))
 	    {
 		j = 0;
 		extra = 0;
-		for (i = 2 + (tp[0] != CSI);
-			i < len && (VIM_ISDIGIT(tp[i])
-			    || tp[i] == ';' || tp[i] == '.'); ++i)
+		for (i = 2 + (tp[0] != CSI); i < len
+				&& !(tp[i] >= '{' && tp[i] <= '~')
+				&& !ASCII_ISALPHA(tp[i]); ++i)
 		    if (tp[i] == ';' && ++j == 1)
 			extra = atoi((char *)tp + i + 1);
 		if (i == len)
@@ -4809,6 +4811,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 15:39:49.000000000 -0400
+++ vim71/src/termlib.c	2008-06-18 06:51:42.000000000 -0400
@@ -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 07:08:01.000000000 -0400
+++ vim71/src/testdir/Makefile	2008-06-18 06:53:02.000000000 -0400
@@ -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 10:32:05.000000000 -0400
+++ vim71/src/testdir/test14.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 10:32:05.000000000 -0400
+++ vim71/src/testdir/test26.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 09:33:24.000000000 -0400
+++ vim71/src/testdir/test34.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 10:32:05.000000000 -0400
+++ vim71/src/testdir/test39.in	2008-06-18 06:55:45.000000000 -0400
@@ -1,8 +1,12 @@
 
 Test Visual block mode commands
+And test "U" in Visual mode, also on German sharp S.
 
 STARTTEST
 :so small.vim
+:so mbyte.vim
+:" This only works when 'encoding' is "latin1", don't depend on the environment
+:set enc=latin1
 /^abcde
 :" Test shift-right of a block
 jlllljj>wlljlll>
@@ -14,7 +18,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 10:32:05.000000000 -0400
+++ vim71/src/testdir/test39.ok	2008-06-18 06:55:34.000000000 -0400
@@ -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/test42.ok vim71/src/testdir/test42.ok
--- vim71.orig/src/testdir/test42.ok	2004-06-07 10:32:05.000000000 -0400
+++ vim71/src/testdir/test42.ok	2008-06-18 06:55:56.000000000 -0400
@@ -15,7 +15,7 @@
 ï»¿utf-8€err
 
 
-  fileencoding=ucs-2
+  fileencoding=utf-16
   bomb
 ucs-2
 
diff -Naur vim71.orig/src/testdir/test45.in vim71/src/testdir/test45.in
--- vim71.orig/src/testdir/test45.in	2004-06-07 10:32:05.000000000 -0400
+++ vim71/src/testdir/test45.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 10:32:05.000000000 -0400
+++ vim71/src/testdir/test47.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 05:29:54.000000000 -0400
+++ vim71/src/testdir/test49.in	2008-06-18 06:55:47.000000000 -0400
@@ -1,13 +1,30 @@
 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
+:lang mess C
 :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 10:07:05.000000000 -0400
+++ vim71/src/testdir/test55.in	2008-06-18 06:55:47.000000000 -0400
@@ -146,7 +146,7 @@
 :try
 :  let n = d[1500]
 :catch
-:  $put =v:exception[:14] . v:exception[-4:-1]
+:  $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '')
 :endtry
 :" lookup each items
 :for i in range(1500)
@@ -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 10:28:41.000000000 -0400
+++ vim71/src/testdir/test56.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 14:24:04.000000000 -0400
+++ vim71/src/testdir/test58.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 14:29:24.000000000 -0400
+++ vim71/src/testdir/test59.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 14:41:18.000000000 -0400
+++ vim71/src/testdir/test60.in	2008-06-18 06:53:02.000000000 -0400
@@ -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 14:45:59.000000000 -0500
+++ vim71/src/testdir/test60.vim	2008-06-18 06:53:02.000000000 -0400
@@ -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 07:29:15.000000000 -0400
+++ vim71/src/testdir/test62.in	2008-06-18 06:53:02.000000000 -0400
@@ -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	1969-12-31 19:00:00.000000000 -0500
+++ vim71/src/testdir/test63.in	2008-06-18 06:53:02.000000000 -0400
@@ -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	1969-12-31 19:00:00.000000000 -0500
+++ vim71/src/testdir/test63.ok	2008-06-18 06:51:23.000000000 -0400
@@ -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	1969-12-31 19:00:00.000000000 -0500
+++ vim71/src/testdir/test64.in	2008-06-18 06:54:16.000000000 -0400
@@ -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	1969-12-31 19:00:00.000000000 -0500
+++ vim71/src/testdir/test64.ok	2008-06-18 06:54:16.000000000 -0400
@@ -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 15:49:09.000000000 -0400
+++ vim71/src/ui.c	2008-06-18 06:52:10.000000000 -0400
@@ -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 15:21:14.000000000 -0400
+++ vim71/src/undo.c	2008-06-18 06:55:41.000000000 -0400
@@ -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 06:23:44.000000000 -0400
+++ vim71/src/version.c	2008-06-18 06:57:02.000000000 -0400
@@ -667,6 +667,582 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    315,
+/**/
+    314,
+/**/
+    313,
+/**/
+    311,
+/**/
+    310,
+/**/
+    309,
+/**/
+    308,
+/**/
+    307,
+/**/
+    306,
+/**/
+    305,
+/**/
+    304,
+/**/
+    303,
+/**/
+    302,
+/**/
+    301,
+/**/
+    300,
+/**/
+    299,
+/**/
+    298,
+/**/
+    297,
+/**/
+    296,
+/**/
+    295,
+/**/
+    294,
+/**/
+    293,
+/**/
+    292,
+/**/
+    291,
+/**/
+    290,
+/**/
+    289,
+/**/
+    288,
+/**/
+    287,
+/**/
+    286,
+/**/
+    284,
+/**/
+    281,
+/**/
+    279,
+/**/
+    277,
+/**/
+    276,
+/**/
+    274,
+/**/
+    273,
+/**/
+    272,
+/**/
+    271,
+/**/
+    270,
+/**/
+    269,
+/**/
+    268,
+/**/
+    267,
+/**/
+    266,
+/**/
+    265,
+/**/
+    264,
+/**/
+    263,
+/**/
+    262,
+/**/
+    261,
+/**/
+    260,
+/**/
+    259,
+/**/
+    258,
+/**/
+    257,
+/**/
+    256,
+/**/
+    255,
+/**/
+    254,
+/**/
+    253,
+/**/
+    252,
+/**/
+    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,
+/**/
+    203,
+/**/
+    202,
+/**/
+    201,
+/**/
+    200,
+/**/
+    199,
+/**/
+    198,
+/**/
+    197,
+/**/
+    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,
+/**/
+    167,
+/**/
+    166,
+/**/
+    165,
+/**/
+    164,
+/**/
+    163,
+/**/
+    162,
+/**/
+    161,
+/**/
+    160,
+/**/
+    159,
+/**/
+    157,
+/**/
+    156,
+/**/
+    155,
+/**/
+    154,
+/**/
+    153,
+/**/
+    152,
+/**/
+    151,
+/**/
+    150,
+/**/
+    149,
+/**/
+    148,
+/**/
+    147,
+/**/
+    145,
+/**/
+    144,
+/**/
+    143,
+/**/
+    142,
+/**/
+    141,
+/**/
+    140,
+/**/
+    139,
+/**/
+    138,
+/**/
+    137,
+/**/
+    136,
+/**/
+    135,
+/**/
+    133,
+/**/
+    132,
+/**/
+    131,
+/**/
+    130,
+/**/
+    127,
+/**/
+    125,
+/**/
+    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,
+/**/
+    90,
+/**/
+    89,
+/**/
+    87,
+/**/
+    86,
+/**/
+    85,
+/**/
+    84,
+/**/
+    83,
+/**/
+    82,
+/**/
+    81,
+/**/
+    79,
+/**/
+    78,
+/**/
+    77,
+/**/
+    76,
+/**/
+    75,
+/**/
+    74,
+/**/
+    73,
+/**/
+    71,
+/**/
+    69,
+/**/
+    68,
+/**/
+    67,
+/**/
+    66,
+/**/
+    64,
+/**/
+    63,
+/**/
+    62,
+/**/
+    61,
+/**/
+    60,
+/**/
+    59,
+/**/
+    58,
+/**/
+    57,
+/**/
+    56,
+/**/
+    55,
+/**/
+    54,
+/**/
+    53,
+/**/
+    52,
+/**/
+    51,
+/**/
+    50,
+/**/
+    49,
+/**/
+    48,
+/**/
+    47,
+/**/
+    46,
+/**/
+    45,
+/**/
+    44,
+/**/
+    43,
+/**/
+    42,
+/**/
+    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,
+/**/
+    6,
+/**/
+    5,
+/**/
+    4,
+/**/
+    2,
+/**/
+    1,
+/**/
     0
 };
 
@@ -1177,9 +1753,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 05:53:29.000000000 -0400
+++ vim71/src/vim.h	2008-06-18 06:56:43.000000000 -0400
@@ -336,10 +336,10 @@
 # endif
 #endif
 #ifdef BACKSLASH_IN_FILENAME
-# define PATH_ESC_CHARS ((char_u *)" \t*?[{`%#")
+# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<")
 #else
-# define PATH_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|")
-# define SHELL_ESC_CHARS ((char_u *)" \t*?[{`$\\%#'\"|<>();&!")
+# define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
+# define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
 #endif
 
 #define NUMBUFLEN 30	    /* length of a buffer to store a number in ASCII */
@@ -721,6 +721,11 @@
 /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
  * is used when executing commands and EW_SILENT for interactive expanding. */
 
+/* Flags for find_file_*() functions. */
+#define FINDFILE_FILE	0	/* only files */
+#define FINDFILE_DIR	1	/* only directories */
+#define FINDFILE_BOTH	2	/* files and directories */
+
 #ifdef FEAT_VERTSPLIT
 # define W_WINCOL(wp)	(wp->w_wincol)
 # define W_WIDTH(wp)	(wp->w_width)
@@ -943,6 +948,7 @@
 #define INSCHAR_FORMAT	1	/* force formatting */
 #define INSCHAR_DO_COM	2	/* format comments */
 #define INSCHAR_CTRLV	4	/* char typed just after CTRL-V */
+#define INSCHAR_NO_FEX	8	/* don't use 'formatexpr' */
 
 /* flags for open_line() */
 #define OPENLINE_DELSPACES  1	/* delete spaces after cursor */
@@ -1380,8 +1386,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 +1556,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 +1704,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 +1778,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 10:32:27.000000000 -0400
+++ vim71/src/vimtutor	2008-06-18 06:56:38.000000000 -0400
@@ -2,11 +2,24 @@
 
 # Start Vim on a copy of the tutor file.
 
-# Usage: vimtutor [xx], where xx is a language code like "es" or "nl".
+# Usage: vimtutor [-g] [xx]
+# Where optional argument -g starts vimtutor in gvim (GUI) instead of vim.
+# and xx is a language code like "es" or "nl".
 # When an argument is given, it tries loading that tutor.
 # When this fails or no argument was given, it tries using 'v:lang'
 # When that also fails, it uses the English version.
 
+# 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"
+if test "$1" = "-g"; then 
+  # Try to use the GUI version of Vim if possible, it will fall back
+  # on Vim if Gvim is not installed.
+  seq="gvim gvim8 gvim75 gvim74 gvim73 gvim72 gvim71 gvim70 gvim7 gvim6 $seq"
+  shift
+fi
+
 xx=$1
 export xx
 
@@ -39,23 +52,23 @@
 # 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`
+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
 # The script tutor.vim tells Vim which file to copy
-$VIM -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim'
+$VIM -f -u NONE -c 'so $VIMRUNTIME/tutor/tutor.vim'
 
 # Start vim without any .vimrc, set 'nocompatible'
-$VIM -u NONE -c "set nocp" $TUTORCOPY
+$VIM -f -u NONE -c "set nocp" $TUTORCOPY
diff -Naur vim71.orig/src/window.c vim71/src/window.c
--- vim71.orig/src/window.c	2007-05-07 15:25:30.000000000 -0400
+++ vim71/src/window.c	2008-06-18 06:53:09.000000000 -0400
@@ -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 15:41:57.000000000 -0400
+++ vim71/src/xxd/xxd.c	2008-06-18 06:54:00.000000000 -0400
@@ -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)
