cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_keyboard.c (22840B)


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