+static unsigned char fn_keycode_to_xkeysym_table[] = {
+ /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /*0x30*/ 0, 0, 0, 0,
+ /*0x34*/ 0, 0, 0, 0,
+ /*0x38*/ 0, 0, 0, 0,
+ /*0x3C*/ 0, 0, 0, 0,
+
+ /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
+ /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
+ /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
+ /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
+
+ /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
+ /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
+ /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
+ /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
+
+ /*0x60*/ 0, 0, 0, 0,
+ /*0x64*/ 0, 0, 0, 0,
+ /*0x68*/ 0, 0, 0, 0,
+ /*0x6C*/ 0, 0, 0, 0,
+
+ /*0x70*/ 0, 0, 0, 0,
+ /*0x74*/ 0, 0, 0, 0,
+ /*0x78*/ 0, 0, 0, 0,
+ /*0x7C*/ 0, 0, 0, 0
+};
+static int
+convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
+{
+#ifdef MAC_OSX
+ /* Use the special map to translate keys when function modifier is
+ to be caught. KeyTranslate can't be used in that case.
+ We can't detect the function key using the input_event.modifiers,
+ because this uses the high word of an UInt32. Therefore,
+ we'll just read it out of the original eventRef.
+ */
+
+
+ /* TODO / known issues
+
+ - Fn-Shift-j is regonized as Fn-j and not Fn-J.
+ The above table always translates to lower characters. We need to use
+ the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
+
+ - The table is meant for English language keyboards, and it will work
+ for many others with the exception of key combinations like Fn-ö on
+ a German keyboard, which is currently mapped to Fn-;.
+ How to solve this without keeping separate tables for all keyboards
+ around? KeyTranslate isn't of much help here, as it only takes a 16-bit
+ value for keycode with the modifiers in he high byte, i.e. no room for the
+ Fn modifier. That's why we need the table.
+
+ */
+ OSStatus err;
+ UInt32 mods = 0;
+ if (!NILP(Vmac_function_modifier))
+ {
+ err = GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
+ NULL, sizeof (UInt32), NULL, &mods);
+ if (err != noErr && mods & kEventKeyModifierFnMask)
+ { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
+
+ return (*newCode != 0);
+ }
+ }
+#endif
+ return false;
+}
+
+static int
+backtranslate_modified_keycode(int mods, int keycode, int def)
+{
+ EventModifiers mapped_modifiers =
+ (NILP (Vmac_control_modifier) ? 0 : controlKey)
+ | (NILP (Vmac_option_modifier) ? 0 : optionKey)
+ | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
+
+ if (mods & mapped_modifiers)
+ {
+ /* This code comes from Keyboard Resource,
+ Appendix C of IM - Text. This is necessary
+ since shift is ignored in KCHR table
+ translation when option or command is pressed.
+ It also does not translate correctly
+ control-shift chars like C-% so mask off shift
+ here also.
+
+ Not done for combinations with the option key (alt)
+ unless it is to be caught by Emacs: this is
+ to preserve key combinations translated by the OS
+ such as Alt-3.
+ */
+ /* Mask off modifier keys that are mapped to some Emacs
+ modifiers. */
+ int new_modifiers = mods & ~mapped_modifiers;
+ /* set high byte of keycode to modifier high byte*/
+ int new_keycode = keycode | new_modifiers;
+ Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+ unsigned long some_state = 0;
+ return (int) KeyTranslate (kchr_ptr, new_keycode,
+ &some_state) & 0xff;
+ /* TO DO: Recognize two separate resulting characters, "for
+ example, when the user presses Option-E followed by N, you
+ can map this through the KeyTranslate function using the
+ U.S. 'KCHR' resource to produce ´n, which KeyTranslate
+ returns as two characters in the bytes labeled Character code
+ 1 and Character code 2." (from Carbon API doc) */
+
+ }
+ else
+ return def;
+}
+
+
+#if !USE_CARBON_EVENTS
+static RgnHandle mouse_region = NULL;
+
+Boolean
+mac_wait_next_event (er, sleep_time, dequeue)
+ EventRecord *er;
+ UInt32 sleep_time;
+ Boolean dequeue;
+{
+ static EventRecord er_buf = {nullEvent};
+ UInt32 target_tick, current_tick;
+ EventMask event_mask;
+
+ if (mouse_region == NULL)
+ mouse_region = NewRgn ();
+
+ event_mask = everyEvent;
+ if (!mac_ready_for_apple_events)
+ event_mask -= highLevelEventMask;
+
+ current_tick = TickCount ();
+ target_tick = current_tick + sleep_time;
+
+ if (er_buf.what == nullEvent)
+ while (!WaitNextEvent (event_mask, &er_buf,
+ target_tick - current_tick, mouse_region))
+ {
+ current_tick = TickCount ();
+ if (target_tick <= current_tick)
+ return false;
+ }
+
+ *er = er_buf;
+ if (dequeue)
+ er_buf.what = nullEvent;
+ return true;
+}
+#endif /* not USE_CARBON_EVENTS */
+