# HG changeset patch # User vimboss # Date 1205329254 0 # Node ID 437fb19625c9e24e2157563cf0a55aeb432b2990 # Parent a83f48a17efb871266ffbcb3b6c9cd5a62408410 updated for version 7.1-275 diff --git a/src/gui_mac.c b/src/gui_mac.c --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -59,7 +59,33 @@ SInt32 gMacSystemVersion; #ifdef MACOS_CONVERT # define USE_CARBONKEYHANDLER + +static int im_is_active = FALSE; +#if 0 +static int im_start_row = 0; +static int im_start_col = 0; +#endif + +#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0])) + +static TSMDocumentID gTSMDocument; + +static void im_on_window_switch(int active); static EventHandlerUPP keyEventHandlerUPP = NULL; +static EventHandlerUPP winEventHandlerUPP = NULL; + +static pascal OSStatus gui_mac_handle_window_activate( + EventHandlerCallRef nextHandler, EventRef theEvent, void *data); + +static pascal OSStatus gui_mac_handle_text_input( + EventHandlerCallRef nextHandler, EventRef theEvent, void *data); + +static pascal OSStatus gui_mac_update_input_area( + EventHandlerCallRef nextHandler, EventRef theEvent); + +static pascal OSStatus gui_mac_unicode_key_event( + EventHandlerCallRef nextHandler, EventRef theEvent); + #endif @@ -137,7 +163,11 @@ static struct #ifdef MACOS_CONVERT # define USE_ATSUI_DRAWING +int p_macatsui_last; ATSUStyle gFontStyle; +# ifdef FEAT_MBYTE +ATSUStyle gWideFontStyle; +# endif Boolean gIsFontFallbackSet; #endif @@ -265,6 +295,11 @@ static void initialise_tabline(void); static WindowRef drawer = NULL; // TODO: put into gui.h #endif +#ifdef USE_ATSUI_DRAWING +static void gui_mac_set_font_attributes(GuiFont font); +static void gui_mac_dispose_atsui_style(void); +#endif + /* * ------------------------------------------------------------ * Conversion Utility @@ -1935,12 +1970,12 @@ gui_mac_doActivateEvent(EventRecord *eve /* Dim scrollbars */ if (whichWindow == gui.VimWindow) { - ControlRef rootControl; - GetRootControl(gui.VimWindow, &rootControl); - if ((event->modifiers) & activeFlag) - ActivateControl(rootControl); - else - DeactivateControl(rootControl); + ControlRef rootControl; + GetRootControl(gui.VimWindow, &rootControl); + if ((event->modifiers) & activeFlag) + ActivateControl(rootControl); + else + DeactivateControl(rootControl); } /* Activate */ @@ -1976,15 +2011,87 @@ gui_mac_doSuspendEvent(EventRecord *even * Handle the key */ #ifdef USE_CARBONKEYHANDLER - -static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the keys */ + static pascal OSStatus +gui_mac_handle_window_activate( + EventHandlerCallRef nextHandler, + EventRef theEvent, + void *data) +{ + UInt32 eventClass = GetEventClass(theEvent); + UInt32 eventKind = GetEventKind(theEvent); + + if (eventClass == kEventClassWindow) + { + switch (eventKind) + { + case kEventWindowActivated: +#if defined(USE_IM_CONTROL) + im_on_window_switch(TRUE); +#endif + return noErr; + + case kEventWindowDeactivated: +#if defined(USE_IM_CONTROL) + im_on_window_switch(FALSE); +#endif + return noErr; + } + } + + return eventNotHandledErr; +} + + static pascal OSStatus +gui_mac_handle_text_input( + EventHandlerCallRef nextHandler, + EventRef theEvent, + void *data) +{ + UInt32 eventClass = GetEventClass(theEvent); + UInt32 eventKind = GetEventKind(theEvent); + + if (eventClass != kEventClassTextInput) + return eventNotHandledErr; + + if ((kEventTextInputUpdateActiveInputArea != eventKind) && + (kEventTextInputUnicodeForKeyEvent != eventKind) && + (kEventTextInputOffsetToPos != eventKind) && + (kEventTextInputPosToOffset != eventKind) && + (kEventTextInputGetSelectedText != eventKind)) + return eventNotHandledErr; + + switch (eventKind) + { + case kEventTextInputUpdateActiveInputArea: + return gui_mac_update_input_area(nextHandler, theEvent); + case kEventTextInputUnicodeForKeyEvent: + return gui_mac_unicode_key_event(nextHandler, theEvent); + + case kEventTextInputOffsetToPos: + case kEventTextInputPosToOffset: + case kEventTextInputGetSelectedText: + break; + } + + return eventNotHandledErr; +} + + static pascal +OSStatus gui_mac_update_input_area( + EventHandlerCallRef nextHandler, + EventRef theEvent) +{ + return eventNotHandledErr; +} + +static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the + keys */ # define INLINE_KEY_BUFFER_SIZE 80 static pascal OSStatus -gui_mac_doKeyEventCarbon( +gui_mac_unicode_key_event( EventHandlerCallRef nextHandler, - EventRef theEvent, - void *data) + EventRef theEvent) { /* Multibyte-friendly key event handler */ OSStatus err = -1; @@ -2000,7 +2107,7 @@ gui_mac_doKeyEventCarbon( char_u *to = NULL; Boolean isSpecial = FALSE; int i; - EventRef keyEvent; + EventRef keyEvent; /* Mask the mouse (as per user setting) */ if (p_mh) @@ -2008,39 +2115,39 @@ gui_mac_doKeyEventCarbon( /* Don't use the keys when the dialog wants them. */ if (dialog_busy) - return eventNotHandledErr; + return eventNotHandledErr; if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, 0, &actualSize, NULL)) - return eventNotHandledErr; + typeUnicodeText, NULL, 0, &actualSize, NULL)) + return eventNotHandledErr; text = (UniChar *)alloc(actualSize); if (!text) - return eventNotHandledErr; + return eventNotHandledErr; err = GetEventParameter(theEvent, kEventParamTextInputSendText, - typeUnicodeText, NULL, actualSize, NULL, text); + typeUnicodeText, NULL, actualSize, NULL, text); require_noerr(err, done); err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent, - typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); + typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyModifiers, - typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); + typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyCode, - typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); + typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); require_noerr(err, done); err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes, - typeChar, NULL, sizeof(char), NULL, &charcode); + typeChar, NULL, sizeof(char), NULL, &charcode); require_noerr(err, done); #ifndef USE_CMD_KEY if (modifiers & cmdKey) - goto done; /* Let system handle Cmd+... */ + goto done; /* Let system handle Cmd+... */ #endif key_char = charcode; @@ -2048,84 +2155,84 @@ gui_mac_doKeyEventCarbon( /* 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 *)&vimModifiers); - isSpecial = TRUE; - break; - } + ((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 *)&vimModifiers); + isSpecial = TRUE; + break; + } } /* Intercept CMD-. and CTRL-c */ if (((modifiers & controlKey) && key_char == 'c') || - ((modifiers & cmdKey) && key_char == '.')) - got_int = TRUE; + ((modifiers & cmdKey) && key_char == '.')) + got_int = TRUE; if (!isSpecial) { - /* remove SHIFT for keys that are already shifted, e.g., - * '(' and '*' */ - if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char)) - vimModifiers &= ~MOD_MASK_SHIFT; - - /* remove CTRL from keys that already have it */ - if (key_char < 0x20) - vimModifiers &= ~MOD_MASK_CTRL; - - /* don't process unicode characters here */ - if (!IS_SPECIAL(key_char)) - { - /* Following code to simplify and consolidate vimModifiers - * taken liberally from gui_w48.c */ - key_char = simplify_key(key_char, (int *)&vimModifiers); - - /* Interpret META, include SHIFT, etc. */ - key_char = extract_modifiers(key_char, (int *)&vimModifiers); - if (key_char == CSI) - key_char = K_CSI; - - if (IS_SPECIAL(key_char)) - isSpecial = TRUE; - } + /* remove SHIFT for keys that are already shifted, e.g., + * '(' and '*' */ + if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char)) + vimModifiers &= ~MOD_MASK_SHIFT; + + /* remove CTRL from keys that already have it */ + if (key_char < 0x20) + vimModifiers &= ~MOD_MASK_CTRL; + + /* don't process unicode characters here */ + if (!IS_SPECIAL(key_char)) + { + /* Following code to simplify and consolidate vimModifiers + * taken liberally from gui_w48.c */ + key_char = simplify_key(key_char, (int *)&vimModifiers); + + /* Interpret META, include SHIFT, etc. */ + key_char = extract_modifiers(key_char, (int *)&vimModifiers); + if (key_char == CSI) + key_char = K_CSI; + + if (IS_SPECIAL(key_char)) + isSpecial = TRUE; + } } if (vimModifiers) { - result[len++] = CSI; - result[len++] = KS_MODIFIER; - result[len++] = vimModifiers; + result[len++] = CSI; + result[len++] = KS_MODIFIER; + result[len++] = vimModifiers; } if (isSpecial && IS_SPECIAL(key_char)) { - result[len++] = CSI; - result[len++] = K_SECOND(key_char); - result[len++] = K_THIRD(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); - } + 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); @@ -2135,10 +2242,10 @@ done: vim_free(text); if (err == noErr) { - /* Fake event to wake up WNE (required to get - * key repeat working */ - PostEvent(keyUp, 0); - return noErr; + /* Fake event to wake up WNE (required to get + * key repeat working */ + PostEvent(keyUp, 0); + return noErr; } return eventNotHandledErr; @@ -2334,7 +2441,7 @@ gui_mac_doMouseDownEvent(EventRecord *th /* prevent that the vim window size changes if it's activated by a click into the tab pane */ if (whichWindow == drawer) - return; + return; #endif switch (thePart) @@ -2569,11 +2676,11 @@ gui_mac_handle_event(EventRecord *event) if (IsShowContextualMenuClick(event)) { # if 0 - gui_mac_handle_contextual_menu(event); + gui_mac_handle_contextual_menu(event); # else - gui_mac_doMouseDownEvent(event); + gui_mac_doMouseDownEvent(event); # endif - return; + return; } /* Handle normal event */ @@ -2832,7 +2939,6 @@ gui_mch_prepare(int *argc, char **argv) # else /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr) * of TN2015 - * This technic remove the ../Contents/MacOS/etc part */ (void)GetCurrentProcess(&psn); /* if (err != noErr) return err; */ @@ -2933,10 +3039,9 @@ gui_mch_init(void) /* TODO: Move most of this stuff toward gui_mch_init */ Rect windRect; MenuHandle pomme; - EventTypeSpec eventTypeSpec; EventHandlerRef mouseWheelHandlerRef; #ifdef USE_CARBONKEYHANDLER - EventHandlerRef keyEventHandlerRef; + EventTypeSpec eventTypeSpec; #endif ControlRef rootControl; @@ -3042,16 +3147,47 @@ gui_mch_init(void) } #ifdef USE_CARBONKEYHANDLER - eventTypeSpec.eventClass = kEventClassTextInput; - eventTypeSpec.eventKind = kEventUnicodeForKeyEvent; - keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon); - if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1, - &eventTypeSpec, NULL, &keyEventHandlerRef)) - { - keyEventHandlerRef = NULL; + InterfaceTypeList supportedServices = { kUnicodeDocument }; + NewTSMDocument(1, supportedServices, &gTSMDocument, 0); + + /* We don't support inline input yet, use input window by default */ + UseInputWindow(gTSMDocument, TRUE); + + /* Should we activate the document by default? */ + // ActivateTSMDocument(gTSMDocument); + + EventTypeSpec textEventTypes[] = { + { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, + { kEventClassTextInput, kEventTextInputPosToOffset }, + { kEventClassTextInput, kEventTextInputOffsetToPos }, + }; + + keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input); + if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, + NR_ELEMS(textEventTypes), + textEventTypes, NULL, NULL)) + { DisposeEventHandlerUPP(keyEventHandlerUPP); keyEventHandlerUPP = NULL; } + + EventTypeSpec windowEventTypes[] = { + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + }; + + /* Install window event handler to support TSMDocument activate and + * deactivate */ + winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate); + if (noErr != InstallWindowEventHandler(gui.VimWindow, + winEventHandlerUPP, + NR_ELEMS(windowEventTypes), + windowEventTypes, NULL, NULL)) + { + DisposeEventHandlerUPP(winEventHandlerUPP); + winEventHandlerUPP = NULL; + } #endif /* @@ -3107,6 +3243,19 @@ gui_mch_open(void) return OK; } +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_dispose_atsui_style(void) +{ + if (p_macatsui && gFontStyle) + ATSUDisposeStyle(gFontStyle); +#ifdef FEAT_MBYTE + if (p_macatsui && gWideFontStyle) + ATSUDisposeStyle(gWideFontStyle); +#endif +} +#endif + void gui_mch_exit(int rc) { @@ -3122,8 +3271,13 @@ gui_mch_exit(int rc) DisposeEventHandlerUPP(mouseWheelHandlerUPP); #ifdef USE_ATSUI_DRAWING - if (p_macatsui && gFontStyle) - ATSUDisposeStyle(gFontStyle); + gui_mac_dispose_atsui_style(); +#endif + +#ifdef USE_CARBONKEYHANDLER + FixTSMDocument(gTSMDocument); + DeactivateTSMDocument(gTSMDocument); + DeleteTSMDocument(gTSMDocument); #endif /* Exit to shell? */ @@ -3263,6 +3417,26 @@ gui_mac_select_font(char_u *font_name) return selected_font; } +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_create_atsui_style(void) +{ + if (p_macatsui && gFontStyle == NULL) + { + if (ATSUCreateStyle(&gFontStyle) != noErr) + gFontStyle = NULL; + } +#ifdef FEAT_MBYTE + if (p_macatsui && gWideFontStyle == NULL) + { + if (ATSUCreateStyle(&gWideFontStyle) != noErr) + gWideFontStyle = NULL; + } +#endif + + p_macatsui_last = p_macatsui; +} +#endif /* * Initialise vim to use the font with the given name. Return FAIL if the font @@ -3280,11 +3454,7 @@ gui_mch_init_font(char_u *font_name, int char_u used_font_name[512]; #ifdef USE_ATSUI_DRAWING - if (p_macatsui && gFontStyle == NULL) - { - if (ATSUCreateStyle(&gFontStyle) != noErr) - gFontStyle = NULL; - } + gui_mac_create_atsui_style(); #endif if (font_name == NULL) @@ -3348,49 +3518,8 @@ gui_mch_init_font(char_u *font_name, int gui.char_height = font_info.ascent + font_info.descent + p_linespace; #ifdef USE_ATSUI_DRAWING - ATSUFontID fontID; - Fixed fontSize; - ATSStyleRenderingOptions fontOptions; - if (p_macatsui && gFontStyle) - { - fontID = font & 0xFFFF; - fontSize = Long2Fix(font >> 16); - - /* No antialiasing by default (do not attempt to touch antialising - * options on pre-Jaguar) */ - fontOptions = - (gMacSystemVersion >= 0x1020) ? - kATSStyleNoAntiAliasing : - 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; - } - } - } + gui_mac_set_font_attributes(font); #endif return OK; @@ -3447,6 +3576,68 @@ gui_mch_get_fontname(GuiFont font, char_ } #endif +#ifdef USE_ATSUI_DRAWING + static void +gui_mac_set_font_attributes(GuiFont font) +{ + ATSUFontID fontID; + Fixed fontSize; + Fixed fontWidth; + + fontID = font & 0xFFFF; + fontSize = Long2Fix(font >> 16); + fontWidth = Long2Fix(gui.char_width); + + ATSUAttributeTag attribTags[] = + { + kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag, + kATSUMaxATSUITagValue + 1 + }; + + ByteCount attribSizes[] = + { + sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth), + sizeof(font) + }; + + ATSUAttributeValuePtr attribValues[] = + { + &fontID, &fontSize, &fontWidth, &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; + } + +#ifdef FEAT_MBYTE + if (has_mbyte) + { + /* FIXME: we should use a more mbyte sensitive way to support + * wide font drawing */ + fontWidth = Long2Fix(gui.char_width * 2); + + if (ATSUSetAttributes(gWideFontStyle, + (sizeof attribTags) / sizeof(ATSUAttributeTag), + attribTags, attribSizes, attribValues) != noErr) + { + ATSUDisposeStyle(gWideFontStyle); + gWideFontStyle = NULL; + } + } +#endif + } +} +#endif + /* * Set the current text font. */ @@ -3456,63 +3647,19 @@ gui_mch_set_font(GuiFont font) #ifdef USE_ATSUI_DRAWING GuiFont currFont; ByteCount actualFontByteCount; - ATSUFontID fontID; - Fixed fontSize; - ATSStyleRenderingOptions fontOptions; if (p_macatsui && gFontStyle) { /* Avoid setting same font again */ - if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font, - &currFont, &actualFontByteCount) == noErr && - actualFontByteCount == (sizeof font)) + 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 = - (p_antialias && (font == gui.wide_font)) ? - kATSStyleNoOptions : kATSStyleNoAntiAliasing; - */ - /*fontOptions = kATSStyleAntiAliasing;*/ - - 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; - } - } - + gui_mac_set_font_attributes(font); } if (p_macatsui && !gIsFontFallbackSet) @@ -3536,7 +3683,9 @@ gui_mch_set_font(GuiFont font) &fallbackFonts, NULL) == noErr) { - ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred); + ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), + &fallbackFonts, + kATSUSequentialFallbacksPreferred); } /* ATSUAttributeValuePtr fallbackValues[] = { }; @@ -3921,7 +4070,10 @@ draw_string_ATSUI(int row, int col, char /* - ATSUI automatically antialiases text (Someone) * - for some reason it does not work... (Jussi) */ - +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n", + row, col, len, len == 1 ? s[0] : ' '); +#endif /* * When antialiasing we're using srcOr mode, we have to clear the block * before drawing the text. @@ -3956,35 +4108,122 @@ draw_string_ATSUI(int row, int col, char } { - /* Use old-style, non-antialiased QuickDraw text rendering. */ TextMode(srcCopy); TextFace(normal); - /* SelectFont(hdc, gui.currFont); */ - + /* SelectFont(hdc, gui.currFont); */ if (flags & DRAW_TRANSP) { TextMode(srcOr); } MoveTo(TEXT_X(col), TEXT_Y(row)); - ATSUTextLayout textLayout; - - if (ATSUCreateTextLayoutWithTextPtr(tofree, - kATSUFromTextBeginning, kATSUToTextEnd, - utf16_len, - (gFontStyle ? 1 : 0), &utf16_len, - (gFontStyle ? &gFontStyle : NULL), - &textLayout) == noErr) + + if (gFontStyle && flags & DRAW_BOLD) + { + Boolean attValue = true; + ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; + ByteCount attribSizes[] = { sizeof(Boolean) }; + ATSUAttributeValuePtr attribValues[] = { &attValue }; + + ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues); + } + +#ifdef FEAT_MBYTE + if (has_mbyte) { + int n, width_in_cell, last_width_in_cell; + UniCharArrayOffset offset = 0; + UniCharCount yet_to_draw = 0; + ATSUTextLayout textLayout; + ATSUStyle textStyle; + + last_width_in_cell = 1; + ATSUCreateTextLayout(&textLayout); + ATSUSetTextPointerLocation(textLayout, tofree, + kATSUFromTextBeginning, + kATSUToTextEnd, utf16_len); + /* + ATSUSetRunStyle(textLayout, gFontStyle, + kATSUFromTextBeginning, kATSUToTextEnd); */ + + /* Compute the length in display cells. */ + for (n = 0; n < len; n += MB_BYTE2LEN(s[n])) + { + width_in_cell = (*mb_ptr2cells)(s + n); + + /* probably we are switching from single byte character + * to multibyte characters (which requires more than one + * cell to draw) */ + if (width_in_cell != last_width_in_cell) + { +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", + n, last_width_in_cell, width_in_cell, offset, yet_to_draw); +#endif + textStyle = last_width_in_cell > 1 ? gWideFontStyle + : gFontStyle; + + ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw); + offset += yet_to_draw; + yet_to_draw = 0; + last_width_in_cell = width_in_cell; + } + + yet_to_draw++; + } + + if (yet_to_draw) + { +#ifdef MAC_ATSUI_DEBUG + fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n", + n, last_width_in_cell, width_in_cell, offset, yet_to_draw); +#endif + /* finish the rest style */ + textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle; + ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd); + } + ATSUSetTransientFontMatching(textLayout, TRUE); - ATSUDrawText(textLayout, - kATSUFromTextBeginning, kATSUToTextEnd, - kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); - + kATSUFromTextBeginning, kATSUToTextEnd, + kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); ATSUDisposeTextLayout(textLayout); } + else +#endif + { + 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); + } + } + + /* drawing is done, now reset bold to normal */ + if (gFontStyle && flags & DRAW_BOLD) + { + Boolean attValue = false; + + ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag }; + ByteCount attribSizes[] = { sizeof(Boolean) }; + ATSUAttributeValuePtr attribValues[] = { &attValue }; + + ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, + attribValues); + } } if (flags & DRAW_UNDERC) @@ -3998,6 +4237,13 @@ draw_string_ATSUI(int row, int col, char gui_mch_draw_string(int row, int col, char_u *s, int len, int flags) { #if defined(USE_ATSUI_DRAWING) + if (p_macatsui == 0 && p_macatsui_last != 0) + /* switch from macatsui to nomacatsui */ + gui_mac_dispose_atsui_style(); + else if (p_macatsui != 0 && p_macatsui_last == 0) + /* switch from nomacatsui to macatsui */ + gui_mac_create_atsui_style(); + if (p_macatsui) draw_string_ATSUI(row, col, s, len, flags); else @@ -4228,12 +4474,13 @@ gui_mch_wait_for_chars(int wtime) */ /* TODO: reduce wtime accordinly??? */ if (wtime > -1) - sleeppyTick = 60*wtime/1000; + sleeppyTick = 60 * wtime / 1000; else sleeppyTick = 32767; + if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn)) { - gui_mac_handle_event(&event); + gui_mac_handle_event(&event); if (input_available()) { allow_scrollbar = FALSE; @@ -6031,7 +6278,7 @@ char_u *FullPathFromFSSpec_save(FSSpec f #endif } -#if defined(USE_IM_CONTROL) || defined(PROTO) +#if (defined(USE_IM_CONTROL) || defined(PROTO)) && defined(USE_CARBONKEYHANDLER) /* * Input Method Control functions. */ @@ -6042,7 +6289,71 @@ char_u *FullPathFromFSSpec_save(FSSpec f void im_set_position(int row, int col) { +#if 0 /* TODO: Implement me! */ + im_start_row = row; + im_start_col = col; +#endif +} + +static ScriptLanguageRecord gTSLWindow; +static ScriptLanguageRecord gTSLInsert; +static ScriptLanguageRecord gTSLDefault = { 0, 0 }; + +static Component gTSCWindow; +static Component gTSCInsert; +static Component gTSCDefault; + +static int im_initialized = 0; + + static void +im_on_window_switch(int active) +{ + ScriptLanguageRecord *slptr = NULL; + OSStatus err; + + if (! gui.in_use) + return; + + if (im_initialized == 0) + { + im_initialized = 1; + + /* save default TSM component (should be U.S.) to default */ + GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + } + + if (active == TRUE) + { + im_is_active = TRUE; + ActivateTSMDocument(gTSMDocument); + slptr = &gTSLWindow; + + if (slptr) + { + err = SetDefaultInputMethodOfClass(gTSCWindow, slptr, + kKeyboardInputMethodClass); + if (err == noErr) + err = SetTextServiceLanguage(slptr); + + if (err == noErr) + KeyScript(slptr->fScript | smKeyForceKeyScriptMask); + } + } + else + { + err = GetTextServiceLanguage(&gTSLWindow); + if (err == noErr) + slptr = &gTSLWindow; + + if (slptr) + GetDefaultInputMethodOfClass(&gTSCWindow, slptr, + kKeyboardInputMethodClass); + + im_is_active = FALSE; + DeactivateTSMDocument(gTSMDocument); + } } /* @@ -6051,7 +6362,57 @@ im_set_position(int row, int col) void im_set_active(int active) { - KeyScript(active ? smKeySysScript : smKeyRoman); + ScriptLanguageRecord *slptr = NULL; + OSStatus err; + + if (! gui.in_use) + return; + + if (im_initialized == 0) + { + im_initialized = 1; + + /* save default TSM component (should be U.S.) to default */ + GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + } + + if (active == TRUE) + { + im_is_active = TRUE; + ActivateTSMDocument(gTSMDocument); + slptr = &gTSLInsert; + + if (slptr) + { + err = SetDefaultInputMethodOfClass(gTSCInsert, slptr, + kKeyboardInputMethodClass); + if (err == noErr) + err = SetTextServiceLanguage(slptr); + + if (err == noErr) + KeyScript(slptr->fScript | smKeyForceKeyScriptMask); + } + } + else + { + err = GetTextServiceLanguage(&gTSLInsert); + if (err == noErr) + slptr = &gTSLInsert; + + if (slptr) + GetDefaultInputMethodOfClass(&gTSCInsert, slptr, + kKeyboardInputMethodClass); + + /* restore to default when switch to normal mode, so than we could + * enter commands easier */ + SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault, + kKeyboardInputMethodClass); + SetTextServiceLanguage(&gTSLDefault); + + im_is_active = FALSE; + DeactivateTSMDocument(gTSMDocument); + } } /* @@ -6060,9 +6421,10 @@ im_set_active(int active) int im_get_status(void) { - SInt32 script = GetScriptManagerVariable(smKeyScript); - return (script != smRoman - && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0; + if (! gui.in_use) + return 0; + + return im_is_active; } #endif /* defined(USE_IM_CONTROL) || defined(PROTO) */ @@ -6118,7 +6480,7 @@ getTabCount(void) int numTabs = 0; for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) - ++numTabs; + ++numTabs; return numTabs; } @@ -6126,8 +6488,8 @@ getTabCount(void) static OSStatus dbItemDataCallback(ControlRef browser, DataBrowserItemID itemID, - DataBrowserPropertyID property /* column id */, - DataBrowserItemDataRef itemData, + DataBrowserPropertyID property /* column id */, + DataBrowserItemDataRef itemData, Boolean changeValue) { OSStatus status = noErr; @@ -6170,9 +6532,9 @@ dbItemNotificationCallback(ControlRef br static void dbGetContextualMenuCallback(ControlRef browser, MenuRef *menu, - UInt32 *helpType, + UInt32 *helpType, CFStringRef *helpItemString, - AEDesc *selection) + AEDesc *selection) { // on mac os 9: kCMHelpItemNoHelp, but it's not the same *helpType = kCMHelpItemRemoveHelp; // OS X only ;-) @@ -6395,9 +6757,9 @@ initialise_tabline(void) gui_mch_show_tabline(int showit) { if (showit == 0) - CloseDrawer(drawer, true); + CloseDrawer(drawer, true); else - OpenDrawer(drawer, kWindowEdgeRight, true); + OpenDrawer(drawer, kWindowEdgeRight, true); } /* @@ -6425,11 +6787,11 @@ gui_mch_update_tabline(void) // adjust data browser if (tabLabels != NULL) { - int i; - - for (i = 0; i < tabLabelsSize; ++i) - CFRelease(tabLabels[i]); - free(tabLabels); + int i; + + for (i = 0; i < tabLabelsSize; ++i) + CFRelease(tabLabels[i]); + free(tabLabels); } tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef)); tabLabelsSize = numTabs; @@ -6438,7 +6800,7 @@ gui_mch_update_tabline(void) { if (tp == curtab) curtabidx = nr; - tabLabels[nr-1] = getTabLabel(tp); + tabLabels[nr-1] = getTabLabel(tp); } RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL, diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -667,6 +667,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 275, +/**/ 274, /**/ 273, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -461,8 +461,9 @@ typedef unsigned long u8char_T; /* l /* * Check input method control. */ -#if defined(FEAT_XIM) || \ - (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) +#if defined(FEAT_XIM) \ + || (defined(FEAT_GUI) && (defined(FEAT_MBYTE_IME) || defined(GLOBAL_IME))) \ + || defined(FEAT_GUI_MAC) # define USE_IM_CONTROL #endif