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>
27 /* #define DEBUG_KEYBOARD */
31 BOOL32 MouseButtonsStates[3];
32 BOOL32 AsyncMouseButtonsStates[3];
33 BYTE InputKeyStateTable[256];
34 BYTE QueueKeyStateTable[256];
35 BYTE AsyncKeyStateTable[256];
37 static int NumLockMask;
39 static int min_keycode, max_keycode;
40 static int keyc2vkey[256];
46 unsigned long count : 16;
47 unsigned long code : 8;
48 unsigned long extended : 1;
49 unsigned long unused : 2;
50 unsigned long win_internal : 2;
51 unsigned long context : 1;
52 unsigned long previous : 1;
53 unsigned long transition : 1;
58 /* Keyboard translation tables */
59 static const int special_key[] =
61 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
62 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
63 0, 0, 0, VK_ESCAPE /* FF18 */
66 static const int cursor_key[] =
68 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
69 VK_NEXT, VK_END /* FF50 */
72 static const int misc_key[] =
74 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
78 static const int keypad_key[] =
80 0, VK_NUMLOCK, /* FF7E */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
82 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
83 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
84 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
85 VK_INSERT, VK_DELETE, /* FF98 */
86 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
87 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
88 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
89 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
90 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
91 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
94 static const int function_key[] =
96 VK_F1, VK_F2, /* FFBE */
97 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
98 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
101 static const int modifier_key[] =
103 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
104 VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
108 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
110 const BYTE vkey2scode[512] = {
111 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
112 0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
113 0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
114 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
115 0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
116 0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
117 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
123 0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x28,0x33,0x34,0x35,0x4c,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
129 0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
131 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,
135 0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,0x00,0x00,0x00,0x00,
136 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
137 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 static WORD EVENT_event_to_vkey( XKeyEvent *e)
150 TSXLookupString(e, NULL, 0, &keysym, NULL);
152 if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask))
153 /* Only the Keypad keys 0-9 and . send different keysyms
154 * depending on the NumLock state */
155 return keypad_key[(keysym & 0xFF) - 0x7E];
157 return keyc2vkey[e->keycode];
160 /**********************************************************************
163 BOOL32 KEYBOARD_Init(void)
165 int i, keysyms_per_keycode;
167 XModifierKeymap *mmp;
173 TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
174 ksp = TSXGetKeyboardMapping(display, min_keycode,
175 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
176 /* We are only interested in keysyms_per_keycode.
177 There is no need to hold a local copy of the keysyms table */
179 mmp = TSXGetModifierMapping(display);
180 kcp = mmp->modifiermap;
181 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
185 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
190 for (k = 0; k < keysyms_per_keycode; k += 1)
191 if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
194 dprintf_key(stddeb, "AltGrMask is %x\n", AltGrMask);
196 else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
198 NumLockMask = 1 << i;
199 dprintf_key(stddeb, "NumLockMask is %x\n", NumLockMask);
203 TSXFreeModifiermap(mmp);
205 /* Now build two conversion arrays :
206 * keycode -> vkey + extended
207 * vkey + extended -> keycode */
209 e2.display = display;
212 OEMvkey = 0xb9; /* first OEM virtual key available is ba */
213 for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
215 TSXLookupString(&e2, NULL, 0, &keysym, NULL);
217 if (keysym) /* otherwise, keycode not used */
219 if ((keysym >> 8) == 0xFF) /* non-character key */
221 int key = keysym & 0xff;
223 if (key >= 0x08 && key <= 0x1B) /* special key */
224 vkey = special_key[key - 0x08];
225 else if (key >= 0x50 && key <= 0x57) /* cursor key */
226 vkey = cursor_key[key - 0x50];
227 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
228 vkey = misc_key[key - 0x60];
229 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
230 vkey = keypad_key[key - 0x7E];
231 else if (key >= 0xBE && key <= 0xCD) /* function key */
233 vkey = function_key[key - 0xBE];
234 vkey |= 0x100; /* set extended bit */
236 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
237 vkey = modifier_key[key - 0xE1];
238 else if (key == 0xFF) /* DEL key */
240 /* extended must also be set for ALT_R, CTRL_R,
241 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
242 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
243 /* FIXME should we set extended bit for NumLock ? My
244 * Windows does ... DF */
264 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
266 keysym = TSXLookupKeysym(&e2, i);
267 if ((keysym >= VK_0 && keysym <= VK_9)
268 || (keysym >= VK_A && keysym <= VK_Z)
269 || keysym == VK_SPACE)
275 /* Others keys: let's assign OEM virtual key codes in the allowed range,
276 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
279 case 0xc1 : OEMvkey=0xdb; break;
280 case 0xe5 : OEMvkey=0xe9; break;
281 case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
286 if (debugging_keyboard)
288 fprintf(stddeb,"OEM specific virtual key %X assigned to keycode %X :\n ("
289 ,OEMvkey,e2.keycode);
290 for (i = 0; i < keysyms_per_keycode; i += 1)
294 keysym = TSXLookupKeysym(&e2, i);
295 ksname = TSXKeysymToString(keysym);
298 fprintf(stddeb, "%lX (%s) ", keysym, ksname);
300 fprintf(stddeb, ")\n");
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_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,
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_keyboard(stddeb,"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_key(stddeb, "EVENT_key : state = %X\n", event->state);
376 if (keysym == XK_Mode_switch)
378 dprintf_key(stddeb, "Alt Gr key event received\n");
379 event->keycode = TSXKeysymToKeycode(event->display, XK_Control_L);
380 dprintf_key(stddeb, "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_key(stddeb, "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';
395 ksname = TSXKeysymToString(keysym);
398 fprintf(stddeb, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
399 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
400 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
403 vkey = EVENT_event_to_vkey(event);
404 if (force_extended) vkey |= 0x100;
406 dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
407 event->keycode, vkey);
412 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
413 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
414 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
415 * don't remember where I read it - AK */
416 /* it's '1' under windows, when a dialog box appears
417 * and you press one of the underlined keys - DF*/
423 KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
427 dprintf_keyboard(stddeb,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
428 KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
430 dprintf_keyboard(stddeb,"State after : %#.2x\n",InputKeyStateTable[vkey]);
435 if (event->type == KeyPress)
437 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
438 if (!(InputKeyStateTable[vkey] & 0x80))
439 InputKeyStateTable[vkey] ^= 0x01;
440 InputKeyStateTable[vkey] |= 0x80;
441 keylp.lp1.transition = 0;
442 message = (InputKeyStateTable[VK_MENU] & 0x80)
443 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
444 ? WM_SYSKEYDOWN : WM_KEYDOWN;
448 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
449 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
450 && (force_extended == FALSE); /* for Alt from AltGr */
452 InputKeyStateTable[vkey] &= ~0x80;
453 keylp.lp1.previous = 1;
454 keylp.lp1.transition = 1;
455 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
457 keylp.lp1.context = ( (event->state & Mod1Mask) ||
458 (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
459 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
461 dprintf_keyboard(stddeb,"Adjusting NumLock state. \n");
462 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
464 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
467 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
469 dprintf_keyboard(stddeb,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
470 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
472 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
474 dprintf_keyboard(stddeb,"State after %#.2x \n",InputKeyStateTable[VK_CAPITAL]);
476 /* End of intermediary states. */
480 dprintf_key(stddeb," wParam=%04X, lParam=%08lX\n",
482 dprintf_key(stddeb," InputKeyState=%X\n",
483 InputKeyStateTable[vkey]);
485 hardware_event( message, vkey, keylp.lp2,
486 event_x, event_y, event_time, 0 );
493 /**********************************************************************
494 * GetKeyState [USER.106]
496 WORD WINAPI GetKeyState16(INT16 vkey)
498 return GetKeyState32(vkey);
501 /**********************************************************************
502 * GetKeyState [USER32.248]
503 * An application calls the GetKeyState function in response to a
504 * keyboard-input message. This function retrieves the state of the key
505 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
507 WORD WINAPI GetKeyState32(INT32 vkey)
513 case VK_LBUTTON : /* VK_LBUTTON is 1 */
514 retval = MouseButtonsStates[0] ? 0x8000 : 0;
516 case VK_MBUTTON : /* VK_MBUTTON is 4 */
517 retval = MouseButtonsStates[1] ? 0x8000 : 0;
519 case VK_RBUTTON : /* VK_RBUTTON is 2 */
520 retval = MouseButtonsStates[2] ? 0x8000 : 0;
523 if (vkey >= 'a' && vkey <= 'z')
525 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
526 (WORD)(QueueKeyStateTable[vkey] & 0x01);
528 dprintf_key(stddeb, "GetKeyState(0x%x) -> %x\n", vkey, retval);
532 /**********************************************************************
533 * GetKeyboardState [USER.222][USER32.253]
534 * An application calls the GetKeyboardState function in response to a
535 * keyboard-input message. This function retrieves the state of the keyboard
536 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
538 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
540 dprintf_key(stddeb, "GetKeyboardState()\n");
541 if (lpKeyState != NULL) {
542 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
543 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
544 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
545 memcpy(lpKeyState, QueueKeyStateTable, 256);
549 /**********************************************************************
550 * SetKeyboardState [USER.223][USER32.483]
552 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
554 dprintf_key(stddeb, "SetKeyboardState()\n");
555 if (lpKeyState != NULL) {
556 memcpy(QueueKeyStateTable, lpKeyState, 256);
557 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
558 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
559 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
563 /**********************************************************************
564 * GetAsyncKeyState (USER32.206)
566 * Determine if a key is or was pressed. retval has high-order
567 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
570 * This uses the variable AsyncMouseButtonsStates and
571 * AsyncKeyStateTable (set in event.c) which have the mouse button
572 * number or key number (whichever is applicable) set to true if the
573 * mouse or key had been depressed since the last call to
576 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
582 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
583 (MouseButtonsStates[0] ? 0x8000 : 0);
586 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
587 (MouseButtonsStates[1] ? 0x8000 : 0);
590 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
591 (MouseButtonsStates[2] ? 0x8000 : 0);
594 retval = AsyncKeyStateTable[nKey] |
595 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
599 /* all states to false */
600 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
601 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
603 dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
607 /**********************************************************************
608 * GetAsyncKeyState (USER.249)
610 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
612 return GetAsyncKeyState32(nKey);
615 /**********************************************************************
616 * TranslateAccelerator [USER.178][USER32.551..]
618 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
620 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
621 BYTE fVirt,WORD key,WORD cmd)
623 BOOL32 sendmsg = FALSE;
625 if(msg->wParam == key)
627 if (msg->message == WM_CHAR) {
628 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
630 dprintf_accel(stddeb,"found accel for WM_CHAR: ('%c')",msg->wParam&0xff);
634 if(fVirt & FVIRTKEY) {
636 dprintf_accel(stddeb,"found accel for virt_key %04x (scan %04x)",
637 msg->wParam,0xff & HIWORD(msg->lParam));
638 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
639 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
640 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
641 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
644 dprintf_accel(stddeb,", but incorrect SHIFT/CTRL/ALT-state\n");
648 if (!(msg->lParam & 0x01000000)) /* no special_key */
650 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
651 { /* ^^ ALT pressed */
652 dprintf_accel(stddeb,"found accel for Alt-%c", msg->wParam&0xff);
659 if (sendmsg) /* found an accelerator, but send a message... ? */
661 INT16 iSysStat,iStat,mesg=0;
664 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
670 if (!IsWindowEnabled32(hWnd))
674 WND* wndPtr = WIN_FindWndPtr(hWnd);
676 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
677 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
678 cmd, MF_BYCOMMAND) : -1 ;
679 iStat = (hMenu) ? GetMenuState32(hMenu,
680 cmd, MF_BYCOMMAND) : -1 ;
684 if (iSysStat & (MF_DISABLED|MF_GRAYED))
693 if (IsIconic32(hWnd))
697 if (iStat & (MF_DISABLED|MF_GRAYED))
707 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
709 dprintf_accel(stddeb,", sending %s, wParam=%0x\n",
710 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
712 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
716 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
717 * #0: unknown (please report!)
718 * #1: for WM_KEYUP,WM_SYSKEYUP
719 * #2: mouse is captured
720 * #3: window is disabled
721 * #4: it's a disabled system menu option
722 * #5: it's a menu option, but window is iconic
723 * #6: it's a menu option, but disabled
725 dprintf_accel(stddeb,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
733 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
735 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
738 if (hAccel == 0 || msg == NULL) return 0;
739 if (msg->message != WM_KEYDOWN &&
740 msg->message != WM_KEYUP &&
741 msg->message != WM_SYSKEYDOWN &&
742 msg->message != WM_SYSKEYUP &&
743 msg->message != WM_CHAR) return 0;
745 dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
746 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
748 for (i = 0; lpAccelTbl[i].key ; i++)
749 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
750 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
755 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
757 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
761 if (hAccel == 0 || msg == NULL) return 0;
762 if (msg->message != WM_KEYDOWN &&
763 msg->message != WM_KEYUP &&
764 msg->message != WM_SYSKEYDOWN &&
765 msg->message != WM_SYSKEYUP &&
766 msg->message != WM_CHAR) return 0;
768 dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
769 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
770 STRUCT32_MSG16to32(msg,&msg32);
773 for (i=0;lpAccelTbl[i].key;i++)
774 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
775 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
781 /******************************************************************************
782 * OemKeyScan [KEYBOARD.128][USER32.400]
784 DWORD WINAPI OemKeyScan(WORD wOemChar)
786 dprintf_keyboard(stddeb,"*OemKeyScan (%d)\n",wOemChar);
791 /******************************************************************************
792 * VkKeyScanA [USER32.572]
794 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
795 * for the current keyboard.
796 * high-order byte yields :
800 * 3-5 Shift-key combinations that are not used for characters
803 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
804 * FIXME : works ok except for dead chars :
805 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
806 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
809 WORD WINAPI VkKeyScan32A(CHAR cChar)
816 /* char->keysym (same for ANSI chars) */
817 keysym=(unsigned char) cChar;/* (!) cChar is signed */
818 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
820 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
822 { /* It didn't work ... let's try with deadchar code. */
823 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
826 dprintf_keyboard(stddeb,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
827 cChar,keysym,keysym,keycode);
831 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
832 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
835 fprintf(stderr,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
837 case 1 : highbyte = 0x0100; break;
838 case 2 : highbyte = 0X0600; break;
839 default : fprintf(stderr,"index %d found by XKeycodeToKeysym. please report! \n",index);
842 index : 0 adds 0x0000
843 index : 1 adds 0x0100 (shift)
844 index : ? adds 0x0200 (ctrl)
845 index : 2 adds 0x0600 (ctrl+alt)
846 index : ? adds 0x0700 (ctrl+alt+shift (used?))
849 dprintf_keyboard(stddeb," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
850 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
853 /******************************************************************************
854 * VkKeyScan [KEYBOARD.129]
856 WORD WINAPI VkKeyScan16(CHAR cChar)
858 return VkKeyScan32A(cChar);
861 /******************************************************************************
862 * VkKeyScanW [USER32.575]
864 WORD WINAPI VkKeyScan32W(WCHAR cChar)
866 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
869 /******************************************************************************
870 * GetKeyboardType [KEYBOARD.130]
872 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
874 return GetKeyboardType32(nTypeFlag);
877 /******************************************************************************
878 * GetKeyboardType [USER32.254]
880 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
882 dprintf_keyboard(stddeb,"GetKeyboardType(%d)\n",nTypeFlag);
885 case 0: /* Keyboard type */
886 return 4; /* AT-101 */
888 case 1: /* Keyboard Subtype */
889 return 0; /* There are no defined subtypes */
891 case 2: /* Number of F-keys */
892 return 12; /* We're doing an 101 for now, so return 12 F-keys */
895 fprintf(stderr, "Unknown type on GetKeyboardType\n");
896 return 0; /* The book says 0 here, so 0 */
901 /******************************************************************************
902 * MapVirtualKeyA [USER32.382]
904 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
906 return MapVirtualKey16(code,maptype);
909 /******************************************************************************
910 * MapVirtualKeyA [USER32.384]
912 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
914 return MapVirtualKey16(code,maptype);
917 /******************************************************************************
918 * MapVirtualKeyA [KEYBOARD.131]
919 * MapVirtualKey translates keycodes from one format to another
921 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
923 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
925 dprintf_keyboard(stddeb,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode,wMapType);
927 case 0: { /* vkey-code to scan-code */
928 /* let's do vkey -> keycode -> scan */
930 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
931 if ((keyc2vkey[keyc] & 0xFF)== wCode)
932 returnMVK (keyc - 8);
935 case 1: /* scan-code to vkey-code */
936 /* let's do scan -> keycode -> vkey */
938 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
940 case 2: { /* vkey-code to unshifted ANSI code */
941 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
942 /* My Windows returns 'A'. */
943 /* let's do vkey -> keycode -> (XLookupString) ansi char */
948 e.state = 0; /* unshifted */
949 e.keycode = MapVirtualKey16( wCode, 0);
950 if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
955 default: /* reserved */
956 fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
964 /****************************************************************************
965 * GetKBCodePage16 (KEYBOARD.132)
967 INT16 WINAPI GetKBCodePage16(void)
969 dprintf_keyboard(stddeb,"GetKBCodePage()\n");
974 /****************************************************************************
975 * GetKBCodePage32 (USER32.245)
977 UINT32 WINAPI GetKBCodePage32(void)
979 dprintf_keyboard(stddeb,"GetKbCodePage()\n");
984 /****************************************************************************
985 * GetKeyNameText32W (USER32.247)
987 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
989 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
990 int res = GetKeyNameText32A(lParam,buf,nSize);
992 lstrcpynAtoW(lpBuffer,buf,nSize);
993 HeapFree( GetProcessHeap(), 0, buf );
997 /****************************************************************************
998 * GetKeyNameText32A (USER32.246)
1000 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1002 return GetKeyNameText16(lParam,lpBuffer,nSize);
1005 /****************************************************************************
1006 * GetKeyNameText16 (KEYBOARD.133)
1008 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1012 dprintf_keyboard(stddeb,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam,nSize);
1017 /* for (i = 0 ; i != KeyTableSize ; i++)
1018 if (KeyTable[i].scancode == lParam) {
1019 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1020 return strlen(lpBuffer);
1023 /* FIXME ! GetKeyNameText is still to do...
1030 /****************************************************************************
1031 * ToAscii (KEYBOARD.4)
1033 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1034 LPVOID lpChar, UINT16 flags)
1036 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1039 /****************************************************************************
1040 * ToAscii (USER32.545)
1042 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1043 LPWORD lpChar,UINT32 flags )
1047 static XComposeStatus cs;
1051 e.display = display;
1053 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1054 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1055 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1056 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... */
1058 if ((e.keycode) && ((virtKey<0x10) || (virtKey>0x12)))
1059 /* it's normal to have 2 shift, control, and alt ! */
1060 dprintf_keyboard(stddeb,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1061 e.keycode,keyc,virtKey);
1065 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1067 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1068 e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1069 if (virtKey==VK_DECIMAL)
1070 e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1074 fprintf(stderr,"ToAscii : Unknown virtual key %X !!! \n",virtKey);
1075 return virtKey; /* whatever */
1078 if (lpKeyState[VK_SHIFT] & 0x80)
1079 e.state |= ShiftMask;
1080 dprintf_keyboard(stddeb,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState[VK_CAPITAL]);
1081 if (lpKeyState[VK_CAPITAL] & 0x01)
1082 e.state |= LockMask;
1083 if (lpKeyState[VK_CONTROL] & 0x80)
1084 if (lpKeyState[VK_MENU] & 0x80)
1085 e.state |= AltGrMask;
1087 e.state |= ControlMask;
1088 if (lpKeyState[VK_NUMLOCK] & 0x01)
1089 e.state |= NumLockMask;
1090 dprintf_key(stddeb, "ToAscii(%04X, %04X) : faked state = %X\n",
1091 virtKey, scanCode, e.state);
1092 ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1097 ((char*)lpChar)[1] = '\0';
1100 /* symbolic ASCII is the same as defined in rfc1345 */
1101 #ifdef XK_dead_tilde
1102 case XK_dead_tilde :
1104 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1105 dead_char = '~'; /* '? */
1107 #ifdef XK_dead_acute
1108 case XK_dead_acute :
1110 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1111 dead_char = 0xb4; /* '' */
1113 #ifdef XK_dead_circumflex
1114 case XK_dead_circumflex :
1116 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1117 dead_char = '^'; /* '> */
1119 #ifdef XK_dead_grave
1120 case XK_dead_grave :
1122 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1123 dead_char = '`'; /* '! */
1125 #ifdef XK_dead_diaeresis
1126 case XK_dead_diaeresis :
1128 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1129 dead_char = 0xa8; /* ': */
1131 #ifdef XK_dead_cedilla
1132 case XK_dead_cedilla :
1133 dead_char = 0xb8; /* ', */
1136 #ifdef XK_dead_macron
1137 case XK_dead_macron :
1138 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1141 #ifdef XK_dead_breve
1142 case XK_dead_breve :
1143 dead_char = 0xa2; /* '( */
1146 #ifdef XK_dead_abovedot
1147 case XK_dead_abovedot :
1148 dead_char = 0xff; /* '. */
1151 #ifdef XK_dead_abovering
1152 case XK_dead_abovering :
1153 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1156 #ifdef XK_dead_doubleacute
1157 case XK_dead_doubleacute :
1158 dead_char = 0xbd; /* '" */
1161 #ifdef XK_dead_caron
1162 case XK_dead_caron :
1163 dead_char = 0xb7; /* '< */
1166 #ifdef XK_dead_ogonek
1167 case XK_dead_ogonek :
1168 dead_char = 0xb2; /* '; */
1171 /* FIXME: I don't know this three.
1175 case XK_dead_voiced_sound :
1178 case XK_dead_semivoiced_sound :
1185 *(char*)lpChar = dead_char;
1192 ksname = TSXKeysymToString(keysym);
1195 if ((keysym >> 8) != 0xff)
1197 fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
1199 fprintf(stderr, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1200 virtKey, scanCode, e.keycode, e.state);
1204 dprintf_key(stddeb, "ToAscii about to return %d with char %x\n",
1205 ret, *(char*)lpChar);
1210 /***********************************************************************
1211 * GetKeyboardLayout (USER32.249)
1213 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1215 fprintf(stderr,"GetKeyboardLayout(%ld),STUB!\n",dwLayout);
1216 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1219 /***********************************************************************
1220 * GetKeyboardLayoutList (USER32.250)
1223 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1225 fprintf(stderr,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff,layouts);
1227 layouts[0] = GetKeyboardLayout(0);
1232 /***********************************************************************
1233 * RegisterHotKey (USER32.433)
1235 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1236 fprintf(stderr,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1237 hwnd,id,modifiers,vk
1242 /***********************************************************************
1243 * UnregisterHotKey (USER32.565)
1245 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1246 fprintf(stderr,"UnregisterHotKey(%08x,%d),stub!\n",hwnd,id);