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