ucrtbase: Add support for r-value demangling in unDName.
[wine.git] / dlls / win32u / input.c
blob90a77639d1a2b13ebced81b208d65d55bf68f604
1 /*
2 * USER Input processing
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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #if 0
26 #pragma makedep unix
27 #endif
29 #include "win32u_private.h"
30 #include "wine/server.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(win);
34 WINE_DECLARE_DEBUG_CHANNEL(keyboard);
36 static const WCHAR keyboard_layouts_keyW[] =
38 '\\','R','e','g','i','s','t','r','y',
39 '\\','M','a','c','h','i','n','e',
40 '\\','S','y','s','t','e','m',
41 '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
42 '\\','C','o','n','t','r','o','l',
43 '\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s'
47 /**********************************************************************
48 * NtUserAttachThreadInput (win32u.@)
50 BOOL WINAPI NtUserAttachThreadInput( DWORD from, DWORD to, BOOL attach )
52 BOOL ret;
54 SERVER_START_REQ( attach_thread_input )
56 req->tid_from = from;
57 req->tid_to = to;
58 req->attach = attach;
59 ret = !wine_server_call_err( req );
61 SERVER_END_REQ;
62 return ret;
65 /***********************************************************************
66 * get_locale_kbd_layout
68 static HKL get_locale_kbd_layout(void)
70 LCID layout;
71 LANGID langid;
73 /* FIXME:
75 * layout = main_key_tab[kbd_layout].lcid;
77 * Winword uses return value of GetKeyboardLayout as a codepage
78 * to translate ANSI keyboard messages to unicode. But we have
79 * a problem with it: for instance Polish keyboard layout is
80 * identical to the US one, and therefore instead of the Polish
81 * locale id we return the US one.
84 NtQueryDefaultLocale( TRUE, &layout );
87 * Microsoft Office expects this value to be something specific
88 * for Japanese and Korean Windows with an IME the value is 0xe001
89 * We should probably check to see if an IME exists and if so then
90 * set this word properly.
92 langid = PRIMARYLANGID( LANGIDFROMLCID( layout ) );
93 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
94 layout = MAKELONG( layout, 0xe001 ); /* IME */
95 else
96 layout = MAKELONG( layout, layout );
98 return ULongToHandle( layout );
101 /***********************************************************************
102 * NtUserGetKeyboardLayout (win32u.@)
104 * Device handle for keyboard layout defaulted to
105 * the language id. This is the way Windows default works.
107 HKL WINAPI NtUserGetKeyboardLayout( DWORD thread_id )
109 struct user_thread_info *thread = get_user_thread_info();
110 HKL layout = thread->kbd_layout;
112 if (thread_id && thread_id != GetCurrentThreadId())
113 FIXME( "couldn't return keyboard layout for thread %04x\n", thread_id );
115 if (!layout) return get_locale_kbd_layout();
116 return layout;
119 /**********************************************************************
120 * NtUserGetKeyState (win32u.@)
122 * An application calls the GetKeyState function in response to a
123 * keyboard-input message. This function retrieves the state of the key
124 * at the time the input message was generated.
126 SHORT WINAPI NtUserGetKeyState( INT vkey )
128 SHORT retval = 0;
130 SERVER_START_REQ( get_key_state )
132 req->key = vkey;
133 if (!wine_server_call( req )) retval = (signed char)(reply->state & 0x81);
135 SERVER_END_REQ;
136 TRACE("key (0x%x) -> %x\n", vkey, retval);
137 return retval;
140 /**********************************************************************
141 * NtUserGetKeyboardState (win32u.@)
143 BOOL WINAPI NtUserGetKeyboardState( BYTE *state )
145 BOOL ret;
146 UINT i;
148 TRACE("(%p)\n", state);
150 memset( state, 0, 256 );
151 SERVER_START_REQ( get_key_state )
153 req->key = -1;
154 wine_server_set_reply( req, state, 256 );
155 ret = !wine_server_call_err( req );
156 for (i = 0; i < 256; i++) state[i] &= 0x81;
158 SERVER_END_REQ;
159 return ret;
162 /**********************************************************************
163 * NtUserSetKeyboardState (win32u.@)
165 BOOL WINAPI NtUserSetKeyboardState( BYTE *state )
167 BOOL ret;
169 SERVER_START_REQ( set_key_state )
171 wine_server_add_data( req, state, 256 );
172 ret = !wine_server_call_err( req );
174 SERVER_END_REQ;
175 return ret;
178 /******************************************************************************
179 * NtUserVkKeyScanEx (win32u.@)
181 WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout )
183 WORD shift = 0x100, ctrl = 0x200;
184 SHORT ret;
186 TRACE_(keyboard)( "chr %s, layout %p\n", debugstr_wn(&chr, 1), layout );
188 if ((ret = user_driver->pVkKeyScanEx( chr, layout )) != -256) return ret;
190 /* FIXME: English keyboard layout specific */
192 if (chr == VK_CANCEL || chr == VK_BACK || chr == VK_TAB || chr == VK_RETURN ||
193 chr == VK_ESCAPE || chr == VK_SPACE) ret = chr;
194 else if (chr >= '0' && chr <= '9') ret = chr;
195 else if (chr == ')') ret = shift + '0';
196 else if (chr == '!') ret = shift + '1';
197 else if (chr == '@') ret = shift + '2';
198 else if (chr == '#') ret = shift + '3';
199 else if (chr == '$') ret = shift + '4';
200 else if (chr == '%') ret = shift + '5';
201 else if (chr == '^') ret = shift + '6';
202 else if (chr == '&') ret = shift + '7';
203 else if (chr == '*') ret = shift + '8';
204 else if (chr == '(') ret = shift + '9';
205 else if (chr >= 'a' && chr <= 'z') ret = chr - 'a' + 'A';
206 else if (chr >= 'A' && chr <= 'Z') ret = shift + chr;
207 else if (chr == ';') ret = VK_OEM_1;
208 else if (chr == '=') ret = VK_OEM_PLUS;
209 else if (chr == ',') ret = VK_OEM_COMMA;
210 else if (chr == '-') ret = VK_OEM_MINUS;
211 else if (chr == '.') ret = VK_OEM_PERIOD;
212 else if (chr == '/') ret = VK_OEM_2;
213 else if (chr == '`') ret = VK_OEM_3;
214 else if (chr == '[') ret = VK_OEM_4;
215 else if (chr == '\\') ret = VK_OEM_5;
216 else if (chr == ']') ret = VK_OEM_6;
217 else if (chr == '\'') ret = VK_OEM_7;
218 else if (chr == ':') ret = shift + VK_OEM_1;
219 else if (chr == '+') ret = shift + VK_OEM_PLUS;
220 else if (chr == '<') ret = shift + VK_OEM_COMMA;
221 else if (chr == '_') ret = shift + VK_OEM_MINUS;
222 else if (chr == '>') ret = shift + VK_OEM_PERIOD;
223 else if (chr == '?') ret = shift + VK_OEM_2;
224 else if (chr == '~') ret = shift + VK_OEM_3;
225 else if (chr == '{') ret = shift + VK_OEM_4;
226 else if (chr == '|') ret = shift + VK_OEM_5;
227 else if (chr == '}') ret = shift + VK_OEM_6;
228 else if (chr == '\"') ret = shift + VK_OEM_7;
229 else if (chr == 0x7f) ret = ctrl + VK_BACK;
230 else if (chr == '\n') ret = ctrl + VK_RETURN;
231 else if (chr == 0xf000) ret = ctrl + '2';
232 else if (chr == 0x0000) ret = ctrl + shift + '2';
233 else if (chr >= 0x0001 && chr <= 0x001a) ret = ctrl + 'A' + chr - 1;
234 else if (chr >= 0x001c && chr <= 0x001d) ret = ctrl + VK_OEM_3 + chr;
235 else if (chr == 0x001e) ret = ctrl + shift + '6';
236 else if (chr == 0x001f) ret = ctrl + shift + VK_OEM_MINUS;
237 else ret = -1;
239 TRACE_(keyboard)( "ret %04x\n", ret );
240 return ret;
243 /* English keyboard layout (0x0409) */
244 static const UINT kbd_en_vsc2vk[] =
246 0x00, 0x1b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0xbd, 0xbb, 0x08, 0x09,
247 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 0x50, 0xdb, 0xdd, 0x0d, 0xa2, 0x41, 0x53,
248 0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0xba, 0xde, 0xc0, 0xa0, 0xdc, 0x5a, 0x58, 0x43, 0x56,
249 0x42, 0x4e, 0x4d, 0xbc, 0xbe, 0xbf, 0xa1, 0x6a, 0xa4, 0x20, 0x14, 0x70, 0x71, 0x72, 0x73, 0x74,
250 0x75, 0x76, 0x77, 0x78, 0x79, 0x90, 0x91, 0x24, 0x26, 0x21, 0x6d, 0x25, 0x0c, 0x27, 0x6b, 0x23,
251 0x28, 0x22, 0x2d, 0x2e, 0x2c, 0x00, 0xe2, 0x7a, 0x7b, 0x0c, 0xee, 0xf1, 0xea, 0xf9, 0xf5, 0xf3,
252 0x00, 0x00, 0xfb, 0x2f, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xed,
253 0x00, 0xe9, 0x00, 0xc1, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x09, 0x00, 0xc2, 0x00,
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 /* 0xe000 */
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x0d, 0xa3, 0x00, 0x00,
265 0xad, 0xb7, 0xb3, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00,
266 0xaf, 0x00, 0xac, 0x00, 0x00, 0x6f, 0x00, 0x2c, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x24, 0x26, 0x21, 0x00, 0x25, 0x00, 0x27, 0x00, 0x23,
268 0x28, 0x22, 0x2d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x5c, 0x5d, 0x00, 0x5f,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xab, 0xa8, 0xa9, 0xa7, 0xa6, 0xb6, 0xb4, 0xb5, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 /* 0xe100 */
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 static const UINT kbd_en_vk2char[] =
300 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00,
302 ' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
305 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00,
306 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '+', 0x00, '-', '.', '/',
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ';', '=', ',', '-', '.', '/',
312 '`', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '[', '\\', ']', '\'', 0x00,
314 0x00, 0x00, '\\', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 static const char *kbd_en_vscname[] =
320 0, "Esc", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Backspace", "Tab",
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Enter", "Ctrl", 0, 0,
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Shift", 0, 0, 0, 0, 0,
323 0, 0, 0, 0, 0, 0, "Right Shift", "Num *", "Alt", "Space", "Caps Lock", "F1", "F2", "F3", "F4", "F5",
324 "F6", "F7", "F8", "F9", "F10", "Pause", "Scroll Lock", "Num 7", "Num 8", "Num 9", "Num -", "Num 4", "Num 5", "Num 6", "Num +", "Num 1",
325 "Num 2", "Num 3", "Num 0", "Num Del", "Sys Req", 0, 0, "F11", "F12", 0, 0, 0, 0, 0, 0, 0,
326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "F13", "F14", "F15", "F16",
328 "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", 0, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
336 /* extended */
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Num Enter", "Right Ctrl", 0, 0,
339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340 0, 0, 0, 0, 0, "Num /", 0, "Prnt Scrn", "Right Alt", 0, 0, 0, 0, 0, 0, 0,
341 0, 0, 0, 0, 0, "Num Lock", "Break", "Home", "Up", "Page Up", 0, "Left", 0, "Right", 0, "End",
342 "Down", "Page Down", "Insert", "Delete", "<00>", 0, "Help", 0, 0, 0, 0, "Left Windows", "Right Windows", "Application", 0, 0,
343 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
345 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
349 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
355 /******************************************************************************
356 * NtUserMapVirtualKeyEx (win32u.@)
358 UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout )
360 const UINT *vsc2vk, *vk2char;
361 UINT vsc2vk_size, vk2char_size;
362 UINT ret;
364 TRACE_(keyboard)( "code %u, type %u, layout %p.\n", code, type, layout );
366 if ((ret = user_driver->pMapVirtualKeyEx( code, type, layout )) != -1) return ret;
368 /* FIXME: English keyboard layout specific */
370 vsc2vk = kbd_en_vsc2vk;
371 vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk);
372 vk2char = kbd_en_vk2char;
373 vk2char_size = ARRAYSIZE(kbd_en_vk2char);
375 switch (type)
377 case MAPVK_VK_TO_VSC_EX:
378 case MAPVK_VK_TO_VSC:
379 switch (code)
381 case VK_SHIFT: code = VK_LSHIFT; break;
382 case VK_CONTROL: code = VK_LCONTROL; break;
383 case VK_MENU: code = VK_LMENU; break;
384 case VK_NUMPAD0: code = VK_INSERT; break;
385 case VK_NUMPAD1: code = VK_END; break;
386 case VK_NUMPAD2: code = VK_DOWN; break;
387 case VK_NUMPAD3: code = VK_NEXT; break;
388 case VK_NUMPAD4: code = VK_LEFT; break;
389 case VK_NUMPAD5: code = VK_CLEAR; break;
390 case VK_NUMPAD6: code = VK_RIGHT; break;
391 case VK_NUMPAD7: code = VK_HOME; break;
392 case VK_NUMPAD8: code = VK_UP; break;
393 case VK_NUMPAD9: code = VK_PRIOR; break;
394 case VK_DECIMAL: code = VK_DELETE; break;
397 for (ret = 0; ret < vsc2vk_size; ++ret) if (vsc2vk[ret] == code) break;
398 if (ret >= vsc2vk_size) ret = 0;
400 if (type == MAPVK_VK_TO_VSC)
402 if (ret >= 0x200) ret = 0;
403 else ret &= 0xff;
405 else if (ret >= 0x100) ret += 0xdf00;
406 break;
407 case MAPVK_VSC_TO_VK:
408 case MAPVK_VSC_TO_VK_EX:
409 if (code & 0xe000) code -= 0xdf00;
410 if (code >= vsc2vk_size) ret = 0;
411 else ret = vsc2vk[code];
413 if (type == MAPVK_VSC_TO_VK)
415 switch (ret)
417 case VK_LSHIFT: case VK_RSHIFT: ret = VK_SHIFT; break;
418 case VK_LCONTROL: case VK_RCONTROL: ret = VK_CONTROL; break;
419 case VK_LMENU: case VK_RMENU: ret = VK_MENU; break;
422 break;
423 case MAPVK_VK_TO_CHAR:
424 if (code >= vk2char_size) ret = 0;
425 else ret = vk2char[code];
426 break;
427 default:
428 FIXME_(keyboard)( "unknown type %d\n", type );
429 return 0;
432 TRACE_(keyboard)( "returning 0x%04x\n", ret );
433 return ret;
436 /****************************************************************************
437 * NtUserGetKeyNameText (win32u.@)
439 INT WINAPI NtUserGetKeyNameText( LONG lparam, WCHAR *buffer, INT size )
441 INT code = ((lparam >> 16) & 0x1ff), vkey, len;
442 UINT vsc2vk_size, vscname_size;
443 const char *const *vscname;
444 const UINT *vsc2vk;
446 TRACE_(keyboard)( "lparam %d, buffer %p, size %d.\n", lparam, buffer, size );
448 if (!buffer || !size) return 0;
449 if ((len = user_driver->pGetKeyNameText( lparam, buffer, size )) >= 0) return len;
451 /* FIXME: English keyboard layout specific */
453 vsc2vk = kbd_en_vsc2vk;
454 vsc2vk_size = ARRAYSIZE(kbd_en_vsc2vk);
455 vscname = kbd_en_vscname;
456 vscname_size = ARRAYSIZE(kbd_en_vscname);
458 if (lparam & 0x2000000)
460 switch ((vkey = vsc2vk[code]))
462 case VK_RSHIFT:
463 case VK_RCONTROL:
464 case VK_RMENU:
465 for (code = 0; code < vsc2vk_size; ++code)
466 if (vsc2vk[code] == (vkey - 1)) break;
467 break;
471 if (code < vscname_size)
473 if (vscname[code])
475 len = min( size - 1, strlen(vscname[code]) );
476 ascii_to_unicode( buffer, vscname[code], len );
478 else if (size > 1)
480 HKL hkl = NtUserGetKeyboardLayout( 0 );
481 vkey = NtUserMapVirtualKeyEx( code & 0xff, MAPVK_VSC_TO_VK, hkl );
482 buffer[0] = NtUserMapVirtualKeyEx( vkey, MAPVK_VK_TO_CHAR, hkl );
483 len = 1;
486 buffer[len] = 0;
488 TRACE_(keyboard)( "ret %d, str %s.\n", len, debugstr_w(buffer) );
489 return len;
492 /****************************************************************************
493 * NtUserToUnicodeEx (win32u.@)
495 INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
496 WCHAR *str, int size, UINT flags, HKL layout )
498 BOOL shift, ctrl, alt, numlock;
499 WCHAR buffer[2];
500 INT len;
502 TRACE_(keyboard)( "virt %u, scan %u, state %p, str %p, size %d, flags %x, layout %p.\n",
503 virt, scan, state, str, size, flags, layout );
505 if (!state) return 0;
506 if ((len = user_driver->pToUnicodeEx( virt, scan, state, str, size, flags, layout )) >= -1)
507 return len;
509 alt = state[VK_MENU] & 0x80;
510 shift = state[VK_SHIFT] & 0x80;
511 ctrl = state[VK_CONTROL] & 0x80;
512 numlock = state[VK_NUMLOCK] & 0x01;
514 /* FIXME: English keyboard layout specific */
516 if (scan & 0x8000) buffer[0] = 0; /* key up */
517 else if (virt == VK_ESCAPE) buffer[0] = VK_ESCAPE;
518 else if (!ctrl)
520 switch (virt)
522 case VK_BACK: buffer[0] = '\b'; break;
523 case VK_OEM_1: buffer[0] = shift ? ':' : ';'; break;
524 case VK_OEM_2: buffer[0] = shift ? '?' : '/'; break;
525 case VK_OEM_3: buffer[0] = shift ? '~' : '`'; break;
526 case VK_OEM_4: buffer[0] = shift ? '{' : '['; break;
527 case VK_OEM_5: buffer[0] = shift ? '|' : '\\'; break;
528 case VK_OEM_6: buffer[0] = shift ? '}' : ']'; break;
529 case VK_OEM_7: buffer[0] = shift ? '"' : '\''; break;
530 case VK_OEM_COMMA: buffer[0] = shift ? '<' : ','; break;
531 case VK_OEM_MINUS: buffer[0] = shift ? '_' : '-'; break;
532 case VK_OEM_PERIOD: buffer[0] = shift ? '>' : '.'; break;
533 case VK_OEM_PLUS: buffer[0] = shift ? '+' : '='; break;
534 case VK_RETURN: buffer[0] = '\r'; break;
535 case VK_SPACE: buffer[0] = ' '; break;
536 case VK_TAB: buffer[0] = '\t'; break;
537 case VK_MULTIPLY: buffer[0] = '*'; break;
538 case VK_ADD: buffer[0] = '+'; break;
539 case VK_SUBTRACT: buffer[0] = '-'; break;
540 case VK_DIVIDE: buffer[0] = '/'; break;
541 default:
542 if (virt >= '0' && virt <= '9')
543 buffer[0] = shift ? ")!@#$%^&*("[virt - '0'] : virt;
544 else if (virt >= 'A' && virt <= 'Z')
545 buffer[0] = shift || (state[VK_CAPITAL] & 0x01) ? virt : virt + 'a' - 'A';
546 else if (virt >= VK_NUMPAD0 && virt <= VK_NUMPAD9 && numlock && !shift)
547 buffer[0] = '0' + virt - VK_NUMPAD0;
548 else if (virt == VK_DECIMAL && numlock && !shift)
549 buffer[0] = '.';
550 else
551 buffer[0] = 0;
552 break;
555 else if (!alt) /* Control codes */
557 switch (virt)
559 case VK_OEM_4: buffer[0] = 0x1b; break;
560 case VK_OEM_5: buffer[0] = 0x1c; break;
561 case VK_OEM_6: buffer[0] = 0x1d; break;
562 case '6': buffer[0] = shift ? 0x1e : 0; break;
563 case VK_OEM_MINUS: buffer[0] = shift ? 0x1f : 0; break;
564 case VK_BACK: buffer[0] = 0x7f; break;
565 case VK_RETURN: buffer[0] = shift ? 0 : '\n'; break;
566 case '2': buffer[0] = shift ? 0xffff : 0xf000; break;
567 case VK_SPACE: buffer[0] = ' '; break;
568 default:
569 if (virt >= 'A' && virt <= 'Z') buffer[0] = virt - 'A' + 1;
570 else buffer[0] = 0;
571 break;
574 else buffer[0] = 0;
575 buffer[1] = 0;
576 len = lstrlenW( buffer );
577 if (buffer[0] == 0xffff) buffer[0] = 0;
578 lstrcpynW( str, buffer, size );
580 TRACE_(keyboard)( "ret %d, str %s.\n", len, debugstr_w(str) );
581 return len;
584 /**********************************************************************
585 * NtUserActivateKeyboardLayout (win32u.@)
587 HKL WINAPI NtUserActivateKeyboardLayout( HKL layout, UINT flags )
589 struct user_thread_info *info = get_user_thread_info();
590 HKL old_layout;
592 TRACE_(keyboard)( "layout %p, flags %x\n", layout, flags );
594 if (flags) FIXME_(keyboard)( "flags %x not supported\n", flags );
596 if (layout == (HKL)HKL_NEXT || layout == (HKL)HKL_PREV)
598 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
599 FIXME_(keyboard)( "HKL_NEXT and HKL_PREV not supported\n" );
600 return 0;
603 if (!user_driver->pActivateKeyboardLayout( layout, flags ))
604 return 0;
606 old_layout = info->kbd_layout;
607 info->kbd_layout = layout;
608 if (old_layout != layout) info->kbd_layout_id = 0;
610 if (!old_layout) return get_locale_kbd_layout();
611 return old_layout;
616 /***********************************************************************
617 * NtUserGetKeyboardLayoutList (win32u.@)
619 * Return number of values available if either input parm is
620 * 0, per MS documentation.
622 UINT WINAPI NtUserGetKeyboardLayoutList( INT size, HKL *layouts )
624 char buffer[4096];
625 KEY_NODE_INFORMATION *key_info = (KEY_NODE_INFORMATION *)buffer;
626 KEY_VALUE_PARTIAL_INFORMATION *value_info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
627 DWORD count, tmp, i = 0;
628 HKEY hkey, subkey;
629 HKL layout;
631 TRACE_(keyboard)( "size %d, layouts %p.\n", size, layouts );
633 if ((count = user_driver->pGetKeyboardLayoutList( size, layouts )) != ~0) return count;
635 layout = get_locale_kbd_layout();
636 count = 0;
638 count++;
639 if (size && layouts)
641 layouts[count - 1] = layout;
642 if (count == size) return count;
645 if ((hkey = reg_open_key( NULL, keyboard_layouts_keyW, sizeof(keyboard_layouts_keyW) )))
647 while (!NtEnumerateKey( hkey, i++, KeyNodeInformation, key_info,
648 sizeof(buffer) - sizeof(WCHAR), &tmp ))
650 if (!(subkey = reg_open_key( hkey, key_info->Name, key_info->NameLength ))) continue;
651 key_info->Name[key_info->NameLength / sizeof(WCHAR)] = 0;
652 tmp = wcstoul( key_info->Name, NULL, 16 );
653 if (query_reg_ascii_value( subkey, "Layout Id", value_info, sizeof(buffer) ) &&
654 value_info->Type == REG_SZ)
655 tmp = MAKELONG( LOWORD( tmp ),
656 0xf000 | (wcstoul( (const WCHAR *)value_info->Data, NULL, 16 ) & 0xfff) );
657 NtClose( subkey );
659 if (layout == UlongToHandle( tmp )) continue;
661 count++;
662 if (size && layouts)
664 layouts[count - 1] = UlongToHandle( tmp );
665 if (count == size) break;
668 NtClose( hkey );
671 return count;
674 /****************************************************************************
675 * NtUserGetKeyboardLayoutName (win32u.@)
677 BOOL WINAPI NtUserGetKeyboardLayoutName( WCHAR *name )
679 struct user_thread_info *info = get_user_thread_info();
680 char buffer[4096];
681 KEY_NODE_INFORMATION *key = (KEY_NODE_INFORMATION *)buffer;
682 KEY_VALUE_PARTIAL_INFORMATION *value = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
683 WCHAR klid[KL_NAMELENGTH];
684 DWORD tmp, i = 0;
685 HKEY hkey, subkey;
686 HKL layout;
688 TRACE_(keyboard)( "name %p\n", name );
690 if (!name)
692 SetLastError( ERROR_NOACCESS );
693 return FALSE;
696 if (info->kbd_layout_id)
698 sprintf( buffer, "%08X", info->kbd_layout_id );
699 asciiz_to_unicode( name, buffer );
700 return TRUE;
703 layout = NtUserGetKeyboardLayout( 0 );
704 tmp = HandleToUlong( layout );
705 if (HIWORD( tmp ) == LOWORD( tmp )) tmp = LOWORD( tmp );
706 sprintf( buffer, "%08X", tmp );
707 asciiz_to_unicode( name, buffer );
709 if ((hkey = reg_open_key( NULL, keyboard_layouts_keyW, sizeof(keyboard_layouts_keyW) )))
711 while (!NtEnumerateKey( hkey, i++, KeyNodeInformation, key,
712 sizeof(buffer) - sizeof(WCHAR), &tmp ))
714 if (!(subkey = reg_open_key( hkey, key->Name, key->NameLength ))) continue;
715 memcpy( klid, key->Name, key->NameLength );
716 klid[key->NameLength / sizeof(WCHAR)] = 0;
717 if (query_reg_ascii_value( subkey, "Layout Id", value, sizeof(buffer) ) &&
718 value->Type == REG_SZ)
719 tmp = 0xf000 | (wcstoul( (const WCHAR *)value->Data, NULL, 16 ) & 0xfff);
720 else
721 tmp = wcstoul( klid, NULL, 16 );
722 NtClose( subkey );
724 if (HIWORD( layout ) == tmp)
726 lstrcpynW( name, klid, KL_NAMELENGTH );
727 break;
730 NtClose( hkey );
733 info->kbd_layout_id = wcstoul( name, NULL, 16 );
735 TRACE_(keyboard)( "ret %s\n", debugstr_w( name ) );
736 return TRUE;
739 /***********************************************************************
740 * NtUserUnregisterHotKey (win32u.@)
742 BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id )
744 BOOL ret;
745 UINT modifiers, vk;
747 TRACE_(keyboard)("(%p,%d)\n",hwnd,id);
749 SERVER_START_REQ( unregister_hotkey )
751 req->window = wine_server_user_handle( hwnd );
752 req->id = id;
753 if ((ret = !wine_server_call_err( req )))
755 modifiers = reply->flags;
756 vk = reply->vkey;
759 SERVER_END_REQ;
761 if (ret)
762 user_driver->pUnregisterHotKey(hwnd, modifiers, vk);
764 return ret;
767 /***********************************************************************
768 * NtUserGetMouseMovePointsEx (win32u.@)
770 int WINAPI NtUserGetMouseMovePointsEx( UINT size, MOUSEMOVEPOINT *ptin, MOUSEMOVEPOINT *ptout,
771 int count, DWORD resolution )
773 cursor_pos_t *pos, positions[64];
774 int copied;
775 unsigned int i;
778 TRACE( "%d, %p, %p, %d, %d\n", size, ptin, ptout, count, resolution );
780 if ((size != sizeof(MOUSEMOVEPOINT)) || (count < 0) || (count > ARRAY_SIZE( positions )))
782 SetLastError( ERROR_INVALID_PARAMETER );
783 return -1;
786 if (!ptin || (!ptout && count))
788 SetLastError( ERROR_NOACCESS );
789 return -1;
792 if (resolution != GMMP_USE_DISPLAY_POINTS)
794 FIXME( "only GMMP_USE_DISPLAY_POINTS is supported for now\n" );
795 SetLastError( ERROR_POINT_NOT_FOUND );
796 return -1;
799 SERVER_START_REQ( get_cursor_history )
801 wine_server_set_reply( req, &positions, sizeof(positions) );
802 if (wine_server_call_err( req )) return -1;
804 SERVER_END_REQ;
806 for (i = 0; i < ARRAY_SIZE( positions ); i++)
808 pos = &positions[i];
809 if (ptin->x == pos->x && ptin->y == pos->y && (!ptin->time || ptin->time == pos->time))
810 break;
813 if (i == ARRAY_SIZE( positions ))
815 SetLastError( ERROR_POINT_NOT_FOUND );
816 return -1;
819 for (copied = 0; copied < count && i < ARRAY_SIZE( positions ); copied++, i++)
821 pos = &positions[i];
822 ptout[copied].x = pos->x;
823 ptout[copied].y = pos->y;
824 ptout[copied].time = pos->time;
825 ptout[copied].dwExtraInfo = pos->info;
828 return copied;