[Win32SS]
[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: 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 */