diff --git a/code/client/cl_console.c b/code/client/cl_console.c index 46438d7a..98ec0b6d 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -321,6 +321,7 @@ void Con_Init (void) { Field_Clear( &historyEditLines[i] ); historyEditLines[i].widthInChars = g_console_field_width; } + CL_LoadConsoleHistory( ); Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f); Cmd_AddCommand ("messagemode", Con_MessageMode_f); diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index 31cbe335..a14b5cea 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -486,7 +486,7 @@ void Console_Key (int key) { // if not in the game explicitly prepend a slash if needed if ( cls.state != CA_ACTIVE && g_consoleField.buffer[0] != '\\' && g_consoleField.buffer[0] != '/' ) { - char temp[MAX_STRING_CHARS]; + char temp[MAX_EDIT_LINE-1]; Q_strncpyz( temp, g_consoleField.buffer, sizeof( temp ) ); Com_sprintf( g_consoleField.buffer, sizeof( g_consoleField.buffer ), "\\%s", temp ); @@ -519,6 +519,8 @@ void Console_Key (int key) { g_consoleField.widthInChars = g_console_field_width; + CL_SaveConsoleHistory( ); + if ( cls.state == CA_DISCONNECTED ) { SCR_UpdateScreen (); // force an update, because the command } // may take some time @@ -1256,3 +1258,107 @@ void Key_ClearStates (void) } } +// This must not exceed MAX_CMD_LINE +#define MAX_CONSOLE_SAVE_BUFFER 1024 +static char consoleSaveBuffer[ MAX_CONSOLE_SAVE_BUFFER ]; + +/* +================ +CL_LoadConsoleHistory + +Load the console history from cl_consoleHistory +================ +*/ +void CL_LoadConsoleHistory( void ) +{ + char *token, *text_p; + int i, numChars, numLines = 0; + cvar_t *cv; + + cv = Cvar_Get( "cl_consoleHistory", "", CVAR_ARCHIVE|CVAR_ROM ); + Q_strncpyz( consoleSaveBuffer, cv->string, MAX_CONSOLE_SAVE_BUFFER ); + + text_p = consoleSaveBuffer; + + for( i = COMMAND_HISTORY - 1; i >= 0; i-- ) + { + if( !*( token = COM_Parse( &text_p ) ) ) + break; + + historyEditLines[ i ].cursor = atoi( token ); + + if( !*( token = COM_Parse( &text_p ) ) ) + break; + + historyEditLines[ i ].scroll = atoi( token ); + + if( !*( token = COM_Parse( &text_p ) ) ) + break; + + numChars = atoi( token ); + text_p++; + if( numChars > ( strlen( consoleSaveBuffer ) - ( text_p - consoleSaveBuffer ) ) ) + { + Com_DPrintf( S_COLOR_YELLOW "WARNING: probable corrupt history\n" ); + break; + } + Com_Memcpy( historyEditLines[ i ].buffer, + text_p, numChars ); + historyEditLines[ i ].buffer[ numChars ] = '\0'; + text_p += numChars; + + numLines++; + } + + memmove( &historyEditLines[ 0 ], &historyEditLines[ i + 1 ], + numLines * sizeof( field_t ) ); + for( i = numLines; i < COMMAND_HISTORY; i++ ) + Field_Clear( &historyEditLines[ i ] ); + + historyLine = nextHistoryLine = numLines; +} + +/* +================ +CL_SaveConsoleHistory + +Save the console history into the cvar cl_consoleHistory +so that it persists across invocations of q3 +================ +*/ +void CL_SaveConsoleHistory( void ) +{ + int i; + int lineLength, saveBufferLength, additionalLength; + + consoleSaveBuffer[ 0 ] = '\0'; + + i = ( nextHistoryLine - 1 ) % COMMAND_HISTORY; + do + { + if( historyEditLines[ i ].buffer[ 0 ] ) + { + lineLength = strlen( historyEditLines[ i ].buffer ); + saveBufferLength = strlen( consoleSaveBuffer ); + + //ICK "seta cl_consoleHistory " + "%d %d %d " = 23 + 13 = 36 + additionalLength = lineLength + 36; + + if( saveBufferLength + additionalLength < MAX_CONSOLE_SAVE_BUFFER ) + { + Q_strcat( consoleSaveBuffer, MAX_CONSOLE_SAVE_BUFFER, + va( "%d %d %d %s ", + historyEditLines[ i ].cursor, + historyEditLines[ i ].scroll, + lineLength, + historyEditLines[ i ].buffer ) ); + } + else + break; + } + i = ( i - 1 + COMMAND_HISTORY ) % COMMAND_HISTORY; + } + while( i != ( nextHistoryLine - 1 ) % COMMAND_HISTORY ); + + Cvar_Set( "cl_consoleHistory", consoleSaveBuffer ); +} diff --git a/code/client/client.h b/code/client/client.h index 599d494f..73106f8c 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -452,6 +452,8 @@ void Con_Top( void ); void Con_Bottom( void ); void Con_Close( void ); +void CL_LoadConsoleHistory( void ); +void CL_SaveConsoleHistory( void ); // // cl_scrn.c diff --git a/code/qcommon/common.c b/code/qcommon/common.c index eb46426b..7848dee1 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -2965,8 +2965,11 @@ PrintCvarMatches =============== */ static void PrintCvarMatches( const char *s ) { + char value[ TRUNCATE_LENGTH ]; + if ( !Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) { - Com_Printf( " %s = \"%s\"\n", s, Cvar_VariableString( s ) ); + Com_TruncateLongString( value, Cvar_VariableString( s ) ); + Com_Printf( " %s = \"%s\"\n", s, value ); } } diff --git a/code/qcommon/cvar.c b/code/qcommon/cvar.c index 2f59810d..2600880b 100644 --- a/code/qcommon/cvar.c +++ b/code/qcommon/cvar.c @@ -469,7 +469,10 @@ Handles variable inspection and changing from the console ============ */ qboolean Cvar_Command( void ) { - cvar_t *v; + cvar_t *v; + char string[ TRUNCATE_LENGTH ]; + char resetString[ TRUNCATE_LENGTH ]; + char latchedString[ TRUNCATE_LENGTH ]; // check variables v = Cvar_FindVar (Cmd_Argv(0)); @@ -479,9 +482,13 @@ qboolean Cvar_Command( void ) { // perform a variable print or set if ( Cmd_Argc() == 1 ) { - Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\" default:\"%s" S_COLOR_WHITE "\"\n", v->name, v->string, v->resetString ); + Com_TruncateLongString( string, v->string ); + Com_TruncateLongString( resetString, v->resetString ); + Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\" default:\"%s" S_COLOR_WHITE "\"\n", + v->name, string, resetString ); if ( v->latchedString ) { - Com_Printf( "latched: \"%s\"\n", v->latchedString ); + Com_TruncateLongString( latchedString, v->latchedString ); + Com_Printf( "latched: \"%s\"\n", latchedString ); } return qtrue; } @@ -645,11 +652,21 @@ void Cvar_WriteVariables( fileHandle_t f ) { if( var->flags & CVAR_ARCHIVE ) { // write the latched value, even if it hasn't taken effect yet if ( var->latchedString ) { + if( strlen( var->name ) + strlen( var->latchedString ) + 10 > sizeof( buffer ) ) { + Com_Printf( S_COLOR_YELLOW "WARNING: value of variable " + "\"%s\" too long to write to file\n", var->name ); + continue; + } Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->latchedString); } else { + if( strlen( var->name ) + strlen( var->string ) + 10 > sizeof( buffer ) ) { + Com_Printf( S_COLOR_YELLOW "WARNING: value of variable " + "\"%s\" too long to write to file\n", var->name ); + continue; + } Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->string); } - FS_Printf (f, "%s", buffer); + FS_Write( buffer, strlen( buffer ), f ); } } } diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index 2100390b..de54e179 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -918,6 +918,26 @@ char * QDECL va( char *format, ... ) { return buf; } +/* +============ +Com_TruncateLongString + +Assumes buffer is atleast TRUNCATE_LENGTH big +============ +*/ +void Com_TruncateLongString( char *buffer, const char *s ) +{ + int length = strlen( s ); + + if( length <= TRUNCATE_LENGTH ) + Q_strncpyz( buffer, s, TRUNCATE_LENGTH ); + else + { + Q_strncpyz( buffer, s, ( TRUNCATE_LENGTH / 2 ) - 3 ); + Q_strcat( buffer, TRUNCATE_LENGTH, " ... " ); + Q_strcat( buffer, TRUNCATE_LENGTH, s + length - ( TRUNCATE_LENGTH / 2 ) + 3 ); + } +} /* ===================================================================== diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 2dc55005..6e55a4d7 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -682,6 +682,9 @@ void Swap_Init (void); */ char * QDECL va(char *format, ...); +#define TRUNCATE_LENGTH 64 +void Com_TruncateLongString( char *buffer, const char *s ); + //============================================= //