MOUSE.DRV routines moved to event.c. Call mouse event procedure.
[wine/wine-kai.git] / windows / keyboard.c
bloba5323867ce9f30cc761eb6dd9fbc4ffa70710086
1 /*
2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
9 */
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <X11/keysym.h>
15 #include "ts_xlib.h"
16 #include "ts_xresource.h"
17 #include "ts_xutil.h"
18 #include <X11/Xatom.h>
20 #include "windows.h"
21 #include "win.h"
22 #include "gdi.h"
23 #include "heap.h"
24 #include "keyboard.h"
25 #include "message.h"
26 #include "debug.h"
27 #include "debugtools.h"
28 #include "struct32.h"
29 #include "winerror.h"
31 BOOL32 MouseButtonsStates[3];
32 BOOL32 AsyncMouseButtonsStates[3];
33 BYTE InputKeyStateTable[256];
34 BYTE QueueKeyStateTable[256];
35 BYTE AsyncKeyStateTable[256];
37 static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
38 static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
39 static int min_keycode, max_keycode, keysyms_per_keycode;
40 static int keyc2vkey[256];
42 typedef union
44 struct
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;
54 } lp1;
55 unsigned long lp2;
56 } KEYLP;
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,
127 /* 256 */
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)
148 KeySym keysym;
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 /**********************************************************************
161 * KEYBOARD_Init
163 BOOL32 KEYBOARD_Init(void)
165 int i;
166 KeySym *ksp;
167 XModifierKeymap *mmp;
168 KeySym keysym;
169 KeyCode *kcp;
170 XKeyEvent e2;
171 WORD vkey, OEMvkey;
172 int keyc;
174 TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
175 ksp = TSXGetKeyboardMapping(display, min_keycode,
176 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
177 /* We are only interested in keysyms_per_keycode.
178 There is no need to hold a local copy of the keysyms table */
179 TSXFree(ksp);
180 mmp = TSXGetModifierMapping(display);
181 kcp = mmp->modifiermap;
182 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
184 int j;
186 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
187 if (*kcp)
189 int k;
191 for (k = 0; k < keysyms_per_keycode; k += 1)
192 if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch)
194 AltGrMask = 1 << i;
195 TRACE(key, "AltGrMask is %x\n", AltGrMask);
197 else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
199 NumLockMask = 1 << i;
200 TRACE(key, "NumLockMask is %x\n", NumLockMask);
204 TSXFreeModifiermap(mmp);
206 /* Now build two conversion arrays :
207 * keycode -> vkey + extended
208 * vkey + extended -> keycode */
210 e2.display = display;
211 e2.state = 0;
213 OEMvkey = VK_OEM_7; /* next is available. */
214 for (keyc = min_keycode; keyc <= max_keycode; keyc++)
216 e2.keycode = (KeyCode)keyc;
217 TSXLookupString(&e2, NULL, 0, &keysym, NULL);
218 vkey = 0;
219 if (keysym) /* otherwise, keycode not used */
221 if ((keysym >> 8) == 0xFF) /* non-character key */
223 int key = keysym & 0xff;
225 if (key >= 0x08 && key <= 0x1B) /* special key */
226 vkey = special_key[key - 0x08];
227 else if (key >= 0x50 && key <= 0x57) /* cursor key */
228 vkey = cursor_key[key - 0x50];
229 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
230 vkey = misc_key[key - 0x60];
231 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
232 vkey = keypad_key[key - 0x7E];
233 else if (key >= 0xBE && key <= 0xCD) /* function key */
235 vkey = function_key[key - 0xBE];
236 vkey |= 0x100; /* set extended bit */
238 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
239 vkey = modifier_key[key - 0xE1];
240 else if (key == 0xFF) /* DEL key */
241 vkey = VK_DELETE;
242 /* extended must also be set for ALT_R, CTRL_R,
243 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
244 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
245 /* FIXME should we set extended bit for NumLock ? My
246 * Windows does ... DF */
247 switch (keysym)
249 case XK_Control_R :
250 case XK_Alt_R :
251 case XK_Insert :
252 case XK_Delete :
253 case XK_Home :
254 case XK_End :
255 case XK_Prior :
256 case XK_Next :
257 case XK_Left :
258 case XK_Up :
259 case XK_Right :
260 case XK_Down :
261 case XK_KP_Divide :
262 case XK_KP_Enter :
263 vkey |= 0x100;
266 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
268 keysym = TSXLookupKeysym(&e2, i);
269 if ((keysym >= VK_0 && keysym <= VK_9)
270 || (keysym >= VK_A && keysym <= VK_Z)
271 || keysym == VK_SPACE)
272 vkey = keysym;
275 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
277 keysym = TSXLookupKeysym(&e2, i);
278 switch (keysym)
280 case ';': vkey = VK_OEM_1; break;
281 case '/': vkey = VK_OEM_2; break;
282 case '`': vkey = VK_OEM_3; break;
283 case '[': vkey = VK_OEM_4; break;
284 case '\\': vkey = VK_OEM_5; break;
285 case ']': vkey = VK_OEM_6; break;
286 case '\'': vkey = VK_OEM_7; break;
287 case ',': vkey = VK_OEM_COMMA; break;
288 case '.': vkey = VK_OEM_PERIOD; break;
289 case '-': vkey = VK_OEM_MINUS; break;
290 case '+': vkey = VK_OEM_PLUS; break;
294 if (!vkey)
296 /* Others keys: let's assign OEM virtual key codes in the allowed range,
297 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
298 switch (++OEMvkey)
300 case 0xc1 : OEMvkey=0xdb; break;
301 case 0xe5 : OEMvkey=0xe9; break;
302 case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n");
305 vkey = OEMvkey;
307 if (TRACE_ON(keyboard))
309 dbg_decl_str(keyboard, 1024);
311 TRACE(keyboard, "OEM specific virtual key %X assigned "
312 "to keycode %X:\n", OEMvkey, e2.keycode);
313 for (i = 0; i < keysyms_per_keycode; i += 1)
315 char *ksname;
317 keysym = TSXLookupKeysym(&e2, i);
318 ksname = TSXKeysymToString(keysym);
319 if (!ksname)
320 ksname = "NoSymbol";
321 dsprintf(keyboard, "%lX (%s) ", keysym, ksname);
323 TRACE(keyboard, "(%s)\n", dbg_str(keyboard));
327 keyc2vkey[e2.keycode] = vkey;
328 } /* for */
329 /* Now store one keycode for each modifier. Used to simulate keypresses. */
330 kcControl = TSXKeysymToKeycode(display, XK_Control_L);
331 kcAlt = TSXKeysymToKeycode(display, XK_Alt_L);
332 kcShift = TSXKeysymToKeycode(display, XK_Shift_L);
333 kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock);
334 kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock);
336 /* all states to false */
337 memset( InputKeyStateTable, 0, sizeof(InputKeyStateTable) );
339 return TRUE;
342 static BOOL32 NumState=FALSE, CapsState=FALSE;
344 /**********************************************************************
345 * KEYBOARD_GenerateMsg
347 * Generate Down+Up messages when NumLock or CapsLock is pressed.
349 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
352 void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y,
353 DWORD event_time, KEYLP localkeylp )
355 BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
357 if (*State) {
358 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
359 don't treat it. It's from the same key press. Then the state goes to ON.
360 And from there, a 'release' event will switch off the toggle key. */
361 *State=FALSE;
362 TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,InputKeyStateTable[vkey]);
363 } else
365 if ( InputKeyStateTable[vkey] & 0x1 ) /* it was ON */
367 if (Evtype!=KeyPress)
369 TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n");
370 localkeylp.lp1.previous = 0; /* ? */
371 localkeylp.lp1.transition = 0;
372 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
373 event_x, event_y, event_time, 0 );
374 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
375 event_x, event_y, event_time, 0 );
376 *State=FALSE;
377 InputKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
380 else /* it was OFF */
381 if (Evtype==KeyPress)
383 TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n");
384 hardware_event( WM_KEYDOWN, vkey, localkeylp.lp2,
385 event_x, event_y, event_time, 0 );
386 localkeylp.lp1.previous = 1;
387 localkeylp.lp1.transition = 1;
388 hardware_event( WM_KEYUP, vkey, localkeylp.lp2,
389 event_x, event_y, event_time, 0 );
390 *State=TRUE; /* Goes to intermediary state before going to ON */
391 InputKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
396 /***********************************************************************
397 * KEYBOARD_UpdateOneState
399 * Updates internal state for <vkey>, depending on key <state> under X
402 void KEYBOARD_UpdateOneState ( int vkey, int state, KEYLP keylp)
404 WORD message;
405 /* Do something if internal table state != X state for keycode */
406 if (((InputKeyStateTable[vkey] & 0x80)!=0) != state)
408 TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n",
409 vkey, InputKeyStateTable[vkey]);
410 keylp.lp1.previous = !state; /* 1 if state = 0, 0 if state = 1 */
411 keylp.lp1.transition = !state;
412 if (state) { /* Fake key being pressed inside wine */
413 InputKeyStateTable[vkey] ^= 0x01;
414 InputKeyStateTable[vkey] |= 0x80;
415 message = (InputKeyStateTable[VK_MENU] & 0x80)
416 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
417 ? WM_SYSKEYDOWN : WM_KEYDOWN;
418 } else {
419 InputKeyStateTable[vkey] &= ~0x80;
420 message = (InputKeyStateTable[VK_MENU] & 0x80)
421 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
422 ? WM_SYSKEYUP : WM_KEYUP;
425 hardware_event( message, vkey, keylp.lp2, 0, 0,
426 GetTickCount() + MSG_WineStartTicks, 0 );
428 TRACE(keyboard,"State after %#.2x \n",InputKeyStateTable[vkey]);
432 /***********************************************************************
433 * KEYBOARD_UpdateState
435 * Update modifiers state (Ctrl, Alt, Shift)
436 * when window is activated (called by EVENT_FocusIn in event.c)
438 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
439 * from wine to another application and back.
440 * Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
441 * about them)
443 void KEYBOARD_UpdateState ( void )
445 /* extract a bit from the char[32] bit suite */
446 #define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
448 char keys_return[32];
449 KEYLP keylp;
451 TRACE(keyboard,"called\n");
452 if (!XQueryKeymap(display, keys_return)) {
453 ERR(keyboard,"Error getting keymap !");
454 return;
457 keylp.lp1.count = 1;
458 keylp.lp1.extended = 0; /* (vkey & 0x100 ? 1 : 0); */
459 keylp.lp1.win_internal = 0;
460 keylp.lp1.context = KeyState(kcAlt);/*(event->state & Mod1Mask)?1:0*/
462 /* Adjust the ALT and CONTROL state if any has been changed outside wine */
463 KEYBOARD_UpdateOneState(VK_MENU, KeyState(kcAlt), keylp);
464 KEYBOARD_UpdateOneState(VK_CONTROL, KeyState(kcControl), keylp);
465 KEYBOARD_UpdateOneState(VK_SHIFT, KeyState(kcShift), keylp);
466 #undef KeyState
470 /***********************************************************************
471 * KEYBOARD_HandleEvent
473 * Handle a X key event
475 void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event )
477 char Str[24];
478 XComposeStatus cs;
479 KeySym keysym;
480 WORD vkey = 0;
481 KEYLP keylp;
482 static BOOL32 force_extended = FALSE; /* hack for AltGr translation */
484 int ascii_chars;
486 INT32 event_x = pWnd->rectWindow.left + event->x;
487 INT32 event_y = pWnd->rectWindow.top + event->y;
488 DWORD event_time = event->time - MSG_WineStartTicks;
490 /* this allows support for dead keys */
491 if ((event->keycode >> 8) == 0x10)
492 event->keycode=(event->keycode & 0xff);
494 ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs);
496 TRACE(key, "EVENT_key : state = %X\n", event->state);
497 if (keysym == XK_Mode_switch)
499 TRACE(key, "Alt Gr key event received\n");
500 event->keycode = kcControl; /* Simulate Control */
501 KEYBOARD_HandleEvent( pWnd, event );
503 event->keycode = kcAlt; /* Simulate Alt */
504 force_extended = TRUE;
505 KEYBOARD_HandleEvent( pWnd, event );
506 force_extended = FALSE;
507 return;
510 Str[ascii_chars] = '\0';
511 if (TRACE_ON(key)){
512 char *ksname;
514 ksname = TSXKeysymToString(keysym);
515 if (!ksname)
516 ksname = "No Name";
517 TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
518 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
519 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
522 vkey = EVENT_event_to_vkey(event);
523 if (force_extended) vkey |= 0x100;
525 TRACE(key, "keycode 0x%x converted to vkey 0x%x\n",
526 event->keycode, vkey);
528 if (vkey)
530 keylp.lp1.count = 1;
531 keylp.lp1.code = vkey2scode[vkey]; /* 5/29/97 chrisf@america.com */
532 keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
533 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
534 * don't remember where I read it - AK */
535 /* it's '1' under windows, when a dialog box appears
536 * and you press one of the underlined keys - DF*/
537 vkey &= 0xff;
539 switch(vkey)
541 case VK_NUMLOCK:
542 KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y,
543 event_time, keylp);
544 break;
545 case VK_CAPITAL:
546 TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,InputKeyStateTable[vkey]);
547 KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y,
548 event_time, keylp );
549 TRACE(keyboard,"State after : %#.2x\n",InputKeyStateTable[vkey]);
550 break;
551 default:
553 WORD message;
555 keylp.lp1.context = ( event->state & Mod1Mask ) ? 1 : 0; /* 1 if alt */
556 if (event->type == KeyPress)
558 keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
559 if (!(InputKeyStateTable[vkey] & 0x80))
560 InputKeyStateTable[vkey] ^= 0x01;
561 InputKeyStateTable[vkey] |= 0x80;
562 keylp.lp1.transition = 0;
563 message = (InputKeyStateTable[VK_MENU] & 0x80)
564 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
565 ? WM_SYSKEYDOWN : WM_KEYDOWN;
567 else
569 BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
570 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
571 && (force_extended == FALSE); /* for Alt from AltGr */
573 InputKeyStateTable[vkey] &= ~0x80;
574 keylp.lp1.previous = 1;
575 keylp.lp1.transition = 1;
576 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
578 /* Adjust the NUMLOCK state if it has been changed outside wine */
579 if (!(InputKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
581 TRACE(keyboard,"Adjusting NumLock state. \n");
582 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y,
583 event_time, keylp );
584 KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y,
585 event_time, keylp );
587 /* Adjust the CAPSLOCK state if it has been changed outside wine */
588 if (!(InputKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
590 TRACE(keyboard,"Adjusting Caps Lock state.\n");
591 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y,
592 event_time, keylp );
593 KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y,
594 event_time, keylp );
596 /* Not Num nor Caps : end of intermediary states for both. */
597 NumState = FALSE;
598 CapsState = FALSE;
600 TRACE(key," wParam=%04X, lParam=%08lX\n",
601 vkey, keylp.lp2 );
602 TRACE(key," InputKeyState=%X\n",
603 InputKeyStateTable[vkey]);
605 hardware_event( message, vkey, keylp.lp2,
606 event_x, event_y, event_time, 0 );
613 /**********************************************************************
614 * GetKeyState (USER.106)
616 WORD WINAPI GetKeyState16(INT16 vkey)
618 return GetKeyState32(vkey);
621 /**********************************************************************
622 * GetKeyState (USER32.249)
624 * An application calls the GetKeyState function in response to a
625 * keyboard-input message. This function retrieves the state of the key
626 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
628 WORD WINAPI GetKeyState32(INT32 vkey)
630 INT32 retval;
632 switch (vkey)
634 case VK_LBUTTON : /* VK_LBUTTON is 1 */
635 retval = MouseButtonsStates[0] ? 0x8000 : 0;
636 break;
637 case VK_MBUTTON : /* VK_MBUTTON is 4 */
638 retval = MouseButtonsStates[1] ? 0x8000 : 0;
639 break;
640 case VK_RBUTTON : /* VK_RBUTTON is 2 */
641 retval = MouseButtonsStates[2] ? 0x8000 : 0;
642 break;
643 default :
644 if (vkey >= 'a' && vkey <= 'z')
645 vkey += 'A' - 'a';
646 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
647 (WORD)(QueueKeyStateTable[vkey] & 0x01);
649 TRACE(key, "(0x%x) -> %x\n", vkey, retval);
650 return retval;
653 /**********************************************************************
654 * GetKeyboardState (USER.222)(USER32.254)
656 * An application calls the GetKeyboardState function in response to a
657 * keyboard-input message. This function retrieves the state of the keyboard
658 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
660 VOID WINAPI GetKeyboardState(LPBYTE lpKeyState)
662 TRACE(key, "(%p)\n", lpKeyState);
663 if (lpKeyState != NULL) {
664 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
665 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
666 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
667 memcpy(lpKeyState, QueueKeyStateTable, 256);
671 /**********************************************************************
672 * SetKeyboardState (USER.223)(USER32.484)
674 VOID WINAPI SetKeyboardState(LPBYTE lpKeyState)
676 TRACE(key, "(%p)\n", lpKeyState);
677 if (lpKeyState != NULL) {
678 memcpy(QueueKeyStateTable, lpKeyState, 256);
679 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
680 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
681 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
685 /**********************************************************************
686 * GetAsyncKeyState32 (USER32.207)
688 * Determine if a key is or was pressed. retval has high-order
689 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
690 * been pressed.
692 * This uses the variable AsyncMouseButtonsStates and
693 * AsyncKeyStateTable (set in event.c) which have the mouse button
694 * number or key number (whichever is applicable) set to true if the
695 * mouse or key had been depressed since the last call to
696 * GetAsyncKeyState.
698 WORD WINAPI GetAsyncKeyState32(INT32 nKey)
700 short retval;
702 switch (nKey) {
703 case VK_LBUTTON:
704 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
705 (MouseButtonsStates[0] ? 0x8000 : 0);
706 break;
707 case VK_MBUTTON:
708 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
709 (MouseButtonsStates[1] ? 0x8000 : 0);
710 break;
711 case VK_RBUTTON:
712 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
713 (MouseButtonsStates[2] ? 0x8000 : 0);
714 break;
715 default:
716 retval = AsyncKeyStateTable[nKey] |
717 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
718 break;
721 /* all states to false */
722 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
723 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
725 TRACE(key, "(%x) -> %x\n", nKey, retval);
726 return retval;
729 /**********************************************************************
730 * GetAsyncKeyState16 (USER.249)
732 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
734 return GetAsyncKeyState32(nKey);
737 /**********************************************************************
738 * KBD_translate_accelerator
740 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
742 static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg,
743 BYTE fVirt,WORD key,WORD cmd)
745 BOOL32 sendmsg = FALSE;
747 if(msg->wParam == key)
749 if (msg->message == WM_CHAR) {
750 if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) )
752 TRACE(accel,"found accel for WM_CHAR: ('%c')\n",
753 msg->wParam&0xff);
754 sendmsg=TRUE;
756 } else {
757 if(fVirt & FVIRTKEY) {
758 INT32 mask = 0;
759 TRACE(accel,"found accel for virt_key %04x (scan %04x)\n",
760 msg->wParam,0xff & HIWORD(msg->lParam));
761 if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT;
762 if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL;
763 if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT;
764 if(mask == (fVirt & (FSHIFT | FCONTROL | FALT)))
765 sendmsg=TRUE;
766 else
767 TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n");
769 else
771 if (!(msg->lParam & 0x01000000)) /* no special_key */
773 if ((fVirt & FALT) && (msg->lParam & 0x20000000))
774 { /* ^^ ALT pressed */
775 TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff);
776 sendmsg=TRUE;
782 if (sendmsg) /* found an accelerator, but send a message... ? */
784 INT16 iSysStat,iStat,mesg=0;
785 HMENU16 hMenu;
787 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
788 mesg=1;
789 else
790 if (GetCapture32())
791 mesg=2;
792 else
793 if (!IsWindowEnabled32(hWnd))
794 mesg=3;
795 else
797 WND* wndPtr = WIN_FindWndPtr(hWnd);
799 hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu;
800 iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0),
801 cmd, MF_BYCOMMAND) : -1 ;
802 iStat = (hMenu) ? GetMenuState32(hMenu,
803 cmd, MF_BYCOMMAND) : -1 ;
805 if (iSysStat!=-1)
807 if (iSysStat & (MF_DISABLED|MF_GRAYED))
808 mesg=4;
809 else
810 mesg=WM_SYSCOMMAND;
812 else
814 if (iStat!=-1)
816 if (IsIconic32(hWnd))
817 mesg=5;
818 else
820 if (iStat & (MF_DISABLED|MF_GRAYED))
821 mesg=6;
822 else
823 mesg=WM_COMMAND;
826 else
827 mesg=WM_COMMAND;
830 if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND )
832 TRACE(accel,", sending %s, wParam=%0x\n",
833 mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND",
834 cmd);
835 SendMessage32A(hWnd, mesg, cmd, 0x00010000L);
837 else
839 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
840 * #0: unknown (please report!)
841 * #1: for WM_KEYUP,WM_SYSKEYUP
842 * #2: mouse is captured
843 * #3: window is disabled
844 * #4: it's a disabled system menu option
845 * #5: it's a menu option, but window is iconic
846 * #6: it's a menu option, but disabled
848 TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg);
849 if(mesg==0)
850 ERR(accel, " unknown reason - please report!");
852 return TRUE;
855 return FALSE;
858 /**********************************************************************
859 * TranslateAccelerator32 (USER32.551)(USER32.552)(USER32.553)
861 INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg)
863 LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel);
864 int i;
866 TRACE(accel,"hwnd=0x%x hacc=0x%x msg=0x%x wp=0x%x lp=0x%lx\n", hWnd, hAccel, msg->message, msg->wParam, msg->lParam);
868 if (hAccel == 0 || msg == NULL ||
869 (msg->message != WM_KEYDOWN &&
870 msg->message != WM_KEYUP &&
871 msg->message != WM_SYSKEYDOWN &&
872 msg->message != WM_SYSKEYUP &&
873 msg->message != WM_CHAR)) {
874 WARN(accel, "erraneous input parameters\n");
875 SetLastError(ERROR_INVALID_PARAMETER);
876 return 0;
879 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,"
880 "msg->hwnd=%04x, msg->message=%04x\n",
881 hAccel,hWnd,msg->hwnd,msg->message);
883 i = 0;
886 if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt,
887 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
888 return 1;
889 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
890 WARN(accel, "couldn't translate accelerator key");
891 return 0;
894 /**********************************************************************
895 * TranslateAccelerator16 (USER.178)
897 INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg)
899 LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel);
900 int i;
901 MSG32 msg32;
903 if (hAccel == 0 || msg == NULL ||
904 (msg->message != WM_KEYDOWN &&
905 msg->message != WM_KEYUP &&
906 msg->message != WM_SYSKEYDOWN &&
907 msg->message != WM_SYSKEYUP &&
908 msg->message != WM_CHAR)) {
909 WARN(accel, "erraneous input parameters\n");
910 SetLastError(ERROR_INVALID_PARAMETER);
911 return 0;
914 TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
915 msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message);
916 STRUCT32_MSG16to32(msg,&msg32);
919 i = 0;
922 if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt,
923 lpAccelTbl[i].key,lpAccelTbl[i].cmd))
924 return 1;
925 } while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
926 WARN(accel, "couldn't translate accelerator key");
927 return 0;
931 /**********************************************************************
932 * ScreenSwitchEnable (KEYBOARD.100)
934 VOID WINAPI ScreenSwitchEnable(WORD unused)
936 FIXME(keyboard,"(%04x): stub\n",unused);
939 /**********************************************************************
940 * OemKeyScan (KEYBOARD.128)(USER32.401)
942 DWORD WINAPI OemKeyScan(WORD wOemChar)
944 TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar);
946 return wOemChar;
949 /**********************************************************************
950 * VkKeyScanA (USER32.573)
952 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
953 * for the current keyboard.
954 * high-order byte yields :
955 * 0 Unshifted
956 * 1 Shift
957 * 2 Ctrl
958 * 3-5 Shift-key combinations that are not used for characters
959 * 6 Ctrl-Alt
960 * 7 Ctrl-Alt-Shift
961 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
962 * FIXME : works ok except for dead chars :
963 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
964 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
967 WORD WINAPI VkKeyScan32A(CHAR cChar)
969 KeyCode keycode;
970 KeySym keysym;
971 int i,index;
972 int highbyte=0;
974 /* char->keysym (same for ANSI chars) */
975 keysym=(unsigned char) cChar;/* (!) cChar is signed */
976 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
978 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
979 if (!keycode)
980 { /* It didn't work ... let's try with deadchar code. */
981 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
984 TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
985 cChar,keysym,keysym,keycode);
987 if (keycode)
989 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
990 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
991 switch (index) {
992 case -1 :
993 WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break;
994 case 0 : break;
995 case 1 : highbyte = 0x0100; break;
996 case 2 : highbyte = 0X0600; break;
997 default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index);
1000 index : 0 adds 0x0000
1001 index : 1 adds 0x0100 (shift)
1002 index : ? adds 0x0200 (ctrl)
1003 index : 2 adds 0x0600 (ctrl+alt)
1004 index : ? adds 0x0700 (ctrl+alt+shift (used?))
1007 TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
1008 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
1011 /******************************************************************************
1012 * VkKeyScan [KEYBOARD.129]
1014 WORD WINAPI VkKeyScan16(CHAR cChar)
1016 return VkKeyScan32A(cChar);
1019 /******************************************************************************
1020 * VkKeyScanW (USER32.576)
1022 WORD WINAPI VkKeyScan32W(WCHAR cChar)
1024 return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */
1027 /******************************************************************************
1028 * GetKeyboardType16 (KEYBOARD.130)
1030 INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag)
1032 return GetKeyboardType32(nTypeFlag);
1035 /******************************************************************************
1036 * GetKeyboardType32 (USER32.255)
1038 INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag)
1040 TRACE(keyboard,"(%d)\n",nTypeFlag);
1041 switch(nTypeFlag)
1043 case 0: /* Keyboard type */
1044 return 4; /* AT-101 */
1045 break;
1046 case 1: /* Keyboard Subtype */
1047 return 0; /* There are no defined subtypes */
1048 break;
1049 case 2: /* Number of F-keys */
1050 return 12; /* We're doing an 101 for now, so return 12 F-keys */
1051 break;
1052 default:
1053 WARN(keyboard, "Unknown type\n");
1054 return 0; /* The book says 0 here, so 0 */
1059 /******************************************************************************
1060 * MapVirtualKey32A (USER32.383)
1062 UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype)
1064 return MapVirtualKey16(code,maptype);
1067 /******************************************************************************
1068 * MapVirtualKey32W (USER32.385)
1070 UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype)
1072 return MapVirtualKey16(code,maptype);
1075 /******************************************************************************
1076 * MapVirtualKey16 (KEYBOARD.131)
1078 * MapVirtualKey translates keycodes from one format to another
1080 UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType)
1082 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
1084 TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
1085 wCode,wMapType);
1086 switch(wMapType) {
1087 case 0: { /* vkey-code to scan-code */
1088 /* let's do vkey -> keycode -> scan */
1089 int keyc;
1090 for (keyc=min_keycode; keyc<=max_keycode; keyc++) /* see event.c */
1091 if ((keyc2vkey[keyc] & 0xFF)== wCode)
1092 returnMVK (keyc - 8);
1093 return 0; }
1095 case 1: /* scan-code to vkey-code */
1096 /* let's do scan -> keycode -> vkey */
1098 returnMVK (keyc2vkey[(wCode & 0xFF) + 8]);
1100 case 2: { /* vkey-code to unshifted ANSI code */
1101 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
1102 /* My Windows returns 'A'. */
1103 /* let's do vkey -> keycode -> (XLookupString) ansi char */
1104 XKeyEvent e;
1105 KeySym keysym;
1106 char s[2];
1107 e.display = display;
1108 e.state = 0; /* unshifted */
1109 e.keycode = MapVirtualKey16( wCode, 0);
1110 if (!TSXLookupString(&e, s , 2 , &keysym, NULL))
1111 returnMVK (*s);
1113 return 0;
1115 default: /* reserved */
1116 WARN(keyboard, "Unknown wMapType %d !\n",
1117 wMapType);
1118 return 0;
1120 return 0;
1124 /****************************************************************************
1125 * GetKBCodePage16 (KEYBOARD.132)
1127 INT16 WINAPI GetKBCodePage16(void)
1129 TRACE(keyboard,"(void)\n");
1130 return 850;
1134 /****************************************************************************
1135 * GetKBCodePage32 (USER32.246)
1137 UINT32 WINAPI GetKBCodePage32(void)
1139 TRACE(keyboard,"(void)\n");
1140 return 850;
1143 /****************************************************************************
1144 * GetKeyboardLayoutName32A (USER32.252)
1146 INT32 WINAPI GetKeyboardLayoutName32A(LPSTR pwszKLID)
1148 return GetKeyboardLayoutName16(pwszKLID);
1151 /****************************************************************************
1152 * GetKeyboardLayoutName32W (USER32.253)
1154 INT32 WINAPI GetKeyboardLayoutName32W(LPWSTR pwszKLID)
1156 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1);
1157 int res = GetKeyboardLayoutName32A(buf);
1158 lstrcpyAtoW(pwszKLID,buf);
1159 HeapFree( GetProcessHeap(), 0, buf );
1160 return res;
1163 /****************************************************************************
1164 * GetKeyboardLayoutName16 (USER.477)
1166 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
1168 FIXME(keyboard,"always returns primary U.S. English layout\n");
1169 strcpy(pwszKLID,"00000409");
1170 return 1;
1173 /****************************************************************************
1174 * GetKeyNameText32A (USER32.247)
1176 INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize)
1178 return GetKeyNameText16(lParam,lpBuffer,nSize);
1181 /****************************************************************************
1182 * GetKeyNameText32W (USER32.248)
1184 INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize)
1186 LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize );
1187 int res = GetKeyNameText32A(lParam,buf,nSize);
1189 lstrcpynAtoW(lpBuffer,buf,nSize);
1190 HeapFree( GetProcessHeap(), 0, buf );
1191 return res;
1195 /****************************************************************************
1196 * GetKeyNameText16 (KEYBOARD.133)
1198 INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize)
1200 /* int i; */
1202 TRACE(keyboard,"(%ld,<ptr>,%d)\n",lParam,nSize);
1204 lParam >>= 16;
1205 lParam &= 0xff;
1207 /* for (i = 0 ; i != KeyTableSize ; i++)
1208 if (KeyTable[i].scancode == lParam) {
1209 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1210 return strlen(lpBuffer);
1213 /* FIXME ! GetKeyNameText is still to do...
1215 *lpBuffer = 0;
1216 return 0;
1220 /****************************************************************************
1221 * ToAscii (KEYBOARD.4)
1223 INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState,
1224 LPVOID lpChar, UINT16 flags)
1226 return ToAscii32(virtKey,scanCode,lpKeyState,lpChar,flags);
1229 /****************************************************************************
1230 * ToAscii32 (USER32.546)
1232 INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState,
1233 LPWORD lpChar,UINT32 flags )
1235 XKeyEvent e;
1236 KeySym keysym;
1237 static XComposeStatus cs;
1238 INT32 ret;
1239 int keyc;
1241 if (scanCode==0) {
1242 /* This happens when doing Alt+letter : a fake 'down arrow' key press
1243 event is generated by windows. Just ignore it. */
1244 TRACE(keyboard,"scanCode=0, doing nothing\n");
1245 return 0;
1247 e.display = display;
1248 e.keycode = 0;
1249 e.state = 0;
1250 if (lpKeyState[VK_SHIFT] & 0x80)
1251 e.state |= ShiftMask;
1252 if (lpKeyState[VK_CAPITAL] & 0x01)
1253 e.state |= LockMask;
1254 if (lpKeyState[VK_CONTROL] & 0x80)
1255 if (lpKeyState[VK_MENU] & 0x80)
1256 e.state |= AltGrMask;
1257 else
1258 e.state |= ControlMask;
1259 if (lpKeyState[VK_NUMLOCK] & 0x01)
1260 e.state |= NumLockMask;
1261 TRACE(key, "(%04X, %04X) : faked state = %X\n",
1262 virtKey, scanCode, e.state);
1263 /* We exit on the first keycode found, to speed up the thing. */
1264 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1265 { /* Find a keycode that could have generated this virtual key */
1266 if ((keyc2vkey[keyc] & 0xFF) == virtKey)
1267 { /* we can filter the extended bit, VK* are different enough... */
1268 e.keycode = keyc; /* Store it temporarily */
1269 if (EVENT_event_to_vkey(&e) != virtKey)
1270 e.keycode = 0; /* Wrong one (ex: because of the NumLock
1271 state), so set it to 0, we'll find another one */
1274 if ((!e.keycode) && (lpKeyState[VK_NUMLOCK] & 0x01))
1276 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1277 e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1278 if (virtKey==VK_DECIMAL)
1279 e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1281 if (!e.keycode)
1283 WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey);
1284 return virtKey; /* whatever */
1286 ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs);
1287 if (ret == 0)
1289 BYTE dead_char = 0;
1291 ((char*)lpChar)[1] = '\0';
1292 switch (keysym)
1294 /* symbolic ASCII is the same as defined in rfc1345 */
1295 #ifdef XK_dead_tilde
1296 case XK_dead_tilde :
1297 #endif
1298 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1299 dead_char = '~'; /* '? */
1300 break;
1301 #ifdef XK_dead_acute
1302 case XK_dead_acute :
1303 #endif
1304 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1305 dead_char = 0xb4; /* '' */
1306 break;
1307 #ifdef XK_dead_circumflex
1308 case XK_dead_circumflex :
1309 #endif
1310 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1311 dead_char = '^'; /* '> */
1312 break;
1313 #ifdef XK_dead_grave
1314 case XK_dead_grave :
1315 #endif
1316 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1317 dead_char = '`'; /* '! */
1318 break;
1319 #ifdef XK_dead_diaeresis
1320 case XK_dead_diaeresis :
1321 #endif
1322 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1323 dead_char = 0xa8; /* ': */
1324 break;
1325 #ifdef XK_dead_cedilla
1326 case XK_dead_cedilla :
1327 dead_char = 0xb8; /* ', */
1328 break;
1329 #endif
1330 #ifdef XK_dead_macron
1331 case XK_dead_macron :
1332 dead_char = '-'; /* 'm isn't defined on iso-8859-x */
1333 break;
1334 #endif
1335 #ifdef XK_dead_breve
1336 case XK_dead_breve :
1337 dead_char = 0xa2; /* '( */
1338 break;
1339 #endif
1340 #ifdef XK_dead_abovedot
1341 case XK_dead_abovedot :
1342 dead_char = 0xff; /* '. */
1343 break;
1344 #endif
1345 #ifdef XK_dead_abovering
1346 case XK_dead_abovering :
1347 dead_char = '0'; /* '0 isn't defined on iso-8859-x */
1348 break;
1349 #endif
1350 #ifdef XK_dead_doubleacute
1351 case XK_dead_doubleacute :
1352 dead_char = 0xbd; /* '" */
1353 break;
1354 #endif
1355 #ifdef XK_dead_caron
1356 case XK_dead_caron :
1357 dead_char = 0xb7; /* '< */
1358 break;
1359 #endif
1360 #ifdef XK_dead_ogonek
1361 case XK_dead_ogonek :
1362 dead_char = 0xb2; /* '; */
1363 break;
1364 #endif
1365 /* FIXME: I don't know this three.
1366 case XK_dead_iota :
1367 dead_char = 'i';
1368 break;
1369 case XK_dead_voiced_sound :
1370 dead_char = 'v';
1371 break;
1372 case XK_dead_semivoiced_sound :
1373 dead_char = 's';
1374 break;
1377 if (dead_char)
1379 *(char*)lpChar = dead_char;
1380 ret = -1;
1382 else
1384 char *ksname;
1386 ksname = TSXKeysymToString(keysym);
1387 if (!ksname)
1388 ksname = "No Name";
1389 if ((keysym >> 8) != 0xff)
1391 ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n",
1392 keysym, ksname);
1393 ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1394 virtKey, scanCode, e.keycode, e.state);
1398 TRACE(key, "ToAscii about to return %d with char %x\n",
1399 ret, *(char*)lpChar);
1400 return ret;
1404 /***********************************************************************
1405 * GetKeyboardLayout (USER32.250)
1407 HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout)
1409 FIXME(keyboard,"(%ld): stub\n",dwLayout);
1410 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1413 /***********************************************************************
1414 * GetKeyboardLayoutList (USER32.251)
1415 * FIXME
1417 INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts)
1419 FIXME(keyboard,"(%d,%p): stub\n",nBuff,layouts);
1420 if (layouts)
1421 layouts[0] = GetKeyboardLayout(0);
1422 return 1;
1426 /***********************************************************************
1427 * RegisterHotKey (USER32.433)
1429 BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) {
1430 FIXME(keyboard,"(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
1431 return TRUE;
1434 /***********************************************************************
1435 * UnregisterHotKey (USER32.565)
1437 BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) {
1438 FIXME(keyboard,"(0x%08x,%d): stub\n",hwnd,id);
1439 return TRUE;
1442 /***********************************************************************
1443 * KeyboardInquire (KEYBOARD.1)
1446 #pragma pack(1)
1447 typedef struct _KBINFO
1449 BYTE Begin_First_Range;
1450 BYTE End_First_Range;
1451 BYTE Begin_Second_Range;
1452 BYTE End_Second_Range;
1453 WORD StateSize;
1454 } KBINFO;
1455 #pragma pack(4)
1457 WORD WINAPI KeyboardInquire(KBINFO *kbInfo)
1459 kbInfo->Begin_First_Range = 0;
1460 kbInfo->End_First_Range = 0;
1461 kbInfo->Begin_Second_Range = 0;
1462 kbInfo->End_Second_Range = 0;
1463 kbInfo->StateSize = 16;
1465 return sizeof(KBINFO);
1468 /***********************************************************************
1469 * KeyboardEnable (KEYBOARD.2)
1471 VOID WINAPI KeyboardEnable(FARPROC16 eventProc, LPBYTE lpKeyState)
1473 FIXME(keyboard, "(%08lx,%08lx): stub\n",
1474 (DWORD)eventProc, (DWORD)lpKeyState);
1477 /***********************************************************************
1478 * KeyboardDisable (KEYBOARD.3)
1480 VOID WINAPI KeyboardDisable(VOID)
1482 FIXME(keyboard, "(): stub\n");
1486 /***********************************************************************
1487 * DisplayInquire (DISPLAY.101)
1490 #pragma pack(1)
1491 typedef struct _CURSORINFO
1493 WORD wXMickeys;
1494 WORD wYMickeys;
1495 } CURSORINFO;
1496 #pragma pack(4)
1498 WORD WINAPI DisplayInquire(CURSORINFO *cursorInfo)
1500 cursorInfo->wXMickeys = 1;
1501 cursorInfo->wYMickeys = 1;
1503 return sizeof(CURSORINFO);
1506 /***********************************************************************
1507 * DisplaySetCursor (DISPLAY.102)
1509 VOID WINAPI DisplaySetCursor( LPVOID cursorShape )
1511 FIXME(keyboard, "(%p): stub\n", cursorShape );
1514 /***********************************************************************
1515 * DisplayMoveCursor (DISPLAY.103)
1517 VOID WINAPI DisplayMoveCursor( WORD wAbsX, WORD wAbsY )
1519 FIXME(keyboard, "(%d,%d): stub\n", wAbsX, wAbsY );
1522 /***********************************************************************
1523 * UserRepaintDisable (DISPLAY.103)
1525 VOID WINAPI UserRepaintDisable( BOOL16 disable )
1527 FIXME(keyboard, "(%d): stub\n", disable);