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