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