Atlas - SDL_keymap.c

Home / ext / SDL / src / events Lines: 1 | Size: 36318 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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#include "SDL_keymap_c.h" 24#include "SDL_keyboard_c.h" 25 26static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate); 27static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate); 28 29SDL_Keymap *SDL_CreateKeymap(bool auto_release) 30{ 31 SDL_Keymap *keymap = (SDL_Keymap *)SDL_calloc(1, sizeof(*keymap)); 32 if (!keymap) { 33 return NULL; 34 } 35 36 keymap->auto_release = auto_release; 37 keymap->scancode_to_keycode = SDL_CreateHashTable(256, false, SDL_HashID, SDL_KeyMatchID, NULL, NULL); 38 keymap->keycode_to_scancode = SDL_CreateHashTable(256, false, SDL_HashID, SDL_KeyMatchID, NULL, NULL); 39 if (!keymap->scancode_to_keycode || !keymap->keycode_to_scancode) { 40 SDL_DestroyKeymap(keymap); 41 return NULL; 42 } 43 return keymap; 44} 45 46static SDL_Keymod NormalizeModifierStateForKeymap(SDL_Keymod modstate) 47{ 48 // The modifiers that affect the keymap are: SHIFT, CAPS, ALT, MODE, and LEVEL5 49 modstate &= (SDL_KMOD_SHIFT | SDL_KMOD_CAPS | SDL_KMOD_ALT | SDL_KMOD_MODE | SDL_KMOD_LEVEL5); 50 51 // If either right or left Shift are set, set both in the output 52 if (modstate & SDL_KMOD_SHIFT) { 53 modstate |= SDL_KMOD_SHIFT; 54 } 55 56 // If either right or left Alt are set, set both in the output 57 if (modstate & SDL_KMOD_ALT) { 58 modstate |= SDL_KMOD_ALT; 59 } 60 61 return modstate; 62} 63 64void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode) 65{ 66 if (!keymap) { 67 return; 68 } 69 70 modstate = NormalizeModifierStateForKeymap(modstate); 71 Uint32 key = ((Uint32)modstate << 16) | scancode; 72 const void *value; 73 if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 74 const SDL_Keycode existing_keycode = (SDL_Keycode)(uintptr_t)value; 75 if (existing_keycode == keycode) { 76 // We already have this mapping 77 return; 78 } 79 // InsertIntoHashTable will replace the existing entry in the keymap atomically. 80 } 81 SDL_InsertIntoHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, (void *)(uintptr_t)keycode, true); 82 83 bool update_keycode = true; 84 if (SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) { 85 const Uint32 existing_value = (Uint32)(uintptr_t)value; 86 const SDL_Keymod existing_modstate = (SDL_Keymod)(existing_value >> 16); 87 88 // Keep the simplest combination of scancode and modifiers to generate this keycode 89 if (existing_modstate <= modstate) { 90 update_keycode = false; 91 } 92 } 93 if (update_keycode) { 94 SDL_InsertIntoHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, (void *)(uintptr_t)key, true); 95 } 96} 97 98SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate) 99{ 100 if (keymap) { 101 const void *value; 102 const SDL_Keymod normalized_modstate = NormalizeModifierStateForKeymap(modstate); 103 Uint32 key = ((Uint32)normalized_modstate << 16) | scancode; 104 105 // First, try the requested set of modifiers. 106 if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 107 return (SDL_Keycode)(uintptr_t)value; 108 } 109 110 // If the requested set of modifiers was not found, search for the key from the highest to lowest modifier levels. 111 if (normalized_modstate) { 112 SDL_Keymod caps_mask = normalized_modstate & SDL_KMOD_CAPS; 113 114 for (int i = caps_mask ? 2 : 1; i; --i) { 115 // Shift level 5 116 if (normalized_modstate & SDL_KMOD_LEVEL5) { 117 const SDL_Keymod shifted_modstate = SDL_KMOD_LEVEL5 | caps_mask; 118 key = ((Uint32)shifted_modstate << 16) | scancode; 119 120 if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 121 return (SDL_Keycode)(uintptr_t)value; 122 } 123 } 124 125 // Shift level 4 (Level 3 + Shift) 126 if ((normalized_modstate & (SDL_KMOD_MODE | SDL_KMOD_SHIFT)) == (SDL_KMOD_MODE | SDL_KMOD_SHIFT)) { 127 const SDL_Keymod shifted_modstate = SDL_KMOD_MODE | SDL_KMOD_SHIFT | caps_mask; 128 key = ((Uint32)shifted_modstate << 16) | scancode; 129 130 if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 131 return (SDL_Keycode)(uintptr_t)value; 132 } 133 } 134 135 // Shift level 3 136 if (normalized_modstate & SDL_KMOD_MODE) { 137 const SDL_Keymod shifted_modstate = SDL_KMOD_MODE | caps_mask; 138 key = ((Uint32)shifted_modstate << 16) | scancode; 139 140 if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 141 return (SDL_Keycode)(uintptr_t)value; 142 } 143 } 144 145 // Shift level 2 146 if (normalized_modstate & SDL_KMOD_SHIFT) { 147 const SDL_Keymod shifted_modstate = SDL_KMOD_SHIFT | caps_mask; 148 key = ((Uint32)shifted_modstate << 16) | scancode; 149 150 if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 151 return (SDL_Keycode)(uintptr_t)value; 152 } 153 } 154 155 // Shift Level 1 (unmodified) 156 key = ((Uint32)caps_mask << 16) | scancode; 157 if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { 158 return (SDL_Keycode)(uintptr_t)value; 159 } 160 161 // Clear the capslock mask, if set. 162 caps_mask = SDL_KMOD_NONE; 163 } 164 } 165 } 166 167 return SDL_GetDefaultKeyFromScancode(scancode, modstate); 168} 169 170SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate) 171{ 172 SDL_Scancode scancode; 173 174 const void *value; 175 if (keymap && SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) { 176 scancode = (SDL_Scancode)((uintptr_t)value & 0xFFFF); 177 if (modstate) { 178 *modstate = (SDL_Keymod)((uintptr_t)value >> 16); 179 } 180 } else { 181 scancode = SDL_GetDefaultScancodeFromKey(keycode, modstate); 182 } 183 return scancode; 184} 185 186SDL_Scancode SDL_GetKeymapNextReservedScancode(SDL_Keymap *keymap) 187{ 188 SDL_Scancode scancode; 189 190 if (!keymap) { 191 return SDL_SCANCODE_UNKNOWN; 192 } 193 194 if (keymap->next_reserved_scancode && keymap->next_reserved_scancode < SDL_SCANCODE_RESERVED + 100) { 195 scancode = keymap->next_reserved_scancode; 196 } else { 197 scancode = SDL_SCANCODE_RESERVED; 198 } 199 keymap->next_reserved_scancode = scancode + 1; 200 201 return scancode; 202} 203 204void SDL_DestroyKeymap(SDL_Keymap *keymap) 205{ 206 if (!keymap) { 207 return; 208 } 209 210 if (!keymap->auto_release && keymap == SDL_GetCurrentKeymap(true)) { 211 SDL_SetKeymap(NULL, false); 212 } 213 214 SDL_DestroyHashTable(keymap->scancode_to_keycode); 215 SDL_DestroyHashTable(keymap->keycode_to_scancode); 216 SDL_free(keymap); 217} 218 219static const SDL_Keycode normal_default_symbols[] = { 220 SDLK_1, 221 SDLK_2, 222 SDLK_3, 223 SDLK_4, 224 SDLK_5, 225 SDLK_6, 226 SDLK_7, 227 SDLK_8, 228 SDLK_9, 229 SDLK_0, 230 SDLK_RETURN, 231 SDLK_ESCAPE, 232 SDLK_BACKSPACE, 233 SDLK_TAB, 234 SDLK_SPACE, 235 SDLK_MINUS, 236 SDLK_EQUALS, 237 SDLK_LEFTBRACKET, 238 SDLK_RIGHTBRACKET, 239 SDLK_BACKSLASH, 240 SDLK_HASH, 241 SDLK_SEMICOLON, 242 SDLK_APOSTROPHE, 243 SDLK_GRAVE, 244 SDLK_COMMA, 245 SDLK_PERIOD, 246 SDLK_SLASH, 247}; 248 249static const SDL_Keycode shifted_default_symbols[] = { 250 SDLK_EXCLAIM, 251 SDLK_AT, 252 SDLK_HASH, 253 SDLK_DOLLAR, 254 SDLK_PERCENT, 255 SDLK_CARET, 256 SDLK_AMPERSAND, 257 SDLK_ASTERISK, 258 SDLK_LEFTPAREN, 259 SDLK_RIGHTPAREN, 260 SDLK_RETURN, 261 SDLK_ESCAPE, 262 SDLK_BACKSPACE, 263 SDLK_TAB, 264 SDLK_SPACE, 265 SDLK_UNDERSCORE, 266 SDLK_PLUS, 267 SDLK_LEFTBRACE, 268 SDLK_RIGHTBRACE, 269 SDLK_PIPE, 270 SDLK_HASH, 271 SDLK_COLON, 272 SDLK_DBLAPOSTROPHE, 273 SDLK_TILDE, 274 SDLK_LESS, 275 SDLK_GREATER, 276 SDLK_QUESTION 277}; 278 279static const struct 280{ 281 SDL_Keycode keycode; 282 SDL_Scancode scancode; 283} extended_default_symbols[] = { 284 { SDLK_LEFT_TAB, SDL_SCANCODE_TAB }, 285 { SDLK_MULTI_KEY_COMPOSE, SDL_SCANCODE_APPLICATION }, // Sun keyboards 286 { SDLK_LMETA, SDL_SCANCODE_LGUI }, 287 { SDLK_RMETA, SDL_SCANCODE_RGUI }, 288 { SDLK_RHYPER, SDL_SCANCODE_APPLICATION } 289}; 290 291static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate) 292{ 293 CHECK_PARAM(((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { 294 SDL_InvalidParamError("scancode"); 295 return SDLK_UNKNOWN; 296 } 297 298 if (scancode < SDL_SCANCODE_A) { 299 return SDLK_UNKNOWN; 300 } 301 302 if (scancode < SDL_SCANCODE_1) { 303 bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false; 304#ifdef SDL_PLATFORM_APPLE 305 // Apple maps to upper case for either shift or capslock inclusive 306 if (modstate & SDL_KMOD_CAPS) { 307 shifted = true; 308 } 309#else 310 if (modstate & SDL_KMOD_CAPS) { 311 shifted = !shifted; 312 } 313#endif 314 if (modstate & SDL_KMOD_MODE) { 315 return SDLK_UNKNOWN; 316 } 317 if (!shifted) { 318 return (SDL_Keycode)('a' + scancode - SDL_SCANCODE_A); 319 } else { 320 return (SDL_Keycode)('A' + scancode - SDL_SCANCODE_A); 321 } 322 } 323 324 if (scancode < SDL_SCANCODE_CAPSLOCK) { 325 bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false; 326 327 if (modstate & SDL_KMOD_MODE) { 328 return SDLK_UNKNOWN; 329 } 330 if (!shifted) { 331 return normal_default_symbols[scancode - SDL_SCANCODE_1]; 332 } else { 333 return shifted_default_symbols[scancode - SDL_SCANCODE_1]; 334 } 335 } 336 337 // These scancodes are not mapped to printable keycodes 338 switch (scancode) { 339 case SDL_SCANCODE_DELETE: 340 return SDLK_DELETE; 341 case SDL_SCANCODE_CAPSLOCK: 342 return SDLK_CAPSLOCK; 343 case SDL_SCANCODE_F1: 344 return SDLK_F1; 345 case SDL_SCANCODE_F2: 346 return SDLK_F2; 347 case SDL_SCANCODE_F3: 348 return SDLK_F3; 349 case SDL_SCANCODE_F4: 350 return SDLK_F4; 351 case SDL_SCANCODE_F5: 352 return SDLK_F5; 353 case SDL_SCANCODE_F6: 354 return SDLK_F6; 355 case SDL_SCANCODE_F7: 356 return SDLK_F7; 357 case SDL_SCANCODE_F8: 358 return SDLK_F8; 359 case SDL_SCANCODE_F9: 360 return SDLK_F9; 361 case SDL_SCANCODE_F10: 362 return SDLK_F10; 363 case SDL_SCANCODE_F11: 364 return SDLK_F11; 365 case SDL_SCANCODE_F12: 366 return SDLK_F12; 367 case SDL_SCANCODE_PRINTSCREEN: 368 return SDLK_PRINTSCREEN; 369 case SDL_SCANCODE_SCROLLLOCK: 370 return SDLK_SCROLLLOCK; 371 case SDL_SCANCODE_PAUSE: 372 return SDLK_PAUSE; 373 case SDL_SCANCODE_INSERT: 374 return SDLK_INSERT; 375 case SDL_SCANCODE_HOME: 376 return SDLK_HOME; 377 case SDL_SCANCODE_PAGEUP: 378 return SDLK_PAGEUP; 379 case SDL_SCANCODE_END: 380 return SDLK_END; 381 case SDL_SCANCODE_PAGEDOWN: 382 return SDLK_PAGEDOWN; 383 case SDL_SCANCODE_RIGHT: 384 return SDLK_RIGHT; 385 case SDL_SCANCODE_LEFT: 386 return SDLK_LEFT; 387 case SDL_SCANCODE_DOWN: 388 return SDLK_DOWN; 389 case SDL_SCANCODE_UP: 390 return SDLK_UP; 391 case SDL_SCANCODE_NUMLOCKCLEAR: 392 return SDLK_NUMLOCKCLEAR; 393 case SDL_SCANCODE_KP_DIVIDE: 394 return SDLK_KP_DIVIDE; 395 case SDL_SCANCODE_KP_MULTIPLY: 396 return SDLK_KP_MULTIPLY; 397 case SDL_SCANCODE_KP_MINUS: 398 return SDLK_KP_MINUS; 399 case SDL_SCANCODE_KP_PLUS: 400 return SDLK_KP_PLUS; 401 case SDL_SCANCODE_KP_ENTER: 402 return SDLK_KP_ENTER; 403 case SDL_SCANCODE_KP_1: 404 return SDLK_KP_1; 405 case SDL_SCANCODE_KP_2: 406 return SDLK_KP_2; 407 case SDL_SCANCODE_KP_3: 408 return SDLK_KP_3; 409 case SDL_SCANCODE_KP_4: 410 return SDLK_KP_4; 411 case SDL_SCANCODE_KP_5: 412 return SDLK_KP_5; 413 case SDL_SCANCODE_KP_6: 414 return SDLK_KP_6; 415 case SDL_SCANCODE_KP_7: 416 return SDLK_KP_7; 417 case SDL_SCANCODE_KP_8: 418 return SDLK_KP_8; 419 case SDL_SCANCODE_KP_9: 420 return SDLK_KP_9; 421 case SDL_SCANCODE_KP_0: 422 return SDLK_KP_0; 423 case SDL_SCANCODE_KP_PERIOD: 424 return SDLK_KP_PERIOD; 425 case SDL_SCANCODE_APPLICATION: 426 return SDLK_APPLICATION; 427 case SDL_SCANCODE_POWER: 428 return SDLK_POWER; 429 case SDL_SCANCODE_KP_EQUALS: 430 return SDLK_KP_EQUALS; 431 case SDL_SCANCODE_F13: 432 return SDLK_F13; 433 case SDL_SCANCODE_F14: 434 return SDLK_F14; 435 case SDL_SCANCODE_F15: 436 return SDLK_F15; 437 case SDL_SCANCODE_F16: 438 return SDLK_F16; 439 case SDL_SCANCODE_F17: 440 return SDLK_F17; 441 case SDL_SCANCODE_F18: 442 return SDLK_F18; 443 case SDL_SCANCODE_F19: 444 return SDLK_F19; 445 case SDL_SCANCODE_F20: 446 return SDLK_F20; 447 case SDL_SCANCODE_F21: 448 return SDLK_F21; 449 case SDL_SCANCODE_F22: 450 return SDLK_F22; 451 case SDL_SCANCODE_F23: 452 return SDLK_F23; 453 case SDL_SCANCODE_F24: 454 return SDLK_F24; 455 case SDL_SCANCODE_EXECUTE: 456 return SDLK_EXECUTE; 457 case SDL_SCANCODE_HELP: 458 return SDLK_HELP; 459 case SDL_SCANCODE_MENU: 460 return SDLK_MENU; 461 case SDL_SCANCODE_SELECT: 462 return SDLK_SELECT; 463 case SDL_SCANCODE_STOP: 464 return SDLK_STOP; 465 case SDL_SCANCODE_AGAIN: 466 return SDLK_AGAIN; 467 case SDL_SCANCODE_UNDO: 468 return SDLK_UNDO; 469 case SDL_SCANCODE_CUT: 470 return SDLK_CUT; 471 case SDL_SCANCODE_COPY: 472 return SDLK_COPY; 473 case SDL_SCANCODE_PASTE: 474 return SDLK_PASTE; 475 case SDL_SCANCODE_FIND: 476 return SDLK_FIND; 477 case SDL_SCANCODE_MUTE: 478 return SDLK_MUTE; 479 case SDL_SCANCODE_VOLUMEUP: 480 return SDLK_VOLUMEUP; 481 case SDL_SCANCODE_VOLUMEDOWN: 482 return SDLK_VOLUMEDOWN; 483 case SDL_SCANCODE_KP_COMMA: 484 return SDLK_KP_COMMA; 485 case SDL_SCANCODE_KP_EQUALSAS400: 486 return SDLK_KP_EQUALSAS400; 487 case SDL_SCANCODE_ALTERASE: 488 return SDLK_ALTERASE; 489 case SDL_SCANCODE_SYSREQ: 490 return SDLK_SYSREQ; 491 case SDL_SCANCODE_CANCEL: 492 return SDLK_CANCEL; 493 case SDL_SCANCODE_CLEAR: 494 return SDLK_CLEAR; 495 case SDL_SCANCODE_PRIOR: 496 return SDLK_PRIOR; 497 case SDL_SCANCODE_RETURN2: 498 return SDLK_RETURN2; 499 case SDL_SCANCODE_SEPARATOR: 500 return SDLK_SEPARATOR; 501 case SDL_SCANCODE_OUT: 502 return SDLK_OUT; 503 case SDL_SCANCODE_OPER: 504 return SDLK_OPER; 505 case SDL_SCANCODE_CLEARAGAIN: 506 return SDLK_CLEARAGAIN; 507 case SDL_SCANCODE_CRSEL: 508 return SDLK_CRSEL; 509 case SDL_SCANCODE_EXSEL: 510 return SDLK_EXSEL; 511 case SDL_SCANCODE_KP_00: 512 return SDLK_KP_00; 513 case SDL_SCANCODE_KP_000: 514 return SDLK_KP_000; 515 case SDL_SCANCODE_THOUSANDSSEPARATOR: 516 return SDLK_THOUSANDSSEPARATOR; 517 case SDL_SCANCODE_DECIMALSEPARATOR: 518 return SDLK_DECIMALSEPARATOR; 519 case SDL_SCANCODE_CURRENCYUNIT: 520 return SDLK_CURRENCYUNIT; 521 case SDL_SCANCODE_CURRENCYSUBUNIT: 522 return SDLK_CURRENCYSUBUNIT; 523 case SDL_SCANCODE_KP_LEFTPAREN: 524 return SDLK_KP_LEFTPAREN; 525 case SDL_SCANCODE_KP_RIGHTPAREN: 526 return SDLK_KP_RIGHTPAREN; 527 case SDL_SCANCODE_KP_LEFTBRACE: 528 return SDLK_KP_LEFTBRACE; 529 case SDL_SCANCODE_KP_RIGHTBRACE: 530 return SDLK_KP_RIGHTBRACE; 531 case SDL_SCANCODE_KP_TAB: 532 return SDLK_KP_TAB; 533 case SDL_SCANCODE_KP_BACKSPACE: 534 return SDLK_KP_BACKSPACE; 535 case SDL_SCANCODE_KP_A: 536 return SDLK_KP_A; 537 case SDL_SCANCODE_KP_B: 538 return SDLK_KP_B; 539 case SDL_SCANCODE_KP_C: 540 return SDLK_KP_C; 541 case SDL_SCANCODE_KP_D: 542 return SDLK_KP_D; 543 case SDL_SCANCODE_KP_E: 544 return SDLK_KP_E; 545 case SDL_SCANCODE_KP_F: 546 return SDLK_KP_F; 547 case SDL_SCANCODE_KP_XOR: 548 return SDLK_KP_XOR; 549 case SDL_SCANCODE_KP_POWER: 550 return SDLK_KP_POWER; 551 case SDL_SCANCODE_KP_PERCENT: 552 return SDLK_KP_PERCENT; 553 case SDL_SCANCODE_KP_LESS: 554 return SDLK_KP_LESS; 555 case SDL_SCANCODE_KP_GREATER: 556 return SDLK_KP_GREATER; 557 case SDL_SCANCODE_KP_AMPERSAND: 558 return SDLK_KP_AMPERSAND; 559 case SDL_SCANCODE_KP_DBLAMPERSAND: 560 return SDLK_KP_DBLAMPERSAND; 561 case SDL_SCANCODE_KP_VERTICALBAR: 562 return SDLK_KP_VERTICALBAR; 563 case SDL_SCANCODE_KP_DBLVERTICALBAR: 564 return SDLK_KP_DBLVERTICALBAR; 565 case SDL_SCANCODE_KP_COLON: 566 return SDLK_KP_COLON; 567 case SDL_SCANCODE_KP_HASH: 568 return SDLK_KP_HASH; 569 case SDL_SCANCODE_KP_SPACE: 570 return SDLK_KP_SPACE; 571 case SDL_SCANCODE_KP_AT: 572 return SDLK_KP_AT; 573 case SDL_SCANCODE_KP_EXCLAM: 574 return SDLK_KP_EXCLAM; 575 case SDL_SCANCODE_KP_MEMSTORE: 576 return SDLK_KP_MEMSTORE; 577 case SDL_SCANCODE_KP_MEMRECALL: 578 return SDLK_KP_MEMRECALL; 579 case SDL_SCANCODE_KP_MEMCLEAR: 580 return SDLK_KP_MEMCLEAR; 581 case SDL_SCANCODE_KP_MEMADD: 582 return SDLK_KP_MEMADD; 583 case SDL_SCANCODE_KP_MEMSUBTRACT: 584 return SDLK_KP_MEMSUBTRACT; 585 case SDL_SCANCODE_KP_MEMMULTIPLY: 586 return SDLK_KP_MEMMULTIPLY; 587 case SDL_SCANCODE_KP_MEMDIVIDE: 588 return SDLK_KP_MEMDIVIDE; 589 case SDL_SCANCODE_KP_PLUSMINUS: 590 return SDLK_KP_PLUSMINUS; 591 case SDL_SCANCODE_KP_CLEAR: 592 return SDLK_KP_CLEAR; 593 case SDL_SCANCODE_KP_CLEARENTRY: 594 return SDLK_KP_CLEARENTRY; 595 case SDL_SCANCODE_KP_BINARY: 596 return SDLK_KP_BINARY; 597 case SDL_SCANCODE_KP_OCTAL: 598 return SDLK_KP_OCTAL; 599 case SDL_SCANCODE_KP_DECIMAL: 600 return SDLK_KP_DECIMAL; 601 case SDL_SCANCODE_KP_HEXADECIMAL: 602 return SDLK_KP_HEXADECIMAL; 603 case SDL_SCANCODE_LCTRL: 604 return SDLK_LCTRL; 605 case SDL_SCANCODE_LSHIFT: 606 return SDLK_LSHIFT; 607 case SDL_SCANCODE_LALT: 608 return SDLK_LALT; 609 case SDL_SCANCODE_LGUI: 610 return SDLK_LGUI; 611 case SDL_SCANCODE_RCTRL: 612 return SDLK_RCTRL; 613 case SDL_SCANCODE_RSHIFT: 614 return SDLK_RSHIFT; 615 case SDL_SCANCODE_RALT: 616 return SDLK_RALT; 617 case SDL_SCANCODE_RGUI: 618 return SDLK_RGUI; 619 case SDL_SCANCODE_MODE: 620 return SDLK_MODE; 621 case SDL_SCANCODE_SLEEP: 622 return SDLK_SLEEP; 623 case SDL_SCANCODE_WAKE: 624 return SDLK_WAKE; 625 case SDL_SCANCODE_CHANNEL_INCREMENT: 626 return SDLK_CHANNEL_INCREMENT; 627 case SDL_SCANCODE_CHANNEL_DECREMENT: 628 return SDLK_CHANNEL_DECREMENT; 629 case SDL_SCANCODE_MEDIA_PLAY: 630 return SDLK_MEDIA_PLAY; 631 case SDL_SCANCODE_MEDIA_PAUSE: 632 return SDLK_MEDIA_PAUSE; 633 case SDL_SCANCODE_MEDIA_RECORD: 634 return SDLK_MEDIA_RECORD; 635 case SDL_SCANCODE_MEDIA_FAST_FORWARD: 636 return SDLK_MEDIA_FAST_FORWARD; 637 case SDL_SCANCODE_MEDIA_REWIND: 638 return SDLK_MEDIA_REWIND; 639 case SDL_SCANCODE_MEDIA_NEXT_TRACK: 640 return SDLK_MEDIA_NEXT_TRACK; 641 case SDL_SCANCODE_MEDIA_PREVIOUS_TRACK: 642 return SDLK_MEDIA_PREVIOUS_TRACK; 643 case SDL_SCANCODE_MEDIA_STOP: 644 return SDLK_MEDIA_STOP; 645 case SDL_SCANCODE_MEDIA_EJECT: 646 return SDLK_MEDIA_EJECT; 647 case SDL_SCANCODE_MEDIA_PLAY_PAUSE: 648 return SDLK_MEDIA_PLAY_PAUSE; 649 case SDL_SCANCODE_MEDIA_SELECT: 650 return SDLK_MEDIA_SELECT; 651 case SDL_SCANCODE_AC_NEW: 652 return SDLK_AC_NEW; 653 case SDL_SCANCODE_AC_OPEN: 654 return SDLK_AC_OPEN; 655 case SDL_SCANCODE_AC_CLOSE: 656 return SDLK_AC_CLOSE; 657 case SDL_SCANCODE_AC_EXIT: 658 return SDLK_AC_EXIT; 659 case SDL_SCANCODE_AC_SAVE: 660 return SDLK_AC_SAVE; 661 case SDL_SCANCODE_AC_PRINT: 662 return SDLK_AC_PRINT; 663 case SDL_SCANCODE_AC_PROPERTIES: 664 return SDLK_AC_PROPERTIES; 665 case SDL_SCANCODE_AC_SEARCH: 666 return SDLK_AC_SEARCH; 667 case SDL_SCANCODE_AC_HOME: 668 return SDLK_AC_HOME; 669 case SDL_SCANCODE_AC_BACK: 670 return SDLK_AC_BACK; 671 case SDL_SCANCODE_AC_FORWARD: 672 return SDLK_AC_FORWARD; 673 case SDL_SCANCODE_AC_STOP: 674 return SDLK_AC_STOP; 675 case SDL_SCANCODE_AC_REFRESH: 676 return SDLK_AC_REFRESH; 677 case SDL_SCANCODE_AC_BOOKMARKS: 678 return SDLK_AC_BOOKMARKS; 679 case SDL_SCANCODE_SOFTLEFT: 680 return SDLK_SOFTLEFT; 681 case SDL_SCANCODE_SOFTRIGHT: 682 return SDLK_SOFTRIGHT; 683 case SDL_SCANCODE_CALL: 684 return SDLK_CALL; 685 case SDL_SCANCODE_ENDCALL: 686 return SDLK_ENDCALL; 687 default: 688 return SDLK_UNKNOWN; 689 } 690} 691 692static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate) 693{ 694 if (modstate) { 695 *modstate = SDL_KMOD_NONE; 696 } 697 698 if (key == SDLK_UNKNOWN) { 699 return SDL_SCANCODE_UNKNOWN; 700 } 701 702 if (key & SDLK_EXTENDED_MASK) { 703 for (int i = 0; i < SDL_arraysize(extended_default_symbols); ++i) { 704 if (extended_default_symbols[i].keycode == key) { 705 return extended_default_symbols[i].scancode; 706 } 707 } 708 709 return SDL_SCANCODE_UNKNOWN; 710 } 711 712 if (key & SDLK_SCANCODE_MASK) { 713 return (SDL_Scancode)(key & ~SDLK_SCANCODE_MASK); 714 } 715 716 if (key >= SDLK_A && key <= SDLK_Z) { 717 return (SDL_Scancode)(SDL_SCANCODE_A + key - SDLK_A); 718 } 719 720 if (key >= 'A' && key <= 'Z') { 721 if (modstate) { 722 *modstate = SDL_KMOD_SHIFT; 723 } 724 return (SDL_Scancode)(SDL_SCANCODE_A + key - 'A'); 725 } 726 727 for (int i = 0; i < SDL_arraysize(normal_default_symbols); ++i) { 728 if (key == normal_default_symbols[i]) { 729 return(SDL_Scancode)(SDL_SCANCODE_1 + i); 730 } 731 } 732 733 for (int i = 0; i < SDL_arraysize(shifted_default_symbols); ++i) { 734 if (key == shifted_default_symbols[i]) { 735 if (modstate) { 736 *modstate = SDL_KMOD_SHIFT; 737 } 738 return(SDL_Scancode)(SDL_SCANCODE_1 + i); 739 } 740 } 741 742 if (key == SDLK_DELETE) { 743 return SDL_SCANCODE_DELETE; 744 } 745 746 return SDL_SCANCODE_UNKNOWN; 747} 748 749static const char *SDL_scancode_names[SDL_SCANCODE_COUNT] = 750{ 751 /* 0 */ NULL, 752 /* 1 */ NULL, 753 /* 2 */ NULL, 754 /* 3 */ NULL, 755 /* 4 */ "A", 756 /* 5 */ "B", 757 /* 6 */ "C", 758 /* 7 */ "D", 759 /* 8 */ "E", 760 /* 9 */ "F", 761 /* 10 */ "G", 762 /* 11 */ "H", 763 /* 12 */ "I", 764 /* 13 */ "J", 765 /* 14 */ "K", 766 /* 15 */ "L", 767 /* 16 */ "M", 768 /* 17 */ "N", 769 /* 18 */ "O", 770 /* 19 */ "P", 771 /* 20 */ "Q", 772 /* 21 */ "R", 773 /* 22 */ "S", 774 /* 23 */ "T", 775 /* 24 */ "U", 776 /* 25 */ "V", 777 /* 26 */ "W", 778 /* 27 */ "X", 779 /* 28 */ "Y", 780 /* 29 */ "Z", 781 /* 30 */ "1", 782 /* 31 */ "2", 783 /* 32 */ "3", 784 /* 33 */ "4", 785 /* 34 */ "5", 786 /* 35 */ "6", 787 /* 36 */ "7", 788 /* 37 */ "8", 789 /* 38 */ "9", 790 /* 39 */ "0", 791 /* 40 */ "Return", 792 /* 41 */ "Escape", 793 /* 42 */ "Backspace", 794 /* 43 */ "Tab", 795 /* 44 */ "Space", 796 /* 45 */ "-", 797 /* 46 */ "=", 798 /* 47 */ "[", 799 /* 48 */ "]", 800 /* 49 */ "\\", 801 /* 50 */ "#", 802 /* 51 */ ";", 803 /* 52 */ "'", 804 /* 53 */ "`", 805 /* 54 */ ",", 806 /* 55 */ ".", 807 /* 56 */ "/", 808 /* 57 */ "CapsLock", 809 /* 58 */ "F1", 810 /* 59 */ "F2", 811 /* 60 */ "F3", 812 /* 61 */ "F4", 813 /* 62 */ "F5", 814 /* 63 */ "F6", 815 /* 64 */ "F7", 816 /* 65 */ "F8", 817 /* 66 */ "F9", 818 /* 67 */ "F10", 819 /* 68 */ "F11", 820 /* 69 */ "F12", 821 /* 70 */ "PrintScreen", 822 /* 71 */ "ScrollLock", 823 /* 72 */ "Pause", 824 /* 73 */ "Insert", 825 /* 74 */ "Home", 826 /* 75 */ "PageUp", 827 /* 76 */ "Delete", 828 /* 77 */ "End", 829 /* 78 */ "PageDown", 830 /* 79 */ "Right", 831 /* 80 */ "Left", 832 /* 81 */ "Down", 833 /* 82 */ "Up", 834 /* 83 */ "Numlock", 835 /* 84 */ "Keypad /", 836 /* 85 */ "Keypad *", 837 /* 86 */ "Keypad -", 838 /* 87 */ "Keypad +", 839 /* 88 */ "Keypad Enter", 840 /* 89 */ "Keypad 1", 841 /* 90 */ "Keypad 2", 842 /* 91 */ "Keypad 3", 843 /* 92 */ "Keypad 4", 844 /* 93 */ "Keypad 5", 845 /* 94 */ "Keypad 6", 846 /* 95 */ "Keypad 7", 847 /* 96 */ "Keypad 8", 848 /* 97 */ "Keypad 9", 849 /* 98 */ "Keypad 0", 850 /* 99 */ "Keypad .", 851 /* 100 */ "NonUSBackslash", 852 /* 101 */ "Application", 853 /* 102 */ "Power", 854 /* 103 */ "Keypad =", 855 /* 104 */ "F13", 856 /* 105 */ "F14", 857 /* 106 */ "F15", 858 /* 107 */ "F16", 859 /* 108 */ "F17", 860 /* 109 */ "F18", 861 /* 110 */ "F19", 862 /* 111 */ "F20", 863 /* 112 */ "F21", 864 /* 113 */ "F22", 865 /* 114 */ "F23", 866 /* 115 */ "F24", 867 /* 116 */ "Execute", 868 /* 117 */ "Help", 869 /* 118 */ "Menu", 870 /* 119 */ "Select", 871 /* 120 */ "Stop", 872 /* 121 */ "Again", 873 /* 122 */ "Undo", 874 /* 123 */ "Cut", 875 /* 124 */ "Copy", 876 /* 125 */ "Paste", 877 /* 126 */ "Find", 878 /* 127 */ "Mute", 879 /* 128 */ "VolumeUp", 880 /* 129 */ "VolumeDown", 881 /* 130 */ NULL, 882 /* 131 */ NULL, 883 /* 132 */ NULL, 884 /* 133 */ "Keypad ,", 885 /* 134 */ "Keypad = (AS400)", 886 /* 135 */ "International 1", 887 /* 136 */ "International 2", 888 /* 137 */ "International 3", 889 /* 138 */ "International 4", 890 /* 139 */ "International 5", 891 /* 140 */ "International 6", 892 /* 141 */ "International 7", 893 /* 142 */ "International 8", 894 /* 143 */ "International 9", 895 /* 144 */ "Language 1", 896 /* 145 */ "Language 2", 897 /* 146 */ "Language 3", 898 /* 147 */ "Language 4", 899 /* 148 */ "Language 5", 900 /* 149 */ "Language 6", 901 /* 150 */ "Language 7", 902 /* 151 */ "Language 8", 903 /* 152 */ "Language 9", 904 /* 153 */ "AltErase", 905 /* 154 */ "SysReq", 906 /* 155 */ "Cancel", 907 /* 156 */ "Clear", 908 /* 157 */ "Prior", 909 /* 158 */ "Return", 910 /* 159 */ "Separator", 911 /* 160 */ "Out", 912 /* 161 */ "Oper", 913 /* 162 */ "Clear / Again", 914 /* 163 */ "CrSel", 915 /* 164 */ "ExSel", 916 /* 165 */ NULL, 917 /* 166 */ NULL, 918 /* 167 */ NULL, 919 /* 168 */ NULL, 920 /* 169 */ NULL, 921 /* 170 */ NULL, 922 /* 171 */ NULL, 923 /* 172 */ NULL, 924 /* 173 */ NULL, 925 /* 174 */ NULL, 926 /* 175 */ NULL, 927 /* 176 */ "Keypad 00", 928 /* 177 */ "Keypad 000", 929 /* 178 */ "ThousandsSeparator", 930 /* 179 */ "DecimalSeparator", 931 /* 180 */ "CurrencyUnit", 932 /* 181 */ "CurrencySubUnit", 933 /* 182 */ "Keypad (", 934 /* 183 */ "Keypad )", 935 /* 184 */ "Keypad {", 936 /* 185 */ "Keypad }", 937 /* 186 */ "Keypad Tab", 938 /* 187 */ "Keypad Backspace", 939 /* 188 */ "Keypad A", 940 /* 189 */ "Keypad B", 941 /* 190 */ "Keypad C", 942 /* 191 */ "Keypad D", 943 /* 192 */ "Keypad E", 944 /* 193 */ "Keypad F", 945 /* 194 */ "Keypad XOR", 946 /* 195 */ "Keypad ^", 947 /* 196 */ "Keypad %", 948 /* 197 */ "Keypad <", 949 /* 198 */ "Keypad >", 950 /* 199 */ "Keypad &", 951 /* 200 */ "Keypad &&", 952 /* 201 */ "Keypad |", 953 /* 202 */ "Keypad ||", 954 /* 203 */ "Keypad :", 955 /* 204 */ "Keypad #", 956 /* 205 */ "Keypad Space", 957 /* 206 */ "Keypad @", 958 /* 207 */ "Keypad !", 959 /* 208 */ "Keypad MemStore", 960 /* 209 */ "Keypad MemRecall", 961 /* 210 */ "Keypad MemClear", 962 /* 211 */ "Keypad MemAdd", 963 /* 212 */ "Keypad MemSubtract", 964 /* 213 */ "Keypad MemMultiply", 965 /* 214 */ "Keypad MemDivide", 966 /* 215 */ "Keypad +/-", 967 /* 216 */ "Keypad Clear", 968 /* 217 */ "Keypad ClearEntry", 969 /* 218 */ "Keypad Binary", 970 /* 219 */ "Keypad Octal", 971 /* 220 */ "Keypad Decimal", 972 /* 221 */ "Keypad Hexadecimal", 973 /* 222 */ NULL, 974 /* 223 */ NULL, 975 /* 224 */ "Left Ctrl", 976 /* 225 */ "Left Shift", 977 /* 226 */ "Left Alt", 978 /* 227 */ "Left GUI", 979 /* 228 */ "Right Ctrl", 980 /* 229 */ "Right Shift", 981 /* 230 */ "Right Alt", 982 /* 231 */ "Right GUI", 983 /* 232 */ NULL, 984 /* 233 */ NULL, 985 /* 234 */ NULL, 986 /* 235 */ NULL, 987 /* 236 */ NULL, 988 /* 237 */ NULL, 989 /* 238 */ NULL, 990 /* 239 */ NULL, 991 /* 240 */ NULL, 992 /* 241 */ NULL, 993 /* 242 */ NULL, 994 /* 243 */ NULL, 995 /* 244 */ NULL, 996 /* 245 */ NULL, 997 /* 246 */ NULL, 998 /* 247 */ NULL, 999 /* 248 */ NULL, 1000 /* 249 */ NULL, 1001 /* 250 */ NULL, 1002 /* 251 */ NULL, 1003 /* 252 */ NULL, 1004 /* 253 */ NULL, 1005 /* 254 */ NULL, 1006 /* 255 */ NULL, 1007 /* 256 */ NULL, 1008 /* 257 */ "ModeSwitch", 1009 /* 258 */ "Sleep", 1010 /* 259 */ "Wake", 1011 /* 260 */ "ChannelUp", 1012 /* 261 */ "ChannelDown", 1013 /* 262 */ "MediaPlay", 1014 /* 263 */ "MediaPause", 1015 /* 264 */ "MediaRecord", 1016 /* 265 */ "MediaFastForward", 1017 /* 266 */ "MediaRewind", 1018 /* 267 */ "MediaTrackNext", 1019 /* 268 */ "MediaTrackPrevious", 1020 /* 269 */ "MediaStop", 1021 /* 270 */ "Eject", 1022 /* 271 */ "MediaPlayPause", 1023 /* 272 */ "MediaSelect", 1024 /* 273 */ "AC New", 1025 /* 274 */ "AC Open", 1026 /* 275 */ "AC Close", 1027 /* 276 */ "AC Exit", 1028 /* 277 */ "AC Save", 1029 /* 278 */ "AC Print", 1030 /* 279 */ "AC Properties", 1031 /* 280 */ "AC Search", 1032 /* 281 */ "AC Home", 1033 /* 282 */ "AC Back", 1034 /* 283 */ "AC Forward", 1035 /* 284 */ "AC Stop", 1036 /* 285 */ "AC Refresh", 1037 /* 286 */ "AC Bookmarks", 1038 /* 287 */ "SoftLeft", 1039 /* 288 */ "SoftRight", 1040 /* 289 */ "Call", 1041 /* 290 */ "EndCall", 1042}; 1043 1044static const char *SDL_extended_key_names[] = { 1045 "LeftTab", /* 0x01 SDLK_LEFT_TAB */ 1046 "Level5Shift", /* 0x02 SDLK_LEVEL5_SHIFT */ 1047 "MultiKeyCompose", /* 0x03 SDLK_MULTI_KEY_COMPOSE */ 1048 "Left Meta", /* 0x04 SDLK_LMETA */ 1049 "Right Meta", /* 0x05 SDLK_RMETA */ 1050 "Left Hyper", /* 0x06 SDLK_LHYPER */ 1051 "Right Hyper" /* 0x07 SDLK_RHYPER */ 1052}; 1053 1054bool SDL_SetScancodeName(SDL_Scancode scancode, const char *name) 1055{ 1056 CHECK_PARAM(((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { 1057 return SDL_InvalidParamError("scancode"); 1058 } 1059 1060 SDL_scancode_names[scancode] = name; 1061 return true; 1062} 1063 1064const char *SDL_GetScancodeName(SDL_Scancode scancode) 1065{ 1066 const char *name; 1067 1068 CHECK_PARAM(((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { 1069 SDL_InvalidParamError("scancode"); 1070 return ""; 1071 } 1072 1073 name = SDL_scancode_names[scancode]; 1074 if (!name) { 1075 name = ""; 1076 } 1077 // This is pointing to static memory or application managed memory 1078 return name; 1079} 1080 1081SDL_Scancode SDL_GetScancodeFromName(const char *name) 1082{ 1083 int i; 1084 1085 CHECK_PARAM(!name || !*name) { 1086 SDL_InvalidParamError("name"); 1087 return SDL_SCANCODE_UNKNOWN; 1088 } 1089 1090 for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) { 1091 if (!SDL_scancode_names[i]) { 1092 continue; 1093 } 1094 if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) { 1095 return (SDL_Scancode)i; 1096 } 1097 } 1098 1099 SDL_InvalidParamError("name"); 1100 return SDL_SCANCODE_UNKNOWN; 1101} 1102 1103const char *SDL_GetKeyName(SDL_Keycode key) 1104{ 1105 const bool uppercase = true; 1106 char name[8]; 1107 char *end; 1108 1109 if (key & SDLK_SCANCODE_MASK) { 1110 return SDL_GetScancodeName((SDL_Scancode)(key & ~SDLK_SCANCODE_MASK)); 1111 } 1112 1113 if (key & SDLK_EXTENDED_MASK) { 1114 const SDL_Keycode idx = (key & ~SDLK_EXTENDED_MASK); 1115 if (idx > 0 && (idx - 1) < SDL_arraysize(SDL_extended_key_names)) { 1116 return SDL_extended_key_names[idx - 1]; 1117 } 1118 1119 // Key out of name index bounds. 1120 SDL_InvalidParamError("key"); 1121 return ""; 1122 } 1123 1124 switch (key) { 1125 case SDLK_RETURN: 1126 return SDL_GetScancodeName(SDL_SCANCODE_RETURN); 1127 case SDLK_ESCAPE: 1128 return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE); 1129 case SDLK_BACKSPACE: 1130 return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE); 1131 case SDLK_TAB: 1132 return SDL_GetScancodeName(SDL_SCANCODE_TAB); 1133 case SDLK_SPACE: 1134 return SDL_GetScancodeName(SDL_SCANCODE_SPACE); 1135 case SDLK_DELETE: 1136 return SDL_GetScancodeName(SDL_SCANCODE_DELETE); 1137 default: 1138 if (uppercase) { 1139 // SDL_Keycode is defined as the unshifted key on the keyboard, 1140 // but the key name is defined as the letter printed on that key, 1141 // which is usually the shifted capital letter. 1142 if (key > 0x7F || (key >= 'a' && key <= 'z')) { 1143 SDL_Keymap *keymap = SDL_GetCurrentKeymap(false); 1144 SDL_Keymod modstate; 1145 SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate); 1146 if (scancode != SDL_SCANCODE_UNKNOWN && !(modstate & SDL_KMOD_SHIFT)) { 1147 SDL_Keycode capital = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_SHIFT); 1148 if (capital > 0x7F || (capital >= 'A' && capital <= 'Z')) { 1149 key = capital; 1150 } 1151 } 1152 } 1153 } 1154 1155 end = SDL_UCS4ToUTF8(key, name); 1156 *end = '\0'; 1157 return SDL_GetPersistentString(name); 1158 } 1159} 1160 1161SDL_Keycode SDL_GetKeyFromName(const char *name) 1162{ 1163 const bool uppercase = true; 1164 SDL_Keycode key; 1165 1166 // Check input 1167 if (!name) { 1168 return SDLK_UNKNOWN; 1169 } 1170 1171 // If it's a single UTF-8 character, then that's the keycode itself 1172 key = *(const unsigned char *)name; 1173 if (key >= 0xF0) { 1174 if (SDL_strlen(name) == 4) { 1175 int i = 0; 1176 key = (Uint16)(name[i] & 0x07) << 18; 1177 key |= (Uint16)(name[++i] & 0x3F) << 12; 1178 key |= (Uint16)(name[++i] & 0x3F) << 6; 1179 key |= (Uint16)(name[++i] & 0x3F); 1180 } else { 1181 key = SDLK_UNKNOWN; 1182 } 1183 } else if (key >= 0xE0) { 1184 if (SDL_strlen(name) == 3) { 1185 int i = 0; 1186 key = (Uint16)(name[i] & 0x0F) << 12; 1187 key |= (Uint16)(name[++i] & 0x3F) << 6; 1188 key |= (Uint16)(name[++i] & 0x3F); 1189 } else { 1190 key = SDLK_UNKNOWN; 1191 } 1192 } else if (key >= 0xC0) { 1193 if (SDL_strlen(name) == 2) { 1194 int i = 0; 1195 key = (Uint16)(name[i] & 0x1F) << 6; 1196 key |= (Uint16)(name[++i] & 0x3F); 1197 } else { 1198 key = SDLK_UNKNOWN; 1199 } 1200 } else { 1201 if (SDL_strlen(name) != 1) { 1202 key = SDLK_UNKNOWN; 1203 } 1204 } 1205 1206 if (key != SDLK_UNKNOWN) { 1207 if (uppercase) { 1208 // SDL_Keycode is defined as the unshifted key on the keyboard, 1209 // but the key name is defined as the letter printed on that key, 1210 // which is usually the shifted capital letter. 1211 SDL_Keymap *keymap = SDL_GetCurrentKeymap(false); 1212 SDL_Keymod modstate; 1213 SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate); 1214 if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & (SDL_KMOD_SHIFT | SDL_KMOD_CAPS))) { 1215 key = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_NONE); 1216 } 1217 } 1218 return key; 1219 } 1220 1221 // Check the extended key names 1222 for (SDL_Keycode i = 0; i < SDL_arraysize(SDL_extended_key_names); ++i) { 1223 if (SDL_strcasecmp(name, SDL_extended_key_names[i]) == 0) { 1224 return (i + 1) | SDLK_EXTENDED_MASK; 1225 } 1226 } 1227 1228 return SDL_GetKeyFromScancode(SDL_GetScancodeFromName(name), SDL_KMOD_NONE, false); 1229} 1230
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.