Implementation of the pushed close button.
[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 <ctype.h>
15 #include <assert.h>
16
17 #include "windows.h"
18 #include "win.h"
19 #include "gdi.h"
20 #include "heap.h"
21 #include "input.h"
22 #include "keyboard.h"
23 #include "mouse.h"
24 #include "message.h"
25 #include "sysmetrics.h"
26 #include "debug.h"
27 #include "debugtools.h"
28 #include "struct32.h"
29 #include "winerror.h"
30 #include "task.h"
31
32 static BOOL32 InputEnabled = TRUE;
33 static BOOL32 SwappedButtons = FALSE;
34
35 BOOL32 MouseButtonsStates[3];
36 BOOL32 AsyncMouseButtonsStates[3];
37 BYTE InputKeyStateTable[256];
38 BYTE QueueKeyStateTable[256];
39 BYTE AsyncKeyStateTable[256];
40
41 typedef union
42 {
43     struct
44     {
45         unsigned long count : 16;
46         unsigned long code : 8;
47         unsigned long extended : 1;
48         unsigned long unused : 2;
49         unsigned long win_internal : 2;
50         unsigned long context : 1;
51         unsigned long previous : 1;
52         unsigned long transition : 1;
53     } lp1;
54     unsigned long lp2;
55 } KEYLP;
56
57 /***********************************************************************
58  *           keybd_event   (USER32.583)
59  */
60 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
61                          DWORD dwFlags, DWORD dwExtraInfo )
62 {
63     DWORD posX, posY, time, extra;
64     WORD message;
65     KEYLP keylp;
66     keylp.lp2 = 0;
67
68     if (!InputEnabled) return;
69
70     /*
71      * If we are called by the Wine keyboard driver, use the additional
72      * info pointed to by the dwExtraInfo argument.
73      * Otherwise, we need to determine that info ourselves (probably
74      * less accurate, but we can't help that ...).
75      */
76     if (   !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) )
77         && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC )
78     {
79         WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo;
80         posX = wke->posX;
81         posY = wke->posY;
82         time = wke->time;
83         extra = 0;
84     }
85     else
86     {
87         DWORD keyState;
88         time = GetTickCount();
89         extra = dwExtraInfo;
90
91         if ( !EVENT_QueryPointer( &posX, &posY, &keyState ))
92             return;
93     }
94
95
96     keylp.lp1.count = 1;
97     keylp.lp1.code = bScan;
98     keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
99     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
100                                 * don't remember where I read it - AK */
101                                 /* it's '1' under windows, when a dialog box appears
102                                  * and you press one of the underlined keys - DF*/
103
104     if ( dwFlags & KEYEVENTF_KEYUP )
105     {
106         BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
107                 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
108                 && !(dwFlags & KEYEVENTF_WINE_FORCEEXTENDED); /* for Alt from AltGr */
109
110         InputKeyStateTable[bVk] &= ~0x80;
111         keylp.lp1.previous = 1;
112         keylp.lp1.transition = 1;
113         message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
114     }
115     else
116     {
117         keylp.lp1.previous = (InputKeyStateTable[bVk] & 0x80) != 0;
118         keylp.lp1.transition = 0;
119
120         if (!(InputKeyStateTable[bVk] & 0x80))
121             InputKeyStateTable[bVk] ^= 0x01;
122         InputKeyStateTable[bVk] |= 0x80;
123
124         message = (InputKeyStateTable[VK_MENU] & 0x80)
125               && !(InputKeyStateTable[VK_CONTROL] & 0x80)
126               ? WM_SYSKEYDOWN : WM_KEYDOWN;
127     }
128
129     if ( message == WM_SYSKEYDOWN || message == WM_SYSKEYUP )
130         keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
131
132
133     TRACE(key, "            wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 );
134     TRACE(key, "            InputKeyState=%X\n", InputKeyStateTable[bVk] );
135
136     hardware_event( message, bVk, keylp.lp2, posX, posY, time, extra );
137 }
138
139 /***********************************************************************
140  *           mouse_event   (USER32.584)
141  */
142 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
143                          DWORD cButtons, DWORD dwExtraInfo )
144 {
145     DWORD posX, posY, keyState, time, extra;
146
147     if (!InputEnabled) return;
148
149     /*
150      * If we are called by the Wine mouse driver, use the additional
151      * info pointed to by the dwExtraInfo argument.
152      * Otherwise, we need to determine that info ourselves (probably
153      * less accurate, but we can't help that ...).
154      */
155     if (   !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
156         && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
157     {
158         WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
159         keyState = wme->keyState;
160         time = wme->time;
161         extra = (DWORD)wme->hWnd;
162
163         assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
164         posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
165         posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
166     }
167     else
168     {
169         time = GetTickCount();
170         extra = dwExtraInfo;
171
172         if ( !EVENT_QueryPointer( &posX, &posY, &keyState ))
173             return;
174
175         if ( dwFlags & MOUSEEVENTF_MOVE )
176         {
177             if ( dwFlags & MOUSEEVENTF_ABSOLUTE )
178             {
179                 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
180                 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
181             }
182             else
183             {
184                 posX += dx;
185                 posY += dy;
186             }
187             /* We have to actually move the cursor */
188             SetCursorPos32( posX, posY );
189         }
190     }
191
192     if ( dwFlags & MOUSEEVENTF_MOVE )
193     {
194         hardware_event( WM_MOUSEMOVE,
195                         keyState, 0L, posX, posY, time, extra );
196     }
197     if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) )
198     {
199         MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
200         hardware_event( WM_LBUTTONDOWN,
201                         keyState, 0L, posX, posY, time, extra );
202     }
203     if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) )
204     {
205         MouseButtonsStates[0] = FALSE;
206         hardware_event( WM_LBUTTONUP,
207                         keyState, 0L, posX, posY, time, extra );
208     }
209     if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) )
210     {
211         MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
212         hardware_event( WM_RBUTTONDOWN,
213                         keyState, 0L, posX, posY, time, extra );
214     }
215     if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) )
216     {
217         MouseButtonsStates[2] = FALSE;
218         hardware_event( WM_RBUTTONUP,
219                         keyState, 0L, posX, posY, time, extra );
220     }
221     if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN )
222     {
223         MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
224         hardware_event( WM_MBUTTONDOWN,
225                         keyState, 0L, posX, posY, time, extra );
226     }
227     if ( dwFlags & MOUSEEVENTF_MIDDLEUP )
228     {
229         MouseButtonsStates[1] = FALSE;
230         hardware_event( WM_MBUTTONUP,
231                         keyState, 0L, posX, posY, time, extra );
232     }
233 }
234
235 /**********************************************************************
236  *                      EnableHardwareInput   (USER.331)
237  */
238 BOOL16 WINAPI EnableHardwareInput(BOOL16 bEnable)
239 {
240   BOOL16 bOldState = InputEnabled;
241   FIXME(event,"(%d) - stub\n", bEnable);
242   InputEnabled = bEnable;
243   return bOldState;
244 }
245
246
247 /***********************************************************************
248  *           SwapMouseButton16   (USER.186)
249  */
250 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
251 {
252     BOOL16 ret = SwappedButtons;
253     SwappedButtons = fSwap;
254     return ret;
255 }
256
257
258 /***********************************************************************
259  *           SwapMouseButton32   (USER32.537)
260  */
261 BOOL32 WINAPI SwapMouseButton32( BOOL32 fSwap )
262 {
263     BOOL32 ret = SwappedButtons;
264     SwappedButtons = fSwap;
265     return ret;
266 }
267
268 /**********************************************************************
269  *              EVENT_Capture
270  *
271  * We need this to be able to generate double click messages
272  * when menu code captures mouse in the window without CS_DBLCLK style.
273  */
274 HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
275 {
276     HWND32 capturePrev = 0, captureWnd = 0;
277     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
278     WND* wndPtr = 0;
279     INT16 captureHT = 0;
280
281     /* Get the messageQ for the current thread */
282     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
283     {
284         WARN( win, "\tCurrent message queue not found. Exiting!\n" );
285         goto CLEANUP;
286     }
287     
288     /* Get the current capture window from the perQ data of the current message Q */
289     capturePrev = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData );
290
291     if (!hwnd)
292     {
293         captureWnd = 0L;
294         captureHT = 0;
295     }
296     else
297     {
298         wndPtr = WIN_FindWndPtr( hwnd );
299         if (wndPtr)
300         {
301             TRACE(win, "(0x%04x)\n", hwnd );
302             captureWnd   = hwnd;
303             captureHT    = ht;
304         }
305     }
306
307     /* Update the perQ capture window and send messages */
308     if( capturePrev != captureWnd )
309     {
310         if (wndPtr)
311         {
312             /* Retrieve the message queue associated with this window */
313             pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
314             if ( !pMsgQ )
315             {
316                 WARN( win, "\tMessage queue not found. Exiting!\n" );
317                 goto CLEANUP;
318             }
319     
320             /* Make sure that message queue for the window we are setting capture to
321              * shares the same perQ data as the current threads message queue.
322              */
323             if ( pCurMsgQ->pQData != pMsgQ->pQData )
324                 goto CLEANUP;
325         }
326
327         PERQDATA_SetCaptureWnd( pCurMsgQ->pQData, captureWnd );
328         PERQDATA_SetCaptureInfo( pCurMsgQ->pQData, captureHT );
329         
330         if( capturePrev )
331     {
332         WND* wndPtr = WIN_FindWndPtr( capturePrev );
333         if( wndPtr && (wndPtr->flags & WIN_ISWIN32) )
334             SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
335     }
336 }
337
338 CLEANUP:
339     /* Unlock the queues before returning */
340     if ( pMsgQ )
341         QUEUE_Unlock( pMsgQ );
342     if ( pCurMsgQ )
343         QUEUE_Unlock( pCurMsgQ );
344     
345     return capturePrev;
346 }
347
348
349 /**********************************************************************
350  *              SetCapture16   (USER.18)
351  */
352 HWND16 WINAPI SetCapture16( HWND16 hwnd )
353 {
354     return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
355 }
356
357
358 /**********************************************************************
359  *              SetCapture32   (USER32.464)
360  */
361 HWND32 WINAPI SetCapture32( HWND32 hwnd )
362 {
363     return EVENT_Capture( hwnd, HTCLIENT );
364 }
365
366
367 /**********************************************************************
368  *              ReleaseCapture   (USER.19) (USER32.439)
369  */
370 void WINAPI ReleaseCapture(void)
371 {
372     EVENT_Capture( 0, 0 );
373 }
374
375
376 /**********************************************************************
377  *              GetCapture16   (USER.236)
378  */
379 HWND16 WINAPI GetCapture16(void)
380 {
381     return (HWND16)GetCapture32();
382 }
383
384 /**********************************************************************
385  *              GetCapture32   (USER32.208)
386  */
387 HWND32 WINAPI GetCapture32(void)
388 {
389     MESSAGEQUEUE *pCurMsgQ = 0;
390     HWND32 hwndCapture = 0;
391
392     /* Get the messageQ for the current thread */
393     if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue() )))
394 {
395         TRACE( win, "GetCapture32:  Current message queue not found. Exiting!\n" );
396         return 0;
397     }
398     
399     /* Get the current capture window from the perQ data of the current message Q */
400     hwndCapture = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData );
401
402     QUEUE_Unlock( pCurMsgQ );
403     return hwndCapture;
404 }
405
406 /**********************************************************************
407  *           GetKeyState      (USER.106)
408  */
409 INT16 WINAPI GetKeyState16(INT16 vkey)
410 {
411     return GetKeyState32(vkey);
412 }
413
414 /**********************************************************************
415  *           GetKeyState      (USER32.249)
416  *
417  * An application calls the GetKeyState function in response to a
418  * keyboard-input message.  This function retrieves the state of the key
419  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
420  */
421 INT16 WINAPI GetKeyState32(INT32 vkey)
422 {
423     INT32 retval;
424
425     switch (vkey)
426         {
427         case VK_LBUTTON : /* VK_LBUTTON is 1 */
428             retval = MouseButtonsStates[0] ? 0x8000 : 0;
429             break;
430         case VK_MBUTTON : /* VK_MBUTTON is 4 */
431             retval = MouseButtonsStates[1] ? 0x8000 : 0;
432             break;
433         case VK_RBUTTON : /* VK_RBUTTON is 2 */
434             retval = MouseButtonsStates[2] ? 0x8000 : 0;
435             break;
436         default :
437             if (vkey >= 'a' && vkey <= 'z')
438                 vkey += 'A' - 'a';
439             retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
440                        (WORD)(QueueKeyStateTable[vkey] & 0x01);
441         }
442     /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
443     return retval;
444 }
445
446 /**********************************************************************
447  *           GetKeyboardState      (USER.222)(USER32.254)
448  *
449  * An application calls the GetKeyboardState function in response to a
450  * keyboard-input message.  This function retrieves the state of the keyboard
451  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
452  */
453 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
454 {
455     TRACE(key, "(%p)\n", lpKeyState);
456     if (lpKeyState != NULL) {
457         QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
458         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
459         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
460         memcpy(lpKeyState, QueueKeyStateTable, 256);
461     }
462 }
463
464 /**********************************************************************
465  *          SetKeyboardState      (USER.223)(USER32.484)
466  */
467 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
468 {
469     TRACE(key, "(%p)\n", lpKeyState);
470     if (lpKeyState != NULL) {
471         memcpy(QueueKeyStateTable, lpKeyState, 256);
472         MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
473         MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
474         MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
475     }
476 }
477
478 /**********************************************************************
479  *           GetAsyncKeyState32      (USER32.207)
480  *
481  *      Determine if a key is or was pressed.  retval has high-order 
482  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
483  * been pressed.
484  *
485  *      This uses the variable AsyncMouseButtonsStates and
486  * AsyncKeyStateTable (set in event.c) which have the mouse button
487  * number or key number (whichever is applicable) set to true if the
488  * mouse or key had been depressed since the last call to 
489  * GetAsyncKeyState.
490  */
491 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
492 {
493     short retval;       
494
495     switch (nKey) {
496      case VK_LBUTTON:
497         retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) | 
498                  (MouseButtonsStates[0] ? 0x8000 : 0);
499         break;
500      case VK_MBUTTON:
501         retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) | 
502                  (MouseButtonsStates[1] ? 0x8000 : 0);
503         break;
504      case VK_RBUTTON:
505         retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) | 
506                  (MouseButtonsStates[2] ? 0x8000 : 0);
507         break;
508      default:
509         retval = AsyncKeyStateTable[nKey] | 
510                 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); 
511         break;
512     }
513
514     /* all states to false */
515     memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
516     memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
517
518     TRACE(key, "(%x) -> %x\n", nKey, retval);
519     return retval;
520 }
521
522 /**********************************************************************
523  *            GetAsyncKeyState16        (USER.249)
524  */
525 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
526 {
527     return GetAsyncKeyState32(nKey);
528 }
529
530 /**********************************************************************
531  *           KBD_translate_accelerator
532  *
533  * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP  -messages
534  */
535 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
536                                         BYTE fVirt,WORD key,WORD cmd)
537 {
538     BOOL32      sendmsg = FALSE;
539
540     if(msg->wParam == key) 
541     {
542         if (msg->message == WM_CHAR) {
543         if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
544         {
545           TRACE(accel,"found accel for WM_CHAR: ('%c')\n",
546                         msg->wParam&0xff);
547           sendmsg=TRUE;
548         }  
549       } else {
550        if(fVirt & FVIRTKEY) {
551         INT32 mask = 0;
552         TRACE(accel,"found accel for virt_key %04x (scan %04x)\n",
553                                msg->wParam,0xff & HIWORD(msg->lParam));                
554         if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
555         if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
556         if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
557         if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
558           sendmsg=TRUE;                     
559         else
560           TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n");
561        }
562        else
563        {
564          if (!(msg->lParam & 0x01000000))  /* no special_key */
565          {
566            if ((fVirt & FALT) && (msg->lParam & 0x20000000))
567            {                                                   /* ^^ ALT pressed */
568             TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff);
569             sendmsg=TRUE;           
570            } 
571          } 
572        }
573       } 
574
575       if (sendmsg)      /* found an accelerator, but send a message... ? */
576       {
577         INT16  iSysStat,iStat,mesg=0;
578         HMENU16 hMenu;
579         
580         if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
581           mesg=1;
582         else 
583          if (GetCapture32())
584            mesg=2;
585          else
586           if (!IsWindowEnabled32(hWnd))
587             mesg=3;
588           else
589           {
590             WND* wndPtr = WIN_FindWndPtr(hWnd);
591
592             hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
593             iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
594                                             cmd, MF_BYCOMMAND) : -1 ;
595             iStat = (hMenu) ? GetMenuState32(hMenu,
596                                             cmd, MF_BYCOMMAND) : -1 ;
597
598             if (iSysStat!=-1)
599             {
600               if (iSysStat & (MF_DISABLED|MF_GRAYED))
601                 mesg=4;
602               else
603                 mesg=WM_SYSCOMMAND;
604             }
605             else
606             {
607               if (iStat!=-1)
608               {
609                 if (IsIconic32(hWnd))
610                   mesg=5;
611                 else
612                 {
613                  if (iStat & (MF_DISABLED|MF_GRAYED))
614                    mesg=6;
615                  else
616                    mesg=WM_COMMAND;  
617                 }   
618               }
619               else
620                mesg=WM_COMMAND;  
621             }
622           }
623           if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
624           {
625               TRACE(accel,", sending %s, wParam=%0x\n",
626                   mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
627                   cmd);
628               SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
629           }
630           else
631           {
632            /*  some reasons for NOT sending the WM_{SYS}COMMAND message: 
633             *   #0: unknown (please report!)
634             *   #1: for WM_KEYUP,WM_SYSKEYUP
635             *   #2: mouse is captured
636             *   #3: window is disabled 
637             *   #4: it's a disabled system menu option
638             *   #5: it's a menu option, but window is iconic
639             *   #6: it's a menu option, but disabled
640             */
641             TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
642             if(mesg==0)
643               ERR(accel, " unknown reason - please report!");
644           }          
645           return TRUE;         
646       }
647     }
648     return FALSE;
649 }
650
651 /**********************************************************************
652  *      TranslateAccelerator32      (USER32.551)(USER32.552)(USER32.553)
653  */
654 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
655 {
656     /* YES, Accel16! */
657     LPACCEL16   lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
658     int         i;
659
660     TRACE(accel,"hwnd=0x%x hacc=0x%x msg=0x%x wp=0x%x lp=0x%lx\n", hWnd, hAccel, msg->message, msg->wParam, msg->lParam);
661     
662     if (hAccel == 0 || msg == NULL ||
663         (msg->message != WM_KEYDOWN &&
664          msg->message != WM_KEYUP &&
665          msg->message != WM_SYSKEYDOWN &&
666          msg->message != WM_SYSKEYUP &&
667          msg->message != WM_CHAR)) {
668       WARN(accel, "erraneous input parameters\n");
669       SetLastError(ERROR_INVALID_PARAMETER);
670       return 0;
671     }
672
673     TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,"
674           "msg->hwnd=%04x, msg->message=%04x\n",
675           hAccel,hWnd,msg->hwnd,msg->message);
676
677     i = 0;
678     do
679     {
680         if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
681                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
682                 return 1;
683     } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
684     WARN(accel, "couldn't translate accelerator key\n");
685     return 0;
686 }
687
688 /**********************************************************************
689  *           TranslateAccelerator16      (USER.178)
690  */     
691 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
692 {
693     LPACCEL16   lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
694     int         i;
695     MSG32       msg32;
696     
697     if (hAccel == 0 || msg == NULL ||
698         (msg->message != WM_KEYDOWN &&
699          msg->message != WM_KEYUP &&
700          msg->message != WM_SYSKEYDOWN &&
701          msg->message != WM_SYSKEYUP &&
702          msg->message != WM_CHAR)) {
703       WARN(accel, "erraneous input parameters\n");
704       SetLastError(ERROR_INVALID_PARAMETER);
705       return 0;
706     }
707
708     TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
709 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
710     STRUCT32_MSG16to32(msg,&msg32);
711
712
713     i = 0;
714     do
715     {
716         if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
717                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
718                 return 1;
719     } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
720     WARN(accel, "couldn't translate accelerator key\n");
721     return 0;
722 }
723
724
725 /**********************************************************************
726  *           VkKeyScanA      (USER32.573)
727  */
728 WORD WINAPI VkKeyScan32A(CHAR cChar)
729 {
730         return VkKeyScan16(cChar);
731 }
732
733 /******************************************************************************
734  *      VkKeyScanW      (USER32.576)
735  */
736 WORD WINAPI VkKeyScan32W(WCHAR cChar)
737 {
738         return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
739 }
740
741 /******************************************************************************
742  *      GetKeyboardType32      (USER32.255)
743  */
744 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
745 {
746   return GetKeyboardType16(nTypeFlag);
747 }
748
749 /******************************************************************************
750  *      MapVirtualKey32A      (USER32.383)
751  */
752 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
753 {
754     return MapVirtualKey16(code,maptype);
755 }
756
757 /******************************************************************************
758  *      MapVirtualKey32W      (USER32.385)
759  */
760 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
761 {
762     return MapVirtualKey16(code,maptype);
763 }
764
765 /******************************************************************************
766  *      MapVirtualKeyEx32A      (USER32.384)
767  */
768 UINT32 WINAPI MapVirtualKeyEx32A(UINT32 code, UINT32 maptype, HKL32 hkl)
769 {
770     if (hkl)
771         FIXME(keyboard,"(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
772     return MapVirtualKey16(code,maptype);
773 }
774
775 /****************************************************************************
776  *      GetKBCodePage32   (USER32.246)
777  */
778 UINT32 WINAPI GetKBCodePage32(void)
779 {
780     return GetKBCodePage16();
781 }
782
783 /****************************************************************************
784  *      GetKeyboardLayoutName16   (USER.477)
785  */
786 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
787 {
788         return GetKeyboardLayoutName32A(pwszKLID);
789 }
790
791 /****************************************************************************
792  *      GetKeyboardLayoutName32A   (USER32.252)
793  */
794 INT32 WINAPI GetKeyboardLayoutName32A(LPSTR pwszKLID)
795 {
796         FIXME(keyboard,"always returns primary U.S. English layout\n");
797         strcpy(pwszKLID,"00000409");
798         return 1;
799 }
800
801 /****************************************************************************
802  *      GetKeyboardLayoutName32W   (USER32.253)
803  */
804 INT32 WINAPI GetKeyboardLayoutName32W(LPWSTR pwszKLID)
805 {
806         LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1);
807         int res = GetKeyboardLayoutName32A(buf);
808         lstrcpyAtoW(pwszKLID,buf);
809         HeapFree( GetProcessHeap(), 0, buf );
810         return res;
811 }
812
813 /****************************************************************************
814  *      GetKeyNameText32A   (USER32.247)
815  */
816 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
817 {
818         return GetKeyNameText16(lParam,lpBuffer,nSize);
819 }
820
821 /****************************************************************************
822  *      GetKeyNameText32W   (USER32.248)
823  */
824 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
825 {
826         LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
827         int res = GetKeyNameText32A(lParam,buf,nSize);
828
829         lstrcpynAtoW(lpBuffer,buf,nSize);
830         HeapFree( GetProcessHeap(), 0, buf );
831         return res;
832 }
833
834 /****************************************************************************
835  *      ToAscii32      (USER32.546)
836  */
837 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
838                         LPWORD lpChar,UINT32 flags )
839 {
840     return ToAscii16(virtKey,scanCode,lpKeyState,lpChar,flags);
841 }
842
843 /***********************************************************************
844  *           GetKeyboardLayout                  (USER32.250)
845  */
846 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
847 {
848         HKL32 layout;
849         FIXME(keyboard,"(%ld): stub\n",dwLayout);
850         layout = (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
851         TRACE(keyboard,"returning %x\n",layout);
852         return layout;
853 }
854
855 /**********************************************************************
856  *           ActivateKeyboardLayout32      (USER32.1)
857  */
858 HKL32 WINAPI ActivateKeyboardLayout32(HKL32 hLayout, UINT32 flags)
859 {
860     FIXME(keyboard, "(%d, %d): stub\n", hLayout, flags);
861
862     return 0;
863 }
864
865
866 /***********************************************************************
867  *           GetKeyboardLayoutList              (USER32.251)
868  * FIXME
869  */
870 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
871 {
872         FIXME(keyboard,"(%d,%p): stub\n",nBuff,layouts);
873         if (layouts)
874                 layouts[0] = GetKeyboardLayout(0);
875         return 1;
876 }
877
878
879 /***********************************************************************
880  *           RegisterHotKey                     (USER32.433)
881  */
882 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
883         FIXME(keyboard,"(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
884         return TRUE;
885 }
886
887 /***********************************************************************
888  *           UnregisterHotKey                   (USER32.565)
889  */
890 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
891         FIXME(keyboard,"(0x%08x,%d): stub\n",hwnd,id);
892         return TRUE;
893 }
894
895
896 /***********************************************************************
897  *           ToUnicode32                       (USER32.548)
898  */
899 INT32 WINAPI ToUnicode32(
900   UINT32 wVirtKey,
901   UINT32 wScanCode,
902   PBYTE  lpKeyState,
903   LPWSTR pwszBuff,
904   int    cchBuff,
905   UINT32 wFlags) {
906
907        FIXME(keyboard,": stub\n");
908        return 0;
909 }
910
911 /***********************************************************************
912  *           LoadKeyboardLayout32A                (USER32.367)
913  */
914 HKL32 WINAPI LoadKeyboardLayout32A(LPCSTR pwszKLID, UINT32 Flags)
915 {
916   FIXME(keyboard, "%s, %d): stub\n", pwszKLID, Flags);
917   return 0; 
918 }
919
920 /***********************************************************************
921  *           LoadKeyboardLayout32W                (USER32.368)
922  */
923 HKL32 WINAPI LoadKeyboardLayout32W(LPCWSTR pwszKLID, UINT32 Flags)
924 {
925   FIXME(keyboard, "%p, %d): stub\n", pwszKLID, Flags);
926   return 0;
927 }