Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

cvar.c (9024B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      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.
      8 
      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.  
     12 
     13 See the GNU General Public License for more details.
     14 
     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.
     18 
     19 */
     20 // cvar.c -- dynamic variable tracking
     21 
     22 #include "qcommon.h"
     23 
     24 cvar_t	*cvar_vars;
     25 
     26 /*
     27 ============
     28 Cvar_InfoValidate
     29 ============
     30 */
     31 static qboolean Cvar_InfoValidate (char *s)
     32 {
     33 	if (strstr (s, "\\"))
     34 		return false;
     35 	if (strstr (s, "\""))
     36 		return false;
     37 	if (strstr (s, ";"))
     38 		return false;
     39 	return true;
     40 }
     41 
     42 /*
     43 ============
     44 Cvar_FindVar
     45 ============
     46 */
     47 static cvar_t *Cvar_FindVar (char *var_name)
     48 {
     49 	cvar_t	*var;
     50 	
     51 	for (var=cvar_vars ; var ; var=var->next)
     52 		if (!strcmp (var_name, var->name))
     53 			return var;
     54 
     55 	return NULL;
     56 }
     57 
     58 /*
     59 ============
     60 Cvar_VariableValue
     61 ============
     62 */
     63 float Cvar_VariableValue (char *var_name)
     64 {
     65 	cvar_t	*var;
     66 	
     67 	var = Cvar_FindVar (var_name);
     68 	if (!var)
     69 		return 0;
     70 	return atof (var->string);
     71 }
     72 
     73 
     74 /*
     75 ============
     76 Cvar_VariableString
     77 ============
     78 */
     79 char *Cvar_VariableString (char *var_name)
     80 {
     81 	cvar_t *var;
     82 	
     83 	var = Cvar_FindVar (var_name);
     84 	if (!var)
     85 		return "";
     86 	return var->string;
     87 }
     88 
     89 
     90 /*
     91 ============
     92 Cvar_CompleteVariable
     93 ============
     94 */
     95 char *Cvar_CompleteVariable (char *partial)
     96 {
     97 	cvar_t		*cvar;
     98 	int			len;
     99 	
    100 	len = strlen(partial);
    101 	
    102 	if (!len)
    103 		return NULL;
    104 		
    105 	// check exact match
    106 	for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
    107 		if (!strcmp (partial,cvar->name))
    108 			return cvar->name;
    109 
    110 	// check partial match
    111 	for (cvar=cvar_vars ; cvar ; cvar=cvar->next)
    112 		if (!strncmp (partial,cvar->name, len))
    113 			return cvar->name;
    114 
    115 	return NULL;
    116 }
    117 
    118 
    119 /*
    120 ============
    121 Cvar_Get
    122 
    123 If the variable already exists, the value will not be set
    124 The flags will be or'ed in if the variable exists.
    125 ============
    126 */
    127 cvar_t *Cvar_Get (char *var_name, char *var_value, int flags)
    128 {
    129 	cvar_t	*var;
    130 	
    131 	if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
    132 	{
    133 		if (!Cvar_InfoValidate (var_name))
    134 		{
    135 			Com_Printf("invalid info cvar name\n");
    136 			return NULL;
    137 		}
    138 	}
    139 
    140 	var = Cvar_FindVar (var_name);
    141 	if (var)
    142 	{
    143 		var->flags |= flags;
    144 		return var;
    145 	}
    146 
    147 	if (!var_value)
    148 		return NULL;
    149 
    150 	if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
    151 	{
    152 		if (!Cvar_InfoValidate (var_value))
    153 		{
    154 			Com_Printf("invalid info cvar value\n");
    155 			return NULL;
    156 		}
    157 	}
    158 
    159 	var = Z_Malloc (sizeof(*var));
    160 	var->name = CopyString (var_name);
    161 	var->string = CopyString (var_value);
    162 	var->modified = true;
    163 	var->value = atof (var->string);
    164 
    165 	// link the variable in
    166 	var->next = cvar_vars;
    167 	cvar_vars = var;
    168 
    169 	var->flags = flags;
    170 
    171 	return var;
    172 }
    173 
    174 /*
    175 ============
    176 Cvar_Set2
    177 ============
    178 */
    179 cvar_t *Cvar_Set2 (char *var_name, char *value, qboolean force)
    180 {
    181 	cvar_t	*var;
    182 
    183 	var = Cvar_FindVar (var_name);
    184 	if (!var)
    185 	{	// create it
    186 		return Cvar_Get (var_name, value, 0);
    187 	}
    188 
    189 	if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO))
    190 	{
    191 		if (!Cvar_InfoValidate (value))
    192 		{
    193 			Com_Printf("invalid info cvar value\n");
    194 			return var;
    195 		}
    196 	}
    197 
    198 	if (!force)
    199 	{
    200 		if (var->flags & CVAR_NOSET)
    201 		{
    202 			Com_Printf ("%s is write protected.\n", var_name);
    203 			return var;
    204 		}
    205 
    206 		if (var->flags & CVAR_LATCH)
    207 		{
    208 			if (var->latched_string)
    209 			{
    210 				if (strcmp(value, var->latched_string) == 0)
    211 					return var;
    212 				Z_Free (var->latched_string);
    213 			}
    214 			else
    215 			{
    216 				if (strcmp(value, var->string) == 0)
    217 					return var;
    218 			}
    219 
    220 			if (Com_ServerState())
    221 			{
    222 				Com_Printf ("%s will be changed for next game.\n", var_name);
    223 				var->latched_string = CopyString(value);
    224 			}
    225 			else
    226 			{
    227 				var->string = CopyString(value);
    228 				var->value = atof (var->string);
    229 				if (!strcmp(var->name, "game"))
    230 				{
    231 					FS_SetGamedir (var->string);
    232 					FS_ExecAutoexec ();
    233 				}
    234 			}
    235 			return var;
    236 		}
    237 	}
    238 	else
    239 	{
    240 		if (var->latched_string)
    241 		{
    242 			Z_Free (var->latched_string);
    243 			var->latched_string = NULL;
    244 		}
    245 	}
    246 
    247 	if (!strcmp(value, var->string))
    248 		return var;		// not changed
    249 
    250 	var->modified = true;
    251 
    252 	if (var->flags & CVAR_USERINFO)
    253 		userinfo_modified = true;	// transmit at next oportunity
    254 	
    255 	Z_Free (var->string);	// free the old value string
    256 	
    257 	var->string = CopyString(value);
    258 	var->value = atof (var->string);
    259 
    260 	return var;
    261 }
    262 
    263 /*
    264 ============
    265 Cvar_ForceSet
    266 ============
    267 */
    268 cvar_t *Cvar_ForceSet (char *var_name, char *value)
    269 {
    270 	return Cvar_Set2 (var_name, value, true);
    271 }
    272 
    273 /*
    274 ============
    275 Cvar_Set
    276 ============
    277 */
    278 cvar_t *Cvar_Set (char *var_name, char *value)
    279 {
    280 	return Cvar_Set2 (var_name, value, false);
    281 }
    282 
    283 /*
    284 ============
    285 Cvar_FullSet
    286 ============
    287 */
    288 cvar_t *Cvar_FullSet (char *var_name, char *value, int flags)
    289 {
    290 	cvar_t	*var;
    291 	
    292 	var = Cvar_FindVar (var_name);
    293 	if (!var)
    294 	{	// create it
    295 		return Cvar_Get (var_name, value, flags);
    296 	}
    297 
    298 	var->modified = true;
    299 
    300 	if (var->flags & CVAR_USERINFO)
    301 		userinfo_modified = true;	// transmit at next oportunity
    302 	
    303 	Z_Free (var->string);	// free the old value string
    304 	
    305 	var->string = CopyString(value);
    306 	var->value = atof (var->string);
    307 	var->flags = flags;
    308 
    309 	return var;
    310 }
    311 
    312 /*
    313 ============
    314 Cvar_SetValue
    315 ============
    316 */
    317 void Cvar_SetValue (char *var_name, float value)
    318 {
    319 	char	val[32];
    320 
    321 	if (value == (int)value)
    322 		Com_sprintf (val, sizeof(val), "%i",(int)value);
    323 	else
    324 		Com_sprintf (val, sizeof(val), "%f",value);
    325 	Cvar_Set (var_name, val);
    326 }
    327 
    328 
    329 /*
    330 ============
    331 Cvar_GetLatchedVars
    332 
    333 Any variables with latched values will now be updated
    334 ============
    335 */
    336 void Cvar_GetLatchedVars (void)
    337 {
    338 	cvar_t	*var;
    339 
    340 	for (var = cvar_vars ; var ; var = var->next)
    341 	{
    342 		if (!var->latched_string)
    343 			continue;
    344 		Z_Free (var->string);
    345 		var->string = var->latched_string;
    346 		var->latched_string = NULL;
    347 		var->value = atof(var->string);
    348 		if (!strcmp(var->name, "game"))
    349 		{
    350 			FS_SetGamedir (var->string);
    351 			FS_ExecAutoexec ();
    352 		}
    353 	}
    354 }
    355 
    356 /*
    357 ============
    358 Cvar_Command
    359 
    360 Handles variable inspection and changing from the console
    361 ============
    362 */
    363 qboolean Cvar_Command (void)
    364 {
    365 	cvar_t			*v;
    366 
    367 // check variables
    368 	v = Cvar_FindVar (Cmd_Argv(0));
    369 	if (!v)
    370 		return false;
    371 		
    372 // perform a variable print or set
    373 	if (Cmd_Argc() == 1)
    374 	{
    375 		Com_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
    376 		return true;
    377 	}
    378 
    379 	Cvar_Set (v->name, Cmd_Argv(1));
    380 	return true;
    381 }
    382 
    383 
    384 /*
    385 ============
    386 Cvar_Set_f
    387 
    388 Allows setting and defining of arbitrary cvars from console
    389 ============
    390 */
    391 void Cvar_Set_f (void)
    392 {
    393 	int		c;
    394 	int		flags;
    395 
    396 	c = Cmd_Argc();
    397 	if (c != 3 && c != 4)
    398 	{
    399 		Com_Printf ("usage: set <variable> <value> [u / s]\n");
    400 		return;
    401 	}
    402 
    403 	if (c == 4)
    404 	{
    405 		if (!strcmp(Cmd_Argv(3), "u"))
    406 			flags = CVAR_USERINFO;
    407 		else if (!strcmp(Cmd_Argv(3), "s"))
    408 			flags = CVAR_SERVERINFO;
    409 		else
    410 		{
    411 			Com_Printf ("flags can only be 'u' or 's'\n");
    412 			return;
    413 		}
    414 		Cvar_FullSet (Cmd_Argv(1), Cmd_Argv(2), flags);
    415 	}
    416 	else
    417 		Cvar_Set (Cmd_Argv(1), Cmd_Argv(2));
    418 }
    419 
    420 
    421 /*
    422 ============
    423 Cvar_WriteVariables
    424 
    425 Appends lines containing "set variable value" for all variables
    426 with the archive flag set to true.
    427 ============
    428 */
    429 void Cvar_WriteVariables (char *path)
    430 {
    431 	cvar_t	*var;
    432 	char	buffer[1024];
    433 	FILE	*f;
    434 
    435 	f = fopen (path, "a");
    436 	for (var = cvar_vars ; var ; var = var->next)
    437 	{
    438 		if (var->flags & CVAR_ARCHIVE)
    439 		{
    440 			Com_sprintf (buffer, sizeof(buffer), "set %s \"%s\"\n", var->name, var->string);
    441 			fprintf (f, "%s", buffer);
    442 		}
    443 	}
    444 	fclose (f);
    445 }
    446 
    447 /*
    448 ============
    449 Cvar_List_f
    450 
    451 ============
    452 */
    453 void Cvar_List_f (void)
    454 {
    455 	cvar_t	*var;
    456 	int		i;
    457 
    458 	i = 0;
    459 	for (var = cvar_vars ; var ; var = var->next, i++)
    460 	{
    461 		if (var->flags & CVAR_ARCHIVE)
    462 			Com_Printf ("*");
    463 		else
    464 			Com_Printf (" ");
    465 		if (var->flags & CVAR_USERINFO)
    466 			Com_Printf ("U");
    467 		else
    468 			Com_Printf (" ");
    469 		if (var->flags & CVAR_SERVERINFO)
    470 			Com_Printf ("S");
    471 		else
    472 			Com_Printf (" ");
    473 		if (var->flags & CVAR_NOSET)
    474 			Com_Printf ("-");
    475 		else if (var->flags & CVAR_LATCH)
    476 			Com_Printf ("L");
    477 		else
    478 			Com_Printf (" ");
    479 		Com_Printf (" %s \"%s\"\n", var->name, var->string);
    480 	}
    481 	Com_Printf ("%i cvars\n", i);
    482 }
    483 
    484 
    485 qboolean userinfo_modified;
    486 
    487 
    488 char	*Cvar_BitInfo (int bit)
    489 {
    490 	static char	info[MAX_INFO_STRING];
    491 	cvar_t	*var;
    492 
    493 	info[0] = 0;
    494 
    495 	for (var = cvar_vars ; var ; var = var->next)
    496 	{
    497 		if (var->flags & bit)
    498 			Info_SetValueForKey (info, var->name, var->string);
    499 	}
    500 	return info;
    501 }
    502 
    503 // returns an info string containing all the CVAR_USERINFO cvars
    504 char	*Cvar_Userinfo (void)
    505 {
    506 	return Cvar_BitInfo (CVAR_USERINFO);
    507 }
    508 
    509 // returns an info string containing all the CVAR_SERVERINFO cvars
    510 char	*Cvar_Serverinfo (void)
    511 {
    512 	return Cvar_BitInfo (CVAR_SERVERINFO);
    513 }
    514 
    515 /*
    516 ============
    517 Cvar_Init
    518 
    519 Reads in all archived cvars
    520 ============
    521 */
    522 void Cvar_Init (void)
    523 {
    524 	Cmd_AddCommand ("set", Cvar_Set_f);
    525 	Cmd_AddCommand ("cvarlist", Cvar_List_f);
    526 
    527 }