summaryrefslogtreecommitdiff
path: root/src/core/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/commands.c')
-rw-r--r--src/core/commands.c212
1 files changed, 193 insertions, 19 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)