src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 12 Aug 2017 12:34:09 -0700
changeset 11240 1f6105d09344
parent 11149 504c67e71589
child 11247 27eb9a10002c
permissions -rw-r--r--
Fixed bug 3249 - keysym.mod is incorrect when mod keys are pressed for SDL_KEYDOWN events

Adam M.

The keysym.mod field does not reflect the state of the modified keys when processing key down events for the modifier keys themselves. The documentation says that it returns the current key modifiers, but they are not current for key down events involving modifier keys. I interpret "current" to mean "equal to SDL_GetModState() at the instant the event is processed/enqueued".

For example, if you depress the Shift key you get a key down event with .mod == 0. However, .mod should not be 0 because a shift key is down. If you then release the Shift key, you get a key up event with .mod == 0. Neither event reports the modifier key.

If you press Shift and then A, .mod is incorrect (== 0) when Shift is pressed, but is correct later when A is pressed (== KMOD_LSHIFT).

You might say this behavior is deliberate, i.e. keysym.mod is the value /before/ the event, not the current value as documented, but that explanation is incorrect because only key down events behave that way. Key up events correctly give the current value, not the value before the event.

Not only is it inconsistent with itself, I think it makes keyboard processing harder.

The problem is near line 740 in SDL_keyboard.c:

if (SDL_KEYDOWN == type) {
modstate = keyboard->modstate; // SHOULD THIS BE MOVED DOWN?
switch (keycode) {
case SDLK_NUMLOCKCLEAR:
keyboard->modstate ^= KMOD_NUM;
break;
case SDLK_CAPSLOCK:
keyboard->modstate ^= KMOD_CAPS;
break;
default:
keyboard->modstate |= modifier;
break;
}
} else {
keyboard->modstate &= ~modifier;
modstate = keyboard->modstate;
}

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