src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 14 Jun 2006 06:26:35 +0000
branchSDL-1.3
changeset 1679 153477a6cc31
parent 1674 7688a73b25b1
child 1720 a1ebb17f9c52
permissions -rw-r--r--
More compile fixes
     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     SDL_Cursor *cursor;
   295     int selected_keyboard;
   296 
   297     /* Add the keyboard to the list of keyboards */
   298     if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
   299         keyboards =
   300             (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
   301                                           (SDL_num_keyboards +
   302                                            1) * sizeof(*keyboards));
   303         if (!keyboards) {
   304             SDL_OutOfMemory();
   305             return -1;
   306         }
   307 
   308         SDL_keyboards = keyboards;
   309         index = SDL_num_keyboards++;
   310     }
   311     SDL_keyboards[index] =
   312         (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
   313     if (!SDL_keyboards[index]) {
   314         SDL_OutOfMemory();
   315         return -1;
   316     }
   317     *SDL_keyboards[index] = *keyboard;
   318 
   319     return index;
   320 }
   321 
   322 void
   323 SDL_DelKeyboard(int index)
   324 {
   325     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   326 
   327     if (!keyboard) {
   328         return;
   329     }
   330 
   331     if (keyboard->FreeKeyboard) {
   332         keyboard->FreeKeyboard(keyboard);
   333     }
   334     SDL_free(keyboard);
   335 
   336     SDL_keyboards[index] = NULL;
   337 }
   338 
   339 void
   340 SDL_ResetKeyboard(int index)
   341 {
   342     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   343     SDL_keysym keysym;
   344     Uint16 key;
   345 
   346     if (!keyboard) {
   347         return;
   348     }
   349 
   350     SDL_memset(&keysym, 0, (sizeof keysym));
   351     for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
   352         if (keyboard->keystate[key] == SDL_PRESSED) {
   353             keysym.sym = key;
   354             SDL_SendKeyboardKey(index, 0, SDL_RELEASED, &keysym);
   355         }
   356     }
   357     keyboard->repeat.timestamp = 0;
   358 }
   359 
   360 void
   361 SDL_KeyboardQuit(void)
   362 {
   363     int i;
   364 
   365     for (i = 0; i < SDL_num_keyboards; ++i) {
   366         SDL_DelKeyboard(i);
   367     }
   368     SDL_num_keyboards = 0;
   369     SDL_current_keyboard = 0;
   370 
   371     if (SDL_keyboards) {
   372         SDL_free(SDL_keyboards);
   373         SDL_keyboards = NULL;
   374     }
   375 }
   376 
   377 int
   378 SDL_GetNumKeyboards(void)
   379 {
   380     return SDL_num_keyboards;
   381 }
   382 
   383 int
   384 SDL_SelectKeyboard(int index)
   385 {
   386     if (index >= 0 && index < SDL_num_keyboards) {
   387         SDL_current_keyboard = index;
   388     }
   389     return SDL_current_keyboard;
   390 }
   391 
   392 int
   393 SDL_EnableUNICODE(int enable)
   394 {
   395     int old_mode;
   396 
   397     old_mode = SDL_TranslateUNICODE;
   398     if (enable >= 0) {
   399         SDL_TranslateUNICODE = enable;
   400     }
   401     return (old_mode);
   402 }
   403 
   404 Uint8 *
   405 SDL_GetKeyState(int *numkeys)
   406 {
   407     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   408 
   409     if (numkeys != (int *) 0) {
   410         *numkeys = SDLK_LAST;
   411     }
   412 
   413     if (!keyboard) {
   414         return NULL;
   415     }
   416     return keyboard->keystate;
   417 }
   418 
   419 SDLMod
   420 SDL_GetModState(void)
   421 {
   422     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   423 
   424     if (!keyboard) {
   425         return KMOD_NONE;
   426     }
   427     return keyboard->modstate;
   428 }
   429 
   430 void
   431 SDL_SetModState(SDLMod modstate)
   432 {
   433     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   434 
   435     if (!keyboard) {
   436         return;
   437     }
   438     keyboard->modstate = modstate;
   439 }
   440 
   441 const char *
   442 SDL_GetKeyName(SDLKey key)
   443 {
   444     const char *keyname;
   445 
   446     if (key < SDL_arraysize(SDL_keynames)) {
   447         keyname = SDL_keynames[key];
   448     } else {
   449         keyname = NULL;
   450     }
   451     if (keyname == NULL) {
   452         if (key < 256) {
   453             static char temp[4];
   454             char *cvt;
   455             temp[0] = (char) key;
   456             temp[1] = '\0';
   457             cvt = SDL_iconv_string("UTF-8", "LATIN1", temp, 1);
   458             SDL_strlcpy(temp, cvt, SDL_arraysize(temp));
   459             SDL_free(cvt);
   460             keyname = temp;
   461         } else {
   462             keyname = "unknown key";
   463         }
   464     }
   465     return keyname;
   466 }
   467 
   468 int
   469 SDL_SendKeyboardKey(int index, SDL_WindowID windowID, Uint8 state,
   470                     SDL_keysym * keysym)
   471 {
   472     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   473     int posted, repeatable;
   474     Uint16 modstate;
   475     Uint8 type;
   476 
   477     if (!keyboard) {
   478         return 0;
   479     }
   480 
   481     if (windowID) {
   482         keyboard->focus = windowID;
   483     }
   484 #if 0
   485     printf("The '%s' key has been %s\n", SDL_GetKeyName(keysym->sym),
   486            state == SDL_PRESSED ? "pressed" : "released");
   487 #endif
   488     /* Set up the keysym */
   489     modstate = keyboard->modstate;
   490 
   491     repeatable = 0;
   492 
   493     if (state == SDL_PRESSED) {
   494         keysym->mod = modstate;
   495         switch (keysym->sym) {
   496         case SDLK_UNKNOWN:
   497             break;
   498         case SDLK_NUMLOCK:
   499             modstate ^= KMOD_NUM;
   500             if (!(modstate & KMOD_NUM))
   501                 state = SDL_RELEASED;
   502             keysym->mod = modstate;
   503             break;
   504         case SDLK_CAPSLOCK:
   505             modstate ^= KMOD_CAPS;
   506             if (!(modstate & KMOD_CAPS))
   507                 state = SDL_RELEASED;
   508             keysym->mod = modstate;
   509             break;
   510         case SDLK_LCTRL:
   511             modstate |= KMOD_LCTRL;
   512             break;
   513         case SDLK_RCTRL:
   514             modstate |= KMOD_RCTRL;
   515             break;
   516         case SDLK_LSHIFT:
   517             modstate |= KMOD_LSHIFT;
   518             break;
   519         case SDLK_RSHIFT:
   520             modstate |= KMOD_RSHIFT;
   521             break;
   522         case SDLK_LALT:
   523             modstate |= KMOD_LALT;
   524             break;
   525         case SDLK_RALT:
   526             modstate |= KMOD_RALT;
   527             break;
   528         case SDLK_LMETA:
   529             modstate |= KMOD_LMETA;
   530             break;
   531         case SDLK_RMETA:
   532             modstate |= KMOD_RMETA;
   533             break;
   534         case SDLK_MODE:
   535             modstate |= KMOD_MODE;
   536             break;
   537         default:
   538             repeatable = 1;
   539             break;
   540         }
   541     } else {
   542         switch (keysym->sym) {
   543         case SDLK_UNKNOWN:
   544             break;
   545         case SDLK_NUMLOCK:
   546         case SDLK_CAPSLOCK:
   547             /* Only send keydown events */
   548             return (0);
   549         case SDLK_LCTRL:
   550             modstate &= ~KMOD_LCTRL;
   551             break;
   552         case SDLK_RCTRL:
   553             modstate &= ~KMOD_RCTRL;
   554             break;
   555         case SDLK_LSHIFT:
   556             modstate &= ~KMOD_LSHIFT;
   557             break;
   558         case SDLK_RSHIFT:
   559             modstate &= ~KMOD_RSHIFT;
   560             break;
   561         case SDLK_LALT:
   562             modstate &= ~KMOD_LALT;
   563             break;
   564         case SDLK_RALT:
   565             modstate &= ~KMOD_RALT;
   566             break;
   567         case SDLK_LMETA:
   568             modstate &= ~KMOD_LMETA;
   569             break;
   570         case SDLK_RMETA:
   571             modstate &= ~KMOD_RMETA;
   572             break;
   573         case SDLK_MODE:
   574             modstate &= ~KMOD_MODE;
   575             break;
   576         default:
   577             break;
   578         }
   579         keysym->mod = modstate;
   580     }
   581 
   582     /* Figure out what type of event this is */
   583     switch (state) {
   584     case SDL_PRESSED:
   585         type = SDL_KEYDOWN;
   586         break;
   587     case SDL_RELEASED:
   588         type = SDL_KEYUP;
   589         /*
   590          * jk 991215 - Added
   591          */
   592         if (keyboard->repeat.timestamp &&
   593             keyboard->repeat.evt.key.keysym.sym == keysym->sym) {
   594             keyboard->repeat.timestamp = 0;
   595         }
   596         break;
   597     default:
   598         /* Invalid state -- bail */
   599         return 0;
   600     }
   601 
   602     if (keysym->sym != SDLK_UNKNOWN) {
   603         /* Drop events that don't change state */
   604         if (keyboard->keystate[keysym->sym] == state) {
   605 #if 0
   606             printf("Keyboard event didn't change state - dropped!\n");
   607 #endif
   608             return 0;
   609         }
   610 
   611         /* Update internal keyboard state */
   612         keyboard->modstate = modstate;
   613         keyboard->keystate[keysym->sym] = state;
   614     }
   615 
   616     /* Post the event, if desired */
   617     posted = 0;
   618     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   619         SDL_Event event;
   620         event.key.type = type;
   621         event.key.which = (Uint8) index;
   622         event.key.state = state;
   623         event.key.keysym = *keysym;
   624         event.key.windowID = keyboard->focus;
   625         /*
   626          * jk 991215 - Added
   627          */
   628         if (repeatable && (keyboard->repeat.delay != 0)) {
   629             Uint32 timestamp = SDL_GetTicks();
   630             if (!timestamp) {
   631                 timestamp = 1;
   632             }
   633             keyboard->repeat.evt = event;
   634             keyboard->repeat.firsttime = 1;
   635             keyboard->repeat.timestamp = 1;
   636         }
   637         if ((SDL_EventOK == NULL) || SDL_EventOK(&event)) {
   638             posted = 1;
   639             SDL_PushEvent(&event);
   640         }
   641     }
   642     return (posted);
   643 }
   644 
   645 /*
   646  * jk 991215 - Added
   647  */
   648 void
   649 SDL_CheckKeyRepeat(void)
   650 {
   651     int i;
   652 
   653     for (i = 0; i < SDL_num_keyboards; ++i) {
   654         SDL_Keyboard *keyboard = SDL_keyboards[i];
   655 
   656         if (!keyboard) {
   657             continue;
   658         }
   659 
   660         if (keyboard->repeat.timestamp) {
   661             Uint32 now, interval;
   662 
   663             now = SDL_GetTicks();
   664             interval = (now - keyboard->repeat.timestamp);
   665             if (keyboard->repeat.firsttime) {
   666                 if (interval > (Uint32) keyboard->repeat.delay) {
   667                     keyboard->repeat.timestamp = now;
   668                     keyboard->repeat.firsttime = 0;
   669                 }
   670             } else {
   671                 if (interval > (Uint32) keyboard->repeat.interval) {
   672                     keyboard->repeat.timestamp = now;
   673                     if ((SDL_EventOK == NULL)
   674                         || SDL_EventOK(&keyboard->repeat.evt)) {
   675                         SDL_PushEvent(&keyboard->repeat.evt);
   676                     }
   677                 }
   678             }
   679         }
   680     }
   681 }
   682 
   683 int
   684 SDL_EnableKeyRepeat(int delay, int interval)
   685 {
   686     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   687 
   688     if (!keyboard) {
   689         SDL_SetError("No keyboard is currently selected");
   690         return -1;
   691     }
   692 
   693     if ((delay < 0) || (interval < 0)) {
   694         SDL_SetError("keyboard repeat value less than zero");
   695         return -1;
   696     }
   697 
   698     keyboard->repeat.firsttime = 0;
   699     keyboard->repeat.delay = delay;
   700     keyboard->repeat.interval = interval;
   701     keyboard->repeat.timestamp = 0;
   702 
   703     return 0;
   704 }
   705 
   706 void
   707 SDL_GetKeyRepeat(int *delay, int *interval)
   708 {
   709     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   710 
   711     if (!keyboard) {
   712         if (delay) {
   713             *delay = 0;
   714         }
   715         if (interval) {
   716             *interval = 0;
   717         }
   718         return;
   719     }
   720     if (delay) {
   721         *delay = keyboard->repeat.delay;
   722     }
   723     if (interval) {
   724         *interval = keyboard->repeat.interval;
   725     }
   726 }
   727 
   728 /* vi: set ts=4 sw=4 expandtab: */