xref: /reactos/win32ss/user/user32/windows/input.c (revision c2c66aff)
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 /* 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 = LOWORD(wcstoul(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     {
328         ERR("Could not find keyboard layout %S.\n", pwszKLID);
329         return NULL;
330     }
331 
332     /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */
333     if (!HIWORD(dwhkl))
334         dwhkl |= dwhkl << 16;
335 
336     ZeroMemory(&ustrKbdName, sizeof(ustrKbdName));
337     RtlInitUnicodeString(&ustrKLID, pwszKLID);
338     return NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName,
339                                       NULL, &ustrKLID,
340                                       dwhkl, Flags);
341 }
342 
343 /*
344  * @implemented
345  */
346 UINT WINAPI
347 MapVirtualKeyA(UINT uCode,
348                UINT uMapType)
349 {
350     return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0));
351 }
352 
353 /*
354  * @implemented
355  */
356 UINT WINAPI
357 MapVirtualKeyExA(UINT uCode,
358                  UINT uMapType,
359                  HKL dwhkl)
360 {
361     return MapVirtualKeyExW(uCode, uMapType, dwhkl);
362 }
363 
364 
365 /*
366  * @implemented
367  */
368 UINT WINAPI
369 MapVirtualKeyExW(UINT uCode,
370                  UINT uMapType,
371                  HKL dwhkl)
372 {
373     return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl);
374 }
375 
376 
377 /*
378  * @implemented
379  */
380 UINT WINAPI
381 MapVirtualKeyW(UINT uCode,
382                UINT uMapType)
383 {
384     return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0));
385 }
386 
387 
388 /*
389  * @implemented
390  */
391 DWORD WINAPI
392 OemKeyScan(WORD wOemChar)
393 {
394     WCHAR p;
395     SHORT Vk;
396     UINT Scan;
397 
398     MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1);
399     Vk = VkKeyScanW(p);
400     Scan = MapVirtualKeyW((Vk & 0x00ff), 0);
401     if (!Scan) return -1;
402     /*
403        Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the
404        scan code and high word has the shift state.
405      */
406     return ((Vk & 0xff00) << 8) | Scan;
407 }
408 
409 
410 /*
411  * @implemented
412  */
413 BOOL WINAPI
414 SetDoubleClickTime(UINT uInterval)
415 {
416     return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME,
417                                             uInterval,
418                                             NULL,
419                                             0);
420 }
421 
422 
423 /*
424  * @implemented
425  */
426 BOOL
427 WINAPI
428 SwapMouseButton(
429     BOOL fSwap)
430 {
431     return NtUserxSwapMouseButton(fSwap);
432 }
433 
434 
435 /*
436  * @implemented
437  */
438 int WINAPI
439 ToAscii(UINT uVirtKey,
440         UINT uScanCode,
441         CONST BYTE *lpKeyState,
442         LPWORD lpChar,
443         UINT uFlags)
444 {
445     return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0);
446 }
447 
448 
449 /*
450  * @implemented
451  */
452 int WINAPI
453 ToAsciiEx(UINT uVirtKey,
454           UINT uScanCode,
455           CONST BYTE *lpKeyState,
456           LPWORD lpChar,
457           UINT uFlags,
458           HKL dwhkl)
459 {
460     WCHAR UniChars[2];
461     int Ret, CharCount;
462 
463     Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl);
464     CharCount = (Ret < 0 ? 1 : Ret);
465     WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL);
466 
467     return Ret;
468 }
469 
470 
471 /*
472  * @implemented
473  */
474 int WINAPI
475 ToUnicode(UINT wVirtKey,
476           UINT wScanCode,
477           CONST BYTE *lpKeyState,
478           LPWSTR pwszBuff,
479           int cchBuff,
480           UINT wFlags)
481 {
482     return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
483                        wFlags, 0);
484 }
485 
486 
487 /*
488  * @implemented
489  */
490 int WINAPI
491 ToUnicodeEx(UINT wVirtKey,
492             UINT wScanCode,
493             CONST BYTE *lpKeyState,
494             LPWSTR pwszBuff,
495             int cchBuff,
496             UINT wFlags,
497             HKL dwhkl)
498 {
499     return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff,
500                              wFlags, dwhkl);
501 }
502 
503 
504 
505 /*
506  * @implemented
507  */
508 SHORT WINAPI
509 VkKeyScanA(CHAR ch)
510 {
511     WCHAR wChar;
512 
513     if (IsDBCSLeadByte(ch))
514         return -1;
515 
516     MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
517     return VkKeyScanW(wChar);
518 }
519 
520 
521 /*
522  * @implemented
523  */
524 SHORT WINAPI
525 VkKeyScanExA(CHAR ch,
526              HKL dwhkl)
527 {
528     WCHAR wChar;
529 
530     if (IsDBCSLeadByte(ch))
531         return -1;
532 
533     MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
534     return VkKeyScanExW(wChar, dwhkl);
535 }
536 
537 
538 /*
539  * @implemented
540  */
541 SHORT WINAPI
542 VkKeyScanExW(WCHAR ch,
543              HKL dwhkl)
544 {
545     return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE);
546 }
547 
548 
549 /*
550  * @implemented
551  */
552 SHORT WINAPI
553 VkKeyScanW(WCHAR ch)
554 {
555     return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE);
556 }
557 
558 
559 /*
560  * @implemented
561  */
562 VOID
563 WINAPI
564 keybd_event(
565     BYTE bVk,
566     BYTE bScan,
567     DWORD dwFlags,
568     ULONG_PTR dwExtraInfo)
569 {
570     INPUT Input;
571 
572     Input.type = INPUT_KEYBOARD;
573     Input.ki.wVk = bVk;
574     Input.ki.wScan = bScan;
575     Input.ki.dwFlags = dwFlags;
576     Input.ki.time = 0;
577     Input.ki.dwExtraInfo = dwExtraInfo;
578 
579     NtUserSendInput(1, &Input, sizeof(INPUT));
580 }
581 
582 
583 /*
584  * @implemented
585  */
586 VOID
587 WINAPI
588 mouse_event(
589     DWORD dwFlags,
590     DWORD dx,
591     DWORD dy,
592     DWORD dwData,
593     ULONG_PTR dwExtraInfo)
594 {
595     INPUT Input;
596 
597     Input.type = INPUT_MOUSE;
598     Input.mi.dx = dx;
599     Input.mi.dy = dy;
600     Input.mi.mouseData = dwData;
601     Input.mi.dwFlags = dwFlags;
602     Input.mi.time = 0;
603     Input.mi.dwExtraInfo = dwExtraInfo;
604 
605     NtUserSendInput(1, &Input, sizeof(INPUT));
606 }
607 
608 /* EOF */
609