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>
26 /* #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);
605 /**********************************************************************
606 * TranslateAccelerator [USER.178]
608 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
610 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
614 STRUCT32_MSG32to16(msg,&msg16);
615 return TranslateAccelerator16(hWnd,hAccel,&msg16);
618 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
620 ACCELHEADER *lpAccelTbl;
624 if (hAccel == 0 || msg == NULL) return 0;
625 if (msg->message != WM_KEYDOWN &&
626 msg->message != WM_KEYUP &&
627 msg->message != WM_SYSKEYDOWN &&
628 msg->message != WM_SYSKEYUP &&
629 msg->message != WM_CHAR) return 0;
631 dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
632 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
634 lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel);
635 for (sendmsg= i = 0; i < lpAccelTbl->wCount; i++)
637 if(msg->wParam == lpAccelTbl->tbl[i].wEvent)
639 if (msg->message == WM_CHAR)
641 if ( !(lpAccelTbl->tbl[i].type & ALT_ACCEL) &&
642 !(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) )
644 dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff);
650 if(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL)
653 dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
654 msg->wParam,0xff & HIWORD(msg->lParam));
655 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= SHIFT_ACCEL;
656 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= CONTROL_ACCEL;
657 if(GetKeyState32(VK_MENU) & 0x8000) mask |= ALT_ACCEL;
658 if(mask == (lpAccelTbl->tbl[i].type &
659 (SHIFT_ACCEL | CONTROL_ACCEL | ALT_ACCEL)))
662 dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n");
666 if (!(msg->lParam & 0x01000000)) /* no special_key */
668 if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) && (msg->lParam & 0x20000000))
669 { /* ^^ ALT pressed */
670 dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff);
677 if (sendmsg) /* found an accelerator, but send a message... ? */
679 INT16 iSysStat,iStat,mesg=0;
682 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
688 if (!IsWindowEnabled16(hWnd))
692 WND* wndPtr = WIN_FindWndPtr(hWnd);
694 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
695 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
696 lpAccelTbl->tbl[i].wIDval, MF_BYCOMMAND) : -1 ;
697 iStat = (hMenu) ? GetMenuState32(hMenu,
698 lpAccelTbl->tbl[i].wIDval, MF_BYCOMMAND) : -1 ;
702 if (iSysStat & (MF_DISABLED|MF_GRAYED))
711 if (IsIconic32(hWnd))
715 if (iStat & (MF_DISABLED|MF_GRAYED))
725 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
727 dprintf_accel(stddeb,", sending %s, wParam=%0x\n",
728 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
729 lpAccelTbl->tbl[i].wIDval);
730 SendMessage16(hWnd, mesg, lpAccelTbl->tbl[i].wIDval,0x00010000L);
734 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
735 * #0: unknown (please report!)
736 * #1: for WM_KEYUP,WM_SYSKEYUP
737 * #2: mouse is captured
738 * #3: window is disabled
739 * #4: it's a disabled system menu option
740 * #5: it's a menu option, but window is iconic
741 * #6: it's a menu option, but disabled
743 dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
745 GlobalUnlock16(hAccel);
750 GlobalUnlock16(hAccel);
755 /******************************************************************************
756 * OemKeyScan [KEYBOARD.128][USER32.400]
758 DWORD WINAPI OemKeyScan(WORD wOemChar)
760 dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
765 /******************************************************************************
766 * VkKeyScanA [USER32.572]
768 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
769 * for the current keyboard.
770 * high-order byte yields :
774 * 3-5 Shift-key combinations that are not used for characters
777 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
778 * FIXME : works ok except for dead chars :
779 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
780 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
783 WORD WINAPI VkKeyScan32A(CHAR cChar)
790 /* char->keysym (same for ANSI chars) */
791 keysym=(unsigned char) cChar;/* (!) cChar is signed */
792 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
794 keycode = XKeysymToKeycode(display, keysym); /* keysym -> keycode */
796 { /* It didn't work ... let's try with deadchar code. */
797 keycode = XKeysymToKeycode(display, keysym | 0xFE00);
800 dprintf_keyboard(stddeb,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
801 cChar,keysym,keysym,keycode);
805 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
806 if (XKeycodeToKeysym(display,keycode,i)==keysym) index=i;
809 fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
811 case 1 : highbyte = 0x0100; break;
812 case 2 : highbyte = 0X0600; break;
813 default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
816 index : 0 adds 0x0000
817 index : 1 adds 0x0100 (shift)
818 index : ? adds 0x0200 (ctrl)
819 index : 2 adds 0x0600 (ctrl+alt)
820 index : ? adds 0x0700 (ctrl+alt+shit (used?))
823 dprintf_keyboard(stddeb," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
824 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
827 /******************************************************************************
828 * VkKeyScan [KEYBOARD.129]
830 WORD WINAPI VkKeyScan16(CHAR cChar)
832 return VkKeyScan32A(cChar);
835 /******************************************************************************
836 * VkKeyScanW [USER32.575]
838 WORD WINAPI VkKeyScan32W(WCHAR cChar)
840 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
843 /******************************************************************************
844 * GetKeyboardType [KEYBOARD.130]
846 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
848 return GetKeyboardType32(nTypeFlag);
851 /******************************************************************************
852 * GetKeyboardType [USER32.254]
854 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
856 dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
859 case 0: /* Keyboard type */
860 return 4; /* AT-101 */
862 case 1: /* Keyboard Subtype */
863 return 0; /* There are no defined subtypes */
865 case 2: /* Number of F-keys */
866 return 12; /* We're doing an 101 for now, so return 12 F-keys */
869 fprintf(stderr, "Unknown type on GetKeyboardType\n");
870 return 0; /* The book says 0 here, so 0 */
875 /******************************************************************************
876 * MapVirtualKeyA [USER32.382]
878 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
880 return MapVirtualKey16(code,maptype);
883 /******************************************************************************
884 * MapVirtualKeyA [USER32.384]
886 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
888 return MapVirtualKey16(code,maptype);
891 /******************************************************************************
892 * MapVirtualKeyA [KEYBOARD.131]
893 * MapVirtualKey translates keycodes from one format to another
895 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
897 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
899 dprintf_keyboard(stddeb,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode,wMapType);
901 case 0: { /* vkey-code to scan-code */
902 /* let's do vkey -> keycode -> scan */
904 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
905 if ((keyc2vkey[keyc] & 0xFF)== wCode)
906 returnMVK (keyc - 8);
909 case 1: /* scan-code to vkey-code */
910 /* let's do scan -> keycode -> vkey */
912 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
914 case 2: { /* vkey-code to unshifted ANSI code */
915 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
916 /* My Windows returns 'A'. */
917 /* let's do vkey -> keycode -> (XLookupString) ansi char */
922 e.state = 0; /* unshifted */
923 e.keycode = MapVirtualKey16( wCode, 0);
924 if (!XLookupString(&e, s , 2 , &keysym, NULL))
929 default: /* reserved */
930 fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
938 /****************************************************************************
939 * GetKBCodePage16 (KEYBOARD.132)
941 INT16 WINAPI GetKBCodePage16(void)
943 dprintf_keyboard(stddeb,"GetKBCodePage()\n");
948 /****************************************************************************
949 * GetKBCodePage32 (USER32.245)
951 UINT32 WINAPI GetKBCodePage32(void)
953 dprintf_keyboard(stddeb,"GetKbCodePage()\n");
958 /****************************************************************************
959 * GetKeyNameText32W (USER32.247)
961 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
963 LPSTR buf = xmalloc(nSize);
964 int res = GetKeyNameText32A(lParam,buf,nSize);
966 lstrcpynAtoW(lpBuffer,buf,nSize);
971 /****************************************************************************
972 * GetKeyNameText32A (USER32.246)
974 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
976 return GetKeyNameText16(lParam,lpBuffer,nSize);
979 /****************************************************************************
980 * GetKeyNameText16 (KEYBOARD.133)
982 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
986 dprintf_keyboard(stddeb,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
991 /* for (i = 0 ; i != KeyTableSize ; i++)
992 if (KeyTable[i].scancode == lParam) {
993 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
994 return strlen(lpBuffer);
997 /* FIXME ! GetKeyNameText is still to do...
1004 /****************************************************************************
1005 * ToAscii (KEYBOARD.4)
1007 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1008 LPVOID lpChar, UINT16 flags)
1010 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1013 /****************************************************************************
1014 * ToAscii (USER32.545)
1016 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1017 LPWORD lpChar,UINT32 flags )
1021 static XComposeStatus cs;
1025 e.display = display;
1027 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1028 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1029 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1030 if ((keyc2vkey[keyc] & 0xFF)== virtKey) /* no need to make a more precise test (with the extended bit correctly set above virtKey ... VK* are different enough... */
1032 if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12)))
1033 /* it's normal to have 2 shift, control, and alt ! */
1034 dprintf_keyboard(stddeb,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1035 e.keycode,keyc,virtKey);
1039 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1041 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1042 e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1043 if (virtKey==VK_DECIMAL)
1044 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1048 fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1049 return virtKey; /* whatever */
1052 if (lpKeyState[VK_SHIFT] & 0x80)
1053 e.state |= ShiftMask;
1054 dprintf_keyboard(stddeb,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1055 if (lpKeyState[VK_CAPITAL] & 0x01)
1056 e.state |= LockMask;
1057 if (lpKeyState[VK_CONTROL] & 0x80)
1058 if (lpKeyState[VK_MENU] & 0x80)
1059 e.state |= AltGrMask;
1061 e.state |= ControlMask;
1062 if (lpKeyState[VK_NUMLOCK] & 0x01)
1063 e.state |= NumLockMask;
1064 dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
1065 virtKey, scanCode, e.state);
1066 ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1071 ((char*)lpChar)[1] = '\0';
1074 /* symbolic ASCII is the same as defined in rfc1345 */
1075 #ifdef XK_dead_tilde
1076 case XK_dead_tilde :
1078 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1079 dead_char = '~'; /* '? */
1081 #ifdef XK_dead_acute
1082 case XK_dead_acute :
1084 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1085 dead_char = 0xb4; /* '' */
1087 #ifdef XK_dead_circumflex
1088 case XK_dead_circumflex :
1090 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1091 dead_char = '^'; /* '> */
1093 #ifdef XK_dead_grave
1094 case XK_dead_grave :
1096 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1097 dead_char = '`'; /* '! */
1099 #ifdef XK_dead_diaeresis
1100 case XK_dead_diaeresis :
1102 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1103 dead_char = 0xa8; /* ': */
1105 #ifdef XK_dead_cedilla
1106 case XK_dead_cedilla :
1107 dead_char = 0xb8; /* ', */
1110 #ifdef XK_dead_macron
1111 case XK_dead_macron :
1112 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1115 #ifdef XK_dead_breve
1116 case XK_dead_breve :
1117 dead_char = 0xa2; /* '( */
1120 #ifdef XK_dead_abovedot
1121 case XK_dead_abovedot :
1122 dead_char = 0xff; /* '. */
1125 #ifdef XK_dead_abovering
1126 case XK_dead_abovering :
1127 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1130 #ifdef XK_dead_doubleacute
1131 case XK_dead_doubleacute :
1132 dead_char = 0xbd; /* '" */
1135 #ifdef XK_dead_caron
1136 case XK_dead_caron :
1137 dead_char = 0xb7; /* '< */
1140 #ifdef XK_dead_ogonek
1141 case XK_dead_ogonek :
1142 dead_char = 0xb2; /* '; */
1145 /* FIXME: I don't know this three.
1149 case XK_dead_voiced_sound :
1152 case XK_dead_semivoiced_sound :
1159 *(char*)lpChar = dead_char;
1166 ksname = XKeysymToString(keysym);
1169 if ((keysym >> 8) != 0xff)
1171 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1173 fprintf(stderr, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1174 virtKey, scanCode, e.keycode, e.state);
1178 dprintf_key(stddeb, "ToAscii about to return %d with char %x\n",
1179 ret, *(char*)lpChar);
1184 /***********************************************************************
1185 * GetKeyboardLayout (USER32.249)
1187 /*HKL*/ HANDLE32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1189 fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);