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 */
Cvar_InfoValidate(char * s)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 */
Cvar_FindVar(char * var_name)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 */
Cvar_VariableValue(char * var_name)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 */
Cvar_VariableString(char * var_name)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 */
Cvar_CompleteVariable(char * partial)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 */
Cvar_Get(char * var_name,char * var_value,int flags)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
145 Z_Free(var->default_string);
146 var->default_string = CopyString (var_value);
147
148 return var;
149 }
150
151 if (!var_value)
152 return NULL;
153
154 if (flags & (CVAR_USERINFO | CVAR_SERVERINFO))
155 {
156 if (!Cvar_InfoValidate (var_value))
157 {
158 Com_Printf("invalid info cvar value\n");
159 return NULL;
160 }
161 }
162
163 var = Z_Malloc (sizeof(*var));
164 var->name = CopyString (var_name);
165 var->string = CopyString (var_value);
166 var->default_string = CopyString (var_value);
167 var->modified = true;
168 var->value = atof (var->string);
169
170 // link the variable in
171 var->next = cvar_vars;
172 cvar_vars = var;
173
174 var->flags = flags;
175
176 return var;
177 }
178
179 /*
180 ============
181 Cvar_Set2
182 ============
183 */
Cvar_Set2(char * var_name,char * value,qboolean force)184 cvar_t *Cvar_Set2 (char *var_name, char *value, qboolean force)
185 {
186 cvar_t *var;
187
188 var = Cvar_FindVar (var_name);
189 if (!var)
190 { // create it
191 return Cvar_Get (var_name, value, 0);
192 }
193
194 if (var->flags & (CVAR_USERINFO | CVAR_SERVERINFO))
195 {
196 if (!Cvar_InfoValidate (value))
197 {
198 Com_Printf("invalid info cvar value\n");
199 return var;
200 }
201 }
202
203 if (!force)
204 {
205 if (var->flags & CVAR_NOSET)
206 {
207 Com_Printf ("%s is write protected.\n", var_name);
208 return var;
209 }
210
211 if (var->flags & CVAR_LATCH)
212 {
213 if (var->latched_string)
214 {
215 if (strcmp(value, var->latched_string) == 0)
216 return var;
217 Z_Free (var->latched_string);
218 }
219 else
220 {
221 if (strcmp(value, var->string) == 0)
222 return var;
223 }
224
225 if (Com_ServerState())
226 {
227 Com_Printf ("%s will be changed for next game.\n", var_name);
228 var->latched_string = CopyString(value);
229 }
230 else
231 {
232 var->string = CopyString(value);
233 var->value = atof (var->string);
234 if (!strcmp(var->name, "game"))
235 {
236 FS_SetGamedir (var->string);
237 FS_ExecAutoexec ();
238 }
239 }
240 return var;
241 }
242 }
243 else
244 {
245 if (var->latched_string)
246 {
247 Z_Free (var->latched_string);
248 var->latched_string = NULL;
249 }
250 }
251
252 if (!strcmp(value, var->string))
253 return var; // not changed
254
255 var->modified = true;
256
257 if (var->flags & CVAR_USERINFO)
258 userinfo_modified = true; // transmit at next oportunity
259
260 Z_Free (var->string); // free the old value string
261
262 var->string = CopyString(value);
263 var->value = atof (var->string);
264
265 return var;
266 }
267
268 /*
269 ============
270 Cvar_ForceSet
271 ============
272 */
Cvar_ForceSet(char * var_name,char * value)273 cvar_t *Cvar_ForceSet (char *var_name, char *value)
274 {
275 return Cvar_Set2 (var_name, value, true);
276 }
277
278 /*
279 ============
280 Cvar_Set
281 ============
282 */
Cvar_Set(char * var_name,char * value)283 cvar_t *Cvar_Set (char *var_name, char *value)
284 {
285 return Cvar_Set2 (var_name, value, false);
286 }
287
288 /*
289 ============
290 Cvar_FullSet
291 ============
292 */
Cvar_FullSet(char * var_name,char * value,int flags)293 cvar_t *Cvar_FullSet (char *var_name, char *value, int flags)
294 {
295 cvar_t *var;
296
297 var = Cvar_FindVar (var_name);
298 if (!var)
299 { // create it
300 return Cvar_Get (var_name, value, flags);
301 }
302
303 var->modified = true;
304
305 if (var->flags & CVAR_USERINFO)
306 userinfo_modified = true; // transmit at next oportunity
307
308 Z_Free (var->string); // free the old value string
309
310 var->string = CopyString(value);
311 var->value = atof (var->string);
312 var->flags = flags;
313
314 return var;
315 }
316
317 /*
318 ============
319 Cvar_SetValue
320 ============
321 */
Cvar_SetValue(char * var_name,float value)322 void Cvar_SetValue (char *var_name, float value)
323 {
324 char val[32];
325
326 if (value == (int)value)
327 Com_sprintf (val, sizeof(val), "%i",(int)value);
328 else
329 Com_sprintf (val, sizeof(val), "%f",value);
330 Cvar_Set (var_name, val);
331 }
332
333
334 /*
335 ============
336 Cvar_GetLatchedVars
337
338 Any variables with latched values will now be updated
339 ============
340 */
Cvar_GetLatchedVars(void)341 void Cvar_GetLatchedVars (void)
342 {
343 cvar_t *var;
344
345 for (var = cvar_vars ; var ; var = var->next)
346 {
347 if (!var->latched_string)
348 continue;
349 Z_Free (var->string);
350 var->string = var->latched_string;
351 var->latched_string = NULL;
352 var->value = atof(var->string);
353 if (!strcmp(var->name, "game"))
354 {
355 FS_SetGamedir (var->string);
356 FS_ExecAutoexec ();
357 }
358 }
359 }
360
361 /*
362 ============
363 Cvar_Command
364
365 Handles variable inspection and changing from the console
366 ============
367 */
Cvar_Command(void)368 qboolean Cvar_Command (void)
369 {
370 cvar_t *v;
371
372 // check variables
373 v = Cvar_FindVar (Cmd_Argv(0));
374 if (!v)
375 return false;
376
377 // perform a variable print or set
378 if (Cmd_Argc() == 1)
379 {
380 Com_Printf ("\"%s\" is \"%s\" : default is \"%s\"\n", v->name, v->string, v->default_string);
381 return true;
382 }
383
384 Cvar_Set (v->name, Cmd_Argv(1));
385 return true;
386 }
387
388
389 /*
390 ============
391 Cvar_Set_f
392
393 Allows setting and defining of arbitrary cvars from console
394 ============
395 */
Cvar_Set_f(void)396 void Cvar_Set_f (void)
397 {
398 int c;
399 int flags;
400
401 c = Cmd_Argc();
402 if (c != 3 && c != 4)
403 {
404 Com_Printf ("usage: set <variable> <value> [u / s]\n");
405 return;
406 }
407
408 if (c == 4)
409 {
410 if (!strcmp(Cmd_Argv(3), "u"))
411 flags = CVAR_USERINFO;
412 else if (!strcmp(Cmd_Argv(3), "s"))
413 flags = CVAR_SERVERINFO;
414 else
415 {
416 Com_Printf ("flags can only be 'u' or 's'\n");
417 return;
418 }
419 Cvar_FullSet (Cmd_Argv(1), Cmd_Argv(2), flags);
420 }
421 else
422 Cvar_Set (Cmd_Argv(1), Cmd_Argv(2));
423 }
424
425
426 /*
427 ============
428 Cvar_WriteVariables
429
430 Appends lines containing "set variable value" for all variables
431 with the archive flag set to true.
432 ============
433 */
Cvar_WriteVariables(char * path)434 void Cvar_WriteVariables (char *path)
435 {
436 cvar_t *var;
437 char buffer[1024];
438 FILE *f;
439
440 f = fopen (path, "a");
441 for (var = cvar_vars ; var ; var = var->next)
442 {
443 if (var->flags & CVAR_ARCHIVE)
444 {
445 Com_sprintf (buffer, sizeof(buffer), "set %s \"%s\"\n", var->name, var->string);
446 fprintf (f, "%s", buffer);
447 }
448 }
449 fclose (f);
450 }
451
452
453 /*
454 ============
455 Cvar_WriteUserVariables
456
457 Appends lines containing "set variable value" for all variables
458 with the archive flag set to true.
459 ============
460 */
Cvar_WriteUserVariables(char * path)461 void Cvar_WriteUserVariables (char *path)
462 {
463 cvar_t *var;
464 char buffer[1024];
465 FILE *f;
466
467 f = fopen (path, "a");
468 for (var = cvar_vars ; var ; var = var->next)
469 {
470 if (var->flags & CVAR_USERVARS)
471 {
472 //set one as var, and one as game command
473
474 Com_sprintf (buffer, sizeof(buffer), "set %s \"%s\"\n", var->name, var->string);
475 fprintf (f, "%s", buffer);
476 Com_sprintf (buffer, sizeof(buffer), "%s %s\n", var->name, var->string);
477 fprintf (f, "%s", buffer);
478 }
479 }
480 fclose (f);
481 }
482
483 /*
484 ============
485 Cvar_List_f
486
487 ============
488 */
Cvar_List_f(void)489 void Cvar_List_f (void)
490 {
491 cvar_t *var;
492 int i, c;
493
494 c = Cmd_Argc();
495 i = 0;
496 for (var = cvar_vars ; var ; var = var->next)
497 {
498 if (c>1)
499 if (!strstr (var->name, Cmd_Argv(1)))
500 continue;
501
502 if (var->flags & CVAR_ARCHIVE)
503 Com_Printf ("*");
504 else
505 Com_Printf (" ");
506 if (var->flags & CVAR_USERINFO)
507 Com_Printf ("U");
508 else
509 Com_Printf (" ");
510 if (var->flags & CVAR_SERVERINFO)
511 Com_Printf ("S");
512 else
513 Com_Printf (" ");
514 if (var->flags & CVAR_NOSET)
515 Com_Printf ("-");
516 else if (var->flags & CVAR_LATCH)
517 Com_Printf ("L");
518 else
519 Com_Printf (" ");
520
521 Com_Printf ("\"%s\" \"%s\" - default: \"%s\"\n", var->name, var->string, var->default_string);
522 //Com_Printf (" %s \"%s\"\n", var->name, var->string);
523
524 i++;
525 }
526 Com_Printf ("%i cvars\n", i);
527 }
528
529
530 qboolean userinfo_modified;
531
532
Cvar_BitInfo(int bit)533 char *Cvar_BitInfo (int bit)
534 {
535 static char info[MAX_INFO_STRING];
536 cvar_t *var;
537
538 info[0] = 0;
539
540 for (var = cvar_vars ; var ; var = var->next)
541 {
542 if (var->flags & bit)
543 Info_SetValueForKey (info, var->name, var->string);
544 }
545 return info;
546 }
547
548 // returns an info string containing all the CVAR_USERINFO cvars
Cvar_Userinfo(void)549 char *Cvar_Userinfo (void)
550 {
551 return Cvar_BitInfo (CVAR_USERINFO);
552 }
553
554 // returns an info string containing all the CVAR_SERVERINFO cvars
Cvar_Serverinfo(void)555 char *Cvar_Serverinfo (void)
556 {
557 return Cvar_BitInfo (CVAR_SERVERINFO);
558 }
559
560 /*
561 ============
562 Cvar_Init
563
564 Reads in all archived cvars
565 ============
566 */
Cvar_Init(void)567 void Cvar_Init (void)
568 {
569 Cmd_AddCommand ("set", Cvar_Set_f);
570 Cmd_AddCommand ("cvarlist", Cvar_List_f);
571
572 }
573