src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 07 Nov 2012 11:13:28 -0800
changeset 6661 cd8befc0a969
parent 6138 4c64952a58fb
child 6665 c0ea8c57034c
permissions -rw-r--r--
Reset the keyboard when we lose input focus
     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     /* See if the current window has lost focus */
   616     if (keyboard->focus && keyboard->focus != window) {
   617         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
   618                             0, 0);
   619 
   620         /* Ensures IME compositions are committed */
   621         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   622             SDL_VideoDevice *video = SDL_GetVideoDevice();
   623             if (video && video->StopTextInput) {
   624                 video->StopTextInput(video);
   625             }
   626         }
   627     }
   628 
   629     keyboard->focus = window;
   630 
   631     if (keyboard->focus) {
   632         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   633                             0, 0);
   634 
   635         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   636             SDL_VideoDevice *video = SDL_GetVideoDevice();
   637             if (video && video->StartTextInput) {
   638                 video->StartTextInput(video);
   639             }
   640         }
   641     } else {
   642         /* We won't get anymore keyboard messages, so reset keyboard state */
   643         SDL_ResetKeyboard();
   644     }
   645 }
   646 
   647 int
   648 SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
   649 {
   650     SDL_Keyboard *keyboard = &SDL_keyboard;
   651     int posted;
   652     Uint16 modstate;
   653     Uint32 type;
   654     Uint8 repeat;
   655 
   656     if (!scancode) {
   657         return 0;
   658     }
   659 #ifdef DEBUG_KEYBOARD
   660     printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
   661            state == SDL_PRESSED ? "pressed" : "released");
   662 #endif
   663     if (state == SDL_PRESSED) {
   664         modstate = keyboard->modstate;
   665         switch (scancode) {
   666         case SDL_SCANCODE_NUMLOCKCLEAR:
   667             keyboard->modstate ^= KMOD_NUM;
   668             break;
   669         case SDL_SCANCODE_CAPSLOCK:
   670             keyboard->modstate ^= KMOD_CAPS;
   671             break;
   672         case SDL_SCANCODE_LCTRL:
   673             keyboard->modstate |= KMOD_LCTRL;
   674             break;
   675         case SDL_SCANCODE_RCTRL:
   676             keyboard->modstate |= KMOD_RCTRL;
   677             break;
   678         case SDL_SCANCODE_LSHIFT:
   679             keyboard->modstate |= KMOD_LSHIFT;
   680             break;
   681         case SDL_SCANCODE_RSHIFT:
   682             keyboard->modstate |= KMOD_RSHIFT;
   683             break;
   684         case SDL_SCANCODE_LALT:
   685             keyboard->modstate |= KMOD_LALT;
   686             break;
   687         case SDL_SCANCODE_RALT:
   688             keyboard->modstate |= KMOD_RALT;
   689             break;
   690         case SDL_SCANCODE_LGUI:
   691             keyboard->modstate |= KMOD_LGUI;
   692             break;
   693         case SDL_SCANCODE_RGUI:
   694             keyboard->modstate |= KMOD_RGUI;
   695             break;
   696         case SDL_SCANCODE_MODE:
   697             keyboard->modstate |= KMOD_MODE;
   698             break;
   699         default:
   700             break;
   701         }
   702     } else {
   703         switch (scancode) {
   704         case SDL_SCANCODE_NUMLOCKCLEAR:
   705         case SDL_SCANCODE_CAPSLOCK:
   706             break;
   707         case SDL_SCANCODE_LCTRL:
   708             keyboard->modstate &= ~KMOD_LCTRL;
   709             break;
   710         case SDL_SCANCODE_RCTRL:
   711             keyboard->modstate &= ~KMOD_RCTRL;
   712             break;
   713         case SDL_SCANCODE_LSHIFT:
   714             keyboard->modstate &= ~KMOD_LSHIFT;
   715             break;
   716         case SDL_SCANCODE_RSHIFT:
   717             keyboard->modstate &= ~KMOD_RSHIFT;
   718             break;
   719         case SDL_SCANCODE_LALT:
   720             keyboard->modstate &= ~KMOD_LALT;
   721             break;
   722         case SDL_SCANCODE_RALT:
   723             keyboard->modstate &= ~KMOD_RALT;
   724             break;
   725         case SDL_SCANCODE_LGUI:
   726             keyboard->modstate &= ~KMOD_LGUI;
   727             break;
   728         case SDL_SCANCODE_RGUI:
   729             keyboard->modstate &= ~KMOD_RGUI;
   730             break;
   731         case SDL_SCANCODE_MODE:
   732             keyboard->modstate &= ~KMOD_MODE;
   733             break;
   734         default:
   735             break;
   736         }
   737         modstate = keyboard->modstate;
   738     }
   739 
   740     /* Figure out what type of event this is */
   741     switch (state) {
   742     case SDL_PRESSED:
   743         type = SDL_KEYDOWN;
   744         break;
   745     case SDL_RELEASED:
   746         type = SDL_KEYUP;
   747         break;
   748     default:
   749         /* Invalid state -- bail */
   750         return 0;
   751     }
   752 
   753     /* Drop events that don't change state */
   754     repeat = (state && keyboard->keystate[scancode]);
   755     if (keyboard->keystate[scancode] == state && !repeat) {
   756 #if 0
   757         printf("Keyboard event didn't change state - dropped!\n");
   758 #endif
   759         return 0;
   760     }
   761 
   762     /* Update internal keyboard state */
   763     keyboard->keystate[scancode] = state;
   764 
   765     /* Post the event, if desired */
   766     posted = 0;
   767     if (SDL_GetEventState(type) == SDL_ENABLE) {
   768         SDL_Event event;
   769         event.key.type = type;
   770         event.key.state = state;
   771         event.key.repeat = repeat;
   772         event.key.keysym.scancode = scancode;
   773         event.key.keysym.sym = keyboard->keymap[scancode];
   774         event.key.keysym.mod = modstate;
   775         event.key.keysym.unicode = 0;
   776         event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
   777         posted = (SDL_PushEvent(&event) > 0);
   778     }
   779     return (posted);
   780 }
   781 
   782 int
   783 SDL_SendKeyboardText(const char *text)
   784 {
   785     SDL_Keyboard *keyboard = &SDL_keyboard;
   786     int posted;
   787 
   788     /* Don't post text events for unprintable characters */
   789     if ((unsigned char)*text < ' ' || *text == 127) {
   790         return 0;
   791     }
   792 
   793     /* Post the event, if desired */
   794     posted = 0;
   795     if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
   796         SDL_Event event;
   797         event.text.type = SDL_TEXTINPUT;
   798         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   799         SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   800         posted = (SDL_PushEvent(&event) > 0);
   801     }
   802     return (posted);
   803 }
   804 
   805 int
   806 SDL_SendEditingText(const char *text, int start, int length)
   807 {
   808     SDL_Keyboard *keyboard = &SDL_keyboard;
   809     int posted;
   810 
   811     /* Post the event, if desired */
   812     posted = 0;
   813     if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
   814         SDL_Event event;
   815         event.edit.type = SDL_TEXTEDITING;
   816         event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
   817         event.edit.start = start;
   818         event.edit.length = length;
   819         SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
   820         posted = (SDL_PushEvent(&event) > 0);
   821     }
   822     return (posted);
   823 }
   824 
   825 void
   826 SDL_KeyboardQuit(void)
   827 {
   828 }
   829 
   830 Uint8 *
   831 SDL_GetKeyboardState(int *numkeys)
   832 {
   833     SDL_Keyboard *keyboard = &SDL_keyboard;
   834 
   835     if (numkeys != (int *) 0) {
   836         *numkeys = SDL_NUM_SCANCODES;
   837     }
   838     return keyboard->keystate;
   839 }
   840 
   841 SDL_Keymod
   842 SDL_GetModState(void)
   843 {
   844     SDL_Keyboard *keyboard = &SDL_keyboard;
   845 
   846     return keyboard->modstate;
   847 }
   848 
   849 void
   850 SDL_SetModState(SDL_Keymod modstate)
   851 {
   852     SDL_Keyboard *keyboard = &SDL_keyboard;
   853 
   854     keyboard->modstate = modstate;
   855 }
   856 
   857 SDL_Keycode
   858 SDL_GetKeyFromScancode(SDL_Scancode scancode)
   859 {
   860     SDL_Keyboard *keyboard = &SDL_keyboard;
   861 
   862     return keyboard->keymap[scancode];
   863 }
   864 
   865 SDL_Scancode
   866 SDL_GetScancodeFromKey(SDL_Keycode key)
   867 {
   868     SDL_Keyboard *keyboard = &SDL_keyboard;
   869     SDL_Scancode scancode;
   870 
   871     for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
   872          ++scancode) {
   873         if (keyboard->keymap[scancode] == key) {
   874             return scancode;
   875         }
   876     }
   877     return SDL_SCANCODE_UNKNOWN;
   878 }
   879 
   880 const char *
   881 SDL_GetScancodeName(SDL_Scancode scancode)
   882 {
   883     const char *name = SDL_scancode_names[scancode];
   884 
   885     if (name)
   886         return name;
   887     else
   888         return "";
   889 }
   890 
   891 SDL_Scancode SDL_GetScancodeFromName(const char *name)
   892 {
   893 	int i;
   894 
   895 	if (!name || !*name) {
   896 		return SDL_SCANCODE_UNKNOWN;
   897 	}
   898 
   899 	for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
   900 		if (!SDL_scancode_names[i]) {
   901 			continue;
   902 		}
   903 		if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
   904 			return (SDL_Scancode)i;
   905 		}
   906 	}
   907 	return SDL_SCANCODE_UNKNOWN;
   908 }
   909 
   910 const char *
   911 SDL_GetKeyName(SDL_Keycode key)
   912 {
   913     static char name[8];
   914     char *end;
   915 
   916     if (key & SDLK_SCANCODE_MASK) {
   917         return
   918             SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
   919     }
   920 
   921     switch (key) {
   922     case SDLK_RETURN:
   923         return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
   924     case SDLK_ESCAPE:
   925         return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
   926     case SDLK_BACKSPACE:
   927         return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
   928     case SDLK_TAB:
   929         return SDL_GetScancodeName(SDL_SCANCODE_TAB);
   930     case SDLK_SPACE:
   931         return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
   932     case SDLK_DELETE:
   933         return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
   934     default:
   935         /* Unaccented letter keys on latin keyboards are normally
   936            labeled in upper case (and probably on others like Greek or
   937            Cyrillic too, so if you happen to know for sure, please
   938            adapt this). */
   939         if (key >= 'a' && key <= 'z') {
   940             key -= 32;
   941         }
   942 
   943         end = SDL_UCS4ToUTF8((Uint32) key, name);
   944         *end = '\0';
   945         return name;
   946     }
   947 }
   948 
   949 SDL_Keycode
   950 SDL_GetKeyFromName(const char *name)
   951 {
   952 	SDL_Keycode key;
   953 
   954 	/* If it's a single UTF-8 character, then that's the keycode itself */
   955 	key = *(const unsigned char *)name;
   956 	if (key >= 0xF0) {
   957 		if (SDL_strlen(name) == 4) {
   958 			int i = 0;
   959 			key  = (Uint16)(name[i]&0x07) << 18;
   960 			key |= (Uint16)(name[++i]&0x3F) << 12;
   961 			key |= (Uint16)(name[++i]&0x3F) << 6;
   962 			key |= (Uint16)(name[++i]&0x3F);
   963 			return key;
   964 		}
   965 		return SDLK_UNKNOWN;
   966 	} else if (key >= 0xE0) {
   967 		if (SDL_strlen(name) == 3) {
   968 			int i = 0;
   969 			key  = (Uint16)(name[i]&0x0F) << 12;
   970 			key |= (Uint16)(name[++i]&0x3F) << 6;
   971 			key |= (Uint16)(name[++i]&0x3F);
   972 			return key;
   973 		}
   974 		return SDLK_UNKNOWN;
   975 	} else if (key >= 0xC0) {
   976 		if (SDL_strlen(name) == 2) {
   977 			int i = 0;
   978 			key  = (Uint16)(name[i]&0x1F) << 6;
   979 			key |= (Uint16)(name[++i]&0x3F);
   980 			return key;
   981 		}
   982 		return SDLK_UNKNOWN;
   983 	} else {
   984 		if (SDL_strlen(name) == 1) {
   985 			if (key >= 'A' && key <= 'Z') {
   986 				key += 32;
   987 			}
   988 			return key;
   989 		}
   990 
   991 		/* Get the scancode for this name, and the associated keycode */
   992 		return SDL_default_keymap[SDL_GetScancodeFromName(name)];
   993 	}
   994 }
   995 
   996 /* vi: set ts=4 sw=4 expandtab: */