summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2005-02-22 08:49:11 +0000
committerBram Moolenaar <Bram@vim.org>2005-02-22 08:49:11 +0000
commit26a60b45245080771bc2452b2634cb1f5acd60ed (patch)
tree82a54fd6544b2c2a57b5c52cb4d64c42dcd640a3 /src
parentdf177f679e950a2ab2ad5fe7d45c1daface004d7 (diff)
downloadvim-26a60b45245080771bc2452b2634cb1f5acd60ed.zip
updated for version 7.0051
Diffstat (limited to 'src')
-rw-r--r--src/ex_getln.c359
-rw-r--r--src/gui_mac.c721
-rw-r--r--src/ops.c22
-rw-r--r--src/option.c61
-rw-r--r--src/option.h7
-rw-r--r--src/os_mac_conv.c323
-rw-r--r--src/po/Make_mvc.mak4
-rw-r--r--src/proto/eval.pro3
-rw-r--r--src/screen.c12
-rw-r--r--src/search.c2
-rw-r--r--src/structs.h4
-rw-r--r--src/syntax.c17
-rw-r--r--src/term.c8
-rw-r--r--src/undo.c184
-rw-r--r--src/version.h4
15 files changed, 1398 insertions, 333 deletions
diff --git a/src/ex_getln.c b/src/ex_getln.c
index 05c85b49f..4c9d17d78 100644
--- 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] == '\\')
{
- windgoto(msg_row, 0);
- out_flush();
+ if (c == K_KENTER)
+ c = '\n';
+ }
+ 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;
}
- 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)
{
- if (got_int)
- {
- msg_putchar('\n');
- break;
- }
+ msg_putchar('\n');
+ break;
+ }
- while (len > 0)
+ 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)
{
- c1 = *pend++;
- --len;
- if ((c1 == K_SPECIAL
-# if !defined(NO_COOKED_INPUT) || defined(FEAT_GUI)
- || c1 == CSI
-# endif
- ) && len >= 2)
+ if (line_ga.ga_len > 0)
{
- c1 = TO_SPECIAL(pend[0], pend[1]);
- pend += 2;
- len -= 2;
+ --line_ga.ga_len;
+ goto redraw;
}
+ continue;
+ }
- 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)
- {
- if (line_ga.ga_len > 0)
- {
- 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;
- }
-
- if (c1 == Ctrl_U)
- {
- msg_col = startcol;
- msg_clr_eos();
- line_ga.ga_len = 0;
- continue;
- }
+ 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_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)
+ {
+ char_u *s = skipwhite(p);
- if (c1 == Ctrl_D)
+ ga_grow(&line_ga, 1);
+ mch_memmove(s + 1, s, line_ga.ga_len - (s - p) + 1);
+ *s = ' ';
+ ++line_ga.ga_len;
+ }
+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)
+ {
+ if (*p == TAB)
{
- 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)
+ do
{
- if (*p == TAB)
- {
- do
- {
- msg_putchar(' ');
- } while (++vcol % 8);
- }
- else
- {
- msg_outtrans_len(p, 1);
- vcol += char2cells(*p);
- }
- }
- msg_clr_eos();
- continue;
+ msg_putchar(' ');
+ } while (++vcol % 8);
}
-
- if (c1 == Ctrl_V)
+ else
{
- 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;
+ }
+ 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;
+ }
+
+ 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);
}
-# ifndef NO_COOKED_INPUT
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;
diff --git a/src/gui_mac.c b/src/gui_mac.c
index dbdda8a0d..b43aec0e5 100644
--- 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 **end, int vertical)
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, AppleEvent *theReply, long refCon)
/* 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 (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 @@ 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);
+ 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, flags)
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, flags)
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, flags)
/* 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, flags)
* 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, flags)
}
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, flags)
}
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, flags)
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
diff --git a/src/ops.c b/src/ops.c
index 7c426d147..78078c342 100644
--- 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, must_append, yank_type, block_len)
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 205b21c20..4444b1f89 100644
--- 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[]) = {"current", "last", "buffer", NULL};
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;
}
/*
diff --git a/src/option.h b/src/option.h
index 674eb4e5d..cd05f539e 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_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
diff --git a/src/os_mac_conv.c b/src/os_mac_conv.c
index 3f64e3da4..68d46c0f2 100644
--- a/src/os_mac_conv.c
+++ b/src/os_mac_conv.c
@@ -21,6 +21,21 @@ extern char_u *mac_string_convert __ARGS((char_u *ptr, int len, int *lenp, int f
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_on_error, from_enc, to_enc, unconvlenp)
*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_on_error, from_enc, to_enc, unconvlenp)
}
if (cfstr == NULL)
return NULL;
+
if (to == kCFStringEncodingUTF8)
buflen = len * 6 + 1;
else
@@ -80,6 +98,22 @@ mac_string_convert(ptr, len, lenp, fail_on_error, from_enc, to_enc, unconvlenp)
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_on_error, from_enc, to_enc, unconvlenp)
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_on_error, from_enc, to_enc, unconvlenp)
CFRelease(cfstr);
if (lenp != NULL)
*lenp = strlen(retval);
+
return retval;
}
@@ -230,4 +266,291 @@ enc2macroman(from, fromlen, to, tolenp, maxtolen, rest, restlenp)
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 b69b5abc5..c902614ac 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 d85ab2ef0..b43003967 100644
--- 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));
diff --git a/src/screen.c b/src/screen.c
index 6271b84c7..d3c9552e1 100644
--- 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.
diff --git a/src/search.c b/src/search.c
index 8520282a9..c9773b587 100644
--- a/src/search.c
+++ b/src/search.c
@@ -4715,7 +4715,7 @@ show_pat_in_path(line, type, did_show, action, fp, lnum, count)
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 92a8428f1..71c692ad1 100644
--- 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
diff --git a/src/syntax.c b/src/syntax.c
index bf9360f47..5d08afac0 100644
--- 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. */
}
diff --git a/src/term.c b/src/term.c
index 386b05cf5..12c506ab2 100644
--- 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
diff --git a/src/undo.c b/src/undo.c
index bdba903d8..4675d9972 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 @@ 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);
+ if (mbp == curbuf->b_mb_current)
+ {
+ int n = (size_align > (MEMBLOCKSIZE / 4)
+ ? size_align : MEMBLOCKSIZE);
+
+ /* 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;
+ }
}
- while (mp->m_size < size)
+ 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 == curbuf->b_m_search) /* back where we started in free
- chunk list */
+ 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)
{
- 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);
-
- 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 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);
}
diff --git a/src/version.h b/src/version.h
index 1925a60e6..f73c68e4f 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 "