changeset 168:4d9eabb1396e

updated for version 7.0051
author vimboss
date Tue, 22 Feb 2005 08:49:11 +0000
parents c93c9cad9618
children 0e902b8f511f
files runtime/doc/autocmd.txt runtime/doc/change.txt runtime/doc/eval.txt runtime/doc/options.txt runtime/doc/pattern.txt runtime/doc/repeat.txt runtime/doc/starting.txt runtime/doc/tags runtime/doc/windows.txt runtime/filetype.vim runtime/ftplugin/vim.vim src/ex_getln.c src/gui_mac.c src/ops.c src/option.c src/option.h src/os_mac_conv.c src/po/Make_mvc.mak src/proto/eval.pro src/screen.c src/search.c src/structs.h src/syntax.c src/term.c src/undo.c src/version.h
diffstat 26 files changed, 1594 insertions(+), 386 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -1,4 +1,4 @@
-*autocmd.txt*   For Vim version 7.0aa.  Last change: 2005 Feb 07
+*autocmd.txt*   For Vim version 7.0aa.  Last change: 2005 Feb 21
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -204,10 +204,12 @@ FilterReadPre			Before reading a file fr
 				the current buffer, not the name of the
 				temporary file that is the output of the
 				filter command.
+				Not triggered when 'shelltemp' is off.
 							*FilterReadPost*
 FilterReadPost			After reading a file from a filter command.
 				Vim checks the pattern against the name of
 				the current buffer as with FilterReadPre.
+				Not triggered when 'shelltemp' is off.
 							*FileType*
 FileType			When the 'filetype' option has been set.
 				<afile> can be used for the name of the file
@@ -270,11 +272,13 @@ FilterWritePre			Before writing a file f
 				the current buffer, not the name of the
 				temporary file that is the output of the
 				filter command.
+				Not triggered when 'shelltemp' is off.
 							*FilterWritePost*
 FilterWritePost			After writing a file for a filter command or
 				making a diff.
 				Vim checks the pattern against the name of
 				the current buffer as with FilterWritePre.
+				Not triggered when 'shelltemp' is off.
 							*FileChangedShell*
 FileChangedShell		When Vim notices that the modification time of
 				a file has changed since editing started.
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt*    For Vim version 7.0aa.  Last change: 2005 Feb 08
+*change.txt*    For Vim version 7.0aa.  Last change: 2005 Feb 21
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -112,19 +112,22 @@ gJ			Join [count] lines, with a minimum 
 			Vi}
 
 							*:j* *:join*
-:[range]j[oin][!]	Join [range] lines.  Same as "J", except with [!]
+:[range]j[oin][!] [flags]
+			Join [range] lines.  Same as "J", except with [!]
 			the join does not insert or delete any spaces.
 			If a [range] has equal start and end values, this
 			command does nothing.  The default behavior is to
 			join the current line with the line below it.
 			{not in Vi: !}
+			See |ex-flags| for [flags].
 
-:[range]j[oin][!] {count}
+:[range]j[oin][!] {count} [flags]
 			Join {count} lines, starting with [range] (default:
 			current line |cmdline-ranges|).  Same as "J", except
 			with [!] the join does not insert or delete any
 			spaces.
 			{not in Vi: !}
+			See |ex-flags| for [flags].
 
 These commands delete the <EOL> between lines.  This has the effect of joining
 multiple lines into one line.  You can repeat these commands (except ":j") and
@@ -236,10 +239,12 @@ If you prefer "cw" to include the space 
 	:map cw dwi
 <
 							*:c* *:ch* *:change*
-:{range}c[hange]	Replace lines of text with some different text.
+:{range}c[hange][!]	Replace lines of text with some different text.
 			Type a line containing only "." to stop replacing.
 			Without {range}, this command changes only the current
 			line.
+			Adding [!] toggles 'autoindent' for the time this
+			command is executed.
 
 ==============================================================================
 3. Simple changes					*simple-change*
@@ -424,12 +429,15 @@ SHIFTING LINES LEFT OR RIGHT				*shift-l
 			lines to [indent] (default 0).  {not in Vi}
 
 							*:>*
-:[range]>		Shift {count} [range] lines one 'shiftwidth' right.
+:[range]> [flags]	Shift {count} [range] lines one 'shiftwidth' right.
 			Repeat '>' for shifting multiple 'shiftwidth's.
+			See |ex-flags| for [flags].
 
-:[range]> {count}	Shift {count} lines one 'shiftwidth' right, starting
+:[range]> {count} [flags]
+			Shift {count} lines one 'shiftwidth' right, starting
 			with [range] (default current line |cmdline-ranges|).
 			Repeat '>' for shifting multiple 'shiftwidth's.
+			See |ex-flags| for [flags].
 
 The ">" and "<" commands are handy for changing the indentation within
 programs.  Use the 'shiftwidth' option to set the size of the white space
@@ -519,7 +527,7 @@ comment (starting with '"') after the ":
 
 4.2 Substitute						*:substitute*
 							*:s* *:su*
-:[range]s[ubstitute]/{pattern}/{string}/[&][c][e][g][p][r][i][I] [count]
+:[range]s[ubstitute]/{pattern}/{string}/[&][#][c][e][g][p][r][i][I] [count]
 			For each line in [range] replace a match of {pattern}
 			with {string}.
 			For the {pattern} see |pattern|.
@@ -533,8 +541,8 @@ 4.2 Substitute						*:substitute*
 			Also see |cmdline-ranges|.
 			See |:s_flags| for the flags.
 
-:[range]s[ubstitute] [c][e][g][p][r][i][I] [count]
-:[range]&[&][c][e][g][p][r][i][I] [count]			*:&*
+:[range]s[ubstitute] [#][c][e][g][p][r][i][I] [count]
+:[range]&[&][#][c][e][g][p][r][i][I] [count]			*:&*
 			Repeat last :substitute with same search pattern and
 			substitute string, but without the same flags.  You
 			may add extra flags (see |:s_flags|).
@@ -544,7 +552,7 @@ 4.2 Substitute						*:substitute*
 			'r' flags isn't required, but in scripts it's a good
 			idea to keep it to avoid confusion.
 
-:[range]~[&][c][e][g][p][r][i][I] [count]			*:~*
+:[range]~[&][#][c][e][g][p][r][i][I] [count]			*:~*
 			Repeat last substitute with same substitute string
 			but with last used search pattern.  This is like
 			":&r".  See |:s_flags| for the flags.
@@ -622,7 +630,10 @@ The flags that you can use for the subst
 	{not in Vi}
 
 [p]	Print the line containing the last substitute.
-	{not in Vi}
+
+[#]	Like [p] and prepend the line number.
+
+[l]	Like [l] but print the text like |:list|.
 
 [r]	Only useful in combination with ":&" or ":s" without arguments.  ":&r"
 	works the same way as ":~":  When the search pattern is empty, use the
@@ -668,6 +679,9 @@ For the definition of a pattern, see |pa
 When the {string} starts with "\=" it is evaluated as an expression, see
 |sub-replace-expression|.  Otherwise these characters in {string} have a
 special meaning:
+								*:s%*
+When {string} is equal to "%" and '/' is included with the 'cpotions' option,
+then the {string} of the previous substitute command is used. |cpo-/|
 
 magic	nomagic	  action    ~
   &	  \&	  replaced with the whole matched pattern	     *s/\&*
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt*      For Vim version 7.0aa.  Last change: 2005 Feb 11
+*eval.txt*      For Vim version 7.0aa.  Last change: 2005 Feb 21
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1484,13 +1484,16 @@ matchstr( {expr}, {pat}[, {start}[, {cou
 				String	{count}'th match of {pat} in {expr}
 max({list})			Number	maximum value of items in {list}
 min({list})			Number	minumum value of items in {list}
+mkdir({name} [, {path} [, {prot}]])
+				Number	create directory {name}
 mode()				String	current editing mode
 nextnonblank( {lnum})		Number	line nr of non-blank line >= {lnum}
 nr2char( {expr})		String	single char with ASCII value {expr}
 prevnonblank( {lnum})		Number	line nr of non-blank line <= {lnum}
 range( {expr} [, {max} [, {stride}]])
 				List	items from {expr} to {max}
-readfile({fname} [, {binary}])	List	get list of lines from file {fname}
+readfile({fname} [, {binary} [, {max}]])
+				List	get list of lines from file {fname}
 remote_expr( {server}, {string} [, {idvar}])
 				String	send expression
 remote_foreground( {server})	Number	bring Vim server to the foreground
@@ -3099,6 +3102,19 @@ min({list})	Return the minumum value of 
 		be used as a Number this results in an error.
 		An empty List results in zero.
 
+							*mkdir()* *E749*
+mkdir({name} [, {path} [, {prot}]])
+		Create directory {name}.
+		If {path} is "p" then intermediate directories are created as
+		necessary.  Otherwise it must be "".
+		If {prot} is given it is used to set the protection bits of
+		the new directory.  The default is 0755 (rwxr-xr-x: r/w for
+		the user readable for others).  Use 0700 to make it unreadable
+		for others.
+		This function is not available in the |sandbox|.
+		Not available on all systems.  To check use: >
+			:if exists("*mkdir")
+<
 							*mode()*
 mode()		Return a string that indicates the current mode:
 			n	Normal
@@ -3158,7 +3174,7 @@ range({expr} [, {max} [, {stride}]])				
 			range(2, -2, -1) 	" [2, 1, 0, -1, -2]
 <
 							*readfile()*
-readfile({fname} [, {binary}])
+readfile({fname} [, {binary} [, {max}]])
 		Read file {fname} and return a List, each line of the file as
 		an item.  Lines broken at NL characters.  Macintosh files
 		separated with CR will result in a single long line (unless a
@@ -3171,9 +3187,16 @@ readfile({fname} [, {binary}])
 		- CR characters that appear before a NL are removed.
 		- Whether the last line ends in a NL or not does not matter.
 		All NUL characters are replaced with a NL character.
-		Note that the whole file is read into memory and there is no
-		recognition of encoding.  Read a file into a buffer if you
-		need to.
+		When {max} is given this specifies the maximum number of lines
+		to be read.  Useful if you only want to check the first ten
+		lines of a file: >
+			:for line in readfile(fname, '', 10)
+			:  if line =~ 'Date' | echo line | endif
+			:endfor
+<		When {max} is zero or negative the result is an empty list.
+		Note that without {max} the whole file is read into memory.
+		Also note that there is no recognition of encoding.  Read a
+		file into a buffer if you need to.
 		When the file can't be opened an error message is given and
 		the result is an empty list.
 		Also see |writefile()|.
@@ -3997,6 +4020,8 @@ extra_search		Compiled with support for 
 			|'hlsearch'|
 farsi			Compiled with Farsi support |farsi|.
 file_in_path		Compiled with support for |gf| and |<cfile>|
+filterpipe		When 'shelltemp' is off pipes are used for shell
+			read/write/filter commands
 find_in_path		Compiled with support for include file searches
 			|+find_in_path|.
 fname_case		Case in file names matters (for Amiga, MS-DOS, and
@@ -4374,7 +4399,7 @@ The file "~/vim/bufnetfuncs.vim" should 
 
 
 Using an autoload script ~
-
+							*autoload* *E746*
 Using a script in the "autoload" directory is simpler, but requires using
 exactly the right file name.  A function that can be autoloaded has a name
 like this: >
@@ -4404,9 +4429,24 @@ Vim will look for the file "autoload/foo
 The name before the first colon must be at least two characters long,
 otherwise it looks like a scope, such as "s:".
 
+This also works when reading a variable that has not been set yet: >
+
+	:let l = foo:bar:lvar
+
+When assigning a value to such a variable nothing special happens.  This can
+be used to pass settings to the autoload script before it's loaded: >
+
+	:let foo:bar:toggle = 1
+	:call foo:bar:func()
+
 Note that when you make a mistake and call a function that is supposed to be
 defined in an autoload script, but the script doesn't actually define the
 function, the script will be sourced every time you try to call the function.
+And you will get an error message every time.
+
+Also note that if you have two script files, and one calls a function in the
+other and vise versa, before the used function is defined, it won't work.
+Avoid using the autoload functionality at the toplevel.
 
 ==============================================================================
 6. Curly braces names					*curly-braces-names*
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.0aa.  Last change: 2005 Feb 10
+*options.txt*	For Vim version 7.0aa.  Last change: 2005 Feb 21
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1745,9 +1745,11 @@ A jump table for the options with a shor
 			enables cancelling the mapping by typing <F1><Esc>.
 								*cpo-l*
 		l	Backslash in a [] range in a search pattern is taken
-			literally, only "\]" is special  See |/[]|
+			literally, only "\]", "\^", "\-" and "\\" are special.
+			See |/[]|
 			   'l' included: "/[ \t]"  finds <Space>, '\' and 't'
 			   'l' excluded: "/[ \t]"  finds <Space> and <Tab>
+			Also see |cpo-\|.
 								*cpo-L*
 		L	When the 'list' option is set, 'wrapmargin',
 			'textwidth', 'softtabstop' and Virtual Replace mode
@@ -1895,17 +1897,31 @@ A jump table for the options with a shor
 	    contains	behavior	~
 			 					*cpo-#*
 		#	A count before "D", "o" and "O" has no effect.
+								*cpo-&*
+		&	When ":preserve" was used keep the swap file when
+			exiting normally while this buffer is still loaded.
+			This flag is tested when exiting.
+								*cpo-\*
+		\	Backslash in a [] range in a search pattern is taken
+			literally, only "\]" is special  See |/[]|
+			   'l' included: "/[ \t]"  finds <Space>, '\' and 't'
+			   'l' excluded: "/[ \t]"  finds <Space> and <Tab>
+			Also see |cpo-\|.
+								*cpo-/*
+		/	When "%" is used as the replacement string in a |:s|
+			command, use the previous replacement string. |:s%|
 								*cpo-{*
 		{	The |{| and |}| commands also stop at a "{" character
 			at the start of a line.
+								*cpo-.*
+		.	The ":chdir" and ":cd" commands fail if the current
+			buffer is modified, unless ! is used.  Vim doesn't
+			need this, since it remembers the full path of an
+			opened file.
 								*cpo-bar*
 		|	The value of the $LINES and $COLUMNS environment
 			variables overrule the terminal size values obtained
 			with system specific functions.
-								*cpo-&*
-		&	When ":preserve" was used keep the swap file when
-			exiting normally while this buffer is still loaded.
-			This flag is tested when exiting.
 
 
 						*'cscopepathcomp'* *'cspc'*
@@ -1972,6 +1988,9 @@ A jump table for the options with a shor
 	When set to "msg", error messages that would otherwise be omitted will
 	be given anyway.  This is useful when debugging 'foldexpr' or
 	'indentexpr'.
+	When set to "beep", a message will be given when otherwise only a beep
+	would be produced.
+	The values can be combined, separated by a comma.
 
 						*'define'* *'def'*
 'define' 'def'		string	(default "^\s*#\s*define")
@@ -4708,6 +4727,11 @@ A jump table for the options with a shor
 	List of items that control the format of the output of |:hardcopy|.
 	See |popt-option|.
 
+						*'prompt'* *'noprompt'*
+'prompt'		boolean	(default on)
+			global
+	When on a ":" prompt is used in Ex mode.
+
 						*'quoteescape'* *'qe'*
 'quoteescape' 'qe'	string	(default "\")
 			local to buffer
@@ -5239,6 +5263,22 @@ A jump table for the options with a shor
 	separator.  To test if this is so use: >
 		if exists('+shellslash')
 <
+			*'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'*
+'shelltemp' 'stmp'	boolean	(Vi default off, Vim default on)
+			global
+			{not in Vi}
+	When on, use temp files for shell commands.  When off use a pipe.
+	When using a pipe is not possible temp files are used anyway.
+	Currently a pipe is only supported on Unix.  You can check it with: >
+		:if has("filterpipe")
+<	The advantage of using a pipe is that nobody can read the temp file
+	and the 'shell' command does not need to support redirection.
+	The advantage of using a temp file is that the file type and encoding
+	can be detected.
+	The |FilterReadPre|, |FilterReadPost| and |FilterWritePre|,
+	|FilterWritePost| autocommands event are not triggered when
+	'shelltemp' is off.
+
 						*'shelltype'* *'st'*
 'shelltype' 'st'	number	(default 0)
 			global
@@ -5288,7 +5328,8 @@ A jump table for the options with a shor
 	|'cindent'|, |>>|, |<<|, etc.
 
 						*'shortmess'* *'shm'*
-'shortmess' 'shm'	string	(Vim default "filnxtToO", Vi default: "")
+'shortmess' 'shm'	string	(Vim default "filnxtToO", Vi default: "",
+							POSIX default: "A")
 			global
 			{not in Vi}
 	This option helps to avoid all the |hit-enter| prompts caused by file
--- a/runtime/doc/pattern.txt
+++ b/runtime/doc/pattern.txt
@@ -1,4 +1,4 @@
-*pattern.txt*   For Vim version 7.0aa.  Last change: 2005 Jan 26
+*pattern.txt*   For Vim version 7.0aa.  Last change: 2005 Feb 20
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -522,11 +522,6 @@ An atom can be followed by an indication
 matched and in what way.  This is called a multi.  See |/multi| for an
 overview.
 
-It is not possible to use a multi that can match more than one time after an
-atom that can match an empty string.  That's because this could result in an
-endless loop.  If you try it, you will get this error message: >
-	*, \+ or \{ operand could be empty
-<
 						*/star* */\star* *E56*
 *	(use \* when 'magic' is not set)
 	Matches 0 or more of the preceding atom, as many as possible.
@@ -577,7 +572,7 @@ endless loop.  If you try it, you will g
 \{-}	matches 0 or more of the preceding atom, as few as possible
 	{Vi does not have any of these}
 
-	n and m are positive decimal numbers
+	n and m are positive decimal numbers or zero
 
 	If a "-" appears immediately after the "{", then a shortest match
 	first algorithm is used (see example below).  In particular, "\{-}" is
@@ -982,6 +977,17 @@ x	A single character, with no special me
 	  a list of at least one character, each of which is either '-', '.',
 	  '/', alphabetic, numeric, '_' or '~'.
 	  These items only work for 8-bit characters.
+							*/[[=* *[==]*
+	- An equivalence class.  This means that characters are matched that
+	  have almost the same meaning, e.g., when ignoring accents.  The form
+	  is:
+	  	[=a=]
+	  Currrently this is only implemented for latin1.  Also works for the
+	  latin1 characters in utf-8 and latin9.
+							*/[[.* *[..]*
+	- A collation element.  This currently simply accepts a single
+	  character in the form:
+	  	[.a.]
 							  */\]*
 	- To include a literal ']', '^', '-' or '\' in the collection, put a
 	  backslash before it: "[xyz\]]", "[\^xyz]", "[xy\-z]" and "[xyz\\]".
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -1,4 +1,4 @@
-*repeat.txt*    For Vim version 7.0aa.  Last change: 2005 Jan 28
+*repeat.txt*    For Vim version 7.0aa.  Last change: 2005 Feb 19
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -81,6 +81,11 @@ This replaces all occurrences of "pat" w
 	:%s/pat/PAT/g
 Which is two characters shorter!
 
+A special case is using ":visual" as a command.  This will move to a matching
+line, go to Normal mode to let you execute commands there until you use |Q| to
+return to Ex mode.  This will be repeated for each matching line.  While doing
+this you cannot use ":global".
+
 ==============================================================================
 3. Complex repeats					*complex-repeat*
 
@@ -102,7 +107,7 @@ q			Stops recording.  (Implementation no
 			expression.  The result of the expression is then
 			executed.  See also |@:|.  {Vi: only named registers}
 
-							*@@*
+							*@@* *E748*
 @@			Repeat the previous @{0-9a-z":*} [count] times.
 
 :[addr]*{0-9a-z".=}						*:@* *:star*
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -1,4 +1,4 @@
-*starting.txt*  For Vim version 7.0aa.  Last change: 2005 Feb 10
+*starting.txt*  For Vim version 7.0aa.  Last change: 2005 Feb 19
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -263,8 +263,14 @@ a slash.  Thus "-R" means recovery and "
 		To be used when Vim is used to execute Ex commands from a file
 		instead of a terminal.  Switches off most prompts and
 		informative messages.  Also warnings and error messages.
-		But ":print" output is displayed.  And when 'verbose' is
-		non-zero messages are printed (for debugging).
+		The output of these commands is displayed (to stdout):
+			:print
+			:list
+			:number
+			:set      to display option values.
+		When 'verbose' is non-zero messages are printed (for
+		debugging, to stderr).
+		'term' and $TERM are not used.
 		If Vim appears to be stuck try typing "qa!<Enter>".  You don't
 		get a prompt thus you can't see Vim is waiting for you to type
 		something.
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -506,6 +506,7 @@
 'nopi'	options.txt	/*'nopi'*
 'nopreserveindent'	options.txt	/*'nopreserveindent'*
 'nopreviewwindow'	options.txt	/*'nopreviewwindow'*
+'noprompt'	options.txt	/*'noprompt'*
 'nopvw'	options.txt	/*'nopvw'*
 'noreadonly'	options.txt	/*'noreadonly'*
 'noremap'	options.txt	/*'noremap'*
@@ -528,6 +529,7 @@
 'nosecure'	options.txt	/*'nosecure'*
 'nosft'	options.txt	/*'nosft'*
 'noshellslash'	options.txt	/*'noshellslash'*
+'noshelltemp'	options.txt	/*'noshelltemp'*
 'noshiftround'	options.txt	/*'noshiftround'*
 'noshortname'	options.txt	/*'noshortname'*
 'noshowcmd'	options.txt	/*'noshowcmd'*
@@ -549,6 +551,7 @@
 'nossl'	options.txt	/*'nossl'*
 'nosta'	options.txt	/*'nosta'*
 'nostartofline'	options.txt	/*'nostartofline'*
+'nostmp'	options.txt	/*'nostmp'*
 'noswapfile'	options.txt	/*'noswapfile'*
 'noswf'	options.txt	/*'noswf'*
 'nota'	options.txt	/*'nota'*
@@ -633,7 +636,7 @@
 'printmbcharset'	options.txt	/*'printmbcharset'*
 'printmbfont'	options.txt	/*'printmbfont'*
 'printoptions'	options.txt	/*'printoptions'*
-'prompt'	vi_diff.txt	/*'prompt'*
+'prompt'	options.txt	/*'prompt'*
 'pt'	options.txt	/*'pt'*
 'pvh'	options.txt	/*'pvh'*
 'pvw'	options.txt	/*'pvw'*
@@ -687,6 +690,7 @@
 'shellquote'	options.txt	/*'shellquote'*
 'shellredir'	options.txt	/*'shellredir'*
 'shellslash'	options.txt	/*'shellslash'*
+'shelltemp'	options.txt	/*'shelltemp'*
 'shelltype'	options.txt	/*'shelltype'*
 'shellxquote'	options.txt	/*'shellxquote'*
 'shiftround'	options.txt	/*'shiftround'*
@@ -732,6 +736,7 @@
 'startofline'	options.txt	/*'startofline'*
 'statusline'	options.txt	/*'statusline'*
 'stl'	options.txt	/*'stl'*
+'stmp'	options.txt	/*'stmp'*
 'sts'	options.txt	/*'sts'*
 'su'	options.txt	/*'su'*
 'sua'	options.txt	/*'sua'*
@@ -1213,6 +1218,8 @@
 /.	pattern.txt	/*\/.*
 //;	pattern.txt	/*\/\/;*
 /<CR>	pattern.txt	/*\/<CR>*
+/[[.	pattern.txt	/*\/[[.*
+/[[=	pattern.txt	/*\/[[=*
 /[]	pattern.txt	/*\/[]*
 /\	pattern.txt	/*\/\\*
 /\$	pattern.txt	/*\/\\$*
@@ -1848,7 +1855,7 @@ 90.5	usr_90.txt	/*90.5*
 :display	change.txt	/*:display*
 :dj	tagsrch.txt	/*:dj*
 :djump	tagsrch.txt	/*:djump*
-:dl	tagsrch.txt	/*:dl*
+:dli	tagsrch.txt	/*:dli*
 :dlist	tagsrch.txt	/*:dlist*
 :do	autocmd.txt	/*:do*
 :doau	autocmd.txt	/*:doau*
@@ -2280,6 +2287,7 @@ 90.5	usr_90.txt	/*90.5*
 :rv	starting.txt	/*:rv*
 :rviminfo	starting.txt	/*:rviminfo*
 :s	change.txt	/*:s*
+:s%	change.txt	/*:s%*
 :sN	windows.txt	/*:sN*
 :sNext	windows.txt	/*:sNext*
 :s\=	change.txt	/*:s\\=*
@@ -2840,6 +2848,7 @@ CTRL-M	motion.txt	/*CTRL-M*
 CTRL-N	motion.txt	/*CTRL-N*
 CTRL-O	motion.txt	/*CTRL-O*
 CTRL-P	motion.txt	/*CTRL-P*
+CTRL-Q	gui_w32.txt	/*CTRL-Q*
 CTRL-R	undo.txt	/*CTRL-R*
 CTRL-T	tagsrch.txt	/*CTRL-T*
 CTRL-U	scroll.txt	/*CTRL-U*
@@ -3653,6 +3662,10 @@ E742	eval.txt	/*E742*
 E743	eval.txt	/*E743*
 E744	netbeans.txt	/*E744*
 E745	eval.txt	/*E745*
+E746	eval.txt	/*E746*
+E747	syntax.txt	/*E747*
+E748	repeat.txt	/*E748*
+E749	eval.txt	/*E749*
 E75	vi_diff.txt	/*E75*
 E76	pattern.txt	/*E76*
 E77	message.txt	/*E77*
@@ -3922,6 +3935,7 @@ ZZ	editing.txt	/*ZZ*
 [(	motion.txt	/*[(*
 [++opt]	editing.txt	/*[++opt]*
 [+cmd]	editing.txt	/*[+cmd]*
+[..]	pattern.txt	/*[..]*
 [/	motion.txt	/*[\/*
 [:alnum:]	pattern.txt	/*[:alnum:]*
 [:alpha:]	pattern.txt	/*[:alpha:]*
@@ -3940,6 +3954,7 @@ ZZ	editing.txt	/*ZZ*
 [:upper:]	pattern.txt	/*[:upper:]*
 [:xdigit:]	pattern.txt	/*[:xdigit:]*
 [<MiddleMouse>	change.txt	/*[<MiddleMouse>*
+[==]	pattern.txt	/*[==]*
 [D	tagsrch.txt	/*[D*
 [I	tagsrch.txt	/*[I*
 [M	motion.txt	/*[M*
@@ -4121,6 +4136,7 @@ autocmds-kept	version5.txt	/*autocmds-ke
 autocommand	autocmd.txt	/*autocommand*
 autocommand-events	autocmd.txt	/*autocommand-events*
 autocommand-pattern	autocmd.txt	/*autocommand-pattern*
+autoload	eval.txt	/*autoload*
 autoload-functions	eval.txt	/*autoload-functions*
 avoid-hit-enter	version5.txt	/*avoid-hit-enter*
 aw	motion.txt	/*aw*
@@ -4385,6 +4401,8 @@ cpo-%	options.txt	/*cpo-%*
 cpo-&	options.txt	/*cpo-&*
 cpo-+	options.txt	/*cpo-+*
 cpo--	options.txt	/*cpo--*
+cpo-.	options.txt	/*cpo-.*
+cpo-/	options.txt	/*cpo-\/*
 cpo-<	options.txt	/*cpo-<*
 cpo->	options.txt	/*cpo->*
 cpo-A	options.txt	/*cpo-A*
@@ -4404,6 +4422,8 @@ cpo-R	options.txt	/*cpo-R*
 cpo-S	options.txt	/*cpo-S*
 cpo-W	options.txt	/*cpo-W*
 cpo-X	options.txt	/*cpo-X*
+cpo-Z	options.txt	/*cpo-Z*
+cpo-\	options.txt	/*cpo-\\*
 cpo-a	options.txt	/*cpo-a*
 cpo-b	options.txt	/*cpo-b*
 cpo-bar	options.txt	/*cpo-bar*
@@ -4655,6 +4675,7 @@ evim.vim	starting.txt	/*evim.vim*
 ex	starting.txt	/*ex*
 ex-cmd-index	index.txt	/*ex-cmd-index*
 ex-edit-index	index.txt	/*ex-edit-index*
+ex-flags	cmdline.txt	/*ex-flags*
 ex:	options.txt	/*ex:*
 except-autocmd	eval.txt	/*except-autocmd*
 except-autocmd-Cmd	eval.txt	/*except-autocmd-Cmd*
@@ -5048,7 +5069,6 @@ hebrew	hebrew.txt	/*hebrew*
 hebrew.txt	hebrew.txt	/*hebrew.txt*
 help	various.txt	/*help*
 help-context	help.txt	/*help-context*
-help-tags	tags	1
 help-translated	various.txt	/*help-translated*
 help-xterm-window	various.txt	/*help-xterm-window*
 help.txt	help.txt	/*help.txt*
@@ -5503,8 +5523,8 @@ messages	message.txt	/*messages*
 meta	intro.txt	/*meta*
 min()	eval.txt	/*min()*
 minimal-features	os_msdos.txt	/*minimal-features*
-missing-commands	vi_diff.txt	/*missing-commands*
 missing-options	vi_diff.txt	/*missing-options*
+mkdir()	eval.txt	/*mkdir()*
 mlang.txt	mlang.txt	/*mlang.txt*
 mode()	eval.txt	/*mode()*
 mode-Ex	intro.txt	/*mode-Ex*
@@ -6132,6 +6152,7 @@ sign.txt	sign.txt	/*sign.txt*
 signs	sign.txt	/*signs*
 simple-change	change.txt	/*simple-change*
 simplify()	eval.txt	/*simplify()*
+simulated-command	vi_diff.txt	/*simulated-command*
 single-repeat	repeat.txt	/*single-repeat*
 skeleton	autocmd.txt	/*skeleton*
 slow-fast-terminal	term.txt	/*slow-fast-terminal*
@@ -6206,6 +6227,7 @@ swap-file	recover.txt	/*swap-file*
 swapfile-changed	version4.txt	/*swapfile-changed*
 syn-sync-grouphere	syntax.txt	/*syn-sync-grouphere*
 syn-sync-groupthere	syntax.txt	/*syn-sync-groupthere*
+syn-sync-linecont	syntax.txt	/*syn-sync-linecont*
 synID()	eval.txt	/*synID()*
 synIDattr()	eval.txt	/*synIDattr()*
 synIDtrans()	eval.txt	/*synIDtrans()*
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -1,4 +1,4 @@
-*windows.txt*   For Vim version 7.0aa.  Last change: 2005 Jan 26
+*windows.txt*   For Vim version 7.0aa.  Last change: 2005 Feb 18
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -587,7 +587,7 @@ can also get to them with the buffer lis
 		not split.  Also see |++opt| and |+cmd|.
 
 						*:sfir* *:sfirst*
-:sfir[st [++opt] [+cmd]
+:sfir[st] [++opt] [+cmd]
 		Same as ":srewind".
 
 						*:sla* *:slast*
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
 " Vim support file to detect file types
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2005 Jan 27
+" Last Change:	2005 Feb 18
 
 " Listen very carefully, I will say this only once
 if exists("did_load_filetypes")
@@ -512,6 +512,9 @@ au BufNewFile,BufRead *.erl			setf erlan
 " Elm Filter Rules file
 au BufNewFile,BufRead filter-rules		setf elmfilt
 
+" ESMTP rc file
+au BufNewFile,BufRead *esmtprc			setf esmtprc
+
 " ESQL-C
 au BufNewFile,BufRead *.ec,*.EC			setf esqlc
 
--- a/runtime/ftplugin/vim.vim
+++ b/runtime/ftplugin/vim.vim
@@ -1,7 +1,7 @@
 " Vim filetype plugin
 " Language:	Vim
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2004 Sep 13
+" Last Change:	2005 Feb 14
 
 " Only do this when not done yet for this buffer
 if exists("b:did_ftplugin")
@@ -58,4 +58,6 @@ if exists("loaded_matchit")
 endif
 
 let &cpo = cpo_save
-setlocal cpo+=M		" makes \%( match \)
+
+" removed this, because 'cpoptions' is a global option.
+" setlocal cpo+=M		" makes \%( match \)
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -681,16 +681,29 @@ getcmdline(firstc, count, indent)
 	if (c == '\n' || c == '\r' || c == K_KENTER || (c == ESC
 			&& (!KeyTyped || vim_strchr(p_cpo, CPO_ESC) != NULL)))
 	{
-	    gotesc = FALSE;	/* Might have typed ESC previously, don't
-				   truncate the cmdline now. */
-	    if (ccheck_abbr(c + ABBR_OFF))
-		goto cmdline_changed;
-	    if (!cmd_silent)
+	    /* In Ex mode a backslash escapes a newline. */
+	    if (exmode_active
+		    && c != ESC
+		    && ccline.cmdpos > 0
+		    && ccline.cmdpos == ccline.cmdlen
+		    && ccline.cmdbuff[ccline.cmdpos - 1] == '\\')
+	    {
+		if (c == K_KENTER)
+		    c = '\n';
+	    }
+	    else
 	    {
-		windgoto(msg_row, 0);
-		out_flush();
+		gotesc = FALSE;	/* Might have typed ESC previously, don't
+				       truncate the cmdline now. */
+		if (ccheck_abbr(c + ABBR_OFF))
+		    goto cmdline_changed;
+		if (!cmd_silent)
+		{
+		    windgoto(msg_row, 0);
+		    out_flush();
+		}
+		break;
 	    }
-	    break;
 	}
 
 	/*
@@ -1879,25 +1892,24 @@ getexline(c, dummy, indent)
  * Get an Ex command line for Ex mode.
  * In Ex mode we only use the OS supplied line editing features and no
  * mappings or abbreviations.
+ * Returns a string in allocated memory or NULL.
  */
 /* ARGSUSED */
     char_u *
-getexmodeline(c, dummy, indent)
-    int		c;		/* normally ':', NUL for ":append" */
+getexmodeline(promptc, dummy, indent)
+    int		promptc;	/* normally ':', NUL for ":append" and '?' for
+				   :s prompt */
     void	*dummy;		/* cookie not used */
     int		indent;		/* indent for inside conditionals */
 {
-    garray_T		line_ga;
-    int			len;
-    int			off = 0;
-    char_u		*pend;
-    int			finished = FALSE;
-#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
-    int			startcol = 0;
-    int			c1;
-    int			escaped = FALSE;	/* CTRL-V typed */
-    int			vcol = 0;
-#endif
+    garray_T	line_ga;
+    char_u	*pend;
+    int		startcol = 0;
+    int		c1;
+    int		escaped = FALSE;	/* CTRL-V typed */
+    int		vcol = 0;
+    char_u	*p;
+    int		prev_char = 0;
 
     /* Switch cursor on now.  This avoids that it happens after the "\n", which
      * confuses the system function that computes tabstops. */
@@ -1905,27 +1917,24 @@ getexmodeline(c, dummy, indent)
 
     /* always start in column 0; write a newline if necessary */
     compute_cmdrow();
-    if (msg_col)
+    if ((msg_col || msg_didout) && promptc != '?')
 	msg_putchar('\n');
-    if (c == ':')
+    if (promptc == ':')
     {
 	/* indent that is only displayed, not in the line itself */
-	msg_putchar(':');
+	if (p_prompt)
+	    msg_putchar(':');
 	while (indent-- > 0)
 	    msg_putchar(' ');
-#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
 	startcol = msg_col;
-#endif
     }
 
     ga_init2(&line_ga, 1, 30);
 
     /* autoindent for :insert and :append is in the line itself */
-    if (c <= 0)
+    if (promptc <= 0)
     {
-#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
 	vcol = indent;
-#endif
 	while (indent >= 8)
 	{
 	    ga_append(&line_ga, TAB);
@@ -1938,198 +1947,180 @@ getexmodeline(c, dummy, indent)
 	    msg_putchar(' ');
 	}
     }
+    ++no_mapping;
+    ++allow_keys;
 
     /*
      * Get the line, one character at a time.
      */
     got_int = FALSE;
-    while (!got_int && !finished)
+    while (!got_int)
     {
 	if (ga_grow(&line_ga, 40) == FAIL)
 	    break;
 	pend = (char_u *)line_ga.ga_data + line_ga.ga_len;
 
-	/* Get one character (inchar gets a third of maxlen characters!) */
-	len = inchar(pend + off, 3, -1L, 0);
-	if (len < 0)
-	    continue;	    /* end of input script reached */
-	/* for a special character, we need at least three characters */
-	if ((*pend == K_SPECIAL || *pend == CSI) && off + len < 3)
-	{
-	    off += len;
-	    continue;
-	}
-	len += off;
-	off = 0;
+	/* Get one character at a time.  Don't use inchar(), it can't handle
+	 * special characters. */
+	c1 = vgetc();
 
 	/*
-	 * When using the GUI, and for systems that don't have cooked input,
-	 * handle line editing here.
+	 * Handle line editing.
+	 * Previously this was left to the system, putting the terminal in
+	 * cooked mode, but then CTRL-D and CTRL-T can't be used properly.
 	 */
-#if defined(FEAT_GUI) || defined(NO_COOKED_INPUT)
-# ifndef NO_COOKED_INPUT
-	if (gui.in_use)
-# endif
+	if (got_int)
+	{
+	    msg_putchar('\n');
+	    break;
+	}
+
+	if (!escaped)
 	{
-	    if (got_int)
+	    /* CR typed means "enter", which is NL */
+	    if (c1 == '\r')
+		c1 = '\n';
+
+	    if (c1 == BS || c1 == K_BS
+			  || c1 == DEL || c1 == K_DEL || c1 == K_KDEL)
 	    {
-		msg_putchar('\n');
-		break;
+		if (line_ga.ga_len > 0)
+		{
+		    --line_ga.ga_len;
+		    goto redraw;
+		}
+		continue;
 	    }
 
-	    while (len > 0)
+	    if (c1 == Ctrl_U)
 	    {
-		c1 = *pend++;
-		--len;
-		if ((c1 == K_SPECIAL
-#  if !defined(NO_COOKED_INPUT) || defined(FEAT_GUI)
-			    || c1 == CSI
-#  endif
-		    ) && len >= 2)
+		msg_col = startcol;
+		msg_clr_eos();
+		line_ga.ga_len = 0;
+		continue;
+	    }
+
+	    if (c1 == Ctrl_T)
+	    {
+		p = (char_u *)line_ga.ga_data;
+		p[line_ga.ga_len] = NUL;
+		indent = get_indent_str(p, 8);
+		indent += curbuf->b_p_sw - indent % curbuf->b_p_sw;
+add_indent:
+		while (get_indent_str(p, 8) < indent)
 		{
-		    c1 = TO_SPECIAL(pend[0], pend[1]);
-		    pend += 2;
-		    len -= 2;
+		    char_u *s = skipwhite(p);
+
+		    ga_grow(&line_ga, 1);
+		    mch_memmove(s + 1, s, line_ga.ga_len - (s - p) + 1);
+		    *s = ' ';
+		    ++line_ga.ga_len;
 		}
-
-		if (!escaped)
+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)
 		{
-		    /* CR typed means "enter", which is NL */
-		    if (c1 == '\r')
-			c1 = '\n';
-
-		    if (c1 == BS || c1 == K_BS
-				  || c1 == DEL || c1 == K_DEL || c1 == K_KDEL)
+		    if (*p == TAB)
 		    {
-			if (line_ga.ga_len > 0)
+			do
 			{
-			    int		i, v;
-			    char_u	*q;
-
-			    --line_ga.ga_len;
-			    /* compute column that cursor should be in */
-			    v = 0;
-			    q = ((char_u *)line_ga.ga_data);
-			    for (i = 0; i < line_ga.ga_len; ++i)
-			    {
-				if (*q == TAB)
-				    v += 8 - v % 8;
-				else
-				    v += ptr2cells(q);
-				++q;
-			    }
-			    /* erase characters to position cursor */
-			    while (vcol > v)
-			    {
-				msg_putchar('\b');
-				msg_putchar(' ');
-				msg_putchar('\b');
-				--vcol;
-			    }
-			}
-			continue;
+			    msg_putchar(' ');
+			} while (++vcol % 8);
 		    }
-
-		    if (c1 == Ctrl_U)
-		    {
-			msg_col = startcol;
-			msg_clr_eos();
-			line_ga.ga_len = 0;
-			continue;
-		    }
-
-		    if (c1 == Ctrl_T)
-			c1 = TAB;	/* very simplistic... */
-
-		    if (c1 == Ctrl_D)
+		    else
 		    {
-			char_u	*p;
-
-			/* Delete one shiftwidth. */
-			p = (char_u *)line_ga.ga_data;
-			p[line_ga.ga_len] = NUL;
-			indent = get_indent_str(p, 8);
-			--indent;
-			indent -= indent % 8;
-			while (get_indent_str(p, 8) > indent)
-			{
-			    char_u *s = skipwhite(p);
-
-			    mch_memmove(s - 1, s, line_ga.ga_len - (s - p) + 1);
-			    --line_ga.ga_len;
-			}
-			msg_col = startcol;
-			for (vcol = 0; *p != NUL; ++p)
-			{
-			    if (*p == TAB)
-			    {
-				do
-				{
-				    msg_putchar(' ');
-				} while (++vcol % 8);
-			    }
-			    else
-			    {
-				msg_outtrans_len(p, 1);
-				vcol += char2cells(*p);
-			    }
-			}
-			msg_clr_eos();
-			continue;
-		    }
-
-		    if (c1 == Ctrl_V)
-		    {
-			escaped = TRUE;
-			continue;
+			msg_outtrans_len(p, 1);
+			vcol += char2cells(*p);
 		    }
 		}
-
-		if (IS_SPECIAL(c1))
-		    c1 = '?';
-		((char_u *)line_ga.ga_data)[line_ga.ga_len] = c1;
-		if (c1 == '\n')
-		    msg_putchar('\n');
-		else if (c1 == TAB)
+		msg_clr_eos();
+		continue;
+	    }
+
+	    if (c1 == Ctrl_D)
+	    {
+		/* Delete one shiftwidth. */
+		p = (char_u *)line_ga.ga_data;
+		if (prev_char == '0' || prev_char == '^')
 		{
-		    /* Don't use chartabsize(), 'ts' can be different */
-		    do
-		    {
-			msg_putchar(' ');
-		    } while (++vcol % 8);
+		    if (prev_char == '^')
+			ex_keep_indent = TRUE;
+		    indent = 0;
+		    p[--line_ga.ga_len] = NUL;
 		}
 		else
 		{
-		    msg_outtrans_len(
-			     ((char_u *)line_ga.ga_data) + line_ga.ga_len, 1);
-		    vcol += char2cells(c1);
+		    p[line_ga.ga_len] = NUL;
+		    indent = get_indent_str(p, 8);
+		    --indent;
+		    indent -= indent % curbuf->b_p_sw;
+		}
+		while (get_indent_str(p, 8) > indent)
+		{
+		    char_u *s = skipwhite(p);
+
+		    mch_memmove(s - 1, s, line_ga.ga_len - (s - p) + 1);
+		    --line_ga.ga_len;
 		}
-		++line_ga.ga_len;
-		escaped = FALSE;
+		goto add_indent;
+	    }
+
+	    if (c1 == Ctrl_V || c1 == Ctrl_Q)
+	    {
+		escaped = TRUE;
+		continue;
 	    }
-	    windgoto(msg_row, msg_col);
+
+	    /* Ignore special key codes: mouse movement, K_IGNORE, etc. */
+	    if (IS_SPECIAL(c1))
+		continue;
 	}
-# ifndef NO_COOKED_INPUT
+
+	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)
+	{
+	    /* Don't use chartabsize(), 'ts' can be different */
+	    do
+	    {
+		msg_putchar(' ');
+	    } while (++vcol % 8);
+	}
 	else
-# endif
-#endif
-#ifndef NO_COOKED_INPUT
 	{
-	    line_ga.ga_len += len;
+	    msg_outtrans_len(
+		     ((char_u *)line_ga.ga_data) + line_ga.ga_len, 1);
+	    vcol += char2cells(c1);
 	}
-#endif
+	++line_ga.ga_len;
+	escaped = FALSE;
+
+	windgoto(msg_row, msg_col);
 	pend = (char_u *)(line_ga.ga_data) + line_ga.ga_len;
-	if (line_ga.ga_len && pend[-1] == '\n')
+
+	/* we are done when a NL is entered, but not when it comes after a
+	 * backslash */
+	if (line_ga.ga_len > 0 && pend[-1] == '\n'
+		&& (line_ga.ga_len <= 1 || pend[-2] != '\\'))
 	{
-	    finished = TRUE;
 	    --line_ga.ga_len;
 	    --pend;
 	    *pend = NUL;
+	    break;
 	}
     }
 
-    /* note that cursor has moved, because of the echoed <CR> */
-    screen_down();
+    --no_mapping;
+    --allow_keys;
+
     /* make following messages go to the next line */
     msg_didout = FALSE;
     msg_col = 0;
@@ -3797,10 +3788,10 @@ addstar(fname, len, context)
 set_expand_context(xp)
     expand_T	*xp;
 {
-    /* only expansion for ':' and '>' commands */
+    /* only expansion for ':', '>' and '=' command-lines */
     if (ccline.cmdfirstc != ':'
 #ifdef FEAT_EVAL
-	    && ccline.cmdfirstc != '>'
+	    && ccline.cmdfirstc != '>' && ccline.cmdfirstc != '='
 #endif
 	    )
     {
@@ -3828,8 +3819,16 @@ set_cmd_context(xp, str, len, col)
 	old_char = str[col];
     str[col] = NUL;
     nextcomm = str;
-    while (nextcomm != NULL)
-	nextcomm = set_one_cmd_context(xp, nextcomm);
+
+#ifdef FEAT_EVAL
+    if (ccline.cmdfirstc == '=')
+	/* pass CMD_SIZE because there is no real command */
+	set_context_for_expression(xp, str, CMD_SIZE);
+    else
+#endif
+	while (nextcomm != NULL)
+	    nextcomm = set_one_cmd_context(xp, nextcomm);
+
     str[col] = old_char;
 }
 
@@ -5477,7 +5476,7 @@ ex_window()
      * Call the main loop until <CR> or CTRL-C is typed.
      */
     cmdwin_result = 0;
-    main_loop(TRUE);
+    main_loop(TRUE, FALSE);
 
     RedrawingDisabled = i;
 
--- a/src/gui_mac.c
+++ b/src/gui_mac.c
@@ -91,6 +91,19 @@ static    OSType	_ftype = 'TEXT';
 static EventHandlerUPP mouseWheelHandlerUPP = NULL;
 #endif
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+# define USE_CARBONKEYHANDLER
+static EventHandlerUPP keyEventHandlerUPP = NULL;
+/* Defined in os_mac_conv.c */
+extern char_u *mac_utf16_to_enc __ARGS((UniChar *from, size_t fromLen, size_t *actualLen));
+extern UniChar *mac_enc_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen));
+extern CFStringRef mac_enc_to_cfstring __ARGS((char_u *from, size_t fromLen));
+#endif
+
+#ifdef MACOS_X
+SInt32 gMacSystemVersion;
+#endif
+
 /* Debugging feature: start Vim window OFFSETed */
 #undef USE_OFFSETED_WINDOW
 
@@ -213,6 +226,12 @@ static struct
 } gFontPanelInfo = { 0, 0, 0, false };
 #endif
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+# define USE_ATSUI_DRAWING
+ATSUStyle   gFontStyle;
+Boolean	    gIsFontFallbackSet;
+#endif
+
 /*
  * The Quickdraw global is predefined in CodeWarior
  * but is not in Apple MPW
@@ -504,6 +523,63 @@ points_to_pixels(char_u *str, char_u **e
     return pixels;
 }
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+/*
+ * Deletes all traces of any Windows-style mnemonic text (including any
+ * parentheses) from a menu item and returns the cleaned menu item title.
+ * The caller is responsible for releasing the returned string.
+ */
+    static CFStringRef
+menu_title_removing_mnemonic(menu)
+    vimmenu_T	*menu;
+{
+    CFStringRef		name;
+    size_t		menuTitleLen;
+    CFIndex		displayLen;
+    CFRange		mnemonicStart;
+    CFRange		mnemonicEnd;
+    CFMutableStringRef	cleanedName;
+
+    menuTitleLen = STRLEN(menu->dname);
+    name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
+
+    if (name)
+    {
+	/* Simple mnemonic-removal algorithm, assumes single parenthesized
+	 * mnemonic character towards the end of the menu text */
+	mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
+	displayLen = CFStringGetLength(name);
+
+	if (mnemonicStart.location != kCFNotFound
+		&& (mnemonicStart.location + 2) < displayLen
+		&& CFStringGetCharacterAtIndex(name,
+		       mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
+	{
+	    if (CFStringFindWithOptions(name, CFSTR(")"),
+			CFRangeMake(mnemonicStart.location + 1,
+			    displayLen - mnemonicStart.location - 1),
+			kCFCompareBackwards, &mnemonicEnd) &&
+		    (mnemonicStart.location + 2) == mnemonicEnd.location)
+	    {
+		cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
+		if (cleanedName)
+		{
+		    CFStringDelete(cleanedName,
+			    CFRangeMake(mnemonicStart.location,
+				mnemonicEnd.location + 1 -
+				mnemonicStart.location));
+
+		    CFRelease(name);
+		    name = cleanedName;
+		}
+	    }
+	}
+    }
+
+    return name;
+}
+#endif
+
 /*
  * Convert a list of FSSpec aliases into a list of fullpathname
  * character strings.
@@ -1231,20 +1307,19 @@ HandleODocAE(const AppleEvent *theAEvent
     /* Select the text if possible */
     if (gotPosition)
     {
-        VIsual_active = TRUE;
-        VIsual_select = FALSE;
-        if (thePosition.lineNum < 0)
+	VIsual_active = TRUE;
+	VIsual_select = FALSE;
+	VIsual = curwin->w_cursor;
+	if (thePosition.lineNum < 0)
 	{
-            VIsual_mode = 'v';
-            VIsual = curwin->w_cursor;
-            goto_byte(thePosition.endRange);
-        }
-        else
+	    VIsual_mode = 'v';
+	    goto_byte(thePosition.endRange);
+	}
+	else
 	{
-            VIsual_mode = 'V';
-            VIsual = curwin->w_cursor;
-            VIsual.col = 0;
-        }
+	    VIsual_mode = 'V';
+	    VIsual.col = 0;
+	}
     }
 #endif
     setcursor();
@@ -1541,25 +1616,47 @@ InstallFontPanelHandler()
  * Fill the buffer pointed to by outName with the name and size
  * of the font currently selected in the Font Panel.
  */
+#define FONT_STYLE_BUFFER_SIZE 32
     static void
 GetFontPanelSelection(char_u* outName)
 {
-    Str255 buf;
-    Boolean isBold = false, isItalic = false;
+    Str255	    buf;
+    ByteCount	    fontNameLen = 0;
+    ATSUFontID	    fid;
+    char_u	    styleString[FONT_STYLE_BUFFER_SIZE];
 
     if (!outName)
 	return;
 
-    (void)FMGetFontFamilyName(gFontPanelInfo.family, buf);
-    p2cstrcpy(outName, buf);
-
-#if 0 /* TODO: enable when styles are supported in gui_mac_find_font() */
-    isBold = (gFontPanelInfo.style & bold);
-    isItalic = (gFontPanelInfo.style & italic);
-#endif
-
-    sprintf(&outName[buf[0]], ":h%d%s%s", gFontPanelInfo.size,
-	    (isBold ? ":b" : ""), (isItalic ? ":i" : ""));
+    if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
+    {
+	/* Canonicalize localized font names */
+	if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
+		    gFontPanelInfo.style, &fid, NULL) != noErr)
+	    return;
+
+	/* Request font name with Mac encoding (otherwise we could
+	 * get an unwanted utf-16 name) */
+	if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
+		    kFontNoScriptCode, kFontNoLanguageCode,
+		    255, outName, &fontNameLen, NULL) != noErr)
+	    return;
+
+	/* Only encode font size, because style (bold, italic, etc) is
+	 * already part of the font full name */
+	snprintf(styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
+		gFontPanelInfo.size/*,
+		((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
+		((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
+		((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
+
+	if ((fontNameLen + STRLEN(styleString)) < 255)
+	    STRCPY(outName + fontNameLen, styleString);
+    }
+    else
+    {
+	*outName = NULL;
+    }
 }
 #endif
 
@@ -2213,7 +2310,187 @@ gui_mac_doSuspendEvent(event)
 /*
  * Handle the key
  */
-
+#ifdef USE_CARBONKEYHANDLER
+# define INLINE_KEY_BUFFER_SIZE 80
+    static pascal OSStatus
+gui_mac_doKeyEventCarbon(EventHandlerCallRef nextHandler, EventRef theEvent,
+	void *data)
+{
+    /* Multibyte-friendly key event handler */
+    OSStatus	e = -1;
+    UInt32	actualSize;
+    UniChar	*text;
+    char_u	result[INLINE_KEY_BUFFER_SIZE];
+    short	len = 0;
+    UInt32	key_sym;
+    char	charcode;
+    int		key_char;
+    UInt32	modifiers;
+    size_t	encLen;
+    char_u	*to = NULL;
+    Boolean	isSpecial = FALSE;
+    int		i;
+
+    /* Mask the mouse (as per user setting) */
+    if (p_mh)
+	ObscureCursor();
+
+    do
+    {
+	if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
+		    typeUnicodeText, NULL, 0, &actualSize, NULL))
+	    break;
+
+	text = (UniChar *)alloc(actualSize);
+
+	if (text)
+	{
+	    do
+	    {
+		if (noErr != GetEventParameter(theEvent,
+			    kEventParamTextInputSendText,
+			    typeUnicodeText, NULL, actualSize, NULL, text))
+		    break;
+		EventRef keyEvent;
+		if (noErr != GetEventParameter(theEvent,
+			    kEventParamTextInputSendKeyboardEvent,
+			    typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
+		    break;
+		if (noErr != GetEventParameter(keyEvent,
+			    kEventParamKeyModifiers,
+			    typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
+		    break;
+		if (noErr != GetEventParameter(keyEvent,
+			    kEventParamKeyCode,
+			    typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
+		    break;
+		if (noErr != GetEventParameter(keyEvent,
+			    kEventParamKeyMacCharCodes,
+			    typeChar, NULL, sizeof(char), NULL, &charcode))
+		    break;
+
+		key_char = charcode;
+
+		if (modifiers & controlKey)
+		{
+		    if ((modifiers & ~(controlKey|shiftKey)) == 0
+			    && (key_char == '2' || key_char == '6'))
+		    {
+			/* CTRL-^ and CTRL-@ don't work in the normal way. */
+			if (key_char == '2')
+			    key_char = Ctrl_AT;
+			else
+			    key_char = Ctrl_HAT;
+
+			text[0] = (UniChar)key_char;
+			modifiers = 0;
+		    }
+		}
+
+		if (modifiers & cmdKey)
+#ifndef USE_CMD_KEY
+		    break;  /* Let system handle Cmd+... */
+#else
+		{
+		    /* Intercept CMD-. */
+		    if (key_char == '.')
+			got_int = TRUE;
+
+		    /* Convert the modifiers */
+		    modifiers = EventModifiers2VimModifiers(modifiers);
+
+		    /* Following code to simplify and consolidate modifiers
+		     * taken liberally from gui_w48.c */
+
+		    key_char = simplify_key(key_char, (int *)&modifiers);
+
+		    /* remove SHIFT for keys that are already shifted, e.g.,
+		     * '(' and '*' */
+		    if (key_char < 0x100 &&
+			    !isalpha(key_char) && isprint(key_char))
+			modifiers &= ~MOD_MASK_SHIFT;
+
+		    /* Interpret META, include SHIFT, etc. */
+		    key_char = extract_modifiers(key_char, (int *)&modifiers);
+		    if (key_char == CSI)
+			key_char = K_CSI;
+
+		    if (modifiers)
+		    {
+			result[len++] = CSI;
+			result[len++] = KS_MODIFIER;
+			result[len++] = modifiers;
+		    }
+
+		    isSpecial = TRUE;
+		}
+#endif
+		else
+		{
+		    /* Find the special key (eg., for cursor keys) */
+		    if (!(actualSize > sizeof(UniChar)) &&
+			    ((text[0] < 0x20) || (text[0] == 0x7f)))
+		    {
+			for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
+			    if (special_keys[i].key_sym == key_sym)
+			    {
+				key_char = TO_SPECIAL(special_keys[i].vim_code0,
+					special_keys[i].vim_code1);
+				key_char = simplify_key(key_char,
+					(int *)&modifiers);
+				isSpecial = TRUE;
+				break;
+			    }
+		    }
+		}
+
+		if (isSpecial && IS_SPECIAL(key_char))
+		{
+		    result[len++] = CSI;
+		    result[len++] = K_SECOND(key_char);
+		    result[len++] = K_THIRD(key_char);
+		}
+		else
+		{
+		    encLen = actualSize;
+		    to = mac_utf16_to_enc(text, actualSize, &encLen);
+		}
+
+		if (to)
+		{
+		    /* This is basically add_to_input_buf_csi() */
+		    for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
+		    {
+			result[len++] = to[i];
+			if (to[i] == CSI)
+			{
+			    result[len++] = KS_EXTRA;
+			    result[len++] = (int)KE_CSI;
+			}
+		    }
+		    vim_free(to);
+		}
+
+		add_to_input_buf(result, len);
+		e = noErr;
+	    }
+	    while (0);
+
+	    vim_free(text);
+	    if (e == noErr)
+	    {
+		/* Fake event to wake up WNE (required to get
+		 * key repeat working */
+		PostEvent(keyUp, 0);
+		return noErr;
+	    }
+	}
+    }
+    while (0);
+
+    return CallNextEventHandler(nextHandler, theEvent);
+}
+#else
     void
 gui_mac_doKeyEvent(EventRecord *theEvent)
 {
@@ -2387,6 +2664,7 @@ gui_mac_doKeyEvent(EventRecord *theEvent
 
     add_to_input_buf(string, len);
 }
+#endif
 
 /*
  * Handle MouseClick
@@ -2664,11 +2942,12 @@ gui_mac_handle_event(event)
     /* Handle normal event */
     switch (event->what)
     {
+#ifndef USE_CARBONKEYHANDLER
 	case (keyDown):
 	case (autoKey):
 	    gui_mac_doKeyEvent(event);
 	    break;
-
+#endif
 	case (keyUp):
 	    /* We don't care about when the key get release */
 	    break;
@@ -2747,7 +3026,27 @@ gui_mac_find_font(font_name)
     pFontName[0] = STRLEN(font_name);
     *p = c;
 
+    /* Get the font name, minus the style suffix (:h, etc) */
+#if defined(MACOS_X) && defined(USE_CARBONIZED)
+    char_u fontName[256];
+    char_u *styleStart = vim_strchr(font_name, ':');
+    size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
+    vim_strncpy(fontName, font_name, fontNameLen);
+
+    ATSUFontID fontRef;
+    FMFontStyle fontStyle;
+    font_id = 0;
+
+    if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
+		kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
+		&fontRef) == noErr)
+    {
+	if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
+	    font_id = 0;
+    }
+#else
     GetFNum(pFontName, &font_id);
+#endif
 
     if (font_id == 0)
     {
@@ -2767,7 +3066,17 @@ gui_mac_find_font(font_name)
 	    }
 	}
 	if (changed)
+#if defined(MACOS_X) && defined(USE_CARBONIZED)
+	    if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
+			kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
+			kFontNoLanguageCode, &fontRef) == noErr)
+	    {
+		if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
+		    font_id = 0;
+	    }
+#else
 	    GetFNum(pFontName, &font_id);
+#endif
     }
 
 #else
@@ -2782,7 +3091,12 @@ gui_mac_find_font(font_name)
     {
 	/* Oups, the system font was it the one the user want */
 
+#if defined(MACOS_X) && defined(USE_CARBONIZED)
+	if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
+	    return NOFONT;
+#else
 	GetFontName(0, systemFontname);
+#endif
 	if (!EqualString(pFontName, systemFontname, false, false))
 	    return NOFONT;
     }
@@ -3079,6 +3393,15 @@ gui_mch_init()
     EventTypeSpec   eventTypeSpec;
     EventHandlerRef mouseWheelHandlerRef;
 #endif
+#ifdef USE_CARBONKEYHANDLER
+    EventHandlerRef keyEventHandlerRef;
+#endif
+
+#ifdef MACOS_X
+    if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
+	gMacSystemVersion = 0x1000; /* Default to minimum sensible value */
+#endif
+
 #if 1
     InitCursor();
 
@@ -3238,9 +3561,24 @@ gui_mch_init()
     }
 #endif
 
+#ifdef USE_CARBONKEYHANDLER
+    eventTypeSpec.eventClass = kEventClassTextInput;
+    eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
+    keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
+    if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
+		&eventTypeSpec, NULL, &keyEventHandlerRef))
+    {
+	keyEventHandlerRef = NULL;
+	DisposeEventHandlerUPP(keyEventHandlerUPP);
+	keyEventHandlerUPP = NULL;
+    }
+#endif
+
+/*
 #ifdef FEAT_MBYTE
-    set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
-#endif
+    set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
+#endif
+*/
 
     /* TODO: Load bitmap if using TOOLBAR */
     return OK;
@@ -3290,11 +3628,21 @@ gui_mch_exit(int rc)
     /* TODO: find out all what is missing here? */
     DisposeRgn(cursorRgn);
 
+#ifdef USE_CARBONKEYHANDLER
+    if (keyEventHandlerUPP)
+	DisposeEventHandlerUPP(keyEventHandlerUPP);
+#endif
+
 #ifdef USE_MOUSEWHEEL
     if (mouseWheelHandlerUPP != NULL)
 	DisposeEventHandlerUPP(mouseWheelHandlerUPP);
 #endif
 
+#ifdef USE_ATSUI_DRAWING
+    if (gFontStyle)
+	ATSUDisposeStyle(gFontStyle);
+#endif
+
     /* Exit to shell? */
     exit(rc);
 }
@@ -3466,6 +3814,14 @@ gui_mch_init_font(font_name, fontset)
     GuiFont	font;
     char_u	used_font_name[512];
 
+#ifdef USE_ATSUI_DRAWING
+    if (gFontStyle == NULL)
+    {
+	if (ATSUCreateStyle(&gFontStyle) != noErr)
+	    gFontStyle = NULL;
+    }
+#endif
+
     if (font_name == NULL)
     {
 	/* First try to get the suggested font */
@@ -3523,6 +3879,54 @@ gui_mch_init_font(font_name, fontset)
     TextSize(font >> 16);
     TextFont(font & 0xFFFF);
 
+#ifdef USE_ATSUI_DRAWING
+    ATSUFontID			fontID;
+    Fixed			fontSize;
+    ATSStyleRenderingOptions	fontOptions;
+
+    if (gFontStyle)
+    {
+	fontID = font & 0xFFFF;
+	fontSize = Long2Fix(font >> 16);
+
+	/* No antialiasing by default (do not attempt to touch antialising
+	 * options on pre-Jaguar) */
+	fontOptions =
+#ifdef MACOS_X
+	    (gMacSystemVersion >= 0x1020) ?
+	    kATSStyleNoAntiAliasing :
+#endif
+	    kATSStyleNoOptions;
+
+	ATSUAttributeTag attribTags[] =
+	{
+	    kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
+	    kATSUMaxATSUITagValue+1
+	};
+	ByteCount attribSizes[] =
+	{
+	    sizeof(ATSUFontID), sizeof(Fixed),
+	    sizeof(ATSStyleRenderingOptions), sizeof font
+	};
+	ATSUAttributeValuePtr attribValues[] =
+	{
+	    &fontID, &fontSize, &fontOptions, &font
+	};
+
+	/* Convert font id to ATSUFontID */
+	if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
+	{
+	    if (ATSUSetAttributes(gFontStyle,
+			(sizeof attribTags)/sizeof(ATSUAttributeTag),
+			attribTags, attribSizes, attribValues) != noErr)
+	    {
+		ATSUDisposeStyle(gFontStyle);
+		gFontStyle = NULL;
+	    }
+	}
+    }
+#endif
+
     GetFontInfo(&font_info);
 
     gui.char_ascent = font_info.ascent;
@@ -3592,9 +3996,99 @@ gui_mch_get_fontname(font, name)
 gui_mch_set_font(font)
     GuiFont	font;
 {
-    /*
-     * TODO: maybe avoid set again the current font.
-     */
+#ifdef USE_ATSUI_DRAWING
+    GuiFont			currFont;
+    ByteCount			actualFontByteCount;
+    ATSUFontID			fontID;
+    Fixed			fontSize;
+    ATSStyleRenderingOptions	fontOptions;
+
+    if (gFontStyle)
+    {
+	/* Avoid setting same font again */
+	if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
+		    &currFont, &actualFontByteCount) == noErr &&
+		actualFontByteCount == (sizeof font))
+	{
+	    if (currFont == font)
+		return;
+	}
+
+	fontID = font & 0xFFFF;
+	fontSize = Long2Fix(font >> 16);
+	/* Respect p_antialias setting only for wide font.
+	 * The reason for doing this at the moment is a bit complicated,
+	 * but it's mainly because a) latin (non-wide) aliased fonts
+	 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
+	 * b) wide multibyte input does not suffer from that problem. */
+	fontOptions =
+#ifdef MACOS_X
+	    (p_antialias && (font == gui.wide_font)) ?
+	    kATSStyleNoOptions : kATSStyleNoAntiAliasing;
+#else
+	    kATSStyleNoOptions;
+#endif
+
+	ATSUAttributeTag attribTags[] =
+	{
+	    kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
+	    kATSUMaxATSUITagValue+1
+	};
+	ByteCount attribSizes[] =
+	{
+	    sizeof(ATSUFontID), sizeof(Fixed),
+	    sizeof(ATSStyleRenderingOptions), sizeof font
+	};
+	ATSUAttributeValuePtr attribValues[] =
+	{
+	    &fontID, &fontSize, &fontOptions, &font
+	};
+
+	if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
+	{
+	    if (ATSUSetAttributes(gFontStyle,
+			(sizeof attribTags)/sizeof(ATSUAttributeTag),
+			attribTags, attribSizes, attribValues) != noErr)
+	    {
+#ifndef NDEBUG
+		fprintf(stderr, "couldn't set font style\n");
+#endif
+		ATSUDisposeStyle(gFontStyle);
+		gFontStyle = NULL;
+	    }
+	}
+
+    }
+
+    if (!gIsFontFallbackSet)
+    {
+	/* Setup automatic font substitution. The user's guifontwide
+	 * is tried first, then the system tries other fonts. */
+/*
+	ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
+	ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
+	ATSUCreateFontFallbacks(&gFontFallbacks);
+	ATSUSetObjFontFallbacks(gFontFallbacks, );
+*/
+	if (gui.wide_font)
+	{
+	    ATSUFontID fallbackFonts;
+	    gIsFontFallbackSet = TRUE;
+
+	    if (FMGetFontFromFontFamilyInstance(
+			(gui.wide_font & 0xFFFF),
+			0,
+			&fallbackFonts,
+			NULL) == noErr)
+	    {
+		ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
+	    }
+/*
+	ATSUAttributeValuePtr fallbackValues[] = { };
+*/
+	}
+    }
+#endif
     TextSize(font >> 16);
     TextFont(font & 0xFFFF);
 }
@@ -3820,9 +4314,17 @@ gui_mch_draw_string(row, col, s, len, fl
     int		flags;
 {
 #if defined(FEAT_GUI) && defined(MACOS_X)
+#ifndef USE_ATSUI_DRAWING
     SInt32	sys_version;
 #endif
+#endif
 #ifdef FEAT_MBYTE
+#ifdef USE_ATSUI_DRAWING
+    /* ATSUI requires utf-16 strings */
+    UniCharCount utf16_len;
+    UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
+    utf16_len /= sizeof(UniChar);
+#else
     char_u	*tofree = NULL;
 
     if (output_conv.vc_type != CONV_NONE)
@@ -3832,8 +4334,11 @@ gui_mch_draw_string(row, col, s, len, fl
 	    s = tofree;
     }
 #endif
+#endif
 
 #if defined(FEAT_GUI) && defined(MACOS_X)
+    /* ATSUI automatically antialiases text */
+#ifndef USE_ATSUI_DRAWING
     /*
      * On OS X, try using Quartz-style text antialiasing.
      */
@@ -3845,8 +4350,9 @@ gui_mch_draw_string(row, col, s, len, fl
 	/* Quartz antialiasing is available only in OS 10.2 and later. */
 	UInt32 qd_flags = (p_antialias ?
 			     kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
-	(void)SwapQDTextFlags(qd_flags);
+	QDSwapTextFlags(qd_flags);
     }
+#endif
 
     /*
      * When antialiasing we're using srcOr mode, we have to clear the block
@@ -3857,18 +4363,37 @@ gui_mch_draw_string(row, col, s, len, fl
      * The following is like calling gui_mch_clear_block(row, col, row, col +
      * len - 1), but without setting the bg color to gui.back_pixel.
      */
+#ifdef USE_ATSUI_DRAWING
+    if ((flags & DRAW_TRANSP) == 0)
+#else
     if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0)
 	    && !(flags & DRAW_TRANSP))
+#endif
     {
 	Rect rc;
 
 	rc.left = FILL_X(col);
 	rc.top = FILL_Y(row);
+#ifdef FEAT_MBYTE
+	/* Multibyte computation taken from gui_w32.c */
+	if (has_mbyte)
+	{
+	    int cell_len = 0;
+	    int n;
+
+	    /* Compute the length in display cells. */
+	    for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
+		cell_len += (*mb_ptr2cells)(s + n);
+	    rc.right = FILL_X(col + cell_len);
+	}
+	else
+#endif
 	rc.right = FILL_X(col + len) + (col + len == Columns);
 	rc.bottom = FILL_Y(row + 1);
 	EraseRect(&rc);
     }
 
+#ifndef USE_ATSUI_DRAWING
     if (sys_version >= 0x1020 && p_antialias)
     {
 	StyleParameter face;
@@ -3888,6 +4413,7 @@ gui_mch_draw_string(row, col, s, len, fl
     }
     else
 #endif
+#endif
     {
 	/* Use old-style, non-antialiased QuickDraw text rendering. */
 	TextMode(srcCopy);
@@ -3901,6 +4427,25 @@ gui_mch_draw_string(row, col, s, len, fl
 	}
 
 	MoveTo(TEXT_X(col), TEXT_Y(row));
+#ifdef USE_ATSUI_DRAWING
+	ATSUTextLayout textLayout;
+
+	if (ATSUCreateTextLayoutWithTextPtr(tofree,
+		    kATSUFromTextBeginning, kATSUToTextEnd,
+		    utf16_len,
+		    (gFontStyle ? 1 : 0), &utf16_len,
+		    (gFontStyle ? &gFontStyle : NULL),
+		    &textLayout) == noErr)
+	{
+	    ATSUSetTransientFontMatching(textLayout, TRUE);
+
+	    ATSUDrawText(textLayout,
+		    kATSUFromTextBeginning, kATSUToTextEnd,
+		    kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
+
+	    ATSUDisposeTextLayout(textLayout);
+	}
+#else
 	DrawText((char *)s, 0, len);
 
 
@@ -3916,6 +4461,7 @@ gui_mch_draw_string(row, col, s, len, fl
 	    MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
 	    LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
 	}
+#endif
     }
 
 #ifdef FEAT_MBYTE
@@ -4021,14 +4567,16 @@ gui_mch_draw_hollow_cursor(color)
 {
     Rect rc;
 
-    gui_mch_set_fg_color(color);
-
     /*
      * Note: FrameRect() excludes right and bottom of rectangle.
      */
     rc.left = FILL_X(gui.col);
     rc.top = FILL_Y(gui.row);
     rc.right = rc.left + gui.char_width;
+#ifdef FEAT_MBYTE
+    if (mb_lefthalve(gui.row, gui.col))
+	rc.right += gui.char_width;
+#endif
     rc.bottom = rc.top + gui.char_height;
 
     gui_mch_set_fg_color(color);
@@ -4060,7 +4608,8 @@ gui_mch_draw_part_cursor(w, h, color)
 
     gui_mch_set_fg_color(color);
 
-    PaintRect(&rc);
+    FrameRect(&rc);
+//    PaintRect(&rc);
 }
 
 
@@ -4346,11 +4895,11 @@ clip_mch_request_selection(cbd)
 
     if (flavor == 0)
     {
-	error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
+	error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags);
 	if (error != noErr)
 	    return;
 
-	error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
+	error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize);
 	if (error != noErr)
 	    return;
     }
@@ -4374,7 +4923,7 @@ clip_mch_request_selection(cbd)
 	HLock(textOfClip);
 #ifdef USE_CARBONIZED
 	error = GetScrapFlavorData(scrap,
-		flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
+		flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode,
 		&scrapSize, *textOfClip);
 #else
 	scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
@@ -4387,7 +4936,11 @@ clip_mch_request_selection(cbd)
 	    type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
 
 	tempclip = lalloc(scrapSize + 1, TRUE);
+#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
+	mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
+#else
 	STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
+#endif
 	tempclip[scrapSize] = 0;
 
 	searchCR = (char *)tempclip;
@@ -4400,19 +4953,15 @@ clip_mch_request_selection(cbd)
 
 	}
 
-#ifdef FEAT_MBYTE
-	if (input_conv.vc_type != CONV_NONE)
+#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
+	/* Convert from utf-16 (clipboard) */
+	size_t encLen = 0;
+	char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
+	if (to)
 	{
-	    char_u	*to;
-	    int		l = scrapSize;
-
-	    to = string_convert(&input_conv, tempclip, &l);
-	    if (to != NULL)
-	    {
-		vim_free(tempclip);
-		tempclip = to;
-		scrapSize = l;
-	    }
+	    scrapSize = encLen;
+	    vim_free(tempclip);
+	    tempclip = to;
 	}
 #endif
 	clip_yank_selection(type, tempclip, scrapSize, cbd);
@@ -4471,19 +5020,14 @@ clip_mch_set_selection(cbd)
 
     type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
 
-#ifdef FEAT_MBYTE
-    if (str != NULL && output_conv.vc_type != CONV_NONE)
+#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
+    size_t utf16_len = 0;
+    UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
+    if (to)
     {
-	char_u	*to;
-	int	l = scrapSize;
-
-	to = string_convert(&output_conv, str, &l);
-	if (to != NULL)
-	{
-	    vim_free(str);
-	    str = to;
-	    scrapSize = l;
-	}
+	scrapSize = utf16_len;
+	vim_free(str);
+	str = (char_u *)to;
     }
 #endif
 
@@ -4504,9 +5048,9 @@ clip_mch_set_selection(cbd)
 
 #ifdef USE_CARBONIZED
 	**textOfClip = type;
-	STRNCPY(*textOfClip + 1, str, scrapSize);
+	mch_memmove(*textOfClip + 1, str, scrapSize);
 	GetCurrentScrap(&scrap);
-	PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
+	PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
 		scrapSize, *textOfClip + 1);
 	PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
 		scrapSize + 1, *textOfClip);
@@ -4599,7 +5143,11 @@ gui_mch_add_menu(menu, idx)
      */
     static long	 next_avail_id = 128;
     long	 menu_after_me = 0; /* Default to the end */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    CFStringRef name;
+#else
     char_u	*name;
+#endif
     short	 index;
     vimmenu_T	*parent = menu->parent;
     vimmenu_T	*brother = menu->next;
@@ -4625,13 +5173,21 @@ gui_mch_add_menu(menu, idx)
 	menu_after_me = hierMenu;
 
     /* Convert the name */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    name = menu_title_removing_mnemonic(menu);
+#else
     name = C2Pascal_save(menu->dname);
+#endif
     if (name == NULL)
 	return;
 
     /* Create the menu unless it's the help menu */
 #ifdef USE_HELPMENU
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    if (menu->priority == 9999)
+#else
     if (STRNCMP(name, "\4Help", 5) == 0)
+#endif
     {
 	menu->submenu_id = kHMHelpMenuID;
 	menu->submenu_handle = gui.MacOSHelpMenu;
@@ -4644,7 +5200,12 @@ gui_mch_add_menu(menu, idx)
 	 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
 	 */
 	menu->submenu_id = next_avail_id;
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+	if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
+	    SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
+#else
 	menu->submenu_handle = NewMenu(menu->submenu_id, name);
+#endif
 	next_avail_id++;
     }
 
@@ -4676,13 +5237,21 @@ gui_mch_add_menu(menu, idx)
 	 * to avoid special character recognition by InsertMenuItem
 	 */
 	InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+	SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
+#else
 	SetMenuItemText(parent->submenu_handle, idx+1, name);
+#endif
 	SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
 	SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
 	InsertMenu(menu->submenu_handle, hierMenu);
     }
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    CFRelease(name);
+#else
     vim_free(name);
+#endif
 
 #if 0
     /* Done by Vim later on */
@@ -4698,7 +5267,11 @@ gui_mch_add_menu_item(menu, idx)
     vimmenu_T	*menu;
     int		idx;
 {
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    CFStringRef name;
+#else
     char_u	*name;
+#endif
     vimmenu_T	*parent = menu->parent;
     int		menu_inserted;
 
@@ -4710,7 +5283,11 @@ gui_mch_add_menu_item(menu, idx)
        for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
 
     /* Convert the name */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    name = menu_title_removing_mnemonic(menu);
+#else
     name = C2Pascal_save(menu->dname);
+#endif
 
     /* Where are just a menu item, so no handle, no id */
     menu->submenu_id = 0;
@@ -4796,15 +5373,23 @@ gui_mch_add_menu_item(menu, idx)
     if (!menu_inserted)
 	InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
     /* Set the menu item name. */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
+#else
     SetMenuItemText(parent->submenu_handle, idx+1, name);
+#endif
 
 #if 0
     /* Called by Vim */
     DrawMenuBar();
 #endif
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    CFRelease(name);
+#else
     /* TODO: Can name be freed? */
     vim_free(name);
+#endif
 }
 
     void
@@ -5811,17 +6396,33 @@ gui_mch_settitle(title, icon)
     /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
      *       that 256. Even better get it to fit nicely in the titlebar.
      */
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    CFStringRef windowTitle;
+    size_t	windowTitleLen;
+#else
     char_u   *pascalTitle;
+#endif
 
     if (title == NULL)		/* nothing to do */
 	return;
 
+#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
+    windowTitleLen = STRLEN(title);
+    windowTitle  = mac_enc_to_cfstring(title, windowTitleLen);
+
+    if (windowTitle)
+    {
+	SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
+	CFRelease(windowTitle);
+    }
+#else
     pascalTitle = C2Pascal_save(title);
     if (pascalTitle != NULL)
     {
 	SetWTitle(gui.VimWindow, pascalTitle);
 	vim_free(pascalTitle);
     }
+#endif
 }
 #endif
 
--- a/src/ops.c
+++ b/src/ops.c
@@ -1105,10 +1105,20 @@ do_execreg(regname, colon, addcr)
     int		remap;
 
     if (regname == '@')			/* repeat previous one */
+    {
+	if (lastc == NUL)
+	{
+	    EMSG(_("E748: No previously used register"));
+	    return FAIL;
+	}
 	regname = lastc;
+    }
 					/* check for valid regname */
     if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
+    {
+	emsg_invreg(regname);
 	return FAIL;
+    }
     lastc = regname;
 
 #ifdef FEAT_CLIPBOARD
@@ -3597,7 +3607,13 @@ error:
 	    else
 		curbuf->b_op_end.col = 0;
 
-	    if (flags & PUT_CURSEND)
+	    if (flags & PUT_CURSLINE)
+	    {
+		/* ":put": put cursor on last inserte line */
+		curwin->w_cursor.lnum = lnum;
+		beginline(BL_WHITE | BL_FIX);
+	    }
+	    else if (flags & PUT_CURSEND)
 	    {
 		/* put cursor after inserted text */
 		if (y_type == MLINE)
@@ -3616,7 +3632,7 @@ error:
 	    }
 	    else if (y_type == MLINE)
 	    {
-		/* put cursor onfirst non-blank in first inserted line */
+		/* put cursor on first non-blank in first inserted line */
 		curwin->w_cursor.col = 0;
 		if (dir == FORWARD)
 		    ++curwin->w_cursor.lnum;
@@ -5676,7 +5692,7 @@ write_reg_contents_ex(name, str, maxlen,
 
     if (!valid_yank_reg(name, TRUE))	    /* check for valid reg name */
     {
-	EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
+	emsg_invreg(name);
 	return;
     }
 
--- a/src/option.c
+++ b/src/option.c
@@ -1723,8 +1723,8 @@ static struct vimoption
 #endif
 			    },
     {"prompt",	    NULL,   P_BOOL|P_VI_DEF,
-			    (char_u *)NULL, PV_NONE,
-			    {(char_u *)FALSE, (char_u *)0L}},
+			    (char_u *)&p_prompt, PV_NONE,
+			    {(char_u *)TRUE, (char_u *)0L}},
     {"quoteescape", "qe",   P_STRING|P_ALLOCED|P_VI_DEF,
 #ifdef FEAT_TEXTOBJ
 			    (char_u *)&p_qe, PV_QE,
@@ -1922,6 +1922,9 @@ static struct vimoption
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)FALSE, (char_u *)0L}},
+    {"shelltemp",   "stmp", P_BOOL,
+			    (char_u *)&p_stmp, PV_NONE,
+			    {(char_u *)FALSE, (char_u *)TRUE}},
     {"shelltype",   "st",   P_NUM|P_VI_DEF,
 #ifdef AMIGA
 			    (char_u *)&p_st, PV_NONE,
@@ -2501,7 +2504,7 @@ static char *(p_bsdir_values[]) = {"curr
 static char *(p_scbopt_values[]) = {"ver", "hor", "jump", NULL};
 #endif
 static char *(p_swb_values[]) = {"useopen", "split", NULL};
-static char *(p_debug_values[]) = {"msg", NULL};
+static char *(p_debug_values[]) = {"msg", "beep", NULL};
 #ifdef FEAT_VERTSPLIT
 static char *(p_ead_values[]) = {"both", "ver", "hor", NULL};
 #endif
@@ -2593,7 +2596,10 @@ set_init_1()
 
     /* Use POSIX compatibility when $VIM_POSIX is set. */
     if (mch_getenv((char_u *)"VIM_POSIX") != NULL)
+    {
 	set_string_default("cpo", (char_u *)CPO_ALL);
+	set_string_default("shm", (char_u *)"A");
+    }
 
     /*
      * Find default value for 'shell' option.
@@ -2885,6 +2891,23 @@ set_init_1()
 	    vim_setenv("LANG", buf);
 	}
     }
+# else
+#  ifdef MACOS
+    if (mch_getenv((char_u *)"LANG") == NULL)
+    {
+	char	buf[20];
+	if (LocaleRefGetPartString(NULL,
+		    kLocaleLanguageMask | kLocaleLanguageVariantMask |
+		    kLocaleRegionMask | kLocaleRegionVariantMask,
+		    sizeof buf, buf) == noErr && *buf)
+	{
+	    vim_setenv("LANG", buf);
+#   ifdef HAVE_LOCALE_H
+	    setlocale(LC_ALL, "");
+#   endif
+	}
+    }
+#  endif
 # endif
 
     /* enc_locale() will try to find the encoding of the current locale. */
@@ -3093,6 +3116,9 @@ set_init_2()
      * wrong when the window height changes.
      */
     set_number_default("scroll", (long_u)Rows >> 1);
+    idx = findoption((char_u *)"scroll");
+    if (!(options[idx].flags & P_WAS_SET))
+	set_option_default(idx, OPT_LOCAL, p_cp);
     comp_col();
 
     /*
@@ -3423,7 +3449,8 @@ do_set(arg, opt_flags)
     if (*arg == NUL)
     {
 	showoptions(0, opt_flags);
-	return OK;
+	did_show = TRUE;
+	goto theend;
     }
 
     while (*arg != NUL)		/* loop to process all options */
@@ -3446,12 +3473,16 @@ do_set(arg, opt_flags)
 		set_options_default(OPT_FREE | opt_flags);
 	    }
 	    else
+	    {
 		showoptions(1, opt_flags);
+		did_show = TRUE;
+	    }
 	}
 	else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE))
 	{
 	    showoptions(2, opt_flags);
 	    show_termcodes();
+	    did_show = TRUE;
 	    arg += 7;
 	}
 	else
@@ -4187,6 +4218,19 @@ skip:
 	arg = skipwhite(arg);
     }
 
+theend:
+    if (silent_mode && did_show)
+    {
+	/* After displaying option values in silent mode. */
+	silent_mode = FALSE;
+	info_message = TRUE;	/* use mch_msg(), not mch_errmsg() */
+	msg_putchar('\n');
+	cursor_on();		/* msg_start() switches it off */
+	out_flush();
+	silent_mode = TRUE;
+	info_message = FALSE;	/* use mch_msg(), not mch_errmsg() */
+    }
+
     return OK;
 }
 
@@ -7547,7 +7591,11 @@ showoneopt(p, opt_flags)
     struct vimoption	*p;
     int			opt_flags;	/* OPT_LOCAL or OPT_GLOBAL */
 {
-    char_u		*varp;
+    char_u	*varp;
+    int		save_silent = silent_mode;
+
+    silent_mode = FALSE;
+    info_message = TRUE;	/* use mch_msg(), not mch_errmsg() */
 
     varp = get_varp_scope(p, opt_flags);
 
@@ -7567,6 +7615,9 @@ showoneopt(p, opt_flags)
 	option_value2string(p, opt_flags);
 	msg_outtrans(NameBuff);
     }
+
+    silent_mode = save_silent;
+    info_message = FALSE;
 }
 
 /*
--- a/src/option.h
+++ b/src/option.h
@@ -174,10 +174,13 @@
 #define CPO_PARA	'{'	/* "{" is also a paragraph boundary */
 #define CPO_TSIZE	'|'	/* $LINES and $COLUMNS overrule term size */
 #define CPO_PRESERVE	'&'	/* keep swap file after :preserve */
+#define CPO_SUBPERCENT	'/'	/* % in :s string uses previous one */
+#define CPO_BACKSL	'\\'	/* \ is not special in [] */
+#define CPO_CHDIR	'.'	/* don't chdir if buffer is modified */
 /* default values for Vim, Vi and POSIX */
 #define CPO_VIM		"aABceFs"
 #define CPO_VI		"aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>"
-#define CPO_ALL		"aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>#{|&"
+#define CPO_ALL		"aAbBcCdDeEfFgHiIjJkKlLmMnoOpqrRsStuvwWxXyZ$!%*-+<>#{|&/\\."
 
 /* characters for p_ww option: */
 #define WW_ALL		"bshl<>[],~"
@@ -479,6 +482,7 @@ EXTERN char_u	*p_pfn;		/* 'printfont' */
 EXTERN char_u	*p_popt;	/* 'printoptions' */
 EXTERN char_u	*p_header;	/* 'printheader' */
 #endif
+EXTERN int	p_prompt;	/* 'prompt' */
 #ifdef FEAT_GUI
 EXTERN char_u	*p_guifont;	/* 'guifont' */
 # ifdef FEAT_XFONTSET
@@ -675,6 +679,7 @@ EXTERN char_u	*p_srr;		/* 'shellredir' *
 #ifdef AMIGA
 EXTERN long	p_st;		/* 'shelltype' */
 #endif
+EXTERN int	p_stmp;		/* 'shelltemp' */
 #ifdef BACKSLASH_IN_FILENAME
 EXTERN int	p_ssl;		/* 'shellslash' */
 #endif
--- a/src/os_mac_conv.c
+++ b/src/os_mac_conv.c
@@ -21,6 +21,21 @@ extern char_u *mac_string_convert __ARGS
 extern int macroman2enc __ARGS((char_u *ptr, long *sizep, long real_size));
 extern int enc2macroman __ARGS((char_u *from, size_t fromlen, char_u *to, int *tolenp, int maxtolen, char_u *rest, int *restlenp));
 
+extern void	    mac_conv_init __ARGS((void));
+extern void	    mac_conv_cleanup __ARGS((void));
+extern char_u	    *mac_utf16_to_enc __ARGS((UniChar *from, size_t fromLen, size_t *actualLen));
+extern UniChar	    *mac_enc_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen));
+extern CFStringRef  mac_enc_to_cfstring __ARGS((char_u *from, size_t fromLen));
+extern char_u	    *mac_precompose_path __ARGS((char_u *decompPath, size_t decompLen, size_t *precompLen));
+
+static char_u	    *mac_utf16_to_utf8 __ARGS((UniChar *from, size_t fromLen, size_t *actualLen));
+static UniChar	    *mac_utf8_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen));
+
+/* Converter for composing decomposed HFS+ file paths */
+static TECObjectRef gPathConverter;
+/* Converter used by mac_utf16_to_utf8 */
+static TECObjectRef gUTF16ToUTF8Converter;
+
 /*
  * A Mac version of string_convert_ext() for special cases.
  */
@@ -59,6 +74,8 @@ mac_string_convert(ptr, len, lenp, fail_
 	*unconvlenp = 0;
     cfstr = CFStringCreateWithBytes(NULL, ptr, len, from, 0);
 
+    if(cfstr == NULL)
+	fprintf(stderr, "Encoding failed\n");
     /* When conversion failed, try excluding bytes from the end, helps when
      * there is an incomplete byte sequence.  Only do up to 6 bytes to avoid
      * looping a long time when there really is something unconvertable. */
@@ -70,6 +87,7 @@ mac_string_convert(ptr, len, lenp, fail_
     }
     if (cfstr == NULL)
 	return NULL;
+
     if (to == kCFStringEncodingUTF8)
 	buflen = len * 6 + 1;
     else
@@ -80,6 +98,22 @@ mac_string_convert(ptr, len, lenp, fail_
 	CFRelease(cfstr);
 	return NULL;
     }
+
+#if 0
+    CFRange convertRange = CFRangeMake(0, CFStringGetLength(cfstr));
+    /*  Determine output buffer size */
+    CFStringGetBytes(cfstr, convertRange, to, NULL, FALSE, NULL, 0, (CFIndex *)&buflen);
+    retval = (buflen > 0) ? alloc(buflen) : NULL;
+    if (retval == NULL) {
+	CFRelease(cfstr);
+	return NULL;
+    }
+
+    if (lenp)
+	*lenp = buflen / sizeof(char_u);
+
+    if (!CFStringGetBytes(cfstr, convertRange, to, NULL, FALSE, retval, buflen, NULL))
+#endif
     if (!CFStringGetCString(cfstr, retval, buflen, to))
     {
 	CFRelease(cfstr);
@@ -89,6 +123,7 @@ mac_string_convert(ptr, len, lenp, fail_
 	    return NULL;
 	}
 
+	fprintf(stderr, "Trying char-by-char conversion...\n");
 	/* conversion failed for the whole string, but maybe it will work
 	 * for each character */
 	for (d = retval, in = 0, out = 0; in < len && out < buflen - 1;)
@@ -128,6 +163,7 @@ mac_string_convert(ptr, len, lenp, fail_
     CFRelease(cfstr);
     if (lenp != NULL)
 	*lenp = strlen(retval);
+
     return retval;
 }
 
@@ -230,4 +266,291 @@ enc2macroman(from, fromlen, to, tolenp, 
     return OK;
 }
 
+/*
+ * Initializes text converters
+ */
+    void
+mac_conv_init()
+{
+    TextEncoding    utf8_encoding;
+    TextEncoding    utf8_hfsplus_encoding;
+    TextEncoding    utf8_canon_encoding;
+    TextEncoding    utf16_encoding;
+
+    utf8_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+	    kTextEncodingDefaultVariant, kUnicodeUTF8Format);
+    utf8_hfsplus_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+	    kUnicodeHFSPlusCompVariant, kUnicodeUTF8Format);
+    utf8_canon_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+	    kUnicodeCanonicalCompVariant, kUnicodeUTF8Format);
+    utf16_encoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
+	    kTextEncodingDefaultVariant, kUnicode16BitFormat);
+
+    if (TECCreateConverter(&gPathConverter, utf8_encoding,
+		utf8_hfsplus_encoding) != noErr)
+	gPathConverter = NULL;
+
+    if (TECCreateConverter(&gUTF16ToUTF8Converter, utf16_encoding,
+		utf8_canon_encoding) != noErr)
+	gUTF16ToUTF8Converter = NULL;
+}
+
+/*
+ * Destroys text converters
+ */
+    void
+mac_conv_cleanup()
+{
+    if (gUTF16ToUTF8Converter)
+    {
+	TECDisposeConverter(gUTF16ToUTF8Converter);
+	gUTF16ToUTF8Converter = NULL;
+    }
+
+    if (gPathConverter)
+    {
+	TECDisposeConverter(gPathConverter);
+	gPathConverter = NULL;
+    }
+}
+
+/*
+ * Conversion from UTF-16 UniChars to 'encoding'
+ */
+    char_u *
+mac_utf16_to_enc(from, fromLen, actualLen)
+    UniChar *from;
+    size_t fromLen;
+    size_t *actualLen;
+{
+    /* Following code borrows somewhat from os_mswin.c */
+    vimconv_T	conv;
+    size_t      utf8_len;
+    char_u      *utf8_str;
+    char_u      *result = NULL;
+
+    /* Convert to utf-8 first, works better with iconv */
+    utf8_len = 0;
+    utf8_str = mac_utf16_to_utf8(from, fromLen, &utf8_len);
+
+    if (utf8_str)
+    {
+	/* We might be called before we have p_enc set up. */
+	conv.vc_type = CONV_NONE;
+
+	/* If encoding (p_enc) is any unicode, it is actually in utf-8 (vim
+	 * internal unicode is always utf-8) so don't convert in such cases */
+
+	if ((enc_canon_props(p_enc) & ENC_UNICODE) == 0)
+	    convert_setup(&conv, (char_u *)"utf-8",
+		    p_enc? p_enc: (char_u *)"macroman");
+	if (conv.vc_type == CONV_NONE)
+	{
+	    /* p_enc is utf-8, so we're done. */
+	    result = utf8_str;
+	}
+	else
+	{
+	    result = string_convert(&conv, utf8_str, (int *)&utf8_len);
+	    vim_free(utf8_str);
+	}
+
+	convert_setup(&conv, NULL, NULL);
+
+	if (actualLen)
+	    *actualLen = utf8_len;
+    }
+    else if (actualLen)
+	*actualLen = 0;
+
+    return result;
+}
+
+/*
+ * Conversion from 'encoding' to UTF-16 UniChars
+ */
+    UniChar *
+mac_enc_to_utf16(from, fromLen, actualLen)
+    char_u *from;
+    size_t fromLen;
+    size_t *actualLen;
+{
+    /* Following code borrows somewhat from os_mswin.c */
+    vimconv_T	conv;
+    size_t      utf8_len;
+    char_u      *utf8_str;
+    UniChar     *result = NULL;
+    Boolean     should_free_utf8 = FALSE;
+
+    do
+    {
+	/* Use MacRoman by default, we might be called before we have p_enc
+	 * set up.  Convert to utf-8 first, works better with iconv().  Does
+	 * nothing if 'encoding' is "utf-8". */
+	conv.vc_type = CONV_NONE;
+	if ((enc_canon_props(p_enc) & ENC_UNICODE) == 0 &&
+		convert_setup(&conv, p_enc ? p_enc : (char_u *)"macroman",
+		    (char_u *)"utf-8") == FAIL)
+	    break;
+
+	if (conv.vc_type != CONV_NONE)
+	{
+	    utf8_len = fromLen;
+	    utf8_str = string_convert(&conv, from, (int *)&utf8_len);
+	    should_free_utf8 = TRUE;
+	}
+	else
+	{
+	    utf8_str = from;
+	    utf8_len = fromLen;
+	}
+
+	if (utf8_str == NULL)
+	    break;
+
+	convert_setup(&conv, NULL, NULL);
+
+	result = mac_utf8_to_utf16(utf8_str, utf8_len, actualLen);
+
+	if (should_free_utf8)
+	    vim_free(utf8_str);
+	return result;
+    }
+    while (0);
+
+    if (actualLen)
+	*actualLen = 0;
+
+    return result;
+}
+
+/*
+ * Converts from UTF-16 UniChars to CFString
+ */
+    CFStringRef
+mac_enc_to_cfstring(from, fromLen)
+    char_u  *from;
+    size_t  fromLen;
+{
+    UniChar	*utf16_str;
+    size_t	utf16_len;
+    CFStringRef	result = NULL;
+
+    utf16_str = mac_enc_to_utf16(from, fromLen, &utf16_len);
+    if (utf16_str)
+    {
+	result = CFStringCreateWithCharacters(NULL, utf16_str, utf16_len/sizeof(UniChar));
+	vim_free(utf16_str);
+    }
+
+    return result;
+}
+
+/*
+ * Converts a decomposed HFS+ UTF-8 path to precomposed UTF-8
+ */
+    char_u *
+mac_precompose_path(decompPath, decompLen, precompLen)
+    char_u  *decompPath;
+    size_t  decompLen;
+    size_t  *precompLen;
+{
+    char_u  *result = NULL;
+    size_t  actualLen = 0;
+
+    if (gPathConverter)
+    {
+	result = alloc(decompLen);
+	if (result)
+	{
+	    if (TECConvertText(gPathConverter, decompPath,
+			decompLen, &decompLen, result,
+			decompLen, &actualLen) != noErr)
+	    {
+		vim_free(result);
+		result = NULL;
+	    }
+	}
+    }
+
+    if (precompLen)
+	*precompLen = actualLen;
+
+    return result;
+}
+
+/*
+ * Converts from UTF-16 UniChars to precomposed UTF-8
+ */
+    char_u *
+mac_utf16_to_utf8(from, fromLen, actualLen)
+    UniChar *from;
+    size_t fromLen;
+    size_t *actualLen;
+{
+    ByteCount		utf8_len;
+    ByteCount		inputRead;
+    char_u		*result;
+
+    if (gUTF16ToUTF8Converter)
+    {
+	result = alloc(fromLen * 6 + 1);
+	if (result && TECConvertText(gUTF16ToUTF8Converter, (ConstTextPtr)from,
+		    fromLen, &inputRead, result,
+		    (fromLen*6+1)*sizeof(char_u), &utf8_len) == noErr)
+	{
+	    TECFlushText(gUTF16ToUTF8Converter, result, (fromLen*6+1)*sizeof(char_u), &inputRead);
+	    utf8_len += inputRead;
+	}
+	else
+	{
+	    vim_free(result);
+	    result = NULL;
+	}
+    }
+    else
+    {
+	result = NULL;
+    }
+
+    if (actualLen)
+	*actualLen = result ? utf8_len : 0;
+
+    return result;
+}
+
+/*
+ * Converts from UTF-8 to UTF-16 UniChars
+ */
+    UniChar *
+mac_utf8_to_utf16(from, fromLen, actualLen)
+    char_u *from;
+    size_t fromLen;
+    size_t *actualLen;
+{
+    CFStringRef  utf8_str;
+    CFRange      convertRange;
+    UniChar      *result = NULL;
+
+    utf8_str = CFStringCreateWithBytes(NULL, from, fromLen,
+	    kCFStringEncodingUTF8, FALSE);
+
+    if (utf8_str == NULL) {
+	if (actualLen)
+	    *actualLen = 0;
+	return NULL;
+    }
+
+    convertRange = CFRangeMake(0, CFStringGetLength(utf8_str));
+    result = (UniChar *)alloc(convertRange.length * sizeof(UniChar));
+
+    CFStringGetCharacters(utf8_str, convertRange, result);
+
+    CFRelease(utf8_str);
+
+    if (actualLen)
+	*actualLen = convertRange.length * sizeof(UniChar);
+
+    return result;
+}
 #endif /* FEAT_MBYTE */
--- a/src/po/Make_mvc.mak
+++ b/src/po/Make_mvc.mak
@@ -6,9 +6,9 @@
 # Please read README_mvc.txt before using this file.
 #
 
-LANGUAGES =	af ca cs de en_GB es fr it ja ko no pl ru sk sv uk zh_TW \
+LANGUAGES =	af ca cs de en_GB es fr ga it ja ko no pl ru sk sv uk zh_TW \
 		zh_TW.UTF-8 zh_CN zh_CN.UTF-8
-MOFILES =	af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo it.mo ja.mo \
+MOFILES =	af.mo ca.mo cs.mo de.mo en_GB.mo es.mo fr.mo ga.mo it.mo ja.mo \
 		ko.mo no.mo pl.mo ru.mo sk.mo sv.mo uk.mo \
 		zh_TW.mo zh_TW.UTF-8.mo zh_CN.mo zh_CN.UTF-8.mo
 
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -6,6 +6,9 @@ int *func_dbg_tick __ARGS((void *cookie)
 int func_level __ARGS((void *cookie));
 int current_func_returned __ARGS((void));
 void set_internal_string_var __ARGS((char_u *name, char_u *value));
+int var_redir_start __ARGS((char_u *name, int append));
+void var_redir_str __ARGS((char_u *value, int len));
+void var_redir_stop __ARGS((void));
 int eval_charconvert __ARGS((char_u *enc_from, char_u *enc_to, char_u *fname_from, char_u *fname_to));
 int eval_printexpr __ARGS((char_u *fname, char_u *args));
 void eval_diff __ARGS((char_u *origfile, char_u *newfile, char_u *outfile));
--- a/src/screen.c
+++ b/src/screen.c
@@ -6847,18 +6847,6 @@ screen_start()
 }
 
 /*
- * Note that the cursor has gone down to the next line, column 0.
- * Used for Ex mode.
- */
-    void
-screen_down()
-{
-    screen_cur_col = 0;
-    if (screen_cur_row < Rows - 1)
-	++screen_cur_row;
-}
-
-/*
  * Move the cursor to position "row","col" in the screen.
  * This tries to find the most efficient way to move, minimizing the number of
  * characters sent to the terminal.
--- a/src/search.c
+++ b/src/search.c
@@ -4715,7 +4715,7 @@ show_pat_in_path(line, type, did_show, a
 	    msg_puts_attr(IObuff, hl_attr(HLF_N));
 	    MSG_PUTS(" ");
 	}
-	msg_prt_line(line);
+	msg_prt_line(line, FALSE);
 	out_flush();			/* show one line at a time */
 
 	/* Definition continues until line that doesn't end with '\' */
--- a/src/structs.h
+++ b/src/structs.h
@@ -307,7 +307,8 @@ struct m_block
 {
     mblock_T	*mb_next;	/* pointer to next allocated block */
     size_t	mb_size;	/* total size of all chunks in this block */
-    minfo_T	mb_info;	/* head of free chuck list for this block */
+    size_t	mb_maxsize;	/* size of largest fee chunk */
+    minfo_T	mb_info;	/* head of free chunk list for this block */
 };
 
 /*
@@ -1211,6 +1212,7 @@ struct file_buffer
     minfo_T	*b_m_search;	/* pointer to chunk before previously
 				   allocated/freed chunk */
     mblock_T	*b_mb_current;	/* block where m_search points in */
+
 #ifdef FEAT_INS_EXPAND
     int		b_scanned;	/* ^N/^P have scanned this buffer */
 #endif
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -4397,8 +4397,19 @@ syn_cmd_keyword(eap, syncing)
 			add_keyword(kw, syn_id, syn_opt_arg.flags,
 						     syn_opt_arg.cont_in_list,
 						       syn_opt_arg.next_list);
-			if (p == NULL || p[1] == NUL || p[1] == ']')
+			if (p == NULL)
+			    break;
+			if (p[1] == NUL)
+			{
+			    EMSG2(_("E747: Missing ']': %s"), kw);
+			    kw = p + 2;		/* skip over the NUL */
 			    break;
+			}
+			if (p[1] == ']')
+			{
+			    kw = p + 1;		/* skip over the "]" */
+			    break;
+			}
 #ifdef FEAT_MBYTE
 			if (has_mbyte)
 			{
@@ -4418,6 +4429,8 @@ syn_cmd_keyword(eap, syncing)
 	    }
 
 	    vim_free(keyword_copy);
+	    vim_free(syn_opt_arg.cont_in_list);
+	    vim_free(syn_opt_arg.next_list);
 	}
     }
 
@@ -4426,8 +4439,6 @@ syn_cmd_keyword(eap, syncing)
     else
 	EMSG2(_(e_invarg2), arg);
 
-    vim_free(syn_opt_arg.cont_in_list);
-    vim_free(syn_opt_arg.next_list);
     redraw_curbuf_later(NOT_VALID);
     syn_stack_free_all(curbuf);		/* Need to recompute all syntax. */
 }
--- a/src/term.c
+++ b/src/term.c
@@ -1590,6 +1590,10 @@ set_termname(term)
     char_u	*error_msg = NULL;
     char_u	*bs_p, *del_p;
 
+    /* In silect mode (ex -s) we don't use the 'term' option. */
+    if (silent_mode)
+	return OK;
+
     detected_8bit = FALSE;		/* reset 8-bit detection */
 
     if (term_is_builtin(term))
@@ -3146,10 +3150,6 @@ settmode(tmode)
 
     if (full_screen)
     {
-	/* In Ex mode, never set to RAW */
-	if (exmode_active == EXMODE_NORMAL)
-	    tmode = TMODE_COOK;
-
 	/*
 	 * When returning after calling a shell we want to really set the
 	 * terminal to raw mode, even though we think it already is, because
--- a/src/undo.c
+++ b/src/undo.c
@@ -41,24 +41,33 @@
  * curbuf->b_u_curhead points to the header of the last undo (the next redo),
  * or is NULL if nothing has been undone.
  *
- * All data is allocated with u_alloc_line(), thus it will be freed as soon as
- * we switch files!
+ * All data is allocated with U_ALLOC_LINE(), it will be freed as soon as the
+ * buffer is unloaded.
  */
 
 #include "vim.h"
 
+/* See below: use malloc()/free() for memory management. */
+#define U_USE_MALLOC 1
+
 static u_entry_T *u_get_headentry __ARGS((void));
 static void u_getbot __ARGS((void));
 static int u_savecommon __ARGS((linenr_T, linenr_T, linenr_T));
 static void u_doit __ARGS((int count));
 static void u_undoredo __ARGS((void));
 static void u_undo_end __ARGS((void));
-static void u_freelist __ARGS((struct u_header *));
+static void u_freelist __ARGS((buf_T *buf, struct u_header *));
 static void u_freeentry __ARGS((u_entry_T *, long));
 
-static char_u *u_blockalloc __ARGS((long_u));
-static void u_free_line __ARGS((char_u *, int keep));
-static char_u *u_alloc_line __ARGS((unsigned));
+#ifdef U_USE_MALLOC
+# define U_FREE_LINE(ptr) vim_free(ptr)
+# define U_ALLOC_LINE(size) lalloc((long_u)((size) + 1), FALSE)
+#else
+static void u_free_line __ARGS((char_u *ptr, int keep));
+static char_u *u_alloc_line __ARGS((unsigned size));
+# define U_FREE_LINE(ptr) u_free_line((ptr), FALSE)
+# define U_ALLOC_LINE(size) u_alloc_line(size)
+#endif
 static char_u *u_save_line __ARGS((linenr_T));
 
 static long	u_newcount, u_oldcount;
@@ -227,13 +236,13 @@ u_savecommon(top, bot, newbot)
 	 * including curbuf->b_u_curhead
 	 */
 	while (curbuf->b_u_curhead != NULL)
-	    u_freelist(curbuf->b_u_newhead);
+	    u_freelist(curbuf, curbuf->b_u_newhead);
 
 	/*
 	 * free headers to keep the size right
 	 */
 	while (curbuf->b_u_numhead > p_ul && curbuf->b_u_oldhead != NULL)
-	    u_freelist(curbuf->b_u_oldhead);
+	    u_freelist(curbuf, curbuf->b_u_oldhead);
 
 	if (p_ul < 0)		/* no undo at all */
 	{
@@ -244,7 +253,7 @@ u_savecommon(top, bot, newbot)
 	/*
 	 * make a new header entry
 	 */
-	uhp = (struct u_header *)u_alloc_line((unsigned)
+	uhp = (struct u_header *)U_ALLOC_LINE((unsigned)
 						     sizeof(struct u_header));
 	if (uhp == NULL)
 	    goto nomem;
@@ -364,7 +373,7 @@ u_savecommon(top, bot, newbot)
     /*
      * add lines in front of entry list
      */
-    uep = (u_entry_T *)u_alloc_line((unsigned)sizeof(u_entry_T));
+    uep = (u_entry_T *)U_ALLOC_LINE((unsigned)sizeof(u_entry_T));
     if (uep == NULL)
 	goto nomem;
 
@@ -384,9 +393,9 @@ u_savecommon(top, bot, newbot)
 	curbuf->b_u_newhead->uh_getbot_entry = uep;
     }
 
-    if (size)
+    if (size > 0)
     {
-	if ((uep->ue_array = (char_u **)u_alloc_line(
+	if ((uep->ue_array = (char_u **)U_ALLOC_LINE(
 				(unsigned)(sizeof(char_u *) * size))) == NULL)
 	{
 	    u_freeentry(uep, 0L);
@@ -609,9 +618,9 @@ u_undoredo()
 	empty_buffer = FALSE;
 
 	/* delete the lines between top and bot and save them in newarray */
-	if (oldsize)
+	if (oldsize > 0)
 	{
-	    if ((newarray = (char_u **)u_alloc_line(
+	    if ((newarray = (char_u **)U_ALLOC_LINE(
 			    (unsigned)(sizeof(char_u *) * oldsize))) == NULL)
 	    {
 		do_outofmem_msg((long_u)(sizeof(char_u *) * oldsize));
@@ -654,9 +663,9 @@ u_undoredo()
 		    ml_replace((linenr_T)1, uep->ue_array[i], TRUE);
 		else
 		    ml_append(lnum, uep->ue_array[i], (colnr_T)0, FALSE);
-		u_free_line(uep->ue_array[i], FALSE);
+		U_FREE_LINE(uep->ue_array[i]);
 	    }
-	    u_free_line((char_u *)uep->ue_array, FALSE);
+	    U_FREE_LINE((char_u *)uep->ue_array);
 	}
 
 	/* adjust marks */
@@ -870,7 +879,8 @@ u_getbot()
  * u_freelist: free one entry list and adjust the pointers
  */
     static void
-u_freelist(uhp)
+u_freelist(buf, uhp)
+    buf_T	    *buf;
     struct u_header *uhp;
 {
     u_entry_T	*uep, *nuep;
@@ -881,21 +891,21 @@ u_freelist(uhp)
 	u_freeentry(uep, uep->ue_size);
     }
 
-    if (curbuf->b_u_curhead == uhp)
-	curbuf->b_u_curhead = NULL;
+    if (buf->b_u_curhead == uhp)
+	buf->b_u_curhead = NULL;
 
     if (uhp->uh_next == NULL)
-	curbuf->b_u_oldhead = uhp->uh_prev;
+	buf->b_u_oldhead = uhp->uh_prev;
     else
 	uhp->uh_next->uh_prev = uhp->uh_prev;
 
     if (uhp->uh_prev == NULL)
-	curbuf->b_u_newhead = uhp->uh_next;
+	buf->b_u_newhead = uhp->uh_next;
     else
 	uhp->uh_prev->uh_next = uhp->uh_next;
 
-    u_free_line((char_u *)uhp, FALSE);
-    --curbuf->b_u_numhead;
+    U_FREE_LINE((char_u *)uhp);
+    --buf->b_u_numhead;
 }
 
 /*
@@ -907,8 +917,8 @@ u_freeentry(uep, n)
     long	    n;
 {
     while (n)
-	u_free_line(uep->ue_array[--n], FALSE);
-    u_free_line((char_u *)uep, FALSE);
+	U_FREE_LINE(uep->ue_array[--n]);
+    U_FREE_LINE((char_u *)uep);
 }
 
 /*
@@ -955,7 +965,7 @@ u_clearline()
 {
     if (curbuf->b_u_line_ptr != NULL)
     {
-	u_free_line(curbuf->b_u_line_ptr, FALSE);
+	U_FREE_LINE(curbuf->b_u_line_ptr);
 	curbuf->b_u_line_ptr = NULL;
 	curbuf->b_u_line_lnum = 0;
     }
@@ -993,7 +1003,7 @@ u_undoline()
     }
     ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, TRUE);
     changed_bytes(curbuf->b_u_line_lnum, 0);
-    u_free_line(curbuf->b_u_line_ptr, FALSE);
+    U_FREE_LINE(curbuf->b_u_line_ptr);
     curbuf->b_u_line_ptr = oldp;
 
     t = curbuf->b_u_line_colnr;
@@ -1004,7 +1014,40 @@ u_undoline()
 }
 
 /*
- * storage allocation for the undo lines and blocks of the current file
+ * There are two implementations of the memory management for undo:
+ * 1. Use the standard malloc()/free() functions.
+ *    This should be fast for allocating memory, but when a buffer is
+ *    abandoned every single allocated chunk must be freed, which may be slow.
+ * 2. Allocate larger blocks of memory and keep track of chunks ourselves.
+ *    This is fast for abandoning, but the use of linked lists is slow for
+ *    finding a free chunk.  Esp. when a lot of lines are changed or deleted.
+ * A bit of profiling showed that the first method is faster, especially when
+ * making a large number of changes, under the condition that malloc()/free()
+ * is implemented efficiently.
+ */
+#ifdef U_USE_MALLOC
+/*
+ * Version of undo memory allocation using malloc()/free()
+ *
+ * U_FREE_LINE() and U_ALLOC_LINE() are macros that invoke vim_free() and
+ * lalloc() directly.
+ */
+
+/*
+ * Free all allocated memory blocks for the buffer 'buf'.
+ */
+    void
+u_blockfree(buf)
+    buf_T	*buf;
+{
+    while (buf->b_u_newhead != NULL)
+	u_freelist(buf, buf->b_u_newhead);
+}
+
+#else
+/*
+ * Storage allocation for the undo lines and blocks of the current file.
+ * Version where Vim keeps track of the available memory.
  */
 
 /*
@@ -1071,6 +1114,8 @@ u_undoline()
 # define M_OFFSET (sizeof(short_u))
 #endif
 
+static char_u *u_blockalloc __ARGS((long_u));
+
 /*
  * Allocate a block of memory and link it in the allocated block list.
  */
@@ -1092,6 +1137,7 @@ u_blockalloc(size)
 	    ;
 	p->mb_next = next;		/* link in block list */
 	p->mb_size = size;
+	p->mb_maxsize = 0;		/* nothing free yet */
 	mp->mb_next = p;
 	p->mb_info.m_next = NULL;	/* clear free list */
 	p->mb_info.m_size = 0;
@@ -1135,6 +1181,7 @@ u_free_line(ptr, keep)
     minfo_T	*mp;
     mblock_T	*nextb;
     mblock_T	*prevb;
+    long_u	maxsize;
 
     if (ptr == NULL || ptr == IObuff)
 	return;	/* illegal address can happen in out-of-memory situations */
@@ -1212,11 +1259,13 @@ u_free_line(ptr, keep)
     }
     else
 	mp->m_next = next;
+    maxsize = mp->m_size;
 
     /* if *curr and *mp are concatenated, join them */
     if (prev != NULL && (char_u *)curr + curr->m_size == (char_u *)mp)
     {
 	curr->m_size += mp->m_size;
+	maxsize = curr->m_size;
 	curr->m_next = mp->m_next;
 	curbuf->b_m_search = prev;
     }
@@ -1244,6 +1293,8 @@ u_free_line(ptr, keep)
 	curbuf->b_mb_current = NULL;
 	curbuf->b_m_search = NULL;
     }
+    else if (curbuf->b_mb_current->mb_maxsize < maxsize)
+	curbuf->b_mb_current->mb_maxsize = maxsize;
 }
 
 /*
@@ -1282,48 +1333,56 @@ u_alloc_line(size)
 	curbuf->b_m_search = &(curbuf->b_block_head.mb_info);
     }
 
-    /* search for space in free list */
-    mprev = curbuf->b_m_search;
+    /* Search for a block with enough space. */
     mbp = curbuf->b_mb_current;
-    mp = curbuf->b_m_search->m_next;
-    if (mp == NULL)
+    while (mbp->mb_maxsize < size_align)
     {
-	if (mbp->mb_next)
+	if (mbp->mb_next != NULL)
 	    mbp = mbp->mb_next;
 	else
 	    mbp = &curbuf->b_block_head;
-	mp = curbuf->b_m_search = &(mbp->mb_info);
-    }
-    while (mp->m_size < size)
-    {
-	if (mp == curbuf->b_m_search)	    /* back where we started in free
-					       chunk list */
+	if (mbp == curbuf->b_mb_current)
 	{
-	    if (mbp->mb_next)
-		mbp = mbp->mb_next;
-	    else
-		mbp = &curbuf->b_block_head;
-	    mp = curbuf->b_m_search = &(mbp->mb_info);
-	    if (mbp == curbuf->b_mb_current)	/* back where we started in
-						   block list */
-	    {
-		int	n = (size_align > (MEMBLOCKSIZE / 4)
-						 ? size_align : MEMBLOCKSIZE);
+	    int	n = (size_align > (MEMBLOCKSIZE / 4)
+					     ? size_align : MEMBLOCKSIZE);
 
-		mp = (minfo_T *)u_blockalloc((long_u)n);
-		if (mp == NULL)
-		    return (NULL);
-		mp->m_size = n;
-		u_free_line((char_u *)mp + M_OFFSET, TRUE);
-		mp = curbuf->b_m_search;
-		mbp = curbuf->b_mb_current;
-	    }
+	    /* Back where we started in block list: need to add a new block
+	     * with enough space. */
+	    mp = (minfo_T *)u_blockalloc((long_u)n);
+	    if (mp == NULL)
+		return (NULL);
+	    mp->m_size = n;
+	    u_free_line((char_u *)mp + M_OFFSET, TRUE);
+	    mbp = curbuf->b_mb_current;
+	    break;
+	}
+    }
+    if (mbp != curbuf->b_mb_current)
+	curbuf->b_m_search = &(mbp->mb_info);
+
+    /* In this block find a chunk with enough space. */
+    mprev = curbuf->b_m_search;
+    mp = curbuf->b_m_search->m_next;
+    while (1)
+    {
+	if (mp == NULL)			    /* at end of the list */
+	    mp = &(mbp->mb_info);	    /* wrap around to begin */
+	if (mp->m_size >= size)
+	    break;
+	if (mp == curbuf->b_m_search)
+	{
+	    /* back where we started in free chunk list: "cannot happen" */
+	    EMSG2(_(e_intern2), "u_alloc_line()");
+	    return NULL;
 	}
 	mprev = mp;
-	if ((mp = mp->m_next) == NULL)	    /* at end of the list */
-	    mp = &(mbp->mb_info);	    /* wrap around to begin */
+	mp = mp->m_next;
     }
 
+    /* when using the largest chunk adjust mb_maxsize */
+    if (mp->m_size >= mbp->mb_maxsize)
+	mbp->mb_maxsize = 0;
+
     /* if the chunk we found is large enough, split it up in two */
     if ((long)mp->m_size - size_align >= (long)(sizeof(minfo_T) + 1))
     {
@@ -1340,11 +1399,18 @@ u_alloc_line(size)
     curbuf->b_m_search = mprev;
     curbuf->b_mb_current = mbp;
 
+    /* If using the largest chunk need to find the new largest chunk */
+    if (mbp->mb_maxsize == 0)
+	for (mp2 = &(mbp->mb_info); mp2 != NULL; mp2 = mp2->m_next)
+	    if (mbp->mb_maxsize < mp2->m_size)
+		mbp->mb_maxsize = mp2->m_size;
+
     mp = (minfo_T *)((char_u *)mp + M_OFFSET);
     *(char_u *)mp = NUL;		    /* set the first byte to NUL */
 
     return ((char_u *)mp);
 }
+#endif
 
 /*
  * u_save_line(): allocate memory with u_alloc_line() and copy line 'lnum'
@@ -1360,7 +1426,7 @@ u_save_line(lnum)
 
     src = ml_get(lnum);
     len = (unsigned)STRLEN(src);
-    if ((dst = u_alloc_line(len)) != NULL)
+    if ((dst = U_ALLOC_LINE(len)) != NULL)
 	mch_memmove(dst, src, (size_t)(len + 1));
     return (dst);
 }
--- a/src/version.h
+++ b/src/version.h
@@ -36,5 +36,5 @@
 #define VIM_VERSION_NODOT	"vim70aa"
 #define VIM_VERSION_SHORT	"7.0aa"
 #define VIM_VERSION_MEDIUM	"7.0aa ALPHA"
-#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 12)"
-#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 12, compiled "
+#define VIM_VERSION_LONG	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 21)"
+#define VIM_VERSION_LONG_DATE	"VIM - Vi IMproved 7.0aa ALPHA (2005 Feb 21, compiled "