[PATCH 1/3] Reworked the keymap so it is more flexible for suppo= mappings that include modifiers. Everything is explained in the updated = files. Removed SDL 1.2 support as per recent conversations on the hatari mailing list.

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


---
 doc/fr/clavier-exemple.txt | 268 +++++++++---------
 doc/keymap-sample.txt      |  89 +++---
 src/includes/keymap.h      |   2 +-
 src/keymap.c               | 558 ++++++++++++++++++++++++++++---------
 4 files changed, 627 insertions(+), 290 deletions(-)

diff --git a/doc/fr/clavier-exemple.txt b/doc/fr/clavier-exemple.txt
index d28a7628..abaf7766 100644
--- a/doc/fr/clavier-exemple.txt
+++ b/doc/fr/clavier-exemple.txt
@@ -1,131 +1,147 @@
-# This file must be UTF-8 coded
-# Mai 2017, Cocoa Pod.
-
-# FRENCH ------------------------------------------------
-# Mappage du clavier AZERTY-fr d'un Macbook Pro
-#
-# Tests sur Macbook Pro (MacBookPro5,3), MacOS 10.12 fr
-# Tests sur Macbook Air, MacOS 10.11 fr
-# Tests sur =C3=A9mulateur Hatari 2.0 _ ST, MegaST, STE, MegaSTE, tout T=
OS fr
-# Apple: Dans "Pr=C3=A9f=C3=A9rences Syst=C3=A8me / clavier",  Valider l=
'option :
-# "Utiliser les touches F1,F2,.... Comme des touches de fonction standar=
d"
-# F1-F8 presser la touche F, F9-F12  presser les touches cmd et F.
-#
-# Les commentaires commencent par un # ou un ;
-# Chaque ligne active commence par deux chiffres s=C3=A9par=C3=A9s par u=
ne virgule.
-# le premier est la valeur du symbole de la touche de votre clavier et l=
e
-# deuxi=C3=A8me est le scancode de la touche =C3=A9quivalente du clavier=
 Atari.
-# Le premier chiffre peut =C3=AAtre remplac=C3=A9 par un symbol.
-
-# ENGLISH ------------------------------------------------
-# Mapping for Macbook Pro keyboard AZERTY-fr
-#
-# Tested on Macbook Pro (MacBookPro5,3), MacOS 10.12 fr
-# Tested on Macbook Air, MacOS 10.11 fr
-# Tested on emulator Hatari 2.0 _ ST, MegaST, STE, MegaSTE, all TOS Fr
-# On Apple: in "System Preferences / Keyboard", Validate the option :
-#   "Use all F1,F2,.... as standard function keys "
-# F1-F8 press F key, F9-F12 press cmd and F keys
-#
-# 'keymap-sample.txt' file explains the syntax and values that can
-# be used for keyboard mapping.
-
-# function keys line
-#
- Escape,1
- F1,59
- F2,60
- F3,61
- F4,62
- F5,63
- F6,64
- F7,65
- F8,66
- F9,67	 # hit cmd-F9
- F10,68	 # hit cmd-F10
-# F11, 	 # cmd-F11  Does not exist in ATARI
-# F12,	 # cmd-F12  Does not exist in ATARI
-
-# first line: @ =C3=A9 " ' ( =C2=A7 =C3=A8 ! =C3=A7 =C3=A0 ) -
+# Keymap. Ce format permet d'associer des codes de touches (scancode) et=
 modificateurs
+# SDL (shift, alt, capslock, etc.) a une combinaison de touche correspon=
dante
+# sur l'ATARI =C3=A9mul=C3=A9.
 #
- <,43
- &,2
- =C3=A9,3
- ",4
- ',5
- (,6
- =C2=A7,7
- =C3=A8,8
- !,9
- =C3=A7,10
- =C3=A0,11
- ),12
- -,13
- Backspace,14
- Delete,83        #  fn + Backspace
-
-
-# second line: a z e r t y u i o p ^ $
+# Le format est le suivant:
+# <description_h=C3=B4te>,<description_Atari>
 #
- Tab,15
- a,16
- z,17
- e,18
- r,19
- t,20
- y,21
- u,22
- i,23
- o,24
- p,25
- ^,26
- $,27
-
-# third line: q s d f g h j k l m =C3=B9 `
+# <description_h=C3=B4te> est le code de touche (scancode en anglais) de=
 la touche du PC
+# concern=C3=A9e (visible dans la console quand on =C3=A9xecute hatari a=
vec l'option --trace keymap).=20
+# On peut aussi:
+# * Sp=C3=A9cifier un modificateur SDL (void https://wiki.libsdl.org/SDL=
_Keymod#Related_Functions)
+# * Ajouter un masque. Ce masque sera appliqu=C3=A9 avec l'op=C3=A9rateu=
r bool=C3=A9an ET =C3=A0 la touche
+#   press=C3=A9e avant qu'elle ne soit compar=C3=A9e aux entr=C3=A9es de=
 la liste d'association.
+#   Ceci permet d'ignorer le status de Verr.num de sorte qu'une associat=
ion puisse fonctionner
+#   ind=C3=A9pendemment de l'=C3=A9tat de cette touche.
+# Toutes ces sp=C3=A9cifications (scancode, modificateurs, masque) doive=
nt appara=C3=AEtre dans cet
+# ordre et =C3=AAtre s=C3=A9par=C3=A9s par le caract=C3=A8re barre verti=
cale '|'.
 #
- q,30
- s,31
- d,32
- f,33
- g,34
- h,35
- j,36
- k,37
- l,38
- m,39
- =C3=B9,40
- `,41
-
-# forth line: < w x c v b n , ; : =3D
+# <description_Atari> est la liste (s=C3=A9par=C3=A9e par barre vertical=
e '|') des touches =C3=A0 envoyer=20
+# =C3=A0 l'Atari (4 maximum). Par facilit=C3=A9, on peut utiliser LSHIFT=
, RSHIFT et ALTERNATE au lieu=20
+# de 2a,36,38 respectively, respectivement..
+# On peut trouver les codes de touche des Atari dans de nombreux livres =
et documentations,
+# par exemple:
+# https://tho-otto.de/keyboards/
+# or https://freemint.github.io/tos.hyp/en/scancode.html
 #
- @,96
- w,44
- x,45
- c,46
- v,47
- b,48
- n,49
- 44,50    # comma
- 59,51    # semicolon
- :,52
- =3D,53
-
- Space,57
- CapsLock,58
-
- Return,28
- Left,75
- Right,77
- Down,80
- Up,72
-
- Keypad Enter,114   # fn + Return
- Home,71            # fn + Left
- End,97             # fn + Right
- PageDown,100       # fn + Down
- PageUp,99          # fn + Up
+# Notes:
+# * Tous les codes de touches doivent =C3=AAtre en hexadecimal.
+# * L'analyseur n'est pas tr=C3=A8s sophistiqu=C3=A9 donc n'ajoutez pas =
d'espace etc au milieu des specifications.
+# * Les associations les plus limitantes doivent appara=C3=AEtre en prem=
ier dans le fichier car elles ont priorit=C3=A9.
=20
- Left Ctrl,29
- Left Shift,42
-# Left Alt,56      # fail, but not need to remap !!!!!
- Right Shift,54
+04,1e
+# ,
+10,32
+# ?
+10|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|33
+10|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|33
+# a
+14,10
+# z
+1a,11
+# w
+1d,2c
+# 1
+1e|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|02
+1e|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|02
+1e|KMOD_CAPS|KMOD_CAPS,02
+# ~
+1f|KMOD_RALT|KMOD_RALT,LSHIFT|ALTERNATE|2b
+# 2
+1f|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|03
+1f|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|03
+1f|KMOD_CAPS|KMOD_CAPS,03
+# #
+20|KMOD_RALT|KMOD_RALT,2b
+# 3
+20|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|04
+20|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|04
+20|KMOD_CAPS|KMOD_CAPS,04
+# {
+21|KMOD_RALT|KMOD_RALT,2a|ALTERNATE|1a
+# 4
+21|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|05
+21|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|05
+# [
+22|KMOD_RALT|KMOD_RALT,ALTERNATE|1a
+# 5
+22|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|06
+22|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|06
+# |
+23|KMOD_RALT|KMOD_RALT,LSHIFT|2b
+# 6
+23|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|07
+23|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|07
+# -
+23,0d
+# 7
+24|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|08
+24|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|08
+# `
+24|KMOD_RALT|KMOD_RALT,29
+# 8
+25|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|09
+25|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|09
+# \
+25|KMOD_RALT|KMOD_RALT,ALTERNATE|28
+# _
+25,LSHIFT|0d
+# ^
+26|KMOD_RALT|KMOD_RALT,1a
+# 9
+26|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|0a
+26|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|0a
+# @
+27|KMOD_RALT|KMOD_RALT,ALTERNATE|2b
+# 0
+27|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|0b
+27|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|0b
+# =C2=B0
+2d|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|0c
+2d|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|0c
+# ]
+2d|KMOD_RALT|KMOD_RALT,ALTERNATE|1b
+# + (pr=C3=A8s de efface)
+2e|KMOD_SHIFT|KMOD_SHIFT,RSHIFT|35
+# }
+2e|KMOD_RALT|KMOD_RALT,LSHIFT|ALTERNATE|1b
+# =3D
+2e,35
+# =C2=A8
+2f|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|1a
+2f|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|1a
+# ^
+2f,1a
+# =C2=A3
+30|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|29
+30|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|29
+# $
+30,1b
+# =C2=B5, ouaip, on peut m=C3=AAme =C3=A9muler les ALT-xyz :)
+31|KMOD_LSHIFT|KMOD_LSHIFT,ALTERNATE|6e|6f|70
+31|KMOD_RSHIFT|KMOD_RSHIFT,ALTERNATE|6e|6f|70
+# * (pas pav=C3=A9 num=C3=A9rique)
+31,RSHIFT|1b
+# m
+33|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|27
+33|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|27
+33|KMOD_LALT|KMOD_LALT,ALTERNATE|27
+33,27
+# %
+34|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|28
+34|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|28
+# =C3=B9
+34,28
+# =C2=B3 (alt-239)
+35|KMOD_LSHIFT|KMOD_LSHIFT,ALTERNATE|6e|6b|6a
+35|KMOD_RSHIFT|KMOD_RSHIFT,ALTERNATE|6e|6b|6a
+# =C2=B2 (alt-253)
+35,ALTERNATE|6e|6b|6f
+# ;
+36,33
+# . (pas pav=C3=A9 num=C3=A9rique)
+36|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|33
+36|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|33
+# =C2=A7
+38|KMOD_LSHIFT|KMOD_LSHIFT,07
+38|KMOD_RSHIFT|KMOD_RSHIFT,07
diff --git a/doc/keymap-sample.txt b/doc/keymap-sample.txt
index ea3cd5f9..8e0e8e8b 100644
--- a/doc/keymap-sample.txt
+++ b/doc/keymap-sample.txt
@@ -1,34 +1,55 @@
-# This is an example for a keyboard mapping file that can be used in Hat=
ari
-# by loading it from the keyboard setup dialog.
-#
-# Lines starting with a '#' or with a ';' are comments. All other lines
-# should contain exactly one key name and a scancode, separated by a com=
ma.
-# Comment characters can be quoted with '\#' and '\;'.
-#
-# The key name is the libSDL symbolic name of the key, see the following
-# URL for a list: https://wiki.libsdl.org/SDL_Keycode
-# You can also use the symbolic keycode value instead of the name, which
-# you can get with the "--trace keymap" output from Hatari, for example.
-#
-# The given host key will be mapped to the ST key which is specified by
-# second number - the ST scan code of the key.  "--trace keymap" output
-# shows the already mapped scan code.
-#
-# All numbers should be given as decimals (not hexadecimals).
-#
-# Note that using keyboard mapping file causes Hatari to use symbolic
-# key mapping.  Symbolic key mapping does not work with so called "dead"
-# keys.
-#
-# Scan codes for Atari keyboard key positions can be seen here:
-#   http://eerott.mbnet.fi/hatari/img/st-keymap.png
-#
-# tests/keymap/ directory contains programs to discover/test the PC SDL
-# and Atari scan code values.  Hatari's default PC key code -> ST scan
-# code mappings are in src/keymap.c source file.
-#
-# Example: If you want to get the 'y' and 'z' keys right with a german T=
OS
-# ROM, you can use the following two lines to map the PC keys to the rig=
ht
-# ST scan codes:
-Y,44
-Z,21
+# Keymap. This format allows you to associate SDL key descriptions with
+# scancodes simulating the corresponding keys pressed on the emulated ST=
..
+#
+# Format is the following:
+# <host_description>,<guest_description>
+#
+# <host_description> is the scancode of the key pressed (which you can s=
ee
+# when running hatari with the "--trace keymap" option).=20
+# Optionally you can:
+# * Add a SDL key modifier (see https://wiki.libsdl.org/SDL_Keymod#Relat=
ed_Functions)
+# * Add a modifier mask. This mask will be bitwise "AND"'ed to the
+#   actual key pressed before it is compared with items from this keymap=
..
+#   This allows to mask out e.g. NumLock to make mappings work regardles=
s=20
+#   of the status of that modifier.
+# All these (scancode, modifiers, mask) must appear in this order and be
+# separated by a pipe |.
+#
+# <guest_description> is the pipe-separated ordered list of scancodes to=
 send
+# to the ST (4 max). For convenience you can use LSHIFT, RSHIFT and
+# ALTERNATE in lieu of 2a,36,38 respectively.
+# You can find scancodes in many Atari documentation places, e.g.
+# https://tho-otto.de/keyboards/
+# http://eerott.mbnet.fi/hatari/img/st-keymap.png
+# https://freemint.github.io/tos.hyp/en/scancode.html
+#
+# Notes:
+# * All scan codes must be in hexadecimal.
+# * The parser is not very smart so don't add spaces etc.
+# * Make the narrowest specification appear first.
+#
+# Examples (taken from the French keyboard mapping):
+
+# Simple scancode mapping
+04,1e
+
+# Mapping with SHIFT keys and mask (LSHIFT) to mask out other modifiers
+# like Numlock, so these mapping (for left and right shift) will work
+# regardless of Numlock
+10|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|33
+10|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|33
+
+
+# Mapping with modifier, which converst a shifted key from the host
+# to ALT-230 to display =C2=B5 on the Atari
+31|KMOD_LSHIFT|KMOD_LSHIFT,ALTERNATE|6e|6f|70
+
+
+# Mapping for CAPS LOCK 1 and shift keys, to obtain "1"
+1e|KMOD_LSHIFT|KMOD_LSHIFT,LSHIFT|02
+1e|KMOD_RSHIFT|KMOD_RSHIFT,RSHIFT|02
+1e|KMOD_CAPS|KMOD_CAPS,02
+
+# Mapping for ALT-key on the PC ~, translated to ALT-SHIFT-key
+# on the Atari
+1f|KMOD_RALT|KMOD_RALT,LSHIFT|ALTERNATE|2b
diff --git a/src/includes/keymap.h b/src/includes/keymap.h
index cb7f9b19..10aa020e 100644
--- a/src/includes/keymap.h
+++ b/src/includes/keymap.h
@@ -32,7 +32,7 @@
 #define SDLK_SCROLLOCK SDLK_SCROLLLOCK
=20
 extern void Keymap_Init(void);
-extern void Keymap_LoadRemapFile(char *pszFileName);
+extern void Keymap_LoadRemapFile(const char *pszFileName);
 extern void Keymap_DebounceAllKeys(void);
 extern void Keymap_KeyDown(SDL_Keysym *sdlkey);
 extern void Keymap_KeyUp(SDL_Keysym *sdlkey);
diff --git a/src/keymap.c b/src/keymap.c
index 404ce776..6efda8fd 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -4,9 +4,10 @@
   This file is distributed under the GNU General Public License, version=
 2
   or at your option any later version. Read the file gpl.txt for details=
..
=20
-  Here we process a key press and the remapping of the scancodes.
+  This file is about being able to map SDL key events to scancodes to se=
nd
+  to the IKBD as pressed/released keys.
+  It is done in several ways, controlled by the configuration.
 */
-const char Keymap_fileid[] =3D "Hatari keymap.c";
=20
 #include <ctype.h>
 #include "main.h"
@@ -21,21 +22,49 @@ const char Keymap_fileid[] =3D "Hatari keymap.c";
 #include "debugui.h"
 #include "log.h"
=20
+/* Highest scancode number. See https://wiki.libsdl.org/SDLScancodeLooku=
p */
+#define MAX_SDLK_SCANCODES 284+1=20
=20
-/* Table for loaded keys: */
-static int LoadedKeymap[KBD_MAX_SCANCODE][2];
+/* Scancodes of ST keyboard */
+#define ST_ESC		 0x01
+#define ST_CTRL		0x1d
+#define ST_LSHIFT	0x2a
+#define ST_RSHIFT	0x36
+#define ST_ALTERNATE 	0x38
+#define ST_CAPSLOCK	0x3a
+
+/* Key mappings: pair a SDL definition with a list of keys we have to pr=
ess/release on the ST */
+#define MAX_ST_SCANCODES 4 /* Max is alt-a-b-c, so 4 chars */
+struct KeyMapping
+{
+	/* Input on PC keyboard */
+	SDL_keysym SdlKeysym;
+	SDL_Keymod modmask;
+	/* Output on the ST's keyboard */
+	uint8_t	   STScanCodesLength;
+	uint8_t    STScanCodes[MAX_ST_SCANCODES];
+	/* What modifiers we effectively had to press (and will have to release=
 when the key is up.
+	 * WARNING: this assumes the keyboard doesn't let you press a key that =
is already pressed. */
+	uint8_t	   PressedModifiers[MAX_ST_SCANCODES];
+};
+static struct KeyMapping LoadedKeyMap[KBD_MAX_SCANCODE];
+static struct KeyMapping KeysDownMapping[MAX_SDLK_SCANCODES]; /* Mapping=
s associated with keys when they're down. The index is the SDL scancode. =
*/
=20
 /* List of ST scan codes to NOT de-bounce when running in maximum speed =
*/
 static const char DebounceExtendedKeys[] =3D
 {
-	0x1d,  /* CTRL */
-	0x2a,  /* Left SHIFT */
-	0x01,  /* ESC */
-	0x38,  /* ALT */
-	0x36,  /* Right SHIFT */
-	0      /* term */
+	ST_CTRL,
+	ST_LSHIFT,
+	ST_ESC,
+	ST_ALTERNATE,
+	ST_RSHIFT,
+	0  /* End of list */
 };
=20
+/* Helper functions for parsing the keymap file */
+static int HostSpecToSDLKeysym(const char *spec, struct KeyMapping* resu=
lt);
+static int GuestSpecToSTScanCodes(const char *spec, struct KeyMapping *r=
esult);
+static SDL_Keymod SDLKeymodFromName(const char *name);
=20
=20
 /*----------------------------------------------------------------------=
-*/
@@ -47,12 +76,14 @@ void Keymap_Init(void)
 	Keymap_LoadRemapFile(ConfigureParams.Keyboard.szMappingFileName);
 }
=20
+
 /**
- * Map SDL symbolic key to ST scan code
+ * Map SDL symbolic key to ST scan code.
+ * This assumes a QWERTY ST keyboard.
  */
-static char Keymap_SymbolicToStScanCode(SDL_keysym* pKeySym)
+static uint8_t Keymap_SymbolicToStScanCode(const SDL_keysym* pKeySym)
 {
-	char code;
+	uint8_t code;
=20
 	switch (pKeySym->sym)
 	{
@@ -60,7 +91,7 @@ static char Keymap_SymbolicToStScanCode(SDL_keysym* pKe=
ySym)
 	 case SDLK_TAB: code =3D 0x0F; break;
 	 case SDLK_CLEAR: code =3D 0x47; break;
 	 case SDLK_RETURN: code =3D 0x1C; break;
-	 case SDLK_ESCAPE: code =3D 0x01; break;
+	 case SDLK_ESCAPE: code =3D ST_ESC; break;
 	 case SDLK_SPACE: code =3D 0x39; break;
 	 case SDLK_EXCLAIM: code =3D 0x09; break;     /* on azerty? */
 	 case SDLK_QUOTEDBL: code =3D 0x04; break;    /* on azerty? */
@@ -175,14 +206,14 @@ static char Keymap_SymbolicToStScanCode(SDL_keysym*=
 pKeySym)
 	 case SDLK_F12: code =3D 0x61; break;
 	 case SDLK_F13: code =3D 0x62; break;
 	 /* Key state modifier keys */
-	 case SDLK_CAPSLOCK: code =3D 0x3A; break;
+	 case SDLK_CAPSLOCK: code =3D ST_CAPSLOCK; break;
 	 case SDLK_SCROLLOCK: code =3D 0x61; break;
-	 case SDLK_RSHIFT: code =3D 0x36; break;
-	 case SDLK_LSHIFT: code =3D 0x2A; break;
-	 case SDLK_RCTRL: code =3D 0x1D; break;
-	 case SDLK_LCTRL: code =3D 0x1D; break;
-	 case SDLK_RALT: code =3D 0x38; break;
-	 case SDLK_LALT: code =3D 0x38; break;
+	 case SDLK_RSHIFT: code =3D ST_RSHIFT; break;
+	 case SDLK_LSHIFT: code =3D ST_LSHIFT; break;
+	 case SDLK_RCTRL: code =3D ST_CTRL; break;
+	 case SDLK_LCTRL: code =3D ST_CTRL; break;
+	 case SDLK_RALT: code =3D ST_ALTERNATE; break;
+	 case SDLK_LALT: code =3D ST_ALTERNATE; break;
 	 /* Miscellaneous function keys */
 	 case SDLK_HELP: code =3D 0x62; break;
 	 case SDLK_PRINT: code =3D 0x62; break;
@@ -197,7 +228,7 @@ static char Keymap_SymbolicToStScanCode(SDL_keysym* p=
KeySym)
 /**
  * Remap SDL scancode key to ST Scan code - this is the version for SDL2
  */
-static char Keymap_PcToStScanCode(SDL_keysym* pKeySym)
+static uint8_t Keymap_PcToStScanCode(const SDL_keysym* pKeySym)
 {
 	switch (pKeySym->scancode)
 	{
@@ -298,7 +329,7 @@ static char Keymap_PcToStScanCode(SDL_keysym* pKeySym=
)
 	 case SDL_SCANCODE_KP_0: return 0x70;
 	 case SDL_SCANCODE_KP_PERIOD: return 0x71;
 	 case SDL_SCANCODE_NONUSBACKSLASH: return 0x60;
-	 //case SDL_SCANCODE_APPLICATION: return ;
+	 /*case SDL_SCANCODE_APPLICATION: return ;*/
 	 case SDL_SCANCODE_KP_EQUALS: return 0x63;
 	 case SDL_SCANCODE_F13: return 0x63;
 	 case SDL_SCANCODE_F14: return 0x64;
@@ -317,11 +348,11 @@ static char Keymap_PcToStScanCode(SDL_keysym* pKeyS=
ym)
 	 case SDL_SCANCODE_KP_HASH: return 0x0c;
 	 case SDL_SCANCODE_KP_SPACE: return 0x39;
 	 case SDL_SCANCODE_KP_CLEAR: return 0x47;
-	 case SDL_SCANCODE_LCTRL: return 0x1d;
-	 case SDL_SCANCODE_LSHIFT: return 0x2a;
-	 case SDL_SCANCODE_LALT: return 0x38;
-	 case SDL_SCANCODE_RCTRL: return 0x1d;
-	 case SDL_SCANCODE_RSHIFT: return 0x36;
+	 case SDL_SCANCODE_LCTRL: return ST_CTRL;
+	 case SDL_SCANCODE_LSHIFT: return ST_LSHIFT;
+	 case SDL_SCANCODE_LALT: return ST_ALTERNATE;
+	 case SDL_SCANCODE_RCTRL: return ST_CTRL;
+	 case SDL_SCANCODE_RSHIFT: return ST_RSHIFT;
 	 default:
 		if (!pKeySym->scancode && pKeySym->sym)
 		{
@@ -343,7 +374,7 @@ static char Keymap_PcToStScanCode(SDL_keysym* pKeySym=
)
  * so that we can easily toggle between number and cursor mode with the
  * numlock key.
  */
-static char Keymap_GetKeyPadScanCode(SDL_keysym* pKeySym)
+static char Keymap_GetKeyPadScanCode(const SDL_keysym* pKeySym)
 {
 	if (SDL_GetModState() & KMOD_NUM)
 	{
@@ -382,39 +413,78 @@ static char Keymap_GetKeyPadScanCode(SDL_keysym* pK=
eySym)
 }
=20
=20
+static int InputMatchesKeyMapping(const SDL_keysym* keySym, const struct=
 KeyMapping *mapping)
+{
+	if (keySym->scancode =3D=3D mapping->SdlKeysym.scancode)
+		LOG_TRACE(TRACE_KEYMAP,"matching 0x%04x and 0x%04x\n", keySym->mod & m=
apping->modmask, mapping->SdlKeysym.mod);
+	return keySym->scancode =3D=3D mapping->SdlKeysym.scancode
+		&& (keySym->mod & mapping->modmask) =3D=3D mapping->SdlKeysym.mod;
+}
+
+
 /**
  * Remap SDL Key to ST Scan code
+ * Receives the pressed key from SDL, and returns a matching key mapping=
..
  */
-static char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
+static struct KeyMapping* Keymap_RemapKeyToSTScanCodes(SDL_keysym* pKeyS=
ym, bool enableTrace)
 {
+	struct KeyMapping *keyDownMapping =3D &KeysDownMapping[pKeySym->scancod=
e];
+
 	/* Check for keypad first so we can handle numlock */
 	if (ConfigureParams.Keyboard.nKeymapType !=3D KEYMAP_LOADED)
 	{
 		if (pKeySym->sym >=3D SDLK_KP1 && pKeySym->sym <=3D SDLK_KP9)
 		{
-			return Keymap_GetKeyPadScanCode(pKeySym);
+			keyDownMapping->STScanCodes[0] =3D Keymap_GetKeyPadScanCode(pKeySym);
+			keyDownMapping->STScanCodesLength =3D 1;
+			return keyDownMapping;
 		}
 	}
=20
 	/* Remap from PC scancodes? */
 	if (ConfigureParams.Keyboard.nKeymapType =3D=3D KEYMAP_SCANCODE)
 	{
-		return Keymap_PcToStScanCode(pKeySym);
+		keyDownMapping->STScanCodes[0] =3D Keymap_PcToStScanCode(pKeySym);
+		keyDownMapping->STScanCodesLength =3D 1;
+		return keyDownMapping;
 	}
=20
 	/* Use loaded keymap? */
 	if (ConfigureParams.Keyboard.nKeymapType =3D=3D KEYMAP_LOADED)
 	{
-		int i;
-		for (i =3D 0; i < KBD_MAX_SCANCODE && LoadedKeymap[i][1] !=3D 0; i++)
+		int i,j;
+
+		for (i =3D 0; i < KBD_MAX_SCANCODE; i++)
 		{
-			if (pKeySym->sym =3D=3D (SDLKey)LoadedKeymap[i][0])
-				return LoadedKeymap[i][1];
+			struct KeyMapping *mapping =3D &LoadedKeyMap[i];
+
+			if (mapping->SdlKeysym.scancode =3D=3D 0)
+				break; /* End of table */
+
+			if (!InputMatchesKeyMapping(pKeySym, mapping))
+				continue;
+
+			if (enableTrace)
+			{
+				/* This is pretty inefficient, that's why it's protected by a switch=
 */
+				LOG_TRACE(TRACE_KEYMAP,"  Mapping: ");
+				for (j =3D 0; j < mapping->STScanCodesLength; j++)
+					LOG_TRACE(TRACE_KEYMAP,"%02x ", mapping->STScanCodes[j]);
+				LOG_TRACE(TRACE_KEYMAP,"(from keymap)\n");
+			}
+
+			*keyDownMapping =3D *mapping;
+			return keyDownMapping;
 		}
 	}
=20
-	/* Use symbolic mapping */
-	return Keymap_SymbolicToStScanCode(pKeySym);
+	/* Fall back to symbolic mapping */
+	keyDownMapping->STScanCodes[0] =3D Keymap_SymbolicToStScanCode(pKeySym)=
;
+	keyDownMapping->STScanCodesLength =3D 1;
+
+	if (enableTrace)
+		LOG_TRACE(TRACE_KEYMAP,"  Mapping: %02x (symbolic)\n",keyDownMapping->=
STScanCodes[0]);
+	return keyDownMapping;
 }
=20
=20
@@ -422,20 +492,28 @@ static char Keymap_RemapKeyToSTScanCode(SDL_keysym*=
 pKeySym)
 /**
  * Load keyboard remap file
  */
-void Keymap_LoadRemapFile(char *pszFileName)
+void Keymap_LoadRemapFile(const char *pszFileName)
 {
-	char szString[1024];
-	int STScanCode, PCKeyCode;
+	char mapLine[1024];
+	int hostSpecIsOk, guestSpecIsOk;
 	FILE *in;
 	int idx =3D 0;
+	int lineNumber =3D 0; /* For logging purposes            */
+	char *token;
+	char *saveptr;		/* For saving strtok_r's state, because host/guest anal=
yses may also use strtok */
+	char hostSpec[50]; 	/* Host (PC) keys specification    */
+	char guestSpec[50];	/* Guest's (ST) keys specification */
+	const char invalidSpecificationMessage[] =3D "Keymap_LoadRemapFile: '%s=
' not a valid specification at line %d\n";
+
+	Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: Loading '%s'\n", pszFileNa=
me);
=20
 	/* Initialize table with default values */
-	memset(LoadedKeymap, 0, sizeof(LoadedKeymap));
+	memset(LoadedKeyMap, 0, sizeof(LoadedKeyMap));
=20
-	if (!*pszFileName)
+	if (strlen(pszFileName) =3D=3D 0)
 		return;
=20
-	/* Attempt to load file */
+	/* Attempt to load mapping file */
 	if (!File_Exists(pszFileName))
 	{
 		Log_Printf(LOG_DEBUG, "Keymap_LoadRemapFile: '%s' not a file\n", pszFi=
leName);
@@ -444,66 +522,153 @@ void Keymap_LoadRemapFile(char *pszFileName)
 	in =3D fopen(pszFileName, "r");
 	if (!in)
 	{
-		Log_Printf(LOG_ERROR, "Keymap_LoadRemapFile: failed to "
-			   " open keymap file '%s'\n", pszFileName);
+		Log_Printf(LOG_ERROR, "Keymap_LoadRemapFile: failed to open keymap fil=
e '%s'\n", pszFileName);
 		return;
 	}
=20
 	while (!feof(in) && idx < KBD_MAX_SCANCODE)
 	{
 		/* Read line from file */
-		if (fgets(szString, sizeof(szString), in) =3D=3D NULL)
+		if (fgets(mapLine, sizeof(mapLine), in) =3D=3D NULL)
 			break;
+
+		++lineNumber;
+
 		/* Remove white-space from start of line */
-		Str_Trim(szString);
-		if (strlen(szString)>0)
+		Str_Trim(mapLine);
+
+		/* Ignore empty line and comments */
+		if (strlen(mapLine) =3D=3D 0 || mapLine[0] =3D=3D ';' || mapLine[0] =3D=
=3D '#')
+			continue;
+
+		/* Cut out the values between host and guest parts */
+		token =3D strtok_r(mapLine, ",", &saveptr);
+		if (token =3D=3D NULL)
+			goto invalidSpecificationError;
+
+		/* Get the host's key specification */
+		strcpy(hostSpec,token);
+		Str_Trim(hostSpec);
+		if (strlen(hostSpec) =3D=3D 0)
+			goto invalidSpecificationError;
+		hostSpecIsOk =3D HostSpecToSDLKeysym(hostSpec, &LoadedKeyMap[idx]);
+
+		/* Get the guest (ST) specification */
+		token =3D strtok_r(NULL, "\n", &saveptr);
+
+		if (token =3D=3D NULL)
+			continue;
+		strcpy(guestSpec,token);
+		Str_Trim(guestSpec);
+		if (strlen(guestSpec) =3D=3D 0)
+			goto invalidSpecificationError;
+		guestSpecIsOk =3D GuestSpecToSTScanCodes(guestSpec, &LoadedKeyMap[idx]=
);
+
+		/* Store into remap table, check both value within range */
+		if (guestSpecIsOk && hostSpecIsOk)
 		{
-			char *p;
-			/* Is a comment? */
-			if (szString[0] =3D=3D ';' || szString[0] =3D=3D '#')
-				continue;
-			/* Cut out the values */
-			p =3D strtok(szString, ",");
-			if (!p)
-				continue;
-			Str_Trim(szString);
-			PCKeyCode =3D atoi(szString);    /* Direct key code? */
-			if (PCKeyCode < 10)
-			{
-				/* If it's not a valid number >=3D 10, then
-				 * assume we've got a symbolic key name
-				 */
-				int offset =3D 0;
-				/* quoted character (e.g. comment line char)? */
-				if (*szString =3D=3D '\\' && strlen(szString) =3D=3D 2)
-					offset =3D 1;
-				PCKeyCode =3D Keymap_GetKeyFromName(szString+offset);
-			}
-			p =3D strtok(NULL, "\n");
-			if (!p)
-				continue;
-			STScanCode =3D atoi(p);
-			/* Store into remap table, check both value within range */
-			if (STScanCode > 0 && STScanCode <=3D KBD_MAX_SCANCODE
-			    && PCKeyCode >=3D 8)
-			{
-				LOG_TRACE(TRACE_KEYMAP,
-				          "keymap from file: sym=3D%i --> scan=3D%i\n",
-				          PCKeyCode, STScanCode);
-				LoadedKeymap[idx][0] =3D PCKeyCode;
-				LoadedKeymap[idx][1] =3D STScanCode;
-				idx +=3D 1;
-			}
+			LOG_TRACE(TRACE_KEYMAP,"keymap from file: host %s --> guest %s\n", ho=
stSpec, guestSpec);
+			idx +=3D 1;
+		}
+		else
+		{
+			Log_Printf(LOG_WARN, "Could not parse keymap specification: %s\n", ma=
pLine);
+		}
+
+		continue;
+
+invalidSpecificationError:
+			Log_Printf(LOG_ERROR, invalidSpecificationMessage, pszFileName, lineN=
umber);
+	}
+
+	fclose(in);
+}
+
+
+static int HostSpecToSDLKeysym(const char *spec, struct KeyMapping* resu=
lt)
+{
+	/* Analyses the host (PC) specification from the table file and populat=
e the keymapping */
+	char buf[100];
+	char *token;
+	SDL_Scancode scancode;
+
+	/* Prepare buffer */
+	strcpy(buf, spec);
+
+	/* Prepare for early returns */
+	result->SdlKeysym.mod =3D 0;
+	result->modmask =3D 0;
+
+	/* Scancode part */
+	token =3D strtok(buf,"|");
+	if (token !=3D NULL && (scancode =3D strtol(token, NULL, 16)))
+		result->SdlKeysym.scancode =3D scancode;
+	else
+		return 0;
+
+	/* Modifier part */
+	token =3D strtok(NULL,"|");
+	if (token !=3D NULL)
+	{
+		/* We have a modifier specified */
+		result->SdlKeysym.mod =3D SDLKeymodFromName(token);
+
+		/* "modifier mask" part */
+		token =3D strtok(NULL,"|");
+		if (token !=3D NULL)
+			result->modmask =3D SDLKeymodFromName(token);
+	}
+
+	return -1; /* Success */
+}
+
+
+static int GuestSpecToSTScanCodes(const char *spec, struct KeyMapping* m=
apping)
+{
+	/* Analyses the guest (Atari ST keyboard) specification from the table =
file */
+	char buf[100];
+	char *start;
+	char *separator;
+	uint8_t *scancodes =3D mapping->STScanCodes; /* Alias for readability *=
/
+	uint8_t scancode;
+	int i =3D 0;
+
+	strcpy(buf, spec);
+	separator =3D buf-1;
+	do
+	{
+		start =3D separator+1;
+		separator =3D strchr(start, '|');
+		if (separator !=3D NULL)
+			*separator =3D '\0';
+
+		if (strlen(start) <=3D 2)
+		{
+			scancode =3D strtol(start, NULL, 16);
+		}
+		else
+		{
+			/* Scancode may be expressed as LSHIFT,RSHIFT,ALTERNATE for user conv=
enience */
+			if (strcmp(start, "LSHIFT") =3D=3D 0)
+				scancode =3D ST_LSHIFT;
+			else if (strcmp(start, "RSHIFT") =3D=3D 0)
+				scancode =3D ST_RSHIFT;
+			else if (strcmp(start, "ALTERNATE") =3D=3D 0)
+				scancode =3D ST_ALTERNATE;
 			else
 			{
-				Log_Printf(LOG_WARN, "Could not parse keymap file:"
-				           " '%s' (%d >=3D 8), '%s' (0 > %d <=3D %d)\n",
-					   szString, PCKeyCode, p, STScanCode, KBD_MAX_SCANCODE);
+				Log_Printf(LOG_ERROR, "GuestSpecToSTScanCodes: Cannot understand sca=
ncode '%s'\n", start);
+				i =3D 0; /* Error out */
+				break;
 			}
 		}
-	}
=20
-	fclose(in);
+		scancodes[i++] =3D scancode;
+	} while (separator !=3D NULL);
+
+	mapping->STScanCodesLength =3D i;
+
+	return i > 0;
 }
=20
=20
@@ -573,17 +738,53 @@ void Keymap_DebounceAllKeys(void)
 }
=20
=20
+static bool IsKeyTranslatable(SDL_Keycode symkey)
+{
+	/* Ignore modifier keys that are not passed to the ST */
+	switch (symkey)
+	{
+		case SDLK_RALT:
+	 	case SDLK_LMETA:
+	 	case SDLK_RMETA:
+	 	case SDLK_MODE:
+	 	case SDLK_NUMLOCK:
+			return false;
+	}
+	return true;
+}
+
+
+/*----------------------------------------------------------------------=
-*/
+/* Returns true if the scancode is for a key that allows to a different =
character
+ * from the same key.
+ */
+static bool IsSTModifier(uint8_t scancode)
+{
+	switch (scancode)
+	{
+		case ST_LSHIFT:
+		case ST_RSHIFT:
+		case ST_ALTERNATE:
+			return true;
+	}
+	return false;
+}
+
+
 /*----------------------------------------------------------------------=
-*/
 /**
- * User press key down
+ * User pressed a key down
  */
 void Keymap_KeyDown(SDL_keysym *sdlkey)
 {
-	uint8_t STScanCode;
+	struct KeyMapping* mapping;
+	uint8_t* modifiers;
+	int i;
+	/* Convenience */
 	int symkey =3D sdlkey->sym;
 	int modkey =3D sdlkey->mod;
=20
-	LOG_TRACE(TRACE_KEYMAP, "key down: sym=3D%i scan=3D%i mod=3D0x%x name=3D=
'%s'\n",
+	LOG_TRACE(TRACE_KEYMAP, "Keymap_KeyDown: sym=3D%i scancode=3D0x%02x mod=
=3D0x%02x name=3D'%s'\n",
 	          symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
=20
 	if (ShortCut_CheckKeys(modkey, symkey, true))
@@ -594,39 +795,62 @@ void Keymap_KeyDown(SDL_keysym *sdlkey)
 	if (Joy_KeyDown(symkey, modkey))
 		return;
=20
-	/* Handle special keys */
-	if (symkey =3D=3D SDLK_RALT || symkey =3D=3D SDLK_LMETA || symkey =3D=3D=
 SDLK_RMETA
-	        || symkey =3D=3D SDLK_MODE || symkey =3D=3D SDLK_NUMLOCK)
-	{
-		/* Ignore modifier keys that aren't passed to the ST */
+	if (!IsKeyTranslatable(symkey))
 		return;
-	}
=20
-	STScanCode =3D Keymap_RemapKeyToSTScanCode(sdlkey);
-	LOG_TRACE(TRACE_KEYMAP, "key map: sym=3D0x%x to ST-scan=3D0x%02x\n", sy=
mkey, STScanCode);
-	if (STScanCode !=3D (uint8_t)-1)
+	mapping =3D Keymap_RemapKeyToSTScanCodes(sdlkey, true);
+	if (mapping =3D=3D NULL)
+		return;
+
+	int modcount =3D 0;
+
+	modifiers =3D mapping->PressedModifiers;
+	for (i =3D 0; i < mapping->STScanCodesLength ; i++)
 	{
-		if (!Keyboard.KeyStates[STScanCode])
+		uint8_t scancode =3D mapping->STScanCodes[i];
+
+		Keyboard.KeyStates[scancode]++;
+
+		/* If it's a modifier that we're pressing, remember to release it late=
r.
+		 * In case you're wondering why we don't release the modifiers immedia=
tely after
+		 * pressing the key: the reason is that if the user keeps the key down=
 to make it
+		 * repeat, the modifiers need to be there, otherwise it is the "unshif=
ter/unalted"
+		 * character that will repeat instead.
+		 * TODO: Unfortunately this causes a bug as the modifiers will accumul=
ate if you
+		 * press multiple modified keys at once. For example, if on a French k=
eyboard you
+		 * press ALT-5 (to get a [), the ALTERNATE modifier will be retained. =
Holding that
+		 * ALT down and pressing the key 6 at the same time (to get |), the | =
only requires
+		 * SHIFT to be pressed. But ALTERNATE also being emulated, you will ge=
t ~.
+		 * To maybe fix that we would have to manage a stack of modifiers, so =
we could
+		 * release ALT while 7 is pressed (as it only requires SHIFT) then pre=
ss it again
+		 * when 7 is released. Is it really worth the effort... */
+		if (IsSTModifier(scancode))
 		{
-			/* Set down */
-			Keyboard.KeyStates[STScanCode] =3D true;
-			IKBD_PressSTKey(STScanCode, true);
+			*modifiers++ =3D scancode;
+			modcount++;
 		}
+
+		/* If that key was not already pressed, press it */
+		if (Keyboard.KeyStates[scancode] =3D=3D 1)
+			IKBD_PressSTKey(scancode, true);
 	}
+	*modifiers =3D 0; /* End the list of modifiers */
 }
=20
=20
 /*----------------------------------------------------------------------=
-*/
 /**
- * User released key
+ * User released a key
  */
 void Keymap_KeyUp(SDL_keysym *sdlkey)
 {
-	uint8_t STScanCode;
+	struct KeyMapping *mapping;
+	uint8_t *modifier;
+	int i;
 	int symkey =3D sdlkey->sym;
 	int modkey =3D sdlkey->mod;
=20
-	LOG_TRACE(TRACE_KEYMAP, "key up: sym=3D%i scan=3D%i mod=3D0x%x name=3D'=
%s'\n",
+	LOG_TRACE(TRACE_KEYMAP, "Keymap_KeyUp: sym=3D%i scancode=3D0x%02x mod=3D=
0x%02x name=3D'%s'\n",
 	          symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
=20
 	/* Ignore short-cut keys here */
@@ -639,25 +863,58 @@ void Keymap_KeyUp(SDL_keysym *sdlkey)
 		return;
=20
 	/* Handle special keys */
-	if (symkey =3D=3D SDLK_RALT || symkey =3D=3D SDLK_LMETA || symkey =3D=3D=
 SDLK_RMETA
-	        || symkey =3D=3D SDLK_MODE || symkey =3D=3D SDLK_NUMLOCK)
+	if (!IsKeyTranslatable(symkey))
 	{
-		/* Ignore modifier keys that aren't passed to the ST */
+		LOG_TRACE(TRACE_KEYMAP, "   Key not translatable to ST keyboard.\n");
+		return;
+	}
+
+	mapping =3D &KeysDownMapping[sdlkey->scancode];
+
+	if (mapping =3D=3D NULL)
+	{
+		Log_Printf(LOG_ERROR, "  No key mapping found !\n");
 		return;
 	}
=20
-	STScanCode =3D Keymap_RemapKeyToSTScanCode(sdlkey);
 	/* Release key (only if was pressed) */
-	if (STScanCode !=3D (uint8_t)-1)
+	for (i =3D 0; i < mapping->STScanCodesLength ; i++)
+	{
+		uint8_t scancode =3D mapping->STScanCodes[i];
+
+		if (IsSTModifier(scancode) && mapping->STScanCodesLength > 1)
+			continue; /* We release emulated modifiers last */
+
+		/* Set up */
+		if (Keyboard.KeyStates[scancode])
+		{
+			LOG_TRACE(TRACE_KEYMAP,"  %02x was down, will be up'ed\n",scancode);
+
+			Keyboard.KeyStates[scancode]--;
+			IKBD_PressSTKey(scancode, false);
+		}
+		else
+			LOG_TRACE(TRACE_KEYMAP,"  %02x will be kept down (presses: %d)\n",sca=
ncode,Keyboard.KeyStates[scancode]);
+
+	}
+
+	/* Release modifiers that were pressed to emulate the key*/
+	modifier =3D mapping->PressedModifiers;
+	while (*modifier)
 	{
-		if (Keyboard.KeyStates[STScanCode])
+		if (Keyboard.KeyStates[*modifier] !=3D 0)
 		{
-			IKBD_PressSTKey(STScanCode, false);
-			Keyboard.KeyStates[STScanCode] =3D false;
+			if (--Keyboard.KeyStates[*modifier] =3D=3D 0)
+				IKBD_PressSTKey(*modifier, false);
 		}
+		modifier++;
 	}
+
+	/* Trace state of modifiers */
+	LOG_TRACE(TRACE_KEYMAP,"  LS:%d LR:%d CTRL:%d ALT:%d\n",Keyboard.KeySta=
tes[ST_LSHIFT],Keyboard.KeyStates[ST_RSHIFT],Keyboard.KeyStates[ST_CTRL],=
Keyboard.KeyStates[ST_ALTERNATE]);
 }
=20
+
 /*----------------------------------------------------------------------=
-*/
 /**
  * Simulate press or release of a key corresponding to given character
@@ -665,24 +922,33 @@ void Keymap_KeyUp(SDL_keysym *sdlkey)
 void Keymap_SimulateCharacter(char asckey, bool press)
 {
 	SDL_keysym sdlkey;
-
 	sdlkey.mod =3D KMOD_NONE;
 	sdlkey.scancode =3D 0;
-	if (isupper((unsigned char)asckey)) {
-		if (press) {
+
+	if (isupper((unsigned char)asckey))
+	{
+		if (press)
+		{
 			sdlkey.sym =3D SDLK_LSHIFT;
 			Keymap_KeyDown(&sdlkey);
 		}
 		sdlkey.sym =3D tolower((unsigned char)asckey);
 		sdlkey.mod =3D KMOD_LSHIFT;
-	} else {
+	}
+	else
+	{
 		sdlkey.sym =3D asckey;
 	}
-	if (press) {
+
+	if (press)
+	{
 		Keymap_KeyDown(&sdlkey);
-	} else {
+	}
+	else
+	{
 		Keymap_KeyUp(&sdlkey);
-		if (isupper((unsigned char)asckey)) {
+		if (isupper((unsigned char)asckey))
+		{
 			sdlkey.sym =3D SDLK_LSHIFT;
 			Keymap_KeyUp(&sdlkey);
 		}
@@ -690,15 +956,49 @@ void Keymap_SimulateCharacter(char asckey, bool pre=
ss)
 }
=20
=20
-int Keymap_GetKeyFromName(const char *name)
+SDL_Keycode Keymap_GetKeyFromName(const char *name)
 {
 	return SDL_GetKeyFromName(name);
 }
=20
-const char *Keymap_GetKeyName(int keycode)
+
+const char *Keymap_GetKeyName(SDL_Keycode keycode)
 {
-	if (!keycode)
-		return "";
+	return keycode ? SDL_GetKeyName(keycode) : "";
+}
+
+
+static SDL_Keymod SDLKeymodFromName(const char *name) {
+	struct {
+		SDL_Keymod mod;
+		const char *name;
+	} const keymodNames[] =3D {
+		{ KMOD_NONE, "KMOD_NONE" },
+		{ KMOD_LSHIFT, "KMOD_LSHIFT" },
+		{ KMOD_RSHIFT, "KMOD_RSHIFT" },
+		{ KMOD_LCTRL, "KMOD_LCTRL" },
+		{ KMOD_RCTRL, "KMOD_RCTRL" },
+		{ KMOD_LALT, "KMOD_LALT" },
+		{ KMOD_RALT, "KMOD_RALT" },
+		{ KMOD_LGUI, "KMOD_LGUI" },
+		{ KMOD_RGUI, "KMOD_RGUI" },
+		{ KMOD_NUM, "KMOD_NUM" },
+		{ KMOD_CAPS, "KMOD_CAPS" },
+		{ KMOD_MODE, "KMOD_MODE" },
+		{ KMOD_CTRL, "KMOD_CTRL" },
+		{ KMOD_SHIFT, "KMOD_SHIFT" },
+		{ KMOD_ALT, "KMOD_ALT" },
+		{ KMOD_GUI, "KMOD_GUI" },
+		{ 0/*whatever*/, NULL }};
+
+	int i;
+	for (i =3D 0; keymodNames[i].name !=3D NULL; i++)
+	{
+		if (strcmp(name, keymodNames[i].name) =3D=3D 0)
+			return keymodNames[i].mod;
+	};
+
+	LOG_TRACE(TRACE_KEYMAP, "SDLKeymodFromName: Didn't find SDL_Keymod \"%s=
\", defaulting to KMOD_NONE.\n", name);
=20
-	return SDL_GetKeyName(keycode);
+	return KMOD_NONE;
 }
--=20
2.25.1




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/