/* ============ Cvar_Register Adds a freestanding variable to the variable list. If the variable already exists, the value will not be set The flags will be or'ed in if the variable exists. ============ */ EXTERNC void Cvar_Register (cvar_t *var) { char string[512]; int key; cvar_t *old; // first check to see if it has already been defined old = Cvar_Find (var->name); if (old && !(old->flags & CVAR_DYNAMIC)) { if (old == var) return; Com_Printf ("Can't register variable %s, already defined\n", var->name); return; } #if 0 // check for overlap with a command if (Cmd_Exists (var->name)) { Com_Printf ("Cvar_Register: %s is a command\n", var->name); return; } #endif if (old) { var->flags |= old->flags & ~(CVAR_DYNAMIC|CVAR_TEMP); strlcpy (string, old->string, sizeof(string)); Cvar_Delete (old->name); if (!(var->flags & CVAR_ROM)) var->string = Q_strdup (string); else var->string = Q_strdup (var->string); } else { // allocate the string on heap because future sets will Q_free it var->string = Q_strdup (var->string); } var->value = Q_atof (var->string); // link the variable in key = Com_HashKey (var->name); var->hash_next = cvar_hash[key]; cvar_hash[key] = var; var->next = cvar_vars; cvar_vars = var; #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif #ifndef SERVERONLY if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); #endif }
/* ============ Cvar_Set ============ */ void Cvar_Set (cvar_t *var, const char *string) { static qbool changing = false; if (!var) return; if (var->flags & CVAR_ROM) { Com_Printf ("\"%s\" is write protected\n", var->name); return; } if ((var->flags & CVAR_INIT) && host_initialized) { //if (cl_warncmd.value) // Com_Printf ("\"%s\" cannot be changed from the console\n", var->name); return; } if (var->OnChange && !changing) { qbool cancel = false; changing = true; var->OnChange(var, (char *)string, &cancel); changing = false; if (cancel) return; } // FIXME, avoid reallocation if the new string has same size? Q_free (var->string); var->string = Q_strdup (string); var->value = Q_atof (var->string); #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif #ifndef SERVERONLY if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); #endif }
/* Adds a freestanding variable to the variable list. If the variable already exists, the value will not be set The flags will be or'ed in if the variable exists. */ void Cvar_Register (cvar_t *var) { char string[512]; int key; cvar_t *old; // first check to see if it has already been defined old = Cvar_Find (var->name); // we alredy register cvar, warn about it if (old && !(old->flags & CVAR_USER_CREATED)) { // allow re-register lacthed cvar if (old->flags & CVAR_LATCH) { // if we have a latched string, take that value now if ( old->latchedString ) { // I did't want bother with all this CVAR_ROM and OnChange handler, just set value Q_free(old->string); old->string = old->latchedString; old->latchedString = NULL; old->value = Q_atof (old->string); old->integer = Q_atoi (old->string); StringToRGB_W(old->string, old->color); old->modified = true; } Cvar_AutoReset(old); return; } // warn if CVAR_SILENT is not set if (!(old->flags & CVAR_SILENT)) Com_Printf ("Can't register variable %s, already defined\n", var->name); return; } if (old && old == var) Sys_Error("Cvar_Register: something wrong with %s", var->name); /* // check for overlap with a command if (Cmd_Exists (var->name)) { Com_Printf ("Cvar_Register: %s is a command\n", var->name); return; } */ if (var->defaultvalue) Sys_Error("Cvar_Register: defaultvalue alredy set for %s", var->name); var->defaultvalue = Q_strdup(var->string); if (old) { var->flags |= old->flags & ~(CVAR_USER_CREATED|CVAR_TEMP); strlcpy (string, (var->flags & CVAR_ROM) ? var->string : old->string, sizeof(string)); Cvar_Delete (old->name); var->string = Q_strdup(string); } else { // allocate the string on zone because future sets will Q_freeit var->string = Q_strdup(var->string); } var->value = Q_atof (var->string); var->integer = Q_atoi (var->string); StringToRGB_W(var->string, var->color); var->modified = true; // link the variable in key = Com_HashKey (var->name) % VAR_HASHPOOL_SIZE; var->hash_next = cvar_hash[key]; cvar_hash[key] = var; var->next = cvar_vars; cvar_vars = var; #ifdef WITH_TCL TCL_RegisterVariable (var); #endif Cvar_AddCvarToGroup(var); #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); }
void Cvar_SetEx(cvar_t *var, char *value, qbool ignore_callback) { extern cvar_t cl_warncmd; extern cvar_t re_subi[10]; static qbool changing = false; float test; char *new_val; if (!var) return; // C code may wrongly use Cvar_Set on non registered variable, some 99.99% accurate check // variables for internal triggers are not registered intentionally if (var < re_subi || var > re_subi + 9) { if (!var->next /* this is fast, but a bit flawed logic */ && !Cvar_Find(var->name)) { Com_Printf("Cvar_Set: on non linked var %s\n", var->name); return; } } if (var->flags & CVAR_ROM) { Com_Printf ("\"%s\" is write protected\n", var->name); return; } if (var->flags & CVAR_RULESET_MIN) { test = Q_atof (value); if (test < var->minrulesetvalue) { Com_Printf ("min \"%s\" is limited to %0.2f\n", var->name,var->minrulesetvalue); return; } } if (var->flags & CVAR_RULESET_MAX) { test = Q_atof (value); if (test > var->maxrulesetvalue) { Com_Printf ("max \"%s\" is limited to %0.2f\n", var->name,var->maxrulesetvalue); return; } } if ((var->flags & CVAR_INIT) && host_initialized) { if (cl_warncmd.value || developer.value) Com_Printf ("\"%s\" can only be changed with \"+set %s %s\" on the command line.\n", var->name, var->name, value); return; } // We do this before OnChange check, which means no OnChange check for latched cvars. if (var->flags & CVAR_LATCH) { if (var->latchedString) { if (strcmp(value, var->latchedString) == 0) return; // latched string alredy has this value Q_free(var->latchedString); // switching latching string to other, so free it } else { if (strcmp(value, var->string) == 0) return; // we change string value to the same, do no create latched string then } // HACK: sometime I need somehow silently change latched cvars. // So, flag CVAR_SILENT for latched cvars mean no this warning. // However keep this flag always on latched variable is stupid imo. // So, do not mix CVAR_LATCHED | CVAR_SILENT in cvar definition. if ( !(var->flags & CVAR_SILENT) ) { const char* restartcmd = "vid_restart (video/graphics)"; if (strncmp(var->name, "in_", 3) == 0) { restartcmd = "in_restart (input)"; } else if (strncmp(var->name, "s_", 2) == 0) { restartcmd = "s_restart (sound)"; } Com_Printf ("%s needs %s to take effect.\n", var->name, restartcmd); } var->latchedString = Q_strdup(value); var->modified = true; // set to true even car->string is not changed yet, that how q3 does return; } if (!ignore_callback && var->OnChange && !changing) { qbool cancel = false; changing = true; var->OnChange(var, value, &cancel); changing = false; if (cancel) return; } // dup string first (before free) since 'value' and 'var->string' can point at the same memory area. new_val = Q_strdup(value); // free the old value string. Q_free(var->string); var->string = new_val; var->value = Q_atof (var->string); var->integer = Q_atoi (var->string); StringToRGB_W(var->string, var->color); Cvar_AutoReset(var); var->modified = true; #ifndef CLIENTONLY if (var->flags & CVAR_SERVERINFO) SV_ServerinfoChanged (var->name, var->string); #endif if (var->flags & CVAR_USERINFO) CL_UserinfoChanged (var->name, var->string); }