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