From 5ca6703d5f57ebe18c1fc1a97c646ba468c49442 Mon Sep 17 00:00:00 2001 From: NaitLee Date: Sun, 29 Jan 2023 22:09:37 +0800 Subject: [PATCH] Fixed two keyboard bugs: Fixed inability to bind non-ascii keys; Fixed only the first character being input when using an Input Method Signed-off-by: NaitLee --- keys.c | 18 +++++++++--------- keys.h | 12 +++++++++++- menu.c | 4 ++-- prvm_cmds.c | 2 +- vid_sdl.c | 15 +++++++++++---- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/keys.c b/keys.c index bcf1c916..1d320ec7 100644 --- a/keys.c +++ b/keys.c @@ -1351,6 +1351,7 @@ the K_* names are matched up. int Key_StringToKeynum (const char *str) { + Uchar ch; const keyname_t *kn; if (!str || !str[0]) @@ -1362,7 +1363,10 @@ Key_StringToKeynum (const char *str) if (!strcasecmp (str, kn->name)) return kn->keynum; } - return -1; + + // non-ascii keys are Unicode codepoints, so give the character + ch = u8_getnchar(str, &str, 3); + return ch == 0 ? -1 : (int)ch; } /* @@ -1387,13 +1391,9 @@ Key_KeynumToString (int keynum, char *tinystr, size_t tinystrlength) return kn->name; // if it is printable, output it as a single character - if (keynum > 32 && keynum < 256) + if (keynum > 32) { - if (tinystrlength >= 2) - { - tinystr[0] = keynum; - tinystr[1] = 0; - } + u8_fromchar(keynum, tinystr, tinystrlength); return tinystr; } @@ -1586,7 +1586,7 @@ static void Key_PrintBindList(int j) { char bindbuf[MAX_INPUTLINE]; - char tinystr[2]; + char tinystr[TINYSTR_LEN]; const char *p; int i; @@ -1679,7 +1679,7 @@ Key_WriteBindings (qfile_t *f) { int i, j; char bindbuf[MAX_INPUTLINE]; - char tinystr[2]; + char tinystr[TINYSTR_LEN]; const char *p; // Override default binds diff --git a/keys.h b/keys.h index 57ec1702..26c711d0 100644 --- a/keys.h +++ b/keys.h @@ -33,6 +33,16 @@ #include "fs.h" #include "cmd.h" +// the highest Unicode character to allow key binding. +// note that an excessively high value may degrade fps +// when code is looping through the bindings +#define MAX_KEY_BINDS 0xfff0 + +// how long is a "tinystr" to hold a keyboard key's +// Unicode utf-8 presentation, plus final \x00 +// to allow all characters <= 0xffff, use 4 +#define TINYSTR_LEN 4 + // // these are the key numbers that should be passed to Key_Event // @@ -353,7 +363,7 @@ typedef enum keynum_e K_MIDINOTE126, K_MIDINOTE127, - MAX_KEYS + MAX_KEYS = MAX_KEY_BINDS } keynum_t; diff --git a/menu.c b/menu.c index ce154097..990d6db3 100644 --- a/menu.c +++ b/menu.c @@ -2643,7 +2643,7 @@ static void M_Keys_Draw (void) strlcpy(keystring, "???", sizeof(keystring)); else { - char tinystr[2]; + char tinystr[TINYSTR_LEN]; keystring[0] = 0; for (j = 0;j < NUMKEYS;j++) { @@ -2669,7 +2669,7 @@ static void M_Keys_Key(cmd_state_t *cmd, int k, int ascii) { char line[80]; int keys[NUMKEYS]; - char tinystr[2]; + char tinystr[TINYSTR_LEN]; if (bind_grab) { // defining a key diff --git a/prvm_cmds.c b/prvm_cmds.c index 3ef0b74c..1cf7e852 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -3268,7 +3268,7 @@ string keynumtostring(float keynum) */ void VM_keynumtostring (prvm_prog_t *prog) { - char tinystr[2]; + char tinystr[TINYSTR_LEN]; VM_SAFEPARMCOUNT(1, VM_keynumtostring); PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0), tinystr, sizeof(tinystr))); diff --git a/vid_sdl.c b/vid_sdl.c index 5845e073..528882a8 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -100,7 +100,8 @@ static int MapKey( unsigned int sdlkey ) { switch(sdlkey) { - default: return 0; + // sdlkey can be Unicode codepoint for non-ascii keys, which are valid + default: return sdlkey; // case SDLK_UNKNOWN: return K_UNKNOWN; case SDLK_RETURN: return K_ENTER; case SDLK_ESCAPE: return K_ESCAPE; @@ -1066,6 +1067,7 @@ void Sys_SendKeyEvents( void ) static qbool sound_active = true; int keycode; int i; + const char *chp; qbool isdown; Uchar unicode; SDL_Event event; @@ -1222,9 +1224,14 @@ void Sys_SendKeyEvents( void ) #endif // convert utf8 string to char // NOTE: this code is supposed to run even if utf8enable is 0 - unicode = u8_getchar_utf8_enabled(event.text.text + (int)u8_bytelen(event.text.text, 0), NULL); - Key_Event(K_TEXT, unicode, true); - Key_Event(K_TEXT, unicode, false); + chp = event.text.text; + while (*chp != 0) + { + // input the chars one by one (there can be multiple chars when e.g. using an "input method") + unicode = u8_getchar_utf8_enabled(chp, &chp); + Key_Event(K_TEXT, unicode, true); + Key_Event(K_TEXT, unicode, false); + } break; case SDL_MOUSEMOTION: break; -- 2.39.2