Logo Search packages:      
Sourcecode: hatari version File versions  Download package

keymap.c

/*
  Hatari - keymap.c

  This file is distributed under the GNU Public License, version 2 or at
  your option any later version. Read the file gpl.txt for details.

  Here we process a key press and the remapping of the scancodes.
*/
char Keymap_rcsid[] = "Hatari $Id: keymap.c,v 1.22 2005/09/26 18:24:09 thothy Exp $";

#include "main.h"
#include "keymap.h"
#include "misc.h"
#include "configuration.h"
#include "ikbd.h"
#include "joy.h"
#include "shortcut.h"
#include "screen.h"
#include "debugui.h"


/*-----------------------------------------------------------------------*/
/*
  Remap table of PC keys to ST scan codes, -ve is invalid key (ie doesn't occur on ST)

  PC Keyboard:-

    Esc  F1  F2  F3  F4    F5  F6  F7  F8    F9  F10 F11 F12       Print Scroll Pause

     1   59  60  61  62    63  64  65  66    67  68  87  88                70     69


  !   "      $   %   ^   &   *   (   )   _   +                                 Page
`  1   2   3   4   5   6   7   8   9   0   -   =   <-               Ins   Home    Up

41 2   3   4   5   6   7   8   9   10  11  12  13  14               82     71     73
                                                                    --     --     --
                                                       |
                                             {   }     |                         Page
Tab  Q   W   E   R   T   Y   U   I   O   P   [   ] <----            Del   End    Down

15   16  17  18  19  20  21  22  23  24  25  26  27  28             83     79     81
                                                                    --     --     --

                                           :   @   ~                       ^
Caps   A   S   D   F   G   H   J   K   L   ;   '   #                       |

58     30  31  32  33  34  35  36  37  38  39  40  43                      72
                                                                           --

^   |                               <   >   ?   ^
|   \   Z   X   C   V   B   N   M   ,   .   /   |                     <-   |   ->

42  86  44  45  46  47  48  49  50  51  52  53  54                    75   80  77
                                                                      --   --  --

Ctrl  Alt          SPACE             Alt Gr      Ctrl

 29    56            57                56         29
                                                  --

  And:-

Num
Lock   /    *    -

69     53   55   74
--     --

 7    8     9    +
Home  ^   Pg Up

71    72    73   78


4     5     6
<-          ->

75    76    77


1     2     3
End   |   Pg Dn  Enter

79    70    81    28
                  --

0     .
Ins   Del

82    83


*/


/* Mask of valid shortcut key modifiers */
#define KEYMAP_SHORTCUTMODS  (KMOD_RALT|KMOD_LMETA|KMOD_RMETA|KMOD_MODE)


/* SDL symbolic key to ST scan code mapping table */
static const char SymbolicKeyToSTScanCode[SDLK_LAST] =
{
/* ST Code,  PC Code */
  -1,    /* 0 */
  -1,    /* 1 */
  -1,    /* 2 */
  -1,    /* 3 */
  -1,    /* 4 */
  -1,    /* 5 */
  -1,    /* 6 */
  -1,    /* 7 */
  0x0E,  /* SDLK_BACKSPACE=8 */
  0x0F,  /* SDLK_TAB=9 */
  -1,    /* 10 */
  -1,    /* 11 */
  0x47,  /* SDLK_CLEAR = 12 */
  0x1C,  /* SDLK_RETURN = 13 */
  -1,    /* 14 */
  -1,    /* 15 */
  -1,    /* 16 */
  -1,    /* 17 */
  -1,    /* 18 */
  -1,    /* SDLK_PAUSE = 19 */
  -1,    /* 20 */
  -1,    /* 21 */
  -1,    /* 22 */
  -1,    /* 23 */
  -1,    /* 24 */
  -1,    /* 25 */
  -1,    /* 26 */
  0x01,  /* SDLK_ESCAPE = 27 */
  -1,    /* 28 */
  -1,    /* 29 */
  -1,    /* 30 */
  -1,    /* 31 */
  0x39,  /* SDLK_SPACE = 32 */
  -1,    /* SDLK_EXCLAIM = 33 */
  -1,    /* SDLK_QUOTEDBL = 34 */
  0x29,  /* SDLK_HASH = 35 */
  -1,    /* SDLK_DOLLAR = 36 */
  -1,    /* 37 */
  -1,    /* SDLK_AMPERSAND = 38 */
  -1,    /* SDLK_QUOTE = 39 */
  0x63,  /* SDLK_LEFTPAREN = 40 */
  0x64,  /* SDLK_RIGHTPAREN = 41 */
  -1,    /* SDLK_ASTERISK = 42 */
  0x1B,  /* SDLK_PLUS = 43 */
  0x33,  /* SDLK_COMMA = 44 */
  0x35,  /* SDLK_MINUS = 45 */
  0x34,  /* SDLK_PERIOD = 46 */
  -1,    /* SDLK_SLASH = 47 */
  0x0B,  /* SDLK_0 = 48 */
  0x02,  /* SDLK_1 = 49 */
  0x03,  /* SDLK_2 = 50 */
  0x04,  /* SDLK_3 = 51 */
  0x05,  /* SDLK_4 = 52 */
  0x06,  /* SDLK_5 = 53 */
  0x07,  /* SDLK_6 = 54 */
  0x08,  /* SDLK_7 = 55 */
  0x09,  /* SDLK_8 = 56 */
  0x0A,  /* SDLK_9 = 57 */
  -1,    /* SDLK_COLON = 58 */
  -1,    /* SDLK_SEMICOLON = 59 */
  0x60,  /* SDLK_LESS = 60 */
  -1,    /* SDLK_EQUALS = 61 */
  -1,    /* SDLK_GREATER  = 62 */
  -1,    /* SDLK_QUESTION = 63 */
  -1,    /* SDLK_AT = 64 */
  -1,    /* 65 */  /* Skip uppercase letters */
  -1,    /* 66 */
  -1,    /* 67 */
  -1,    /* 68 */
  -1,    /* 69 */
  -1,    /* 70 */
  -1,    /* 71 */
  -1,    /* 72 */
  -1,    /* 73 */
  -1,    /* 74 */
  -1,    /* 75 */
  -1,    /* 76 */
  -1,    /* 77 */
  -1,    /* 78 */
  -1,    /* 79 */
  -1,    /* 80 */
  -1,    /* 81 */
  -1,    /* 82 */
  -1,    /* 83 */
  -1,    /* 84 */
  -1,    /* 85 */
  -1,    /* 86 */
  -1,    /* 87 */
  -1,    /* 88 */
  -1,    /* 89 */
  -1,    /* 90 */
  0x63,  /* SDLK_LEFTBRACKET = 91 */
  -1,    /* SDLK_BACKSLASH = 92 */
  0x64,  /* SDLK_RIGHTBRACKET = 93 */
  0x2B,  /* SDLK_CARET = 94 */
  -1,    /* SDLK_UNDERSCORE = 95 */
  -1,    /* SDLK_BACKQUOTE = 96 */
  0x1E,  /* SDLK_a = 97 */
  0x30,  /* SDLK_b = 98 */
  0x2E,  /* SDLK_c = 99 */
  0x20,  /* SDLK_d = 100 */
  0x12,  /* SDLK_e = 101 */
  0x21,  /* SDLK_f = 102 */
  0x22,  /* SDLK_g = 103 */
  0x23,  /* SDLK_h = 104 */
  0x17,  /* SDLK_i = 105 */
  0x24,  /* SDLK_j = 106 */
  0x25,  /* SDLK_k = 107 */
  0x26,  /* SDLK_l = 108 */
  0x32,  /* SDLK_m = 109 */
  0x31,  /* SDLK_n = 110 */
  0x18,  /* SDLK_o = 111 */
  0x19,  /* SDLK_p = 112 */
  0x10,  /* SDLK_q = 113 */
  0x13,  /* SDLK_r = 114 */
  0x1F,  /* SDLK_s = 115 */
  0x14,  /* SDLK_t = 116 */
  0x16,  /* SDLK_u = 117 */
  0x2F,  /* SDLK_v = 118 */
  0x11,  /* SDLK_w = 119 */
  0x2D,  /* SDLK_x = 120 */
  0x15,  /* SDLK_y = 121 */
  0x2C,  /* SDLK_z = 122 */
  -1,    /* 123 */
  -1,    /* 124 */
  -1,    /* 125 */
  -1,    /* 126 */
  0x53,  /* SDLK_DELETE = 127 */
  /* End of ASCII mapped keysyms */
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 128-143*/
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 144-159*/
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 160-175*/
  -1, -1, -1, -1, 0x0D, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 176-191*/
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 192-207*/
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x0C, /* 208-223*/
  -1, -1, -1, -1, 0x28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 224-239*/
  -1, -1, -1, -1, -1, -1, 0x27, -1, -1, -1, -1, -1, 0x1A, -1, -1, -1, /* 240-255*/
  /* Numeric keypad: */
  0x70,    /* SDLK_KP0 = 256 */
  0x6D,    /* SDLK_KP1 = 257 */
  0x6E,    /* SDLK_KP2 = 258 */
  0x6F,    /* SDLK_KP3 = 259 */
  0x6A,    /* SDLK_KP4 = 260 */
  0x6B,    /* SDLK_KP5 = 261 */
  0x6C,    /* SDLK_KP6 = 262 */
  0x67,    /* SDLK_KP7 = 263 */
  0x68,    /* SDLK_KP8 = 264 */
  0x69,    /* SDLK_KP9 = 265 */
  0x71,    /* SDLK_KP_PERIOD = 266 */
  0x65,    /* SDLK_KP_DIVIDE = 267 */
  0x66,    /* SDLK_KP_MULTIPLY = 268 */
  0x4A,    /* SDLK_KP_MINUS = 269 */
  0x4E,    /* SDLK_KP_PLUS = 270 */
  0x72,    /* SDLK_KP_ENTER = 271 */
  -1,      /* SDLK_KP_EQUALS = 272 */
  /* Arrows + Home/End pad */
  0x48,    /* SDLK_UP = 273 */
  0x50,    /* SDLK_DOWN = 274 */
  0x4D,    /* SDLK_RIGHT = 275 */
  0x4B,    /* SDLK_LEFT = 276 */
  0x52,    /* SDLK_INSERT = 277 */
  0x47,    /* SDLK_HOME = 278 */
  0x61,    /* SDLK_END = 279 */
  0x63,    /* SDLK_PAGEUP = 280 */
  0x64,    /* SDLK_PAGEDOWN = 281 */
  /* Function keys */
  0x3B,    /* SDLK_F1 = 282 */
  0x3C,    /* SDLK_F2 = 283 */
  0x3D,    /* SDLK_F3 = 284 */
  0x3E,    /* SDLK_F4 = 285 */
  0x3F,    /* SDLK_F5 = 286 */
  0x40,    /* SDLK_F6 = 287 */
  0x41,    /* SDLK_F7 = 288 */
  0x42,    /* SDLK_F8 = 289 */
  0x43,    /* SDLK_F9 = 290 */
  0x44,    /* SDLK_F10 = 291 */
  -1,      /* SDLK_F11 = 292 */
  -1,      /* SDLK_F12 = 293 */
  -1,      /* SDLK_F13 = 294 */
  -1,      /* SDLK_F14 = 295 */
  -1,      /* SDLK_F15 = 296 */
  -1,      /* 297 */
  -1,      /* 298 */
  -1,      /* 299 */
  /* Key state modifier keys */
  -1,      /* SDLK_NUMLOCK = 300 */
  0x3A,    /* SDLK_CAPSLOCK = 301 */
  0x61,    /* SDLK_SCROLLOCK = 302 */
  0x36,    /* SDLK_RSHIFT = 303 */
  0x2A,    /* SDLK_LSHIFT = 304 */
  0x1D,    /* SDLK_RCTRL = 305 */
  0x1D,    /* SDLK_LCTRL = 306 */
  0x38,    /* SDLK_RALT = 307 */
  0x38,    /* SDLK_LALT = 308 */
  -1,      /* SDLK_RMETA = 309 */
  -1,      /* SDLK_LMETA = 310 */
  -1,      /* SDLK_LSUPER = 311 */
  -1,      /* SDLK_RSUPER = 312 */
  -1,      /* SDLK_MODE = 313 */     /* "Alt Gr" key */
  -1,      /* SDLK_COMPOSE = 314 */
  /* Miscellaneous function keys */
  0x62,    /* SDLK_HELP = 315 */
  0x62,    /* SDLK_PRINT = 316 */
  -1,      /* SDLK_SYSREQ = 317 */
  -1,      /* SDLK_BREAK = 318 */
  -1,      /* SDLK_MENU = 319 */
  -1,      /* SDLK_POWER = 320 */
  -1,      /* SDLK_EURO = 321 */
  0x61     /* SDLK_UNDO = 322 */
};

/* Table for loaded keys: */
static char LoadedKeyToSTScanCode[SDLK_LAST];

/* This table is used to translate a symbolic keycode to the (SDL) scancode */
static Uint8 SdlSymToSdlScan[SDLK_LAST];


/* List of ST scan codes to NOT de-bounce when running in maximum speed */
static char DebounceExtendedKeys[] =
{
  0x1d,  /* CTRL */
  0x2a,  /* Left SHIFT */
  0x01,  /* ESC */
  0x38,  /* ALT */
  0x36,  /* Right SHIFT */
  0      /* term */
};



/*-----------------------------------------------------------------------*/
/*
  Initialization.
*/
void Keymap_Init(void)
{
  memset(SdlSymToSdlScan, 0, sizeof(SdlSymToSdlScan));      /* Clear array */
  Keymap_LoadRemapFile(ConfigureParams.Keyboard.szMappingFileName);
}


/*-----------------------------------------------------------------------*/
/*
  Heuristic analysis to find out the obscure scancode offset.
  Some keys like 'z' can't be used for detection since they are on different
  locations on "qwertz" and "azerty" keyboards.
  This clever code has originally been taken from the emulator Aranym. (cheers!)
*/
static int Keymap_FindScanCodeOffset(SDL_keysym* keysym)
{
  int offset = -1;    /* uninitialized scancode offset */
  int scanPC = keysym->scancode;

  if(scanPC == 0)  return -1;  /* Ignore illegal scancode */

  switch(keysym->sym)
  {
    case SDLK_ESCAPE:  offset = scanPC - 0x01; break;
    case SDLK_1:  offset = scanPC - 0x02; break;
    case SDLK_2:  offset = scanPC - 0x03; break;
    case SDLK_3:  offset = scanPC - 0x04; break;
    case SDLK_4:  offset = scanPC - 0x05; break;
    case SDLK_5:  offset = scanPC - 0x06; break;
    case SDLK_6:  offset = scanPC - 0x07; break;
    case SDLK_7:  offset = scanPC - 0x08; break;
    case SDLK_8:  offset = scanPC - 0x09; break;
    case SDLK_9:  offset = scanPC - 0x0a; break;
    case SDLK_0:  offset = scanPC - 0x0b; break;
    case SDLK_BACKSPACE:  offset = scanPC - 0x0e; break;
    case SDLK_TAB:  offset = scanPC - 0x0f; break;
    case SDLK_RETURN:  offset = scanPC - 0x1c; break;
    case SDLK_SPACE:  offset = scanPC - 0x39; break;
    /*case SDLK_q:  offset = scanPC - 0x10; break;*/  /* different on azerty */
    /*case SDLK_w:  offset = scanPC - 0x11; break;*/  /* different on azerty */
    case SDLK_e:  offset = scanPC - 0x12; break;
    case SDLK_r:  offset = scanPC - 0x13; break;
    case SDLK_t:  offset = scanPC - 0x14; break;
    /*case SDLK_y:  offset = scanPC - 0x15; break;*/  /* different on qwertz */
    case SDLK_u:  offset = scanPC - 0x16; break;
    case SDLK_i:  offset = scanPC - 0x17; break;
    case SDLK_o:  offset = scanPC - 0x18; break;
    case SDLK_p:  offset = scanPC - 0x19; break;
    /*case SDLK_a:  offset = scanPC - 0x1e; break;*/  /* different on azerty */
    case SDLK_s:  offset = scanPC - 0x1f; break;
    case SDLK_d:  offset = scanPC - 0x20; break;
    case SDLK_f:  offset = scanPC - 0x21; break;
    case SDLK_g:  offset = scanPC - 0x22; break;
    case SDLK_h:  offset = scanPC - 0x23; break;
    case SDLK_j:  offset = scanPC - 0x24; break;
    case SDLK_k:  offset = scanPC - 0x25; break;
    case SDLK_l:  offset = scanPC - 0x26; break;
    /*case SDLK_z:  offset = scanPC - 0x2c; break;*/  /* different on qwertz and azerty */
    case SDLK_x:  offset = scanPC - 0x2d; break;
    case SDLK_c:  offset = scanPC - 0x2e; break;
    case SDLK_v:  offset = scanPC - 0x2f; break;
    case SDLK_b:  offset = scanPC - 0x30; break;
    case SDLK_n:  offset = scanPC - 0x31; break;
    /*case SDLK_m:  offset = scanPC - 0x32; break;*/  /* different on azerty */
    case SDLK_CAPSLOCK:  offset = scanPC - 0x3a; break;
    case SDLK_LSHIFT:  offset = scanPC - 0x2a; break;
    case SDLK_LCTRL:  offset = scanPC - 0x1d; break;
    case SDLK_LALT:  offset = scanPC - 0x38; break;
    case SDLK_F1:  offset = scanPC - 0x3b; break;
    case SDLK_F2:  offset = scanPC - 0x3c; break;
    case SDLK_F3:  offset = scanPC - 0x3d; break;
    case SDLK_F4:  offset = scanPC - 0x3e; break;
    case SDLK_F5:  offset = scanPC - 0x3f; break;
    case SDLK_F6:  offset = scanPC - 0x40; break;
    case SDLK_F7:  offset = scanPC - 0x41; break;
    case SDLK_F8:  offset = scanPC - 0x42; break;
    case SDLK_F9:  offset = scanPC - 0x43; break;
    case SDLK_F10:  offset = scanPC - 0x44; break;
    default:  break;
  }

  if (offset != -1)
  {
    fprintf(stderr, "Detected scancode offset = %d (key: '%s' with scancode $%02x)\n",
            offset, SDL_GetKeyName(keysym->sym), scanPC);
  }

  return offset;
}


/*-----------------------------------------------------------------------*/
/*
  Map PC scancode to ST scancode.
  This code was heavily inspired by the emulator Aranym. (cheers!)
*/
static char Keymap_PcToStScanCode(SDL_keysym* keysym)
{
  static int offset = -1;    /* uninitialized scancode offset */

  switch(keysym->sym)
  {
    /* Numeric Pad */
    /* note that the numbers are handled in Keymap_GetKeyPadScanCode()! */
    case SDLK_KP_DIVIDE:   return 0x65;  /* Numpad / */
    case SDLK_KP_MULTIPLY: return 0x66;  /* NumPad * */
    case SDLK_KP_MINUS:    return 0x4a;  /* NumPad - */
    case SDLK_KP_PLUS:     return 0x4e;  /* NumPad + */
    case SDLK_KP_PERIOD:   return 0x71;  /* NumPad . */
    case SDLK_KP_ENTER:    return 0x72;  /* NumPad Enter */

    /* Special Keys */
    case SDLK_PAGEUP:  return 0x62;  /* F11 => Help */
    case SDLK_PAGEDOWN:  return 0x61;  /* F12 => Undo */
    case SDLK_HOME:   return 0x47;  /* Home */
    case SDLK_END:    return 0x60;  /* End => "<>" on German Atari kbd */
    case SDLK_UP:     return 0x48;  /* Arrow Up */
    case SDLK_LEFT:   return 0x4b;  /* Arrow Left */
    case SDLK_RIGHT:  return 0x4d;  /* Arrow Right */
    case SDLK_DOWN:   return 0x50;  /* Arrow Down */
    case SDLK_INSERT: return 0x52;  /* Insert */
    case SDLK_DELETE: return 0x53;  /* Delete */
    case SDLK_LESS:   return 0x60;  /* "<" */

    /* Map Right Alt/Alt Gr/Control to the Atari keys */
    case SDLK_RCTRL:  return 0x1d;  /* Control */
    case SDLK_RALT:   return 0x38;  /* Alternate */

    default:
    {
      /* Process remaining keys: assume that it's PC101 keyboard
       * and that it is compatible with Atari ST keyboard (basically
       * same scancodes but on different platforms with different
       * base offset (framebuffer = 0, X11 = 8).
       * Try to detect the offset using a little bit of black magic.
       * If offset is known then simply pass the scancode. */
      if (offset == -1)
      {
        offset = Keymap_FindScanCodeOffset(keysym);
      }

      if (offset >= 0)
      {
        /* offset is defined so pass the scancode directly */
        return (keysym->scancode - offset);
      }
      else
      {
        /* Failed to detect offset, so use default value 8 */
        fprintf(stderr, "Offset detection failed with "
                "key '%s', scancode = 0x%02x, symcode =  0x%02x\n",
                SDL_GetKeyName(keysym->sym), keysym->scancode, keysym->sym);
        return (keysym->scancode - 8);
      }
    }
  }
}


/*-----------------------------------------------------------------------*/
/*
  Remap a keypad key to ST scan code. We use a separate function for this
  so that we can easily toggle between number and cursor mode with the
  numlock key.
*/
static char Keymap_GetKeyPadScanCode(SDL_keysym* pKeySym)
{
  if(SDL_GetModState() & KMOD_NUM)
  {
    switch(pKeySym->sym)
    {
      case SDLK_KP0:  return 0x70;  /* NumPad 0 */
      case SDLK_KP1:  return 0x6d;  /* NumPad 1 */
      case SDLK_KP2:  return 0x6e;  /* NumPad 2 */
      case SDLK_KP3:  return 0x6f;  /* NumPad 3 */
      case SDLK_KP4:  return 0x6a;  /* NumPad 4 */
      case SDLK_KP5:  return 0x6b;  /* NumPad 5 */
      case SDLK_KP6:  return 0x6c;  /* NumPad 6 */
      case SDLK_KP7:  return 0x67;  /* NumPad 7 */
      case SDLK_KP8:  return 0x68;  /* NumPad 8 */
      case SDLK_KP9:  return 0x69;  /* NumPad 9 */
      default:  break;
    }
  }
  else
  {
    switch(pKeySym->sym)
    {
      case SDLK_KP0:  return 0x70;  /* NumPad 0 */
      case SDLK_KP1:  return 0x6d;  /* NumPad 1 */
      case SDLK_KP2:  return 0x50;  /* Cursor down */
      case SDLK_KP3:  return 0x6f;  /* NumPad 3 */
      case SDLK_KP4:  return 0x4b;  /* Cursor left */
      case SDLK_KP5:  return 0x50;  /* Cursor down (again?) */
      case SDLK_KP6:  return 0x4d;  /* Cursor right */
      case SDLK_KP7:  return 0x52;  /* Insert - good for Dungeon Master */
      case SDLK_KP8:  return 0x48;  /* Cursor up */
      case SDLK_KP9:  return 0x47;  /* Home - again for Dungeon Master */
      default:  break;
    }
  }

  return -1;
}


/*-----------------------------------------------------------------------*/
/*
  Remap SDL Key to ST Scan code
*/
char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
{
  if(pKeySym->sym >= SDLK_LAST)  return -1;  /* Avoid illegal keys */

  /* Check for keypad first so we can handle numlock */
  if(ConfigureParams.Keyboard.nKeymapType != KEYMAP_LOADED)
  {
    if(pKeySym->sym >= SDLK_KP0 && pKeySym->sym <= SDLK_KP9)
    {
      return Keymap_GetKeyPadScanCode(pKeySym);
    }
  }

  /* Remap from PC scancodes? */
  if(ConfigureParams.Keyboard.nKeymapType == KEYMAP_SCANCODE)
  {
    /* We sometimes enter here with an illegal (=0) scancode, so we keep
     * track of the right scancodes in a table and then use a value from there.
     */
    if(pKeySym->scancode != 0)
    {
      SdlSymToSdlScan[pKeySym->sym] = pKeySym->scancode;
    }
    else
    {
      pKeySym->scancode = SdlSymToSdlScan[pKeySym->sym];
      if(pKeySym->scancode == 0)
        fprintf(stderr, "Warning: Key scancode is 0!\n");
    }

    return Keymap_PcToStScanCode(pKeySym);
  }

  /* Use default or loaded? */
  if(ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
    return LoadedKeyToSTScanCode[pKeySym->sym];
  else
    return SymbolicKeyToSTScanCode[pKeySym->sym];
}


/*-----------------------------------------------------------------------*/
/*
  Load keyboard remap file
*/
void Keymap_LoadRemapFile(char *pszFileName)
{
  char szString[1024];
  unsigned int STScanCode, PCKeyCode;
  FILE *in;

  /* Initialize table with default values */
  memcpy(LoadedKeyToSTScanCode, SymbolicKeyToSTScanCode, sizeof(LoadedKeyToSTScanCode));

  /* Attempt to load file */
  if (strlen(pszFileName)>0)
  {
    /* Open file */
    in = fopen(pszFileName, "r");
    if (in)
    {
      while(!feof(in))
      {
        /* Read line from file */
        fgets(szString, sizeof(szString), in);
        /* Remove white-space from start of line */
        Misc_RemoveWhiteSpace(szString,sizeof(szString));
        if (strlen(szString)>0)
        {
          /* Is a comment? */
          if ( (szString[0]==';') || (szString[0]=='#') )
            continue;
          /* Read values */
          sscanf(szString, "%d,%d", &PCKeyCode, &STScanCode);
          /* Store into remap table, check both value within range */
          if ( (PCKeyCode>=0) && (PCKeyCode<SDLK_LAST) && (STScanCode>=0) && (STScanCode<256) )
            LoadedKeyToSTScanCode[PCKeyCode] = STScanCode;
        }
      }

      fclose(in);
    }
  }
}


/*-----------------------------------------------------------------------*/
/*
  Scan list of keys to NOT de-bounce when running in maximum speed, eg ALT,SHIFT,CTRL etc...
  Return TRUE if key requires de-bouncing
*/
static BOOL Keymap_DebounceSTKey(char STScanCode)
{
  int i=0;

  /* Are we in maximum speed, and have disabled key repeat? */
  if((ConfigureParams.System.nMinMaxSpeed!=MINMAXSPEED_MIN) && (ConfigureParams.Keyboard.bDisableKeyRepeat))
  {
    /* We should de-bounce all non extended keys, eg leave ALT,SHIFT,CTRL etc... held */
    while (DebounceExtendedKeys[i])
    {
      if (STScanCode==DebounceExtendedKeys[i])
        return(FALSE);
      i++;
    }

    /* De-bounce key */
    return(TRUE);
  }

  /* Do not de-bounce key */
  return(FALSE);
}


/*-----------------------------------------------------------------------*/
/*
  Debounce any PC key held down if running with key repeat disabled
  This is called each ST frame, so keys get held down for one VBL which is enough for 68000 code to scan
*/
void Keymap_DebounceAllKeys(void)
{
  unsigned int key;
  char STScanCode;
  SDL_keysym tmpKeySym;

  /* Return if we aren't in maximum speed or have not disabled key repeat */
  if((ConfigureParams.System.nMinMaxSpeed == MINMAXSPEED_MIN)
     || (!ConfigureParams.Keyboard.bDisableKeyRepeat))
  {
     return;
  }

  tmpKeySym.mod = 0;

  /* Now run through each PC key looking for ones held down */
  for(key = 0; key < SDLK_LAST; key++)
  {
    /* Is key held? */
    if(Keyboard.KeyStates[key])
    {
      tmpKeySym.sym = key;
      tmpKeySym.scancode = 0;

      /* Get scan code */
      STScanCode = Keymap_RemapKeyToSTScanCode(&tmpKeySym);
      if(STScanCode != (char)-1)
      {
        /* Does this require de-bouncing? */
        if(Keymap_DebounceSTKey(STScanCode))
          Keymap_KeyUp(&tmpKeySym);
      }
    }
  }

}


/*-----------------------------------------------------------------------*/
/*
  User press key down
*/
void Keymap_KeyDown(SDL_keysym *sdlkey)
{
  BOOL bPreviousKeyState;
  char STScanCode;
  int symkey = sdlkey->sym;
  int modkey = sdlkey->mod;

  /*fprintf(stderr, "keydown: sym=%i scan=%i mod=$%x\n",symkey, sdlkey->scancode, modkey);*/

  /* If pressed short-cut key, retain keypress until safe to execute (start of VBL) */
  if ((modkey & KEYMAP_SHORTCUTMODS) || symkey == SDLK_F11 || symkey == SDLK_F12)
  {
    ShortCutKey.Key = symkey;
    if (modkey & KMOD_CTRL)
      ShortCutKey.bCtrlPressed = TRUE;
    if (modkey & KMOD_SHIFT)
      ShortCutKey.bShiftPressed = TRUE;
    return;
  }

  /* If using joystick emulation via keyboard, DON'T send keys to keyboard processor!!!
   * Some games use keyboard as pause! */
  if (Joy_KeyDown(symkey, modkey))
    return;

  /* Handle special keys */
  if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
      || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
  {
    /* Ignore modifier keys that aren't passed to the ST */
    return;
  }
  else if(symkey == SDLK_PAUSE && bEnableDebug)
  {
    /* Call the debugger */
    if(bInFullScreen)  Screen_ReturnFromFullScreen();
    DebugUI();
    return;
  }

  /* Set down */
  bPreviousKeyState = Keyboard.KeyStates[symkey];
  Keyboard.KeyStates[symkey] = TRUE;

  STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
  if (STScanCode != (char)-1)
  {
    if (!bPreviousKeyState)
      IKBD_PressSTKey(STScanCode, TRUE);
  }
}


/*-----------------------------------------------------------------------*/
/*
  User released key
*/
void Keymap_KeyUp(SDL_keysym *sdlkey)
{
  char STScanCode;
  int symkey = sdlkey->sym;
  int modkey = sdlkey->mod;

  /*fprintf(stderr, "keyup: sym=%i scan=%i mod=$%x\n",symkey, sdlkey->scancode, modkey);*/

  /* Ignore short-cut keys here */
  if ((modkey & KEYMAP_SHORTCUTMODS) || symkey == SDLK_F11 || symkey == SDLK_F12)
  {
    return;
  }

  /* If using keyboard emulation, DON'T send keys to keyboard processor!!!
   * Some games use keyboard as pause! */
  if (Joy_KeyUp(symkey, modkey))
    return;

  /* Handle special keys */
  if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
      || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
  {
    /* Ignore modifier keys that aren't passed to the ST */
    return;
  }
  else if(symkey == SDLK_CAPSLOCK)
  {
    /* Simulate another capslock key press */
    IKBD_PressSTKey(0x3A, TRUE);
  }

  /* Release key (only if was pressed) */
  if(Keyboard.KeyStates[symkey])
  {
    STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
    if(STScanCode != (char)-1)
    {
      IKBD_PressSTKey(STScanCode,FALSE);
    }
  }

  Keyboard.KeyStates[symkey] = FALSE;
}


Generated by  Doxygen 1.6.0   Back to index