diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/chat-commands.c | 2 | ||||
-rw-r--r-- | src/core/expandos.c | 90 | ||||
-rw-r--r-- | src/core/expandos.h | 4 | ||||
-rw-r--r-- | src/core/signals.c | 21 | ||||
-rw-r--r-- | src/core/signals.h | 1 | ||||
-rw-r--r-- | src/core/special-vars.c | 96 | ||||
-rw-r--r-- | src/core/special-vars.h | 13 |
7 files changed, 191 insertions, 36 deletions
diff --git a/src/core/chat-commands.c b/src/core/chat-commands.c index f2cae1ab..969be382 100644 --- a/src/core/chat-commands.c +++ b/src/core/chat-commands.c @@ -81,7 +81,7 @@ static void cmd_msg(const char *data, SERVER_REC *server, WI_ITEM_REC *item) free_ret = FALSE; if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) { target = parse_special(&target, server, item, - NULL, &free_ret, NULL); + NULL, &free_ret, NULL, 0); } else if (strcmp(target, "*") == 0 && item != NULL) target = item->name; 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); diff --git a/src/core/expandos.h b/src/core/expandos.h index 2ce00ecc..a937fcd1 100644 --- a/src/core/expandos.h +++ b/src/core/expandos.h @@ -1,6 +1,7 @@ #ifndef __EXPANDOS_H #define __EXPANDOS_H +#include "signals.h" #include "servers.h" /* first argument of signal must match to active .. */ @@ -25,6 +26,9 @@ void expando_add_signal(const char *key, const char *signal, ExpandoArg arg); /* Destroy expando */ void expando_destroy(const char *key, EXPANDO_FUNC func); +void expando_bind(const char *key, int funccount, SIGNAL_FUNC *funcs); +void expando_unbind(const char *key, int funccount, SIGNAL_FUNC *funcs); + /* internal: */ EXPANDO_FUNC expando_find_char(char chr); EXPANDO_FUNC expando_find_long(const char *key); diff --git a/src/core/signals.c b/src/core/signals.c index 710d0687..3c1e4281 100644 --- a/src/core/signals.c +++ b/src/core/signals.c @@ -146,25 +146,24 @@ static int signal_remove_from_lists(SIGNAL_REC *rec, int signal_id, return 0; } -/* unbind signal */ -void signal_remove(const char *signal, SIGNAL_FUNC func) +void signal_remove_id(int signal_id, SIGNAL_FUNC func) { SIGNAL_REC *rec; - int signal_id, found; - g_return_if_fail(signal != NULL); + g_return_if_fail(signal_id >= 0); g_return_if_fail(func != NULL); - signal_id = signal_get_uniq_id(signal); - rec = g_hash_table_lookup(signals, GINT_TO_POINTER(signal_id)); - found = rec == NULL ? 0 : + if (rec != NULL) signal_remove_from_lists(rec, signal_id, func); +} - if (!found) { - g_warning("signal_remove() : signal \"%s\" isn't " - "grabbed for %p", signal, func); - } +/* unbind signal */ +void signal_remove(const char *signal, SIGNAL_FUNC func) +{ + g_return_if_fail(signal != NULL); + + signal_remove_id(signal_get_uniq_id(signal), func); } /* Remove all NULL functions from signal list */ diff --git a/src/core/signals.h b/src/core/signals.h index 24e0ecbf..f1fabf6c 100644 --- a/src/core/signals.h +++ b/src/core/signals.h @@ -23,6 +23,7 @@ void signal_add_to_id(const char *module, int pos, /* unbind signal */ void signal_remove(const char *signal, SIGNAL_FUNC func); +void signal_remove_id(int signal_id, SIGNAL_FUNC func); /* emit signal */ int signal_emit(const char *signal, int params, ...); diff --git a/src/core/special-vars.c b/src/core/special-vars.c index f3f7cf14..7d4deb78 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -125,7 +125,7 @@ static char *get_long_variable_value(const char *key, SERVER_REC *server, } static char *get_long_variable(char **cmd, SERVER_REC *server, - void *item, int *free_ret) + void *item, int *free_ret, int getname) { char *start, *var, *ret; @@ -134,30 +134,41 @@ static char *get_long_variable(char **cmd, SERVER_REC *server, while (isvarchar((*cmd)[1])) (*cmd)++; var = g_strndup(start, (int) (*cmd-start)+1); + if (getname) { + *free_ret = TRUE; + return var; + } ret = get_long_variable_value(var, server, item, free_ret); g_free(var); return ret; } -/* return the value of the variable found from `cmd' */ +/* return the value of the variable found from `cmd'. + if 'getname' is TRUE, return the name of the variable instead it's value */ static char *get_variable(char **cmd, SERVER_REC *server, void *item, - char **arglist, int *free_ret, int *arg_used) + char **arglist, int *free_ret, int *arg_used, + int getname) { EXPANDO_FUNC func; if (isdigit(**cmd) || **cmd == '*' || **cmd == '-' || **cmd == '~') { - /* argument */ + /* argument */ *free_ret = TRUE; if (arg_used != NULL) *arg_used = TRUE; - return get_argument(cmd, arglist); + return getname ? g_strdup_printf("%c", **cmd) : + get_argument(cmd, arglist); } if (isalpha(**cmd) && isvarchar((*cmd)[1])) { /* long variable name.. */ - return get_long_variable(cmd, server, item, free_ret); + return get_long_variable(cmd, server, item, free_ret, getname); } /* single character variable. */ + if (getname) { + *free_ret = TRUE; + return g_strdup_printf("%c", **cmd); + } *free_ret = FALSE; func = expando_find_char(**cmd); return func == NULL ? NULL : func(server, item, free_ret); @@ -184,13 +195,17 @@ static char *get_history(char **cmd, void *item, int *free_ret) } static char *get_special_value(char **cmd, SERVER_REC *server, void *item, - char **arglist, int *free_ret, int *arg_used) + char **arglist, int *free_ret, int *arg_used, + int flags) { char command, *value, *p; int len; if (**cmd == '!') { /* find text from command history */ + if (flags & PARSE_FLAG_GETNAME) + return "!"; + return get_history(cmd, item, free_ret); } @@ -203,12 +218,19 @@ static char *get_special_value(char **cmd, SERVER_REC *server, void *item, /* default to $* */ char *temp_cmd = "*"; + if (flags & PARSE_FLAG_GETNAME) + return "*"; + *free_ret = TRUE; return get_argument(&temp_cmd, arglist); } } - value = get_variable(cmd, server, item, arglist, free_ret, arg_used); + value = get_variable(cmd, server, item, arglist, free_ret, + arg_used, flags & PARSE_FLAG_GETNAME); + + if (flags & PARSE_FLAG_GETNAME) + return value; if (command == '#') { /* number of words */ @@ -314,7 +336,7 @@ static char *get_alignment(const char *text, int align, int flags, char pad) /* Parse and expand text after '$' character. return value has to be g_free()'d if `free_ret' is TRUE. */ char *parse_special(char **cmd, SERVER_REC *server, void *item, - char **arglist, int *free_ret, int *arg_used) + char **arglist, int *free_ret, int *arg_used, int flags) { static char **nested_orig_cmd = NULL; /* FIXME: KLUDGE! */ char command, *value; @@ -355,7 +377,8 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item, } else { (*cmd)++; nest_value = parse_special(cmd, server, item, arglist, - &nest_free, arg_used); + &nest_free, arg_used, + flags); } while ((*nested_orig_cmd)[1] != '\0') { @@ -377,10 +400,13 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item, } value = get_special_value(cmd, server, item, arglist, - free_ret, arg_used); + free_ret, arg_used, flags); if (**cmd == '\0') g_error("parse_special() : buffer overflow!"); + if (value != NULL && *value != '\0' && (flags & PARSE_FLAG_ISSET_ANY)) + *arg_used = TRUE; + if (brackets) { while (**cmd != '}' && (*cmd)[1] != '\0') (*cmd)++; @@ -388,7 +414,7 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item, if (nest_free) g_free(nest_value); - if (command == '[') { + if (command == '[' && (flags & PARSE_FLAG_GETNAME) == 0) { /* alignment */ char *p; @@ -406,7 +432,7 @@ char *parse_special(char **cmd, SERVER_REC *server, void *item, /* parse the whole string. $ and \ chars are replaced */ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item, - const char *data, int *arg_used) + const char *data, int *arg_used, int flags) { char code, **arglist, *ret; GString *str; @@ -438,7 +464,8 @@ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item, char *ret; ret = parse_special((char **) &cmd, server, item, - arglist, &need_free, arg_used); + arglist, &need_free, arg_used, + flags); if (ret != NULL) { g_string_append(str, ret); if (need_free) g_free(ret); @@ -488,7 +515,7 @@ void eval_special_string(const char *cmd, const char *data, } ret = parse_special_string(start, server, item, - data, &arg_used); + data, &arg_used, 0); if (arg_used) arg_used_ever = TRUE; if (strchr(cmdchars, *ret) == NULL) { @@ -525,3 +552,42 @@ void special_history_func_set(SPECIAL_HISTORY_FUNC func) { history_func = func; } + +static void special_vars_signals_do(const char *text, int funccount, + SIGNAL_FUNC *funcs, int bind) +{ + char *ret; + int need_free; + + while (*text != '\0') { + if (*text == '\\' && text[1] != '\0') { + text += 2; + } else if (*text == '$' && text[1] != '\0') { + text++; + ret = parse_special((char **) &text, NULL, NULL, + NULL, &need_free, NULL, + PARSE_FLAG_GETNAME); + if (ret != NULL) { + if (bind) + expando_bind(ret, funccount, funcs); + else + expando_unbind(ret, funccount, funcs); + if (need_free) g_free(ret); + } + + } + else text++; + } +} + +void special_vars_add_signals(const char *text, + int funccount, SIGNAL_FUNC *funcs) +{ + special_vars_signals_do(text, funccount, funcs, TRUE); +} + +void special_vars_remove_signals(const char *text, + int funccount, SIGNAL_FUNC *funcs) +{ + special_vars_signals_do(text, funccount, funcs, FALSE); +} diff --git a/src/core/special-vars.h b/src/core/special-vars.h index 1b8b3e20..deb4de40 100644 --- a/src/core/special-vars.h +++ b/src/core/special-vars.h @@ -1,19 +1,23 @@ #ifndef __SPECIAL_VARS_H #define __SPECIAL_VARS_H +#include "signals.h" #include "servers.h" +#define PARSE_FLAG_GETNAME 0x01 /* return argument name instead of it's value */ +#define PARSE_FLAG_ISSET_ANY 0x02 /* arg_used field specifies that at least one of the $variables was non-empty */ + typedef char* (*SPECIAL_HISTORY_FUNC) (const char *text, void *item, int *free_ret); /* Parse and expand text after '$' character. return value has to be g_free()'d if `free_ret' is TRUE. */ char *parse_special(char **cmd, SERVER_REC *server, void *item, - char **arglist, int *free_ret, int *arg_used); + char **arglist, int *free_ret, int *arg_used, int flags); /* parse the whole string. $ and \ chars are replaced */ char *parse_special_string(const char *cmd, SERVER_REC *server, void *item, - const char *data, int *arg_used); + const char *data, int *arg_used, int flags); /* execute the commands in string - commands can be split with ';' */ void eval_special_string(const char *cmd, const char *data, @@ -21,4 +25,9 @@ void eval_special_string(const char *cmd, const char *data, void special_history_func_set(SPECIAL_HISTORY_FUNC func); +void special_vars_add_signals(const char *text, + int funccount, SIGNAL_FUNC *funcs); +void special_vars_remove_signals(const char *text, + int funccount, SIGNAL_FUNC *funcs); + #endif |