Added mappings for a few messages.
[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 "wine/server.h"
27 #include "win.h"
28 #include "input.h"
29 #include "keyboard.h"
30 #include "mouse.h"
31 #include "message.h"
32 #include "queue.h"
33 #include "debugtools.h"
34 #include "winerror.h"
35
36 DECLARE_DEBUG_CHANNEL(key);
37 DECLARE_DEBUG_CHANNEL(keyboard);
38 DECLARE_DEBUG_CHANNEL(win);
39 DEFAULT_DEBUG_CHANNEL(event);
40
41 static BOOL InputEnabled = TRUE;
42 static BOOL SwappedButtons;
43
44 BOOL MouseButtonsStates[3];
45 BOOL AsyncMouseButtonsStates[3];
46 BYTE InputKeyStateTable[256];
47 BYTE QueueKeyStateTable[256];
48 BYTE AsyncKeyStateTable[256];
49
50 /* Storage for the USER-maintained mouse positions */
51 static DWORD PosX, PosY;
52
53 #define GET_KEYSTATE() \
54      ((MouseButtonsStates[SwappedButtons ? 2 : 0]  ? MK_LBUTTON : 0) | \
55       (MouseButtonsStates[1]                       ? MK_RBUTTON : 0) | \
56       (MouseButtonsStates[SwappedButtons ? 0 : 2]  ? MK_MBUTTON : 0) | \
57       (InputKeyStateTable[VK_SHIFT]   & 0x80       ? MK_SHIFT   : 0) | \
58       (InputKeyStateTable[VK_CONTROL] & 0x80       ? MK_CONTROL : 0))
59
60 typedef union
61 {
62     struct
63     {
64         unsigned long count : 16;
65         unsigned long code : 8;
66         unsigned long extended : 1;
67         unsigned long unused : 2;
68         unsigned long win_internal : 2;
69         unsigned long context : 1;
70         unsigned long previous : 1;
71         unsigned long transition : 1;
72     } lp1;
73     unsigned long lp2;
74 } KEYLP;
75
76
77 /***********************************************************************
78  *           queue_raw_hardware_message
79  *
80  * Add a message to the raw hardware queue.
81  * Note: the position is relative to the desktop window.
82  */
83 static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lParam,
84                                         int xPos, int yPos, DWORD time, DWORD extraInfo )
85 {
86     SERVER_START_REQ( send_message )
87     {
88         req->id     = (void *)GetCurrentThreadId();
89         req->type   = MSG_HARDWARE_RAW;
90         req->win    = 0;
91         req->msg    = message;
92         req->wparam = wParam;
93         req->lparam = lParam;
94         req->x      = xPos;
95         req->y      = yPos;
96         req->time   = time;
97         req->info   = extraInfo;
98         req->timeout = 0;
99         SERVER_CALL();
100     }
101     SERVER_END_REQ;
102 }
103
104
105 /***********************************************************************
106  *           queue_kbd_event
107  *
108  * Put a keyboard event into a thread queue
109  */
110 static void queue_kbd_event( const KEYBDINPUT *ki )
111 {
112     UINT message;
113     KEYLP keylp;
114
115     keylp.lp2 = 0;
116     keylp.lp1.count = 1;
117     keylp.lp1.code = ki->wScan;
118     keylp.lp1.extended = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
119     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
120                                 * don't remember where I read it - AK */
121                                 /* it's '1' under windows, when a dialog box appears
122                                  * and you press one of the underlined keys - DF*/
123
124     if (ki->dwFlags & KEYEVENTF_KEYUP )
125     {
126         BOOL sysKey = ((InputKeyStateTable[VK_MENU] & 0x80) &&
127                        !(InputKeyStateTable[VK_CONTROL] & 0x80) &&
128                        !(ki->dwFlags & KEYEVENTF_WINE_FORCEEXTENDED)); /* for Alt from AltGr */
129         InputKeyStateTable[ki->wVk] &= ~0x80;
130         keylp.lp1.previous = 1;
131         keylp.lp1.transition = 1;
132         message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
133     }
134     else
135     {
136         keylp.lp1.previous = (InputKeyStateTable[ki->wVk] & 0x80) != 0;
137         keylp.lp1.transition = 0;
138         if (!(InputKeyStateTable[ki->wVk] & 0x80)) InputKeyStateTable[ki->wVk] ^= 0x01;
139         InputKeyStateTable[ki->wVk] |= 0x80;
140         AsyncKeyStateTable[ki->wVk] |= 0x80;
141
142         message = (InputKeyStateTable[VK_MENU] & 0x80) && !(InputKeyStateTable[VK_CONTROL] & 0x80)
143               ? WM_SYSKEYDOWN : WM_KEYDOWN;
144     }
145
146     if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP )
147         keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
148
149     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
150                 ki->wVk, keylp.lp2, InputKeyStateTable[ki->wVk] );
151
152     queue_raw_hardware_message( message, ki->wVk, keylp.lp2,
153                                 PosX, PosY, ki->time, ki->dwExtraInfo );
154 }
155
156
157 /***********************************************************************
158  *              queue_mouse_event
159  */
160 static void queue_mouse_event( const MOUSEINPUT *mi, WORD keystate )
161 {
162     if (mi->dwFlags & MOUSEEVENTF_MOVE)
163     {
164         if (mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
165         {
166             PosX = (mi->dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
167             PosY = (mi->dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
168         }
169         else
170         {
171             int width  = GetSystemMetrics(SM_CXSCREEN);
172             int height = GetSystemMetrics(SM_CYSCREEN);
173             long posX = (long) PosX, posY = (long) PosY;
174
175             /* dx and dy can be negative numbers for relative movements */
176             posX += (long)mi->dx;
177             posY += (long)mi->dy;
178
179             /* Clip to the current screen size */
180             if (posX < 0) PosX = 0;
181             else if (posX >= width) PosX = width - 1;
182             else PosX = posX;
183
184             if (posY < 0) PosY = 0;
185             else if (posY >= height) PosY = height - 1;
186             else PosY = posY;
187         }
188     }
189
190     if (mi->dwFlags & MOUSEEVENTF_MOVE)
191     {
192         queue_raw_hardware_message( WM_MOUSEMOVE, keystate, 0, PosX, PosY,
193                                     mi->time, mi->dwExtraInfo );
194     }
195     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN))
196     {
197         MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
198         queue_raw_hardware_message( WM_LBUTTONDOWN, keystate, 0, PosX, PosY,
199                                     mi->time, mi->dwExtraInfo );
200     }
201     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP))
202     {
203         MouseButtonsStates[0] = FALSE;
204         queue_raw_hardware_message( WM_LBUTTONUP, keystate, 0, PosX, PosY,
205                                     mi->time, mi->dwExtraInfo );
206     }
207     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN))
208     {
209         MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
210         queue_raw_hardware_message( WM_RBUTTONDOWN, keystate, 0, PosX, PosY,
211                                     mi->time, mi->dwExtraInfo );
212     }
213     if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP))
214     {
215         MouseButtonsStates[2] = FALSE;
216         queue_raw_hardware_message( WM_RBUTTONUP, keystate, 0, PosX, PosY,
217                                     mi->time, mi->dwExtraInfo );
218     }
219     if (mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
220     {
221         MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
222         queue_raw_hardware_message( WM_MBUTTONDOWN, keystate, 0, PosX, PosY,
223                                     mi->time, mi->dwExtraInfo );
224     }
225     if (mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
226     {
227         MouseButtonsStates[1] = FALSE;
228         queue_raw_hardware_message( WM_MBUTTONUP, keystate, 0, PosX, PosY,
229                                     mi->time, mi->dwExtraInfo );
230     }
231     if (mi->dwFlags & MOUSEEVENTF_WHEEL)
232     {
233         queue_raw_hardware_message( WM_MOUSEWHEEL, MAKELONG( keystate, mi->mouseData), 0,
234                                     PosX, PosY, mi->time, mi->dwExtraInfo );
235     }
236 }
237
238
239 /***********************************************************************
240  *              SendInput  (USER32.@)
241  */
242 UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
243 {
244     UINT i;
245
246     if (!InputEnabled) return 0;
247
248     for (i = 0; i < count; i++, inputs++)
249     {
250         switch(inputs->type)
251         {
252         case INPUT_MOUSE:
253             queue_mouse_event( &inputs->u.mi, GET_KEYSTATE() );
254             break;
255         case INPUT_KEYBOARD:
256             queue_kbd_event( &inputs->u.ki );
257             break;
258         case INPUT_HARDWARE:
259             FIXME( "INPUT_HARDWARE not supported\n" );
260             break;
261         }
262     }
263     return count;
264 }
265
266
267 /***********************************************************************
268  *              keybd_event (USER32.@)
269  */
270 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
271                          DWORD dwFlags, DWORD dwExtraInfo )
272 {
273     INPUT input;
274
275     /*
276      * If we are called by the Wine keyboard driver, use the additional
277      * info pointed to by the dwExtraInfo argument.
278      * Otherwise, we need to determine that info ourselves (probably
279      * less accurate, but we can't help that ...).
280      */
281     if (   !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) )
282         && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC )
283     {
284         WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo;
285         input.u.ki.time = wke->time;
286         input.u.ki.dwExtraInfo = 0;
287     }
288     else
289     {
290         input.u.ki.time = GetTickCount();
291         input.u.ki.dwExtraInfo = dwExtraInfo;
292     }
293     input.type = INPUT_KEYBOARD;
294     input.u.ki.wVk = bVk;
295     input.u.ki.wScan = bScan;
296     input.u.ki.dwFlags = dwFlags;
297     SendInput( 1, &input, sizeof(input) );
298 }
299
300
301 /***********************************************************************
302  *              keybd_event (USER.289)
303  */
304 void WINAPI keybd_event16( CONTEXT86 *context )
305 {
306     DWORD dwFlags = 0;
307
308     if (AH_reg(context) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
309     if (BH_reg(context) & 1   ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
310
311     keybd_event( AL_reg(context), BL_reg(context),
312                  dwFlags, MAKELONG(SI_reg(context), DI_reg(context)) );
313 }
314
315
316 /***********************************************************************
317  *              mouse_event (USER32.@)
318  */
319 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
320                          DWORD dwData, DWORD dwExtraInfo )
321 {
322     INPUT input;
323     WORD keyState;
324
325     input.type = INPUT_MOUSE;
326     input.u.mi.dx = dx;
327     input.u.mi.dy = dy;
328     input.u.mi.mouseData = dwData;
329     input.u.mi.dwFlags = dwFlags;
330
331     /*
332      * If we are called by the Wine mouse driver, use the additional
333      * info pointed to by the dwExtraInfo argument.
334      * Otherwise, we need to determine that info ourselves (probably
335      * less accurate, but we can't help that ...).
336      */
337     if (dwExtraInfo && !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
338         && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
339     {
340         WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
341
342         keyState = wme->keyState;
343
344         if (keyState != GET_KEYSTATE())
345         {
346             /* We need to update the keystate with what X provides us */
347             MouseButtonsStates[SwappedButtons ? 2 : 0] = (keyState & MK_LBUTTON ? TRUE : FALSE);
348             MouseButtonsStates[SwappedButtons ? 0 : 2] = (keyState & MK_RBUTTON ? TRUE : FALSE);
349             MouseButtonsStates[1]                      = (keyState & MK_MBUTTON ? TRUE : FALSE);
350             InputKeyStateTable[VK_SHIFT]               = (keyState & MK_SHIFT   ? 0x80 : 0);
351             InputKeyStateTable[VK_CONTROL]             = (keyState & MK_CONTROL ? 0x80 : 0);
352         }
353         input.u.mi.time = wme->time;
354         input.u.mi.dwExtraInfo = wme->hWnd;
355         queue_mouse_event( &input.u.mi, keyState );
356     }
357     else
358     {
359         if ( dwFlags & MOUSEEVENTF_MOVE ) /* we have to actually move the cursor */
360             SetCursorPos( PosX, PosY );
361
362         input.u.mi.time = GetCurrentTime();
363         input.u.mi.dwExtraInfo = dwExtraInfo;
364         SendInput( 1, &input, sizeof(input) );
365     }
366 }
367
368
369 /***********************************************************************
370  *              mouse_event (USER.299)
371  */
372 void WINAPI mouse_event16( CONTEXT86 *context )
373 {
374     mouse_event( AX_reg(context), BX_reg(context), CX_reg(context),
375                  DX_reg(context), MAKELONG(SI_reg(context), DI_reg(context)) );
376 }
377
378 /***********************************************************************
379  *              GetMouseEventProc (USER.337)
380  */
381 FARPROC16 WINAPI GetMouseEventProc16(void)
382 {
383     HMODULE16 hmodule = GetModuleHandle16("USER");
384     return GetProcAddress16( hmodule, "mouse_event" );
385 }
386
387
388 /**********************************************************************
389  *              EnableHardwareInput (USER.331)
390  */
391 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
392 {
393   BOOL16 bOldState = InputEnabled;
394   FIXME_(event)("(%d) - stub\n", bEnable);
395   InputEnabled = bEnable;
396   return bOldState;
397 }
398
399
400 /***********************************************************************
401  *              SwapMouseButton (USER.186)
402  */
403 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
404 {
405     BOOL16 ret = SwappedButtons;
406     SwappedButtons = fSwap;
407     return ret;
408 }
409
410
411 /***********************************************************************
412  *              SwapMouseButton (USER32.@)
413  */
414 BOOL WINAPI SwapMouseButton( BOOL fSwap )
415 {
416     BOOL ret = SwappedButtons;
417     SwappedButtons = fSwap;
418     return ret;
419 }
420
421
422 /***********************************************************************
423  *              GetCursorPos (USER.17)
424  */
425 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
426 {
427     POINT pos;
428     if (!pt) return 0;
429     GetCursorPos(&pos);
430     pt->x = pos.x;
431     pt->y = pos.y;
432     return 1;
433 }
434
435
436 /***********************************************************************
437  *              GetCursorPos (USER32.@)
438  */
439 BOOL WINAPI GetCursorPos( POINT *pt )
440 {
441     if (!pt) return 0;
442     pt->x = PosX;
443     pt->y = PosY;
444     if (USER_Driver.pGetCursorPos) USER_Driver.pGetCursorPos( pt );
445     return 1;
446 }
447
448
449 /***********************************************************************
450  *              SetCursorPos (USER.70)
451  */
452 void WINAPI SetCursorPos16( INT16 x, INT16 y )
453 {
454     SetCursorPos( x, y );
455 }
456
457
458 /***********************************************************************
459  *              SetCursorPos (USER32.@)
460  */
461 BOOL WINAPI SetCursorPos( INT x, INT y )
462 {
463     if (USER_Driver.pSetCursorPos) USER_Driver.pSetCursorPos( x, y );
464     PosX = x;
465     PosY = y;
466     return TRUE;
467 }
468
469
470 /**********************************************************************
471  *              EVENT_Capture
472  *
473  * We need this to be able to generate double click messages
474  * when menu code captures mouse in the window without CS_DBLCLK style.
475  */
476 HWND EVENT_Capture(HWND hwnd, INT16 ht)
477 {
478     HWND capturePrev = 0, captureWnd = 0;
479     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
480     WND* wndPtr = 0;
481     INT16 captureHT = 0;
482
483     capturePrev = GetCapture();
484
485     if (!hwnd)
486     {
487         captureWnd = 0;
488         captureHT = 0;
489     }
490     else
491     {
492         wndPtr = WIN_FindWndPtr( hwnd );
493         if (wndPtr)
494         {
495             TRACE_(win)("(0x%04x)\n", hwnd );
496             captureWnd   = hwnd;
497             captureHT    = ht;
498         }
499     }
500
501     /* Get the messageQ for the current thread */
502     if (!(pCurMsgQ = QUEUE_Current()))
503     {
504         WARN_(win)("\tCurrent message queue not found. Exiting!\n" );
505         goto CLEANUP;
506     }
507
508     /* Update the perQ capture window and send messages */
509     if( capturePrev != captureWnd )
510     {
511         if (wndPtr)
512         {
513             /* Retrieve the message queue associated with this window */
514             pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
515             if ( !pMsgQ )
516             {
517                 WARN_(win)("\tMessage queue not found. Exiting!\n" );
518                 goto CLEANUP;
519             }
520
521             /* Make sure that message queue for the window we are setting capture to
522              * shares the same perQ data as the current threads message queue.
523              */
524             if ( pCurMsgQ->pQData != pMsgQ->pQData )
525                 goto CLEANUP;
526         }
527
528         PERQDATA_SetCaptureWnd( captureWnd, captureHT );
529         if (capturePrev) SendMessageA( capturePrev, WM_CAPTURECHANGED, 0, hwnd );
530     }
531
532 CLEANUP:
533     /* Unlock the queues before returning */
534     if ( pMsgQ )
535         QUEUE_Unlock( pMsgQ );
536
537     WIN_ReleaseWndPtr(wndPtr);
538     return capturePrev;
539 }
540
541
542 /**********************************************************************
543  *              SetCapture (USER.18)
544  */
545 HWND16 WINAPI SetCapture16( HWND16 hwnd )
546 {
547     return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
548 }
549
550
551 /**********************************************************************
552  *              SetCapture (USER32.@)
553  */
554 HWND WINAPI SetCapture( HWND hwnd )
555 {
556     return EVENT_Capture( hwnd, HTCLIENT );
557 }
558
559
560 /**********************************************************************
561  *              ReleaseCapture (USER.19)
562  *              ReleaseCapture (USER32.@)
563  */
564 BOOL WINAPI ReleaseCapture(void)
565 {
566     return (EVENT_Capture( 0, 0 ) != 0);
567 }
568
569
570 /**********************************************************************
571  *              GetCapture (USER.236)
572  */
573 HWND16 WINAPI GetCapture16(void)
574 {
575     return (HWND16)GetCapture();
576 }
577
578 /**********************************************************************
579  *              GetCapture (USER32.@)
580  */
581 HWND WINAPI GetCapture(void)
582 {
583     INT hittest;
584     return PERQDATA_GetCaptureWnd( &hittest );
585 }
586
587 /**********************************************************************
588  *              GetKeyState (USER.106)
589  */
590 INT16 WINAPI GetKeyState16(INT16 vkey)
591 {
592     return GetKeyState(vkey);
593 }
594
595 /**********************************************************************
596  *              GetKeyState (USER32.@)
597  *
598  * An application calls the GetKeyState function in response to a
599  * keyboard-input message.  This function retrieves the state of the key
600  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
601  */
602 SHORT WINAPI GetKeyState(INT vkey)
603 {
604     INT retval;
605
606     switch (vkey)
607         {
608         case VK_LBUTTON : /* VK_LBUTTON is 1 */
609             retval = MouseButtonsStates[0] ? 0x8000 : 0;
610             break;
611         case VK_MBUTTON : /* VK_MBUTTON is 4 */
612             retval = MouseButtonsStates[1] ? 0x8000 : 0;
613             break;
614         case VK_RBUTTON : /* VK_RBUTTON is 2 */
615             retval = MouseButtonsStates[2] ? 0x8000 : 0;
616             break;
617         default :
618             if (vkey >= 'a' && vkey <= 'z')
619                 vkey += 'A' - 'a';
620             retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
621                        (WORD)(QueueKeyStateTable[vkey] & 0x01);
622         }
623     /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
624     return retval;
625 }
626
627 /**********************************************************************
628  *              GetKeyboardState (USER.222)
629  *              GetKeyboardState (USER32.@)
630  *
631  * An application calls the GetKeyboardState function in response to a
632  * keyboard-input message.  This function retrieves the state of the keyboard
633  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
634  */
635 BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
636 {
637     TRACE_(key)("(%p)\n", lpKeyState);
638     if (lpKeyState != NULL) {
639         QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
640         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
641         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
642         memcpy(lpKeyState, QueueKeyStateTable, 256);
643     }
644
645     return TRUE;
646 }
647
648 /**********************************************************************
649  *              SetKeyboardState (USER.223)
650  *              SetKeyboardState (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 }