diff --git a/README b/README index fa03714d..4a4ce723 100644 --- a/README +++ b/README @@ -399,15 +399,14 @@ SDL Keyboard Differences If you use such a keyboard layout, you can set the cvar cl_consoleKeys. This is a space delimited list of key names that will toggle the console. The key - names are the usual Q3 names e.g. "BACKSPACE", "PAUSE", "WINDOWS" etc. It's - also possible to use ASCII characters, either by hexadecimal number e.g. - "0x7e" (equivalent to ~) or directly by character. Some example values for - cl_consoleKeys: + names are the usual Q3 names e.g. "~", "`", "c", "BACKSPACE", "PAUSE", + "WINDOWS" etc. It's also possible to use ASCII characters, by hexadecimal + number. Some example values for cl_consoleKeys: - "0x7e 0x60" Toggle on ~ or ` (the default) + "~ ` 0x7e 0x60" Toggle on ~ or ` (the default) "WINDOWS" Toggle on the Windows key - "c" Toggle on the c character - "C" Toggle on the C character (Shift-c) + "c" Toggle on the c key + "0x43" Toggle on the C character (Shift-c) "PAUSE F1 PGUP" Toggle on the Pause, F1 or Page Up keys Note that when you elect a set of console keys or characters, they cannot diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index fea1b747..3097f54b 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -776,7 +776,6 @@ qboolean Key_IsDown( int keynum ) { return keys[keynum].down; } - /* =================== Key_StringToKeynum @@ -801,28 +800,12 @@ int Key_StringToKeynum( char *str ) { } // check for hex code - if ( str[0] == '0' && str[1] == 'x' && strlen( str ) == 4) { - int n1, n2; - - n1 = str[2]; - if ( n1 >= '0' && n1 <= '9' ) { - n1 -= '0'; - } else if ( n1 >= 'a' && n1 <= 'f' ) { - n1 = n1 - 'a' + 10; - } else { - n1 = 0; - } + if ( strlen( str ) == 4 ) { + int n = Com_HexStrToInt( str ); - n2 = str[3]; - if ( n2 >= '0' && n2 <= '9' ) { - n2 -= '0'; - } else if ( n2 >= 'a' && n2 <= 'f' ) { - n2 = n2 - 'a' + 10; - } else { - n2 = 0; + if ( n >= 0 ) { + return n; } - - return n1 * 16 + n2; } // scan for a text match diff --git a/code/client/cl_main.c b/code/client/cl_main.c index 23a07d67..353d2b39 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -3079,8 +3079,8 @@ void CL_Init( void ) { cl_guidServerUniq = Cvar_Get ("cl_guidServerUniq", "1", CVAR_ARCHIVE); - // 0x7e = ~ and 0x60 = ` - cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "0x7e 0x60", CVAR_ARCHIVE); + // ~ and `, as keys and characters + cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE); // userinfo Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index bf9a341e..de173d88 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -361,48 +361,48 @@ int COM_Compress( char *data_p ) { in++; if ( *in ) in += 2; - // record when we hit a newline - } else if ( c == '\n' || c == '\r' ) { - newline = qtrue; - in++; - // record when we hit whitespace - } else if ( c == ' ' || c == '\t') { - whitespace = qtrue; - in++; - // an actual token + // record when we hit a newline + } else if ( c == '\n' || c == '\r' ) { + newline = qtrue; + in++; + // record when we hit whitespace + } else if ( c == ' ' || c == '\t') { + whitespace = qtrue; + in++; + // an actual token } else { - // if we have a pending newline, emit it (and it counts as whitespace) - if (newline) { - *out++ = '\n'; - newline = qfalse; - whitespace = qfalse; - } if (whitespace) { - *out++ = ' '; - whitespace = qfalse; - } - - // copy quoted strings unmolested - if (c == '"') { - *out++ = c; - in++; - while (1) { - c = *in; - if (c && c != '"') { - *out++ = c; - in++; - } else { - break; - } - } - if (c == '"') { - *out++ = c; - in++; - } - } else { - *out = c; - out++; - in++; - } + // if we have a pending newline, emit it (and it counts as whitespace) + if (newline) { + *out++ = '\n'; + newline = qfalse; + whitespace = qfalse; + } if (whitespace) { + *out++ = ' '; + whitespace = qfalse; + } + + // copy quoted strings unmolested + if (c == '"') { + *out++ = c; + in++; + while (1) { + c = *in; + if (c && c != '"') { + *out++ = c; + in++; + } else { + break; + } + } + if (c == '"') { + *out++ = c; + in++; + } + } else { + *out = c; + out++; + in++; + } } } } @@ -512,62 +512,6 @@ char *COM_ParseExt( char **data_p, qboolean allowLineBreaks ) return com_token; } - -#if 0 -// no longer used -/* -=============== -COM_ParseInfos -=============== -*/ -int COM_ParseInfos( char *buf, int max, char infos[][MAX_INFO_STRING] ) { - char *token; - int count; - char key[MAX_TOKEN_CHARS]; - - count = 0; - - while ( 1 ) { - token = COM_Parse( &buf ); - if ( !token[0] ) { - break; - } - if ( strcmp( token, "{" ) ) { - Com_Printf( "Missing { in info file\n" ); - break; - } - - if ( count == max ) { - Com_Printf( "Max infos exceeded\n" ); - break; - } - - infos[count][0] = 0; - while ( 1 ) { - token = COM_ParseExt( &buf, qtrue ); - if ( !token[0] ) { - Com_Printf( "Unexpected end of info file\n" ); - break; - } - if ( !strcmp( token, "}" ) ) { - break; - } - Q_strncpyz( key, token, sizeof( key ) ); - - token = COM_ParseExt( &buf, qfalse ); - if ( !token[0] ) { - strcpy( token, "" ); - } - Info_SetValueForKey( infos[count], key, token ); - } - count++; - } - - return count; -} -#endif - - /* ================== COM_MatchToken @@ -669,6 +613,44 @@ void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m) { COM_MatchToken( buf_p, ")" ); } +/* +=================== +Com_HexStrToInt +=================== +*/ +int Com_HexStrToInt( const char *str ) +{ + if ( !str || !str[ 0 ] ) + return -1; + + // check for hex code + if( str[ 0 ] == '0' && str[ 1 ] == 'x' ) + { + int i, n = 0; + + for( i = 2; i < strlen( str ); i++ ) + { + char digit; + + n *= 16; + + digit = tolower( str[ i ] ); + + if( digit >= '0' && digit <= '9' ) + digit -= '0'; + else if( digit >= 'a' && digit <= 'f' ) + digit = digit - 'a' + 10; + else + return -1; + + n += digit; + } + + return n; + } + + return -1; +} /* ============================================================================ diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 9a7ddacd..a18ea298 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -652,6 +652,7 @@ void SkipRestOfLine ( char **data ); void Parse1DMatrix (char **buf_p, int x, float *m); void Parse2DMatrix (char **buf_p, int y, int x, float *m); void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m); +int Com_HexStrToInt( const char *str ); void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index b2fb9816..a74887a0 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -84,7 +84,7 @@ static void IN_PrintKey( const SDL_keysym *keysym, keyNum_t key, qboolean down ) else Com_Printf( " " ); - Com_Printf( "0x%hx \"%s\"", keysym->scancode, + Com_Printf( "0x%02x \"%s\"", keysym->scancode, SDL_GetKeyName( keysym->sym ) ); if( keysym->mod & KMOD_LSHIFT ) Com_Printf( " KMOD_LSHIFT" ); @@ -100,11 +100,11 @@ static void IN_PrintKey( const SDL_keysym *keysym, keyNum_t key, qboolean down ) if( keysym->mod & KMOD_MODE ) Com_Printf( " KMOD_MODE" ); if( keysym->mod & KMOD_RESERVED ) Com_Printf( " KMOD_RESERVED" ); - Com_Printf( " Q:%d(%s)", key, Key_KeynumToString( key ) ); + Com_Printf( " Q:0x%02x(%s)", key, Key_KeynumToString( key ) ); if( keysym->unicode ) { - Com_Printf( " U:%d", keysym->unicode ); + Com_Printf( " U:0x%02x", keysym->unicode ); if( keysym->unicode > ' ' && keysym->unicode < '~' ) Com_Printf( "(%c)", (char)keysym->unicode ); @@ -120,7 +120,7 @@ static void IN_PrintKey( const SDL_keysym *keysym, keyNum_t key, qboolean down ) IN_IsConsoleKey =============== */ -static qboolean IN_IsConsoleKey( keyNum_t key, const char character ) +static qboolean IN_IsConsoleKey( keyNum_t key, const unsigned char character ) { typedef struct consoleKey_s { @@ -133,7 +133,7 @@ static qboolean IN_IsConsoleKey( keyNum_t key, const char character ) union { keyNum_t key; - char character; + unsigned char character; } u; } consoleKey_t; @@ -153,34 +153,36 @@ static qboolean IN_IsConsoleKey( keyNum_t key, const char character ) while( numConsoleKeys < MAX_CONSOLE_KEYS ) { consoleKey_t *c = &consoleKeys[ numConsoleKeys ]; - char *keyName; + int charCode = 0; token = COM_Parse( &text_p ); if( !token[ 0 ] ) break; - c->u.key = Key_StringToKeynum( token ); + if( strlen( token ) == 4 ) + charCode = Com_HexStrToInt( token ); - // 0 isn't a key - if( c->u.key == 0 ) - continue; - - keyName = Key_KeynumToString( c->u.key ); - - if( strlen( keyName ) == 1 ) + if( charCode > 0 ) { c->type = CHARACTER; - c->u.character = *keyName; + c->u.character = (unsigned char)charCode; } else + { c->type = KEY; + c->u.key = Key_StringToKeynum( token ); + + // 0 isn't a key + if( c->u.key <= 0 ) + continue; + } numConsoleKeys++; } } - // Use the character in preference to the key name - if( character != '\0' ) + // If the character is the same as the key, prefer the character + if( key == character ) key = 0; for( i = 0; i < numConsoleKeys; i++ ) @@ -212,7 +214,7 @@ IN_TranslateSDLToQ3Key static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym, keyNum_t *key, qboolean down ) { - static char buf[ 2 ] = { '\0', '\0' }; + static unsigned char buf[ 2 ] = { '\0', '\0' }; *buf = '\0'; *key = 0; @@ -311,9 +313,9 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym, } } - if( down && keysym->unicode && !( keysym->unicode & 0xFF80 ) ) + if( down && keysym->unicode && !( keysym->unicode & 0xFF00 ) ) { - char ch = (char)keysym->unicode & 0x7F; + unsigned char ch = (unsigned char)keysym->unicode & 0xFF; switch( ch ) { @@ -333,6 +335,17 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym, if( in_keyboardDebug->integer ) IN_PrintKey( keysym, *key, down ); + // Keys that have ASCII names but produce no character are probably + // dead keys -- ignore them + if( down && strlen( Key_KeynumToString( *key ) ) == 1 && + keysym->unicode == 0 ) + { + if( in_keyboardDebug->integer ) + Com_Printf( " Ignored dead key '%c'\n", *key ); + + *key = 0; + } + if( IN_IsConsoleKey( *key, *buf ) ) { // Console keys can't be bound or generate characters @@ -340,7 +353,11 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym, *buf = '\0'; } - return buf; + // Don't allow extended ASCII to generate characters + if( *buf & 0x80 ) + *buf = '\0'; + + return (char *)buf; } #ifdef MACOS_X_ACCELERATION_HACK @@ -817,7 +834,7 @@ IN_ProcessEvents static void IN_ProcessEvents( void ) { SDL_Event e; - const char *p = NULL; + const char *character = NULL; keyNum_t key = 0; if( !SDL_WasInit( SDL_INIT_VIDEO ) ) @@ -840,20 +857,19 @@ static void IN_ProcessEvents( void ) switch( e.type ) { case SDL_KEYDOWN: - p = IN_TranslateSDLToQ3Key( &e.key.keysym, &key, qtrue ); + character = IN_TranslateSDLToQ3Key( &e.key.keysym, &key, qtrue ); if( key ) Com_QueueEvent( 0, SE_KEY, key, qtrue, 0, NULL ); - if( p ) - { - while( *p ) - Com_QueueEvent( 0, SE_CHAR, *p++, 0, 0, NULL ); - } + if( character ) + Com_QueueEvent( 0, SE_CHAR, *character, 0, 0, NULL ); break; case SDL_KEYUP: IN_TranslateSDLToQ3Key( &e.key.keysym, &key, qfalse ); - Com_QueueEvent( 0, SE_KEY, key, qfalse, 0, NULL ); + + if( key ) + Com_QueueEvent( 0, SE_KEY, key, qfalse, 0, NULL ); break; case SDL_MOUSEMOTION: