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