Release 1.5.29.
[wine] / dlls / winemac.drv / keyboard.c
1 /*
2  * MACDRV keyboard driver
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  * Copyright 1999 Ove Kåven
10  * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28
29 #include "macdrv.h"
30 #include "winuser.h"
31 #include "wine/unicode.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
34 WINE_DECLARE_DEBUG_CHANNEL(key);
35
36
37 /* Carbon-style modifier mask definitions from <Carbon/HIToolbox/Events.h>. */
38 enum {
39     cmdKeyBit       = 8,
40     shiftKeyBit     = 9,
41     alphaLockBit    = 10,
42     optionKeyBit    = 11,
43     controlKeyBit   = 12,
44 };
45
46 enum {
47     cmdKey      = 1 << cmdKeyBit,
48     shiftKey    = 1 << shiftKeyBit,
49     alphaLock   = 1 << alphaLockBit,
50     optionKey   = 1 << optionKeyBit,
51     controlKey  = 1 << controlKeyBit,
52 };
53
54
55 /* Mac virtual key code definitions from <Carbon/HIToolbox/Events.h>. */
56 enum {
57     kVK_ANSI_A              = 0x00,
58     kVK_ANSI_S              = 0x01,
59     kVK_ANSI_D              = 0x02,
60     kVK_ANSI_F              = 0x03,
61     kVK_ANSI_H              = 0x04,
62     kVK_ANSI_G              = 0x05,
63     kVK_ANSI_Z              = 0x06,
64     kVK_ANSI_X              = 0x07,
65     kVK_ANSI_C              = 0x08,
66     kVK_ANSI_V              = 0x09,
67     kVK_ISO_Section         = 0x0A,
68     kVK_ANSI_B              = 0x0B,
69     kVK_ANSI_Q              = 0x0C,
70     kVK_ANSI_W              = 0x0D,
71     kVK_ANSI_E              = 0x0E,
72     kVK_ANSI_R              = 0x0F,
73     kVK_ANSI_Y              = 0x10,
74     kVK_ANSI_T              = 0x11,
75     kVK_ANSI_1              = 0x12,
76     kVK_ANSI_2              = 0x13,
77     kVK_ANSI_3              = 0x14,
78     kVK_ANSI_4              = 0x15,
79     kVK_ANSI_6              = 0x16,
80     kVK_ANSI_5              = 0x17,
81     kVK_ANSI_Equal          = 0x18,
82     kVK_ANSI_9              = 0x19,
83     kVK_ANSI_7              = 0x1A,
84     kVK_ANSI_Minus          = 0x1B,
85     kVK_ANSI_8              = 0x1C,
86     kVK_ANSI_0              = 0x1D,
87     kVK_ANSI_RightBracket   = 0x1E,
88     kVK_ANSI_O              = 0x1F,
89     kVK_ANSI_U              = 0x20,
90     kVK_ANSI_LeftBracket    = 0x21,
91     kVK_ANSI_I              = 0x22,
92     kVK_ANSI_P              = 0x23,
93     kVK_Return              = 0x24,
94     kVK_ANSI_L              = 0x25,
95     kVK_ANSI_J              = 0x26,
96     kVK_ANSI_Quote          = 0x27,
97     kVK_ANSI_K              = 0x28,
98     kVK_ANSI_Semicolon      = 0x29,
99     kVK_ANSI_Backslash      = 0x2A,
100     kVK_ANSI_Comma          = 0x2B,
101     kVK_ANSI_Slash          = 0x2C,
102     kVK_ANSI_N              = 0x2D,
103     kVK_ANSI_M              = 0x2E,
104     kVK_ANSI_Period         = 0x2F,
105     kVK_Tab                 = 0x30,
106     kVK_Space               = 0x31,
107     kVK_ANSI_Grave          = 0x32,
108     kVK_Delete              = 0x33,
109     kVK_Escape              = 0x35,
110     kVK_RightCommand        = 0x36, /* invented for Wine; co-opt unused key code */
111     kVK_Command             = 0x37,
112     kVK_Shift               = 0x38,
113     kVK_CapsLock            = 0x39,
114     kVK_Option              = 0x3A,
115     kVK_Control             = 0x3B,
116     kVK_RightShift          = 0x3C,
117     kVK_RightOption         = 0x3D,
118     kVK_RightControl        = 0x3E,
119     kVK_Function            = 0x3F,
120     kVK_F17                 = 0x40,
121     kVK_ANSI_KeypadDecimal  = 0x41,
122     kVK_ANSI_KeypadMultiply = 0x43,
123     kVK_ANSI_KeypadPlus     = 0x45,
124     kVK_ANSI_KeypadClear    = 0x47,
125     kVK_VolumeUp            = 0x48,
126     kVK_VolumeDown          = 0x49,
127     kVK_Mute                = 0x4A,
128     kVK_ANSI_KeypadDivide   = 0x4B,
129     kVK_ANSI_KeypadEnter    = 0x4C,
130     kVK_ANSI_KeypadMinus    = 0x4E,
131     kVK_F18                 = 0x4F,
132     kVK_F19                 = 0x50,
133     kVK_ANSI_KeypadEquals   = 0x51,
134     kVK_ANSI_Keypad0        = 0x52,
135     kVK_ANSI_Keypad1        = 0x53,
136     kVK_ANSI_Keypad2        = 0x54,
137     kVK_ANSI_Keypad3        = 0x55,
138     kVK_ANSI_Keypad4        = 0x56,
139     kVK_ANSI_Keypad5        = 0x57,
140     kVK_ANSI_Keypad6        = 0x58,
141     kVK_ANSI_Keypad7        = 0x59,
142     kVK_F20                 = 0x5A,
143     kVK_ANSI_Keypad8        = 0x5B,
144     kVK_ANSI_Keypad9        = 0x5C,
145     kVK_JIS_Yen             = 0x5D,
146     kVK_JIS_Underscore      = 0x5E,
147     kVK_JIS_KeypadComma     = 0x5F,
148     kVK_F5                  = 0x60,
149     kVK_F6                  = 0x61,
150     kVK_F7                  = 0x62,
151     kVK_F3                  = 0x63,
152     kVK_F8                  = 0x64,
153     kVK_F9                  = 0x65,
154     kVK_JIS_Eisu            = 0x66,
155     kVK_F11                 = 0x67,
156     kVK_JIS_Kana            = 0x68,
157     kVK_F13                 = 0x69,
158     kVK_F16                 = 0x6A,
159     kVK_F14                 = 0x6B,
160     kVK_F10                 = 0x6D,
161     kVK_F12                 = 0x6F,
162     kVK_F15                 = 0x71,
163     kVK_Help                = 0x72,
164     kVK_Home                = 0x73,
165     kVK_PageUp              = 0x74,
166     kVK_ForwardDelete       = 0x75,
167     kVK_F4                  = 0x76,
168     kVK_End                 = 0x77,
169     kVK_F2                  = 0x78,
170     kVK_PageDown            = 0x79,
171     kVK_F1                  = 0x7A,
172     kVK_LeftArrow           = 0x7B,
173     kVK_RightArrow          = 0x7C,
174     kVK_DownArrow           = 0x7D,
175     kVK_UpArrow             = 0x7E,
176 };
177
178
179 /* Indexed by Mac virtual keycode values defined above. */
180 static const struct {
181     WORD vkey;
182     WORD scan;
183     BOOL fixed;
184 } default_map[128] = {
185     { 'A',                      0x1E,           FALSE },    /* kVK_ANSI_A */
186     { 'S',                      0x1F,           FALSE },    /* kVK_ANSI_S */
187     { 'D',                      0x20,           FALSE },    /* kVK_ANSI_D */
188     { 'F',                      0x21,           FALSE },    /* kVK_ANSI_F */
189     { 'H',                      0x23,           FALSE },    /* kVK_ANSI_H */
190     { 'G',                      0x22,           FALSE },    /* kVK_ANSI_G */
191     { 'Z',                      0x2C,           FALSE },    /* kVK_ANSI_Z */
192     { 'X',                      0x2D,           FALSE },    /* kVK_ANSI_X */
193     { 'C',                      0x2E,           FALSE },    /* kVK_ANSI_C */
194     { 'V',                      0x2F,           FALSE },    /* kVK_ANSI_V */
195     { VK_OEM_102,               0x56,           TRUE },     /* kVK_ISO_Section */
196     { 'B',                      0x30,           FALSE },    /* kVK_ANSI_B */
197     { 'Q',                      0x10,           FALSE },    /* kVK_ANSI_Q */
198     { 'W',                      0x11,           FALSE },    /* kVK_ANSI_W */
199     { 'E',                      0x12,           FALSE },    /* kVK_ANSI_E */
200     { 'R',                      0x13,           FALSE },    /* kVK_ANSI_R */
201     { 'Y',                      0x15,           FALSE },    /* kVK_ANSI_Y */
202     { 'T',                      0x14,           FALSE },    /* kVK_ANSI_T */
203     { '1',                      0x02,           FALSE },    /* kVK_ANSI_1 */
204     { '2',                      0x03,           FALSE },    /* kVK_ANSI_2 */
205     { '3',                      0x04,           FALSE },    /* kVK_ANSI_3 */
206     { '4',                      0x05,           FALSE },    /* kVK_ANSI_4 */
207     { '6',                      0x07,           FALSE },    /* kVK_ANSI_6 */
208     { '5',                      0x06,           FALSE },    /* kVK_ANSI_5 */
209     { VK_OEM_PLUS,              0x0D,           FALSE },    /* kVK_ANSI_Equal */
210     { '9',                      0x0A,           FALSE },    /* kVK_ANSI_9 */
211     { '7',                      0x08,           FALSE },    /* kVK_ANSI_7 */
212     { VK_OEM_MINUS,             0x0C,           FALSE },    /* kVK_ANSI_Minus */
213     { '8',                      0x09,           FALSE },    /* kVK_ANSI_8 */
214     { '0',                      0x0B,           FALSE },    /* kVK_ANSI_0 */
215     { VK_OEM_6,                 0x1B,           FALSE },    /* kVK_ANSI_RightBracket */
216     { 'O',                      0x18,           FALSE },    /* kVK_ANSI_O */
217     { 'U',                      0x16,           FALSE },    /* kVK_ANSI_U */
218     { VK_OEM_4,                 0x1A,           FALSE },    /* kVK_ANSI_LeftBracket */
219     { 'I',                      0x17,           FALSE },    /* kVK_ANSI_I */
220     { 'P',                      0x19,           FALSE },    /* kVK_ANSI_P */
221     { VK_RETURN,                0x1C,           TRUE },     /* kVK_Return */
222     { 'L',                      0x26,           FALSE },    /* kVK_ANSI_L */
223     { 'J',                      0x24,           FALSE },    /* kVK_ANSI_J */
224     { VK_OEM_7,                 0x28,           FALSE },    /* kVK_ANSI_Quote */
225     { 'K',                      0x25,           FALSE },    /* kVK_ANSI_K */
226     { VK_OEM_1,                 0x27,           FALSE },    /* kVK_ANSI_Semicolon */
227     { VK_OEM_5,                 0x2B,           FALSE },    /* kVK_ANSI_Backslash */
228     { VK_OEM_COMMA,             0x33,           FALSE },    /* kVK_ANSI_Comma */
229     { VK_OEM_2,                 0x35,           FALSE },    /* kVK_ANSI_Slash */
230     { 'N',                      0x31,           FALSE },    /* kVK_ANSI_N */
231     { 'M',                      0x32,           FALSE },    /* kVK_ANSI_M */
232     { VK_OEM_PERIOD,            0x34,           FALSE },    /* kVK_ANSI_Period */
233     { VK_TAB,                   0x0F,           TRUE },     /* kVK_Tab */
234     { VK_SPACE,                 0x39,           TRUE },     /* kVK_Space */
235     { VK_OEM_3,                 0x29,           FALSE },    /* kVK_ANSI_Grave */
236     { VK_BACK,                  0x0E,           TRUE },     /* kVK_Delete */
237     { 0,                        0,              FALSE },    /* 0x34 unused */
238     { VK_ESCAPE,                0x01,           TRUE },     /* kVK_Escape */
239     { VK_RMENU,                 0x38 | 0x100,   TRUE },     /* kVK_RightCommand */
240     { VK_LMENU,                 0x38,           TRUE },     /* kVK_Command */
241     { VK_LSHIFT,                0x2A,           TRUE },     /* kVK_Shift */
242     { VK_CAPITAL,               0x3A,           TRUE },     /* kVK_CapsLock */
243     { 0,                        0,              FALSE },    /* kVK_Option */
244     { VK_LCONTROL,              0x1D,           TRUE },     /* kVK_Control */
245     { VK_RSHIFT,                0x36,           TRUE },     /* kVK_RightShift */
246     { 0,                        0,              FALSE },    /* kVK_RightOption */
247     { VK_RCONTROL,              0x1D | 0x100,   TRUE },     /* kVK_RightControl */
248     { 0,                        0,              FALSE },    /* kVK_Function */
249     { VK_F17,                   0x68,           TRUE },     /* kVK_F17 */
250     { VK_DECIMAL,               0x53,           TRUE },     /* kVK_ANSI_KeypadDecimal */
251     { 0,                        0,              FALSE },    /* 0x42 unused */
252     { VK_MULTIPLY,              0x37,           TRUE },     /* kVK_ANSI_KeypadMultiply */
253     { 0,                        0,              FALSE },    /* 0x44 unused */
254     { VK_ADD,                   0x4E,           TRUE },     /* kVK_ANSI_KeypadPlus */
255     { 0,                        0,              FALSE },    /* 0x46 unused */
256     { VK_OEM_CLEAR,             0x59,           TRUE },     /* kVK_ANSI_KeypadClear */
257     { VK_VOLUME_UP,             0 | 0x100,      TRUE },     /* kVK_VolumeUp */
258     { VK_VOLUME_DOWN,           0 | 0x100,      TRUE },     /* kVK_VolumeDown */
259     { VK_VOLUME_MUTE,           0 | 0x100,      TRUE },     /* kVK_Mute */
260     { VK_DIVIDE,                0x35 | 0x100,   TRUE },     /* kVK_ANSI_KeypadDivide */
261     { VK_RETURN,                0x1C | 0x100,   TRUE },     /* kVK_ANSI_KeypadEnter */
262     { 0,                        0,              FALSE },    /* 0x4D unused */
263     { VK_SUBTRACT,              0x4A,           TRUE },     /* kVK_ANSI_KeypadMinus */
264     { VK_F18,                   0x69,           TRUE },     /* kVK_F18 */
265     { VK_F19,                   0x6A,           TRUE },     /* kVK_F19 */
266     { VK_OEM_NEC_EQUAL,         0x0D | 0x100,   TRUE },     /* kVK_ANSI_KeypadEquals */
267     { VK_NUMPAD0,               0x52,           TRUE },     /* kVK_ANSI_Keypad0 */
268     { VK_NUMPAD1,               0x4F,           TRUE },     /* kVK_ANSI_Keypad1 */
269     { VK_NUMPAD2,               0x50,           TRUE },     /* kVK_ANSI_Keypad2 */
270     { VK_NUMPAD3,               0x51,           TRUE },     /* kVK_ANSI_Keypad3 */
271     { VK_NUMPAD4,               0x4B,           TRUE },     /* kVK_ANSI_Keypad4 */
272     { VK_NUMPAD5,               0x4C,           TRUE },     /* kVK_ANSI_Keypad5 */
273     { VK_NUMPAD6,               0x4D,           TRUE },     /* kVK_ANSI_Keypad6 */
274     { VK_NUMPAD7,               0x47,           TRUE },     /* kVK_ANSI_Keypad7 */
275     { VK_F20,                   0x6B,           TRUE },     /* kVK_F20 */
276     { VK_NUMPAD8,               0x48,           TRUE },     /* kVK_ANSI_Keypad8 */
277     { VK_NUMPAD9,               0x49,           TRUE },     /* kVK_ANSI_Keypad9 */
278     { 0xFF,                     0x7D,           TRUE },     /* kVK_JIS_Yen */
279     { 0xC1,                     0x73,           TRUE },     /* kVK_JIS_Underscore */
280     { VK_SEPARATOR,             0x7E,           TRUE },     /* kVK_JIS_KeypadComma */
281     { VK_F5,                    0x3F,           TRUE },     /* kVK_F5 */
282     { VK_F6,                    0x40,           TRUE },     /* kVK_F6 */
283     { VK_F7,                    0x41,           TRUE },     /* kVK_F7 */
284     { VK_F3,                    0x3D,           TRUE },     /* kVK_F3 */
285     { VK_F8,                    0x42,           TRUE },     /* kVK_F8 */
286     { VK_F9,                    0x43,           TRUE },     /* kVK_F9 */
287     { 0xFF,                     0x72,           TRUE },     /* kVK_JIS_Eisu */
288     { VK_F11,                   0x57,           TRUE },     /* kVK_F11 */
289     { VK_OEM_RESET,             0x71,           TRUE },     /* kVK_JIS_Kana */
290     { VK_F13,                   0x64,           TRUE },     /* kVK_F13 */
291     { VK_F16,                   0x67,           TRUE },     /* kVK_F16 */
292     { VK_F14,                   0x65,           TRUE },     /* kVK_F14 */
293     { 0,                        0,              FALSE },    /* 0x6C unused */
294     { VK_F10,                   0x44,           TRUE },     /* kVK_F10 */
295     { 0,                        0,              FALSE },    /* 0x6E unused */
296     { VK_F12,                   0x58,           TRUE },     /* kVK_F12 */
297     { 0,                        0,              FALSE },    /* 0x70 unused */
298     { VK_F15,                   0x66,           TRUE },     /* kVK_F15 */
299     { VK_INSERT,                0x52 | 0x100,   TRUE },     /* kVK_Help */ /* map to Insert */
300     { VK_HOME,                  0x47 | 0x100,   TRUE },     /* kVK_Home */
301     { VK_PRIOR,                 0x49 | 0x100,   TRUE },     /* kVK_PageUp */
302     { VK_DELETE,                0x53 | 0x100,   TRUE },     /* kVK_ForwardDelete */
303     { VK_F4,                    0x3E,           TRUE },     /* kVK_F4 */
304     { VK_END,                   0x4F | 0x100,   TRUE },     /* kVK_End */
305     { VK_F2,                    0x3C,           TRUE },     /* kVK_F2 */
306     { VK_NEXT,                  0x51 | 0x100,   TRUE },     /* kVK_PageDown */
307     { VK_F1,                    0x3B,           TRUE },     /* kVK_F1 */
308     { VK_LEFT,                  0x4B | 0x100,   TRUE },     /* kVK_LeftArrow */
309     { VK_RIGHT,                 0x4D | 0x100,   TRUE },     /* kVK_RightArrow */
310     { VK_DOWN,                  0x50 | 0x100,   TRUE },     /* kVK_DownArrow */
311     { VK_UP,                    0x48 | 0x100,   TRUE },     /* kVK_UpArrow */
312 };
313
314
315 static const struct {
316     DWORD       vkey;
317     const char *name;
318 } vkey_names[] = {
319     { VK_ADD,                   "Num +" },
320     { VK_BACK,                  "Backspace" },
321     { VK_CAPITAL,               "Caps Lock" },
322     { VK_CONTROL,               "Ctrl" },
323     { VK_DECIMAL,               "Num Del" },
324     { VK_DELETE | 0x100,        "Delete" },
325     { VK_DIVIDE | 0x100,        "Num /" },
326     { VK_DOWN | 0x100,          "Down" },
327     { VK_END | 0x100,           "End" },
328     { VK_ESCAPE,                "Esc" },
329     { VK_F1,                    "F1" },
330     { VK_F2,                    "F2" },
331     { VK_F3,                    "F3" },
332     { VK_F4,                    "F4" },
333     { VK_F5,                    "F5" },
334     { VK_F6,                    "F6" },
335     { VK_F7,                    "F7" },
336     { VK_F8,                    "F8" },
337     { VK_F9,                    "F9" },
338     { VK_F10,                   "F10" },
339     { VK_F11,                   "F11" },
340     { VK_F12,                   "F12" },
341     { VK_F13,                   "F13" },
342     { VK_F14,                   "F14" },
343     { VK_F15,                   "F15" },
344     { VK_F16,                   "F16" },
345     { VK_F17,                   "F17" },
346     { VK_F18,                   "F18" },
347     { VK_F19,                   "F19" },
348     { VK_F20,                   "F20" },
349     { VK_F21,                   "F21" },
350     { VK_F22,                   "F22" },
351     { VK_F23,                   "F23" },
352     { VK_F24,                   "F24" },
353     { VK_HELP | 0x100,          "Help" },
354     { VK_HOME | 0x100,          "Home" },
355     { VK_INSERT | 0x100,        "Insert" },
356     { VK_LCONTROL,              "Ctrl" },
357     { VK_LEFT | 0x100,          "Left" },
358     { VK_LMENU,                 "Alt" },
359     { VK_LSHIFT,                "Shift" },
360     { VK_LWIN | 0x100,          "Win" },
361     { VK_MENU,                  "Alt" },
362     { VK_MULTIPLY,              "Num *" },
363     { VK_NEXT | 0x100,          "Page Down" },
364     { VK_NUMLOCK | 0x100,       "Num Lock" },
365     { VK_NUMPAD0,               "Num 0" },
366     { VK_NUMPAD1,               "Num 1" },
367     { VK_NUMPAD2,               "Num 2" },
368     { VK_NUMPAD3,               "Num 3" },
369     { VK_NUMPAD4,               "Num 4" },
370     { VK_NUMPAD5,               "Num 5" },
371     { VK_NUMPAD6,               "Num 6" },
372     { VK_NUMPAD7,               "Num 7" },
373     { VK_NUMPAD8,               "Num 8" },
374     { VK_NUMPAD9,               "Num 9" },
375     { VK_OEM_CLEAR,             "Num Clear" },
376     { VK_OEM_NEC_EQUAL | 0x100, "Num =" },
377     { VK_PRIOR | 0x100,         "Page Up" },
378     { VK_RCONTROL | 0x100,      "Right Ctrl" },
379     { VK_RETURN,                "Return" },
380     { VK_RETURN | 0x100,        "Num Enter" },
381     { VK_RIGHT | 0x100,         "Right" },
382     { VK_RMENU | 0x100,         "Right Alt" },
383     { VK_RSHIFT,                "Right Shift" },
384     { VK_RWIN | 0x100,          "Right Win" },
385     { VK_SEPARATOR,             "Num ," },
386     { VK_SHIFT,                 "Shift" },
387     { VK_SPACE,                 "Space" },
388     { VK_SUBTRACT,              "Num -" },
389     { VK_TAB,                   "Tab" },
390     { VK_UP | 0x100,            "Up" },
391     { VK_VOLUME_DOWN | 0x100,   "Volume Down" },
392     { VK_VOLUME_MUTE | 0x100,   "Mute" },
393     { VK_VOLUME_UP | 0x100,     "Volume Up" },
394 };
395
396
397 static BOOL char_matches_string(WCHAR wchar, UniChar *string, BOOL ignore_diacritics)
398 {
399     BOOL ret;
400     CFStringRef s1 = CFStringCreateWithCharactersNoCopy(NULL, (UniChar*)&wchar, 1, kCFAllocatorNull);
401     CFStringRef s2 = CFStringCreateWithCharactersNoCopy(NULL, string, strlenW(string), kCFAllocatorNull);
402     CFStringCompareFlags flags = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareWidthInsensitive;
403     if (ignore_diacritics)
404         flags |= kCFCompareDiacriticInsensitive;
405     ret = (CFStringCompare(s1, s2, flags) == kCFCompareEqualTo);
406     CFRelease(s1);
407     CFRelease(s2);
408     return ret;
409 }
410
411
412 /* Filter Apple-specific private-use characters (see NSEvent.h) out of a
413  * string.  Returns the length of the string after stripping. */
414 static int strip_apple_private_chars(LPWSTR bufW, int len)
415 {
416     int i;
417     for (i = 0; i < len; )
418     {
419         if (0xF700 <= bufW[i] && bufW[i] <= 0xF8FF)
420         {
421             memmove(&bufW[i], &bufW[i+1], (len - i - 1) * sizeof(bufW[0]));
422             len--;
423         }
424         else
425             i++;
426     }
427     return len;
428 }
429
430
431 /***********************************************************************
432  *              macdrv_compute_keyboard_layout
433  */
434 void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data)
435 {
436     int keyc;
437     WCHAR vkey;
438     const UCKeyboardLayout *uchr;
439     const UInt32 modifier_combos[] = {
440         0,
441         shiftKey >> 8,
442         cmdKey >> 8,
443         (shiftKey | cmdKey) >> 8,
444         optionKey >> 8,
445         (shiftKey | optionKey) >> 8,
446     };
447     UniChar map[128][sizeof(modifier_combos) / sizeof(modifier_combos[0])][4 + 1];
448     int combo;
449     BYTE vkey_used[256];
450     int ignore_diacritics;
451     static const struct {
452         WCHAR wchar;
453         DWORD vkey;
454     } symbol_vkeys[] = {
455         { '-', VK_OEM_MINUS },
456         { '+', VK_OEM_PLUS },
457         { '_', VK_OEM_MINUS },
458         { ',', VK_OEM_COMMA },
459         { '.', VK_OEM_PERIOD },
460         { '=', VK_OEM_PLUS },
461         { '>', VK_OEM_PERIOD },
462         { '<', VK_OEM_COMMA },
463         { '|', VK_OEM_5 },
464         { '\\', VK_OEM_5 },
465         { '`', VK_OEM_3 },
466         { '[', VK_OEM_4 },
467         { '~', VK_OEM_3 },
468         { '?', VK_OEM_2 },
469         { ']', VK_OEM_6 },
470         { '/', VK_OEM_2 },
471         { ':', VK_OEM_1 },
472         { '}', VK_OEM_6 },
473         { '{', VK_OEM_4 },
474         { ';', VK_OEM_1 },
475         { '\'', VK_OEM_7 },
476         { ':', VK_OEM_PERIOD },
477         { ';', VK_OEM_COMMA },
478         { '"', VK_OEM_7 },
479         { 0x00B4, VK_OEM_4 }, /* 0x00B4 is ACUTE ACCENT */
480         { '\'', VK_OEM_2 },
481         { 0x00A7, VK_OEM_5 }, /* 0x00A7 is SECTION SIGN */
482         { '*', VK_OEM_PLUS },
483         { 0x00B4, VK_OEM_7 },
484         { '`', VK_OEM_4 },
485         { '[', VK_OEM_6 },
486         { '/', VK_OEM_5 },
487         { '^', VK_OEM_6 },
488         { '*', VK_OEM_2 },
489         { '{', VK_OEM_6 },
490         { '~', VK_OEM_1 },
491         { '?', VK_OEM_PLUS },
492         { '?', VK_OEM_4 },
493         { 0x00B4, VK_OEM_3 },
494         { '?', VK_OEM_COMMA },
495         { '~', VK_OEM_PLUS },
496         { ']', VK_OEM_4 },
497         { '\'', VK_OEM_3 },
498         { 0x00A7, VK_OEM_7 },
499     };
500     int i;
501
502     /* Vkeys that are suitable for assigning to arbitrary keys, organized in
503        contiguous ranges. */
504     static const struct {
505         WORD first, last;
506     } vkey_ranges[] = {
507         { 'A', 'Z' },
508         { '0', '9' },
509         { VK_OEM_1, VK_OEM_3 },
510         { VK_OEM_4, VK_ICO_CLEAR },
511         { 0xe9, 0xf5 },
512         { VK_OEM_NEC_EQUAL, VK_OEM_NEC_EQUAL },
513         { VK_F1, VK_F24 },
514         { 0, 0 }
515     };
516     int vkey_range;
517
518     if (!thread_data->keyboard_layout_uchr)
519     {
520         ERR("no keyboard layout UCHR data\n");
521         return;
522     }
523
524     memset(thread_data->keyc2vkey, 0, sizeof(thread_data->keyc2vkey));
525     memset(vkey_used, 0, sizeof(vkey_used));
526
527     for (keyc = 0; keyc < sizeof(default_map) / sizeof(default_map[0]); keyc++)
528     {
529         thread_data->keyc2scan[keyc] = default_map[keyc].scan;
530         if (default_map[keyc].fixed)
531         {
532             vkey = default_map[keyc].vkey;
533             thread_data->keyc2vkey[keyc] = vkey;
534             vkey_used[vkey] = 1;
535             TRACE("keyc 0x%04x -> vkey 0x%04x (fixed)\n", keyc, vkey);
536         }
537     }
538
539     if (thread_data->iso_keyboard)
540     {
541         /* In almost all cases, the Mac key codes indicate a physical key position
542            and this corresponds nicely to Win32 scan codes.  However, the Mac key
543            codes differ in one case between ANSI and ISO keyboards.  For ANSI
544            keyboards, the key to the left of the digits and above the Tab key
545            produces key code kVK_ANSI_Grave.  For ISO keyboards, the key in that
546            some position produces kVK_ISO_Section.  The additional key on ISO
547            keyboards, the one to the right of the left Shift key, produces
548            kVK_ANSI_Grave, which is just weird.
549
550            Since we want the key in that upper left corner to always produce the
551            same scan code (0x29), we need to swap the scan codes of those two
552            Mac key codes for ISO keyboards. */
553         DWORD temp = thread_data->keyc2scan[kVK_ANSI_Grave];
554         thread_data->keyc2scan[kVK_ANSI_Grave] = thread_data->keyc2scan[kVK_ISO_Section];
555         thread_data->keyc2scan[kVK_ISO_Section] = temp;
556     }
557
558     uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
559
560     /* Using the keyboard layout, build a map of key code + modifiers -> characters. */
561     memset(map, 0, sizeof(map));
562     for (keyc = 0; keyc < sizeof(map) / sizeof(map[0]); keyc++)
563     {
564         if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
565         if (thread_data->keyc2vkey[keyc]) continue; /* assigned a fixed vkey */
566
567         TRACE("keyc 0x%04x: ", keyc);
568
569         for (combo = 0; combo < sizeof(modifier_combos) / sizeof(modifier_combos[0]); combo++)
570         {
571             UInt32 deadKeyState;
572             UniCharCount len;
573             OSStatus status;
574
575             deadKeyState = 0;
576             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, modifier_combos[combo],
577                 thread_data->keyboard_type, kUCKeyTranslateNoDeadKeysMask,
578                 &deadKeyState, sizeof(map[keyc][combo])/sizeof(map[keyc][combo][0]) - 1,
579                 &len, map[keyc][combo]);
580             if (status != noErr)
581                 map[keyc][combo][0] = 0;
582
583             TRACE("%s%s", (combo ? ", " : ""), debugstr_w(map[keyc][combo]));
584         }
585
586         TRACE("\n");
587     }
588
589     /* First try to match key codes to the vkeys for the letters A through Z.
590        Try unmodified first, then with various modifier combinations in succession.
591        On the first pass, try to get a match lacking diacritical marks.  On the
592        second pass, accept matches with diacritical marks. */
593     for (ignore_diacritics = 0; ignore_diacritics <= 1; ignore_diacritics++)
594     {
595         for (combo = 0; combo < sizeof(modifier_combos) / sizeof(modifier_combos[0]); combo++)
596         {
597             for (vkey = 'A'; vkey <= 'Z'; vkey++)
598             {
599                 if (vkey_used[vkey])
600                     continue;
601
602                 for (keyc = 0; keyc < sizeof(map) / sizeof(map[0]); keyc++)
603                 {
604                     if (thread_data->keyc2vkey[keyc] || !map[keyc][combo][0])
605                         continue;
606
607                     if (char_matches_string(vkey, map[keyc][combo], ignore_diacritics))
608                     {
609                         thread_data->keyc2vkey[keyc] = vkey;
610                         vkey_used[vkey] = 1;
611                         TRACE("keyc 0x%04x -> vkey 0x%04x (%s match %s)\n", keyc, vkey,
612                               debugstr_wn(&vkey, 1), debugstr_w(map[keyc][combo]));
613                         break;
614                     }
615                 }
616             }
617         }
618     }
619
620     /* Next try to match key codes to the vkeys for the digits 0 through 9. */
621     for (combo = 0; combo < sizeof(modifier_combos) / sizeof(modifier_combos[0]); combo++)
622     {
623         for (vkey = '0'; vkey <= '9'; vkey++)
624         {
625             if (vkey_used[vkey])
626                 continue;
627
628             for (keyc = 0; keyc < sizeof(map) / sizeof(map[0]); keyc++)
629             {
630                 if (thread_data->keyc2vkey[keyc] || !map[keyc][combo][0])
631                     continue;
632
633                 if (char_matches_string(vkey, map[keyc][combo], FALSE))
634                 {
635                     thread_data->keyc2vkey[keyc] = vkey;
636                     vkey_used[vkey] = 1;
637                     TRACE("keyc 0x%04x -> vkey 0x%04x (%s match %s)\n", keyc, vkey,
638                           debugstr_wn(&vkey, 1), debugstr_w(map[keyc][combo]));
639                     break;
640                 }
641             }
642         }
643     }
644
645     /* Now try to match key codes for certain common punctuation characters to
646        the most common OEM vkeys (e.g. '.' to VK_OEM_PERIOD). */
647     for (i = 0; i < sizeof(symbol_vkeys) / sizeof(symbol_vkeys[0]); i++)
648     {
649         vkey = symbol_vkeys[i].vkey;
650
651         if (vkey_used[vkey])
652             continue;
653
654         for (combo = 0; combo < sizeof(modifier_combos) / sizeof(modifier_combos[0]); combo++)
655         {
656             for (keyc = 0; keyc < sizeof(map) / sizeof(map[0]); keyc++)
657             {
658                 if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
659                 if (thread_data->keyc2vkey[keyc] || !map[keyc][combo][0])
660                     continue;
661
662                 if (char_matches_string(symbol_vkeys[i].wchar, map[keyc][combo], FALSE))
663                 {
664                     thread_data->keyc2vkey[keyc] = vkey;
665                     vkey_used[vkey] = 1;
666                     TRACE("keyc 0x%04x -> vkey 0x%04x (%s match %s)\n", keyc, vkey,
667                           debugstr_wn(&symbol_vkeys[i].wchar, 1), debugstr_w(map[keyc][combo]));
668                     break;
669                 }
670             }
671
672             if (vkey_used[vkey])
673                 break;
674         }
675     }
676
677     /* For those key codes still without a vkey, try to use the default vkey
678        from the default map, if it's still available. */
679     for (keyc = 0; keyc < sizeof(default_map) / sizeof(default_map[0]); keyc++)
680     {
681         DWORD vkey = default_map[keyc].vkey;
682
683         if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
684         if (thread_data->keyc2vkey[keyc]) continue; /* already assigned */
685
686         if (!vkey_used[vkey])
687         {
688             thread_data->keyc2vkey[keyc] = vkey;
689             vkey_used[vkey] = 1;
690             TRACE("keyc 0x%04x -> vkey 0x%04x (default map)\n", keyc, vkey);
691         }
692     }
693
694     /* For any unassigned key codes which would map to a letter in the default
695        map, but whose normal letter vkey wasn't available, try to find a
696        different letter. */
697     vkey = 'A';
698     for (keyc = 0; keyc < sizeof(default_map) / sizeof(default_map[0]); keyc++)
699     {
700         if (default_map[keyc].vkey < 'A' || 'Z' < default_map[keyc].vkey)
701             continue; /* not a letter in ANSI layout */
702         if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
703         if (thread_data->keyc2vkey[keyc]) continue; /* already assigned */
704
705         while (vkey <= 'Z' && vkey_used[vkey]) vkey++;
706         if (vkey <= 'Z')
707         {
708             thread_data->keyc2vkey[keyc] = vkey;
709             vkey_used[vkey] = 1;
710             TRACE("keyc 0x%04x -> vkey 0x%04x (spare letter)\n", keyc, vkey);
711         }
712         else
713             break; /* no more unused letter vkeys, so stop trying */
714     }
715
716     /* Same thing but with the digits. */
717     vkey = '0';
718     for (keyc = 0; keyc < sizeof(default_map) / sizeof(default_map[0]); keyc++)
719     {
720         if (default_map[keyc].vkey < '0' || '9' < default_map[keyc].vkey)
721             continue; /* not a digit in ANSI layout */
722         if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
723         if (thread_data->keyc2vkey[keyc]) continue; /* already assigned */
724
725         while (vkey <= '9' && vkey_used[vkey]) vkey++;
726         if (vkey <= '9')
727         {
728             thread_data->keyc2vkey[keyc] = vkey;
729             vkey_used[vkey] = 1;
730             TRACE("keyc 0x%04x -> vkey 0x%04x (spare digit)\n", keyc, vkey);
731         }
732         else
733             break; /* no more unused digit vkeys, so stop trying */
734     }
735
736     /* Last chance.  Assign any available vkey. */
737     vkey_range = 0;
738     vkey = vkey_ranges[vkey_range].first;
739     for (keyc = 0; keyc < sizeof(default_map) / sizeof(default_map[0]); keyc++)
740     {
741         if (!thread_data->keyc2scan[keyc]) continue; /* not a known Mac key code */
742         if (thread_data->keyc2vkey[keyc]) continue; /* already assigned */
743
744         while (vkey && vkey_used[vkey])
745         {
746             if (vkey == vkey_ranges[vkey_range].last)
747             {
748                 vkey_range++;
749                 vkey = vkey_ranges[vkey_range].first;
750             }
751             else
752                 vkey++;
753         }
754
755         if (!vkey)
756         {
757             WARN("No more vkeys available!\n");
758             break;
759         }
760
761         thread_data->keyc2vkey[keyc] = vkey;
762         vkey_used[vkey] = 1;
763         TRACE("keyc 0x%04x -> vkey 0x%04x (spare vkey)\n", keyc, vkey);
764     }
765 }
766
767
768 /***********************************************************************
769  *              macdrv_send_keyboard_input
770  */
771 static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD flags, DWORD time)
772 {
773     INPUT input;
774
775     TRACE_(key)("hwnd %p vkey=%04x scan=%04x flags=%04x\n", hwnd, vkey, scan, flags);
776
777     input.type              = INPUT_KEYBOARD;
778     input.ki.wVk            = vkey;
779     input.ki.wScan          = scan;
780     input.ki.dwFlags        = flags;
781     input.ki.time           = time;
782     input.ki.dwExtraInfo    = 0;
783
784     __wine_send_input(hwnd, &input);
785 }
786
787
788 /***********************************************************************
789  *              macdrv_key_event
790  *
791  * Handler for KEY_PRESS and KEY_RELEASE events.
792  */
793 void macdrv_key_event(HWND hwnd, const macdrv_event *event)
794 {
795     struct macdrv_thread_data *thread_data = macdrv_thread_data();
796     WORD vkey, scan;
797     DWORD flags;
798
799     TRACE_(key)("win %p/%p key %s keycode %hu modifiers 0x%08llx\n",
800                 hwnd, event->window, (event->type == KEY_PRESS ? "press" : "release"),
801                 event->key.keycode, event->key.modifiers);
802
803     thread_data->last_modifiers = event->key.modifiers;
804
805     if (event->key.keycode < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
806     {
807         vkey = thread_data->keyc2vkey[event->key.keycode];
808         scan = thread_data->keyc2scan[event->key.keycode];
809     }
810     else
811         vkey = scan = 0;
812
813     TRACE_(key)("keycode %hu converted to vkey 0x%X scan 0x%02x\n",
814                 event->key.keycode, vkey, scan);
815
816     if (!vkey) return;
817
818     flags = 0;
819     if (event->type == KEY_RELEASE) flags |= KEYEVENTF_KEYUP;
820     if (scan & 0x100)               flags |= KEYEVENTF_EXTENDEDKEY;
821
822     macdrv_send_keyboard_input(hwnd, vkey, scan & 0xff, flags, event->key.time_ms);
823 }
824
825
826 /***********************************************************************
827  *              macdrv_keyboard_changed
828  *
829  * Handler for KEYBOARD_CHANGED events.
830  */
831 void macdrv_keyboard_changed(const macdrv_event *event)
832 {
833     struct macdrv_thread_data *thread_data = macdrv_thread_data();
834
835     TRACE("new keyboard layout uchr data %p, type %u, iso %d\n", event->keyboard_changed.uchr,
836           event->keyboard_changed.keyboard_type, event->keyboard_changed.iso_keyboard);
837
838     if (thread_data->keyboard_layout_uchr)
839         CFRelease(thread_data->keyboard_layout_uchr);
840     thread_data->keyboard_layout_uchr = CFDataCreateCopy(NULL, event->keyboard_changed.uchr);
841     thread_data->keyboard_type = event->keyboard_changed.keyboard_type;
842     thread_data->iso_keyboard = event->keyboard_changed.iso_keyboard;
843     thread_data->dead_key_state = 0;
844
845     macdrv_compute_keyboard_layout(thread_data);
846 }
847
848
849 /***********************************************************************
850  *              get_locale_keyboard_layout
851  */
852 static HKL get_locale_keyboard_layout(void)
853 {
854     ULONG_PTR layout;
855     LANGID langid;
856
857     layout = GetUserDefaultLCID();
858
859     /*
860      * Microsoft Office expects this value to be something specific
861      * for Japanese and Korean Windows with an IME the value is 0xe001
862      * We should probably check to see if an IME exists and if so then
863      * set this word properly.
864      */
865     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
866     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
867         layout |= 0xe001 << 16; /* IME */
868     else
869         layout |= layout << 16;
870
871     return (HKL)layout;
872 }
873
874
875 /***********************************************************************
876  *              match_keyboard_layout
877  */
878 static BOOL match_keyboard_layout(HKL hkl)
879 {
880     const DWORD isIME = 0xE0000000;
881     HKL current_hkl = get_locale_keyboard_layout();
882
883     /* if the layout is an IME, only match the low word (LCID) */
884     if (((ULONG_PTR)hkl & isIME) == isIME)
885         return (LOWORD(hkl) == LOWORD(current_hkl));
886     else
887         return (hkl == current_hkl);
888 }
889
890
891 /***********************************************************************
892  *              macdrv_process_text_input
893  */
894 BOOL macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *key_state, void *himc)
895 {
896     struct macdrv_thread_data *thread_data = macdrv_thread_data();
897     unsigned int flags;
898     int keyc;
899     BOOL ret = FALSE;
900
901     TRACE("vkey 0x%04x scan 0x%04x repeat %u himc %p\n", vkey, scan, repeat, himc);
902
903     flags = thread_data->last_modifiers;
904     if (key_state[VK_SHIFT] & 0x80)
905         flags |= NX_SHIFTMASK;
906     else
907         flags &= ~(NX_SHIFTMASK | NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK);
908     if (key_state[VK_CAPITAL] & 0x01)
909         flags |= NX_ALPHASHIFTMASK;
910     else
911         flags &= ~NX_ALPHASHIFTMASK;
912     if (key_state[VK_CONTROL] & 0x80)
913         flags |= NX_CONTROLMASK;
914     else
915         flags &= ~(NX_CONTROLMASK | NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK);
916     if (key_state[VK_MENU] & 0x80)
917         flags |= NX_COMMANDMASK;
918     else
919         flags &= ~(NX_COMMANDMASK | NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK);
920
921     /* Find the Mac keycode corresponding to the scan code */
922     for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
923         if (thread_data->keyc2vkey[keyc] == vkey) break;
924
925     if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
926         goto done;
927
928     TRACE("flags 0x%08x keyc 0x%04x\n", flags, keyc);
929
930     ret = macdrv_send_text_input_event(((scan & 0x8000) == 0), flags, repeat, keyc, himc);
931
932 done:
933     TRACE(" -> %s\n", ret ? "TRUE" : "FALSE");
934     return ret;
935 }
936
937
938 /***********************************************************************
939  *              ActivateKeyboardLayout (MACDRV.@)
940  */
941 HKL CDECL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags)
942 {
943     HKL oldHkl = 0;
944     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
945
946     /* FIXME: Use Text Input Services or NSTextInputContext to actually
947               change the Mac keyboard input source. */
948
949     FIXME("hkl %p flags %04x: semi-stub!\n", hkl, flags);
950     if (flags & KLF_SETFORPROCESS)
951     {
952         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
953         FIXME("KLF_SETFORPROCESS not supported\n");
954         return 0;
955     }
956
957     if (flags)
958         FIXME("flags %x not supported\n",flags);
959
960     if (hkl == (HKL)HKL_NEXT || hkl == (HKL)HKL_PREV)
961     {
962         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
963         FIXME("HKL_NEXT and HKL_PREV not supported\n");
964         return 0;
965     }
966
967     if (!match_keyboard_layout(hkl))
968     {
969         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
970         FIXME("setting keyboard of different locales not supported\n");
971         return 0;
972     }
973
974     oldHkl = thread_data->active_keyboard_layout;
975     if (!oldHkl) oldHkl = get_locale_keyboard_layout();
976
977     thread_data->active_keyboard_layout = hkl;
978
979     return oldHkl;
980 }
981
982
983 /***********************************************************************
984  *              Beep (MACDRV.@)
985  */
986 void CDECL macdrv_Beep(void)
987 {
988     macdrv_beep();
989 }
990
991
992 /***********************************************************************
993  *              GetKeyNameText (MACDRV.@)
994  */
995 INT CDECL macdrv_GetKeyNameText(LONG lparam, LPWSTR buffer, INT size)
996 {
997     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
998     int scan, keyc;
999
1000     scan = (lparam >> 16) & 0x1FF;
1001     for (keyc = 0; keyc < sizeof(thread_data->keyc2scan)/sizeof(thread_data->keyc2scan[0]); keyc++)
1002     {
1003         if (thread_data->keyc2scan[keyc] == scan)
1004         {
1005             static const WCHAR dead[] = {' ','d','e','a','d',0};
1006             const UCKeyboardLayout *uchr;
1007             UInt32 deadKeyState = 0;
1008             UniCharCount len;
1009             OSStatus status;
1010
1011             uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1012             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDisplay, 0, thread_data->keyboard_type,
1013                                     0, &deadKeyState, size - 1, &len, (UniChar*)buffer);
1014             if (status != noErr)
1015                 len = 0;
1016             if (len && isgraphW(buffer[0]))
1017                 buffer[len] = 0;
1018             else
1019             {
1020                 DWORD vkey = thread_data->keyc2vkey[keyc];
1021                 int i;
1022
1023                 if (scan & 0x100) vkey |= 0x100;
1024
1025                 if (lparam & (1 << 25))
1026                 {
1027                     /* Caller doesn't care about distinctions between left and
1028                        right keys. */
1029                     switch (vkey)
1030                     {
1031                         case VK_LSHIFT:
1032                         case VK_RSHIFT:
1033                             vkey = VK_SHIFT; break;
1034                         case VK_LCONTROL:
1035                         case VK_RCONTROL:
1036                             vkey = VK_CONTROL; break;
1037                         case VK_LMENU:
1038                         case VK_RMENU:
1039                             vkey = VK_MENU; break;
1040                     }
1041                 }
1042
1043                 len = 0;
1044                 for (i = 0; i < sizeof(vkey_names) / sizeof(vkey_names[0]); i++)
1045                 {
1046                     if (vkey_names[i].vkey == vkey)
1047                     {
1048                         len = MultiByteToWideChar(CP_UTF8, 0, vkey_names[i].name, -1, buffer, size);
1049                         if (len) len--;
1050                         break;
1051                     }
1052                 }
1053
1054                 if (!len)
1055                 {
1056                     static const WCHAR format[] = {'K','e','y',' ','0','x','%','0','2','x',0};
1057                     snprintfW(buffer, size, format, vkey);
1058                     len = strlenW(buffer);
1059                 }
1060             }
1061
1062             if (!len)
1063                 break;
1064
1065             if (status == noErr && deadKeyState)
1066             {
1067                 lstrcpynW(buffer + len, dead, size - len);
1068                 len = strlenW(buffer);
1069             }
1070
1071             TRACE("lparam 0x%08x -> %s\n", lparam, debugstr_w(buffer));
1072             return len;
1073         }
1074     }
1075
1076     WARN("found no name for lparam 0x%08x\n", lparam);
1077     return 0;
1078 }
1079
1080
1081 /***********************************************************************
1082  *              GetKeyboardLayout (MACDRV.@)
1083  */
1084 HKL CDECL macdrv_GetKeyboardLayout(DWORD thread_id)
1085 {
1086     if (!thread_id || thread_id == GetCurrentThreadId())
1087     {
1088         struct macdrv_thread_data *thread_data = macdrv_thread_data();
1089         if (thread_data && thread_data->active_keyboard_layout)
1090             return thread_data->active_keyboard_layout;
1091     }
1092     else
1093         FIXME("couldn't return keyboard layout for thread %04x\n", thread_id);
1094
1095     /* FIXME: Use TISGetInputSourceProperty() and kTISPropertyInputSourceLanguages
1096      *        to get input source language ID string.  Use
1097      *        CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier() to convert that
1098      *        to a Windows locale ID and from there to a layout handle.
1099      */
1100
1101     return get_locale_keyboard_layout();
1102 }
1103
1104
1105 /***********************************************************************
1106  *              GetKeyboardLayoutName (MACDRV.@)
1107  */
1108 BOOL CDECL macdrv_GetKeyboardLayoutName(LPWSTR name)
1109 {
1110     static const WCHAR formatW[] = {'%','0','8','x',0};
1111     DWORD layout;
1112
1113     layout = HandleToUlong(get_locale_keyboard_layout());
1114     if (HIWORD(layout) == LOWORD(layout)) layout = LOWORD(layout);
1115     sprintfW(name, formatW, layout);
1116     TRACE("returning %s\n", debugstr_w(name));
1117     return TRUE;
1118 }
1119
1120
1121 /***********************************************************************
1122  *              MapVirtualKeyEx (MACDRV.@)
1123  */
1124 UINT CDECL macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
1125 {
1126     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1127     UINT ret = 0;
1128     int keyc;
1129
1130     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
1131
1132     switch (wMapType)
1133     {
1134         case MAPVK_VK_TO_VSC: /* vkey-code to scan-code */
1135         case MAPVK_VK_TO_VSC_EX:
1136             switch (wCode)
1137             {
1138                 case VK_SHIFT: wCode = VK_LSHIFT; break;
1139                 case VK_CONTROL: wCode = VK_LCONTROL; break;
1140                 case VK_MENU: wCode = VK_LMENU; break;
1141             }
1142
1143             /* vkey -> keycode -> scan */
1144             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1145             {
1146                 if (thread_data->keyc2vkey[keyc] == wCode)
1147                 {
1148                     ret = thread_data->keyc2scan[keyc] & 0xFF;
1149                     break;
1150                 }
1151             }
1152             break;
1153
1154         case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
1155         case MAPVK_VSC_TO_VK_EX:
1156             /* scan -> keycode -> vkey */
1157             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1158                 if ((thread_data->keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1159                 {
1160                     ret = thread_data->keyc2vkey[keyc];
1161                     /* Only stop if it's not a numpad vkey; otherwise keep
1162                        looking for a potential better vkey. */
1163                     if (ret && (ret < VK_NUMPAD0 || VK_DIVIDE < ret))
1164                         break;
1165                 }
1166
1167             if (wMapType == MAPVK_VSC_TO_VK)
1168                 switch (ret)
1169                 {
1170                     case VK_LSHIFT:
1171                     case VK_RSHIFT:
1172                         ret = VK_SHIFT; break;
1173                     case VK_LCONTROL:
1174                     case VK_RCONTROL:
1175                         ret = VK_CONTROL; break;
1176                     case VK_LMENU:
1177                     case VK_RMENU:
1178                         ret = VK_MENU; break;
1179                 }
1180
1181             break;
1182
1183         case MAPVK_VK_TO_CHAR: /* vkey-code to character */
1184         {
1185             /* vkey -> keycode -> (UCKeyTranslate) wide char */
1186             struct macdrv_thread_data *thread_data = macdrv_thread_data();
1187             const UCKeyboardLayout *uchr;
1188             UniChar s[10];
1189             OSStatus status;
1190             UInt32 deadKeyState;
1191             UniCharCount len;
1192             BOOL deadKey = FALSE;
1193
1194             if ((VK_PRIOR <= wCode && wCode <= VK_HELP) ||
1195                 (VK_F1 <= wCode && wCode <= VK_F24))
1196                 break;
1197
1198             if (!thread_data || !thread_data->keyboard_layout_uchr)
1199             {
1200                 WARN("No keyboard layout uchr data\n");
1201                 break;
1202             }
1203
1204             uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1205
1206             /* Find the Mac keycode corresponding to the vkey */
1207             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1208                 if (thread_data->keyc2vkey[keyc] == wCode) break;
1209
1210             if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
1211             {
1212                 WARN("Unknown virtual key %X\n", wCode);
1213                 break;
1214             }
1215
1216             TRACE("Found keycode %u\n", keyc);
1217
1218             deadKeyState = 0;
1219             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, 0,
1220                 thread_data->keyboard_type, 0, &deadKeyState,
1221                 sizeof(s)/sizeof(s[0]), &len, s);
1222             if (status == noErr && !len && deadKeyState)
1223             {
1224                 deadKey = TRUE;
1225                 deadKeyState = 0;
1226                 status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, 0,
1227                     thread_data->keyboard_type, kUCKeyTranslateNoDeadKeysMask,
1228                     &deadKeyState, sizeof(s)/sizeof(s[0]), &len, s);
1229             }
1230
1231             if (status == noErr && len)
1232                 ret = toupperW(s[0]) | (deadKey ? 0x80000000 : 0);
1233
1234             break;
1235         }
1236         default: /* reserved */
1237             FIXME("Unknown wMapType %d\n", wMapType);
1238             break;
1239     }
1240
1241     TRACE("returning 0x%04x\n", ret);
1242     return ret;
1243 }
1244
1245
1246 /***********************************************************************
1247  *              ToUnicodeEx (MACDRV.@)
1248  *
1249  * The ToUnicode function translates the specified virtual-key code and keyboard
1250  * state to the corresponding Windows character or characters.
1251  *
1252  * If the specified key is a dead key, the return value is negative. Otherwise,
1253  * it is one of the following values:
1254  * Value        Meaning
1255  * -1           The specified virtual key is a dead-key.  If possible, the
1256  *              non-combining form of the dead character is written to bufW.
1257  * 0            The specified virtual key has no translation for the current
1258  *              state of the keyboard.
1259  * 1            One Windows character was copied to the buffer.
1260  * 2 or more    Multiple characters were copied to the buffer. This usually
1261  *              happens when a dead-key character (accent or diacritic) stored
1262  *              in the keyboard layout cannot be composed with the specified
1263  *              virtual key to form a single character.
1264  *
1265  */
1266 INT CDECL macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
1267                              LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
1268 {
1269     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1270     INT ret = 0;
1271     int keyc;
1272     BOOL is_menu = (flags & 0x1);
1273     OSStatus status;
1274     const UCKeyboardLayout *uchr;
1275     UInt16 keyAction;
1276     UInt32 modifierKeyState;
1277     OptionBits options;
1278     UInt32 deadKeyState, savedDeadKeyState;
1279     UniCharCount len;
1280     BOOL dead = FALSE;
1281
1282     TRACE_(key)("virtKey 0x%04x scanCode 0x%04x lpKeyState %p bufW %p bufW_size %d flags 0x%08x hkl %p\n",
1283                 virtKey, scanCode, lpKeyState, bufW, bufW_size, flags, hkl);
1284
1285     if (!virtKey)
1286         goto done;
1287
1288     /* UCKeyTranslate, below, terminates a dead-key sequence if passed a
1289        modifier key press.  We want it to effectively ignore modifier key
1290        presses.  I think that one isn't supposed to call it at all for modifier
1291        events (e.g. NSFlagsChanged or kEventRawKeyModifiersChanged), since they
1292        are different event types than key up/down events. */
1293     switch (virtKey)
1294     {
1295         case VK_SHIFT:
1296         case VK_CONTROL:
1297         case VK_MENU:
1298         case VK_CAPITAL:
1299         case VK_LSHIFT:
1300         case VK_RSHIFT:
1301         case VK_LCONTROL:
1302         case VK_RCONTROL:
1303         case VK_LMENU:
1304         case VK_RMENU:
1305             goto done;
1306     }
1307
1308     /* There are a number of key combinations for which Windows does not
1309        produce characters, but Mac keyboard layouts may.  Eat them.  Do this
1310        here to avoid the expense of UCKeyTranslate() but also because these
1311        keys shouldn't terminate dead key sequences. */
1312     if ((VK_PRIOR <= virtKey && virtKey <= VK_HELP) || (VK_F1 <= virtKey && virtKey <= VK_F24))
1313         goto done;
1314
1315     /* Shift + <non-digit keypad keys>. */
1316     if ((lpKeyState[VK_SHIFT] & 0x80) && VK_MULTIPLY <= virtKey && virtKey <= VK_DIVIDE)
1317         goto done;
1318
1319     if (lpKeyState[VK_CONTROL] & 0x80)
1320     {
1321         /* Control-Tab, with or without other modifiers. */
1322         if (virtKey == VK_TAB)
1323             goto done;
1324
1325         /* Control-Shift-<key>, Control-Alt-<key>, and Control-Alt-Shift-<key>
1326            for these keys. */
1327         if ((lpKeyState[VK_SHIFT] & 0x80) || (lpKeyState[VK_MENU] & 0x80))
1328         {
1329             switch (virtKey)
1330             {
1331                 case VK_CANCEL:
1332                 case VK_BACK:
1333                 case VK_ESCAPE:
1334                 case VK_SPACE:
1335                 case VK_RETURN:
1336                     goto done;
1337             }
1338         }
1339     }
1340
1341     if (thread_data->keyboard_layout_uchr)
1342         uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1343     else
1344         uchr = NULL;
1345
1346     keyAction = (scanCode & 0x8000) ? kUCKeyActionUp : kUCKeyActionDown;
1347
1348     modifierKeyState = 0;
1349     if (lpKeyState[VK_SHIFT] & 0x80)
1350         modifierKeyState |= (shiftKey >> 8);
1351     if (lpKeyState[VK_CAPITAL] & 0x01)
1352         modifierKeyState |= (alphaLock >> 8);
1353     if (lpKeyState[VK_CONTROL] & 0x80)
1354         modifierKeyState |= (controlKey >> 8);
1355     if (lpKeyState[VK_MENU] & 0x80)
1356         modifierKeyState |= (cmdKey >> 8);
1357     if (thread_data->last_modifiers & (NX_ALTERNATEMASK | NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK))
1358         modifierKeyState |= (optionKey >> 8);
1359
1360     /* Find the Mac keycode corresponding to the vkey */
1361     for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1362         if (thread_data->keyc2vkey[keyc] == virtKey) break;
1363
1364     if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
1365     {
1366         WARN_(key)("Unknown virtual key 0x%04x\n", virtKey);
1367         goto done;
1368     }
1369
1370     TRACE_(key)("Key code 0x%04x %s, faked modifiers = 0x%04x\n", keyc,
1371                 (keyAction == kUCKeyActionDown) ? "pressed" : "released", (unsigned)modifierKeyState);
1372
1373     if (is_menu)
1374     {
1375         options = kUCKeyTranslateNoDeadKeysMask;
1376         deadKeyState = 0;
1377     }
1378     else
1379     {
1380         options = 0;
1381         deadKeyState = thread_data->dead_key_state;
1382     }
1383     savedDeadKeyState = deadKeyState;
1384     status = UCKeyTranslate(uchr, keyc, keyAction, modifierKeyState,
1385         thread_data->keyboard_type, options, &deadKeyState, bufW_size,
1386         &len, bufW);
1387     if (status != noErr)
1388     {
1389         ERR_(key)("Couldn't translate keycode 0x%04x, status %ld\n", keyc, status);
1390         goto done;
1391     }
1392     if (!is_menu)
1393         thread_data->dead_key_state = deadKeyState;
1394
1395     if (len == 0 && deadKeyState)
1396     {
1397         /* Repeat the translation, but disabling dead-key generation to
1398            learn which dead key it was. */
1399         status = UCKeyTranslate(uchr, keyc, keyAction, modifierKeyState,
1400             thread_data->keyboard_type, kUCKeyTranslateNoDeadKeysMask,
1401             &savedDeadKeyState, bufW_size, &len, bufW);
1402         if (status != noErr)
1403         {
1404             ERR_(key)("Couldn't translate keycode 0x%04x, status %ld\n", keyc, status);
1405             goto done;
1406         }
1407
1408         dead = TRUE;
1409     }
1410
1411     if (len > 0)
1412         len = strip_apple_private_chars(bufW, len);
1413
1414     if (dead && len > 0) ret = -1;
1415     else ret = len;
1416
1417     /* Control-Return produces line feed instead of carriage return. */
1418     if (ret > 0 && (lpKeyState[VK_CONTROL] & 0x80) && virtKey == VK_RETURN)
1419     {
1420         int i;
1421         for (i = 0; i < len; i++)
1422             if (bufW[i] == '\r')
1423                 bufW[i] = '\n';
1424     }
1425
1426 done:
1427     /* Null-terminate the buffer, if there's room.  MSDN clearly states that the
1428        caller must not assume this is done, but some programs (e.g. Audiosurf) do. */
1429     if (1 <= ret && ret < bufW_size)
1430         bufW[ret] = 0;
1431
1432     TRACE_(key)("returning %d / %s\n", ret, debugstr_wn(bufW, abs(ret)));
1433     return ret;
1434 }
1435
1436
1437 /***********************************************************************
1438  *              VkKeyScanEx (MACDRV.@)
1439  *
1440  * Note: Windows ignores HKL parameter and uses current active layout instead
1441  */
1442 SHORT CDECL macdrv_VkKeyScanEx(WCHAR wChar, HKL hkl)
1443 {
1444     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1445     SHORT ret = -1;
1446     int state;
1447     const UCKeyboardLayout *uchr;
1448
1449     TRACE("%04x, %p\n", wChar, hkl);
1450
1451     uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1452     if (!uchr)
1453     {
1454         TRACE("no keyboard layout UCHR data; returning -1\n");
1455         return -1;
1456     }
1457
1458     for (state = 0; state < 8; state++)
1459     {
1460         UInt32 modifierKeyState = 0;
1461         int keyc;
1462
1463         if (state & 1)
1464             modifierKeyState |= (shiftKey >> 8);
1465         if ((state & 6) == 6)
1466             modifierKeyState |= (optionKey >> 8);
1467         else
1468         {
1469             if (state & 2)
1470                 modifierKeyState |= (controlKey >> 8);
1471             if (state & 4)
1472                 modifierKeyState |= (cmdKey >> 8);
1473         }
1474
1475         for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey) / sizeof(thread_data->keyc2vkey[0]); keyc++)
1476         {
1477             UInt32 deadKeyState = 0;
1478             UniChar uchar;
1479             UniCharCount len;
1480             OSStatus status;
1481
1482             if (!thread_data->keyc2vkey[keyc]) continue;
1483
1484             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, modifierKeyState,
1485                                     thread_data->keyboard_type, 0, &deadKeyState,
1486                                     1, &len, &uchar);
1487             if (status == noErr && len == 1 && uchar == wChar)
1488             {
1489                 WORD vkey = thread_data->keyc2vkey[keyc];
1490
1491                 ret = vkey | (state << 8);
1492                 if ((VK_NUMPAD0 <= vkey && vkey <= VK_DIVIDE) ||
1493                     keyc == kVK_ANSI_KeypadClear || keyc == kVK_ANSI_KeypadEnter ||
1494                     keyc == kVK_ANSI_KeypadEquals)
1495                 {
1496                     /* Keep searching for a non-numpad match, which is preferred. */
1497                 }
1498                 else
1499                     goto done;
1500             }
1501         }
1502     }
1503
1504 done:
1505     TRACE(" -> 0x%04x\n", ret);
1506     return ret;
1507 }