Fixed some issues found by winapi_check.
[wine] / windows / input.c
1 /*
2  * USER Input processing
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine 
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  *
10  */
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <assert.h>
17
18 #include "windef.h"
19 #include "winnls.h"
20 #include "winbase.h"
21 #include "wingdi.h"
22 #include "winuser.h"
23 #include "wine/winbase16.h"
24 #include "wine/winuser16.h"
25 #include "wine/keyboard16.h"
26 #include "server.h"
27 #include "win.h"
28 #include "heap.h"
29 #include "input.h"
30 #include "keyboard.h"
31 #include "mouse.h"
32 #include "message.h"
33 #include "queue.h"
34 #include "debugtools.h"
35 #include "winerror.h"
36
37 DECLARE_DEBUG_CHANNEL(key);
38 DECLARE_DEBUG_CHANNEL(keyboard);
39 DECLARE_DEBUG_CHANNEL(win);
40 DEFAULT_DEBUG_CHANNEL(event);
41
42 static BOOL InputEnabled = TRUE;
43 static BOOL SwappedButtons;
44
45 BOOL MouseButtonsStates[3];
46 BOOL AsyncMouseButtonsStates[3];
47 BYTE InputKeyStateTable[256];
48 BYTE QueueKeyStateTable[256];
49 BYTE AsyncKeyStateTable[256];
50
51 /* Storage for the USER-maintained mouse positions */
52 static DWORD PosX, PosY;
53
54 #define GET_KEYSTATE() \
55      ((MouseButtonsStates[SwappedButtons ? 2 : 0]  ? MK_LBUTTON : 0) | \
56       (MouseButtonsStates[1]                       ? MK_RBUTTON : 0) | \
57       (MouseButtonsStates[SwappedButtons ? 0 : 2]  ? MK_MBUTTON : 0) | \
58       (InputKeyStateTable[VK_SHIFT]   & 0x80       ? MK_SHIFT   : 0) | \
59       (InputKeyStateTable[VK_CONTROL] & 0x80       ? MK_CONTROL : 0))
60
61 typedef union
62 {
63     struct
64     {
65         unsigned long count : 16;
66         unsigned long code : 8;
67         unsigned long extended : 1;
68         unsigned long unused : 2;
69         unsigned long win_internal : 2;
70         unsigned long context : 1;
71         unsigned long previous : 1;
72         unsigned long transition : 1;
73     } lp1;
74     unsigned long lp2;
75 } KEYLP;
76
77
78 /***********************************************************************
79  *           queue_raw_hardware_message
80  *
81  * Add a message to the raw hardware queue.
82  * Note: the position is relative to the desktop window.
83  */
84 static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lParam,
85                                         int xPos, int yPos, DWORD time, DWORD extraInfo )
86 {
87     SERVER_START_REQ( send_message )
88     {
89         req->kind   = RAW_HW_MESSAGE;
90         req->id     = (void *)GetCurrentThreadId();
91         req->type   = 0;
92         req->win    = 0;
93         req->msg    = message;
94         req->wparam = wParam;
95         req->lparam = lParam;
96         req->x      = xPos;
97         req->y      = yPos;
98         req->time   = time;
99         req->info   = extraInfo;
100         SERVER_CALL();
101     }
102     SERVER_END_REQ;
103 }
104
105
106 /***********************************************************************
107  *           queue_kbd_event
108  *
109  * Put a keyboard event into a thread queue
110  */
111 static void queue_kbd_event( const KEYBDINPUT *ki )
112 {
113     UINT message;
114     KEYLP keylp;
115
116     keylp.lp2 = 0;
117     keylp.lp1.count = 1;
118     keylp.lp1.code = ki->wScan;
119     keylp.lp1.extended = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
120     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
121                                 * don't remember where I read it - AK */
122                                 /* it's '1' under windows, when a dialog box appears
123                                  * and you press one of the underlined keys - DF*/
124
125     if (ki->dwFlags & KEYEVENTF_KEYUP )
126     {
127         BOOL sysKey = ((InputKeyStateTable[VK_MENU] & 0x80) &&
128                        !(InputKeyStateTable[VK_CONTROL] & 0x80) &&
129                        !(ki->dwFlags & KEYEVENTF_WINE_FORCEEXTENDED)); /* for Alt from AltGr */
130         InputKeyStateTable[ki->wVk] &= ~0x80;
131         keylp.lp1.previous = 1;
132         keylp.lp1.transition = 1;
133         message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
134     }
135     else
136     {
137         keylp.lp1.previous = (InputKeyStateTable[ki->wVk] & 0x80) != 0;
138         keylp.lp1.transition = 0;
139         if (!(InputKeyStateTable[ki->wVk] & 0x80)) InputKeyStateTable[ki->wVk] ^= 0x01;
140         InputKeyStateTable[ki->wVk] |= 0x80;
141         AsyncKeyStateTable[ki->wVk] |= 0x80;
142
143         message = (InputKeyStateTable[VK_MENU] & 0x80) && !(InputKeyStateTable[VK_CONTROL] & 0x80)
144               ? WM_SYSKEYDOWN : WM_KEYDOWN;
145     }
146
147     if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP )
148         keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
149
150     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
151                 ki->wVk, keylp.lp2, InputKeyStateTable[ki->wVk] );
152
153     queue_raw_hardware_message( message, ki->wVk, keylp.lp2,
154                                 PosX, PosY, ki->time, ki->dwExtraInfo );
155 }
156
157
158 /***********************************************************************
159  *              queue_mouse_event
160  */
161 static void queue_mouse_event( const MOUSEINPUT *mi, WORD keystate )
162 {
163     if (mi->dwFlags & MOUSEEVENTF_MOVE)
164     {
165         if (mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
166         {
167             PosX = (mi->dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
168             PosY = (mi->dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
169         }
170         else
171         {
172             int width  = GetSystemMetrics(SM_CXSCREEN);
173             int height = GetSystemMetrics(SM_CYSCREEN);
174             long posX = (long) PosX, posY = (long) PosY;
175
176             /* dx and dy can be negative numbers for relative movements */
177             posX += (long)mi->dx;
178             posY += (long)mi->dy;
179
180             /* Clip to the current screen size */
181             if (posX < 0) PosX = 0;
182             else if (posX >= width) PosX = width - 1;
183             else PosX = posX;
184
185             if (posY < 0) PosY = 0;
186             else if (posY >= height) PosY = height - 1;
187             else PosY = posY;
188         }
189     }
190
191     if (mi->dwFlags & MOUSEEVENTF_MOVE)
192     {
193         queue_raw_hardware_message( WM_MOUSEMOVE, keystate, 0, PosX, PosY,
194                                     mi->time, mi->dwExtraInfo );
195     }
196     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN))
197     {
198         MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
199         queue_raw_hardware_message( WM_LBUTTONDOWN, keystate, 0, PosX, PosY,
200                                     mi->time, mi->dwExtraInfo );
201     }
202     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP))
203     {
204         MouseButtonsStates[0] = FALSE;
205         queue_raw_hardware_message( WM_LBUTTONUP, keystate, 0, PosX, PosY,
206                                     mi->time, mi->dwExtraInfo );
207     }
208     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN))
209     {
210         MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
211         queue_raw_hardware_message( WM_RBUTTONDOWN, keystate, 0, PosX, PosY,
212                                     mi->time, mi->dwExtraInfo );
213     }
214     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP))
215     {
216         MouseButtonsStates[2] = FALSE;
217         queue_raw_hardware_message( WM_RBUTTONUP, keystate, 0, PosX, PosY,
218                                     mi->time, mi->dwExtraInfo );
219     }
220     if (mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
221     {
222         MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
223         queue_raw_hardware_message( WM_MBUTTONDOWN, keystate, 0, PosX, PosY,
224                                     mi->time, mi->dwExtraInfo );
225     }
226     if (mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
227     {
228         MouseButtonsStates[1] = FALSE;
229         queue_raw_hardware_message( WM_MBUTTONUP, keystate, 0, PosX, PosY,
230                                     mi->time, mi->dwExtraInfo );
231     }
232     if (mi->dwFlags & MOUSEEVENTF_WHEEL)
233     {
234         queue_raw_hardware_message( WM_MOUSEWHEEL, MAKELONG( keystate, mi->mouseData), 0,
235                                     PosX, PosY, mi->time, mi->dwExtraInfo );
236     }
237 }
238
239
240 /***********************************************************************
241  *              SendInput  (USER32.@)
242  */
243 UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
244 {
245     UINT i;
246
247     if (!InputEnabled) return 0;
248
249     for (i = 0; i < count; i++, inputs++)
250     {
251         switch(inputs->type)
252         {
253         case INPUT_MOUSE:
254             queue_mouse_event( &inputs->u.mi, GET_KEYSTATE() );
255             break;
256         case INPUT_KEYBOARD:
257             queue_kbd_event( &inputs->u.ki );
258             break;
259         case INPUT_HARDWARE:
260             FIXME( "INPUT_HARDWARE not supported\n" );
261             break;
262         }
263     }
264     return count;
265 }
266
267
268 /***********************************************************************
269  *              keybd_event (USER32.@)
270  */
271 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
272                          DWORD dwFlags, DWORD dwExtraInfo )
273 {
274     INPUT input;
275
276     /*
277      * If we are called by the Wine keyboard driver, use the additional
278      * info pointed to by the dwExtraInfo argument.
279      * Otherwise, we need to determine that info ourselves (probably
280      * less accurate, but we can't help that ...).
281      */
282     if (   !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) )
283         && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC )
284     {
285         WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo;
286         input.u.ki.time = wke->time;
287         input.u.ki.dwExtraInfo = 0;
288     }
289     else
290     {
291         input.u.ki.time = GetTickCount();
292         input.u.ki.dwExtraInfo = dwExtraInfo;
293     }
294     input.type = INPUT_KEYBOARD;
295     input.u.ki.wVk = bVk;
296     input.u.ki.wScan = bScan;
297     input.u.ki.dwFlags = dwFlags;
298     SendInput( 1, &input, sizeof(input) );
299 }
300
301
302 /***********************************************************************
303  *              keybd_event (USER.289)
304  */
305 void WINAPI keybd_event16( CONTEXT86 *context )
306 {
307     DWORD dwFlags = 0;
308
309     if (AH_reg(context) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
310     if (BH_reg(context) & 1   ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
311
312     keybd_event( AL_reg(context), BL_reg(context),
313                  dwFlags, MAKELONG(SI_reg(context), DI_reg(context)) );
314 }
315
316
317 /***********************************************************************
318  *              mouse_event (USER32.@)
319  */
320 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
321                          DWORD dwData, DWORD dwExtraInfo )
322 {
323     INPUT input;
324     WORD keyState;
325
326     input.type = INPUT_MOUSE;
327     input.u.mi.dx = dx;
328     input.u.mi.dy = dy;
329     input.u.mi.mouseData = dwData;
330     input.u.mi.dwFlags = dwFlags;
331
332     /*
333      * If we are called by the Wine mouse driver, use the additional
334      * info pointed to by the dwExtraInfo argument.
335      * Otherwise, we need to determine that info ourselves (probably
336      * less accurate, but we can't help that ...).
337      */
338     if (dwExtraInfo && !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
339         && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
340     {
341         WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
342
343         keyState = wme->keyState;
344
345         if (keyState != GET_KEYSTATE())
346         {
347             /* We need to update the keystate with what X provides us */
348             MouseButtonsStates[SwappedButtons ? 2 : 0] = (keyState & MK_LBUTTON ? TRUE : FALSE);
349             MouseButtonsStates[SwappedButtons ? 0 : 2] = (keyState & MK_RBUTTON ? TRUE : FALSE);
350             MouseButtonsStates[1]                      = (keyState & MK_MBUTTON ? TRUE : FALSE);
351             InputKeyStateTable[VK_SHIFT]               = (keyState & MK_SHIFT   ? 0x80 : 0);
352             InputKeyStateTable[VK_CONTROL]             = (keyState & MK_CONTROL ? 0x80 : 0);
353         }
354         input.u.mi.time = wme->time;
355         input.u.mi.dwExtraInfo = wme->hWnd;
356         queue_mouse_event( &input.u.mi, keyState );
357     }
358     else
359     {
360         if ( dwFlags & MOUSEEVENTF_MOVE ) /* we have to actually move the cursor */
361             SetCursorPos( PosX, PosY );
362
363         input.u.mi.time = GetCurrentTime();
364         input.u.mi.dwExtraInfo = dwExtraInfo;
365         SendInput( 1, &input, sizeof(input) );
366     }
367 }
368
369
370 /***********************************************************************
371  *              mouse_event (USER.299)
372  */
373 void WINAPI mouse_event16( CONTEXT86 *context )
374 {
375     mouse_event( AX_reg(context), BX_reg(context), CX_reg(context),
376                  DX_reg(context), MAKELONG(SI_reg(context), DI_reg(context)) );
377 }
378
379 /***********************************************************************
380  *              GetMouseEventProc (USER.337)
381  */
382 FARPROC16 WINAPI GetMouseEventProc16(void)
383 {
384     HMODULE16 hmodule = GetModuleHandle16("USER");
385     return GetProcAddress16( hmodule, "mouse_event" );
386 }
387
388
389 /**********************************************************************
390  *              EnableHardwareInput (USER.331)
391  */
392 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
393 {
394   BOOL16 bOldState = InputEnabled;
395   FIXME_(event)("(%d) - stub\n", bEnable);
396   InputEnabled = bEnable;
397   return bOldState;
398 }
399
400
401 /***********************************************************************
402  *              SwapMouseButton (USER.186)
403  */
404 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
405 {
406     BOOL16 ret = SwappedButtons;
407     SwappedButtons = fSwap;
408     return ret;
409 }
410
411
412 /***********************************************************************
413  *              SwapMouseButton (USER32.@)
414  */
415 BOOL WINAPI SwapMouseButton( BOOL fSwap )
416 {
417     BOOL ret = SwappedButtons;
418     SwappedButtons = fSwap;
419     return ret;
420 }
421
422
423 /***********************************************************************
424  *              GetCursorPos (USER.17)
425  */
426 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
427 {
428     POINT pos;
429     if (!pt) return 0;
430     GetCursorPos(&pos);
431     pt->x = pos.x;
432     pt->y = pos.y;
433     return 1;
434 }
435
436
437 /***********************************************************************
438  *              GetCursorPos (USER32.@)
439  */
440 BOOL WINAPI GetCursorPos( POINT *pt )
441 {
442     if (!pt) return 0;
443     pt->x = PosX;
444     pt->y = PosY;
445     if (USER_Driver.pGetCursorPos) USER_Driver.pGetCursorPos( pt );
446     return 1;
447 }
448
449
450 /***********************************************************************
451  *              SetCursorPos (USER.70)
452  */
453 void WINAPI SetCursorPos16( INT16 x, INT16 y )
454 {
455     SetCursorPos( x, y );
456 }
457
458
459 /***********************************************************************
460  *              SetCursorPos (USER32.@)
461  */
462 BOOL WINAPI SetCursorPos( INT x, INT y )
463 {
464     if (USER_Driver.pSetCursorPos) USER_Driver.pSetCursorPos( x, y );
465     PosX = x;
466     PosY = y;
467     return TRUE;
468 }
469
470
471 /**********************************************************************
472  *              EVENT_Capture
473  *
474  * We need this to be able to generate double click messages
475  * when menu code captures mouse in the window without CS_DBLCLK style.
476  */
477 HWND EVENT_Capture(HWND hwnd, INT16 ht)
478 {
479     HWND capturePrev = 0, captureWnd = 0;
480     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
481     WND* wndPtr = 0;
482     INT16 captureHT = 0;
483
484     capturePrev = GetCapture();
485
486     if (!hwnd)
487     {
488         captureWnd = 0;
489         captureHT = 0;
490     }
491     else
492     {
493         wndPtr = WIN_FindWndPtr( hwnd );
494         if (wndPtr)
495         {
496             TRACE_(win)("(0x%04x)\n", hwnd );
497             captureWnd   = hwnd;
498             captureHT    = ht;
499         }
500     }
501
502     /* Get the messageQ for the current thread */
503     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
504     {
505         WARN_(win)("\tCurrent message queue not found. Exiting!\n" );
506         goto CLEANUP;
507     }
508
509     /* Update the perQ capture window and send messages */
510     if( capturePrev != captureWnd )
511     {
512         if (wndPtr)
513         {
514             /* Retrieve the message queue associated with this window */
515             pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
516             if ( !pMsgQ )
517             {
518                 WARN_(win)("\tMessage queue not found. Exiting!\n" );
519                 goto CLEANUP;
520             }
521
522             /* Make sure that message queue for the window we are setting capture to
523              * shares the same perQ data as the current threads message queue.
524              */
525             if ( pCurMsgQ->pQData != pMsgQ->pQData )
526                 goto CLEANUP;
527         }
528
529         PERQDATA_SetCaptureWnd( captureWnd, captureHT );
530         if (capturePrev) SendMessageA( capturePrev, WM_CAPTURECHANGED, 0, hwnd );
531     }
532
533 CLEANUP:
534     /* Unlock the queues before returning */
535     if ( pMsgQ )
536         QUEUE_Unlock( pMsgQ );
537     if ( pCurMsgQ )
538         QUEUE_Unlock( pCurMsgQ );
539     
540     WIN_ReleaseWndPtr(wndPtr);
541     return capturePrev;
542 }
543
544
545 /**********************************************************************
546  *              SetCapture (USER.18)
547  */
548 HWND16 WINAPI SetCapture16( HWND16 hwnd )
549 {
550     return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
551 }
552
553
554 /**********************************************************************
555  *              SetCapture (USER32.@)
556  */
557 HWND WINAPI SetCapture( HWND hwnd )
558 {
559     return EVENT_Capture( hwnd, HTCLIENT );
560 }
561
562
563 /**********************************************************************
564  *              ReleaseCapture (USER.19) (USER32.@)
565  */
566 BOOL WINAPI ReleaseCapture(void)
567 {
568     return (EVENT_Capture( 0, 0 ) != 0);
569 }
570
571
572 /**********************************************************************
573  *              GetCapture (USER.236)
574  */
575 HWND16 WINAPI GetCapture16(void)
576 {
577     return (HWND16)GetCapture();
578 }
579
580 /**********************************************************************
581  *              GetCapture (USER32.@)
582  */
583 HWND WINAPI GetCapture(void)
584 {
585     INT hittest;
586     return PERQDATA_GetCaptureWnd( &hittest );
587 }
588
589 /**********************************************************************
590  *              GetKeyState (USER.106)
591  */
592 INT16 WINAPI GetKeyState16(INT16 vkey)
593 {
594     return GetKeyState(vkey);
595 }
596
597 /**********************************************************************
598  *              GetKeyState (USER32.@)
599  *
600  * An application calls the GetKeyState function in response to a
601  * keyboard-input message.  This function retrieves the state of the key
602  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
603  */
604 SHORT WINAPI GetKeyState(INT vkey)
605 {
606     INT retval;
607
608     switch (vkey)
609         {
610         case VK_LBUTTON : /* VK_LBUTTON is 1 */
611             retval = MouseButtonsStates[0] ? 0x8000 : 0;
612             break;
613         case VK_MBUTTON : /* VK_MBUTTON is 4 */
614             retval = MouseButtonsStates[1] ? 0x8000 : 0;
615             break;
616         case VK_RBUTTON : /* VK_RBUTTON is 2 */
617             retval = MouseButtonsStates[2] ? 0x8000 : 0;
618             break;
619         default :
620             if (vkey >= 'a' && vkey <= 'z')
621                 vkey += 'A' - 'a';
622             retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
623                        (WORD)(QueueKeyStateTable[vkey] & 0x01);
624         }
625     /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
626     return retval;
627 }
628
629 /**********************************************************************
630  *              GetKeyboardState (USER.222) (USER32.@)
631  *
632  * An application calls the GetKeyboardState function in response to a
633  * keyboard-input message.  This function retrieves the state of the keyboard
634  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
635  */
636 BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
637 {
638     TRACE_(key)("(%p)\n", lpKeyState);
639     if (lpKeyState != NULL) {
640         QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
641         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
642         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
643         memcpy(lpKeyState, QueueKeyStateTable, 256);
644     }
645
646     return TRUE;
647 }
648
649 /**********************************************************************
650  *              SetKeyboardState (USER.223) (USER32.@)
651  */
652 BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
653 {
654     TRACE_(key)("(%p)\n", lpKeyState);
655     if (lpKeyState != NULL) {
656         memcpy(QueueKeyStateTable, lpKeyState, 256);
657         MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
658         MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
659         MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
660     }
661
662     return TRUE;
663 }
664
665 /**********************************************************************
666  *              GetAsyncKeyState (USER32.@)
667  *
668  *      Determine if a key is or was pressed.  retval has high-order 
669  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
670  * been pressed.
671  *
672  *      This uses the variable AsyncMouseButtonsStates and
673  * AsyncKeyStateTable (set in event.c) which have the mouse button
674  * number or key number (whichever is applicable) set to true if the
675  * mouse or key had been depressed since the last call to 
676  * GetAsyncKeyState.
677  */
678 WORD WINAPI GetAsyncKeyState(INT nKey)
679 {
680     WORD retval;
681
682     switch (nKey) {
683      case VK_LBUTTON:
684          retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
685                  (MouseButtonsStates[0] ? 0x8000 : 0);
686         AsyncMouseButtonsStates[0] = 0;
687         break;
688      case VK_MBUTTON:
689          retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
690                  (MouseButtonsStates[1] ? 0x8000 : 0);
691         AsyncMouseButtonsStates[1] = 0;
692         break;
693      case VK_RBUTTON:
694          retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
695                  (MouseButtonsStates[2] ? 0x8000 : 0);
696         AsyncMouseButtonsStates[2] = 0;
697         break;
698      default:
699          retval = ((AsyncKeyStateTable[nKey] & 0x80) ? 0x0001 : 0) |
700                   ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
701         AsyncKeyStateTable[nKey] = 0;
702         break;
703     }
704
705     TRACE_(key)("(%x) -> %x\n", nKey, retval);
706     return retval;
707 }
708
709 /**********************************************************************
710  *              GetAsyncKeyState (USER.249)
711  */
712 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
713 {
714     return GetAsyncKeyState(nKey);
715 }
716
717 /***********************************************************************
718  *              IsUserIdle (USER.333)
719  */
720 BOOL16 WINAPI IsUserIdle16(void)
721 {
722     if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
723         return FALSE;
724
725     if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
726         return FALSE;
727
728     if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
729         return FALSE;
730
731     /* Should check for screen saver activation here ... */
732
733     return TRUE;
734 }
735
736 /**********************************************************************
737  *              VkKeyScanA (USER32.@)
738  */
739 WORD WINAPI VkKeyScanA(CHAR cChar)
740 {
741         return VkKeyScan16(cChar);
742 }
743
744 /******************************************************************************
745  *              VkKeyScanW (USER32.@)
746  */
747 WORD WINAPI VkKeyScanW(WCHAR cChar)
748 {
749         return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
750 }
751
752 /**********************************************************************
753  *              VkKeyScanExA (USER32.@)
754  */
755 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
756 {
757                                 /* FIXME: complete workaround this is */
758                                 return VkKeyScan16(cChar);
759 }
760
761 /******************************************************************************
762  *              VkKeyScanExW (USER32.@)
763  */
764 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
765 {
766                                 /* FIXME: complete workaround this is */
767                                 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
768 }
769  
770 /******************************************************************************
771  *              GetKeyboardType (USER32.@)
772  */
773 INT WINAPI GetKeyboardType(INT nTypeFlag)
774 {
775   return GetKeyboardType16(nTypeFlag);
776 }
777
778 /******************************************************************************
779  *              MapVirtualKeyA (USER32.@)
780  */
781 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
782 {
783     return MapVirtualKey16(code,maptype);
784 }
785
786 /******************************************************************************
787  *              MapVirtualKeyW (USER32.@)
788  */
789 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
790 {
791     return MapVirtualKey16(code,maptype);
792 }
793
794 /******************************************************************************
795  *              MapVirtualKeyExA (USER32.@)
796  */
797 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
798 {
799     if (hkl)
800         FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
801     return MapVirtualKey16(code,maptype);
802 }
803
804 /******************************************************************************
805  *              MapVirtualKeyExW (USER32.@)
806  */
807 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
808 {
809     if (hkl)
810         FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
811     return MapVirtualKey16(code,maptype);
812 }
813
814 /****************************************************************************
815  *              GetKBCodePage (USER32.@)
816  */
817 UINT WINAPI GetKBCodePage(void)
818 {
819     return GetOEMCP();
820 }
821
822 /****************************************************************************
823  *              GetKeyboardLayoutName (USER.477)
824  */
825 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
826 {
827         return GetKeyboardLayoutNameA(pwszKLID);
828 }
829
830 /***********************************************************************
831  *              GetKeyboardLayout (USER32.@)
832  *
833  * FIXME: - device handle for keyboard layout defaulted to 
834  *          the language id. This is the way Windows default works.
835  *        - the thread identifier (dwLayout) is also ignored.
836  */
837 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
838 {
839         HKL layout;
840         layout = GetSystemDefaultLCID(); /* FIXME */
841         layout |= (layout<<16);          /* FIXME */
842         TRACE_(keyboard)("returning %08x\n",layout);
843         return layout;
844 }
845
846 /****************************************************************************
847  *              GetKeyboardLayoutNameA (USER32.@)
848  */
849 INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
850 {
851         sprintf(pwszKLID, "%08x",GetKeyboardLayout(0));
852         return 1;
853 }
854
855 /****************************************************************************
856  *              GetKeyboardLayoutNameW (USER32.@)
857  */
858 INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
859 {
860         char buf[KL_NAMELENGTH];
861         int res = GetKeyboardLayoutNameA(buf);
862         MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
863         return res;
864 }
865
866 /****************************************************************************
867  *              GetKeyNameTextA (USER32.@)
868  */
869 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
870 {
871         return GetKeyNameText16(lParam,lpBuffer,nSize);
872 }
873
874 /****************************************************************************
875  *              GetKeyNameTextW (USER32.@)
876  */
877 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
878 {
879         int res;
880         LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
881         if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
882         res = GetKeyNameTextA(lParam,buf,nSize);
883
884         if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
885             lpBuffer[nSize-1] = 0;
886         HeapFree( GetProcessHeap(), 0, buf );
887         return res;
888 }
889
890 /****************************************************************************
891  *              ToUnicode (USER32.@)
892  */
893 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
894                      LPWSTR lpwStr, int size, UINT flags)
895 {
896     return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
897 }
898
899 /****************************************************************************
900  *              ToUnicodeEx (USER32.@)
901  */
902 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
903                        LPWSTR lpwStr, int size, UINT flags, HKL hkl)
904 {
905     /* FIXME: need true implementation */
906     return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
907 }
908
909 /****************************************************************************
910  *              ToAscii (USER32.@)
911  */
912 INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
913                         LPWORD lpChar,UINT flags )
914 {
915     WCHAR uni_chars[2];
916     INT ret, n_ret;
917
918     ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
919     if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
920     else n_ret = ret;
921     WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
922     return ret;
923 }
924
925 /****************************************************************************
926  *              ToAsciiEx (USER32.@)
927  */
928 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
929                       LPWORD lpChar, UINT flags, HKL dwhkl )
930 {
931     /* FIXME: need true implementation */
932     return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
933 }
934
935 /**********************************************************************
936  *              ActivateKeyboardLayout (USER32.@)
937  *
938  * Call ignored. WINE supports only system default keyboard layout.
939  */
940 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
941 {
942     TRACE_(keyboard)("(%d, %d)\n", hLayout, flags);
943     ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
944     return 0;
945 }
946
947
948 /***********************************************************************
949  *              GetKeyboardLayoutList (USER32.@)
950  *
951  * FIXME: Supports only the system default language and layout and 
952  *          returns only 1 value.
953  *
954  * Return number of values available if either input parm is 
955  *  0, per MS documentation.
956  *
957  */
958 INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
959 {
960         TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
961         if (!nBuff || !layouts)
962             return 1;
963         if (layouts)
964                 layouts[0] = GetKeyboardLayout(0);
965         return 1;
966 }
967
968
969 /***********************************************************************
970  *              RegisterHotKey (USER32.@)
971  */
972 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) {
973         FIXME_(keyboard)("(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
974         return TRUE;
975 }
976
977 /***********************************************************************
978  *              UnregisterHotKey (USER32.@)
979  */
980 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) {
981         FIXME_(keyboard)("(0x%08x,%d): stub\n",hwnd,id);
982         return TRUE;
983 }
984
985 /***********************************************************************
986  *              LoadKeyboardLayoutA (USER32.@)
987  * Call ignored. WINE supports only system default keyboard layout.
988  */
989 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
990 {
991     TRACE_(keyboard)("(%s, %d)\n", pwszKLID, Flags);
992     ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
993   return 0; 
994 }
995
996 /***********************************************************************
997  *              LoadKeyboardLayoutW (USER32.@)
998  */
999 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
1000 {
1001     char buf[9];
1002     
1003     WideCharToMultiByte( CP_ACP, 0, pwszKLID, -1, buf, sizeof(buf), NULL, NULL );
1004     buf[8] = 0;
1005     return LoadKeyboardLayoutA(buf, Flags);
1006 }