diff options
-rw-r--r-- | src/core/commands.c | 212 | ||||
-rw-r--r-- | src/core/commands.h | 26 | ||||
-rw-r--r-- | src/core/modules.c | 6 | ||||
-rw-r--r-- | src/core/settings.c | 31 | ||||
-rw-r--r-- | src/core/settings.h | 18 |
5 files changed, 261 insertions, 32 deletions
diff --git a/src/core/commands.c b/src/core/commands.c index 042f26b6..200dc3d0 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -53,6 +53,42 @@ COMMAND_REC *command_find(const char *cmd) return NULL; } +static COMMAND_MODULE_REC *command_module_find(COMMAND_REC *rec, + const char *module) +{ + GSList *tmp; + + g_return_val_if_fail(rec != NULL, NULL); + g_return_val_if_fail(module != NULL, NULL); + + for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) { + COMMAND_MODULE_REC *rec = tmp->data; + + if (g_strcasecmp(rec->name, module) == 0) + return rec; + } + + return NULL; +} + +static COMMAND_MODULE_REC *command_module_find_func(COMMAND_REC *rec, + SIGNAL_FUNC func) +{ + GSList *tmp; + + g_return_val_if_fail(rec != NULL, NULL); + g_return_val_if_fail(func != NULL, NULL); + + for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) { + COMMAND_MODULE_REC *rec = tmp->data; + + if (g_slist_find(rec->signals, func) != NULL) + return rec; + } + + return NULL; +} + int command_have_sub(const char *command) { GSList *tmp; @@ -73,12 +109,31 @@ int command_have_sub(const char *command) return FALSE; } -void command_bind_to(int pos, const char *cmd, +static COMMAND_MODULE_REC *command_module_get(COMMAND_REC *rec, + const char *module) +{ + COMMAND_MODULE_REC *modrec; + + g_return_val_if_fail(rec != NULL, NULL); + + modrec = command_module_find(rec, module); + if (modrec == NULL) { + modrec = g_new0(COMMAND_MODULE_REC, 1); + modrec->name = g_strdup(module); + rec->modules = g_slist_append(rec->modules, modrec); + } + + return modrec; +} + +void command_bind_to(const char *module, int pos, const char *cmd, const char *category, SIGNAL_FUNC func) { COMMAND_REC *rec; + COMMAND_MODULE_REC *modrec; char *str; + g_return_if_fail(module != NULL); g_return_if_fail(cmd != NULL); rec = command_find(cmd); @@ -88,18 +143,20 @@ void command_bind_to(int pos, const char *cmd, rec->category = category == NULL ? NULL : g_strdup(category); commands = g_slist_append(commands, rec); } - rec->count++; + modrec = command_module_get(rec, module); + + modrec->signals = g_slist_append(modrec->signals, func); if (func != NULL) { str = g_strconcat("command ", cmd, NULL); - signal_add_to(MODULE_NAME, pos, str, func); + signal_add_to(module, pos, str, func); g_free(str); } signal_emit("commandlist new", 1, rec); } -void command_free(COMMAND_REC *rec) +static void command_free(COMMAND_REC *rec) { commands = g_slist_remove(commands, rec); signal_emit("commandlist remove", 1, rec); @@ -110,22 +167,66 @@ void command_free(COMMAND_REC *rec) g_free(rec); } +static void command_module_free(COMMAND_MODULE_REC *modrec, COMMAND_REC *rec) +{ + rec->modules = g_slist_remove(rec->modules, modrec); + + g_slist_free(modrec->signals); + g_free(modrec->name); + g_free_not_null(modrec->options); + g_free(modrec); +} + +static void command_module_destroy(COMMAND_REC *rec, + COMMAND_MODULE_REC *modrec) +{ + GSList *tmp, *freelist; + + command_module_free(modrec, rec); + + /* command_set_options() might have added module declaration of it's + own without any signals .. check if they're the only ones left + and if so, destroy them. */ + freelist = NULL; + for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) { + COMMAND_MODULE_REC *rec = tmp->data; + + if (rec->signals == NULL) + freelist = g_slist_append(freelist, rec); + else { + g_slist_free(freelist); + freelist = NULL; + break; + } + } + + g_slist_foreach(freelist, (GFunc) command_module_free, rec); + g_slist_free(freelist); + + if (rec->modules == NULL) + command_free(rec); +} + void command_unbind(const char *cmd, SIGNAL_FUNC func) { COMMAND_REC *rec; + COMMAND_MODULE_REC *modrec; char *str; g_return_if_fail(cmd != NULL); + g_return_if_fail(func != NULL); rec = command_find(cmd); - if (rec != NULL && --rec->count == 0) - command_free(rec); - - if (func != NULL) { - str = g_strconcat("command ", cmd, NULL); - signal_remove(str, func); - g_free(str); + if (rec != NULL) { + modrec = command_module_find_func(rec, func); + modrec->signals = g_slist_remove(modrec->signals, func); + if (modrec->signals == NULL) + command_module_destroy(rec, modrec); } + + str = g_strconcat("command ", cmd, NULL); + signal_remove(str, func); + g_free(str); } /* Expand `cmd' - returns `cmd' if not found, NULL if more than one @@ -256,18 +357,11 @@ int command_have_option(const char *cmd, const char *option) return FALSE; } -void command_set_options(const char *cmd, const char *options) +static void command_calc_options(COMMAND_REC *rec, const char *options) { - COMMAND_REC *rec; char **optlist, **tmp, *name, *str; GSList *list, *oldopt; - g_return_if_fail(cmd != NULL); - g_return_if_fail(options != NULL); - - rec = command_find(cmd); - g_return_if_fail(rec != NULL); - optlist = g_strsplit(options, " ", -1); if (rec->options == NULL) { @@ -307,6 +401,52 @@ void command_set_options(const char *cmd, const char *options) g_slist_free(list); } +/* recalculate options to command from options in all modules */ +static void command_update_options(COMMAND_REC *rec) +{ + GSList *tmp; + + g_strfreev(rec->options); + rec->options = NULL; + + for (tmp = rec->modules; tmp != NULL; tmp = tmp->next) { + COMMAND_MODULE_REC *modrec = tmp->data; + + if (modrec->options != NULL) + command_calc_options(rec, modrec->options); + } +} + +void command_set_options_module(const char *module, + const char *cmd, const char *options) +{ + COMMAND_REC *rec; + COMMAND_MODULE_REC *modrec; + int reload; + + g_return_if_fail(module != NULL); + g_return_if_fail(cmd != NULL); + g_return_if_fail(options != NULL); + + rec = command_find(cmd); + g_return_if_fail(rec != NULL); + modrec = command_module_get(rec, module); + + reload = modrec->options != NULL; + if (reload) { + /* options already set for the module .. + we need to recalculate everything */ + g_free(modrec->options); + } + + modrec->options = g_strdup(options); + + if (reload) + command_update_options(rec); + else + command_calc_options(rec, options); +} + char *cmd_get_param(char **data) { char *pos; @@ -600,6 +740,40 @@ void cmd_get_remove_func(CMD_GET_FUNC func) cmdget_funcs = g_slist_prepend(cmdget_funcs, (void *) func); } +static void command_module_unbind_all(COMMAND_REC *rec, + COMMAND_MODULE_REC *modrec) +{ + GSList *tmp, *next; + + for (tmp = modrec->signals; tmp != NULL; tmp = next) { + next = tmp->next; + + command_unbind(rec->cmd, tmp->data); + } + + if (g_slist_find(commands, rec) != NULL) { + /* this module might have removed some options + from command, update them. */ + command_update_options(rec); + } +} + +void commands_remove_module(const char *module) +{ + GSList *tmp, *next, *modlist; + + g_return_if_fail(module != NULL); + + for (tmp = commands; tmp != NULL; tmp = next) { + COMMAND_REC *rec = tmp->data; + + next = tmp->next; + modlist = gslist_find_string(rec->modules, module); + if (modlist != NULL) + command_module_unbind_all(rec, modlist->data); + } +} + #define alias_runstack_push(alias) \ alias_runstack = g_slist_append(alias_runstack, alias) diff --git a/src/core/commands.h b/src/core/commands.h index 6a9d9be4..6acf11f3 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -4,10 +4,16 @@ #include "signals.h" typedef struct { - int count; + char *name; + char *options; + GSList *signals; +} COMMAND_MODULE_REC; + +typedef struct { + GSList *modules; char *category; char *cmd; - char **options; + char **options; /* combined from modules[..]->options */ } COMMAND_REC; enum { @@ -49,11 +55,12 @@ extern GSList *commands; extern char *current_command; /* the command we're right now. */ /* Bind command to specified function. */ -void command_bind_to(int pos, const char *cmd, +void command_bind_to(const char *module, int pos, const char *cmd, const char *category, SIGNAL_FUNC func); -#define command_bind(a, b, c) command_bind_to(1, a, b, c) -#define command_bind_first(a, b, c) command_bind_to(0, a, b, c) -#define command_bind_last(a, b, c) command_bind_to(2, a, b, c) +#define command_bind(a, b, c) command_bind_to(MODULE_NAME, 1, a, b, c) +#define command_bind_first(a, b, c) command_bind_to(MODULE_NAME, 0, a, b, c) +#define command_bind_last(a, b, c) command_bind_to(MODULE_NAME, 2, a, b, c) + void command_unbind(const char *cmd, SIGNAL_FUNC func); /* Run subcommand, `cmd' contains the base command, first word in `data' @@ -81,7 +88,10 @@ int command_have_sub(const char *command); call will override the previous */ #define iscmdtype(c) \ ((c) == '!' || (c) == '-' || (c) == '+' || (c) == '@') -void command_set_options(const char *cmd, const char *options); +void command_set_options_module(const char *module, + const char *cmd, const char *options); +#define command_set_options(cmd, options) \ + command_set_options_module(MODULE_NAME, cmd, options) /* Returns TRUE if command has specified option. */ int command_have_option(const char *cmd, const char *option); @@ -131,6 +141,8 @@ typedef char* (*CMD_GET_FUNC) (const char *data, int *count, va_list *args); void cmd_get_add_func(CMD_GET_FUNC func); void cmd_get_remove_func(CMD_GET_FUNC func); +void commands_remove_module(const char *module); + void commands_init(void); void commands_deinit(void); diff --git a/src/core/modules.c b/src/core/modules.c index 85bbf587..e45a05b5 100644 --- a/src/core/modules.c +++ b/src/core/modules.c @@ -22,6 +22,9 @@ #include "modules.h" #include "signals.h" +#include "commands.h" +#include "settings.h" + GSList *modules; static GHashTable *uniqids, *uniqstrids; @@ -342,7 +345,10 @@ void module_unload(MODULE_REC *module) module_deinit(); g_free(deinitfunc); + settings_remove_module(module->name); + commands_remove_module(module->name); signals_remove_module(module->name); + g_module_close(module->gmodule); g_free(module->name); g_free(module); diff --git a/src/core/settings.c b/src/core/settings.c index 926b1120..fbf46164 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -88,7 +88,8 @@ int settings_get_bool(const char *key) settings_get_default_int(key)); } -void settings_add_str(const char *section, const char *key, const char *def) +void settings_add_str_module(const char *module, const char *section, + const char *key, const char *def) { SETTINGS_REC *rec; @@ -99,6 +100,7 @@ void settings_add_str(const char *section, const char *key, const char *def) g_return_if_fail(rec == NULL); rec = g_new0(SETTINGS_REC, 1); + rec->module = g_strdup(module); rec->key = g_strdup(key); rec->section = g_strdup(section); rec->def = def == NULL ? NULL : g_strdup(def); @@ -106,7 +108,8 @@ void settings_add_str(const char *section, const char *key, const char *def) g_hash_table_insert(settings, rec->key, rec); } -void settings_add_int(const char *section, const char *key, int def) +void settings_add_int_module(const char *module, const char *section, + const char *key, int def) { SETTINGS_REC *rec; @@ -117,6 +120,7 @@ void settings_add_int(const char *section, const char *key, int def) g_return_if_fail(rec == NULL); rec = g_new0(SETTINGS_REC, 1); + rec->module = g_strdup(module); rec->type = SETTING_TYPE_INT; rec->key = g_strdup(key); rec->section = g_strdup(section); @@ -125,7 +129,8 @@ void settings_add_int(const char *section, const char *key, int def) g_hash_table_insert(settings, rec->key, rec); } -void settings_add_bool(const char *section, const char *key, int def) +void settings_add_bool_module(const char *module, const char *section, + const char *key, int def) { SETTINGS_REC *rec; @@ -136,6 +141,7 @@ void settings_add_bool(const char *section, const char *key, int def) g_return_if_fail(rec == NULL); rec = g_new0(SETTINGS_REC, 1); + rec->module = g_strdup(module); rec->type = SETTING_TYPE_BOOLEAN; rec->key = g_strdup(key); rec->section = g_strdup(section); @@ -148,6 +154,7 @@ static void settings_destroy(SETTINGS_REC *rec) { if (rec->type == SETTING_TYPE_STRING) g_free_not_null(rec->def); + g_free(rec->module); g_free(rec->section); g_free(rec->key); g_free(rec); @@ -166,6 +173,24 @@ void settings_remove(const char *key) settings_destroy(rec); } +static int settings_remove_hash(const char *key, SETTINGS_REC *rec, + const char *module) +{ + if (strcmp(rec->module, module) == 0) { + settings_destroy(rec); + return TRUE; + } + + return FALSE; +} + +void settings_remove_module(const char *module) +{ + g_hash_table_foreach_remove(settings, + (GHRFunc) settings_remove_hash, + (void *) module); +} + int settings_get_type(const char *key) { SETTINGS_REC *rec; diff --git a/src/core/settings.h b/src/core/settings.h index e56daefc..bd4c5b94 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -12,6 +12,7 @@ enum { }; typedef struct { + char *module; int type; char *key; char *section; @@ -45,10 +46,21 @@ int settings_get_int(const char *key); int settings_get_bool(const char *key); /* Functions to add/remove settings */ -void settings_add_str(const char *section, const char *key, const char *def); -void settings_add_int(const char *section, const char *key, int def); -void settings_add_bool(const char *section, const char *key, int def); +void settings_add_str_module(const char *module, const char *section, + const char *key, const char *def); +void settings_add_int_module(const char *module, const char *section, + const char *key, int def); +void settings_add_bool_module(const char *module, const char *section, + const char *key, int def); void settings_remove(const char *key); +void settings_remove_module(const char *module); + +#define settings_add_str(section, key, def) \ + settings_add_str_module(MODULE_NAME, section, key, def) +#define settings_add_int(section, key, def) \ + settings_add_int_module(MODULE_NAME, section, key, def) +#define settings_add_bool(section, key, def) \ + settings_add_bool_module(MODULE_NAME, section, key, def) /* Get the type (SETTING_TYPE_xxx) of `key' */ int settings_get_type(const char *key); |