]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/cvar.qh
Merge branch 'terencehill/eraseable_functions'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / cvar.qh
index 1da1f276dfb158bf3327d82af0313207ba71092a..f322753c0af92d9d5eda78b9e57497633777b052 100644 (file)
-#ifndef CVAR_H
-#define CVAR_H
+#pragma once
 
+#include "nil.qh"
+#include "progname.qh"
 #include "static.qh"
 
-void RegisterCvars(void(string name, string desc, bool archive, string file) f) { }
+[[eraseable]]
+void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) {}
 
-void RegisterCvars_Set(string name, string desc, bool archive, string file)
+[[eraseable]]
+bool cvar_value_issafe(string s)
 {
-    localcmd(sprintf("\n%1$s %2$s \"$%2$s\" \"%3$s\"\n", (archive ? "seta" : "set"), name, desc));
+       if (strstrofs(s, "\"", 0) >= 0) return false;
+       if (strstrofs(s, "\\", 0) >= 0) return false;
+       if (strstrofs(s, ";", 0) >= 0) return false;
+       if (strstrofs(s, "$", 0) >= 0) return false;
+       if (strstrofs(s, "\r", 0) >= 0) return false;
+       if (strstrofs(s, "\n", 0) >= 0) return false;
+       return true;
 }
 
-STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
+/** escape the string to make it safe for consoles */
+[[eraseable]]
+string MakeConsoleSafe(string input)
+{
+       input = strreplace("\n", "", input);
+       input = strreplace("\\", "\\\\", input);
+       input = strreplace("$", "$$", input);
+       input = strreplace("\"", "\\\"", input);
+       return input;
+}
+
+[[eraseable]]
+void cvar_describe(string name, string desc)
+{
+       localcmd(sprintf("\nset %1$s \"$%1$s\" \"%2$s\"\n", name, MakeConsoleSafe(desc)));
+}
+
+[[eraseable]]
+void cvar_archive(string name)
+{
+       localcmd(sprintf("\nseta %1$s \"$%1$s\"\n", name));
+}
+
+[[eraseable]]
+void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
+{
+       cvar_describe(name, desc);
+       if (archive) cvar_archive(name);
+}
 
+int RegisterCvars_Save_fd;
+[[eraseable]]
+void RegisterCvars_Save(string name, string def, string desc, bool archive, string file)
+{
+       if (!archive) return;
+       fputs(RegisterCvars_Save_fd, sprintf("seta %s \"%s\"\n", name, def));
+}
+
+STATIC_INIT_LATE(Cvars)
+{
+       RegisterCvars(RegisterCvars_Set);
+       RegisterCvars_Save_fd = fopen(sprintf("default%s.cfg", PROGNAME), FILE_WRITE);
+       if (RegisterCvars_Save_fd >= 0)
+       {
+               RegisterCvars(RegisterCvars_Save);
+               fclose(RegisterCvars_Save_fd);
+       }
+}
+
+const noref bool default_bool = false;
+const noref int default_int = 0;
+const noref float default_float = 0;
+const noref string default_string = "";
+const noref vector default_vector = '0 0 0';
+
+#define repr_cvar_bool(x) ((x) ? "1" : "0")
+#define repr_cvar_int(x) (ftos(x))
+#define repr_cvar_float(x) (ftos(x))
+#define repr_cvar_string(x) (x)
+#define repr_cvar_vector(x) (sprintf("%v", x))
+
+//pseudo prototypes:
+// void AUTOCVAR(<cvar_name>, <qc_var_type>, default_cvar_value, string desc)
+// void AUTOCVAR_SAVE(<cvar_name>, <qc_var_type>, default_cvar_value, string desc)
+//  where default_cvar_value has type <qc_var_type>
+//  e.g.: AUTOCVAR(mycvar, float, 2.5, "cvar description")
+
+#define __AUTOCVAR(file, archive, var, type, desc, default) \
+       [[accumulate]] void RegisterCvars(void(string, string, string, bool, string) f) \
+       { \
+               f( #var, repr_cvar_##type(default), desc, archive, file); \
+       } \
+       type autocvar_##var = default
 #define AUTOCVAR_5(file, archive, var, type, desc) \
-    [[accumulate]] void RegisterCvars(void(string, string, bool, string) f) { f(#var, desc, archive, file); } \
-    type autocvar_##var
+       __AUTOCVAR(file, archive, var, type, desc, default_##type)
 #define AUTOCVAR_6(file, archive, var, type, default, desc) \
-    AUTOCVAR_5(file, archive, var, type, desc) = default
-#define _AUTOCVAR(...) EVAL(OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__))
+       __AUTOCVAR(file, archive, var, type, desc, default)
+#define _AUTOCVAR(...) EVAL__AUTOCVAR(OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__))
+#define EVAL__AUTOCVAR(...) __VA_ARGS__
 #define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
 #define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
-
-#endif