To: vim-dev@vim.org Subject: Patch 7.0.138 (extra) Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 7.0.138 (extra) Problem: Mac: modifiers don't work with function keys. Solution: Use GetEventParameter() to obtain modifiers. (Nicolas Weber) Files: src/gui_mac.c *** ../vim-7.0.137/src/gui_mac.c Tue Aug 22 21:39:18 2006 --- src/gui_mac.c Sun Oct 15 14:53:38 2006 *************** *** 2014,2020 **** void *data) { /* Multibyte-friendly key event handler */ ! OSStatus e = -1; UInt32 actualSize; UniChar *text; char_u result[INLINE_KEY_BUFFER_SIZE]; --- 2014,2020 ---- void *data) { /* Multibyte-friendly key event handler */ ! OSStatus err = -1; UInt32 actualSize; UniChar *text; char_u result[INLINE_KEY_BUFFER_SIZE]; *************** *** 2022,2195 **** 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 ! { ! /* Don't use the keys when the dialog wants them. */ ! if (dialog_busy) ! break; ! 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 --- 2022,2174 ---- UInt32 key_sym; char charcode; int key_char; ! UInt32 modifiers, vimModifiers; size_t encLen; char_u *to = NULL; Boolean isSpecial = FALSE; int i; + EventRef keyEvent; /* Mask the mouse (as per user setting) */ if (p_mh) ObscureCursor(); ! /* Don't use the keys when the dialog wants them. */ ! if (dialog_busy) ! return eventNotHandledErr; ! ! if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText, ! typeUnicodeText, NULL, 0, &actualSize, NULL)) ! return eventNotHandledErr; ! ! text = (UniChar *)alloc(actualSize); ! if (!text) ! return eventNotHandledErr; ! ! err = GetEventParameter(theEvent, kEventParamTextInputSendText, ! typeUnicodeText, NULL, actualSize, NULL, text); ! require_noerr(err, done); ! ! err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent, ! typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent); ! require_noerr(err, done); ! ! err = GetEventParameter(keyEvent, kEventParamKeyModifiers, ! typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); ! require_noerr(err, done); ! ! err = GetEventParameter(keyEvent, kEventParamKeyCode, ! typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym); ! require_noerr(err, done); ! ! err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes, ! typeChar, NULL, sizeof(char), NULL, &charcode); ! require_noerr(err, done); ! #ifndef USE_CMD_KEY ! if (modifiers & cmdKey) ! goto done; /* Let system handle Cmd+... */ ! #endif ! key_char = charcode; ! vimModifiers = EventModifiers2VimModifiers(modifiers); ! /* 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; ! } ! } ! /* Intercept CMD-. and CTRL-c */ ! if (((modifiers & controlKey) && key_char == 'c') || ! ((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; ! } ! } ! if (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); ! } ! 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); ! err = noErr; ! done: ! vim_free(text); ! if (err == noErr) ! { ! /* Fake event to wake up WNE (required to get ! * key repeat working */ ! PostEvent(keyUp, 0); ! return noErr; } ! return eventNotHandledErr; } #else void *************** *** 5748,5754 **** /* TODO: Get the text selection from Vim */ /* Call to Handle Popup */ ! status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem); if (status == noErr) { --- 5727,5734 ---- /* TODO: Get the text selection from Vim */ /* Call to Handle Popup */ ! status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, ! HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem); if (status == noErr) { *************** *** 5756,5762 **** { /* Handle the menu CntxMenuID, CntxMenuItem */ /* The submenu can be handle directly by gui_mac_handle_menu */ ! /* But what about the current menu, is the menu changed by ContextualMenuSelect */ gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem); } else if (CntxMenuID == kCMShowHelpSelected) --- 5736,5743 ---- { /* Handle the menu CntxMenuID, CntxMenuItem */ /* The submenu can be handle directly by gui_mac_handle_menu */ ! /* But what about the current menu, is the menu changed by ! * ContextualMenuSelect */ gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem); } else if (CntxMenuID == kCMShowHelpSelected) *** ../vim-7.0.137/src/version.c Tue Oct 17 11:50:45 2006 --- src/version.c Tue Oct 17 12:51:21 2006 *************** *** 668,669 **** --- 668,671 ---- { /* Add new patch number below this line */ + /**/ + 138, /**/ -- hundred-and-one symptoms of being an internet addict: 52. You ask a plumber how much it would cost to replace the chair in front of your computer with a toilet. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ download, build and distribute -- http://www.A-A-P.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///