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