src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 12 Aug 2007 05:48:51 +0000
changeset 2229 22342048bcb8
parent 2129 047245361002
child 2268 4baee598306d
permissions -rw-r--r--
Fixed crash if conversion fails. Use ISO name for Latin-1
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* General keyboard handling code for SDL */
    25 
    26 #include "SDL_timer.h"
    27 #include "SDL_events.h"
    28 #include "SDL_events_c.h"
    29 #include "SDL_sysevents.h"
    30 
    31 
    32 /* Global keyboard information */
    33 int SDL_TranslateUNICODE = 0;
    34 static int SDL_num_keyboards;
    35 static int SDL_current_keyboard;
    36 static SDL_Keyboard **SDL_keyboards;
    37 
    38 static const char *SDL_keynames[SDLK_LAST];     /* Array of keycode names */
    39 
    40 /* Public functions */
    41 int
    42 SDL_KeyboardInit(void)
    43 {
    44     int i;
    45 
    46     /* Set default mode of UNICODE translation */
    47     SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
    48 
    49     /* Initialize the tables */
    50     for (i = 0; i < SDL_arraysize(SDL_keynames); ++i) {
    51         switch (i) {
    52         case SDLK_BACKSPACE:
    53             SDL_keynames[i] = "backspace";
    54             break;
    55         case SDLK_TAB:
    56             SDL_keynames[i] = "tab";
    57             break;
    58         case SDLK_CLEAR:
    59             SDL_keynames[i] = "clear";
    60             break;
    61         case SDLK_RETURN:
    62             SDL_keynames[i] = "return";
    63             break;
    64         case SDLK_PAUSE:
    65             SDL_keynames[i] = "pause";
    66             break;
    67         case SDLK_ESCAPE:
    68             SDL_keynames[i] = "escape";
    69             break;
    70         case SDLK_SPACE:
    71             SDL_keynames[i] = "space";
    72             break;
    73 
    74         case SDLK_KP0:
    75             SDL_keynames[i] = "[0]";
    76             break;
    77         case SDLK_KP1:
    78             SDL_keynames[i] = "[1]";
    79             break;
    80         case SDLK_KP2:
    81             SDL_keynames[i] = "[2]";
    82             break;
    83         case SDLK_KP3:
    84             SDL_keynames[i] = "[3]";
    85             break;
    86         case SDLK_KP4:
    87             SDL_keynames[i] = "[4]";
    88             break;
    89         case SDLK_KP5:
    90             SDL_keynames[i] = "[5]";
    91             break;
    92         case SDLK_KP6:
    93             SDL_keynames[i] = "[6]";
    94             break;
    95         case SDLK_KP7:
    96             SDL_keynames[i] = "[7]";
    97             break;
    98         case SDLK_KP8:
    99             SDL_keynames[i] = "[8]";
   100             break;
   101         case SDLK_KP9:
   102             SDL_keynames[i] = "[9]";
   103             break;
   104         case SDLK_KP_PERIOD:
   105             SDL_keynames[i] = "[.]";
   106             break;
   107         case SDLK_KP_DIVIDE:
   108             SDL_keynames[i] = "[/]";
   109             break;
   110         case SDLK_KP_MULTIPLY:
   111             SDL_keynames[i] = "[*]";
   112             break;
   113         case SDLK_KP_MINUS:
   114             SDL_keynames[i] = "[-]";
   115             break;
   116         case SDLK_KP_PLUS:
   117             SDL_keynames[i] = "[+]";
   118             break;
   119         case SDLK_KP_ENTER:
   120             SDL_keynames[i] = "enter";
   121             break;
   122         case SDLK_KP_EQUALS:
   123             SDL_keynames[i] = "equals";
   124             break;
   125 
   126         case SDLK_UP:
   127             SDL_keynames[i] = "up";
   128             break;
   129         case SDLK_DOWN:
   130             SDL_keynames[i] = "down";
   131             break;
   132         case SDLK_RIGHT:
   133             SDL_keynames[i] = "right";
   134             break;
   135         case SDLK_LEFT:
   136             SDL_keynames[i] = "left";
   137             break;
   138         case SDLK_INSERT:
   139             SDL_keynames[i] = "insert";
   140             break;
   141         case SDLK_HOME:
   142             SDL_keynames[i] = "home";
   143             break;
   144         case SDLK_END:
   145             SDL_keynames[i] = "end";
   146             break;
   147         case SDLK_PAGEUP:
   148             SDL_keynames[i] = "page up";
   149             break;
   150         case SDLK_PAGEDOWN:
   151             SDL_keynames[i] = "page down";
   152             break;
   153 
   154         case SDLK_F1:
   155             SDL_keynames[i] = "f1";
   156             break;
   157         case SDLK_F2:
   158             SDL_keynames[i] = "f2";
   159             break;
   160         case SDLK_F3:
   161             SDL_keynames[i] = "f3";
   162             break;
   163         case SDLK_F4:
   164             SDL_keynames[i] = "f4";
   165             break;
   166         case SDLK_F5:
   167             SDL_keynames[i] = "f5";
   168             break;
   169         case SDLK_F6:
   170             SDL_keynames[i] = "f6";
   171             break;
   172         case SDLK_F7:
   173             SDL_keynames[i] = "f7";
   174             break;
   175         case SDLK_F8:
   176             SDL_keynames[i] = "f8";
   177             break;
   178         case SDLK_F9:
   179             SDL_keynames[i] = "f9";
   180             break;
   181         case SDLK_F10:
   182             SDL_keynames[i] = "f10";
   183             break;
   184         case SDLK_F11:
   185             SDL_keynames[i] = "f11";
   186             break;
   187         case SDLK_F12:
   188             SDL_keynames[i] = "f12";
   189             break;
   190         case SDLK_F13:
   191             SDL_keynames[i] = "f13";
   192             break;
   193         case SDLK_F14:
   194             SDL_keynames[i] = "f14";
   195             break;
   196         case SDLK_F15:
   197             SDL_keynames[i] = "f15";
   198             break;
   199 
   200         case SDLK_NUMLOCK:
   201             SDL_keynames[i] = "numlock";
   202             break;
   203         case SDLK_CAPSLOCK:
   204             SDL_keynames[i] = "caps lock";
   205             break;
   206         case SDLK_SCROLLOCK:
   207             SDL_keynames[i] = "scroll lock";
   208             break;
   209         case SDLK_RSHIFT:
   210             SDL_keynames[i] = "right shift";
   211             break;
   212         case SDLK_LSHIFT:
   213             SDL_keynames[i] = "left shift";
   214             break;
   215         case SDLK_RCTRL:
   216             SDL_keynames[i] = "right ctrl";
   217             break;
   218         case SDLK_LCTRL:
   219             SDL_keynames[i] = "left ctrl";
   220             break;
   221         case SDLK_RALT:
   222             SDL_keynames[i] = "right alt";
   223             break;
   224         case SDLK_LALT:
   225             SDL_keynames[i] = "left alt";
   226             break;
   227         case SDLK_RMETA:
   228             SDL_keynames[i] = "right meta";
   229             break;
   230         case SDLK_LMETA:
   231             SDL_keynames[i] = "left meta";
   232             break;
   233         case SDLK_LSUPER:
   234             SDL_keynames[i] = "left super";     /* "Windows" keys */
   235             break;
   236         case SDLK_RSUPER:
   237             SDL_keynames[i] = "right super";
   238             break;
   239         case SDLK_MODE:
   240             SDL_keynames[i] = "alt gr";
   241             break;
   242         case SDLK_COMPOSE:
   243             SDL_keynames[i] = "compose";
   244             break;
   245 
   246         case SDLK_HELP:
   247             SDL_keynames[i] = "help";
   248             break;
   249         case SDLK_PRINT:
   250             SDL_keynames[i] = "print screen";
   251             break;
   252         case SDLK_SYSREQ:
   253             SDL_keynames[i] = "sys req";
   254             break;
   255         case SDLK_BREAK:
   256             SDL_keynames[i] = "break";
   257             break;
   258         case SDLK_MENU:
   259             SDL_keynames[i] = "menu";
   260             break;
   261         case SDLK_POWER:
   262             SDL_keynames[i] = "power";
   263             break;
   264         case SDLK_EURO:
   265             SDL_keynames[i] = "euro";
   266             break;
   267         case SDLK_UNDO:
   268             SDL_keynames[i] = "undo";
   269             break;
   270 
   271         default:
   272             SDL_keynames[i] = NULL;
   273             break;
   274         }
   275     }
   276 
   277     /* Done.  Whew. */
   278     return (0);
   279 }
   280 
   281 SDL_Keyboard *
   282 SDL_GetKeyboard(int index)
   283 {
   284     if (index < 0 || index >= SDL_num_keyboards) {
   285         return NULL;
   286     }
   287     return SDL_keyboards[index];
   288 }
   289 
   290 int
   291 SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
   292 {
   293     SDL_Keyboard **keyboards;
   294 
   295     /* Add the keyboard to the list of keyboards */
   296     if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
   297         keyboards =
   298             (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
   299                                           (SDL_num_keyboards +
   300                                            1) * sizeof(*keyboards));
   301         if (!keyboards) {
   302             SDL_OutOfMemory();
   303             return -1;
   304         }
   305 
   306         SDL_keyboards = keyboards;
   307         index = SDL_num_keyboards++;
   308     }
   309     SDL_keyboards[index] =
   310         (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
   311     if (!SDL_keyboards[index]) {
   312         SDL_OutOfMemory();
   313         return -1;
   314     }
   315     *SDL_keyboards[index] = *keyboard;
   316 
   317     return index;
   318 }
   319 
   320 void
   321 SDL_DelKeyboard(int index)
   322 {
   323     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   324 
   325     if (!keyboard) {
   326         return;
   327     }
   328 
   329     if (keyboard->FreeKeyboard) {
   330         keyboard->FreeKeyboard(keyboard);
   331     }
   332     SDL_free(keyboard);
   333 
   334     SDL_keyboards[index] = NULL;
   335 }
   336 
   337 void
   338 SDL_ResetKeyboard(int index)
   339 {
   340     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   341     SDLKey key;
   342 
   343     if (!keyboard) {
   344         return;
   345     }
   346 
   347     for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
   348         if (keyboard->keystate[key] == SDL_PRESSED) {
   349             SDL_SendKeyboardKey(index, SDL_RELEASED, 0, key);
   350         }
   351     }
   352 }
   353 
   354 void
   355 SDL_KeyboardQuit(void)
   356 {
   357     int i;
   358 
   359     for (i = 0; i < SDL_num_keyboards; ++i) {
   360         SDL_DelKeyboard(i);
   361     }
   362     SDL_num_keyboards = 0;
   363     SDL_current_keyboard = 0;
   364 
   365     if (SDL_keyboards) {
   366         SDL_free(SDL_keyboards);
   367         SDL_keyboards = NULL;
   368     }
   369 }
   370 
   371 int
   372 SDL_GetNumKeyboards(void)
   373 {
   374     return SDL_num_keyboards;
   375 }
   376 
   377 int
   378 SDL_SelectKeyboard(int index)
   379 {
   380     if (index >= 0 && index < SDL_num_keyboards) {
   381         SDL_current_keyboard = index;
   382     }
   383     return SDL_current_keyboard;
   384 }
   385 
   386 int
   387 SDL_EnableUNICODE(int enable)
   388 {
   389     int old_mode;
   390 
   391     old_mode = SDL_TranslateUNICODE;
   392     if (enable >= 0) {
   393         SDL_TranslateUNICODE = enable;
   394     }
   395     return (old_mode);
   396 }
   397 
   398 Uint8 *
   399 SDL_GetKeyState(int *numkeys)
   400 {
   401     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   402 
   403     if (numkeys != (int *) 0) {
   404         *numkeys = SDLK_LAST;
   405     }
   406 
   407     if (!keyboard) {
   408         return NULL;
   409     }
   410     return keyboard->keystate;
   411 }
   412 
   413 SDLMod
   414 SDL_GetModState(void)
   415 {
   416     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   417 
   418     if (!keyboard) {
   419         return KMOD_NONE;
   420     }
   421     return keyboard->modstate;
   422 }
   423 
   424 void
   425 SDL_SetModState(SDLMod modstate)
   426 {
   427     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   428 
   429     if (!keyboard) {
   430         return;
   431     }
   432     keyboard->modstate = modstate;
   433 }
   434 
   435 const char *
   436 SDL_GetKeyName(SDLKey key)
   437 {
   438     const char *keyname;
   439 
   440     if (key < SDL_arraysize(SDL_keynames)) {
   441         keyname = SDL_keynames[key];
   442     } else {
   443         keyname = NULL;
   444     }
   445     if (keyname == NULL) {
   446         if (key < 256) {
   447             static char temp[4];
   448             char *cvt;
   449             temp[0] = (char) key;
   450             temp[1] = '\0';
   451             cvt = SDL_iconv_string("UTF-8", "ISO-8859-1", temp, 1);
   452             if (cvt) {
   453                 SDL_strlcpy(temp, cvt, SDL_arraysize(temp));
   454                 SDL_free(cvt);
   455             }
   456             keyname = temp;
   457         } else {
   458             keyname = "unknown key";
   459         }
   460     }
   461     return keyname;
   462 }
   463 
   464 void
   465 SDL_SetKeyboardFocus(int index, SDL_WindowID windowID)
   466 {
   467     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   468     int i;
   469     SDL_bool focus;
   470 
   471     if (!keyboard || (keyboard->focus == windowID)) {
   472         return;
   473     }
   474 
   475     /* See if the current window has lost focus */
   476     if (keyboard->focus) {
   477         focus = SDL_FALSE;
   478         for (i = 0; i < SDL_num_keyboards; ++i) {
   479             SDL_Keyboard *check;
   480             if (i != index) {
   481                 check = SDL_GetKeyboard(i);
   482                 if (check && check->focus == keyboard->focus) {
   483                     focus = SDL_TRUE;
   484                     break;
   485                 }
   486             }
   487         }
   488         if (!focus) {
   489             SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
   490                                 0, 0);
   491         }
   492     }
   493 
   494     keyboard->focus = windowID;
   495 
   496     if (keyboard->focus) {
   497         focus = SDL_FALSE;
   498         for (i = 0; i < SDL_num_keyboards; ++i) {
   499             SDL_Keyboard *check;
   500             if (i != index) {
   501                 check = SDL_GetKeyboard(i);
   502                 if (check && check->focus == keyboard->focus) {
   503                     focus = SDL_TRUE;
   504                     break;
   505                 }
   506             }
   507         }
   508         if (!focus) {
   509             SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
   510                                 0, 0);
   511         }
   512     }
   513 }
   514 
   515 int
   516 SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode, SDLKey key)
   517 {
   518     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   519     int posted;
   520     Uint16 modstate;
   521     Uint8 type;
   522 
   523     if (!keyboard) {
   524         return 0;
   525     }
   526 #if 0
   527     printf("The '%s' key has been %s\n", SDL_GetKeyName(key),
   528            state == SDL_PRESSED ? "pressed" : "released");
   529 #endif
   530     if (state == SDL_PRESSED) {
   531         modstate = keyboard->modstate;
   532         switch (key) {
   533         case SDLK_UNKNOWN:
   534             break;
   535         case SDLK_NUMLOCK:
   536             keyboard->modstate ^= KMOD_NUM;
   537             break;
   538         case SDLK_CAPSLOCK:
   539             keyboard->modstate ^= KMOD_CAPS;
   540             break;
   541         case SDLK_LCTRL:
   542             keyboard->modstate |= KMOD_LCTRL;
   543             break;
   544         case SDLK_RCTRL:
   545             keyboard->modstate |= KMOD_RCTRL;
   546             break;
   547         case SDLK_LSHIFT:
   548             keyboard->modstate |= KMOD_LSHIFT;
   549             break;
   550         case SDLK_RSHIFT:
   551             keyboard->modstate |= KMOD_RSHIFT;
   552             break;
   553         case SDLK_LALT:
   554             keyboard->modstate |= KMOD_LALT;
   555             break;
   556         case SDLK_RALT:
   557             keyboard->modstate |= KMOD_RALT;
   558             break;
   559         case SDLK_LMETA:
   560             keyboard->modstate |= KMOD_LMETA;
   561             break;
   562         case SDLK_RMETA:
   563             keyboard->modstate |= KMOD_RMETA;
   564             break;
   565         case SDLK_MODE:
   566             keyboard->modstate |= KMOD_MODE;
   567             break;
   568         default:
   569             break;
   570         }
   571     } else {
   572         switch (key) {
   573         case SDLK_UNKNOWN:
   574             break;
   575         case SDLK_NUMLOCK:
   576         case SDLK_CAPSLOCK:
   577             break;
   578         case SDLK_LCTRL:
   579             keyboard->modstate &= ~KMOD_LCTRL;
   580             break;
   581         case SDLK_RCTRL:
   582             keyboard->modstate &= ~KMOD_RCTRL;
   583             break;
   584         case SDLK_LSHIFT:
   585             keyboard->modstate &= ~KMOD_LSHIFT;
   586             break;
   587         case SDLK_RSHIFT:
   588             keyboard->modstate &= ~KMOD_RSHIFT;
   589             break;
   590         case SDLK_LALT:
   591             keyboard->modstate &= ~KMOD_LALT;
   592             break;
   593         case SDLK_RALT:
   594             keyboard->modstate &= ~KMOD_RALT;
   595             break;
   596         case SDLK_LMETA:
   597             keyboard->modstate &= ~KMOD_LMETA;
   598             break;
   599         case SDLK_RMETA:
   600             keyboard->modstate &= ~KMOD_RMETA;
   601             break;
   602         case SDLK_MODE:
   603             keyboard->modstate &= ~KMOD_MODE;
   604             break;
   605         default:
   606             break;
   607         }
   608         modstate = keyboard->modstate;
   609     }
   610 
   611     /* Figure out what type of event this is */
   612     switch (state) {
   613     case SDL_PRESSED:
   614         type = SDL_KEYDOWN;
   615         break;
   616     case SDL_RELEASED:
   617         type = SDL_KEYUP;
   618         break;
   619     default:
   620         /* Invalid state -- bail */
   621         return 0;
   622     }
   623 
   624     if (key != SDLK_UNKNOWN) {
   625         /* Drop events that don't change state */
   626         if (keyboard->keystate[key] == state) {
   627 #if 0
   628             printf("Keyboard event didn't change state - dropped!\n");
   629 #endif
   630             return 0;
   631         }
   632 
   633         /* Update internal keyboard state */
   634         keyboard->keystate[key] = state;
   635     }
   636 
   637     /* Post the event, if desired */
   638     posted = 0;
   639     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   640         SDL_Event event;
   641         event.key.type = type;
   642         event.key.which = (Uint8) index;
   643         event.key.state = state;
   644         event.key.keysym.scancode = scancode;
   645         event.key.keysym.sym = (Uint16) key;
   646         event.key.keysym.mod = modstate;
   647         event.key.keysym.unicode = 0;
   648         event.key.windowID = keyboard->focus;
   649         posted = (SDL_PushEvent(&event) > 0);
   650     }
   651     return (posted);
   652 }
   653 
   654 int
   655 SDL_SendKeyboardText(int index, const char *text)
   656 {
   657     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   658     int posted;
   659 
   660     if (!keyboard) {
   661         return 0;
   662     }
   663 
   664     /* Post the event, if desired */
   665     posted = 0;
   666     if (SDL_ProcessEvents[SDL_TEXTINPUT] == SDL_ENABLE) {
   667         SDL_Event event;
   668         event.text.type = SDL_TEXTINPUT;
   669         event.text.which = (Uint8) index;
   670         SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
   671         event.text.windowID = keyboard->focus;
   672         posted = (SDL_PushEvent(&event) > 0);
   673     }
   674     return (posted);
   675 }
   676 
   677 /* vi: set ts=4 sw=4 expandtab: */