summaryrefslogtreecommitdiff
path: root/src/core/expandos.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/expandos.c')
-rw-r--r--src/core/expandos.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/src/core/expandos.c b/src/core/expandos.c
index 1dbd95ac..37f770a3 100644
--- a/src/core/expandos.c
+++ b/src/core/expandos.c
@@ -44,6 +44,8 @@ typedef struct {
int signal_args[MAX_EXPANDO_SIGNALS];
} EXPANDO_REC;
+static int timer_tag;
+
static EXPANDO_REC *char_expandos[127];
static GHashTable *expandos;
static time_t client_start_time;
@@ -86,6 +88,14 @@ void expando_create(const char *key, EXPANDO_FUNC func, ...)
va_end(va);
}
+static EXPANDO_REC *expando_find(const char *key)
+{
+ if (key[1] != '\0')
+ return g_hash_table_lookup(expandos, key);
+ else
+ return char_expandos[(int) *key];
+}
+
/* Add new signal to expando */
void expando_add_signal(const char *key, const char *signal, ExpandoArg arg)
{
@@ -94,15 +104,15 @@ void expando_add_signal(const char *key, const char *signal, ExpandoArg arg)
g_return_if_fail(key != NULL);
g_return_if_fail(signal != NULL);
- if (key[1] != '\0')
- rec = g_hash_table_lookup(expandos, key);
- else {
- /* single character expando */
- rec = char_expandos[(int) *key];
- }
+ rec = expando_find(key);
g_return_if_fail(rec != NULL);
- if (rec->signals < MAX_EXPANDO_SIGNALS) {
+ if (arg == EXPANDO_NEVER) {
+ /* expando changes never */
+ rec->signals = -1;
+ } else if (rec->signals < MAX_EXPANDO_SIGNALS) {
+ g_return_if_fail(rec->signals != -1);
+
rec->signal_ids[rec->signals] = signal_get_uniq_id(signal);
rec->signal_args[rec->signals] = arg;
rec->signals++;
@@ -135,6 +145,64 @@ void expando_destroy(const char *key, EXPANDO_FUNC func)
}
}
+void expando_bind(const char *key, int funccount, SIGNAL_FUNC *funcs)
+{
+ SIGNAL_FUNC func;
+ EXPANDO_REC *rec;
+ int n, arg;
+
+ g_return_if_fail(key != NULL);
+ g_return_if_fail(funccount >= 1);
+ g_return_if_fail(funcs != NULL);
+ g_return_if_fail(funcs[0] != NULL);
+
+ rec = expando_find(key);
+ g_return_if_fail(rec != NULL);
+
+ if (rec->signals == 0) {
+ /* it's unknown when this expando changes..
+ check it once in a second */
+ signal_add("expando timer", funcs[EXPANDO_ARG_NONE]);
+ }
+
+ for (n = 0; n < rec->signals; n++) {
+ arg = rec->signal_args[n];
+ func = arg < funccount ? funcs[arg] : NULL;
+ if (func == NULL) func = funcs[EXPANDO_ARG_NONE];
+
+ signal_add_to_id(MODULE_NAME, 1, rec->signal_ids[n], func);
+ }
+}
+
+void expando_unbind(const char *key, int funccount, SIGNAL_FUNC *funcs)
+{
+ SIGNAL_FUNC func;
+ EXPANDO_REC *rec;
+ int n, arg;
+
+ g_return_if_fail(key != NULL);
+ g_return_if_fail(funccount >= 1);
+ g_return_if_fail(funcs != NULL);
+ g_return_if_fail(funcs[0] != NULL);
+
+ rec = expando_find(key);
+ g_return_if_fail(rec != NULL);
+
+ if (rec->signals == 0) {
+ /* it's unknown when this expando changes..
+ check it once in a second */
+ signal_remove("expando timer", funcs[EXPANDO_ARG_NONE]);
+ }
+
+ for (n = 0; n < rec->signals; n++) {
+ arg = rec->signal_args[n];
+ func = arg < funccount ? funcs[arg] : NULL;
+ if (func == NULL) func = funcs[EXPANDO_ARG_NONE];
+
+ signal_remove_id(rec->signal_ids[n], func);
+ }
+}
+
EXPANDO_FUNC expando_find_char(char chr)
{
g_return_val_if_fail(chr < sizeof(char_expandos) /
@@ -360,6 +428,12 @@ static void cmd_msg(const char *data, SERVER_REC *server)
cmd_params_free(free_arg);
}
+static int sig_timer(void)
+{
+ signal_emit("expando timer", 0);
+ return 1;
+}
+
void expandos_init(void)
{
#ifdef HAVE_SYS_UTSNAME_H
@@ -455,6 +529,7 @@ void expandos_init(void)
"window changed", EXPANDO_ARG_NONE,
"window server changed", EXPANDO_ARG_WINDOW, NULL);
+ timer_tag = g_timeout_add(1000, (GSourceFunc) sig_timer, NULL);
signal_add("command msg", (SIGNAL_FUNC) cmd_msg);
signal_add("message public", (SIGNAL_FUNC) sig_message_public);
signal_add("message private", (SIGNAL_FUNC) sig_message_private);
@@ -479,6 +554,7 @@ void expandos_deinit(void)
g_free_not_null(last_privmsg_from); g_free_not_null(last_public_from);
g_free_not_null(sysname); g_free_not_null(sysrelease);
+ g_source_remove(timer_tag);
signal_remove("message public", (SIGNAL_FUNC) sig_message_public);
signal_remove("message private", (SIGNAL_FUNC) sig_message_private);
signal_remove("command msg", (SIGNAL_FUNC) cmd_msg);