Release 980104
[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] ? 0x8000 : 0;
515             break;
516         case VK_MBUTTON : /* VK_MBUTTON is 4 */
517             retval = MouseButtonsStates[1] ? 0x8000 : 0;
518             break;
519         case VK_RBUTTON : /* VK_RBUTTON is 2 */
520             retval = MouseButtonsStates[2] ? 0x8000 : 0;
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] ? 0x80 : 0;
543         QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
544         QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
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] != 0);
558         MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
559         MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 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] ? 0x0001 : 0) | 
583                  (MouseButtonsStates[0] ? 0x8000 : 0);
584         break;
585      case VK_MBUTTON:
586         retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) | 
587                  (MouseButtonsStates[1] ? 0x8000 : 0);
588         break;
589      case VK_RBUTTON:
590         retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) | 
591                  (MouseButtonsStates[2] ? 0x8000 : 0);
592         break;
593      default:
594         retval = AsyncKeyStateTable[nKey] | 
595                 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); 
596         break;
597     }
598
599     /* all states to false */
600     memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
601     memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
602
603     dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
604     return retval;
605 }
606
607 /**********************************************************************
608  *            GetAsyncKeyState        (USER.249)
609  */
610 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
611 {
612     return GetAsyncKeyState32(nKey);
613 }
614
615 /**********************************************************************
616  *                      TranslateAccelerator    [USER.178][USER32.551..]
617  *
618  * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP  -messages
619  */
620 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
621                                         BYTE fVirt,WORD key,WORD cmd)
622 {
623     BOOL32      sendmsg = FALSE;
624
625     if(msg->wParam == key) 
626     {
627         if (msg->message == WM_CHAR) {
628         if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
629         {
630           dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff);
631           sendmsg=TRUE;
632         }  
633       } else {
634        if(fVirt & FVIRTKEY) {
635         INT32 mask = 0;
636         dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
637                                msg->wParam,0xff & HIWORD(msg->lParam));                
638         if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
639         if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
640         if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
641         if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
642           sendmsg=TRUE;                     
643         else
644           dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n");
645        }
646        else
647        {
648          if (!(msg->lParam & 0x01000000))  /* no special_key */
649          {
650            if ((fVirt & FALT) && (msg->lParam & 0x20000000))
651            {                                                   /* ^^ ALT pressed */
652             dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff);
653             sendmsg=TRUE;           
654            } 
655          } 
656        }
657       } 
658
659       if (sendmsg)      /* found an accelerator, but send a message... ? */
660       {
661         INT16  iSysStat,iStat,mesg=0;
662         HMENU16 hMenu;
663         
664         if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
665           mesg=1;
666         else 
667          if (GetCapture32())
668            mesg=2;
669          else
670           if (!IsWindowEnabled32(hWnd))
671             mesg=3;
672           else
673           {
674             WND* wndPtr = WIN_FindWndPtr(hWnd);
675
676             hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
677             iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
678                                             cmd, MF_BYCOMMAND) : -1 ;
679             iStat = (hMenu) ? GetMenuState32(hMenu,
680                                             cmd, MF_BYCOMMAND) : -1 ;
681
682             if (iSysStat!=-1)
683             {
684               if (iSysStat & (MF_DISABLED|MF_GRAYED))
685                 mesg=4;
686               else
687                 mesg=WM_SYSCOMMAND;
688             }
689             else
690             {
691               if (iStat!=-1)
692               {
693                 if (IsIconic32(hWnd))
694                   mesg=5;
695                 else
696                 {
697                  if (iStat & (MF_DISABLED|MF_GRAYED))
698                    mesg=6;
699                  else
700                    mesg=WM_COMMAND;  
701                 }   
702               }
703               else
704                mesg=WM_COMMAND;  
705             }
706           }
707           if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
708           {
709               dprintf_accel(stddeb,", sending %s, wParam=%0x\n",
710                   mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
711                   cmd);
712               SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
713           }
714           else
715           {
716            /*  some reasons for NOT sending the WM_{SYS}COMMAND message: 
717             *   #0: unknown (please report!)
718             *   #1: for WM_KEYUP,WM_SYSKEYUP
719             *   #2: mouse is captured
720             *   #3: window is disabled 
721             *   #4: it's a disabled system menu option
722             *   #5: it's a menu option, but window is iconic
723             *   #6: it's a menu option, but disabled
724             */
725             dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
726           }          
727           return TRUE;         
728       }
729     }
730     return FALSE;
731 }
732
733 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
734 {
735     LPACCEL32   lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
736     int         i;
737     
738     if (hAccel == 0 || msg == NULL) return 0;
739     if (msg->message != WM_KEYDOWN &&
740         msg->message != WM_KEYUP &&
741         msg->message != WM_SYSKEYDOWN &&
742         msg->message != WM_SYSKEYUP &&
743         msg->message != WM_CHAR) return 0;
744
745     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
746 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
747
748     for (i = 0; lpAccelTbl[i].key ; i++)
749         if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
750                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
751                 return 1;
752     return 0;
753 }
754         
755 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
756 {
757     LPACCEL16   lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
758     int         i;
759     MSG32       msg32;
760     
761     if (hAccel == 0 || msg == NULL) return 0;
762     if (msg->message != WM_KEYDOWN &&
763         msg->message != WM_KEYUP &&
764         msg->message != WM_SYSKEYDOWN &&
765         msg->message != WM_SYSKEYUP &&
766         msg->message != WM_CHAR) return 0;
767
768     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
769 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
770     STRUCT32_MSG16to32(msg,&msg32);
771
772
773     for (i=0;lpAccelTbl[i].key;i++) 
774         if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
775                                       lpAccelTbl[i].key,lpAccelTbl[i].cmd))
776                 return 1;
777     return 0;
778 }
779
780
781 /******************************************************************************
782  *      OemKeyScan                      [KEYBOARD.128][USER32.400]
783  */
784 DWORD WINAPI OemKeyScan(WORD wOemChar)
785 {
786     dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
787
788     return wOemChar;
789 }
790
791 /******************************************************************************
792  *      VkKeyScanA                      [USER32.572]
793  */
794 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
795  * for the current keyboard.
796  * high-order byte yields :
797  *      0       Unshifted
798  *      1       Shift
799  *      2       Ctrl
800  *      3-5     Shift-key combinations that are not used for characters
801  *      6       Ctrl-Alt
802  *      7       Ctrl-Alt-Shift
803  *      I.e. :  Shift = 1, Ctrl = 2, Alt = 4.
804  * FIXME : works ok except for dead chars :
805  * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
806  * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
807  */
808
809 WORD WINAPI VkKeyScan32A(CHAR cChar)
810 {
811         KeyCode keycode;
812         KeySym keysym;          
813         int i,index;
814         int highbyte=0;
815
816         /* char->keysym (same for ANSI chars) */
817         keysym=(unsigned char) cChar;/* (!) cChar is signed */
818         if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
819         
820         keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
821         if (!keycode)
822         { /* It didn't work ... let's try with deadchar code. */
823           keycode = XKeysymToKeycode(display, keysym | 0xFE00);
824         }
825
826         dprintf_keyboard(stddeb,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
827             cChar,keysym,keysym,keycode);
828         
829         if (keycode)
830           {
831             for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
832               if (XKeycodeToKeysym(display,keycode,i)==keysym) index=i;
833             switch (index) {
834             case -1 :
835               fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
836             case 0 : break;
837             case 1 : highbyte = 0x0100; break;
838             case 2 : highbyte = 0X0600; break;
839             default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
840             }
841             /*
842               index : 0     adds 0x0000
843               index : 1     adds 0x0100 (shift)
844               index : ?     adds 0x0200 (ctrl)
845               index : 2     adds 0x0600 (ctrl+alt)
846               index : ?     adds 0x0700 (ctrl+alt+shift (used?))
847              */
848           }
849         dprintf_keyboard(stddeb," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
850         return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
851 }
852
853 /******************************************************************************
854  *      VkKeyScan                       [KEYBOARD.129]
855  */
856 WORD WINAPI VkKeyScan16(CHAR cChar)
857 {
858         return VkKeyScan32A(cChar);
859 }
860
861 /******************************************************************************
862  *      VkKeyScanW                      [USER32.575]
863  */
864 WORD WINAPI VkKeyScan32W(WCHAR cChar)
865 {
866         return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
867 }
868
869 /******************************************************************************
870  *      GetKeyboardType                 [KEYBOARD.130]
871  */
872 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
873 {
874   return GetKeyboardType32(nTypeFlag);
875 }
876
877 /******************************************************************************
878  *      GetKeyboardType                 [USER32.254]
879  */
880 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
881 {
882   dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
883   switch(nTypeFlag)
884     {
885     case 0:      /* Keyboard type */
886       return 4;    /* AT-101 */
887       break;
888     case 1:      /* Keyboard Subtype */
889       return 0;    /* There are no defined subtypes */
890       break;
891     case 2:      /* Number of F-keys */
892       return 12;   /* We're doing an 101 for now, so return 12 F-keys */
893       break;
894     default:     
895       fprintf(stderr, "Unknown type on GetKeyboardType\n");
896       return 0;    /* The book says 0 here, so 0 */
897     }
898 }
899
900
901 /******************************************************************************
902  *      MapVirtualKeyA                  [USER32.382]
903  */
904 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
905 {
906     return MapVirtualKey16(code,maptype);
907 }
908
909 /******************************************************************************
910  *      MapVirtualKeyA                  [USER32.384]
911  */
912 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
913 {
914     return MapVirtualKey16(code,maptype);
915 }
916
917 /******************************************************************************
918  *      MapVirtualKeyA                  [KEYBOARD.131]
919  * MapVirtualKey translates keycodes from one format to another
920  */
921 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
922 {
923 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
924
925         dprintf_keyboard(stddeb,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode,wMapType);
926         switch(wMapType) {
927                 case 0: { /* vkey-code to scan-code */
928                         /* let's do vkey -> keycode -> scan */
929                         KeyCode keyc;
930                         for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
931                                 if ((keyc2vkey[keyc] & 0xFF)== wCode)
932                                         returnMVK (keyc - 8);
933                         return 0; }
934
935                 case 1: /* scan-code to vkey-code */
936                         /* let's do scan -> keycode -> vkey */
937
938                         returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
939
940                 case 2: { /* vkey-code to unshifted ANSI code */
941                         /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
942                         /* My Windows returns 'A'. */
943                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
944                         XKeyEvent e;
945                         KeySym keysym;
946                         char s[2];
947                         e.display = display;
948                         e.state = 0; /* unshifted */
949                         e.keycode = MapVirtualKey16( wCode, 0);
950                         if (!XLookupString(&e, s , 2 , &keysym, NULL))
951                           returnMVK (*s);
952                         
953                         return 0;
954                         }
955                 default: /* reserved */
956                         fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
957                                 wMapType);
958                         return 0;       
959         }
960         return 0;
961 }
962
963
964 /****************************************************************************
965  *      GetKBCodePage16   (KEYBOARD.132)
966  */
967 INT16 WINAPI GetKBCodePage16(void)
968 {
969     dprintf_keyboard(stddeb,"GetKBCodePage()\n");
970     return 850;
971 }
972
973
974 /****************************************************************************
975  *      GetKBCodePage32   (USER32.245)
976  */
977 UINT32 WINAPI GetKBCodePage32(void)
978 {
979     dprintf_keyboard(stddeb,"GetKbCodePage()\n");
980     return 850;
981 }
982
983
984 /****************************************************************************
985  *      GetKeyNameText32W   (USER32.247)
986  */
987 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
988 {
989         LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
990         int res = GetKeyNameText32A(lParam,buf,nSize);
991
992         lstrcpynAtoW(lpBuffer,buf,nSize);
993         HeapFree( GetProcessHeap(), 0, buf );
994         return res;
995 }
996
997 /****************************************************************************
998  *      GetKeyNameText32A   (USER32.246)
999  */
1000 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1001 {
1002         return GetKeyNameText16(lParam,lpBuffer,nSize);
1003 }
1004
1005 /****************************************************************************
1006  *      GetKeyNameText16   (KEYBOARD.133)
1007  */
1008 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1009 {
1010   /*    int i; */
1011         
1012         dprintf_keyboard(stddeb,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
1013
1014         lParam >>= 16;
1015         lParam &= 0xff;
1016
1017         /*      for (i = 0 ; i != KeyTableSize ; i++) 
1018                 if (KeyTable[i].scancode == lParam)  {
1019                         lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1020                         return strlen(lpBuffer);
1021                 }
1022                 */
1023         /* FIXME ! GetKeyNameText is still to do...
1024  */
1025         *lpBuffer = 0;
1026         return 0;
1027 }
1028
1029
1030 /****************************************************************************
1031  *      ToAscii   (KEYBOARD.4)
1032  */
1033 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, 
1034                        LPVOID lpChar, UINT16 flags) 
1035 {
1036     return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1037 }
1038
1039 /****************************************************************************
1040  *      ToAscii   (USER32.545)
1041  */
1042 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1043                         LPWORD lpChar,UINT32 flags )
1044 {
1045     XKeyEvent e;
1046     KeySym keysym;
1047     static XComposeStatus cs;
1048     INT32 ret;
1049     WORD keyc;
1050
1051     e.display = display;
1052     e.keycode = 0;
1053     for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1054       { /* this could be speeded up by making another table, an array of struct vkey,keycode
1055          * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)!  DF */
1056         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... */
1057           {
1058             if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12))) 
1059                 /* it's normal to have 2 shift, control, and alt ! */
1060                 dprintf_keyboard(stddeb,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1061                                  e.keycode,keyc,virtKey);
1062             e.keycode = keyc;
1063           }
1064       }
1065     if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01)) 
1066       {
1067         if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1068           e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1069         if (virtKey==VK_DECIMAL)
1070           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1071       }
1072     if (!e.keycode)
1073       {
1074         fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1075         return virtKey; /* whatever */
1076       }
1077     e.state = 0;
1078     if (lpKeyState[VK_SHIFT] & 0x80)
1079         e.state |= ShiftMask;
1080     dprintf_keyboard(stddeb,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1081     if (lpKeyState[VK_CAPITAL] & 0x01)
1082         e.state |= LockMask;
1083     if (lpKeyState[VK_CONTROL] & 0x80)
1084         if (lpKeyState[VK_MENU] & 0x80)
1085             e.state |= AltGrMask;
1086         else
1087             e.state |= ControlMask;
1088     if (lpKeyState[VK_NUMLOCK] & 0x01)
1089         e.state |= NumLockMask;
1090     dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
1091                 virtKey, scanCode, e.state);
1092     ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1093     if (ret == 0)
1094         {
1095         BYTE dead_char = 0;
1096
1097         ((char*)lpChar)[1] = '\0';
1098         switch (keysym)
1099             {
1100         /* symbolic ASCII is the same as defined in rfc1345 */
1101 #ifdef XK_dead_tilde
1102             case XK_dead_tilde :
1103 #endif
1104             case 0x1000FE7E : /* Xfree's XK_Dtilde */
1105                 dead_char = '~';        /* '? */
1106                 break;
1107 #ifdef XK_dead_acute
1108             case XK_dead_acute :
1109 #endif
1110             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1111                 dead_char = 0xb4;       /* '' */
1112                 break;
1113 #ifdef XK_dead_circumflex
1114             case XK_dead_circumflex :
1115 #endif
1116             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1117                 dead_char = '^';        /* '> */
1118                 break;
1119 #ifdef XK_dead_grave
1120             case XK_dead_grave :
1121 #endif
1122             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1123                 dead_char = '`';        /* '! */
1124                 break;
1125 #ifdef XK_dead_diaeresis
1126             case XK_dead_diaeresis :
1127 #endif
1128             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1129                 dead_char = 0xa8;       /* ': */
1130                 break;
1131 #ifdef XK_dead_cedilla
1132             case XK_dead_cedilla :
1133                 dead_char = 0xb8;       /* ', */
1134                 break;
1135 #endif
1136 #ifdef XK_dead_macron
1137             case XK_dead_macron :
1138                 dead_char = '-';        /* 'm isn't defined on iso-8859-x */
1139                 break;
1140 #endif
1141 #ifdef XK_dead_breve
1142             case XK_dead_breve :
1143                 dead_char = 0xa2;       /* '( */
1144                 break;
1145 #endif
1146 #ifdef XK_dead_abovedot
1147             case XK_dead_abovedot :
1148                 dead_char = 0xff;       /* '. */
1149                 break;
1150 #endif
1151 #ifdef XK_dead_abovering
1152             case XK_dead_abovering :
1153                 dead_char = '0';        /* '0 isn't defined on iso-8859-x */
1154                 break;
1155 #endif
1156 #ifdef XK_dead_doubleacute
1157             case XK_dead_doubleacute :
1158                 dead_char = 0xbd;       /* '" */
1159                 break;
1160 #endif
1161 #ifdef XK_dead_caron
1162             case XK_dead_caron :
1163                 dead_char = 0xb7;       /* '< */
1164                 break;
1165 #endif
1166 #ifdef XK_dead_ogonek
1167             case XK_dead_ogonek :
1168                 dead_char = 0xb2;       /* '; */
1169                 break;
1170 #endif
1171 /* FIXME: I don't know this three.
1172             case XK_dead_iota :
1173                 dead_char = 'i';         
1174                 break;
1175             case XK_dead_voiced_sound :
1176                 dead_char = 'v';
1177                 break;
1178             case XK_dead_semivoiced_sound :
1179                 dead_char = 's';
1180                 break;
1181 */
1182             }
1183         if (dead_char)
1184             {
1185             *(char*)lpChar = dead_char;
1186             ret = -1;
1187             }
1188         else
1189             {
1190             char        *ksname;
1191
1192             ksname = XKeysymToString(keysym);
1193             if (!ksname)
1194                 ksname = "No Name";
1195             if ((keysym >> 8) != 0xff)
1196                 {
1197                 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1198                         keysym, ksname);
1199                 fprintf(stderr, "  virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1200                         virtKey, scanCode, e.keycode, e.state);
1201                 }
1202             }
1203         }
1204     dprintf_key(stddeb, "ToAscii about to return %d with char %x\n",
1205                 ret, *(char*)lpChar);
1206     return ret;
1207 }
1208
1209
1210 /***********************************************************************
1211  *           GetKeyboardLayout                  (USER32.249)
1212  */
1213 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1214 {
1215         fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1216         return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1217 }
1218
1219 /***********************************************************************
1220  *           GetKeyboardLayoutList              (USER32.250)
1221  * FIXME
1222  */
1223 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1224 {
1225         fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1226         if (layouts)
1227                 layouts[0] = GetKeyboardLayout(0);
1228         return 1;
1229 }
1230
1231
1232 /***********************************************************************
1233  *           RegisterHotKey                     (USER32.433)
1234  */
1235 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1236         fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1237                 hwnd,id,modifiers,vk
1238         );
1239         return TRUE;
1240 }
1241
1242 /***********************************************************************
1243  *           UnregisterHotKey                   (USER32.565)
1244  */
1245 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1246         fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);
1247         return TRUE;
1248 }