Skip to content

Commit

Permalink
support for native keyboard input (from Chocolate Doom) (#2030)
Browse files Browse the repository at this point in the history
* matching Chocolate Doom behaviour with cheat codes

* implement `ev_text` event
  • Loading branch information
rfomin authored Nov 23, 2024
1 parent dd46dfb commit 86f56d2
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 140 deletions.
3 changes: 2 additions & 1 deletion src/d_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ typedef enum evtype_e
ev_joyb_up,
ev_joystick,
ev_joystick_state,
ev_gyro
ev_gyro,
ev_text
} evtype_t;

typedef union evdata_u
Expand Down
1 change: 1 addition & 0 deletions src/d_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2634,6 +2634,7 @@ void D_DoomMain(void)

// [FG] init graphics (video.widedelta) before HUD widgets
I_InitGraphics();
I_InitKeyboard();

MN_InitMenuStrings();

Expand Down
6 changes: 3 additions & 3 deletions src/f_finale.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ void F_TextWrite (void)
}

c = M_ToUpper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
if (c < 0 || c> HU_FONTSIZE || hu_font[c] == NULL)
{
cx += 4;
continue;
Expand Down Expand Up @@ -618,7 +618,7 @@ void F_CastPrint (char* text)
if (!c)
break;
c = M_ToUpper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
if (c < 0 || c> HU_FONTSIZE || hu_font[c] == NULL)
{
width += 4;
continue;
Expand All @@ -637,7 +637,7 @@ void F_CastPrint (char* text)
if (!c)
break;
c = M_ToUpper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
if (c < 0 || c> HU_FONTSIZE || hu_font[c] == NULL)
{
cx += 4;
continue;
Expand Down
169 changes: 161 additions & 8 deletions src/i_input.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//
// Copyright(C) 2005-2014 Simon Howard
// Copyright(C) 2023 Roman Fomin
//
// This program is free software; you can redistribute it and/or
Expand Down Expand Up @@ -606,8 +607,63 @@ void I_HandleGamepadEvent(SDL_Event *sdlevent, boolean menu)

static const int scancode_translate_table[] = SCANCODE_TO_KEYS_ARRAY;

static int TranslateKey(int scancode)
{
// If true, I_StartTextInput() has been called, and we are populating
// the data3 field of ev_keydown events.

static boolean text_input_enabled;

// key tables
// jff 5/10/98 french support removed,
// as it was not being used and couldn't be easily tested
//

static const char shiftxform[] =
{
0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31,
' ', '!', '"', '#', '$', '%', '&',
'"', // shift-'
'(', ')', '*', '+',
'<', // shift-,
'_', // shift--
'>', // shift-.
'?', // shift-/
')', // shift-0
'!', // shift-1
'@', // shift-2
'#', // shift-3
'$', // shift-4
'%', // shift-5
'^', // shift-6
'&', // shift-7
'*', // shift-8
'(', // shift-9
':',
':', // shift-;
'<',
'+', // shift-=
'>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'[', // shift-[
'!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
']', // shift-]
'"', '_',
'\'', // shift-`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'{', '|', '}', '~', 127
};

static boolean vanilla_keyboard_mapping;

static int TranslateKey(SDL_Keysym *sym)
{
int scancode = sym->scancode;

switch (scancode)
{
case SDL_SCANCODE_LCTRL:
Expand Down Expand Up @@ -636,6 +692,67 @@ static int TranslateKey(int scancode)
}
}


// Get the localized version of the key press. This takes into account the
// keyboard layout, but does not apply any changes due to modifiers, (eg.
// shift-, alt-, etc.)

static int GetLocalizedKey(SDL_Keysym *sym)
{
// When using Vanilla mapping, we just base everything off the scancode
// and always pretend the user is using a US layout keyboard.
if (vanilla_keyboard_mapping)
{
return TranslateKey(sym);
}
else
{
int result = sym->sym;

if (result < 0 || result >= 128)
{
result = 0;
}

return result;
}
}

static int GetTypedChar(SDL_Keysym *sym)
{
int result = TranslateKey(sym);

// If shift is held down, apply the original uppercase
// translation table used under DOS.
if ((SDL_GetModState() & KMOD_SHIFT) != 0 && result >= 0
&& result < arrlen(shiftxform))
{
result = shiftxform[result];
}

return result;
}

void I_StartTextInput(void)
{
text_input_enabled = true;

if (!vanilla_keyboard_mapping)
{
SDL_StartTextInput();
}
}

void I_StopTextInput(void)
{
text_input_enabled = false;

if (!vanilla_keyboard_mapping)
{
SDL_StopTextInput();
}
}

static void UpdateMouseButtonState(unsigned int button, boolean on,
unsigned int dclick)
{
Expand Down Expand Up @@ -782,31 +899,67 @@ void I_HandleKeyboardEvent(SDL_Event *sdlevent)
{
case SDL_KEYDOWN:
event.type = ev_keydown;
event.data1.i = TranslateKey(sdlevent->key.keysym.scancode);
event.data1.i = TranslateKey(&sdlevent->key.keysym);
event.data2.i = GetLocalizedKey(&sdlevent->key.keysym);

if (event.data1.i != 0)
{
D_PostEvent(&event);
}

if (text_input_enabled && vanilla_keyboard_mapping)
{
event.type = ev_text;
event.data1.i = GetTypedChar(&sdlevent->key.keysym);

if (event.data1.i != 0)
{
D_PostEvent(&event);
}
}
break;

case SDL_KEYUP:
event.type = ev_keyup;
event.data1.i = TranslateKey(sdlevent->key.keysym.scancode);
event.data1.i = TranslateKey(&sdlevent->key.keysym);

// data2/data3 are initialized to zero for ev_keyup.
// For ev_keydown it's the shifted Unicode character
// that was typed, but if something wants to detect
// key releases it should do so based on data1
// data2 is initialized to zero for ev_keyup. For ev_keydown it's
// the shifted Unicode character that was typed, but if something
// wants to detect key releases it should do so based on data1
// (key ID), not the printable char.

event.data2.i = 0;

if (event.data1.i != 0)
{
D_PostEvent(&event);
}
break;

case SDL_TEXTINPUT:
// SDL_TEXTINPUT are fired only after SDL_StartTextInput().
if (strlen(sdlevent->text.text) == 1
&& (sdlevent->text.text[0] & 0x80) == 0)
{
event.type = ev_text;
event.data1.i = sdlevent->text.text[0];
D_PostEvent(&event);
}
break;

default:
break;
}
}

void I_InitKeyboard(void)
{
// On desktop platforms, SDL_StartTextInput() is implicitly called on SDL
// window creation
SDL_StopTextInput();
}

void I_BindKeyboardVariables(void)
{
BIND_BOOL(vanilla_keyboard_mapping, false, "Vanilla keyboard mapping");
}
5 changes: 5 additions & 0 deletions src/i_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,9 @@ void I_HandleGamepadEvent(SDL_Event *sdlevent, boolean menu);
void I_HandleKeyboardEvent(SDL_Event *sdlevent);
void I_HandleMouseEvent(SDL_Event *sdlevent);

void I_InitKeyboard(void);
void I_StartTextInput(void);
void I_StopTextInput(void);
void I_BindKeyboardVariables(void);

#endif
1 change: 1 addition & 0 deletions src/i_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ static void ProcessEvent(SDL_Event *ev)
// deliberate fall-though

case SDL_KEYUP:
case SDL_TEXTINPUT:
I_HandleKeyboardEvent(ev);
break;

Expand Down
2 changes: 1 addition & 1 deletion src/m_cheat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,7 @@ boolean M_CheatResponder(event_t *ev)
if (strictmode && demorecording)
return false;

if (ev->type == ev_keydown && M_FindCheats(ev->data1.i))
if (ev->type == ev_keydown && M_FindCheats(ev->data2.i))
return true;

if (WS_Override())
Expand Down
4 changes: 3 additions & 1 deletion src/m_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "i_flickstick.h"
#include "i_gamepad.h"
#include "i_gyro.h"
#include "i_input.h"
#include "i_oalequalizer.h"
#include "i_printf.h"
#include "i_rumble.h"
Expand All @@ -49,8 +50,8 @@
#include "m_input.h"
#include "m_io.h"
#include "m_misc.h"
#include "mn_menu.h"
#include "mn_internal.h"
#include "mn_menu.h"
#include "r_main.h"
#include "s_sound.h"
#include "st_stuff.h"
Expand Down Expand Up @@ -126,6 +127,7 @@ void M_InitConfig(void)
G_BindGameInputVariables();
G_BindMouseVariables();

I_BindKeyboardVariables();
I_BindGamepadVariables();
I_BindRumbleVariables();
I_BindFlickStickVariables();
Expand Down
27 changes: 19 additions & 8 deletions src/mn_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "d_event.h"
#include "d_main.h"
#include "doomdef.h"
#include "doomkeys.h"
#include "doomstat.h"
#include "doomtype.h"
#include "dstrings.h"
Expand Down Expand Up @@ -1409,6 +1410,9 @@ static void M_SaveSelect(int choice)
// we are going to be intercepting all chars
saveStringEnter = 1;

// We need to turn on text input:
I_StartTextInput();

saveSlot = choice;
strcpy(saveOldString, savegamestrings[choice]);
// [FG] override savegame name if it already starts with a map identifier
Expand Down Expand Up @@ -2926,6 +2930,9 @@ boolean M_Responder(event_t *ev)
ch = ev->data1.i;
break;

case ev_text:
break;

case ev_keyup:
return false;

Expand Down Expand Up @@ -3003,7 +3010,7 @@ boolean M_Responder(event_t *ev)

if (saveStringEnter)
{
if (action == MENU_BACKSPACE) // phares 3/7/98
if (ch == KEY_BACKSPACE) // phares 3/7/98
{
if (saveCharIndex > 0)
{
Expand All @@ -3019,28 +3026,32 @@ boolean M_Responder(event_t *ev)
savegamestrings[saveSlot][saveCharIndex] = 0;
}
}
else if (action == MENU_ESCAPE) // phares 3/7/98
else if (ch == KEY_ESCAPE) // phares 3/7/98
{
I_StopTextInput();
saveStringEnter = 0;
strcpy(&savegamestrings[saveSlot][0], saveOldString);
}
else if (action == MENU_ENTER) // phares 3/7/98
else if (ch == KEY_ENTER) // phares 3/7/98
{
I_StopTextInput();
saveStringEnter = 0;
if (savegamestrings[saveSlot][0])
{
M_DoSave(saveSlot);
}
}
else
else if (ev->type == ev_text)
{
ch = M_ToUpper(ch);
int txt = ev->data1.i;

txt = M_ToUpper(txt);

if (ch >= 32 && ch <= 127 && saveCharIndex < SAVESTRINGSIZE - 1
if (txt >= ' ' && txt <= '_' && saveCharIndex < SAVESTRINGSIZE - 1
&& MN_StringWidth(savegamestrings[saveSlot])
< (SAVESTRINGSIZE - 2) * 8)
{
savegamestrings[saveSlot][saveCharIndex++] = ch;
savegamestrings[saveSlot][saveCharIndex++] = txt;
savegamestrings[saveSlot][saveCharIndex] = 0;
}
saveStringEnter = 2; // [FG] save string modified
Expand Down Expand Up @@ -3612,7 +3623,7 @@ static void WriteText(int x, int y, const char *string)
}

c = M_ToUpper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE)
if (c < 0 || c >= HU_FONTSIZE || hu_font[c] == NULL)
{
cx += 4;
continue;
Expand Down
Loading

0 comments on commit 86f56d2

Please sign in to comment.