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