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 "ts_xresource.h"
18 #include <X11/Xatom.h>
29 BOOL32 MouseButtonsStates[3];
30 BOOL32 AsyncMouseButtonsStates[3];
31 BYTE InputKeyStateTable[256];
32 BYTE QueueKeyStateTable[256];
33 BYTE AsyncKeyStateTable[256];
35 static int NumLockMask;
37 static int min_keycode, max_keycode;
38 static int keyc2vkey[256];
44 unsigned long count : 16;
45 unsigned long code : 8;
46 unsigned long extended : 1;
47 unsigned long unused : 2;
48 unsigned long win_internal : 2;
49 unsigned long context : 1;
50 unsigned long previous : 1;
51 unsigned long transition : 1;
56 /* Keyboard translation tables */
57 static const int special_key[] =
59 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
60 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
61 0, 0, 0, VK_ESCAPE /* FF18 */
64 static const int cursor_key[] =
66 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
67 VK_NEXT, VK_END /* FF50 */
70 static const int misc_key[] =
72 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
73 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
76 static const int keypad_key[] =
78 0, VK_NUMLOCK, /* FF7E */
79 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
80 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
81 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
82 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
83 VK_INSERT, VK_DELETE, /* FF98 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
85 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
86 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
87 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
88 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
89 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
92 static const int function_key[] =
94 VK_F1, VK_F2, /* FFBE */
95 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
96 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
99 static const int modifier_key[] =
101 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
102 VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
106 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
108 const BYTE vkey2scode[512] = {
109 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
110 0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
111 0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
112 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
113 0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
114 0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
115 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
116 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x00,0x00,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,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
121 0x27,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,0x28,0x33,0x34,0x35,0x4c,
123 0x00,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,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
127 0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
129 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x35,
133 0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,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,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,
144 static WORD EVENT_event_to_vkey( XKeyEvent *e)
148 TSXLookupString(e, NULL, 0, &keysym, NULL);
150 if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask))
151 /* Only the Keypad keys 0-9 and . send different keysyms
152 * depending on the NumLock state */
153 return keypad_key[(keysym & 0xFF) - 0x7E];
155 return keyc2vkey[e->keycode];
158 /**********************************************************************
161 BOOL32 KEYBOARD_Init(void)
163 int i, keysyms_per_keycode;
165 XModifierKeymap *mmp;
171 TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
172 ksp = TSXGetKeyboardMapping(display, min_keycode,
173 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
174 /* We are only interested in keysyms_per_keycode.
175 There is no need to hold a local copy of the keysyms table */
177 mmp = TSXGetModifierMapping(display);
178 kcp = mmp->modifiermap;
179 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
183 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
188 for (k = 0; k < keysyms_per_keycode; k += 1)
189 if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
192 dprintf_info(key, "AltGrMask is %x\n", AltGrMask);
194 else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
196 NumLockMask = 1 << i;
197 dprintf_info(key, "NumLockMask is %x\n", NumLockMask);
201 TSXFreeModifiermap(mmp);
203 /* Now build two conversion arrays :
204 * keycode -> vkey + extended
205 * vkey + extended -> keycode */
207 e2.display = display;
210 OEMvkey = 0xb9; /* first OEM virtual key available is ba */
211 for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
213 TSXLookupString(&e2, NULL, 0, &keysym, NULL);
215 if (keysym) /* otherwise, keycode not used */
217 if ((keysym >> 8) == 0xFF) /* non-character key */
219 int key = keysym & 0xff;
221 if (key >= 0x08 && key <= 0x1B) /* special key */
222 vkey = special_key[key - 0x08];
223 else if (key >= 0x50 && key <= 0x57) /* cursor key */
224 vkey = cursor_key[key - 0x50];
225 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
226 vkey = misc_key[key - 0x60];
227 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
228 vkey = keypad_key[key - 0x7E];
229 else if (key >= 0xBE && key <= 0xCD) /* function key */
231 vkey = function_key[key - 0xBE];
232 vkey |= 0x100; /* set extended bit */
234 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
235 vkey = modifier_key[key - 0xE1];
236 else if (key == 0xFF) /* DEL key */
238 /* extended must also be set for ALT_R, CTRL_R,
239 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
240 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
241 /* FIXME should we set extended bit for NumLock ? My
242 * Windows does ... DF */
262 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
264 keysym = TSXLookupKeysym(&e2, i);
265 if ((keysym >= VK_0 && keysym <= VK_9)
266 || (keysym >= VK_A && keysym <= VK_Z)
267 || keysym == VK_SPACE)
273 /* Others keys: let's assign OEM virtual key codes in the allowed range,
274 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
277 case 0xc1 : OEMvkey=0xdb; break;
278 case 0xe5 : OEMvkey=0xe9; break;
279 case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
284 if (debugging_info(keyboard))
286 dbg_decl_str(keyboard, 1024);
288 dprintf_info(keyboard, "OEM specific virtual key %X assigned"
289 "to keycode %X :\n", OEMvkey, e2.keycode);
290 for (i = 0; i < keysyms_per_keycode; i += 1)
294 keysym = TSXLookupKeysym(&e2, i);
295 ksname = TSXKeysymToString(keysym);
298 dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
300 dprintf_info(keyboard, "(%s)\n", dbg_str(keyboard));
304 keyc2vkey[e2.keycode] = vkey;
309 static BOOL32 NumState=FALSE, CapsState=FALSE;
311 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
312 DWORD event_time, 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_info(keyboard,"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_info(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
329 localkeylp.lp1.previous = 0; /* ? */
330 localkeylp.lp1.transition = 0;
331 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
332 event_x, event_y, event_time, 0 );
333 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
334 event_x, event_y, event_time, 0 );
336 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
339 else /* it was OFF */
340 if (Evtype==KeyPress)
342 dprintf_info(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
343 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
344 event_x, event_y, event_time, 0 );
345 localkeylp.lp1.previous = 1;
346 localkeylp.lp1.transition = 1;
347 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
348 event_x, event_y, event_time, 0 );
349 *State=TRUE; /* Goes to intermediary state before going to ON */
350 InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
355 /***********************************************************************
356 * KEYBOARD_HandleEvent
358 * Handle a X key event
360 void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
367 static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
369 int ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
371 INT32 event_x = pWnd->rectWindow.left + event->x;
372 INT32 event_y = pWnd->rectWindow.top + event->y;
373 DWORD event_time = event->time - MSG_WineStartTicks;
375 dprintf_info(key, "EVENT_key : state = %X\n", event->state);
376 if (keysym == XK_Mode_switch)
378 dprintf_info(key, "Alt Gr key event received\n");
379 event->keycode = TSXKeysymToKeycode(event->display, XK_Control_L);
380 dprintf_info(key, "Control_L is keycode 0x%x\n", event->keycode);
381 KEYBOARD_HandleEvent( pWnd, event );
382 event->keycode = TSXKeysymToKeycode(event->display, XK_Alt_L);
383 dprintf_info(key, "Alt_L is keycode 0x%x\n", event->keycode);
384 force_extended = TRUE;
385 KEYBOARD_HandleEvent( pWnd, event );
386 force_extended = FALSE;
390 Str[ascii_chars] = '\0';
391 if (debugging_info(key)){
394 ksname = TSXKeysymToString(keysym);
397 dprintf_info(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
398 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
399 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
402 vkey = EVENT_event_to_vkey(event);
403 if (force_extended) vkey |= 0x100;
405 dprintf_info(key, "keycode 0x%x converted to vkey 0x%x\n",
406 event->keycode, vkey);
411 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
412 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
413 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
414 * don't remember where I read it - AK */
415 /* it's '1' under windows, when a dialog box appears
416 * and you press one of the underlined keys - DF*/
422 KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
426 dprintf_info(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
427 KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
429 dprintf_info(keyboard,"State after : %#.2x\n",InputKeyStateTable[vkey]);
434 if (event->type == KeyPress)
436 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
437 if (!(InputKeyStateTable[vkey] & 0x80))
438 InputKeyStateTable[vkey] ^= 0x01;
439 InputKeyStateTable[vkey] |= 0x80;
440 keylp.lp1.transition = 0;
441 message = (InputKeyStateTable[VK_MENU] & 0x80)
442 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
443 ? WM_SYSKEYDOWN : WM_KEYDOWN;
447 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
448 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
449 && (force_extended == FALSE); /* for Alt from AltGr */
451 InputKeyStateTable[vkey] &= ~0x80;
452 keylp.lp1.previous = 1;
453 keylp.lp1.transition = 1;
454 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
456 keylp.lp1.context = ( (event->state & Mod1Mask) ||
457 (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
458 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
460 dprintf_info(keyboard,"Adjusting NumLock state. \n");
461 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
463 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
466 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
468 dprintf_info(keyboard,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
469 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
471 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
473 dprintf_info(keyboard,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
475 /* End of intermediary states. */
479 dprintf_info(key," wParam=%04X, lParam=%08lX\n",
481 dprintf_info(key," InputKeyState=%X\n",
482 InputKeyStateTable[vkey]);
484 hardware_event( message, vkey, keylp.lp2,
485 event_x, event_y, event_time, 0 );
492 /**********************************************************************
493 * GetKeyState [USER.106]
495 WORD WINAPI GetKeyState16(INT16 vkey)
497 return GetKeyState32(vkey);
500 /**********************************************************************
501 * GetKeyState [USER32.248]
502 * An application calls the GetKeyState function in response to a
503 * keyboard-input message. This function retrieves the state of the key
504 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
506 WORD WINAPI GetKeyState32(INT32 vkey)
512 case VK_LBUTTON : /* VK_LBUTTON is 1 */
513 retval = MouseButtonsStates[0] ? 0x8000 : 0;
515 case VK_MBUTTON : /* VK_MBUTTON is 4 */
516 retval = MouseButtonsStates[1] ? 0x8000 : 0;
518 case VK_RBUTTON : /* VK_RBUTTON is 2 */
519 retval = MouseButtonsStates[2] ? 0x8000 : 0;
522 if (vkey >= 'a' && vkey <= 'z')
524 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
525 (WORD)(QueueKeyStateTable[vkey] & 0x01);
527 dprintf_info(key, "GetKeyState(0x%x) -> %x\n", vkey, retval);
531 /**********************************************************************
532 * GetKeyboardState [USER.222][USER32.253]
533 * An application calls the GetKeyboardState function in response to a
534 * keyboard-input message. This function retrieves the state of the keyboard
535 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
537 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
539 dprintf_info(key, "GetKeyboardState()\n");
540 if (lpKeyState != NULL) {
541 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
542 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
543 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
544 memcpy(lpKeyState, QueueKeyStateTable, 256);
548 /**********************************************************************
549 * SetKeyboardState [USER.223][USER32.483]
551 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
553 dprintf_info(key, "SetKeyboardState()\n");
554 if (lpKeyState != NULL) {
555 memcpy(QueueKeyStateTable, lpKeyState, 256);
556 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
557 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
558 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
562 /**********************************************************************
563 * GetAsyncKeyState (USER32.206)
565 * Determine if a key is or was pressed. retval has high-order
566 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
569 * This uses the variable AsyncMouseButtonsStates and
570 * AsyncKeyStateTable (set in event.c) which have the mouse button
571 * number or key number (whichever is applicable) set to true if the
572 * mouse or key had been depressed since the last call to
575 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
581 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
582 (MouseButtonsStates[0] ? 0x8000 : 0);
585 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
586 (MouseButtonsStates[1] ? 0x8000 : 0);
589 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
590 (MouseButtonsStates[2] ? 0x8000 : 0);
593 retval = AsyncKeyStateTable[nKey] |
594 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
598 /* all states to false */
599 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
600 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
602 dprintf_info(key, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
606 /**********************************************************************
607 * GetAsyncKeyState (USER.249)
609 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
611 return GetAsyncKeyState32(nKey);
614 /*********************************************************************
615 * CreateAcceleratorTable (USER.64)
617 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries) {
618 fprintf(stderr, "CreateAcceleratorTable32A Stub\n");
622 /**********************************************************************
623 * TranslateAccelerator [USER.178][USER32.551..]
625 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
627 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
628 BYTE fVirt,WORD key,WORD cmd)
630 BOOL32 sendmsg = FALSE;
632 if(msg->wParam == key)
634 if (msg->message == WM_CHAR) {
635 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
637 dprintf_info(accel,"found accel for WM_CHAR: ('%c')\n",
642 if(fVirt & FVIRTKEY) {
644 dprintf_info(accel,"found accel for virt_key %04x (scan %04x)\n",
645 msg->wParam,0xff & HIWORD(msg->lParam));
646 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
647 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
648 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
649 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
652 dprintf_info(accel,", but incorrect SHIFT/CTRL/ALT-state\n");
656 if (!(msg->lParam & 0x01000000)) /* no special_key */
658 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
659 { /* ^^ ALT pressed */
660 dprintf_info(accel,"found accel for Alt-%c\n", msg->wParam&0xff);
667 if (sendmsg) /* found an accelerator, but send a message... ? */
669 INT16 iSysStat,iStat,mesg=0;
672 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
678 if (!IsWindowEnabled32(hWnd))
682 WND* wndPtr = WIN_FindWndPtr(hWnd);
684 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
685 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
686 cmd, MF_BYCOMMAND) : -1 ;
687 iStat = (hMenu) ? GetMenuState32(hMenu,
688 cmd, MF_BYCOMMAND) : -1 ;
692 if (iSysStat & (MF_DISABLED|MF_GRAYED))
701 if (IsIconic32(hWnd))
705 if (iStat & (MF_DISABLED|MF_GRAYED))
715 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
717 dprintf_info(accel,", sending %s, wParam=%0x\n",
718 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
720 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
724 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
725 * #0: unknown (please report!)
726 * #1: for WM_KEYUP,WM_SYSKEYUP
727 * #2: mouse is captured
728 * #3: window is disabled
729 * #4: it's a disabled system menu option
730 * #5: it's a menu option, but window is iconic
731 * #6: it's a menu option, but disabled
733 dprintf_info(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
735 dprintf_err(accel, " unknown reason - please report!");
743 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
745 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
748 if (hAccel == 0 || msg == NULL) return 0;
749 if (msg->message != WM_KEYDOWN &&
750 msg->message != WM_KEYUP &&
751 msg->message != WM_SYSKEYDOWN &&
752 msg->message != WM_SYSKEYUP &&
753 msg->message != WM_CHAR) return 0;
755 dprintf_info(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
756 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
758 for (i = 0; lpAccelTbl[i].key ; i++)
759 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
760 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
765 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
767 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
771 if (hAccel == 0 || msg == NULL) return 0;
772 if (msg->message != WM_KEYDOWN &&
773 msg->message != WM_KEYUP &&
774 msg->message != WM_SYSKEYDOWN &&
775 msg->message != WM_SYSKEYUP &&
776 msg->message != WM_CHAR) return 0;
778 dprintf_info(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
779 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
780 STRUCT32_MSG16to32(msg,&msg32);
783 for (i=0;lpAccelTbl[i].key;i++)
784 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
785 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
791 /******************************************************************************
792 * OemKeyScan [KEYBOARD.128][USER32.400]
794 DWORD WINAPI OemKeyScan(WORD wOemChar)
796 dprintf_info(keyboard,"*OemKeyScan (%d)\n",wOemChar);
801 /******************************************************************************
802 * VkKeyScanA [USER32.572]
804 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
805 * for the current keyboard.
806 * high-order byte yields :
810 * 3-5 Shift-key combinations that are not used for characters
813 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
814 * FIXME : works ok except for dead chars :
815 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
816 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
819 WORD WINAPI VkKeyScan32A(CHAR cChar)
826 /* char->keysym (same for ANSI chars) */
827 keysym=(unsigned char) cChar;/* (!) cChar is signed */
828 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
830 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
832 { /* It didn't work ... let's try with deadchar code. */
833 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
836 dprintf_info(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
837 cChar,keysym,keysym,keycode);
841 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
842 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
845 fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
847 case 1 : highbyte = 0x0100; break;
848 case 2 : highbyte = 0X0600; break;
849 default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
852 index : 0 adds 0x0000
853 index : 1 adds 0x0100 (shift)
854 index : ? adds 0x0200 (ctrl)
855 index : 2 adds 0x0600 (ctrl+alt)
856 index : ? adds 0x0700 (ctrl+alt+shift (used?))
859 dprintf_info(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
860 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
863 /******************************************************************************
864 * VkKeyScan [KEYBOARD.129]
866 WORD WINAPI VkKeyScan16(CHAR cChar)
868 return VkKeyScan32A(cChar);
871 /******************************************************************************
872 * VkKeyScanW [USER32.575]
874 WORD WINAPI VkKeyScan32W(WCHAR cChar)
876 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
879 /******************************************************************************
880 * GetKeyboardType [KEYBOARD.130]
882 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
884 return GetKeyboardType32(nTypeFlag);
887 /******************************************************************************
888 * GetKeyboardType [USER32.254]
890 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
892 dprintf_info(keyboard,"GetKeyboardType(%d)\n",nTypeFlag);
895 case 0: /* Keyboard type */
896 return 4; /* AT-101 */
898 case 1: /* Keyboard Subtype */
899 return 0; /* There are no defined subtypes */
901 case 2: /* Number of F-keys */
902 return 12; /* We're doing an 101 for now, so return 12 F-keys */
905 fprintf(stderr, "Unknown type on GetKeyboardType\n");
906 return 0; /* The book says 0 here, so 0 */
911 /******************************************************************************
912 * MapVirtualKeyA [USER32.382]
914 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
916 return MapVirtualKey16(code,maptype);
919 /******************************************************************************
920 * MapVirtualKeyA [USER32.384]
922 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
924 return MapVirtualKey16(code,maptype);
927 /******************************************************************************
928 * MapVirtualKeyA [KEYBOARD.131]
929 * MapVirtualKey translates keycodes from one format to another
931 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
933 #define returnMVK(value) { dprintf_info(keyboard,"returning 0x%x.\n",value); return value; }
935 dprintf_info(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
938 case 0: { /* vkey-code to scan-code */
939 /* let's do vkey -> keycode -> scan */
941 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
942 if ((keyc2vkey[keyc] & 0xFF)== wCode)
943 returnMVK (keyc - 8);
946 case 1: /* scan-code to vkey-code */
947 /* let's do scan -> keycode -> vkey */
949 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
951 case 2: { /* vkey-code to unshifted ANSI code */
952 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
953 /* My Windows returns 'A'. */
954 /* let's do vkey -> keycode -> (XLookupString) ansi char */
959 e.state = 0; /* unshifted */
960 e.keycode = MapVirtualKey16( wCode, 0);
961 if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
966 default: /* reserved */
967 fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
975 /****************************************************************************
976 * GetKBCodePage16 (KEYBOARD.132)
978 INT16 WINAPI GetKBCodePage16(void)
980 dprintf_info(keyboard,"GetKBCodePage()\n");
985 /****************************************************************************
986 * GetKBCodePage32 (USER32.245)
988 UINT32 WINAPI GetKBCodePage32(void)
990 dprintf_info(keyboard,"GetKbCodePage()\n");
995 /****************************************************************************
996 * GetKeyNameText32W (USER32.247)
998 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
1000 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
1001 int res = GetKeyNameText32A(lParam,buf,nSize);
1003 lstrcpynAtoW(lpBuffer,buf,nSize);
1004 HeapFree( GetProcessHeap(), 0, buf );
1008 /****************************************************************************
1009 * GetKeyNameText32A (USER32.246)
1011 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1013 return GetKeyNameText16(lParam,lpBuffer,nSize);
1016 /****************************************************************************
1017 * GetKeyNameText16 (KEYBOARD.133)
1019 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1023 dprintf_info(keyboard,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
1028 /* for (i = 0 ; i != KeyTableSize ; i++)
1029 if (KeyTable[i].scancode == lParam) {
1030 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1031 return strlen(lpBuffer);
1034 /* FIXME ! GetKeyNameText is still to do...
1041 /****************************************************************************
1042 * ToAscii (KEYBOARD.4)
1044 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1045 LPVOID lpChar, UINT16 flags)
1047 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1050 /****************************************************************************
1051 * ToAscii (USER32.545)
1053 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1054 LPWORD lpChar,UINT32 flags )
1058 static XComposeStatus cs;
1062 e.display = display;
1064 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1065 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1066 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1067 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... */
1069 if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12)))
1070 /* it's normal to have 2 shift, control, and alt ! */
1071 dprintf_info(keyboard,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1072 e.keycode,keyc,virtKey);
1076 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1078 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1079 e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1080 if (virtKey==VK_DECIMAL)
1081 e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1085 fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1086 return virtKey; /* whatever */
1089 if (lpKeyState[VK_SHIFT] & 0x80)
1090 e.state |= ShiftMask;
1091 dprintf_info(keyboard,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1092 if (lpKeyState[VK_CAPITAL] & 0x01)
1093 e.state |= LockMask;
1094 if (lpKeyState[VK_CONTROL] & 0x80)
1095 if (lpKeyState[VK_MENU] & 0x80)
1096 e.state |= AltGrMask;
1098 e.state |= ControlMask;
1099 if (lpKeyState[VK_NUMLOCK] & 0x01)
1100 e.state |= NumLockMask;
1101 dprintf_info(key, "ToAscii(%04X, %04X) : faked state = %X\n",
1102 virtKey, scanCode, e.state);
1103 ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1108 ((char*)lpChar)[1] = '\0';
1111 /* symbolic ASCII is the same as defined in rfc1345 */
1112 #ifdef XK_dead_tilde
1113 case XK_dead_tilde :
1115 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1116 dead_char = '~'; /* '? */
1118 #ifdef XK_dead_acute
1119 case XK_dead_acute :
1121 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1122 dead_char = 0xb4; /* '' */
1124 #ifdef XK_dead_circumflex
1125 case XK_dead_circumflex :
1127 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1128 dead_char = '^'; /* '> */
1130 #ifdef XK_dead_grave
1131 case XK_dead_grave :
1133 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1134 dead_char = '`'; /* '! */
1136 #ifdef XK_dead_diaeresis
1137 case XK_dead_diaeresis :
1139 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1140 dead_char = 0xa8; /* ': */
1142 #ifdef XK_dead_cedilla
1143 case XK_dead_cedilla :
1144 dead_char = 0xb8; /* ', */
1147 #ifdef XK_dead_macron
1148 case XK_dead_macron :
1149 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1152 #ifdef XK_dead_breve
1153 case XK_dead_breve :
1154 dead_char = 0xa2; /* '( */
1157 #ifdef XK_dead_abovedot
1158 case XK_dead_abovedot :
1159 dead_char = 0xff; /* '. */
1162 #ifdef XK_dead_abovering
1163 case XK_dead_abovering :
1164 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1167 #ifdef XK_dead_doubleacute
1168 case XK_dead_doubleacute :
1169 dead_char = 0xbd; /* '" */
1172 #ifdef XK_dead_caron
1173 case XK_dead_caron :
1174 dead_char = 0xb7; /* '< */
1177 #ifdef XK_dead_ogonek
1178 case XK_dead_ogonek :
1179 dead_char = 0xb2; /* '; */
1182 /* FIXME: I don't know this three.
1186 case XK_dead_voiced_sound :
1189 case XK_dead_semivoiced_sound :
1196 *(char*)lpChar = dead_char;
1203 ksname = TSXKeysymToString(keysym);
1206 if ((keysym >> 8) != 0xff)
1208 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1210 fprintf(stderr, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1211 virtKey, scanCode, e.keycode, e.state);
1215 dprintf_info(key, "ToAscii about to return %d with char %x\n",
1216 ret, *(char*)lpChar);
1221 /***********************************************************************
1222 * GetKeyboardLayout (USER32.249)
1224 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1226 fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1227 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1230 /***********************************************************************
1231 * GetKeyboardLayoutList (USER32.250)
1234 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1236 fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1238 layouts[0] = GetKeyboardLayout(0);
1243 /***********************************************************************
1244 * RegisterHotKey (USER32.433)
1246 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1247 fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1248 hwnd,id,modifiers,vk
1253 /***********************************************************************
1254 * UnregisterHotKey (USER32.565)
1256 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1257 fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);