Release 971130
[wine] / windows / keyboard.c
1 /*
2  * Keyboard related functions
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine 
6  * Copyright 1997 David Faure
7  *
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <X11/keysym.h>
15 #include <X11/Xlib.h>
16 #include <X11/Xresource.h>
17 #include <X11/Xutil.h>
18 #include <X11/Xatom.h>
19
20 #include "windows.h"
21 #include "win.h"
22 #include "gdi.h"
23 #include "heap.h"
24 #include "keyboard.h"
25 #include "message.h"
26 #include "stddebug.h"
27 /* #define DEBUG_KEYBOARD */
28 #include "debug.h"
29 #include "struct32.h"
30
31 BOOL32 MouseButtonsStates[3];
32 BOOL32 AsyncMouseButtonsStates[3];
33 BYTE InputKeyStateTable[256];
34 BYTE QueueKeyStateTable[256];
35 BYTE AsyncKeyStateTable[256];
36
37 static int NumLockMask;
38 static int AltGrMask;
39 static int min_keycode, max_keycode;
40 static int keyc2vkey[256];
41
42 typedef union
43 {
44     struct
45     {
46         unsigned long count : 16;
47         unsigned long code : 8;
48         unsigned long extended : 1;
49         unsigned long unused : 2;
50         unsigned long win_internal : 2;
51         unsigned long context : 1;
52         unsigned long previous : 1;
53         unsigned long transition : 1;
54     } lp1;
55     unsigned long lp2;
56 } KEYLP;
57
58 /* Keyboard translation tables */
59 static const int special_key[] =
60 {
61     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
62     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
63     0, 0, 0, VK_ESCAPE                                          /* FF18 */
64 };
65
66 static const int cursor_key[] =
67 {
68     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
69                                        VK_NEXT, VK_END          /* FF50 */
70 };
71
72 static const int misc_key[] =
73 {
74     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
75     VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
76 };
77
78 static const int keypad_key[] =
79 {
80     0, VK_NUMLOCK,                                              /* FF7E */
81     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
82     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
83     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
84     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
85                                  VK_INSERT, VK_DELETE,          /* FF98 */
86     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
87     0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
88                                VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
89     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
90                             VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
91     VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
92 };
93     
94 static const int function_key[] =
95 {
96     VK_F1, VK_F2,                                               /* FFBE */
97     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
98     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
99 };
100
101 static const int modifier_key[] =
102 {
103     VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
104     VK_MENU, VK_MENU, VK_MENU, VK_MENU                         /* FFE7 */
105 };
106
107 /*
108  * Table for vkey to scancode translation - 5/29/97 chrisf@america.com 
109  */
110 static const BYTE vkey2scode[512] = {
111   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
112   0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
113   0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
114   0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
115   0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
116   0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
117   0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
118   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119   0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
123   0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x28,0x33,0x34,0x35,0x4c,
125   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127 /* 256 */
128   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
129   0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130   0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
131   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,
135   0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,0x00,0x00,0x00,0x00,
136   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
137   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 };
145
146 static WORD EVENT_event_to_vkey( XKeyEvent *e)
147 {
148     KeySym keysym;
149
150     XLookupString(e, NULL, 0, &keysym, NULL);
151
152     if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask)) 
153         /* Only the Keypad keys 0-9 and . send different keysyms
154          * depending on the NumLock state */
155         return keypad_key[(keysym & 0xFF) - 0x7E];
156
157     return keyc2vkey[e->keycode];
158 }
159
160 /**********************************************************************
161  *              KEYBOARD_Init
162  */
163 BOOL32 KEYBOARD_Init(void)
164 {
165     int i, keysyms_per_keycode;
166     KeySym *ksp;
167     XModifierKeymap *mmp;
168     KeySym keysym;
169     KeyCode *kcp;
170     XKeyEvent e2;
171     WORD vkey, OEMvkey;
172
173     XDisplayKeycodes(display, &min_keycode, &max_keycode);
174     ksp = XGetKeyboardMapping(display, min_keycode,
175                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
176     /* We are only interested in keysyms_per_keycode.
177        There is no need to hold a local copy of the keysyms table */
178     XFree(ksp);
179     mmp = XGetModifierMapping(display);
180     kcp = mmp->modifiermap;
181     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
182     {
183         int j;
184         
185         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
186             if (*kcp)
187             {
188                 int k;
189                 
190                 for (k = 0; k < keysyms_per_keycode; k += 1)
191                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
192                     {
193                         AltGrMask = 1 << i;
194                         dprintf_key(stddeb, "AltGrMask is %x\n", AltGrMask);
195                     }
196                     else if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
197                     {
198                         NumLockMask = 1 << i;
199                         dprintf_key(stddeb, "NumLockMask is %x\n", NumLockMask);
200                     }
201             }
202     }
203     XFreeModifiermap(mmp);
204
205     /* Now build two conversion arrays :
206      * keycode -> vkey + extended
207      * vkey + extended -> keycode */
208
209     e2.display = display;
210     e2.state = 0;
211
212     OEMvkey = 0xb9; /* first OEM virtual key available is ba */
213     for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
214     {
215         XLookupString(&e2, NULL, 0, &keysym, NULL);
216         vkey = 0;
217         if (keysym)  /* otherwise, keycode not used */
218         {
219             if ((keysym >> 8) == 0xFF)         /* non-character key */
220             {
221                 int key = keysym & 0xff;
222                 
223                 if (key >= 0x08 && key <= 0x1B)         /* special key */
224                     vkey = special_key[key - 0x08];
225                 else if (key >= 0x50 && key <= 0x57)    /* cursor key */
226                     vkey = cursor_key[key - 0x50];
227                 else if (key >= 0x60 && key <= 0x6B)    /* miscellaneous key */
228                     vkey = misc_key[key - 0x60];
229                 else if (key >= 0x7E && key <= 0xB9)    /* keypad key */
230                     vkey = keypad_key[key - 0x7E];
231                 else if (key >= 0xBE && key <= 0xCD)    /* function key */
232                 {
233                     vkey = function_key[key - 0xBE];
234                     vkey |= 0x100; /* set extended bit */
235                 }
236                 else if (key >= 0xE1 && key <= 0xEA)    /* modifier key */
237                     vkey = modifier_key[key - 0xE1];
238                 else if (key == 0xFF)                   /* DEL key */
239                     vkey = VK_DELETE;
240                 /* extended must also be set for ALT_R, CTRL_R,
241                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
242                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
243                 /* FIXME should we set extended bit for NumLock ? My
244                  * Windows does ... DF */
245                 switch (keysym)
246                 {
247                 case XK_Control_R :
248                 case XK_Alt_R :
249                 case XK_Insert :
250                 case XK_Delete :
251                 case XK_Home :
252                 case XK_End :
253                 case XK_Prior :
254                 case XK_Next :
255                 case XK_Left :
256                 case XK_Up :
257                 case XK_Right :
258                 case XK_Down :
259                 case XK_KP_Divide :
260                 case XK_KP_Enter :
261                     vkey |= 0x100;
262                 }
263             }
264             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
265             {
266                 keysym = XLookupKeysym(&e2, i);
267                 if ((keysym >= VK_0 && keysym <= VK_9)
268                     || (keysym >= VK_A && keysym <= VK_Z)
269                     || keysym == VK_SPACE)
270                     vkey = keysym;
271             }
272
273             if (!vkey)
274             {
275                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
276                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
277                 switch (++OEMvkey)
278                 {
279                 case 0xc1 : OEMvkey=0xdb; break;
280                 case 0xe5 : OEMvkey=0xe9; break;
281                 case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
282                 }
283
284                 vkey = OEMvkey;
285                   
286                 if (debugging_keyboard)
287                 {
288                     fprintf(stddeb,"OEM specific virtual key %X assigned to keycode %X :\n ("
289                             ,OEMvkey,e2.keycode);
290                     for (i = 0; i < keysyms_per_keycode; i += 1)
291                     {
292                         char    *ksname;
293                         
294                         keysym = XLookupKeysym(&e2, i);
295                         ksname = XKeysymToString(keysym);
296                         if (!ksname)
297                             ksname = "NoSymbol";
298                         fprintf(stddeb, "%lX (%s) ", keysym, ksname);
299                     }
300                     fprintf(stddeb, ")\n");
301                 }
302             }
303         }
304         keyc2vkey[e2.keycode] = vkey;
305     } /* for */
306     return TRUE;
307 }
308
309 static BOOL32 NumState=FALSE, CapsState=FALSE;
310
311 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
312                            DWORD event_time, KEYLP localkeylp )
313 {
314   BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
315
316   if (*State) {
317     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
318        don't treat it. It's from the same key press. Then the state goes to ON.
319        And from there, a 'release' event will switch off the toggle key. */
320     *State=FALSE;
321     dprintf_keyboard(stddeb,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
322   } else
323     {
324         if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
325           {
326             if (Evtype!=KeyPress)
327               {
328                 dprintf_keyboard(stddeb,"ON + KeyRelease => generating DOWN and UP messages.\n");
329                 localkeylp.lp1.previous = 0; /* ? */
330                 localkeylp.lp1.transition = 0;
331                 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
332                                 event_x, event_y, event_time, 0 );
333                 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
334                                 event_x, event_y, event_time, 0 );
335                 *State=FALSE;
336                 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ 
337               } 
338           }
339         else /* it was OFF */
340           if (Evtype==KeyPress)
341             {
342               dprintf_keyboard(stddeb,"OFF + Keypress => generating DOWN and UP messages.\n");
343               hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
344                               event_x, event_y, event_time, 0 );
345               localkeylp.lp1.previous = 1;
346               localkeylp.lp1.transition = 1;
347               hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
348                               event_x, event_y, event_time, 0 );
349               *State=TRUE; /* Goes to intermediary state before going to ON */
350               InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
351             }
352     }
353 }
354
355 /***********************************************************************
356  *           KEYBOARD_HandleEvent
357  *
358  * Handle a X key event
359  */
360 void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
361 {
362     char Str[24]; 
363     XComposeStatus cs; 
364     KeySym keysym;
365     WORD vkey = 0;
366     KEYLP keylp;
367     static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
368
369     int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
370
371     INT32 event_x = pWnd->rectWindow.left + event->x;
372     INT32 event_y = pWnd->rectWindow.top + event->y;
373     DWORD event_time = event->time - MSG_WineStartTicks;
374
375     dprintf_key(stddeb, "EVENT_key : state = %X\n", event->state);
376     if (keysym == XK_Mode_switch)
377         {
378         dprintf_key(stddeb, "Alt Gr key event received\n");
379         event->keycode = XKeysymToKeycode(event->display, XK_Control_L);
380         dprintf_key(stddeb, "Control_L is keycode 0x%x\n", event->keycode);
381         KEYBOARD_HandleEvent( pWnd, event );
382         event->keycode = XKeysymToKeycode(event->display, XK_Alt_L);
383         dprintf_key(stddeb, "Alt_L is keycode 0x%x\n", event->keycode);
384         force_extended = TRUE;
385         KEYBOARD_HandleEvent( pWnd, event );
386         force_extended = FALSE;
387         return;
388         }
389
390     Str[ascii_chars] = '\0';
391     if (debugging_key)
392         {
393         char    *ksname;
394
395         ksname = XKeysymToString(keysym);
396         if (!ksname)
397             ksname = "No Name";
398         fprintf(stddeb, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", 
399                 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
400                 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
401         }
402
403     vkey = EVENT_event_to_vkey(event);
404     if (force_extended) vkey |= 0x100;
405
406     dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
407                     event->keycode, vkey);
408
409    if (vkey)
410    {
411     keylp.lp1.count = 1;
412     keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
413     keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
414     keylp.lp1.win_internal = 0; /* this has something to do with dialogs, 
415                                 * don't remember where I read it - AK */
416                                 /* it's '1' under windows, when a dialog box appears
417                                  * and you press one of the underlined keys - DF*/
418     vkey &= 0xff;
419
420     switch(vkey)
421     {
422     case VK_NUMLOCK:    
423       KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
424                             event_time, keylp);
425       break;
426     case VK_CAPITAL:
427       dprintf_keyboard(stddeb,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
428       KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
429                             event_time, keylp ); 
430       dprintf_keyboard(stddeb,"State after : %#.2x\n",InputKeyStateTable[vkey]);
431       break;
432     default:
433       {
434         WORD message;
435         if (event->type == KeyPress)
436           {
437             keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
438             if (!(InputKeyStateTable[vkey] & 0x80))
439               InputKeyStateTable[vkey] ^= 0x01;
440             InputKeyStateTable[vkey] |= 0x80;
441             keylp.lp1.transition = 0;
442             message = (InputKeyStateTable[VK_MENU] & 0x80)
443               && !(InputKeyStateTable[VK_CONTROL] & 0x80)
444               ? WM_SYSKEYDOWN : WM_KEYDOWN;
445           }
446         else
447           {
448             BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
449                 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
450                 && (force_extended == FALSE); /* for Alt from AltGr */
451             
452             InputKeyStateTable[vkey] &= ~0x80; 
453             keylp.lp1.previous = 1;
454             keylp.lp1.transition = 1;
455             message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
456           }
457         keylp.lp1.context = ( (event->state & Mod1Mask)  || 
458                               (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
459         if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
460           { 
461             dprintf_keyboard(stddeb,"Adjusting NumLock state. \n");
462             KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
463                                   event_time, keylp );
464             KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
465                                   event_time, keylp );
466           }
467         if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
468           {
469             dprintf_keyboard(stddeb,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
470             KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
471                                   event_time, keylp );
472             KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
473                                   event_time, keylp );
474             dprintf_keyboard(stddeb,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
475           }
476         /* End of intermediary states. */
477         NumState = FALSE;
478         CapsState = FALSE;
479
480         dprintf_key(stddeb,"            wParam=%04X, lParam=%08lX\n", 
481                     vkey, keylp.lp2 );
482         dprintf_key(stddeb,"            InputKeyState=%X\n",
483                     InputKeyStateTable[vkey]);
484
485         hardware_event( message, vkey, keylp.lp2,
486                         event_x, event_y, event_time, 0 );
487       }
488     }
489    }
490 }
491
492
493 /**********************************************************************
494  *              GetKeyState                     [USER.106]
495  */
496 WORD WINAPI GetKeyState16(INT16 vkey)
497 {
498     return GetKeyState32(vkey);
499 }
500
501 /**********************************************************************
502  *              GetKeyState                     [USER32.248]
503  * An application calls the GetKeyState function in response to a
504  * keyboard-input message.  This function retrieves the state of the key
505  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
506  */
507 WORD WINAPI GetKeyState32(INT32 vkey)
508 {
509     INT32 retval;
510
511     switch (vkey)
512         {
513         case VK_LBUTTON : /* VK_LBUTTON is 1 */
514             retval = MouseButtonsStates[0];
515             break;
516         case VK_MBUTTON : /* VK_MBUTTON is 4 */
517             retval = MouseButtonsStates[1];
518             break;
519         case VK_RBUTTON : /* VK_RBUTTON is 2 */
520             retval = MouseButtonsStates[2];
521             break;
522         default :
523             if (vkey >= 'a' && vkey <= 'z')
524                 vkey += 'A' - 'a';
525             retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
526                        (WORD)(QueueKeyStateTable[vkey] & 0x01);
527         }
528     dprintf_key(stddeb, "GetKeyState(0x%x) -> %x\n", vkey, retval);
529     return retval;
530 }
531
532 /**********************************************************************
533  *              GetKeyboardState        [USER.222][USER32.253]
534  * An application calls the GetKeyboardState function in response to a
535  * keyboard-input message.  This function retrieves the state of the keyboard
536  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
537  */
538 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
539 {
540     dprintf_key(stddeb, "GetKeyboardState()\n");
541     if (lpKeyState != NULL) {
542         QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
543         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
544         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
545         memcpy(lpKeyState, QueueKeyStateTable, 256);
546     }
547 }
548
549 /**********************************************************************
550  *      SetKeyboardState            [USER.223][USER32.483]
551  */
552 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
553 {
554     dprintf_key(stddeb, "SetKeyboardState()\n");
555     if (lpKeyState != NULL) {
556         memcpy(QueueKeyStateTable, lpKeyState, 256);
557         MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0;
558         MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0;
559         MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0;
560     }
561 }
562
563 /**********************************************************************
564  *            GetAsyncKeyState        (USER32.206)
565  *
566  *      Determine if a key is or was pressed.  retval has high-order 
567  * bit set to 1 if currently pressed, low-order bit set to 1 if key has
568  * been pressed.
569  *
570  *      This uses the variable AsyncMouseButtonsStates and
571  * AsyncKeyStateTable (set in event.c) which have the mouse button
572  * number or key number (whichever is applicable) set to true if the
573  * mouse or key had been depressed since the last call to 
574  * GetAsyncKeyState.
575  */
576 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
577 {
578     short retval;       
579
580     switch (nKey) {
581      case VK_LBUTTON:
582         retval = AsyncMouseButtonsStates[0] | 
583         MouseButtonsStates[0]? 0x0001: 0;
584         break;
585      case VK_MBUTTON:
586         retval = AsyncMouseButtonsStates[1] |
587         MouseButtonsStates[1]? 0x0001: 0;
588         break;
589      case VK_RBUTTON:
590         retval = AsyncMouseButtonsStates[2] |
591         MouseButtonsStates[2]? 0x0001: 0;
592         break;
593      default:
594         retval = AsyncKeyStateTable[nKey] | 
595                 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); 
596         break;
597     }
598
599     memset( AsyncMouseButtonsStates, 0, 3 );  /* all states to false */
600     memset( AsyncKeyStateTable, 0, 256 );
601
602     dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
603     return retval;
604 }
605
606 /**********************************************************************
607  *            GetAsyncKeyState        (USER.249)
608  */
609 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
610 {
611     return GetAsyncKeyState32(nKey);
612 }
613
614 /**********************************************************************
615  *                      TranslateAccelerator    [USER.178][USER32.551..]
616  *
617  * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP  -messages
618  */
619 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
620                                         BYTE fVirt,WORD key,WORD cmd)
621 {
622     BOOL32      sendmsg = FALSE;
623
624     if(msg->wParam == key) 
625     {
626         if (msg->message == WM_CHAR) {
627         if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
628         {
629           dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff);
630           sendmsg=TRUE;
631         }  
632       } else {
633        if(fVirt & FVIRTKEY) {
634         INT32 mask = 0;
635         dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
636                                msg->wParam,0xff & HIWORD(msg->lParam));                
637         if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
638         if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
639         if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
640         if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
641           sendmsg=TRUE;                     
642         else
643           dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n");
644        }
645        else
646        {
647          if (!(msg->lParam & 0x01000000))  /* no special_key */
648          {
649            if ((fVirt & FALT) && (msg->lParam & 0x20000000))
650            {                                                   /* ^^ ALT pressed */
651             dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff);
652             sendmsg=TRUE;           
653            } 
654          } 
655        }
656       } 
657
658       if (sendmsg)      /* found an accelerator, but send a message... ? */
659       {
660         INT16  iSysStat,iStat,mesg=0;
661         HMENU16 hMenu;
662         
663         if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
664           mesg=1;
665         else 
666          if (GetCapture32())
667            mesg=2;
668          else
669           if (!IsWindowEnabled32(hWnd))
670             mesg=3;
671           else
672           {
673             WND* wndPtr = WIN_FindWndPtr(hWnd);
674
675             hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
676             iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
677                                             cmd, MF_BYCOMMAND) : -1 ;
678             iStat = (hMenu) ? GetMenuState32(hMenu,
679                                             cmd, MF_BYCOMMAND) : -1 ;
680
681             if (iSysStat!=-1)
682             {
683               if (iSysStat & (MF_DISABLED|MF_GRAYED))
684                 mesg=4;
685               else
686                 mesg=WM_SYSCOMMAND;
687             }
688             else
689             {
690               if (iStat!=-1)
691               {
692                 if (IsIconic32(hWnd))
693                   mesg=5;
694                 else
695                 {
696                  if (iStat & (MF_DISABLED|MF_GRAYED))
697                    mesg=6;
698                  else
699                    mesg=WM_COMMAND;  
700                 }   
701               }
702               else
703                mesg=WM_COMMAND;  
704             }
705           }
706           if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
707           {
708               dprintf_accel(stddeb,", sending %s, wParam=%0x\n",
709                   mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
710                   cmd);
711               SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
712           }
713           else
714           {
715            /*  some reasons for NOT sending the WM_{SYS}COMMAND message: 
716             *   #0: unknown (please report!)
717             *   #1: for WM_KEYUP,WM_SYSKEYUP
718             *   #2: mouse is captured
719             *   #3: window is disabled 
720             *   #4: it's a disabled system menu option
721             *   #5: it's a menu option, but window is iconic
722             *   #6: it's a menu option, but disabled
723             */
724             dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
725           }          
726           return TRUE;         
727       }
728     }
729     return FALSE;
730 }
731
732 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
733 {
734     LPACCEL32   lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
735     int         i;
736     
737     if (hAccel == 0 || msg == NULL) return 0;
738     if (msg->message != WM_KEYDOWN &&
739         msg->message != WM_KEYUP &&
740         msg->message != WM_SYSKEYDOWN &&
741         msg->message != WM_SYSKEYUP &&
742         msg->message != WM_CHAR) return 0;
743
744     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
745 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
746
747     for (i = 0; lpAccelTbl[i].key ; i++)
748         if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
749                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
750                 return 1;
751     return 0;
752 }
753         
754 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
755 {
756     LPACCEL16   lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
757     int         i;
758     MSG32       msg32;
759     
760     if (hAccel == 0 || msg == NULL) return 0;
761     if (msg->message != WM_KEYDOWN &&
762         msg->message != WM_KEYUP &&
763         msg->message != WM_SYSKEYDOWN &&
764         msg->message != WM_SYSKEYUP &&
765         msg->message != WM_CHAR) return 0;
766
767     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
768 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
769     STRUCT32_MSG16to32(msg,&msg32);
770
771
772     for (i=0;lpAccelTbl[i].key;i++) 
773         if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
774                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
775                 return 1;
776     return 0;
777 }
778
779
780 /******************************************************************************
781  *      OemKeyScan                      [KEYBOARD.128][USER32.400]
782  */
783 DWORD WINAPI OemKeyScan(WORD wOemChar)
784 {
785     dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
786
787     return wOemChar;
788 }
789
790 /******************************************************************************
791  *      VkKeyScanA                      [USER32.572]
792  */
793 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
794  * for the current keyboard.
795  * high-order byte yields :
796  *      0       Unshifted
797  *      1       Shift
798  *      2       Ctrl
799  *      3-5     Shift-key combinations that are not used for characters
800  *      6       Ctrl-Alt
801  *      7       Ctrl-Alt-Shift
802  *      I.e. :  Shift = 1, Ctrl = 2, Alt = 4.
803  * FIXME : works ok except for dead chars :
804  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
805  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
806  */
807
808 WORD WINAPI VkKeyScan32A(CHAR cChar)
809 {
810         KeyCode keycode;
811         KeySym keysym;          
812         int i,index;
813         int highbyte=0;
814
815         /* char->keysym (same for ANSI chars) */
816         keysym=(unsigned char) cChar;/* (!) cChar is signed */
817         if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
818         
819         keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
820         if (!keycode)
821         { /* It didn't work ... let's try with deadchar code. */
822           keycode = XKeysymToKeycode(display, keysym | 0xFE00);
823         }
824
825         dprintf_keyboard(stddeb,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
826             cChar,keysym,keysym,keycode);
827         
828         if (keycode)
829           {
830             for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
831               if (XKeycodeToKeysym(display,keycode,i)==keysym) index=i;
832             switch (index) {
833             case -1 :
834               fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
835             case 0 : break;
836             case 1 : highbyte = 0x0100; break;
837             case 2 : highbyte = 0X0600; break;
838             default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
839             }
840             /*
841               index : 0     adds 0x0000
842               index : 1     adds 0x0100 (shift)
843               index : ?     adds 0x0200 (ctrl)
844               index : 2     adds 0x0600 (ctrl+alt)
845               index : ?     adds 0x0700 (ctrl+alt+shift (used?))
846              */
847           }
848         dprintf_keyboard(stddeb," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
849         return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
850 }
851
852 /******************************************************************************
853  *      VkKeyScan                       [KEYBOARD.129]
854  */
855 WORD WINAPI VkKeyScan16(CHAR cChar)
856 {
857         return VkKeyScan32A(cChar);
858 }
859
860 /******************************************************************************
861  *      VkKeyScanW                      [USER32.575]
862  */
863 WORD WINAPI VkKeyScan32W(WCHAR cChar)
864 {
865         return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
866 }
867
868 /******************************************************************************
869  *      GetKeyboardType                 [KEYBOARD.130]
870  */
871 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
872 {
873   return GetKeyboardType32(nTypeFlag);
874 }
875
876 /******************************************************************************
877  *      GetKeyboardType                 [USER32.254]
878  */
879 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
880 {
881   dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
882   switch(nTypeFlag)
883     {
884     case 0:      /* Keyboard type */
885       return 4;    /* AT-101 */
886       break;
887     case 1:      /* Keyboard Subtype */
888       return 0;    /* There are no defined subtypes */
889       break;
890     case 2:      /* Number of F-keys */
891       return 12;   /* We're doing an 101 for now, so return 12 F-keys */
892       break;
893     default:     
894       fprintf(stderr, "Unknown type on GetKeyboardType\n");
895       return 0;    /* The book says 0 here, so 0 */
896     }
897 }
898
899
900 /******************************************************************************
901  *      MapVirtualKeyA                  [USER32.382]
902  */
903 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
904 {
905     return MapVirtualKey16(code,maptype);
906 }
907
908 /******************************************************************************
909  *      MapVirtualKeyA                  [USER32.384]
910  */
911 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
912 {
913     return MapVirtualKey16(code,maptype);
914 }
915
916 /******************************************************************************
917  *      MapVirtualKeyA                  [KEYBOARD.131]
918  * MapVirtualKey translates keycodes from one format to another
919  */
920 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
921 {
922 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
923
924         dprintf_keyboard(stddeb,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode,wMapType);
925         switch(wMapType) {
926                 case 0: { /* vkey-code to scan-code */
927                         /* let's do vkey -> keycode -> scan */
928                         KeyCode keyc;
929                         for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
930                                 if ((keyc2vkey[keyc] & 0xFF)== wCode)
931                                         returnMVK (keyc - 8);
932                         return 0; }
933
934                 case 1: /* scan-code to vkey-code */
935                         /* let's do scan -> keycode -> vkey */
936
937                         returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
938
939                 case 2: { /* vkey-code to unshifted ANSI code */
940                         /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
941                         /* My Windows returns 'A'. */
942                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
943                         XKeyEvent e;
944                         KeySym keysym;
945                         char s[2];
946                         e.display = display;
947                         e.state = 0; /* unshifted */
948                         e.keycode = MapVirtualKey16( wCode, 0);
949                         if (!XLookupString(&e, s , 2 , &keysym, NULL))
950                           returnMVK (*s);
951                         
952                         return 0;
953                         }
954                 default: /* reserved */
955                         fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
956                                 wMapType);
957                         return 0;       
958         }
959         return 0;
960 }
961
962
963 /****************************************************************************
964  *      GetKBCodePage16   (KEYBOARD.132)
965  */
966 INT16 WINAPI GetKBCodePage16(void)
967 {
968     dprintf_keyboard(stddeb,"GetKBCodePage()\n");
969     return 850;
970 }
971
972
973 /****************************************************************************
974  *      GetKBCodePage32   (USER32.245)
975  */
976 UINT32 WINAPI GetKBCodePage32(void)
977 {
978     dprintf_keyboard(stddeb,"GetKbCodePage()\n");
979     return 850;
980 }
981
982
983 /****************************************************************************
984  *      GetKeyNameText32W   (USER32.247)
985  */
986 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
987 {
988         LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
989         int res = GetKeyNameText32A(lParam,buf,nSize);
990
991         lstrcpynAtoW(lpBuffer,buf,nSize);
992         HeapFree( GetProcessHeap(), 0, buf );
993         return res;
994 }
995
996 /****************************************************************************
997  *      GetKeyNameText32A   (USER32.246)
998  */
999 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1000 {
1001         return GetKeyNameText16(lParam,lpBuffer,nSize);
1002 }
1003
1004 /****************************************************************************
1005  *      GetKeyNameText16   (KEYBOARD.133)
1006  */
1007 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1008 {
1009   /*    int i; */
1010         
1011         dprintf_keyboard(stddeb,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
1012
1013         lParam >>= 16;
1014         lParam &= 0xff;
1015
1016         /*      for (i = 0 ; i != KeyTableSize ; i++) 
1017                 if (KeyTable[i].scancode == lParam)  {
1018                         lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1019                         return strlen(lpBuffer);
1020                 }
1021                 */
1022         /* FIXME ! GetKeyNameText is still to do...
1023  */
1024         *lpBuffer = 0;
1025         return 0;
1026 }
1027
1028
1029 /****************************************************************************
1030  *      ToAscii   (KEYBOARD.4)
1031  */
1032 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
1033                        LPVOID lpChar, UINT16 flags) 
1034 {
1035     return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1036 }
1037
1038 /****************************************************************************
1039  *      ToAscii   (USER32.545)
1040  */
1041 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1042                         LPWORD lpChar,UINT32 flags )
1043 {
1044     XKeyEvent e;
1045     KeySym keysym;
1046     static XComposeStatus cs;
1047     INT32 ret;
1048     WORD keyc;
1049
1050     e.display = display;
1051     e.keycode = 0;
1052     for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1053       { /* this could be speeded up by making another table, an array of struct vkey,keycode
1054          * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)!  DF */
1055         if ((keyc2vkey[keyc] & 0xFF)== virtKey) /* no need to make a more precise test (with the extended bit correctly set above virtKey ... VK* are different enough... */
1056           {
1057             if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12))) 
1058                 /* it's normal to have 2 shift, control, and alt ! */
1059                 dprintf_keyboard(stddeb,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1060                                  e.keycode,keyc,virtKey);
1061             e.keycode = keyc;
1062           }
1063       }
1064     if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01)) 
1065       {
1066         if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1067           e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1068         if (virtKey==VK_DECIMAL)
1069           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1070       }
1071     if (!e.keycode)
1072       {
1073         fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1074         return virtKey; /* whatever */
1075       }
1076     e.state = 0;
1077     if (lpKeyState[VK_SHIFT] & 0x80)
1078         e.state |= ShiftMask;
1079     dprintf_keyboard(stddeb,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1080     if (lpKeyState[VK_CAPITAL] & 0x01)
1081         e.state |= LockMask;
1082     if (lpKeyState[VK_CONTROL] & 0x80)
1083         if (lpKeyState[VK_MENU] & 0x80)
1084             e.state |= AltGrMask;
1085         else
1086             e.state |= ControlMask;
1087     if (lpKeyState[VK_NUMLOCK] & 0x01)
1088         e.state |= NumLockMask;
1089     dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
1090                 virtKey, scanCode, e.state);
1091     ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1092     if (ret == 0)
1093         {
1094         BYTE dead_char = 0;
1095
1096         ((char*)lpChar)[1] = '\0';
1097         switch (keysym)
1098             {
1099         /* symbolic ASCII is the same as defined in rfc1345 */
1100 #ifdef XK_dead_tilde
1101             case XK_dead_tilde :
1102 #endif
1103             case 0x1000FE7E : /* Xfree's XK_Dtilde */
1104                 dead_char = '~';        /* '? */
1105                 break;
1106 #ifdef XK_dead_acute
1107             case XK_dead_acute :
1108 #endif
1109             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1110                 dead_char = 0xb4;       /* '' */
1111                 break;
1112 #ifdef XK_dead_circumflex
1113             case XK_dead_circumflex :
1114 #endif
1115             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1116                 dead_char = '^';        /* '> */
1117                 break;
1118 #ifdef XK_dead_grave
1119             case XK_dead_grave :
1120 #endif
1121             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1122                 dead_char = '`';        /* '! */
1123                 break;
1124 #ifdef XK_dead_diaeresis
1125             case XK_dead_diaeresis :
1126 #endif
1127             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1128                 dead_char = 0xa8;       /* ': */
1129                 break;
1130 #ifdef XK_dead_cedilla
1131             case XK_dead_cedilla :
1132                 dead_char = 0xb8;       /* ', */
1133                 break;
1134 #endif
1135 #ifdef XK_dead_macron
1136             case XK_dead_macron :
1137                 dead_char = '-';        /* 'm isn't defined on iso-8859-x */
1138                 break;
1139 #endif
1140 #ifdef XK_dead_breve
1141             case XK_dead_breve :
1142                 dead_char = 0xa2;       /* '( */
1143                 break;
1144 #endif
1145 #ifdef XK_dead_abovedot
1146             case XK_dead_abovedot :
1147                 dead_char = 0xff;       /* '. */
1148                 break;
1149 #endif
1150 #ifdef XK_dead_abovering
1151             case XK_dead_abovering :
1152                 dead_char = '0';        /* '0 isn't defined on iso-8859-x */
1153                 break;
1154 #endif
1155 #ifdef XK_dead_doubleacute
1156             case XK_dead_doubleacute :
1157                 dead_char = 0xbd;       /* '" */
1158                 break;
1159 #endif
1160 #ifdef XK_dead_caron
1161             case XK_dead_caron :
1162                 dead_char = 0xb7;       /* '< */
1163                 break;
1164 #endif
1165 #ifdef XK_dead_ogonek
1166             case XK_dead_ogonek :
1167                 dead_char = 0xb2;       /* '; */
1168                 break;
1169 #endif
1170 /* FIXME: I don't know this three.
1171             case XK_dead_iota :
1172                 dead_char = 'i';         
1173                 break;
1174             case XK_dead_voiced_sound :
1175                 dead_char = 'v';
1176                 break;
1177             case XK_dead_semivoiced_sound :
1178                 dead_char = 's';
1179                 break;
1180 */
1181             }
1182         if (dead_char)
1183             {
1184             *(char*)lpChar = dead_char;
1185             ret = -1;
1186             }
1187         else
1188             {
1189             char        *ksname;
1190
1191             ksname = XKeysymToString(keysym);
1192             if (!ksname)
1193                 ksname = "No Name";
1194             if ((keysym >> 8) != 0xff)
1195                 {
1196                 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1197                         keysym, ksname);
1198                 fprintf(stderr, "  virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1199                         virtKey, scanCode, e.keycode, e.state);
1200                 }
1201             }
1202         }
1203     dprintf_key(stddeb, "ToAscii about to return %d with char %x\n",
1204                 ret, *(char*)lpChar);
1205     return ret;
1206 }
1207
1208
1209 /***********************************************************************
1210  *           GetKeyboardLayout                  (USER32.249)
1211  */
1212 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1213 {
1214         fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1215         return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1216 }
1217
1218 /***********************************************************************
1219  *           GetKeyboardLayoutList              (USER32.250)
1220  * FIXME
1221  */
1222 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1223 {
1224         fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1225         if (layouts)
1226                 layouts[0] = GetKeyboardLayout(0);
1227         return 1;
1228 }
1229
1230
1231 /***********************************************************************
1232  *           RegisterHotKey                     (USER32.433)
1233  */
1234 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1235         fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1236                 hwnd,id,modifiers,vk
1237         );
1238         return TRUE;
1239 }
1240
1241 /***********************************************************************
1242  *           UnregisterHotKey                   (USER32.565)
1243  */
1244 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1245         fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);
1246         return TRUE;
1247 }