src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 12 Aug 2017 15:41:03 -0700
changeset 11247 27eb9a10002c
parent 11240 1f6105d09344
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Fixed bug 3188 - AZERTY keyboard support broken and inconsistent

Daniel Gibson

AZERTY keyboard layouts (which are the default layouts in France and Belgium) don't have the number keys (1, 2, ..., 9, 0) in the first row of keys, but ², &, é", ', (, -, è_, çà), = (with small differences between the France and Belgian variants). Numbers are reached via shift.

On Linux and OSX, SDL seems to use the corresponding ISO 8859-1 codes (231 for ç232 for ètc) as SDL_Keycode (but no SDK_* constants exists for those values!), while on Windows SDL seems to map those keys to SDLK_1, SDLK_2 etc, like you'd get on QWERTY.
I don't know how other platforms behave.

So we have two problems:
1. At least on Linux and OSX invalid/undefined SDL_Keycodes are returned
2. Different platforms behave differently (Windows vs Linux/OSX)

It's unclear what behavior is desired: Should SDL_* constants for those keys be introduced (and Windows behavior changed accordingly)?
Or should all platforms behave like Windows here and use the existing SDLK_1, ..., SDLK_0 keycodes?

This bug on the mailing list:
https://forums.libsdl.org/viewtopic.php?t=11555 (my post about Linux/Windows)
https://forums.libsdl.org/viewtopic.php?t=11573 (Tim Walters discovered the same problem on OSX about 1.5 weeks later).
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@11247
   597
    SDL_Scancode scancode;
slouken@1895
   598
slouken@2303
   599
    if (start < 0 || start + length > SDL_NUM_SCANCODES) {
slouken@2303
   600
        return;
slouken@1895
   601
    }
slouken@2268
   602
slouken@2303
   603
    SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
slouken@11247
   604
slouken@11247
   605
    /* The number key scancodes always map to the number key keycodes.
slouken@11247
   606
     * On AZERTY layouts these technically are symbols, but users (and games)
slouken@11247
   607
     * always think of them and view them in UI as number keys.
slouken@11247
   608
     */
slouken@11247
   609
    keyboard->keymap[SDL_SCANCODE_0] = SDLK_0;
slouken@11247
   610
    for (scancode = SDL_SCANCODE_1; scancode <= SDL_SCANCODE_9; ++scancode) {
slouken@11247
   611
        keyboard->keymap[scancode] = SDLK_1 + (scancode - SDL_SCANCODE_1);
slouken@11247
   612
    }
slouken@1895
   613
}
slouken@1895
   614
slouken@1895
   615
void
slouken@5218
   616
SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
slouken@2268
   617
{
slouken@2303
   618
    SDL_scancode_names[scancode] = name;
slouken@2268
   619
}
slouken@2268
   620
slouken@4465
   621
SDL_Window *
slouken@4465
   622
SDL_GetKeyboardFocus(void)
slouken@4465
   623
{
slouken@4465
   624
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@4465
   625
slouken@4465
   626
    return keyboard->focus;
slouken@4465
   627
}
slouken@4465
   628
slouken@2268
   629
void
slouken@4465
   630
SDL_SetKeyboardFocus(SDL_Window * window)
slouken@1895
   631
{
slouken@4465
   632
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@1895
   633
slouken@6665
   634
    if (keyboard->focus && !window) {
slouken@6665
   635
        /* We won't get anymore keyboard messages, so reset keyboard state */
slouken@6665
   636
        SDL_ResetKeyboard();
slouken@6665
   637
    }
slouken@6665
   638
slouken@1895
   639
    /* See if the current window has lost focus */
slouken@3685
   640
    if (keyboard->focus && keyboard->focus != window) {
icculus@8927
   641
icculus@8927
   642
        /* new window shouldn't think it has mouse captured. */
icculus@8927
   643
        SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
icculus@8927
   644
icculus@8927
   645
        /* old window must lose an existing mouse capture. */
icculus@8927
   646
        if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
icculus@8927
   647
            SDL_CaptureMouse(SDL_FALSE);  /* drop the capture. */
icculus@8927
   648
            SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
icculus@8927
   649
        }
icculus@8927
   650
slouken@4465
   651
        SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
slouken@4465
   652
                            0, 0);
slouken@4890
   653
slouken@4890
   654
        /* Ensures IME compositions are committed */
slouken@4890
   655
        if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
slouken@4890
   656
            SDL_VideoDevice *video = SDL_GetVideoDevice();
slouken@4890
   657
            if (video && video->StopTextInput) {
slouken@4890
   658
                video->StopTextInput(video);
slouken@4890
   659
            }
slouken@4890
   660
        }
slouken@1895
   661
    }
slouken@1895
   662
slouken@3685
   663
    keyboard->focus = window;
slouken@1895
   664
slouken@1895
   665
    if (keyboard->focus) {
slouken@3502
   666
        SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
slouken@3502
   667
                            0, 0);
slouken@4435
   668
slouken@4435
   669
        if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
slouken@4890
   670
            SDL_VideoDevice *video = SDL_GetVideoDevice();
slouken@4890
   671
            if (video && video->StartTextInput) {
slouken@4890
   672
                video->StartTextInput(video);
slouken@4890
   673
            }
slouken@4435
   674
        }
slouken@1895
   675
    }
slouken@1895
   676
}
slouken@1895
   677
slouken@1895
   678
int
slouken@5218
   679
SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
slouken@1895
   680
{
slouken@4465
   681
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@2129
   682
    int posted;
slouken@9678
   683
    SDL_Keymod modifier;
slouken@9678
   684
    SDL_Keycode keycode;
slouken@4429
   685
    Uint32 type;
slouken@4565
   686
    Uint8 repeat;
slouken@1895
   687
slouken@4465
   688
    if (!scancode) {
slouken@1895
   689
        return 0;
slouken@1895
   690
    }
slouken@6661
   691
#ifdef DEBUG_KEYBOARD
slouken@2303
   692
    printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
slouken@1895
   693
           state == SDL_PRESSED ? "pressed" : "released");
slouken@0
   694
#endif
slouken@0
   695
slouken@1895
   696
    /* Figure out what type of event this is */
slouken@1895
   697
    switch (state) {
slouken@1895
   698
    case SDL_PRESSED:
slouken@1895
   699
        type = SDL_KEYDOWN;
slouken@1895
   700
        break;
slouken@1895
   701
    case SDL_RELEASED:
slouken@1895
   702
        type = SDL_KEYUP;
slouken@1895
   703
        break;
slouken@1895
   704
    default:
slouken@1895
   705
        /* Invalid state -- bail */
slouken@1895
   706
        return 0;
slouken@1895
   707
    }
slouken@0
   708
slouken@2303
   709
    /* Drop events that don't change state */
slouken@4565
   710
    repeat = (state && keyboard->keystate[scancode]);
slouken@4560
   711
    if (keyboard->keystate[scancode] == state && !repeat) {
slouken@1895
   712
#if 0
slouken@2303
   713
        printf("Keyboard event didn't change state - dropped!\n");
slouken@1895
   714
#endif
slouken@2303
   715
        return 0;
slouken@2303
   716
    }
slouken@0
   717
slouken@2303
   718
    /* Update internal keyboard state */
slouken@2303
   719
    keyboard->keystate[scancode] = state;
slouken@0
   720
slouken@9678
   721
    keycode = keyboard->keymap[scancode];
slouken@9678
   722
slouken@9678
   723
    /* Update modifiers state if applicable */
slouken@9678
   724
    switch (keycode) {
slouken@9678
   725
    case SDLK_LCTRL:
slouken@9678
   726
        modifier = KMOD_LCTRL;
slouken@9678
   727
        break;
slouken@9678
   728
    case SDLK_RCTRL:
slouken@9678
   729
        modifier = KMOD_RCTRL;
slouken@9678
   730
        break;
slouken@9678
   731
    case SDLK_LSHIFT:
slouken@9678
   732
        modifier = KMOD_LSHIFT;
slouken@9678
   733
        break;
slouken@9678
   734
    case SDLK_RSHIFT:
slouken@9678
   735
        modifier = KMOD_RSHIFT;
slouken@9678
   736
        break;
slouken@9678
   737
    case SDLK_LALT:
slouken@9678
   738
        modifier = KMOD_LALT;
slouken@9678
   739
        break;
slouken@9678
   740
    case SDLK_RALT:
slouken@9678
   741
        modifier = KMOD_RALT;
slouken@9678
   742
        break;
slouken@9678
   743
    case SDLK_LGUI:
slouken@9678
   744
        modifier = KMOD_LGUI;
slouken@9678
   745
        break;
slouken@9678
   746
    case SDLK_RGUI:
slouken@9678
   747
        modifier = KMOD_RGUI;
slouken@9678
   748
        break;
slouken@9678
   749
    case SDLK_MODE:
slouken@9678
   750
        modifier = KMOD_MODE;
slouken@9678
   751
        break;
slouken@9678
   752
    default:
slouken@9678
   753
        modifier = KMOD_NONE;
slouken@9678
   754
        break;
slouken@9678
   755
    }
slouken@9678
   756
    if (SDL_KEYDOWN == type) {
slouken@9678
   757
        switch (keycode) {
slouken@9678
   758
        case SDLK_NUMLOCKCLEAR:
slouken@9678
   759
            keyboard->modstate ^= KMOD_NUM;
slouken@9678
   760
            break;
slouken@9678
   761
        case SDLK_CAPSLOCK:
slouken@9678
   762
            keyboard->modstate ^= KMOD_CAPS;
slouken@9678
   763
            break;
slouken@9678
   764
        default:
slouken@9678
   765
            keyboard->modstate |= modifier;
slouken@9678
   766
            break;
slouken@9678
   767
        }
slouken@9678
   768
    } else {
slouken@9678
   769
        keyboard->modstate &= ~modifier;
slouken@9678
   770
    }
slouken@9678
   771
slouken@1895
   772
    /* Post the event, if desired */
slouken@1895
   773
    posted = 0;
slouken@4429
   774
    if (SDL_GetEventState(type) == SDL_ENABLE) {
slouken@1895
   775
        SDL_Event event;
slouken@1895
   776
        event.key.type = type;
slouken@1895
   777
        event.key.state = state;
slouken@4565
   778
        event.key.repeat = repeat;
slouken@1895
   779
        event.key.keysym.scancode = scancode;
slouken@9678
   780
        event.key.keysym.sym = keycode;
slouken@11240
   781
        event.key.keysym.mod = keyboard->modstate;
gzjjgod@4437
   782
        event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
slouken@1895
   783
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   784
    }
slouken@1895
   785
    return (posted);
slouken@1895
   786
}
slouken@1327
   787
slouken@1895
   788
int
slouken@4465
   789
SDL_SendKeyboardText(const char *text)
slouken@1895
   790
{
slouken@4465
   791
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@1895
   792
    int posted;
slouken@0
   793
slouken@4529
   794
    /* Don't post text events for unprintable characters */
slouken@4567
   795
    if ((unsigned char)*text < ' ' || *text == 127) {
slouken@4529
   796
        return 0;
slouken@4529
   797
    }
slouken@4529
   798
slouken@1895
   799
    /* Post the event, if desired */
slouken@1895
   800
    posted = 0;
slouken@4429
   801
    if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
slouken@1895
   802
        SDL_Event event;
slouken@1895
   803
        event.text.type = SDL_TEXTINPUT;
slouken@4435
   804
        event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
dewyatt@4754
   805
        SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
slouken@1895
   806
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   807
    }
slouken@1895
   808
    return (posted);
slouken@0
   809
}
slouken@0
   810
slouken@3280
   811
int
slouken@4465
   812
SDL_SendEditingText(const char *text, int start, int length)
slouken@3280
   813
{
slouken@4465
   814
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@3280
   815
    int posted;
slouken@3280
   816
slouken@3280
   817
    /* Post the event, if desired */
slouken@3280
   818
    posted = 0;
slouken@4429
   819
    if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
slouken@3280
   820
        SDL_Event event;
slouken@3280
   821
        event.edit.type = SDL_TEXTEDITING;
slouken@4435
   822
        event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
slouken@3280
   823
        event.edit.start = start;
slouken@3280
   824
        event.edit.length = length;
dewyatt@4754
   825
        SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
slouken@3280
   826
        posted = (SDL_PushEvent(&event) > 0);
slouken@3280
   827
    }
slouken@3280
   828
    return (posted);
slouken@3280
   829
}
slouken@3280
   830
slouken@2303
   831
void
slouken@2303
   832
SDL_KeyboardQuit(void)
slouken@2303
   833
{
slouken@2303
   834
}
slouken@2303
   835
slouken@7258
   836
const Uint8 *
slouken@2303
   837
SDL_GetKeyboardState(int *numkeys)
slouken@2303
   838
{
slouken@4465
   839
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@2303
   840
slouken@2303
   841
    if (numkeys != (int *) 0) {
slouken@2303
   842
        *numkeys = SDL_NUM_SCANCODES;
slouken@2303
   843
    }
slouken@2303
   844
    return keyboard->keystate;
slouken@2303
   845
}
slouken@2303
   846
slouken@5220
   847
SDL_Keymod
slouken@2303
   848
SDL_GetModState(void)
slouken@2303
   849
{
slouken@4465
   850
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@2303
   851
icculus@10926
   852
    return (SDL_Keymod) keyboard->modstate;
slouken@2303
   853
}
slouken@2303
   854
slouken@2303
   855
void
slouken@5220
   856
SDL_SetModState(SDL_Keymod modstate)
slouken@2303
   857
{
slouken@4465
   858
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@2303
   859
slouken@2303
   860
    keyboard->modstate = modstate;
slouken@2303
   861
}
slouken@2303
   862
icculus@9973
   863
/* Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. */
icculus@9973
   864
void
icculus@9973
   865
SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
icculus@9973
   866
{
icculus@9973
   867
    SDL_Keyboard *keyboard = &SDL_keyboard;
icculus@9973
   868
    if (toggle) {
icculus@9973
   869
        keyboard->modstate |= modstate;
icculus@9973
   870
    } else {
icculus@9973
   871
        keyboard->modstate &= ~modstate;
icculus@9973
   872
    }
icculus@9973
   873
}
icculus@9973
   874
icculus@9973
   875
slouken@5220
   876
SDL_Keycode
slouken@5218
   877
SDL_GetKeyFromScancode(SDL_Scancode scancode)
slouken@2303
   878
{
slouken@4465
   879
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@7191
   880
icculus@10926
   881
    if (((int)scancode) < ((int)SDL_SCANCODE_UNKNOWN) || scancode >= SDL_NUM_SCANCODES) {
aschiffler@6813
   882
          SDL_InvalidParamError("scancode");
aschiffler@6813
   883
          return 0;
aschiffler@6813
   884
    }
slouken@2303
   885
slouken@2303
   886
    return keyboard->keymap[scancode];
slouken@2303
   887
}
slouken@2303
   888
slouken@5218
   889
SDL_Scancode
slouken@5220
   890
SDL_GetScancodeFromKey(SDL_Keycode key)
slouken@2303
   891
{
slouken@4465
   892
    SDL_Keyboard *keyboard = &SDL_keyboard;
slouken@5218
   893
    SDL_Scancode scancode;
slouken@2303
   894
slouken@2303
   895
    for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
slouken@2303
   896
         ++scancode) {
slouken@2303
   897
        if (keyboard->keymap[scancode] == key) {
slouken@2303
   898
            return scancode;
slouken@2303
   899
        }
slouken@2303
   900
    }
slouken@2303
   901
    return SDL_SCANCODE_UNKNOWN;
slouken@2303
   902
}
slouken@2303
   903
slouken@2303
   904
const char *
slouken@5218
   905
SDL_GetScancodeName(SDL_Scancode scancode)
slouken@2303
   906
{
aschiffler@6983
   907
    const char *name;
icculus@10926
   908
    if (((int)scancode) < ((int)SDL_SCANCODE_UNKNOWN) || scancode >= SDL_NUM_SCANCODES) {
aschiffler@6983
   909
          SDL_InvalidParamError("scancode");
slouken@7191
   910
          return "";
aschiffler@6983
   911
    }
slouken@2303
   912
aschiffler@6983
   913
    name = SDL_scancode_names[scancode];
slouken@2303
   914
    if (name)
slouken@2303
   915
        return name;
slouken@2303
   916
    else
slouken@2303
   917
        return "";
slouken@2303
   918
}
slouken@2303
   919
slouken@6029
   920
SDL_Scancode SDL_GetScancodeFromName(const char *name)
slouken@6029
   921
{
slouken@7191
   922
    int i;
slouken@6029
   923
slouken@7191
   924
    if (!name || !*name) {
slouken@7191
   925
            SDL_InvalidParamError("name");
slouken@7191
   926
        return SDL_SCANCODE_UNKNOWN;
slouken@7191
   927
    }
slouken@6029
   928
slouken@7191
   929
    for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
slouken@7191
   930
        if (!SDL_scancode_names[i]) {
slouken@7191
   931
            continue;
slouken@7191
   932
        }
slouken@7191
   933
        if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
slouken@7191
   934
            return (SDL_Scancode)i;
slouken@7191
   935
        }
slouken@7191
   936
    }
aschiffler@6811
   937
slouken@7191
   938
    SDL_InvalidParamError("name");
slouken@7191
   939
    return SDL_SCANCODE_UNKNOWN;
slouken@6029
   940
}
slouken@6029
   941
slouken@2303
   942
const char *
slouken@5220
   943
SDL_GetKeyName(SDL_Keycode key)
slouken@2303
   944
{
slouken@2303
   945
    static char name[8];
slouken@2303
   946
    char *end;
slouken@2303
   947
slouken@2303
   948
    if (key & SDLK_SCANCODE_MASK) {
slouken@2303
   949
        return
slouken@5218
   950
            SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
slouken@2303
   951
    }
slouken@2303
   952
slouken@2989
   953
    switch (key) {
slouken@2989
   954
    case SDLK_RETURN:
slouken@2990
   955
        return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
slouken@2989
   956
    case SDLK_ESCAPE:
slouken@2990
   957
        return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
slouken@2989
   958
    case SDLK_BACKSPACE:
slouken@2990
   959
        return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
slouken@2989
   960
    case SDLK_TAB:
slouken@2990
   961
        return SDL_GetScancodeName(SDL_SCANCODE_TAB);
slouken@2989
   962
    case SDLK_SPACE:
slouken@2990
   963
        return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
slouken@2989
   964
    case SDLK_DELETE:
slouken@2990
   965
        return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
slouken@2989
   966
    default:
slouken@2989
   967
        /* Unaccented letter keys on latin keyboards are normally
slouken@2989
   968
           labeled in upper case (and probably on others like Greek or
slouken@2989
   969
           Cyrillic too, so if you happen to know for sure, please
slouken@2989
   970
           adapt this). */
slouken@2989
   971
        if (key >= 'a' && key <= 'z') {
slouken@2989
   972
            key -= 32;
slouken@2989
   973
        }
slouken@2989
   974
slouken@2989
   975
        end = SDL_UCS4ToUTF8((Uint32) key, name);
slouken@2989
   976
        *end = '\0';
slouken@2989
   977
        return name;
slouken@2303
   978
    }
slouken@2303
   979
}
slouken@2303
   980
slouken@6029
   981
SDL_Keycode
slouken@6029
   982
SDL_GetKeyFromName(const char *name)
slouken@6029
   983
{
slouken@7191
   984
    SDL_Keycode key;
slouken@6029
   985
slouken@10801
   986
    /* Check input */
slouken@10801
   987
    if (name == NULL) {
slouken@10801
   988
        return SDLK_UNKNOWN;
slouken@10801
   989
    }
slouken@6029
   990
slouken@7191
   991
    /* If it's a single UTF-8 character, then that's the keycode itself */
slouken@7191
   992
    key = *(const unsigned char *)name;
slouken@7191
   993
    if (key >= 0xF0) {
slouken@7191
   994
        if (SDL_strlen(name) == 4) {
slouken@7191
   995
            int i = 0;
slouken@7191
   996
            key  = (Uint16)(name[i]&0x07) << 18;
slouken@7191
   997
            key |= (Uint16)(name[++i]&0x3F) << 12;
slouken@7191
   998
            key |= (Uint16)(name[++i]&0x3F) << 6;
slouken@7191
   999
            key |= (Uint16)(name[++i]&0x3F);
slouken@7191
  1000
            return key;
slouken@7191
  1001
        }
slouken@7191
  1002
        return SDLK_UNKNOWN;
slouken@7191
  1003
    } else if (key >= 0xE0) {
slouken@7191
  1004
        if (SDL_strlen(name) == 3) {
slouken@7191
  1005
            int i = 0;
slouken@7191
  1006
            key  = (Uint16)(name[i]&0x0F) << 12;
slouken@7191
  1007
            key |= (Uint16)(name[++i]&0x3F) << 6;
slouken@7191
  1008
            key |= (Uint16)(name[++i]&0x3F);
slouken@7191
  1009
            return key;
slouken@7191
  1010
        }
slouken@7191
  1011
        return SDLK_UNKNOWN;
slouken@7191
  1012
    } else if (key >= 0xC0) {
slouken@7191
  1013
        if (SDL_strlen(name) == 2) {
slouken@7191
  1014
            int i = 0;
slouken@7191
  1015
            key  = (Uint16)(name[i]&0x1F) << 6;
slouken@7191
  1016
            key |= (Uint16)(name[++i]&0x3F);
slouken@7191
  1017
            return key;
slouken@7191
  1018
        }
slouken@7191
  1019
        return SDLK_UNKNOWN;
slouken@7191
  1020
    } else {
slouken@7191
  1021
        if (SDL_strlen(name) == 1) {
slouken@7191
  1022
            if (key >= 'A' && key <= 'Z') {
slouken@7191
  1023
                key += 32;
slouken@7191
  1024
            }
slouken@7191
  1025
            return key;
slouken@7191
  1026
        }
slouken@7191
  1027
slouken@7191
  1028
        /* Get the scancode for this name, and the associated keycode */
slouken@7191
  1029
        return SDL_default_keymap[SDL_GetScancodeFromName(name)];
slouken@7191
  1030
    }
slouken@6029
  1031
}
slouken@6029
  1032
slouken@1895
  1033
/* vi: set ts=4 sw=4 expandtab: */