about summary refs log tree commit diff stats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/api.c14
-rw-r--r--src/plugins/api.h8
-rw-r--r--src/plugins/c_api.c14
-rw-r--r--src/plugins/callbacks.c125
-rw-r--r--src/plugins/callbacks.h6
-rw-r--r--src/plugins/python_api.c26
6 files changed, 152 insertions, 41 deletions
diff --git a/src/plugins/api.c b/src/plugins/api.c
index ea134fe4..2a577296 100644
--- a/src/plugins/api.c
+++ b/src/plugins/api.c
@@ -107,18 +107,21 @@ api_cons_bad_cmd_usage(const char *const cmd)
 
 void
 api_register_command(const char *const plugin_name, const char *command_name, int min_args, int max_args,
-    const char **synopsis, const char *description, const char *arguments[][2], const char **examples, void *callback,
-    void(*callback_exec)(PluginCommand *command, gchar **args))
+    const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
+    void *callback, void(*callback_exec)(PluginCommand *command, gchar **args), void(*callback_destroy)(void *callback))
 {
     PluginCommand *command = malloc(sizeof(PluginCommand));
-    command->command_name = command_name;
+    command->command_name = strdup(command_name);
     command->min_args = min_args;
     command->max_args = max_args;
     command->callback = callback;
     command->callback_exec = callback_exec;
+    command->callback_destroy = callback_destroy;
 
     CommandHelp *help = malloc(sizeof(CommandHelp));
 
+    help->tags[0] = NULL;
+
     int i = 0;
     for (i = 0; synopsis[i] != NULL; i++) {
         help->synopsis[i] = strdup(synopsis[i]);
@@ -140,16 +143,17 @@ api_register_command(const char *const plugin_name, const char *command_name, in
 
     command->help = help;
 
-    callbacks_add_command(command);
+    callbacks_add_command(plugin_name, command);
 }
 
 void
 api_register_timed(const char *const plugin_name, void *callback, int interval_seconds,
-    void (*callback_exec)(PluginTimedFunction *timed_function))
+    void (*callback_exec)(PluginTimedFunction *timed_function), void(*callback_destroy)(void *callback))
 {
     PluginTimedFunction *timed_function = malloc(sizeof(PluginTimedFunction));
     timed_function->callback = callback;
     timed_function->callback_exec = callback_exec;
+    timed_function->callback_destroy = callback_destroy;
     timed_function->interval_seconds = interval_seconds;
     timed_function->timer = g_timer_new();
 
diff --git a/src/plugins/api.h b/src/plugins/api.h
index 571c6168..0b1aec32 100644
--- a/src/plugins/api.h
+++ b/src/plugins/api.h
@@ -52,9 +52,9 @@ char** api_get_current_occupants(void);
 
 void api_register_command(const char *const plugin_name, const char *command_name, int min_args, int max_args,
     const char **synopsis, const char *description, const char *arguments[][2], const char **examples,
-    void *callback, void(*callback_func)(PluginCommand *command, gchar **args));
+    void *callback, void(*callback_func)(PluginCommand *command, gchar **args), void(*callback_destroy)(void *callback));
 void api_register_timed(const char *const plugin_name, void *callback, int interval_seconds,
-    void (*callback_func)(PluginTimedFunction *timed_function));
+    void (*callback_func)(PluginTimedFunction *timed_function), void(*callback_destroy)(void *callback));
 
 void api_completer_add(const char *const plugin_name, const char *key, char **items);
 void api_completer_remove(const char *key, char **items);
@@ -70,8 +70,8 @@ void api_win_create(
     const char *const plugin_name,
     const char *tag,
     void *callback,
-    void(*destroy)(void *callback),
-    void(*callback_func)(PluginWindowCallback *window_callback, char *tag, char *line));
+    void(*callback_func)(PluginWindowCallback *window_callback, char *tag, char *line),
+    void(*destroy)(void *callback));
 int api_win_focus(const char *tag);
 int api_win_show(const char *tag, const char *line);
 int api_win_show_themed(const char *tag, const char *const group, const char *const key, const char *const def, const char *line);
diff --git a/src/plugins/c_api.c b/src/plugins/c_api.c
index 96673972..32719feb 100644
--- a/src/plugins/c_api.c
+++ b/src/plugins/c_api.c
@@ -90,7 +90,9 @@ c_api_register_command(const char *filename, const char *command_name, int min_a
     CommandWrapper *wrapper = malloc(sizeof(CommandWrapper));
     wrapper->func = callback;
     api_register_command(plugin_name, command_name, min_args, max_args, synopsis,
-        description, arguments, examples, wrapper, c_command_callback);
+        description, arguments, examples, wrapper, c_command_callback, free);
+
+    free(plugin_name);
 }
 
 static void
@@ -101,7 +103,9 @@ c_api_register_timed(const char *filename, void(*callback)(void), int interval_s
 
     TimedWrapper *wrapper = malloc(sizeof(TimedWrapper));
     wrapper->func = callback;
-    api_register_timed(plugin_name, wrapper, interval_seconds, c_timed_callback);
+    api_register_timed(plugin_name, wrapper, interval_seconds, c_timed_callback, free);
+
+    free(plugin_name);
 }
 
 static void
@@ -111,6 +115,8 @@ c_api_completer_add(const char *filename, const char *key, char **items)
     log_debug("Autocomplete add %s for %s", key, plugin_name);
 
     api_completer_add(plugin_name, key, items);
+
+    free(plugin_name);
 }
 
 static void
@@ -205,7 +211,9 @@ c_api_win_create(const char *filename, char *tag, void(*callback)(char *tag, cha
 
     WindowWrapper *wrapper = malloc(sizeof(WindowWrapper));
     wrapper->func = callback;
-    api_win_create(plugin_name, tag, wrapper, free, c_window_callback);
+    api_win_create(plugin_name, tag, wrapper, c_window_callback, free);
+
+    free(plugin_name);
 }
 
 static int
diff --git a/src/plugins/callbacks.c b/src/plugins/callbacks.c
index 57a8c09d..2569962c 100644
--- a/src/plugins/callbacks.c
+++ b/src/plugins/callbacks.c
@@ -44,7 +44,7 @@
 
 #include "ui/ui.h"
 
-static GSList *p_commands = NULL;
+static GHashTable *p_commands = NULL;
 static GSList *p_timed_functions = NULL;
 static GHashTable *p_window_callbacks = NULL;
 
@@ -57,22 +57,88 @@ _free_window_callback(PluginWindowCallback *window_callback)
     free(window_callback);
 }
 
+//typedef struct cmd_help_t {
+//    const gchar *tags[20];
+//    const gchar *synopsis[50];
+//    const gchar *desc;
+//    const gchar *args[128][2];
+//    const gchar *examples[20];
+//} CommandHelp;
+
+static void
+_free_command_help(CommandHelp *help)
+{
+    int i = 0;
+    while (help->tags[i] != NULL) {
+        free(help->tags[i++]);
+    }
+
+    i = 0;
+    while (help->synopsis[i] != NULL) {
+        free(help->synopsis[i++]);
+    }
+
+    free(help->desc);
+
+    i = 0;
+    while (help->args[i] != NULL && help->args[i][0] != NULL) {
+        free(help->args[i][0]);
+        free(help->args[i][1]);
+        i++;
+    }
+
+    i = 0;
+    while (help->examples[i] != NULL) {
+        free(help->examples[i++]);
+    }
+
+    free(help);
+}
+
+static void
+_free_command(PluginCommand *command)
+{
+    if (command->callback_destroy) {
+        command->callback_destroy(command->callback);
+    }
+    free(command->command_name);
+
+    _free_command_help(command->help);
+    free(command);
+}
+
+static void
+_free_command_hash(GHashTable *command_hash)
+{
+    g_hash_table_destroy(command_hash);
+}
+
 void
 callbacks_init(void)
 {
+    p_commands = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_free_command_hash);
     p_window_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_free_window_callback);
 }
 
+// TODO move to plugin destroy functions
 void
 callbacks_close(void)
 {
+    g_hash_table_destroy(p_commands);
     g_hash_table_destroy(p_window_callbacks);
 }
 
 void
-callbacks_add_command(PluginCommand *command)
+callbacks_add_command(const char *const plugin_name, PluginCommand *command)
 {
-    p_commands = g_slist_append(p_commands, command);
+    GHashTable *command_hash = g_hash_table_lookup(p_commands, plugin_name);
+    if (command_hash) {
+        g_hash_table_insert(command_hash, strdup(command->command_name), command);
+    } else {
+        command_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_free_command);
+        g_hash_table_insert(command_hash, strdup(command->command_name), command);
+        g_hash_table_insert(p_commands, strdup(plugin_name), command_hash);
+    }
     cmd_ac_add(command->command_name);
     cmd_ac_add_help(&command->command_name[1]);
 }
@@ -104,25 +170,32 @@ plugins_run_command(const char * const input)
 {
     gchar **split = g_strsplit(input, " ", -1);
 
-    GSList *p_command = p_commands;
-    while (p_command) {
-        PluginCommand *command = p_command->data;
-        if (g_strcmp0(split[0], command->command_name) == 0) {
+    GList *command_hashes = g_hash_table_get_values(p_commands);
+    GList *curr_hash = command_hashes;
+    while (curr_hash) {
+        GHashTable *command_hash = curr_hash->data;
+
+        PluginCommand *command = g_hash_table_lookup(command_hash, split[0]);
+        if (command) {
             gboolean result;
             gchar **args = parse_args_with_freetext(input, command->min_args, command->max_args, &result);
             if (result == FALSE) {
                 ui_invalid_command_usage(command->command_name, NULL);
                 g_strfreev(split);
+                g_list_free(command_hashes);
                 return TRUE;
             } else {
                 command->callback_exec(command, args);
                 g_strfreev(split);
                 g_strfreev(args);
+                g_list_free(command_hashes);
                 return TRUE;
             }
         }
-        p_command = g_slist_next(p_command);
+
+        curr_hash = g_list_next(curr_hash);
     }
+
     g_strfreev(split);
     return FALSE;
 }
@@ -130,16 +203,22 @@ plugins_run_command(const char * const input)
 CommandHelp*
 plugins_get_help(const char *const cmd)
 {
-    GSList *curr = p_commands;
-    while (curr) {
-        PluginCommand *command = curr->data;
-        if (g_strcmp0(cmd, command->command_name) == 0) {
+    GList *command_hashes = g_hash_table_get_values(p_commands);
+    GList *curr_hash = command_hashes;
+    while (curr_hash) {
+        GHashTable *command_hash = curr_hash->data;
+
+        PluginCommand *command = g_hash_table_lookup(command_hash, cmd);
+        if (command) {
+            g_list_free(command_hashes);
             return command->help;
         }
 
-        curr = g_slist_next(curr);
+        curr_hash = g_list_next(curr_hash);
     }
 
+    g_list_free(command_hashes);
+
     return NULL;
 }
 
@@ -167,12 +246,22 @@ plugins_get_command_names(void)
 {
     GList *result = NULL;
 
-    GSList *curr = p_commands;
-    while (curr) {
-        PluginCommand *command = curr->data;
-        result = g_list_append(result, (char*)command->command_name);
-        curr = g_slist_next(curr);
+    GList *command_hashes = g_hash_table_get_values(p_commands);
+    GList *curr_hash = command_hashes;
+    while (curr_hash) {
+        GHashTable *command_hash = curr_hash->data;
+        GList *commands = g_hash_table_get_keys(command_hash);
+        GList *curr = commands;
+        while (curr) {
+            char *command = curr->data;
+            result = g_list_append(result, command);
+            curr = g_list_next(curr);
+        }
+        g_list_free(commands);
+        curr_hash = g_list_next(curr_hash);
     }
 
+    g_list_free(command_hashes);
+
     return result;
 }
diff --git a/src/plugins/callbacks.h b/src/plugins/callbacks.h
index 0ef6de9f..fa78d2c6 100644
--- a/src/plugins/callbacks.h
+++ b/src/plugins/callbacks.h
@@ -40,17 +40,19 @@
 #include "command/cmd_defs.h"
 
 typedef struct p_command {
-    const char *command_name;
+    char *command_name;
     int min_args;
     int max_args;
     CommandHelp *help;
     void *callback;
     void (*callback_exec)(struct p_command *command, gchar **args);
+    void (*callback_destroy)(void *callback);
 } PluginCommand;
 
 typedef struct p_timed_function {
     void *callback;
     void (*callback_exec)(struct p_timed_function *timed_function);
+    void (*callback_destroy)(void *callback);
     int interval_seconds;
     GTimer *timer;
 } PluginTimedFunction;
@@ -64,7 +66,7 @@ typedef struct p_window_input_callback {
 void callbacks_init(void);
 void callbacks_close(void);
 
-void callbacks_add_command(PluginCommand *command);
+void callbacks_add_command(const char *const plugin, PluginCommand *command);
 void callbacks_add_timed(PluginTimedFunction *timed_function);
 void callbacks_add_window_handler(const char *tag, PluginWindowCallback *window_callback);
 void * callbacks_get_window_handler(const char *tag);
diff --git a/src/plugins/python_api.c b/src/plugins/python_api.c
index 1a60a07c..82cf22eb 100644
--- a/src/plugins/python_api.c
+++ b/src/plugins/python_api.c
@@ -166,19 +166,18 @@ python_api_register_command(PyObject *self, PyObject *args)
 
         allow_python_threads();
         api_register_command(plugin_name, command_name, min_args, max_args, c_synopsis,
-            description, c_arguments, c_examples, p_callback, python_command_callback);
+            description, c_arguments, c_examples, p_callback, python_command_callback, NULL);
         disable_python_threads();
     }
 
+    free(plugin_name);
+
     return Py_BuildValue("");
 }
 
 static PyObject *
 python_api_register_timed(PyObject *self, PyObject *args)
 {
-    char *plugin_name = _python_plugin_name();
-    log_debug("Register timed for %s", plugin_name);
-
     PyObject *p_callback = NULL;
     int interval_seconds = 0;
 
@@ -186,12 +185,17 @@ python_api_register_timed(PyObject *self, PyObject *args)
         return Py_BuildValue("");
     }
 
+    char *plugin_name = _python_plugin_name();
+    log_debug("Register timed for %s", plugin_name);
+
     if (p_callback && PyCallable_Check(p_callback)) {
         allow_python_threads();
-        api_register_timed(plugin_name, p_callback, interval_seconds, python_timed_callback);
+        api_register_timed(plugin_name, p_callback, interval_seconds, python_timed_callback, NULL);
         disable_python_threads();
     }
 
+    free(plugin_name);
+
     return Py_BuildValue("");
 }
 
@@ -223,6 +227,8 @@ python_api_completer_add(PyObject *self, PyObject *args)
     api_completer_add(plugin_name, key, c_items);
     disable_python_threads();
 
+    free(plugin_name);
+
     return Py_BuildValue("");
 }
 
@@ -456,19 +462,21 @@ python_api_win_create(PyObject *self, PyObject *args)
     char *tag = NULL;
     PyObject *p_callback = NULL;
 
-    char *plugin_name = _python_plugin_name();
-    log_debug("Win create %s for %s", tag, plugin_name);
-
     if (!PyArg_ParseTuple(args, "sO", &tag, &p_callback)) {
         return Py_BuildValue("");
     }
 
+    char *plugin_name = _python_plugin_name();
+    log_debug("Win create %s for %s", tag, plugin_name);
+
     if (p_callback && PyCallable_Check(p_callback)) {
         allow_python_threads();
-        api_win_create(plugin_name, tag, p_callback, NULL, python_window_callback);
+        api_win_create(plugin_name, tag, p_callback, python_window_callback, NULL);
         disable_python_threads();
     }
 
+    free(plugin_name);
+
     return Py_BuildValue("");
 }