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