Release 980329
[wine.git] / windows / keyboard.c
blob6d91398dde3162851e55063949b65437333e8682
1 /*
2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
8 */
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>
20 #include "windows.h"
21 #include "win.h"
22 #include "gdi.h"
23 #include "heap.h"
24 #include "keyboard.h"
25 #include "message.h"
26 #include "debug.h"
27 #include "debugtools.h"
28 #include "struct32.h"
29 #include "winerror.h"
31 BOOL32 MouseButtonsStates[3];
32 BOOL32 AsyncMouseButtonsStates[3];
33 BYTE InputKeyStateTable[256];
34 BYTE QueueKeyStateTable[256];
35 BYTE AsyncKeyStateTable[256];
37 static int NumLockMask;
38 static int AltGrMask;
39 static int min_keycode, max_keycode;
40 static int keyc2vkey[256];
42 typedef union
44 struct
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;
58 /* Keyboard translation tables */
59 static const int special_key[] =
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 */
66 static const int cursor_key[] =
68 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
69 VK_NEXT, VK_END /* FF50 */
72 static const int misc_key[] =
74 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
78 static const int keypad_key[] =
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 */
94 static const int function_key[] =
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 */
101 static const int modifier_key[] =
103 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
104 VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
108 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
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,
146 static WORD EVENT_event_to_vkey( XKeyEvent *e)
148 KeySym keysym;
150 TSXLookupString(e, NULL, 0, &keysym, NULL);
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];
157 return keyc2vkey[e->keycode];
160 /**********************************************************************
161 * KEYBOARD_Init
163 BOOL32 KEYBOARD_Init(void)
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;
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 */
183 int j;
185 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
186 if (*kcp)
188 int k;
190 for (k = 0; k < keysyms_per_keycode; k += 1)
191 if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
193 AltGrMask = 1 << i;
194 TRACE(key, "AltGrMask is %x\n", AltGrMask);
196 else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
198 NumLockMask = 1 << i;
199 TRACE(key, "NumLockMask is %x\n", NumLockMask);
203 TSXFreeModifiermap(mmp);
205 /* Now build two conversion arrays :
206 * keycode -> vkey + extended
207 * vkey + extended -> keycode */
209 e2.display = display;
210 e2.state = 0;
212 OEMvkey = 0xb9; /* first OEM virtual key available is ba */
213 for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
215 TSXLookupString(&e2, NULL, 0, &keysym, NULL);
216 vkey = 0;
217 if (keysym) /* otherwise, keycode not used */
219 if ((keysym >> 8) == 0xFF) /* non-character key */
221 int key = keysym & 0xff;
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 */
233 vkey = function_key[key - 0xBE];
234 vkey |= 0x100; /* set extended bit */
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)
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;
264 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
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;
273 if (!vkey)
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)
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");
284 vkey = OEMvkey;
286 if (TRACE_ON(keyboard))
288 dbg_decl_str(keyboard, 1024);
290 TRACE(keyboard, "OEM specific virtual key %X assigned"
291 "to keycode %X :\n", OEMvkey, e2.keycode);
292 for (i = 0; i < keysyms_per_keycode; i += 1)
294 char *ksname;
296 keysym = TSXLookupKeysym(&e2, i);
297 ksname = TSXKeysymToString(keysym);
298 if (!ksname)
299 ksname = "NoSymbol";
300 dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
302 TRACE(keyboard, "(%s)\n", dbg_str(keyboard));
306 keyc2vkey[e2.keycode] = vkey;
307 } /* for */
308 return TRUE;
311 static BOOL32 NumState=FALSE, CapsState=FALSE;
313 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
314 DWORD event_time, KEYLP localkeylp )
316 BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
318 if (*State) {
319 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
320 don't treat it. It's from the same key press. Then the state goes to ON.
321 And from there, a 'release' event will switch off the toggle key. */
322 *State=FALSE;
323 TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
324 } else
326 if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
328 if (Evtype!=KeyPress)
330 TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
331 localkeylp.lp1.previous = 0; /* ? */
332 localkeylp.lp1.transition = 0;
333 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
334 event_x, event_y, event_time, 0 );
335 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
336 event_x, event_y, event_time, 0 );
337 *State=FALSE;
338 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
341 else /* it was OFF */
342 if (Evtype==KeyPress)
344 TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
345 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
346 event_x, event_y, event_time, 0 );
347 localkeylp.lp1.previous = 1;
348 localkeylp.lp1.transition = 1;
349 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
350 event_x, event_y, event_time, 0 );
351 *State=TRUE; /* Goes to intermediary state before going to ON */
352 InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
357 /***********************************************************************
358 * KEYBOARD_HandleEvent
360 * Handle a X key event
362 void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
364 char Str[24];
365 XComposeStatus cs;
366 KeySym keysym;
367 WORD vkey = 0;
368 KEYLP keylp;
369 static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
371 int ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
373 INT32 event_x = pWnd->rectWindow.left + event->x;
374 INT32 event_y = pWnd->rectWindow.top + event->y;
375 DWORD event_time = event->time - MSG_WineStartTicks;
377 TRACE(key, "EVENT_key : state = %X\n", event->state);
378 if (keysym == XK_Mode_switch)
380 TRACE(key, "Alt Gr key event received\n");
381 event->keycode = TSXKeysymToKeycode(event->display, XK_Control_L);
382 TRACE(key, "Control_L is keycode 0x%x\n", event->keycode);
383 KEYBOARD_HandleEvent( pWnd, event );
384 event->keycode = TSXKeysymToKeycode(event->display, XK_Alt_L);
385 TRACE(key, "Alt_L is keycode 0x%x\n", event->keycode);
386 force_extended = TRUE;
387 KEYBOARD_HandleEvent( pWnd, event );
388 force_extended = FALSE;
389 return;
392 Str[ascii_chars] = '\0';
393 if (TRACE_ON(key)){
394 char *ksname;
396 ksname = TSXKeysymToString(keysym);
397 if (!ksname)
398 ksname = "No Name";
399 TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
400 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
401 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
404 vkey = EVENT_event_to_vkey(event);
405 if (force_extended) vkey |= 0x100;
407 TRACE(key, "keycode 0x%x converted to vkey 0x%x\n",
408 event->keycode, vkey);
410 if (vkey)
412 keylp.lp1.count = 1;
413 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
414 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
415 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
416 * don't remember where I read it - AK */
417 /* it's '1' under windows, when a dialog box appears
418 * and you press one of the underlined keys - DF*/
419 vkey &= 0xff;
421 switch(vkey)
423 case VK_NUMLOCK:
424 KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
425 event_time, keylp);
426 break;
427 case VK_CAPITAL:
428 TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
429 KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
430 event_time, keylp );
431 TRACE(keyboard,"State after : %#.2x\n",InputKeyStateTable[vkey]);
432 break;
433 default:
435 WORD message;
436 if (event->type == KeyPress)
438 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
439 if (!(InputKeyStateTable[vkey] & 0x80))
440 InputKeyStateTable[vkey] ^= 0x01;
441 InputKeyStateTable[vkey] |= 0x80;
442 keylp.lp1.transition = 0;
443 message = (InputKeyStateTable[VK_MENU] & 0x80)
444 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
445 ? WM_SYSKEYDOWN : WM_KEYDOWN;
447 else
449 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
450 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
451 && (force_extended == FALSE); /* for Alt from AltGr */
453 InputKeyStateTable[vkey] &= ~0x80;
454 keylp.lp1.previous = 1;
455 keylp.lp1.transition = 1;
456 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
458 keylp.lp1.context = ( (event->state & Mod1Mask) ||
459 (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
460 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
462 TRACE(keyboard,"Adjusting NumLock state. \n");
463 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
464 event_time, keylp );
465 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
466 event_time, keylp );
468 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
470 TRACE(keyboard,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
471 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
472 event_time, keylp );
473 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
474 event_time, keylp );
475 TRACE(keyboard,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
477 /* End of intermediary states. */
478 NumState = FALSE;
479 CapsState = FALSE;
481 TRACE(key," wParam=%04X, lParam=%08lX\n",
482 vkey, keylp.lp2 );
483 TRACE(key," InputKeyState=%X\n",
484 InputKeyStateTable[vkey]);
486 hardware_event( message, vkey, keylp.lp2,
487 event_x, event_y, event_time, 0 );
494 /**********************************************************************
495 * GetKeyState [USER.106]
497 WORD WINAPI GetKeyState16(INT16 vkey)
499 return GetKeyState32(vkey);
502 /**********************************************************************
503 * GetKeyState [USER32.248]
504 * An application calls the GetKeyState function in response to a
505 * keyboard-input message. This function retrieves the state of the key
506 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
508 WORD WINAPI GetKeyState32(INT32 vkey)
510 INT32 retval;
512 switch (vkey)
514 case VK_LBUTTON : /* VK_LBUTTON is 1 */
515 retval = MouseButtonsStates[0] ? 0x8000 : 0;
516 break;
517 case VK_MBUTTON : /* VK_MBUTTON is 4 */
518 retval = MouseButtonsStates[1] ? 0x8000 : 0;
519 break;
520 case VK_RBUTTON : /* VK_RBUTTON is 2 */
521 retval = MouseButtonsStates[2] ? 0x8000 : 0;
522 break;
523 default :
524 if (vkey >= 'a' && vkey <= 'z')
525 vkey += 'A' - 'a';
526 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
527 (WORD)(QueueKeyStateTable[vkey] & 0x01);
529 TRACE(key, "(0x%x) -> %x\n", vkey, retval);
530 return retval;
533 /**********************************************************************
534 * GetKeyboardState [USER.222][USER32.253]
535 * An application calls the GetKeyboardState function in response to a
536 * keyboard-input message. This function retrieves the state of the keyboard
537 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
539 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
541 TRACE(key, "(%p)\n", lpKeyState);
542 if (lpKeyState != NULL) {
543 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
544 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
545 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
546 memcpy(lpKeyState, QueueKeyStateTable, 256);
550 /**********************************************************************
551 * SetKeyboardState [USER.223][USER32.483]
553 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
555 TRACE(key, "(%p)\n", lpKeyState);
556 if (lpKeyState != NULL) {
557 memcpy(QueueKeyStateTable, lpKeyState, 256);
558 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
559 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
560 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
564 /**********************************************************************
565 * GetAsyncKeyState (USER32.206)
567 * Determine if a key is or was pressed. retval has high-order
568 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
569 * been pressed.
571 * This uses the variable AsyncMouseButtonsStates and
572 * AsyncKeyStateTable (set in event.c) which have the mouse button
573 * number or key number (whichever is applicable) set to true if the
574 * mouse or key had been depressed since the last call to
575 * GetAsyncKeyState.
577 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
579 short retval;
581 switch (nKey) {
582 case VK_LBUTTON:
583 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
584 (MouseButtonsStates[0] ? 0x8000 : 0);
585 break;
586 case VK_MBUTTON:
587 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
588 (MouseButtonsStates[1] ? 0x8000 : 0);
589 break;
590 case VK_RBUTTON:
591 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
592 (MouseButtonsStates[2] ? 0x8000 : 0);
593 break;
594 default:
595 retval = AsyncKeyStateTable[nKey] |
596 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
597 break;
600 /* all states to false */
601 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
602 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
604 TRACE(key, "(%x) -> %x\n", nKey, retval);
605 return retval;
608 /**********************************************************************
609 * GetAsyncKeyState (USER.249)
611 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
613 return GetAsyncKeyState32(nKey);
616 /**********************************************************************
617 * TranslateAccelerator [USER.178][USER32.551..]
619 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
621 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
622 BYTE fVirt,WORD key,WORD cmd)
624 BOOL32 sendmsg = FALSE;
626 if(msg->wParam == key)
628 if (msg->message == WM_CHAR) {
629 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
631 TRACE(accel,"found accel for WM_CHAR: ('%c')\n",
632 msg->wParam&0xff);
633 sendmsg=TRUE;
635 } else {
636 if(fVirt & FVIRTKEY) {
637 INT32 mask = 0;
638 TRACE(accel,"found accel for virt_key %04x (scan %04x)\n",
639 msg->wParam,0xff & HIWORD(msg->lParam));
640 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
641 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
642 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
643 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
644 sendmsg=TRUE;
645 else
646 TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n");
648 else
650 if (!(msg->lParam & 0x01000000)) /* no special_key */
652 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
653 { /* ^^ ALT pressed */
654 TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff);
655 sendmsg=TRUE;
661 if (sendmsg) /* found an accelerator, but send a message... ? */
663 INT16 iSysStat,iStat,mesg=0;
664 HMENU16 hMenu;
666 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
667 mesg=1;
668 else
669 if (GetCapture32())
670 mesg=2;
671 else
672 if (!IsWindowEnabled32(hWnd))
673 mesg=3;
674 else
676 WND* wndPtr = WIN_FindWndPtr(hWnd);
678 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
679 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
680 cmd, MF_BYCOMMAND) : -1 ;
681 iStat = (hMenu) ? GetMenuState32(hMenu,
682 cmd, MF_BYCOMMAND) : -1 ;
684 if (iSysStat!=-1)
686 if (iSysStat & (MF_DISABLED|MF_GRAYED))
687 mesg=4;
688 else
689 mesg=WM_SYSCOMMAND;
691 else
693 if (iStat!=-1)
695 if (IsIconic32(hWnd))
696 mesg=5;
697 else
699 if (iStat & (MF_DISABLED|MF_GRAYED))
700 mesg=6;
701 else
702 mesg=WM_COMMAND;
705 else
706 mesg=WM_COMMAND;
709 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
711 TRACE(accel,", sending %s, wParam=%0x\n",
712 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
713 cmd);
714 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
716 else
718 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
719 * #0: unknown (please report!)
720 * #1: for WM_KEYUP,WM_SYSKEYUP
721 * #2: mouse is captured
722 * #3: window is disabled
723 * #4: it's a disabled system menu option
724 * #5: it's a menu option, but window is iconic
725 * #6: it's a menu option, but disabled
727 TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
728 if(mesg==0)
729 ERR(accel, " unknown reason - please report!");
731 return TRUE;
734 return FALSE;
737 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
739 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
740 int i;
742 if (hAccel == 0 || msg == NULL ||
743 (msg->message != WM_KEYDOWN &&
744 msg->message != WM_KEYUP &&
745 msg->message != WM_SYSKEYDOWN &&
746 msg->message != WM_SYSKEYUP &&
747 msg->message != WM_CHAR)) {
748 WARN(accel, "erraneous input parameters\n");
749 SetLastError(ERROR_INVALID_PARAMETER);
750 return 0;
753 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,"
754 "msg->hwnd=%04x, msg->message=%04x\n",
755 hAccel,hWnd,msg->hwnd,msg->message);
757 for (i = 0; lpAccelTbl[i].key ; i++)
758 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
759 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
760 return 1;
761 WARN(accel, "couldn't translate accelerator key");
762 return 0;
765 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
767 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
768 int i;
769 MSG32 msg32;
771 if (hAccel == 0 || msg == NULL ||
772 (msg->message != WM_KEYDOWN &&
773 msg->message != WM_KEYUP &&
774 msg->message != WM_SYSKEYDOWN &&
775 msg->message != WM_SYSKEYUP &&
776 msg->message != WM_CHAR)) {
777 WARN(accel, "erraneous input parameters\n");
778 SetLastError(ERROR_INVALID_PARAMETER);
779 return 0;
782 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
783 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
784 STRUCT32_MSG16to32(msg,&msg32);
787 for (i=0;lpAccelTbl[i].key;i++)
788 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
789 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
790 return 1;
791 WARN(accel, "couldn't translate accelerator key");
792 return 0;
796 /******************************************************************************
797 * OemKeyScan [KEYBOARD.128][USER32.400]
799 DWORD WINAPI OemKeyScan(WORD wOemChar)
801 TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar);
803 return wOemChar;
806 /******************************************************************************
807 * VkKeyScanA [USER32.572]
809 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
810 * for the current keyboard.
811 * high-order byte yields :
812 * 0 Unshifted
813 * 1 Shift
814 * 2 Ctrl
815 * 3-5 Shift-key combinations that are not used for characters
816 * 6 Ctrl-Alt
817 * 7 Ctrl-Alt-Shift
818 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
819 * FIXME : works ok except for dead chars :
820 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
821 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
824 WORD WINAPI VkKeyScan32A(CHAR cChar)
826 KeyCode keycode;
827 KeySym keysym;
828 int i,index;
829 int highbyte=0;
831 /* char->keysym (same for ANSI chars) */
832 keysym=(unsigned char) cChar;/* (!) cChar is signed */
833 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
835 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
836 if (!keycode)
837 { /* It didn't work ... let's try with deadchar code. */
838 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
841 TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
842 cChar,keysym,keysym,keycode);
844 if (keycode)
846 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
847 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
848 switch (index) {
849 case -1 :
850 fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
851 case 0 : break;
852 case 1 : highbyte = 0x0100; break;
853 case 2 : highbyte = 0X0600; break;
854 default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
857 index : 0 adds 0x0000
858 index : 1 adds 0x0100 (shift)
859 index : ? adds 0x0200 (ctrl)
860 index : 2 adds 0x0600 (ctrl+alt)
861 index : ? adds 0x0700 (ctrl+alt+shift (used?))
864 TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
865 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
868 /******************************************************************************
869 * VkKeyScan [KEYBOARD.129]
871 WORD WINAPI VkKeyScan16(CHAR cChar)
873 return VkKeyScan32A(cChar);
876 /******************************************************************************
877 * VkKeyScanW [USER32.575]
879 WORD WINAPI VkKeyScan32W(WCHAR cChar)
881 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
884 /******************************************************************************
885 * GetKeyboardType [KEYBOARD.130]
887 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
889 return GetKeyboardType32(nTypeFlag);
892 /******************************************************************************
893 * GetKeyboardType [USER32.254]
895 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
897 TRACE(keyboard,"(%d)\n",nTypeFlag);
898 switch(nTypeFlag)
900 case 0: /* Keyboard type */
901 return 4; /* AT-101 */
902 break;
903 case 1: /* Keyboard Subtype */
904 return 0; /* There are no defined subtypes */
905 break;
906 case 2: /* Number of F-keys */
907 return 12; /* We're doing an 101 for now, so return 12 F-keys */
908 break;
909 default:
910 fprintf(stderr, "Unknown type on GetKeyboardType\n");
911 return 0; /* The book says 0 here, so 0 */
916 /******************************************************************************
917 * MapVirtualKeyA [USER32.382]
919 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
921 return MapVirtualKey16(code,maptype);
924 /******************************************************************************
925 * MapVirtualKeyA [USER32.384]
927 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
929 return MapVirtualKey16(code,maptype);
932 /******************************************************************************
933 * MapVirtualKeyA [KEYBOARD.131]
934 * MapVirtualKey translates keycodes from one format to another
936 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
938 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
940 TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
941 wCode,wMapType);
942 switch(wMapType) {
943 case 0: { /* vkey-code to scan-code */
944 /* let's do vkey -> keycode -> scan */
945 KeyCode keyc;
946 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
947 if ((keyc2vkey[keyc] & 0xFF)== wCode)
948 returnMVK (keyc - 8);
949 return 0; }
951 case 1: /* scan-code to vkey-code */
952 /* let's do scan -> keycode -> vkey */
954 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
956 case 2: { /* vkey-code to unshifted ANSI code */
957 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
958 /* My Windows returns 'A'. */
959 /* let's do vkey -> keycode -> (XLookupString) ansi char */
960 XKeyEvent e;
961 KeySym keysym;
962 char s[2];
963 e.display = display;
964 e.state = 0; /* unshifted */
965 e.keycode = MapVirtualKey16( wCode, 0);
966 if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
967 returnMVK (*s);
969 return 0;
971 default: /* reserved */
972 fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
973 wMapType);
974 return 0;
976 return 0;
980 /****************************************************************************
981 * GetKBCodePage16 (KEYBOARD.132)
983 INT16 WINAPI GetKBCodePage16(void)
985 TRACE(keyboard,"(void)\n");
986 return 850;
990 /****************************************************************************
991 * GetKBCodePage32 (USER32.245)
993 UINT32 WINAPI GetKBCodePage32(void)
995 TRACE(keyboard,"(void)\n");
996 return 850;
1000 /****************************************************************************
1001 * GetKeyNameText32W (USER32.247)
1003 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
1005 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
1006 int res = GetKeyNameText32A(lParam,buf,nSize);
1008 lstrcpynAtoW(lpBuffer,buf,nSize);
1009 HeapFree( GetProcessHeap(), 0, buf );
1010 return res;
1013 /****************************************************************************
1014 * GetKeyNameText32A (USER32.246)
1016 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1018 return GetKeyNameText16(lParam,lpBuffer,nSize);
1021 /****************************************************************************
1022 * GetKeyNameText16 (KEYBOARD.133)
1024 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1026 /* int i; */
1028 TRACE(keyboard,"(%ld,<ptr>,%d)\n",lParam,nSize);
1030 lParam >>= 16;
1031 lParam &= 0xff;
1033 /* for (i = 0 ; i != KeyTableSize ; i++)
1034 if (KeyTable[i].scancode == lParam) {
1035 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1036 return strlen(lpBuffer);
1039 /* FIXME ! GetKeyNameText is still to do...
1041 *lpBuffer = 0;
1042 return 0;
1046 /****************************************************************************
1047 * ToAscii (KEYBOARD.4)
1049 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1050 LPVOID lpChar, UINT16 flags)
1052 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1055 /****************************************************************************
1056 * ToAscii (USER32.545)
1058 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1059 LPWORD lpChar,UINT32 flags )
1061 XKeyEvent e;
1062 KeySym keysym;
1063 static XComposeStatus cs;
1064 INT32 ret;
1065 WORD keyc;
1067 e.display = display;
1068 e.keycode = 0;
1069 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1070 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1071 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1072 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... */
1074 if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12)))
1075 /* it's normal to have 2 shift, control, and alt ! */
1076 TRACE(keyboard,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1077 e.keycode,keyc,virtKey);
1078 e.keycode = keyc;
1081 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1083 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1084 e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1085 if (virtKey==VK_DECIMAL)
1086 e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1088 if (!e.keycode)
1090 fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1091 return virtKey; /* whatever */
1093 e.state = 0;
1094 if (lpKeyState[VK_SHIFT] & 0x80)
1095 e.state |= ShiftMask;
1096 TRACE(keyboard,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1097 if (lpKeyState[VK_CAPITAL] & 0x01)
1098 e.state |= LockMask;
1099 if (lpKeyState[VK_CONTROL] & 0x80)
1100 if (lpKeyState[VK_MENU] & 0x80)
1101 e.state |= AltGrMask;
1102 else
1103 e.state |= ControlMask;
1104 if (lpKeyState[VK_NUMLOCK] & 0x01)
1105 e.state |= NumLockMask;
1106 TRACE(key, "(%04X, %04X) : faked state = %X\n",
1107 virtKey, scanCode, e.state);
1108 ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1109 if (ret == 0)
1111 BYTE dead_char = 0;
1113 ((char*)lpChar)[1] = '\0';
1114 switch (keysym)
1116 /* symbolic ASCII is the same as defined in rfc1345 */
1117 #ifdef XK_dead_tilde
1118 case XK_dead_tilde :
1119 #endif
1120 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1121 dead_char = '~'; /* '? */
1122 break;
1123 #ifdef XK_dead_acute
1124 case XK_dead_acute :
1125 #endif
1126 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1127 dead_char = 0xb4; /* '' */
1128 break;
1129 #ifdef XK_dead_circumflex
1130 case XK_dead_circumflex :
1131 #endif
1132 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1133 dead_char = '^'; /* '> */
1134 break;
1135 #ifdef XK_dead_grave
1136 case XK_dead_grave :
1137 #endif
1138 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1139 dead_char = '`'; /* '! */
1140 break;
1141 #ifdef XK_dead_diaeresis
1142 case XK_dead_diaeresis :
1143 #endif
1144 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1145 dead_char = 0xa8; /* ': */
1146 break;
1147 #ifdef XK_dead_cedilla
1148 case XK_dead_cedilla :
1149 dead_char = 0xb8; /* ', */
1150 break;
1151 #endif
1152 #ifdef XK_dead_macron
1153 case XK_dead_macron :
1154 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1155 break;
1156 #endif
1157 #ifdef XK_dead_breve
1158 case XK_dead_breve :
1159 dead_char = 0xa2; /* '( */
1160 break;
1161 #endif
1162 #ifdef XK_dead_abovedot
1163 case XK_dead_abovedot :
1164 dead_char = 0xff; /* '. */
1165 break;
1166 #endif
1167 #ifdef XK_dead_abovering
1168 case XK_dead_abovering :
1169 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1170 break;
1171 #endif
1172 #ifdef XK_dead_doubleacute
1173 case XK_dead_doubleacute :
1174 dead_char = 0xbd; /* '" */
1175 break;
1176 #endif
1177 #ifdef XK_dead_caron
1178 case XK_dead_caron :
1179 dead_char = 0xb7; /* '< */
1180 break;
1181 #endif
1182 #ifdef XK_dead_ogonek
1183 case XK_dead_ogonek :
1184 dead_char = 0xb2; /* '; */
1185 break;
1186 #endif
1187 /* FIXME: I don't know this three.
1188 case XK_dead_iota :
1189 dead_char = 'i';
1190 break;
1191 case XK_dead_voiced_sound :
1192 dead_char = 'v';
1193 break;
1194 case XK_dead_semivoiced_sound :
1195 dead_char = 's';
1196 break;
1199 if (dead_char)
1201 *(char*)lpChar = dead_char;
1202 ret = -1;
1204 else
1206 char *ksname;
1208 ksname = TSXKeysymToString(keysym);
1209 if (!ksname)
1210 ksname = "No Name";
1211 if ((keysym >> 8) != 0xff)
1213 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1214 keysym, ksname);
1215 fprintf(stderr, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1216 virtKey, scanCode, e.keycode, e.state);
1220 TRACE(key, "ToAscii about to return %d with char %x\n",
1221 ret, *(char*)lpChar);
1222 return ret;
1226 /***********************************************************************
1227 * GetKeyboardLayout (USER32.249)
1229 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1231 fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1232 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1235 /***********************************************************************
1236 * GetKeyboardLayoutList (USER32.250)
1237 * FIXME
1239 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1241 fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1242 if (layouts)
1243 layouts[0] = GetKeyboardLayout(0);
1244 return 1;
1248 /***********************************************************************
1249 * RegisterHotKey (USER32.433)
1251 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1252 fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1253 hwnd,id,modifiers,vk
1255 return TRUE;
1258 /***********************************************************************
1259 * UnregisterHotKey (USER32.565)
1261 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1262 fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);
1263 return TRUE;