Skip to content

Commit

Permalink
Initial changes to support non-american keyboard layouts & cyrillic c…
Browse files Browse the repository at this point in the history
…haracters.

Uses SDL2 TextInput event, unfortunately the unicode character is sent
after the keydown event, so we need to know if the keydown event is going
to produce a character or not... currently the system lets the keydown
event produce that character, but then backspaces and replaces it with
the unicode version, which seems ugly.

The console still translates and stores in wchar at the moment, so true
utf8 printing isn't possible, we only support up to 3-byte utf8 characters.

Can now also choose the encoding method on outgoing messages:

cl_textencoding
 Controls method to encode outgoing extended characters (> 255)

 0 - koi8 encoding (wrapped with =`k8:<text>`=)
 1 - utf8 encoding (wrapped with =`utf8:<text>`=)
 2 - FTE encoding (convert to ^Uxxxx where xxxx is hex)

 0 can encode limited set of characters, but compatible with 2.2 clients
 1 encodes all characters correctly for all but only other 3.0 clients
 2 compatible with FTE & 3.0

Regardless of this setting, the client will continue to decode svc_print
messages using all of the above incoming methods.

Previously only -cyr suffix was supported for extended character sets.  Now
all are supported, from -001 to -256.  If -004 isn't present it will fall
back to loading -cyr.  This is a lot of textures to load and we might need
to look at methods to reduce the number.

To support compatibility with existing configuration files (and passing
config files between machines with different keyboard layouts), the bind
and unbind commands look up the key based on the keyboard layout only when
con_bindphysical is set to 0.  All configuration files will start with
con_bindphysical set to 1, and it is reset back to its previous value once
the configuration file has completed.

If configuration files want to bind to a key based on layout (a
demo-watching configuration where the user should press R to toggle radar
for example) then the configuration file should set con_bindphysical to 0
before binding any keys.

Hopefully this is a solution to non-american keyboards that is natural to
use in the console and is backwards-compatible with existing configs.
  • Loading branch information
meag committed Oct 14, 2015
1 parent d2ec3bf commit 6ac7059
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 62 deletions.
17 changes: 12 additions & 5 deletions cmd.c
Expand Up @@ -445,6 +445,7 @@ void Cmd_StuffCmds_f (void)
void Cmd_Exec_f (void)
{
char *f, name[MAX_OSPATH];
char reset_bindphysical[128];
int mark;

if (Cmd_Argc () != 2) {
Expand All @@ -471,14 +472,20 @@ void Cmd_Exec_f (void)
Com_Printf("execing %s/%s\n", FS_Locate_GetPath(name), name);
}

// All config files default to con_bindphysical 1, and would have to over-ride if they
// want different behaviour.
sprintf(reset_bindphysical, "\ncon_bindphysical %d\n", con_bindphysical.integer);
if (cbuf_current == &cbuf_svc) {
Cbuf_AddTextEx (&cbuf_main, "con_bindphysical 1\n");
Cbuf_AddTextEx (&cbuf_main, f);
Cbuf_AddTextEx (&cbuf_main, "\n");
} else
{
Cbuf_InsertText ("\n");
Cbuf_InsertText (f);
Cbuf_AddTextEx (&cbuf_main, reset_bindphysical);
}
else {
Cbuf_InsertTextEx (&cbuf_main, reset_bindphysical);
Cbuf_InsertTextEx (&cbuf_main, f);
Cbuf_InsertTextEx (&cbuf_main, "con_bindphysical 1\n");
}

Hunk_FreeToLowMark (mark);
}

Expand Down
5 changes: 3 additions & 2 deletions config_manager.c
Expand Up @@ -104,8 +104,9 @@ void DumpBindings (FILE *f)
static qbool Config_Unsaved_Cvar(const char *name)
{
return (!strcmp(name, "cl_delay_packet"))
|| (!strcmp(name, "cl_proxyaddr"))
|| (!strcmp(name, "hud_planmode"));
|| (!strcmp(name, "cl_proxyaddr"))
|| (!strcmp(name, "hud_planmode"))
|| (!strcmp(name, "con_bindphysical"));
}

#define CONFIG_MAX_COL 60
Expand Down
9 changes: 6 additions & 3 deletions console.c
Expand Up @@ -73,8 +73,9 @@ cvar_t con_sound_mm2_volume = {"s_mm2_volume", "1"};
cvar_t con_sound_spec_volume = {"s_spec_volume", "1"};
cvar_t con_sound_other_volume = {"s_otherchat_volume", "1"};

cvar_t con_timestamps = {"con_timestamps", "0"};
cvar_t con_shift = {"con_shift", "-10"};
cvar_t con_timestamps = {"con_timestamps", "0"};
cvar_t con_shift = {"con_shift", "-10"};
cvar_t cl_textEncoding = {"cl_textencoding", "0"};

#define NUM_CON_TIMES 16
float con_times[NUM_CON_TIMES]; // cls.realtime time the line was generated
Expand Down Expand Up @@ -472,6 +473,8 @@ void Con_Init (void) {

Cvar_ResetCurrentGroup();

Cvar_Register(&cl_textEncoding);

Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
Cmd_AddCommand ("messagemode", Con_MessageMode_f);
Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
Expand Down Expand Up @@ -648,7 +651,7 @@ void Con_PrintW (wchar *txt) {
Con_Linefeed ();
y = con.current % con_totallines;
idx = y * con_linewidth + con.x;
con.text[idx] = c | mask | con_ormask;
con.text[idx] = c | (c <= 0x7F ? mask | con_ormask : 0); // only apply mask if in 'standard' charset
memset(&con.clr[idx], 0, sizeof(clrinfo_t)); // zeroing whole struct
con.clr[idx].c = color;
con.clr[idx].i = idx; // no, that not stupid :P
Expand Down
2 changes: 1 addition & 1 deletion draw.h
Expand Up @@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __DRAW_H__
#define __DRAW_H__

#define MAX_CHARSETS 16
#define MAX_CHARSETS 256
extern int char_textures[MAX_CHARSETS];

typedef struct
Expand Down
17 changes: 15 additions & 2 deletions gl_draw.c
Expand Up @@ -689,6 +689,7 @@ static int Draw_LoadCharset(const char *name)
{
int flags = TEX_ALPHA | TEX_NOCOMPRESS | TEX_NOSCALE | TEX_NO_TEXTUREMODE;
int texnum;
int i = 0;
qbool loaded = false;

//
Expand Down Expand Up @@ -716,9 +717,21 @@ static int Draw_LoadCharset(const char *name)
return 1;
}

// Load cyrillic charset if available
Load_Locale_Charset(name, "cyr", 1, 0x0400, flags);
// Load alternate charsets if available
for (i = 1; i < MAX_CHARSETS; ++i)
{
char charsetName[10];
int textureNumber;

snprintf(charsetName, sizeof(charsetName), "%03d", i);

textureNumber = Load_Locale_Charset(name, charsetName, i, i << 8, flags);

// 2.2 only supported -cyr suffix
if (i == 4 && !textureNumber)
Load_Locale_Charset(name, "cyr", 4, 0x0400, flags);
}

// apply gl_smoothfont
Apply_OnChange_gl_smoothfont(gl_smoothfont.integer);

Expand Down
59 changes: 53 additions & 6 deletions keys.c
Expand Up @@ -54,6 +54,7 @@ cvar_t con_tilde_mode = {"con_tilde_mode", "0"};
cvar_t con_completion_format = {"con_completion_format", "2"};
cvar_t con_hide_chat_input = {"con_hide_chat_input", "1"};
cvar_t con_completion_changed_mark = {"con_completion_changed_mark", "1"};
cvar_t con_bindphysical = {"con_bindphysical", "0" };

char* escape_regex(char* string);
void OnChange_con_prompt_charcode(cvar_t *var, char *string, qbool *cancel);
Expand Down Expand Up @@ -102,6 +103,10 @@ int key_repeats[UNKNOWN + 256]; // if > 1, it is autorepeating
qbool keydown[UNKNOWN + 256];
qbool keyactive[UNKNOWN + 256];

// SDL2 sends a KEYDOWN event and then an optional TEXTINPUT event for the actual character generated
// This stores the last quake key (K_*) from the KEYDOWN, or 0 if any subsequent TEXTINPUT event should be ignored.
static int lastKeyDown = 0;

typedef struct
{
char *name;
Expand Down Expand Up @@ -821,6 +826,14 @@ void Key_ClearTyping (void)
key_linepos = 1;
}

void Key_Console_Backspace(void)
{
if (key_linepos > 1)
{
qwcscpy(key_lines[edit_line] + key_linepos - 1, key_lines[edit_line] + key_linepos);
key_linepos--;
}
}

//
// Interactive line editing and console scrollback.
Expand Down Expand Up @@ -988,11 +1001,7 @@ void Key_Console (int key, int unichar)
}
else
{
if(key_linepos > 1)
{
qwcscpy(key_lines[edit_line] + key_linepos - 1, key_lines[edit_line] + key_linepos);
key_linepos--;
}
Key_Console_Backspace();
}

// disable red chars mode if the last character was deleted
Expand Down Expand Up @@ -1508,19 +1517,30 @@ void Key_Message (int key, wchar unichar) {
//Returns a key number to be used to index keybindings[] by looking at the given string.
//Single ascii characters return themselves, while the K_* names are matched up.
#define UNKNOWN_S "UNKNOWN"

int Key_CharacterToQuakeCode(char ch);

int Key_StringToKeynum (const char *str)
{
keyname_t *kn;

if (!str || !str[0])
return -1;

if (!str[1] && !con_bindphysical.value)
{
int value = Key_CharacterToQuakeCode(str[0]);

if (value != 0)
return value;
}

if (!str[1])
return (int)(unsigned char)str[0];

for (kn = keynames; kn->name; kn++) {
if (!strcasecmp (str,kn->name))
return kn->keynum;
return kn->keynum;
}

return -1;
Expand Down Expand Up @@ -1858,6 +1878,7 @@ void Key_Init (void) {
Cvar_Register(&con_completion_padding);
Cvar_Register(&con_completion_color_title);
Cvar_Register(&con_completion_changed_mark);
Cvar_Register(&con_bindphysical);

Cvar_ResetCurrentGroup();
}
Expand Down Expand Up @@ -2175,6 +2196,9 @@ void Key_EventEx (int key, wchar unichar, qbool down)

void Key_Event (int key, qbool down)
{
qbool processTextInput = (key_dest == key_console || key_dest == key_message);
qbool consoleToggle = (key == '`' || key == '~') && !con_tilde_mode.integer;

assert (key >= 0 && key <= 255);

if (key >= K_MOUSE1 && key <= K_MOUSE8)
Expand All @@ -2197,8 +2221,31 @@ void Key_Event (int key, qbool down)
unichar = keydown[K_SHIFT] ? keyshift[key] : key;
if (unichar < 32 || unichar > 127)
unichar = 0;

Key_EventEx (key, unichar, down);
}

// Store this as we may need it for subsequent SDL_TextInput event
lastKeyDown = 0;
if (down && processTextInput && !consoleToggle)
lastKeyDown = key;
}

void Key_Event_TextInput(wchar unichar)
{
if (!lastKeyDown)
return;

if (key_dest == key_message)
{
Key_Message(K_BACKSPACE, K_BACKSPACE);
Key_Message(lastKeyDown, unichar);
}
else if (key_dest == key_console)
{
Key_Console_Backspace();
Key_Console(lastKeyDown, unichar);
}
}

void Key_ClearStates (void)
Expand Down
2 changes: 2 additions & 0 deletions keys.h
Expand Up @@ -227,6 +227,8 @@ extern int key_linepos;
extern int edit_line;
extern qbool con_redchars;

extern cvar_t con_bindphysical;

#define CONSOLE_LINE_EMPTY() (!key_lines[edit_line][1])

// }
Expand Down
5 changes: 4 additions & 1 deletion menu.c
Expand Up @@ -488,7 +488,10 @@ void M_Main_Key (int key) {
switch (key) {
case K_ESCAPE:
case K_MOUSE2:
key_dest = key_game;
if (cls.state < ca_active)
key_dest = key_console;
else
key_dest = key_game;
m_state = m_none;
break;

Expand Down
2 changes: 1 addition & 1 deletion teamplay.c
Expand Up @@ -1165,7 +1165,7 @@ wchar *TP_ParseWhiteText (const wchar *s, qbool team, int offset)
continue;
}
}
if (*p != 10 && *p != 13 && !(p==s && (*p==1 || *p==2)))
if (*p != 10 && *p != 13 && !(p==s && (*p==1 || *p==2)) && *p <= 0x7F)
*out++ = *p | 128; // convert to red
else
*out++ = *p;
Expand Down

0 comments on commit 6ac7059

Please sign in to comment.