--- a/ChangeLog.API Sun May 15 05:41:39 2016 -0300
+++ b/ChangeLog.API Sun May 15 18:53:55 2016 -0300
@@ -5,6 +5,8 @@
* account-status-changing signal (account signals)
* buddy-removed-from-group signal (blist signals)
+ * PurpleCommandsUiOps, to allow the UI to override the + built-in handling of commands. --- a/libpurple/cmds.c Sun May 15 05:41:39 2016 -0300
+++ b/libpurple/cmds.c Sun May 15 18:53:55 2016 -0300
@@ -27,10 +27,11 @@
+static PurpleCommandsUiOps *cmds_ui_ops = NULL; static GList *cmds = NULL;
static guint next_id = 1;
-typedef struct _PurpleCmd {
@@ -40,7 +41,7 @@
static gint cmds_compare_func(const PurpleCmd *a, const PurpleCmd *b)
@@ -59,6 +60,7 @@
+ PurpleCommandsUiOps *ops; g_return_val_if_fail(cmd != NULL && *cmd != '\0', 0);
g_return_val_if_fail(args != NULL, 0);
@@ -79,6 +81,10 @@
cmds = g_list_insert_sorted(cmds, c, (GCompareFunc)cmds_compare_func);
+ ops = purple_cmds_get_ui_ops(); + if (ops && ops->register_command) + ops->register_command(cmd, p, f, prpl_id, helpstr, c); purple_signal_emit(purple_cmds_get_handle(), "cmd-added", cmd, p, f);
@@ -102,6 +108,10 @@
+ PurpleCommandsUiOps *ops = purple_cmds_get_ui_ops(); + if (ops && ops->unregister_command) + ops->unregister_command(c->cmd, c->prpl_id); cmds = g_list_remove(cmds, c);
purple_signal_emit(purple_cmds_get_handle(), "cmd-removed", c->cmd);
@@ -301,6 +311,39 @@
+gboolean purple_cmd_execute(PurpleCmd *c, PurpleConversation *conv, + PurpleCmdRet ret = PURPLE_CMD_RET_CONTINUE; + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + if (!(c->flags & PURPLE_CMD_FLAG_IM)) + else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + if (!(c->flags & PURPLE_CMD_FLAG_CHAT)) + /* XXX: Don't worry much about the markup version of the command + line, there's not a single use case... */ + /* this checks the allow bad args flag for us */ + if (!purple_cmd_parse_args(c, cmdline, cmdline, &args)) { + ret = c->func(conv, c->cmd, args, &err, c->data); + return ret == PURPLE_CMD_RET_OK; GList *purple_cmd_list(PurpleConversation *conv)
@@ -368,6 +411,21 @@
+purple_cmds_set_ui_ops(PurpleCommandsUiOps *ops) +purple_cmds_get_ui_ops(void) + /* It is perfectly acceptable for cmds_ui_ops to be NULL; this just + * means that the default libpurple implementation will be used. void purple_cmds_init(void)
gpointer handle = purple_cmds_get_handle();
--- a/libpurple/cmds.h Sun May 15 05:41:39 2016 -0300
+++ b/libpurple/cmds.h Sun May 15 18:53:55 2016 -0300
@@ -31,6 +31,8 @@
/**************************************************************************/
+typedef struct _PurpleCmd PurpleCmd; /** The possible results of running a command with purple_cmd_do_command(). */
typedef enum _PurpleCmdStatus {
@@ -96,6 +98,31 @@
PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS = 0x08
+ * Command UI operations; UIs should implement this if they want to handle + * commands themselves, rather than relying on the core. + /** If implemented, the UI is responsible for handling commands. */ + /* @see purple_cmd_register for the argument values. */ + void (*register_command)(const gchar *name, PurpleCmdPriority p, + PurpleCmdFlag f, const gchar *prpl_id, + const gchar *helpstr, PurpleCmd *cmd); + /** Should be implemented if register_command is implemented. + * name and prpl_id should have the same value that were used + * for the register_command call. + void (*unregister_command)(const gchar *name, const gchar *prpl_id); + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); @@ -194,6 +221,23 @@
const gchar *markup, gchar **errormsg);
+ * Execute a specific command. + * The UI calls this to execute a command, after parsing the + * @param c The command to execute. + * @param conv The conversation the command was typed in. + * @param cmdline The command the user typed (only the arguments). + * The caller should remove the prefix and the command name. + * It should not contain any formatting, and should be + * in plain text (no html entities). + * @return TRUE if the command handled the cmdline, FALSE otherwise. +gboolean purple_cmd_execute(PurpleCmd *c, PurpleConversation *conv, * List registered commands.
* Returns a <tt>GList</tt> (which must be freed by the caller) of all commands
@@ -230,6 +274,23 @@
gpointer purple_cmds_get_handle(void);
+ * Sets the UI operations structure to be used when registering and + * unregistering commands. The UI operations need only be set if the + * UI wants to handle the commands itself; otherwise, leave it as NULL. + * @param ops The UI operations structure. +void purple_cmds_set_ui_ops(PurpleCommandsUiOps *ops); + * Returns the UI operations structure to be used when registering and + * unregistering commands. + * @return The UI operations structure. +PurpleCommandsUiOps *purple_cmds_get_ui_ops(void); * Initialize the commands subsystem.