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