src/events/SDL_keyboard.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Sun, 13 Jan 2013 22:55:26 -0800
changeset 6813 b21879e67db2
parent 6811 60d95fcfaf3c
child 6885 700f1b25f77f
permissions -rw-r--r--
Add input validation to SDL_GetKeyFromScancode; fix compiler warning in testautomation driver on Linux; update keyboard test suite
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 /* General keyboard handling code for SDL */
    24 
    25 #include "SDL_timer.h"
    26 #include "SDL_events.h"
    27 #include "SDL_events_c.h"
    28 #include "../video/SDL_sysvideo.h"
    29 
    30 
    31 /*#define DEBUG_KEYBOARD*/
    32 
    33 /* Global keyboard information */
    34 
    35 typedef struct SDL_Keyboard SDL_Keyboard;
    36 
    37 struct SDL_Keyboard
    38 {
    39     /* Data common to all keyboards */
    40     SDL_Window *focus;
    41     Uint16 modstate;
    42     Uint8 keystate[SDL_NUM_SCANCODES];
    43     SDL_Keycode keymap[SDL_NUM_SCANCODES];
    44 };
    45 
    46 static SDL_Keyboard SDL_keyboard;
    47 
    48 static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = {
    49     0, 0, 0, 0,
    50     'a',
    51     'b',
    52     'c',
    53     'd',
    54     'e',
    55     'f',
    56     'g',
    57     'h',
    58     'i',
    59     'j',
    60     'k',
    61     'l',
    62     'm',
    63     'n',
    64     'o',
    65     'p',
    66     'q',
    67     'r',
    68     's',
    69     't',
    70     'u',
    71     'v',
    72     'w',
    73     'x',
    74     'y',
    75     'z',
    76     '1',
    77     '2',
    78     '3',
    79     '4',
    80     '5',
    81     '6',
    82     '7',
    83     '8',
    84     '9',
    85     '0',
    86     SDLK_RETURN,
    87     SDLK_ESCAPE,
    88     SDLK_BACKSPACE,
    89     SDLK_TAB,
    90     SDLK_SPACE,
    91     '-',
    92     '=',
    93     '[',
    94     ']',
    95     '\\',
    96     '#',
    97     ';',
    98     '\'',
    99     '`',
   100     ',',
   101     '.',
   102     '/',
   103     SDLK_CAPSLOCK,
   104     SDLK_F1,
   105     SDLK_F2,
   106     SDLK_F3,
   107     SDLK_F4,
   108     SDLK_F5,
   109     SDLK_F6,
   110     SDLK_F7,
   111     SDLK_F8,
   112     SDLK_F9,
   113     SDLK_F10,
   114     SDLK_F11,
   115     SDLK_F12,
   116     SDLK_PRINTSCREEN,
   117     SDLK_SCROLLLOCK,
   118     SDLK_PAUSE,
   119     SDLK_INSERT,
   120     SDLK_HOME,
   121     SDLK_PAGEUP,
   122     SDLK_DELETE,
   123     SDLK_END,
   124     SDLK_PAGEDOWN,
   125     SDLK_RIGHT,
   126     SDLK_LEFT,
   127     SDLK_DOWN,
   128     SDLK_UP,
   129     SDLK_NUMLOCKCLEAR,
   130     SDLK_KP_DIVIDE,
   131     SDLK_KP_MULTIPLY,
   132     SDLK_KP_MINUS,
   133     SDLK_KP_PLUS,
   134     SDLK_KP_ENTER,
   135     SDLK_KP_1,
   136     SDLK_KP_2,
   137     SDLK_KP_3,
   138     SDLK_KP_4,
   139     SDLK_KP_5,
   140     SDLK_KP_6,
   141     SDLK_KP_7,
   142     SDLK_KP_8,
   143     SDLK_KP_9,
   144     SDLK_KP_0,
   145     SDLK_KP_PERIOD,
   146     0,
   147     SDLK_APPLICATION,
   148     SDLK_POWER,
   149     SDLK_KP_EQUALS,
   150     SDLK_F13,
   151     SDLK_F14,
   152     SDLK_F15,
   153     SDLK_F16,
   154     SDLK_F17,
   155     SDLK_F18,
   156     SDLK_F19,
   157     SDLK_F20,
   158     SDLK_F21,
   159     SDLK_F22,
   160     SDLK_F23,
   161     SDLK_F24,
   162     SDLK_EXECUTE,
   163     SDLK_HELP,
   164     SDLK_MENU,
   165     SDLK_SELECT,
   166     SDLK_STOP,
   167     SDLK_AGAIN,
   168     SDLK_UNDO,
   169     SDLK_CUT,
   170     SDLK_COPY,
   171     SDLK_PASTE,
   172     SDLK_FIND,
   173     SDLK_MUTE,
   174     SDLK_VOLUMEUP,
   175     SDLK_VOLUMEDOWN,
   176     0, 0, 0,
   177     SDLK_KP_COMMA,
   178     SDLK_KP_EQUALSAS400,
   179     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   180     SDLK_ALTERASE,
   181     SDLK_SYSREQ,
   182     SDLK_CANCEL,
   183     SDLK_CLEAR,
   184     SDLK_PRIOR,
   185     SDLK_RETURN2,
   186     SDLK_SEPARATOR,
   187     SDLK_OUT,
   188     SDLK_OPER,
   189     SDLK_CLEARAGAIN,
   190     SDLK_CRSEL,
   191     SDLK_EXSEL,
   192     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   193     SDLK_KP_00,
   194     SDLK_KP_000,
   195     SDLK_THOUSANDSSEPARATOR,
   196     SDLK_DECIMALSEPARATOR,
   197     SDLK_CURRENCYUNIT,
   198     SDLK_CURRENCYSUBUNIT,
   199     SDLK_KP_LEFTPAREN,
   200     SDLK_KP_RIGHTPAREN,
   201     SDLK_KP_LEFTBRACE,
   202     SDLK_KP_RIGHTBRACE,
   203     SDLK_KP_TAB,
   204     SDLK_KP_BACKSPACE,
   205     SDLK_KP_A,
   206     SDLK_KP_B,
   207     SDLK_KP_C,
   208     SDLK_KP_D,
   209     SDLK_KP_E,
   210     SDLK_KP_F,
   211     SDLK_KP_XOR,
   212     SDLK_KP_POWER,
   213     SDLK_KP_PERCENT,
   214     SDLK_KP_LESS,
   215     SDLK_KP_GREATER,
   216     SDLK_KP_AMPERSAND,
   217     SDLK_KP_DBLAMPERSAND,
   218     SDLK_KP_VERTICALBAR,
   219     SDLK_KP_DBLVERTICALBAR,
   220     SDLK_KP_COLON,
   221     SDLK_KP_HASH,
   222     SDLK_KP_SPACE,
   223     SDLK_KP_AT,
   224     SDLK_KP_EXCLAM,
   225     SDLK_KP_MEMSTORE,
   226     SDLK_KP_MEMRECALL,
   227     SDLK_KP_MEMCLEAR,
   228     SDLK_KP_MEMADD,
   229     SDLK_KP_MEMSUBTRACT,
   230     SDLK_KP_MEMMULTIPLY,
   231     SDLK_KP_MEMDIVIDE,
   232     SDLK_KP_PLUSMINUS,
   233     SDLK_KP_CLEAR,
   234     SDLK_KP_CLEARENTRY,
   235     SDLK_KP_BINARY,
   236     SDLK_KP_OCTAL,
   237     SDLK_KP_DECIMAL,
   238     SDLK_KP_HEXADECIMAL,
   239     0, 0,
   240     SDLK_LCTRL,
   241     SDLK_LSHIFT,
   242     SDLK_LALT,
   243     SDLK_LGUI,
   244     SDLK_RCTRL,
   245     SDLK_RSHIFT,
   246     SDLK_RALT,
   247     SDLK_RGUI,
   248     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,
   249     SDLK_MODE,
   250     SDLK_AUDIONEXT,
   251     SDLK_AUDIOPREV,
   252     SDLK_AUDIOSTOP,
   253     SDLK_AUDIOPLAY,
   254     SDLK_AUDIOMUTE,
   255     SDLK_MEDIASELECT,
   256     SDLK_WWW,
   257     SDLK_MAIL,
   258     SDLK_CALCULATOR,
   259     SDLK_COMPUTER,
   260     SDLK_AC_SEARCH,
   261     SDLK_AC_HOME,
   262     SDLK_AC_BACK,
   263     SDLK_AC_FORWARD,
   264     SDLK_AC_STOP,
   265     SDLK_AC_REFRESH,
   266     SDLK_AC_BOOKMARKS,
   267     SDLK_BRIGHTNESSDOWN,
   268     SDLK_BRIGHTNESSUP,
   269     SDLK_DISPLAYSWITCH,
   270     SDLK_KBDILLUMTOGGLE,
   271     SDLK_KBDILLUMDOWN,
   272     SDLK_KBDILLUMUP,
   273     SDLK_EJECT,
   274     SDLK_SLEEP,
   275 };
   276 
   277 static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
   278     NULL, NULL, NULL, NULL,
   279     "A",
   280     "B",
   281     "C",
   282     "D",
   283     "E",
   284     "F",
   285     "G",
   286     "H",
   287     "I",
   288     "J",
   289     "K",
   290     "L",
   291     "M",
   292     "N",
   293     "O",
   294     "P",
   295     "Q",
   296     "R",
   297     "S",
   298     "T",
   299     "U",
   300     "V",
   301     "W",
   302     "X",
   303     "Y",
   304     "Z",
   305     "1",
   306     "2",
   307     "3",
   308     "4",
   309     "5",
   310     "6",
   311     "7",
   312     "8",
   313     "9",
   314     "0",
   315     "Return",
   316     "Escape",
   317     "Backspace",
   318     "Tab",
   319     "Space",
   320     "-",
   321     "=",
   322     "[",
   323     "]",
   324     "\\",
   325     "#",
   326     ";",
   327     "'",
   328     "`",
   329     ",",
   330     ".",
   331     "/",
   332     "CapsLock",
   333     "F1",
   334     "F2",
   335     "F3",
   336     "F4",
   337     "F5",
   338     "F6",
   339     "F7",
   340     "F8",
   341     "F9",
   342     "F10",
   343     "F11",
   344     "F12",
   345     "PrintScreen",
   346     "ScrollLock",
   347     "Pause",
   348     "Insert",
   349     "Home",
   350     "PageUp",
   351     "Delete",
   352     "End",
   353     "PageDown",
   354     "Right",
   355     "Left",
   356     "Down",
   357     "Up",
   358     "Numlock",
   359     "Keypad /",
   360     "Keypad *",
   361     "Keypad -",
   362     "Keypad +",
   363     "Keypad Enter",
   364     "Keypad 1",
   365     "Keypad 2",
   366     "Keypad 3",
   367     "Keypad 4",
   368     "Keypad 5",
   369     "Keypad 6",
   370     "Keypad 7",
   371     "Keypad 8",
   372     "Keypad 9",
   373     "Keypad 0",
   374     "Keypad .",
   375     NULL,
   376     "Application",
   377     "Power",
   378     "Keypad =",
   379     "F13",
   380     "F14",
   381     "F15",
   382     "F16",
   383     "F17",
   384     "F18",
   385     "F19",
   386     "F20",
   387     "F21",
   388     "F22",
   389     "F23",
   390     "F24",
   391     "Execute",
   392     "Help",
   393     "Menu",
   394     "Select",
   395     "Stop",
   396     "Again",
   397     "Undo",
   398     "Cut",
   399     "Copy",
   400     "Paste",
   401     "Find",
   402     "Mute",
   403     "VolumeUp",
   404     "VolumeDown",
   405     NULL, NULL, NULL,
   406     "Keypad ,",
   407     "Keypad = (AS400)",
   408     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   409     NULL, NULL, NULL, NULL, NULL, NULL,
   410     "AltErase",
   411     "SysReq",
   412     "Cancel",
   413     "Clear",
   414     "Prior",
   415     "Return",
   416     "Separator",
   417     "Out",
   418     "Oper",
   419     "Clear / Again",
   420     "CrSel",
   421     "ExSel",
   422     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   423     "Keypad 00",
   424     "Keypad 000",
   425     "ThousandsSeparator",
   426     "DecimalSeparator",
   427     "CurrencyUnit",
   428     "CurrencySubUnit",
   429     "Keypad (",
   430     "Keypad )",
   431     "Keypad {",
   432     "Keypad }",
   433     "Keypad Tab",
   434     "Keypad Backspace",
   435     "Keypad A",
   436     "Keypad B",
   437     "Keypad C",
   438     "Keypad D",
   439     "Keypad E",
   440     "Keypad F",
   441     "Keypad XOR",
   442     "Keypad ^",
   443     "Keypad %",
   444     "Keypad <",
   445     "Keypad >",
   446     "Keypad &",
   447     "Keypad &&",
   448     "Keypad |",
   449     "Keypad ||",
   450     "Keypad :",
   451     "Keypad #",
   452     "Keypad Space",
   453     "Keypad @",
   454     "Keypad !",
   455     "Keypad MemStore",
   456     "Keypad MemRecall",
   457     "Keypad MemClear",
   458     "Keypad MemAdd",
   459     "Keypad MemSubtract",
   460     "Keypad MemMultiply",
   461     "Keypad MemDivide",
   462     "Keypad +/-",
   463     "Keypad Clear",
   464     "Keypad ClearEntry",
   465     "Keypad Binary",
   466     "Keypad Octal",
   467     "Keypad Decimal",
   468     "Keypad Hexadecimal",
   469     NULL, NULL,
   470     "Left Ctrl",
   471     "Left Shift",
   472     "Left Alt",
   473     "Left GUI",
   474     "Right Ctrl",
   475     "Right Shift",
   476     "Right Alt",
   477     "Right GUI",
   478     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   479     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   480     NULL,
   481     "ModeSwitch",
   482     "AudioNext",
   483     "AudioPrev",
   484     "AudioStop",
   485     "AudioPlay",
   486     "AudioMute",
   487     "MediaSelect",
   488     "WWW",
   489     "Mail",
   490     "Calculator",
   491     "Computer",
   492     "AC Search",
   493     "AC Home",
   494     "AC Back",
   495     "AC Forward",
   496     "AC Stop",
   497     "AC Refresh",
   498     "AC Bookmarks",
   499     "BrightnessDown",
   500     "BrightnessUp",
   501     "DisplaySwitch",
   502     "KBDIllumToggle",
   503     "KBDIllumDown",
   504     "KBDIllumUp",
   505     "Eject",
   506     "Sleep",
   507 };
   508 
   509 /* Taken from SDL_iconv() */
   510 static char *
   511 SDL_UCS4ToUTF8(Uint32 ch, char *dst)
   512 {
   513     Uint8 *p = (Uint8 *) dst;
   514     if (ch <= 0x7F) {
   515         *p = (Uint8) ch;
   516         ++dst;
   517     } else if (ch <= 0x7FF) {
   518         p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
   519         p[1] = 0x80 | (Uint8) (ch & 0x3F);
   520         dst += 2;
   521     } else if (ch <= 0xFFFF) {
   522         p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
   523         p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   524         p[2] = 0x80 | (Uint8) (ch & 0x3F);
   525         dst += 3;
   526     } else if (ch <= 0x1FFFFF) {
   527         p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
   528         p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   529         p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   530         p[3] = 0x80 | (Uint8) (ch & 0x3F);
   531         dst += 4;
   532     } else if (ch <= 0x3FFFFFF) {
   533         p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
   534         p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   535         p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   536         p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   537         p[4] = 0x80 | (Uint8) (ch & 0x3F);
   538         dst += 5;
   539     } else {
   540         p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
   541         p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
   542         p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   543         p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   544         p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   545         p[5] = 0x80 | (Uint8) (ch & 0x3F);
   546         dst += 6;
   547     }
   548     return dst;
   549 }
   550 
   551 /* Public functions */
   552 int
   553 SDL_KeyboardInit(void)
   554 {
   555     SDL_Keyboard *keyboard = &SDL_keyboard;
   556 
   557     /* Set the default keymap */
   558     SDL_memcpy(keyboard->keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
   559     return (0);
   560 }
   561 
   562 void
   563 SDL_ResetKeyboard(void)
   564 {
   565     SDL_Keyboard *keyboard = &SDL_keyboard;
   566     SDL_Scancode scancode;
   567 
   568 #ifdef DEBUG_KEYBOARD
   569     printf("Resetting keyboard\n");
   570 #endif
   571     for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
   572         if (keyboard->keystate[scancode] == SDL_PRESSED) {
   573             SDL_SendKeyboardKey(SDL_RELEASED, scancode);
   574         }
   575     }
   576 }
   577 
   578 void
   579 SDL_GetDefaultKeymap(SDL_Keycode * keymap)
   580 {
   581     SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
   582 }
   583 
   584 void
   585 SDL_SetKeymap(int start, SDL_Keycode * keys, int length)
   586 {
   587     SDL_Keyboard *keyboard = &SDL_keyboard;
   588 
   589     if (start < 0 || start + length > SDL_NUM_SCANCODES) {
   590         return;
   591     }
   592 
   593     SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
   594 }
   595 
   596 void
   597 SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
   598 {
   599     SDL_scancode_names[scancode] = name;
   600 }
   601 
   602 SDL_Window *
   603 SDL_GetKeyboardFocus(void)
   604 {
   605     SDL_Keyboard *keyboard = &SDL_keyboard;
   606 
   607     return keyboard->focus;
   608 }
   609 
   610 void
   611 SDL_SetKeyboardFocus(SDL_Window * window)
   612 {
   613     SDL_Keyboard *keyboard = &SDL_keyboard;
   614 
   615     if (keyboard->focus && !window) {
   616         /* We won't get anymore keyboard messages, so reset keyboard state */
   617         SDL_ResetKeyboard();
   618     }
   619 
   620     /* See if the current window has lost focus */
   621     if (keyboard->focus && keyboard->focus != window) {
   622         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
   623                             0, 0);
   624 
   625         /* Ensures IME compositions are committed */
   626         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   627             SDL_VideoDevice *video = SDL_GetVideoDevice();
   628             if (video && video->StopTextInput) {
   629                 video->StopTextInput(video);
   630             }
   631         }
   632     }
   633 
   634     keyboard->focus = window;
   635 
   636     if (keyboard->focus) {
   637         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   638                             0, 0);
   639 
   640         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   641             SDL_VideoDevice *video = SDL_GetVideoDevice();
   642             if (video && video->StartTextInput) {
   643                 video->StartTextInput(video);
   644             }
   645         }
   646     }
   647 }
   648 
   649 int
   650 SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
   651 {
   652     SDL_Keyboard *keyboard = &SDL_keyboard;
   653     int posted;
   654     Uint16 modstate;
   655     Uint32 type;
   656     Uint8 repeat;
   657 
   658     if (!scancode) {
   659         return 0;
   660     }
   661 #ifdef DEBUG_KEYBOARD
   662     printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
   663            state == SDL_PRESSED ? "pressed" : "released");
   664 #endif
   665     if (state == SDL_PRESSED) {
   666         modstate = keyboard->modstate;
   667         switch (scancode) {
   668         case SDL_SCANCODE_NUMLOCKCLEAR:
   669             keyboard->modstate ^= KMOD_NUM;
   670             break;
   671         case SDL_SCANCODE_CAPSLOCK:
   672             keyboard->modstate ^= KMOD_CAPS;
   673             break;
   674         case SDL_SCANCODE_LCTRL:
   675             keyboard->modstate |= KMOD_LCTRL;
   676             break;
   677         case SDL_SCANCODE_RCTRL:
   678             keyboard->modstate |= KMOD_RCTRL;
   679             break;
   680         case SDL_SCANCODE_LSHIFT:
   681             keyboard->modstate |= KMOD_LSHIFT;
   682             break;
   683         case SDL_SCANCODE_RSHIFT:
   684             keyboard->modstate |= KMOD_RSHIFT;
   685             break;
   686         case SDL_SCANCODE_LALT:
   687             keyboard->modstate |= KMOD_LALT;
   688             break;
   689         case SDL_SCANCODE_RALT:
   690             keyboard->modstate |= KMOD_RALT;
   691             break;
   692         case SDL_SCANCODE_LGUI:
   693             keyboard->modstate |= KMOD_LGUI;
   694             break;
   695         case SDL_SCANCODE_RGUI:
   696             keyboard->modstate |= KMOD_RGUI;
   697             break;
   698         case SDL_SCANCODE_MODE:
   699             keyboard->modstate |= KMOD_MODE;
   700             break;
   701         default:
   702             break;
   703         }
   704     } else {
   705         switch (scancode) {
   706         case SDL_SCANCODE_NUMLOCKCLEAR:
   707         case SDL_SCANCODE_CAPSLOCK:
   708             break;
   709         case SDL_SCANCODE_LCTRL:
   710             keyboard->modstate &= ~KMOD_LCTRL;
   711             break;
   712         case SDL_SCANCODE_RCTRL:
   713             keyboard->modstate &= ~KMOD_RCTRL;
   714             break;
   715         case SDL_SCANCODE_LSHIFT:
   716             keyboard->modstate &= ~KMOD_LSHIFT;
   717             break;
   718         case SDL_SCANCODE_RSHIFT:
   719             keyboard->modstate &= ~KMOD_RSHIFT;
   720             break;
   721         case SDL_SCANCODE_LALT:
   722             keyboard->modstate &= ~KMOD_LALT;
   723             break;
   724         case SDL_SCANCODE_RALT:
   725             keyboard->modstate &= ~KMOD_RALT;
   726             break;
   727         case SDL_SCANCODE_LGUI:
   728             keyboard->modstate &= ~KMOD_LGUI;
   729             break;
   730         case SDL_SCANCODE_RGUI:
   731             keyboard->modstate &= ~KMOD_RGUI;
   732             break;
   733         case SDL_SCANCODE_MODE:
   734             keyboard->modstate &= ~KMOD_MODE;
   735             break;
   736         default:
   737             break;
   738         }
   739         modstate = keyboard->modstate;
   740     }
   741 
   742     /* Figure out what type of event this is */
   743     switch (state) {
   744     case SDL_PRESSED:
   745         type = SDL_KEYDOWN;
   746         break;
   747     case SDL_RELEASED:
   748         type = SDL_KEYUP;
   749         break;
   750     default:
   751         /* Invalid state -- bail */
   752         return 0;
   753     }
   754 
   755     /* Drop events that don't change state */
   756     repeat = (state && keyboard->keystate[scancode]);
   757     if (keyboard->keystate[scancode] == state && !repeat) {
   758 #if 0
   759         printf("Keyboard event didn't change state - dropped!\n");
   760 #endif
   761         return 0;
   762     }
   763 
   764     /* Update internal keyboard state */
   765     keyboard->keystate[scancode] = state;
   766 
   767     /* Post the event, if desired */
   768     posted = 0;
   769     if (SDL_GetEventState(type) == SDL_ENABLE) {
   770         SDL_Event event;
   771         event.key.type = type;
   772         event.key.state = state;
   773         event.key.repeat = repeat;
   774         event.key.keysym.scancode = scancode;
   775         event.key.keysym.sym = keyboard->keymap[scancode];
   776         event.key.keysym.mod = modstate;
   777         event.key.keysym.unicode = 0;
   778         event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
   779         posted = (SDL_PushEvent(&event) > 0);
   780     }
   781     return (posted);
   782 }
   783 
   784 int
   785 SDL_SendKeyboardText(const char *text)
   786 {
   787     SDL_Keyboard *keyboard = &SDL_keyboard;
   788     int posted;
   789 
   790     /* Don't post text events for unprintable characters */
   791     if ((unsigned char)*text < ' ' || *text == 127) {
   792         return 0;
   793     }
   794 
   795     /* Post the event, if desired */
   796     posted = 0;
   797     if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
   798         SDL_Event event;
   799         event.text.type = SDL_TEXTINPUT;
   800         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   801         SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   802         posted = (SDL_PushEvent(&event) > 0);
   803     }
   804     return (posted);
   805 }
   806 
   807 int
   808 SDL_SendEditingText(const char *text, int start, int length)
   809 {
   810     SDL_Keyboard *keyboard = &SDL_keyboard;
   811     int posted;
   812 
   813     /* Post the event, if desired */
   814     posted = 0;
   815     if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
   816         SDL_Event event;
   817         event.edit.type = SDL_TEXTEDITING;
   818         event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
   819         event.edit.start = start;
   820         event.edit.length = length;
   821         SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
   822         posted = (SDL_PushEvent(&event) > 0);
   823     }
   824     return (posted);
   825 }
   826 
   827 void
   828 SDL_KeyboardQuit(void)
   829 {
   830 }
   831 
   832 Uint8 *
   833 SDL_GetKeyboardState(int *numkeys)
   834 {
   835     SDL_Keyboard *keyboard = &SDL_keyboard;
   836 
   837     if (numkeys != (int *) 0) {
   838         *numkeys = SDL_NUM_SCANCODES;
   839     }
   840     return keyboard->keystate;
   841 }
   842 
   843 SDL_Keymod
   844 SDL_GetModState(void)
   845 {
   846     SDL_Keyboard *keyboard = &SDL_keyboard;
   847 
   848     return keyboard->modstate;
   849 }
   850 
   851 void
   852 SDL_SetModState(SDL_Keymod modstate)
   853 {
   854     SDL_Keyboard *keyboard = &SDL_keyboard;
   855 
   856     keyboard->modstate = modstate;
   857 }
   858 
   859 SDL_Keycode
   860 SDL_GetKeyFromScancode(SDL_Scancode scancode)
   861 {
   862     SDL_Keyboard *keyboard = &SDL_keyboard;
   863     
   864     if (scancode<SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
   865           SDL_InvalidParamError("scancode");
   866           return 0;
   867     }
   868 
   869     return keyboard->keymap[scancode];
   870 }
   871 
   872 SDL_Scancode
   873 SDL_GetScancodeFromKey(SDL_Keycode key)
   874 {
   875     SDL_Keyboard *keyboard = &SDL_keyboard;
   876     SDL_Scancode scancode;
   877 
   878     for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
   879          ++scancode) {
   880         if (keyboard->keymap[scancode] == key) {
   881             return scancode;
   882         }
   883     }
   884     return SDL_SCANCODE_UNKNOWN;
   885 }
   886 
   887 const char *
   888 SDL_GetScancodeName(SDL_Scancode scancode)
   889 {
   890     const char *name = SDL_scancode_names[scancode];
   891 
   892     if (name)
   893         return name;
   894     else
   895         return "";
   896 }
   897 
   898 SDL_Scancode SDL_GetScancodeFromName(const char *name)
   899 {
   900 	int i;
   901 
   902 	if (!name || !*name) {
   903 	        SDL_InvalidParamError("name");
   904 		return SDL_SCANCODE_UNKNOWN;
   905 	}
   906 
   907 	for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
   908 		if (!SDL_scancode_names[i]) {
   909 			continue;
   910 		}		
   911 		if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
   912 			return (SDL_Scancode)i;
   913 		}
   914 	}
   915 
   916 	SDL_InvalidParamError("name");
   917 	return SDL_SCANCODE_UNKNOWN;
   918 }
   919 
   920 const char *
   921 SDL_GetKeyName(SDL_Keycode key)
   922 {
   923     static char name[8];
   924     char *end;
   925 
   926     if (key & SDLK_SCANCODE_MASK) {
   927         return
   928             SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
   929     }
   930 
   931     switch (key) {
   932     case SDLK_RETURN:
   933         return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
   934     case SDLK_ESCAPE:
   935         return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
   936     case SDLK_BACKSPACE:
   937         return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
   938     case SDLK_TAB:
   939         return SDL_GetScancodeName(SDL_SCANCODE_TAB);
   940     case SDLK_SPACE:
   941         return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
   942     case SDLK_DELETE:
   943         return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
   944     default:
   945         /* Unaccented letter keys on latin keyboards are normally
   946            labeled in upper case (and probably on others like Greek or
   947            Cyrillic too, so if you happen to know for sure, please
   948            adapt this). */
   949         if (key >= 'a' && key <= 'z') {
   950             key -= 32;
   951         }
   952 
   953         end = SDL_UCS4ToUTF8((Uint32) key, name);
   954         *end = '\0';
   955         return name;
   956     }
   957 }
   958 
   959 SDL_Keycode
   960 SDL_GetKeyFromName(const char *name)
   961 {
   962 	SDL_Keycode key;
   963 
   964         /* Check input */
   965         if (name == NULL) return SDLK_UNKNOWN;
   966         
   967 	/* If it's a single UTF-8 character, then that's the keycode itself */
   968 	key = *(const unsigned char *)name;
   969 	if (key >= 0xF0) {
   970 		if (SDL_strlen(name) == 4) {
   971 			int i = 0;
   972 			key  = (Uint16)(name[i]&0x07) << 18;
   973 			key |= (Uint16)(name[++i]&0x3F) << 12;
   974 			key |= (Uint16)(name[++i]&0x3F) << 6;
   975 			key |= (Uint16)(name[++i]&0x3F);
   976 			return key;
   977 		}
   978 		return SDLK_UNKNOWN;
   979 	} else if (key >= 0xE0) {
   980 		if (SDL_strlen(name) == 3) {
   981 			int i = 0;
   982 			key  = (Uint16)(name[i]&0x0F) << 12;
   983 			key |= (Uint16)(name[++i]&0x3F) << 6;
   984 			key |= (Uint16)(name[++i]&0x3F);
   985 			return key;
   986 		}
   987 		return SDLK_UNKNOWN;
   988 	} else if (key >= 0xC0) {
   989 		if (SDL_strlen(name) == 2) {
   990 			int i = 0;
   991 			key  = (Uint16)(name[i]&0x1F) << 6;
   992 			key |= (Uint16)(name[++i]&0x3F);
   993 			return key;
   994 		}
   995 		return SDLK_UNKNOWN;
   996 	} else {
   997 		if (SDL_strlen(name) == 1) {
   998 			if (key >= 'A' && key <= 'Z') {
   999 				key += 32;
  1000 			}
  1001 			return key;
  1002 		}
  1003 
  1004 		/* Get the scancode for this name, and the associated keycode */
  1005 		return SDL_default_keymap[SDL_GetScancodeFromName(name)];
  1006 	}
  1007 }
  1008 
  1009 /* vi: set ts=4 sw=4 expandtab: */