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