Documentation fixes.
[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)
565  *              ReleaseCapture (USER32.@)
566  */
567 BOOL WINAPI ReleaseCapture(void)
568 {
569     return (EVENT_Capture( 0, 0 ) != 0);
570 }
571
572
573 /**********************************************************************
574  *              GetCapture (USER.236)
575  */
576 HWND16 WINAPI GetCapture16(void)
577 {
578     return (HWND16)GetCapture();
579 }
580
581 /**********************************************************************
582  *              GetCapture (USER32.@)
583  */
584 HWND WINAPI GetCapture(void)
585 {
586     INT hittest;
587     return PERQDATA_GetCaptureWnd( &hittest );
588 }
589
590 /**********************************************************************
591  *              GetKeyState (USER.106)
592  */
593 INT16 WINAPI GetKeyState16(INT16 vkey)
594 {
595     return GetKeyState(vkey);
596 }
597
598 /**********************************************************************
599  *              GetKeyState (USER32.@)
600  *
601  * An application calls the GetKeyState function in response to a
602  * keyboard-input message.  This function retrieves the state of the key
603  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
604  */
605 SHORT WINAPI GetKeyState(INT vkey)
606 {
607     INT retval;
608
609     switch (vkey)
610         {
611         case VK_LBUTTON : /* VK_LBUTTON is 1 */
612             retval = MouseButtonsStates[0] ? 0x8000 : 0;
613             break;
614         case VK_MBUTTON : /* VK_MBUTTON is 4 */
615             retval = MouseButtonsStates[1] ? 0x8000 : 0;
616             break;
617         case VK_RBUTTON : /* VK_RBUTTON is 2 */
618             retval = MouseButtonsStates[2] ? 0x8000 : 0;
619             break;
620         default :
621             if (vkey >= 'a' && vkey <= 'z')
622                 vkey += 'A' - 'a';
623             retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
624                        (WORD)(QueueKeyStateTable[vkey] & 0x01);
625         }
626     /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
627     return retval;
628 }
629
630 /**********************************************************************
631  *              GetKeyboardState (USER.222)
632  *              GetKeyboardState (USER32.@)
633  *
634  * An application calls the GetKeyboardState function in response to a
635  * keyboard-input message.  This function retrieves the state of the keyboard
636  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
637  */
638 BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
639 {
640     TRACE_(key)("(%p)\n", lpKeyState);
641     if (lpKeyState != NULL) {
642         QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
643         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
644         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
645         memcpy(lpKeyState, QueueKeyStateTable, 256);
646     }
647
648     return TRUE;
649 }
650
651 /**********************************************************************
652  *              SetKeyboardState (USER.223)
653  *              SetKeyboardState (USER32.@)
654  */
655 BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
656 {
657     TRACE_(key)("(%p)\n", lpKeyState);
658     if (lpKeyState != NULL) {
659         memcpy(QueueKeyStateTable, lpKeyState, 256);
660         MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
661         MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
662         MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
663     }
664
665     return TRUE;
666 }
667
668 /**********************************************************************
669  *              GetAsyncKeyState (USER32.@)
670  *
671  *      Determine if a key is or was pressed.  retval has high-order 
672  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
673  * been pressed.
674  *
675  *      This uses the variable AsyncMouseButtonsStates and
676  * AsyncKeyStateTable (set in event.c) which have the mouse button
677  * number or key number (whichever is applicable) set to true if the
678  * mouse or key had been depressed since the last call to 
679  * GetAsyncKeyState.
680  */
681 WORD WINAPI GetAsyncKeyState(INT nKey)
682 {
683     WORD retval;
684
685     switch (nKey) {
686      case VK_LBUTTON:
687          retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
688                  (MouseButtonsStates[0] ? 0x8000 : 0);
689         AsyncMouseButtonsStates[0] = 0;
690         break;
691      case VK_MBUTTON:
692          retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
693                  (MouseButtonsStates[1] ? 0x8000 : 0);
694         AsyncMouseButtonsStates[1] = 0;
695         break;
696      case VK_RBUTTON:
697          retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
698                  (MouseButtonsStates[2] ? 0x8000 : 0);
699         AsyncMouseButtonsStates[2] = 0;
700         break;
701      default:
702          retval = ((AsyncKeyStateTable[nKey] & 0x80) ? 0x0001 : 0) |
703                   ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
704         AsyncKeyStateTable[nKey] = 0;
705         break;
706     }
707
708     TRACE_(key)("(%x) -> %x\n", nKey, retval);
709     return retval;
710 }
711
712 /**********************************************************************
713  *              GetAsyncKeyState (USER.249)
714  */
715 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
716 {
717     return GetAsyncKeyState(nKey);
718 }
719
720 /***********************************************************************
721  *              IsUserIdle (USER.333)
722  */
723 BOOL16 WINAPI IsUserIdle16(void)
724 {
725     if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
726         return FALSE;
727
728     if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
729         return FALSE;
730
731     if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
732         return FALSE;
733
734     /* Should check for screen saver activation here ... */
735
736     return TRUE;
737 }
738
739 /**********************************************************************
740  *              VkKeyScanA (USER32.@)
741  */
742 WORD WINAPI VkKeyScanA(CHAR cChar)
743 {
744         return VkKeyScan16(cChar);
745 }
746
747 /******************************************************************************
748  *              VkKeyScanW (USER32.@)
749  */
750 WORD WINAPI VkKeyScanW(WCHAR cChar)
751 {
752         return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
753 }
754
755 /**********************************************************************
756  *              VkKeyScanExA (USER32.@)
757  */
758 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
759 {
760                                 /* FIXME: complete workaround this is */
761                                 return VkKeyScan16(cChar);
762 }
763
764 /******************************************************************************
765  *              VkKeyScanExW (USER32.@)
766  */
767 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
768 {
769                                 /* FIXME: complete workaround this is */
770                                 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
771 }
772  
773 /******************************************************************************
774  *              GetKeyboardType (USER32.@)
775  */
776 INT WINAPI GetKeyboardType(INT nTypeFlag)
777 {
778   return GetKeyboardType16(nTypeFlag);
779 }
780
781 /******************************************************************************
782  *              MapVirtualKeyA (USER32.@)
783  */
784 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
785 {
786     return MapVirtualKey16(code,maptype);
787 }
788
789 /******************************************************************************
790  *              MapVirtualKeyW (USER32.@)
791  */
792 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
793 {
794     return MapVirtualKey16(code,maptype);
795 }
796
797 /******************************************************************************
798  *              MapVirtualKeyExA (USER32.@)
799  */
800 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
801 {
802     if (hkl)
803         FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
804     return MapVirtualKey16(code,maptype);
805 }
806
807 /******************************************************************************
808  *              MapVirtualKeyExW (USER32.@)
809  */
810 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
811 {
812     if (hkl)
813         FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
814     return MapVirtualKey16(code,maptype);
815 }
816
817 /****************************************************************************
818  *              GetKBCodePage (USER32.@)
819  */
820 UINT WINAPI GetKBCodePage(void)
821 {
822     return GetOEMCP();
823 }
824
825 /****************************************************************************
826  *              GetKeyboardLayoutName (USER.477)
827  */
828 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
829 {
830         return GetKeyboardLayoutNameA(pwszKLID);
831 }
832
833 /***********************************************************************
834  *              GetKeyboardLayout (USER32.@)
835  *
836  * FIXME: - device handle for keyboard layout defaulted to 
837  *          the language id. This is the way Windows default works.
838  *        - the thread identifier (dwLayout) is also ignored.
839  */
840 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
841 {
842         HKL layout;
843         layout = GetSystemDefaultLCID(); /* FIXME */
844         layout |= (layout<<16);          /* FIXME */
845         TRACE_(keyboard)("returning %08x\n",layout);
846         return layout;
847 }
848
849 /****************************************************************************
850  *              GetKeyboardLayoutNameA (USER32.@)
851  */
852 INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
853 {
854         sprintf(pwszKLID, "%08x",GetKeyboardLayout(0));
855         return 1;
856 }
857
858 /****************************************************************************
859  *              GetKeyboardLayoutNameW (USER32.@)
860  */
861 INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
862 {
863         char buf[KL_NAMELENGTH];
864         int res = GetKeyboardLayoutNameA(buf);
865         MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
866         return res;
867 }
868
869 /****************************************************************************
870  *              GetKeyNameTextA (USER32.@)
871  */
872 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
873 {
874         return GetKeyNameText16(lParam,lpBuffer,nSize);
875 }
876
877 /****************************************************************************
878  *              GetKeyNameTextW (USER32.@)
879  */
880 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
881 {
882         int res;
883         LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
884         if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
885         res = GetKeyNameTextA(lParam,buf,nSize);
886
887         if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
888             lpBuffer[nSize-1] = 0;
889         HeapFree( GetProcessHeap(), 0, buf );
890         return res;
891 }
892
893 /****************************************************************************
894  *              ToUnicode (USER32.@)
895  */
896 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
897                      LPWSTR lpwStr, int size, UINT flags)
898 {
899     return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
900 }
901
902 /****************************************************************************
903  *              ToUnicodeEx (USER32.@)
904  */
905 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
906                        LPWSTR lpwStr, int size, UINT flags, HKL hkl)
907 {
908     /* FIXME: need true implementation */
909     return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
910 }
911
912 /****************************************************************************
913  *              ToAscii (USER32.@)
914  */
915 INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
916                         LPWORD lpChar,UINT flags )
917 {
918     WCHAR uni_chars[2];
919     INT ret, n_ret;
920
921     ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
922     if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
923     else n_ret = ret;
924     WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
925     return ret;
926 }
927
928 /****************************************************************************
929  *              ToAsciiEx (USER32.@)
930  */
931 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
932                       LPWORD lpChar, UINT flags, HKL dwhkl )
933 {
934     /* FIXME: need true implementation */
935     return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
936 }
937
938 /**********************************************************************
939  *              ActivateKeyboardLayout (USER32.@)
940  *
941  * Call ignored. WINE supports only system default keyboard layout.
942  */
943 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
944 {
945     TRACE_(keyboard)("(%d, %d)\n", hLayout, flags);
946     ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
947     return 0;
948 }
949
950
951 /***********************************************************************
952  *              GetKeyboardLayoutList (USER32.@)
953  *
954  * FIXME: Supports only the system default language and layout and 
955  *          returns only 1 value.
956  *
957  * Return number of values available if either input parm is 
958  *  0, per MS documentation.
959  *
960  */
961 INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
962 {
963         TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
964         if (!nBuff || !layouts)
965             return 1;
966         if (layouts)
967                 layouts[0] = GetKeyboardLayout(0);
968         return 1;
969 }
970
971
972 /***********************************************************************
973  *              RegisterHotKey (USER32.@)
974  */
975 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) {
976         FIXME_(keyboard)("(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
977         return TRUE;
978 }
979
980 /***********************************************************************
981  *              UnregisterHotKey (USER32.@)
982  */
983 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) {
984         FIXME_(keyboard)("(0x%08x,%d): stub\n",hwnd,id);
985         return TRUE;
986 }
987
988 /***********************************************************************
989  *              LoadKeyboardLayoutA (USER32.@)
990  * Call ignored. WINE supports only system default keyboard layout.
991  */
992 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
993 {
994     TRACE_(keyboard)("(%s, %d)\n", pwszKLID, Flags);
995     ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
996   return 0; 
997 }
998
999 /***********************************************************************
1000  *              LoadKeyboardLayoutW (USER32.@)
1001  */
1002 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
1003 {
1004     char buf[9];
1005     
1006     WideCharToMultiByte( CP_ACP, 0, pwszKLID, -1, buf, sizeof(buf), NULL, NULL );
1007     buf[8] = 0;
1008     return LoadKeyboardLayoutA(buf, Flags);
1009 }