Blob Blame History Raw
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


*** ../vim-7.1.284/src/gui_mac.c	Wed Mar 12 21:47:31 2008
--- src/gui_mac.c	Sun Mar 16 15:25:13 2008
***************
*** 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);
  
*** ../vim-7.1.284/src/version.c	Thu Mar 20 13:22:47 2008
--- src/version.c	Thu Mar 20 14:38:06 2008
***************
*** 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    ///