+ Cvar_Set(cvars, var_name, val);
+}
+
+void Cvar_RegisterCallback(cvar_t *variable, void (*callback)(cvar_t *))
+{
+ if (variable == NULL)
+ {
+ Con_Print(CON_WARN "Cvar_RegisterCallback: var == NULL\n");
+ return;
+ }
+
+ if (!(variable->flags & cmd_local->cvars_flagsmask))
+ {
+ if (developer_extra.integer)
+ Con_DPrintf("^6Cvar_RegisterCallback: rejecting cvar \"%s\"\n", variable->name);
+ return;
+ }
+
+ variable->callback = callback;
+}
+
+void Cvar_RegisterVirtual(cvar_t *variable, const char *name )
+{
+ cvar_state_t *cvars = &cvars_all;
+ cvar_hash_t *hash;
+ unsigned hashindex;
+
+ if (!(variable->flags & cmd_local->cvars_flagsmask))
+ {
+ if (developer_extra.integer)
+ Con_DPrintf("^6Cvar_RegisterVirtual: rejecting cvar \"%s\" alias \"%s\"\n", variable->name, name);
+ return;
+ }
+
+ if(!*name)
+ {
+ Con_Printf(CON_WARN "Cvar_RegisterVirtual: invalid virtual cvar name\n");
+ return;
+ }
+
+ // check for overlap with a command
+ if (Cmd_Exists(cmd_local, name))
+ {
+ Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a command\n", name);
+ return;
+ }
+
+ if(Cvar_FindVar(&cvars_all, name, 0))
+ {
+ Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a cvar\n", name);
+ return;
+ }
+
+ // Resize the variable->aliases list to have room for another entry and a null terminator.
+ // This zero-pads when resizing, so we don't need to write the NULL terminator manually here.
+ // Also if aliases is NULL this allocates fresh for the correct size, so it's fine to just do this.
+ variable->aliases = (char **)Z_Realloc(variable->aliases, sizeof(char *) * (variable->aliases_size + 2));
+ // Add the new alias, and increment the number of aliases in the list
+ variable->aliases[variable->aliases_size++] = Z_strdup(name);
+
+ // link to head of list in this hash table index
+ hash = (cvar_hash_t *)Z_Malloc(sizeof(cvar_hash_t));
+ hashindex = CRC_Block((const unsigned char *)name, strlen(name)) % CVAR_HASHSIZE;
+ hash->next = cvars->hashtable[hashindex];
+ cvars->hashtable[hashindex] = hash;
+ hash->cvar = variable;
+}
+
+/*
+============
+Cvar_Link
+
+Links a variable to the variable list and hashtable
+============
+*/
+static void Cvar_Link(cvar_t *variable, cvar_state_t *cvars)
+{
+ cvar_t *current, *next;
+ cvar_hash_t *hash;
+ unsigned hashindex;
+ /*
+ * Link the variable in
+ * alphanumerical order
+ */
+ for( current = NULL, next = cvars->vars ; next && strcmp( next->name, variable->name ) < 0 ; current = next, next = next->next )
+ ;
+ if(current)
+ current->next = variable;
+ else
+ cvars->vars = variable;
+ variable->next = next;
+
+ // link to head of list in this hash table index
+ hash = (cvar_hash_t *)Z_Malloc(sizeof(cvar_hash_t));
+ hashindex = CRC_Block((const unsigned char *)variable->name, strlen(variable->name)) % CVAR_HASHSIZE;
+ hash->next = cvars->hashtable[hashindex];
+ hash->cvar = variable;
+ cvars->hashtable[hashindex] = hash;