1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22 // cvar.c -- dynamic variable tracking
23
24 #include "q_shared.h"
25 #include "qcommon.h"
26
27 cvar_t *cvar_vars;
28 cvar_t *cvar_cheats;
29 int cvar_modifiedFlags;
30
31 #define MAX_CVARS 1024
32 cvar_t cvar_indexes[MAX_CVARS];
33 int cvar_numIndexes;
34
35 #define FILE_HASH_SIZE 256
36 static cvar_t* hashTable[FILE_HASH_SIZE];
37
38 cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force);
39
40 /*
41 ================
42 return a hash value for the filename
43 ================
44 */
generateHashValue(const char * fname)45 static long generateHashValue( const char *fname ) {
46 int i;
47 long hash;
48 char letter;
49
50 hash = 0;
51 i = 0;
52 while (fname[i] != '\0') {
53 letter = tolower(fname[i]);
54 hash+=(long)(letter)*(i+119);
55 i++;
56 }
57 hash &= (FILE_HASH_SIZE-1);
58 return hash;
59 }
60
61 /*
62 ============
63 Cvar_ValidateString
64 ============
65 */
Cvar_ValidateString(const char * s)66 static qboolean Cvar_ValidateString( const char *s ) {
67 if ( !s ) {
68 return qfalse;
69 }
70 if ( strchr( s, '\\' ) ) {
71 return qfalse;
72 }
73 if ( strchr( s, '\"' ) ) {
74 return qfalse;
75 }
76 if ( strchr( s, ';' ) ) {
77 return qfalse;
78 }
79 return qtrue;
80 }
81
82 /*
83 ============
84 Cvar_FindVar
85 ============
86 */
Cvar_FindVar(const char * var_name)87 static cvar_t *Cvar_FindVar( const char *var_name ) {
88 cvar_t *var;
89 long hash;
90
91 hash = generateHashValue(var_name);
92
93 for (var=hashTable[hash] ; var ; var=var->hashNext) {
94 if (!Q_stricmp(var_name, var->name)) {
95 return var;
96 }
97 }
98
99 return NULL;
100 }
101
102 /*
103 ============
104 Cvar_VariableValue
105 ============
106 */
Cvar_VariableValue(const char * var_name)107 float Cvar_VariableValue( const char *var_name ) {
108 cvar_t *var;
109
110 var = Cvar_FindVar (var_name);
111 if (!var)
112 return 0;
113 return var->value;
114 }
115
116
117 /*
118 ============
119 Cvar_VariableIntegerValue
120 ============
121 */
Cvar_VariableIntegerValue(const char * var_name)122 int Cvar_VariableIntegerValue( const char *var_name ) {
123 cvar_t *var;
124
125 var = Cvar_FindVar (var_name);
126 if (!var)
127 return 0;
128 return var->integer;
129 }
130
131
132 /*
133 ============
134 Cvar_VariableString
135 ============
136 */
Cvar_VariableString(const char * var_name)137 char *Cvar_VariableString( const char *var_name ) {
138 cvar_t *var;
139
140 var = Cvar_FindVar (var_name);
141 if (!var)
142 return "";
143 return var->string;
144 }
145
146
147 /*
148 ============
149 Cvar_VariableStringBuffer
150 ============
151 */
Cvar_VariableStringBuffer(const char * var_name,char * buffer,int bufsize)152 void Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) {
153 cvar_t *var;
154
155 var = Cvar_FindVar (var_name);
156 if (!var) {
157 *buffer = 0;
158 }
159 else {
160 Q_strncpyz( buffer, var->string, bufsize );
161 }
162 }
163
164 /*
165 ============
166 Cvar_Flags
167 ============
168 */
Cvar_Flags(const char * var_name)169 int Cvar_Flags(const char *var_name)
170 {
171 cvar_t *var;
172
173 if(! (var = Cvar_FindVar(var_name)) )
174 return CVAR_NONEXISTENT;
175 else
176 return var->flags;
177 }
178
179 /*
180 ============
181 Cvar_CommandCompletion
182 ============
183 */
Cvar_CommandCompletion(void (* callback)(const char * s))184 void Cvar_CommandCompletion( void(*callback)(const char *s) ) {
185 cvar_t *cvar;
186
187 for ( cvar = cvar_vars ; cvar ; cvar = cvar->next ) {
188 callback( cvar->name );
189 }
190 }
191
192
193 /*
194 ============
195 Cvar_Get
196
197 If the variable already exists, the value will not be set unless CVAR_ROM
198 The flags will be or'ed in if the variable exists.
199 ============
200 */
Cvar_Get(const char * var_name,const char * var_value,int flags)201 cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
202 cvar_t *var;
203 long hash;
204
205 if ( !var_name || ! var_value ) {
206 Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" );
207 }
208
209 if ( !Cvar_ValidateString( var_name ) ) {
210 Com_Printf("invalid cvar name string: %s\n", var_name );
211 var_name = "BADNAME";
212 }
213
214 #if 0 // FIXME: values with backslash happen
215 if ( !Cvar_ValidateString( var_value ) ) {
216 Com_Printf("invalid cvar value string: %s\n", var_value );
217 var_value = "BADVALUE";
218 }
219 #endif
220
221 var = Cvar_FindVar (var_name);
222 if ( var ) {
223 // if the C code is now specifying a variable that the user already
224 // set a value for, take the new value as the reset value
225 if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED )
226 && var_value[0] ) {
227 var->flags &= ~CVAR_USER_CREATED;
228 Z_Free( var->resetString );
229 var->resetString = CopyString( var_value );
230
231 if(flags & CVAR_ROM)
232 {
233 // this variable was set by the user,
234 // so force it to value given by the engine.
235
236 if(var->latchedString)
237 Z_Free(var->latchedString);
238
239 var->latchedString = CopyString(var_value);
240 }
241
242 // ZOID--needs to be set so that cvars the game sets as
243 // SERVERINFO get sent to clients
244 cvar_modifiedFlags |= flags;
245 }
246
247 var->flags |= flags;
248 // only allow one non-empty reset string without a warning
249 if ( !var->resetString[0] ) {
250 // we don't have a reset string yet
251 Z_Free( var->resetString );
252 var->resetString = CopyString( var_value );
253 } else if ( var_value[0] && strcmp( var->resetString, var_value ) ) {
254 Com_DPrintf( "Warning: cvar \"%s\" given initial values: \"%s\" and \"%s\"\n",
255 var_name, var->resetString, var_value );
256 }
257 // if we have a latched string, take that value now
258 if ( var->latchedString ) {
259 char *s;
260
261 s = var->latchedString;
262 var->latchedString = NULL; // otherwise cvar_set2 would free it
263 Cvar_Set2( var_name, s, qtrue );
264 Z_Free( s );
265 }
266
267 return var;
268 }
269
270 //
271 // allocate a new cvar
272 //
273 if ( cvar_numIndexes >= MAX_CVARS ) {
274 Com_Error( ERR_FATAL, "MAX_CVARS" );
275 }
276 var = &cvar_indexes[cvar_numIndexes];
277 cvar_numIndexes++;
278 var->name = CopyString (var_name);
279 var->string = CopyString (var_value);
280 var->modified = qtrue;
281 var->modificationCount = 1;
282 var->value = atof (var->string);
283 var->integer = atoi(var->string);
284 var->resetString = CopyString( var_value );
285
286 // link the variable in
287 var->next = cvar_vars;
288 cvar_vars = var;
289
290 var->flags = flags;
291 // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
292 cvar_modifiedFlags |= var->flags;
293
294 hash = generateHashValue(var_name);
295 var->hashNext = hashTable[hash];
296 hashTable[hash] = var;
297
298 return var;
299 }
300
301 /*
302 ============
303 Cvar_Print
304
305 Prints the value, default, and latched string of the given variable
306 ============
307 */
Cvar_Print(cvar_t * v)308 void Cvar_Print( cvar_t *v ) {
309 Com_Printf ("\"%s\" is:\"%s" S_COLOR_WHITE "\"",
310 v->name, v->string );
311
312 if ( !( v->flags & CVAR_ROM ) ) {
313 if ( !Q_stricmp( v->string, v->resetString ) ) {
314 Com_Printf (", the default" );
315 } else {
316 Com_Printf (" default:\"%s" S_COLOR_WHITE "\"",
317 v->resetString );
318 }
319 }
320
321 Com_Printf ("\n");
322
323 if ( v->latchedString ) {
324 Com_Printf( "latched: \"%s\"\n", v->latchedString );
325 }
326 }
327
328 /*
329 ============
330 Cvar_Set2
331 ============
332 */
Cvar_Set2(const char * var_name,const char * value,qboolean force)333 cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
334 cvar_t *var;
335
336 // Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value );
337
338 if ( !Cvar_ValidateString( var_name ) ) {
339 Com_Printf("invalid cvar name string: %s\n", var_name );
340 var_name = "BADNAME";
341 }
342
343 #if 0 // FIXME
344 if ( value && !Cvar_ValidateString( value ) ) {
345 Com_Printf("invalid cvar value string: %s\n", value );
346 var_value = "BADVALUE";
347 }
348 #endif
349
350 var = Cvar_FindVar (var_name);
351 if (!var) {
352 if ( !value ) {
353 return NULL;
354 }
355 // create it
356 if ( !force ) {
357 return Cvar_Get( var_name, value, CVAR_USER_CREATED );
358 } else {
359 return Cvar_Get (var_name, value, 0);
360 }
361 }
362
363 if (!value ) {
364 value = var->resetString;
365 }
366
367 if((var->flags & CVAR_LATCH) && var->latchedString) {
368 if(!strcmp(value,var->latchedString))
369 return var;
370 }
371 else if (!strcmp(value,var->string)) {
372 return var;
373 }
374 // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
375 cvar_modifiedFlags |= var->flags;
376
377 if (!force)
378 {
379 if (var->flags & CVAR_ROM)
380 {
381 Com_Printf ("%s is read only.\n", var_name);
382 return var;
383 }
384
385 if (var->flags & CVAR_INIT)
386 {
387 Com_Printf ("%s is write protected.\n", var_name);
388 return var;
389 }
390
391 if (var->flags & CVAR_LATCH)
392 {
393 if (var->latchedString)
394 {
395 if (strcmp(value, var->latchedString) == 0)
396 return var;
397 Z_Free (var->latchedString);
398 }
399 else
400 {
401 if (strcmp(value, var->string) == 0)
402 return var;
403 }
404
405 Com_Printf ("%s will be changed upon restarting.\n", var_name);
406 var->latchedString = CopyString(value);
407 var->modified = qtrue;
408 var->modificationCount++;
409 return var;
410 }
411
412 if ( (var->flags & CVAR_CHEAT) && !cvar_cheats->integer )
413 {
414 Com_Printf ("%s is cheat protected.\n", var_name);
415 return var;
416 }
417
418 }
419 else
420 {
421 if (var->latchedString)
422 {
423 Z_Free (var->latchedString);
424 var->latchedString = NULL;
425 }
426 }
427
428 if (!strcmp(value, var->string))
429 return var; // not changed
430
431 var->modified = qtrue;
432 var->modificationCount++;
433
434 Z_Free (var->string); // free the old value string
435
436 var->string = CopyString(value);
437 var->value = atof (var->string);
438 var->integer = atoi (var->string);
439
440 return var;
441 }
442
443 /*
444 ============
445 Cvar_Set
446 ============
447 */
Cvar_Set(const char * var_name,const char * value)448 void Cvar_Set( const char *var_name, const char *value) {
449 Cvar_Set2 (var_name, value, qtrue);
450 }
451
452 /*
453 ============
454 Cvar_SetLatched
455 ============
456 */
Cvar_SetLatched(const char * var_name,const char * value)457 void Cvar_SetLatched( const char *var_name, const char *value) {
458 Cvar_Set2 (var_name, value, qfalse);
459 }
460
461 /*
462 ============
463 Cvar_SetValue
464 ============
465 */
Cvar_SetValue(const char * var_name,float value)466 void Cvar_SetValue( const char *var_name, float value) {
467 char val[32];
468
469 if ( value == (int)value ) {
470 Com_sprintf (val, sizeof(val), "%i",(int)value);
471 } else {
472 Com_sprintf (val, sizeof(val), "%f",value);
473 }
474 Cvar_Set (var_name, val);
475 }
476
477
478 /*
479 ============
480 Cvar_Reset
481 ============
482 */
Cvar_Reset(const char * var_name)483 void Cvar_Reset( const char *var_name ) {
484 Cvar_Set2( var_name, NULL, qfalse );
485 }
486
487 /*
488 ============
489 Cvar_ForceReset
490 ============
491 */
Cvar_ForceReset(const char * var_name)492 void Cvar_ForceReset(const char *var_name)
493 {
494 Cvar_Set2(var_name, NULL, qtrue);
495 }
496
497 /*
498 ============
499 Cvar_SetCheatState
500
501 Any testing variables will be reset to the safe values
502 ============
503 */
Cvar_SetCheatState(void)504 void Cvar_SetCheatState( void ) {
505 cvar_t *var;
506
507 // set all default vars to the safe value
508 for ( var = cvar_vars ; var ; var = var->next ) {
509 if ( var->flags & CVAR_CHEAT ) {
510 // the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
511 // because of a different var->latchedString
512 if (var->latchedString)
513 {
514 Z_Free(var->latchedString);
515 var->latchedString = NULL;
516 }
517 if (strcmp(var->resetString,var->string)) {
518 Cvar_Set( var->name, var->resetString );
519 }
520 }
521 }
522 }
523
524 /*
525 ============
526 Cvar_Command
527
528 Handles variable inspection and changing from the console
529 ============
530 */
Cvar_Command(void)531 qboolean Cvar_Command( void ) {
532 cvar_t *v;
533
534 // check variables
535 v = Cvar_FindVar (Cmd_Argv(0));
536 if (!v) {
537 return qfalse;
538 }
539
540 // perform a variable print or set
541 if ( Cmd_Argc() == 1 ) {
542 Cvar_Print( v );
543 return qtrue;
544 }
545
546 // set the value if forcing isn't required
547 Cvar_Set2 (v->name, Cmd_Argv(1), qfalse);
548 return qtrue;
549 }
550
551
552 /*
553 ============
554 Cvar_Print_f
555
556 Prints the contents of a cvar
557 (preferred over Cvar_Command where cvar names and commands conflict)
558 ============
559 */
Cvar_Print_f(void)560 void Cvar_Print_f(void)
561 {
562 char *name;
563 cvar_t *cv;
564
565 if(Cmd_Argc() != 2)
566 {
567 Com_Printf ("usage: print <variable>\n");
568 return;
569 }
570
571 name = Cmd_Argv(1);
572
573 cv = Cvar_FindVar(name);
574
575 if(cv)
576 Cvar_Print(cv);
577 else
578 Com_Printf ("Cvar %s does not exist.\n", name);
579 }
580
581 /*
582 ============
583 Cvar_Toggle_f
584
585 Toggles a cvar for easy single key binding
586 ============
587 */
Cvar_Toggle_f(void)588 void Cvar_Toggle_f( void ) {
589 int v;
590
591 if ( Cmd_Argc() != 2 ) {
592 Com_Printf ("usage: toggle <variable>\n");
593 return;
594 }
595
596 v = Cvar_VariableValue( Cmd_Argv( 1 ) );
597 v = !v;
598
599 Cvar_Set2 (Cmd_Argv(1), va("%i", v), qfalse);
600 }
601
602 /*
603 ============
604 Cvar_Set_f
605
606 Allows setting and defining of arbitrary cvars from console, even if they
607 weren't declared in C code.
608 ============
609 */
Cvar_Set_f(void)610 void Cvar_Set_f( void ) {
611 int i, c, l, len;
612 char cmd[5], combined[MAX_STRING_TOKENS];
613 cvar_t *v;
614
615 c = Cmd_Argc();
616 Q_strncpyz( cmd, Cmd_Argv(0), sizeof( cmd ) );
617
618 if ( c < 2 ) {
619 Com_Printf ("usage: %s <variable> <value>\n", cmd);
620 return;
621 }
622 if ( c == 2 ) {
623 Cvar_Print_f();
624 return;
625 }
626
627 combined[0] = 0;
628 l = 0;
629 for ( i = 2 ; i < c ; i++ ) {
630 len = strlen ( Cmd_Argv( i ) + 1 );
631 if ( l + len >= MAX_STRING_TOKENS - 2 ) {
632 break;
633 }
634 strcat( combined, Cmd_Argv( i ) );
635 if ( i != c-1 ) {
636 strcat( combined, " " );
637 }
638 l += len;
639 }
640 v = Cvar_Set2 (Cmd_Argv(1), combined, qfalse);
641 if( !v ) {
642 return;
643 }
644 switch( cmd[3] ) {
645 default:
646 case '\0':
647 break;
648 case 'u':
649 v->flags |= CVAR_USERINFO;
650 break;
651 case 's':
652 v->flags |= CVAR_SERVERINFO;
653 break;
654 case 'a':
655 v->flags |= CVAR_ARCHIVE;
656 break;
657 }
658 }
659
660 /*
661 ============
662 Cvar_Reset_f
663 ============
664 */
Cvar_Reset_f(void)665 void Cvar_Reset_f( void ) {
666 if ( Cmd_Argc() != 2 ) {
667 Com_Printf ("usage: reset <variable>\n");
668 return;
669 }
670 Cvar_Reset( Cmd_Argv( 1 ) );
671 }
672
673 /*
674 ============
675 Cvar_WriteVariables
676
677 Appends lines containing "set variable value" for all variables
678 with the archive flag set to qtrue.
679 ============
680 */
Cvar_WriteVariables(fileHandle_t f)681 void Cvar_WriteVariables( fileHandle_t f ) {
682 cvar_t *var;
683 char buffer[1024];
684
685 for (var = cvar_vars ; var ; var = var->next) {
686 if( Q_stricmp( var->name, "cl_cdkey" ) == 0 ) {
687 continue;
688 }
689 if( var->flags & CVAR_ARCHIVE ) {
690 // write the latched value, even if it hasn't taken effect yet
691 if ( var->latchedString ) {
692 if( strlen( var->name ) + strlen( var->latchedString ) + 10 > sizeof( buffer ) ) {
693 Com_Printf( S_COLOR_YELLOW "WARNING: value of variable "
694 "\"%s\" too long to write to file\n", var->name );
695 continue;
696 }
697 Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->latchedString);
698 } else {
699 if( strlen( var->name ) + strlen( var->string ) + 10 > sizeof( buffer ) ) {
700 Com_Printf( S_COLOR_YELLOW "WARNING: value of variable "
701 "\"%s\" too long to write to file\n", var->name );
702 continue;
703 }
704 Com_sprintf (buffer, sizeof(buffer), "seta %s \"%s\"\n", var->name, var->string);
705 }
706 FS_Write( buffer, strlen( buffer ), f );
707 }
708 }
709 }
710
711 /*
712 ============
713 Cvar_List_f
714 ============
715 */
Cvar_List_f(void)716 void Cvar_List_f( void ) {
717 cvar_t *var;
718 int i;
719 char *match;
720
721 if ( Cmd_Argc() > 1 ) {
722 match = Cmd_Argv( 1 );
723 } else {
724 match = NULL;
725 }
726
727 i = 0;
728 for (var = cvar_vars ; var ; var = var->next, i++)
729 {
730 if (match && !Com_Filter(match, var->name, qfalse)) continue;
731
732 if (var->flags & CVAR_SERVERINFO) {
733 Com_Printf("S");
734 } else {
735 Com_Printf(" ");
736 }
737 if (var->flags & CVAR_USERINFO) {
738 Com_Printf("U");
739 } else {
740 Com_Printf(" ");
741 }
742 if (var->flags & CVAR_ROM) {
743 Com_Printf("R");
744 } else {
745 Com_Printf(" ");
746 }
747 if (var->flags & CVAR_INIT) {
748 Com_Printf("I");
749 } else {
750 Com_Printf(" ");
751 }
752 if (var->flags & CVAR_ARCHIVE) {
753 Com_Printf("A");
754 } else {
755 Com_Printf(" ");
756 }
757 if (var->flags & CVAR_LATCH) {
758 Com_Printf("L");
759 } else {
760 Com_Printf(" ");
761 }
762 if (var->flags & CVAR_CHEAT) {
763 Com_Printf("C");
764 } else {
765 Com_Printf(" ");
766 }
767
768 Com_Printf (" %s \"%s\"\n", var->name, var->string);
769 }
770
771 Com_Printf ("\n%i total cvars\n", i);
772 Com_Printf ("%i cvar indexes\n", cvar_numIndexes);
773 }
774
775 /*
776 ============
777 Cvar_Restart_f
778
779 Resets all cvars to their hardcoded values
780 ============
781 */
Cvar_Restart_f(void)782 void Cvar_Restart_f( void ) {
783 cvar_t *var;
784 cvar_t **prev;
785
786 prev = &cvar_vars;
787 while ( 1 ) {
788 var = *prev;
789 if ( !var ) {
790 break;
791 }
792
793 // don't mess with rom values, or some inter-module
794 // communication will get broken (com_cl_running, etc)
795 if ( var->flags & ( CVAR_ROM | CVAR_INIT | CVAR_NORESTART ) ) {
796 prev = &var->next;
797 continue;
798 }
799
800 // throw out any variables the user created
801 if ( var->flags & CVAR_USER_CREATED ) {
802 *prev = var->next;
803 if ( var->name ) {
804 Z_Free( var->name );
805 }
806 if ( var->string ) {
807 Z_Free( var->string );
808 }
809 if ( var->latchedString ) {
810 Z_Free( var->latchedString );
811 }
812 if ( var->resetString ) {
813 Z_Free( var->resetString );
814 }
815 // clear the var completely, since we
816 // can't remove the index from the list
817 Com_Memset( var, 0, sizeof( var ) );
818 continue;
819 }
820
821 Cvar_Set( var->name, var->resetString );
822
823 prev = &var->next;
824 }
825 }
826
827
828
829 /*
830 =====================
831 Cvar_InfoString
832 =====================
833 */
Cvar_InfoString(int bit)834 char *Cvar_InfoString( int bit ) {
835 static char info[MAX_INFO_STRING];
836 cvar_t *var;
837
838 info[0] = 0;
839
840 for (var = cvar_vars ; var ; var = var->next) {
841 if (var->flags & bit) {
842 Info_SetValueForKey (info, var->name, var->string);
843 }
844 }
845 return info;
846 }
847
848 /*
849 =====================
850 Cvar_InfoString_Big
851
852 handles large info strings ( CS_SYSTEMINFO )
853 =====================
854 */
Cvar_InfoString_Big(int bit)855 char *Cvar_InfoString_Big( int bit ) {
856 static char info[BIG_INFO_STRING];
857 cvar_t *var;
858
859 info[0] = 0;
860
861 for (var = cvar_vars ; var ; var = var->next) {
862 if (var->flags & bit) {
863 Info_SetValueForKey_Big (info, var->name, var->string);
864 }
865 }
866 return info;
867 }
868
869
870
871 /*
872 =====================
873 Cvar_InfoStringBuffer
874 =====================
875 */
Cvar_InfoStringBuffer(int bit,char * buff,int buffsize)876 void Cvar_InfoStringBuffer( int bit, char* buff, int buffsize ) {
877 Q_strncpyz(buff,Cvar_InfoString(bit),buffsize);
878 }
879
880 /*
881 =====================
882 Cvar_Register
883
884 basically a slightly modified Cvar_Get for the interpreted modules
885 =====================
886 */
Cvar_Register(vmCvar_t * vmCvar,const char * varName,const char * defaultValue,int flags)887 void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) {
888 cvar_t *cv;
889
890 cv = Cvar_Get( varName, defaultValue, flags );
891 if ( !vmCvar ) {
892 return;
893 }
894 vmCvar->handle = cv - cvar_indexes;
895 vmCvar->modificationCount = -1;
896 Cvar_Update( vmCvar );
897 }
898
899
900 /*
901 =====================
902 Cvar_Register
903
904 updates an interpreted modules' version of a cvar
905 =====================
906 */
Cvar_Update(vmCvar_t * vmCvar)907 void Cvar_Update( vmCvar_t *vmCvar ) {
908 cvar_t *cv = NULL;
909 assert(vmCvar);
910
911 if ( (unsigned)vmCvar->handle >= cvar_numIndexes ) {
912 Com_Error( ERR_DROP, "Cvar_Update: handle out of range" );
913 }
914
915 cv = cvar_indexes + vmCvar->handle;
916
917 if ( cv->modificationCount == vmCvar->modificationCount ) {
918 return;
919 }
920 if ( !cv->string ) {
921 return; // variable might have been cleared by a cvar_restart
922 }
923 vmCvar->modificationCount = cv->modificationCount;
924 if ( strlen(cv->string)+1 > MAX_CVAR_VALUE_STRING )
925 Com_Error( ERR_DROP, "Cvar_Update: src %s length %zd exceeds MAX_CVAR_VALUE_STRING",
926 cv->string,
927 strlen(cv->string));
928 Q_strncpyz( vmCvar->string, cv->string, MAX_CVAR_VALUE_STRING );
929
930 vmCvar->value = cv->value;
931 vmCvar->integer = cv->integer;
932 }
933
934
935 /*
936 ============
937 Cvar_Init
938
939 Reads in all archived cvars
940 ============
941 */
Cvar_Init(void)942 void Cvar_Init (void) {
943 cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO );
944
945 Cmd_AddCommand ("print", Cvar_Print_f);
946 Cmd_AddCommand ("toggle", Cvar_Toggle_f);
947 Cmd_AddCommand ("set", Cvar_Set_f);
948 Cmd_AddCommand ("sets", Cvar_Set_f);
949 Cmd_AddCommand ("setu", Cvar_Set_f);
950 Cmd_AddCommand ("seta", Cvar_Set_f);
951 Cmd_AddCommand ("reset", Cvar_Reset_f);
952 Cmd_AddCommand ("cvarlist", Cvar_List_f);
953 Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
954 }
955