updated for version 7.0051
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 05c85b4..4c9d17d 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -681,16 +681,29 @@
 	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] == '\\')
 	    {
-		windgoto(msg_row, 0);
-		out_flush();
+		if (c == K_KENTER)
+		    c = '\n';
 	    }
-	    break;
+	    else
+	    {
+		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;
+	    }
 	}
 
 	/*
@@ -1879,25 +1892,24 @@
  * 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 @@
 
     /* 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 @@
 	    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)
 	{
-	    if (got_int)
+	    msg_putchar('\n');
+	    break;
+	}
+
+	if (!escaped)
+	{
+	    /* 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)
+		    else
 		    {
-			msg_col = startcol;
-			msg_clr_eos();
-			line_ga.ga_len = 0;
-			continue;
-		    }
-
-		    if (c1 == Ctrl_T)
-			c1 = TAB;	/* very simplistic... */
-
-		    if (c1 == Ctrl_D)
-		    {
-			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);
 		    }
 		}
+		msg_clr_eos();
+		continue;
+	    }
 
-		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)
+	    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;
 		}
-		++line_ga.ga_len;
-		escaped = FALSE;
+		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;
+		}
+		goto add_indent;
 	    }
-	    windgoto(msg_row, msg_col);
+
+	    if (c1 == Ctrl_V || c1 == Ctrl_Q)
+	    {
+		escaped = TRUE;
+		continue;
+	    }
+
+	    /* 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 @@
 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 @@
 	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 @@
      * Call the main loop until <CR> or CTRL-C is typed.
      */
     cmdwin_result = 0;
-    main_loop(TRUE);
+    main_loop(TRUE, FALSE);
 
     RedrawingDisabled = i;
 
diff --git a/src/gui_mac.c b/src/gui_mac.c
index dbdda8a..b43aec0 100644
--- a/src/gui_mac.c
+++ b/src/gui_mac.c
@@ -91,6 +91,19 @@
 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 @@
 } 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 @@
     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 @@
     /* 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 @@
  * 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 (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
+    {
+	/* Canonicalize localized font names */
+	if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
+		    gFontPanelInfo.style, &fid, NULL) != noErr)
+	    return;
 
-#if 0 /* TODO: enable when styles are supported in gui_mac_find_font() */
-    isBold = (gFontPanelInfo.style & bold);
-    isItalic = (gFontPanelInfo.style & italic);
-#endif
+	/* 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;
 
-    sprintf(&outName[buf[0]], ":h%d%s%s", gFontPanelInfo.size,
-	    (isBold ? ":b" : ""), (isItalic ? ":i" : ""));
+	/* 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 @@
 /*
  * 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 @@
 
     add_to_input_buf(string, len);
 }
+#endif
 
 /*
  * Handle MouseClick
@@ -2664,11 +2942,12 @@
     /* 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 @@
     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 @@
 	    }
 	}
 	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 @@
     {
 	/* 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 @@
     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,10 +3561,25 @@
     }
 #endif
 
-#ifdef FEAT_MBYTE
-    set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
+#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 *)"encoding", 0L, (char_u *)"utf-8", 0);
+#endif
+*/
+
     /* TODO: Load bitmap if using TOOLBAR */
     return OK;
 }
@@ -3290,11 +3628,21 @@
     /* 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 @@
     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 @@
     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_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 @@
     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 @@
 	    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 @@
 	/* 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 @@
      * 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 @@
     }
     else
 #endif
+#endif
     {
 	/* Use old-style, non-antialiased QuickDraw text rendering. */
 	TextMode(srcCopy);
@@ -3901,6 +4427,25 @@
 	}
 
 	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 @@
 	    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 @@
 {
     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_set_fg_color(color);
 
-    PaintRect(&rc);
+    FrameRect(&rc);
+//    PaintRect(&rc);
 }
 
 
@@ -4346,11 +4895,11 @@
 
     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 @@
 	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 @@
 	    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 @@
 
 	}
 
-#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 @@
 
     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 @@
 
 #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 @@
      */
     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 @@
 	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 @@
 	 * 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 @@
 	 * 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 @@
     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 @@
        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 @@
     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 @@
     /* 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
 
diff --git a/src/ops.c b/src/ops.c
index 7c426d1..78078c3 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -1105,10 +1105,20 @@
     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 @@
 	    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 @@
 	    }
 	    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 @@
 
     if (!valid_yank_reg(name, TRUE))	    /* check for valid reg name */
     {
-	EMSG2(_("E354: Invalid register name: '%s'"), transchar(name));
+	emsg_invreg(name);
 	return;
     }
 
diff --git a/src/option.c b/src/option.c
index 205b21c..4444b1f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -1723,8 +1723,8 @@
 #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 @@
 			    (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_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 @@
 
     /* 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 @@
 	    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 @@
      * 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 @@
     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 @@
 		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 @@
 	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 @@
     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 @@
 	option_value2string(p, opt_flags);
 	msg_outtrans(NameBuff);
     }
+
+    silent_mode = save_silent;
+    info_message = FALSE;
 }
 
 /*
diff --git a/src/option.h b/src/option.h
index 674eb4e..cd05f53 100644
--- 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_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 @@
 #ifdef AMIGA
 EXTERN long	p_st;		/* 'shelltype' */
 #endif
+EXTERN int	p_stmp;		/* 'shelltemp' */
 #ifdef BACKSLASH_IN_FILENAME
 EXTERN int	p_ssl;		/* 'shellslash' */
 #endif
diff --git a/src/os_mac_conv.c b/src/os_mac_conv.c
index 3f64e3d..68d46c0 100644
--- a/src/os_mac_conv.c
+++ b/src/os_mac_conv.c
@@ -21,6 +21,21 @@
 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 @@
 	*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 @@
     }
     if (cfstr == NULL)
 	return NULL;
+
     if (to == kCFStringEncodingUTF8)
 	buflen = len * 6 + 1;
     else
@@ -80,6 +98,22 @@
 	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 @@
 	    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 @@
     CFRelease(cfstr);
     if (lenp != NULL)
 	*lenp = strlen(retval);
+
     return retval;
 }
 
@@ -230,4 +266,291 @@
     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 */
diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak
index b69b5ab..c902614 100644
--- 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
 
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index d85ab2e..b430039 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -6,6 +6,9 @@
 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));
diff --git a/src/screen.c b/src/screen.c
index 6271b84..d3c9552 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -6847,18 +6847,6 @@
 }
 
 /*
- * 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.
diff --git a/src/search.c b/src/search.c
index 8520282..c9773b5 100644
--- a/src/search.c
+++ b/src/search.c
@@ -4715,7 +4715,7 @@
 	    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 '\' */
diff --git a/src/structs.h b/src/structs.h
index 92a8428..71c692a 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -307,7 +307,8 @@
 {
     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 @@
     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
diff --git a/src/syntax.c b/src/syntax.c
index bf9360f..5d08afa 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -4397,8 +4397,19 @@
 			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 @@
 	    }
 
 	    vim_free(keyword_copy);
+	    vim_free(syn_opt_arg.cont_in_list);
+	    vim_free(syn_opt_arg.next_list);
 	}
     }
 
@@ -4426,8 +4439,6 @@
     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. */
 }
diff --git a/src/term.c b/src/term.c
index 386b05c..12c506a 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1590,6 +1590,10 @@
     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 @@
 
     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
diff --git a/src/undo.c b/src/undo.c
index bdba903..4675d99 100644
--- 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 @@
 	 * 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 @@
 	/*
 	 * 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 @@
     /*
      * 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 @@
 	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 @@
 	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 @@
 		    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_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_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 @@
     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 @@
 {
     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 @@
     }
     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 @@
 }
 
 /*
- * 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 @@
 # 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 @@
 	    ;
 	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 @@
     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 @@
     }
     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 @@
 	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 @@
 	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 @@
     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 @@
 
     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);
 }
diff --git a/src/version.h b/src/version.h
index 1925a60..f73c68e 100644
--- 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 "