src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 10 Jun 2006 09:11:59 +0000
branchSDL-1.3
changeset 1673 624e1412fbba
parent 1670 eef792d31de8
child 1674 7688a73b25b1
permissions -rw-r--r--
Keyboard code update in progress
     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 static int SDL_num_keyboards;
    34 static int SDL_current_keyboard;
    35 static SDL_Keyboard **SDL_keyboards;
    36 int SDL_TranslateUNICODE = 0;
    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     /* Set default keyboard repeat setting */
    50     SDL_EnableKeyRepeat(0, 0);
    51 
    52     /* Initialize the tables */
    53     for (i = 0; i < SDL_arraysize(SDL_keynames); ++i) {
    54         switch (i) {
    55         case SDLK_BACKSPACE:
    56             SDL_keynames[i] = "backspace";
    57             break;
    58         case SDLK_TAB:
    59             SDL_keynames[i] = "tab";
    60             break;
    61         case SDLK_CLEAR:
    62             SDL_keynames[i] = "clear";
    63             break;
    64         case SDLK_RETURN:
    65             SDL_keynames[i] = "return";
    66             break;
    67         case SDLK_PAUSE:
    68             SDL_keynames[i] = "pause";
    69             break;
    70         case SDLK_ESCAPE:
    71             SDL_keynames[i] = "escape";
    72             break;
    73         case SDLK_SPACE:
    74             SDL_keynames[i] = "space";
    75             break;
    76 
    77         case SDLK_KP0:
    78             SDL_keynames[i] = "[0]";
    79             break;
    80         case SDLK_KP1:
    81             SDL_keynames[i] = "[1]";
    82             break;
    83         case SDLK_KP2:
    84             SDL_keynames[i] = "[2]";
    85             break;
    86         case SDLK_KP3:
    87             SDL_keynames[i] = "[3]";
    88             break;
    89         case SDLK_KP4:
    90             SDL_keynames[i] = "[4]";
    91             break;
    92         case SDLK_KP5:
    93             SDL_keynames[i] = "[5]";
    94             break;
    95         case SDLK_KP6:
    96             SDL_keynames[i] = "[6]";
    97             break;
    98         case SDLK_KP7:
    99             SDL_keynames[i] = "[7]";
   100             break;
   101         case SDLK_KP8:
   102             SDL_keynames[i] = "[8]";
   103             break;
   104         case SDLK_KP9:
   105             SDL_keynames[i] = "[9]";
   106             break;
   107         case SDLK_KP_PERIOD:
   108             SDL_keynames[i] = "[.]";
   109             break;
   110         case SDLK_KP_DIVIDE:
   111             SDL_keynames[i] = "[/]";
   112             break;
   113         case SDLK_KP_MULTIPLY:
   114             SDL_keynames[i] = "[*]";
   115             break;
   116         case SDLK_KP_MINUS:
   117             SDL_keynames[i] = "[-]";
   118             break;
   119         case SDLK_KP_PLUS:
   120             SDL_keynames[i] = "[+]";
   121             break;
   122         case SDLK_KP_ENTER:
   123             SDL_keynames[i] = "enter";
   124             break;
   125         case SDLK_KP_EQUALS:
   126             SDL_keynames[i] = "equals";
   127             break;
   128 
   129         case SDLK_UP:
   130             SDL_keynames[i] = "up";
   131             break;
   132         case SDLK_DOWN:
   133             SDL_keynames[i] = "down";
   134             break;
   135         case SDLK_RIGHT:
   136             SDL_keynames[i] = "right";
   137             break;
   138         case SDLK_LEFT:
   139             SDL_keynames[i] = "left";
   140             break;
   141         case SDLK_DOWN:
   142             SDL_keynames[i] = "down";
   143             break;
   144         case SDLK_INSERT:
   145             SDL_keynames[i] = "insert";
   146             break;
   147         case SDLK_HOME:
   148             SDL_keynames[i] = "home";
   149             break;
   150         case SDLK_END:
   151             SDL_keynames[i] = "end";
   152             break;
   153         case SDLK_PAGEUP:
   154             SDL_keynames[i] = "page up";
   155             break;
   156         case SDLK_PAGEDOWN:
   157             SDL_keynames[i] = "page down";
   158             break;
   159 
   160         case SDLK_F1:
   161             SDL_keynames[i] = "f1";
   162             break;
   163         case SDLK_F2:
   164             SDL_keynames[i] = "f2";
   165             break;
   166         case SDLK_F3:
   167             SDL_keynames[i] = "f3";
   168             break;
   169         case SDLK_F4:
   170             SDL_keynames[i] = "f4";
   171             break;
   172         case SDLK_F5:
   173             SDL_keynames[i] = "f5";
   174             break;
   175         case SDLK_F6:
   176             SDL_keynames[i] = "f6";
   177             break;
   178         case SDLK_F7:
   179             SDL_keynames[i] = "f7";
   180             break;
   181         case SDLK_F8:
   182             SDL_keynames[i] = "f8";
   183             break;
   184         case SDLK_F9:
   185             SDL_keynames[i] = "f9";
   186             break;
   187         case SDLK_F10:
   188             SDL_keynames[i] = "f10";
   189             break;
   190         case SDLK_F11:
   191             SDL_keynames[i] = "f11";
   192             break;
   193         case SDLK_F12:
   194             SDL_keynames[i] = "f12";
   195             break;
   196         case SDLK_F13:
   197             SDL_keynames[i] = "f13";
   198             break;
   199         case SDLK_F14:
   200             SDL_keynames[i] = "f14";
   201             break;
   202         case SDLK_F15:
   203             SDL_keynames[i] = "f15";
   204             break;
   205 
   206         case SDLK_NUMLOCK:
   207             SDL_keynames[i] = "numlock";
   208             break;
   209         case SDLK_CAPSLOCK:
   210             SDL_keynames[i] = "caps lock";
   211             break;
   212         case SDLK_SCROLLOCK:
   213             SDL_keynames[i] = "scroll lock";
   214             break;
   215         case SDLK_RSHIFT:
   216             SDL_keynames[i] = "right shift";
   217             break;
   218         case SDLK_LSHIFT:
   219             SDL_keynames[i] = "left shift";
   220             break;
   221         case SDLK_RCTRL:
   222             SDL_keynames[i] = "right ctrl";
   223             break;
   224         case SDLK_LCTRL:
   225             SDL_keynames[i] = "left ctrl";
   226             break;
   227         case SDLK_RALT:
   228             SDL_keynames[i] = "right alt";
   229             break;
   230         case SDLK_LALT:
   231             SDL_keynames[i] = "left alt";
   232             break;
   233         case SDLK_RMETA:
   234             SDL_keynames[i] = "right meta";
   235             break;
   236         case SDLK_LMETA:
   237             SDL_keynames[i] = "left meta";
   238             break;
   239         case SDLK_LSUPER:
   240             SDL_keynames[i] = "left super";     /* "Windows" keys */
   241             break;
   242         case SDLK_RSUPER:
   243             SDL_keynames[i] = "right super";
   244             break;
   245         case SDLK_MODE:
   246             SDL_keynames[i] = "alt gr";
   247             break;
   248         case SDLK_COMPOSE:
   249             SDL_keynames[i] = "compose";
   250             break;
   251 
   252         case SDLK_HELP:
   253             SDL_keynames[i] = "help";
   254             break;
   255         case SDLK_PRINT:
   256             SDL_keynames[i] = "print screen";
   257             break;
   258         case SDLK_SYSREQ:
   259             SDL_keynames[i] = "sys req";
   260             break;
   261         case SDLK_BREAK:
   262             SDL_keynames[i] = "break";
   263             break;
   264         case SDLK_MENU:
   265             SDL_keynames[i] = "menu";
   266             break;
   267         case SDLK_POWER:
   268             SDL_keynames[i] = "power";
   269             break;
   270         case SDLK_EURO:
   271             SDL_keynames[i] = "euro";
   272             break;
   273         case SDLK_UNDO:
   274             SDL_keynames[i] = "undo";
   275             break;
   276 
   277         default:
   278             SDL_keynames[i] = NULL;
   279             break;
   280         }
   281     }
   282 
   283     /* Done.  Whew. */
   284     return (0);
   285 }
   286 
   287 SDL_Keyboard *
   288 SDL_GetKeyboard(int index)
   289 {
   290     if (index < 0 || index >= SDL_num_keyboards) {
   291         return NULL;
   292     }
   293     return SDL_keyboards[index];
   294 }
   295 
   296 int
   297 SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
   298 {
   299     SDL_Keyboard **keyboards;
   300     SDL_Cursor *cursor;
   301     int selected_keyboard;
   302 
   303     /* Add the keyboard to the list of keyboards */
   304     if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
   305         keyboards =
   306             (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
   307                                           (SDL_num_keyboards +
   308                                            1) * sizeof(*keyboards));
   309         if (!keyboards) {
   310             SDL_OutOfMemory();
   311             return -1;
   312         }
   313 
   314         SDL_keyboards = keyboards;
   315         index = SDL_num_keyboards++;
   316     }
   317     SDL_keyboards[index] =
   318         (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
   319     if (!SDL_keyboards[index]) {
   320         SDL_OutOfMemory();
   321         return -1;
   322     }
   323     *SDL_keyboards[index] = *keyboard;
   324 
   325     return index;
   326 }
   327 
   328 void
   329 SDL_DelKeyboard(int index)
   330 {
   331     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   332 
   333     if (!keyboard) {
   334         return;
   335     }
   336 
   337     if (keyboard->FreeKeyboard) {
   338         keyboard->FreeKeyboard(keyboard);
   339     }
   340     SDL_free(keyboard);
   341 
   342     SDL_keyboards[index] = NULL;
   343 }
   344 
   345 void
   346 SDL_ResetKeyboard(int index)
   347 {
   348     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   349     SDL_keysym keysym;
   350     SDLKey key;
   351 
   352     if (!keyboard) {
   353         return;
   354     }
   355 
   356     SDL_memset(&keysym, 0, (sizeof keysym));
   357     for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
   358         if (keyboard->keystate[key] == SDL_PRESSED) {
   359             keysym.sym = key;
   360             SDL_SendKeyboardKey(index, SDL_RELEASED, &keysym);
   361         }
   362     }
   363     keyboard->keyrepeat.timestamp = 0;
   364 }
   365 
   366 void
   367 SDL_KeyboardQuit(void)
   368 {
   369     int i;
   370 
   371     for (i = 0; i < SDL_num_keyboards; ++i) {
   372         SDL_DelKeyboard(i);
   373     }
   374     SDL_num_keyboards = 0;
   375     SDL_current_keyboard = 0;
   376 
   377     if (SDL_keyboards) {
   378         SDL_free(SDL_keyboards);
   379         SDL_keyboards = NULL;
   380     }
   381 }
   382 
   383 int
   384 SDL_GetNumKeyboards(void)
   385 {
   386     return SDL_num_keyboards;
   387 }
   388 
   389 int
   390 SDL_SelectKeyboard(int index)
   391 {
   392     if (index >= 0 && index < SDL_num_keyboards) {
   393         SDL_current_keyboard = index;
   394     }
   395     return SDL_current_keyboard;
   396 }
   397 
   398 int
   399 SDL_EnableUNICODE(int enable)
   400 {
   401     int old_mode;
   402 
   403     old_mode = SDL_TranslateUNICODE;
   404     if (enable >= 0) {
   405         SDL_TranslateUNICODE = enable;
   406     }
   407     return (old_mode);
   408 }
   409 
   410 Uint8 *
   411 SDL_GetKeyState(int *numkeys)
   412 {
   413     if (numkeys != (int *) 0)
   414         *numkeys = SDLK_LAST;
   415     return (SDL_KeyState);
   416 }
   417 
   418 SDLMod
   419 SDL_GetModState(void)
   420 {
   421     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   422 
   423     if (!keyboard) {
   424         return KMOD_NONE;
   425     }
   426     return keyboard->modstate;
   427 }
   428 
   429 void
   430 SDL_SetModState(SDLMod modstate)
   431 {
   432     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   433 
   434     if (!keyboard) {
   435         return;
   436     }
   437     keyboard->modstate = modstate;
   438 }
   439 
   440 const char *
   441 SDL_GetKeyName(SDLKey key)
   442 {
   443     const char *keyname;
   444 
   445     keyname = keynames[key];
   446     if (keyname == NULL) {
   447         if (key < 256) {
   448             static char temp[4];
   449           FIXME:Convert to UTF - 8 keyname = temp;
   450         } else {
   451             keyname = "unknown key";
   452         }
   453     }
   454     return keyname;
   455 }
   456 
   457 /* These are global for SDL_eventloop.c */
   458 int
   459 SDL_SendKeyboardKey(int index, Uint8 state, const SDL_keysym * keysym)
   460 {
   461     SDL_Event event;
   462     int posted, repeatable;
   463     Uint16 modstate;
   464 
   465     SDL_memset(&event, 0, sizeof(event));
   466 
   467 #if 0
   468     printf("The '%s' key has been %s\n", SDL_GetKeyName(keysym->sym),
   469            state == SDL_PRESSED ? "pressed" : "released");
   470 #endif
   471     /* Set up the keysym */
   472     modstate = (Uint16) SDL_ModState;
   473 
   474     repeatable = 0;
   475 
   476     if (state == SDL_PRESSED) {
   477         keysym->mod = (SDLMod) modstate;
   478         switch (keysym->sym) {
   479         case SDLK_UNKNOWN:
   480             break;
   481         case SDLK_NUMLOCK:
   482             modstate ^= KMOD_NUM;
   483             if (!(modstate & KMOD_NUM))
   484                 state = SDL_RELEASED;
   485             keysym->mod = (SDLMod) modstate;
   486             break;
   487         case SDLK_CAPSLOCK:
   488             modstate ^= KMOD_CAPS;
   489             if (!(modstate & KMOD_CAPS))
   490                 state = SDL_RELEASED;
   491             keysym->mod = (SDLMod) modstate;
   492             break;
   493         case SDLK_LCTRL:
   494             modstate |= KMOD_LCTRL;
   495             break;
   496         case SDLK_RCTRL:
   497             modstate |= KMOD_RCTRL;
   498             break;
   499         case SDLK_LSHIFT:
   500             modstate |= KMOD_LSHIFT;
   501             break;
   502         case SDLK_RSHIFT:
   503             modstate |= KMOD_RSHIFT;
   504             break;
   505         case SDLK_LALT:
   506             modstate |= KMOD_LALT;
   507             break;
   508         case SDLK_RALT:
   509             modstate |= KMOD_RALT;
   510             break;
   511         case SDLK_LMETA:
   512             modstate |= KMOD_LMETA;
   513             break;
   514         case SDLK_RMETA:
   515             modstate |= KMOD_RMETA;
   516             break;
   517         case SDLK_MODE:
   518             modstate |= KMOD_MODE;
   519             break;
   520         default:
   521             repeatable = 1;
   522             break;
   523         }
   524     } else {
   525         switch (keysym->sym) {
   526         case SDLK_UNKNOWN:
   527             break;
   528         case SDLK_NUMLOCK:
   529         case SDLK_CAPSLOCK:
   530             /* Only send keydown events */
   531             return (0);
   532         case SDLK_LCTRL:
   533             modstate &= ~KMOD_LCTRL;
   534             break;
   535         case SDLK_RCTRL:
   536             modstate &= ~KMOD_RCTRL;
   537             break;
   538         case SDLK_LSHIFT:
   539             modstate &= ~KMOD_LSHIFT;
   540             break;
   541         case SDLK_RSHIFT:
   542             modstate &= ~KMOD_RSHIFT;
   543             break;
   544         case SDLK_LALT:
   545             modstate &= ~KMOD_LALT;
   546             break;
   547         case SDLK_RALT:
   548             modstate &= ~KMOD_RALT;
   549             break;
   550         case SDLK_LMETA:
   551             modstate &= ~KMOD_LMETA;
   552             break;
   553         case SDLK_RMETA:
   554             modstate &= ~KMOD_RMETA;
   555             break;
   556         case SDLK_MODE:
   557             modstate &= ~KMOD_MODE;
   558             break;
   559         default:
   560             break;
   561         }
   562         keysym->mod = (SDLMod) modstate;
   563     }
   564 
   565     /* Figure out what type of event this is */
   566     switch (state) {
   567     case SDL_PRESSED:
   568         event.type = SDL_KEYDOWN;
   569         break;
   570     case SDL_RELEASED:
   571         event.type = SDL_KEYUP;
   572         /*
   573          * jk 991215 - Added
   574          */
   575         if (SDL_KeyRepeat.timestamp &&
   576             SDL_KeyRepeat.evt.key.keysym.sym == keysym->sym) {
   577             SDL_KeyRepeat.timestamp = 0;
   578         }
   579         break;
   580     default:
   581         /* Invalid state -- bail */
   582         return (0);
   583     }
   584 
   585     if (keysym->sym != SDLK_UNKNOWN) {
   586         /* Drop events that don't change state */
   587         if (SDL_KeyState[keysym->sym] == state) {
   588 #if 0
   589             printf("Keyboard event didn't change state - dropped!\n");
   590 #endif
   591             return (0);
   592         }
   593 
   594         /* Update internal keyboard state */
   595         SDL_ModState = (SDLMod) modstate;
   596         SDL_KeyState[keysym->sym] = state;
   597     }
   598 
   599     /* Post the event, if desired */
   600     posted = 0;
   601     if (SDL_ProcessEvents[event.type] == SDL_ENABLE) {
   602         event.key.state = state;
   603         event.key.keysym = *keysym;
   604         /*
   605          * jk 991215 - Added
   606          */
   607         if (repeatable && (SDL_KeyRepeat.delay != 0)) {
   608             SDL_KeyRepeat.evt = event;
   609             SDL_KeyRepeat.firsttime = 1;
   610             SDL_KeyRepeat.timestamp = SDL_GetTicks();
   611         }
   612         if ((SDL_EventOK == NULL) || SDL_EventOK(&event)) {
   613             posted = 1;
   614             SDL_PushEvent(&event);
   615         }
   616     }
   617     return (posted);
   618 }
   619 
   620 /*
   621  * jk 991215 - Added
   622  */
   623 void
   624 SDL_CheckKeyRepeat(void)
   625 {
   626     if (SDL_KeyRepeat.timestamp) {
   627         Uint32 now, interval;
   628 
   629         now = SDL_GetTicks();
   630         interval = (now - SDL_KeyRepeat.timestamp);
   631         if (SDL_KeyRepeat.firsttime) {
   632             if (interval > (Uint32) SDL_KeyRepeat.delay) {
   633                 SDL_KeyRepeat.timestamp = now;
   634                 SDL_KeyRepeat.firsttime = 0;
   635             }
   636         } else {
   637             if (interval > (Uint32) SDL_KeyRepeat.interval) {
   638                 SDL_KeyRepeat.timestamp = now;
   639                 if ((SDL_EventOK == NULL)
   640                     || SDL_EventOK(&SDL_KeyRepeat.evt)) {
   641                     SDL_PushEvent(&SDL_KeyRepeat.evt);
   642                 }
   643             }
   644         }
   645     }
   646 }
   647 
   648 int
   649 SDL_EnableKeyRepeat(int delay, int interval)
   650 {
   651     if ((delay < 0) || (interval < 0)) {
   652         SDL_SetError("keyboard repeat value less than zero");
   653         return (-1);
   654     }
   655     SDL_KeyRepeat.firsttime = 0;
   656     SDL_KeyRepeat.delay = delay;
   657     SDL_KeyRepeat.interval = interval;
   658     SDL_KeyRepeat.timestamp = 0;
   659     return (0);
   660 }
   661 
   662 void
   663 SDL_GetKeyRepeat(int *delay, int *interval)
   664 {
   665     *delay = SDL_KeyRepeat.delay;
   666     *interval = SDL_KeyRepeat.interval;
   667 }
   668 
   669 /* vi: set ts=4 sw=4 expandtab: */