diff plugins/perl/perl-handlers.c @ 12882:e1603fd610fa

[gaim-migrate @ 15234] I give you perl /cmd support. I only tested this a little bit but it seemed to work for me, let me know if anything breaks. committer: Tailor Script <tailor@pidgin.im>
author Etan Reisner <pidgin@unreliablesource.net>
date Sun, 15 Jan 2006 07:56:58 +0000
parents e65a7a7eabaf
children b457aa723bab
line wrap: on
line diff
--- a/plugins/perl/perl-handlers.c	Sun Jan 15 07:43:09 2006 +0000
+++ b/plugins/perl/perl-handlers.c	Sun Jan 15 07:56:58 2006 +0000
@@ -4,9 +4,10 @@
 #include "debug.h"
 #include "signals.h"
 
-static GList *timeout_handlers = NULL;
+extern PerlInterpreter *my_perl;
+static GList *cmd_handlers = NULL;
 static GList *signal_handlers = NULL;
-extern PerlInterpreter *my_perl;
+static GList *timeout_handlers = NULL;
 
 /* perl < 5.8.0 doesn't define PERL_MAGIC_ext */
 #ifndef PERL_MAGIC_ext
@@ -441,3 +442,149 @@
 	while (signal_handlers != NULL)
 		destroy_signal_handler(signal_handlers->data);
 }
+
+static GaimCmdRet
+perl_cmd_cb(GaimConversation *conv, const gchar *command,
+            gchar **args, gchar **error, void *data)
+{
+	int i = 0, count, ret_value = GAIM_CMD_RET_OK;
+	SV *cmdSV, *tmpSV, *convSV;
+	GaimPerlCmdHandler *handler = (GaimPerlCmdHandler *)data;
+
+	dSP;
+	ENTER;
+	SAVETMPS;
+	PUSHMARK(SP);
+
+	/* Push the conversation onto the perl stack */
+	convSV = sv_2mortal(gaim_perl_bless_object(conv, "Gaim::Conversation"));
+	XPUSHs(convSV);
+
+	/* Push the command string onto the perl stack */
+	cmdSV = newSVpv(command, 0);
+	cmdSV = sv_2mortal(cmdSV);
+	XPUSHs(cmdSV);
+
+	/* Push the data onto the perl stack */
+	XPUSHs((SV *)handler->data);
+
+	/* Push any arguments we may have */
+	for (i = 0; args[i] != NULL; i++) {
+		/* XXX The mortality of these created SV's should prevent
+		 * memory issues, if I read/understood everything correctly...
+		 */
+		tmpSV = newSVpv(args[i], 0);
+		tmpSV = sv_2mortal(tmpSV);
+		XPUSHs(tmpSV);
+	}
+
+	PUTBACK;
+	count = call_sv(handler->callback, G_EVAL|G_SCALAR);
+
+	if (count != 1)
+		croak("call_sv: Did not return the correct number of values.\n");
+
+	SPAGAIN;
+
+	ret_value = POPi;
+
+	PUTBACK;
+	FREETMPS;
+	LEAVE;
+
+	return ret_value;
+}
+
+GaimCmdId
+gaim_perl_cmd_register(GaimPlugin *plugin, const gchar *command,
+                       const gchar *args, GaimCmdPriority priority,
+                       GaimCmdFlag flag, const gchar *prpl_id, SV *callback,
+                       const gchar *helpstr, SV *data)
+{
+	GaimPerlCmdHandler *handler;
+
+	handler          = g_new0(GaimPerlCmdHandler, 1);
+	handler->plugin  = plugin;
+	handler->cmd     = g_strdup(command);
+	handler->prpl_id = g_strdup(prpl_id);
+
+	if (callback != NULL && callback != &PL_sv_undef)
+		handler->callback = newSVsv(callback);
+	else
+		handler->callback = NULL;
+
+	if (data != NULL && data != &PL_sv_undef)
+		handler->data = newSVsv(data);
+	else
+		handler->data = NULL;
+
+	cmd_handlers = g_list_append(cmd_handlers, handler);
+
+	handler->id = gaim_cmd_register(command, args, priority, flag, prpl_id,
+	                                GAIM_CMD_FUNC(perl_cmd_cb), helpstr,
+	                                handler);
+
+	return handler->id;
+}
+
+static void
+destroy_cmd_handler(GaimPerlCmdHandler *handler)
+{
+	cmd_handlers = g_list_remove(cmd_handlers, handler);
+
+	if (handler->callback != NULL)
+		SvREFCNT_dec(handler->callback);
+
+	if (handler->data != NULL)
+		SvREFCNT_dec(handler->data);
+
+	g_free(handler->cmd);
+	g_free(handler->prpl_id);
+	g_free(handler);
+}
+
+void
+gaim_perl_cmd_clear_for_plugin(GaimPlugin *plugin)
+{
+	GList *l, *l_next;
+
+	for (l = cmd_handlers; l != NULL; l = l_next) {
+		GaimPerlCmdHandler *handler = (GaimPerlCmdHandler *)l->data;
+
+		l_next = l->next;
+
+		if (handler->plugin == plugin)
+			destroy_cmd_handler(handler);
+	}
+}
+
+static GaimPerlCmdHandler *
+find_cmd_handler(GaimCmdId id)
+{
+	GList *l;
+
+	for (l = cmd_handlers; l != NULL; l = l->next) {
+		GaimPerlCmdHandler *handler = (GaimPerlCmdHandler *)l->data;
+
+		if (handler->id == id)
+			return handler;
+	}
+
+	return NULL;
+}
+
+void
+gaim_perl_cmd_unregister(GaimCmdId id)
+{
+	GaimPerlCmdHandler *handler;
+
+	handler = find_cmd_handler(id);
+
+	if (handler == NULL) {
+		croak("Invalid command id in removing a perl command handler.\n");
+		return;
+	}
+
+	gaim_cmd_unregister(id);
+	destroy_cmd_handler(handler);
+}