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