#include "keycode.h" #if defined(IS_MACOSX) #include #include /* For kVK_ constants, and TIS functions. */ /* Returns string representation of key, if it is printable. * Ownership follows the Create Rule; that is, it is the caller's * responsibility to release the returned object. */ CFStringRef createStringForKey(CGKeyCode keyCode); #elif defined(USE_X11) /* * Structs to store key mappings not handled by XStringToKeysym() on some * Linux systems. */ struct XSpecialCharacterMapping { char name; MMKeyCode code; }; struct XSpecialCharacterMapping XSpecialCharacterTable[] = { {'~', XK_asciitilde}, {'_', XK_underscore}, {'[', XK_bracketleft}, {']', XK_bracketright}, {'!', XK_exclam}, {'#', XK_numbersign}, {'$', XK_dollar}, {'%', XK_percent}, {'&', XK_ampersand}, {'*', XK_asterisk}, {'+', XK_plus}, {',', XK_comma}, {'-', XK_minus}, {'.', XK_period}, {'?', XK_question}, {'<', XK_less}, {'>', XK_greater}, {'=', XK_equal}, {'@', XK_at}, {':', XK_colon}, {';', XK_semicolon}, {'`', XK_grave}, {'{', XK_braceleft}, {'}', XK_braceright}, {'|', XK_bar}, {'^', XK_asciicircum}, {'(', XK_parenleft}, {')', XK_parenright}, {' ', XK_space}, {'/', XK_slash}, {'"', XK_quoteright}, {'\'', XK_quotedbl}, // {'\'', XK_quoteright}, {'\\', XK_backslash}, {'\t', XK_Tab}, {'\n', XK_Return} }; #endif MMKeyCode keyCodeForChar(const char c){ #if defined(IS_MACOSX) /* OS X does not appear to have a built-in function for this, so instead we * have to write our own. */ static CFMutableDictionaryRef charToCodeDict = NULL; CGKeyCode code; UniChar character = c; CFStringRef charStr = NULL; /* Generate table of keycodes and characters. */ if (charToCodeDict == NULL) { size_t i; charToCodeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, &kCFCopyStringDictionaryKeyCallBacks, NULL); if (charToCodeDict == NULL) return UINT16_MAX; /* Loop through every keycode (0 - 127) to find its current mapping. */ for (i = 0; i < 128; ++i) { CFStringRef string = createStringForKey((CGKeyCode)i); if (string != NULL) { CFDictionaryAddValue(charToCodeDict, string, (const void *)i); CFRelease(string); } } } charStr = CFStringCreateWithCharacters(kCFAllocatorDefault, &character, 1); /* Our values may be NULL (0), so we need to use this function. */ if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr, (const void **)&code)) { code = UINT16_MAX; /* Error */ } CFRelease(charStr); return (MMKeyCode)code; #elif defined(IS_WINDOWS) return VkKeyScan(c); #elif defined(USE_X11) MMKeyCode code; char buf[2]; buf[0] = c; buf[1] = '\0'; code = XStringToKeysym(buf); if (code == NoSymbol) { /* Some special keys are apparently not handled properly by * XStringToKeysym() on some systems, so search for them instead in our * mapping table. */ size_t i; const size_t specialCharacterCount = sizeof(XSpecialCharacterTable) / sizeof(XSpecialCharacterTable[0]); for (i = 0; i < specialCharacterCount; ++i) { if (c == XSpecialCharacterTable[i].name) { code = XSpecialCharacterTable[i].code; break; } } } return code; #endif } #if defined(IS_MACOSX) CFStringRef createStringForKey(CGKeyCode keyCode){ TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); if (layoutData == nil) { return 0; } const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); UInt32 keysDown = 0; UniChar chars[4]; UniCharCount realLength; UCKeyTranslate(keyboardLayout, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &keysDown, sizeof(chars) / sizeof(chars[0]), &realLength, chars); CFRelease(currentKeyboard); return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); } #endif