src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 18 Sep 2010 18:31:01 -0700
changeset 4890 443771460df9
parent 4882 e725a6a60c32
child 5081 25d4feb7c127
permissions -rw-r--r--
Fixed crash on systems that don't have StopTextInput
     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         /* Ensures IME compositions are committed */
   617         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   618             SDL_VideoDevice *video = SDL_GetVideoDevice();
   619             if (video && video->StopTextInput) {
   620                 video->StopTextInput(video);
   621             }
   622         }
   623     }
   624 
   625     keyboard->focus = window;
   626 
   627     if (keyboard->focus) {
   628         SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   629                             0, 0);
   630 
   631         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   632             SDL_VideoDevice *video = SDL_GetVideoDevice();
   633             if (video && video->StartTextInput) {
   634                 video->StartTextInput(video);
   635             }
   636         }
   637     }
   638 }
   639 
   640 int
   641 SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
   642 {
   643     SDL_Keyboard *keyboard = &SDL_keyboard;
   644     int posted;
   645     Uint16 modstate;
   646     Uint32 type;
   647     Uint8 repeat;
   648 
   649     if (!scancode) {
   650         return 0;
   651     }
   652 #if 0
   653     printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
   654            state == SDL_PRESSED ? "pressed" : "released");
   655 #endif
   656     if (state == SDL_PRESSED) {
   657         modstate = keyboard->modstate;
   658         switch (scancode) {
   659         case SDL_SCANCODE_NUMLOCKCLEAR:
   660             keyboard->modstate ^= KMOD_NUM;
   661             break;
   662         case SDL_SCANCODE_CAPSLOCK:
   663             keyboard->modstate ^= KMOD_CAPS;
   664             break;
   665         case SDL_SCANCODE_LCTRL:
   666             keyboard->modstate |= KMOD_LCTRL;
   667             break;
   668         case SDL_SCANCODE_RCTRL:
   669             keyboard->modstate |= KMOD_RCTRL;
   670             break;
   671         case SDL_SCANCODE_LSHIFT:
   672             keyboard->modstate |= KMOD_LSHIFT;
   673             break;
   674         case SDL_SCANCODE_RSHIFT:
   675             keyboard->modstate |= KMOD_RSHIFT;
   676             break;
   677         case SDL_SCANCODE_LALT:
   678             keyboard->modstate |= KMOD_LALT;
   679             break;
   680         case SDL_SCANCODE_RALT:
   681             keyboard->modstate |= KMOD_RALT;
   682             break;
   683         case SDL_SCANCODE_LGUI:
   684             keyboard->modstate |= KMOD_LGUI;
   685             break;
   686         case SDL_SCANCODE_RGUI:
   687             keyboard->modstate |= KMOD_RGUI;
   688             break;
   689         case SDL_SCANCODE_MODE:
   690             keyboard->modstate |= KMOD_MODE;
   691             break;
   692         default:
   693             break;
   694         }
   695     } else {
   696         switch (scancode) {
   697         case SDL_SCANCODE_NUMLOCKCLEAR:
   698         case SDL_SCANCODE_CAPSLOCK:
   699             break;
   700         case SDL_SCANCODE_LCTRL:
   701             keyboard->modstate &= ~KMOD_LCTRL;
   702             break;
   703         case SDL_SCANCODE_RCTRL:
   704             keyboard->modstate &= ~KMOD_RCTRL;
   705             break;
   706         case SDL_SCANCODE_LSHIFT:
   707             keyboard->modstate &= ~KMOD_LSHIFT;
   708             break;
   709         case SDL_SCANCODE_RSHIFT:
   710             keyboard->modstate &= ~KMOD_RSHIFT;
   711             break;
   712         case SDL_SCANCODE_LALT:
   713             keyboard->modstate &= ~KMOD_LALT;
   714             break;
   715         case SDL_SCANCODE_RALT:
   716             keyboard->modstate &= ~KMOD_RALT;
   717             break;
   718         case SDL_SCANCODE_LGUI:
   719             keyboard->modstate &= ~KMOD_LGUI;
   720             break;
   721         case SDL_SCANCODE_RGUI:
   722             keyboard->modstate &= ~KMOD_RGUI;
   723             break;
   724         case SDL_SCANCODE_MODE:
   725             keyboard->modstate &= ~KMOD_MODE;
   726             break;
   727         default:
   728             break;
   729         }
   730         modstate = keyboard->modstate;
   731     }
   732 
   733     /* Figure out what type of event this is */
   734     switch (state) {
   735     case SDL_PRESSED:
   736         type = SDL_KEYDOWN;
   737         break;
   738     case SDL_RELEASED:
   739         type = SDL_KEYUP;
   740         break;
   741     default:
   742         /* Invalid state -- bail */
   743         return 0;
   744     }
   745 
   746     /* Drop events that don't change state */
   747     repeat = (state && keyboard->keystate[scancode]);
   748     if (keyboard->keystate[scancode] == state && !repeat) {
   749 #if 0
   750         printf("Keyboard event didn't change state - dropped!\n");
   751 #endif
   752         return 0;
   753     }
   754 
   755     /* Update internal keyboard state */
   756     keyboard->keystate[scancode] = state;
   757 
   758     /* Post the event, if desired */
   759     posted = 0;
   760     if (SDL_GetEventState(type) == SDL_ENABLE) {
   761         SDL_Event event;
   762         event.key.type = type;
   763         event.key.state = state;
   764         event.key.repeat = repeat;
   765         event.key.keysym.scancode = scancode;
   766         event.key.keysym.sym = keyboard->keymap[scancode];
   767         event.key.keysym.mod = modstate;
   768         event.key.keysym.unicode = 0;
   769         event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
   770         posted = (SDL_PushEvent(&event) > 0);
   771     }
   772     return (posted);
   773 }
   774 
   775 int
   776 SDL_SendKeyboardText(const char *text)
   777 {
   778     SDL_Keyboard *keyboard = &SDL_keyboard;
   779     int posted;
   780 
   781     /* Don't post text events for unprintable characters */
   782     if ((unsigned char)*text < ' ' || *text == 127) {
   783         return 0;
   784     }
   785 
   786     /* Post the event, if desired */
   787     posted = 0;
   788     if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
   789         SDL_Event event;
   790         event.text.type = SDL_TEXTINPUT;
   791         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   792         SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   793         event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
   794         posted = (SDL_PushEvent(&event) > 0);
   795     }
   796     return (posted);
   797 }
   798 
   799 int
   800 SDL_SendEditingText(const char *text, int start, int length)
   801 {
   802     SDL_Keyboard *keyboard = &SDL_keyboard;
   803     int posted;
   804 
   805     /* Post the event, if desired */
   806     posted = 0;
   807     if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
   808         SDL_Event event;
   809         event.edit.type = SDL_TEXTEDITING;
   810         event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
   811         event.edit.start = start;
   812         event.edit.length = length;
   813         SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
   814         posted = (SDL_PushEvent(&event) > 0);
   815     }
   816     return (posted);
   817 }
   818 
   819 void
   820 SDL_KeyboardQuit(void)
   821 {
   822 }
   823 
   824 Uint8 *
   825 SDL_GetKeyboardState(int *numkeys)
   826 {
   827     SDL_Keyboard *keyboard = &SDL_keyboard;
   828 
   829     if (numkeys != (int *) 0) {
   830         *numkeys = SDL_NUM_SCANCODES;
   831     }
   832     return keyboard->keystate;
   833 }
   834 
   835 SDLMod
   836 SDL_GetModState(void)
   837 {
   838     SDL_Keyboard *keyboard = &SDL_keyboard;
   839 
   840     return keyboard->modstate;
   841 }
   842 
   843 void
   844 SDL_SetModState(SDLMod modstate)
   845 {
   846     SDL_Keyboard *keyboard = &SDL_keyboard;
   847 
   848     keyboard->modstate = modstate;
   849 }
   850 
   851 SDLKey
   852 SDL_GetKeyFromScancode(SDL_scancode scancode)
   853 {
   854     SDL_Keyboard *keyboard = &SDL_keyboard;
   855 
   856     return keyboard->keymap[scancode];
   857 }
   858 
   859 SDL_scancode
   860 SDL_GetScancodeFromKey(SDLKey key)
   861 {
   862     SDL_Keyboard *keyboard = &SDL_keyboard;
   863     SDL_scancode scancode;
   864 
   865     for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
   866          ++scancode) {
   867         if (keyboard->keymap[scancode] == key) {
   868             return scancode;
   869         }
   870     }
   871     return SDL_SCANCODE_UNKNOWN;
   872 }
   873 
   874 const char *
   875 SDL_GetScancodeName(SDL_scancode scancode)
   876 {
   877     const char *name = SDL_scancode_names[scancode];
   878 
   879     if (name)
   880         return name;
   881     else
   882         return "";
   883 }
   884 
   885 const char *
   886 SDL_GetKeyName(SDLKey key)
   887 {
   888     static char name[8];
   889     char *end;
   890 
   891     if (key & SDLK_SCANCODE_MASK) {
   892         return
   893             SDL_GetScancodeName((SDL_scancode) (key & ~SDLK_SCANCODE_MASK));
   894     }
   895 
   896     switch (key) {
   897     case SDLK_RETURN:
   898         return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
   899     case SDLK_ESCAPE:
   900         return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
   901     case SDLK_BACKSPACE:
   902         return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
   903     case SDLK_TAB:
   904         return SDL_GetScancodeName(SDL_SCANCODE_TAB);
   905     case SDLK_SPACE:
   906         return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
   907     case SDLK_DELETE:
   908         return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
   909     default:
   910         /* Unaccented letter keys on latin keyboards are normally
   911            labeled in upper case (and probably on others like Greek or
   912            Cyrillic too, so if you happen to know for sure, please
   913            adapt this). */
   914         if (key >= 'a' && key <= 'z') {
   915             key -= 32;
   916         }
   917 
   918         end = SDL_UCS4ToUTF8((Uint32) key, name);
   919         *end = '\0';
   920         return name;
   921     }
   922 }
   923 
   924 /* vi: set ts=4 sw=4 expandtab: */