Re: [hatari-devel] Fwd: Fwd: Hatari and keymap

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


Hi,
	
On my PC-Fr Keyboard, for inserting a '{' I must press keys
  - 'AltGr' (mod 0x200)
  - '4'     (scancode 33)
So this sequence must be --translate-- like if I press on the Atari
ST-Fr Keyboard "SHIFT and ALT together with that key that is on the
right of "P" :
  - SHIFT       : scancode 0x2A
  - ALT         : scancode 0x38
  - key tioro P : scancode 0x1A

Now, with the patch, I can add in the keymap file this entry :

**** BEGIN
# '{'
@33-0x200,0x2A-0x38-0x1A
**** END

Now, when I press [scancode 33] + [AltGr(0x200)] the following sequence
is sent : ST-scancode 0x2A + ST-scancode 0x38 + ST-scancode 0x1A

PS : checkkeys utility uses SDL (not SDL2)! But, Hatari uses SDL2!
Scancode & mod are differents between SDL & SDL2.

JMV

Le 13/04/2020 à 05:51, Thomas Huth a écrit :
> Am Sat, 11 Apr 2020 14:24:59 +0200
> schrieb Nicolas Pomarède <npomarede@xxxxxxxxxxxx>:
> 
>> Hi
>>
>> these are some messages we sent privately about improving keymap for 
>> french keyboard. I thought it would be bette to send to devel list in 
>> case someone can comment on those patch or give a different solution.
>>
>> Original message is in english, then we switched to french, sorry for 
>> non french speakers :)
>>
>> JM Vic : please use english again on this mailing list, people are
>> from various countries and not everyone speak french :)
> 
> My french is a little bit rusty, but if I've got that right, the
> problem is how to get the "{" character on a French keyboard?
> Well, looking at the original Azerty keyboard of a french Atari ST, the
> "{" character can be found on the key that is on the right of the "P"
> key. So to get that character with a French TOS, you have to press
> SHIFT and ALT together with that key that is on the right of "P" on
> your keyboard (assuming that you are using the "scancode" keyboard
> mapping - not sure whether it works with the "symbolic" mapping on
> French keyboards, too).
> 
>  HTH,
>   Thomas
> 
> 
>>
>>
>> Le 11/04/2020 à 13:53, jmvic@xxxxxxxxxxx a écrit :
>>>
>>>
>>> -------- Message transféré --------
>>> Sujet : Re: Hatari and keymap
>>> Date : Tue, 7 Apr 2020 22:44:43 +0200
>>> De : Nicolas Pomarède <npomarede@xxxxxxxxxxxx>
>>> Pour : jmvic@xxxxxxxxxxx <jmvic@xxxxxxxxxxx>
>>>
>>> salut
>>>
>>> je dois avouer que je n'ai pas essayé récemment  de taper un '{'
>>> depuis hatari pour voir si ça marche. Il est en effet possible que
>>> ça ne marche pas :)
>>> Dans ce cas, l'idée d'envoyer une séquences de touches pourrait
>>> être une solution.
>>>
>>> Mais je ne suis pas le "spécialiste" de la partie clavier dans
>>> hatari qui fait la conversion TOS / OS local, d'autres devs l'ont
>>> écrite. Du coup, pour avoir des retours d'autres personnes qui ont
>>> peut être une autre façon de régler le pb que tu remontes, est-ce
>>> que tu pourrais poster ton message sur la mailing list hatari-devel
>>> ?
>>>
>>> Il n'y a pas trop de messages à suivre et c'est le meilleur moyen de
>>> centraliser des idées et que tout le monde puisse y réfléchir.
>>>
>>> Nicolas
>>>
>>> Le 07/04/2020 à 21:54, jmvic@xxxxxxxxxxx a écrit :  
>>>> Salut,
>>>> Alors oui, ça va grandement simplifier les choses pour moi, le
>>>> français...
>>>>
>>>> Merci pour ta réponse.
>>>> Initialement j'avais un problème avec le symbole '{'.
>>>> Configuré en "symbolique", la pression de la touche correspondante
>>>> sur mon clavier Fr me donne le symbole ''' !
>>>> Configuré en "scancode" même résultat !
>>>> J'ai alors voulu faire un fichier de mapping... Mais comment faire
>>>> alors pour associer au symbole '{' le scancode correspondant du ST
>>>> ? Puisque effectivement, pour produire ce symbole depuis le
>>>> clavier du ST il faut à la fois presser la touche Shift(scancode
>>>> 0x2A), Alt(scancode 0x38) et la touche de scancode 0x1A !
>>>> En effet, dans sa conception initiale, le fichier ne permet de
>>>> faire correspondre à un symbole qu'un unique scancode du ST...
>>>> Voilà voilà.
>>>> De plus, de ne pas trouver sur internet de fichier prêt à
>>>> l'emploie, m'a conforté dans l'idée que ce n'était pas possible de
>>>> faire ce que je voulais en l'état actuel des choses. Mais je me
>>>> trompe peut-être et même, au vu de ta réponse, sans doute ;) Le
>>>> besoin est tellement primordial qu'il doit être possible de le
>>>> faire. Mais comment ? Alors sans vouloir abuser de ton temps,
>>>> pourrais tu me mettre sur la voie ? Dans tout les cas, un grand
>>>> merci pour tout. JM Vic
>>>>  
>>>   
>>>>>
>>>>> bonjour
>>>>>
>>>>> je parle français, ça devrait être plus facile :)
>>>>>
>>>>> merci pour le clavier azerty, mais quel était le problème
>>>>> exactement avec ce que fait déjà hatari ? J'ai l'impression que
>>>>> les touches de mon clavier pc marchent déjà sous hatari, quel cas
>>>>> ce patch résout-il ?
>>>>>
>>>>> en tout cas merci de proposer des évolutions pour hatari et de les
>>>>> partager.
>>>>>
>>>>> Nicolas  
>>>   
>>>>> Le 06/04/2020 à 21:58, jmvic@xxxxxxxxxxx a écrit :  
>>>>>> Hello,
>>>>>> Sorry for my bad english.
>>>>>> First, thank you for Hatari!
>>>>>>
>>>>>> Now, my objective : get a complete keybinding with an Azerty
>>>>>> French PC keyboard, and an Azerty French(?) Atari STF keyboard.
>>>>>>
>>>>>> Actually, no solution seems really available.
>>>>>>
>>>>>> So, I made some change in keymap.c...
>>>>>>
>>>>>> Keymap file accepts a new line syntax:
>>>>>> @PC_SCANCODE[-PC_MOD],ST_SCANCODE[-ST_SCANCODE[...]]
>>>>>>
>>>>>> If the scancode+modifiers is pressed, then the ST scancode
>>>>>> --sequence-- is played.
>>>>>>
>>>>>> Hexadecimal representation can be use in all parts with the 0x
>>>>>> prefix.
>>>>>>
>>>>>> I did a minimum of test.
>>>>>>
>>>>>> Again, thank you a lot.
>>>>>>
>>>>>> JM Vic
>>>>>>  
>>>
>>>
>>>   
>>
>>
>>
diff --git a/doc/keymap-azerty-fr.txt b/doc/keymap-azerty-fr.txt
new file mode 100644
index 00000000..434a8572
--- /dev/null
+++ b/doc/keymap-azerty-fr.txt
@@ -0,0 +1,133 @@
+# This is an example for a keyboard mapping file that can be used in Hatari
+# 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 comma.
+# 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, but note that the values are different between SDL1 and SDL2
+# and thus they are not portable.
+#
+# 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 can be given as decimals or hexadecimals (with "0x" prefix).
+#
+# Syntaxe : <SDL Key>[-<SDL Key Mod>],<ST Scancode>[-<ST Scancode>[...]]
+#   <SDL Key>=<SDL Key Name> or <SDL Key SYMbole Code> or <SDL Key POSition/SCANCODE>
+#   Note:
+#     <ST Scancode> are playing in the given order; it's important!
+#     So, must be in first place, LShift(0x2A), LAlt(0x38), ...
+#
+# 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 1: If you want to get the 'y' and 'z' keys right with a german TOS
+# ROM, you can use the following two lines to map the PC keys to the right
+# ST scan codes:
+#Y,44
+#Z,21
+#
+# Example 2: Layout for Atari STF with AZERTY French Keyboard
+# 'q': @4=Position of key "q/Q" on an AZERTY French Keyboard
+#      => So, lower case letter "q" is targeted.
+#      30=ST Scancode of key "q/Q"
+@4,30
+# 'Q': @4=SDL Scancode; Position of key "q/Q" on an AZERTY French Keyboard
+#      -1=SDL Modifiers; Here, when LSHIFT is pressed
+#      => So, upper case letter "Q" is targeted.
+#      0x2A=ST Scancode of key LSHIFT
+#        30=ST Scancode of key "q/Q"
+@4-1,0x2A-30
+# ','
+@16,0x32
+# '?'
+@16-1,0x2A-0x32
+# 'a'
+@20,16
+# 'A'
+@20-1,0x2A-16
+# 'z'
+@26,17
+# 'Z'
+@26-1,0x2A-17
+# 'w'
+@29,44
+# 'W'
+@29-1,0x2A-44
+# '1'
+@30-1,0x2A-2
+# '2'
+@31-1,0x2A-3
+# '3'
+@32-1,0x2A-4
+# '#'
+@32-0x200,0x2B
+# '4'
+@33-1,0x2A-5
+# '{'
+@33-0x200,0x2A-0x38-0x1A
+# '5'
+@34-1,0x2A-6
+# '['
+@34-0x200,0x38-0x1A
+# '-'
+@35,13
+# '6'
+@35-1,0x2A-7
+# '|'
+@35-0x200,0x2A-0x2B
+# '7'
+@36-1,0x2A-8
+# '`'
+@36-0x200,0x29
+# '_'
+@37,0x2A-13
+# '8'
+@37-1,0x2A-9
+# '\'
+@37-0x200,0x38-0x28
+# '9'
+@38-1,0x2A-10
+# '^'
+@38-0x200,0x1A
+# '0'
+@39-1,0x2A-11
+# '@'
+@39-0x200,0x38-0x2B
+# '°'
+@45-1,0x2A-0x0C
+# ']'
+@45-0x200,0x38-0x1B
+# '='
+@46,0x35
+# '+'
+@46-1,0x2A-0x35
+# '}'
+@46-0x200,0x2A-0x38-0x1B
+# 'm'
+@51,0x27
+# 'M'
+@51-1,0x2A-0x27
+# 'ù'
+@52,0x28
+# '%'
+@52-1,0x2A-0x28
+# ";"
+@54,0x33
+# '.'
+@54-1,0x2A-0x33
+# '/'
+@55-1,0x2A-0x34
+# '>'
+@100-1,0x2A-0x60
+
diff --git a/src/keymap.c b/src/keymap.c
index 89833e17..f9c900c8 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -21,6 +21,104 @@ const char Keymap_fileid[] = "Hatari keymap.c : " __DATE__ " " __TIME__;
 #include "debugui.h"
 #include "log.h"
 
+#define MAX_KEYSYM_VALUE 255
+#define SIZEOF_KEYSYM_ARRAY (MAX_KEYSYM_VALUE + 1)
+#define SIZEOF_KEYPOS_ARRAY 256
+/* LoadedKeySym */
+typedef struct s_STScanCodeList
+{
+	char stScancode;
+	struct s_STScanCodeList *next;
+} t_STScanCodeList;
+
+typedef struct s_ModList
+{
+	int Mod;
+	struct s_STScanCodeList *stScancodeList;
+	struct s_ModList *next;
+} t_ModList;
+
+static t_ModList *findMod(t_ModList *ModList, int Mod)
+{
+	t_ModList *iter = ModList;
+	while (iter != NULL)
+	{
+		/* printf("iter->Mod=%d (expected %d)\n", iter->Mod, Mod); */
+		if (iter->Mod == Mod)
+		{
+			return iter;
+		}
+		iter = iter->next;
+	}
+	return NULL;
+}
+
+static t_ModList *addMod(t_ModList **ModList)
+{
+	t_ModList **iter = ModList;
+
+	for(;;)
+	{
+		if (*iter == NULL)
+		{
+			*iter = malloc(sizeof(t_ModList));
+			memset(*iter, 0, sizeof(t_ModList));
+			return *iter;
+		}
+		iter = &((*iter)->next);
+	}
+}
+
+static t_STScanCodeList *addSTScanCode(t_STScanCodeList **stScancodeList)
+{
+	t_STScanCodeList **iter = stScancodeList;
+
+	for(;;)
+	{
+		if (*iter == NULL)
+		{
+			*iter = malloc(sizeof(t_STScanCodeList));
+			memset(*iter, 0, sizeof(t_STScanCodeList));
+			return *iter;
+		}
+		iter = &((*iter)->next);
+	}
+}
+
+static void cleanSTScanCodeList(t_STScanCodeList **stScancodeList)
+{
+	if (*stScancodeList == NULL)
+	{
+		return;
+	}
+	t_STScanCodeList *iter = *stScancodeList, *nextIter;
+	while (iter != NULL)
+	{
+		nextIter = iter->next;
+		free(iter);
+		iter = nextIter;
+	}
+	*stScancodeList = NULL;
+}
+
+static void cleanModList(t_ModList **ModList)
+{
+	if (*ModList == NULL)
+	{
+		return;
+	}
+	t_ModList *iter = *ModList, *nextIter;
+	while (iter != NULL)
+	{
+		nextIter = iter->next;
+		cleanSTScanCodeList(&(iter->stScancodeList));
+		free(iter);
+		iter = nextIter;
+	}
+	*ModList = NULL;
+}
+
+
 
 #if !WITH_SDL2
 /* This table is used to translate a symbolic keycode to the (SDL) scancode */
@@ -28,7 +126,11 @@ static Uint8 SdlSymToSdlScan[SDLK_LAST];
 #endif
 
 /* Table for loaded keys: */
-static int LoadedKeymap[KBD_MAX_SCANCODE][2];
+/*
+  sdl.event.sym -> LoadedKeySym[sdl.event.sym] -> list(<sdl.event.mod, list(stscancode)>)
+*/
+static t_ModList *LoadedKeySym[SIZEOF_KEYSYM_ARRAY];
+static t_ModList *LoadedKeyPos[SIZEOF_KEYPOS_ARRAY];
 
 /* List of ST scan codes to NOT de-bounce when running in maximum speed */
 static const char DebounceExtendedKeys[] =
@@ -64,151 +166,151 @@ static char Keymap_SymbolicToStScanCode(SDL_keysym* pKeySym)
 
 	switch (pKeySym->sym)
 	{
-	 case SDLK_BACKSPACE: code = 0x0E; break;
-	 case SDLK_TAB: code = 0x0F; break;
-	 case SDLK_CLEAR: code = 0x47; break;
-	 case SDLK_RETURN: code = 0x1C; break;
-	 case SDLK_ESCAPE: code = 0x01; break;
-	 case SDLK_SPACE: code = 0x39; break;
-	 case SDLK_EXCLAIM: code = 0x09; break;     /* on azerty? */
-	 case SDLK_QUOTEDBL: code = 0x04; break;    /* on azerty? */
-	 case SDLK_HASH: code = 0x29; break;
-	 case SDLK_DOLLAR: code = 0x1b; break;      /* on azerty */
-	 case SDLK_AMPERSAND: code = 0x02; break;   /* on azerty? */
-	 case SDLK_QUOTE: code = 0x28; break;
-	 case SDLK_LEFTPAREN: code = 0x63; break;
-	 case SDLK_RIGHTPAREN: code = 0x64; break;
-	 case SDLK_ASTERISK: code = 0x66; break;
-	 case SDLK_PLUS: code = 0x1B; break;
-	 case SDLK_COMMA: code = 0x33; break;
-	 case SDLK_MINUS: code = 0x35; break;
-	 case SDLK_PERIOD: code = 0x34; break;
-	 case SDLK_SLASH: code = 0x35; break;
-	 case SDLK_0: code = 0x0B; break;
-	 case SDLK_1: code = 0x02; break;
-	 case SDLK_2: code = 0x03; break;
-	 case SDLK_3: code = 0x04; break;
-	 case SDLK_4: code = 0x05; break;
-	 case SDLK_5: code = 0x06; break;
-	 case SDLK_6: code = 0x07; break;
-	 case SDLK_7: code = 0x08; break;
-	 case SDLK_8: code = 0x09; break;
-	 case SDLK_9: code = 0x0A; break;
-	 case SDLK_COLON: code = 0x34; break;
-	 case SDLK_SEMICOLON: code = 0x27; break;
-	 case SDLK_LESS: code = 0x60; break;
-	 case SDLK_EQUALS: code = 0x0D; break;
-	 case SDLK_GREATER : code = 0x34; break;
-	 case SDLK_QUESTION: code = 0x35; break;
-	 case SDLK_AT: code = 0x28; break;
-	 case SDLK_LEFTBRACKET: code = 0x63; break;
-	 case SDLK_BACKSLASH: code = 0x2B; break;     /* Might be 0x60 for UK keyboards */
-	 case SDLK_RIGHTBRACKET: code = 0x64; break;
-	 case SDLK_CARET: code = 0x2B; break;
-	 case SDLK_UNDERSCORE: code = 0x0C; break;
-	 case SDLK_BACKQUOTE: code = 0x52; break;
-	 case SDLK_a: code = 0x1E; break;
-	 case SDLK_b: code = 0x30; break;
-	 case SDLK_c: code = 0x2E; break;
-	 case SDLK_d: code = 0x20; break;
-	 case SDLK_e: code = 0x12; break;
-	 case SDLK_f: code = 0x21; break;
-	 case SDLK_g: code = 0x22; break;
-	 case SDLK_h: code = 0x23; break;
-	 case SDLK_i: code = 0x17; break;
-	 case SDLK_j: code = 0x24; break;
-	 case SDLK_k: code = 0x25; break;
-	 case SDLK_l: code = 0x26; break;
-	 case SDLK_m: code = 0x32; break;
-	 case SDLK_n: code = 0x31; break;
-	 case SDLK_o: code = 0x18; break;
-	 case SDLK_p: code = 0x19; break;
-	 case SDLK_q: code = 0x10; break;
-	 case SDLK_r: code = 0x13; break;
-	 case SDLK_s: code = 0x1F; break;
-	 case SDLK_t: code = 0x14; break;
-	 case SDLK_u: code = 0x16; break;
-	 case SDLK_v: code = 0x2F; break;
-	 case SDLK_w: code = 0x11; break;
-	 case SDLK_x: code = 0x2D; break;
-	 case SDLK_y: code = 0x15; break;
-	 case SDLK_z: code = 0x2C; break;
-	 case SDLK_DELETE: code = 0x53; break;
-	 /* End of ASCII mapped keysyms */
+		case SDLK_BACKSPACE: code = 0x0E; break;
+		case SDLK_TAB: code = 0x0F; break;
+		case SDLK_CLEAR: code = 0x47; break;
+		case SDLK_RETURN: code = 0x1C; break;
+		case SDLK_ESCAPE: code = 0x01; break;
+		case SDLK_SPACE: code = 0x39; break;
+		case SDLK_EXCLAIM: code = 0x09; break;     /* on azerty? */
+		case SDLK_QUOTEDBL: code = 0x04; break;    /* on azerty? */
+		case SDLK_HASH: code = 0x29; break;
+		case SDLK_DOLLAR: code = 0x1b; break;      /* on azerty */
+		case SDLK_AMPERSAND: code = 0x02; break;   /* on azerty? */
+		case SDLK_QUOTE: code = 0x28; break;
+		case SDLK_LEFTPAREN: code = 0x63; break;
+		case SDLK_RIGHTPAREN: code = 0x64; break;
+		case SDLK_ASTERISK: code = 0x66; break;
+		case SDLK_PLUS: code = 0x1B; break;
+		case SDLK_COMMA: code = 0x33; break;
+		case SDLK_MINUS: code = 0x35; break;
+		case SDLK_PERIOD: code = 0x34; break;
+		case SDLK_SLASH: code = 0x35; break;
+		case SDLK_0: code = 0x0B; break;
+		case SDLK_1: code = 0x02; break;
+		case SDLK_2: code = 0x03; break;
+		case SDLK_3: code = 0x04; break;
+		case SDLK_4: code = 0x05; break;
+		case SDLK_5: code = 0x06; break;
+		case SDLK_6: code = 0x07; break;
+		case SDLK_7: code = 0x08; break;
+		case SDLK_8: code = 0x09; break;
+		case SDLK_9: code = 0x0A; break;
+		case SDLK_COLON: code = 0x34; break;
+		case SDLK_SEMICOLON: code = 0x27; break;
+		case SDLK_LESS: code = 0x60; break;
+		case SDLK_EQUALS: code = 0x0D; break;
+		case SDLK_GREATER : code = 0x34; break;
+		case SDLK_QUESTION: code = 0x35; break;
+		case SDLK_AT: code = 0x28; break;
+		case SDLK_LEFTBRACKET: code = 0x63; break;
+		case SDLK_BACKSLASH: code = 0x2B; break;     /* Might be 0x60 for UK keyboards */
+		case SDLK_RIGHTBRACKET: code = 0x64; break;
+		case SDLK_CARET: code = 0x2B; break;
+		case SDLK_UNDERSCORE: code = 0x0C; break;
+		case SDLK_BACKQUOTE: code = 0x52; break;
+		case SDLK_a: code = 0x1E; break;
+		case SDLK_b: code = 0x30; break;
+		case SDLK_c: code = 0x2E; break;
+		case SDLK_d: code = 0x20; break;
+		case SDLK_e: code = 0x12; break;
+		case SDLK_f: code = 0x21; break;
+		case SDLK_g: code = 0x22; break;
+		case SDLK_h: code = 0x23; break;
+		case SDLK_i: code = 0x17; break;
+		case SDLK_j: code = 0x24; break;
+		case SDLK_k: code = 0x25; break;
+		case SDLK_l: code = 0x26; break;
+		case SDLK_m: code = 0x32; break;
+		case SDLK_n: code = 0x31; break;
+		case SDLK_o: code = 0x18; break;
+		case SDLK_p: code = 0x19; break;
+		case SDLK_q: code = 0x10; break;
+		case SDLK_r: code = 0x13; break;
+		case SDLK_s: code = 0x1F; break;
+		case SDLK_t: code = 0x14; break;
+		case SDLK_u: code = 0x16; break;
+		case SDLK_v: code = 0x2F; break;
+		case SDLK_w: code = 0x11; break;
+		case SDLK_x: code = 0x2D; break;
+		case SDLK_y: code = 0x15; break;
+		case SDLK_z: code = 0x2C; break;
+		case SDLK_DELETE: code = 0x53; break;
+			/* End of ASCII mapped keysyms */
 #if WITH_SDL2
-	 case 180: code = 0x0D; break;
-	 case 223: code = 0x0C; break;
-	 case 228: code = 0x28; break;
-	 case 246: code = 0x27; break;
-	 case 252: code = 0x1A; break;
+		case 180: code = 0x0D; break;
+		case 223: code = 0x0C; break;
+		case 228: code = 0x28; break;
+		case 246: code = 0x27; break;
+		case 252: code = 0x1A; break;
 #else /* !WITH_SDL2 */
-	 case SDLK_WORLD_0: code = 0x0d; break;
-	 case SDLK_WORLD_1: code = 0x0c; break;
-	 case SDLK_WORLD_2: code = 0x1a; break;
-	 case SDLK_WORLD_3: code = 0x28; break;
-	 case SDLK_WORLD_4: code = 0x27; break;
-	 case SDLK_WORLD_20: code = 0x0D; break;
-	 case SDLK_WORLD_63: code = 0x0C; break;
-	 case SDLK_WORLD_68: code = 0x28; break;
-	 case SDLK_WORLD_86: code = 0x27; break;
-	 case SDLK_WORLD_92: code = 0x1A; break;
+		case SDLK_WORLD_0: code = 0x0d; break;
+		case SDLK_WORLD_1: code = 0x0c; break;
+		case SDLK_WORLD_2: code = 0x1a; break;
+		case SDLK_WORLD_3: code = 0x28; break;
+		case SDLK_WORLD_4: code = 0x27; break;
+		case SDLK_WORLD_20: code = 0x0D; break;
+		case SDLK_WORLD_63: code = 0x0C; break;
+		case SDLK_WORLD_68: code = 0x28; break;
+		case SDLK_WORLD_86: code = 0x27; break;
+		case SDLK_WORLD_92: code = 0x1A; break;
 #endif /* !WITH_SDL2 */
-	 /* Numeric keypad: */
-	 case SDLK_KP0: code = 0x70; break;
-	 case SDLK_KP1: code = 0x6D; break;
-	 case SDLK_KP2: code = 0x6E; break;
-	 case SDLK_KP3: code = 0x6F; break;
-	 case SDLK_KP4: code = 0x6A; break;
-	 case SDLK_KP5: code = 0x6B; break;
-	 case SDLK_KP6: code = 0x6C; break;
-	 case SDLK_KP7: code = 0x67; break;
-	 case SDLK_KP8: code = 0x68; break;
-	 case SDLK_KP9: code = 0x69; break;
-	 case SDLK_KP_PERIOD: code = 0x71; break;
-	 case SDLK_KP_DIVIDE: code = 0x65; break;
-	 case SDLK_KP_MULTIPLY: code = 0x66; break;
-	 case SDLK_KP_MINUS: code = 0x4A; break;
-	 case SDLK_KP_PLUS: code = 0x4E; break;
-	 case SDLK_KP_ENTER: code = 0x72; break;
-	 case SDLK_KP_EQUALS: code = 0x61; break;
-	 /* Arrows + Home/End pad */
-	 case SDLK_UP: code = 0x48; break;
-	 case SDLK_DOWN: code = 0x50; break;
-	 case SDLK_RIGHT: code = 0x4D; break;
-	 case SDLK_LEFT: code = 0x4B; break;
-	 case SDLK_INSERT: code = 0x52; break;
-	 case SDLK_HOME: code = 0x47; break;
-	 case SDLK_END: code = 0x61; break;
-	 case SDLK_PAGEUP: code = 0x63; break;
-	 case SDLK_PAGEDOWN: code = 0x64; break;
-	 /* Function keys */
-	 case SDLK_F1: code = 0x3B; break;
-	 case SDLK_F2: code = 0x3C; break;
-	 case SDLK_F3: code = 0x3D; break;
-	 case SDLK_F4: code = 0x3E; break;
-	 case SDLK_F5: code = 0x3F; break;
-	 case SDLK_F6: code = 0x40; break;
-	 case SDLK_F7: code = 0x41; break;
-	 case SDLK_F8: code = 0x42; break;
-	 case SDLK_F9: code = 0x43; break;
-	 case SDLK_F10: code = 0x44; break;
-	 case SDLK_F11: code = 0x62; break;
-	 case SDLK_F12: code = 0x61; break;
-	 case SDLK_F13: code = 0x62; break;
-	 /* Key state modifier keys */
-	 case SDLK_CAPSLOCK: code = 0x3A; break;
-	 case SDLK_SCROLLOCK: code = 0x61; break;
-	 case SDLK_RSHIFT: code = 0x36; break;
-	 case SDLK_LSHIFT: code = 0x2A; break;
-	 case SDLK_RCTRL: code = 0x1D; break;
-	 case SDLK_LCTRL: code = 0x1D; break;
-	 case SDLK_RALT: code = 0x38; break;
-	 case SDLK_LALT: code = 0x38; break;
-	 /* Miscellaneous function keys */
-	 case SDLK_HELP: code = 0x62; break;
-	 case SDLK_PRINT: code = 0x62; break;
-	 case SDLK_UNDO: code = 0x61; break;
-	 default: code = -1;
+			/* Numeric keypad: */
+		case SDLK_KP0: code = 0x70; break;
+		case SDLK_KP1: code = 0x6D; break;
+		case SDLK_KP2: code = 0x6E; break;
+		case SDLK_KP3: code = 0x6F; break;
+		case SDLK_KP4: code = 0x6A; break;
+		case SDLK_KP5: code = 0x6B; break;
+		case SDLK_KP6: code = 0x6C; break;
+		case SDLK_KP7: code = 0x67; break;
+		case SDLK_KP8: code = 0x68; break;
+		case SDLK_KP9: code = 0x69; break;
+		case SDLK_KP_PERIOD: code = 0x71; break;
+		case SDLK_KP_DIVIDE: code = 0x65; break;
+		case SDLK_KP_MULTIPLY: code = 0x66; break;
+		case SDLK_KP_MINUS: code = 0x4A; break;
+		case SDLK_KP_PLUS: code = 0x4E; break;
+		case SDLK_KP_ENTER: code = 0x72; break;
+		case SDLK_KP_EQUALS: code = 0x61; break;
+			/* Arrows + Home/End pad */
+		case SDLK_UP: code = 0x48; break;
+		case SDLK_DOWN: code = 0x50; break;
+		case SDLK_RIGHT: code = 0x4D; break;
+		case SDLK_LEFT: code = 0x4B; break;
+		case SDLK_INSERT: code = 0x52; break;
+		case SDLK_HOME: code = 0x47; break;
+		case SDLK_END: code = 0x61; break;
+		case SDLK_PAGEUP: code = 0x63; break;
+		case SDLK_PAGEDOWN: code = 0x64; break;
+			/* Function keys */
+		case SDLK_F1: code = 0x3B; break;
+		case SDLK_F2: code = 0x3C; break;
+		case SDLK_F3: code = 0x3D; break;
+		case SDLK_F4: code = 0x3E; break;
+		case SDLK_F5: code = 0x3F; break;
+		case SDLK_F6: code = 0x40; break;
+		case SDLK_F7: code = 0x41; break;
+		case SDLK_F8: code = 0x42; break;
+		case SDLK_F9: code = 0x43; break;
+		case SDLK_F10: code = 0x44; break;
+		case SDLK_F11: code = 0x62; break;
+		case SDLK_F12: code = 0x61; break;
+		case SDLK_F13: code = 0x62; break;
+			/* Key state modifier keys */
+		case SDLK_CAPSLOCK: code = 0x3A; break;
+		case SDLK_SCROLLOCK: code = 0x61; break;
+		case SDLK_RSHIFT: code = 0x36; break;
+		case SDLK_LSHIFT: code = 0x2A; break;
+		case SDLK_RCTRL: code = 0x1D; break;
+		case SDLK_LCTRL: code = 0x1D; break;
+		case SDLK_RALT: code = 0x38; break;
+		case SDLK_LALT: code = 0x38; break;
+			/* Miscellaneous function keys */
+		case SDLK_HELP: code = 0x62; break;
+		case SDLK_PRINT: code = 0x62; break;
+		case SDLK_UNDO: code = 0x61; break;
+		default: code = -1;
 	}
 
 	return code;
@@ -224,139 +326,139 @@ static char Keymap_PcToStScanCode(SDL_keysym* pKeySym)
 {
 	switch (pKeySym->scancode)
 	{
-	 case SDL_SCANCODE_A: return 0x1e;
-	 case SDL_SCANCODE_B: return 0x30;
-	 case SDL_SCANCODE_C: return 0x2e;
-	 case SDL_SCANCODE_D: return 0x20;
-	 case SDL_SCANCODE_E: return 0x12;
-	 case SDL_SCANCODE_F: return 0x21;
-	 case SDL_SCANCODE_G: return 0x22;
-	 case SDL_SCANCODE_H: return 0x23;
-	 case SDL_SCANCODE_I: return 0x17;
-	 case SDL_SCANCODE_J: return 0x24;
-	 case SDL_SCANCODE_K: return 0x25;
-	 case SDL_SCANCODE_L: return 0x26;
-	 case SDL_SCANCODE_M: return 0x32;
-	 case SDL_SCANCODE_N: return 0x31;
-	 case SDL_SCANCODE_O: return 0x18;
-	 case SDL_SCANCODE_P: return 0x19;
-	 case SDL_SCANCODE_Q: return 0x10;
-	 case SDL_SCANCODE_R: return 0x13;
-	 case SDL_SCANCODE_S: return 0x1f;
-	 case SDL_SCANCODE_T: return 0x14;
-	 case SDL_SCANCODE_U: return 0x16;
-	 case SDL_SCANCODE_V: return 0x2f;
-	 case SDL_SCANCODE_W: return 0x11;
-	 case SDL_SCANCODE_X: return 0x2d;
-	 case SDL_SCANCODE_Y: return 0x15;
-	 case SDL_SCANCODE_Z: return 0x2c;
-	 case SDL_SCANCODE_1: return 0x02;
-	 case SDL_SCANCODE_2: return 0x03;
-	 case SDL_SCANCODE_3: return 0x04;
-	 case SDL_SCANCODE_4: return 0x05;
-	 case SDL_SCANCODE_5: return 0x06;
-	 case SDL_SCANCODE_6: return 0x07;
-	 case SDL_SCANCODE_7: return 0x08;
-	 case SDL_SCANCODE_8: return 0x09;
-	 case SDL_SCANCODE_9: return 0x0a;
-	 case SDL_SCANCODE_0: return 0x0b;
-	 case SDL_SCANCODE_RETURN: return 0x1c;
-	 case SDL_SCANCODE_ESCAPE: return 0x01;
-	 case SDL_SCANCODE_BACKSPACE: return 0x0e;
-	 case SDL_SCANCODE_TAB: return 0x0f;
-	 case SDL_SCANCODE_SPACE: return 0x39;
-	 case SDL_SCANCODE_MINUS: return 0x0c;
-	 case SDL_SCANCODE_EQUALS: return 0x0d;
-	 case SDL_SCANCODE_LEFTBRACKET: return 0x1a;
-	 case SDL_SCANCODE_RIGHTBRACKET: return 0x1b;
-	 case SDL_SCANCODE_BACKSLASH: return 0x29;  /* for 0x60 see NONUSBACKSLASH */
-	 case SDL_SCANCODE_NONUSHASH: return 0x2b;
-	 case SDL_SCANCODE_SEMICOLON: return 0x27;
-	 case SDL_SCANCODE_APOSTROPHE: return 0x28;
-	 case SDL_SCANCODE_GRAVE: return 0x2b;      /* ok? */
-	 case SDL_SCANCODE_COMMA: return 0x33;
-	 case SDL_SCANCODE_PERIOD: return 0x34;
-	 case SDL_SCANCODE_SLASH: return 0x35;
-	 case SDL_SCANCODE_CAPSLOCK: return 0x3a;
-	 case SDL_SCANCODE_F1: return 0x3b;
-	 case SDL_SCANCODE_F2: return 0x3c;
-	 case SDL_SCANCODE_F3: return 0x3d;
-	 case SDL_SCANCODE_F4: return 0x3e;
-	 case SDL_SCANCODE_F5: return 0x3f;
-	 case SDL_SCANCODE_F6: return 0x40;
-	 case SDL_SCANCODE_F7: return 0x41;
-	 case SDL_SCANCODE_F8: return 0x42;
-	 case SDL_SCANCODE_F9: return 0x43;
-	 case SDL_SCANCODE_F10: return 0x44;
-	 case SDL_SCANCODE_F11: return 0x62;
-	 case SDL_SCANCODE_F12: return 0x61;
-	 case SDL_SCANCODE_PRINTSCREEN: return 0x62;
-	 case SDL_SCANCODE_SCROLLLOCK: return 0x61;
-	 case SDL_SCANCODE_PAUSE: return 0x61;
-	 case SDL_SCANCODE_INSERT: return 0x52;
-	 case SDL_SCANCODE_HOME: return 0x47;
-	 case SDL_SCANCODE_PAGEUP: return 0x63;
-	 case SDL_SCANCODE_DELETE: return 0x53;
-	 case SDL_SCANCODE_END: return 0x2b;
-	 case SDL_SCANCODE_PAGEDOWN: return 0x64;
-	 case SDL_SCANCODE_RIGHT: return 0x4d;
-	 case SDL_SCANCODE_LEFT: return 0x4b;
-	 case SDL_SCANCODE_DOWN: return 0x50;
-	 case SDL_SCANCODE_UP: return 0x48;
-	 case SDL_SCANCODE_NUMLOCKCLEAR: return 0x64;
-	 case SDL_SCANCODE_KP_DIVIDE: return 0x65;
-	 case SDL_SCANCODE_KP_MULTIPLY: return 0x66;
-	 case SDL_SCANCODE_KP_MINUS: return 0x4a;
-	 case SDL_SCANCODE_KP_PLUS: return 0x4e;
-	 case SDL_SCANCODE_KP_ENTER: return 0x72;
-	 case SDL_SCANCODE_KP_1: return 0x6d;
-	 case SDL_SCANCODE_KP_2: return 0x6e;
-	 case SDL_SCANCODE_KP_3: return 0x6f;
-	 case SDL_SCANCODE_KP_4: return 0x6a;
-	 case SDL_SCANCODE_KP_5: return 0x6b;
-	 case SDL_SCANCODE_KP_6: return 0x6c;
-	 case SDL_SCANCODE_KP_7: return 0x67;
-	 case SDL_SCANCODE_KP_8: return 0x68;
-	 case SDL_SCANCODE_KP_9: return 0x69;
-	 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_KP_EQUALS: return 0x63;
-	 case SDL_SCANCODE_F13: return 0x63;
-	 case SDL_SCANCODE_F14: return 0x64;
-	 case SDL_SCANCODE_HELP: return 0x62;
-	 case SDL_SCANCODE_UNDO: return 0x61;
-	 case SDL_SCANCODE_KP_COMMA: return 0x71;
-	 case SDL_SCANCODE_CLEAR: return 0x47;
-	 case SDL_SCANCODE_RETURN2: return 0x1c;
-	 case SDL_SCANCODE_KP_LEFTPAREN: return 0x63;
-	 case SDL_SCANCODE_KP_RIGHTPAREN: return 0x64;
-	 case SDL_SCANCODE_KP_LEFTBRACE: return 0x63;
-	 case SDL_SCANCODE_KP_RIGHTBRACE: return 0x64;
-	 case SDL_SCANCODE_KP_TAB: return 0x0f;
-	 case SDL_SCANCODE_KP_BACKSPACE: return 0x0e;
-	 case SDL_SCANCODE_KP_COLON: return 0x33;
-	 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;
-	 default:
-		if (!pKeySym->scancode && pKeySym->sym)
-		{
-			/* assume SimulateKey
-			 * -> KeyUp/Down
-			 *    -> Remap (with scancode mode configured)
-			 *       -> PcToStScanCode
-			 */
-			return Keymap_SymbolicToStScanCode(pKeySym);
-		}
-		Log_Printf(LOG_WARN, "Unhandled scancode 0x%x!\n", pKeySym->scancode);
-		return -1;
+		case SDL_SCANCODE_A: return 0x1e;
+		case SDL_SCANCODE_B: return 0x30;
+		case SDL_SCANCODE_C: return 0x2e;
+		case SDL_SCANCODE_D: return 0x20;
+		case SDL_SCANCODE_E: return 0x12;
+		case SDL_SCANCODE_F: return 0x21;
+		case SDL_SCANCODE_G: return 0x22;
+		case SDL_SCANCODE_H: return 0x23;
+		case SDL_SCANCODE_I: return 0x17;
+		case SDL_SCANCODE_J: return 0x24;
+		case SDL_SCANCODE_K: return 0x25;
+		case SDL_SCANCODE_L: return 0x26;
+		case SDL_SCANCODE_M: return 0x32;
+		case SDL_SCANCODE_N: return 0x31;
+		case SDL_SCANCODE_O: return 0x18;
+		case SDL_SCANCODE_P: return 0x19;
+		case SDL_SCANCODE_Q: return 0x10;
+		case SDL_SCANCODE_R: return 0x13;
+		case SDL_SCANCODE_S: return 0x1f;
+		case SDL_SCANCODE_T: return 0x14;
+		case SDL_SCANCODE_U: return 0x16;
+		case SDL_SCANCODE_V: return 0x2f;
+		case SDL_SCANCODE_W: return 0x11;
+		case SDL_SCANCODE_X: return 0x2d;
+		case SDL_SCANCODE_Y: return 0x15;
+		case SDL_SCANCODE_Z: return 0x2c;
+		case SDL_SCANCODE_1: return 0x02;
+		case SDL_SCANCODE_2: return 0x03;
+		case SDL_SCANCODE_3: return 0x04;
+		case SDL_SCANCODE_4: return 0x05;
+		case SDL_SCANCODE_5: return 0x06;
+		case SDL_SCANCODE_6: return 0x07;
+		case SDL_SCANCODE_7: return 0x08;
+		case SDL_SCANCODE_8: return 0x09;
+		case SDL_SCANCODE_9: return 0x0a;
+		case SDL_SCANCODE_0: return 0x0b;
+		case SDL_SCANCODE_RETURN: return 0x1c;
+		case SDL_SCANCODE_ESCAPE: return 0x01;
+		case SDL_SCANCODE_BACKSPACE: return 0x0e;
+		case SDL_SCANCODE_TAB: return 0x0f;
+		case SDL_SCANCODE_SPACE: return 0x39;
+		case SDL_SCANCODE_MINUS: return 0x0c;
+		case SDL_SCANCODE_EQUALS: return 0x0d;
+		case SDL_SCANCODE_LEFTBRACKET: return 0x1a;
+		case SDL_SCANCODE_RIGHTBRACKET: return 0x1b;
+		case SDL_SCANCODE_BACKSLASH: return 0x29;  /* for 0x60 see NONUSBACKSLASH */
+		case SDL_SCANCODE_NONUSHASH: return 0x2b;
+		case SDL_SCANCODE_SEMICOLON: return 0x27;
+		case SDL_SCANCODE_APOSTROPHE: return 0x28;
+		case SDL_SCANCODE_GRAVE: return 0x2b;      /* ok? */
+		case SDL_SCANCODE_COMMA: return 0x33;
+		case SDL_SCANCODE_PERIOD: return 0x34;
+		case SDL_SCANCODE_SLASH: return 0x35;
+		case SDL_SCANCODE_CAPSLOCK: return 0x3a;
+		case SDL_SCANCODE_F1: return 0x3b;
+		case SDL_SCANCODE_F2: return 0x3c;
+		case SDL_SCANCODE_F3: return 0x3d;
+		case SDL_SCANCODE_F4: return 0x3e;
+		case SDL_SCANCODE_F5: return 0x3f;
+		case SDL_SCANCODE_F6: return 0x40;
+		case SDL_SCANCODE_F7: return 0x41;
+		case SDL_SCANCODE_F8: return 0x42;
+		case SDL_SCANCODE_F9: return 0x43;
+		case SDL_SCANCODE_F10: return 0x44;
+		case SDL_SCANCODE_F11: return 0x62;
+		case SDL_SCANCODE_F12: return 0x61;
+		case SDL_SCANCODE_PRINTSCREEN: return 0x62;
+		case SDL_SCANCODE_SCROLLLOCK: return 0x61;
+		case SDL_SCANCODE_PAUSE: return 0x61;
+		case SDL_SCANCODE_INSERT: return 0x52;
+		case SDL_SCANCODE_HOME: return 0x47;
+		case SDL_SCANCODE_PAGEUP: return 0x63;
+		case SDL_SCANCODE_DELETE: return 0x53;
+		case SDL_SCANCODE_END: return 0x2b;
+		case SDL_SCANCODE_PAGEDOWN: return 0x64;
+		case SDL_SCANCODE_RIGHT: return 0x4d;
+		case SDL_SCANCODE_LEFT: return 0x4b;
+		case SDL_SCANCODE_DOWN: return 0x50;
+		case SDL_SCANCODE_UP: return 0x48;
+		case SDL_SCANCODE_NUMLOCKCLEAR: return 0x64;
+		case SDL_SCANCODE_KP_DIVIDE: return 0x65;
+		case SDL_SCANCODE_KP_MULTIPLY: return 0x66;
+		case SDL_SCANCODE_KP_MINUS: return 0x4a;
+		case SDL_SCANCODE_KP_PLUS: return 0x4e;
+		case SDL_SCANCODE_KP_ENTER: return 0x72;
+		case SDL_SCANCODE_KP_1: return 0x6d;
+		case SDL_SCANCODE_KP_2: return 0x6e;
+		case SDL_SCANCODE_KP_3: return 0x6f;
+		case SDL_SCANCODE_KP_4: return 0x6a;
+		case SDL_SCANCODE_KP_5: return 0x6b;
+		case SDL_SCANCODE_KP_6: return 0x6c;
+		case SDL_SCANCODE_KP_7: return 0x67;
+		case SDL_SCANCODE_KP_8: return 0x68;
+		case SDL_SCANCODE_KP_9: return 0x69;
+		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_KP_EQUALS: return 0x63;
+		case SDL_SCANCODE_F13: return 0x63;
+		case SDL_SCANCODE_F14: return 0x64;
+		case SDL_SCANCODE_HELP: return 0x62;
+		case SDL_SCANCODE_UNDO: return 0x61;
+		case SDL_SCANCODE_KP_COMMA: return 0x71;
+		case SDL_SCANCODE_CLEAR: return 0x47;
+		case SDL_SCANCODE_RETURN2: return 0x1c;
+		case SDL_SCANCODE_KP_LEFTPAREN: return 0x63;
+		case SDL_SCANCODE_KP_RIGHTPAREN: return 0x64;
+		case SDL_SCANCODE_KP_LEFTBRACE: return 0x63;
+		case SDL_SCANCODE_KP_RIGHTBRACE: return 0x64;
+		case SDL_SCANCODE_KP_TAB: return 0x0f;
+		case SDL_SCANCODE_KP_BACKSPACE: return 0x0e;
+		case SDL_SCANCODE_KP_COLON: return 0x33;
+		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;
+		default:
+			if (!pKeySym->scancode && pKeySym->sym)
+			{
+				/* assume SimulateKey
+				 * -> KeyUp/Down
+				 *    -> Remap (with scancode mode configured)
+				 *       -> PcToStScanCode
+				 */
+				return Keymap_SymbolicToStScanCode(pKeySym);
+			}
+			Log_Printf(LOG_WARN, "Unhandled scancode 0x%x!\n", pKeySym->scancode);
+			return -1;
 	}
 }
 
@@ -377,68 +479,68 @@ static int Keymap_FindScanCodeOffset(SDL_keysym* keysym)
 
 	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;
+		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)
 	{
 		Log_Printf(LOG_WARN, "Detected scancode offset = %d (key: '%s' with scancode $%02x)\n",
-		        offset, SDL_GetKeyName(keysym->sym), scanPC);
+				   offset, SDL_GetKeyName(keysym->sym), scanPC);
 	}
 
 	return offset;
@@ -469,64 +571,64 @@ static char Keymap_PcToStScanCode(SDL_keysym* keysym)
 
 	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_PRINT:    return 0x62;  /* Help */
-	 case SDLK_SCROLLOCK: return 0x61; /* Undo */
-	 case SDLK_PAGEUP:   return 0x63;  /* Keypad ( */
-	 case SDLK_PAGEDOWN: return 0x64;  /* Keypad ) */
-	 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);
-		}
+		/* 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_PRINT:    return 0x62;  /* Help */
+		case SDLK_SCROLLOCK: return 0x61; /* Undo */
+		case SDLK_PAGEUP:   return 0x63;  /* Keypad ( */
+		case SDLK_PAGEDOWN: return 0x64;  /* Keypad ) */
+		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 */
-			Log_Printf(LOG_WARN, "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);
-		}
-		break;
+			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 */
+				Log_Printf(LOG_WARN, "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);
+			}
+			break;
 	}
 }
 
-#endif	/* !WITH_SDL2 */
+#endif  /* !WITH_SDL2 */
 
 
 /**
@@ -540,32 +642,32 @@ static char Keymap_GetKeyPadScanCode(SDL_keysym* pKeySym)
 	{
 		switch (pKeySym->sym)
 		{
-		 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;
+			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_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;
+			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;
 		}
 	}
 
@@ -578,9 +680,14 @@ static char Keymap_GetKeyPadScanCode(SDL_keysym* pKeySym)
  */
 static char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
 {
+	static t_STScanCodeList *_stScancodeList = 0;
 	/* Check for keypad first so we can handle numlock */
 	if (ConfigureParams.Keyboard.nKeymapType != KEYMAP_LOADED)
 	{
+		if (pKeySym == 0)
+		{
+			return -1;
+		}
 		if (pKeySym->sym >= SDLK_KP1 && pKeySym->sym <= SDLK_KP9)
 		{
 			return Keymap_GetKeyPadScanCode(pKeySym);
@@ -590,21 +697,71 @@ static char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
 	/* Remap from PC scancodes? */
 	if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_SCANCODE)
 	{
+		if (pKeySym == 0)
+		{
+			return -1;
+		}
 		return Keymap_PcToStScanCode(pKeySym);
 	}
 
 	/* Use loaded keymap? */
 	if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
 	{
-		int i;
-		for (i = 0; i < KBD_MAX_SCANCODE && LoadedKeymap[i][1] != 0; i++)
+		if (pKeySym != 0)
 		{
-			if (pKeySym->sym == (SDLKey)LoadedKeymap[i][0])
-				return LoadedKeymap[i][1];
+			t_ModList *modList = NULL;
+			_stScancodeList = 0;
+			if (pKeySym->sym < SIZEOF_KEYSYM_ARRAY)
+			{
+				modList = LoadedKeySym[pKeySym->sym];
+			}
+			if (modList == NULL)
+			{
+				if (pKeySym->scancode < SIZEOF_KEYPOS_ARRAY)
+				{
+					modList = LoadedKeyPos[pKeySym->scancode];
+				}
+			}
+			if (modList != NULL)
+			{
+				Log_Printf(LOG_DEBUG, "1) Find for SDL.Sym=%d modList=%p\n", pKeySym->sym, (void *)modList);
+				modList = findMod(modList, pKeySym->mod & ~KMOD_NUM);
+				Log_Printf(LOG_DEBUG, "2) Find for SDL.Sym=%d SDL.mod=%d. modList=%p\n", pKeySym->sym, pKeySym->mod & ~KMOD_NUM, (void *)modList);
+				if (modList != NULL)
+				{
+					_stScancodeList = modList->stScancodeList;
+					if (_stScancodeList != NULL)
+					{
+						Log_Printf(LOG_DEBUG, "Find (1st) for SDL.Sym=%d stScancode=%d\n", pKeySym->sym, _stScancodeList->stScancode);
+						return _stScancodeList->stScancode;
+					}
+				}
+			}
+		}
+		else
+		{
+			/* printf("x2\n"); */
+			if (_stScancodeList == 0)
+			{
+				return -1;
+			}
+			/* printf("x3\n"); */
+			_stScancodeList = _stScancodeList->next;
+			/* printf("x4\n"); */
+			if (_stScancodeList == 0)
+			{
+				return -1;
+			}
+			Log_Printf(LOG_DEBUG, "Find (-) stScancode=%d\n", _stScancodeList->stScancode);
+			return _stScancodeList->stScancode;
 		}
 	}
-
+      
 	/* Use symbolic mapping */
+	if (pKeySym == 0)
+	{
+		return -1;
+	}
 	return Keymap_SymbolicToStScanCode(pKeySym);
 }
 
@@ -615,13 +772,43 @@ static char Keymap_RemapKeyToSTScanCode(SDL_keysym* pKeySym)
  */
 void Keymap_LoadRemapFile(char *pszFileName)
 {
+	static int _initialized = 0;
 	char szString[1024];
-	int STScanCode, PCKeyCode;
+	char szSTScanCode[1024];
+	char szPCKeyCode[1024];
+	int stScancode;
 	FILE *in;
-	int idx = 0;
+	int sdlPos = 0;
+	int sdlSym = 0;
+	int sdlMod = 0;
+	char *part = 0;
+	t_ModList *modList = 0;
+	t_STScanCodeList *iter = 0;
+	t_STScanCodeList **iter2 = 0;
 
 	/* Initialize table with default values */
-	memset(LoadedKeymap, 0, sizeof(LoadedKeymap));
+   
+	Log_Printf(LOG_DEBUG, "KBD_MAX_SCANCODE=%d\n", KBD_MAX_SCANCODE);
+	Log_Printf(LOG_DEBUG, "sizeof(LoadedKeySym)=%ld\n", sizeof(LoadedKeySym));
+	Log_Printf(LOG_DEBUG, "sizeof(LoadedKeySym[0])=%ld\n", sizeof(LoadedKeySym[0]));
+	if (_initialized)
+	{
+		int i = 0;
+		for (i = 0; i < SIZEOF_KEYSYM_ARRAY; i++)
+		{
+			cleanModList(&LoadedKeySym[i]);
+		}
+		for (i = 0; i < SIZEOF_KEYPOS_ARRAY; i++)
+		{
+			cleanModList(&LoadedKeyPos[i]);
+		}
+	}
+	else
+	{
+		memset(LoadedKeySym, 0, sizeof(LoadedKeySym));
+		memset(LoadedKeyPos, 0, sizeof(LoadedKeyPos));
+		_initialized = -1;
+	}
 
 	if (!*pszFileName)
 		return;
@@ -636,11 +823,11 @@ void Keymap_LoadRemapFile(char *pszFileName)
 	if (!in)
 	{
 		Log_Printf(LOG_ERROR, "Keymap_LoadRemapFile: failed to "
-			   " open keymap file '%s'\n", pszFileName);
+				   " open keymap file '%s'\n", pszFileName);
 		return;
 	}
 
-	while (!feof(in) && idx < KBD_MAX_SCANCODE)
+	while (!feof(in))
 	{
 		/* Read line from file */
 		if (fgets(szString, sizeof(szString), in) == NULL)
@@ -649,47 +836,117 @@ void Keymap_LoadRemapFile(char *pszFileName)
 		Str_Trim(szString);
 		if (strlen(szString)>0)
 		{
-			char *p;
+			int first_char_pos = 0;
 			/* Is a comment? */
-			if (szString[0] == ';' || szString[0] == '#')
+			if ( (szString[0]==';') || (szString[0]=='#') ) continue;
+			/* Read values */
+			if (szString[0]=='@')
+			{
+				first_char_pos=1;
+			}
+			part = strtok(&szString[first_char_pos], ",");
+			if (part == 0)
+			{
+				Log_Printf(LOG_WARN, "(1) This line is ignored: %s.\n", szString);
 				continue;
-			/* Cut out the values */
-			p = strtok(szString, ",");
-			if (!p)
+			}
+			strncpy(szPCKeyCode, part, sizeof(szPCKeyCode) - 1);
+			part = strtok(0, " ");
+			if (part == 0)
+			{
+				Log_Printf(LOG_WARN, "(2) This line is ignored: %s.\n", szString);
 				continue;
-			Str_Trim(szString);
-			PCKeyCode = atoi(szString);    /* Direct key code? */
-			if (PCKeyCode < 10)
+			}
+			strncpy(szSTScanCode, part, sizeof(szSTScanCode) - 1);
+			Log_Printf(LOG_DEBUG, "szPCKeyCode=%s szSTScanCode=%s\n", szPCKeyCode, szSTScanCode);
+
+			sdlMod = 0;
+			if (first_char_pos == 1)
 			{
-				/* If it's not a valid number >= 10, then
-				 * assume we've got a symbolic key name
-				 */
-				int offset = 0;
-				/* quoted character (e.g. comment line char)? */
-				if (*szString == '\\' && strlen(szString) == 2)
-					offset = 1;
-				PCKeyCode = Keymap_GetKeyFromName(szString+offset);
+				/* Part 1 (before ','): <SDL.evt.scancode>-<SDL.evt.mod> */
+				if (
+					(sscanf(szPCKeyCode, "%i-%i", &sdlPos, &sdlMod) != 2) && 
+					(sscanf(szPCKeyCode, "%i", &sdlPos) != 1)                ) 
+				{
+					Log_Printf(LOG_ERROR, "Bad syntaxe! This PCKeyCode can't be retrieved: '%s'", szPCKeyCode);
+					continue;
+				}
+				if (sdlPos >= SIZEOF_KEYPOS_ARRAY)
+				{
+					Log_Printf(LOG_ERROR, "KeyPos (%d>%d) overflow!", sdlPos, SIZEOF_KEYPOS_ARRAY);
+					continue;
+				}
+				modList = findMod(LoadedKeyPos[sdlPos], sdlMod);
+			}
+			else
+			{
+				/* Part 1 (before ','): <SDL.evt.sym>-<SDL.evt.mod> */
+				sdlSym = Keymap_GetKeyFromName(szPCKeyCode);
+				if ((sdlSym == 0) &&
+					(sscanf(szPCKeyCode, "%i-%i", &sdlSym, &sdlMod) != 2) && 
+					(sscanf(szPCKeyCode, "%i", &sdlSym) != 1)                ) 
+				{
+					Log_Printf(LOG_ERROR, "Bad syntaxe! This PCKeyCode can't be retrieved: '%s'", szPCKeyCode);
+					continue;
+				}
+				if (sdlSym >= SIZEOF_KEYSYM_ARRAY)
+				{
+					Log_Printf(LOG_ERROR, "KeySym (%d>%d) overflow!", sdlPos, SIZEOF_KEYSYM_ARRAY);
+					continue;
+				}
+				modList = findMod(LoadedKeySym[sdlSym], sdlMod);
 			}
-			p = strtok(NULL, "\n");
-			if (!p)
+			/* printf("Register SDL.Sym=%d SDL.Mod=%d...\n", sdlSym, sdlMod); */
+			if (modList != NULL)
+			{
+				Log_Printf(LOG_WARN, "Pair (sdlSym-sdlMod=%d-%d) is already registered.\n", sdlSym, sdlMod);
 				continue;
-			STScanCode = atoi(p);
-			/* Store into remap table, check both value within range */
-			if (STScanCode > 0 && STScanCode <= KBD_MAX_SCANCODE
-			    && PCKeyCode >= 8)
+			}
+			/* printf("Add... 0x%08X\n", (void *)LoadedKeySym[sdlSym]); */
+			if (first_char_pos == 1)
 			{
-				LOG_TRACE(TRACE_KEYMAP,
-				          "keymap from file: sym=%i --> scan=%i\n",
-				          PCKeyCode, STScanCode);
-				LoadedKeymap[idx][0] = PCKeyCode;
-				LoadedKeymap[idx][1] = STScanCode;
-				idx += 1;
+				modList = addMod(&LoadedKeyPos[sdlPos]);
 			}
 			else
 			{
-				Log_Printf(LOG_WARN, "Could not parse keymap file:"
-				           " '%s' (%d >= 8), '%s' (0 > %d <= %d)\n",
-					   szString, PCKeyCode, p, STScanCode, KBD_MAX_SCANCODE);
+				modList = addMod(&LoadedKeySym[sdlSym]);
+			}
+			modList->Mod = sdlMod;
+			/* Part 2 (after ','): <STScanCode 1>[-<STScanCode 2>[...]] */
+			part = strtok(szSTScanCode, "-");
+			iter = 0;
+			iter2 = &modList->stScancodeList;
+			while (part != NULL)
+			{
+				if (sscanf(part, "%i", &stScancode) != 1)
+				{
+					continue;
+				}
+				if (stScancode >= 0 && stScancode <= KBD_MAX_SCANCODE)
+				{
+					if (first_char_pos == 1)
+					{
+						LOG_TRACE(TRACE_KEYMAP,
+								  "keymap from file: '%s' pos=%i Mod=%i --> '%s' scan=%i\n",
+								  szPCKeyCode, sdlPos, sdlMod, szSTScanCode, stScancode);
+					}
+					else
+					{
+						LOG_TRACE(TRACE_KEYMAP,
+								  "keymap from file: '%s' sym=%i Mod=%i --> '%s' scan=%i\n",
+								  szPCKeyCode, sdlSym, sdlMod, szSTScanCode, stScancode);
+					}
+					iter = addSTScanCode(iter2);
+					iter->stScancode = stScancode;
+					part = strtok(0, "-");
+					iter2 = &(iter->next);
+				}
+				else
+				{
+					Log_Printf(LOG_WARN, "Could not parse keymap file:"
+							   " '%s' (%d >= 8), '%s' (0 > %d <= %d)\n",
+							   szString, sdlSym, part, stScancode, KBD_MAX_SCANCODE);
+				}
 			}
 		}
 	}
@@ -709,7 +966,7 @@ static bool Keymap_DebounceSTKey(char STScanCode)
 
 	/* Are we in fast forward, and have disabled key repeat? */
 	if ((ConfigureParams.System.bFastForward == true)
-	    && (ConfigureParams.Keyboard.bDisableKeyRepeat))
+		&& (ConfigureParams.Keyboard.bDisableKeyRepeat))
 	{
 		/* We should de-bounce all non extended keys,
 		 * e.g. leave ALT, SHIFT, CTRL etc... held */
@@ -741,7 +998,7 @@ void Keymap_DebounceAllKeys(void)
 
 	/* Return if we aren't in fast forward or have not disabled key repeat */
 	if ((ConfigureParams.System.bFastForward == false)
-	        || (!ConfigureParams.Keyboard.bDisableKeyRepeat))
+		|| (!ConfigureParams.Keyboard.bDisableKeyRepeat))
 	{
 		return;
 	}
@@ -775,7 +1032,7 @@ void Keymap_KeyDown(SDL_keysym *sdlkey)
 	int modkey = sdlkey->mod;
 
 	LOG_TRACE(TRACE_KEYMAP, "key down: sym=%i scan=%i mod=0x%x name='%s'\n",
-	          symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
+			  symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
 
 	if (ShortCut_CheckKeys(modkey, symkey, true))
 		return;
@@ -787,7 +1044,7 @@ void Keymap_KeyDown(SDL_keysym *sdlkey)
 
 	/* Handle special keys */
 	if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
-	        || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
+		|| symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
 	{
 		/* Ignore modifier keys that aren't passed to the ST */
 		return;
@@ -795,7 +1052,7 @@ void Keymap_KeyDown(SDL_keysym *sdlkey)
 
 	STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
 	LOG_TRACE(TRACE_KEYMAP, "key map: sym=0x%x to ST-scan=0x%02x\n", symkey, STScanCode);
-	if (STScanCode != (uint8_t)-1)
+	while (STScanCode != (uint8_t)-1)
 	{
 		if (!Keyboard.KeyStates[STScanCode])
 		{
@@ -803,6 +1060,7 @@ void Keymap_KeyDown(SDL_keysym *sdlkey)
 			Keyboard.KeyStates[STScanCode] = true;
 			IKBD_PressSTKey(STScanCode, true);
 		}
+		STScanCode = Keymap_RemapKeyToSTScanCode(0);
 	}
 }
 
@@ -818,7 +1076,7 @@ void Keymap_KeyUp(SDL_keysym *sdlkey)
 	int modkey = sdlkey->mod;
 
 	LOG_TRACE(TRACE_KEYMAP, "key up: sym=%i scan=%i mod=0x%x name='%s'\n",
-	          symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
+			  symkey, sdlkey->scancode, modkey, Keymap_GetKeyName(symkey));
 
 	/* Ignore short-cut keys here */
 	if (ShortCut_CheckKeys(modkey, symkey, false))
@@ -831,7 +1089,7 @@ void Keymap_KeyUp(SDL_keysym *sdlkey)
 
 	/* Handle special keys */
 	if (symkey == SDLK_RALT || symkey == SDLK_LMETA || symkey == SDLK_RMETA
-	        || symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
+		|| symkey == SDLK_MODE || symkey == SDLK_NUMLOCK)
 	{
 		/* Ignore modifier keys that aren't passed to the ST */
 		return;
@@ -839,13 +1097,14 @@ void Keymap_KeyUp(SDL_keysym *sdlkey)
 
 	STScanCode = Keymap_RemapKeyToSTScanCode(sdlkey);
 	/* Release key (only if was pressed) */
-	if (STScanCode != (uint8_t)-1)
+	while (STScanCode != (uint8_t)-1)
 	{
 		if (Keyboard.KeyStates[STScanCode])
 		{
 			IKBD_PressSTKey(STScanCode, false);
 			Keyboard.KeyStates[STScanCode] = false;
 		}
+		STScanCode = Keymap_RemapKeyToSTScanCode(0);
 	}
 }
 
@@ -896,7 +1155,7 @@ const char *Keymap_GetKeyName(int keycode)
 	return SDL_GetKeyName(keycode);
 }
 
-#else	/* !WITH_SDL2 */
+#else   /* !WITH_SDL2 */
 
 static struct {
 	int code;
@@ -1034,100 +1293,100 @@ static struct {
 	{ SDLK_POWER, "Power" },
 	{ SDLK_UNDO, "Undo" },
 
-	{ SDLK_WORLD_1, "¡" },	/* 161 */
-	{ SDLK_WORLD_2, "¢" },	/* 162 */
-	{ SDLK_WORLD_3, "£" },	/* 163 */
-	{ SDLK_WORLD_4, "¤" },	/* 164 */
-	{ SDLK_WORLD_5, "¥" },	/* 165 */
-	{ SDLK_WORLD_6, "¦" },	/* 166 */
-	{ SDLK_WORLD_7, "§" },	/* 167 */
-	{ SDLK_WORLD_8, "¨" },	/* 168 */
-	{ SDLK_WORLD_9, "©" },	/* 169 */
-	{ SDLK_WORLD_10, "ª" },	/* 170 */
-	{ SDLK_WORLD_11, "«" },	/* 171 */
-	{ SDLK_WORLD_12, "¬" },	/* 172 */
-	{ SDLK_WORLD_14, "®" },	/* 174 */
-	{ SDLK_WORLD_15, "¯" },	/* 175 */
-	{ SDLK_WORLD_16, "°" },	/* 176 */
-	{ SDLK_WORLD_17, "±" },	/* 177 */
-	{ SDLK_WORLD_18, "²" },	/* 178 */
-	{ SDLK_WORLD_19, "³" },	/* 179 */
-	{ SDLK_WORLD_20, "´" },	/* 180 */
-	{ SDLK_WORLD_21, "µ" },	/* 181 */
-	{ SDLK_WORLD_22, "¶" },	/* 182 */
-	{ SDLK_WORLD_23, "·" },	/* 183 */
-	{ SDLK_WORLD_24, "¸" },	/* 184 */
-	{ SDLK_WORLD_25, "¹" },	/* 185 */
-	{ SDLK_WORLD_26, "º" },	/* 186 */
-	{ SDLK_WORLD_27, "»" },	/* 187 */
-	{ SDLK_WORLD_28, "¼" },	/* 188 */
-	{ SDLK_WORLD_29, "½" },	/* 189 */
-	{ SDLK_WORLD_30, "¾" },	/* 190 */
-	{ SDLK_WORLD_31, "¿" },	/* 191 */
-	{ SDLK_WORLD_32, "À" },	/* 192 */
-	{ SDLK_WORLD_33, "Á" },	/* 193 */
-	{ SDLK_WORLD_34, "Â" },	/* 194 */
-	{ SDLK_WORLD_35, "Ã" },	/* 195 */
-	{ SDLK_WORLD_36, "Ä" },	/* 196 */
-	{ SDLK_WORLD_37, "Å" },	/* 197 */
-	{ SDLK_WORLD_38, "Æ" },	/* 198 */
-	{ SDLK_WORLD_39, "Ç" },	/* 199 */
-	{ SDLK_WORLD_40, "È" },	/* 200 */
-	{ SDLK_WORLD_41, "É" },	/* 201 */
-	{ SDLK_WORLD_42, "Ê" },	/* 202 */
-	{ SDLK_WORLD_43, "Ë" },	/* 203 */
-	{ SDLK_WORLD_44, "Ì" },	/* 204 */
-	{ SDLK_WORLD_45, "Í" },	/* 205 */
-	{ SDLK_WORLD_46, "Î" },	/* 206 */
-	{ SDLK_WORLD_47, "Ï" },	/* 207 */
-	{ SDLK_WORLD_48, "Ð" },	/* 208 */
-	{ SDLK_WORLD_49, "Ñ" },	/* 209 */
-	{ SDLK_WORLD_50, "Ò" },	/* 210 */
-	{ SDLK_WORLD_51, "Ó" },	/* 211 */
-	{ SDLK_WORLD_52, "Ô" },	/* 212 */
-	{ SDLK_WORLD_53, "Õ" },	/* 213 */
-	{ SDLK_WORLD_54, "Ö" },	/* 214 */
-	{ SDLK_WORLD_55, "×" },	/* 215 */
-	{ SDLK_WORLD_56, "Ø" },	/* 216 */
-	{ SDLK_WORLD_57, "Ù" },	/* 217 */
-	{ SDLK_WORLD_58, "Ú" },	/* 218 */
-	{ SDLK_WORLD_59, "Û" },	/* 219 */
-	{ SDLK_WORLD_60, "Ü" },	/* 220 */
-	{ SDLK_WORLD_61, "Ý" },	/* 221 */
-	{ SDLK_WORLD_62, "Þ" },	/* 222 */
-	{ SDLK_WORLD_63, "ß" },	/* 223 */
-	{ SDLK_WORLD_64, "à" },	/* 224 */
-	{ SDLK_WORLD_65, "á" },	/* 225 */
-	{ SDLK_WORLD_66, "â" },	/* 226 */
-	{ SDLK_WORLD_67, "ã" },	/* 227 */
-	{ SDLK_WORLD_68, "ä" },	/* 228 */
-	{ SDLK_WORLD_69, "å" },	/* 229 */
-	{ SDLK_WORLD_70, "æ" },	/* 230 */
-	{ SDLK_WORLD_71, "ç" },	/* 231 */
-	{ SDLK_WORLD_72, "è" },	/* 232 */
-	{ SDLK_WORLD_73, "é" },	/* 233 */
-	{ SDLK_WORLD_74, "ê" },	/* 234 */
-	{ SDLK_WORLD_75, "ë" },	/* 235 */
-	{ SDLK_WORLD_76, "ì" },	/* 236 */
-	{ SDLK_WORLD_77, "í" },	/* 237 */
-	{ SDLK_WORLD_78, "î" },	/* 238 */
-	{ SDLK_WORLD_79, "ï" },	/* 239 */
-	{ SDLK_WORLD_80, "ð" },	/* 240 */
-	{ SDLK_WORLD_81, "ñ" },	/* 241 */
-	{ SDLK_WORLD_82, "ò" },	/* 242 */
-	{ SDLK_WORLD_83, "ó" },	/* 243 */
-	{ SDLK_WORLD_84, "ô" },	/* 244 */
-	{ SDLK_WORLD_85, "õ" },	/* 245 */
-	{ SDLK_WORLD_86, "ö" },	/* 246 */
-	{ SDLK_WORLD_87, "÷" },	/* 247 */
-	{ SDLK_WORLD_88, "ø" },	/* 248 */
-	{ SDLK_WORLD_89, "ù" },	/* 249 */
-	{ SDLK_WORLD_90, "ú" },	/* 250 */
-	{ SDLK_WORLD_91, "û" },	/* 251 */
-	{ SDLK_WORLD_92, "ü" },	/* 252 */
-	{ SDLK_WORLD_93, "ý" },	/* 253 */
-	{ SDLK_WORLD_94, "þ" },	/* 254 */
-	{ SDLK_WORLD_95, "ÿ" },	/* 255 */
+	{ SDLK_WORLD_1, "¡" },  /* 161 */
+	{ SDLK_WORLD_2, "¢" },  /* 162 */
+	{ SDLK_WORLD_3, "£" },  /* 163 */
+	{ SDLK_WORLD_4, "¤" },  /* 164 */
+	{ SDLK_WORLD_5, "¥" },  /* 165 */
+	{ SDLK_WORLD_6, "¦" },  /* 166 */
+	{ SDLK_WORLD_7, "§" },  /* 167 */
+	{ SDLK_WORLD_8, "¨" },  /* 168 */
+	{ SDLK_WORLD_9, "©" },  /* 169 */
+	{ SDLK_WORLD_10, "ª" }, /* 170 */
+	{ SDLK_WORLD_11, "«" }, /* 171 */
+	{ SDLK_WORLD_12, "¬" }, /* 172 */
+	{ SDLK_WORLD_14, "®" }, /* 174 */
+	{ SDLK_WORLD_15, "¯" }, /* 175 */
+	{ SDLK_WORLD_16, "°" }, /* 176 */
+	{ SDLK_WORLD_17, "±" }, /* 177 */
+	{ SDLK_WORLD_18, "²" }, /* 178 */
+	{ SDLK_WORLD_19, "³" }, /* 179 */
+	{ SDLK_WORLD_20, "´" }, /* 180 */
+	{ SDLK_WORLD_21, "µ" }, /* 181 */
+	{ SDLK_WORLD_22, "¶" }, /* 182 */
+	{ SDLK_WORLD_23, "·" }, /* 183 */
+	{ SDLK_WORLD_24, "¸" }, /* 184 */
+	{ SDLK_WORLD_25, "¹" }, /* 185 */
+	{ SDLK_WORLD_26, "º" }, /* 186 */
+	{ SDLK_WORLD_27, "»" }, /* 187 */
+	{ SDLK_WORLD_28, "¼" }, /* 188 */
+	{ SDLK_WORLD_29, "½" }, /* 189 */
+	{ SDLK_WORLD_30, "¾" }, /* 190 */
+	{ SDLK_WORLD_31, "¿" }, /* 191 */
+	{ SDLK_WORLD_32, "À" }, /* 192 */
+	{ SDLK_WORLD_33, "Á" }, /* 193 */
+	{ SDLK_WORLD_34, "Â" }, /* 194 */
+	{ SDLK_WORLD_35, "Ã" }, /* 195 */
+	{ SDLK_WORLD_36, "Ä" }, /* 196 */
+	{ SDLK_WORLD_37, "Å" }, /* 197 */
+	{ SDLK_WORLD_38, "Æ" }, /* 198 */
+	{ SDLK_WORLD_39, "Ç" }, /* 199 */
+	{ SDLK_WORLD_40, "È" }, /* 200 */
+	{ SDLK_WORLD_41, "É" }, /* 201 */
+	{ SDLK_WORLD_42, "Ê" }, /* 202 */
+	{ SDLK_WORLD_43, "Ë" }, /* 203 */
+	{ SDLK_WORLD_44, "Ì" }, /* 204 */
+	{ SDLK_WORLD_45, "Í" }, /* 205 */
+	{ SDLK_WORLD_46, "Î" }, /* 206 */
+	{ SDLK_WORLD_47, "Ï" }, /* 207 */
+	{ SDLK_WORLD_48, "Ð" }, /* 208 */
+	{ SDLK_WORLD_49, "Ñ" }, /* 209 */
+	{ SDLK_WORLD_50, "Ò" }, /* 210 */
+	{ SDLK_WORLD_51, "Ó" }, /* 211 */
+	{ SDLK_WORLD_52, "Ô" }, /* 212 */
+	{ SDLK_WORLD_53, "Õ" }, /* 213 */
+	{ SDLK_WORLD_54, "Ö" }, /* 214 */
+	{ SDLK_WORLD_55, "×" }, /* 215 */
+	{ SDLK_WORLD_56, "Ø" }, /* 216 */
+	{ SDLK_WORLD_57, "Ù" }, /* 217 */
+	{ SDLK_WORLD_58, "Ú" }, /* 218 */
+	{ SDLK_WORLD_59, "Û" }, /* 219 */
+	{ SDLK_WORLD_60, "Ü" }, /* 220 */
+	{ SDLK_WORLD_61, "Ý" }, /* 221 */
+	{ SDLK_WORLD_62, "Þ" }, /* 222 */
+	{ SDLK_WORLD_63, "ß" }, /* 223 */
+	{ SDLK_WORLD_64, "à" }, /* 224 */
+	{ SDLK_WORLD_65, "á" }, /* 225 */
+	{ SDLK_WORLD_66, "â" }, /* 226 */
+	{ SDLK_WORLD_67, "ã" }, /* 227 */
+	{ SDLK_WORLD_68, "ä" }, /* 228 */
+	{ SDLK_WORLD_69, "å" }, /* 229 */
+	{ SDLK_WORLD_70, "æ" }, /* 230 */
+	{ SDLK_WORLD_71, "ç" }, /* 231 */
+	{ SDLK_WORLD_72, "è" }, /* 232 */
+	{ SDLK_WORLD_73, "é" }, /* 233 */
+	{ SDLK_WORLD_74, "ê" }, /* 234 */
+	{ SDLK_WORLD_75, "ë" }, /* 235 */
+	{ SDLK_WORLD_76, "ì" }, /* 236 */
+	{ SDLK_WORLD_77, "í" }, /* 237 */
+	{ SDLK_WORLD_78, "î" }, /* 238 */
+	{ SDLK_WORLD_79, "ï" }, /* 239 */
+	{ SDLK_WORLD_80, "ð" }, /* 240 */
+	{ SDLK_WORLD_81, "ñ" }, /* 241 */
+	{ SDLK_WORLD_82, "ò" }, /* 242 */
+	{ SDLK_WORLD_83, "ó" }, /* 243 */
+	{ SDLK_WORLD_84, "ô" }, /* 244 */
+	{ SDLK_WORLD_85, "õ" }, /* 245 */
+	{ SDLK_WORLD_86, "ö" }, /* 246 */
+	{ SDLK_WORLD_87, "÷" }, /* 247 */
+	{ SDLK_WORLD_88, "ø" }, /* 248 */
+	{ SDLK_WORLD_89, "ù" }, /* 249 */
+	{ SDLK_WORLD_90, "ú" }, /* 250 */
+	{ SDLK_WORLD_91, "û" }, /* 251 */
+	{ SDLK_WORLD_92, "ü" }, /* 252 */
+	{ SDLK_WORLD_93, "ý" }, /* 253 */
+	{ SDLK_WORLD_94, "þ" }, /* 254 */
+	{ SDLK_WORLD_95, "ÿ" }, /* 255 */
 
 	{ -1, NULL }
 };
@@ -1154,7 +1413,7 @@ const char *Keymap_GetKeyName(int keycode)
 
 	if (!keycode)
 		return "";
-
+   
 	for (i = 0; sdl_keytab[i].name != NULL; i++)
 	{
 		if (keycode == sdl_keytab[i].code)


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