2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
14 #include <X11/keysym.h>
16 #include <X11/Xresource.h>
17 #include <X11/Xutil.h>
18 #include <X11/Xatom.h>
27 /* #define DEBUG_KEYBOARD */
32 BOOL32 MouseButtonsStates[3];
33 BOOL32 AsyncMouseButtonsStates[3];
34 BYTE InputKeyStateTable[256];
35 BYTE QueueKeyStateTable[256];
36 BYTE AsyncKeyStateTable[256];
38 static int NumLockMask;
40 static int min_keycode, max_keycode;
41 static int keyc2vkey[256];
47 unsigned long count : 16;
48 unsigned long code : 8;
49 unsigned long extended : 1;
50 unsigned long unused : 2;
51 unsigned long win_internal : 2;
52 unsigned long context : 1;
53 unsigned long previous : 1;
54 unsigned long transition : 1;
59 /* Keyboard translation tables */
60 static const int special_key[] =
62 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
63 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
64 0, 0, 0, VK_ESCAPE /* FF18 */
67 static const int cursor_key[] =
69 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
70 VK_NEXT, VK_END /* FF50 */
73 static const int misc_key[] =
75 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
76 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
79 static const int keypad_key[] =
81 0, VK_NUMLOCK, /* FF7E */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
83 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
84 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
85 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
86 VK_INSERT, VK_DELETE, /* FF98 */
87 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
88 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
89 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
90 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
91 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
92 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
95 static const int function_key[] =
97 VK_F1, VK_F2, /* FFBE */
98 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
99 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
102 static const int modifier_key[] =
104 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
105 VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
109 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
111 static const BYTE vkey2scode[512] = {
112 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
113 0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
114 0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
115 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
116 0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
117 0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
118 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
119 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
124 0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x28,0x33,0x34,0x35,0x4c,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
127 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
129 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
130 0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
131 0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
132 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,
136 0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,0x00,0x00,0x00,0x00,
137 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
144 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
147 static WORD EVENT_event_to_vkey( XKeyEvent *e)
151 XLookupString(e, NULL, 0, &keysym, NULL);
153 if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask))
154 /* Only the Keypad keys 0-9 and . send different keysyms
155 * depending on the NumLock state */
156 return keypad_key[(keysym & 0xFF) - 0x7E];
158 return keyc2vkey[e->keycode];
161 /**********************************************************************
164 BOOL32 KEYBOARD_Init(void)
166 int i, keysyms_per_keycode;
168 XModifierKeymap *mmp;
174 XDisplayKeycodes(display, &min_keycode, &max_keycode);
175 ksp = XGetKeyboardMapping(display, min_keycode,
176 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
177 /* We are only interested in keysyms_per_keycode.
178 There is no need to hold a local copy of the keysyms table */
180 mmp = XGetModifierMapping(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 (XKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
195 dprintf_key(stddeb, "AltGrMask is %x\n", AltGrMask);
197 else if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
199 NumLockMask = 1 << i;
200 dprintf_key(stddeb, "NumLockMask is %x\n", NumLockMask);
204 XFreeModifiermap(mmp);
206 /* Now build two conversion arrays :
207 * keycode -> vkey + extended
208 * vkey + extended -> keycode */
210 e2.display = display;
213 OEMvkey = 0xb9; /* first OEM virtual key available is ba */
214 for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
216 XLookupString(&e2, NULL, 0, &keysym, NULL);
218 if (keysym) /* otherwise, keycode not used */
220 if ((keysym >> 8) == 0xFF) /* non-character key */
222 int key = keysym & 0xff;
224 if (key >= 0x08 && key <= 0x1B) /* special key */
225 vkey = special_key[key - 0x08];
226 else if (key >= 0x50 && key <= 0x57) /* cursor key */
227 vkey = cursor_key[key - 0x50];
228 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
229 vkey = misc_key[key - 0x60];
230 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
231 vkey = keypad_key[key - 0x7E];
232 else if (key >= 0xBE && key <= 0xCD) /* function key */
234 vkey = function_key[key - 0xBE];
235 vkey |= 0x100; /* set extended bit */
237 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
238 vkey = modifier_key[key - 0xE1];
239 else if (key == 0xFF) /* DEL key */
241 /* extended must also be set for ALT_R, CTRL_R,
242 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
243 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
244 /* FIXME should we set extended bit for NumLock ? My
245 * Windows does ... DF */
265 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
267 keysym = XLookupKeysym(&e2, i);
268 if ((keysym >= VK_0 && keysym <= VK_9)
269 || (keysym >= VK_A && keysym <= VK_Z)
270 || keysym == VK_SPACE)
276 /* Others keys: let's assign OEM virtual key codes in the allowed range,
277 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
280 case 0xc1 : OEMvkey=0xdb; break;
281 case 0xe5 : OEMvkey=0xe9; break;
282 case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
287 if (debugging_keyboard)
289 fprintf(stddeb,"OEM specific virtual key %X assigned to keycode %X :\n ("
290 ,OEMvkey,e2.keycode);
291 for (i = 0; i < keysyms_per_keycode; i += 1)
295 keysym = XLookupKeysym(&e2, i);
296 ksname = XKeysymToString(keysym);
299 fprintf(stddeb, "%lX (%s) ", keysym, ksname);
301 fprintf(stddeb, ")\n");
305 keyc2vkey[e2.keycode] = vkey;
310 static BOOL32 NumState=FALSE, CapsState=FALSE;
312 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, XKeyEvent * event, KEYLP localkeylp )
314 BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
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. */
321 dprintf_keyboard(stddeb,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
324 if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
326 if (Evtype!=KeyPress)
328 dprintf_keyboard(stddeb,"ON + KeyRelease => generating DOWN and UP messages.\n");
329 localkeylp.lp1.previous = 0; /* ? */
330 localkeylp.lp1.transition = 0;
331 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2, event->x_root - desktopX,
332 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
333 hardware_event( WM_KEYUP, vkey, localkeylp.lp2, event->x_root - desktopX,
334 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
336 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
339 else /* it was OFF */
340 if (Evtype==KeyPress)
342 dprintf_keyboard(stddeb,"OFF + Keypress => generating DOWN and UP messages.\n");
343 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2, event->x_root - desktopX,
344 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
345 localkeylp.lp1.previous = 1;
346 localkeylp.lp1.transition = 1;
347 hardware_event( WM_KEYUP, vkey, localkeylp.lp2, event->x_root - desktopX,
348 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0);
349 *State=TRUE; /* Goes to intermediary state before going to ON */
350 InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
355 /***********************************************************************
356 * KEYBOARD_HandleEvent
358 * Handle a X key event
360 void KEYBOARD_HandleEvent( XKeyEvent *event )
367 static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
369 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
371 dprintf_key(stddeb, "EVENT_key : state = %X\n", event->state);
372 if (keysym == XK_Mode_switch)
374 dprintf_key(stddeb, "Alt Gr key event received\n");
375 event->keycode = XKeysymToKeycode(event->display, XK_Control_L);
376 dprintf_key(stddeb, "Control_L is keycode 0x%x\n", event->keycode);
377 KEYBOARD_HandleEvent(event);
378 event->keycode = XKeysymToKeycode(event->display, XK_Alt_L);
379 dprintf_key(stddeb, "Alt_L is keycode 0x%x\n", event->keycode);
380 force_extended = TRUE;
381 KEYBOARD_HandleEvent(event);
382 force_extended = FALSE;
386 Str[ascii_chars] = '\0';
391 ksname = XKeysymToString(keysym);
394 fprintf(stddeb, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
395 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
396 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
399 vkey = EVENT_event_to_vkey(event);
400 if (force_extended) vkey |= 0x100;
402 dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
403 event->keycode, vkey);
408 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
409 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
410 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
411 * don't remember where I read it - AK */
412 /* it's '1' under windows, when a dialog box appears
413 * and you press one of the underlined keys - DF*/
419 KEYBOARD_GenerateMsg(VK_NUMLOCK,event->type,event,keylp); break;
421 dprintf_keyboard(stddeb,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
422 KEYBOARD_GenerateMsg(VK_CAPITAL,event->type,event,keylp);
423 dprintf_keyboard(stddeb,"State after : %#.2x\n",InputKeyStateTable[vkey]);
428 if (event->type == KeyPress)
430 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
431 if (!(InputKeyStateTable[vkey] & 0x80))
432 InputKeyStateTable[vkey] ^= 0x01;
433 InputKeyStateTable[vkey] |= 0x80;
434 keylp.lp1.transition = 0;
435 message = (InputKeyStateTable[VK_MENU] & 0x80)
436 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
437 ? WM_SYSKEYDOWN : WM_KEYDOWN;
441 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
442 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
443 && (force_extended == FALSE); /* for Alt from AltGr */
445 InputKeyStateTable[vkey] &= ~0x80;
446 keylp.lp1.previous = 1;
447 keylp.lp1.transition = 1;
448 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
450 keylp.lp1.context = ( (event->state & Mod1Mask) ||
451 (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
452 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
454 dprintf_keyboard(stddeb,"Adjusting NumLock state. \n");
455 KEYBOARD_GenerateMsg(VK_NUMLOCK,KeyPress,event,keylp);
456 KEYBOARD_GenerateMsg(VK_NUMLOCK,KeyRelease,event,keylp);
458 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
460 dprintf_keyboard(stddeb,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
461 KEYBOARD_GenerateMsg(VK_CAPITAL,KeyPress,event,keylp);
462 KEYBOARD_GenerateMsg(VK_CAPITAL,KeyRelease,event,keylp);
463 dprintf_keyboard(stddeb,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
465 /* End of intermediary states. */
469 dprintf_key(stddeb," wParam=%04X, lParam=%08lX\n",
471 dprintf_key(stddeb," InputKeyState=%X\n",
472 InputKeyStateTable[vkey]);
474 hardware_event( message, vkey, keylp.lp2, event->x_root - desktopX,
475 event->y_root - desktopY, event->time - MSG_WineStartTicks, 0 );
482 /**********************************************************************
483 * GetKeyState [USER.106]
485 WORD WINAPI GetKeyState16(INT16 vkey)
487 return GetKeyState32(vkey);
490 /**********************************************************************
491 * GetKeyState [USER32.248]
492 * An application calls the GetKeyState function in response to a
493 * keyboard-input message. This function retrieves the state of the key
494 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
496 WORD WINAPI GetKeyState32(INT32 vkey)
502 case VK_LBUTTON : /* VK_LBUTTON is 1 */
503 retval = MouseButtonsStates[0];
505 case VK_MBUTTON : /* VK_MBUTTON is 4 */
506 retval = MouseButtonsStates[1];
508 case VK_RBUTTON : /* VK_RBUTTON is 2 */
509 retval = MouseButtonsStates[2];
512 if (vkey >= 'a' && vkey <= 'z')
514 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
515 (WORD)(QueueKeyStateTable[vkey] & 0x01);
517 dprintf_key(stddeb, "GetKeyState(0x%x) -> %x\n", vkey, retval);
521 /**********************************************************************
522 * GetKeyboardState [USER.222][USER32.253]
523 * An application calls the GetKeyboardState function in response to a
524 * keyboard-input message. This function retrieves the state of the keyboard
525 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
527 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
529 dprintf_key(stddeb, "GetKeyboardState()\n");
530 if (lpKeyState != NULL) {
531 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
532 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
533 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
534 memcpy(lpKeyState, QueueKeyStateTable, 256);
538 /**********************************************************************
539 * SetKeyboardState [USER.223][USER32.483]
541 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
543 dprintf_key(stddeb, "SetKeyboardState()\n");
544 if (lpKeyState != NULL) {
545 memcpy(QueueKeyStateTable, lpKeyState, 256);
546 MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0;
547 MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0;
548 MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0;
552 /**********************************************************************
553 * GetAsyncKeyState (USER32.206)
555 * Determine if a key is or was pressed. retval has high-order
556 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
559 * This uses the variable AsyncMouseButtonsStates and
560 * AsyncKeyStateTable (set in event.c) which have the mouse button
561 * number or key number (whichever is applicable) set to true if the
562 * mouse or key had been depressed since the last call to
565 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
571 retval = AsyncMouseButtonsStates[0] |
572 MouseButtonsStates[0]? 0x0001: 0;
575 retval = AsyncMouseButtonsStates[1] |
576 MouseButtonsStates[1]? 0x0001: 0;
579 retval = AsyncMouseButtonsStates[2] |
580 MouseButtonsStates[2]? 0x0001: 0;
583 retval = AsyncKeyStateTable[nKey] |
584 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
588 memset( AsyncMouseButtonsStates, 0, 3 ); /* all states to false */
589 memset( AsyncKeyStateTable, 0, 256 );
591 dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
595 /**********************************************************************
596 * GetAsyncKeyState (USER.249)
598 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
600 return GetAsyncKeyState32(nKey);
603 /**********************************************************************
604 * TranslateAccelerator [USER.178][USER32.551..]
606 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
608 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
609 BYTE fVirt,WORD key,WORD cmd)
611 BOOL32 sendmsg = FALSE;
613 if(msg->wParam == key)
615 if (msg->message == WM_CHAR) {
616 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
618 dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff);
622 if(fVirt & FVIRTKEY) {
624 dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
625 msg->wParam,0xff & HIWORD(msg->lParam));
626 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
627 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
628 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
629 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
632 dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n");
636 if (!(msg->lParam & 0x01000000)) /* no special_key */
638 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
639 { /* ^^ ALT pressed */
640 dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff);
647 if (sendmsg) /* found an accelerator, but send a message... ? */
649 INT16 iSysStat,iStat,mesg=0;
652 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
658 if (!IsWindowEnabled32(hWnd))
662 WND* wndPtr = WIN_FindWndPtr(hWnd);
664 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
665 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
666 cmd, MF_BYCOMMAND) : -1 ;
667 iStat = (hMenu) ? GetMenuState32(hMenu,
668 cmd, MF_BYCOMMAND) : -1 ;
672 if (iSysStat & (MF_DISABLED|MF_GRAYED))
681 if (IsIconic32(hWnd))
685 if (iStat & (MF_DISABLED|MF_GRAYED))
695 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
697 dprintf_accel(stddeb,", sending %s, wParam=%0x\n",
698 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
700 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
704 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
705 * #0: unknown (please report!)
706 * #1: for WM_KEYUP,WM_SYSKEYUP
707 * #2: mouse is captured
708 * #3: window is disabled
709 * #4: it's a disabled system menu option
710 * #5: it's a menu option, but window is iconic
711 * #6: it's a menu option, but disabled
713 dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
721 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
723 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
726 if (hAccel == 0 || msg == NULL) return 0;
727 if (msg->message != WM_KEYDOWN &&
728 msg->message != WM_KEYUP &&
729 msg->message != WM_SYSKEYDOWN &&
730 msg->message != WM_SYSKEYUP &&
731 msg->message != WM_CHAR) return 0;
733 dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
734 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
736 for (i = 0; lpAccelTbl[i].key ; i++)
737 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
738 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
743 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
745 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
749 if (hAccel == 0 || msg == NULL) return 0;
750 if (msg->message != WM_KEYDOWN &&
751 msg->message != WM_KEYUP &&
752 msg->message != WM_SYSKEYDOWN &&
753 msg->message != WM_SYSKEYUP &&
754 msg->message != WM_CHAR) return 0;
756 dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
757 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
758 STRUCT32_MSG16to32(msg,&msg32);
761 for (i=0;lpAccelTbl[i].key;i++)
762 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
763 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
769 /******************************************************************************
770 * OemKeyScan [KEYBOARD.128][USER32.400]
772 DWORD WINAPI OemKeyScan(WORD wOemChar)
774 dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
779 /******************************************************************************
780 * VkKeyScanA [USER32.572]
782 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
783 * for the current keyboard.
784 * high-order byte yields :
788 * 3-5 Shift-key combinations that are not used for characters
791 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
792 * FIXME : works ok except for dead chars :
793 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
794 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
797 WORD WINAPI VkKeyScan32A(CHAR cChar)
804 /* char->keysym (same for ANSI chars) */
805 keysym=(unsigned char) cChar;/* (!) cChar is signed */
806 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
808 keycode = XKeysymToKeycode(display, keysym); /* keysym -> keycode */
810 { /* It didn't work ... let's try with deadchar code. */
811 keycode = XKeysymToKeycode(display, keysym | 0xFE00);
814 dprintf_keyboard(stddeb,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
815 cChar,keysym,keysym,keycode);
819 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
820 if (XKeycodeToKeysym(display,keycode,i)==keysym) index=i;
823 fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
825 case 1 : highbyte = 0x0100; break;
826 case 2 : highbyte = 0X0600; break;
827 default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
830 index : 0 adds 0x0000
831 index : 1 adds 0x0100 (shift)
832 index : ? adds 0x0200 (ctrl)
833 index : 2 adds 0x0600 (ctrl+alt)
834 index : ? adds 0x0700 (ctrl+alt+shit (used?))
837 dprintf_keyboard(stddeb," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
838 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
841 /******************************************************************************
842 * VkKeyScan [KEYBOARD.129]
844 WORD WINAPI VkKeyScan16(CHAR cChar)
846 return VkKeyScan32A(cChar);
849 /******************************************************************************
850 * VkKeyScanW [USER32.575]
852 WORD WINAPI VkKeyScan32W(WCHAR cChar)
854 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
857 /******************************************************************************
858 * GetKeyboardType [KEYBOARD.130]
860 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
862 return GetKeyboardType32(nTypeFlag);
865 /******************************************************************************
866 * GetKeyboardType [USER32.254]
868 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
870 dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
873 case 0: /* Keyboard type */
874 return 4; /* AT-101 */
876 case 1: /* Keyboard Subtype */
877 return 0; /* There are no defined subtypes */
879 case 2: /* Number of F-keys */
880 return 12; /* We're doing an 101 for now, so return 12 F-keys */
883 fprintf(stderr, "Unknown type on GetKeyboardType\n");
884 return 0; /* The book says 0 here, so 0 */
889 /******************************************************************************
890 * MapVirtualKeyA [USER32.382]
892 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
894 return MapVirtualKey16(code,maptype);
897 /******************************************************************************
898 * MapVirtualKeyA [USER32.384]
900 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
902 return MapVirtualKey16(code,maptype);
905 /******************************************************************************
906 * MapVirtualKeyA [KEYBOARD.131]
907 * MapVirtualKey translates keycodes from one format to another
909 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
911 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
913 dprintf_keyboard(stddeb,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode,wMapType);
915 case 0: { /* vkey-code to scan-code */
916 /* let's do vkey -> keycode -> scan */
918 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
919 if ((keyc2vkey[keyc] & 0xFF)== wCode)
920 returnMVK (keyc - 8);
923 case 1: /* scan-code to vkey-code */
924 /* let's do scan -> keycode -> vkey */
926 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
928 case 2: { /* vkey-code to unshifted ANSI code */
929 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
930 /* My Windows returns 'A'. */
931 /* let's do vkey -> keycode -> (XLookupString) ansi char */
936 e.state = 0; /* unshifted */
937 e.keycode = MapVirtualKey16( wCode, 0);
938 if (!XLookupString(&e, s , 2 , &keysym, NULL))
943 default: /* reserved */
944 fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
952 /****************************************************************************
953 * GetKBCodePage16 (KEYBOARD.132)
955 INT16 WINAPI GetKBCodePage16(void)
957 dprintf_keyboard(stddeb,"GetKBCodePage()\n");
962 /****************************************************************************
963 * GetKBCodePage32 (USER32.245)
965 UINT32 WINAPI GetKBCodePage32(void)
967 dprintf_keyboard(stddeb,"GetKbCodePage()\n");
972 /****************************************************************************
973 * GetKeyNameText32W (USER32.247)
975 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
977 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
978 int res = GetKeyNameText32A(lParam,buf,nSize);
980 lstrcpynAtoW(lpBuffer,buf,nSize);
981 HeapFree( GetProcessHeap(), 0, buf );
985 /****************************************************************************
986 * GetKeyNameText32A (USER32.246)
988 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
990 return GetKeyNameText16(lParam,lpBuffer,nSize);
993 /****************************************************************************
994 * GetKeyNameText16 (KEYBOARD.133)
996 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1000 dprintf_keyboard(stddeb,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
1005 /* for (i = 0 ; i != KeyTableSize ; i++)
1006 if (KeyTable[i].scancode == lParam) {
1007 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1008 return strlen(lpBuffer);
1011 /* FIXME ! GetKeyNameText is still to do...
1018 /****************************************************************************
1019 * ToAscii (KEYBOARD.4)
1021 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1022 LPVOID lpChar, UINT16 flags)
1024 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1027 /****************************************************************************
1028 * ToAscii (USER32.545)
1030 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1031 LPWORD lpChar,UINT32 flags )
1035 static XComposeStatus cs;
1039 e.display = display;
1041 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1042 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1043 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1044 if ((keyc2vkey[keyc] & 0xFF)== virtKey) /* no need to make a more precise test (with the extended bit correctly set above virtKey ... VK* are different enough... */
1046 if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12)))
1047 /* it's normal to have 2 shift, control, and alt ! */
1048 dprintf_keyboard(stddeb,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1049 e.keycode,keyc,virtKey);
1053 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1055 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1056 e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1057 if (virtKey==VK_DECIMAL)
1058 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1062 fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1063 return virtKey; /* whatever */
1066 if (lpKeyState[VK_SHIFT] & 0x80)
1067 e.state |= ShiftMask;
1068 dprintf_keyboard(stddeb,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1069 if (lpKeyState[VK_CAPITAL] & 0x01)
1070 e.state |= LockMask;
1071 if (lpKeyState[VK_CONTROL] & 0x80)
1072 if (lpKeyState[VK_MENU] & 0x80)
1073 e.state |= AltGrMask;
1075 e.state |= ControlMask;
1076 if (lpKeyState[VK_NUMLOCK] & 0x01)
1077 e.state |= NumLockMask;
1078 dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
1079 virtKey, scanCode, e.state);
1080 ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1085 ((char*)lpChar)[1] = '\0';
1088 /* symbolic ASCII is the same as defined in rfc1345 */
1089 #ifdef XK_dead_tilde
1090 case XK_dead_tilde :
1092 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1093 dead_char = '~'; /* '? */
1095 #ifdef XK_dead_acute
1096 case XK_dead_acute :
1098 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1099 dead_char = 0xb4; /* '' */
1101 #ifdef XK_dead_circumflex
1102 case XK_dead_circumflex :
1104 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1105 dead_char = '^'; /* '> */
1107 #ifdef XK_dead_grave
1108 case XK_dead_grave :
1110 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1111 dead_char = '`'; /* '! */
1113 #ifdef XK_dead_diaeresis
1114 case XK_dead_diaeresis :
1116 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1117 dead_char = 0xa8; /* ': */
1119 #ifdef XK_dead_cedilla
1120 case XK_dead_cedilla :
1121 dead_char = 0xb8; /* ', */
1124 #ifdef XK_dead_macron
1125 case XK_dead_macron :
1126 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1129 #ifdef XK_dead_breve
1130 case XK_dead_breve :
1131 dead_char = 0xa2; /* '( */
1134 #ifdef XK_dead_abovedot
1135 case XK_dead_abovedot :
1136 dead_char = 0xff; /* '. */
1139 #ifdef XK_dead_abovering
1140 case XK_dead_abovering :
1141 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1144 #ifdef XK_dead_doubleacute
1145 case XK_dead_doubleacute :
1146 dead_char = 0xbd; /* '" */
1149 #ifdef XK_dead_caron
1150 case XK_dead_caron :
1151 dead_char = 0xb7; /* '< */
1154 #ifdef XK_dead_ogonek
1155 case XK_dead_ogonek :
1156 dead_char = 0xb2; /* '; */
1159 /* FIXME: I don't know this three.
1163 case XK_dead_voiced_sound :
1166 case XK_dead_semivoiced_sound :
1173 *(char*)lpChar = dead_char;
1180 ksname = XKeysymToString(keysym);
1183 if ((keysym >> 8) != 0xff)
1185 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1187 fprintf(stderr, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1188 virtKey, scanCode, e.keycode, e.state);
1192 dprintf_key(stddeb, "ToAscii about to return %d with char %x\n",
1193 ret, *(char*)lpChar);
1198 /***********************************************************************
1199 * GetKeyboardLayout (USER32.249)
1201 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1203 fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1204 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1207 /***********************************************************************
1208 * GetKeyboardLayoutList (USER32.250)
1211 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1213 fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1215 layouts[0] = GetKeyboardLayout(0);