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