summaryrefslogtreecommitdiff
path: root/src/qcommon/cvar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/qcommon/cvar.c')
-rw-r--r--src/qcommon/cvar.c306
1 files changed, 222 insertions, 84 deletions
diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c
index f82eb78f..459f602b 100644
--- a/src/qcommon/cvar.c
+++ b/src/qcommon/cvar.c
@@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "q_shared.h"
#include "qcommon.h"
-cvar_t *cvar_vars;
+cvar_t *cvar_vars = NULL;
cvar_t *cvar_cheats;
int cvar_modifiedFlags;
@@ -34,7 +34,7 @@ cvar_t cvar_indexes[MAX_CVARS];
int cvar_numIndexes;
#define FILE_HASH_SIZE 256
-static cvar_t* hashTable[FILE_HASH_SIZE];
+static cvar_t *hashTable[FILE_HASH_SIZE];
cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force);
@@ -182,11 +182,14 @@ int Cvar_Flags(const char *var_name)
Cvar_CommandCompletion
============
*/
-void Cvar_CommandCompletion( void(*callback)(const char *s) ) {
+void Cvar_CommandCompletion(void (*callback)(const char *s))
+{
cvar_t *cvar;
- for ( cvar = cvar_vars ; cvar ; cvar = cvar->next ) {
- callback( cvar->name );
+ for(cvar = cvar_vars; cvar; cvar = cvar->next)
+ {
+ if(cvar->name)
+ callback(cvar->name);
}
}
@@ -305,6 +308,7 @@ The flags will be or'ed in if the variable exists.
cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
cvar_t *var;
long hash;
+ int index;
if ( !var_name || ! var_value ) {
Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" );
@@ -323,13 +327,15 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
#endif
var = Cvar_FindVar (var_name);
- if ( var ) {
- var_value = Cvar_Validate( var, var_value, qfalse );
+
+ if(var)
+ {
+ var_value = Cvar_Validate(var, var_value, qfalse);
// if the C code is now specifying a variable that the user already
// set a value for, take the new value as the reset value
- if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED )
- && var_value[0] ) {
+ if(var->flags & CVAR_USER_CREATED)
+ {
var->flags &= ~CVAR_USER_CREATED;
Z_Free( var->resetString );
var->resetString = CopyString( var_value );
@@ -344,13 +350,22 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
var->latchedString = CopyString(var_value);
}
-
- // ZOID--needs to be set so that cvars the game sets as
- // SERVERINFO get sent to clients
- cvar_modifiedFlags |= flags;
}
-
+
+ // Make sure the game code cannot mark engine-added variables as gamecode vars
+ if(var->flags & CVAR_VM_CREATED)
+ {
+ if(!(flags & CVAR_VM_CREATED))
+ var->flags &= ~CVAR_VM_CREATED;
+ }
+ else
+ {
+ if(flags & CVAR_VM_CREATED)
+ flags &= ~CVAR_VM_CREATED;
+ }
+
var->flags |= flags;
+
// only allow one non-empty reset string without a warning
if ( !var->resetString[0] ) {
// we don't have a reset string yet
@@ -368,6 +383,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
var->latchedString = NULL; // otherwise cvar_set2 would free it
Cvar_Set2( var_name, s, qtrue );
Z_Free( s );
+
+ // ZOID--needs to be set so that cvars the game sets as
+ // SERVERINFO get sent to clients
+ cvar_modifiedFlags |= flags;
}
return var;
@@ -376,11 +395,27 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
//
// allocate a new cvar
//
- if ( cvar_numIndexes >= MAX_CVARS ) {
- Com_Error( ERR_FATAL, "MAX_CVARS" );
+
+ // find a free cvar
+ for(index = 0; index < MAX_CVARS; index++)
+ {
+ if(!cvar_indexes[index].name)
+ break;
+ }
+
+ if(index >= MAX_CVARS)
+ {
+ if(!com_errorEntered)
+ Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!");
+
+ return NULL;
}
- var = &cvar_indexes[cvar_numIndexes];
- cvar_numIndexes++;
+
+ var = &cvar_indexes[index];
+
+ if(index >= cvar_numIndexes)
+ cvar_numIndexes = index + 1;
+
var->name = CopyString (var_name);
var->string = CopyString (var_value);
var->modified = qtrue;
@@ -392,6 +427,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
// link the variable in
var->next = cvar_vars;
+ if(cvar_vars)
+ cvar_vars->prev = var;
+
+ var->prev = NULL;
cvar_vars = var;
var->flags = flags;
@@ -399,7 +438,13 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
cvar_modifiedFlags |= var->flags;
hash = generateHashValue(var_name);
+ var->hashIndex = hash;
+
var->hashNext = hashTable[hash];
+ if(hashTable[hash])
+ hashTable[hash]->hashPrev = var;
+
+ var->hashPrev = NULL;
hashTable[hash] = var;
return var;
@@ -471,15 +516,23 @@ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
value = var->resetString;
}
- value = Cvar_Validate( var, value, qtrue );
+ value = Cvar_Validate(var, value, qtrue);
- if((var->flags & CVAR_LATCH) && var->latchedString) {
- if(!strcmp(value,var->latchedString))
+ if((var->flags & CVAR_LATCH) && var->latchedString)
+ {
+ if(!strcmp(value, var->string))
+ {
+ Z_Free(var->latchedString);
+ var->latchedString = NULL;
+ return var;
+ }
+
+ if(!strcmp(value, var->latchedString))
return var;
}
- else if (!strcmp(value,var->string)) {
+ else if(!strcmp(value, var->string))
return var;
- }
+
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
cvar_modifiedFlags |= var->flags;
@@ -610,12 +663,15 @@ Cvar_SetCheatState
Any testing variables will be reset to the safe values
============
*/
-void Cvar_SetCheatState( void ) {
+void Cvar_SetCheatState(void)
+{
cvar_t *var;
// set all default vars to the safe value
- for ( var = cvar_vars ; var ; var = var->next ) {
- if ( var->flags & CVAR_CHEAT ) {
+ for(var = cvar_vars; var ; var = var->next)
+ {
+ if(var->flags & CVAR_CHEAT)
+ {
// the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
// because of a different var->latchedString
if (var->latchedString)
@@ -623,9 +679,8 @@ void Cvar_SetCheatState( void ) {
Z_Free(var->latchedString);
var->latchedString = NULL;
}
- if (strcmp(var->resetString,var->string)) {
- Cvar_Set( var->name, var->resetString );
- }
+ if (strcmp(var->resetString,var->string))
+ Cvar_Set(var->name, var->resetString);
}
}
}
@@ -803,11 +858,16 @@ Appends lines containing "set variable value" for all variables
with the archive flag set to qtrue.
============
*/
-void Cvar_WriteVariables( fileHandle_t f ) {
+void Cvar_WriteVariables(fileHandle_t f)
+{
cvar_t *var;
char buffer[1024];
- for (var = cvar_vars ; var ; var = var->next) {
+ for (var = cvar_vars; var; var = var->next)
+ {
+ if(!var->name)
+ continue;
+
if( var->flags & CVAR_ARCHIVE ) {
// write the latched value, even if it hasn't taken effect yet
if ( var->latchedString ) {
@@ -849,7 +909,8 @@ void Cvar_List_f( void ) {
i = 0;
for (var = cvar_vars ; var ; var = var->next, i++)
{
- if (match && !Com_Filter(match, var->name, qfalse)) continue;
+ if(!var->name || (match && !Com_Filter(match, var->name, qfalse)))
+ continue;
if (var->flags & CVAR_SERVERINFO) {
Com_Printf("S");
@@ -906,74 +967,141 @@ void Cvar_List_f( void ) {
/*
============
-Cvar_Restart_f
+Cvar_Unset
-Resets all cvars to their hardcoded values
+Unsets a cvar
============
*/
-void Cvar_Restart_f( void ) {
- cvar_t *var;
- cvar_t **prev;
- prev = &cvar_vars;
- while ( 1 ) {
- var = *prev;
- if ( !var ) {
- break;
- }
+cvar_t *Cvar_Unset(cvar_t *cv)
+{
+ cvar_t *next = cv->next;
+
+ if(cv->name)
+ Z_Free(cv->name);
+ if(cv->string)
+ Z_Free(cv->string);
+ if(cv->latchedString)
+ Z_Free(cv->latchedString);
+ if(cv->resetString)
+ Z_Free(cv->resetString);
+
+ if(cv->prev)
+ cv->prev->next = cv->next;
+ else
+ cvar_vars = cv->next;
+ if(cv->next)
+ cv->next->prev = cv->prev;
- // don't mess with rom values, or some inter-module
- // communication will get broken (com_cl_running, etc)
- if ( var->flags & ( CVAR_ROM | CVAR_INIT | CVAR_NORESTART ) ) {
- prev = &var->next;
- continue;
- }
+ if(cv->hashPrev)
+ cv->hashPrev->hashNext = cv->hashNext;
+ else
+ hashTable[cv->hashIndex] = cv->hashNext;
+ if(cv->hashNext)
+ cv->hashNext->hashPrev = cv->hashPrev;
- // throw out any variables the user created
- if ( var->flags & CVAR_USER_CREATED ) {
- *prev = var->next;
- if ( var->name ) {
- Z_Free( var->name );
- }
- if ( var->string ) {
- Z_Free( var->string );
- }
- if ( var->latchedString ) {
- Z_Free( var->latchedString );
- }
- if ( var->resetString ) {
- Z_Free( var->resetString );
- }
- // clear the var completely, since we
- // can't remove the index from the list
- Com_Memset( var, 0, sizeof( var ) );
- continue;
- }
+ Com_Memset(cv, '\0', sizeof(*cv));
+
+ return next;
+}
- Cvar_Set( var->name, var->resetString );
+/*
+============
+Cvar_Unset_f
+
+Unsets a userdefined cvar
+============
+*/
- prev = &var->next;
+void Cvar_Unset_f(void)
+{
+ cvar_t *cv;
+
+ if(Cmd_Argc() != 2)
+ {
+ Com_Printf("Usage: %s <varname>\n", Cmd_Argv(0));
+ return;
}
+
+ cv = Cvar_FindVar(Cmd_Argv(1));
+
+ if(!cv)
+ return;
+
+ if(cv->flags & CVAR_USER_CREATED)
+ Cvar_Unset(cv);
+ else
+ Com_Printf("Error: %s: Variable %s is not user created.\n", Cmd_Argv(0), cv->name);
}
/*
+============
+Cvar_Restart
+
+Resets all cvars to their hardcoded values and removes userdefined variables
+and variables added via the VMs if requested.
+============
+*/
+
+void Cvar_Restart(qboolean unsetVM)
+{
+ cvar_t *curvar;
+
+ curvar = cvar_vars;
+
+ while(curvar)
+ {
+ if((curvar->flags & CVAR_USER_CREATED) ||
+ (unsetVM && (curvar->flags & CVAR_VM_CREATED)))
+ {
+ // throw out any variables the user/vm created
+ curvar = Cvar_Unset(curvar);
+ continue;
+ }
+
+ if(!(curvar->flags & (CVAR_ROM | CVAR_INIT | CVAR_NORESTART)))
+ {
+ // Just reset the rest to their default values.
+ Cvar_Set2(curvar->name, curvar->resetString, qfalse);
+ }
+
+ curvar = curvar->next;
+ }
+}
+
+
+/*
+============
+Cvar_Restart_f
+
+Resets all cvars to their hardcoded values
+============
+*/
+void Cvar_Restart_f(void)
+{
+ Cvar_Restart(qfalse);
+}
+
+/*
=====================
Cvar_InfoString
=====================
*/
-char *Cvar_InfoString( int bit ) {
+char *Cvar_InfoString(int bit)
+{
static char info[MAX_INFO_STRING];
cvar_t *var;
info[0] = 0;
- for (var = cvar_vars ; var ; var = var->next) {
- if (var->flags & bit) {
+ for(var = cvar_vars; var; var = var->next)
+ {
+ if(var->name && (var->flags & bit))
Info_SetValueForKey (info, var->name, var->string);
- }
}
+
return info;
}
@@ -984,16 +1112,17 @@ Cvar_InfoString_Big
handles large info strings ( CS_SYSTEMINFO )
=====================
*/
-char *Cvar_InfoString_Big( int bit ) {
+char *Cvar_InfoString_Big(int bit)
+{
static char info[BIG_INFO_STRING];
cvar_t *var;
info[0] = 0;
- for (var = cvar_vars ; var ; var = var->next) {
- if (var->flags & bit) {
+ for (var = cvar_vars; var; var = var->next)
+ {
+ if(var->name && (var->flags & bit))
Info_SetValueForKey_Big (info, var->name, var->string);
- }
}
return info;
}
@@ -1032,13 +1161,15 @@ Cvar_Register
basically a slightly modified Cvar_Get for the interpreted modules
=====================
*/
-void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) {
+void Cvar_Register(vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags)
+{
cvar_t *cv;
- cv = Cvar_Get( varName, defaultValue, flags );
- if ( !vmCvar ) {
+ cv = Cvar_Get(varName, defaultValue, flags | CVAR_VM_CREATED);
+
+ if (!vmCvar)
return;
- }
+
vmCvar->handle = cv - cvar_indexes;
vmCvar->modificationCount = -1;
Cvar_Update( vmCvar );
@@ -1103,7 +1234,11 @@ Cvar_Init
Reads in all archived cvars
============
*/
-void Cvar_Init (void) {
+void Cvar_Init (void)
+{
+ Com_Memset(cvar_indexes, '\0', sizeof(cvar_indexes));
+ Com_Memset(hashTable, '\0', sizeof(hashTable));
+
cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO );
Cmd_AddCommand ("print", Cvar_Print_f);
@@ -1119,6 +1254,9 @@ void Cvar_Init (void) {
Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName );
Cmd_AddCommand ("reset", Cvar_Reset_f);
Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName );
+ Cmd_AddCommand ("unset", Cvar_Unset_f);
+ Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName);
+
Cmd_AddCommand ("cvarlist", Cvar_List_f);
Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
}