| To: vim-dev@vim.org |
| Subject: Patch 7.1.285 (extra) |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.1.285 (extra) |
| Problem: Mac: dialog hotkeys don't work. |
| Solution: Add hotkey support. (Dan Sandler) |
| Files: src/gui_mac.c |
| |
| |
| |
| |
| |
| *** 153,158 **** |
| --- 153,161 ---- |
| /* Keeping track of which scrollbar is being dragged */ |
| static ControlHandle dragged_sb = NULL; |
| |
| + /* Vector of char_u --> control index for hotkeys in dialogs */ |
| + static short *gDialogHotKeys; |
| + |
| static struct |
| { |
| FMFontFamily family; |
| |
| *** 5519,5524 **** |
| --- 5522,5570 ---- |
| SetDialogItemText(itemHandle, itemName); |
| } |
| |
| + |
| + /* ModalDialog() handler for message dialogs that have hotkey accelerators. |
| + * Expects a mapping of hotkey char to control index in gDialogHotKeys; |
| + * setting gDialogHotKeys to NULL disables any hotkey handling. |
| + */ |
| + static pascal Boolean |
| + DialogHotkeyFilterProc ( |
| + DialogRef theDialog, |
| + EventRecord *event, |
| + DialogItemIndex *itemHit) |
| + { |
| + char_u keyHit; |
| + |
| + if (event->what == keyDown || event->what == autoKey) |
| + { |
| + keyHit = (event->message & charCodeMask); |
| + |
| + if (gDialogHotKeys && gDialogHotKeys[keyHit]) |
| + { |
| + #ifdef DEBUG_MAC_DIALOG_HOTKEYS |
| + printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]); |
| + #endif |
| + *itemHit = gDialogHotKeys[keyHit]; |
| + |
| + /* When handing off to StdFilterProc, pretend that the user |
| + * clicked the control manually. Note that this is also supposed |
| + * to cause the button to hilite briefly (to give some user |
| + * feedback), but this seems not to actually work (or it's too |
| + * fast to be seen). |
| + */ |
| + event->what = kEventControlSimulateHit; |
| + |
| + return true; /* we took care of it */ |
| + } |
| + |
| + /* Defer to the OS's standard behavior for this event. |
| + * This ensures that Enter will still activate the default button. */ |
| + return StdFilterProc(theDialog, event, itemHit); |
| + } |
| + return false; /* Let ModalDialog deal with it */ |
| + } |
| + |
| + |
| /* TODO: There have been some crashes with dialogs, check your inbox |
| * (Jussi) |
| */ |
| |
| *** 5544,5549 **** |
| --- 5590,5597 ---- |
| GrafPtr oldPort; |
| short itemHit; |
| char_u *buttonChar; |
| + short hotKeys[256]; /* map of hotkey -> control ID */ |
| + char_u aHotKey; |
| Rect box; |
| short button; |
| short lastButton; |
| |
| *** 5571,5576 **** |
| --- 5619,5626 ---- |
| |
| WindowRef theWindow; |
| |
| + ModalFilterUPP dialogUPP; |
| + |
| /* Check 'v' flag in 'guioptions': vertical button placement. */ |
| vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL); |
| |
| |
| *** 5610,5615 **** |
| --- 5660,5668 ---- |
| buttonChar = buttons; |
| button = 0; |
| |
| + /* initialize the hotkey mapping */ |
| + memset(hotKeys, 0, sizeof(hotKeys)); |
| + |
| for (;*buttonChar != 0;) |
| { |
| /* Get the name of the button */ |
| |
| *** 5619,5625 **** |
| --- 5672,5689 ---- |
| { |
| if (*buttonChar != DLG_HOTKEY_CHAR) |
| name[++len] = *buttonChar; |
| + else |
| + { |
| + aHotKey = (char_u)*(buttonChar+1); |
| + if (aHotKey >= 'A' && aHotKey <= 'Z') |
| + aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A'); |
| + hotKeys[aHotKey] = button; |
| + #ifdef DEBUG_MAC_DIALOG_HOTKEYS |
| + printf("### hotKey for button %d is '%c'\n", button, aHotKey); |
| + #endif |
| + } |
| } |
| + |
| if (*buttonChar != 0) |
| buttonChar++; |
| name[0] = len; |
| |
| *** 5688,5694 **** |
| --- 5752,5764 ---- |
| (void) C2PascalString(textfield, &name); |
| SetDialogItemText(itemHandle, name); |
| inputItm.width = StringWidth(name); |
| + |
| + /* Hotkeys don't make sense if there's a text field */ |
| + gDialogHotKeys = NULL; |
| } |
| + else |
| + /* Install hotkey table */ |
| + gDialogHotKeys = (short *)&hotKeys; |
| |
| /* Set the <ENTER> and <ESC> button. */ |
| SetDialogDefaultItem(theDialog, dfltbutton); |
| |
| *** 5777,5786 **** |
| dialog_busy = TRUE; |
| #endif |
| |
| /* Hang until one of the button is hit */ |
| do |
| { |
| ! ModalDialog(nil, &itemHit); |
| } while ((itemHit < 1) || (itemHit > lastButton)); |
| |
| #ifdef USE_CARBONKEYHANDLER |
| --- 5847,5859 ---- |
| dialog_busy = TRUE; |
| #endif |
| |
| + /* Prepare the shortcut-handling filterProc for handing to the dialog */ |
| + dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc); |
| + |
| /* Hang until one of the button is hit */ |
| do |
| { |
| ! ModalDialog(dialogUPP, &itemHit); |
| } while ((itemHit < 1) || (itemHit > lastButton)); |
| |
| #ifdef USE_CARBONKEYHANDLER |
| |
| *** 5803,5808 **** |
| --- 5876,5884 ---- |
| /* Restore the original graphical port */ |
| SetPort(oldPort); |
| |
| + /* Free the modal filterProc */ |
| + DisposeRoutineDescriptor(dialogUPP); |
| + |
| /* Get ride of th edialog (free memory) */ |
| DisposeDialog(theDialog); |
| |
| |
| |
| |
| *** 668,669 **** |
| --- 668,671 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 285, |
| /**/ |
| |
| -- |
| hundred-and-one symptoms of being an internet addict: |
| 163. You go outside for the fresh air (at -30 degrees) but open the |
| window first to hear new mail arrive. |
| |
| /// 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 /// |