[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
]
- Subject: [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.
- From: Vincent Barrilliot <vincent.barrilliot@xxxxxx>
- Date: Sun, 3 Jan 2021 18:44:02 +0100
---
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