2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // cvar.c -- dynamic variable tracking
24 cvar_t *cvar_vars = NULL;
25 char *cvar_null_string = "";
32 cvar_t *Cvar_FindVar (const char *var_name)
36 for (var = cvar_vars;var;var = var->next)
37 if (!strcasecmp (var_name, var->name))
43 cvar_t *Cvar_FindVarAfter (const char *prev_var_name, int neededflags)
49 var = Cvar_FindVar (prev_var_name);
57 // search for the next cvar matching the needed flags
60 if ((var->flags & neededflags) || !neededflags)
72 float Cvar_VariableValue (const char *var_name)
76 var = Cvar_FindVar (var_name);
79 return atof (var->string);
88 const char *Cvar_VariableString (const char *var_name)
92 var = Cvar_FindVar (var_name);
94 return cvar_null_string;
100 Cvar_VariableDefString
103 const char *Cvar_VariableDefString (const char *var_name)
107 var = Cvar_FindVar (var_name);
109 return cvar_null_string;
110 return var->defstring;
116 Cvar_CompleteVariable
119 const char *Cvar_CompleteVariable (const char *partial)
124 len = strlen(partial);
130 for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
131 if (!strncasecmp (partial,cvar->name, len))
139 CVar_CompleteCountPossible
141 New function for tab-completion system
143 Thanks to Fett erich@heintz.com
146 int Cvar_CompleteCountPossible (const char *partial)
153 len = strlen(partial);
158 // Loop through the cvars and count all possible matches
159 for (cvar = cvar_vars; cvar; cvar = cvar->next)
160 if (!strncasecmp(partial, cvar->name, len))
167 CVar_CompleteBuildList
169 New function for tab-completion system
171 Thanks to Fett erich@heintz.com
175 const char **Cvar_CompleteBuildList (const char *partial)
180 size_t sizeofbuf = (Cvar_CompleteCountPossible (partial) + 1) * sizeof (const char *);
183 len = strlen(partial);
184 buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
185 // Loop through the alias list and print all matches
186 for (cvar = cvar_vars; cvar; cvar = cvar->next)
187 if (!strncasecmp(partial, cvar->name, len))
188 buf[bpos++] = cvar->name;
199 void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
203 changed = strcmp(var->string, value);
204 // LordHavoc: don't reallocate when there is no change
208 // LordHavoc: don't reallocate when the buffer is the same size
209 if (!var->string || strlen(var->string) != strlen(value))
211 Z_Free (var->string); // free the old value string
213 var->string = (char *)Z_Malloc (strlen(value)+1);
215 strcpy (var->string, value);
216 var->value = atof (var->string);
217 var->integer = (int) var->value;
218 if ((var->flags & CVAR_NOTIFY) && changed && sv.active)
219 SV_BroadcastPrintf("\"%s\" changed to \"%s\"\n", var->name, var->string);
222 void Cvar_SetQuick (cvar_t *var, const char *value)
226 Con_Print("Cvar_SetQuick: var == NULL\n");
230 if (developer.integer)
231 Con_Printf("Cvar_SetQuick({\"%s\", \"%s\", %i, \"%s\"}, \"%s\");\n", var->name, var->string, var->flags, var->defstring, value);
233 Cvar_SetQuick_Internal(var, value);
236 void Cvar_Set (const char *var_name, const char *value)
239 var = Cvar_FindVar (var_name);
242 Con_Printf("Cvar_Set: variable %s not found\n", var_name);
245 Cvar_SetQuick(var, value);
253 void Cvar_SetValueQuick(cvar_t *var, float value)
257 if ((float)((int)value) == value)
258 sprintf(val, "%i", (int)value);
260 sprintf(val, "%f", value);
261 Cvar_SetQuick(var, val);
264 void Cvar_SetValue(const char *var_name, float value)
268 if ((float)((int)value) == value)
269 sprintf(val, "%i", (int)value);
271 sprintf(val, "%f", value);
272 Cvar_Set(var_name, val);
277 Cvar_RegisterVariable
279 Adds a freestanding variable to the variable list.
282 void Cvar_RegisterVariable (cvar_t *variable)
284 cvar_t *current, *next, *cvar;
287 if (developer.integer)
288 Con_Printf("Cvar_RegisterVariable({\"%s\", \"%s\", %i});\n", variable->name, variable->string, variable->flags);
290 // first check to see if it has already been defined
291 cvar = Cvar_FindVar (variable->name);
294 if (cvar->flags & CVAR_ALLOCATED)
296 if (developer.integer)
297 Con_Printf("... replacing existing allocated cvar {\"%s\", \"%s\", %i}", cvar->name, cvar->string, cvar->flags);
298 // fixed variables replace allocated ones
299 // (because the engine directly accesses fixed variables)
300 // NOTE: this isn't actually used currently
301 // (all cvars are registered before config parsing)
302 variable->flags |= (cvar->flags & ~CVAR_ALLOCATED);
303 // cvar->string is now owned by variable instead
304 variable->string = cvar->string;
305 variable->defstring = cvar->defstring;
306 variable->value = atof (variable->string);
307 variable->integer = (int) variable->value;
308 // replace cvar with this one...
309 variable->next = cvar->next;
310 if (cvar_vars == cvar)
312 // head of the list is easy to change
313 cvar_vars = variable;
317 // otherwise find it somewhere in the list
318 for (current = cvar_vars;current->next != cvar;current = current->next)
320 current->next = variable;
323 // get rid of old allocated cvar
324 // (but not cvar->string and cvar->defstring, because we kept those)
329 Con_Printf("Can't register variable %s, already defined\n", variable->name);
333 // check for overlap with a command
334 if (Cmd_Exists (variable->name))
336 Con_Printf("Cvar_RegisterVariable: %s is a command\n", variable->name);
340 // copy the value off, because future sets will Z_Free it
341 oldstr = variable->string;
342 variable->string = (char *)Z_Malloc (strlen(variable->string)+1);
343 strcpy (variable->string, oldstr);
344 variable->defstring = (char *)Z_Malloc (strlen(variable->string)+1);
345 strcpy (variable->defstring, oldstr);
346 variable->value = atof (variable->string);
347 variable->integer = (int) variable->value;
349 // link the variable in
350 // alphanumerical order
351 for( current = NULL, next = cvar_vars ; next && strcmp( next->name, variable->name ) < 0 ; current = next, next = next->next )
354 current->next = variable;
356 cvar_vars = variable;
358 variable->next = next;
365 Adds a newly allocated variable to the variable list or sets its value.
368 cvar_t *Cvar_Get (const char *name, const char *value, int flags)
372 if (developer.integer)
373 Con_Printf("Cvar_Get(\"%s\", \"%s\", %i);\n", name, value, flags);
375 // first check to see if it has already been defined
376 cvar = Cvar_FindVar (name);
379 cvar->flags |= flags;
380 Cvar_SetQuick_Internal (cvar, value);
381 // also set the default value (but only once)
382 if (~cvar->flags & CVAR_DEFAULTSET)
384 cvar->flags |= CVAR_DEFAULTSET;
386 Z_Free(cvar->defstring);
387 cvar->defstring = (char *)Z_Malloc(strlen(value) + 1);
388 strcpy(cvar->defstring, value);
393 // check for overlap with a command
394 if (Cmd_Exists (name))
396 Con_Printf("Cvar_Get: %s is a command\n", name);
400 // allocate a new cvar, cvar name, and cvar string
401 // FIXME: these never get Z_Free'd
402 cvar = (cvar_t *)Z_Malloc(sizeof(cvar_t));
403 cvar->flags = flags | CVAR_ALLOCATED | CVAR_DEFAULTSET;
404 cvar->name = (char *)Z_Malloc(strlen(name)+1);
405 strcpy(cvar->name, name);
406 cvar->string = (char *)Z_Malloc(strlen(value)+1);
407 strcpy(cvar->string, value);
408 cvar->defstring = (char *)Z_Malloc(strlen(value)+1);
409 strcpy(cvar->defstring, value);
410 cvar->value = atof (cvar->string);
411 cvar->integer = (int) cvar->value;
413 // link the variable in
414 cvar->next = cvar_vars;
424 Handles variable inspection and changing from the console
427 qboolean Cvar_Command (void)
432 v = Cvar_FindVar (Cmd_Argv(0));
436 // perform a variable print or set
439 Con_Printf("\"%s\" is \"%s\" [\"%s\"]\n", v->name, v->string, v->defstring);
443 Con_DPrint("Cvar_Command: ");
445 if (v->flags & CVAR_READONLY)
447 Con_Printf("%s is read-only\n", v->name);
450 Cvar_Set (v->name, Cmd_Argv(1));
459 Writes lines containing "set variable value" for all variables
460 with the archive flag set to true.
463 void Cvar_WriteVariables (qfile_t *f)
467 for (var = cvar_vars ; var ; var = var->next)
468 if (var->flags & CVAR_SAVE)
469 FS_Printf(f, "%s%s \"%s\"\n", var->flags & CVAR_ALLOCATED ? "seta " : "", var->name, var->string);
473 // Added by EvilTypeGuy eviltypeguy@qeradiant.com
474 // 2000-01-09 CvarList command By Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
480 void Cvar_List_f (void)
489 partial = Cmd_Argv (1);
490 len = strlen(partial);
499 for (cvar = cvar_vars; cvar; cvar = cvar->next)
501 if (partial && strncasecmp (partial,cvar->name,len))
504 Con_Printf("%s is \"%s\" [\"%s\"]\n", cvar->name, cvar->string, cvar->defstring);
508 Con_Printf("%i cvar(s)", count);
510 Con_Printf(" beginning with \"%s\"", partial);
513 // 2000-01-09 CvarList command by Maddes
515 void Cvar_Set_f (void)
519 // make sure it's the right number of parameters
522 Con_Printf("Set: wrong number of parameters, usage: set <variablename> <value>\n");
526 // check if it's read-only
527 cvar = Cvar_FindVar(Cmd_Argv(1));
528 if (cvar && cvar->flags & CVAR_READONLY)
530 Con_Printf("Set: %s is read-only\n", cvar->name);
536 // all looks ok, create/modify the cvar
537 Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), 0);
540 void Cvar_SetA_f (void)
544 // make sure it's the right number of parameters
547 Con_Printf("SetA: wrong number of parameters, usage: seta <variablename> <value>\n");
551 // check if it's read-only
552 cvar = Cvar_FindVar(Cmd_Argv(1));
553 if (cvar && cvar->flags & CVAR_READONLY)
555 Con_Printf("SetA: %s is read-only\n", cvar->name);
559 Con_DPrint("SetA: ");
561 // all looks ok, create/modify the cvar
562 Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), CVAR_SAVE);