[USER32]
[reactos.git] / reactos / win32ss / user / user32 / windows / input.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS user32.dll
21 * FILE: dll/win32/user32/windows/input.c
22 * PURPOSE: Input
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 09-05-2001 CSH Created
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <user32.h>
31
32 #include <strsafe.h>
33
34 #include <wine/debug.h>
35 WINE_DEFAULT_DEBUG_CHANNEL(user32);
36
37 /* GLOBALS *******************************************************************/
38
39
40
41 /* FUNCTIONS *****************************************************************/
42
43
44 /*
45 * @implemented
46 */
47 BOOL
48 WINAPI
49 DragDetect(
50 HWND hWnd,
51 POINT pt)
52 {
53 return NtUserDragDetect(hWnd, pt);
54 #if 0
55 MSG msg;
56 RECT rect;
57 POINT tmp;
58 ULONG dx = GetSystemMetrics(SM_CXDRAG);
59 ULONG dy = GetSystemMetrics(SM_CYDRAG);
60
61 rect.left = pt.x - dx;
62 rect.right = pt.x + dx;
63 rect.top = pt.y - dy;
64 rect.bottom = pt.y + dy;
65
66 SetCapture(hWnd);
67
68 for (;;)
69 {
70 while (
71 PeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
72 PeekMessageW(&msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)
73 )
74 {
75 if (msg.message == WM_LBUTTONUP)
76 {
77 ReleaseCapture();
78 return FALSE;
79 }
80 if (msg.message == WM_MOUSEMOVE)
81 {
82 tmp.x = LOWORD(msg.lParam);
83 tmp.y = HIWORD(msg.lParam);
84 if (!PtInRect(&rect, tmp))
85 {
86 ReleaseCapture();
87 return TRUE;
88 }
89 }
90 if (msg.message == WM_KEYDOWN)
91 {
92 if (msg.wParam == VK_ESCAPE)
93 {
94 ReleaseCapture();
95 return TRUE;
96 }
97 }
98 }
99 WaitMessage();
100 }
101 return 0;
102 #endif
103 }
104
105 /*
106 * @implemented
107 */
108 BOOL WINAPI
109 EnableWindow(HWND hWnd, BOOL bEnable)
110 {
111 return NtUserxEnableWindow(hWnd, bEnable);
112 }
113
114 /*
115 * @implemented
116 */
117 SHORT WINAPI
118 GetAsyncKeyState(int vKey)
119 {
120 if (vKey < 0 || vKey > 256)
121 return 0;
122 return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey);
123 }
124
125
126 /*
127 * @implemented
128 */
129 HKL WINAPI
130 GetKeyboardLayout(DWORD idThread)
131 {
132 return NtUserxGetKeyboardLayout(idThread);
133 }
134
135
136 /*
137 * @implemented
138 */
139 UINT WINAPI
140 GetKBCodePage(VOID)
141 {
142 return GetOEMCP();
143 }
144
145
146 /*
147 * @implemented
148 */
149 int WINAPI
150 GetKeyNameTextA(LONG lParam,
151 LPSTR lpString,
152 int nSize)
153 {
154 LPWSTR pwszBuf;
155 UINT cchBuf = 0;
156 int iRet = 0;
157 BOOL defChar = FALSE;
158
159 pwszBuf = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR));
160 if (!pwszBuf)
161 return 0;
162
163 cchBuf = NtUserGetKeyNameText(lParam, pwszBuf, nSize);
164
165 iRet = WideCharToMultiByte(CP_ACP, 0,
166 pwszBuf, cchBuf,
167 lpString, nSize, ".", &defChar); // FIXME: do we need defChar?
168 lpString[iRet] = 0;
169 HeapFree(GetProcessHeap(), 0, pwszBuf);
170
171 return iRet;
172 }
173
174 /*
175 * @implemented
176 */
177 int WINAPI
178 GetKeyNameTextW(LONG lParam,
179 LPWSTR lpString,
180 int nSize)
181 {
182 return NtUserGetKeyNameText(lParam, lpString, nSize);
183 }
184
185 /*
186 * @implemented
187 */
188 SHORT WINAPI
189 GetKeyState(int nVirtKey)
190 {
191 return (SHORT)NtUserGetKeyState((DWORD)nVirtKey);
192 }
193
194 /*
195 * @implemented
196 */
197 BOOL WINAPI
198 GetKeyboardLayoutNameA(LPSTR pwszKLID)
199 {
200 WCHAR buf[KL_NAMELENGTH];
201
202 if (!GetKeyboardLayoutNameW(buf))
203 return FALSE;
204
205 if (!WideCharToMultiByte(CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH, NULL, NULL))
206 return FALSE;
207
208 return TRUE;
209 }
210
211 /*
212 * @implemented
213 */
214 BOOL WINAPI
215 GetKeyboardLayoutNameW(LPWSTR pwszKLID)
216 {
217 return NtUserGetKeyboardLayoutName(pwszKLID);
218 }
219
220 /*
221 * @implemented
222 */
223 int WINAPI
224 GetKeyboardType(int nTypeFlag)
225 {
226 return NtUserxGetKeyboardType(nTypeFlag);
227 }
228
229 /*
230 * @implemented
231 */
232 BOOL WINAPI
233 GetLastInputInfo(PLASTINPUTINFO plii)
234 {
235 TRACE("%p\n", plii);
236
237 if (plii->cbSize != sizeof (*plii))
238 {
239 SetLastError(ERROR_INVALID_PARAMETER);
240 return FALSE;
241 }
242
243 plii->dwTime = gpsi->dwLastRITEventTickCount;
244 return TRUE;
245 }
246
247 /*
248 * @implemented
249 */
250 HKL WINAPI
251 LoadKeyboardLayoutA(LPCSTR pszKLID,
252 UINT Flags)
253 {
254 WCHAR wszKLID[16];
255
256 if (!MultiByteToWideChar(CP_ACP, 0, pszKLID, -1,
257 wszKLID, sizeof(wszKLID)/sizeof(wszKLID[0])))
258 {
259 return FALSE;
260 }
261
262 return LoadKeyboardLayoutW(wszKLID, Flags);
263 }
264
265 /*
266 * @implemented
267 */
268 HKL WINAPI
269 LoadKeyboardLayoutW(LPCWSTR pwszKLID,
270 UINT Flags)
271 {
272 DWORD dwhkl, dwType, dwSize;
273 UNICODE_STRING ustrKbdName;
274 UNICODE_STRING ustrKLID;
275 WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
276 WCHAR wszLayoutId[10], wszNewKLID[10];
277 HKEY hKey;
278
279 /* LOWORD of dwhkl is Locale Identifier */
280 dwhkl = wcstol(pwszKLID, NULL, 16);
281
282 if (Flags & KLF_SUBSTITUTE_OK)
283 {
284 /* Check substitutes key */
285 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0,
286 KEY_READ, &hKey) == ERROR_SUCCESS)
287 {
288 dwSize = sizeof(wszNewKLID);
289 if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS)
290 {
291 /* Use new KLID value */
292 pwszKLID = wszNewKLID;
293 }
294
295 /* Close the key now */
296 RegCloseKey(hKey);
297 }
298 }
299
300 /* Append KLID at the end of registry key */
301 StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID);
302
303 /* Open layout registry key for read */
304 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0,
305 KEY_READ, &hKey) == ERROR_SUCCESS)
306 {
307 dwSize = sizeof(wszLayoutId);
308 if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS)
309 {
310 /* If Layout Id is specified, use this value | f000 as HIWORD */
311 /* FIXME: Microsoft Office expects this value to be something specific
312 * for Japanese and Korean Windows with an IME the value is 0xe001
313 * We should probably check to see if an IME exists and if so then
314 * set this word properly.
315 */
316 dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16;
317 }
318
319 /* Close the key now */
320 RegCloseKey(hKey);
321 }
322 else
323 ERR("RegOpenKeyExW failed!\n");
324
325 /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */
326 if (!HIWORD(dwhkl))
327 dwhkl |= dwhkl << 16;
328
329 ZeroMemory(&ustrKbdName, sizeof(ustrKbdName));
330 RtlInitUnicodeString(&ustrKLID, pwszKLID);
331 return NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName,
332 NULL, &ustrKLID,
333 dwhkl, Flags);
334 }
335
336 /*
337 * @implemented
338 */
339 UINT WINAPI
340 MapVirtualKeyA(UINT uCode,
341 UINT uMapType)
342 {
343 return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0));
344 }
345
346 /*
347 * @implemented
348 */
349 UINT WINAPI
350 MapVirtualKeyExA(UINT uCode,
351 UINT uMapType,
352 HKL dwhkl)
353 {
354 return MapVirtualKeyExW(uCode, uMapType, dwhkl);
355 }
356
357
358 /*
359 * @implemented
360 */
361 UINT WINAPI
362 MapVirtualKeyExW(UINT uCode,
363 UINT uMapType,
364 HKL dwhkl)
365 {
366 return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl);
367 }
368
369
370 /*
371 * @implemented
372 */
373 UINT WINAPI
374 MapVirtualKeyW(UINT uCode,
375 UINT uMapType)
376 {
377 return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0));
378 }
379
380
381 /*
382 * @implemented
383 */
384 DWORD WINAPI
385 OemKeyScan(WORD wOemChar)
386 {
387 WCHAR p;
388 SHORT Vk;
389 UINT Scan;
390
391 MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1);
392 Vk = VkKeyScanW(p);
393 Scan = MapVirtualKeyW((Vk & 0x00ff), 0);
394 if (!Scan) return -1;
395 /*
396 Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the
397 scan code and high word has the shift state.
398 */
399 return ((Vk & 0xff00) << 8) | Scan;
400 }
401
402
403 /*
404 * @implemented
405 */
406 BOOL WINAPI
407 SetDoubleClickTime(UINT uInterval)
408 {
409 return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME,
410 uInterval,
411 NULL,
412 0);
413 }
414
415
416 /*
417 * @implemented
418 */
419 BOOL
420 WINAPI
421 SwapMouseButton(
422 BOOL fSwap)
423 {
424 return NtUserxSwapMouseButton(fSwap);
425 }
426
427
428 /*
429 * @implemented
430 */
431 int WINAPI
432 ToAscii(UINT uVirtKey,
433 UINT uScanCode,
434 CONST BYTE *lpKeyState,
435 LPWORD lpChar,
436 UINT uFlags)
437 {
438 return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0);
439 }
440
441
442 /*
443 * @implemented
444 */
445 int WINAPI
446 ToAsciiEx(UINT uVirtKey,
447 UINT uScanCode,
448 CONST BYTE *lpKeyState,
449 LPWORD lpChar,
450 UINT uFlags,
451 HKL dwhkl)
452 {
453 WCHAR UniChars[2];
454 int Ret, CharCount;
455
456 Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl);
457 CharCount = (Ret < 0 ? 1 : Ret);
458 WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL);
459
460 return Ret;
461 }
462
463
464 /*
465 * @implemented
466 */
467 int WINAPI
468 ToUnicode(UINT wVirtKey,
469 UINT wScanCode,
470 CONST BYTE *lpKeyState,
471 LPWSTR pwszBuff,
472 int cchBuff,
473 UINT wFlags)
474 {
475 return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
476 wFlags, 0);
477 }
478
479
480 /*
481 * @implemented
482 */
483 int WINAPI
484 ToUnicodeEx(UINT wVirtKey,
485 UINT wScanCode,
486 CONST BYTE *lpKeyState,
487 LPWSTR pwszBuff,
488 int cchBuff,
489 UINT wFlags,
490 HKL dwhkl)
491 {
492 return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff,
493 wFlags, dwhkl);
494 }
495
496
497
498 /*
499 * @implemented
500 */
501 SHORT WINAPI
502 VkKeyScanA(CHAR ch)
503 {
504 WCHAR wChar;
505
506 if (IsDBCSLeadByte(ch))
507 return -1;
508
509 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
510 return VkKeyScanW(wChar);
511 }
512
513
514 /*
515 * @implemented
516 */
517 SHORT WINAPI
518 VkKeyScanExA(CHAR ch,
519 HKL dwhkl)
520 {
521 WCHAR wChar;
522
523 if (IsDBCSLeadByte(ch))
524 return -1;
525
526 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
527 return VkKeyScanExW(wChar, dwhkl);
528 }
529
530
531 /*
532 * @implemented
533 */
534 SHORT WINAPI
535 VkKeyScanExW(WCHAR ch,
536 HKL dwhkl)
537 {
538 return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE);
539 }
540
541
542 /*
543 * @implemented
544 */
545 SHORT WINAPI
546 VkKeyScanW(WCHAR ch)
547 {
548 return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE);
549 }
550
551
552 /*
553 * @implemented
554 */
555 VOID
556 WINAPI
557 keybd_event(
558 BYTE bVk,
559 BYTE bScan,
560 DWORD dwFlags,
561 ULONG_PTR dwExtraInfo)
562 {
563 INPUT Input;
564
565 Input.type = INPUT_KEYBOARD;
566 Input.ki.wVk = bVk;
567 Input.ki.wScan = bScan;
568 Input.ki.dwFlags = dwFlags;
569 Input.ki.time = 0;
570 Input.ki.dwExtraInfo = dwExtraInfo;
571
572 NtUserSendInput(1, &Input, sizeof(INPUT));
573 }
574
575
576 /*
577 * @implemented
578 */
579 VOID
580 WINAPI
581 mouse_event(
582 DWORD dwFlags,
583 DWORD dx,
584 DWORD dy,
585 DWORD dwData,
586 ULONG_PTR dwExtraInfo)
587 {
588 INPUT Input;
589
590 Input.type = INPUT_MOUSE;
591 Input.mi.dx = dx;
592 Input.mi.dy = dy;
593 Input.mi.mouseData = dwData;
594 Input.mi.dwFlags = dwFlags;
595 Input.mi.time = 0;
596 Input.mi.dwExtraInfo = dwExtraInfo;
597
598 NtUserSendInput(1, &Input, sizeof(INPUT));
599 }
600
601 /* EOF */