4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
8 * Copyright 1998 Ulrich Weigand
13 #ifndef X_DISPLAY_MISSING
15 #include <X11/Xatom.h>
16 #include <X11/keysym.h>
18 #include "ts_xresource.h"
26 extern LPBYTE pKeyStateTable
;
28 int min_keycode
, max_keycode
, keysyms_per_keycode
;
31 static int NumLockMask
, AltGrMask
; /* mask in the XKeyEvent state */
32 static int kcControl
, kcAlt
, kcShift
, kcNumLock
, kcCapsLock
; /* keycodes */
34 /* Keyboard translation tables */
35 static const int special_key
[] =
37 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
38 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
39 0, 0, 0, VK_ESCAPE
/* FF18 */
42 static const int cursor_key
[] =
44 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
45 VK_NEXT
, VK_END
/* FF50 */
48 static const int misc_key
[] =
50 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
51 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
54 static const int keypad_key
[] =
56 0, VK_NUMLOCK
, /* FF7E */
57 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
58 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
59 0, 0, 0, 0, 0, VK_HOME
, VK_LEFT
, VK_UP
, /* FF90 */
60 VK_RIGHT
, VK_DOWN
, VK_PRIOR
, VK_NEXT
, VK_END
, 0,
61 VK_INSERT
, VK_DELETE
, /* FF98 */
62 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
63 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
64 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
65 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
66 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
67 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
70 static const int function_key
[] =
72 VK_F1
, VK_F2
, /* FFBE */
73 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
74 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
77 static const int modifier_key
[] =
79 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
, 0, /* FFE1 */
80 VK_MENU
, VK_MENU
, VK_MENU
, VK_MENU
/* FFE7 */
83 /* Returns the Windows virtual key code associated with the X event <e> */
84 static WORD
EVENT_event_to_vkey( XKeyEvent
*e
)
88 TSXLookupString(e
, NULL
, 0, &keysym
, NULL
);
90 if ((keysym
>= 0xFFAE) && (keysym
<= 0xFFB9) && (e
->state
& NumLockMask
))
91 /* Only the Keypad keys 0-9 and . send different keysyms
92 * depending on the NumLock state */
93 return keypad_key
[(keysym
& 0xFF) - 0x7E];
95 return keyc2vkey
[e
->keycode
];
98 static BOOL32 NumState
=FALSE
, CapsState
=FALSE
;
100 /**********************************************************************
101 * KEYBOARD_GenerateMsg
103 * Generate Down+Up messages when NumLock or CapsLock is pressed.
105 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
108 void KEYBOARD_GenerateMsg( WORD vkey
, int Evtype
, INT32 event_x
, INT32 event_y
,
111 BOOL32
* State
= (vkey
==VK_NUMLOCK
? &NumState
: &CapsState
);
114 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
115 don't treat it. It's from the same key press. Then the state goes to ON.
116 And from there, a 'release' event will switch off the toggle key. */
118 TRACE(keyboard
,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey
,pKeyStateTable
[vkey
]);
121 if ( pKeyStateTable
[vkey
] & 0x1 ) /* it was ON */
123 if (Evtype
!=KeyPress
)
125 TRACE(keyboard
,"ON + KeyRelease => generating DOWN and UP messages.\n");
126 KEYBOARD_SendEvent( vkey
, 0, 0,
127 event_x
, event_y
, event_time
);
128 KEYBOARD_SendEvent( vkey
, 0, KEYEVENTF_KEYUP
,
129 event_x
, event_y
, event_time
);
131 pKeyStateTable
[vkey
] &= ~0x01; /* Toggle state to off. */
134 else /* it was OFF */
135 if (Evtype
==KeyPress
)
137 TRACE(keyboard
,"OFF + Keypress => generating DOWN and UP messages.\n");
138 KEYBOARD_SendEvent( vkey
, 0, 0,
139 event_x
, event_y
, event_time
);
140 KEYBOARD_SendEvent( vkey
, 0, KEYEVENTF_KEYUP
,
141 event_x
, event_y
, event_time
);
142 *State
=TRUE
; /* Goes to intermediary state before going to ON */
143 pKeyStateTable
[vkey
] |= 0x01; /* Toggle state to on. */
148 /***********************************************************************
149 * KEYBOARD_UpdateOneState
151 * Updates internal state for <vkey>, depending on key <state> under X
154 void KEYBOARD_UpdateOneState ( int vkey
, int state
)
156 /* Do something if internal table state != X state for keycode */
157 if (((pKeyStateTable
[vkey
] & 0x80)!=0) != state
)
159 TRACE(keyboard
,"Adjusting state for vkey %#.2x. State before %#.2x \n",
160 vkey
, pKeyStateTable
[vkey
]);
162 /* Fake key being pressed inside wine */
163 KEYBOARD_SendEvent( vkey
, 0, state
? 0 : KEYEVENTF_KEYUP
,
164 0, 0, GetTickCount() );
166 TRACE(keyboard
,"State after %#.2x \n",pKeyStateTable
[vkey
]);
170 /***********************************************************************
171 * KEYBOARD_UpdateState
173 * Update modifiers state (Ctrl, Alt, Shift)
174 * when window is activated (called by EVENT_FocusIn in event.c)
176 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
177 * from wine to another application and back.
178 * Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
181 void KEYBOARD_UpdateState ( void )
183 /* extract a bit from the char[32] bit suite */
184 #define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
186 char keys_return
[32];
188 TRACE(keyboard
,"called\n");
189 if (!TSXQueryKeymap(display
, keys_return
)) {
190 ERR(keyboard
,"Error getting keymap !");
194 /* Adjust the ALT and CONTROL state if any has been changed outside wine */
195 KEYBOARD_UpdateOneState(VK_MENU
, KeyState(kcAlt
));
196 KEYBOARD_UpdateOneState(VK_CONTROL
, KeyState(kcControl
));
197 KEYBOARD_UpdateOneState(VK_SHIFT
, KeyState(kcShift
));
201 /***********************************************************************
202 * KEYBOARD_HandleEvent
204 * Handle a X key event
206 void KEYBOARD_HandleEvent( WND
*pWnd
, XKeyEvent
*event
)
211 WORD vkey
= 0, bScan
;
213 static BOOL32 force_extended
= FALSE
; /* hack for AltGr translation */
217 INT32 event_x
= (pWnd
? pWnd
->rectWindow
.left
: 0) + event
->x
;
218 INT32 event_y
= (pWnd
? pWnd
->rectWindow
.top
: 0) + event
->y
;
219 DWORD event_time
= event
->time
- MSG_WineStartTicks
;
221 /* this allows support for dead keys */
222 if ((event
->keycode
>> 8) == 0x10)
223 event
->keycode
=(event
->keycode
& 0xff);
225 ascii_chars
= TSXLookupString(event
, Str
, 1, &keysym
, &cs
);
227 TRACE(key
, "EVENT_key : state = %X\n", event
->state
);
228 if (keysym
== XK_Mode_switch
)
230 TRACE(key
, "Alt Gr key event received\n");
231 event
->keycode
= kcControl
; /* Simulate Control */
232 KEYBOARD_HandleEvent( pWnd
, event
);
234 event
->keycode
= kcAlt
; /* Simulate Alt */
235 force_extended
= TRUE
;
236 KEYBOARD_HandleEvent( pWnd
, event
);
237 force_extended
= FALSE
;
241 Str
[ascii_chars
] = '\0';
245 ksname
= TSXKeysymToString(keysym
);
248 TRACE(key
, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
249 (event
->type
== KeyPress
) ? "KeyPress" : "KeyRelease",
250 keysym
, ksname
, ascii_chars
, Str
[0] & 0xff, Str
);
253 vkey
= EVENT_event_to_vkey(event
);
254 if (force_extended
) vkey
|= 0x100;
256 TRACE(key
, "keycode 0x%x converted to vkey 0x%x\n",
257 event
->keycode
, vkey
);
264 KEYBOARD_GenerateMsg( VK_NUMLOCK
, event
->type
, event_x
, event_y
,
268 TRACE(keyboard
,"Caps Lock event. (type %d). State before : %#.2x\n",event
->type
,pKeyStateTable
[vkey
]);
269 KEYBOARD_GenerateMsg( VK_CAPITAL
, event
->type
, event_x
, event_y
,
271 TRACE(keyboard
,"State after : %#.2x\n",pKeyStateTable
[vkey
]);
274 /* Adjust the NUMLOCK state if it has been changed outside wine */
275 if (!(pKeyStateTable
[VK_NUMLOCK
] & 0x01) != !(event
->state
& NumLockMask
))
277 TRACE(keyboard
,"Adjusting NumLock state. \n");
278 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyPress
, event_x
, event_y
,
280 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyRelease
, event_x
, event_y
,
283 /* Adjust the CAPSLOCK state if it has been changed outside wine */
284 if (!(pKeyStateTable
[VK_CAPITAL
] & 0x01) != !(event
->state
& LockMask
))
286 TRACE(keyboard
,"Adjusting Caps Lock state.\n");
287 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyPress
, event_x
, event_y
,
289 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyRelease
, event_x
, event_y
,
292 /* Not Num nor Caps : end of intermediary states for both. */
297 /* Windows expects extended keys to generate the unexetended scan
298 code and then set the extended flag */
299 case XK_Control_R
: bScan
= TSXKeysymToKeycode(display
, XK_Control_L
); break;
300 case XK_Alt_R
: bScan
= TSXKeysymToKeycode(display
, XK_Alt_L
); break;
301 case XK_Insert
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Insert
); break;
302 case XK_Delete
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Delete
); break;
303 case XK_Home
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Home
); break;
304 case XK_End
: bScan
= TSXKeysymToKeycode(display
, XK_KP_End
); break;
305 case XK_Prior
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Prior
); break;
306 case XK_Next
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Next
); break;
307 case XK_Left
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Left
); break;
308 case XK_Up
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Up
); break;
309 case XK_Right
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Right
); break;
310 case XK_Down
: bScan
= TSXKeysymToKeycode(display
, XK_KP_Down
); break;
311 case XK_KP_Divide
: bScan
= TSXKeysymToKeycode(display
, XK_slash
); break;
312 case XK_KP_Enter
: bScan
= TSXKeysymToKeycode(display
, XK_Return
); break;
314 bScan
= event
->keycode
;
317 bScan
-= min_keycode
- 1; /* Windows starts from 1,
318 X from min_keycode (8 usually) */
319 TRACE(key
, "bScan = 0x%02x.\n", bScan
);
322 if ( event
->type
== KeyRelease
) dwFlags
|= KEYEVENTF_KEYUP
;
323 if ( vkey
& 0x100 ) dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
324 if ( force_extended
) dwFlags
|= KEYEVENTF_WINE_FORCEEXTENDED
;
326 KEYBOARD_SendEvent( vkey
& 0xff, bScan
, dwFlags
,
327 event_x
, event_y
, event_time
);
332 /**********************************************************************
333 * X11DRV_KEYBOARD_Init
335 void X11DRV_KEYBOARD_Init(void)
339 XModifierKeymap
*mmp
;
346 TSXDisplayKeycodes(display
, &min_keycode
, &max_keycode
);
347 ksp
= TSXGetKeyboardMapping(display
, min_keycode
,
348 max_keycode
+ 1 - min_keycode
, &keysyms_per_keycode
);
349 /* We are only interested in keysyms_per_keycode.
350 There is no need to hold a local copy of the keysyms table */
352 mmp
= TSXGetModifierMapping(display
);
353 kcp
= mmp
->modifiermap
;
354 for (i
= 0; i
< 8; i
+= 1) /* There are 8 modifier keys */
358 for (j
= 0; j
< mmp
->max_keypermod
; j
+= 1, kcp
+= 1)
363 for (k
= 0; k
< keysyms_per_keycode
; k
+= 1)
364 if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Mode_switch
)
367 TRACE(key
, "AltGrMask is %x\n", AltGrMask
);
369 else if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Num_Lock
)
371 NumLockMask
= 1 << i
;
372 TRACE(key
, "NumLockMask is %x\n", NumLockMask
);
376 TSXFreeModifiermap(mmp
);
378 /* Now build two conversion arrays :
379 * keycode -> vkey + extended
380 * vkey + extended -> keycode */
382 e2
.display
= display
;
385 OEMvkey
= VK_OEM_7
; /* next is available. */
386 for (keyc
= min_keycode
; keyc
<= max_keycode
; keyc
++)
388 e2
.keycode
= (KeyCode
)keyc
;
389 TSXLookupString(&e2
, NULL
, 0, &keysym
, NULL
);
391 if (keysym
) /* otherwise, keycode not used */
393 if ((keysym
>> 8) == 0xFF) /* non-character key */
395 int key
= keysym
& 0xff;
397 if (key
>= 0x08 && key
<= 0x1B) /* special key */
398 vkey
= special_key
[key
- 0x08];
399 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
400 vkey
= cursor_key
[key
- 0x50];
401 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
402 vkey
= misc_key
[key
- 0x60];
403 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
404 vkey
= keypad_key
[key
- 0x7E];
405 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
407 vkey
= function_key
[key
- 0xBE];
408 vkey
|= 0x100; /* set extended bit */
410 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
411 vkey
= modifier_key
[key
- 0xE1];
412 else if (key
== 0xFF) /* DEL key */
414 /* extended must also be set for ALT_R, CTRL_R,
415 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
416 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
417 /* FIXME should we set extended bit for NumLock ? My
418 * Windows does ... DF */
438 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
440 keysym
= TSXLookupKeysym(&e2
, i
);
441 if ((keysym
>= VK_0
&& keysym
<= VK_9
)
442 || (keysym
>= VK_A
&& keysym
<= VK_Z
)
443 || keysym
== VK_SPACE
)
447 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
449 keysym
= TSXLookupKeysym(&e2
, i
);
452 case ';': vkey
= VK_OEM_1
; break;
453 case '/': vkey
= VK_OEM_2
; break;
454 case '`': vkey
= VK_OEM_3
; break;
455 case '[': vkey
= VK_OEM_4
; break;
456 case '\\': vkey
= VK_OEM_5
; break;
457 case ']': vkey
= VK_OEM_6
; break;
458 case '\'': vkey
= VK_OEM_7
; break;
459 case ',': vkey
= VK_OEM_COMMA
; break;
460 case '.': vkey
= VK_OEM_PERIOD
; break;
461 case '-': vkey
= VK_OEM_MINUS
; break;
462 case '+': vkey
= VK_OEM_PLUS
; break;
468 /* Others keys: let's assign OEM virtual key codes in the allowed range,
469 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
472 case 0xc1 : OEMvkey
=0xdb; break;
473 case 0xe5 : OEMvkey
=0xe9; break;
474 case 0xf6 : OEMvkey
=0xf5; WARN(keyboard
,"No more OEM vkey available!\n");
479 if (TRACE_ON(keyboard
))
481 dbg_decl_str(keyboard
, 1024);
483 TRACE(keyboard
, "OEM specific virtual key %X assigned "
484 "to keycode %X:\n", OEMvkey
, e2
.keycode
);
485 for (i
= 0; i
< keysyms_per_keycode
; i
+= 1)
489 keysym
= TSXLookupKeysym(&e2
, i
);
490 ksname
= TSXKeysymToString(keysym
);
493 dsprintf(keyboard
, "%lX (%s) ", keysym
, ksname
);
495 TRACE(keyboard
, "(%s)\n", dbg_str(keyboard
));
499 keyc2vkey
[e2
.keycode
] = vkey
;
501 /* Now store one keycode for each modifier. Used to simulate keypresses. */
502 kcControl
= TSXKeysymToKeycode(display
, XK_Control_L
);
503 kcAlt
= TSXKeysymToKeycode(display
, XK_Alt_L
);
504 if (!kcAlt
) kcAlt
= TSXKeysymToKeycode(display
, XK_Meta_L
);
505 kcShift
= TSXKeysymToKeycode(display
, XK_Shift_L
);
506 kcNumLock
= TSXKeysymToKeycode(display
, XK_Num_Lock
);
507 kcCapsLock
= TSXKeysymToKeycode(display
, XK_Caps_Lock
);
510 /***********************************************************************
511 * X11DRV_KEYBOARD_VkKeyScan
513 WORD
X11DRV_KEYBOARD_VkKeyScan(CHAR cChar
)
520 /* char->keysym (same for ANSI chars) */
521 keysym
=(unsigned char) cChar
;/* (!) cChar is signed */
522 if (keysym
<=27) keysym
+=0xFF00;/*special chars : return, backspace...*/
524 keycode
= TSXKeysymToKeycode(display
, keysym
); /* keysym -> keycode */
526 { /* It didn't work ... let's try with deadchar code. */
527 keycode
= TSXKeysymToKeycode(display
, keysym
| 0xFE00);
530 TRACE(keyboard
,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
531 cChar
,keysym
,keysym
,keycode
);
535 for (index
=-1, i
=0; (i
<8) && (index
<0); i
++) /* find shift state */
536 if (TSXKeycodeToKeysym(display
,keycode
,i
)==keysym
) index
=i
;
539 WARN(keyboard
,"Keysym %lx not found while parsing the keycode table\n",keysym
); break;
541 case 1 : highbyte
= 0x0100; break;
542 case 2 : highbyte
= 0X0600; break;
543 default : ERR(keyboard
,"index %d found by XKeycodeToKeysym. please report! \n",index
);
546 index : 0 adds 0x0000
547 index : 1 adds 0x0100 (shift)
548 index : ? adds 0x0200 (ctrl)
549 index : 2 adds 0x0600 (ctrl+alt)
550 index : ? adds 0x0700 (ctrl+alt+shift (used?))
553 TRACE(keyboard
," ... returning %#.2x\n", keyc2vkey
[keycode
]+highbyte
);
554 return keyc2vkey
[keycode
]+highbyte
; /* keycode -> (keyc2vkey) vkey */
557 /***********************************************************************
558 * X11DRV_KEYBOARD_MapVirtualKey
560 UINT16
X11DRV_KEYBOARD_MapVirtualKey(UINT16 wCode
, UINT16 wMapType
)
562 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
564 TRACE(keyboard
,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
567 case 0: { /* vkey-code to scan-code */
568 /* let's do vkey -> keycode -> scan */
570 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
571 if ((keyc2vkey
[keyc
] & 0xFF) == wCode
)
572 returnMVK (keyc
- min_keycode
);
575 case 1: /* scan-code to vkey-code */
576 /* let's do scan -> keycode -> vkey */
578 returnMVK (keyc2vkey
[(wCode
& 0xFF) + min_keycode
]);
580 case 2: { /* vkey-code to unshifted ANSI code */
581 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
582 /* My Windows returns 'A'. */
583 /* let's do vkey -> keycode -> (XLookupString) ansi char */
588 e
.state
= 0; /* unshifted */
589 e
.keycode
= MapVirtualKey16( wCode
, 0);
590 if (!TSXLookupString(&e
, s
, 2 , &keysym
, NULL
))
595 default: /* reserved */
596 WARN(keyboard
, "Unknown wMapType %d !\n",
603 /***********************************************************************
604 * X11DRV_KEYBOARD_GetKeyNameText
606 INT16
X11DRV_KEYBOARD_GetKeyNameText(LONG lParam
, LPSTR lpBuffer
, INT16 nSize
)
612 FIXME(keyboard
,"(%ld,<ptr>,%d): stub\n",lParam
,nSize
);
618 for (i
= 0 ; i
!= KeyTableSize
; i
++)
619 if (KeyTable
[i
].scancode
== lParam
) {
620 lstrcpyn32A( lpBuffer
, KeyTable
[i
].name
, nSize
);
621 return strlen(lpBuffer
);
629 /***********************************************************************
630 * X11DRV_KEYBOARD_ToAscii
632 * The ToAscii function translates the specified virtual-key code and keyboard
633 * state to the corresponding Windows character or characters.
635 * If the specified key is a dead key, the return value is negative. Otherwise,
636 * it is one of the following values:
638 * 0 The specified virtual key has no translation for the current state of the keyboard.
639 * 1 One Windows character was copied to the buffer.
640 * 2 Two characters were copied to the buffer. This usually happens when a
641 * dead-key character (accent or diacritic) stored in the keyboard layout cannot
642 * be composed with the specified virtual key to form a single character.
644 * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
647 INT16
X11DRV_KEYBOARD_ToAscii(
648 UINT16 virtKey
,UINT16 scanCode
, LPBYTE lpKeyState
,
649 LPVOID lpChar
, UINT16 flags
)
653 static XComposeStatus cs
;
658 /* This happens when doing Alt+letter : a fake 'down arrow' key press
659 event is generated by windows. Just ignore it. */
660 TRACE(keyboard
,"scanCode=0, doing nothing\n");
666 if (lpKeyState
[VK_SHIFT
] & 0x80)
667 e
.state
|= ShiftMask
;
668 if (lpKeyState
[VK_CAPITAL
] & 0x01)
670 if (lpKeyState
[VK_CONTROL
] & 0x80)
672 if (lpKeyState
[VK_MENU
] & 0x80)
673 e
.state
|= AltGrMask
;
675 e
.state
|= ControlMask
;
677 if (lpKeyState
[VK_NUMLOCK
] & 0x01)
678 e
.state
|= NumLockMask
;
679 TRACE(key
, "(%04X, %04X) : faked state = %X\n",
680 virtKey
, scanCode
, e
.state
);
681 /* We exit on the first keycode found, to speed up the thing. */
682 for (keyc
=min_keycode
; (keyc
<=max_keycode
) && (!e
.keycode
) ; keyc
++)
683 { /* Find a keycode that could have generated this virtual key */
684 if ((keyc2vkey
[keyc
] & 0xFF) == virtKey
)
685 { /* We filter the extended bit, we don't know it */
686 e
.keycode
= keyc
; /* Store it temporarily */
687 if ((EVENT_event_to_vkey(&e
) & 0xFF) != virtKey
) {
688 e
.keycode
= 0; /* Wrong one (ex: because of the NumLock
689 state), so set it to 0, we'll find another one */
694 if ((virtKey
>=VK_NUMPAD0
) && (virtKey
<=VK_NUMPAD9
))
695 e
.keycode
= TSXKeysymToKeycode(e
.display
, virtKey
-VK_NUMPAD0
+XK_KP_0
);
697 if (virtKey
==VK_DECIMAL
)
698 e
.keycode
= TSXKeysymToKeycode(e
.display
, XK_KP_Decimal
);
702 WARN(keyboard
,"Unknown virtual key %X !!! \n",virtKey
);
703 return virtKey
; /* whatever */
705 else TRACE(keyboard
,"Found keycode %d (0x%2X)\n",e
.keycode
,e
.keycode
);
707 ret
= TSXLookupString(&e
, (LPVOID
)lpChar
, 2, &keysym
, &cs
);
712 ((char*)lpChar
)[1] = '\0';
715 /* symbolic ASCII is the same as defined in rfc1345 */
719 case 0x1000FE7E : /* Xfree's XK_Dtilde */
720 dead_char
= '~'; /* '? */
725 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
726 dead_char
= 0xb4; /* '' */
728 #ifdef XK_dead_circumflex
729 case XK_dead_circumflex
:
731 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
732 dead_char
= '^'; /* '> */
737 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
738 dead_char
= '`'; /* '! */
740 #ifdef XK_dead_diaeresis
741 case XK_dead_diaeresis
:
743 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
744 dead_char
= 0xa8; /* ': */
746 #ifdef XK_dead_cedilla
747 case XK_dead_cedilla
:
748 dead_char
= 0xb8; /* ', */
751 #ifdef XK_dead_macron
752 case XK_dead_macron
:
753 dead_char
= '-'; /* 'm isn't defined on iso-8859-x */
758 dead_char
= 0xa2; /* '( */
761 #ifdef XK_dead_abovedot
762 case XK_dead_abovedot
:
763 dead_char
= 0xff; /* '. */
766 #ifdef XK_dead_abovering
767 case XK_dead_abovering
:
768 dead_char
= '0'; /* '0 isn't defined on iso-8859-x */
771 #ifdef XK_dead_doubleacute
772 case XK_dead_doubleacute
:
773 dead_char
= 0xbd; /* '" */
778 dead_char
= 0xb7; /* '< */
781 #ifdef XK_dead_ogonek
782 case XK_dead_ogonek
:
783 dead_char
= 0xb2; /* '; */
786 /* FIXME: I don't know this three.
790 case XK_dead_voiced_sound :
793 case XK_dead_semivoiced_sound :
800 *(char*)lpChar
= dead_char
;
807 ksname
= TSXKeysymToString(keysym
);
810 if ((keysym
>> 8) != 0xff)
812 ERR(keyboard
, "Please report: no char for keysym %04lX (%s) :\n",
814 ERR(keyboard
, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
815 virtKey
, scanCode
, e
.keycode
, e
.state
);
820 /* We have a special case to handle : Shift + arrow, shift + home, ...
821 X returns a char for it, but Windows doesn't. Let's eat it. */
822 if (!(lpKeyState
[VK_NUMLOCK
] & 0x01) /* NumLock is off */
823 && (lpKeyState
[VK_SHIFT
] & 0x80) /* Shift is pressed */
824 && (keysym
>=XK_KP_0
) && (keysym
<=XK_KP_9
))
831 TRACE(key
, "ToAscii about to return %d with char %x\n",
832 ret
, *(char*)lpChar
);
836 #endif /* !defined(X_DISPLAY_MISSING) */