mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
[util] Add listeners to cvars
Listeners are separate to the main callback as listeners have only read-only access to the objects, but the main callback is free to modify the cvar and thus can act as a parser and validator. The listeners are invoked after the main callback if the cvar is modified. There does not need to be a main callback for the listeners to be invoked.
This commit is contained in:
parent
3f299155a3
commit
c4118a4bf1
2 changed files with 42 additions and 3 deletions
|
@ -33,6 +33,7 @@
|
|||
*/
|
||||
///@{
|
||||
|
||||
#include "QF/listener.h"
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/quakeio.h"
|
||||
|
||||
|
@ -51,6 +52,7 @@ typedef struct cvar_s {
|
|||
\param var This cvar.
|
||||
*/
|
||||
void (*callback)(struct cvar_s *var);
|
||||
struct cvar_listener_set_s *listeners;
|
||||
const char *description; ///< for "help" command
|
||||
float value; ///< The current cvar value as a float
|
||||
int int_val; ///< The current cvar value as an integer
|
||||
|
@ -58,6 +60,10 @@ typedef struct cvar_s {
|
|||
struct cvar_s *next; ///< \internal Linked list of cvars.
|
||||
} cvar_t;
|
||||
|
||||
typedef struct cvar_listener_set_s LISTENER_SET_TYPE (cvar_t)
|
||||
cvar_listener_set_t;
|
||||
typedef void (*cvar_listener_t) (void *data, const cvar_t *cvar);
|
||||
|
||||
typedef struct cvar_alias_s {
|
||||
char *name; ///< The name of the alias.
|
||||
cvar_t *cvar; ///< The cvar to which this alias refers
|
||||
|
@ -97,6 +103,8 @@ cvar_t *Cvar_FindAlias (const char *alias_name);
|
|||
|
||||
cvar_t *Cvar_MakeAlias (const char *name, cvar_t *cvar);
|
||||
cvar_t *Cvar_RemoveAlias (const char *name);
|
||||
void Cvar_AddListener (cvar_t *cvar, cvar_listener_t listener, void *data);
|
||||
void Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data);
|
||||
|
||||
// equivelants to "<name> <variable>" typed at the console
|
||||
void Cvar_Set (cvar_t *var, const char *value);
|
||||
|
|
|
@ -249,6 +249,24 @@ Cvar_CompleteBuildList (const char *partial)
|
|||
return buf;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Cvar_AddListener (cvar_t *cvar, cvar_listener_t listener, void *data)
|
||||
{
|
||||
if (!cvar->listeners) {
|
||||
cvar->listeners = malloc (sizeof (*cvar->listeners));
|
||||
LISTENER_SET_INIT (cvar->listeners, 8);
|
||||
}
|
||||
LISTENER_ADD (cvar->listeners, listener, data);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data)
|
||||
{
|
||||
if (cvar->listeners) {
|
||||
LISTENER_REMOVE (cvar->listeners, listener, data);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Cvar_Set (cvar_t *var, const char *value)
|
||||
{
|
||||
|
@ -279,6 +297,10 @@ Cvar_Set (cvar_t *var, const char *value)
|
|||
|
||||
if (var->callback)
|
||||
var->callback (var);
|
||||
|
||||
if (var->listeners) {
|
||||
LISTENER_INVOKE (var->listeners, var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,7 +732,7 @@ VISIBLE cvar_t *
|
|||
Cvar_Get (const char *name, const char *string, int cvarflags,
|
||||
void (*callback)(cvar_t*), const char *description)
|
||||
{
|
||||
|
||||
int changed = 0;
|
||||
cvar_t *var;
|
||||
|
||||
if (Cmd_Exists (name)) {
|
||||
|
@ -740,10 +762,13 @@ Cvar_Get (const char *name, const char *string, int cvarflags,
|
|||
break;
|
||||
var->next = *v;
|
||||
*v = var;
|
||||
|
||||
changed = 1;
|
||||
} else {
|
||||
// Cvar does exist, so we update the flags and return.
|
||||
var->flags &= ~CVAR_USER_CREATED;
|
||||
var->flags |= cvarflags;
|
||||
changed = !strequal (var->string, string) || var->callback != callback;
|
||||
if (!var->callback)
|
||||
var->callback = callback;
|
||||
if (!var->description
|
||||
|
@ -753,8 +778,14 @@ Cvar_Get (const char *name, const char *string, int cvarflags,
|
|||
if (!var->default_string)
|
||||
var->default_string = strdup (string);
|
||||
}
|
||||
if (var->callback)
|
||||
var->callback (var);
|
||||
if (changed) {
|
||||
if (var->callback)
|
||||
var->callback (var);
|
||||
|
||||
if (var->listeners) {
|
||||
LISTENER_INVOKE (var->listeners, var);
|
||||
}
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue