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 * CreateAcceleratorTable (USER.64)
618 HACCEL32 WINAPI
CreateAcceleratorTable32A(LPACCEL32 lpaccel
, INT32 cEntries
) {
619 fprintf(stderr
, "CreateAcceleratorTable32A Stub\n");
623 /**********************************************************************
624 * TranslateAccelerator [USER.178][USER32.551..]
626 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
628 static BOOL32
KBD_translate_accelerator(HWND32 hWnd
,LPMSG32 msg
,
629 BYTE fVirt
,WORD key
,WORD cmd
)
631 BOOL32 sendmsg
= FALSE
;
633 if(msg
->wParam
== key
)
635 if (msg
->message
== WM_CHAR
) {
636 if ( !(fVirt
& FALT
) && !(fVirt
& FVIRTKEY
) )
638 dprintf_accel(stddeb
,"found accel for WM_CHAR: ('%c')",msg
->wParam
&0xff);
642 if(fVirt
& FVIRTKEY
) {
644 dprintf_accel(stddeb
,"found accel for virt_key %04x (scan %04x)",
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_accel(stddeb
,", 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_accel(stddeb
,"found accel for Alt-%c", 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_accel(stddeb
,", 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_accel(stddeb
,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg
);
741 INT32 WINAPI
TranslateAccelerator32(HWND32 hWnd
, HACCEL32 hAccel
, LPMSG32 msg
)
743 LPACCEL32 lpAccelTbl
= (LPACCEL32
)LockResource32(hAccel
);
746 if (hAccel
== 0 || msg
== NULL
) return 0;
747 if (msg
->message
!= WM_KEYDOWN
&&
748 msg
->message
!= WM_KEYUP
&&
749 msg
->message
!= WM_SYSKEYDOWN
&&
750 msg
->message
!= WM_SYSKEYUP
&&
751 msg
->message
!= WM_CHAR
) return 0;
753 dprintf_accel(stddeb
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
754 msg->hwnd=%04x, msg->message=%04x\n", hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
756 for (i
= 0; lpAccelTbl
[i
].key
; i
++)
757 if (KBD_translate_accelerator(hWnd
,msg
,lpAccelTbl
[i
].fVirt
,
758 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
763 INT16 WINAPI
TranslateAccelerator16(HWND16 hWnd
, HACCEL16 hAccel
, LPMSG16 msg
)
765 LPACCEL16 lpAccelTbl
= (LPACCEL16
)LockResource16(hAccel
);
769 if (hAccel
== 0 || msg
== NULL
) return 0;
770 if (msg
->message
!= WM_KEYDOWN
&&
771 msg
->message
!= WM_KEYUP
&&
772 msg
->message
!= WM_SYSKEYDOWN
&&
773 msg
->message
!= WM_SYSKEYUP
&&
774 msg
->message
!= WM_CHAR
) return 0;
776 dprintf_accel(stddeb
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
777 msg->hwnd=%04x, msg->message=%04x\n", hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
778 STRUCT32_MSG16to32(msg
,&msg32
);
781 for (i
=0;lpAccelTbl
[i
].key
;i
++)
782 if (KBD_translate_accelerator(hWnd
,&msg32
,lpAccelTbl
[i
].fVirt
,
783 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
789 /******************************************************************************
790 * OemKeyScan [KEYBOARD.128][USER32.400]
792 DWORD WINAPI
OemKeyScan(WORD wOemChar
)
794 dprintf_keyboard(stddeb
,"*OemKeyScan (%d)\n",wOemChar
);
799 /******************************************************************************
800 * VkKeyScanA [USER32.572]
802 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
803 * for the current keyboard.
804 * high-order byte yields :
808 * 3-5 Shift-key combinations that are not used for characters
811 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
812 * FIXME : works ok except for dead chars :
813 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
814 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
817 WORD WINAPI
VkKeyScan32A(CHAR cChar
)
824 /* char->keysym (same for ANSI chars) */
825 keysym
=(unsigned char) cChar
;/* (!) cChar is signed */
826 if (keysym
<=27) keysym
+=0xFF00;/*special chars : return, backspace...*/
828 keycode
= TSXKeysymToKeycode(display
, keysym
); /* keysym -> keycode */
830 { /* It didn't work ... let's try with deadchar code. */
831 keycode
= TSXKeysymToKeycode(display
, keysym
| 0xFE00);
834 dprintf_keyboard(stddeb
,"VkKeyScan '%c'(%#lx, %lu) : got keycode %#.2x ",
835 cChar
,keysym
,keysym
,keycode
);
839 for (index
=-1, i
=0; (i
<8) && (index
<0); i
++) /* find shift state */
840 if (TSXKeycodeToKeysym(display
,keycode
,i
)==keysym
) index
=i
;
843 fprintf(stderr
,"Keysym %lx not found while parsing the keycode table\n",keysym
); break;
845 case 1 : highbyte
= 0x0100; break;
846 case 2 : highbyte
= 0X0600; break;
847 default : fprintf(stderr
,"index %d found by XKeycodeToKeysym. please report! \n",index
);
850 index : 0 adds 0x0000
851 index : 1 adds 0x0100 (shift)
852 index : ? adds 0x0200 (ctrl)
853 index : 2 adds 0x0600 (ctrl+alt)
854 index : ? adds 0x0700 (ctrl+alt+shift (used?))
857 dprintf_keyboard(stddeb
," ... returning %#.2x\n", keyc2vkey
[keycode
]+highbyte
);
858 return keyc2vkey
[keycode
]+highbyte
; /* keycode -> (keyc2vkey) vkey */
861 /******************************************************************************
862 * VkKeyScan [KEYBOARD.129]
864 WORD WINAPI
VkKeyScan16(CHAR cChar
)
866 return VkKeyScan32A(cChar
);
869 /******************************************************************************
870 * VkKeyScanW [USER32.575]
872 WORD WINAPI
VkKeyScan32W(WCHAR cChar
)
874 return VkKeyScan32A((CHAR
)cChar
); /* FIXME: check unicode */
877 /******************************************************************************
878 * GetKeyboardType [KEYBOARD.130]
880 INT16 WINAPI
GetKeyboardType16(INT16 nTypeFlag
)
882 return GetKeyboardType32(nTypeFlag
);
885 /******************************************************************************
886 * GetKeyboardType [USER32.254]
888 INT32 WINAPI
GetKeyboardType32(INT32 nTypeFlag
)
890 dprintf_keyboard(stddeb
,"GetKeyboardType(%d)\n",nTypeFlag
);
893 case 0: /* Keyboard type */
894 return 4; /* AT-101 */
896 case 1: /* Keyboard Subtype */
897 return 0; /* There are no defined subtypes */
899 case 2: /* Number of F-keys */
900 return 12; /* We're doing an 101 for now, so return 12 F-keys */
903 fprintf(stderr
, "Unknown type on GetKeyboardType\n");
904 return 0; /* The book says 0 here, so 0 */
909 /******************************************************************************
910 * MapVirtualKeyA [USER32.382]
912 UINT32 WINAPI
MapVirtualKey32A(UINT32 code
, UINT32 maptype
)
914 return MapVirtualKey16(code
,maptype
);
917 /******************************************************************************
918 * MapVirtualKeyA [USER32.384]
920 UINT32 WINAPI
MapVirtualKey32W(UINT32 code
, UINT32 maptype
)
922 return MapVirtualKey16(code
,maptype
);
925 /******************************************************************************
926 * MapVirtualKeyA [KEYBOARD.131]
927 * MapVirtualKey translates keycodes from one format to another
929 UINT16 WINAPI
MapVirtualKey16(UINT16 wCode
, UINT16 wMapType
)
931 #define returnMVK(value) { dprintf_keyboard(stddeb,"returning 0x%x.\n",value); return value; }
933 dprintf_keyboard(stddeb
,"MapVirtualKey wCode=0x%x wMapType=%d ... ",wCode
,wMapType
);
935 case 0: { /* vkey-code to scan-code */
936 /* let's do vkey -> keycode -> scan */
938 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++) /* see event.c */
939 if ((keyc2vkey
[keyc
] & 0xFF)== wCode
)
940 returnMVK (keyc
- 8);
943 case 1: /* scan-code to vkey-code */
944 /* let's do scan -> keycode -> vkey */
946 returnMVK (keyc2vkey
[(wCode
& 0xFF) + 8]);
948 case 2: { /* vkey-code to unshifted ANSI code */
949 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
950 /* My Windows returns 'A'. */
951 /* let's do vkey -> keycode -> (XLookupString) ansi char */
956 e
.state
= 0; /* unshifted */
957 e
.keycode
= MapVirtualKey16( wCode
, 0);
958 if (!TSXLookupString(&e
, s
, 2 , &keysym
, NULL
))
963 default: /* reserved */
964 fprintf(stderr
, "MapVirtualKey: unknown wMapType %d !\n",
972 /****************************************************************************
973 * GetKBCodePage16 (KEYBOARD.132)
975 INT16 WINAPI
GetKBCodePage16(void)
977 dprintf_keyboard(stddeb
,"GetKBCodePage()\n");
982 /****************************************************************************
983 * GetKBCodePage32 (USER32.245)
985 UINT32 WINAPI
GetKBCodePage32(void)
987 dprintf_keyboard(stddeb
,"GetKbCodePage()\n");
992 /****************************************************************************
993 * GetKeyNameText32W (USER32.247)
995 INT32 WINAPI
GetKeyNameText32W(LONG lParam
, LPWSTR lpBuffer
, INT32 nSize
)
997 LPSTR buf
= HEAP_xalloc( GetProcessHeap(), 0, nSize
);
998 int res
= GetKeyNameText32A(lParam
,buf
,nSize
);
1000 lstrcpynAtoW(lpBuffer
,buf
,nSize
);
1001 HeapFree( GetProcessHeap(), 0, buf
);
1005 /****************************************************************************
1006 * GetKeyNameText32A (USER32.246)
1008 INT32 WINAPI
GetKeyNameText32A(LONG lParam
, LPSTR lpBuffer
, INT32 nSize
)
1010 return GetKeyNameText16(lParam
,lpBuffer
,nSize
);
1013 /****************************************************************************
1014 * GetKeyNameText16 (KEYBOARD.133)
1016 INT16 WINAPI
GetKeyNameText16(LONG lParam
, LPSTR lpBuffer
, INT16 nSize
)
1020 dprintf_keyboard(stddeb
,"GetKeyNameText(%ld,<ptr>,%d)\n",lParam
,nSize
);
1025 /* for (i = 0 ; i != KeyTableSize ; i++)
1026 if (KeyTable[i].scancode == lParam) {
1027 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1028 return strlen(lpBuffer);
1031 /* FIXME ! GetKeyNameText is still to do...
1038 /****************************************************************************
1039 * ToAscii (KEYBOARD.4)
1041 INT16 WINAPI
ToAscii16(UINT16 virtKey
,UINT16 scanCode
, LPBYTE lpKeyState
,
1042 LPVOID lpChar
, UINT16 flags
)
1044 return ToAscii32(virtKey
,scanCode
,lpKeyState
,lpChar
,flags
);
1047 /****************************************************************************
1048 * ToAscii (USER32.545)
1050 INT32 WINAPI
ToAscii32( UINT32 virtKey
,UINT32 scanCode
,LPBYTE lpKeyState
,
1051 LPWORD lpChar
,UINT32 flags
)
1055 static XComposeStatus cs
;
1059 e
.display
= display
;
1061 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
1062 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1063 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1064 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... */
1066 if ((e
.keycode
) && ((virtKey
<0x10) || (virtKey
>0x12)))
1067 /* it's normal to have 2 shift, control, and alt ! */
1068 dprintf_keyboard(stddeb
,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1069 e
.keycode
,keyc
,virtKey
);
1073 if ((!e
.keycode
) && (lpKeyState
[VK_NUMLOCK
] & 0x01))
1075 if ((virtKey
>=VK_NUMPAD0
) && (virtKey
<=VK_NUMPAD9
))
1076 e
.keycode
= TSXKeysymToKeycode(e
.display
, virtKey
-VK_NUMPAD0
+XK_KP_0
);
1077 if (virtKey
==VK_DECIMAL
)
1078 e
.keycode
= TSXKeysymToKeycode(e
.display
, XK_KP_Decimal
);
1082 fprintf(stderr
,"ToAscii : Unknown virtual key %X !!! \n",virtKey
);
1083 return virtKey
; /* whatever */
1086 if (lpKeyState
[VK_SHIFT
] & 0x80)
1087 e
.state
|= ShiftMask
;
1088 dprintf_keyboard(stddeb
,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState
[VK_CAPITAL
]);
1089 if (lpKeyState
[VK_CAPITAL
] & 0x01)
1090 e
.state
|= LockMask
;
1091 if (lpKeyState
[VK_CONTROL
] & 0x80)
1092 if (lpKeyState
[VK_MENU
] & 0x80)
1093 e
.state
|= AltGrMask
;
1095 e
.state
|= ControlMask
;
1096 if (lpKeyState
[VK_NUMLOCK
] & 0x01)
1097 e
.state
|= NumLockMask
;
1098 dprintf_key(stddeb
, "ToAscii(%04X, %04X) : faked state = %X\n",
1099 virtKey
, scanCode
, e
.state
);
1100 ret
= TSXLookupString(&e
, (LPVOID
)lpChar
, 2, &keysym
, &cs
);
1105 ((char*)lpChar
)[1] = '\0';
1108 /* symbolic ASCII is the same as defined in rfc1345 */
1109 #ifdef XK_dead_tilde
1110 case XK_dead_tilde
:
1112 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1113 dead_char
= '~'; /* '? */
1115 #ifdef XK_dead_acute
1116 case XK_dead_acute
:
1118 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1119 dead_char
= 0xb4; /* '' */
1121 #ifdef XK_dead_circumflex
1122 case XK_dead_circumflex
:
1124 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1125 dead_char
= '^'; /* '> */
1127 #ifdef XK_dead_grave
1128 case XK_dead_grave
:
1130 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1131 dead_char
= '`'; /* '! */
1133 #ifdef XK_dead_diaeresis
1134 case XK_dead_diaeresis
:
1136 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1137 dead_char
= 0xa8; /* ': */
1139 #ifdef XK_dead_cedilla
1140 case XK_dead_cedilla
:
1141 dead_char
= 0xb8; /* ', */
1144 #ifdef XK_dead_macron
1145 case XK_dead_macron
:
1146 dead_char
= '-'; /* 'm isn't defined on iso-8859-x */
1149 #ifdef XK_dead_breve
1150 case XK_dead_breve
:
1151 dead_char
= 0xa2; /* '( */
1154 #ifdef XK_dead_abovedot
1155 case XK_dead_abovedot
:
1156 dead_char
= 0xff; /* '. */
1159 #ifdef XK_dead_abovering
1160 case XK_dead_abovering
:
1161 dead_char
= '0'; /* '0 isn't defined on iso-8859-x */
1164 #ifdef XK_dead_doubleacute
1165 case XK_dead_doubleacute
:
1166 dead_char
= 0xbd; /* '" */
1169 #ifdef XK_dead_caron
1170 case XK_dead_caron
:
1171 dead_char
= 0xb7; /* '< */
1174 #ifdef XK_dead_ogonek
1175 case XK_dead_ogonek
:
1176 dead_char
= 0xb2; /* '; */
1179 /* FIXME: I don't know this three.
1183 case XK_dead_voiced_sound :
1186 case XK_dead_semivoiced_sound :
1193 *(char*)lpChar
= dead_char
;
1200 ksname
= TSXKeysymToString(keysym
);
1203 if ((keysym
>> 8) != 0xff)
1205 fprintf(stderr
, "Please report : no char for keysym %04lX (%s) :\n",
1207 fprintf(stderr
, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1208 virtKey
, scanCode
, e
.keycode
, e
.state
);
1212 dprintf_key(stddeb
, "ToAscii about to return %d with char %x\n",
1213 ret
, *(char*)lpChar
);
1218 /***********************************************************************
1219 * GetKeyboardLayout (USER32.249)
1221 HKL32 WINAPI
GetKeyboardLayout(DWORD dwLayout
)
1223 fprintf(stderr
,"GetKeyboardLayout(%ld),STUB!\n",dwLayout
);
1224 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1227 /***********************************************************************
1228 * GetKeyboardLayoutList (USER32.250)
1231 INT32 WINAPI
GetKeyboardLayoutList(INT32 nBuff
,HKL32
*layouts
)
1233 fprintf(stderr
,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff
,layouts
);
1235 layouts
[0] = GetKeyboardLayout(0);
1240 /***********************************************************************
1241 * RegisterHotKey (USER32.433)
1243 BOOL32 WINAPI
RegisterHotKey(HWND32 hwnd
,INT32 id
,UINT32 modifiers
,UINT32 vk
) {
1244 fprintf(stderr
,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1245 hwnd
,id
,modifiers
,vk
1250 /***********************************************************************
1251 * UnregisterHotKey (USER32.565)
1253 BOOL32 WINAPI
UnregisterHotKey(HWND32 hwnd
,INT32 id
) {
1254 fprintf(stderr
,"UnregisterHotKey(%08x,%d),stub!\n",hwnd
,id
);