diff src/events/SDL_keyboard.c @ 2303:d87417504c75

First pass implementation of new SDL scancode concept, as discussed with Christian Walther. Currently only implemented on Mac OS X for sanity checking purposes.
author Sam Lantinga <slouken@libsdl.org>
date Tue, 05 Feb 2008 07:19:23 +0000
parents c97ad1abe05b
children fbe8ff44c519
line wrap: on
line diff
--- a/src/events/SDL_keyboard.c	Mon Feb 04 17:25:33 2008 +0000
+++ b/src/events/SDL_keyboard.c	Tue Feb 05 07:19:23 2008 +0000
@@ -27,18 +27,475 @@
 #include "SDL_events.h"
 #include "SDL_events_c.h"
 #include "SDL_sysevents.h"
-#include "SDL_keynames.h"
 
 
 /* Global keyboard information */
-int SDL_TranslateUNICODE = 0;
 static int SDL_num_keyboards;
 static int SDL_current_keyboard;
 static SDL_Keyboard **SDL_keyboards;
 
+static SDLKey SDL_default_keymap[SDL_NUM_SCANCODES] = {
+    0, 0, 0, 0,
+    'a',
+    'b',
+    'c',
+    'd',
+    'e',
+    'f',
+    'g',
+    'h',
+    'i',
+    'j',
+    'k',
+    'l',
+    'm',
+    'n',
+    'o',
+    'p',
+    'q',
+    'r',
+    's',
+    't',
+    'u',
+    'v',
+    'w',
+    'x',
+    'y',
+    'z',
+    '1',
+    '2',
+    '3',
+    '4',
+    '5',
+    '6',
+    '7',
+    '8',
+    '9',
+    '0',
+    SDLK_RETURN,
+    SDLK_ESCAPE,
+    SDLK_BACKSPACE,
+    SDLK_TAB,
+    SDLK_SPACE,
+    '-',
+    '=',
+    '[',
+    ']',
+    '\\',
+    '#',
+    ';',
+    '\'',
+    '`',
+    ',',
+    '.',
+    '/',
+    SDLK_CAPSLOCK,
+    SDLK_F1,
+    SDLK_F2,
+    SDLK_F3,
+    SDLK_F4,
+    SDLK_F5,
+    SDLK_F6,
+    SDLK_F7,
+    SDLK_F8,
+    SDLK_F9,
+    SDLK_F10,
+    SDLK_F11,
+    SDLK_F12,
+    SDLK_PRINTSCREEN,
+    SDLK_SCROLLLOCK,
+    SDLK_PAUSE,
+    SDLK_INSERT,
+    SDLK_HOME,
+    SDLK_PAGEUP,
+    SDLK_DELETE,
+    SDLK_END,
+    SDLK_PAGEDOWN,
+    SDLK_RIGHT,
+    SDLK_LEFT,
+    SDLK_DOWN,
+    SDLK_UP,
+    SDLK_NUMLOCKCLEAR,
+    SDLK_KP_DIVIDE,
+    SDLK_KP_MULTIPLY,
+    SDLK_KP_MINUS,
+    SDLK_KP_PLUS,
+    SDLK_KP_ENTER,
+    SDLK_KP_1,
+    SDLK_KP_2,
+    SDLK_KP_3,
+    SDLK_KP_4,
+    SDLK_KP_5,
+    SDLK_KP_6,
+    SDLK_KP_7,
+    SDLK_KP_8,
+    SDLK_KP_9,
+    SDLK_KP_0,
+    SDLK_KP_PERIOD,
+    0,
+    SDLK_APPLICATION,
+    SDLK_POWER,
+    SDLK_KP_EQUALS,
+    SDLK_F13,
+    SDLK_F14,
+    SDLK_F15,
+    SDLK_F16,
+    SDLK_F17,
+    SDLK_F18,
+    SDLK_F19,
+    SDLK_F20,
+    SDLK_F21,
+    SDLK_F22,
+    SDLK_F23,
+    SDLK_F24,
+    SDLK_EXECUTE,
+    SDLK_HELP,
+    SDLK_MENU,
+    SDLK_SELECT,
+    SDLK_STOP,
+    SDLK_AGAIN,
+    SDLK_UNDO,
+    SDLK_CUT,
+    SDLK_COPY,
+    SDLK_PASTE,
+    SDLK_FIND,
+    SDLK_MUTE,
+    SDLK_VOLUMEUP,
+    SDLK_VOLUMEDOWN,
+    0, 0, 0,
+    SDLK_KP_COMMA,
+    SDLK_KP_EQUALSAS400,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    SDLK_ALTERASE,
+    SDLK_SYSREQ,
+    SDLK_CANCEL,
+    SDLK_CLEAR,
+    SDLK_PRIOR,
+    SDLK_RETURN2,
+    SDLK_SEPARATOR,
+    SDLK_OUT,
+    SDLK_OPER,
+    SDLK_CLEARAGAIN,
+    SDLK_CRSEL,
+    SDLK_EXSEL,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    SDLK_KP_00,
+    SDLK_KP_000,
+    SDLK_THOUSANDSSEPARATOR,
+    SDLK_DECIMALSEPARATOR,
+    SDLK_CURRENCYUNIT,
+    SDLK_CURRENCYSUBUNIT,
+    SDLK_KP_LEFTPAREN,
+    SDLK_KP_RIGHTPAREN,
+    SDLK_KP_LEFTBRACE,
+    SDLK_KP_RIGHTBRACE,
+    SDLK_KP_TAB,
+    SDLK_KP_BACKSPACE,
+    SDLK_KP_A,
+    SDLK_KP_B,
+    SDLK_KP_C,
+    SDLK_KP_D,
+    SDLK_KP_E,
+    SDLK_KP_F,
+    SDLK_KP_XOR,
+    SDLK_KP_POWER,
+    SDLK_KP_PERCENT,
+    SDLK_KP_LESS,
+    SDLK_KP_GREATER,
+    SDLK_KP_AMPERSAND,
+    SDLK_KP_DBLAMPERSAND,
+    SDLK_KP_VERTICALBAR,
+    SDLK_KP_DBLVERTICALBAR,
+    SDLK_KP_COLON,
+    SDLK_KP_HASH,
+    SDLK_KP_SPACE,
+    SDLK_KP_AT,
+    SDLK_KP_EXCLAM,
+    SDLK_KP_MEMSTORE,
+    SDLK_KP_MEMRECALL,
+    SDLK_KP_MEMCLEAR,
+    SDLK_KP_MEMADD,
+    SDLK_KP_MEMSUBTRACT,
+    SDLK_KP_MEMMULTIPLY,
+    SDLK_KP_MEMDIVIDE,
+    SDLK_KP_PLUSMINUS,
+    SDLK_KP_CLEAR,
+    SDLK_KP_CLEARENTRY,
+    SDLK_KP_BINARY,
+    SDLK_KP_OCTAL,
+    SDLK_KP_DECIMAL,
+    SDLK_KP_HEXADECIMAL,
+    0, 0,
+    SDLK_LCTRL,
+    SDLK_LSHIFT,
+    SDLK_LALT,
+    SDLK_LGUI,
+    SDLK_RCTRL,
+    SDLK_RSHIFT,
+    SDLK_RALT,
+    SDLK_RGUI,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    SDLK_MODE,
+    SDLK_AUDIONEXT,
+    SDLK_AUDIOPREV,
+    SDLK_AUDIOSTOP,
+    SDLK_AUDIOPLAY,
+    SDLK_AUDIOMUTE,
+    SDLK_MEDIASELECT,
+    SDLK_MAIL,
+    SDLK_CALCULATOR,
+    SDLK_COMPUTER,
+    SDLK_AC_SEARCH,
+    SDLK_AC_HOME,
+    SDLK_AC_BACK,
+    SDLK_AC_FORWARD,
+    SDLK_AC_STOP,
+    SDLK_AC_REFRESH,
+    SDLK_AC_BOOKMARKS,
+    SDLK_BRIGHTNESSDOWN,
+    SDLK_BRIGHTNESSUP,
+    SDLK_DISPLAYSWITCH,
+    SDLK_KBDILLUMTOGGLE,
+    SDLK_KBDILLUMDOWN,
+    SDLK_KBDILLUMUP,
+    SDLK_EJECT,
+    SDLK_SLEEP,
+};
+
+static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
+    NULL, NULL, NULL, NULL,
+    "A",
+    "B",
+    "C",
+    "D",
+    "E",
+    "F",
+    "G",
+    "H",
+    "I",
+    "J",
+    "K",
+    "L",
+    "M",
+    "N",
+    "O",
+    "P",
+    "Q",
+    "R",
+    "S",
+    "T",
+    "U",
+    "V",
+    "W",
+    "X",
+    "Y",
+    "Z",
+    "1",
+    "2",
+    "3",
+    "4",
+    "5",
+    "6",
+    "7",
+    "8",
+    "9",
+    "0",
+    "Return",
+    "Escape",
+    "Backspace",
+    "Tab",
+    "Space",
+    "-",
+    "=",
+    "[",
+    "]",
+    "\\",
+    "#",
+    ";",
+    "'",
+    "`",
+    ",",
+    ".",
+    "/",
+    "CapsLock",
+    "F1",
+    "F2",
+    "F3",
+    "F4",
+    "F5",
+    "F6",
+    "F7",
+    "F8",
+    "F9",
+    "F10",
+    "F11",
+    "F12",
+    "PrintScreen",
+    "ScrollLock",
+    "Pause",
+    "Insert",
+    "Home",
+    "PageUp",
+    "Delete",
+    "End",
+    "PageDown",
+    "Right",
+    "Left",
+    "Down",
+    "Up",
+    "Numlock",
+    "Keypad /",
+    "Keypad *",
+    "Keypad -",
+    "Keypad +",
+    "Keypad Enter",
+    "Keypad 1",
+    "Keypad 2",
+    "Keypad 3",
+    "Keypad 4",
+    "Keypad 5",
+    "Keypad 6",
+    "Keypad 7",
+    "Keypad 8",
+    "Keypad 9",
+    "Keypad 0",
+    "Keypad .",
+    NULL,
+    "Application",
+    "Power",
+    "Keypad =",
+    "F13",
+    "F14",
+    "F15",
+    "F16",
+    "F17",
+    "F18",
+    "F19",
+    "F20",
+    "F21",
+    "F22",
+    "F23",
+    "F24",
+    "Execute",
+    "Help",
+    "Menu",
+    "Select",
+    "Stop",
+    "Again",
+    "Undo",
+    "Cut",
+    "Copy",
+    "Paste",
+    "Find",
+    "Mute",
+    "VolumeUp",
+    "VolumeDown",
+    NULL, NULL, NULL,
+    "Keypad ,",
+    "Keypad = (AS400)",
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL,
+    "AltErase",
+    "SysReq",
+    "Cancel",
+    "Clear",
+    "Prior",
+    "Return",
+    "Separator",
+    "Out",
+    "Oper",
+    "Clear / Again",
+    "CrSel",
+    "ExSel",
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    "Keypad 00",
+    "Keypad 000",
+    "ThousandsSeparator",
+    "DecimalSeparator",
+    "CurrencyUnit",
+    "CurrencySubUnit",
+    "Keypad (",
+    "Keypad )",
+    "Keypad {",
+    "Keypad }",
+    "Keypad Tab",
+    "Keypad Backspace",
+    "Keypad A",
+    "Keypad B",
+    "Keypad C",
+    "Keypad D",
+    "Keypad E",
+    "Keypad F",
+    "Keypad XOR",
+    "Keypad ^",
+    "Keypad %",
+    "Keypad <",
+    "Keypad >",
+    "Keypad &",
+    "Keypad &&",
+    "Keypad |",
+    "Keypad ||",
+    "Keypad :",
+    "Keypad #",
+    "Keypad Space",
+    "Keypad @",
+    "Keypad !",
+    "Keypad MemStore",
+    "Keypad MemRecall",
+    "Keypad MemClear",
+    "Keypad MemAdd",
+    "Keypad MemSubtract",
+    "Keypad MemMultiply",
+    "Keypad MemDivide",
+    "Keypad +/-",
+    "Keypad Clear",
+    "Keypad ClearEntry",
+    "Keypad Binary",
+    "Keypad Octal",
+    "Keypad Decimal",
+    "Keypad Hexadecimal",
+    NULL, NULL,
+    "Left Ctrl",
+    "Left Shift",
+    "Left Alt",
+    "Left GUI",
+    "Right Ctrl",
+    "Right Shift",
+    "Right Alt",
+    "Right GUI",
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL,
+    "ModeSwitch",
+    "AudioNext",
+    "AudioPrev",
+    "AudioStop",
+    "AudioPlay",
+    "AudioMute",
+    "MediaSelect",
+    "Mail",
+    "Calculator",
+    "Computer",
+    "AC Search",
+    "AC Home",
+    "AC Back",
+    "AC Forward",
+    "AC Stop",
+    "AC Refresh",
+    "AC Bookmarks",
+    "BrightnessDown",
+    "BrightnessUp",
+    "DisplaySwitch",
+    "KBDIllumToggle",
+    "KBDIllumDown",
+    "KBDIllumUp",
+    "Eject",
+    "Sleep",
+};
+
 /* Taken from SDL_iconv() */
-char *
-SDL_Ucs4ToUtf8(Uint32 ch, char *dst)
+static char *
+SDL_UCS4ToUTF8(Uint32 ch, char *dst)
 {
     Uint8 *p = (Uint8 *) dst;
     if (ch <= 0x7F) {
@@ -82,9 +539,6 @@
 int
 SDL_KeyboardInit(void)
 {
-    /* Set default mode of UNICODE translation */
-    SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
-
     return (0);
 }
 
@@ -148,170 +602,45 @@
 SDL_ResetKeyboard(int index)
 {
     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
-    int key;
+    SDL_scancode scancode;
 
     if (!keyboard) {
         return;
     }
 
-    for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
-        if (keyboard->keystate[key] == SDL_PRESSED) {
-            SDL_SendKeyboardKey(index, SDL_RELEASED, 0,
-                                key | SDL_KEY_CAN_BE_PHYSICAL_BIT);
+    for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
+        if (keyboard->keystate[scancode] == SDL_PRESSED) {
+            SDL_SendKeyboardKey(index, SDL_RELEASED, scancode);
         }
     }
 }
 
 void
-SDL_KeyboardQuit(void)
-{
-    int i;
-
-    for (i = 0; i < SDL_num_keyboards; ++i) {
-        SDL_DelKeyboard(i);
-    }
-    SDL_num_keyboards = 0;
-    SDL_current_keyboard = 0;
-
-    if (SDL_keyboards) {
-        SDL_free(SDL_keyboards);
-        SDL_keyboards = NULL;
-    }
-}
-
-int
-SDL_GetNumKeyboards(void)
-{
-    return SDL_num_keyboards;
-}
-
-int
-SDL_SelectKeyboard(int index)
-{
-    if (index >= 0 && index < SDL_num_keyboards) {
-        SDL_current_keyboard = index;
-    }
-    return SDL_current_keyboard;
-}
-
-int
-SDL_EnableUNICODE(int enable)
+SDL_GetDefaultKeymap(SDLKey * keymap)
 {
-    int old_mode;
-
-    old_mode = SDL_TranslateUNICODE;
-    if (enable >= 0) {
-        SDL_TranslateUNICODE = enable;
-    }
-    return (old_mode);
-}
-
-Uint8 *
-SDL_GetKeyState(int *numkeys)
-{
-    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
-
-    if (numkeys != (int *) 0) {
-        *numkeys = SDLK_LAST;
-    }
-
-    if (!keyboard) {
-        return NULL;
-    }
-    return keyboard->keystate;
-}
-
-SDLMod
-SDL_GetModState(void)
-{
-    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
-
-    if (!keyboard) {
-        return KMOD_NONE;
-    }
-    return keyboard->modstate;
+    SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
 }
 
 void
-SDL_SetModState(SDLMod modstate)
+SDL_SetKeymap(int index, int start, SDLKey * keys, int length)
 {
-    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
 
     if (!keyboard) {
         return;
     }
-    keyboard->modstate = modstate;
-}
 
-SDLKey
-SDL_GetLayoutKey(SDLKey physicalKey)
-{
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    if (_this && _this->GetLayoutKey) {
-        return _this->GetLayoutKey(_this, physicalKey)
-            | (physicalKey & SDL_KEY_KEYPAD_BIT);
-    } else {
-        return physicalKey;
-    }
-}
-
-const char *
-SDL_GetKeyName(SDLKey layoutKey)
-{
-    const char *keyname = NULL;
-
-    if ((layoutKey & SDL_KEY_LAYOUT_SPECIAL_BIT) != 0) {
-        SDL_VideoDevice *_this = SDL_GetVideoDevice();
-        if (_this && _this->GetSpecialKeyName) {
-            keyname = _this->GetSpecialKeyName(_this, layoutKey);
-        }
-    } else if ((layoutKey & SDL_KEY_CAN_BE_PHYSICAL_BIT) == 0) {
-        /* SDLK_INDEX(layoutKey) is the unicode code point of the
-           character generated by the key */
-        static char buffer[9];  /* 6 (maximal UTF-8 char length) + 2 ([] for keypad) + 1 (null teminator) */
-        char *bufferPtr = &buffer[1];
-        Uint32 codepoint = SDLK_INDEX(layoutKey);
-
-        /* Unaccented letter keys on latin keyboards are normally
-           labeled in upper case (and probably on others like Greek or
-           Cyrillic too, so if you happen to know for sure, please
-           adapt this). */
-        if (codepoint >= 'a' && codepoint <= 'z') {
-            codepoint -= 32;
-        }
-
-        bufferPtr = SDL_Ucs4ToUtf8(codepoint, bufferPtr);
-        *bufferPtr = '\0';
-
-        if ((layoutKey & SDL_KEY_KEYPAD_BIT) != 0) {
-            buffer[0] = '[';
-            *bufferPtr++ = ']';
-            *bufferPtr = '\0';
-            keyname = buffer;
-        } else {
-            keyname = &buffer[1];
-        }
-    } else {
-        /* SDLK_INDEX(layoutKey) is a physical key number */
-        if (SDLK_INDEX(layoutKey) < SDL_arraysize(SDL_keynames)) {
-            keyname = SDL_keynames[SDLK_INDEX(layoutKey)];
-        }
+    if (start < 0 || start + length > SDL_NUM_SCANCODES) {
+        return;
     }
 
-    if (keyname == NULL) {
-        keyname = SDL_keynames[SDLK_INDEX(SDLK_UNKNOWN)];
-    }
-
-    return keyname;
+    SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
 }
 
 void
-SDL_SetKeyName(SDLKey physicalKey, const char *name)
+SDL_SetScancodeName(SDL_scancode scancode, const char *name)
 {
-    physicalKey = SDLK_INDEX(physicalKey);
-    if (physicalKey < SDL_arraysize(SDL_keynames)) {
-        SDL_keynames[physicalKey] = name;
-    }
+    SDL_scancode_names[scancode] = name;
 }
 
 void
@@ -366,94 +695,89 @@
 }
 
 int
-SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode,
-                    SDLKey physicalKey)
+SDL_SendKeyboardKey(int index, Uint8 state, SDL_scancode scancode)
 {
     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
     int posted;
     Uint16 modstate;
     Uint8 type;
 
-    if (!keyboard || physicalKey == SDLK_NONE) {
+    if (!keyboard || !scancode) {
         return 0;
     }
 #if 0
-    printf("The '%s' key has been %s\n", SDL_GetKeyName(physicalKey),
+    printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
            state == SDL_PRESSED ? "pressed" : "released");
 #endif
     if (state == SDL_PRESSED) {
         modstate = keyboard->modstate;
-        switch (physicalKey) {
-        case SDLK_UNKNOWN:
-            break;
-        case SDLK_KP_NUMLOCKCLEAR:
+        switch (scancode) {
+        case SDL_SCANCODE_NUMLOCKCLEAR:
             keyboard->modstate ^= KMOD_NUM;
             break;
-        case SDLK_CAPSLOCK:
+        case SDL_SCANCODE_CAPSLOCK:
             keyboard->modstate ^= KMOD_CAPS;
             break;
-        case SDLK_LCTRL:
+        case SDL_SCANCODE_LCTRL:
             keyboard->modstate |= KMOD_LCTRL;
             break;
-        case SDLK_RCTRL:
+        case SDL_SCANCODE_RCTRL:
             keyboard->modstate |= KMOD_RCTRL;
             break;
-        case SDLK_LSHIFT:
+        case SDL_SCANCODE_LSHIFT:
             keyboard->modstate |= KMOD_LSHIFT;
             break;
-        case SDLK_RSHIFT:
+        case SDL_SCANCODE_RSHIFT:
             keyboard->modstate |= KMOD_RSHIFT;
             break;
-        case SDLK_LALT:
+        case SDL_SCANCODE_LALT:
             keyboard->modstate |= KMOD_LALT;
             break;
-        case SDLK_RALT:
+        case SDL_SCANCODE_RALT:
             keyboard->modstate |= KMOD_RALT;
             break;
-        case SDLK_LMETA:
-            keyboard->modstate |= KMOD_LMETA;
+        case SDL_SCANCODE_LGUI:
+            keyboard->modstate |= KMOD_LGUI;
             break;
-        case SDLK_RMETA:
-            keyboard->modstate |= KMOD_RMETA;
+        case SDL_SCANCODE_RGUI:
+            keyboard->modstate |= KMOD_RGUI;
             break;
-        case SDLK_MODE:
+        case SDL_SCANCODE_MODE:
             keyboard->modstate |= KMOD_MODE;
             break;
         default:
             break;
         }
     } else {
-        switch (physicalKey) {
-        case SDLK_UNKNOWN:
+        switch (scancode) {
+        case SDL_SCANCODE_NUMLOCKCLEAR:
+        case SDL_SCANCODE_CAPSLOCK:
             break;
-        case SDLK_KP_NUMLOCKCLEAR:
-        case SDLK_CAPSLOCK:
-            break;
-        case SDLK_LCTRL:
+        case SDL_SCANCODE_LCTRL:
             keyboard->modstate &= ~KMOD_LCTRL;
             break;
-        case SDLK_RCTRL:
+        case SDL_SCANCODE_RCTRL:
             keyboard->modstate &= ~KMOD_RCTRL;
             break;
-        case SDLK_LSHIFT:
+        case SDL_SCANCODE_LSHIFT:
             keyboard->modstate &= ~KMOD_LSHIFT;
             break;
-        case SDLK_RSHIFT:
+        case SDL_SCANCODE_RSHIFT:
             keyboard->modstate &= ~KMOD_RSHIFT;
             break;
-        case SDLK_LALT:
+        case SDL_SCANCODE_LALT:
             keyboard->modstate &= ~KMOD_LALT;
             break;
-        case SDLK_RALT:
+        case SDL_SCANCODE_RALT:
             keyboard->modstate &= ~KMOD_RALT;
             break;
-        case SDLK_LMETA:
-            keyboard->modstate &= ~KMOD_LMETA;
+        case SDL_SCANCODE_LGUI:
+            keyboard->modstate &= ~KMOD_LGUI;
             break;
-        case SDLK_RMETA:
-            keyboard->modstate &= ~KMOD_RMETA;
+        case SDL_SCANCODE_RGUI:
+            keyboard->modstate &= ~KMOD_RGUI;
             break;
-        case SDLK_MODE:
+        case SDL_SCANCODE_MODE:
             keyboard->modstate &= ~KMOD_MODE;
             break;
         default:
@@ -475,18 +799,16 @@
         return 0;
     }
 
-    if (physicalKey != SDLK_UNKNOWN) {
-        /* Drop events that don't change state */
-        if (keyboard->keystate[SDLK_INDEX(physicalKey)] == state) {
+    /* Drop events that don't change state */
+    if (keyboard->keystate[scancode] == state) {
 #if 0
-            printf("Keyboard event didn't change state - dropped!\n");
+        printf("Keyboard event didn't change state - dropped!\n");
 #endif
-            return 0;
-        }
+        return 0;
+    }
 
-        /* Update internal keyboard state */
-        keyboard->keystate[SDLK_INDEX(physicalKey)] = state;
-    }
+    /* Update internal keyboard state */
+    keyboard->keystate[scancode] = state;
 
     /* Post the event, if desired */
     posted = 0;
@@ -496,7 +818,7 @@
         event.key.which = (Uint8) index;
         event.key.state = state;
         event.key.keysym.scancode = scancode;
-        event.key.keysym.sym = physicalKey;
+        event.key.keysym.sym = keyboard->keymap[scancode];
         event.key.keysym.mod = modstate;
         event.key.keysym.unicode = 0;
         event.key.windowID = keyboard->focus;
@@ -528,4 +850,138 @@
     return (posted);
 }
 
+void
+SDL_KeyboardQuit(void)
+{
+    int i;
+
+    for (i = 0; i < SDL_num_keyboards; ++i) {
+        SDL_DelKeyboard(i);
+    }
+    SDL_num_keyboards = 0;
+    SDL_current_keyboard = 0;
+
+    if (SDL_keyboards) {
+        SDL_free(SDL_keyboards);
+        SDL_keyboards = NULL;
+    }
+}
+
+int
+SDL_GetNumKeyboards(void)
+{
+    return SDL_num_keyboards;
+}
+
+int
+SDL_SelectKeyboard(int index)
+{
+    if (index >= 0 && index < SDL_num_keyboards) {
+        SDL_current_keyboard = index;
+    }
+    return SDL_current_keyboard;
+}
+
+Uint8 *
+SDL_GetKeyboardState(int *numkeys)
+{
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+
+    if (numkeys != (int *) 0) {
+        *numkeys = SDL_NUM_SCANCODES;
+    }
+
+    if (!keyboard) {
+        return NULL;
+    }
+    return keyboard->keystate;
+}
+
+SDLMod
+SDL_GetModState(void)
+{
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+
+    if (!keyboard) {
+        return KMOD_NONE;
+    }
+    return keyboard->modstate;
+}
+
+void
+SDL_SetModState(SDLMod modstate)
+{
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+
+    if (!keyboard) {
+        return;
+    }
+    keyboard->modstate = modstate;
+}
+
+SDLKey
+SDL_GetKeyFromScancode(SDL_scancode scancode)
+{
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+
+    if (!keyboard) {
+        return SDLK_UNKNOWN;
+    }
+    return keyboard->keymap[scancode];
+}
+
+SDL_scancode
+SDL_GetScancodeFromKey(SDLKey key)
+{
+    SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
+    SDL_scancode scancode;
+
+    if (!keyboard) {
+        return SDL_SCANCODE_UNKNOWN;
+    }
+
+    for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
+         ++scancode) {
+        if (keyboard->keymap[scancode] == key) {
+            return scancode;
+        }
+    }
+    return SDL_SCANCODE_UNKNOWN;
+}
+
+const char *
+SDL_GetScancodeName(SDL_scancode scancode)
+{
+    const char *name = SDL_scancode_names[scancode];
+
+    if (name)
+        return name;
+    else
+        return "";
+}
+
+const char *
+SDL_GetKeyName(SDLKey key)
+{
+    static char name[8];
+    char *end;
+
+    if (key & SDLK_SCANCODE_MASK) {
+        return
+            SDL_GetScancodeName((SDL_scancode) (key & ~SDLK_SCANCODE_MASK));
+    }
+
+    /* Unaccented letter keys on latin keyboards are normally
+       labeled in upper case (and probably on others like Greek or
+       Cyrillic too, so if you happen to know for sure, please
+       adapt this). */
+    if (key >= 'a' && key <= 'z') {
+        key -= 32;
+    }
+
+    end = SDL_UCS4ToUTF8((Uint32) key, name);
+    *end = '\0';
+    return name;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */