[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
118 WINAPI
119 DECLSPEC_HOTPATCH
120 GetAsyncKeyState(int vKey)
121 {
122 if (vKey < 0 || vKey > 256)
123 return 0;
124 return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey);
125 }
126
127
128 /*
129 * @implemented
130 */
131 HKL WINAPI
132 GetKeyboardLayout(DWORD idThread)
133 {
134 return NtUserxGetKeyboardLayout(idThread);
135 }
136
137
138 /*
139 * @implemented
140 */
141 UINT WINAPI
142 GetKBCodePage(VOID)
143 {
144 return GetOEMCP();
145 }
146
147
148 /*
149 * @implemented
150 */
151 int WINAPI
152 GetKeyNameTextA(LONG lParam,
153 LPSTR lpString,
154 int nSize)
155 {
156 LPWSTR pwszBuf;
157 UINT cchBuf = 0;
158 int iRet = 0;
159 BOOL defChar = FALSE;
160
161 pwszBuf = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR));
162 if (!pwszBuf)
163 return 0;
164
165 cchBuf = NtUserGetKeyNameText(lParam, pwszBuf, nSize);
166
167 iRet = WideCharToMultiByte(CP_ACP, 0,
168 pwszBuf, cchBuf,
169 lpString, nSize, ".", &defChar); // FIXME: do we need defChar?
170 lpString[iRet] = 0;
171 HeapFree(GetProcessHeap(), 0, pwszBuf);
172
173 return iRet;
174 }
175
176 /*
177 * @implemented
178 */
179 int WINAPI
180 GetKeyNameTextW(LONG lParam,
181 LPWSTR lpString,
182 int nSize)
183 {
184 return NtUserGetKeyNameText(lParam, lpString, nSize);
185 }
186
187 /*
188 * @implemented
189 */
190 SHORT
191 WINAPI
192 DECLSPEC_HOTPATCH
193 GetKeyState(int nVirtKey)
194 {
195 return (SHORT)NtUserGetKeyState((DWORD)nVirtKey);
196 }
197
198 /*
199 * @implemented
200 */
201 BOOL WINAPI
202 GetKeyboardLayoutNameA(LPSTR pwszKLID)
203 {
204 WCHAR buf[KL_NAMELENGTH];
205
206 if (!GetKeyboardLayoutNameW(buf))
207 return FALSE;
208
209 if (!WideCharToMultiByte(CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH, NULL, NULL))
210 return FALSE;
211
212 return TRUE;
213 }
214
215 /*
216 * @implemented
217 */
218 BOOL WINAPI
219 GetKeyboardLayoutNameW(LPWSTR pwszKLID)
220 {
221 return NtUserGetKeyboardLayoutName(pwszKLID);
222 }
223
224 /*
225 * @implemented
226 */
227 int WINAPI
228 GetKeyboardType(int nTypeFlag)
229 {
230 return NtUserxGetKeyboardType(nTypeFlag);
231 }
232
233 /*
234 * @implemented
235 */
236 BOOL WINAPI
237 GetLastInputInfo(PLASTINPUTINFO plii)
238 {
239 TRACE("%p\n", plii);
240
241 if (plii->cbSize != sizeof (*plii))
242 {
243 SetLastError(ERROR_INVALID_PARAMETER);
244 return FALSE;
245 }
246
247 plii->dwTime = gpsi->dwLastRITEventTickCount;
248 return TRUE;
249 }
250
251 /*
252 * @implemented
253 */
254 HKL WINAPI
255 LoadKeyboardLayoutA(LPCSTR pszKLID,
256 UINT Flags)
257 {
258 WCHAR wszKLID[16];
259
260 if (!MultiByteToWideChar(CP_ACP, 0, pszKLID, -1,
261 wszKLID, sizeof(wszKLID)/sizeof(wszKLID[0])))
262 {
263 return FALSE;
264 }
265
266 return LoadKeyboardLayoutW(wszKLID, Flags);
267 }
268
269 /*
270 * @implemented
271 */
272 HKL WINAPI
273 LoadKeyboardLayoutW(LPCWSTR pwszKLID,
274 UINT Flags)
275 {
276 DWORD dwhkl, dwType, dwSize;
277 UNICODE_STRING ustrKbdName;
278 UNICODE_STRING ustrKLID;
279 WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
280 WCHAR wszLayoutId[10], wszNewKLID[10];
281 HKEY hKey;
282
283 /* LOWORD of dwhkl is Locale Identifier */
284 dwhkl = wcstol(pwszKLID, NULL, 16);
285
286 if (Flags & KLF_SUBSTITUTE_OK)
287 {
288 /* Check substitutes key */
289 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0,
290 KEY_READ, &hKey) == ERROR_SUCCESS)
291 {
292 dwSize = sizeof(wszNewKLID);
293 if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS)
294 {
295 /* Use new KLID value */
296 pwszKLID = wszNewKLID;
297 }
298
299 /* Close the key now */
300 RegCloseKey(hKey);
301 }
302 }
303
304 /* Append KLID at the end of registry key */
305 StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID);
306
307 /* Open layout registry key for read */
308 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0,
309 KEY_READ, &hKey) == ERROR_SUCCESS)
310 {
311 dwSize = sizeof(wszLayoutId);
312 if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS)
313 {
314 /* If Layout Id is specified, use this value | f000 as HIWORD */
315 /* FIXME: Microsoft Office expects this value to be something specific
316 * for Japanese and Korean Windows with an IME the value is 0xe001
317 * We should probably check to see if an IME exists and if so then
318 * set this word properly.
319 */
320 dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16;
321 }
322
323 /* Close the key now */
324 RegCloseKey(hKey);
325 }
326 else
327 ERR("RegOpenKeyExW failed!\n");
328
329 /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */
330 if (!HIWORD(dwhkl))
331 dwhkl |= dwhkl << 16;
332
333 ZeroMemory(&ustrKbdName, sizeof(ustrKbdName));
334 RtlInitUnicodeString(&ustrKLID, pwszKLID);
335 return NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName,
336 NULL, &ustrKLID,
337 dwhkl, Flags);
338 }
339
340 /*
341 * @implemented
342 */
343 UINT WINAPI
344 MapVirtualKeyA(UINT uCode,
345 UINT uMapType)
346 {
347 return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0));
348 }
349
350 /*
351 * @implemented
352 */
353 UINT WINAPI
354 MapVirtualKeyExA(UINT uCode,
355 UINT uMapType,
356 HKL dwhkl)
357 {
358 return MapVirtualKeyExW(uCode, uMapType, dwhkl);
359 }
360
361
362 /*
363 * @implemented
364 */
365 UINT WINAPI
366 MapVirtualKeyExW(UINT uCode,
367 UINT uMapType,
368 HKL dwhkl)
369 {
370 return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl);
371 }
372
373
374 /*
375 * @implemented
376 */
377 UINT WINAPI
378 MapVirtualKeyW(UINT uCode,
379 UINT uMapType)
380 {
381 return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0));
382 }
383
384
385 /*
386 * @implemented
387 */
388 DWORD WINAPI
389 OemKeyScan(WORD wOemChar)
390 {
391 WCHAR p;
392 SHORT Vk;
393 UINT Scan;
394
395 MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1);
396 Vk = VkKeyScanW(p);
397 Scan = MapVirtualKeyW((Vk & 0x00ff), 0);
398 if (!Scan) return -1;
399 /*
400 Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the
401 scan code and high word has the shift state.
402 */
403 return ((Vk & 0xff00) << 8) | Scan;
404 }
405
406
407 /*
408 * @implemented
409 */
410 BOOL WINAPI
411 SetDoubleClickTime(UINT uInterval)
412 {
413 return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME,
414 uInterval,
415 NULL,
416 0);
417 }
418
419
420 /*
421 * @implemented
422 */
423 BOOL
424 WINAPI
425 SwapMouseButton(
426 BOOL fSwap)
427 {
428 return NtUserxSwapMouseButton(fSwap);
429 }
430
431
432 /*
433 * @implemented
434 */
435 int WINAPI
436 ToAscii(UINT uVirtKey,
437 UINT uScanCode,
438 CONST BYTE *lpKeyState,
439 LPWORD lpChar,
440 UINT uFlags)
441 {
442 return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0);
443 }
444
445
446 /*
447 * @implemented
448 */
449 int WINAPI
450 ToAsciiEx(UINT uVirtKey,
451 UINT uScanCode,
452 CONST BYTE *lpKeyState,
453 LPWORD lpChar,
454 UINT uFlags,
455 HKL dwhkl)
456 {
457 WCHAR UniChars[2];
458 int Ret, CharCount;
459
460 Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl);
461 CharCount = (Ret < 0 ? 1 : Ret);
462 WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL);
463
464 return Ret;
465 }
466
467
468 /*
469 * @implemented
470 */
471 int WINAPI
472 ToUnicode(UINT wVirtKey,
473 UINT wScanCode,
474 CONST BYTE *lpKeyState,
475 LPWSTR pwszBuff,
476 int cchBuff,
477 UINT wFlags)
478 {
479 return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
480 wFlags, 0);
481 }
482
483
484 /*
485 * @implemented
486 */
487 int WINAPI
488 ToUnicodeEx(UINT wVirtKey,
489 UINT wScanCode,
490 CONST BYTE *lpKeyState,
491 LPWSTR pwszBuff,
492 int cchBuff,
493 UINT wFlags,
494 HKL dwhkl)
495 {
496 return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff,
497 wFlags, dwhkl);
498 }
499
500
501
502 /*
503 * @implemented
504 */
505 SHORT WINAPI
506 VkKeyScanA(CHAR ch)
507 {
508 WCHAR wChar;
509
510 if (IsDBCSLeadByte(ch))
511 return -1;
512
513 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
514 return VkKeyScanW(wChar);
515 }
516
517
518 /*
519 * @implemented
520 */
521 SHORT WINAPI
522 VkKeyScanExA(CHAR ch,
523 HKL dwhkl)
524 {
525 WCHAR wChar;
526
527 if (IsDBCSLeadByte(ch))
528 return -1;
529
530 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
531 return VkKeyScanExW(wChar, dwhkl);
532 }
533
534
535 /*
536 * @implemented
537 */
538 SHORT WINAPI
539 VkKeyScanExW(WCHAR ch,
540 HKL dwhkl)
541 {
542 return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE);
543 }
544
545
546 /*
547 * @implemented
548 */
549 SHORT WINAPI
550 VkKeyScanW(WCHAR ch)
551 {
552 return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE);
553 }
554
555
556 /*
557 * @implemented
558 */
559 VOID
560 WINAPI
561 keybd_event(
562 BYTE bVk,
563 BYTE bScan,
564 DWORD dwFlags,
565 ULONG_PTR dwExtraInfo)
566 {
567 INPUT Input;
568
569 Input.type = INPUT_KEYBOARD;
570 Input.ki.wVk = bVk;
571 Input.ki.wScan = bScan;
572 Input.ki.dwFlags = dwFlags;
573 Input.ki.time = 0;
574 Input.ki.dwExtraInfo = dwExtraInfo;
575
576 NtUserSendInput(1, &Input, sizeof(INPUT));
577 }
578
579
580 /*
581 * @implemented
582 */
583 VOID
584 WINAPI
585 mouse_event(
586 DWORD dwFlags,
587 DWORD dx,
588 DWORD dy,
589 DWORD dwData,
590 ULONG_PTR dwExtraInfo)
591 {
592 INPUT Input;
593
594 Input.type = INPUT_MOUSE;
595 Input.mi.dx = dx;
596 Input.mi.dy = dy;
597 Input.mi.mouseData = dwData;
598 Input.mi.dwFlags = dwFlags;
599 Input.mi.time = 0;
600 Input.mi.dwExtraInfo = dwExtraInfo;
601
602 NtUserSendInput(1, &Input, sizeof(INPUT));
603 }
604
605 /* EOF */