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