src/events/SDL_keyboard.c
author Andreas Schiffler <aschiffler@ferzkopp.net>
Mon, 23 Aug 2010 23:44:28 -0700
changeset 4865 fff50e86c891
parent 4763 518d1679d2d0
child 4882 e725a6a60c32
permissions -rw-r--r--
Update VS2010 project to add new files; update new files so code builds on Win32/Win64
     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     SDL_Keyboard *keyboard = &SDL_keyboard;
   555 
   556     /* Set the default keymap */
   557     SDL_memcpy(keyboard->keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
   558     return (0);
   559 }
   560 
   561 void
   562 SDL_ResetKeyboard(void)
   563 {
   564     SDL_Keyboard *keyboard = &SDL_keyboard;
   565     SDL_scancode scancode;
   566 
   567     for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
   568         if (keyboard->keystate[scancode] == SDL_PRESSED) {
   569             SDL_SendKeyboardKey(SDL_RELEASED, scancode);
   570         }
   571     }
   572 }
   573 
   574 void
   575 SDL_GetDefaultKeymap(SDLKey * keymap)
   576 {
   577     SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
   578 }
   579 
   580 void
   581 SDL_SetKeymap(int start, SDLKey * keys, int length)
   582 {
   583     SDL_Keyboard *keyboard = &SDL_keyboard;
   584 
   585     if (start < 0 || start + length > SDL_NUM_SCANCODES) {
   586         return;
   587     }
   588 
   589     SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
   590 }
   591 
   592 void
   593 SDL_SetScancodeName(SDL_scancode scancode, const char *name)
   594 {
   595     SDL_scancode_names[scancode] = name;
   596 }
   597 
   598 SDL_Window *
   599 SDL_GetKeyboardFocus(void)
   600 {
   601     SDL_Keyboard *keyboard = &SDL_keyboard;
   602 
   603     return keyboard->focus;
   604 }
   605 
   606 void
   607 SDL_SetKeyboardFocus(SDL_Window * window)
   608 {
   609     SDL_Keyboard *keyboard = &SDL_keyboard;
   610 
   611     /* See if the current window has lost focus */
   612     if (keyboard->focus && keyboard->focus != window) {
   613         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
   614                             0, 0);
   615     }
   616 
   617     keyboard->focus = window;
   618 
   619     if (keyboard->focus) {
   620         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   621                             0, 0);
   622 
   623         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   624             SDL_StartTextInput();
   625         }
   626     }
   627 }
   628 
   629 int
   630 SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
   631 {
   632     SDL_Keyboard *keyboard = &SDL_keyboard;
   633     int posted;
   634     Uint16 modstate;
   635     Uint32 type;
   636     Uint8 repeat;
   637 
   638     if (!scancode) {
   639         return 0;
   640     }
   641 #if 0
   642     printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
   643            state == SDL_PRESSED ? "pressed" : "released");
   644 #endif
   645     if (state == SDL_PRESSED) {
   646         modstate = keyboard->modstate;
   647         switch (scancode) {
   648         case SDL_SCANCODE_NUMLOCKCLEAR:
   649             keyboard->modstate ^= KMOD_NUM;
   650             break;
   651         case SDL_SCANCODE_CAPSLOCK:
   652             keyboard->modstate ^= KMOD_CAPS;
   653             break;
   654         case SDL_SCANCODE_LCTRL:
   655             keyboard->modstate |= KMOD_LCTRL;
   656             break;
   657         case SDL_SCANCODE_RCTRL:
   658             keyboard->modstate |= KMOD_RCTRL;
   659             break;
   660         case SDL_SCANCODE_LSHIFT:
   661             keyboard->modstate |= KMOD_LSHIFT;
   662             break;
   663         case SDL_SCANCODE_RSHIFT:
   664             keyboard->modstate |= KMOD_RSHIFT;
   665             break;
   666         case SDL_SCANCODE_LALT:
   667             keyboard->modstate |= KMOD_LALT;
   668             break;
   669         case SDL_SCANCODE_RALT:
   670             keyboard->modstate |= KMOD_RALT;
   671             break;
   672         case SDL_SCANCODE_LGUI:
   673             keyboard->modstate |= KMOD_LGUI;
   674             break;
   675         case SDL_SCANCODE_RGUI:
   676             keyboard->modstate |= KMOD_RGUI;
   677             break;
   678         case SDL_SCANCODE_MODE:
   679             keyboard->modstate |= KMOD_MODE;
   680             break;
   681         default:
   682             break;
   683         }
   684     } else {
   685         switch (scancode) {
   686         case SDL_SCANCODE_NUMLOCKCLEAR:
   687         case SDL_SCANCODE_CAPSLOCK:
   688             break;
   689         case SDL_SCANCODE_LCTRL:
   690             keyboard->modstate &= ~KMOD_LCTRL;
   691             break;
   692         case SDL_SCANCODE_RCTRL:
   693             keyboard->modstate &= ~KMOD_RCTRL;
   694             break;
   695         case SDL_SCANCODE_LSHIFT:
   696             keyboard->modstate &= ~KMOD_LSHIFT;
   697             break;
   698         case SDL_SCANCODE_RSHIFT:
   699             keyboard->modstate &= ~KMOD_RSHIFT;
   700             break;
   701         case SDL_SCANCODE_LALT:
   702             keyboard->modstate &= ~KMOD_LALT;
   703             break;
   704         case SDL_SCANCODE_RALT:
   705             keyboard->modstate &= ~KMOD_RALT;
   706             break;
   707         case SDL_SCANCODE_LGUI:
   708             keyboard->modstate &= ~KMOD_LGUI;
   709             break;
   710         case SDL_SCANCODE_RGUI:
   711             keyboard->modstate &= ~KMOD_RGUI;
   712             break;
   713         case SDL_SCANCODE_MODE:
   714             keyboard->modstate &= ~KMOD_MODE;
   715             break;
   716         default:
   717             break;
   718         }
   719         modstate = keyboard->modstate;
   720     }
   721 
   722     /* Figure out what type of event this is */
   723     switch (state) {
   724     case SDL_PRESSED:
   725         type = SDL_KEYDOWN;
   726         break;
   727     case SDL_RELEASED:
   728         type = SDL_KEYUP;
   729         break;
   730     default:
   731         /* Invalid state -- bail */
   732         return 0;
   733     }
   734 
   735     /* Drop events that don't change state */
   736     repeat = (state && keyboard->keystate[scancode]);
   737     if (keyboard->keystate[scancode] == state && !repeat) {
   738 #if 0
   739         printf("Keyboard event didn't change state - dropped!\n");
   740 #endif
   741         return 0;
   742     }
   743 
   744     /* Update internal keyboard state */
   745     keyboard->keystate[scancode] = state;
   746 
   747     /* Post the event, if desired */
   748     posted = 0;
   749     if (SDL_GetEventState(type) == SDL_ENABLE) {
   750         SDL_Event event;
   751         event.key.type = type;
   752         event.key.state = state;
   753         event.key.repeat = repeat;
   754         event.key.keysym.scancode = scancode;
   755         event.key.keysym.sym = keyboard->keymap[scancode];
   756         event.key.keysym.mod = modstate;
   757         event.key.keysym.unicode = 0;
   758         event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
   759         posted = (SDL_PushEvent(&event) > 0);
   760     }
   761     return (posted);
   762 }
   763 
   764 int
   765 SDL_SendKeyboardText(const char *text)
   766 {
   767     SDL_Keyboard *keyboard = &SDL_keyboard;
   768     int posted;
   769 
   770     /* Don't post text events for unprintable characters */
   771     if ((unsigned char)*text < ' ' || *text == 127) {
   772         return 0;
   773     }
   774 
   775     /* Post the event, if desired */
   776     posted = 0;
   777     if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
   778         SDL_Event event;
   779         event.text.type = SDL_TEXTINPUT;
   780         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   781         SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   782         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   783         posted = (SDL_PushEvent(&event) > 0);
   784     }
   785     return (posted);
   786 }
   787 
   788 int
   789 SDL_SendEditingText(const char *text, int start, int length)
   790 {
   791     SDL_Keyboard *keyboard = &SDL_keyboard;
   792     int posted;
   793 
   794     /* Post the event, if desired */
   795     posted = 0;
   796     if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
   797         SDL_Event event;
   798         event.edit.type = SDL_TEXTEDITING;
   799         event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
   800         event.edit.start = start;
   801         event.edit.length = length;
   802         SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
   803         posted = (SDL_PushEvent(&event) > 0);
   804     }
   805     return (posted);
   806 }
   807 
   808 void
   809 SDL_KeyboardQuit(void)
   810 {
   811 }
   812 
   813 Uint8 *
   814 SDL_GetKeyboardState(int *numkeys)
   815 {
   816     SDL_Keyboard *keyboard = &SDL_keyboard;
   817 
   818     if (numkeys != (int *) 0) {
   819         *numkeys = SDL_NUM_SCANCODES;
   820     }
   821     return keyboard->keystate;
   822 }
   823 
   824 SDLMod
   825 SDL_GetModState(void)
   826 {
   827     SDL_Keyboard *keyboard = &SDL_keyboard;
   828 
   829     return keyboard->modstate;
   830 }
   831 
   832 void
   833 SDL_SetModState(SDLMod modstate)
   834 {
   835     SDL_Keyboard *keyboard = &SDL_keyboard;
   836 
   837     keyboard->modstate = modstate;
   838 }
   839 
   840 SDLKey
   841 SDL_GetKeyFromScancode(SDL_scancode scancode)
   842 {
   843     SDL_Keyboard *keyboard = &SDL_keyboard;
   844 
   845     return keyboard->keymap[scancode];
   846 }
   847 
   848 SDL_scancode
   849 SDL_GetScancodeFromKey(SDLKey key)
   850 {
   851     SDL_Keyboard *keyboard = &SDL_keyboard;
   852     SDL_scancode scancode;
   853 
   854     for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
   855          ++scancode) {
   856         if (keyboard->keymap[scancode] == key) {
   857             return scancode;
   858         }
   859     }
   860     return SDL_SCANCODE_UNKNOWN;
   861 }
   862 
   863 const char *
   864 SDL_GetScancodeName(SDL_scancode scancode)
   865 {
   866     const char *name = SDL_scancode_names[scancode];
   867 
   868     if (name)
   869         return name;
   870     else
   871         return "";
   872 }
   873 
   874 const char *
   875 SDL_GetKeyName(SDLKey key)
   876 {
   877     static char name[8];
   878     char *end;
   879 
   880     if (key & SDLK_SCANCODE_MASK) {
   881         return
   882             SDL_GetScancodeName((SDL_scancode) (key & ~SDLK_SCANCODE_MASK));
   883     }
   884 
   885     switch (key) {
   886     case SDLK_RETURN:
   887         return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
   888     case SDLK_ESCAPE:
   889         return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
   890     case SDLK_BACKSPACE:
   891         return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
   892     case SDLK_TAB:
   893         return SDL_GetScancodeName(SDL_SCANCODE_TAB);
   894     case SDLK_SPACE:
   895         return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
   896     case SDLK_DELETE:
   897         return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
   898     default:
   899         /* Unaccented letter keys on latin keyboards are normally
   900            labeled in upper case (and probably on others like Greek or
   901            Cyrillic too, so if you happen to know for sure, please
   902            adapt this). */
   903         if (key >= 'a' && key <= 'z') {
   904             key -= 32;
   905         }
   906 
   907         end = SDL_UCS4ToUTF8((Uint32) key, name);
   908         *end = '\0';
   909         return name;
   910     }
   911 }
   912 
   913 /* vi: set ts=4 sw=4 expandtab: */