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