-/*
+/*
* tkWinKey.c --
*
* This file contains X emulation routines for keyboard related
*/
#include "tkWinInt.h"
-
-/*
- * FIXME - these are in i386-cygwin32/includes/Windows32/Defines.h
- * but not in the current Progressive release...
+/*
+ * The keymap table holds mappings of Windows keycodes to X keysyms.
+ * If Windows ever comes along and changes the value of their keycodes,
+ * this will break all kinds of things. However, this table lookup is much
+ * faster than the alternative, in which we walked a list of keycodes looking
+ * for a match. Since this lookup is performed for every Windows keypress
+ * event, it seems like a worthwhile improvement to use the table.
*/
-
-#ifdef __CYGWIN32__
-#define VK_LWIN (91)
-#define VK_RWIN (92)
-#define VK_APPS (93)
-#endif
-
-typedef struct {
- unsigned int keycode;
- KeySym keysym;
-} Keys;
-
-static Keys keymap[] = {
- VK_CANCEL, XK_Cancel,
- VK_BACK, XK_BackSpace,
- VK_TAB, XK_Tab,
- VK_CLEAR, XK_Clear,
- VK_RETURN, XK_Return,
- VK_SHIFT, XK_Shift_L,
- VK_CONTROL, XK_Control_L,
- VK_MENU, XK_Alt_L,
- VK_PAUSE, XK_Pause,
- VK_CAPITAL, XK_Caps_Lock,
- VK_ESCAPE, XK_Escape,
- VK_SPACE, XK_space,
- VK_PRIOR, XK_Prior,
- VK_NEXT, XK_Next,
- VK_END, XK_End,
- VK_HOME, XK_Home,
- VK_LEFT, XK_Left,
- VK_UP, XK_Up,
- VK_RIGHT, XK_Right,
- VK_DOWN, XK_Down,
- VK_SELECT, XK_Select,
- VK_PRINT, XK_Print,
- VK_EXECUTE, XK_Execute,
- VK_INSERT, XK_Insert,
- VK_DELETE, XK_Delete,
- VK_HELP, XK_Help,
- VK_F1, XK_F1,
- VK_F2, XK_F2,
- VK_F3, XK_F3,
- VK_F4, XK_F4,
- VK_F5, XK_F5,
- VK_F6, XK_F6,
- VK_F7, XK_F7,
- VK_F8, XK_F8,
- VK_F9, XK_F9,
- VK_F10, XK_F10,
- VK_F11, XK_F11,
- VK_F12, XK_F12,
- VK_F13, XK_F13,
- VK_F14, XK_F14,
- VK_F15, XK_F15,
- VK_F16, XK_F16,
- VK_F17, XK_F17,
- VK_F18, XK_F18,
- VK_F19, XK_F19,
- VK_F20, XK_F20,
- VK_F21, XK_F21,
- VK_F22, XK_F22,
- VK_F23, XK_F23,
- VK_F24, XK_F24,
- VK_NUMLOCK, XK_Num_Lock,
- VK_SCROLL, XK_Scroll_Lock,
-
- /*
- * The following support the new keys in the Microsoft keyboard.
- * Win_L and Win_R have the windows logo. App has the menu.
- */
-
- VK_LWIN, XK_Win_L,
- VK_RWIN, XK_Win_R,
- VK_APPS, XK_App,
-
- 0, NoSymbol
+#define MAX_KEYCODE 145 /* VK_SCROLL is the last entry in our table below */
+static KeySym keymap[] = {
+ NoSymbol, NoSymbol, NoSymbol, XK_Cancel, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, XK_BackSpace, XK_Tab,
+ NoSymbol, NoSymbol, XK_Clear, XK_Return, NoSymbol,
+ NoSymbol, XK_Shift_L, XK_Control_L, XK_Alt_L, XK_Pause,
+ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_Escape, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_space, XK_Prior, XK_Next,
+ XK_End, XK_Home, XK_Left, XK_Up, XK_Right,
+ XK_Down, XK_Select, XK_Print, XK_Execute, NoSymbol,
+ XK_Insert, XK_Delete, XK_Help, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, XK_Win_L, XK_Win_R, XK_App, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, XK_F1, XK_F2, XK_F3,
+ XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,
+ XK_F9, XK_F10, XK_F11, XK_F12, XK_F13,
+ XK_F14, XK_F15, XK_F16, XK_F17, XK_F18,
+ XK_F19, XK_F20, XK_F21, XK_F22, XK_F23,
+ XK_F24, NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol, XK_Num_Lock,
+ XK_Scroll_Lock
};
+/*
+ * Prototypes for local procedures defined in this file:
+ */
+
+static KeySym KeycodeToKeysym _ANSI_ARGS_((unsigned int keycode,
+ int state, int noascii));
\f
/*
*----------------------------------------------------------------------
*
- * XLookupString --
+ * TkpGetString --
*
- * Retrieve the string equivalent for the given keyboard event.
+ * Retrieve the UTF string equivalent for the given keyboard event.
*
* Results:
- * Returns the number of characters stored in buffer_return.
+ * Returns the UTF string.
*
* Side effects:
- * Retrieves the characters stored in the event and inserts them
- * into buffer_return.
+ * None.
*
*----------------------------------------------------------------------
*/
-int
-XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return,
- status_in_out)
- XKeyEvent* event_struct;
- char* buffer_return;
- int bytes_buffer;
- KeySym* keysym_return;
- XComposeStatus* status_in_out;
+char *
+TkpGetString(winPtr, eventPtr, dsPtr)
+ TkWindow *winPtr; /* Window where event occurred: needed to
+ * get input context. */
+ XEvent *eventPtr; /* X keyboard event. */
+ Tcl_DString *dsPtr; /* Uninitialized or empty string to hold
+ * result. */
{
- int i, limit;
+ KeySym keysym;
+ XKeyEvent* keyEv = &eventPtr->xkey;
- if (event_struct->send_event != -1) {
+ Tcl_DStringInit(dsPtr);
+ if (eventPtr->xkey.send_event != -1) {
/*
* This is an event generated from generic code. It has no
* nchars or trans_chars members.
*/
- int index;
- KeySym keysym;
-
- index = 0;
- if (event_struct->state & ShiftMask) {
- index |= 1;
- }
- if (event_struct->state & Mod1Mask) {
- index |= 2;
- }
- keysym = XKeycodeToKeysym(event_struct->display,
- event_struct->keycode, index);
+ keysym = KeycodeToKeysym(eventPtr->xkey.keycode,
+ eventPtr->xkey.state, 0);
if (((keysym != NoSymbol) && (keysym > 0) && (keysym < 256))
|| (keysym == XK_Return)
|| (keysym == XK_Tab)) {
- buffer_return[0] = (char) keysym;
- return 1;
+ char buf[TCL_UTF_MAX];
+ int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
+ Tcl_DStringAppend(dsPtr, buf, len);
}
- return 0;
- }
- if ((event_struct->nchars <= 0) || (buffer_return == NULL)) {
- return 0;
+ } else if (eventPtr->xkey.nbytes > 0) {
+ Tcl_ExternalToUtfDString(NULL, eventPtr->xkey.trans_chars,
+ eventPtr->xkey.nbytes, dsPtr);
}
- limit = (event_struct->nchars < bytes_buffer) ? event_struct->nchars :
- bytes_buffer;
-
- for (i = 0; i < limit; i++) {
- buffer_return[i] = event_struct->trans_chars[i];
- }
-
- if (keysym_return != NULL) {
- *keysym_return = NoSymbol;
- }
- return i;
+ return Tcl_DStringValue(dsPtr);
}
\f
/*
unsigned int keycode;
int index;
{
- Keys* key;
+ int state = 0;
+
+ if (index & 0x01) {
+ state |= ShiftMask;
+ }
+ return KeycodeToKeysym(keycode, state, 0);
+}
+
+\f
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * KeycodeToKeysym --
+ *
+ * Translate from a system-dependent keycode to a
+ * system-independent keysym.
+ *
+ * Results:
+ * Returns the translated keysym, or NoSymbol on failure.
+ *
+ * Side effects:
+ * It may affect the internal state of the keyboard, such as
+ * remembered dead key or lock indicator lamps.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static KeySym
+KeycodeToKeysym(keycode, state, noascii)
+ unsigned int keycode;
+ int state;
+ int noascii;
+{
BYTE keys[256];
- int result;
+ int result, deadkey, shift;
char buf[4];
unsigned int scancode = MapVirtualKey(keycode, 0);
+ /*
+ * Do not run keycodes of lock keys through ToAscii().
+ * One of ToAscii()'s side effects is to handle the lights
+ * on the keyboard, and we don't want to mess that up.
+ */
+
+ if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL ||
+ keycode == VK_NUMLOCK)
+ goto skipToAscii;
+
+ /*
+ * Use MapVirtualKey() to detect some dead keys.
+ */
+
+ if (MapVirtualKey(keycode, 2) > 0x7fffUL)
+ return XK_Multi_key;
+
+ /*
+ * Set up a keyboard with correct modifiers
+ */
+
memset(keys, 0, 256);
- if (index & 0x02) {
+ if (state & ShiftMask)
+ keys[VK_SHIFT] = 0x80;
+ if (state & ControlMask)
+ keys[VK_CONTROL] = 0x80;
+ if (state & Mod2Mask)
+ keys[VK_MENU] = 0x80;
+
+ /*
+ * Make sure all lock button info is correct so we don't mess up the
+ * lights
+ */
+
+ if (state & LockMask)
+ keys[VK_CAPITAL] = 1;
+ if (state & Mod3Mask)
+ keys[VK_SCROLL] = 1;
+ if (state & Mod1Mask)
keys[VK_NUMLOCK] = 1;
+
+ result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+
+ if (result < 0) {
+ /*
+ * Win95/98:
+ * This was a dead char, which is now remembered by the keyboard.
+ * Call ToAscii() again to forget it.
+ * WinNT:
+ * This was a dead char, overwriting any previously remembered
+ * key. Calling ToAscii() again does not affect anything.
+ */
+
+ ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- if (index & 0x01) {
- keys[VK_SHIFT] = 0x80;
+ if (result == 2) {
+ /*
+ * This was a dead char, and there were one previously remembered
+ * by the keyboard.
+ * Call ToAscii() again with proper parameters to restore it.
+ */
+
+ /*
+ * Get information about the old char
+ */
+
+ deadkey = VkKeyScan(buf[0]);
+ shift = deadkey >> 8;
+ deadkey &= 255;
+ scancode = MapVirtualKey(deadkey, 0);
+
+ /*
+ * Set up a keyboard with proper modifier keys
+ */
+
+ memset(keys, 0, 256);
+ if (shift & 1)
+ keys[VK_SHIFT] = 0x80;
+ if (shift & 2)
+ keys[VK_CONTROL] = 0x80;
+ if (shift & 4)
+ keys[VK_MENU] = 0x80;
+ ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0);
+ return XK_Multi_key;
}
- result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0);
/*
* Keycode mapped to a valid Latin-1 character. Since the keysyms
* for alphanumeric characters map onto Latin-1, we just return it.
+ *
+ * We treat 0x7F as a special case mostly for backwards compatibility.
+ * In versions of Tk<=8.2, Control-Backspace returned "XK_BackSpace"
+ * as the X Keysym. This was due to the fact that we did not
+ * initialize the keys array properly when we passed it to ToAscii, above.
+ * We had previously not been setting the state bit for the Control key.
+ * When we fixed that, we found that Control-Backspace on Windows is
+ * interpreted as ASCII-127 (0x7F), which corresponds to the Delete key.
+ *
+ * Upon discovering this, we realized we had two choices: return XK_Delete
+ * or return XK_BackSpace. If we returned XK_Delete, that could be
+ * considered "more correct" (although the correctness would be dependant
+ * on whether you believe that ToAscii is doing the right thing in that
+ * case); however, this would break backwards compatibility, and worse,
+ * it would limit application programmers -- they would effectively be
+ * unable to bind to <Control-Backspace> on Windows. We therefore chose
+ * instead to return XK_BackSpace (handled here by letting the code
+ * "fall-through" to the return statement below, which works because the
+ * keycode for this event is VK_BACKSPACE, and the keymap table maps that
+ * keycode to XK_BackSpace).
*/
- if (result == 1 && buf[0] >= 0x20) {
- return (KeySym) buf[0];
+ if (result == 1 && UCHAR(buf[0]) >= 0x20 && UCHAR(buf[0]) != 0x7F) {
+ return (KeySym) UCHAR(buf[0]);
}
/*
* Keycode is a non-alphanumeric key, so we have to do the lookup.
*/
- for (key = keymap; key->keycode != 0; key++) {
- if (key->keycode == keycode) {
- return key->keysym;
+ skipToAscii:
+ if (keycode < 0 || keycode > MAX_KEYCODE) {
+ return NoSymbol;
+ }
+ switch (keycode) {
+ /*
+ * Windows only gives us an undifferentiated VK_CONTROL
+ * code (for example) when either Control key is pressed.
+ * To distinguish between left and right, we have to query the
+ * state of one of the two to determine which was actually
+ * pressed. So if the keycode indicates Control, Shift, or Menu
+ * (the key that everybody else calls Alt), do this extra test.
+ * If the right-side key was pressed, return the appropriate
+ * keycode. Otherwise, we fall through and rely on the
+ * keymap table to hold the correct keysym value.
+ */
+ case VK_CONTROL: {
+ if (GetKeyState(VK_RCONTROL) & 0x80) {
+ return XK_Control_R;
+ }
+ break;
+ }
+ case VK_SHIFT: {
+ if (GetKeyState(VK_RSHIFT) & 0x80) {
+ return XK_Shift_R;
+ }
+ break;
+ }
+ case VK_MENU: {
+ if (GetKeyState(VK_RMENU) & 0x80) {
+ return XK_Alt_R;
+ }
+ break;
}
}
+ return keymap[keycode];
+}
+\f
- return NoSymbol;
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpGetKeySym --
+ *
+ * Given an X KeyPress or KeyRelease event, map the
+ * keycode in the event into a KeySym.
+ *
+ * Results:
+ * The return value is the KeySym corresponding to
+ * eventPtr, or NoSymbol if no matching Keysym could be
+ * found.
+ *
+ * Side effects:
+ * In the first call for a given display, keycode-to-
+ * KeySym maps get loaded.
+ *
+ *----------------------------------------------------------------------
+ */
+
+KeySym
+TkpGetKeySym(dispPtr, eventPtr)
+ TkDisplay *dispPtr; /* Display in which to map keycode. */
+ XEvent *eventPtr; /* Description of X event. */
+{
+ KeySym sym;
+ int state = eventPtr->xkey.state;
+
+ /*
+ * Refresh the mapping information if it's stale
+ */
+
+ if (dispPtr->bindInfoStale) {
+ TkpInitKeymapInfo(dispPtr);
+ }
+
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+
+ /*
+ * Special handling: if this is a ctrl-alt or shifted key, and there
+ * is no keysym defined, try without the modifiers.
+ */
+
+ if ((sym == NoSymbol) && ((state & ControlMask) || (state & Mod2Mask))) {
+ state &= ~(ControlMask | Mod2Mask);
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ if ((sym == NoSymbol) && (state & ShiftMask)) {
+ state &= ~ShiftMask;
+ sym = KeycodeToKeysym(eventPtr->xkey.keycode, state, 0);
+ }
+ return sym;
+}
+\f
+/*
+ *--------------------------------------------------------------
+ *
+ * TkpInitKeymapInfo --
+ *
+ * This procedure is invoked to scan keymap information
+ * to recompute stuff that's important for binding, such
+ * as the modifier key (if any) that corresponds to "mode
+ * switch".
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Keymap-related information in dispPtr is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+void
+TkpInitKeymapInfo(dispPtr)
+ TkDisplay *dispPtr; /* Display for which to recompute keymap
+ * information. */
+{
+ XModifierKeymap *modMapPtr;
+ KeyCode *codePtr;
+ KeySym keysym;
+ int count, i, j, max, arraySize;
+#define KEYCODE_ARRAY_SIZE 20
+
+ dispPtr->bindInfoStale = 0;
+ modMapPtr = XGetModifierMapping(dispPtr->display);
+
+ /*
+ * Check the keycodes associated with the Lock modifier. If
+ * any of them is associated with the XK_Shift_Lock modifier,
+ * then Lock has to be interpreted as Shift Lock, not Caps Lock.
+ */
+
+ dispPtr->lockUsage = LU_IGNORE;
+ codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
+ for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Shift_Lock) {
+ dispPtr->lockUsage = LU_SHIFT;
+ break;
+ }
+ if (keysym == XK_Caps_Lock) {
+ dispPtr->lockUsage = LU_CAPS;
+ break;
+ }
+ }
+
+ /*
+ * Look through the keycodes associated with modifiers to see if
+ * the the "mode switch", "meta", or "alt" keysyms are associated
+ * with any modifiers. If so, remember their modifier mask bits.
+ */
+
+ dispPtr->modeModMask = 0;
+ dispPtr->metaModMask = 0;
+ dispPtr->altModMask = 0;
+ codePtr = modMapPtr->modifiermap;
+ max = 8*modMapPtr->max_keypermod;
+ for (i = 0; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+ keysym = KeycodeToKeysym(*codePtr, 0, 1);
+ if (keysym == XK_Mode_switch) {
+ dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
+ dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
+ dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
+ }
+ }
+
+ /*
+ * Create an array of the keycodes for all modifier keys.
+ */
+
+ if (dispPtr->modKeyCodes != NULL) {
+ ckfree((char *) dispPtr->modKeyCodes);
+ }
+ dispPtr->numModKeyCodes = 0;
+ arraySize = KEYCODE_ARRAY_SIZE;
+ dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
+ (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
+ for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
+ if (*codePtr == 0) {
+ continue;
+ }
+
+ /*
+ * Make sure that the keycode isn't already in the array.
+ */
+
+ for (j = 0; j < dispPtr->numModKeyCodes; j++) {
+ if (dispPtr->modKeyCodes[j] == *codePtr) {
+ goto nextModCode;
+ }
+ }
+ if (dispPtr->numModKeyCodes >= arraySize) {
+ KeyCode *new;
+
+ /*
+ * Ran out of space in the array; grow it.
+ */
+
+ arraySize *= 2;
+ new = (KeyCode *) ckalloc((unsigned)
+ (arraySize * sizeof(KeyCode)));
+ memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
+ (dispPtr->numModKeyCodes * sizeof(KeyCode)));
+ ckfree((char *) dispPtr->modKeyCodes);
+ dispPtr->modKeyCodes = new;
+ }
+ dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
+ dispPtr->numModKeyCodes++;
+ nextModCode: continue;
+ }
+ XFreeModifiermap(modMapPtr);
+}
+\f
+/*
+ * When mapping from a keysym to a keycode, need
+ * information about the modifier state that should be used
+ * so that when they call XKeycodeToKeysym taking into
+ * account the xkey.state, they will get back the original
+ * keysym.
+ */
+
+void
+TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
+ Tk_Window tkwin;
+ KeySym keySym;
+ XEvent *eventPtr;
+{
+ int i;
+ SHORT result;
+ int shift;
+
+ eventPtr->xkey.keycode = 0;
+ if (keySym == NoSymbol) {
+ return;
+ }
+
+ /*
+ * We check our private map first for a virtual keycode,
+ * as VkKeyScan will return values that don't map to X
+ * for the "extended" Syms. This may be due to just casting
+ * problems below, but this works.
+ */
+ for (i = 0; i <= MAX_KEYCODE; i++) {
+ if (keymap[i] == keySym) {
+ eventPtr->xkey.keycode = i;
+ return;
+ }
+ }
+ if (keySym >= 0x20) {
+ result = VkKeyScan((char) keySym);
+ if (result != -1) {
+ shift = result >> 8;
+ if (shift & 1)
+ eventPtr->xkey.state |= ShiftMask;
+ if (shift & 2)
+ eventPtr->xkey.state |= ControlMask;
+ if (shift & 4)
+ eventPtr->xkey.state |= Mod2Mask;
+ eventPtr->xkey.keycode = (KeyCode) (result & 0xff);
+ }
+ }
+ {
+ /* Debug log */
+ FILE *fp = fopen("c:\\temp\\tklog.txt", "a");
+ if (fp != NULL) {
+ fprintf(fp, "TkpSetKeycode. Keycode %d State %d Keysym %d\n", eventPtr->xkey.keycode, eventPtr->xkey.state, keySym);
+ fclose(fp);
+ }
+ }
}
\f
/*
Display* display;
KeySym keysym;
{
- Keys* key;
+ int i;
SHORT result;
+ /*
+ * We check our private map first for a virtual keycode,
+ * as VkKeyScan will return values that don't map to X
+ * for the "extended" Syms. This may be due to just casting
+ * problems below, but this works.
+ */
+ if (keysym == NoSymbol) {
+ return 0;
+ }
+ for (i = 0; i <= MAX_KEYCODE; i++) {
+ if (keymap[i] == keysym) {
+ return ((KeyCode) i);
+ }
+ }
if (keysym >= 0x20) {
result = VkKeyScan((char) keysym);
if (result != -1) {
}
}
- /*
- * Couldn't map the character to a virtual keycode, so do a
- * table lookup.
- */
-
- for (key = keymap; key->keycode != 0; key++) {
- if (key->keysym == keysym) {
- return key->keycode;
- }
- }
return 0;
}
\f