]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cvar.c
menuqc += +VM_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC)
[xonotic/darkplaces.git] / cvar.c
diff --git a/cvar.c b/cvar.c
index 8f3abc390a64e94d92aa8998b7df4c53154506ca..c6f69360825f07765f71b485561f40370f17ae09 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -70,6 +70,36 @@ cvar_t *Cvar_FindVarAfter (const char *prev_var_name, int neededflags)
        return var;
 }
 
+cvar_t *Cvar_FindVarLink (const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha)
+{
+       int hashindex;
+       cvar_t *var;
+
+       // use hash lookup to minimize search time
+       hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name));
+       if(parent) *parent = NULL;
+       if(prev_alpha) *prev_alpha = NULL;
+       if(link) *link = &cvar_hashtable[hashindex];
+       for (var = cvar_hashtable[hashindex];var;var = var->nextonhashchain)
+       {
+               if (!strcmp (var_name, var->name))
+               {
+                       if(!prev_alpha || var == cvar_vars)
+                               return var;
+
+                       *prev_alpha = cvar_vars;
+                       // if prev_alpha happens to become NULL then there has been some inconsistency elsewhere
+                       // already - should I still insert '*prev_alpha &&' in the loop?
+                       while((*prev_alpha)->next != var)
+                               *prev_alpha = (*prev_alpha)->next;
+                       return var;
+               }
+               if(parent) *parent = var;
+       }
+
+       return NULL;
+}
+
 /*
 ============
 Cvar_VariableValue
@@ -223,6 +253,55 @@ void Cvar_CompleteCvarPrint (const char *partial)
                        Con_Printf ("^3%s^7 is \"%s\" [\"%s\"] %s\n", cvar->name, cvar->string, cvar->defstring, cvar->description);
 }
 
+// we assume that prog is already set to the target progs
+static void Cvar_UpdateAutoCvar(cvar_t *var)
+{
+       int i;
+       if(!prog)
+               Host_Error("Cvar_UpdateAutoCvar: no prog set");
+       i = PRVM_GetProgNr();
+       if(var->globaldefindex_progid[i] == prog->id)
+       {
+               // MUST BE SYNCED WITH prvm_edict.c PRVM_LoadProgs
+               int j;
+               const char *s;
+               prvm_eval_t *val = (prvm_eval_t *)(prog->globals.generic + prog->globaldefs[var->globaldefindex[i]].ofs);
+               switch(prog->globaldefs[var->globaldefindex[i]].type & ~DEF_SAVEGLOBAL)
+               {
+                       case ev_float:
+                               val->_float = var->value;
+                               break;
+                       case ev_vector:
+                               s = var->string;
+                               VectorClear(val->vector);
+                               for (j = 0;j < 3;j++)
+                               {
+                                       while (*s && ISWHITESPACE(*s))
+                                               s++;
+                                       if (!*s)
+                                               break;
+                                       val->vector[j] = atof(s);
+                                       while (!ISWHITESPACE(*s))
+                                               s++;
+                                       if (!*s)
+                                               break;
+                               }
+                               break;
+                       case ev_string:
+                               PRVM_ChangeEngineString(var->globaldefindex_stringno[i], var->string);
+                               val->string = var->globaldefindex_stringno[i];
+                               break;
+               }
+       }
+}
+
+// called after loading a savegame
+void Cvar_UpdateAllAutoCvars(void)
+{
+       cvar_t *var;
+       for (var = cvar_vars ; var ; var = var->next)
+               Cvar_UpdateAutoCvar(var);
+}
 
 /*
 ============
@@ -314,39 +393,7 @@ void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
                if(PRVM_ProgLoaded(i))
                {
                        PRVM_SetProg(i);
-                       if(var->globaldefindex_progid[i] == prog->id)
-                       {
-                               // MUST BE SYNCED WITH prvm_edict.c PRVM_LoadProgs
-                               int j;
-                               const char *s;
-                               prvm_eval_t *val = (prvm_eval_t *)(prog->globals.generic + prog->globaldefs[var->globaldefindex[i]].ofs);
-                               switch(prog->globaldefs[var->globaldefindex[i]].type & ~DEF_SAVEGLOBAL)
-                               {
-                                       case ev_float:
-                                               val->_float = var->value;
-                                               break;
-                                       case ev_vector:
-                                               s = var->string;
-                                               VectorClear(val->vector);
-                                               for (j = 0;j < 3;j++)
-                                               {
-                                                       while (*s && ISWHITESPACE(*s))
-                                                               s++;
-                                                       if (!*s)
-                                                               break;
-                                                       val->vector[j] = atof(s);
-                                                       while (!ISWHITESPACE(*s))
-                                                               s++;
-                                                       if (!*s)
-                                                               break;
-                                               }
-                                               break;
-                                       case ev_string:
-                                               PRVM_ChangeEngineString(var->globaldefindex_stringno[i], var->string);
-                                               val->string = var->globaldefindex_stringno[i];
-                                               break;
-                               }
-                       }
+                       Cvar_UpdateAutoCvar(var);
                }
        }
        prog = tmpprog;
@@ -820,6 +867,60 @@ void Cvar_SetA_f (void)
        Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), CVAR_SAVE, Cmd_Argc() > 3 ? Cmd_Argv(3) : NULL);
 }
 
+void Cvar_Del_f (void)
+{
+       int i;
+       cvar_t *cvar, *parent, **link, *prev;
+
+       if(Cmd_Argc() < 2)
+       {
+               Con_Printf("Del: wrong number of parameters, useage: unset <variablename1> [<variablename2> ...]\n");
+               return;
+       }
+       for(i = 1; i < Cmd_Argc(); ++i)
+       {
+               cvar = Cvar_FindVarLink(Cmd_Argv(i), &parent, &link, &prev);
+               if(!cvar)
+               {
+                       Con_Printf("Del: %s is not defined\n", Cmd_Argv(i));
+                       continue;
+               }
+               if(cvar->flags & CVAR_READONLY)
+               {
+                       Con_Printf("Del: %s is read-only\n", cvar->name);
+                       continue;
+               }
+               if(!(cvar->flags & CVAR_ALLOCATED))
+               {
+                       Con_Printf("Del: %s is static and cannot be deleted\n", cvar->name);
+                       continue;
+               }
+               if(cvar == cvar_vars)
+               {
+                       cvar_vars = cvar->next;
+               }
+               else
+               {
+                       // in this case, prev must be set, otherwise there has been some inconsistensy
+                       // elsewhere already... should I still check for prev != NULL?
+                       prev->next = cvar->next;
+               }
+
+               if(parent)
+                       parent->nextonhashchain = cvar->nextonhashchain;
+               else if(link)
+                       *link = cvar->nextonhashchain;
+
+               if(cvar->description != cvar_dummy_description)
+                       Z_Free(cvar->description);
+
+               Z_Free(cvar->name);
+               Z_Free(cvar->string);
+               Z_Free(cvar->defstring);
+               Z_Free(cvar);
+       }
+}
+
 #ifdef FILLALLCVARSWITHRUBBISH
 void Cvar_FillAll_f()
 {