winemac: Enable pasteboard functions to operate on arbitrary pasteboards.
[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  *              ActivateKeyboardLayout (MACDRV.@)
893  */
894 HKL CDECL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags)
895 {
896     HKL oldHkl = 0;
897     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
898
899     /* FIXME: Use Text Input Services or NSTextInputContext to actually
900               change the Mac keyboard input source. */
901
902     FIXME("hkl %p flags %04x: semi-stub!\n", hkl, flags);
903     if (flags & KLF_SETFORPROCESS)
904     {
905         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
906         FIXME("KLF_SETFORPROCESS not supported\n");
907         return 0;
908     }
909
910     if (flags)
911         FIXME("flags %x not supported\n",flags);
912
913     if (hkl == (HKL)HKL_NEXT || hkl == (HKL)HKL_PREV)
914     {
915         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
916         FIXME("HKL_NEXT and HKL_PREV not supported\n");
917         return 0;
918     }
919
920     if (!match_keyboard_layout(hkl))
921     {
922         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
923         FIXME("setting keyboard of different locales not supported\n");
924         return 0;
925     }
926
927     oldHkl = thread_data->active_keyboard_layout;
928     if (!oldHkl) oldHkl = get_locale_keyboard_layout();
929
930     thread_data->active_keyboard_layout = hkl;
931
932     return oldHkl;
933 }
934
935
936 /***********************************************************************
937  *              Beep (MACDRV.@)
938  */
939 void CDECL macdrv_Beep(void)
940 {
941     macdrv_beep();
942 }
943
944
945 /***********************************************************************
946  *              GetKeyNameText (MACDRV.@)
947  */
948 INT CDECL macdrv_GetKeyNameText(LONG lparam, LPWSTR buffer, INT size)
949 {
950     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
951     int scan, keyc;
952
953     scan = (lparam >> 16) & 0x1FF;
954     for (keyc = 0; keyc < sizeof(thread_data->keyc2scan)/sizeof(thread_data->keyc2scan[0]); keyc++)
955     {
956         if (thread_data->keyc2scan[keyc] == scan)
957         {
958             static const WCHAR dead[] = {' ','d','e','a','d',0};
959             const UCKeyboardLayout *uchr;
960             UInt32 deadKeyState = 0;
961             UniCharCount len;
962             OSStatus status;
963
964             uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
965             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDisplay, 0, thread_data->keyboard_type,
966                                     0, &deadKeyState, size - 1, &len, (UniChar*)buffer);
967             if (status != noErr)
968                 len = 0;
969             if (len && isgraphW(buffer[0]))
970                 buffer[len] = 0;
971             else
972             {
973                 DWORD vkey = thread_data->keyc2vkey[keyc];
974                 int i;
975
976                 if (scan & 0x100) vkey |= 0x100;
977
978                 if (lparam & (1 << 25))
979                 {
980                     /* Caller doesn't care about distinctions between left and
981                        right keys. */
982                     switch (vkey)
983                     {
984                         case VK_LSHIFT:
985                         case VK_RSHIFT:
986                             vkey = VK_SHIFT; break;
987                         case VK_LCONTROL:
988                         case VK_RCONTROL:
989                             vkey = VK_CONTROL; break;
990                         case VK_LMENU:
991                         case VK_RMENU:
992                             vkey = VK_MENU; break;
993                     }
994                 }
995
996                 len = 0;
997                 for (i = 0; i < sizeof(vkey_names) / sizeof(vkey_names[0]); i++)
998                 {
999                     if (vkey_names[i].vkey == vkey)
1000                     {
1001                         len = MultiByteToWideChar(CP_UTF8, 0, vkey_names[i].name, -1, buffer, size);
1002                         if (len) len--;
1003                         break;
1004                     }
1005                 }
1006
1007                 if (!len)
1008                 {
1009                     static const WCHAR format[] = {'K','e','y',' ','0','x','%','0','2','x',0};
1010                     snprintfW(buffer, size, format, vkey);
1011                     len = strlenW(buffer);
1012                 }
1013             }
1014
1015             if (!len)
1016                 break;
1017
1018             if (status == noErr && deadKeyState)
1019             {
1020                 lstrcpynW(buffer + len, dead, size - len);
1021                 len = strlenW(buffer);
1022             }
1023
1024             TRACE("lparam 0x%08x -> %s\n", lparam, debugstr_w(buffer));
1025             return len;
1026         }
1027     }
1028
1029     WARN("found no name for lparam 0x%08x\n", lparam);
1030     return 0;
1031 }
1032
1033
1034 /***********************************************************************
1035  *              GetKeyboardLayout (MACDRV.@)
1036  */
1037 HKL CDECL macdrv_GetKeyboardLayout(DWORD thread_id)
1038 {
1039     if (!thread_id || thread_id == GetCurrentThreadId())
1040     {
1041         struct macdrv_thread_data *thread_data = macdrv_thread_data();
1042         if (thread_data && thread_data->active_keyboard_layout)
1043             return thread_data->active_keyboard_layout;
1044     }
1045     else
1046         FIXME("couldn't return keyboard layout for thread %04x\n", thread_id);
1047
1048     /* FIXME: Use TISGetInputSourceProperty() and kTISPropertyInputSourceLanguages
1049      *        to get input source language ID string.  Use
1050      *        CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier() to convert that
1051      *        to a Windows locale ID and from there to a layout handle.
1052      */
1053
1054     return get_locale_keyboard_layout();
1055 }
1056
1057
1058 /***********************************************************************
1059  *              GetKeyboardLayoutName (MACDRV.@)
1060  */
1061 BOOL CDECL macdrv_GetKeyboardLayoutName(LPWSTR name)
1062 {
1063     static const WCHAR formatW[] = {'%','0','8','x',0};
1064     DWORD layout;
1065
1066     layout = HandleToUlong(get_locale_keyboard_layout());
1067     if (HIWORD(layout) == LOWORD(layout)) layout = LOWORD(layout);
1068     sprintfW(name, formatW, layout);
1069     TRACE("returning %s\n", debugstr_w(name));
1070     return TRUE;
1071 }
1072
1073
1074 /***********************************************************************
1075  *              MapVirtualKeyEx (MACDRV.@)
1076  */
1077 UINT CDECL macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
1078 {
1079     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1080     UINT ret = 0;
1081     int keyc;
1082
1083     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
1084
1085     switch (wMapType)
1086     {
1087         case MAPVK_VK_TO_VSC: /* vkey-code to scan-code */
1088         case MAPVK_VK_TO_VSC_EX:
1089             switch (wCode)
1090             {
1091                 case VK_SHIFT: wCode = VK_LSHIFT; break;
1092                 case VK_CONTROL: wCode = VK_LCONTROL; break;
1093                 case VK_MENU: wCode = VK_LMENU; break;
1094             }
1095
1096             /* vkey -> keycode -> scan */
1097             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1098             {
1099                 if (thread_data->keyc2vkey[keyc] == wCode)
1100                 {
1101                     ret = thread_data->keyc2scan[keyc] & 0xFF;
1102                     break;
1103                 }
1104             }
1105             break;
1106
1107         case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
1108         case MAPVK_VSC_TO_VK_EX:
1109             /* scan -> keycode -> vkey */
1110             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1111                 if ((thread_data->keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1112                 {
1113                     ret = thread_data->keyc2vkey[keyc];
1114                     /* Only stop if it's not a numpad vkey; otherwise keep
1115                        looking for a potential better vkey. */
1116                     if (ret && (ret < VK_NUMPAD0 || VK_DIVIDE < ret))
1117                         break;
1118                 }
1119
1120             if (wMapType == MAPVK_VSC_TO_VK)
1121                 switch (ret)
1122                 {
1123                     case VK_LSHIFT:
1124                     case VK_RSHIFT:
1125                         ret = VK_SHIFT; break;
1126                     case VK_LCONTROL:
1127                     case VK_RCONTROL:
1128                         ret = VK_CONTROL; break;
1129                     case VK_LMENU:
1130                     case VK_RMENU:
1131                         ret = VK_MENU; break;
1132                 }
1133
1134             break;
1135
1136         case MAPVK_VK_TO_CHAR: /* vkey-code to character */
1137         {
1138             /* vkey -> keycode -> (UCKeyTranslate) wide char */
1139             struct macdrv_thread_data *thread_data = macdrv_thread_data();
1140             const UCKeyboardLayout *uchr;
1141             UniChar s[10];
1142             OSStatus status;
1143             UInt32 deadKeyState;
1144             UniCharCount len;
1145             BOOL deadKey = FALSE;
1146
1147             if ((VK_PRIOR <= wCode && wCode <= VK_HELP) ||
1148                 (VK_F1 <= wCode && wCode <= VK_F24))
1149                 break;
1150
1151             if (!thread_data || !thread_data->keyboard_layout_uchr)
1152             {
1153                 WARN("No keyboard layout uchr data\n");
1154                 break;
1155             }
1156
1157             uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1158
1159             /* Find the Mac keycode corresponding to the vkey */
1160             for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1161                 if (thread_data->keyc2vkey[keyc] == wCode) break;
1162
1163             if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
1164             {
1165                 WARN("Unknown virtual key %X\n", wCode);
1166                 break;
1167             }
1168
1169             TRACE("Found keycode %u\n", keyc);
1170
1171             deadKeyState = 0;
1172             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, 0,
1173                 thread_data->keyboard_type, 0, &deadKeyState,
1174                 sizeof(s)/sizeof(s[0]), &len, s);
1175             if (status == noErr && !len && deadKeyState)
1176             {
1177                 deadKey = TRUE;
1178                 deadKeyState = 0;
1179                 status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, 0,
1180                     thread_data->keyboard_type, kUCKeyTranslateNoDeadKeysMask,
1181                     &deadKeyState, sizeof(s)/sizeof(s[0]), &len, s);
1182             }
1183
1184             if (status == noErr && len)
1185                 ret = toupperW(s[0]) | (deadKey ? 0x80000000 : 0);
1186
1187             break;
1188         }
1189         default: /* reserved */
1190             FIXME("Unknown wMapType %d\n", wMapType);
1191             break;
1192     }
1193
1194     TRACE("returning 0x%04x\n", ret);
1195     return ret;
1196 }
1197
1198
1199 /***********************************************************************
1200  *              ToUnicodeEx (MACDRV.@)
1201  *
1202  * The ToUnicode function translates the specified virtual-key code and keyboard
1203  * state to the corresponding Windows character or characters.
1204  *
1205  * If the specified key is a dead key, the return value is negative. Otherwise,
1206  * it is one of the following values:
1207  * Value        Meaning
1208  * -1           The specified virtual key is a dead-key.  If possible, the
1209  *              non-combining form of the dead character is written to bufW.
1210  * 0            The specified virtual key has no translation for the current
1211  *              state of the keyboard.
1212  * 1            One Windows character was copied to the buffer.
1213  * 2 or more    Multiple characters were copied to the buffer. This usually
1214  *              happens when a dead-key character (accent or diacritic) stored
1215  *              in the keyboard layout cannot be composed with the specified
1216  *              virtual key to form a single character.
1217  *
1218  */
1219 INT CDECL macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
1220                              LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
1221 {
1222     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1223     INT ret = 0;
1224     int keyc;
1225     BOOL is_menu = (flags & 0x1);
1226     OSStatus status;
1227     const UCKeyboardLayout *uchr;
1228     UInt16 keyAction;
1229     UInt32 modifierKeyState;
1230     OptionBits options;
1231     UInt32 deadKeyState, savedDeadKeyState;
1232     UniCharCount len;
1233     BOOL dead = FALSE;
1234
1235     TRACE_(key)("virtKey 0x%04x scanCode 0x%04x lpKeyState %p bufW %p bufW_size %d flags 0x%08x hkl %p\n",
1236                 virtKey, scanCode, lpKeyState, bufW, bufW_size, flags, hkl);
1237
1238     if (!virtKey)
1239         goto done;
1240
1241     /* UCKeyTranslate, below, terminates a dead-key sequence if passed a
1242        modifier key press.  We want it to effectively ignore modifier key
1243        presses.  I think that one isn't supposed to call it at all for modifier
1244        events (e.g. NSFlagsChanged or kEventRawKeyModifiersChanged), since they
1245        are different event types than key up/down events. */
1246     switch (virtKey)
1247     {
1248         case VK_SHIFT:
1249         case VK_CONTROL:
1250         case VK_MENU:
1251         case VK_CAPITAL:
1252         case VK_LSHIFT:
1253         case VK_RSHIFT:
1254         case VK_LCONTROL:
1255         case VK_RCONTROL:
1256         case VK_LMENU:
1257         case VK_RMENU:
1258             goto done;
1259     }
1260
1261     /* There are a number of key combinations for which Windows does not
1262        produce characters, but Mac keyboard layouts may.  Eat them.  Do this
1263        here to avoid the expense of UCKeyTranslate() but also because these
1264        keys shouldn't terminate dead key sequences. */
1265     if ((VK_PRIOR <= virtKey && virtKey <= VK_HELP) || (VK_F1 <= virtKey && virtKey <= VK_F24))
1266         goto done;
1267
1268     /* Shift + <non-digit keypad keys>. */
1269     if ((lpKeyState[VK_SHIFT] & 0x80) && VK_MULTIPLY <= virtKey && virtKey <= VK_DIVIDE)
1270         goto done;
1271
1272     if (lpKeyState[VK_CONTROL] & 0x80)
1273     {
1274         /* Control-Tab, with or without other modifiers. */
1275         if (virtKey == VK_TAB)
1276             goto done;
1277
1278         /* Control-Shift-<key>, Control-Alt-<key>, and Control-Alt-Shift-<key>
1279            for these keys. */
1280         if ((lpKeyState[VK_SHIFT] & 0x80) || (lpKeyState[VK_MENU] & 0x80))
1281         {
1282             switch (virtKey)
1283             {
1284                 case VK_CANCEL:
1285                 case VK_BACK:
1286                 case VK_ESCAPE:
1287                 case VK_SPACE:
1288                 case VK_RETURN:
1289                     goto done;
1290             }
1291         }
1292     }
1293
1294     if (thread_data->keyboard_layout_uchr)
1295         uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1296     else
1297         uchr = NULL;
1298
1299     keyAction = (scanCode & 0x8000) ? kUCKeyActionUp : kUCKeyActionDown;
1300
1301     modifierKeyState = 0;
1302     if (lpKeyState[VK_SHIFT] & 0x80)
1303         modifierKeyState |= (shiftKey >> 8);
1304     if (lpKeyState[VK_CAPITAL] & 0x01)
1305         modifierKeyState |= (alphaLock >> 8);
1306     if (lpKeyState[VK_CONTROL] & 0x80)
1307         modifierKeyState |= (controlKey >> 8);
1308     if (lpKeyState[VK_MENU] & 0x80)
1309         modifierKeyState |= (cmdKey >> 8);
1310     if (thread_data->last_modifiers & (NX_ALTERNATEMASK | NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK))
1311         modifierKeyState |= (optionKey >> 8);
1312
1313     /* Find the Mac keycode corresponding to the vkey */
1314     for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]); keyc++)
1315         if (thread_data->keyc2vkey[keyc] == virtKey) break;
1316
1317     if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
1318     {
1319         WARN_(key)("Unknown virtual key 0x%04x\n", virtKey);
1320         goto done;
1321     }
1322
1323     TRACE_(key)("Key code 0x%04x %s, faked modifiers = 0x%04x\n", keyc,
1324                 (keyAction == kUCKeyActionDown) ? "pressed" : "released", (unsigned)modifierKeyState);
1325
1326     if (is_menu)
1327     {
1328         options = kUCKeyTranslateNoDeadKeysMask;
1329         deadKeyState = 0;
1330     }
1331     else
1332     {
1333         options = 0;
1334         deadKeyState = thread_data->dead_key_state;
1335     }
1336     savedDeadKeyState = deadKeyState;
1337     status = UCKeyTranslate(uchr, keyc, keyAction, modifierKeyState,
1338         thread_data->keyboard_type, options, &deadKeyState, bufW_size,
1339         &len, bufW);
1340     if (status != noErr)
1341     {
1342         ERR_(key)("Couldn't translate keycode 0x%04x, status %ld\n", keyc, status);
1343         goto done;
1344     }
1345     if (!is_menu)
1346         thread_data->dead_key_state = deadKeyState;
1347
1348     if (len == 0 && deadKeyState)
1349     {
1350         /* Repeat the translation, but disabling dead-key generation to
1351            learn which dead key it was. */
1352         status = UCKeyTranslate(uchr, keyc, keyAction, modifierKeyState,
1353             thread_data->keyboard_type, kUCKeyTranslateNoDeadKeysMask,
1354             &savedDeadKeyState, bufW_size, &len, bufW);
1355         if (status != noErr)
1356         {
1357             ERR_(key)("Couldn't translate keycode 0x%04x, status %ld\n", keyc, status);
1358             goto done;
1359         }
1360
1361         dead = TRUE;
1362     }
1363
1364     if (len > 0)
1365         len = strip_apple_private_chars(bufW, len);
1366
1367     if (dead && len > 0) ret = -1;
1368     else ret = len;
1369
1370     /* Control-Return produces line feed instead of carriage return. */
1371     if (ret > 0 && (lpKeyState[VK_CONTROL] & 0x80) && virtKey == VK_RETURN)
1372     {
1373         int i;
1374         for (i = 0; i < len; i++)
1375             if (bufW[i] == '\r')
1376                 bufW[i] = '\n';
1377     }
1378
1379 done:
1380     /* Null-terminate the buffer, if there's room.  MSDN clearly states that the
1381        caller must not assume this is done, but some programs (e.g. Audiosurf) do. */
1382     if (1 <= ret && ret < bufW_size)
1383         bufW[ret] = 0;
1384
1385     TRACE_(key)("returning %d / %s\n", ret, debugstr_wn(bufW, abs(ret)));
1386     return ret;
1387 }
1388
1389
1390 /***********************************************************************
1391  *              VkKeyScanEx (MACDRV.@)
1392  *
1393  * Note: Windows ignores HKL parameter and uses current active layout instead
1394  */
1395 SHORT CDECL macdrv_VkKeyScanEx(WCHAR wChar, HKL hkl)
1396 {
1397     struct macdrv_thread_data *thread_data = macdrv_init_thread_data();
1398     SHORT ret = -1;
1399     int state;
1400     const UCKeyboardLayout *uchr;
1401
1402     TRACE("%04x, %p\n", wChar, hkl);
1403
1404     uchr = (const UCKeyboardLayout*)CFDataGetBytePtr(thread_data->keyboard_layout_uchr);
1405     if (!uchr)
1406     {
1407         TRACE("no keyboard layout UCHR data; returning -1\n");
1408         return -1;
1409     }
1410
1411     for (state = 0; state < 8; state++)
1412     {
1413         UInt32 modifierKeyState = 0;
1414         int keyc;
1415
1416         if (state & 1)
1417             modifierKeyState |= (shiftKey >> 8);
1418         if ((state & 6) == 6)
1419             modifierKeyState |= (optionKey >> 8);
1420         else
1421         {
1422             if (state & 2)
1423                 modifierKeyState |= (controlKey >> 8);
1424             if (state & 4)
1425                 modifierKeyState |= (cmdKey >> 8);
1426         }
1427
1428         for (keyc = 0; keyc < sizeof(thread_data->keyc2vkey) / sizeof(thread_data->keyc2vkey[0]); keyc++)
1429         {
1430             UInt32 deadKeyState = 0;
1431             UniChar uchar;
1432             UniCharCount len;
1433             OSStatus status;
1434
1435             if (!thread_data->keyc2vkey[keyc]) continue;
1436
1437             status = UCKeyTranslate(uchr, keyc, kUCKeyActionDown, modifierKeyState,
1438                                     thread_data->keyboard_type, 0, &deadKeyState,
1439                                     1, &len, &uchar);
1440             if (status == noErr && len == 1 && uchar == wChar)
1441             {
1442                 WORD vkey = thread_data->keyc2vkey[keyc];
1443
1444                 ret = vkey | (state << 8);
1445                 if ((VK_NUMPAD0 <= vkey && vkey <= VK_DIVIDE) ||
1446                     keyc == kVK_ANSI_KeypadClear || keyc == kVK_ANSI_KeypadEnter ||
1447                     keyc == kVK_ANSI_KeypadEquals)
1448                 {
1449                     /* Keep searching for a non-numpad match, which is preferred. */
1450                 }
1451                 else
1452                     goto done;
1453             }
1454         }
1455     }
1456
1457 done:
1458     TRACE(" -> 0x%04x\n", ret);
1459     return ret;
1460 }