Submitted By: Matt Burgess (matthew at linuxfromscratch dot org)
Date: 2007-09-07
Initial Package Version: 7.1
Origin: Upstream
Upstream Status: Applied
Description: Contains patches 001-100 from upstream excluding patches 003, 007,
             041, 065, 070, 072, 080, 088, 091 and 092 as they are for "extras"
             (e.g. Mac, Windows) only.

diff -Naur vim71.orig/runtime/doc/change.txt vim71/runtime/doc/change.txt
--- vim71.orig/runtime/doc/change.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/change.txt	2007-09-07 07:42:15.000000000 +0000
@@ -1571,6 +1571,10 @@
 			in their original order, right before the sorted
 			lines.
 
+			If {pattern} is empty (e.g. // is specified), the
+			last search pattern is used.  This allows trying out
+			a pattern first.
+
 Note that using ":sort" with ":global" doesn't sort the matching lines, it's
 quite useless.
 
diff -Naur vim71.orig/runtime/doc/eval.txt vim71/runtime/doc/eval.txt
--- vim71.orig/runtime/doc/eval.txt	2007-05-12 10:18:46.000000000 +0000
+++ vim71/runtime/doc/eval.txt	2007-09-07 07:42:16.000000000 +0000
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.1.  Last change: 2007 May 11
+*eval.txt*      For Vim version 7.1.  Last change: 2007 Jul 25
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1557,6 +1557,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
@@ -1622,6 +1623,7 @@
 getline( {lnum})		String	line {lnum} of current buffer
 getline( {lnum}, {end})		List	lines {lnum} to {end} of current buffer
 getloclist({nr})		List	list of location list items
+getmatches()			List	list of current matches
 getpos( {expr})			List	position of cursor, mark, etc.
 getqflist()			List	list of quickfix items
 getreg( [{regname} [, 1]])	String	contents of register
@@ -1676,7 +1678,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}]])
@@ -1731,6 +1736,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
@@ -2012,6 +2018,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 +2030,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()|.
@@ -2824,6 +2838,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 +2928,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 +3654,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 +3701,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
@@ -4379,7 +4462,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})
@@ -5022,14 +5111,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 10:18:47.000000000 +0000
+++ vim71/runtime/doc/options.txt	2007-09-07 07:42:17.000000000 +0000
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.1.  Last change: 2007 May 11
+*options.txt*	For Vim version 7.1.  Last change: 2007 Aug 10
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2415,8 +2415,8 @@
 	When mixing vertically and horizontally split windows, a minimal size
 	is computed and some windows may be larger if there is room.  The
 	'eadirection' option tells in which direction the size is affected.
-	Changing the height of a window can be avoided by setting
-	'winfixheight'.
+	Changing the height and width of a window can be avoided by setting
+	'winfixheight' and 'winfixwidth', respectively.
 
 						*'equalprg'* *'ep'*
 'equalprg' 'ep'		string	(default "")
diff -Naur vim71.orig/runtime/doc/pattern.txt vim71/runtime/doc/pattern.txt
--- vim71.orig/runtime/doc/pattern.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/pattern.txt	2007-09-07 07:42:16.000000000 +0000
@@ -1212,7 +1212,10 @@
 		{group} must exist at the moment this command is executed.
 
 		The {group} highlighting still applies when a character is
-		to be highlighted for 'hlsearch'.
+		to be highlighted for 'hlsearch', as the highlighting for
+		matches is given higher priority than that of 'hlsearch'.
+		Syntax highlighting (see 'syntax') is also overruled by
+		matches.
 
 		Note that highlighting the last used search pattern with
 		'hlsearch' is used in all windows, while the pattern defined
@@ -1226,8 +1229,15 @@
 		display you may get unexpected results.  That is because Vim
 		looks for a match in the line where redrawing starts.
 
-		Also see |matcharg()|, it returns the highlight group and
-		pattern of a previous :match command.
+		Also see |matcharg()|and |getmatches()|. The former returns
+		the highlight group and pattern of a previous |:match|
+		command.  The latter returns a list with highlight groups and
+		patterns defined by both |matchadd()| and |:match|.
+
+		Highlighting matches using |:match| are limited to three
+		matches (aside from |:match|, |:2match| and |:3match|are
+		available). |matchadd()| does not have this limitation and in
+		addition makes it possible to prioritize matches.
 
 		Another example, which highlights all characters in virtual
 		column 72 and more: >
diff -Naur vim71.orig/runtime/doc/pi_paren.txt vim71/runtime/doc/pi_paren.txt
--- vim71.orig/runtime/doc/pi_paren.txt	2007-05-12 10:18:47.000000000 +0000
+++ vim71/runtime/doc/pi_paren.txt	2007-09-07 07:42:17.000000000 +0000
@@ -12,8 +12,8 @@
 You can avoid loading this plugin by setting the "loaded_matchparen" variable: >
 	:let loaded_matchparen = 1
 
-The plugin installs CursorMoved autocommands to redefine the match
-highlighting.
+The plugin installs CursorMoved, CursorMovedI and WinEnter autocommands to
+redefine the match highlighting.
 
 To disable the plugin after it was loaded use this command: >
 
diff -Naur vim71.orig/runtime/doc/usr_41.txt vim71/runtime/doc/usr_41.txt
--- vim71.orig/runtime/doc/usr_41.txt	2007-05-12 10:18:48.000000000 +0000
+++ vim71/runtime/doc/usr_41.txt	2007-09-07 07:42:16.000000000 +0000
@@ -763,13 +763,22 @@
 	foldtextresult()	get the text displayed for a closed fold
 
 Syntax and highlighting:
+	clearmatches()		clear all matches defined by |matchadd()| and
+				the |:match| commands
+	getmatches()		get all matches defined by |matchadd()| and
+				the |:match| commands
 	hlexists()		check if a highlight group exists
 	hlID()			get ID of a highlight group
 	synID()			get syntax ID at a specific position
 	synIDattr()		get a specific attribute of a syntax ID
 	synIDtrans()		get translated syntax ID
 	diff_hlID()		get highlight ID for diff mode at a position
+	matchadd()		define a pattern to highlight (a "match")
 	matcharg()		get info about |:match| arguments
+	matchdelete()		delete a match defined by |matchadd()| or a
+				|:match| command
+	setmatches()		restore a list of matches saved by
+				|getmatches()|
 
 Spelling:
 	spellbadword()		locate badly spelled word at or after cursor
diff -Naur vim71.orig/runtime/doc/windows.txt vim71/runtime/doc/windows.txt
--- vim71.orig/runtime/doc/windows.txt	2007-05-12 10:18:49.000000000 +0000
+++ vim71/runtime/doc/windows.txt	2007-09-07 07:42:17.000000000 +0000
@@ -132,7 +132,8 @@
 		the same file.  Make new window N high (default is to use half
 		the height of the current window).  Reduces the current window
 		height to create room (and others, if the 'equalalways' option
-		is set and 'eadirection' isn't "hor").
+		is set, 'eadirection' isn't "hor", and one of them is higher
+		than the current or the new window).
 		Note: CTRL-S does not work on all terminals and might block
 		further input, use CTRL-Q to get going again.
 		Also see |++opt| and |+cmd|.
@@ -140,9 +141,13 @@
 CTRL-W CTRL-V						*CTRL-W_CTRL-V*
 CTRL-W v						*CTRL-W_v*
 :[N]vs[plit] [++opt] [+cmd] [file]			*:vs* *:vsplit*
-		Like |:split|, but split vertically.  If 'equalalways' is set
-		and 'eadirection' isn't "ver" the windows will be spread out
-		horizontally, unless a width was specified.
+		Like |:split|, but split vertically.  The windows will be
+		spread out horizontally if
+		1. a width was not specified,
+		2. 'equalalways' is set,
+		3. 'eadirection' isn't "ver", and
+		4. one of the other windows are wider than the current or new
+		   window.
 		Note: In other places CTRL-Q does the same as CTRL-V, but here
 		it doesn't!
 
diff -Naur vim71.orig/runtime/filetype.vim vim71/runtime/filetype.vim
--- vim71.orig/runtime/filetype.vim	2007-05-10 15:14:37.000000000 +0000
+++ vim71/runtime/filetype.vim	2007-09-07 07:42:14.000000000 +0000
@@ -1,7 +1,7 @@
 " Vim support file to detect file types
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2007 May 10
+" Last Change:	2007 May 15
 
 " Listen very carefully, I will say this only once
 if exists("did_load_filetypes")
@@ -1286,7 +1286,7 @@
 au BufNewFile,BufRead *.it,*.ih			setf ppwiz
 
 " Oracle Pro*C/C++
-au BufNewFile,BufRead .pc			setf proc
+au BufNewFile,BufRead *.pc			setf proc
 
 " Privoxy actions file
 au BufNewFile,BufRead *.action			setf privoxy
diff -Naur vim71.orig/runtime/plugin/matchparen.vim vim71/runtime/plugin/matchparen.vim
--- vim71.orig/runtime/plugin/matchparen.vim	2006-10-12 20:05:05.000000000 +0000
+++ vim71/runtime/plugin/matchparen.vim	2007-09-07 07:42:17.000000000 +0000
@@ -1,6 +1,6 @@
 " Vim plugin for showing matching parens
 " Maintainer:  Bram Moolenaar <Bram@vim.org>
-" Last Change: 2006 Oct 12
+" Last Change: 2007 Aug 8
 
 " Exit quickly when:
 " - this plugin was already loaded (or disabled)
@@ -13,7 +13,7 @@
 
 augroup matchparen
   " Replace all matchparen autocommands
-  autocmd! CursorMoved,CursorMovedI * call s:Highlight_Matching_Pair()
+  autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair()
 augroup END
 
 " Skip the rest if it was already done.
@@ -62,25 +62,37 @@
   " Figure out the arguments for searchpairpos().
   " Restrict the search to visible lines with "stopline".
   " And avoid searching very far (e.g., for closed folds and long lines)
+  " The "viewable" variables give a range in which we can scroll while keeping
+  " the cursor at the same position
+  " adjustedScrolloff accounts for very large numbers of scrolloff
+  let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2])
+  let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2])
+  let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2])
+  " one of these stoplines will be adjusted below, but the current values are
+  " minimal boundaries within the current window
+  let stoplinebottom = line('w$')
+  let stoplinetop = line('w0')
   if i % 2 == 0
     let s_flags = 'nW'
     let c2 = plist[i + 1]
     if has("byte_offset") && has("syntax_items") && &smc > 0
       let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2])
-      let stopline = min([line('w$'), byte2line(stopbyte)])
+      let stopline = min([bottom_viewable, byte2line(stopbyte)])
     else
-      let stopline = min([line('w$'), c_lnum + 100])
+      let stopline = min([bottom_viewable, c_lnum + 100])
     endif
+    let stoplinebottom = stopline
   else
     let s_flags = 'nbW'
     let c2 = c
     let c = plist[i - 1]
     if has("byte_offset") && has("syntax_items") && &smc > 0
       let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2])
-      let stopline = max([line('w0'), byte2line(stopbyte)])
+      let stopline = max([top_viewable, byte2line(stopbyte)])
     else
-      let stopline = max([line('w0'), c_lnum - 100])
+      let stopline = max([top_viewable, c_lnum - 100])
     endif
+    let stoplinetop = stopline
   endif
   if c == '['
     let c = '\['
@@ -106,7 +118,7 @@
   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 +126,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/auto/configure vim71/src/auto/configure
--- vim71.orig/src/auto/configure	2007-05-12 11:49:09.000000000 +0000
+++ vim71/src/auto/configure	2007-09-07 07:42:14.000000000 +0000
@@ -3843,7 +3843,9 @@
   fi
 
   if test "X$vi_cv_path_mzscheme_pfx" != "X"; then
-    if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
+    if test "x$MACOSX" = "xyes"; then
+      MZSCHEME_LIBS="-framework PLT_MzScheme"
+    elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
       MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"
     else
       MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc"
diff -Naur vim71.orig/src/buffer.c vim71/src/buffer.c
--- vim71.orig/src/buffer.c	2007-05-10 15:25:59.000000000 +0000
+++ vim71/src/buffer.c	2007-09-07 07:42:17.000000000 +0000
@@ -171,6 +171,13 @@
 	    /* Put the cursor on the first line. */
 	    curwin->w_cursor.lnum = 1;
 	    curwin->w_cursor.col = 0;
+
+	    /* Set or reset 'modified' before executing autocommands, so that
+	     * it can be changed there. */
+	    if (!readonlymode && !bufempty())
+		changed();
+	    else if (retval != FAIL)
+		unchanged(curbuf, FALSE);
 #ifdef FEAT_AUTOCMD
 # ifdef FEAT_EVAL
 	    apply_autocmds_retval(EVENT_STDINREADPOST, NULL, NULL, FALSE,
@@ -194,16 +201,16 @@
     /* When reading stdin, the buffer contents always needs writing, so set
      * the changed flag.  Unless in readonly mode: "ls | gview -".
      * When interrupted and 'cpoptions' contains 'i' set changed flag. */
-    if ((read_stdin && !readonlymode && !bufempty())
+    if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
 #ifdef FEAT_AUTOCMD
 		|| modified_was_set	/* ":set modified" used in autocmd */
 # ifdef FEAT_EVAL
 		|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
 # endif
 #endif
-		|| (got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL))
+       )
 	changed();
-    else if (retval != FAIL)
+    else if (retval != FAIL && !read_stdin)
 	unchanged(curbuf, FALSE);
     save_file_ff(curbuf);		/* keep this fileformat */
 
@@ -495,6 +502,7 @@
     buf->b_start_eol = TRUE;
 #ifdef FEAT_MBYTE
     buf->b_p_bomb = FALSE;
+    buf->b_start_bomb = FALSE;
 #endif
     buf->b_ml.ml_mfp = NULL;
     buf->b_ml.ml_flags = ML_EMPTY;		/* empty buffer */
@@ -4853,7 +4861,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;
 
diff -Naur vim71.orig/src/charset.c vim71/src/charset.c
--- vim71.orig/src/charset.c	2007-03-24 20:10:37.000000000 +0000
+++ vim71/src/charset.c	2007-09-07 07:42:17.000000000 +0000
@@ -207,7 +207,10 @@
 	    }
 	    while (c <= c2)
 	    {
-		if (!do_isalpha || isalpha(c)
+		/* Use the MB_ functions here, because isalpha() doesn't
+		 * work properly when 'encoding' is "latin1" and the locale is
+		 * "C".  */
+		if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c)
 #ifdef FEAT_FKMAP
 			|| (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
 #endif
@@ -929,6 +932,23 @@
 }
 
 /*
+ * return TRUE if 'c' is a valid file-name character or a wildcard character
+ * Assume characters above 0x100 are valid (multi-byte).
+ * Explicitly interpret ']' as a wildcard character as mch_has_wildcard("]")
+ * returns false.
+ */
+    int
+vim_isfilec_or_wc(c)
+    int c;
+{
+    char_u buf[2];
+
+    buf[0] = (char_u)c;
+    buf[1] = NUL;
+    return vim_isfilec(c) || c == ']' || mch_has_wildcard(buf);
+}
+
+/*
  * return TRUE if 'c' is a printable character
  * Assume characters above 0x100 are printable (multi-byte), except for
  * Unicode.
@@ -1898,7 +1918,7 @@
 {
     for ( ; *p; ++p)
 	if (rem_backslash(p))
-	    STRCPY(p, p + 1);
+	    mch_memmove(p, p + 1, STRLEN(p));
 }
 
 /*
diff -Naur vim71.orig/src/configure.in vim71/src/configure.in
--- vim71.orig/src/configure.in	2007-05-12 09:19:27.000000000 +0000
+++ vim71/src/configure.in	2007-09-07 07:42:14.000000000 +0000
@@ -423,7 +423,9 @@
   fi
 
   if test "X$vi_cv_path_mzscheme_pfx" != "X"; then
-    if test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
+    if test "x$MACOSX" = "xyes"; then
+      MZSCHEME_LIBS="-framework PLT_MzScheme"
+    elif test -f "${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"; then
       MZSCHEME_LIBS="${vi_cv_path_mzscheme_pfx}/lib/libmzscheme.a ${vi_cv_path_mzscheme_pfx}/lib/libmzgc.a"
     else
       MZSCHEME_LIBS="-L${vi_cv_path_mzscheme_pfx}/lib -lmzscheme -lmzgc"
diff -Naur vim71.orig/src/digraph.c vim71/src/digraph.c
--- vim71.orig/src/digraph.c	2006-05-02 18:24:04.000000000 +0000
+++ vim71/src/digraph.c	2007-09-07 07:42:14.000000000 +0000
@@ -2349,8 +2349,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_unload, as no keymap is active now. */
 	keymap_unload();
+	do_cmdline_cmd((char_u *)"unlet! b:keymap_name");
     }
     else
     {
@@ -2500,7 +2502,6 @@
 
     ga_clear(&curbuf->b_kmap_ga);
     curbuf->b_kmap_state &= ~KEYMAP_LOADED;
-    do_cmdline_cmd((char_u *)"unlet! b:keymap_name");
 #ifdef FEAT_WINDOWS
     status_redraw_curbuf();
 #endif
diff -Naur vim71.orig/src/edit.c vim71/src/edit.c
--- vim71.orig/src/edit.c	2007-05-07 19:43:55.000000000 +0000
+++ vim71/src/edit.c	2007-09-07 07:42:17.000000000 +0000
@@ -2057,7 +2057,6 @@
  * 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 +2067,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)
     {
-	/* 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;
+		    }
 		}
-		was_letter = isalpha(compl_orig_text[idx]);
 	    }
-	}
 
-	/* Copy the original case of the part we typed */
-	STRNCPY(IObuff, compl_orig_text, compl_length);
+	    /*
+	     * 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);
+		}
+	    }
+
+	    /* 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 +2934,7 @@
 			/*
 			 * Add the other matches on the line
 			 */
+			ptr = buf;
 			while (!got_int)
 			{
 			    /* Find start of the next word.  Skip white
@@ -2851,7 +2944,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 +2961,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)
@@ -7215,6 +7311,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] == ':')
@@ -7998,7 +8096,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' */
diff -Naur vim71.orig/src/eval.c vim71/src/eval.c
--- vim71.orig/src/eval.c	2007-05-07 19:47:32.000000000 +0000
+++ vim71/src/eval.c	2007-09-07 07:42:17.000000000 +0000
@@ -369,17 +369,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 +475,7 @@
 static void f_changenr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_clearmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
 #if defined(FEAT_INS_EXPAND)
 static void f_complete __ARGS((typval_T *argvars, typval_T *rettv));
@@ -529,6 +530,7 @@
 static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
+static void f_getmatches __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getpos __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
@@ -577,7 +579,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 +622,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));
@@ -672,7 +677,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 +704,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 +997,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();
@@ -1411,7 +1416,8 @@
 }
 
 
-#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
+#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \
+	|| defined(FEAT_COMPL_FUNC) || defined(PROTO)
 /*
  * Call some vimL function and return the result in "*rettv".
  * Uses argv[argc] for the function arguments.
@@ -1484,6 +1490,7 @@
     return ret;
 }
 
+# if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
 /*
  * Call vimL function "func" and return the result as a string.
  * Returns NULL when calling the function fails.
@@ -1506,8 +1513,9 @@
     clear_tv(&rettv);
     return retval;
 }
+# endif
 
-#if defined(FEAT_COMPL_FUNC) || defined(PROTO)
+# if defined(FEAT_COMPL_FUNC) || defined(PROTO)
 /*
  * Call vimL function "func" and return the result as a number.
  * Returns -1 when calling the function fails.
@@ -1530,7 +1538,7 @@
     clear_tv(&rettv);
     return retval;
 }
-#endif
+# endif
 
 /*
  * Call vimL function "func" and return the result as a list
@@ -1556,9 +1564,9 @@
 
     return rettv.vval.v_list;
 }
-
 #endif
 
+
 /*
  * Save the current function call pointer, and set it to NULL.
  * Used when executing autocommands and for ":source".
@@ -1691,6 +1699,7 @@
     int		semicolon = 0;
     char_u	op[2];
     char_u	*argend;
+    int		first = TRUE;
 
     argend = skip_var_list(arg, &var_count, &semicolon);
     if (argend == NULL)
@@ -1707,19 +1716,19 @@
 	    EMSG(_(e_invarg));
 	else if (!ends_excmd(*arg))
 	    /* ":let var1 var2" */
-	    arg = list_arg_vars(eap, arg);
+	    arg = list_arg_vars(eap, arg, &first);
 	else if (!eap->skip)
 	{
 	    /* ":let" */
-	    list_glob_vars();
-	    list_buf_vars();
-	    list_win_vars();
+	    list_glob_vars(&first);
+	    list_buf_vars(&first);
+	    list_win_vars(&first);
 #ifdef FEAT_WINDOWS
-	    list_tab_vars();
+	    list_tab_vars(&first);
 #endif
-	    list_script_vars();
-	    list_func_vars();
-	    list_vim_vars();
+	    list_script_vars(&first);
+	    list_func_vars(&first);
+	    list_vim_vars(&first);
 	}
 	eap->nextcmd = check_nextcmd(arg);
     }
@@ -1924,10 +1933,11 @@
  * If "empty" is TRUE also list NULL strings as empty strings.
  */
     static void
-list_hashtable_vars(ht, prefix, empty)
+list_hashtable_vars(ht, prefix, empty, first)
     hashtab_T	*ht;
     char_u	*prefix;
     int		empty;
+    int		*first;
 {
     hashitem_T	*hi;
     dictitem_T	*di;
@@ -1942,7 +1952,7 @@
 	    di = HI2DI(hi);
 	    if (empty || di->di_tv.v_type != VAR_STRING
 					   || di->di_tv.vval.v_string != NULL)
-		list_one_var(di, prefix);
+		list_one_var(di, prefix, first);
 	}
     }
 }
@@ -1951,32 +1961,38 @@
  * List global variables.
  */
     static void
-list_glob_vars()
+list_glob_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
+    list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
 }
 
 /*
  * List buffer variables.
  */
     static void
-list_buf_vars()
+list_buf_vars(first)
+    int *first;
 {
     char_u	numbuf[NUMBUFLEN];
 
-    list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
+    list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:",
+								 TRUE, first);
 
     sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
-    list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
+    list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
+							       numbuf, first);
 }
 
 /*
  * List window variables.
  */
     static void
-list_win_vars()
+list_win_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
+    list_hashtable_vars(&curwin->w_vars.dv_hashtab,
+						 (char_u *)"w:", TRUE, first);
 }
 
 #ifdef FEAT_WINDOWS
@@ -1984,9 +2000,11 @@
  * List tab page variables.
  */
     static void
-list_tab_vars()
+list_tab_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&curtab->tp_vars.dv_hashtab, (char_u *)"t:", TRUE);
+    list_hashtable_vars(&curtab->tp_vars.dv_hashtab,
+						 (char_u *)"t:", TRUE, first);
 }
 #endif
 
@@ -1994,39 +2012,44 @@
  * List Vim variables.
  */
     static void
-list_vim_vars()
+list_vim_vars(first)
+    int *first;
 {
-    list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
+    list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
 }
 
 /*
  * List script-local variables, if there is a script.
  */
     static void
-list_script_vars()
+list_script_vars(first)
+    int *first;
 {
     if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
-	list_hashtable_vars(&SCRIPT_VARS(current_SID), (char_u *)"s:", FALSE);
+	list_hashtable_vars(&SCRIPT_VARS(current_SID),
+						(char_u *)"s:", FALSE, first);
 }
 
 /*
  * List function variables, if there is a function.
  */
     static void
-list_func_vars()
+list_func_vars(first)
+    int *first;
 {
     if (current_funccal != NULL)
 	list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
-						       (char_u *)"l:", FALSE);
+						(char_u *)"l:", FALSE, first);
 }
 
 /*
  * List variables in "arg".
  */
     static char_u *
-list_arg_vars(eap, arg)
+list_arg_vars(eap, arg, first)
     exarg_T	*eap;
     char_u	*arg;
+    int		*first;
 {
     int		error = FALSE;
     int		len;
@@ -2083,15 +2106,15 @@
 			{
 			    switch (*name)
 			    {
-				case 'g': list_glob_vars(); break;
-				case 'b': list_buf_vars(); break;
-				case 'w': list_win_vars(); break;
+				case 'g': list_glob_vars(first); break;
+				case 'b': list_buf_vars(first); break;
+				case 'w': list_win_vars(first); break;
 #ifdef FEAT_WINDOWS
-				case 't': list_tab_vars(); break;
+				case 't': list_tab_vars(first); break;
 #endif
-				case 'v': list_vim_vars(); break;
-				case 's': list_script_vars(); break;
-				case 'l': list_func_vars(); break;
+				case 'v': list_vim_vars(first); break;
+				case 's': list_script_vars(first); break;
+				case 'l': list_func_vars(first); break;
 				default:
 					  EMSG2(_("E738: Can't list variables for %s"), name);
 			    }
@@ -2108,7 +2131,9 @@
 			    *arg = NUL;
 			    list_one_var_a((char_u *)"",
 				    arg == arg_subsc ? name : name_start,
-				    tv.v_type, s == NULL ? (char_u *)"" : s);
+				    tv.v_type,
+				    s == NULL ? (char_u *)"" : s,
+				    first);
 			    *arg = c;
 			    vim_free(tf);
 			}
@@ -6794,7 +6819,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 +6904,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 +7068,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},
@@ -7099,6 +7125,7 @@
     {"getftype",	1, 1, f_getftype},
     {"getline",		1, 2, f_getline},
     {"getloclist",	1, 1, f_getqflist},
+    {"getmatches",	0, 0, f_getmatches},
     {"getpos",		1, 1, f_getpos},
     {"getqflist",	0, 0, f_getqflist},
     {"getreg",		0, 2, f_getreg},
@@ -7149,7 +7176,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},
@@ -7190,6 +7219,7 @@
     {"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},
@@ -8240,6 +8270,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
@@ -9868,18 +9912,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 +10186,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 +10325,40 @@
 }
 
 /*
+ * "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->dv_refcount;
+	    dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
+	    dict_add_nr_str(dict, "pattern", 0L, cur->pattern);
+	    dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
+	    dict_add_nr_str(dict, "id", (long)cur->id, NULL);
+	    list_append_dict(rettv->vval.v_list, dict);
+	    cur = cur->next;
+	}
+    }
+#endif
+}
+
+/*
  * "getpos(string)" function
  */
     static void
@@ -12439,6 +12529,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 +12577,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 +13830,7 @@
 	    }
 	    /* Shorten "remain". */
 	    if (*q != NUL)
-		STRCPY(remain, q - 1);
+		mch_memmove(remain, q - 1, STRLEN(q - 1) + 1);
 	    else
 	    {
 		vim_free(remain);
@@ -13919,6 +14069,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;
 
@@ -14498,6 +14650,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*/
@@ -14785,6 +14997,10 @@
 
     p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1, 0);
     p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2, 0);
+    if (p1 == NULL)
+	p1 = (char_u *)"";
+    if (p2 == NULL)
+	p2 = (char_u *)"";
     if (item_compare_ic)
 	res = STRICMP(p1, p2);
     else
@@ -15274,7 +15490,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);
 }
 
@@ -16497,9 +16714,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 +16729,7 @@
 	list_T		*l;
 	int		len;
 	int		error = FALSE;
+	listitem_T	*li;
 
 	l = varp->vval.v_list;
 	if (l == NULL)
@@ -16527,6 +16745,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 +16785,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 +16803,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 +18024,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 +18035,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 +18077,11 @@
 
     if (type == VAR_FUNC)
 	msg_puts((char_u *)"()");
+    if (*first)
+    {
+	msg_clr_eos();
+	*first = FALSE;
+    }
 }
 
 /*
@@ -19136,6 +19371,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 +20226,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 +20237,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 +20321,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 */
 
diff -Naur vim71.orig/src/ex_cmds.c vim71/src/ex_cmds.c
--- vim71.orig/src/ex_cmds.c	2007-05-07 19:41:01.000000000 +0000
+++ vim71/src/ex_cmds.c	2007-09-07 07:42:17.000000000 +0000
@@ -408,7 +408,11 @@
 		goto sortend;
 	    }
 	    *s = NUL;
-	    regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
+	    /* Use last search pattern if sort pattern is empty. */
+	    if (s == p + 1 && last_search_pat() != NULL)
+		regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
+	    else
+		regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
 	    if (regmatch.regprog == NULL)
 		goto sortend;
 	    p = s;		/* continue after the regexp */
@@ -2912,22 +2916,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 +2958,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 +2974,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 +3389,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 +3584,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 +3682,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 +3787,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
     }
@@ -4294,6 +4327,7 @@
 	do_error = TRUE;
 	do_print = FALSE;
 	do_count = FALSE;
+	do_number = FALSE;
 	do_ic = 0;
     }
     while (*cmd)
@@ -6351,9 +6385,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_docmd.c vim71/src/ex_docmd.c
--- vim71.orig/src/ex_docmd.c	2007-05-07 19:49:38.000000000 +0000
+++ vim71/src/ex_docmd.c	2007-09-07 07:42:17.000000000 +0000
@@ -133,6 +133,7 @@
 static void	get_flags __ARGS((exarg_T *eap));
 #if !defined(FEAT_PERL) || !defined(FEAT_PYTHON) || !defined(FEAT_TCL) \
 	|| !defined(FEAT_RUBY) || !defined(FEAT_MZSCHEME)
+# define HAVE_EX_SCRIPT_NI
 static void	ex_script_ni __ARGS((exarg_T *eap));
 #endif
 static char_u	*invalid_range __ARGS((exarg_T *eap));
@@ -2118,7 +2119,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
     /*
@@ -3276,39 +3281,65 @@
 
     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)
+#ifdef FEAT_MBYTE
+	    if (has_mbyte)
+		c = mb_ptr2char(p);
+	    else
+#endif
+		c = *p;
+	    if (c == '\\' && p[1] != NUL)
 		++p;
+	    else if (c == '`')
+	    {
+		if (!in_quote)
+		{
+		    xp->xp_pattern = p;
+		    bow = p + 1;
+		}
+		in_quote = !in_quote;
+	    }
 #ifdef SPACE_IN_FILENAME
-	    else if (vim_iswhite(*p) && (!(ea.argt & NOSPC) || usefilter))
+	    else if (!vim_isfilec_or_wc(c)
+					 && (!(ea.argt & NOSPC) || usefilter))
 #else
-	    else if (vim_iswhite(*p))
+	    else if (!vim_isfilec_or_wc(c))
 #endif
 	    {
-		p = skipwhite(p);
+		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;
-	    }
-	    else if (*p == '`')
-	    {
-		if (!in_quote)
-		{
-		    xp->xp_pattern = p;
-		    bow = p + 1;
-		}
-		in_quote = !in_quote;
+		p -= len;
 	    }
 	    mb_ptr_adv(p);
 	}
@@ -3401,14 +3432,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 +3447,8 @@
 		}
 	    }
 	    return find_nextcmd(arg);
-#endif
+# endif
 
-#ifdef FEAT_CMDL_COMPL
 /*
  * All completion for the +cmdline_compl feature goes here.
  */
@@ -3617,8 +3646,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:
@@ -3997,8 +4025,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.
@@ -4492,7 +4519,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;
 	}
@@ -10816,12 +10844,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 +10859,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 +10870,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 +10894,8 @@
 
 	    c = *end;
 	    *end = NUL;
-	    curwin->w_match[mi].regprog = vim_regcomp(p + 1, RE_MAGIC);
-	    if (curwin->w_match[mi].regprog == NULL)
-	    {
-		EMSG2(_(e_invarg2), p);
-		*end = c;
-		return;
-	    }
-	    curwin->w_match_pat[mi] = vim_strsave(p + 1);
+	    match_add(curwin, g, p + 1, 10, id);
+	    vim_free(g);
 	    *end = c;
 	}
     }
diff -Naur vim71.orig/src/ex_eval.c vim71/src/ex_eval.c
--- vim71.orig/src/ex_eval.c	2007-05-07 19:47:50.000000000 +0000
+++ vim71/src/ex_eval.c	2007-09-07 07:42:16.000000000 +0000
@@ -1551,7 +1551,7 @@
 		}
 		save_cpo  = p_cpo;
 		p_cpo = (char_u *)"";
-		regmatch.regprog = vim_regcomp(pat, TRUE);
+		regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
 		regmatch.rm_ic = FALSE;
 		if (end != NULL)
 		    *end = save_char;
diff -Naur vim71.orig/src/ex_getln.c vim71/src/ex_getln.c
--- vim71.orig/src/ex_getln.c	2007-05-07 19:47:23.000000000 +0000
+++ vim71/src/ex_getln.c	2007-09-07 07:42:17.000000000 +0000
@@ -268,7 +268,9 @@
     {
 	xpc.xp_context = ccline.xp_context;
 	xpc.xp_pattern = ccline.cmdbuff;
+# if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
 	xpc.xp_arg = ccline.xp_arg;
+# endif
     }
 #endif
 
@@ -484,7 +486,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 +536,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 */
@@ -730,8 +735,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)
@@ -2090,11 +2095,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 +2152,7 @@
 
 	/* Get one character at a time.  Don't use inchar(), it can't handle
 	 * special characters. */
+	prev_char = c1;
 	c1 = vgetc();
 
 	/*
@@ -2204,7 +2210,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 +2228,7 @@
 		    }
 		}
 		msg_clr_eos();
+		windgoto(msg_row, msg_col);
 		continue;
 	    }
 
@@ -2268,7 +2274,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)
@@ -4148,13 +4153,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 +4306,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 +4514,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 +4553,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;
 
diff -Naur vim71.orig/src/feature.h vim71/src/feature.h
--- vim71.orig/src/feature.h	2007-05-07 19:33:19.000000000 +0000
+++ vim71/src/feature.h	2007-09-07 07:42:16.000000000 +0000
@@ -673,7 +673,7 @@
 # define ESC_CHG_TO_ENG_MODE		/* if defined, when ESC pressed,
 					 * turn to english mode
 					 */
-# if !defined(FEAT_XFONTSET) && defined(HAVE_X11)
+# if !defined(FEAT_XFONTSET) && defined(HAVE_X11) && !defined(HAVE_GTK2)
 #  define FEAT_XFONTSET			/* Hangul input requires xfontset */
 # endif
 # if defined(FEAT_XIM) && !defined(LINT)
diff -Naur vim71.orig/src/fileio.c vim71/src/fileio.c
--- vim71.orig/src/fileio.c	2007-05-10 11:29:44.000000000 +0000
+++ vim71/src/fileio.c	2007-09-07 07:42:17.000000000 +0000
@@ -44,6 +44,10 @@
 /* Is there any system that doesn't have access()? */
 #define USE_MCH_ACCESS
 
+#if defined(sun) && defined(S_ISCHR)
+# define OPEN_CHR_FILES
+static int is_dev_fd_file(char_u *fname);
+#endif
 #ifdef FEAT_MBYTE
 static char_u *next_fenc __ARGS((char_u **pp));
 # ifdef FEAT_EVAL
@@ -406,6 +410,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 +432,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;
@@ -646,6 +654,7 @@
 	curbuf->b_start_eol = TRUE;
 #ifdef FEAT_MBYTE
 	curbuf->b_p_bomb = FALSE;
+	curbuf->b_start_bomb = FALSE;
 #endif
     }
 
@@ -904,7 +913,10 @@
 	file_rewind = FALSE;
 #ifdef FEAT_MBYTE
 	if (set_options)
+	{
 	    curbuf->b_p_bomb = FALSE;
+	    curbuf->b_start_bomb = FALSE;
+	}
 	conv_error = 0;
 #endif
     }
@@ -1353,7 +1365,10 @@
 		    size -= blen;
 		    mch_memmove(ptr, ptr + blen, (size_t)size);
 		    if (set_options)
+		    {
 			curbuf->b_p_bomb = TRUE;
+			curbuf->b_start_bomb = TRUE;
+		    }
 		}
 
 		if (fio_flags == FIO_UCSBOM)
@@ -2265,6 +2280,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 +2486,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 +2775,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.
@@ -3219,17 +3286,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)
diff -Naur vim71.orig/src/getchar.c vim71/src/getchar.c
--- vim71.orig/src/getchar.c	2007-05-07 19:18:20.000000000 +0000
+++ vim71/src/getchar.c	2007-09-07 07:42:17.000000000 +0000
@@ -1596,8 +1596,15 @@
 		continue;
 	    }
 #endif
-
 #ifdef FEAT_GUI
+	    /* The caller doesn't need to know that the focus event is delayed
+	     * until getting a character. */
+	    if (c == K_FOCUSGAINED || c == K_FOCUSLOST)
+	    {
+		ui_focus_change(c == K_FOCUSGAINED);
+		continue;
+	    }
+
 	    /* 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)
diff -Naur vim71.orig/src/globals.h vim71/src/globals.h
--- vim71.orig/src/globals.h	2007-05-07 19:44:26.000000000 +0000
+++ vim71/src/globals.h	2007-09-07 07:42:17.000000000 +0000
@@ -801,7 +801,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);
 
diff -Naur vim71.orig/src/gui.c vim71/src/gui.c
--- vim71.orig/src/gui.c	2007-05-07 19:50:55.000000000 +0000
+++ vim71/src/gui.c	2007-09-07 07:42:17.000000000 +0000
@@ -1080,7 +1080,8 @@
 		cur_width = gui.char_width;
 	    }
 #ifdef FEAT_MBYTE
-	    if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col) > 1)
+	    if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col,
+				    LineOffset[gui.row] + screen_Columns) > 1)
 	    {
 		/* Double wide character. */
 		if (shape_table[idx].shape != SHAPE_VER)
@@ -1159,7 +1160,7 @@
 #endif
 
 # if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
- 	|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC))
+	|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_MAC))
     if (gui_has_tabline())
 	text_area_y += gui.tabline_height;
 #endif
@@ -4518,7 +4519,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
 }
 
@@ -5117,7 +5129,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 08:37:37.000000000 +0000
+++ vim71/src/gui_gtk.c	2007-09-07 07:42:17.000000000 +0000
@@ -53,8 +53,8 @@
 # ifdef bindtextdomain
 #  undef bindtextdomain
 # endif
-# ifdef bindtextdomain_codeset
-#  undef bindtextdomain_codeset
+# ifdef bind_textdomain_codeset
+#  undef bind_textdomain_codeset
 # endif
 # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
 #  define ENABLE_NLS	/* so the texts in the dialog boxes are translated */
@@ -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 08:37:49.000000000 +0000
+++ vim71/src/gui_gtk_x11.c	2007-09-07 07:42:17.000000000 +0000
@@ -36,8 +36,8 @@
 # ifdef bindtextdomain
 #  undef bindtextdomain
 # endif
-# ifdef bindtextdomain_codeset
-#  undef bindtextdomain_codeset
+# ifdef bind_textdomain_codeset
+#  undef bind_textdomain_codeset
 # endif
 # if defined(FEAT_GETTEXT) && !defined(ENABLE_NLS)
 #  define ENABLE_NLS	/* so the texts in the dialog boxes are translated */
@@ -813,10 +813,15 @@
     if (blink_state == BLINK_NONE)
 	gui_mch_start_blink();
 
-    /* make sure keyboard input goes to the draw area (if this is focus for a window) */
+    /* make sure keyboard input goes to the draw area (if this is focus for a
+     * window) */
     if (widget != gui.drawarea)
 	gtk_widget_grab_focus(gui.drawarea);
 
+    /* make sure the input buffer is read */
+    if (gtk_main_level() > 0)
+	gtk_main_quit();
+
     return TRUE;
 }
 
@@ -829,6 +834,10 @@
     if (blink_state != BLINK_NONE)
 	gui_mch_stop_blink();
 
+    /* make sure the input buffer is read */
+    if (gtk_main_level() > 0)
+	gtk_main_quit();
+
     return TRUE;
 }
 
@@ -2188,8 +2197,10 @@
     escaped_filename = vim_strsave_escaped(filename, escape_chars);
     if (escaped_filename == NULL)
 	return FALSE;
-    mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename, NULL);
+    mksession_cmdline = g_strconcat("mksession ", (char *)escaped_filename,
+									NULL);
     vim_free(escaped_filename);
+
     /*
      * Use a reasonable hardcoded set of 'sessionoptions' flags to avoid
      * unpredictable effects when the session is saved automatically.  Also,
@@ -2199,7 +2210,7 @@
      */
     save_ssop_flags = ssop_flags;
     ssop_flags = (SSOP_BLANK|SSOP_CURDIR|SSOP_FOLDS|SSOP_GLOBALS
-		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE);
+		  |SSOP_HELP|SSOP_OPTIONS|SSOP_WINSIZE|SSOP_TABPAGES);
 
     do_cmdline_cmd((char_u *)"let Save_VV_this_session = v:this_session");
     failed = (do_cmdline_cmd((char_u *)mksession_cmdline) == FAIL);
diff -Naur vim71.orig/src/if_cscope.c vim71/src/if_cscope.c
--- vim71.orig/src/if_cscope.c	2007-03-11 14:29:57.000000000 +0000
+++ vim71/src/if_cscope.c	2007-09-07 07:42:17.000000000 +0000
@@ -24,11 +24,6 @@
     /* not UNIX, must be WIN32 */
 # include "vimio.h"
 # include <fcntl.h>
-# include <process.h>
-# define STDIN_FILENO    0
-# define STDOUT_FILENO   1
-# define STDERR_FILENO   2
-# define pipe(fds) _pipe(fds, 256, O_TEXT|O_NOINHERIT)
 #endif
 #include "if_cscope.h"
 
@@ -65,7 +60,7 @@
 static char *	    cs_parse_results __ARGS((int cnumber, char *buf, int bufsize, char **context, char **linenumber, char **search));
 static char *	    cs_pathcomponents __ARGS((char *path));
 static void	    cs_print_tags_priv __ARGS((char **, char **, int));
-static int	    cs_read_prompt __ARGS((int ));
+static int	    cs_read_prompt __ARGS((int));
 static void	    cs_release_csp __ARGS((int, int freefnpp));
 static int	    cs_reset __ARGS((exarg_T *eap));
 static char *	    cs_resolve_file __ARGS((int, char *));
@@ -73,6 +68,8 @@
 
 
 static csinfo_T	    csinfo[CSCOPE_MAX_CONNECTIONS];
+static int	    eap_arg_len;    /* length of eap->arg, set in
+				       cs_lookup_cmd() */
 static cscmd_T	    cs_cmds[] =
 {
     { "add",	cs_add,
@@ -260,14 +257,7 @@
 
     if ((p = cs_manage_matches(NULL, NULL, -1, Get)) == NULL)
 	return TRUE;
-
-    if ((int)strlen(p) > size)
-    {
-	strncpy((char *)buf, p, size - 1);
-	buf[size] = '\0';
-    }
-    else
-	(void)strcpy((char *)buf, p);
+    vim_strncpy(buf, (char_u *)p, size - 1);
 
     return FALSE;
 } /* cs_fgets */
@@ -386,7 +376,7 @@
  * PRIVATE: cs_add
  *
  * add cscope database or a directory name (to look for cscope.out)
- * the the cscope connection list
+ * to the cscope connection list
  *
  * MAXPATHL 256
  */
@@ -509,7 +499,7 @@
 #if defined(UNIX)
     else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))
 #else
-	/* substitute define S_ISREG from os_unix.h */
+	/* WIN32 - substitute define S_ISREG from os_unix.h */
     else if (((statbuf.st_mode) & S_IFMT) == S_IFREG)
 #endif
     {
@@ -722,17 +712,23 @@
 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;
-# endif
+#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;
 #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 +749,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 +763,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 +796,7 @@
 #ifdef UNIX
 	    return CSCOPE_FAILURE;
 #else
+	    /* WIN32 */
 	    goto err_closing;
 #endif
 	}
@@ -805,6 +813,7 @@
 #ifdef UNIX
 		return CSCOPE_FAILURE;
 #else
+		/* WIN32 */
 		goto err_closing;
 #endif
 	    }
@@ -823,6 +832,7 @@
 #ifdef UNIX
 	    return CSCOPE_FAILURE;
 #else
+	    /* WIN32 */
 	    goto err_closing;
 #endif
 	}
@@ -831,6 +841,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 +867,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 +876,52 @@
 	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((intptr_t)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((intptr_t)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 +953,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 +1304,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 +1388,9 @@
     if (eap->arg == NULL)
 	return NULL;
 
+    /* Store length of eap->arg before it gets modified by strtok(). */
+    eap_arg_len = STRLEN(eap->arg);
+
     if ((stok = strtok((char *)(eap->arg), (const char *)" ")) == NULL)
 	return NULL;
 
@@ -2099,8 +2089,8 @@
 /*
  * PRIVATE: cs_release_csp
  *
- * does the actual free'ing for the cs ptr with an optional flag of whether
- * or not to free the filename.  called by cs_kill and cs_reset.
+ * Does the actual free'ing for the cs ptr with an optional flag of whether
+ * or not to free the filename.  Called by cs_kill and cs_reset.
  */
     static void
 cs_release_csp(i, freefnpp)
@@ -2118,10 +2108,13 @@
 	(void)fputs("q\n", csinfo[i].to_fp);
 	(void)fflush(csinfo[i].to_fp);
     }
-    /* give cscope chance to exit normally */
-    if (csinfo[i].hProc != NULL
-	    && WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT)
-	TerminateProcess(csinfo[i].hProc, 0);
+    if (csinfo[i].hProc != NULL)
+    {
+	/* Give cscope a chance to exit normally */
+	if (WaitForSingleObject(csinfo[i].hProc, 1000) == WAIT_TIMEOUT)
+	    TerminateProcess(csinfo[i].hProc, 0);
+	CloseHandle(csinfo[i].hProc);
+    }
 #endif
 
     if (csinfo[i].fr_fp != NULL)
@@ -2195,7 +2188,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 +2297,21 @@
     return CSCOPE_SUCCESS;
 } /* cs_show */
 
+
+/*
+ * PUBLIC: cs_end
+ *
+ * Only called when VIM exits to quit any cscope sessions.
+ */
+    void
+cs_end()
+{
+    int i;
+
+    for (i = 0; i < CSCOPE_MAX_CONNECTIONS; i++)
+	cs_release_csp(i, TRUE);
+}
+
 #endif	/* FEAT_CSCOPE */
 
 /* the end */
diff -Naur vim71.orig/src/if_cscope.h vim71/src/if_cscope.h
--- vim71.orig/src/if_cscope.h	2005-06-30 17:14:22.000000000 +0000
+++ vim71/src/if_cscope.h	2007-09-07 07:42:17.000000000 +0000
@@ -72,7 +72,7 @@
     ino_t	    st_ino;	/* inode number of cscope db */
 #else
 # if defined(WIN32)
-    int	    pid;	/* Can't get pid so set it to 0 ;) */
+    DWORD	    pid;	/* PID of the connected cscope process. */
     HANDLE	    hProc;	/* cscope process handle */
     DWORD	    nVolume;	/* Volume serial number, instead of st_dev */
     DWORD	    nIndexHigh;	/* st_ino has no meaning in the Windows */
diff -Naur vim71.orig/src/if_mzsch.c vim71/src/if_mzsch.c
--- vim71.orig/src/if_mzsch.c	2007-05-12 11:13:47.000000000 +0000
+++ vim71/src/if_mzsch.c	2007-09-07 07:42:14.000000000 +0000
@@ -308,6 +308,8 @@
 static Scheme_Config *(*dll_scheme_current_config)(void);
 static Scheme_Object *(*dll_scheme_char_string_to_byte_string)
     (Scheme_Object *s);
+static Scheme_Object *(*dll_scheme_char_string_to_path)
+    (Scheme_Object *s);
 # endif
 
 /* arrays are imported directly */
@@ -398,6 +400,8 @@
 #  define scheme_current_config dll_scheme_current_config
 #  define scheme_char_string_to_byte_string \
     dll_scheme_char_string_to_byte_string
+#  define scheme_char_string_to_path \
+    dll_scheme_char_string_to_path
 # endif
 
 typedef struct
@@ -498,6 +502,8 @@
     {"scheme_current_config", (void **)&dll_scheme_current_config},
     {"scheme_char_string_to_byte_string",
 	(void **)&dll_scheme_char_string_to_byte_string},
+    {"scheme_char_string_to_path",
+	(void **)&dll_scheme_char_string_to_path},
 # endif
     {NULL, NULL}};
 
@@ -773,7 +779,14 @@
 #ifdef MZSCHEME_COLLECTS
     /* setup 'current-library-collection-paths' parameter */
     scheme_set_param(scheme_config, MZCONFIG_COLLECTION_PATHS,
-	    scheme_make_pair(scheme_make_string(MZSCHEME_COLLECTS),
+	    scheme_make_pair(
+# if MZSCHEME_VERSION_MAJOR >= 299
+		scheme_char_string_to_path(
+		    scheme_byte_string_to_char_string(
+			scheme_make_byte_string(MZSCHEME_COLLECTS))),
+# else
+		scheme_make_string(MZSCHEME_COLLECTS),
+# endif
 		scheme_null));
 #endif
 #ifdef HAVE_SANDBOX
diff -Naur vim71.orig/src/keymap.h vim71/src/keymap.h
--- vim71.orig/src/keymap.h	2006-08-22 11:38:38.000000000 +0000
+++ vim71/src/keymap.h	2007-09-07 07:42:17.000000000 +0000
@@ -254,6 +254,8 @@
     , KE_DROP		/* DnD data is available */
     , KE_CURSORHOLD	/* CursorHold event */
     , KE_NOP		/* doesn't do something */
+    , KE_FOCUSGAINED	/* focus gained */
+    , KE_FOCUSLOST	/* focus lost */
 };
 
 /*
@@ -445,6 +447,8 @@
 #define K_CMDWIN	TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
 
 #define K_DROP		TERMCAP2KEY(KS_EXTRA, KE_DROP)
+#define K_FOCUSGAINED	TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
+#define K_FOCUSLOST	TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
 
 #define K_CURSORHOLD	TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
 
diff -Naur vim71.orig/src/macros.h vim71/src/macros.h
--- vim71.orig/src/macros.h	2007-05-07 19:38:22.000000000 +0000
+++ vim71/src/macros.h	2007-09-07 07:42:17.000000000 +0000
@@ -54,10 +54,12 @@
 
 /*
  * toupper() and tolower() that use the current locale.
- * On some systems toupper()/tolower() only work on lower/uppercase characters
+ * On some systems toupper()/tolower() only work on lower/uppercase
+ * characters, first use islower() or isupper() then.
  * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
  * range 0 - 255.  toupper()/tolower() on some systems can't handle others.
- * Note: for UTF-8 use utf_toupper() and utf_tolower().
+ * Note: It is often better to use MB_TOLOWER() and MB_TOUPPER(), because many
+ * toupper() and tolower() implementations only work for ASCII.
  */
 #ifdef MSWIN
 #  define TOUPPER_LOC(c)	toupper_tab[(c) & 255]
diff -Naur vim71.orig/src/main.c vim71/src/main.c
--- vim71.orig/src/main.c	2007-05-07 19:38:44.000000000 +0000
+++ vim71/src/main.c	2007-09-07 07:42:17.000000000 +0000
@@ -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,9 @@
 #ifdef FEAT_NETBEANS_INTG
     netbeans_end();
 #endif
+#ifdef FEAT_CSCOPE
+    cs_end();
+#endif
 
     mch_exit(exitval);
 }
@@ -1360,8 +1384,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)
@@ -3632,7 +3655,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/main.c.orig vim71/src/main.c.orig
--- vim71.orig/src/main.c.orig	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/main.c.orig	2007-09-07 07:42:17.000000000 +0000
@@ -0,0 +1,3861 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved	by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#if defined(MSDOS) || defined(WIN32) || defined(_WIN64)
+# include "vimio.h"		/* for close() and dup() */
+#endif
+
+#define EXTERN
+#include "vim.h"
+
+#ifdef SPAWNO
+# include <spawno.h>		/* special MS-DOS swapping library */
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef __CYGWIN__
+# ifndef WIN32
+#  include <sys/cygwin.h>	/* for cygwin_conv_to_posix_path() */
+# endif
+# include <limits.h>
+#endif
+
+/* Maximum number of commands from + or -c arguments. */
+#define MAX_ARG_CMDS 10
+
+/* values for "window_layout" */
+#define WIN_HOR	    1	    /* "-o" horizontally split windows */
+#define	WIN_VER	    2	    /* "-O" vertically split windows */
+#define	WIN_TABS    3	    /* "-p" windows on tab pages */
+
+/* Struct for various parameters passed between main() and other functions. */
+typedef struct
+{
+    int		argc;
+    char	**argv;
+
+    int		evim_mode;		/* started as "evim" */
+    char_u	*use_vimrc;		/* vimrc from -u argument */
+
+    int		n_commands;		     /* no. of commands from + or -c */
+    char_u	*commands[MAX_ARG_CMDS];     /* commands from + or -c arg. */
+    char_u	cmds_tofree[MAX_ARG_CMDS];   /* commands that need free() */
+    int		n_pre_commands;		     /* no. of commands from --cmd */
+    char_u	*pre_commands[MAX_ARG_CMDS]; /* commands from --cmd argument */
+
+    int		edit_type;		/* type of editing to do */
+    char_u	*tagname;		/* tag from -t argument */
+#ifdef FEAT_QUICKFIX
+    char_u	*use_ef;		/* 'errorfile' from -q argument */
+#endif
+
+    int		want_full_screen;
+    int		stdout_isatty;		/* is stdout a terminal? */
+    char_u	*term;			/* specified terminal name */
+#ifdef FEAT_CRYPT
+    int		ask_for_key;		/* -x argument */
+#endif
+    int		no_swap_file;		/* "-n" argument used */
+#ifdef FEAT_EVAL
+    int		use_debug_break_level;
+#endif
+#ifdef FEAT_WINDOWS
+    int		window_count;		/* number of windows to use */
+    int		window_layout;		/* 0, WIN_HOR, WIN_VER or WIN_TABS */
+#endif
+
+#ifdef FEAT_CLIENTSERVER
+    int		serverArg;		/* TRUE when argument for a server */
+    char_u	*serverName_arg;	/* cmdline arg for server name */
+    char_u	*serverStr;		/* remote server command */
+    char_u	*serverStrEnc;		/* encoding of serverStr */
+    char_u	*servername;		/* allocated name for our server */
+#endif
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+    int		literal;		/* don't expand file names */
+#endif
+#ifdef MSWIN
+    int		full_path;		/* file name argument was full path */
+#endif
+#ifdef FEAT_DIFF
+    int		diff_mode;		/* start with 'diff' set */
+#endif
+} mparm_T;
+
+/* Values for edit_type. */
+#define EDIT_NONE   0	    /* no edit type yet */
+#define EDIT_FILE   1	    /* file name argument[s] given, use argument list */
+#define EDIT_STDIN  2	    /* read file from stdin */
+#define EDIT_TAG    3	    /* tag name argument given, use tagname */
+#define EDIT_QF	    4	    /* start in quickfix mode */
+
+#if defined(UNIX) || defined(VMS)
+static int file_owned __ARGS((char *fname));
+#endif
+static void mainerr __ARGS((int, char_u *));
+static void main_msg __ARGS((char *s));
+static void usage __ARGS((void));
+static int get_number_arg __ARGS((char_u *p, int *idx, int def));
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+static void init_locale __ARGS((void));
+#endif
+static void parse_command_name __ARGS((mparm_T *parmp));
+static void early_arg_scan __ARGS((mparm_T *parmp));
+static void command_line_scan __ARGS((mparm_T *parmp));
+static void check_tty __ARGS((mparm_T *parmp));
+static void read_stdin __ARGS((void));
+static void create_windows __ARGS((mparm_T *parmp));
+#ifdef FEAT_WINDOWS
+static void edit_buffers __ARGS((mparm_T *parmp));
+#endif
+static void exe_pre_commands __ARGS((mparm_T *parmp));
+static void exe_commands __ARGS((mparm_T *parmp));
+static void source_startup_scripts __ARGS((mparm_T *parmp));
+static void main_start_gui __ARGS((void));
+#if defined(HAS_SWAP_EXISTS_ACTION)
+static void check_swap_exists_action __ARGS((void));
+#endif
+#ifdef FEAT_CLIENTSERVER
+static void exec_on_server __ARGS((mparm_T *parmp));
+static void prepare_server __ARGS((mparm_T *parmp));
+static void cmdsrv_main __ARGS((int *argc, char **argv, char_u *serverName_arg, char_u **serverStr));
+static char_u *serverMakeName __ARGS((char_u *arg, char *cmd));
+#endif
+
+
+#ifdef STARTUPTIME
+static FILE *time_fd = NULL;
+#endif
+
+/*
+ * Different types of error messages.
+ */
+static char *(main_errors[]) =
+{
+    N_("Unknown option argument"),
+#define ME_UNKNOWN_OPTION	0
+    N_("Too many edit arguments"),
+#define ME_TOO_MANY_ARGS	1
+    N_("Argument missing after"),
+#define ME_ARG_MISSING		2
+    N_("Garbage after option argument"),
+#define ME_GARBAGE		3
+    N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),
+#define ME_EXTRA_CMD		4
+    N_("Invalid argument for"),
+#define ME_INVALID_ARG		5
+};
+
+#ifndef PROTO	    /* don't want a prototype for main() */
+    int
+# ifdef VIMDLL
+_export
+# endif
+# ifdef FEAT_GUI_MSWIN
+#  ifdef __BORLANDC__
+_cdecl
+#  endif
+VimMain
+# else
+main
+# endif
+(argc, argv)
+    int		argc;
+    char	**argv;
+{
+    char_u	*fname = NULL;		/* file name from command line */
+    mparm_T	params;			/* various parameters passed between
+					 * main() and other functions. */
+
+    /*
+     * Do any system-specific initialisations.  These can NOT use IObuff or
+     * NameBuff.  Thus emsg2() cannot be called!
+     */
+    mch_early_init();
+
+    /* Many variables are in "params" so that we can pass them to invoked
+     * functions without a lot of arguments.  "argc" and "argv" are also
+     * copied, so that they can be changed. */
+    vim_memset(&params, 0, sizeof(params));
+    params.argc = argc;
+    params.argv = argv;
+    params.want_full_screen = TRUE;
+#ifdef FEAT_EVAL
+    params.use_debug_break_level = -1;
+#endif
+#ifdef FEAT_WINDOWS
+    params.window_count = -1;
+#endif
+
+#ifdef FEAT_TCL
+    vim_tcl_init(params.argv[0]);
+#endif
+
+#ifdef MEM_PROFILE
+    atexit(vim_mem_profile_dump);
+#endif
+
+#ifdef STARTUPTIME
+    time_fd = mch_fopen(STARTUPTIME, "a");
+    TIME_MSG("--- VIM STARTING ---");
+#endif
+    starttime = time(NULL);
+
+#ifdef __EMX__
+    _wildcard(&params.argc, &params.argv);
+#endif
+
+#ifdef FEAT_MBYTE
+    (void)mb_init();	/* init mb_bytelen_tab[] to ones */
+#endif
+#ifdef FEAT_EVAL
+    eval_init();	/* init global variables */
+#endif
+
+#ifdef __QNXNTO__
+    qnx_init();		/* PhAttach() for clipboard, (and gui) */
+#endif
+
+#ifdef MAC_OS_CLASSIC
+    /* Prepare for possibly starting GUI sometime */
+    /* Macintosh needs this before any memory is allocated. */
+    gui_prepare(&params.argc, params.argv);
+    TIME_MSG("GUI prepared");
+#endif
+
+    /* Init the table of Normal mode commands. */
+    init_normal_cmds();
+
+#if defined(HAVE_DATE_TIME) && defined(VMS) && defined(VAXC)
+    make_version();	/* Construct the long version string. */
+#endif
+
+    /*
+     * Allocate space for the generic buffers (needed for set_init_1() and
+     * EMSG2()).
+     */
+    if ((IObuff = alloc(IOSIZE)) == NULL
+	    || (NameBuff = alloc(MAXPATHL)) == NULL)
+	mch_exit(0);
+    TIME_MSG("Allocated generic buffers");
+
+#ifdef NBDEBUG
+    /* Wait a moment for debugging NetBeans.  Must be after allocating
+     * NameBuff. */
+    nbdebug_log_init("SPRO_GVIM_DEBUG", "SPRO_GVIM_DLEVEL");
+    nbdebug_wait(WT_ENV | WT_WAIT | WT_STOP, "SPRO_GVIM_WAIT", 20);
+    TIME_MSG("NetBeans debug wait");
+#endif
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+    /*
+     * Setup to use the current locale (for ctype() and many other things).
+     * NOTE: Translated messages with encodings other than latin1 will not
+     * work until set_init_1() has been called!
+     */
+    init_locale();
+    TIME_MSG("locale set");
+#endif
+
+#ifdef FEAT_GUI
+    gui.dofork = TRUE;		    /* default is to use fork() */
+#endif
+
+    /*
+     * Do a first scan of the arguments in "argv[]":
+     *   -display or --display
+     *   --server...
+     *   --socketid
+     */
+    early_arg_scan(&params);
+
+#ifdef FEAT_SUN_WORKSHOP
+    findYourself(params.argv[0]);
+#endif
+#if defined(FEAT_GUI) && !defined(MAC_OS_CLASSIC)
+    /* Prepare for possibly starting GUI sometime */
+    gui_prepare(&params.argc, params.argv);
+    TIME_MSG("GUI prepared");
+#endif
+
+#ifdef FEAT_CLIPBOARD
+    clip_init(FALSE);		/* Initialise clipboard stuff */
+    TIME_MSG("clipboard setup");
+#endif
+
+    /*
+     * Check if we have an interactive window.
+     * On the Amiga: If there is no window, we open one with a newcli command
+     * (needed for :! to * work). mch_check_win() will also handle the -d or
+     * -dev argument.
+     */
+    params.stdout_isatty = (mch_check_win(params.argc, params.argv) != FAIL);
+    TIME_MSG("window checked");
+
+    /*
+     * Allocate the first window and buffer.
+     * Can't do anything without it, exit when it fails.
+     */
+    if (win_alloc_first() == FAIL)
+	mch_exit(0);
+
+    init_yank();		/* init yank buffers */
+
+    alist_init(&global_alist);	/* Init the argument list to empty. */
+
+    /*
+     * Set the default values for the options.
+     * NOTE: Non-latin1 translated messages are working only after this,
+     * because this is where "has_mbyte" will be set, which is used by
+     * msg_outtrans_len_attr().
+     * First find out the home directory, needed to expand "~" in options.
+     */
+    init_homedir();		/* find real value of $HOME */
+    set_init_1();
+    TIME_MSG("inits 1");
+
+#ifdef FEAT_EVAL
+    set_lang_var();		/* set v:lang and v:ctype */
+#endif
+
+#ifdef FEAT_CLIENTSERVER
+    /*
+     * Do the client-server stuff, unless "--servername ''" was used.
+     * This may exit Vim if the command was sent to the server.
+     */
+    exec_on_server(&params);
+#endif
+
+    /*
+     * Figure out the way to work from the command name argv[0].
+     * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
+     */
+    parse_command_name(&params);
+
+    /*
+     * Process the command line arguments.  File names are put in the global
+     * argument list "global_alist".
+     */
+    command_line_scan(&params);
+    TIME_MSG("parsing arguments");
+
+    /*
+     * On some systems, when we compile with the GUI, we always use it.  On Mac
+     * there is no terminal version, and on Windows we can't fork one off with
+     * :gui.
+     */
+#ifdef ALWAYS_USE_GUI
+    gui.starting = TRUE;
+#else
+# if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+    /*
+     * Check if the GUI can be started.  Reset gui.starting if not.
+     * Don't know about other systems, stay on the safe side and don't check.
+     */
+    if (gui.starting && gui_init_check() == FAIL)
+    {
+	gui.starting = FALSE;
+
+	/* When running "evim" or "gvim -y" we need the menus, exit if we
+	 * don't have them. */
+	if (params.evim_mode)
+	    mch_exit(1);
+    }
+# endif
+#endif
+
+    if (GARGCOUNT > 0)
+    {
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+	/*
+	 * Expand wildcards in file names.
+	 */
+	if (!params.literal)
+	{
+	    /* Temporarily add '(' and ')' to 'isfname'.  These are valid
+	     * filename characters but are excluded from 'isfname' to make
+	     * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
+	    do_cmdline_cmd((char_u *)":set isf+=(,)");
+	    alist_expand(NULL, 0);
+	    do_cmdline_cmd((char_u *)":set isf&");
+	}
+#endif
+	fname = alist_name(&GARGLIST[0]);
+    }
+
+#if defined(WIN32) && defined(FEAT_MBYTE)
+    {
+	extern void set_alist_count(void);
+
+	/* Remember the number of entries in the argument list.  If it changes
+	 * we don't react on setting 'encoding'. */
+	set_alist_count();
+    }
+#endif
+
+#ifdef MSWIN
+    if (GARGCOUNT == 1 && params.full_path)
+    {
+	/*
+	 * If there is one filename, fully qualified, we have very probably
+	 * been invoked from explorer, so change to the file's directory.
+	 * Hint: to avoid this when typing a command use a forward slash.
+	 * If the cd fails, it doesn't matter.
+	 */
+	(void)vim_chdirfile(fname);
+    }
+#endif
+    TIME_MSG("expanding arguments");
+
+#ifdef FEAT_DIFF
+    if (params.diff_mode && params.window_count == -1)
+	params.window_count = 0;	/* open up to 3 windows */
+#endif
+
+    /* Don't redraw until much later. */
+    ++RedrawingDisabled;
+
+    /*
+     * When listing swap file names, don't do cursor positioning et. al.
+     */
+    if (recoverymode && fname == NULL)
+	params.want_full_screen = FALSE;
+
+    /*
+     * When certain to start the GUI, don't check capabilities of terminal.
+     * For GTK we can't be sure, but when started from the desktop it doesn't
+     * make sense to try using a terminal.
+     */
+#if defined(ALWAYS_USE_GUI) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
+    if (gui.starting
+# ifdef FEAT_GUI_GTK
+	    && !isatty(2)
+# endif
+	    )
+	params.want_full_screen = FALSE;
+#endif
+
+#if defined(FEAT_GUI_MAC) && defined(MACOS_X_UNIX)
+    /* When the GUI is started from Finder, need to display messages in a
+     * message box.  isatty(2) returns TRUE anyway, thus we need to check the
+     * name to know we're not started from a terminal. */
+    if (gui.starting && (!isatty(2) || strcmp("/dev/console", ttyname(2)) == 0))
+    {
+	params.want_full_screen = FALSE;
+
+	/* Avoid always using "/" as the current directory.  Note that when
+	 * started from Finder the arglist will be filled later in
+	 * HandleODocAE() and "fname" will be NULL. */
+	if (getcwd((char *)NameBuff, MAXPATHL) != NULL
+						&& STRCMP(NameBuff, "/") == 0)
+	{
+	    if (fname != NULL)
+		(void)vim_chdirfile(fname);
+	    else
+	    {
+		expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
+		vim_chdir(NameBuff);
+	    }
+	}
+    }
+#endif
+
+    /*
+     * mch_init() sets up the terminal (window) for use.  This must be
+     * done after resetting full_screen, otherwise it may move the cursor
+     * (MSDOS).
+     * Note that we may use mch_exit() before mch_init()!
+     */
+    mch_init();
+    TIME_MSG("shell init");
+
+#ifdef USE_XSMP
+    /*
+     * For want of anywhere else to do it, try to connect to xsmp here.
+     * Fitting it in after gui_mch_init, but before gui_init (via termcapinit).
+     * Hijacking -X 'no X connection' to also disable XSMP connection as that
+     * has a similar delay upon failure.
+     * Only try if SESSION_MANAGER is set to something non-null.
+     */
+    if (!x_no_connect)
+    {
+	char *p = getenv("SESSION_MANAGER");
+
+	if (p != NULL && *p != NUL)
+	{
+	    xsmp_init();
+	    TIME_MSG("xsmp init");
+	}
+    }
+#endif
+
+    /*
+     * Print a warning if stdout is not a terminal.
+     */
+    check_tty(&params);
+
+    /* This message comes before term inits, but after setting "silent_mode"
+     * when the input is not a tty. */
+    if (GARGCOUNT > 1 && !silent_mode)
+	printf(_("%d files to edit\n"), GARGCOUNT);
+
+    if (params.want_full_screen && !silent_mode)
+    {
+	termcapinit(params.term);	/* set terminal name and get terminal
+				   capabilities (will set full_screen) */
+	screen_start();		/* don't know where cursor is now */
+	TIME_MSG("Termcap init");
+    }
+
+    /*
+     * Set the default values for the options that use Rows and Columns.
+     */
+    ui_get_shellsize();		/* inits Rows and Columns */
+#ifdef FEAT_NETBEANS_INTG
+    if (usingNetbeans)
+	Columns += 2;		/* leave room for glyph gutter */
+#endif
+    win_init_size();
+#ifdef FEAT_DIFF
+    /* Set the 'diff' option now, so that it can be checked for in a .vimrc
+     * file.  There is no buffer yet though. */
+    if (params.diff_mode)
+	diff_win_options(firstwin, FALSE);
+#endif
+
+    cmdline_row = Rows - p_ch;
+    msg_row = cmdline_row;
+    screenalloc(FALSE);		/* allocate screen buffers */
+    set_init_2();
+    TIME_MSG("inits 2");
+
+    msg_scroll = TRUE;
+    no_wait_return = TRUE;
+
+    init_mappings();		/* set up initial mappings */
+
+    init_highlight(TRUE, FALSE); /* set the default highlight groups */
+    TIME_MSG("init highlight");
+
+#ifdef FEAT_EVAL
+    /* Set the break level after the terminal is initialized. */
+    debug_break_level = params.use_debug_break_level;
+#endif
+
+    /* Execute --cmd arguments. */
+    exe_pre_commands(&params);
+
+    /* Source startup scripts. */
+    source_startup_scripts(&params);
+
+#ifdef FEAT_EVAL
+    /*
+     * Read all the plugin files.
+     * Only when compiled with +eval, since most plugins need it.
+     */
+    if (p_lpl)
+    {
+# ifdef VMS	/* Somehow VMS doesn't handle the "**". */
+	source_runtime((char_u *)"plugin/*.vim", TRUE);
+# else
+	source_runtime((char_u *)"plugin/**/*.vim", TRUE);
+# endif
+	TIME_MSG("loading plugins");
+    }
+#endif
+
+#ifdef FEAT_DIFF
+    /* Decide about window layout for diff mode after reading vimrc. */
+    if (params.diff_mode && params.window_layout == 0)
+    {
+	if (diffopt_horizontal())
+	    params.window_layout = WIN_HOR;	/* use horizontal split */
+	else
+	    params.window_layout = WIN_VER;	/* use vertical split */
+    }
+#endif
+
+    /*
+     * Recovery mode without a file name: List swap files.
+     * This uses the 'dir' option, therefore it must be after the
+     * initializations.
+     */
+    if (recoverymode && fname == NULL)
+    {
+	recover_names(NULL, TRUE, 0);
+	mch_exit(0);
+    }
+
+    /*
+     * Set a few option defaults after reading .vimrc files:
+     * 'title' and 'icon', Unix: 'shellpipe' and 'shellredir'.
+     */
+    set_init_3();
+    TIME_MSG("inits 3");
+
+    /*
+     * "-n" argument: Disable swap file by setting 'updatecount' to 0.
+     * Note that this overrides anything from a vimrc file.
+     */
+    if (params.no_swap_file)
+	p_uc = 0;
+
+#ifdef FEAT_FKMAP
+    if (curwin->w_p_rl && p_altkeymap)
+    {
+	p_hkmap = FALSE;	/* Reset the Hebrew keymap mode */
+# ifdef FEAT_ARABIC
+	curwin->w_p_arab = FALSE; /* Reset the Arabic keymap mode */
+# endif
+	p_fkmap = TRUE;		/* Set the Farsi keymap mode */
+    }
+#endif
+
+#ifdef FEAT_GUI
+    if (gui.starting)
+    {
+#if defined(UNIX) || defined(VMS)
+	/* When something caused a message from a vimrc script, need to output
+	 * an extra newline before the shell prompt. */
+	if (did_emsg || msg_didout)
+	    putchar('\n');
+#endif
+
+	gui_start();		/* will set full_screen to TRUE */
+	TIME_MSG("starting GUI");
+
+	/* When running "evim" or "gvim -y" we need the menus, exit if we
+	 * don't have them. */
+	if (!gui.in_use && params.evim_mode)
+	    mch_exit(1);
+    }
+#endif
+
+#ifdef SPAWNO		/* special MSDOS swapping library */
+    init_SPAWNO("", SWAP_ANY);
+#endif
+
+#ifdef FEAT_VIMINFO
+    /*
+     * Read in registers, history etc, but not marks, from the viminfo file
+     */
+    if (*p_viminfo != NUL)
+    {
+	read_viminfo(NULL, TRUE, FALSE, FALSE);
+	TIME_MSG("reading viminfo");
+    }
+#endif
+
+#ifdef FEAT_QUICKFIX
+    /*
+     * "-q errorfile": Load the error file now.
+     * If the error file can't be read, exit before doing anything else.
+     */
+    if (params.edit_type == EDIT_QF)
+    {
+	if (params.use_ef != NULL)
+	    set_string_option_direct((char_u *)"ef", -1,
+					   params.use_ef, OPT_FREE, SID_CARG);
+	if (qf_init(NULL, p_ef, p_efm, TRUE) < 0)
+	{
+	    out_char('\n');
+	    mch_exit(3);
+	}
+	TIME_MSG("reading errorfile");
+    }
+#endif
+
+    /*
+     * Start putting things on the screen.
+     * Scroll screen down before drawing over it
+     * Clear screen now, so file message will not be cleared.
+     */
+    starting = NO_BUFFERS;
+    no_wait_return = FALSE;
+    if (!exmode_active)
+	msg_scroll = FALSE;
+
+#ifdef FEAT_GUI
+    /*
+     * This seems to be required to make callbacks to be called now, instead
+     * of after things have been put on the screen, which then may be deleted
+     * when getting a resize callback.
+     * For the Mac this handles putting files dropped on the Vim icon to
+     * global_alist.
+     */
+    if (gui.in_use)
+    {
+# ifdef FEAT_SUN_WORKSHOP
+	if (!usingSunWorkShop)
+# endif
+	    gui_wait_for_chars(50L);
+	TIME_MSG("GUI delay");
+    }
+#endif
+
+#if defined(FEAT_GUI_PHOTON) && defined(FEAT_CLIPBOARD)
+    qnx_clip_init();
+#endif
+
+#ifdef FEAT_XCLIPBOARD
+    /* Start using the X clipboard, unless the GUI was started. */
+# ifdef FEAT_GUI
+    if (!gui.in_use)
+# endif
+    {
+	setup_term_clip();
+	TIME_MSG("setup clipboard");
+    }
+#endif
+
+#ifdef FEAT_CLIENTSERVER
+    /* Prepare for being a Vim server. */
+    prepare_server(&params);
+#endif
+
+    /*
+     * If "-" argument given: Read file from stdin.
+     * Do this before starting Raw mode, because it may change things that the
+     * writing end of the pipe doesn't like, e.g., in case stdin and stderr
+     * are the same terminal: "cat | vim -".
+     * Using autocommands here may cause trouble...
+     */
+    if (params.edit_type == EDIT_STDIN && !recoverymode)
+	read_stdin();
+
+#if defined(UNIX) || defined(VMS)
+    /* When switching screens and something caused a message from a vimrc
+     * script, need to output an extra newline on exit. */
+    if ((did_emsg || msg_didout) && *T_TI != NUL)
+	newline_on_exit = TRUE;
+#endif
+
+    /*
+     * When done something that is not allowed or error message call
+     * wait_return.  This must be done before starttermcap(), because it may
+     * switch to another screen. It must be done after settmode(TMODE_RAW),
+     * because we want to react on a single key stroke.
+     * Call settmode and starttermcap here, so the T_KS and T_TI may be
+     * defined by termcapinit and redefined in .exrc.
+     */
+    settmode(TMODE_RAW);
+    TIME_MSG("setting raw mode");
+
+    if (need_wait_return || msg_didany)
+    {
+	wait_return(TRUE);
+	TIME_MSG("waiting for return");
+    }
+
+    starttermcap();	    /* start termcap if not done by wait_return() */
+    TIME_MSG("start termcap");
+
+#ifdef FEAT_MOUSE
+    setmouse();				/* may start using the mouse */
+#endif
+    if (scroll_region)
+	scroll_region_reset();		/* In case Rows changed */
+    scroll_start();	/* may scroll the screen to the right position */
+
+    /*
+     * Don't clear the screen when starting in Ex mode, unless using the GUI.
+     */
+    if (exmode_active
+#ifdef FEAT_GUI
+			&& !gui.in_use
+#endif
+					)
+	must_redraw = CLEAR;
+    else
+    {
+	screenclear();			/* clear screen */
+	TIME_MSG("clearing screen");
+    }
+
+#ifdef FEAT_CRYPT
+    if (params.ask_for_key)
+    {
+	(void)get_crypt_key(TRUE, TRUE);
+	TIME_MSG("getting crypt key");
+    }
+#endif
+
+    no_wait_return = TRUE;
+
+    /*
+     * Create the requested number of windows and edit buffers in them.
+     * Also does recovery if "recoverymode" set.
+     */
+    create_windows(&params);
+    TIME_MSG("opening buffers");
+
+#ifdef FEAT_EVAL
+    /* clear v:swapcommand */
+    set_vim_var_string(VV_SWAPCOMMAND, NULL, -1);
+#endif
+
+    /* Ex starts at last line of the file */
+    if (exmode_active)
+	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
+    TIME_MSG("BufEnter autocommands");
+#endif
+    setpcmark();
+
+#ifdef FEAT_QUICKFIX
+    /*
+     * When started with "-q errorfile" jump to first error now.
+     */
+    if (params.edit_type == EDIT_QF)
+    {
+	qf_jump(NULL, 0, 0, FALSE);
+	TIME_MSG("jump to first error");
+    }
+#endif
+
+#ifdef FEAT_WINDOWS
+    /*
+     * If opened more than one window, start editing files in the other
+     * windows.
+     */
+    edit_buffers(&params);
+#endif
+
+#ifdef FEAT_DIFF
+    if (params.diff_mode)
+    {
+	win_T	*wp;
+
+	/* set options in each window for "vimdiff". */
+	for (wp = firstwin; wp != NULL; wp = wp->w_next)
+	    diff_win_options(wp, TRUE);
+    }
+#endif
+
+    /*
+     * Shorten any of the filenames, but only when absolute.
+     */
+    shorten_fnames(FALSE);
+
+    /*
+     * Need to jump to the tag before executing the '-c command'.
+     * Makes "vim -c '/return' -t main" work.
+     */
+    if (params.tagname != NULL)
+    {
+#if defined(HAS_SWAP_EXISTS_ACTION)
+	swap_exists_did_quit = FALSE;
+#endif
+
+	vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
+	do_cmdline_cmd(IObuff);
+	TIME_MSG("jumping to tag");
+
+#if defined(HAS_SWAP_EXISTS_ACTION)
+	/* If the user doesn't want to edit the file then we quit here. */
+	if (swap_exists_did_quit)
+	    getout(1);
+#endif
+    }
+
+    /* Execute any "+", "-c" and "-S" arguments. */
+    if (params.n_commands > 0)
+	exe_commands(&params);
+
+    RedrawingDisabled = 0;
+    redraw_all_later(NOT_VALID);
+    no_wait_return = FALSE;
+    starting = 0;
+
+#ifdef FEAT_TERMRESPONSE
+    /* Requesting the termresponse is postponed until here, so that a "-c q"
+     * argument doesn't make it appear in the shell Vim was started from. */
+    may_req_termresponse();
+#endif
+
+    /* start in insert mode */
+    if (p_im)
+	need_start_insertmode = TRUE;
+
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_VIMENTER, NULL, NULL, FALSE, curbuf);
+    TIME_MSG("VimEnter autocommands");
+#endif
+
+#if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND)
+    /* When a startup script or session file setup for diff'ing and
+     * scrollbind, sync the scrollbind now. */
+    if (curwin->w_p_diff && curwin->w_p_scb)
+    {
+	update_topline();
+	check_scrollbind((linenr_T)0, 0L);
+	TIME_MSG("diff scrollbinding");
+    }
+#endif
+
+#if defined(WIN3264) && !defined(FEAT_GUI_W32)
+    mch_set_winsize_now();	    /* Allow winsize changes from now on */
+#endif
+
+#if defined(FEAT_GUI) && defined(FEAT_WINDOWS)
+    /* When tab pages were created, may need to update the tab pages line and
+     * scrollbars.  This is skipped while creating them. */
+    if (first_tabpage->tp_next != NULL)
+    {
+	out_flush();
+	gui_init_which_components(NULL);
+	gui_update_scrollbars(TRUE);
+    }
+    need_mouse_correct = TRUE;
+#endif
+
+    /* If ":startinsert" command used, stuff a dummy command to be able to
+     * call normal_cmd(), which will then start Insert mode. */
+    if (restart_edit != 0)
+	stuffcharReadbuff(K_NOP);
+
+#ifdef FEAT_NETBEANS_INTG
+    if (usingNetbeans)
+	/* Tell the client that it can start sending commands. */
+	netbeans_startup_done();
+#endif
+
+    TIME_MSG("before starting main loop");
+
+    /*
+     * Call the main command loop.  This never returns.
+     */
+    main_loop(FALSE, FALSE);
+
+    return 0;
+}
+#endif /* PROTO */
+
+/*
+ * Main loop: Execute Normal mode commands until exiting Vim.
+ * Also used to handle commands in the command-line window, until the window
+ * is closed.
+ * Also used to handle ":visual" command after ":global": execute Normal mode
+ * commands, return when entering Ex mode.  "noexmode" is TRUE then.
+ */
+    void
+main_loop(cmdwin, noexmode)
+    int		cmdwin;	    /* TRUE when working in the command-line window */
+    int		noexmode;   /* TRUE when return on entering Ex mode */
+{
+    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
+     * it, restore the state and continue.  This might not always work
+     * properly, but at least we don't exit unexpectedly when the X server
+     * exists while Vim is running in a console. */
+    if (!cmdwin && !noexmode && SETJMP(x_jump_env))
+    {
+	State = NORMAL;
+# ifdef FEAT_VISUAL
+	VIsual_active = FALSE;
+# endif
+	got_int = TRUE;
+	need_wait_return = FALSE;
+	global_busy = FALSE;
+	exmode_active = 0;
+	skip_redraw = FALSE;
+	RedrawingDisabled = 0;
+	no_wait_return = 0;
+# ifdef FEAT_EVAL
+	emsg_skip = 0;
+# endif
+	emsg_off = 0;
+# ifdef FEAT_MOUSE
+	setmouse();
+# endif
+	settmode(TMODE_RAW);
+	starttermcap();
+	scroll_start();
+	redraw_later_clear();
+    }
+#endif
+
+    clear_oparg(&oa);
+    while (!cmdwin
+#ifdef FEAT_CMDWIN
+	    || cmdwin_result == 0
+#endif
+	    )
+    {
+	if (stuff_empty())
+	{
+	    did_check_timestamps = FALSE;
+	    if (need_check_timestamps)
+		check_timestamps(FALSE);
+	    if (need_wait_return)	/* if wait_return still needed ... */
+		wait_return(FALSE);	/* ... call it now */
+	    if (need_start_insertmode && goto_im()
+#ifdef FEAT_VISUAL
+		    && !VIsual_active
+#endif
+		    )
+	    {
+		need_start_insertmode = FALSE;
+		stuffReadbuff((char_u *)"i");	/* start insert mode next */
+		/* skip the fileinfo message now, because it would be shown
+		 * after insert mode finishes! */
+		need_fileinfo = FALSE;
+	    }
+	}
+
+	/* 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 (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;
+
+	/*
+	 * If skip redraw is set (for ":" in wait_return()), don't redraw now.
+	 * If there is nothing in the stuff_buffer or do_redraw is TRUE,
+	 * update cursor and redraw.
+	 */
+	if (skip_redraw || exmode_active)
+	    skip_redraw = FALSE;
+	else if (do_redraw || stuff_empty())
+	{
+#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
+
+#if defined(FEAT_DIFF) && defined(FEAT_SCROLLBIND)
+	    /* Scroll-binding for diff mode may have been postponed until
+	     * here.  Avoids doing it for every change. */
+	    if (diff_need_scrollbind)
+	    {
+		check_scrollbind((linenr_T)0, 0L);
+		diff_need_scrollbind = FALSE;
+	    }
+#endif
+#if defined(FEAT_FOLDING) && defined(FEAT_VISUAL)
+	    /* Include a closed fold completely in the Visual area. */
+	    foldAdjustVisual();
+#endif
+#ifdef FEAT_FOLDING
+	    /*
+	     * When 'foldclose' is set, apply 'foldlevel' to folds that don't
+	     * contain the cursor.
+	     * When 'foldopen' is "all", open the fold(s) under the cursor.
+	     * This may mark the window for redrawing.
+	     */
+	    if (hasAnyFolding(curwin) && !char_avail())
+	    {
+		foldCheckClose();
+		if (fdo_flags & FDO_ALL)
+		    foldOpenCursor();
+	    }
+#endif
+
+	    /*
+	     * Before redrawing, make sure w_topline is correct, and w_leftcol
+	     * if lines don't wrap, and w_skipcol if lines wrap.
+	     */
+	    update_topline();
+	    validate_cursor();
+
+#ifdef FEAT_VISUAL
+	    if (VIsual_active)
+		update_curbuf(INVERTED);/* update inverted part */
+	    else
+#endif
+		if (must_redraw)
+		update_screen(0);
+	    else if (redraw_cmdline || clear_cmdline)
+		showmode();
+#ifdef FEAT_WINDOWS
+	    redraw_statuslines();
+#endif
+#ifdef FEAT_TITLE
+	    if (need_maketitle)
+		maketitle();
+#endif
+	    /* display message after redraw */
+	    if (keep_msg != NULL)
+	    {
+		char_u *p;
+
+		/* msg_attr_keep() will set keep_msg to NULL, must free the
+		 * string here. */
+		p = keep_msg;
+		keep_msg = NULL;
+		msg_attr(p, keep_msg_attr);
+		vim_free(p);
+	    }
+	    if (need_fileinfo)		/* show file info after redraw */
+	    {
+		fileinfo(FALSE, TRUE, FALSE);
+		need_fileinfo = FALSE;
+	    }
+
+	    emsg_on_display = FALSE;	/* can delete error message now */
+	    did_emsg = FALSE;
+	    msg_didany = FALSE;		/* reset lines_left in msg_start() */
+	    may_clear_sb_text();	/* clear scroll-back text on next msg */
+	    showruler(FALSE);
+
+	    setcursor();
+	    cursor_on();
+
+	    do_redraw = FALSE;
+	}
+#ifdef FEAT_GUI
+	if (need_mouse_correct)
+	    gui_mouse_correct();
+#endif
+
+	/*
+	 * Update w_curswant if w_set_curswant has been set.
+	 * Postponed until here to avoid computing w_virtcol too often.
+	 */
+	update_curswant();
+
+#ifdef FEAT_EVAL
+	/*
+	 * May perform garbage collection when waiting for a character, but
+	 * only at the very toplevel.  Otherwise we may be using a List or
+	 * Dict internally somewhere.
+	 * "may_garbage_collect" is reset in vgetc() which is invoked through
+	 * do_exmode() and normal_cmd().
+	 */
+	may_garbage_collect = (!cmdwin && !noexmode);
+#endif
+	/*
+	 * If we're invoked as ex, do a round of ex commands.
+	 * Otherwise, get and execute a normal mode command.
+	 */
+	if (exmode_active)
+	{
+	    if (noexmode)   /* End of ":global/path/visual" commands */
+		return;
+	    do_exmode(exmode_active == EXMODE_VIM);
+	}
+	else
+	    normal_cmd(&oa, TRUE);
+    }
+}
+
+
+#if defined(USE_XSMP) || defined(FEAT_GUI_MSWIN) || defined(PROTO)
+/*
+ * Exit, but leave behind swap files for modified buffers.
+ */
+    void
+getout_preserve_modified(exitval)
+    int		exitval;
+{
+# if defined(SIGHUP) && defined(SIG_IGN)
+    /* Ignore SIGHUP, because a dropped connection causes a read error, which
+     * makes Vim exit and then handling SIGHUP causes various reentrance
+     * problems. */
+    signal(SIGHUP, SIG_IGN);
+# endif
+
+    ml_close_notmod();		    /* close all not-modified buffers */
+    ml_sync_all(FALSE, FALSE);	    /* preserve all swap files */
+    ml_close_all(FALSE);	    /* close all memfiles, without deleting */
+    getout(exitval);		    /* exit Vim properly */
+}
+#endif
+
+
+/* Exit properly */
+    void
+getout(exitval)
+    int		exitval;
+{
+#ifdef FEAT_AUTOCMD
+    buf_T	*buf;
+    win_T	*wp;
+    tabpage_T	*tp, *next_tp;
+#endif
+
+    exiting = TRUE;
+
+    /* When running in Ex mode an error causes us to exit with a non-zero exit
+     * code.  POSIX requires this, although it's not 100% clear from the
+     * standard. */
+    if (exmode_active)
+	exitval += ex_exitval;
+
+    /* Position the cursor on the last screen line, below all the text */
+#ifdef FEAT_GUI
+    if (!gui.in_use)
+#endif
+	windgoto((int)Rows - 1, 0);
+
+#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
+    /* Optionally print hashtable efficiency. */
+    hash_debug_results();
+#endif
+
+#ifdef FEAT_GUI
+    msg_didany = FALSE;
+#endif
+
+#ifdef FEAT_AUTOCMD
+    /* Trigger BufWinLeave for all windows, but only once per buffer. */
+# if defined FEAT_WINDOWS
+    for (tp = first_tabpage; tp != NULL; tp = next_tp)
+    {
+	next_tp = tp->tp_next;
+	for (wp = (tp == curtab)
+		    ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next)
+	{
+	    buf = wp->w_buffer;
+	    if (buf->b_changedtick != -1)
+	    {
+		apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
+								  FALSE, buf);
+		buf->b_changedtick = -1;    /* note that we did it already */
+		/* start all over, autocommands may mess up the lists */
+		next_tp = first_tabpage;
+		break;
+	    }
+	}
+    }
+# else
+    apply_autocmds(EVENT_BUFWINLEAVE, curbuf, curbuf->b_fname, FALSE, curbuf);
+# endif
+
+    /* Trigger BufUnload for buffers that are loaded */
+    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
+	if (buf->b_ml.ml_mfp != NULL)
+	{
+	    apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
+								  FALSE, buf);
+	    if (!buf_valid(buf))	/* autocmd may delete the buffer */
+		break;
+	}
+    apply_autocmds(EVENT_VIMLEAVEPRE, NULL, NULL, FALSE, curbuf);
+#endif
+
+#ifdef FEAT_VIMINFO
+    if (*p_viminfo != NUL)
+	/* Write out the registers, history, marks etc, to the viminfo file */
+	write_viminfo(NULL, FALSE);
+#endif
+
+#ifdef FEAT_AUTOCMD
+    apply_autocmds(EVENT_VIMLEAVE, NULL, NULL, FALSE, curbuf);
+#endif
+
+#ifdef FEAT_PROFILE
+    profile_dump();
+#endif
+
+    if (did_emsg
+#ifdef FEAT_GUI
+	    || (gui.in_use && msg_didany && p_verbose > 0)
+#endif
+	    )
+    {
+	/* give the user a chance to read the (error) message */
+	no_wait_return = FALSE;
+	wait_return(FALSE);
+    }
+
+#ifdef FEAT_AUTOCMD
+    /* Position the cursor again, the autocommands may have moved it */
+# ifdef FEAT_GUI
+    if (!gui.in_use)
+# endif
+	windgoto((int)Rows - 1, 0);
+#endif
+
+#ifdef FEAT_MZSCHEME
+    mzscheme_end();
+#endif
+#ifdef FEAT_TCL
+    tcl_end();
+#endif
+#ifdef FEAT_RUBY
+    ruby_end();
+#endif
+#ifdef FEAT_PYTHON
+    python_end();
+#endif
+#ifdef FEAT_PERL
+    perl_end();
+#endif
+#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
+    iconv_end();
+#endif
+#ifdef FEAT_NETBEANS_INTG
+    netbeans_end();
+#endif
+
+    mch_exit(exitval);
+}
+
+/*
+ * Get a (optional) count for a Vim argument.
+ */
+    static int
+get_number_arg(p, idx, def)
+    char_u	*p;	    /* pointer to argument */
+    int		*idx;	    /* index in argument, is incremented */
+    int		def;	    /* default value */
+{
+    if (vim_isdigit(p[*idx]))
+    {
+	def = atoi((char *)&(p[*idx]));
+	while (vim_isdigit(p[*idx]))
+	    *idx = *idx + 1;
+    }
+    return def;
+}
+
+#if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
+/*
+ * Setup to use the current locale (for ctype() and many other things).
+ */
+    static void
+init_locale()
+{
+    setlocale(LC_ALL, "");
+# ifdef WIN32
+    /* Apparently MS-Windows printf() may cause a crash when we give it 8-bit
+     * text while it's expecting text in the current locale.  This call avoids
+     * that. */
+    setlocale(LC_CTYPE, "C");
+# endif
+
+# ifdef FEAT_GETTEXT
+    {
+	int	mustfree = FALSE;
+	char_u	*p;
+
+#  ifdef DYNAMIC_GETTEXT
+	/* Initialize the gettext library */
+	dyn_libintl_init(NULL);
+#  endif
+	/* expand_env() doesn't work yet, because chartab[] is not initialized
+	 * yet, call vim_getenv() directly */
+	p = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
+	if (p != NULL && *p != NUL)
+	{
+	    vim_snprintf((char *)NameBuff, MAXPATHL, "%s/lang", p);
+	    bindtextdomain(VIMPACKAGE, (char *)NameBuff);
+	}
+	if (mustfree)
+	    vim_free(p);
+	textdomain(VIMPACKAGE);
+    }
+# endif
+}
+#endif
+
+/*
+ * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
+ * If the executable name starts with "r" we disable shell commands.
+ * If the next character is "e" we run in Easy mode.
+ * If the next character is "g" we run the GUI version.
+ * If the next characters are "view" we start in readonly mode.
+ * If the next characters are "diff" or "vimdiff" we start in diff mode.
+ * If the next characters are "ex" we start in Ex mode.  If it's followed
+ * by "im" use improved Ex mode.
+ */
+    static void
+parse_command_name(parmp)
+    mparm_T	*parmp;
+{
+    char_u	*initstr;
+
+    initstr = gettail((char_u *)parmp->argv[0]);
+
+#ifdef MACOS_X_UNIX
+    /* An issue has been seen when launching Vim in such a way that
+     * $PWD/$ARGV[0] or $ARGV[0] is not the absolute path to the
+     * executable or a symbolic link of it. Until this issue is resolved
+     * we prohibit the GUI from being used.
+     */
+    if (STRCMP(initstr, parmp->argv[0]) == 0)
+	disallow_gui = TRUE;
+
+    /* TODO: On MacOS X default to gui if argv[0] ends in:
+     *       /Vim.app/Contents/MacOS/Vim */
+#endif
+
+#ifdef FEAT_EVAL
+    set_vim_var_string(VV_PROGNAME, initstr, -1);
+#endif
+
+    if (TOLOWER_ASC(initstr[0]) == 'r')
+    {
+	restricted = TRUE;
+	++initstr;
+    }
+
+    /* Avoid using evim mode for "editor". */
+    if (TOLOWER_ASC(initstr[0]) == 'e'
+	    && (TOLOWER_ASC(initstr[1]) == 'v'
+		|| TOLOWER_ASC(initstr[1]) == 'g'))
+    {
+#ifdef FEAT_GUI
+	gui.starting = TRUE;
+#endif
+	parmp->evim_mode = TRUE;
+	++initstr;
+    }
+
+    if (TOLOWER_ASC(initstr[0]) == 'g' || initstr[0] == 'k')
+    {
+	main_start_gui();
+#ifdef FEAT_GUI
+	++initstr;
+#endif
+    }
+
+    if (STRNICMP(initstr, "view", 4) == 0)
+    {
+	readonlymode = TRUE;
+	curbuf->b_p_ro = TRUE;
+	p_uc = 10000;			/* don't update very often */
+	initstr += 4;
+    }
+    else if (STRNICMP(initstr, "vim", 3) == 0)
+	initstr += 3;
+
+    /* Catch "[r][g]vimdiff" and "[r][g]viewdiff". */
+    if (STRICMP(initstr, "diff") == 0)
+    {
+#ifdef FEAT_DIFF
+	parmp->diff_mode = TRUE;
+#else
+	mch_errmsg(_("This Vim was not compiled with the diff feature."));
+	mch_errmsg("\n");
+	mch_exit(2);
+#endif
+    }
+
+    if (STRNICMP(initstr, "ex", 2) == 0)
+    {
+	if (STRNICMP(initstr + 2, "im", 2) == 0)
+	    exmode_active = EXMODE_VIM;
+	else
+	    exmode_active = EXMODE_NORMAL;
+	change_compatible(TRUE);	/* set 'compatible' */
+    }
+}
+
+/*
+ * Get the name of the display, before gui_prepare() removes it from
+ * argv[].  Used for the xterm-clipboard display.
+ *
+ * Also find the --server... arguments and --socketid
+ */
+/*ARGSUSED*/
+    static void
+early_arg_scan(parmp)
+    mparm_T	*parmp;
+{
+#if defined(FEAT_XCLIPBOARD) || defined(FEAT_CLIENTSERVER)
+    int		argc = parmp->argc;
+    char	**argv = parmp->argv;
+    int		i;
+
+    for (i = 1; i < argc; i++)
+    {
+	if (STRCMP(argv[i], "--") == 0)
+	    break;
+# ifdef FEAT_XCLIPBOARD
+	else if (STRICMP(argv[i], "-display") == 0
+#  if defined(FEAT_GUI_GTK)
+		|| STRICMP(argv[i], "--display") == 0
+#  endif
+		)
+	{
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    xterm_display = argv[++i];
+	}
+# endif
+# ifdef FEAT_CLIENTSERVER
+	else if (STRICMP(argv[i], "--servername") == 0)
+	{
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    parmp->serverName_arg = (char_u *)argv[++i];
+	}
+	else if (STRICMP(argv[i], "--serverlist") == 0)
+	    parmp->serverArg = TRUE;
+	else if (STRNICMP(argv[i], "--remote", 8) == 0)
+	{
+	    parmp->serverArg = TRUE;
+#  ifdef FEAT_GUI
+	    if (strstr(argv[i], "-wait") != 0)
+		/* don't fork() when starting the GUI to edit files ourself */
+		gui.dofork = FALSE;
+#  endif
+	}
+# endif
+# ifdef FEAT_GUI_GTK
+	else if (STRICMP(argv[i], "--socketid") == 0)
+	{
+	    unsigned int    socket_id;
+	    int		    count;
+
+	    if (i == argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    if (STRNICMP(argv[i+1], "0x", 2) == 0)
+		count = sscanf(&(argv[i + 1][2]), "%x", &socket_id);
+	    else
+		count = sscanf(argv[i+1], "%u", &socket_id);
+	    if (count != 1)
+		mainerr(ME_INVALID_ARG, (char_u *)argv[i]);
+	    else
+		gtk_socket_id = socket_id;
+	    i++;
+	}
+	else if (STRICMP(argv[i], "--echo-wid") == 0)
+	    echo_wid_arg = TRUE;
+# endif
+    }
+#endif
+}
+
+/*
+ * Scan the command line arguments.
+ */
+    static void
+command_line_scan(parmp)
+    mparm_T	*parmp;
+{
+    int		argc = parmp->argc;
+    char	**argv = parmp->argv;
+    int		argv_idx;		/* index in argv[n][] */
+    int		had_minmin = FALSE;	/* found "--" argument */
+    int		want_argument;		/* option argument with argument */
+    int		c;
+    char_u	*p = NULL;
+    long	n;
+
+    --argc;
+    ++argv;
+    argv_idx = 1;	    /* active option letter is argv[0][argv_idx] */
+    while (argc > 0)
+    {
+	/*
+	 * "+" or "+{number}" or "+/{pat}" or "+{command}" argument.
+	 */
+	if (argv[0][0] == '+' && !had_minmin)
+	{
+	    if (parmp->n_commands >= MAX_ARG_CMDS)
+		mainerr(ME_EXTRA_CMD, NULL);
+	    argv_idx = -1;	    /* skip to next argument */
+	    if (argv[0][1] == NUL)
+		parmp->commands[parmp->n_commands++] = (char_u *)"$";
+	    else
+		parmp->commands[parmp->n_commands++] = (char_u *)&(argv[0][1]);
+	}
+
+	/*
+	 * Optional argument.
+	 */
+	else if (argv[0][0] == '-' && !had_minmin)
+	{
+	    want_argument = FALSE;
+	    c = argv[0][argv_idx++];
+#ifdef VMS
+	    /*
+	     * VMS only uses upper case command lines.  Interpret "-X" as "-x"
+	     * and "-/X" as "-X".
+	     */
+	    if (c == '/')
+	    {
+		c = argv[0][argv_idx++];
+		c = TOUPPER_ASC(c);
+	    }
+	    else
+		c = TOLOWER_ASC(c);
+#endif
+	    switch (c)
+	    {
+	    case NUL:		/* "vim -"  read from stdin */
+				/* "ex -" silent mode */
+		if (exmode_active)
+		    silent_mode = TRUE;
+		else
+		{
+		    if (parmp->edit_type != EDIT_NONE)
+			mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		    parmp->edit_type = EDIT_STDIN;
+		    read_cmd_fd = 2;	/* read from stderr instead of stdin */
+		}
+		argv_idx = -1;		/* skip to next argument */
+		break;
+
+	    case '-':		/* "--" don't take any more option arguments */
+				/* "--help" give help message */
+				/* "--version" give version message */
+				/* "--literal" take files literally */
+				/* "--nofork" don't fork */
+				/* "--noplugin[s]" skip plugins */
+				/* "--cmd <cmd>" execute cmd before vimrc */
+		if (STRICMP(argv[0] + argv_idx, "help") == 0)
+		    usage();
+		else if (STRICMP(argv[0] + argv_idx, "version") == 0)
+		{
+		    Columns = 80;	/* need to init Columns */
+		    info_message = TRUE; /* use mch_msg(), not mch_errmsg() */
+		    list_version();
+		    msg_putchar('\n');
+		    msg_didout = FALSE;
+		    mch_exit(0);
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0)
+		{
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+		    parmp->literal = TRUE;
+#endif
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "nofork", 6) == 0)
+		{
+#ifdef FEAT_GUI
+		    gui.dofork = FALSE;	/* don't fork() when starting GUI */
+#endif
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "noplugin", 8) == 0)
+		    p_lpl = FALSE;
+		else if (STRNICMP(argv[0] + argv_idx, "cmd", 3) == 0)
+		{
+		    want_argument = TRUE;
+		    argv_idx += 3;
+		}
+#ifdef FEAT_CLIENTSERVER
+		else if (STRNICMP(argv[0] + argv_idx, "serverlist", 10) == 0)
+		    ; /* already processed -- no arg */
+		else if (STRNICMP(argv[0] + argv_idx, "servername", 10) == 0
+		       || STRNICMP(argv[0] + argv_idx, "serversend", 10) == 0)
+		{
+		    /* already processed -- snatch the following arg */
+		    if (argc > 1)
+		    {
+			--argc;
+			++argv;
+		    }
+		}
+#endif
+#ifdef FEAT_GUI_GTK
+		else if (STRNICMP(argv[0] + argv_idx, "socketid", 8) == 0)
+		{
+		    /* already processed -- snatch the following arg */
+		    if (argc > 1)
+		    {
+			--argc;
+			++argv;
+		    }
+		}
+		else if (STRNICMP(argv[0] + argv_idx, "echo-wid", 8) == 0)
+		{
+		    /* already processed, skip */
+		}
+#endif
+		else
+		{
+		    if (argv[0][argv_idx])
+			mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
+		    had_minmin = TRUE;
+		}
+		if (!want_argument)
+		    argv_idx = -1;	/* skip to next argument */
+		break;
+
+	    case 'A':		/* "-A" start in Arabic mode */
+#ifdef FEAT_ARABIC
+		set_option_value((char_u *)"arabic", 1L, NULL, 0);
+#else
+		mch_errmsg(_(e_noarabic));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'b':		/* "-b" binary mode */
+		/* Needs to be effective before expanding file names, because
+		 * for Win32 this makes us edit a shortcut file itself,
+		 * instead of the file it links to. */
+		set_options_bin(curbuf->b_p_bin, 1, 0);
+		curbuf->b_p_bin = 1;	    /* binary file I/O */
+		break;
+
+	    case 'C':		/* "-C"  Compatible */
+		change_compatible(TRUE);
+		break;
+
+	    case 'e':		/* "-e" Ex mode */
+		exmode_active = EXMODE_NORMAL;
+		break;
+
+	    case 'E':		/* "-E" Improved Ex mode */
+		exmode_active = EXMODE_VIM;
+		break;
+
+	    case 'f':		/* "-f"  GUI: run in foreground.  Amiga: open
+				window directly, not with newcli */
+#ifdef FEAT_GUI
+		gui.dofork = FALSE;	/* don't fork() when starting GUI */
+#endif
+		break;
+
+	    case 'g':		/* "-g" start GUI */
+		main_start_gui();
+		break;
+
+	    case 'F':		/* "-F" start in Farsi mode: rl + fkmap set */
+#ifdef FEAT_FKMAP
+		curwin->w_p_rl = p_fkmap = TRUE;
+#else
+		mch_errmsg(_(e_nofarsi));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'h':		/* "-h" give help message */
+#ifdef FEAT_GUI_GNOME
+		/* Tell usage() to exit for "gvim". */
+		gui.starting = FALSE;
+#endif
+		usage();
+		break;
+
+	    case 'H':		/* "-H" start in Hebrew mode: rl + hkmap set */
+#ifdef FEAT_RIGHTLEFT
+		curwin->w_p_rl = p_hkmap = TRUE;
+#else
+		mch_errmsg(_(e_nohebrew));
+		mch_exit(2);
+#endif
+		break;
+
+	    case 'l':		/* "-l" lisp mode, 'lisp' and 'showmatch' on */
+#ifdef FEAT_LISP
+		set_option_value((char_u *)"lisp", 1L, NULL, 0);
+		p_sm = TRUE;
+#endif
+		break;
+
+	    case 'M':		/* "-M"  no changes or writing of files */
+		reset_modifiable();
+		/* FALLTHROUGH */
+
+	    case 'm':		/* "-m"  no writing of files */
+		p_write = FALSE;
+		break;
+
+	    case 'y':		/* "-y"  easy mode */
+#ifdef FEAT_GUI
+		gui.starting = TRUE;	/* start GUI a bit later */
+#endif
+		parmp->evim_mode = TRUE;
+		break;
+
+	    case 'N':		/* "-N"  Nocompatible */
+		change_compatible(FALSE);
+		break;
+
+	    case 'n':		/* "-n" no swap file */
+		parmp->no_swap_file = TRUE;
+		break;
+
+	    case 'p':		/* "-p[N]" open N tab pages */
+#ifdef TARGET_API_MAC_OSX
+		/* For some reason on MacOS X, an argument like:
+		   -psn_0_10223617 is passed in when invoke from Finder
+		   or with the 'open' command */
+		if (argv[0][argv_idx] == 's')
+		{
+		    argv_idx = -1; /* bypass full -psn */
+		    main_start_gui();
+		    break;
+		}
+#endif
+#ifdef FEAT_WINDOWS
+		/* default is 0: open window for each file */
+		parmp->window_count = get_number_arg((char_u *)argv[0],
+								&argv_idx, 0);
+		parmp->window_layout = WIN_TABS;
+#endif
+		break;
+
+	    case 'o':		/* "-o[N]" open N horizontal split windows */
+#ifdef FEAT_WINDOWS
+		/* default is 0: open window for each file */
+		parmp->window_count = get_number_arg((char_u *)argv[0],
+								&argv_idx, 0);
+		parmp->window_layout = WIN_HOR;
+#endif
+		break;
+
+		case 'O':	/* "-O[N]" open N vertical split windows */
+#if defined(FEAT_VERTSPLIT) && defined(FEAT_WINDOWS)
+		/* default is 0: open window for each file */
+		parmp->window_count = get_number_arg((char_u *)argv[0],
+								&argv_idx, 0);
+		parmp->window_layout = WIN_VER;
+#endif
+		break;
+
+#ifdef FEAT_QUICKFIX
+	    case 'q':		/* "-q" QuickFix mode */
+		if (parmp->edit_type != EDIT_NONE)
+		    mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		parmp->edit_type = EDIT_QF;
+		if (argv[0][argv_idx])		/* "-q{errorfile}" */
+		{
+		    parmp->use_ef = (char_u *)argv[0] + argv_idx;
+		    argv_idx = -1;
+		}
+		else if (argc > 1)		/* "-q {errorfile}" */
+		    want_argument = TRUE;
+		break;
+#endif
+
+	    case 'R':		/* "-R" readonly mode */
+		readonlymode = TRUE;
+		curbuf->b_p_ro = TRUE;
+		p_uc = 10000;			/* don't update very often */
+		break;
+
+	    case 'r':		/* "-r" recovery mode */
+	    case 'L':		/* "-L" recovery mode */
+		recoverymode = 1;
+		break;
+
+	    case 's':
+		if (exmode_active)	/* "-s" silent (batch) mode */
+		    silent_mode = TRUE;
+		else		/* "-s {scriptin}" read from script file */
+		    want_argument = TRUE;
+		break;
+
+	    case 't':		/* "-t {tag}" or "-t{tag}" jump to tag */
+		if (parmp->edit_type != EDIT_NONE)
+		    mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+		parmp->edit_type = EDIT_TAG;
+		if (argv[0][argv_idx])		/* "-t{tag}" */
+		{
+		    parmp->tagname = (char_u *)argv[0] + argv_idx;
+		    argv_idx = -1;
+		}
+		else				/* "-t {tag}" */
+		    want_argument = TRUE;
+		break;
+
+#ifdef FEAT_EVAL
+	    case 'D':		/* "-D"		Debugging */
+		parmp->use_debug_break_level = 9999;
+		break;
+#endif
+#ifdef FEAT_DIFF
+	    case 'd':		/* "-d"		'diff' */
+# ifdef AMIGA
+		/* check for "-dev {device}" */
+		if (argv[0][argv_idx] == 'e' && argv[0][argv_idx + 1] == 'v')
+		    want_argument = TRUE;
+		else
+# endif
+		    parmp->diff_mode = TRUE;
+		break;
+#endif
+	    case 'V':		/* "-V{N}"	Verbose level */
+		/* default is 10: a little bit verbose */
+		p_verbose = get_number_arg((char_u *)argv[0], &argv_idx, 10);
+		if (argv[0][argv_idx] != NUL)
+		{
+		    set_option_value((char_u *)"verbosefile", 0L,
+					     (char_u *)argv[0] + argv_idx, 0);
+		    argv_idx = (int)STRLEN(argv[0]);
+		}
+		break;
+
+	    case 'v':		/* "-v"  Vi-mode (as if called "vi") */
+		exmode_active = 0;
+#ifdef FEAT_GUI
+		gui.starting = FALSE;	/* don't start GUI */
+#endif
+		break;
+
+	    case 'w':		/* "-w{number}"	set window height */
+				/* "-w {scriptout}"	write to script */
+		if (vim_isdigit(((char_u *)argv[0])[argv_idx]))
+		{
+		    n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
+		    set_option_value((char_u *)"window", n, NULL, 0);
+		    break;
+		}
+		want_argument = TRUE;
+		break;
+
+#ifdef FEAT_CRYPT
+	    case 'x':		/* "-x"  encrypted reading/writing of files */
+		parmp->ask_for_key = TRUE;
+		break;
+#endif
+
+	    case 'X':		/* "-X"  don't connect to X server */
+#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
+		x_no_connect = TRUE;
+#endif
+		break;
+
+	    case 'Z':		/* "-Z"  restricted mode */
+		restricted = TRUE;
+		break;
+
+	    case 'c':		/* "-c{command}" or "-c {command}" execute
+				   command */
+		if (argv[0][argv_idx] != NUL)
+		{
+		    if (parmp->n_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    parmp->commands[parmp->n_commands++] = (char_u *)argv[0]
+								   + argv_idx;
+		    argv_idx = -1;
+		    break;
+		}
+		/*FALLTHROUGH*/
+	    case 'S':		/* "-S {file}" execute Vim script */
+	    case 'i':		/* "-i {viminfo}" use for viminfo */
+#ifndef FEAT_DIFF
+	    case 'd':		/* "-d {device}" device (for Amiga) */
+#endif
+	    case 'T':		/* "-T {terminal}" terminal name */
+	    case 'u':		/* "-u {vimrc}" vim inits file */
+	    case 'U':		/* "-U {gvimrc}" gvim inits file */
+	    case 'W':		/* "-W {scriptout}" overwrite */
+#ifdef FEAT_GUI_W32
+	    case 'P':		/* "-P {parent title}" MDI parent */
+#endif
+		want_argument = TRUE;
+		break;
+
+	    default:
+		mainerr(ME_UNKNOWN_OPTION, (char_u *)argv[0]);
+	    }
+
+	    /*
+	     * Handle option arguments with argument.
+	     */
+	    if (want_argument)
+	    {
+		/*
+		 * Check for garbage immediately after the option letter.
+		 */
+		if (argv[0][argv_idx] != NUL)
+		    mainerr(ME_GARBAGE, (char_u *)argv[0]);
+
+		--argc;
+		if (argc < 1 && c != 'S')
+		    mainerr_arg_missing((char_u *)argv[0]);
+		++argv;
+		argv_idx = -1;
+
+		switch (c)
+		{
+		case 'c':	/* "-c {command}" execute command */
+		case 'S':	/* "-S {file}" execute Vim script */
+		    if (parmp->n_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    if (c == 'S')
+		    {
+			char	*a;
+
+			if (argc < 1)
+			    /* "-S" without argument: use default session file
+			     * name. */
+			    a = SESSION_FILE;
+			else if (argv[0][0] == '-')
+			{
+			    /* "-S" followed by another option: use default
+			     * session file name. */
+			    a = SESSION_FILE;
+			    ++argc;
+			    --argv;
+			}
+			else
+			    a = argv[0];
+			p = alloc((unsigned)(STRLEN(a) + 4));
+			if (p == NULL)
+			    mch_exit(2);
+			sprintf((char *)p, "so %s", a);
+			parmp->cmds_tofree[parmp->n_commands] = TRUE;
+			parmp->commands[parmp->n_commands++] = p;
+		    }
+		    else
+			parmp->commands[parmp->n_commands++] =
+							    (char_u *)argv[0];
+		    break;
+
+		case '-':	/* "--cmd {command}" execute command */
+		    if (parmp->n_pre_commands >= MAX_ARG_CMDS)
+			mainerr(ME_EXTRA_CMD, NULL);
+		    parmp->pre_commands[parmp->n_pre_commands++] =
+							    (char_u *)argv[0];
+		    break;
+
+	    /*	case 'd':   -d {device} is handled in mch_check_win() for the
+	     *		    Amiga */
+
+#ifdef FEAT_QUICKFIX
+		case 'q':	/* "-q {errorfile}" QuickFix mode */
+		    parmp->use_ef = (char_u *)argv[0];
+		    break;
+#endif
+
+		case 'i':	/* "-i {viminfo}" use for viminfo */
+		    use_viminfo = (char_u *)argv[0];
+		    break;
+
+		case 's':	/* "-s {scriptin}" read from script file */
+		    if (scriptin[0] != NULL)
+		    {
+scripterror:
+			mch_errmsg(_("Attempt to open script file again: \""));
+			mch_errmsg(argv[-1]);
+			mch_errmsg(" ");
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    if ((scriptin[0] = mch_fopen(argv[0], READBIN)) == NULL)
+		    {
+			mch_errmsg(_("Cannot open for reading: \""));
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    if (save_typebuf() == FAIL)
+			mch_exit(2);	/* out of memory */
+		    break;
+
+		case 't':	/* "-t {tag}" */
+		    parmp->tagname = (char_u *)argv[0];
+		    break;
+
+		case 'T':	/* "-T {terminal}" terminal name */
+		    /*
+		     * The -T term argument is always available and when
+		     * HAVE_TERMLIB is supported it overrides the environment
+		     * variable TERM.
+		     */
+#ifdef FEAT_GUI
+		    if (term_is_gui((char_u *)argv[0]))
+			gui.starting = TRUE;	/* start GUI a bit later */
+		    else
+#endif
+			parmp->term = (char_u *)argv[0];
+		    break;
+
+		case 'u':	/* "-u {vimrc}" vim inits file */
+		    parmp->use_vimrc = (char_u *)argv[0];
+		    break;
+
+		case 'U':	/* "-U {gvimrc}" gvim inits file */
+#ifdef FEAT_GUI
+		    use_gvimrc = (char_u *)argv[0];
+#endif
+		    break;
+
+		case 'w':	/* "-w {nr}" 'window' value */
+				/* "-w {scriptout}" append to script file */
+		    if (vim_isdigit(*((char_u *)argv[0])))
+		    {
+			argv_idx = 0;
+			n = get_number_arg((char_u *)argv[0], &argv_idx, 10);
+			set_option_value((char_u *)"window", n, NULL, 0);
+			argv_idx = -1;
+			break;
+		    }
+		    /*FALLTHROUGH*/
+		case 'W':	/* "-W {scriptout}" overwrite script file */
+		    if (scriptout != NULL)
+			goto scripterror;
+		    if ((scriptout = mch_fopen(argv[0],
+				    c == 'w' ? APPENDBIN : WRITEBIN)) == NULL)
+		    {
+			mch_errmsg(_("Cannot open for script output: \""));
+			mch_errmsg(argv[0]);
+			mch_errmsg("\"\n");
+			mch_exit(2);
+		    }
+		    break;
+
+#ifdef FEAT_GUI_W32
+		case 'P':		/* "-P {parent title}" MDI parent */
+		    gui_mch_set_parent(argv[0]);
+		    break;
+#endif
+		}
+	    }
+	}
+
+	/*
+	 * File name argument.
+	 */
+	else
+	{
+	    argv_idx = -1;	    /* skip to next argument */
+
+	    /* Check for only one type of editing. */
+	    if (parmp->edit_type != EDIT_NONE && parmp->edit_type != EDIT_FILE)
+		mainerr(ME_TOO_MANY_ARGS, (char_u *)argv[0]);
+	    parmp->edit_type = EDIT_FILE;
+
+#ifdef MSWIN
+	    /* Remember if the argument was a full path before changing
+	     * slashes to backslashes. */
+	    if (argv[0][0] != NUL && argv[0][1] == ':' && argv[0][2] == '\\')
+		parmp->full_path = TRUE;
+#endif
+
+	    /* Add the file to the global argument list. */
+	    if (ga_grow(&global_alist.al_ga, 1) == FAIL
+		    || (p = vim_strsave((char_u *)argv[0])) == NULL)
+		mch_exit(2);
+#ifdef FEAT_DIFF
+	    if (parmp->diff_mode && mch_isdir(p) && GARGCOUNT > 0
+				      && !mch_isdir(alist_name(&GARGLIST[0])))
+	    {
+		char_u	    *r;
+
+		r = concat_fnames(p, gettail(alist_name(&GARGLIST[0])), TRUE);
+		if (r != NULL)
+		{
+		    vim_free(p);
+		    p = r;
+		}
+	    }
+#endif
+#if defined(__CYGWIN32__) && !defined(WIN32)
+	    /*
+	     * If vim is invoked by non-Cygwin tools, convert away any
+	     * DOS paths, so things like .swp files are created correctly.
+	     * Look for evidence of non-Cygwin paths before we bother.
+	     * This is only for when using the Unix files.
+	     */
+	    if (strpbrk(p, "\\:") != NULL)
+	    {
+		char posix_path[PATH_MAX];
+
+		cygwin_conv_to_posix_path(p, posix_path);
+		vim_free(p);
+		p = vim_strsave(posix_path);
+		if (p == NULL)
+		    mch_exit(2);
+	    }
+#endif
+
+#ifdef USE_FNAME_CASE
+	    /* Make the case of the file name match the actual file. */
+	    fname_case(p, 0);
+#endif
+
+	    alist_add(&global_alist, p,
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+		    parmp->literal ? 2 : 0	/* add buffer nr after exp. */
+#else
+		    2		/* add buffer number now and use curbuf */
+#endif
+		    );
+
+#if defined(FEAT_MBYTE) && defined(WIN32)
+	    {
+		/* Remember this argument has been added to the argument list.
+		 * Needed when 'encoding' is changed. */
+		used_file_arg(argv[0], parmp->literal, parmp->full_path,
+							    parmp->diff_mode);
+	    }
+#endif
+	}
+
+	/*
+	 * If there are no more letters after the current "-", go to next
+	 * argument.  argv_idx is set to -1 when the current argument is to be
+	 * skipped.
+	 */
+	if (argv_idx <= 0 || argv[0][argv_idx] == NUL)
+	{
+	    --argc;
+	    ++argv;
+	    argv_idx = 1;
+	}
+    }
+
+#ifdef FEAT_EVAL
+    /* If there is a "+123" or "-c" command, set v:swapcommand to the first
+     * one. */
+    if (parmp->n_commands > 0)
+    {
+	p = alloc((unsigned)STRLEN(parmp->commands[0]) + 3);
+	if (p != NULL)
+	{
+	    sprintf((char *)p, ":%s\r", parmp->commands[0]);
+	    set_vim_var_string(VV_SWAPCOMMAND, p, -1);
+	    vim_free(p);
+	}
+    }
+#endif
+}
+
+/*
+ * Print a warning if stdout is not a terminal.
+ * When starting in Ex mode and commands come from a file, set Silent mode.
+ */
+    static void
+check_tty(parmp)
+    mparm_T	*parmp;
+{
+    int		input_isatty;		/* is active input a terminal? */
+
+    input_isatty = mch_input_isatty();
+    if (exmode_active)
+    {
+	if (!input_isatty)
+	    silent_mode = TRUE;
+    }
+    else if (parmp->want_full_screen && (!parmp->stdout_isatty || !input_isatty)
+#ifdef FEAT_GUI
+	    /* don't want the delay when started from the desktop */
+	    && !gui.starting
+#endif
+	    )
+    {
+#ifdef NBDEBUG
+	/*
+	 * This shouldn't be necessary. But if I run netbeans with the log
+	 * output coming to the console and XOpenDisplay fails, I get vim
+	 * trying to start with input/output to my console tty.  This fills my
+	 * input buffer so fast I can't even kill the process in under 2
+	 * minutes (and it beeps continuously the whole time :-)
+	 */
+	if (usingNetbeans && (!parmp->stdout_isatty || !input_isatty))
+	{
+	    mch_errmsg(_("Vim: Error: Failure to start gvim from NetBeans\n"));
+	    exit(1);
+	}
+#endif
+	if (!parmp->stdout_isatty)
+	    mch_errmsg(_("Vim: Warning: Output is not to a terminal\n"));
+	if (!input_isatty)
+	    mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
+	out_flush();
+	if (scriptin[0] == NULL)
+	    ui_delay(2000L, TRUE);
+	TIME_MSG("Warning delay");
+    }
+}
+
+/*
+ * Read text from stdin.
+ */
+    static void
+read_stdin()
+{
+    int	    i;
+
+#if defined(HAS_SWAP_EXISTS_ACTION)
+    /* When getting the ATTENTION prompt here, use a dialog */
+    swap_exists_action = SEA_DIALOG;
+#endif
+    no_wait_return = TRUE;
+    i = msg_didany;
+    set_buflisted(TRUE);
+    (void)open_buffer(TRUE, NULL);	/* create memfile and read file */
+    no_wait_return = FALSE;
+    msg_didany = i;
+    TIME_MSG("reading stdin");
+#if defined(HAS_SWAP_EXISTS_ACTION)
+    check_swap_exists_action();
+#endif
+#if !(defined(AMIGA) || defined(MACOS))
+    /*
+     * Close stdin and dup it from stderr.  Required for GPM to work
+     * properly, and for running external commands.
+     * Is there any other system that cannot do this?
+     */
+    close(0);
+    dup(2);
+#endif
+}
+
+/*
+ * Create the requested number of windows and edit buffers in them.
+ * Also does recovery if "recoverymode" set.
+ */
+/*ARGSUSED*/
+    static void
+create_windows(parmp)
+    mparm_T	*parmp;
+{
+#ifdef FEAT_WINDOWS
+    int		dorewind;
+    int		done = 0;
+
+    /*
+     * Create the number of windows that was requested.
+     */
+    if (parmp->window_count == -1)	/* was not set */
+	parmp->window_count = 1;
+    if (parmp->window_count == 0)
+	parmp->window_count = GARGCOUNT;
+    if (parmp->window_count > 1)
+    {
+	/* Don't change the windows if there was a command in .vimrc that
+	 * already split some windows */
+	if (parmp->window_layout == 0)
+	    parmp->window_layout = WIN_HOR;
+	if (parmp->window_layout == WIN_TABS)
+	{
+	    parmp->window_count = make_tabpages(parmp->window_count);
+	    TIME_MSG("making tab pages");
+	}
+	else if (firstwin->w_next == NULL)
+	{
+	    parmp->window_count = make_windows(parmp->window_count,
+					     parmp->window_layout == WIN_VER);
+	    TIME_MSG("making windows");
+	}
+	else
+	    parmp->window_count = win_count();
+    }
+    else
+	parmp->window_count = 1;
+#endif
+
+    if (recoverymode)			/* do recover */
+    {
+	msg_scroll = TRUE;		/* scroll message up */
+	ml_recover();
+	if (curbuf->b_ml.ml_mfp == NULL) /* failed */
+	    getout(1);
+	do_modelines(0);		/* do modelines */
+    }
+    else
+    {
+	/*
+	 * Open a buffer for windows that don't have one yet.
+	 * Commands in the .vimrc might have loaded a file or split the window.
+	 * Watch out for autocommands that delete a window.
+	 */
+#ifdef FEAT_AUTOCMD
+	/*
+	 * Don't execute Win/Buf Enter/Leave autocommands here
+	 */
+	++autocmd_no_enter;
+	++autocmd_no_leave;
+#endif
+#ifdef FEAT_WINDOWS
+	dorewind = TRUE;
+	while (done++ < 1000)
+	{
+	    if (dorewind)
+	    {
+		if (parmp->window_layout == WIN_TABS)
+		    goto_tabpage(1);
+		else
+		    curwin = firstwin;
+	    }
+	    else if (parmp->window_layout == WIN_TABS)
+	    {
+		if (curtab->tp_next == NULL)
+		    break;
+		goto_tabpage(0);
+	    }
+	    else
+	    {
+		if (curwin->w_next == NULL)
+		    break;
+		curwin = curwin->w_next;
+	    }
+	    dorewind = FALSE;
+#endif
+	    curbuf = curwin->w_buffer;
+	    if (curbuf->b_ml.ml_mfp == NULL)
+	    {
+#ifdef FEAT_FOLDING
+		/* Set 'foldlevel' to 'foldlevelstart' if it's not negative. */
+		if (p_fdls >= 0)
+		    curwin->w_p_fdl = p_fdls;
+#endif
+#if defined(HAS_SWAP_EXISTS_ACTION)
+		/* When getting the ATTENTION prompt here, use a dialog */
+		swap_exists_action = SEA_DIALOG;
+#endif
+		set_buflisted(TRUE);
+		(void)open_buffer(FALSE, NULL); /* create memfile, read file */
+
+#if defined(HAS_SWAP_EXISTS_ACTION)
+		if (swap_exists_action == SEA_QUIT)
+		{
+		    if (got_int || only_one_window())
+		    {
+			/* abort selected or quit and only one window */
+			did_emsg = FALSE;   /* avoid hit-enter prompt */
+			getout(1);
+		    }
+		    /* We can't close the window, it would disturb what
+		     * happens next.  Clear the file name and set the arg
+		     * index to -1 to delete it later. */
+		    setfname(curbuf, NULL, NULL, FALSE);
+		    curwin->w_arg_idx = -1;
+		    swap_exists_action = SEA_NONE;
+		}
+		else
+		    handle_swap_exists(NULL);
+#endif
+#ifdef FEAT_AUTOCMD
+		dorewind = TRUE;		/* start again */
+#endif
+	    }
+#ifdef FEAT_WINDOWS
+	    ui_breakcheck();
+	    if (got_int)
+	    {
+		(void)vgetc();	/* only break the file loading, not the rest */
+		break;
+	    }
+	}
+#endif
+#ifdef FEAT_WINDOWS
+	if (parmp->window_layout == WIN_TABS)
+	    goto_tabpage(1);
+	else
+	    curwin = firstwin;
+	curbuf = curwin->w_buffer;
+#endif
+#ifdef FEAT_AUTOCMD
+	--autocmd_no_enter;
+	--autocmd_no_leave;
+#endif
+    }
+}
+
+#ifdef FEAT_WINDOWS
+    /*
+     * If opened more than one window, start editing files in the other
+     * windows.  make_windows() has already opened the windows.
+     */
+    static void
+edit_buffers(parmp)
+    mparm_T	*parmp;
+{
+    int		arg_idx;		/* index in argument list */
+    int		i;
+    int		advance = TRUE;
+    buf_T	*old_curbuf;
+
+# ifdef FEAT_AUTOCMD
+    /*
+     * Don't execute Win/Buf Enter/Leave autocommands here
+     */
+    ++autocmd_no_enter;
+    ++autocmd_no_leave;
+# endif
+
+    /* When w_arg_idx is -1 remove the window (see create_windows()). */
+    if (curwin->w_arg_idx == -1)
+    {
+	win_close(curwin, TRUE);
+	advance = FALSE;
+    }
+
+    arg_idx = 1;
+    for (i = 1; i < parmp->window_count; ++i)
+    {
+	/* When w_arg_idx is -1 remove the window (see create_windows()). */
+	if (curwin->w_arg_idx == -1)
+	{
+	    ++arg_idx;
+	    win_close(curwin, TRUE);
+	    advance = FALSE;
+	    continue;
+	}
+
+	if (advance)
+	{
+	    if (parmp->window_layout == WIN_TABS)
+	    {
+		if (curtab->tp_next == NULL)	/* just checking */
+		    break;
+		goto_tabpage(0);
+	    }
+	    else
+	    {
+		if (curwin->w_next == NULL)	/* just checking */
+		    break;
+		win_enter(curwin->w_next, FALSE);
+	    }
+	}
+	advance = TRUE;
+
+	/* Only open the file if there is no file in this window yet (that can
+	 * happen when .vimrc contains ":sall"). */
+	if (curbuf == firstwin->w_buffer || curbuf->b_ffname == NULL)
+	{
+	    curwin->w_arg_idx = arg_idx;
+	    /* Edit file from arg list, if there is one.  When "Quit" selected
+	     * at the ATTENTION prompt close the window. */
+	    old_curbuf = curbuf;
+	    (void)do_ecmd(0, arg_idx < GARGCOUNT
+			  ? alist_name(&GARGLIST[arg_idx]) : NULL,
+			  NULL, NULL, ECMD_LASTL, ECMD_HIDE);
+	    if (curbuf == old_curbuf)
+	    {
+		if (got_int || only_one_window())
+		{
+		    /* abort selected or quit and only one window */
+		    did_emsg = FALSE;   /* avoid hit-enter prompt */
+		    getout(1);
+		}
+		win_close(curwin, TRUE);
+		advance = FALSE;
+	    }
+	    if (arg_idx == GARGCOUNT - 1)
+		arg_had_last = TRUE;
+	    ++arg_idx;
+	}
+	ui_breakcheck();
+	if (got_int)
+	{
+	    (void)vgetc();	/* only break the file loading, not the rest */
+	    break;
+	}
+    }
+
+    if (parmp->window_layout == WIN_TABS)
+	goto_tabpage(1);
+# ifdef FEAT_AUTOCMD
+    --autocmd_no_enter;
+# endif
+    win_enter(firstwin, FALSE);		/* back to first window */
+# ifdef FEAT_AUTOCMD
+    --autocmd_no_leave;
+# endif
+    TIME_MSG("editing files in windows");
+    if (parmp->window_count > 1 && parmp->window_layout != WIN_TABS)
+	win_equal(curwin, FALSE, 'b');	/* adjust heights */
+}
+#endif /* FEAT_WINDOWS */
+
+/*
+ * Execute the commands from --cmd arguments "cmds[cnt]".
+ */
+    static void
+exe_pre_commands(parmp)
+    mparm_T	*parmp;
+{
+    char_u	**cmds = parmp->pre_commands;
+    int		cnt = parmp->n_pre_commands;
+    int		i;
+
+    if (cnt > 0)
+    {
+	curwin->w_cursor.lnum = 0; /* just in case.. */
+	sourcing_name = (char_u *)_("pre-vimrc command line");
+# ifdef FEAT_EVAL
+	current_SID = SID_CMDARG;
+# endif
+	for (i = 0; i < cnt; ++i)
+	    do_cmdline_cmd(cmds[i]);
+	sourcing_name = NULL;
+# ifdef FEAT_EVAL
+	current_SID = 0;
+# endif
+	TIME_MSG("--cmd commands");
+    }
+}
+
+/*
+ * Execute "+", "-c" and "-S" arguments.
+ */
+    static void
+exe_commands(parmp)
+    mparm_T	*parmp;
+{
+    int		i;
+
+    /*
+     * We start commands on line 0, make "vim +/pat file" match a
+     * pattern on line 1.  But don't move the cursor when an autocommand
+     * with g`" was used.
+     */
+    msg_scroll = TRUE;
+    if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
+	curwin->w_cursor.lnum = 0;
+    sourcing_name = (char_u *)"command line";
+#ifdef FEAT_EVAL
+    current_SID = SID_CARG;
+#endif
+    for (i = 0; i < parmp->n_commands; ++i)
+    {
+	do_cmdline_cmd(parmp->commands[i]);
+	if (parmp->cmds_tofree[i])
+	    vim_free(parmp->commands[i]);
+    }
+    sourcing_name = NULL;
+#ifdef FEAT_EVAL
+    current_SID = 0;
+#endif
+    if (curwin->w_cursor.lnum == 0)
+	curwin->w_cursor.lnum = 1;
+
+    if (!exmode_active)
+	msg_scroll = FALSE;
+
+#ifdef FEAT_QUICKFIX
+    /* When started with "-q errorfile" jump to first error again. */
+    if (parmp->edit_type == EDIT_QF)
+	qf_jump(NULL, 0, 0, FALSE);
+#endif
+    TIME_MSG("executing command arguments");
+}
+
+/*
+ * Source startup scripts.
+ */
+    static void
+source_startup_scripts(parmp)
+    mparm_T	*parmp;
+{
+    int		i;
+
+    /*
+     * For "evim" source evim.vim first of all, so that the user can overrule
+     * any things he doesn't like.
+     */
+    if (parmp->evim_mode)
+    {
+	(void)do_source((char_u *)EVIM_FILE, FALSE, DOSO_NONE);
+	TIME_MSG("source evim file");
+    }
+
+    /*
+     * If -u argument given, use only the initializations from that file and
+     * nothing else.
+     */
+    if (parmp->use_vimrc != NULL)
+    {
+	if (STRCMP(parmp->use_vimrc, "NONE") == 0
+				     || STRCMP(parmp->use_vimrc, "NORC") == 0)
+	{
+#ifdef FEAT_GUI
+	    if (use_gvimrc == NULL)	    /* don't load gvimrc either */
+		use_gvimrc = parmp->use_vimrc;
+#endif
+	    if (parmp->use_vimrc[2] == 'N')
+		p_lpl = FALSE;		    /* don't load plugins either */
+	}
+	else
+	{
+	    if (do_source(parmp->use_vimrc, FALSE, DOSO_NONE) != OK)
+		EMSG2(_("E282: Cannot read from \"%s\""), parmp->use_vimrc);
+	}
+    }
+    else if (!silent_mode)
+    {
+#ifdef AMIGA
+	struct Process	*proc = (struct Process *)FindTask(0L);
+	APTR		save_winptr = proc->pr_WindowPtr;
+
+	/* Avoid a requester here for a volume that doesn't exist. */
+	proc->pr_WindowPtr = (APTR)-1L;
+#endif
+
+	/*
+	 * Get system wide defaults, if the file name is defined.
+	 */
+#ifdef SYS_VIMRC_FILE
+	(void)do_source((char_u *)SYS_VIMRC_FILE, FALSE, DOSO_NONE);
+#endif
+#ifdef MACOS_X
+	(void)do_source((char_u *)"$VIMRUNTIME/macmap.vim", FALSE, DOSO_NONE);
+#endif
+
+	/*
+	 * Try to read initialization commands from the following places:
+	 * - environment variable VIMINIT
+	 * - user vimrc file (s:.vimrc for Amiga, ~/.vimrc otherwise)
+	 * - second user vimrc file ($VIM/.vimrc for Dos)
+	 * - environment variable EXINIT
+	 * - user exrc file (s:.exrc for Amiga, ~/.exrc otherwise)
+	 * - second user exrc file ($VIM/.exrc for Dos)
+	 * The first that exists is used, the rest is ignored.
+	 */
+	if (process_env((char_u *)"VIMINIT", TRUE) != OK)
+	{
+	    if (do_source((char_u *)USR_VIMRC_FILE, TRUE, DOSO_VIMRC) == FAIL
+#ifdef USR_VIMRC_FILE2
+		&& do_source((char_u *)USR_VIMRC_FILE2, TRUE,
+							   DOSO_VIMRC) == FAIL
+#endif
+#ifdef USR_VIMRC_FILE3
+		&& do_source((char_u *)USR_VIMRC_FILE3, TRUE,
+							   DOSO_VIMRC) == FAIL
+#endif
+		&& process_env((char_u *)"EXINIT", FALSE) == FAIL
+		&& do_source((char_u *)USR_EXRC_FILE, FALSE, DOSO_NONE) == FAIL)
+	    {
+#ifdef USR_EXRC_FILE2
+		(void)do_source((char_u *)USR_EXRC_FILE2, FALSE, DOSO_NONE);
+#endif
+	    }
+	}
+
+	/*
+	 * Read initialization commands from ".vimrc" or ".exrc" in current
+	 * directory.  This is only done if the 'exrc' option is set.
+	 * Because of security reasons we disallow shell and write commands
+	 * now, except for unix if the file is owned by the user or 'secure'
+	 * option has been reset in environment of global ".exrc" or ".vimrc".
+	 * Only do this if VIMRC_FILE is not the same as USR_VIMRC_FILE or
+	 * SYS_VIMRC_FILE.
+	 */
+	if (p_exrc)
+	{
+#if defined(UNIX) || defined(VMS)
+	    /* If ".vimrc" file is not owned by user, set 'secure' mode. */
+	    if (!file_owned(VIMRC_FILE))
+#endif
+		secure = p_secure;
+
+	    i = FAIL;
+	    if (fullpathcmp((char_u *)USR_VIMRC_FILE,
+				      (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+#ifdef USR_VIMRC_FILE2
+		    && fullpathcmp((char_u *)USR_VIMRC_FILE2,
+				      (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+#endif
+#ifdef USR_VIMRC_FILE3
+		    && fullpathcmp((char_u *)USR_VIMRC_FILE3,
+				      (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+#endif
+#ifdef SYS_VIMRC_FILE
+		    && fullpathcmp((char_u *)SYS_VIMRC_FILE,
+				      (char_u *)VIMRC_FILE, FALSE) != FPC_SAME
+#endif
+				)
+		i = do_source((char_u *)VIMRC_FILE, TRUE, DOSO_VIMRC);
+
+	    if (i == FAIL)
+	    {
+#if defined(UNIX) || defined(VMS)
+		/* if ".exrc" is not owned by user set 'secure' mode */
+		if (!file_owned(EXRC_FILE))
+		    secure = p_secure;
+		else
+		    secure = 0;
+#endif
+		if (	   fullpathcmp((char_u *)USR_EXRC_FILE,
+				      (char_u *)EXRC_FILE, FALSE) != FPC_SAME
+#ifdef USR_EXRC_FILE2
+			&& fullpathcmp((char_u *)USR_EXRC_FILE2,
+				      (char_u *)EXRC_FILE, FALSE) != FPC_SAME
+#endif
+				)
+		    (void)do_source((char_u *)EXRC_FILE, FALSE, DOSO_NONE);
+	    }
+	}
+	if (secure == 2)
+	    need_wait_return = TRUE;
+	secure = 0;
+#ifdef AMIGA
+	proc->pr_WindowPtr = save_winptr;
+#endif
+    }
+    TIME_MSG("sourcing vimrc file(s)");
+}
+
+/*
+ * Setup to start using the GUI.  Exit with an error when not available.
+ */
+    static void
+main_start_gui()
+{
+#ifdef FEAT_GUI
+    gui.starting = TRUE;	/* start GUI a bit later */
+#else
+    mch_errmsg(_(e_nogvim));
+    mch_errmsg("\n");
+    mch_exit(2);
+#endif
+}
+
+/*
+ * Get an environment variable, and execute it as Ex commands.
+ * Returns FAIL if the environment variable was not executed, OK otherwise.
+ */
+    int
+process_env(env, is_viminit)
+    char_u	*env;
+    int		is_viminit; /* when TRUE, called for VIMINIT */
+{
+    char_u	*initstr;
+    char_u	*save_sourcing_name;
+    linenr_T	save_sourcing_lnum;
+#ifdef FEAT_EVAL
+    scid_T	save_sid;
+#endif
+
+    if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL)
+    {
+	if (is_viminit)
+	    vimrc_found(NULL, NULL);
+	save_sourcing_name = sourcing_name;
+	save_sourcing_lnum = sourcing_lnum;
+	sourcing_name = env;
+	sourcing_lnum = 0;
+#ifdef FEAT_EVAL
+	save_sid = current_SID;
+	current_SID = SID_ENV;
+#endif
+	do_cmdline_cmd(initstr);
+	sourcing_name = save_sourcing_name;
+	sourcing_lnum = save_sourcing_lnum;
+#ifdef FEAT_EVAL
+	current_SID = save_sid;;
+#endif
+	return OK;
+    }
+    return FAIL;
+}
+
+#if defined(UNIX) || defined(VMS)
+/*
+ * Return TRUE if we are certain the user owns the file "fname".
+ * Used for ".vimrc" and ".exrc".
+ * Use both stat() and lstat() for extra security.
+ */
+    static int
+file_owned(fname)
+    char	*fname;
+{
+    struct stat s;
+# ifdef UNIX
+    uid_t	uid = getuid();
+# else	 /* VMS */
+    uid_t	uid = ((getgid() << 16) | getuid());
+# endif
+
+    return !(mch_stat(fname, &s) != 0 || s.st_uid != uid
+# ifdef HAVE_LSTAT
+	    || mch_lstat(fname, &s) != 0 || s.st_uid != uid
+# endif
+	    );
+}
+#endif
+
+/*
+ * Give an error message main_errors["n"] and exit.
+ */
+    static void
+mainerr(n, str)
+    int		n;	/* one of the ME_ defines */
+    char_u	*str;	/* extra argument or NULL */
+{
+#if defined(UNIX) || defined(__EMX__) || defined(VMS)
+    reset_signals();		/* kill us with CTRL-C here, if you like */
+#endif
+
+    mch_errmsg(longVersion);
+    mch_errmsg("\n");
+    mch_errmsg(_(main_errors[n]));
+    if (str != NULL)
+    {
+	mch_errmsg(": \"");
+	mch_errmsg((char *)str);
+	mch_errmsg("\"");
+    }
+    mch_errmsg(_("\nMore info with: \"vim -h\"\n"));
+
+    mch_exit(1);
+}
+
+    void
+mainerr_arg_missing(str)
+    char_u	*str;
+{
+    mainerr(ME_ARG_MISSING, str);
+}
+
+/*
+ * print a message with three spaces prepended and '\n' appended.
+ */
+    static void
+main_msg(s)
+    char *s;
+{
+    mch_msg("   ");
+    mch_msg(s);
+    mch_msg("\n");
+}
+
+/*
+ * Print messages for "vim -h" or "vim --help" and exit.
+ */
+    static void
+usage()
+{
+    int		i;
+    static char	*(use[]) =
+    {
+	N_("[file ..]       edit specified file(s)"),
+	N_("-               read text from stdin"),
+	N_("-t tag          edit file where tag is defined"),
+#ifdef FEAT_QUICKFIX
+	N_("-q [errorfile]  edit file with first error")
+#endif
+    };
+
+#if defined(UNIX) || defined(__EMX__) || defined(VMS)
+    reset_signals();		/* kill us with CTRL-C here, if you like */
+#endif
+
+    mch_msg(longVersion);
+    mch_msg(_("\n\nusage:"));
+    for (i = 0; ; ++i)
+    {
+	mch_msg(_(" vim [arguments] "));
+	mch_msg(_(use[i]));
+	if (i == (sizeof(use) / sizeof(char_u *)) - 1)
+	    break;
+	mch_msg(_("\n   or:"));
+    }
+#ifdef VMS
+    mch_msg(_("\nWhere case is ignored prepend / to make flag upper case"));
+#endif
+
+    mch_msg(_("\n\nArguments:\n"));
+    main_msg(_("--\t\t\tOnly file names after this"));
+#if (!defined(UNIX) && !defined(__EMX__)) || defined(ARCHIE)
+    main_msg(_("--literal\t\tDon't expand wildcards"));
+#endif
+#ifdef FEAT_OLE
+    main_msg(_("-register\t\tRegister this gvim for OLE"));
+    main_msg(_("-unregister\t\tUnregister gvim for OLE"));
+#endif
+#ifdef FEAT_GUI
+    main_msg(_("-g\t\t\tRun using GUI (like \"gvim\")"));
+    main_msg(_("-f  or  --nofork\tForeground: Don't fork when starting GUI"));
+#endif
+    main_msg(_("-v\t\t\tVi mode (like \"vi\")"));
+    main_msg(_("-e\t\t\tEx mode (like \"ex\")"));
+    main_msg(_("-s\t\t\tSilent (batch) mode (only for \"ex\")"));
+#ifdef FEAT_DIFF
+    main_msg(_("-d\t\t\tDiff mode (like \"vimdiff\")"));
+#endif
+    main_msg(_("-y\t\t\tEasy mode (like \"evim\", modeless)"));
+    main_msg(_("-R\t\t\tReadonly mode (like \"view\")"));
+    main_msg(_("-Z\t\t\tRestricted mode (like \"rvim\")"));
+    main_msg(_("-m\t\t\tModifications (writing files) not allowed"));
+    main_msg(_("-M\t\t\tModifications in text not allowed"));
+    main_msg(_("-b\t\t\tBinary mode"));
+#ifdef FEAT_LISP
+    main_msg(_("-l\t\t\tLisp mode"));
+#endif
+    main_msg(_("-C\t\t\tCompatible with Vi: 'compatible'"));
+    main_msg(_("-N\t\t\tNot fully Vi compatible: 'nocompatible'"));
+    main_msg(_("-V[N][fname]\t\tBe verbose [level N] [log messages to fname]"));
+#ifdef FEAT_EVAL
+    main_msg(_("-D\t\t\tDebugging mode"));
+#endif
+    main_msg(_("-n\t\t\tNo swap file, use memory only"));
+    main_msg(_("-r\t\t\tList swap files and exit"));
+    main_msg(_("-r (with file name)\tRecover crashed session"));
+    main_msg(_("-L\t\t\tSame as -r"));
+#ifdef AMIGA
+    main_msg(_("-f\t\t\tDon't use newcli to open window"));
+    main_msg(_("-dev <device>\t\tUse <device> for I/O"));
+#endif
+#ifdef FEAT_ARABIC
+    main_msg(_("-A\t\t\tstart in Arabic mode"));
+#endif
+#ifdef FEAT_RIGHTLEFT
+    main_msg(_("-H\t\t\tStart in Hebrew mode"));
+#endif
+#ifdef FEAT_FKMAP
+    main_msg(_("-F\t\t\tStart in Farsi mode"));
+#endif
+    main_msg(_("-T <terminal>\tSet terminal type to <terminal>"));
+    main_msg(_("-u <vimrc>\t\tUse <vimrc> instead of any .vimrc"));
+#ifdef FEAT_GUI
+    main_msg(_("-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc"));
+#endif
+    main_msg(_("--noplugin\t\tDon't load plugin scripts"));
+#ifdef FEAT_WINDOWS
+    main_msg(_("-p[N]\t\tOpen N tab pages (default: one for each file)"));
+    main_msg(_("-o[N]\t\tOpen N windows (default: one for each file)"));
+    main_msg(_("-O[N]\t\tLike -o but split vertically"));
+#endif
+    main_msg(_("+\t\t\tStart at end of file"));
+    main_msg(_("+<lnum>\t\tStart at line <lnum>"));
+    main_msg(_("--cmd <command>\tExecute <command> before loading any vimrc file"));
+    main_msg(_("-c <command>\t\tExecute <command> after loading the first file"));
+    main_msg(_("-S <session>\t\tSource file <session> after loading the first file"));
+    main_msg(_("-s <scriptin>\tRead Normal mode commands from file <scriptin>"));
+    main_msg(_("-w <scriptout>\tAppend all typed commands to file <scriptout>"));
+    main_msg(_("-W <scriptout>\tWrite all typed commands to file <scriptout>"));
+#ifdef FEAT_CRYPT
+    main_msg(_("-x\t\t\tEdit encrypted files"));
+#endif
+#if (defined(UNIX) || defined(VMS)) && defined(FEAT_X11)
+# if defined(FEAT_GUI_X11) && !defined(FEAT_GUI_GTK)
+    main_msg(_("-display <display>\tConnect vim to this particular X-server"));
+# endif
+    main_msg(_("-X\t\t\tDo not connect to X server"));
+#endif
+#ifdef FEAT_CLIENTSERVER
+    main_msg(_("--remote <files>\tEdit <files> in a Vim server if possible"));
+    main_msg(_("--remote-silent <files>  Same, don't complain if there is no server"));
+    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"));
+# 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"));
+    main_msg(_("--serverlist\t\tList available Vim server names and exit"));
+    main_msg(_("--servername <name>\tSend to/become the Vim server <name>"));
+#endif
+#ifdef FEAT_VIMINFO
+    main_msg(_("-i <viminfo>\t\tUse <viminfo> instead of .viminfo"));
+#endif
+    main_msg(_("-h  or  --help\tPrint Help (this message) and exit"));
+    main_msg(_("--version\t\tPrint version information and exit"));
+
+#ifdef FEAT_GUI_X11
+# ifdef FEAT_GUI_MOTIF
+    mch_msg(_("\nArguments recognised by gvim (Motif version):\n"));
+# else
+#  ifdef FEAT_GUI_ATHENA
+#   ifdef FEAT_GUI_NEXTAW
+    mch_msg(_("\nArguments recognised by gvim (neXtaw version):\n"));
+#   else
+    mch_msg(_("\nArguments recognised by gvim (Athena version):\n"));
+#   endif
+#  endif
+# endif
+    main_msg(_("-display <display>\tRun vim on <display>"));
+    main_msg(_("-iconic\t\tStart vim iconified"));
+# if 0
+    main_msg(_("-name <name>\t\tUse resource as if vim was <name>"));
+    mch_msg(_("\t\t\t  (Unimplemented)\n"));
+# endif
+    main_msg(_("-background <color>\tUse <color> for the background (also: -bg)"));
+    main_msg(_("-foreground <color>\tUse <color> for normal text (also: -fg)"));
+    main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
+    main_msg(_("-boldfont <font>\tUse <font> for bold text"));
+    main_msg(_("-italicfont <font>\tUse <font> for italic text"));
+    main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
+    main_msg(_("-borderwidth <width>\tUse a border width of <width> (also: -bw)"));
+    main_msg(_("-scrollbarwidth <width>  Use a scrollbar width of <width> (also: -sw)"));
+# ifdef FEAT_GUI_ATHENA
+    main_msg(_("-menuheight <height>\tUse a menu bar height of <height> (also: -mh)"));
+# endif
+    main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
+    main_msg(_("+reverse\t\tDon't use reverse video (also: +rv)"));
+    main_msg(_("-xrm <resource>\tSet the specified resource"));
+#endif /* FEAT_GUI_X11 */
+#if defined(FEAT_GUI) && defined(RISCOS)
+    mch_msg(_("\nArguments recognised by gvim (RISC OS version):\n"));
+    main_msg(_("--columns <number>\tInitial width of window in columns"));
+    main_msg(_("--rows <number>\tInitial height of window in rows"));
+#endif
+#ifdef FEAT_GUI_GTK
+    mch_msg(_("\nArguments recognised by gvim (GTK+ version):\n"));
+    main_msg(_("-font <font>\t\tUse <font> for normal text (also: -fn)"));
+    main_msg(_("-geometry <geom>\tUse <geom> for initial geometry (also: -geom)"));
+    main_msg(_("-reverse\t\tUse reverse video (also: -rv)"));
+    main_msg(_("-display <display>\tRun vim on <display> (also: --display)"));
+# ifdef HAVE_GTK2
+    main_msg(_("--role <role>\tSet a unique role to identify the main window"));
+# endif
+    main_msg(_("--socketid <xid>\tOpen Vim inside another GTK widget"));
+#endif
+#ifdef FEAT_GUI_W32
+    main_msg(_("-P <parent title>\tOpen Vim inside parent application"));
+#endif
+
+#ifdef FEAT_GUI_GNOME
+    /* Gnome gives extra messages for --help if we continue, but not for -h. */
+    if (gui.starting)
+	mch_msg("\n");
+    else
+#endif
+	mch_exit(0);
+}
+
+#if defined(HAS_SWAP_EXISTS_ACTION)
+/*
+ * Check the result of the ATTENTION dialog:
+ * When "Quit" selected, exit Vim.
+ * When "Recover" selected, recover the file.
+ */
+    static void
+check_swap_exists_action()
+{
+    if (swap_exists_action == SEA_QUIT)
+	getout(1);
+    handle_swap_exists(NULL);
+}
+#endif
+
+#if defined(STARTUPTIME) || defined(PROTO)
+static void time_diff __ARGS((struct timeval *then, struct timeval *now));
+
+static struct timeval	prev_timeval;
+
+/*
+ * Save the previous time before doing something that could nest.
+ * set "*tv_rel" to the time elapsed so far.
+ */
+    void
+time_push(tv_rel, tv_start)
+    void	*tv_rel, *tv_start;
+{
+    *((struct timeval *)tv_rel) = prev_timeval;
+    gettimeofday(&prev_timeval, NULL);
+    ((struct timeval *)tv_rel)->tv_usec = prev_timeval.tv_usec
+					- ((struct timeval *)tv_rel)->tv_usec;
+    ((struct timeval *)tv_rel)->tv_sec = prev_timeval.tv_sec
+					 - ((struct timeval *)tv_rel)->tv_sec;
+    if (((struct timeval *)tv_rel)->tv_usec < 0)
+    {
+	((struct timeval *)tv_rel)->tv_usec += 1000000;
+	--((struct timeval *)tv_rel)->tv_sec;
+    }
+    *(struct timeval *)tv_start = prev_timeval;
+}
+
+/*
+ * Compute the previous time after doing something that could nest.
+ * Subtract "*tp" from prev_timeval;
+ * Note: The arguments are (void *) to avoid trouble with systems that don't
+ * have struct timeval.
+ */
+    void
+time_pop(tp)
+    void	*tp;	/* actually (struct timeval *) */
+{
+    prev_timeval.tv_usec -= ((struct timeval *)tp)->tv_usec;
+    prev_timeval.tv_sec -= ((struct timeval *)tp)->tv_sec;
+    if (prev_timeval.tv_usec < 0)
+    {
+	prev_timeval.tv_usec += 1000000;
+	--prev_timeval.tv_sec;
+    }
+}
+
+    static void
+time_diff(then, now)
+    struct timeval	*then;
+    struct timeval	*now;
+{
+    long	usec;
+    long	msec;
+
+    usec = now->tv_usec - then->tv_usec;
+    msec = (now->tv_sec - then->tv_sec) * 1000L + usec / 1000L,
+    usec = usec % 1000L;
+    fprintf(time_fd, "%03ld.%03ld", msec, usec >= 0 ? usec : usec + 1000L);
+}
+
+    void
+time_msg(msg, tv_start)
+    char	*msg;
+    void	*tv_start;  /* only for do_source: start time; actually
+			       (struct timeval *) */
+{
+    static struct timeval	start;
+    struct timeval		now;
+
+    if (time_fd != NULL)
+    {
+	if (strstr(msg, "STARTING") != NULL)
+	{
+	    gettimeofday(&start, NULL);
+	    prev_timeval = start;
+	    fprintf(time_fd, "\n\ntimes in msec\n");
+	    fprintf(time_fd, " clock   self+sourced   self:  sourced script\n");
+	    fprintf(time_fd, " clock   elapsed:              other lines\n\n");
+	}
+	gettimeofday(&now, NULL);
+	time_diff(&start, &now);
+	if (((struct timeval *)tv_start) != NULL)
+	{
+	    fprintf(time_fd, "  ");
+	    time_diff(((struct timeval *)tv_start), &now);
+	}
+	fprintf(time_fd, "  ");
+	time_diff(&prev_timeval, &now);
+	prev_timeval = now;
+	fprintf(time_fd, ": %s\n", msg);
+    }
+}
+
+# ifdef WIN3264
+/*
+ * Windows doesn't have gettimeofday(), although it does have struct timeval.
+ */
+    int
+gettimeofday(struct timeval *tv, char *dummy)
+{
+    long t = clock();
+    tv->tv_sec = t / CLOCKS_PER_SEC;
+    tv->tv_usec = (t - tv->tv_sec * CLOCKS_PER_SEC) * 1000000 / CLOCKS_PER_SEC;
+    return 0;
+}
+# endif
+
+#endif
+
+#if defined(FEAT_CLIENTSERVER) || defined(PROTO)
+
+/*
+ * Common code for the X command server and the Win32 command server.
+ */
+
+static char_u *build_drop_cmd __ARGS((int filec, char **filev, int tabs, int sendReply));
+
+/*
+ * Do the client-server stuff, unless "--servername ''" was used.
+ */
+    static void
+exec_on_server(parmp)
+    mparm_T	*parmp;
+{
+    if (parmp->serverName_arg == NULL || *parmp->serverName_arg != NUL)
+    {
+# ifdef WIN32
+	/* Initialise the client/server messaging infrastructure. */
+	serverInitMessaging();
+# endif
+
+	/*
+	 * When a command server argument was found, execute it.  This may
+	 * exit Vim when it was successful.  Otherwise it's executed further
+	 * on.  Remember the encoding used here in "serverStrEnc".
+	 */
+	if (parmp->serverArg)
+	{
+	    cmdsrv_main(&parmp->argc, parmp->argv,
+				    parmp->serverName_arg, &parmp->serverStr);
+# ifdef FEAT_MBYTE
+	    parmp->serverStrEnc = vim_strsave(p_enc);
+# endif
+	}
+
+	/* If we're still running, get the name to register ourselves.
+	 * On Win32 can register right now, for X11 need to setup the
+	 * clipboard first, it's further down. */
+	parmp->servername = serverMakeName(parmp->serverName_arg,
+							      parmp->argv[0]);
+# ifdef WIN32
+	if (parmp->servername != NULL)
+	{
+	    serverSetName(parmp->servername);
+	    vim_free(parmp->servername);
+	}
+# endif
+    }
+}
+
+/*
+ * Prepare for running as a Vim server.
+ */
+    static void
+prepare_server(parmp)
+    mparm_T	*parmp;
+{
+# if defined(FEAT_X11)
+    /*
+     * Register for remote command execution with :serversend and --remote
+     * unless there was a -X or a --servername '' on the command line.
+     * Only register nongui-vim's with an explicit --servername argument.
+     * When running as root --servername is also required.
+     */
+    if (X_DISPLAY != NULL && parmp->servername != NULL && (
+#  ifdef FEAT_GUI
+		(gui.in_use
+#   ifdef UNIX
+		 && getuid() != ROOT_UID
+#   endif
+		) ||
+#  endif
+		parmp->serverName_arg != NULL))
+    {
+	(void)serverRegisterName(X_DISPLAY, parmp->servername);
+	vim_free(parmp->servername);
+	TIME_MSG("register server name");
+    }
+    else
+	serverDelayedStartName = parmp->servername;
+# endif
+
+    /*
+     * Execute command ourselves if we're here because the send failed (or
+     * else we would have exited above).
+     */
+    if (parmp->serverStr != NULL)
+    {
+	char_u *p;
+
+	server_to_input_buf(serverConvert(parmp->serverStrEnc,
+						       parmp->serverStr, &p));
+	vim_free(p);
+    }
+}
+
+    static void
+cmdsrv_main(argc, argv, serverName_arg, serverStr)
+    int		*argc;
+    char	**argv;
+    char_u	*serverName_arg;
+    char_u	**serverStr;
+{
+    char_u	*res;
+    int		i;
+    char_u	*sname;
+    int		ret;
+    int		didone = FALSE;
+    int		exiterr = 0;
+    char	**newArgV = argv + 1;
+    int		newArgC = 1,
+		Argc = *argc;
+    int		argtype;
+#define ARGTYPE_OTHER		0
+#define ARGTYPE_EDIT		1
+#define ARGTYPE_EDIT_WAIT	2
+#define ARGTYPE_SEND		3
+    int		silent = FALSE;
+    int		tabs = FALSE;
+# ifndef FEAT_X11
+    HWND	srv;
+# else
+    Window	srv;
+
+    setup_term_clip();
+# endif
+
+    sname = serverMakeName(serverName_arg, argv[0]);
+    if (sname == NULL)
+	return;
+
+    /*
+     * Execute the command server related arguments and remove them
+     * from the argc/argv array; We may have to return into main()
+     */
+    for (i = 1; i < Argc; i++)
+    {
+	res = NULL;
+	if (STRCMP(argv[i], "--") == 0)	/* end of option arguments */
+	{
+	    for (; i < *argc; i++)
+	    {
+		*newArgV++ = argv[i];
+		newArgC++;
+	    }
+	    break;
+	}
+
+	if (STRICMP(argv[i], "--remote-send") == 0)
+	    argtype = ARGTYPE_SEND;
+	else if (STRNICMP(argv[i], "--remote", 8) == 0)
+	{
+	    char	*p = argv[i] + 8;
+
+	    argtype = ARGTYPE_EDIT;
+	    while (*p != NUL)
+	    {
+		if (STRNICMP(p, "-wait", 5) == 0)
+		{
+		    argtype = ARGTYPE_EDIT_WAIT;
+		    p += 5;
+		}
+		else if (STRNICMP(p, "-silent", 7) == 0)
+		{
+		    silent = TRUE;
+		    p += 7;
+		}
+		else if (STRNICMP(p, "-tab", 4) == 0)
+		{
+		    tabs = TRUE;
+		    p += 4;
+		}
+		else
+		{
+		    argtype = ARGTYPE_OTHER;
+		    break;
+		}
+	    }
+	}
+	else
+	    argtype = ARGTYPE_OTHER;
+
+	if (argtype != ARGTYPE_OTHER)
+	{
+	    if (i == *argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+	    if (argtype == ARGTYPE_SEND)
+	    {
+		*serverStr = (char_u *)argv[i + 1];
+		i++;
+	    }
+	    else
+	    {
+		*serverStr = build_drop_cmd(*argc - i - 1, argv + i + 1,
+					  tabs, argtype == ARGTYPE_EDIT_WAIT);
+		if (*serverStr == NULL)
+		{
+		    /* Probably out of memory, exit. */
+		    didone = TRUE;
+		    exiterr = 1;
+		    break;
+		}
+		Argc = i;
+	    }
+# ifdef FEAT_X11
+	    if (xterm_dpy == NULL)
+	    {
+		mch_errmsg(_("No display"));
+		ret = -1;
+	    }
+	    else
+		ret = serverSendToVim(xterm_dpy, sname, *serverStr,
+						    NULL, &srv, 0, 0, silent);
+# else
+	    /* Win32 always works? */
+	    ret = serverSendToVim(sname, *serverStr, NULL, &srv, 0, silent);
+# endif
+	    if (ret < 0)
+	    {
+		if (argtype == ARGTYPE_SEND)
+		{
+		    /* Failed to send, abort. */
+		    mch_errmsg(_(": Send failed.\n"));
+		    didone = TRUE;
+		    exiterr = 1;
+		}
+		else if (!silent)
+		    /* Let vim start normally.  */
+		    mch_errmsg(_(": Send failed. Trying to execute locally\n"));
+		break;
+	    }
+
+# ifdef FEAT_GUI_W32
+	    /* Guess that when the server name starts with "g" it's a GUI
+	     * server, which we can bring to the foreground here.
+	     * Foreground() in the server doesn't work very well. */
+	    if (argtype != ARGTYPE_SEND && TOUPPER_ASC(*sname) == 'G')
+		SetForegroundWindow(srv);
+# endif
+
+	    /*
+	     * For --remote-wait: Wait until the server did edit each
+	     * file.  Also detect that the server no longer runs.
+	     */
+	    if (ret >= 0 && argtype == ARGTYPE_EDIT_WAIT)
+	    {
+		int	numFiles = *argc - i - 1;
+		int	j;
+		char_u  *done = alloc(numFiles);
+		char_u  *p;
+# ifdef FEAT_GUI_W32
+		NOTIFYICONDATA ni;
+		int	count = 0;
+		extern HWND message_window;
+# endif
+
+		if (numFiles > 0 && argv[i + 1][0] == '+')
+		    /* Skip "+cmd" argument, don't wait for it to be edited. */
+		    --numFiles;
+
+# ifdef FEAT_GUI_W32
+		ni.cbSize = sizeof(ni);
+		ni.hWnd = message_window;
+		ni.uID = 0;
+		ni.uFlags = NIF_ICON|NIF_TIP;
+		ni.hIcon = LoadIcon((HINSTANCE)GetModuleHandle(0), "IDR_VIM");
+		sprintf(ni.szTip, _("%d of %d edited"), count, numFiles);
+		Shell_NotifyIcon(NIM_ADD, &ni);
+# endif
+
+		/* Wait for all files to unload in remote */
+		memset(done, 0, numFiles);
+		while (memchr(done, 0, numFiles) != NULL)
+		{
+# ifdef WIN32
+		    p = serverGetReply(srv, NULL, TRUE, TRUE);
+		    if (p == NULL)
+			break;
+# else
+		    if (serverReadReply(xterm_dpy, srv, &p, TRUE) < 0)
+			break;
+# endif
+		    j = atoi((char *)p);
+		    if (j >= 0 && j < numFiles)
+		    {
+# ifdef FEAT_GUI_W32
+			++count;
+			sprintf(ni.szTip, _("%d of %d edited"),
+							     count, numFiles);
+			Shell_NotifyIcon(NIM_MODIFY, &ni);
+# endif
+			done[j] = 1;
+		    }
+		}
+# ifdef FEAT_GUI_W32
+		Shell_NotifyIcon(NIM_DELETE, &ni);
+# endif
+	    }
+	}
+	else if (STRICMP(argv[i], "--remote-expr") == 0)
+	{
+	    if (i == *argc - 1)
+		mainerr_arg_missing((char_u *)argv[i]);
+# ifdef WIN32
+	    /* Win32 always works? */
+	    if (serverSendToVim(sname, (char_u *)argv[i + 1],
+						    &res, NULL, 1, FALSE) < 0)
+# else
+	    if (xterm_dpy == NULL)
+		mch_errmsg(_("No display: Send expression failed.\n"));
+	    else if (serverSendToVim(xterm_dpy, sname, (char_u *)argv[i + 1],
+						 &res, NULL, 1, 1, FALSE) < 0)
+# endif
+	    {
+		if (res != NULL && *res != NUL)
+		{
+		    /* Output error from remote */
+		    mch_errmsg((char *)res);
+		    vim_free(res);
+		    res = NULL;
+		}
+		mch_errmsg(_(": Send expression failed.\n"));
+	    }
+	}
+	else if (STRICMP(argv[i], "--serverlist") == 0)
+	{
+# ifdef WIN32
+	    /* Win32 always works? */
+	    res = serverGetVimNames();
+# else
+	    if (xterm_dpy != NULL)
+		res = serverGetVimNames(xterm_dpy);
+# endif
+	    if (called_emsg)
+		mch_errmsg("\n");
+	}
+	else if (STRICMP(argv[i], "--servername") == 0)
+	{
+	    /* Alredy processed. Take it out of the command line */
+	    i++;
+	    continue;
+	}
+	else
+	{
+	    *newArgV++ = argv[i];
+	    newArgC++;
+	    continue;
+	}
+	didone = TRUE;
+	if (res != NULL && *res != NUL)
+	{
+	    mch_msg((char *)res);
+	    if (res[STRLEN(res) - 1] != '\n')
+		mch_msg("\n");
+	}
+	vim_free(res);
+    }
+
+    if (didone)
+    {
+	display_errors();	/* display any collected messages */
+	exit(exiterr);	/* Mission accomplished - get out */
+    }
+
+    /* Return back into main() */
+    *argc = newArgC;
+    vim_free(sname);
+}
+
+/*
+ * Build a ":drop" command to send to a Vim server.
+ */
+    static char_u *
+build_drop_cmd(filec, filev, tabs, sendReply)
+    int		filec;
+    char	**filev;
+    int		tabs;		/* Use ":tab drop" instead of ":drop". */
+    int		sendReply;
+{
+    garray_T	ga;
+    int		i;
+    char_u	*inicmd = NULL;
+    char_u	*p;
+    char_u	cwd[MAXPATHL];
+
+    if (filec > 0 && filev[0][0] == '+')
+    {
+	inicmd = (char_u *)filev[0] + 1;
+	filev++;
+	filec--;
+    }
+    /* Check if we have at least one argument. */
+    if (filec <= 0)
+	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)
+	return NULL;
+    ga_init2(&ga, 1, 100);
+    ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd ");
+    ga_concat(&ga, p);
+    vim_free(p);
+
+    /* Call inputsave() so that a prompt for an encryption key works. */
+    ga_concat(&ga, (char_u *)"<CR>:if exists('*inputsave')|call inputsave()|endif|");
+    if (tabs)
+	ga_concat(&ga, (char_u *)"tab ");
+    ga_concat(&ga, (char_u *)"drop");
+    for (i = 0; i < filec; i++)
+    {
+	/* On Unix the shell has already expanded the wildcards, don't want to
+	 * do it again in the Vim server.  On MS-Windows only escape
+	 * non-wildcard characters. */
+	p = vim_strsave_escaped((char_u *)filev[i],
+#ifdef UNIX
+		PATH_ESC_CHARS
+#else
+		(char_u *)" \t%#"
+#endif
+		);
+	if (p == NULL)
+	{
+	    vim_free(ga.ga_data);
+	    return NULL;
+	}
+	ga_concat(&ga, (char_u *)" ");
+	ga_concat(&ga, p);
+	vim_free(p);
+    }
+    /* The :drop commands goes to Insert mode when 'insertmode' is set, use
+     * CTRL-\ CTRL-N again. */
+    ga_concat(&ga, (char_u *)"|if exists('*inputrestore')|call inputrestore()|endif<CR>");
+    ga_concat(&ga, (char_u *)"<C-\\><C-N>:cd -");
+    if (sendReply)
+	ga_concat(&ga, (char_u *)"<CR>:call SetupRemoteReplies()");
+    ga_concat(&ga, (char_u *)"<CR>:");
+    if (inicmd != NULL)
+    {
+	/* Can't use <CR> after "inicmd", because an "startinsert" would cause
+	 * the following commands to be inserted as text.  Use a "|",
+	 * hopefully "inicmd" does allow this... */
+	ga_concat(&ga, inicmd);
+	ga_concat(&ga, (char_u *)"|");
+    }
+    /* Bring the window to the foreground, goto Insert mode when 'im' set and
+     * clear command line. */
+    ga_concat(&ga, (char_u *)"cal foreground()|if &im|star|en|redr|f<CR>");
+    ga_append(&ga, NUL);
+    return ga.ga_data;
+}
+
+/*
+ * Replace termcodes such as <CR> and insert as key presses if there is room.
+ */
+    void
+server_to_input_buf(str)
+    char_u	*str;
+{
+    char_u      *ptr = NULL;
+    char_u      *cpo_save = p_cpo;
+
+    /* Set 'cpoptions' the way we want it.
+     *    B set - backslashes are *not* treated specially
+     *    k set - keycodes are *not* reverse-engineered
+     *    < unset - <Key> sequences *are* interpreted
+     *  The last but one parameter of replace_termcodes() is TRUE so that the
+     *  <lt> sequence is recognised - needed for a real backslash.
+     */
+    p_cpo = (char_u *)"Bk";
+    str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE, FALSE);
+    p_cpo = cpo_save;
+
+    if (*ptr != NUL)	/* trailing CTRL-V results in nothing */
+    {
+	/*
+	 * Add the string to the input stream.
+	 * Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
+	 *
+	 * First clear typed characters from the typeahead buffer, there could
+	 * be half a mapping there.  Then append to the existing string, so
+	 * that multiple commands from a client are concatenated.
+	 */
+	if (typebuf.tb_maplen < typebuf.tb_len)
+	    del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
+	(void)ins_typebuf(str, REMAP_NONE, typebuf.tb_len, TRUE, FALSE);
+
+	/* Let input_available() know we inserted text in the typeahead
+	 * buffer. */
+	typebuf_was_filled = TRUE;
+    }
+    vim_free((char_u *)ptr);
+}
+
+/*
+ * Evaluate an expression that the client sent to a string.
+ * Handles disabling error messages and disables debugging, otherwise Vim
+ * hangs, waiting for "cont" to be typed.
+ */
+    char_u *
+eval_client_expr_to_string(expr)
+    char_u *expr;
+{
+    char_u	*res;
+    int		save_dbl = debug_break_level;
+    int		save_ro = redir_off;
+
+    debug_break_level = -1;
+    redir_off = 0;
+    ++emsg_skip;
+
+    res = eval_to_string(expr, NULL, TRUE);
+
+    debug_break_level = save_dbl;
+    redir_off = save_ro;
+    --emsg_skip;
+
+    /* A client can tell us to redraw, but not to display the cursor, so do
+     * that here. */
+    setcursor();
+    out_flush();
+#ifdef FEAT_GUI
+    if (gui.in_use)
+	gui_update_cursor(FALSE, FALSE);
+#endif
+
+    return res;
+}
+
+/*
+ * If conversion is needed, convert "data" from "client_enc" to 'encoding' and
+ * return an allocated string.  Otherwise return "data".
+ * "*tofree" is set to the result when it needs to be freed later.
+ */
+/*ARGSUSED*/
+    char_u *
+serverConvert(client_enc, data, tofree)
+    char_u *client_enc;
+    char_u *data;
+    char_u **tofree;
+{
+    char_u	*res = data;
+
+    *tofree = NULL;
+# ifdef FEAT_MBYTE
+    if (client_enc != NULL && p_enc != NULL)
+    {
+	vimconv_T	vimconv;
+
+	vimconv.vc_type = CONV_NONE;
+	if (convert_setup(&vimconv, client_enc, p_enc) != FAIL
+					      && vimconv.vc_type != CONV_NONE)
+	{
+	    res = string_convert(&vimconv, data, NULL);
+	    if (res == NULL)
+		res = data;
+	    else
+		*tofree = res;
+	}
+	convert_setup(&vimconv, NULL, NULL);
+    }
+# endif
+    return res;
+}
+
+
+/*
+ * Make our basic server name: use the specified "arg" if given, otherwise use
+ * the tail of the command "cmd" we were started with.
+ * Return the name in allocated memory.  This doesn't include a serial number.
+ */
+    static char_u *
+serverMakeName(arg, cmd)
+    char_u	*arg;
+    char	*cmd;
+{
+    char_u *p;
+
+    if (arg != NULL && *arg != NUL)
+	p = vim_strsave_up(arg);
+    else
+    {
+	p = vim_strsave_up(gettail((char_u *)cmd));
+	/* Remove .exe or .bat from the name. */
+	if (p != NULL && vim_strchr(p, '.') != NULL)
+	    *vim_strchr(p, '.') = NUL;
+    }
+    return p;
+}
+#endif /* FEAT_CLIENTSERVER */
+
+/*
+ * When FEAT_FKMAP is defined, also compile the Farsi source code.
+ */
+#if defined(FEAT_FKMAP) || defined(PROTO)
+# include "farsi.c"
+#endif
+
+/*
+ * When FEAT_ARABIC is defined, also compile the Arabic source code.
+ */
+#if defined(FEAT_ARABIC) || defined(PROTO)
+# include "arabic.c"
+#endif
diff -Naur vim71.orig/src/mbyte.c vim71/src/mbyte.c
--- vim71.orig/src/mbyte.c	2007-05-07 19:47:09.000000000 +0000
+++ vim71/src/mbyte.c	2007-09-07 07:42:17.000000000 +0000
@@ -1310,20 +1310,26 @@
 /*
  * mb_off2cells() function pointer.
  * Return number of display cells for char at ScreenLines[off].
- * Caller must make sure "off" and "off + 1" are valid!
+ * We make sure that the offset used is less than "max_off".
  */
 /*ARGSUSED*/
     int
-latin_off2cells(off)
+latin_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
     return 1;
 }
 
     int
-dbcs_off2cells(off)
+dbcs_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
+    /* never check beyond end of the line */
+    if (off >= max_off)
+	return 1;
+
     /* Number of cells is equal to number of bytes, except for euc-jp when
      * the first byte is 0x8e. */
     if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e)
@@ -1332,10 +1338,11 @@
 }
 
     int
-utf_off2cells(off)
+utf_off2cells(off, max_off)
     unsigned	off;
+    unsigned	max_off;
 {
-    return ScreenLines[off + 1] == 0 ? 2 : 1;
+    return (off + 1 < max_off && ScreenLines[off + 1] == 0) ? 2 : 1;
 }
 
 /*
@@ -2320,7 +2327,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;
 		}
@@ -2899,12 +2906,8 @@
     if (composing_hangul)
 	return TRUE;
 #endif
-    if (enc_dbcs != 0)
-	return dbcs_off2cells(LineOffset[row] + col) > 1;
-    if (enc_utf8)
-	return (col + 1 < Columns
-		&& ScreenLines[LineOffset[row] + col + 1] == 0);
-    return FALSE;
+    return (*mb_off2cells)(LineOffset[row] + col,
+					LineOffset[row] + screen_Columns) > 1;
 }
 
 # if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \
diff -Naur vim71.orig/src/message.c vim71/src/message.c
--- vim71.orig/src/message.c	2007-05-07 19:31:59.000000000 +0000
+++ vim71/src/message.c	2007-09-07 07:42:17.000000000 +0000
@@ -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,
@@ -3456,11 +3458,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 +3495,7 @@
 			*msgp++ = (dfltbutton == 1) ? ']' : ')';
 
 			/* redefine hotkey */
-			(void)copy_char(r, hotkp, TRUE);
+			hotkp[copy_char(r, hotkp, TRUE)] = NUL;
 		    }
 		}
 		else
@@ -3519,8 +3521,6 @@
 	    *msgp++ = ':';
 	    *msgp++ = ' ';
 	    *msgp = NUL;
-	    mb_ptr_adv(hotkp);
-	    *hotkp = NUL;
 	}
 	else
 	{
@@ -3555,8 +3555,9 @@
 	    msgp = confirm_msg + 1 + STRLEN(message);
 	    hotkp = hotk;
 
-	    /* define first default hotkey */
-	    (void)copy_char(buttons, hotkp, TRUE);
+	    /* Define first default hotkey.  Keep the hotkey string NUL
+	     * terminated to avoid reading past the end. */
+	    hotkp[copy_char(buttons, hotkp, TRUE)] = NUL;
 
 	    /* Remember where the choices start, displaying starts here when
 	     * "hotkp" typed at the more prompt. */
diff -Naur vim71.orig/src/misc1.c vim71/src/misc1.c
--- vim71.orig/src/misc1.c	2007-05-07 19:49:03.000000000 +0000
+++ vim71/src/misc1.c	2007-09-07 07:42:17.000000000 +0000
@@ -90,7 +90,7 @@
  */
     int
 set_indent(size, flags)
-    int		size;
+    int		size;		    /* measured in spaces */
     int		flags;
 {
     char_u	*p;
@@ -98,12 +98,14 @@
     char_u	*oldline;
     char_u	*s;
     int		todo;
-    int		ind_len;
+    int		ind_len;	    /* measured in characters */
     int		line_len;
     int		doit = FALSE;
-    int		ind_done;
+    int		ind_done = 0;	    /* measured in spaces */
     int		tab_pad;
     int		retval = FALSE;
+    int		orig_char_len = -1; /* number of initial whitespace chars when
+				       'et' and 'pi' are both set */
 
     /*
      * First check if there is anything to do and compute the number of
@@ -116,8 +118,10 @@
     /* Calculate the buffer size for the new indent, and check to see if it
      * isn't already set */
 
-    /* if 'expandtab' isn't set: use TABs */
-    if (!curbuf->b_p_et)
+    /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and
+     * 'preserveindent' are set count the number of characters at the
+     * beginning of the line to be copied */
+    if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi))
     {
 	/* If 'preserveindent' is set then reuse as much as possible of
 	 * the existing indent structure for the new indent */
@@ -148,9 +152,14 @@
 		++p;
 	    }
 
+	    /* Set initial number of whitespace chars to copy if we are
+	     * preserving indent but expandtab is set */
+	    if (curbuf->b_p_et)
+		orig_char_len = ind_len;
+
 	    /* Fill to next tabstop with a tab, if possible */
 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
-	    if (todo >= tab_pad)
+	    if (todo >= tab_pad && orig_char_len == -1)
 	    {
 		doit = TRUE;
 		todo -= tab_pad;
@@ -193,13 +202,42 @@
     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))
+	    (void)*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)
     {
@@ -1320,8 +1358,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);
 
@@ -4786,7 +4824,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 +5589,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 +5623,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 +5641,8 @@
 	--lnum;
     }
 
-    s = cin_skipcomment(ml_get(lnum));
+    line = ml_get(lnum);
+    s = cin_skipcomment(line);
     for (;;)
     {
 	if (*s == NUL)
@@ -5610,7 +5650,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] == ':')
@@ -7079,7 +7122,7 @@
 		n = FALSE;
 		if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass > 0)
 		{
-		    n = cin_is_cpp_baseclass(l, &col);
+		    n = cin_is_cpp_baseclass(&col);
 		    l = ml_get_curline();
 		}
 		if (n)
@@ -7670,7 +7713,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)
@@ -8596,7 +8639,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 +8940,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;
 	}
diff -Naur vim71.orig/src/normal.c vim71/src/normal.c
--- vim71.orig/src/normal.c	2007-05-07 19:34:39.000000000 +0000
+++ vim71/src/normal.c	2007-09-07 07:42:17.000000000 +0000
@@ -889,6 +889,11 @@
 
 	++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')
 	{
 	    /*
@@ -3755,7 +3760,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())
@@ -6379,7 +6385,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,
@@ -6662,6 +6668,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 +6701,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
diff -Naur vim71.orig/src/ops.c vim71/src/ops.c
--- vim71.orig/src/ops.c	2007-05-07 19:33:47.000000000 +0000
+++ vim71/src/ops.c	2007-09-07 07:42:14.000000000 +0000
@@ -3404,7 +3404,9 @@
 
 #ifdef FEAT_VIRTUALEDIT
 	col += curwin->w_cursor.coladd;
-	if (ve_flags == VE_ALL && curwin->w_cursor.coladd > 0)
+	if (ve_flags == VE_ALL
+		&& (curwin->w_cursor.coladd > 0
+		    || endcol2 == curwin->w_cursor.col))
 	{
 	    if (dir == FORWARD && c == NUL)
 		++col;
diff -Naur vim71.orig/src/option.c vim71/src/option.c
--- vim71.orig/src/option.c	2007-05-01 11:26:10.000000000 +0000
+++ vim71/src/option.c	2007-09-07 07:42:17.000000000 +0000
@@ -427,6 +427,8 @@
 #define P_NOGLOB       0x100000L/* do not use local value for global vimrc */
 #define P_NFNAME       0x200000L/* only normal file name chars allowed */
 #define P_INSECURE     0x400000L/* option was set from a modeline */
+#define P_PRI_MKRC     0x800000L/* priority for :mkvimrc (setting option has
+				   side effects) */
 
 #define ISK_LATIN1  (char_u *)"@,48-57,_,192-255"
 
@@ -773,6 +775,8 @@
 			    {(char_u *)0L, (char_u *)0L}
 #endif
 			    },
+			    /* P_PRI_MKRC isn't needed here, optval_default()
+			     * always returns TRUE for 'compatible' */
     {"compatible",  "cp",   P_BOOL|P_RALL,
 			    (char_u *)&p_cp, PV_NONE,
 			    {(char_u *)TRUE, (char_u *)FALSE}},
@@ -1515,7 +1519,7 @@
 			    {(char_u *)0L, (char_u *)0L}
 #endif
 			    },
-    {"keymap",	    "kmp",  P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME,
+    {"keymap",	    "kmp",  P_STRING|P_ALLOCED|P_VI_DEF|P_RBUF|P_RSTAT|P_NFNAME|P_PRI_MKRC,
 #ifdef FEAT_KEYMAP
 			    (char_u *)&p_keymap, PV_KMAP,
 			    {(char_u *)"", (char_u *)0L}
@@ -1836,7 +1840,7 @@
     {"paragraphs",  "para", P_STRING|P_VI_DEF,
 			    (char_u *)&p_para, PV_NONE,
 			    {(char_u *)"IPLPPPQPP LIpplpipbp", (char_u *)0L}},
-    {"paste",	    NULL,   P_BOOL|P_VI_DEF,
+    {"paste",	    NULL,   P_BOOL|P_VI_DEF|P_PRI_MKRC,
 			    (char_u *)&p_paste, PV_NONE,
 			    {(char_u *)FALSE, (char_u *)0L}},
     {"pastetoggle", "pt",   P_STRING|P_VI_DEF,
@@ -4628,7 +4632,7 @@
 				    if ((!(flags & P_COMMA) || *s != ',')
 					    && vim_strchr(s + 1, *s) != NULL)
 				    {
-					STRCPY(s, s + 1);
+					mch_memmove(s, s + 1, STRLEN(s));
 					--s;
 				    }
 			    }
@@ -6348,7 +6352,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 +7122,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 */
@@ -8219,6 +8228,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 +8539,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 +8648,7 @@
 		}
 	    }
 	}
+    }
     return OK;
 }
 
@@ -10585,6 +10621,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 +10636,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 +10656,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/os_unix.c vim71/src/os_unix.c
--- vim71.orig/src/os_unix.c	2007-05-09 19:41:58.000000000 +0000
+++ vim71/src/os_unix.c	2007-09-07 07:42:17.000000000 +0000
@@ -753,7 +753,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));
@@ -2499,7 +2500,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
 }
 
 /*
@@ -5682,7 +5689,7 @@
 
 /*
  * Closes connection to gpm
- * returns non-zero if connection succesfully closed
+ * returns non-zero if connection successfully closed
  */
     static void
 gpm_close()
diff -Naur vim71.orig/src/os_unix.h vim71/src/os_unix.h
--- vim71.orig/src/os_unix.h	2007-05-07 19:35:05.000000000 +0000
+++ vim71/src/os_unix.h	2007-09-07 07:42:15.000000000 +0000
@@ -508,6 +508,9 @@
 #if !defined(S_ISFIFO) && defined(S_IFIFO)
 # define	S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
 #endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+# define	S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
 
 /* Note: Some systems need both string.h and strings.h (Savage).  However,
  * some systems can't handle both, only use string.h in that case. */
diff -Naur vim71.orig/src/popupmnu.c vim71/src/popupmnu.c
--- vim71.orig/src/popupmnu.c	2007-03-24 20:07:39.000000000 +0000
+++ vim71/src/popupmnu.c	2007-09-07 07:42:17.000000000 +0000
@@ -75,7 +75,6 @@
 
     row = curwin->w_cline_row + W_WINROW(curwin);
     height = curwin->w_cline_height;
-    col = curwin->w_wcol + W_WINCOL(curwin) - curwin->w_leftcol;
 
     if (firstwin->w_p_pvw)
 	top_clear = firstwin->w_height;
@@ -167,6 +166,15 @@
     pum_base_width = max_width;
     pum_kind_width = kind_width;
 
+    /* Calculate column */
+#ifdef FEAT_RIGHTLEFT
+    if (curwin->w_p_rl)
+	col = W_WINCOL(curwin) + W_WIDTH(curwin) - curwin->w_wcol -
+							curwin->w_leftcol - 1;
+    else
+#endif
+	col = W_WINCOL(curwin) + curwin->w_wcol - curwin->w_leftcol;
+
     /* if there are more items than room we need a scrollbar */
     if (pum_height < size)
     {
@@ -179,11 +187,23 @@
     if (def_width < max_width)
 	def_width = max_width;
 
-    if (col < Columns - PUM_DEF_WIDTH || col < Columns - max_width)
+    if (((col < Columns - PUM_DEF_WIDTH || col < Columns - max_width)
+#ifdef FEAT_RIGHTLEFT
+		&& !curwin->w_p_rl)
+	    || (curwin->w_p_rl && (col > PUM_DEF_WIDTH || col > max_width)
+#endif
+       ))
     {
 	/* align pum column with "col" */
 	pum_col = col;
-	pum_width = Columns - pum_col - pum_scrollbar;
+
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_width = pum_col - pum_scrollbar + 1;
+	else
+#endif
+	    pum_width = Columns - pum_col - pum_scrollbar;
+
 	if (pum_width > max_width + kind_width + extra_width + 1
 						 && pum_width > PUM_DEF_WIDTH)
 	{
@@ -195,14 +215,24 @@
     else if (Columns < def_width)
     {
 	/* not enough room, will use what we have */
-	pum_col = 0;
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_col = Columns - 1;
+	else
+#endif
+	    pum_col = 0;
 	pum_width = Columns - 1;
     }
     else
     {
 	if (max_width > PUM_DEF_WIDTH)
 	    max_width = PUM_DEF_WIDTH;	/* truncate */
-	pum_col = Columns - max_width;
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    pum_col = max_width - 1;
+	else
+#endif
+	    pum_col = Columns - max_width;
 	pum_width = max_width - pum_scrollbar;
     }
 
@@ -255,8 +285,16 @@
 	attr = (idx == pum_selected) ? attr_select : attr_norm;
 
 	/* prepend a space if there is room */
-	if (pum_col > 0)
-	    screen_putchar(' ', row, pum_col - 1, attr);
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	{
+	    if (pum_col < W_WINCOL(curwin) + W_WIDTH(curwin) - 1)
+		screen_putchar(' ', row, pum_col + 1, attr);
+	}
+	else
+#endif
+	    if (pum_col > 0)
+		screen_putchar(' ', row, pum_col - 1, attr);
 
 	/* Display each entry, use two spaces for a Tab.
 	 * Do this 3 times: For the main text, kind and extra info */
@@ -282,26 +320,67 @@
 		    {
 			/* Display the text that fits or comes before a Tab.
 			 * First convert it to printable characters. */
-			char_u *st;
-			int  saved = *p;
+			char_u	*st;
+			int	saved = *p;
 
 			*p = NUL;
 			st = transstr(s);
 			*p = saved;
-			if (st != NULL)
+#ifdef FEAT_RIGHTLEFT
+			if (curwin->w_p_rl)
 			{
-			    screen_puts_len(st, (int)STRLEN(st), row, col,
+			    if (st != NULL)
+			    {
+				char_u	*rt = reverse_text(st);
+				char_u	*rt_saved = rt;
+				int	len, j;
+
+				if (rt != NULL)
+				{
+				    len = STRLEN(rt);
+				    if (len > pum_width)
+				    {
+					for (j = pum_width; j < len; ++j)
+					    mb_ptr_adv(rt);
+					len = pum_width;
+				    }
+				    screen_puts_len(rt, len, row,
+							col - len + 1, attr);
+				    vim_free(rt_saved);
+				}
+				vim_free(st);
+			    }
+			    col -= width;
+			}
+			else
+#endif
+			{
+			    if (st != NULL)
+			    {
+				screen_puts_len(st, (int)STRLEN(st), row, col,
 									attr);
-			    vim_free(st);
+				vim_free(st);
+			    }
+			    col += width;
 			}
-			col += width;
 
 			if (*p != TAB)
 			    break;
 
 			/* Display two spaces for a Tab. */
-			screen_puts_len((char_u *)"  ", 2, row, col, attr);
-			col += 2;
+#ifdef FEAT_RIGHTLEFT
+			if (curwin->w_p_rl)
+			{
+			    screen_puts_len((char_u *)"  ", 2, row, col - 1,
+									attr);
+			    col -= 2;
+			}
+			else
+#endif
+			{
+			    screen_puts_len((char_u *)"  ", 2, row, col, attr);
+			    col += 2;
+			}
 			totwidth += 2;
 			s = NULL;	    /* start text at next char */
 			width = 0;
@@ -322,17 +401,44 @@
 					  && pum_array[idx].pum_extra == NULL)
 		    || pum_base_width + n >= pum_width)
 		break;
-	    screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
+#ifdef FEAT_RIGHTLEFT
+	    if (curwin->w_p_rl)
+	    {
+		screen_fill(row, row + 1, pum_col - pum_base_width - n + 1,
+						    col + 1, ' ', ' ', attr);
+		col = pum_col - pum_base_width - n + 1;
+	    }
+	    else
+#endif
+	    {
+		screen_fill(row, row + 1, col, pum_col + pum_base_width + n,
 							      ' ', ' ', attr);
-	    col = pum_col + pum_base_width + n;
+		col = pum_col + pum_base_width + n;
+	    }
 	    totwidth = pum_base_width + n;
 	}
 
-	screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ', attr);
+#ifdef FEAT_RIGHTLEFT
+	if (curwin->w_p_rl)
+	    screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ',
+								    ' ', attr);
+	else
+#endif
+	    screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ',
+									attr);
 	if (pum_scrollbar > 0)
-	    screen_putchar(' ', row, pum_col + pum_width,
-		    i >= thumb_pos && i < thumb_pos + thumb_heigth
+	{
+#ifdef FEAT_RIGHTLEFT
+	    if (curwin->w_p_rl)
+		screen_putchar(' ', row, pum_col - pum_width,
+			i >= thumb_pos && i < thumb_pos + thumb_heigth
 						  ? attr_thumb : attr_scroll);
+	    else
+#endif
+		screen_putchar(' ', row, pum_col + pum_width,
+			i >= thumb_pos && i < thumb_pos + thumb_heigth
+						  ? attr_thumb : attr_scroll);
+	}
 
 	++row;
     }
@@ -466,7 +572,7 @@
 			set_option_value((char_u *)"bh", 0L,
 						 (char_u *)"wipe", OPT_LOCAL);
 			set_option_value((char_u *)"diff", 0L,
-						     (char_u *)"", OPT_LOCAL);
+							     NULL, OPT_LOCAL);
 		    }
 		}
 		if (res == OK)
diff -Naur vim71.orig/src/proto/charset.pro vim71/src/proto/charset.pro
--- vim71.orig/src/proto/charset.pro	2007-05-12 10:39:01.000000000 +0000
+++ vim71/src/proto/charset.pro	2007-09-07 07:42:17.000000000 +0000
@@ -21,6 +21,7 @@
 int vim_iswordp __ARGS((char_u *p));
 int vim_iswordc_buf __ARGS((char_u *p, buf_T *buf));
 int vim_isfilec __ARGS((int c));
+int vim_isfilec_or_wc __ARGS((int c));
 int vim_isprintc __ARGS((int c));
 int vim_isprintc_strict __ARGS((int c));
 int lbr_chartabsize __ARGS((unsigned char *s, colnr_T col));
diff -Naur vim71.orig/src/proto/fileio.pro vim71/src/proto/fileio.pro
--- vim71.orig/src/proto/fileio.pro	2007-05-12 10:39:14.000000000 +0000
+++ vim71/src/proto/fileio.pro	2007-09-07 07:42:14.000000000 +0000
@@ -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));
diff -Naur vim71.orig/src/proto/if_cscope.pro vim71/src/proto/if_cscope.pro
--- vim71.orig/src/proto/if_cscope.pro	2007-05-12 10:39:21.000000000 +0000
+++ vim71/src/proto/if_cscope.pro	2007-09-07 07:42:17.000000000 +0000
@@ -6,4 +6,5 @@
 void cs_free_tags __ARGS((void));
 void cs_print_tags __ARGS((void));
 int cs_connection __ARGS((int num, char_u *dbpath, char_u *ppath));
+void cs_end __ARGS((void));
 /* vim: set ft=c : */
diff -Naur vim71.orig/src/proto/mbyte.pro vim71/src/proto/mbyte.pro
--- vim71.orig/src/proto/mbyte.pro	2007-05-12 10:39:38.000000000 +0000
+++ vim71/src/proto/mbyte.pro	2007-09-07 07:42:17.000000000 +0000
@@ -12,9 +12,9 @@
 int utf_ptr2cells __ARGS((char_u *p));
 int dbcs_ptr2cells __ARGS((char_u *p));
 int latin_char2cells __ARGS((int c));
-int latin_off2cells __ARGS((unsigned off));
-int dbcs_off2cells __ARGS((unsigned off));
-int utf_off2cells __ARGS((unsigned off));
+int latin_off2cells __ARGS((unsigned off, unsigned max_off));
+int dbcs_off2cells __ARGS((unsigned off, unsigned max_off));
+int utf_off2cells __ARGS((unsigned off, unsigned max_off));
 int latin_ptr2char __ARGS((char_u *p));
 int utf_ptr2char __ARGS((char_u *p));
 int mb_ptr2char_adv __ARGS((char_u **pp));
diff -Naur vim71.orig/src/proto/search.pro vim71/src/proto/search.pro
--- vim71.orig/src/proto/search.pro	2007-05-12 10:39:50.000000000 +0000
+++ vim71/src/proto/search.pro	2007-09-07 07:42:17.000000000 +0000
@@ -1,6 +1,7 @@
 /* search.c */
 int search_regcomp __ARGS((char_u *pat, int pat_save, int pat_use, int options, regmmatch_T *regmatch));
 char_u *get_search_pat __ARGS((void));
+char_u *reverse_text __ARGS((char_u *s));
 void save_search_patterns __ARGS((void));
 void restore_search_patterns __ARGS((void));
 void free_search_patterns __ARGS((void));
diff -Naur vim71.orig/src/proto/syntax.pro vim71/src/proto/syntax.pro
--- vim71.orig/src/proto/syntax.pro	2007-05-12 10:39:52.000000000 +0000
+++ vim71/src/proto/syntax.pro	2007-09-07 07:42:16.000000000 +0000
@@ -8,6 +8,8 @@
 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));
diff -Naur vim71.orig/src/proto/window.pro vim71/src/proto/window.pro
--- vim71.orig/src/proto/window.pro	2007-05-12 10:40:00.000000000 +0000
+++ vim71/src/proto/window.pro	2007-09-07 07:42:16.000000000 +0000
@@ -59,4 +59,8 @@
 int only_one_window __ARGS((void));
 void check_lnums __ARGS((int do_curwin));
 int win_hasvertsplit __ARGS((void));
+int match_add __ARGS((win_T *wp, char_u *grp, char_u *pat, int prio, int id));
+int match_delete __ARGS((win_T *wp, int id, int perr));
+void clear_matches __ARGS((win_T *wp));
+matchitem_T *get_match __ARGS((win_T *wp, int id));
 /* vim: set ft=c : */
diff -Naur vim71.orig/src/quickfix.c vim71/src/quickfix.c
--- vim71.orig/src/quickfix.c	2007-02-04 00:50:17.000000000 +0000
+++ vim71/src/quickfix.c	2007-09-07 07:42:14.000000000 +0000
@@ -2331,7 +2331,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
diff -Naur vim71.orig/src/regexp.c vim71/src/regexp.c
--- vim71.orig/src/regexp.c	2007-05-07 19:50:03.000000000 +0000
+++ vim71/src/regexp.c	2007-09-07 07:42:17.000000000 +0000
@@ -2220,7 +2220,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 +2240,7 @@
 				break;
 			    case CLASS_UPPER:
 				for (cu = 1; cu <= 255; cu++)
-				    if (isupper(cu))
+				    if (MB_ISUPPER(cu))
 					regc(cu);
 				break;
 			    case CLASS_XDIGIT:
@@ -3465,7 +3465,7 @@
 			(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;
@@ -4200,7 +4200,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 +4733,10 @@
 		    rst.nextb = *OPERAND(next);
 		    if (ireg_ic)
 		    {
-			if (isupper(rst.nextb))
-			    rst.nextb_ic = TOLOWER_LOC(rst.nextb);
+			if (MB_ISUPPER(rst.nextb))
+			    rst.nextb_ic = MB_TOLOWER(rst.nextb);
 			else
-			    rst.nextb_ic = TOUPPER_LOC(rst.nextb);
+			    rst.nextb_ic = MB_TOUPPER(rst.nextb);
 		    }
 		    else
 			rst.nextb_ic = rst.nextb;
@@ -5558,11 +5558,12 @@
 	    int	    cu, cl;
 
 	    /* This doesn't do a multi-byte character, because a MULTIBYTECODE
-	     * would have been used for it. */
+	     * would have been used for it.  It does handle single-byte
+	     * characters, such as latin1. */
 	    if (ireg_ic)
 	    {
-		cu = TOUPPER_LOC(*opnd);
-		cl = TOLOWER_LOC(*opnd);
+		cu = MB_TOUPPER(*opnd);
+		cl = MB_TOLOWER(*opnd);
 		while (count < maxcount && (*scan == cu || *scan == cl))
 		{
 		    count++;
@@ -6490,10 +6491,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 +6638,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 +7015,14 @@
 #ifdef FEAT_MBYTE
 			    if (has_mbyte)
 			    {
-				int l = mb_ptr2len(s) - 1;
+				int l;
+
+				/* Copy composing characters separately, one
+				 * at a time. */
+				if (enc_utf8)
+				    l = utf_ptr2len(s) - 1;
+				else
+				    l = mb_ptr2len(s) - 1;
 
 				s += l;
 				len -= l;
diff -Naur vim71.orig/src/screen.c vim71/src/screen.c
--- vim71.orig/src/screen.c	2007-05-07 19:27:53.000000000 +0000
+++ vim71/src/screen.c	2007-09-07 07:42:17.000000000 +0000
@@ -100,27 +100,7 @@
 static int	screen_cur_row, screen_cur_col;	/* last known cursor position */
 
 #ifdef FEAT_SEARCH_EXTRA
-/*
- * Struct used for highlighting 'hlsearch' matches for the last use search
- * pattern or a ":match" item.
- * For 'hlsearch' there is one pattern for all windows.  For ":match" there is
- * a different pattern for each window.
- */
-typedef struct
-{
-    regmmatch_T	rm;	/* points to the regexp program; contains last found
-			   match (may continue in next line) */
-    buf_T	*buf;	/* the buffer to search for a match */
-    linenr_T	lnum;	/* the line to search for a match */
-    int		attr;	/* attributes to be used for a match */
-    int		attr_cur; /* attributes currently active in win_line() */
-    linenr_T	first_lnum;	/* first lnum to search for multi-line pat */
-    colnr_T	startcol; /* in win_line() points to char where HL starts */
-    colnr_T	endcol;	 /* in win_line() points to char where HL ends */
-} match_T;
-
 static match_T search_hl;	/* used for 'hlsearch' highlight matching */
-static match_T match_hl[3];	/* used for ":match" highlight matching */
 #endif
 
 #ifdef FEAT_FOLDING
@@ -155,6 +135,7 @@
 static void redraw_custum_statusline __ARGS((win_T *wp));
 #endif
 #ifdef FEAT_SEARCH_EXTRA
+#define SEARCH_HL_PRIORITY 0
 static void start_search_hl __ARGS((void));
 static void end_search_hl __ARGS((void));
 static void prepare_search_hl __ARGS((win_T *wp, linenr_T lnum));
@@ -350,6 +331,11 @@
     {
 	if (type < must_redraw)	    /* use maximal type */
 	    type = must_redraw;
+
+	/* must_redraw is reset here, so that when we run into some weird
+	 * reason to redraw while busy redrawing (e.g., asynchronous
+	 * scrolling), or update_topline() in win_update() will cause a
+	 * scroll, the screen will be redrawn later or in win_update(). */
 	must_redraw = 0;
     }
 
@@ -787,6 +773,7 @@
 					   w_topline got smaller a bit */
 #endif
 #ifdef FEAT_SEARCH_EXTRA
+    matchitem_T *cur;		/* points to the match list */
     int		top_to_mod = FALSE;    /* redraw above mod_top */
 #endif
 
@@ -848,18 +835,20 @@
 #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;
+	cur = cur->next;
     }
     search_hl.buf = buf;
     search_hl.lnum = 0;
@@ -923,19 +912,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 +1024,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 +1232,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 +1244,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
     {
@@ -2542,7 +2555,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
@@ -2626,10 +2639,13 @@
     int		line_attr = 0;		/* atrribute 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 */
@@ -3074,12 +3090,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 +3146,8 @@
 		area_highlighting = TRUE;
 	    }
 	}
+	if (shl != &search_hl && cur != NULL)
+	    cur = cur->next;
     }
 #endif
 
@@ -3163,10 +3189,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 +3206,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 +3413,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 +3478,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 +3549,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 +3666,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;
@@ -3752,10 +3809,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)
 		    {
@@ -4254,14 +4309,29 @@
 	     * 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,15 +4372,27 @@
 #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
@@ -4460,6 +4542,8 @@
 	    {
 		if (mb_utf8)
 		{
+		    int i;
+
 		    ScreenLinesUC[off] = mb_c;
 		    if ((c & 0xff) == 0)
 			ScreenLines[off] = 0x80;   /* avoid storing zero */
@@ -4548,7 +4632,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 +4709,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 +4875,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 +4905,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 +4943,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 +5020,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 +5029,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 +5049,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 +5192,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 +5382,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 +5448,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 +6200,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 +6217,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
@@ -6241,19 +6343,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 +6420,7 @@
 
 #ifdef FEAT_SEARCH_EXTRA
 /*
- * Prepare for 'searchhl' highlighting.
+ * Prepare for 'hlsearch' highlighting.
  */
     static void
 start_search_hl()
@@ -6331,7 +6433,7 @@
 }
 
 /*
- * Clean up for 'searchhl' highlighting.
+ * Clean up for 'hlsearch' highlighting.
  */
     static void
 end_search_hl()
@@ -6351,18 +6453,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 +6509,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 +6525,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 */
 {
@@ -6479,7 +6593,7 @@
 	    /* 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 +6941,9 @@
 {
     int		r, c;
     int		off;
+#ifdef FEAT_MBYTE
+    int		max_off;
+#endif
 
     /* Can't use ScreenLines unless initialized */
     if (ScreenLines == NULL)
@@ -6837,10 +6954,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 +6970,7 @@
 	    {
 		screen_char(off + c, r, c);
 #ifdef FEAT_MBYTE
-		if (utf_off2cells(off + c) > 1)
+		if (utf_off2cells(off + c, max_off) > 1)
 		    ++c;
 #endif
 	    }
diff -Naur vim71.orig/src/search.c vim71/src/search.c
--- vim71.orig/src/search.c	2007-05-07 19:42:02.000000000 +0000
+++ vim71/src/search.c	2007-09-07 07:42:17.000000000 +0000
@@ -101,7 +101,6 @@
 static char_u	    *mr_pattern = NULL;	/* pattern used by search_regcomp() */
 #ifdef FEAT_RIGHTLEFT
 static int	    mr_pattern_alloced = FALSE; /* mr_pattern was allocated */
-static char_u	    *reverse_text __ARGS((char_u *s));
 #endif
 
 #ifdef FEAT_FIND_ID
@@ -228,12 +227,12 @@
     return mr_pattern;
 }
 
-#ifdef FEAT_RIGHTLEFT
+#if defined(FEAT_RIGHTLEFT) || defined(PROTO)
 /*
  * Reverse text into allocated memory.
  * Returns the allocated string, NULL when out of memory.
  */
-    static char_u *
+    char_u *
 reverse_text(s)
     char_u *s;
 {
@@ -573,8 +572,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;
@@ -1894,7 +1897,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 +2127,9 @@
 			else if (!backwards)
 			    inquote = TRUE;
 		    }
+
+		    /* ml_get() only keeps one line, need to get linep again */
+		    linep = ml_get(pos.lnum);
 		}
 	    }
 	}
@@ -2795,7 +2801,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 +3606,16 @@
     {
 	oap->start = start_pos;
 	oap->motion_type = MCHAR;
+	oap->inclusive = FALSE;
 	if (sol)
-	{
 	    incl(&curwin->w_cursor);
-	    oap->inclusive = FALSE;
-	}
-	else
+	else if (lt(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;
@@ -3734,7 +3743,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;
@@ -3838,7 +3847,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 +3869,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 +3885,15 @@
     {
 	oap->start = start_pos;
 	oap->motion_type = MCHAR;
-	oap->inclusive = TRUE;
+	if (lt(end_pos, start_pos))
+	{
+	    /* End is before the start: there is no text between tags; operate
+	     * on an empty area. */
+	    curwin->w_cursor = start_pos;
+	    oap->inclusive = FALSE;
+	}
+	else
+	    oap->inclusive = TRUE;
     }
     retval = OK;
 
diff -Naur vim71.orig/src/spell.c vim71/src/spell.c
--- vim71.orig/src/spell.c	2007-05-07 19:48:38.000000000 +0000
+++ vim71/src/spell.c	2007-09-07 07:42:17.000000000 +0000
@@ -7829,7 +7829,7 @@
 # if (_MSC_VER <= 1200)
 /* This line is required for VC6 without the service pack.  Also see the
  * matching #pragma below. */
-/* # pragma optimize("", off) */
+ #  pragma optimize("", off)
 # endif
 #endif
 
@@ -7859,7 +7859,7 @@
 
 #ifdef _MSC_VER
 # if (_MSC_VER <= 1200)
-/* # pragma optimize("", on) */
+ #  pragma optimize("", on)
 # endif
 #endif
 
@@ -12182,7 +12182,9 @@
 	    {
 		n = mb_cptr2len(p);
 		c = mb_ptr2char(p);
-		if (!soundfold && !spell_iswordp(p + n, curbuf))
+		if (p[n] == NUL)
+		    c2 = NUL;
+		else if (!soundfold && !spell_iswordp(p + n, curbuf))
 		    c2 = c; /* don't swap non-word char */
 		else
 		    c2 = mb_ptr2char(p + n);
@@ -12190,12 +12192,21 @@
 	    else
 #endif
 	    {
-		if (!soundfold && !spell_iswordp(p + 1, curbuf))
+		if (p[1] == NUL)
+		    c2 = NUL;
+		else if (!soundfold && !spell_iswordp(p + 1, curbuf))
 		    c2 = c; /* don't swap non-word char */
 		else
 		    c2 = p[1];
 	    }
 
+	    /* When the second character is NUL we can't swap. */
+	    if (c2 == NUL)
+	    {
+		sp->ts_state = STATE_REP_INI;
+		break;
+	    }
+
 	    /* When characters are identical, swap won't do anything.
 	     * Also get here if the second char is not a word character. */
 	    if (c == c2)
diff -Naur vim71.orig/src/structs.h vim71/src/structs.h
--- vim71.orig/src/structs.h	2007-05-07 19:50:49.000000000 +0000
+++ vim71/src/structs.h	2007-09-07 07:42:17.000000000 +0000
@@ -1453,6 +1453,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 +1695,41 @@
 #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 */
+} 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 +1970,8 @@
 #endif
 
 #ifdef FEAT_SEARCH_EXTRA
-    regmmatch_T	w_match[3];	    /* regexp programs for ":match" */
-    char_u	*(w_match_pat[3]);  /* patterns for ":match" */
-    int		w_match_id[3];	    /* highlight IDs for ":match" */
+    matchitem_T	*w_match_head;		/* head of match list */
+    int		w_next_match_id;	/* next match ID */
 #endif
 
     /*
diff -Naur vim71.orig/src/syntax.c vim71/src/syntax.c
--- vim71.orig/src/syntax.c	2007-05-07 19:42:55.000000000 +0000
+++ vim71/src/syntax.c	2007-09-07 07:42:17.000000000 +0000
@@ -66,8 +66,10 @@
 #define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
 
 #ifdef FEAT_CMDL_COMPL
-static int include_default = FALSE;	/* include "default" for expansion */
-static int include_link = FALSE;	/* include "link" for expansion */
+/* Flags to indicate an additional string for highlight name completion. */
+static int include_none = 0;	/* when 1 include "None" */
+static int include_default = 0;	/* when 1 include "default" */
+static int include_link = 0;	/* when 2 include "link" and "clear" */
 #endif
 
 /*
@@ -277,7 +279,8 @@
  */
 typedef struct state_item
 {
-    int		si_idx;			/* index of syntax pattern */
+    int		si_idx;			/* index of syntax pattern or
+					   KEYWORD_IDX */
     int		si_id;			/* highlight group ID for keywords */
     int		si_trans_id;		/* idem, transparancy removed */
     int		si_m_lnum;		/* lnum of the match */
@@ -835,9 +838,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;
@@ -1725,6 +1737,13 @@
 {
     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;
@@ -2524,6 +2543,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 +2662,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 +2778,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
@@ -4460,8 +4491,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 +5987,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 +5999,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 +6037,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)
@@ -8479,7 +8533,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 +9003,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 +9021,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 +9030,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 +9039,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 +9099,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/termlib.c vim71/src/termlib.c
--- vim71.orig/src/termlib.c	2007-05-07 19:39:49.000000000 +0000
+++ vim71/src/termlib.c	2007-09-07 07:42:17.000000000 +0000
@@ -191,7 +191,7 @@
 	    lbuf[0] == '\t' &&
 	    lbuf[1] == ':')
 	{
-	    strcpy(lbuf, lbuf+2);
+	    mch_memmove(lbuf, lbuf + 2, strlen(lbuf + 2) + 1);
 	    llen -= 2;
 	}
 	if (lbuf[llen-2] == '\\')		/* and continuations */
diff -Naur vim71.orig/src/testdir/Makefile vim71/src/testdir/Makefile
--- vim71.orig/src/testdir/Makefile	2006-04-30 11:08:01.000000000 +0000
+++ vim71/src/testdir/Makefile	2007-09-07 07:42:17.000000000 +0000
@@ -1,9 +1,13 @@
 #
-# Makefile to run al tests for Vim
+# Makefile to run all tests for Vim
 #
 
 VIMPROG = ../vim
 
+# Uncomment this line for using valgrind.
+# The output goes into a file "valgrind.$PID" (sorry, no test number).
+# VALGRIND = valgrind --tool=memcheck --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
 
@@ -38,7 +43,7 @@
 
 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; \
diff -Naur vim71.orig/src/testdir/test63.in vim71/src/testdir/test63.in
--- vim71.orig/src/testdir/test63.in	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test63.in	2007-09-07 07:42:16.000000000 +0000
@@ -0,0 +1,157 @@
+Test for ":match", ":2match", ":3match", "clearmatches()", "getmatches()",
+"matchadd()", "matcharg()", "matchdelete()", and "setmatches()".
+
+STARTTEST
+:so small.vim
+:" --- Check that "matcharg()" returns the correct group and pattern if a match
+:" --- is defined.
+:let @r = "*** Test 1: "
+:highlight MyGroup1 ctermbg=red
+:highlight MyGroup2 ctermbg=green
+:highlight MyGroup3 ctermbg=blue
+:match MyGroup1 /TODO/
+:2match MyGroup2 /FIXME/
+:3match MyGroup3 /XXX/
+:if matcharg(1) == ['MyGroup1', 'TODO'] && matcharg(2) == ['MyGroup2', 'FIXME'] && matcharg(3) == ['MyGroup3', 'XXX']
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matcharg()" returns an empty list if the argument is not 1,
+:" --- 2 or 3 (only 0 and 4 are tested).
+:let @r .= "*** Test 2: "
+:if matcharg(0) == [] && matcharg(4) == []
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matcharg()" returns ['', ''] if a match is not defined.
+:let @r .= "*** Test 3: "
+:match
+:2match
+:3match
+:if matcharg(1) == ['', ''] && matcharg(2) == ['', ''] && matcharg(3) == ['', '']
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchadd()" and "getmatches()" agree on added matches and
+:" --- that default values apply.
+:let @r .= "*** Test 4: "
+:let m1 = matchadd("MyGroup1", "TODO")
+:let m2 = matchadd("MyGroup2", "FIXME", 42)
+:let m3 = matchadd("MyGroup3", "XXX", 60, 17)
+:if getmatches() == [{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 4}, {'group': 'MyGroup2', 'pattern': 'FIXME', 'priority': 42, 'id': 5}, {'group': 'MyGroup3', 'pattern': 'XXX', 'priority': 60, 'id': 17}]
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchdelete()" deletes the matches defined in the previous
+:" --- test correctly.
+:let @r .= "*** Test 5: "
+:call matchdelete(m1)
+:call matchdelete(m2)
+:call matchdelete(m3)
+:unlet m1
+:unlet m2
+:unlet m3
+:if getmatches() == []
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:" --- Check that "matchdelete()" returns 0 if succesfull 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 succesfull 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 succesfull and otherwise -1.
+:" --- (A range of valid and invalid input values are tried out to generate the
+:" --- return values.)
+:let @r .= "*** Test 10: "
+:let rs1 = setmatches([])
+:let rs2 = setmatches([{'group': 'MyGroup1', 'pattern': 'TODO', 'priority': 10, 'id': 1}])
+:call clearmatches()
+:let rf1 = setmatches(0)
+:let rf2 = setmatches([0])
+:let rf3 = setmatches([{'wrong key': 'wrong value'}])
+:if rs1 == 0 && rs2 == 0 && rf1 == -1 && rf2 == -1 && rf3 == -1
+:  let @r .= "OK\n"
+:else
+:  let @r .= "FAILED\n"
+:endif
+:unlet rs1
+:unlet rs2
+:unlet rf1
+:unlet rf2
+:unlet rf3
+:highlight clear MyGroup1
+:highlight clear MyGroup2
+:highlight clear MyGroup3
+G"rp
+:/^Results/,$wq! test.out
+ENDTEST
+
+Results of test63:
diff -Naur vim71.orig/src/testdir/test63.ok vim71/src/testdir/test63.ok
--- vim71.orig/src/testdir/test63.ok	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test63.ok	2007-09-07 07:42:16.000000000 +0000
@@ -0,0 +1,11 @@
+Results of test63:
+*** Test 1: OK
+*** Test 2: OK
+*** Test 3: OK
+*** Test 4: OK
+*** Test 5: OK
+*** Test 6: OK
+*** Test 7: OK
+*** Test 8: OK
+*** Test 9: OK
+*** Test 10: OK
diff -Naur vim71.orig/src/testdir/test64.in vim71/src/testdir/test64.in
--- vim71.orig/src/testdir/test64.in	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test64.in	2007-09-07 07:42:17.000000000 +0000
@@ -0,0 +1,52 @@
+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, ['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, ['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
+:  endif
+:endfor
+:/^Results/,$wq! test.out
+ENDTEST
+
+Results of test64:
diff -Naur vim71.orig/src/testdir/test64.ok vim71/src/testdir/test64.ok
--- vim71.orig/src/testdir/test64.ok	1970-01-01 00:00:00.000000000 +0000
+++ vim71/src/testdir/test64.ok	2007-09-07 07:42:17.000000000 +0000
@@ -0,0 +1,6 @@
+Results of test64:
+OK
+OK
+OK
+OK
+OK
diff -Naur vim71.orig/src/ui.c vim71/src/ui.c
--- vim71.orig/src/ui.c	2007-05-07 19:49:09.000000000 +0000
+++ vim71/src/ui.c	2007-09-07 07:42:17.000000000 +0000
@@ -1603,8 +1603,6 @@
 #if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) \
 	|| defined(FEAT_XCLIPBOARD) || defined(VMS) \
 	|| defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) \
-	|| (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
-		|| defined(FEAT_MENU))) \
 	|| defined(PROTO)
 /*
  * Add the given bytes to the input buffer
@@ -1630,7 +1628,9 @@
 }
 #endif
 
-#if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \
+#if ((defined(FEAT_XIM) || defined(FEAT_DND)) && defined(FEAT_GUI_GTK)) \
+	|| defined(FEAT_GUI_MSWIN) \
+	|| defined(FEAT_GUI_MAC) \
 	|| (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \
 	|| (defined(FEAT_GUI) && (!defined(USE_ON_FLY_SCROLL) \
 		|| defined(FEAT_MENU))) \
diff -Naur vim71.orig/src/version.c vim71/src/version.c
--- vim71.orig/src/version.c	2007-05-12 10:23:44.000000000 +0000
+++ vim71/src/version.c	2007-09-07 07:42:17.000000000 +0000
@@ -667,6 +667,186 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    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
 };
 
diff -Naur vim71.orig/src/vim.h vim71/src/vim.h
--- vim71.orig/src/vim.h	2007-05-12 09:53:29.000000000 +0000
+++ vim71/src/vim.h	2007-09-07 07:42:17.000000000 +0000
@@ -1380,8 +1380,14 @@
 #endif
 
 #ifdef FEAT_MBYTE
-# define MB_STRICMP(d, s)	(has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL) : STRICMP((d), (s)))
-# define MB_STRNICMP(d, s, n)	(has_mbyte ? mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n)) : STRNICMP((d), (s), (n)))
+/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte
+ * encoding because mb_stricmp() takes care of all ascii and non-ascii
+ * encodings, including characters with umluats in latin1, etc., while
+ * STRICMP() only handles the system locale version, which often does not
+ * handle non-ascii properly. */
+
+# define MB_STRICMP(d, s)	mb_strnicmp((char_u *)(d), (char_u *)(s), (int)MAXCOL)
+# define MB_STRNICMP(d, s, n)	mb_strnicmp((char_u *)(d), (char_u *)(s), (int)(n))
 #else
 # define MB_STRICMP(d, s)	STRICMP((d), (s))
 # define MB_STRNICMP(d, s, n)	STRNICMP((d), (s), (n))
diff -Naur vim71.orig/src/vimtutor vim71/src/vimtutor
--- vim71.orig/src/vimtutor	2004-06-07 14:32:27.000000000 +0000
+++ vim71/src/vimtutor	2007-09-07 07:42:15.000000000 +0000
@@ -39,18 +39,22 @@
 # remove the copy of the tutor on exit
 trap "rm -rf $TODELETE" 0 1 2 3 9 11 13 15
 
-# Vim could be called "vim" or "vi".  Also check for "vim6", for people who
-# have Vim 5.x installed as "vim" and Vim 6.0 as "vim6".
-testvim=`which vim6 2>/dev/null`
-if test -f "$testvim"; then
-	VIM=vim6
-else
-	testvim=`which vim`
+# Vim could be called "vim" or "vi".  Also check for "vimN", for people who
+# have Vim installed with its version number.
+# We anticipate up to a future Vim 8 version :-).
+seq="vim vim8 vim75 vim74 vim73 vim72 vim71 vim70 vim7 vim6 vi"
+for i in $seq; do
+	testvim=`which $i 2>/dev/null`
 	if test -f "$testvim"; then
-		VIM=vim
-	else
-		VIM=vi
+		VIM=$i
+		break
 	fi
+done
+
+# When no Vim version was found fall back to "vim", you'll get an error message
+# below.
+if test -z "$VIM"; then
+	VIM=vim
 fi
 
 # Use Vim to copy the tutor, it knows the value of $VIMRUNTIME
diff -Naur vim71.orig/src/window.c vim71/src/window.c
--- vim71.orig/src/window.c	2007-05-07 19:25:30.000000000 +0000
+++ vim71/src/window.c	2007-09-07 07:42:17.000000000 +0000
@@ -75,6 +75,7 @@
 static win_T *restore_snapshot_rec __ARGS((frame_T *sn, frame_T *fr));
 
 #endif /* FEAT_WINDOWS */
+
 static win_T *win_alloc __ARGS((win_T *after));
 static void win_new_height __ARGS((win_T *, int));
 
@@ -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;
+	    }
+	}
     }
 
     /*
@@ -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
@@ -4128,6 +4209,10 @@
 #ifdef FEAT_AUTOCMD
 	--autocmd_block;
 #endif
+#ifdef FEAT_SEARCH_EXTRA
+	newwin->w_match_head = NULL;
+	newwin->w_next_match_id = 4;
+#endif
     }
     return newwin;
 }
@@ -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
@@ -6174,3 +6259,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
