1/*
2 * tkMacOSXKeyboard.c --
3 *
4 *	Routines to support keyboard events on the Macintosh.
5 *
6 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
7 * Copyright 2001-2009, Apple Inc.
8 * Copyright (c) 2005-2009 Daniel A. Steffen <das@users.sourceforge.net>
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id$
14 */
15
16#include "tkMacOSXPrivate.h"
17#include "tkMacOSXEvent.h"
18
19/*
20 * A couple of simple definitions to make code a bit more self-explaining.
21 *
22 * For the assignments of Mod1==meta==command and Mod2==alt==option, see also
23 * tkMacOSXMouseEvent.c.
24 */
25
26#define LATIN1_MAX	 255
27#define MAC_KEYCODE_MAX	 0x7F
28#define MAC_KEYCODE_MASK 0x7F
29#define COMMAND_MASK	 Mod1Mask
30#define OPTION_MASK	 Mod2Mask
31
32
33/*
34 * Tables enumerating the special keys defined on Mac keyboards. These are
35 * necessary for correct keysym mappings for all keys where the keysyms are
36 * not identical with their ASCII or Latin-1 code points.
37 */
38
39typedef struct {
40    int keycode;		/* Macintosh keycode. */
41    KeySym keysym;		/* X windows keysym. */
42} KeyInfo;
43
44/*
45 * Notes on keyArray:
46 *
47 * 0x34, XK_Return - Powerbooks use this and some keymaps define it.
48 *
49 * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
50 *
51 * 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
52 * applications don't use it like that, nor does Apple's X11.
53 *
54 * All other keycodes are taken from the published ADB keyboard layouts.
55 */
56
57static KeyInfo keyArray[] = {
58    {0x24,	XK_Return},
59    {0x30,	XK_Tab},
60    {0x33,	XK_BackSpace},
61    {0x34,	XK_Return},
62    {0x35,	XK_Escape},
63
64    {0x47,	XK_Clear},
65    {0x4C,	XK_KP_Enter},
66
67    {0x72,	XK_Help},
68    {0x73,	XK_Home},
69    {0x74,	XK_Page_Up},
70    {0x75,	XK_Delete},
71    {0x77,	XK_End},
72    {0x79,	XK_Page_Down},
73
74    {0x7B,	XK_Left},
75    {0x7C,	XK_Right},
76    {0x7D,	XK_Down},
77    {0x7E,	XK_Up},
78
79    {0,		0}
80};
81
82static KeyInfo virtualkeyArray[] = {
83    {122,	XK_F1},
84    {120,	XK_F2},
85    {99,	XK_F3},
86    {118,	XK_F4},
87    {96,	XK_F5},
88    {97,	XK_F6},
89    {98,	XK_F7},
90    {100,	XK_F8},
91    {101,	XK_F9},
92    {109,	XK_F10},
93    {103,	XK_F11},
94    {111,	XK_F12},
95    {105,	XK_F13},
96    {107,	XK_F14},
97    {113,	XK_F15},
98    {0,		0}
99};
100
101static int initialized = 0;
102static Tcl_HashTable keycodeTable;	/* keyArray hashed by keycode value. */
103static Tcl_HashTable vkeyTable;		/* virtualkeyArray hashed by virtual
104					 * keycode value. */
105
106static int latin1Table[LATIN1_MAX+1];	/* Reverse mapping table for
107					 * controls, ASCII and Latin-1. */
108
109static int keyboardChanged = 1;
110
111/*
112 * Prototypes for static functions used in this file.
113 */
114
115static void	InitKeyMaps (void);
116static void	InitLatin1Table(Display *display);
117static int	XKeysymToMacKeycode(Display *display, KeySym keysym);
118static int	KeycodeToUnicode(UniChar * uniChars, int maxChars,
119			UInt16 keyaction, UInt32 keycode, UInt32 modifiers,
120			UInt32 * deadKeyStatePtr);
121
122#pragma mark TKApplication(TKKeyboard)
123
124@implementation TKApplication(TKKeyboard)
125- (void)keyboardChanged:(NSNotification *)notification {
126#ifdef TK_MAC_DEBUG_NOTIFICATIONS
127    TKLog(@"-[%@(%p) %s] %@", [self class], self, _cmd, notification);
128#endif
129    keyboardChanged = 1;
130}
131@end
132
133#pragma mark -
134
135/*
136 *----------------------------------------------------------------------
137 *
138 * InitKeyMaps --
139 *
140 *	Creates hash tables used by some of the functions in this file.
141 *
142 *	FIXME: As keycodes are defined to be in the limited range 0-127, it
143 *	would be easier and more efficient to use directly initialized plain
144 *	arrays and drop this function.
145 *
146 * Results:
147 *	None.
148 *
149 * Side effects:
150 *	Allocates memory & creates some hash tables.
151 *
152 *----------------------------------------------------------------------
153 */
154
155static void
156InitKeyMaps(void)
157{
158    Tcl_HashEntry *hPtr;
159    KeyInfo *kPtr;
160    int dummy;
161
162    Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
163    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
164	hPtr = Tcl_CreateHashEntry(&keycodeTable, INT2PTR(kPtr->keycode),
165		&dummy);
166	Tcl_SetHashValue(hPtr, kPtr->keysym);
167    }
168    Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
169    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
170	hPtr = Tcl_CreateHashEntry(&vkeyTable, INT2PTR(kPtr->keycode),
171		&dummy);
172	Tcl_SetHashValue(hPtr, kPtr->keysym);
173    }
174    initialized = 1;
175}
176
177/*
178 *----------------------------------------------------------------------
179 *
180 * InitLatin1Table --
181 *
182 *	Creates a simple table to be used for mapping from keysyms to keycodes.
183 *	Always needs to be called before using latin1Table, because the
184 *	keyboard layout may have changed, and than the table must be
185 *	re-computed.
186 *
187 * Results:
188 *	None.
189 *
190 * Side effects:
191 *	Sets the global latin1Table.
192 *
193 *----------------------------------------------------------------------
194 */
195
196static void
197InitLatin1Table(
198    Display *display)
199{
200    int keycode;
201    KeySym keysym;
202    int state;
203    int modifiers;
204
205    memset(latin1Table, 0, sizeof(latin1Table));
206
207    /*
208     * In the common X11 implementations, a keymap has four columns
209     * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We don't
210     * use "Mode_switch", but we use "Option" instead. (This is similar to
211     * Apple's X11 implementation, where "Mode_switch" is used as an alias
212     * for "Option".)
213     *
214     * So here we go through all 4 columns of the keymap and find all
215     * Latin-1 compatible keycodes. We go through the columns back-to-front
216     * from the more exotic columns to the more simple, so that simple
217     * keycode-modifier combinations are preferred in the resulting table.
218     */
219
220    for (state = 3; state >= 0; state--) {
221	modifiers = 0;
222	if (state & 1) {
223	    modifiers |= shiftKey;
224	}
225	if (state & 2) {
226	    modifiers |= optionKey;
227	}
228
229	for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
230	    keysym = XKeycodeToKeysym(display,keycode<<16,state);
231	    if (keysym <= LATIN1_MAX) {
232		latin1Table[keysym] = keycode | modifiers;
233	    }
234	}
235    }
236}
237
238/*
239 *----------------------------------------------------------------------
240 *
241 * KeycodeToUnicode --
242 *
243 *	Given MacOS key event data this function generates the Unicode
244 *	characters. It does this using OS resources and APIs.
245 *
246 *	The parameter deadKeyStatePtr can be NULL, if no deadkey handling is
247 *	needed.
248 *
249 *	This function is called from XKeycodeToKeysym() in tkMacOSKeyboard.c.
250 *
251 * Results:
252 *	The number of characters generated if any, 0 if we are waiting for
253 *	another byte of a dead-key sequence. Fills in the uniChars array with a
254 *	Unicode string.
255 *
256 * Side Effects:
257 *	None
258 *
259 *----------------------------------------------------------------------
260 */
261
262static int
263KeycodeToUnicode(
264    UniChar *uniChars,
265    int maxChars,
266    UInt16 keyaction,
267    UInt32 keycode,
268    UInt32 modifiers,
269    UInt32 *deadKeyStatePtr)
270{
271    static const void *uchr = NULL;
272    static UInt32 keyboardType = 0;
273    UniCharCount actuallength = 0;
274
275    if (keyboardChanged) {
276	TISInputSourceRef currentKeyboardLayout =
277		TISCopyCurrentKeyboardLayoutInputSource();
278
279	if (currentKeyboardLayout) {
280	    CFDataRef keyLayoutData = (CFDataRef) TISGetInputSourceProperty(
281		    currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData);
282
283	    if (keyLayoutData) {
284		uchr = CFDataGetBytePtr(keyLayoutData);
285		keyboardType = LMGetKbdType();
286	    }
287	    CFRelease(currentKeyboardLayout);
288	}
289	keyboardChanged = 0;
290    }
291    if (uchr) {
292	OptionBits options = 0;
293	UInt32 dummyState;
294	OSStatus err;
295
296	keycode &= 0xFF;
297	modifiers = (modifiers >> 8) & 0xFF;
298
299	if (!deadKeyStatePtr) {
300	    options = kUCKeyTranslateNoDeadKeysMask;
301	    dummyState = 0;
302	    deadKeyStatePtr = &dummyState;
303	}
304
305	err = ChkErr(UCKeyTranslate, uchr, keycode, keyaction, modifiers,
306		keyboardType, options, deadKeyStatePtr, maxChars,
307		&actuallength, uniChars);
308
309	if (!actuallength && *deadKeyStatePtr) {
310	    /*
311	     * More data later
312	     */
313
314	    return 0;
315	}
316	*deadKeyStatePtr = 0;
317	if (err != noErr) {
318	    actuallength = 0;
319	}
320    }
321    return actuallength;
322}
323
324/*
325 *----------------------------------------------------------------------
326 *
327 * XKeycodeToKeysym --
328 *
329 *	Translate from a system-dependent keycode to a system-independent
330 *	keysym.
331 *
332 * Results:
333 *	Returns the translated keysym, or NoSymbol on failure.
334 *
335 * Side effects:
336 *	None.
337 *
338 *----------------------------------------------------------------------
339 */
340
341KeySym
342XKeycodeToKeysym(
343    Display* display,
344    KeyCode keycode,
345    int index)
346{
347    register Tcl_HashEntry *hPtr;
348    int newKeycode;
349    UniChar newChar;
350
351    (void) display; /*unused*/
352
353    if (!initialized) {
354	InitKeyMaps();
355    }
356
357    /*
358     * When determining what keysym to produce we first check to see if the key
359     * is a function key. We then check to see if the character is another
360     * non-printing key. Finally, we return the key syms for all ASCII and
361     * Latin-1 chars.
362     */
363
364    newKeycode = keycode >> 16;
365
366    if ((keycode & 0xFFFF) >= 0xF700) { /* NSEvent.h function key unicodes */
367	hPtr = Tcl_FindHashEntry(&vkeyTable, INT2PTR(newKeycode));
368	if (hPtr != NULL) {
369	    return (KeySym) Tcl_GetHashValue(hPtr);
370	}
371    }
372    hPtr = Tcl_FindHashEntry(&keycodeTable, INT2PTR(newKeycode));
373    if (hPtr != NULL) {
374	return (KeySym) Tcl_GetHashValue(hPtr);
375    }
376
377    /*
378     * Add in the Mac modifier flags for shift and option.
379     */
380
381    if (index & 1) {
382	newKeycode |= shiftKey;
383    }
384    if (index & 2) {
385	newKeycode |= optionKey;
386    }
387
388    newChar = 0;
389    KeycodeToUnicode(&newChar, 1, kUCKeyActionDown, newKeycode & 0x00FF,
390	    newKeycode & 0xFF00, NULL);
391
392    /*
393     * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up for
394     * other characters for now.
395     */
396
397    if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
398	return newChar;
399    }
400
401    return NoSymbol;
402}
403
404/*
405 *----------------------------------------------------------------------
406 *
407 * TkpGetString --
408 *
409 *	Retrieve the string equivalent for the given keyboard event.
410 *
411 * Results:
412 *	Returns the UTF string.
413 *
414 * Side effects:
415 *	None.
416 *
417 *----------------------------------------------------------------------
418 */
419
420char *
421TkpGetString(
422    TkWindow *winPtr,		/* Window where event occurred: Needed to get
423				 * input context. */
424    XEvent *eventPtr,		/* X keyboard event. */
425    Tcl_DString *dsPtr)		/* Uninitialized or empty string to hold
426				 * result. */
427{
428    (void) winPtr; /*unused*/
429    Tcl_DStringInit(dsPtr);
430    return Tcl_DStringAppend(dsPtr, eventPtr->xkey.trans_chars, -1);
431}
432
433/*
434 *----------------------------------------------------------------------
435 *
436 * XGetModifierMapping --
437 *
438 *	Fetch the current keycodes used as modifiers.
439 *
440 * Results:
441 *	Returns a new modifier map.
442 *
443 * Side effects:
444 *	Allocates a new modifier map data structure.
445 *
446 *----------------------------------------------------------------------
447 */
448
449XModifierKeymap *
450XGetModifierMapping(
451    Display *display)
452{
453    XModifierKeymap *modmap;
454
455    (void) display; /*unused*/
456
457    /*
458     * MacOSX doesn't use the key codes for the modifiers for anything, and we
459     * don't generate them either. So there is no modifier map.
460     */
461
462    modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
463    modmap->max_keypermod = 0;
464    modmap->modifiermap = NULL;
465    return modmap;
466}
467
468/*
469 *----------------------------------------------------------------------
470 *
471 * XFreeModifiermap --
472 *
473 *	Deallocate a modifier map that was created by XGetModifierMapping.
474 *
475 * Results:
476 *	None.
477 *
478 * Side effects:
479 *	Frees the datastructure referenced by modmap.
480 *
481 *----------------------------------------------------------------------
482 */
483
484void
485XFreeModifiermap(
486    XModifierKeymap *modmap)
487{
488    if (modmap->modifiermap != NULL) {
489	ckfree((char *) modmap->modifiermap);
490    }
491    ckfree((char *) modmap);
492}
493
494/*
495 *----------------------------------------------------------------------
496 *
497 * XKeysymToString, XStringToKeysym --
498 *
499 *	These X window functions map keysyms to strings & strings to keysyms.
500 *	However, Tk already does this for the most common keysyms. Therefore,
501 *	these functions only need to support keysyms that will be specific to
502 *	the Macintosh. Currently, there are none.
503 *
504 * Results:
505 *	None.
506 *
507 * Side effects:
508 *	None.
509 *
510 *----------------------------------------------------------------------
511 */
512
513char *
514XKeysymToString(
515    KeySym keysym)
516{
517    return NULL;
518}
519
520KeySym
521XStringToKeysym(
522    const char* string)
523{
524    return NoSymbol;
525}
526
527/*
528 *----------------------------------------------------------------------
529 *
530 * XKeysymToMacKeycode --
531 *
532 *	An internal function like XKeysymToKeycode but only generating the Mac
533 *	specific keycode plus the modifiers Shift and Option.
534 *
535 * Results:
536 *	A Mac keycode with the actual keycode in the low byte and Mac-style
537 *	modifier bits in the high byte.
538 *
539 * Side effects:
540 *	None.
541 *
542 *----------------------------------------------------------------------
543 */
544
545static int
546XKeysymToMacKeycode(
547    Display *display,
548    KeySym keysym)
549{
550    KeyInfo *kPtr;
551
552    if (keysym <= LATIN1_MAX) {
553	/*
554	 * Handle keysyms in the Latin-1 range where keysym and Unicode
555	 * character code point are the same.
556	 */
557
558	if (keyboardChanged) {
559	    InitLatin1Table(display);
560	    keyboardChanged = 0;
561	}
562	return latin1Table[keysym];
563    }
564
565    /*
566     * Handle special keys from our exception tables. Don't mind if this is
567     * slow, neither the test suite nor [event generate] need to be optimized
568     * (we hope).
569     */
570
571    for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
572	if (kPtr->keysym == keysym) {
573	    return kPtr->keycode;
574	}
575    }
576    for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
577	if (kPtr->keysym == keysym) {
578	    return kPtr->keycode;
579	}
580    }
581
582    /*
583     * For other keysyms (not Latin-1 and not special keys), we'd need a
584     * generic keysym-to-unicode table. We don't have that, so we give up here.
585     */
586
587    return 0;
588}
589
590/*
591 *----------------------------------------------------------------------
592 *
593 * XKeysymToKeycode --
594 *
595 *	The function XKeysymToKeycode takes an X11 keysym and converts it into
596 *	a Mac keycode. It is in the stubs table for compatibility but not used
597 *	anywhere in the core.
598 *
599 * Results:
600 *	A 32 bit keycode with the the mac keycode (without modifiers) in the
601 *	higher 16 bits of the keycode and the ASCII or Latin-1 code in the
602 *	lower 8 bits of the keycode.
603 *
604 * Side effects:
605 *	None.
606 *
607 *----------------------------------------------------------------------
608 */
609
610KeyCode
611XKeysymToKeycode(
612    Display* display,
613    KeySym keysym)
614{
615    int macKeycode = XKeysymToMacKeycode(display, keysym);
616    KeyCode result;
617
618    /*
619     * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
620     * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
621     * the keysym are usually a related ASCII control code.
622     */
623
624    if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
625	result = 0x0010;
626    } else {
627	result = 0x00FF & keysym;
628    }
629    result |= (macKeycode & MAC_KEYCODE_MASK) << 16;
630
631    return result;
632}
633
634/*
635 *----------------------------------------------------------------------
636 *
637 * TkpSetKeycodeAndState --
638 *
639 *	The function TkpSetKeycodeAndState takes a keysym and fills in the
640 *	appropriate members of an XEvent. It is similar to XKeysymToKeycode,
641 *	but it also sets the modifier mask in the XEvent. It is used by [event
642 *	generate] and it is in the stubs table.
643 *
644 * Results:
645 *	Fills an XEvent, sets the member xkey.keycode with a keycode
646 *	formatted the same as XKeysymToKeycode and the member xkey.state with
647 *	the modifiers implied by the keysym. Also fills in xkey.trans_chars,
648 *	so that the actual characters can be retrieved later.
649 *
650 * Side effects:
651 *	None.
652 *
653 *----------------------------------------------------------------------
654 */
655
656void
657TkpSetKeycodeAndState(
658    Tk_Window tkwin,
659    KeySym keysym,
660    XEvent *eventPtr)
661{
662    if (keysym == NoSymbol) {
663	eventPtr->xkey.keycode = 0;
664    } else {
665	Display *display = Tk_Display(tkwin);
666	int macKeycode = XKeysymToMacKeycode(display, keysym);
667
668	/*
669	 * See also XKeysymToKeycode.
670	 */
671
672	if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
673	    eventPtr->xkey.keycode = 0x0010;
674	} else {
675	    eventPtr->xkey.keycode = 0x00FF & keysym;
676	}
677	eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;
678
679	if (shiftKey & macKeycode) {
680	    eventPtr->xkey.state |= ShiftMask;
681	}
682	if (optionKey & macKeycode) {
683	    eventPtr->xkey.state |= OPTION_MASK;
684	}
685
686	if (keysym <= LATIN1_MAX) {
687	    int done = Tcl_UniCharToUtf(keysym, eventPtr->xkey.trans_chars);
688
689	    eventPtr->xkey.trans_chars[done] = 0;
690	} else {
691	    eventPtr->xkey.trans_chars[0] = 0;
692	}
693    }
694}
695
696/*
697 *----------------------------------------------------------------------
698 *
699 * TkpGetKeySym --
700 *
701 *	Given an X KeyPress or KeyRelease event, map the keycode in the event
702 *	into a keysym.
703 *
704 * Results:
705 *	The return value is the keysym corresponding to eventPtr, or NoSymbol
706 *	if no matching keysym could be found.
707 *
708 * Side effects:
709 *	In the first call for a given display, keycode-to-keysym maps get
710 *	loaded.
711 *
712 *----------------------------------------------------------------------
713 */
714
715KeySym
716TkpGetKeySym(
717    TkDisplay *dispPtr,		/* Display in which to map keycode. */
718    XEvent *eventPtr)		/* Description of X event. */
719{
720    KeySym sym;
721    int index;
722
723    /*
724     * Refresh the mapping information if it's stale.
725     */
726
727    if (dispPtr->bindInfoStale) {
728	TkpInitKeymapInfo(dispPtr);
729    }
730
731    /*
732     * Handle pure modifier keys specially. We use -1 as a signal for
733     * this.
734     */
735
736    if (eventPtr->xany.send_event == -1) {
737	int modifier = eventPtr->xkey.keycode;
738
739	if (modifier == NSCommandKeyMask) {
740	    return XK_Meta_L;
741	} else if (modifier == NSShiftKeyMask) {
742	    return XK_Shift_L;
743	} else if (modifier == NSAlphaShiftKeyMask) {
744	    return XK_Caps_Lock;
745	} else if (modifier == NSAlternateKeyMask) {
746	    return XK_Alt_L;
747	} else if (modifier == NSControlKeyMask) {
748	    return XK_Control_L;
749	} else if (modifier == NSNumericPadKeyMask) {
750	    return XK_Num_Lock;
751	} else if (modifier == NSFunctionKeyMask) {
752	    return XK_Super_L;
753/*
754	} else if (modifier == rightShiftKey) {
755	    return XK_Shift_R;
756	} else if (modifier == rightOptionKey) {
757	    return XK_Alt_R;
758	} else if (modifier == rightControlKey) {
759	    return XK_Control_R;
760*/
761	} else {
762	    /*
763	     * If we get here, we probably need to implement something new.
764	     */
765
766	    return NoSymbol;
767	}
768    }
769
770#if 0
771    if (eventPtr->xkey.nbytes) {
772	return eventPtr->xkey.nbytes;
773    }
774#endif
775
776    /*
777     * Figure out which of the four slots in the keymap vector to use for this
778     * key. Refer to Xlib documentation for more info on how this computation
779     * works. (Note: We use "Option" in keymap columns 2 and 3 where other
780     * implementations have "Mode_switch".)
781     */
782
783    index = 0;
784
785    /*
786     * We want Option key combinations to use their base chars as keysyms, so
787     * we ignore the option modifier here.
788     */
789
790#if 0
791    if (eventPtr->xkey.state & OPTION_MASK) {
792	index |= 2;
793    }
794#endif
795
796    if ((eventPtr->xkey.state & ShiftMask)
797	    || (/* (dispPtr->lockUsage != LU_IGNORE)
798	    && */ (eventPtr->xkey.state & LockMask))) {
799	index |= 1;
800    }
801
802    /*
803     * First try of the actual translation.
804     */
805
806    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
807
808    /*
809     * Special handling: If the key was shifted because of Lock, but lock is
810     * only caps lock, not shift lock, and the shifted keysym isn't upper-case
811     * alphabetic, then switch back to the unshifted keysym.
812     */
813
814    if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
815	    /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) {
816	/*
817	 * FIXME: Keysyms are only identical to Unicode for ASCII and Latin-1,
818	 * so we can't use Tcl_UniCharIsUpper() for keysyms outside that range.
819	 * This may be a serious problem here.
820	 */
821
822	if ((sym == NoSymbol) || (sym > LATIN1_MAX)
823		|| !Tcl_UniCharIsUpper(sym)) {
824	    index &= ~1;
825	    sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
826		    index);
827	}
828    }
829
830    /*
831     * Another bit of special handling: If this is a shifted key and there is
832     * no keysym defined, then use the keysym for the unshifted key.
833     */
834
835    if ((index & 1) && (sym == NoSymbol)) {
836	sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
837		index & ~1);
838    }
839    return sym;
840}
841
842/*
843 *--------------------------------------------------------------
844 *
845 * TkpInitKeymapInfo --
846 *
847 *	This procedure is invoked to scan keymap information to recompute stuff
848 *	that's important for binding, such as the modifier key (if any) that
849 *	corresponds to the "Mode_switch" keysym.
850 *
851 * Results:
852 *	None.
853 *
854 * Side effects:
855 *	Keymap-related information in dispPtr is updated.
856 *
857 *--------------------------------------------------------------
858 */
859
860void
861TkpInitKeymapInfo(
862    TkDisplay *dispPtr)		/* Display for which to recompute keymap
863				 * information. */
864{
865    dispPtr->bindInfoStale = 0;
866
867    /*
868     * Behaviours that are variable on X11 are defined constant on MacOSX.
869     * lockUsage is only used above in TkpGetKeySym(), nowhere else currently.
870     * There is no offical "Mode_switch" key.
871     */
872
873    dispPtr->lockUsage = LU_CAPS;
874    dispPtr->modeModMask = 0;
875
876#if 0
877    /*
878     * With this, <Alt> and <Meta> become synonyms for <Command> and <Option>
879     * in bindings like they are (and always have been) in the keysyms that
880     * are reported by KeyPress events. But the init scripts like text.tcl
881     * have some disabling bindings for <Meta>, so we don't want this without
882     * some changes in those scripts. See also bug #700311.
883     */
884
885    dispPtr->altModMask = OPTION_MASK;
886    dispPtr->metaModMask = COMMAND_MASK;
887#else
888    dispPtr->altModMask = 0;
889    dispPtr->metaModMask = 0;
890#endif
891
892    /*
893     * MacOSX doesn't use the keycodes for the modifiers for anything, and we
894     * don't generate them either (the keycodes actually given in the simulated
895     * modifier events are bogus). So there is no modifier map. If we ever want
896     * to simulate real modifier keycodes, the list will be constant in the
897     * Carbon implementation.
898     */
899
900    if (dispPtr->modKeyCodes != NULL) {
901	ckfree((char *) dispPtr->modKeyCodes);
902    }
903    dispPtr->numModKeyCodes = 0;
904    dispPtr->modKeyCodes = NULL;
905}
906
907/*
908 * Local Variables:
909 * mode: c
910 * c-basic-offset: 4
911 * fill-column: 79
912 * coding: utf-8
913 * End:
914 */
915