src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 05 Feb 2008 07:19:23 +0000
changeset 2303 d87417504c75
parent 2300 c97ad1abe05b
child 2305 fbe8ff44c519
permissions -rw-r--r--
First pass implementation of new SDL scancode concept, as discussed with
Christian Walther. Currently only implemented on Mac OS X for sanity
checking purposes.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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 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_MAIL,
   246     SDLK_CALCULATOR,
   247     SDLK_COMPUTER,
   248     SDLK_AC_SEARCH,
   249     SDLK_AC_HOME,
   250     SDLK_AC_BACK,
   251     SDLK_AC_FORWARD,
   252     SDLK_AC_STOP,
   253     SDLK_AC_REFRESH,
   254     SDLK_AC_BOOKMARKS,
   255     SDLK_BRIGHTNESSDOWN,
   256     SDLK_BRIGHTNESSUP,
   257     SDLK_DISPLAYSWITCH,
   258     SDLK_KBDILLUMTOGGLE,
   259     SDLK_KBDILLUMDOWN,
   260     SDLK_KBDILLUMUP,
   261     SDLK_EJECT,
   262     SDLK_SLEEP,
   263 };
   264 
   265 static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
   266     NULL, NULL, NULL, NULL,
   267     "A",
   268     "B",
   269     "C",
   270     "D",
   271     "E",
   272     "F",
   273     "G",
   274     "H",
   275     "I",
   276     "J",
   277     "K",
   278     "L",
   279     "M",
   280     "N",
   281     "O",
   282     "P",
   283     "Q",
   284     "R",
   285     "S",
   286     "T",
   287     "U",
   288     "V",
   289     "W",
   290     "X",
   291     "Y",
   292     "Z",
   293     "1",
   294     "2",
   295     "3",
   296     "4",
   297     "5",
   298     "6",
   299     "7",
   300     "8",
   301     "9",
   302     "0",
   303     "Return",
   304     "Escape",
   305     "Backspace",
   306     "Tab",
   307     "Space",
   308     "-",
   309     "=",
   310     "[",
   311     "]",
   312     "\\",
   313     "#",
   314     ";",
   315     "'",
   316     "`",
   317     ",",
   318     ".",
   319     "/",
   320     "CapsLock",
   321     "F1",
   322     "F2",
   323     "F3",
   324     "F4",
   325     "F5",
   326     "F6",
   327     "F7",
   328     "F8",
   329     "F9",
   330     "F10",
   331     "F11",
   332     "F12",
   333     "PrintScreen",
   334     "ScrollLock",
   335     "Pause",
   336     "Insert",
   337     "Home",
   338     "PageUp",
   339     "Delete",
   340     "End",
   341     "PageDown",
   342     "Right",
   343     "Left",
   344     "Down",
   345     "Up",
   346     "Numlock",
   347     "Keypad /",
   348     "Keypad *",
   349     "Keypad -",
   350     "Keypad +",
   351     "Keypad Enter",
   352     "Keypad 1",
   353     "Keypad 2",
   354     "Keypad 3",
   355     "Keypad 4",
   356     "Keypad 5",
   357     "Keypad 6",
   358     "Keypad 7",
   359     "Keypad 8",
   360     "Keypad 9",
   361     "Keypad 0",
   362     "Keypad .",
   363     NULL,
   364     "Application",
   365     "Power",
   366     "Keypad =",
   367     "F13",
   368     "F14",
   369     "F15",
   370     "F16",
   371     "F17",
   372     "F18",
   373     "F19",
   374     "F20",
   375     "F21",
   376     "F22",
   377     "F23",
   378     "F24",
   379     "Execute",
   380     "Help",
   381     "Menu",
   382     "Select",
   383     "Stop",
   384     "Again",
   385     "Undo",
   386     "Cut",
   387     "Copy",
   388     "Paste",
   389     "Find",
   390     "Mute",
   391     "VolumeUp",
   392     "VolumeDown",
   393     NULL, NULL, NULL,
   394     "Keypad ,",
   395     "Keypad = (AS400)",
   396     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   397     NULL, NULL, NULL, NULL, NULL, NULL,
   398     "AltErase",
   399     "SysReq",
   400     "Cancel",
   401     "Clear",
   402     "Prior",
   403     "Return",
   404     "Separator",
   405     "Out",
   406     "Oper",
   407     "Clear / Again",
   408     "CrSel",
   409     "ExSel",
   410     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   411     "Keypad 00",
   412     "Keypad 000",
   413     "ThousandsSeparator",
   414     "DecimalSeparator",
   415     "CurrencyUnit",
   416     "CurrencySubUnit",
   417     "Keypad (",
   418     "Keypad )",
   419     "Keypad {",
   420     "Keypad }",
   421     "Keypad Tab",
   422     "Keypad Backspace",
   423     "Keypad A",
   424     "Keypad B",
   425     "Keypad C",
   426     "Keypad D",
   427     "Keypad E",
   428     "Keypad F",
   429     "Keypad XOR",
   430     "Keypad ^",
   431     "Keypad %",
   432     "Keypad <",
   433     "Keypad >",
   434     "Keypad &",
   435     "Keypad &&",
   436     "Keypad |",
   437     "Keypad ||",
   438     "Keypad :",
   439     "Keypad #",
   440     "Keypad Space",
   441     "Keypad @",
   442     "Keypad !",
   443     "Keypad MemStore",
   444     "Keypad MemRecall",
   445     "Keypad MemClear",
   446     "Keypad MemAdd",
   447     "Keypad MemSubtract",
   448     "Keypad MemMultiply",
   449     "Keypad MemDivide",
   450     "Keypad +/-",
   451     "Keypad Clear",
   452     "Keypad ClearEntry",
   453     "Keypad Binary",
   454     "Keypad Octal",
   455     "Keypad Decimal",
   456     "Keypad Hexadecimal",
   457     NULL, NULL,
   458     "Left Ctrl",
   459     "Left Shift",
   460     "Left Alt",
   461     "Left GUI",
   462     "Right Ctrl",
   463     "Right Shift",
   464     "Right Alt",
   465     "Right GUI",
   466     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   467     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
   468     NULL,
   469     "ModeSwitch",
   470     "AudioNext",
   471     "AudioPrev",
   472     "AudioStop",
   473     "AudioPlay",
   474     "AudioMute",
   475     "MediaSelect",
   476     "Mail",
   477     "Calculator",
   478     "Computer",
   479     "AC Search",
   480     "AC Home",
   481     "AC Back",
   482     "AC Forward",
   483     "AC Stop",
   484     "AC Refresh",
   485     "AC Bookmarks",
   486     "BrightnessDown",
   487     "BrightnessUp",
   488     "DisplaySwitch",
   489     "KBDIllumToggle",
   490     "KBDIllumDown",
   491     "KBDIllumUp",
   492     "Eject",
   493     "Sleep",
   494 };
   495 
   496 /* Taken from SDL_iconv() */
   497 static char *
   498 SDL_UCS4ToUTF8(Uint32 ch, char *dst)
   499 {
   500     Uint8 *p = (Uint8 *) dst;
   501     if (ch <= 0x7F) {
   502         *p = (Uint8) ch;
   503         ++dst;
   504     } else if (ch <= 0x7FF) {
   505         p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
   506         p[1] = 0x80 | (Uint8) (ch & 0x3F);
   507         dst += 2;
   508     } else if (ch <= 0xFFFF) {
   509         p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
   510         p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   511         p[2] = 0x80 | (Uint8) (ch & 0x3F);
   512         dst += 3;
   513     } else if (ch <= 0x1FFFFF) {
   514         p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
   515         p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   516         p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   517         p[3] = 0x80 | (Uint8) (ch & 0x3F);
   518         dst += 4;
   519     } else if (ch <= 0x3FFFFFF) {
   520         p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
   521         p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   522         p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   523         p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   524         p[4] = 0x80 | (Uint8) (ch & 0x3F);
   525         dst += 5;
   526     } else {
   527         p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
   528         p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
   529         p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
   530         p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
   531         p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
   532         p[5] = 0x80 | (Uint8) (ch & 0x3F);
   533         dst += 6;
   534     }
   535     return dst;
   536 }
   537 
   538 /* Public functions */
   539 int
   540 SDL_KeyboardInit(void)
   541 {
   542     return (0);
   543 }
   544 
   545 SDL_Keyboard *
   546 SDL_GetKeyboard(int index)
   547 {
   548     if (index < 0 || index >= SDL_num_keyboards) {
   549         return NULL;
   550     }
   551     return SDL_keyboards[index];
   552 }
   553 
   554 int
   555 SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
   556 {
   557     SDL_Keyboard **keyboards;
   558 
   559     /* Add the keyboard to the list of keyboards */
   560     if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
   561         keyboards =
   562             (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
   563                                           (SDL_num_keyboards +
   564                                            1) * sizeof(*keyboards));
   565         if (!keyboards) {
   566             SDL_OutOfMemory();
   567             return -1;
   568         }
   569 
   570         SDL_keyboards = keyboards;
   571         index = SDL_num_keyboards++;
   572     }
   573     SDL_keyboards[index] =
   574         (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
   575     if (!SDL_keyboards[index]) {
   576         SDL_OutOfMemory();
   577         return -1;
   578     }
   579     *SDL_keyboards[index] = *keyboard;
   580 
   581     return index;
   582 }
   583 
   584 void
   585 SDL_DelKeyboard(int index)
   586 {
   587     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   588 
   589     if (!keyboard) {
   590         return;
   591     }
   592 
   593     if (keyboard->FreeKeyboard) {
   594         keyboard->FreeKeyboard(keyboard);
   595     }
   596     SDL_free(keyboard);
   597 
   598     SDL_keyboards[index] = NULL;
   599 }
   600 
   601 void
   602 SDL_ResetKeyboard(int index)
   603 {
   604     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   605     SDL_scancode scancode;
   606 
   607     if (!keyboard) {
   608         return;
   609     }
   610 
   611     for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
   612         if (keyboard->keystate[scancode] == SDL_PRESSED) {
   613             SDL_SendKeyboardKey(index, SDL_RELEASED, scancode);
   614         }
   615     }
   616 }
   617 
   618 void
   619 SDL_GetDefaultKeymap(SDLKey * keymap)
   620 {
   621     SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
   622 }
   623 
   624 void
   625 SDL_SetKeymap(int index, int start, SDLKey * keys, int length)
   626 {
   627     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   628 
   629     if (!keyboard) {
   630         return;
   631     }
   632 
   633     if (start < 0 || start + length > SDL_NUM_SCANCODES) {
   634         return;
   635     }
   636 
   637     SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
   638 }
   639 
   640 void
   641 SDL_SetScancodeName(SDL_scancode scancode, const char *name)
   642 {
   643     SDL_scancode_names[scancode] = name;
   644 }
   645 
   646 void
   647 SDL_SetKeyboardFocus(int index, SDL_WindowID windowID)
   648 {
   649     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   650     int i;
   651     SDL_bool focus;
   652 
   653     if (!keyboard || (keyboard->focus == windowID)) {
   654         return;
   655     }
   656 
   657     /* See if the current window has lost focus */
   658     if (keyboard->focus) {
   659         focus = SDL_FALSE;
   660         for (i = 0; i < SDL_num_keyboards; ++i) {
   661             SDL_Keyboard *check;
   662             if (i != index) {
   663                 check = SDL_GetKeyboard(i);
   664                 if (check && check->focus == keyboard->focus) {
   665                     focus = SDL_TRUE;
   666                     break;
   667                 }
   668             }
   669         }
   670         if (!focus) {
   671             SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
   672                                 0, 0);
   673         }
   674     }
   675 
   676     keyboard->focus = windowID;
   677 
   678     if (keyboard->focus) {
   679         focus = SDL_FALSE;
   680         for (i = 0; i < SDL_num_keyboards; ++i) {
   681             SDL_Keyboard *check;
   682             if (i != index) {
   683                 check = SDL_GetKeyboard(i);
   684                 if (check && check->focus == keyboard->focus) {
   685                     focus = SDL_TRUE;
   686                     break;
   687                 }
   688             }
   689         }
   690         if (!focus) {
   691             SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   692                                 0, 0);
   693         }
   694     }
   695 }
   696 
   697 int
   698 SDL_SendKeyboardKey(int index, Uint8 state, SDL_scancode scancode)
   699 {
   700     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   701     int posted;
   702     Uint16 modstate;
   703     Uint8 type;
   704 
   705     if (!keyboard || !scancode) {
   706         return 0;
   707     }
   708 #if 0
   709     printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
   710            state == SDL_PRESSED ? "pressed" : "released");
   711 #endif
   712     if (state == SDL_PRESSED) {
   713         modstate = keyboard->modstate;
   714         switch (scancode) {
   715         case SDL_SCANCODE_NUMLOCKCLEAR:
   716             keyboard->modstate ^= KMOD_NUM;
   717             break;
   718         case SDL_SCANCODE_CAPSLOCK:
   719             keyboard->modstate ^= KMOD_CAPS;
   720             break;
   721         case SDL_SCANCODE_LCTRL:
   722             keyboard->modstate |= KMOD_LCTRL;
   723             break;
   724         case SDL_SCANCODE_RCTRL:
   725             keyboard->modstate |= KMOD_RCTRL;
   726             break;
   727         case SDL_SCANCODE_LSHIFT:
   728             keyboard->modstate |= KMOD_LSHIFT;
   729             break;
   730         case SDL_SCANCODE_RSHIFT:
   731             keyboard->modstate |= KMOD_RSHIFT;
   732             break;
   733         case SDL_SCANCODE_LALT:
   734             keyboard->modstate |= KMOD_LALT;
   735             break;
   736         case SDL_SCANCODE_RALT:
   737             keyboard->modstate |= KMOD_RALT;
   738             break;
   739         case SDL_SCANCODE_LGUI:
   740             keyboard->modstate |= KMOD_LGUI;
   741             break;
   742         case SDL_SCANCODE_RGUI:
   743             keyboard->modstate |= KMOD_RGUI;
   744             break;
   745         case SDL_SCANCODE_MODE:
   746             keyboard->modstate |= KMOD_MODE;
   747             break;
   748         default:
   749             break;
   750         }
   751     } else {
   752         switch (scancode) {
   753         case SDL_SCANCODE_NUMLOCKCLEAR:
   754         case SDL_SCANCODE_CAPSLOCK:
   755             break;
   756         case SDL_SCANCODE_LCTRL:
   757             keyboard->modstate &= ~KMOD_LCTRL;
   758             break;
   759         case SDL_SCANCODE_RCTRL:
   760             keyboard->modstate &= ~KMOD_RCTRL;
   761             break;
   762         case SDL_SCANCODE_LSHIFT:
   763             keyboard->modstate &= ~KMOD_LSHIFT;
   764             break;
   765         case SDL_SCANCODE_RSHIFT:
   766             keyboard->modstate &= ~KMOD_RSHIFT;
   767             break;
   768         case SDL_SCANCODE_LALT:
   769             keyboard->modstate &= ~KMOD_LALT;
   770             break;
   771         case SDL_SCANCODE_RALT:
   772             keyboard->modstate &= ~KMOD_RALT;
   773             break;
   774         case SDL_SCANCODE_LGUI:
   775             keyboard->modstate &= ~KMOD_LGUI;
   776             break;
   777         case SDL_SCANCODE_RGUI:
   778             keyboard->modstate &= ~KMOD_RGUI;
   779             break;
   780         case SDL_SCANCODE_MODE:
   781             keyboard->modstate &= ~KMOD_MODE;
   782             break;
   783         default:
   784             break;
   785         }
   786         modstate = keyboard->modstate;
   787     }
   788 
   789     /* Figure out what type of event this is */
   790     switch (state) {
   791     case SDL_PRESSED:
   792         type = SDL_KEYDOWN;
   793         break;
   794     case SDL_RELEASED:
   795         type = SDL_KEYUP;
   796         break;
   797     default:
   798         /* Invalid state -- bail */
   799         return 0;
   800     }
   801 
   802     /* Drop events that don't change state */
   803     if (keyboard->keystate[scancode] == state) {
   804 #if 0
   805         printf("Keyboard event didn't change state - dropped!\n");
   806 #endif
   807         return 0;
   808     }
   809 
   810     /* Update internal keyboard state */
   811     keyboard->keystate[scancode] = state;
   812 
   813     /* Post the event, if desired */
   814     posted = 0;
   815     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   816         SDL_Event event;
   817         event.key.type = type;
   818         event.key.which = (Uint8) index;
   819         event.key.state = state;
   820         event.key.keysym.scancode = scancode;
   821         event.key.keysym.sym = keyboard->keymap[scancode];
   822         event.key.keysym.mod = modstate;
   823         event.key.keysym.unicode = 0;
   824         event.key.windowID = keyboard->focus;
   825         posted = (SDL_PushEvent(&event) > 0);
   826     }
   827     return (posted);
   828 }
   829 
   830 int
   831 SDL_SendKeyboardText(int index, const char *text)
   832 {
   833     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   834     int posted;
   835 
   836     if (!keyboard) {
   837         return 0;
   838     }
   839 
   840     /* Post the event, if desired */
   841     posted = 0;
   842     if (SDL_ProcessEvents[SDL_TEXTINPUT] == SDL_ENABLE) {
   843         SDL_Event event;
   844         event.text.type = SDL_TEXTINPUT;
   845         event.text.which = (Uint8) index;
   846         SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   847         event.text.windowID = keyboard->focus;
   848         posted = (SDL_PushEvent(&event) > 0);
   849     }
   850     return (posted);
   851 }
   852 
   853 void
   854 SDL_KeyboardQuit(void)
   855 {
   856     int i;
   857 
   858     for (i = 0; i < SDL_num_keyboards; ++i) {
   859         SDL_DelKeyboard(i);
   860     }
   861     SDL_num_keyboards = 0;
   862     SDL_current_keyboard = 0;
   863 
   864     if (SDL_keyboards) {
   865         SDL_free(SDL_keyboards);
   866         SDL_keyboards = NULL;
   867     }
   868 }
   869 
   870 int
   871 SDL_GetNumKeyboards(void)
   872 {
   873     return SDL_num_keyboards;
   874 }
   875 
   876 int
   877 SDL_SelectKeyboard(int index)
   878 {
   879     if (index >= 0 && index < SDL_num_keyboards) {
   880         SDL_current_keyboard = index;
   881     }
   882     return SDL_current_keyboard;
   883 }
   884 
   885 Uint8 *
   886 SDL_GetKeyboardState(int *numkeys)
   887 {
   888     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   889 
   890     if (numkeys != (int *) 0) {
   891         *numkeys = SDL_NUM_SCANCODES;
   892     }
   893 
   894     if (!keyboard) {
   895         return NULL;
   896     }
   897     return keyboard->keystate;
   898 }
   899 
   900 SDLMod
   901 SDL_GetModState(void)
   902 {
   903     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   904 
   905     if (!keyboard) {
   906         return KMOD_NONE;
   907     }
   908     return keyboard->modstate;
   909 }
   910 
   911 void
   912 SDL_SetModState(SDLMod modstate)
   913 {
   914     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   915 
   916     if (!keyboard) {
   917         return;
   918     }
   919     keyboard->modstate = modstate;
   920 }
   921 
   922 SDLKey
   923 SDL_GetKeyFromScancode(SDL_scancode scancode)
   924 {
   925     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   926 
   927     if (!keyboard) {
   928         return SDLK_UNKNOWN;
   929     }
   930     return keyboard->keymap[scancode];
   931 }
   932 
   933 SDL_scancode
   934 SDL_GetScancodeFromKey(SDLKey key)
   935 {
   936     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   937     SDL_scancode scancode;
   938 
   939     if (!keyboard) {
   940         return SDL_SCANCODE_UNKNOWN;
   941     }
   942 
   943     for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
   944          ++scancode) {
   945         if (keyboard->keymap[scancode] == key) {
   946             return scancode;
   947         }
   948     }
   949     return SDL_SCANCODE_UNKNOWN;
   950 }
   951 
   952 const char *
   953 SDL_GetScancodeName(SDL_scancode scancode)
   954 {
   955     const char *name = SDL_scancode_names[scancode];
   956 
   957     if (name)
   958         return name;
   959     else
   960         return "";
   961 }
   962 
   963 const char *
   964 SDL_GetKeyName(SDLKey key)
   965 {
   966     static char name[8];
   967     char *end;
   968 
   969     if (key & SDLK_SCANCODE_MASK) {
   970         return
   971             SDL_GetScancodeName((SDL_scancode) (key & ~SDLK_SCANCODE_MASK));
   972     }
   973 
   974     /* Unaccented letter keys on latin keyboards are normally
   975        labeled in upper case (and probably on others like Greek or
   976        Cyrillic too, so if you happen to know for sure, please
   977        adapt this). */
   978     if (key >= 'a' && key <= 'z') {
   979         key -= 32;
   980     }
   981 
   982     end = SDL_UCS4ToUTF8((Uint32) key, name);
   983     *end = '\0';
   984     return name;
   985 }
   986 
   987 /* vi: set ts=4 sw=4 expandtab: */