1 /* darwin-new-keymap.c -- code to build a keymap from the system
2 $Id: darwin-new-keymap.c,v 1.7 2003/02/21 22:33:19 jharper Exp $
4 Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
6 Permission is hereby granted, free of charge, to any person
7 obtaining a copy of this software and associated documentation files
8 (the "Software"), to deal in the Software without restriction,
9 including without limitation the rights to use, copy, modify, merge,
10 publish, distribute, sublicense, and/or sell copies of the Software,
11 and to permit persons to whom the Software is furnished to do so,
12 subject to the following conditions:
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
21 HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name(s) of the above
27 copyright holders shall not be used in advertising or otherwise to
28 promote the sale, use or other dealings in this Software without
29 prior written authorization. */
32 #define Cursor X_Cursor
33 # include "darwin-keyboard.h"
37 #include <CoreServices/CoreServices.h>
38 #include <Carbon/Carbon.h>
40 #include "keysym2ucs.h"
42 #define HACK_MISSING 1
52 #define UKEYSYM(u) ((u) | 0x01000000)
54 /* Table of keycode->keysym mappings we use to fallback on for important
55 keys that are often not in the Unicode mapping. */
58 unsigned short keycode;
87 /* Table of keycode->old,new-keysym mappings we use to fixup the numeric
91 unsigned short keycode;
92 KeySym normal, keypad;
93 } known_numeric_keys[] = {
94 {65, XK_period, XK_KP_Decimal},
95 {67, XK_asterisk, XK_KP_Multiply},
96 {69, XK_plus, XK_KP_Add},
97 {75, XK_slash, XK_KP_Divide},
98 {76, 0x01000003, XK_KP_Enter},
99 {78, XK_minus, XK_KP_Subtract},
100 {81, XK_equal, XK_KP_Equal},
113 /* Table mapping normal keysyms to their dead equivalents.
114 FIXME: all the unicode keysyms (apart from circumflex) were guessed. */
116 const static struct {
119 {XK_grave, XK_dead_grave},
120 {XK_acute, XK_dead_acute},
121 {XK_asciicircum, XK_dead_circumflex},
122 {UKEYSYM (0x2c6), XK_dead_circumflex}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
123 {XK_asciitilde, XK_dead_tilde},
124 {UKEYSYM (0x2dc), XK_dead_tilde}, /* SMALL TILDE */
125 {XK_macron, XK_dead_macron},
126 {XK_breve, XK_dead_breve},
127 {XK_abovedot, XK_dead_abovedot},
128 {XK_diaeresis, XK_dead_diaeresis},
129 {UKEYSYM (0x2da), XK_dead_abovering}, /* DOT ABOVE */
130 {XK_doubleacute, XK_dead_doubleacute},
131 {XK_caron, XK_dead_caron},
132 {XK_cedilla, XK_dead_cedilla},
133 {XK_ogonek, XK_dead_ogonek},
134 {UKEYSYM (0x269), XK_dead_iota}, /* LATIN SMALL LETTER IOTA */
135 {UKEYSYM (0x2ec), XK_dead_voiced_sound}, /* MODIFIER LETTER VOICING */
136 /* {XK_semivoiced_sound, XK_dead_semivoiced_sound}, */
137 {UKEYSYM (0x323), XK_dead_belowdot}, /* COMBINING DOT BELOW */
138 {UKEYSYM (0x309), XK_dead_hook}, /* COMBINING HOOK ABOVE */
139 {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
143 DarwinSystemKeymapSeed (void)
145 static unsigned int seed;
147 static KeyboardLayoutRef last_key_layout;
148 KeyboardLayoutRef key_layout;
150 KLGetCurrentKeyboardLayout (&key_layout);
152 if (key_layout != last_key_layout)
155 last_key_layout = key_layout;
160 static inline UniChar
161 macroman2ucs (unsigned char c)
163 /* Precalculated table mapping MacRoman-128 to Unicode. Generated
164 by creating single element CFStringRefs then extracting the
167 static const unsigned short table[128] = {
168 0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
169 0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
170 0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
171 0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
172 0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
173 0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
174 0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
175 0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
176 0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
177 0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
178 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
179 0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
180 0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
181 0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
182 0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
183 0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7,
189 return table[c - 128];
193 make_dead_key (KeySym in)
197 for (i = 0; i < sizeof (dead_keys) / sizeof (dead_keys[0]); i++)
199 if (dead_keys[i].normal == in)
200 return dead_keys[i].dead;
207 DarwinReadSystemKeymap (darwin_keyboard_info *info)
209 KeyboardLayoutRef key_layout;
210 const void *chr_data;
211 int num_keycodes = NUM_KEYCODES;
212 UInt32 keyboard_type = 0;
217 KLGetCurrentKeyboardLayout (&key_layout);
218 KLGetKeyboardLayoutProperty (key_layout, kKLuchrData, &chr_data);
220 if (chr_data != NULL)
223 keyboard_type = LMGetKbdType ();
227 KLGetKeyboardLayoutProperty (key_layout, kKLKCHRData, &chr_data);
229 if (chr_data == NULL)
231 fprintf (stderr, "couldn't get uchr or kchr resource\n");
240 /* Scan the keycode range for the Unicode character that each
241 key produces in the four shift states. Then convert that to
242 an X11 keysym (which may just the bit that says "this is
243 Unicode" if it can't find the real symbol.) */
245 for (i = 0; i < num_keycodes; i++)
247 static const int mods[4] = {0, MOD_SHIFT, MOD_OPTION,
248 MOD_OPTION | MOD_SHIFT};
250 k = info->key_map + i * GLYPHS_PER_KEY;
252 for (j = 0; j < 4; j++)
258 UInt32 dead_key_state, extra_dead;
261 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
262 mods[j] >> 8, keyboard_type, 0,
263 &dead_key_state, 8, &len, s);
267 if (len == 0 && dead_key_state != 0)
269 /* Found a dead key. Work out which one it is, but
270 remembering that it's dead. */
273 err = UCKeyTranslate (chr_data, i, kUCKeyActionDown,
274 mods[j] >> 8, keyboard_type,
275 kUCKeyTranslateNoDeadKeysMask,
276 &extra_dead, 8, &len, s);
281 if (len > 0 && s[0] != 0x0010)
283 k[j] = ucs2keysym (s[0]);
285 if (dead_key_state != 0)
286 k[j] = make_dead_key (k[j]);
295 c = KeyTranslate (chr_data, code, &state);
297 /* Dead keys are only processed on key-down, so ask
298 to translate those events. When we find a dead key,
299 translating the matching key up event will give
300 us the actual dead character. */
305 c = KeyTranslate (chr_data, code | 128, &state2);
308 /* Characters seem to be in MacRoman encoding. */
310 if (c != 0 && c != 0x0010)
312 k[j] = ucs2keysym (macroman2ucs (c & 255));
315 k[j] = make_dead_key (k[j]);
326 if (k[0] == k[2] && k[1] == k[3])
327 k[2] = k[3] = NoSymbol;
330 /* Fix up some things that are normally missing.. */
334 for (i = 0; i < sizeof (known_keys) / sizeof (known_keys[0]); i++)
336 k = info->key_map + known_keys[i].keycode * GLYPHS_PER_KEY;
338 if (k[0] == NoSymbol && k[1] == NoSymbol
339 && k[2] == NoSymbol && k[3] == NoSymbol)
341 k[0] = known_keys[i].keysym;
346 /* And some more things. We find the right symbols for the numeric
347 keypad, but not the KP_ keysyms. So try to convert known keycodes. */
351 for (i = 0; i < sizeof (known_numeric_keys)
352 / sizeof (known_numeric_keys[0]); i++)
354 k = info->key_map + known_numeric_keys[i].keycode * GLYPHS_PER_KEY;
356 if (k[0] == known_numeric_keys[i].normal)
358 k[0] = known_numeric_keys[i].keypad;