2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
14 #include <X11/keysym.h>
16 #include "ts_xresource.h"
18 #include <X11/Xatom.h>
27 #include "debugtools.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, AltGrMask; /* mask in the XKeyEvent state */
38 static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
39 static int min_keycode, max_keycode, keysyms_per_keycode;
40 static int keyc2vkey[256];
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;
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,
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)
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 /**********************************************************************
163 BOOL32 KEYBOARD_Init(void)
167 XModifierKeymap *mmp;
174 TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
175 ksp = TSXGetKeyboardMapping(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 */
180 mmp = TSXGetModifierMapping(display);
181 kcp = mmp->modifiermap;
182 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
186 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
191 for (k = 0; k < keysyms_per_keycode; k += 1)
192 if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
195 TRACE(key, "AltGrMask is %x\n", AltGrMask);
197 else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
199 NumLockMask = 1 << i;
200 TRACE(key, "NumLockMask is %x\n", NumLockMask);
204 TSXFreeModifiermap(mmp);
206 /* Now build two conversion arrays :
207 * keycode -> vkey + extended
208 * vkey + extended -> keycode */
210 e2.display = display;
213 OEMvkey = VK_OEM_7; /* next is available. */
214 for (keyc = min_keycode; keyc <= max_keycode; keyc++)
216 e2.keycode = (KeyCode)keyc;
217 TSXLookupString(&e2, NULL, 0, &keysym, NULL);
219 if (keysym) /* otherwise, keycode not used */
221 if ((keysym >> 8) == 0xFF) /* non-character key */
223 int key = keysym & 0xff;
225 if (key >= 0x08 && key <= 0x1B) /* special key */
226 vkey = special_key[key - 0x08];
227 else if (key >= 0x50 && key <= 0x57) /* cursor key */
228 vkey = cursor_key[key - 0x50];
229 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
230 vkey = misc_key[key - 0x60];
231 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
232 vkey = keypad_key[key - 0x7E];
233 else if (key >= 0xBE && key <= 0xCD) /* function key */
235 vkey = function_key[key - 0xBE];
236 vkey |= 0x100; /* set extended bit */
238 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
239 vkey = modifier_key[key - 0xE1];
240 else if (key == 0xFF) /* DEL key */
242 /* extended must also be set for ALT_R, CTRL_R,
243 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
244 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
245 /* FIXME should we set extended bit for NumLock ? My
246 * Windows does ... DF */
266 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
268 keysym = TSXLookupKeysym(&e2, i);
269 if ((keysym >= VK_0 && keysym <= VK_9)
270 || (keysym >= VK_A && keysym <= VK_Z)
271 || keysym == VK_SPACE)
275 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
277 keysym = TSXLookupKeysym(&e2, i);
280 case ';': vkey = VK_OEM_1; break;
281 case '/': vkey = VK_OEM_2; break;
282 case '`': vkey = VK_OEM_3; break;
283 case '[': vkey = VK_OEM_4; break;
284 case '\\': vkey = VK_OEM_5; break;
285 case ']': vkey = VK_OEM_6; break;
286 case '\'': vkey = VK_OEM_7; break;
287 case ',': vkey = VK_OEM_COMMA; break;
288 case '.': vkey = VK_OEM_PERIOD; break;
289 case '-': vkey = VK_OEM_MINUS; break;
290 case '+': vkey = VK_OEM_PLUS; break;
296 /* Others keys: let's assign OEM virtual key codes in the allowed range,
297 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
300 case 0xc1 : OEMvkey=0xdb; break;
301 case 0xe5 : OEMvkey=0xe9; break;
302 case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n");
307 if (TRACE_ON(keyboard))
309 dbg_decl_str(keyboard, 1024);
311 TRACE(keyboard, "OEM specific virtual key %X assigned "
312 "to keycode %X:\n", OEMvkey, e2.keycode);
313 for (i = 0; i < keysyms_per_keycode; i += 1)
317 keysym = TSXLookupKeysym(&e2, i);
318 ksname = TSXKeysymToString(keysym);
321 dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
323 TRACE(keyboard, "(%s)\n", dbg_str(keyboard));
327 keyc2vkey[e2.keycode] = vkey;
329 /* Now store one keycode for each modifier. Used to simulate keypresses. */
330 kcControl = TSXKeysymToKeycode(display, XK_Control_L);
331 kcAlt = TSXKeysymToKeycode(display, XK_Alt_L);
332 kcShift = TSXKeysymToKeycode(display, XK_Shift_L);
333 kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock);
334 kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock);
336 /* all states to false */
337 memset( InputKeyStateTable, 0, sizeof(InputKeyStateTable) );
342 static BOOL32 NumState=FALSE, CapsState=FALSE;
344 /**********************************************************************
345 * KEYBOARD_GenerateMsg
347 * Generate Down+Up messages when NumLock or CapsLock is pressed.
349 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
352 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
353 DWORD event_time, KEYLP localkeylp )
355 BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
358 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
359 don't treat it. It's from the same key press. Then the state goes to ON.
360 And from there, a 'release' event will switch off the toggle key. */
362 TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
365 if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
367 if (Evtype!=KeyPress)
369 TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
370 localkeylp.lp1.previous = 0; /* ? */
371 localkeylp.lp1.transition = 0;
372 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
373 event_x, event_y, event_time, 0 );
374 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
375 event_x, event_y, event_time, 0 );
377 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
380 else /* it was OFF */
381 if (Evtype==KeyPress)
383 TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
384 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
385 event_x, event_y, event_time, 0 );
386 localkeylp.lp1.previous = 1;
387 localkeylp.lp1.transition = 1;
388 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
389 event_x, event_y, event_time, 0 );
390 *State=TRUE; /* Goes to intermediary state before going to ON */
391 InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
396 /***********************************************************************
397 * KEYBOARD_UpdateOneState
399 * Updates internal state for <vkey>, depending on key <state> under X
402 void KEYBOARD_UpdateOneState ( int vkey, int state, KEYLP keylp)
405 /* Do something if internal table state != X state for keycode */
406 if (((InputKeyStateTable[vkey] & 0x80)!=0) != state)
408 TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n",
409 vkey, InputKeyStateTable[vkey]);
410 keylp.lp1.previous = !state; /* 1 if state = 0, 0 if state = 1 */
411 keylp.lp1.transition = !state;
412 if (state) { /* Fake key being pressed inside wine */
413 InputKeyStateTable[vkey] ^= 0x01;
414 InputKeyStateTable[vkey] |= 0x80;
415 message = (InputKeyStateTable[VK_MENU] & 0x80)
416 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
417 ? WM_SYSKEYDOWN : WM_KEYDOWN;
419 InputKeyStateTable[vkey] &= ~0x80;
420 message = (InputKeyStateTable[VK_MENU] & 0x80)
421 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
422 ? WM_SYSKEYUP : WM_KEYUP;
425 hardware_event( message, vkey, keylp.lp2, 0, 0,
426 GetTickCount() + MSG_WineStartTicks, 0 );
428 TRACE(keyboard,"State after %#.2x \n",InputKeyStateTable[vkey]);
432 /***********************************************************************
433 * KEYBOARD_UpdateState
435 * Update modifiers state (Ctrl, Alt, Shift)
436 * when window is activated (called by EVENT_FocusIn in event.c)
438 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
439 * from wine to another application and back.
440 * Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
443 void KEYBOARD_UpdateState ( void )
445 /* extract a bit from the char[32] bit suite */
446 #define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
448 char keys_return[32];
451 TRACE(keyboard,"called\n");
452 if (!XQueryKeymap(display, keys_return)) {
453 ERR(keyboard,"Error getting keymap !");
458 keylp.lp1.extended = 0; /* (vkey & 0x100 ? 1 : 0); */
459 keylp.lp1.win_internal = 0;
460 keylp.lp1.context = KeyState(kcAlt);/*(event->state & Mod1Mask)?1:0*/
462 /* Adjust the ALT and CONTROL state if any has been changed outside wine */
463 KEYBOARD_UpdateOneState(VK_MENU, KeyState(kcAlt), keylp);
464 KEYBOARD_UpdateOneState(VK_CONTROL, KeyState(kcControl), keylp);
465 KEYBOARD_UpdateOneState(VK_SHIFT, KeyState(kcShift), keylp);
470 /***********************************************************************
471 * KEYBOARD_HandleEvent
473 * Handle a X key event
475 void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
482 static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
486 INT32 event_x = pWnd->rectWindow.left + event->x;
487 INT32 event_y = pWnd->rectWindow.top + event->y;
488 DWORD event_time = event->time - MSG_WineStartTicks;
490 /* this allows support for dead keys */
491 if ((event->keycode >> 8) == 0x10)
492 event->keycode=(event->keycode & 0xff);
494 ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
496 TRACE(key, "EVENT_key : state = %X\n", event->state);
497 if (keysym == XK_Mode_switch)
499 TRACE(key, "Alt Gr key event received\n");
500 event->keycode = kcControl; /* Simulate Control */
501 KEYBOARD_HandleEvent( pWnd, event );
503 event->keycode = kcAlt; /* Simulate Alt */
504 force_extended = TRUE;
505 KEYBOARD_HandleEvent( pWnd, event );
506 force_extended = FALSE;
510 Str[ascii_chars] = '\0';
514 ksname = TSXKeysymToString(keysym);
517 TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
518 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
519 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
522 vkey = EVENT_event_to_vkey(event);
523 if (force_extended) vkey |= 0x100;
525 TRACE(key, "keycode 0x%x converted to vkey 0x%x\n",
526 event->keycode, vkey);
531 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
532 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
533 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
534 * don't remember where I read it - AK */
535 /* it's '1' under windows, when a dialog box appears
536 * and you press one of the underlined keys - DF*/
542 KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
546 TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
547 KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
549 TRACE(keyboard,"State after : %#.2x\n",InputKeyStateTable[vkey]);
555 keylp.lp1.context = ( event->state & Mod1Mask ) ? 1 : 0; /* 1 if alt */
556 if (event->type == KeyPress)
558 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
559 if (!(InputKeyStateTable[vkey] & 0x80))
560 InputKeyStateTable[vkey] ^= 0x01;
561 InputKeyStateTable[vkey] |= 0x80;
562 keylp.lp1.transition = 0;
563 message = (InputKeyStateTable[VK_MENU] & 0x80)
564 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
565 ? WM_SYSKEYDOWN : WM_KEYDOWN;
569 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
570 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
571 && (force_extended == FALSE); /* for Alt from AltGr */
573 InputKeyStateTable[vkey] &= ~0x80;
574 keylp.lp1.previous = 1;
575 keylp.lp1.transition = 1;
576 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
578 /* Adjust the NUMLOCK state if it has been changed outside wine */
579 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
581 TRACE(keyboard,"Adjusting NumLock state. \n");
582 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
584 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
587 /* Adjust the CAPSLOCK state if it has been changed outside wine */
588 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
590 TRACE(keyboard,"Adjusting Caps Lock state.\n");
591 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
593 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
596 /* Not Num nor Caps : end of intermediary states for both. */
600 TRACE(key," wParam=%04X, lParam=%08lX\n",
602 TRACE(key," InputKeyState=%X\n",
603 InputKeyStateTable[vkey]);
605 hardware_event( message, vkey, keylp.lp2,
606 event_x, event_y, event_time, 0 );
613 /**********************************************************************
614 * GetKeyState (USER.106)
616 WORD WINAPI GetKeyState16(INT16 vkey)
618 return GetKeyState32(vkey);
621 /**********************************************************************
622 * GetKeyState (USER32.249)
624 * An application calls the GetKeyState function in response to a
625 * keyboard-input message. This function retrieves the state of the key
626 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
628 WORD WINAPI GetKeyState32(INT32 vkey)
634 case VK_LBUTTON : /* VK_LBUTTON is 1 */
635 retval = MouseButtonsStates[0] ? 0x8000 : 0;
637 case VK_MBUTTON : /* VK_MBUTTON is 4 */
638 retval = MouseButtonsStates[1] ? 0x8000 : 0;
640 case VK_RBUTTON : /* VK_RBUTTON is 2 */
641 retval = MouseButtonsStates[2] ? 0x8000 : 0;
644 if (vkey >= 'a' && vkey <= 'z')
646 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
647 (WORD)(QueueKeyStateTable[vkey] & 0x01);
649 TRACE(key, "(0x%x) -> %x\n", vkey, retval);
653 /**********************************************************************
654 * GetKeyboardState (USER.222)(USER32.254)
656 * An application calls the GetKeyboardState function in response to a
657 * keyboard-input message. This function retrieves the state of the keyboard
658 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
660 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
662 TRACE(key, "(%p)\n", lpKeyState);
663 if (lpKeyState != NULL) {
664 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
665 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
666 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
667 memcpy(lpKeyState, QueueKeyStateTable, 256);
671 /**********************************************************************
672 * SetKeyboardState (USER.223)(USER32.484)
674 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
676 TRACE(key, "(%p)\n", lpKeyState);
677 if (lpKeyState != NULL) {
678 memcpy(QueueKeyStateTable, lpKeyState, 256);
679 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
680 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
681 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
685 /**********************************************************************
686 * GetAsyncKeyState32 (USER32.207)
688 * Determine if a key is or was pressed. retval has high-order
689 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
692 * This uses the variable AsyncMouseButtonsStates and
693 * AsyncKeyStateTable (set in event.c) which have the mouse button
694 * number or key number (whichever is applicable) set to true if the
695 * mouse or key had been depressed since the last call to
698 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
704 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
705 (MouseButtonsStates[0] ? 0x8000 : 0);
708 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
709 (MouseButtonsStates[1] ? 0x8000 : 0);
712 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
713 (MouseButtonsStates[2] ? 0x8000 : 0);
716 retval = AsyncKeyStateTable[nKey] |
717 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
721 /* all states to false */
722 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
723 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
725 TRACE(key, "(%x) -> %x\n", nKey, retval);
729 /**********************************************************************
730 * GetAsyncKeyState16 (USER.249)
732 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
734 return GetAsyncKeyState32(nKey);
737 /**********************************************************************
738 * KBD_translate_accelerator
740 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
742 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
743 BYTE fVirt,WORD key,WORD cmd)
745 BOOL32 sendmsg = FALSE;
747 if(msg->wParam == key)
749 if (msg->message == WM_CHAR) {
750 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
752 TRACE(accel,"found accel for WM_CHAR: ('%c')\n",
757 if(fVirt & FVIRTKEY) {
759 TRACE(accel,"found accel for virt_key %04x (scan %04x)\n",
760 msg->wParam,0xff & HIWORD(msg->lParam));
761 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
762 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
763 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
764 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
767 TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n");
771 if (!(msg->lParam & 0x01000000)) /* no special_key */
773 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
774 { /* ^^ ALT pressed */
775 TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff);
782 if (sendmsg) /* found an accelerator, but send a message... ? */
784 INT16 iSysStat,iStat,mesg=0;
787 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
793 if (!IsWindowEnabled32(hWnd))
797 WND* wndPtr = WIN_FindWndPtr(hWnd);
799 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
800 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
801 cmd, MF_BYCOMMAND) : -1 ;
802 iStat = (hMenu) ? GetMenuState32(hMenu,
803 cmd, MF_BYCOMMAND) : -1 ;
807 if (iSysStat & (MF_DISABLED|MF_GRAYED))
816 if (IsIconic32(hWnd))
820 if (iStat & (MF_DISABLED|MF_GRAYED))
830 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
832 TRACE(accel,", sending %s, wParam=%0x\n",
833 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
835 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
839 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
840 * #0: unknown (please report!)
841 * #1: for WM_KEYUP,WM_SYSKEYUP
842 * #2: mouse is captured
843 * #3: window is disabled
844 * #4: it's a disabled system menu option
845 * #5: it's a menu option, but window is iconic
846 * #6: it's a menu option, but disabled
848 TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
850 ERR(accel, " unknown reason - please report!");
858 /**********************************************************************
859 * TranslateAccelerator32 (USER32.551)(USER32.552)(USER32.553)
861 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
863 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
866 TRACE(accel,"hwnd=0x%x hacc=0x%x msg=0x%x wp=0x%x lp=0x%lx\n", hWnd, hAccel, msg->message, msg->wParam, msg->lParam);
868 if (hAccel == 0 || msg == NULL ||
869 (msg->message != WM_KEYDOWN &&
870 msg->message != WM_KEYUP &&
871 msg->message != WM_SYSKEYDOWN &&
872 msg->message != WM_SYSKEYUP &&
873 msg->message != WM_CHAR)) {
874 WARN(accel, "erraneous input parameters\n");
875 SetLastError(ERROR_INVALID_PARAMETER);
879 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,"
880 "msg->hwnd=%04x, msg->message=%04x\n",
881 hAccel,hWnd,msg->hwnd,msg->message);
886 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
887 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
889 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
890 WARN(accel, "couldn't translate accelerator key");
894 /**********************************************************************
895 * TranslateAccelerator16 (USER.178)
897 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
899 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
903 if (hAccel == 0 || msg == NULL ||
904 (msg->message != WM_KEYDOWN &&
905 msg->message != WM_KEYUP &&
906 msg->message != WM_SYSKEYDOWN &&
907 msg->message != WM_SYSKEYUP &&
908 msg->message != WM_CHAR)) {
909 WARN(accel, "erraneous input parameters\n");
910 SetLastError(ERROR_INVALID_PARAMETER);
914 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
915 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
916 STRUCT32_MSG16to32(msg,&msg32);
922 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
923 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
925 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
926 WARN(accel, "couldn't translate accelerator key");
931 /**********************************************************************
932 * ScreenSwitchEnable (KEYBOARD.100)
934 VOID WINAPI ScreenSwitchEnable(WORD unused)
936 FIXME(keyboard,"(%04x): stub\n",unused);
939 /**********************************************************************
940 * OemKeyScan (KEYBOARD.128)(USER32.401)
942 DWORD WINAPI OemKeyScan(WORD wOemChar)
944 TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar);
949 /**********************************************************************
950 * VkKeyScanA (USER32.573)
952 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
953 * for the current keyboard.
954 * high-order byte yields :
958 * 3-5 Shift-key combinations that are not used for characters
961 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
962 * FIXME : works ok except for dead chars :
963 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
964 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
967 WORD WINAPI VkKeyScan32A(CHAR cChar)
974 /* char->keysym (same for ANSI chars) */
975 keysym=(unsigned char) cChar;/* (!) cChar is signed */
976 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
978 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
980 { /* It didn't work ... let's try with deadchar code. */
981 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
984 TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
985 cChar,keysym,keysym,keycode);
989 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
990 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
993 WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
995 case 1 : highbyte = 0x0100; break;
996 case 2 : highbyte = 0X0600; break;
997 default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index);
1000 index : 0 adds 0x0000
1001 index : 1 adds 0x0100 (shift)
1002 index : ? adds 0x0200 (ctrl)
1003 index : 2 adds 0x0600 (ctrl+alt)
1004 index : ? adds 0x0700 (ctrl+alt+shift (used?))
1007 TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
1008 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
1011 /******************************************************************************
1012 * VkKeyScan [KEYBOARD.129]
1014 WORD WINAPI VkKeyScan16(CHAR cChar)
1016 return VkKeyScan32A(cChar);
1019 /******************************************************************************
1020 * VkKeyScanW (USER32.576)
1022 WORD WINAPI VkKeyScan32W(WCHAR cChar)
1024 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
1027 /******************************************************************************
1028 * GetKeyboardType16 (KEYBOARD.130)
1030 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
1032 return GetKeyboardType32(nTypeFlag);
1035 /******************************************************************************
1036 * GetKeyboardType32 (USER32.255)
1038 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
1040 TRACE(keyboard,"(%d)\n",nTypeFlag);
1043 case 0: /* Keyboard type */
1044 return 4; /* AT-101 */
1046 case 1: /* Keyboard Subtype */
1047 return 0; /* There are no defined subtypes */
1049 case 2: /* Number of F-keys */
1050 return 12; /* We're doing an 101 for now, so return 12 F-keys */
1053 WARN(keyboard, "Unknown type\n");
1054 return 0; /* The book says 0 here, so 0 */
1059 /******************************************************************************
1060 * MapVirtualKey32A (USER32.383)
1062 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
1064 return MapVirtualKey16(code,maptype);
1067 /******************************************************************************
1068 * MapVirtualKey32W (USER32.385)
1070 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
1072 return MapVirtualKey16(code,maptype);
1075 /******************************************************************************
1076 * MapVirtualKey16 (KEYBOARD.131)
1078 * MapVirtualKey translates keycodes from one format to another
1080 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
1082 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
1084 TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
1087 case 0: { /* vkey-code to scan-code */
1088 /* let's do vkey -> keycode -> scan */
1090 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
1091 if ((keyc2vkey[keyc] & 0xFF)== wCode)
1092 returnMVK (keyc - 8);
1095 case 1: /* scan-code to vkey-code */
1096 /* let's do scan -> keycode -> vkey */
1098 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
1100 case 2: { /* vkey-code to unshifted ANSI code */
1101 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
1102 /* My Windows returns 'A'. */
1103 /* let's do vkey -> keycode -> (XLookupString) ansi char */
1107 e.display = display;
1108 e.state = 0; /* unshifted */
1109 e.keycode = MapVirtualKey16( wCode, 0);
1110 if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
1115 default: /* reserved */
1116 WARN(keyboard, "Unknown wMapType %d !\n",
1124 /****************************************************************************
1125 * GetKBCodePage16 (KEYBOARD.132)
1127 INT16 WINAPI GetKBCodePage16(void)
1129 TRACE(keyboard,"(void)\n");
1134 /****************************************************************************
1135 * GetKBCodePage32 (USER32.246)
1137 UINT32 WINAPI GetKBCodePage32(void)
1139 TRACE(keyboard,"(void)\n");
1143 /****************************************************************************
1144 * GetKeyboardLayoutName32A (USER32.252)
1146 INT32 WINAPI GetKeyboardLayoutName32A(LPSTR pwszKLID)
1148 return GetKeyboardLayoutName16(pwszKLID);
1151 /****************************************************************************
1152 * GetKeyboardLayoutName32W (USER32.253)
1154 INT32 WINAPI GetKeyboardLayoutName32W(LPWSTR pwszKLID)
1156 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1);
1157 int res = GetKeyboardLayoutName32A(buf);
1158 lstrcpyAtoW(pwszKLID,buf);
1159 HeapFree( GetProcessHeap(), 0, buf );
1163 /****************************************************************************
1164 * GetKeyboardLayoutName16 (USER.477)
1166 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
1168 FIXME(keyboard,"always returns primary U.S. English layout\n");
1169 strcpy(pwszKLID,"00000409");
1173 /****************************************************************************
1174 * GetKeyNameText32A (USER32.247)
1176 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1178 return GetKeyNameText16(lParam,lpBuffer,nSize);
1181 /****************************************************************************
1182 * GetKeyNameText32W (USER32.248)
1184 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
1186 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
1187 int res = GetKeyNameText32A(lParam,buf,nSize);
1189 lstrcpynAtoW(lpBuffer,buf,nSize);
1190 HeapFree( GetProcessHeap(), 0, buf );
1195 /****************************************************************************
1196 * GetKeyNameText16 (KEYBOARD.133)
1198 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1202 TRACE(keyboard,"(%ld,<ptr>,%d)\n",lParam,nSize);
1207 /* for (i = 0 ; i != KeyTableSize ; i++)
1208 if (KeyTable[i].scancode == lParam) {
1209 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1210 return strlen(lpBuffer);
1213 /* FIXME ! GetKeyNameText is still to do...
1220 /****************************************************************************
1221 * ToAscii (KEYBOARD.4)
1223 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1224 LPVOID lpChar, UINT16 flags)
1226 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1229 /****************************************************************************
1230 * ToAscii32 (USER32.546)
1232 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1233 LPWORD lpChar,UINT32 flags )
1237 static XComposeStatus cs;
1242 /* This happens when doing Alt+letter : a fake 'down arrow' key press
1243 event is generated by windows. Just ignore it. */
1244 TRACE(keyboard,"scanCode=0, doing nothing\n");
1247 e.display = display;
1250 if (lpKeyState[VK_SHIFT] & 0x80)
1251 e.state |= ShiftMask;
1252 if (lpKeyState[VK_CAPITAL] & 0x01)
1253 e.state |= LockMask;
1254 if (lpKeyState[VK_CONTROL] & 0x80)
1255 if (lpKeyState[VK_MENU] & 0x80)
1256 e.state |= AltGrMask;
1258 e.state |= ControlMask;
1259 if (lpKeyState[VK_NUMLOCK] & 0x01)
1260 e.state |= NumLockMask;
1261 TRACE(key, "(%04X, %04X) : faked state = %X\n",
1262 virtKey, scanCode, e.state);
1263 /* We exit on the first keycode found, to speed up the thing. */
1264 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1265 { /* Find a keycode that could have generated this virtual key */
1266 if ((keyc2vkey[keyc] & 0xFF) == virtKey)
1267 { /* we can filter the extended bit, VK* are different enough... */
1268 e.keycode = keyc; /* Store it temporarily */
1269 if (EVENT_event_to_vkey(&e) != virtKey)
1270 e.keycode = 0; /* Wrong one (ex: because of the NumLock
1271 state), so set it to 0, we'll find another one */
1274 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1276 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1277 e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1278 if (virtKey==VK_DECIMAL)
1279 e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1283 WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey);
1284 return virtKey; /* whatever */
1286 ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1291 ((char*)lpChar)[1] = '\0';
1294 /* symbolic ASCII is the same as defined in rfc1345 */
1295 #ifdef XK_dead_tilde
1296 case XK_dead_tilde :
1298 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1299 dead_char = '~'; /* '? */
1301 #ifdef XK_dead_acute
1302 case XK_dead_acute :
1304 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1305 dead_char = 0xb4; /* '' */
1307 #ifdef XK_dead_circumflex
1308 case XK_dead_circumflex :
1310 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1311 dead_char = '^'; /* '> */
1313 #ifdef XK_dead_grave
1314 case XK_dead_grave :
1316 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1317 dead_char = '`'; /* '! */
1319 #ifdef XK_dead_diaeresis
1320 case XK_dead_diaeresis :
1322 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1323 dead_char = 0xa8; /* ': */
1325 #ifdef XK_dead_cedilla
1326 case XK_dead_cedilla :
1327 dead_char = 0xb8; /* ', */
1330 #ifdef XK_dead_macron
1331 case XK_dead_macron :
1332 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1335 #ifdef XK_dead_breve
1336 case XK_dead_breve :
1337 dead_char = 0xa2; /* '( */
1340 #ifdef XK_dead_abovedot
1341 case XK_dead_abovedot :
1342 dead_char = 0xff; /* '. */
1345 #ifdef XK_dead_abovering
1346 case XK_dead_abovering :
1347 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1350 #ifdef XK_dead_doubleacute
1351 case XK_dead_doubleacute :
1352 dead_char = 0xbd; /* '" */
1355 #ifdef XK_dead_caron
1356 case XK_dead_caron :
1357 dead_char = 0xb7; /* '< */
1360 #ifdef XK_dead_ogonek
1361 case XK_dead_ogonek :
1362 dead_char = 0xb2; /* '; */
1365 /* FIXME: I don't know this three.
1369 case XK_dead_voiced_sound :
1372 case XK_dead_semivoiced_sound :
1379 *(char*)lpChar = dead_char;
1386 ksname = TSXKeysymToString(keysym);
1389 if ((keysym >> 8) != 0xff)
1391 ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n",
1393 ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1394 virtKey, scanCode, e.keycode, e.state);
1398 TRACE(key, "ToAscii about to return %d with char %x\n",
1399 ret, *(char*)lpChar);
1404 /***********************************************************************
1405 * GetKeyboardLayout (USER32.250)
1407 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1409 FIXME(keyboard,"(%ld): stub\n",dwLayout);
1410 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1413 /***********************************************************************
1414 * GetKeyboardLayoutList (USER32.251)
1417 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1419 FIXME(keyboard,"(%d,%p): stub\n",nBuff,layouts);
1421 layouts[0] = GetKeyboardLayout(0);
1426 /***********************************************************************
1427 * RegisterHotKey (USER32.433)
1429 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1430 FIXME(keyboard,"(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
1434 /***********************************************************************
1435 * UnregisterHotKey (USER32.565)
1437 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1438 FIXME(keyboard,"(0x%08x,%d): stub\n",hwnd,id);
1442 /***********************************************************************
1443 * KeyboardInquire (KEYBOARD.1)
1447 typedef struct _KBINFO
1449 BYTE Begin_First_Range;
1450 BYTE End_First_Range;
1451 BYTE Begin_Second_Range;
1452 BYTE End_Second_Range;
1457 WORD WINAPI KeyboardInquire(KBINFO *kbInfo)
1459 kbInfo->Begin_First_Range = 0;
1460 kbInfo->End_First_Range = 0;
1461 kbInfo->Begin_Second_Range = 0;
1462 kbInfo->End_Second_Range = 0;
1463 kbInfo->StateSize = 16;
1465 return sizeof(KBINFO);
1468 /***********************************************************************
1469 * KeyboardEnable (KEYBOARD.2)
1471 VOID WINAPI KeyboardEnable(FARPROC16 eventProc, LPBYTE lpKeyState)
1473 FIXME(keyboard, "(%08lx,%08lx): stub\n",
1474 (DWORD)eventProc, (DWORD)lpKeyState);
1477 /***********************************************************************
1478 * KeyboardDisable (KEYBOARD.3)
1480 VOID WINAPI KeyboardDisable(VOID)
1482 FIXME(keyboard, "(): stub\n");
1486 /***********************************************************************
1487 * DisplayInquire (DISPLAY.101)
1491 typedef struct _CURSORINFO
1498 WORD WINAPI DisplayInquire(CURSORINFO *cursorInfo)
1500 cursorInfo->wXMickeys = 1;
1501 cursorInfo->wYMickeys = 1;
1503 return sizeof(CURSORINFO);
1506 /***********************************************************************
1507 * DisplaySetCursor (DISPLAY.102)
1509 VOID WINAPI DisplaySetCursor( LPVOID cursorShape )
1511 FIXME(keyboard, "(%p): stub\n", cursorShape );
1514 /***********************************************************************
1515 * DisplayMoveCursor (DISPLAY.103)
1517 VOID WINAPI DisplayMoveCursor( WORD wAbsX, WORD wAbsY )
1519 FIXME(keyboard, "(%d,%d): stub\n", wAbsX, wAbsY );
1522 /***********************************************************************
1523 * UserRepaintDisable (DISPLAY.103)
1525 VOID WINAPI UserRepaintDisable( BOOL16 disable )
1527 FIXME(keyboard, "(%d): stub\n", disable);