changeset 90:f5b305c0d974

[gaim-migrate @ 100] Added plugin code. I have yet to test it. :P All I know is, I can successfully load a plugin. I don't know what I can do with it yet, and I'm not even sure I can unload it yet. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 07 Apr 2000 17:43:29 +0000
parents a382929aeb4f
children 308d0896d979
files plugins/Makefile plugins/simple.c src/Makefile.am src/buddy.c src/gaim.h src/plugins.c
diffstat 6 files changed, 270 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Makefile	Fri Apr 07 17:43:29 2000 +0000
@@ -0,0 +1,6 @@
+CC = gcc
+CFLAGS = -Wall
+LDFLAGS = -ggdb
+
+simple.so: simple.c
+	$(CC) $(CFLAGS) $(LDFLAGS) -shared -Wl,-soname,$@ -o $@ $<
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/simple.c	Fri Apr 07 17:43:29 2000 +0000
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+void gaim_plugin_init() {
+	printf("works.\n");
+}
+
+void gaim_plugin_remove() {
+	printf("works again.\n");
+}
--- a/src/Makefile.am	Fri Apr 07 07:51:14 2000 +0000
+++ b/src/Makefile.am	Fri Apr 07 17:43:29 2000 +0000
@@ -1,9 +1,9 @@
 if GNOMEAPPLET
 bin_PROGRAMS = gaim_applet
-gaim_applet_SOURCES = about.c aim.c away.c buddy.c buddy_chat.c conversation.c \
-	dialogs.c html.c prefs.c proxy.c toc.c sound.c gaim.h \
-	gnome_applet_mgr.c plugins.c network.c server.c \
-        browser.c util.c oscar.c gtkhtml.c idle.c gaimrc.c
+gaim_applet_SOURCES = about.c aim.c away.c browser.c buddy.c buddy_chat.c \
+	conversation.c dialogs.c gaimrc.c gnome_applet_mgr.c gtkhtml.c \
+	html.c idle.c network.c oscar.c plugins.c prefs.c proxy.c server.c \
+	sound.c toc.c util.c
 else
 bin_PROGRAMS = gaim
 gaim_SOURCES = about.c aim.c away.c buddy.c buddy_chat.c conversation.c \
--- a/src/buddy.c	Fri Apr 07 07:51:14 2000 +0000
+++ b/src/buddy.c	Fri Apr 07 17:43:29 2000 +0000
@@ -1632,7 +1632,6 @@
 	gtk_menu_append(GTK_MENU(findmenu), menuitem);
 	gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(show_find_info), NULL);
  	gtk_widget_show(menuitem);
-	
 
 	setmenu = gtk_menu_new();
 	gtk_widget_show(setmenu);
@@ -1648,18 +1647,22 @@
 	gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(show_set_dir), NULL);	
 	gtk_widget_show(menuitem);
 
-	/* Ok, this is the menu hookup for the plugin stuff */
-#ifdef GAIM_PLUGINS
-	gaim_seperator(menu);
-	
-	gaim_new_item(menu, "Plugins", GTK_SIGNAL_FUNC(show_plugins));
-#endif
-
-        /*---------------*/
-
 	gaim_seperator(menu);
 
         gaim_new_item(menu, "Preferences", GTK_SIGNAL_FUNC(show_prefs));
+
+#ifdef GAIM_PLUGINS
+	menu = gtk_menu_new();
+
+	menuitem = gaim_new_item(NULL, "Plugins", NULL);
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
+	gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
+
+	gaim_new_item(menu, "Load Plugin", GTK_SIGNAL_FUNC(load_plugin));
+	/* FIXME */
+	gaim_new_item(menu, "Remove Plugin", GTK_SIGNAL_FUNC(show_plugins));
+	gaim_new_item(menu, "Show Plugins", GTK_SIGNAL_FUNC(show_plugins));
+#endif
 	
 	menu = gtk_menu_new();
 
--- a/src/gaim.h	Fri Apr 07 07:51:14 2000 +0000
+++ b/src/gaim.h	Fri Apr 07 17:43:29 2000 +0000
@@ -64,7 +64,7 @@
 
 #define AUTO_RESPONSE "<AUTO-REPLY> : "
 
-#define PLUGIN_DIR "$HOME/.gaim/plugins/"
+#define PLUGIN_DIR ".gaim/plugins/"
 
 #define REG_EMAIL_ADDR "gaiminfo@blueridge.net"
 #define REG_SRVR "blueridge.net"
@@ -117,15 +117,14 @@
         char page[255];
 };
 
+#ifdef GAIM_PLUGINS
 struct gaim_plugin {
-        char name[64];
-        char filename[512];
-/*        char description[256];
-        int major_version;
-        int minor_version; */
-        char *(*init_gaim_plugin)();
-        void (*toc_receive)(char *);
+	char  *name;
+	char  *filename;
+	char  *description;
+	void  *handle;
 };
+#endif
 
 struct buddy {
 	char name[80];
@@ -269,7 +268,7 @@
 #define TYPE_SIGNOFF   4
 #define TYPE_KEEPALIVE 5
 
-#define REVISION "gaim:$Revision: 92 $"
+#define REVISION "gaim:$Revision: 100 $"
 #define FLAPON "FLAPON\r\n\r\n"
 
 #define ROAST "Tic/Toc"
@@ -541,7 +540,9 @@
 
 #ifdef GAIM_PLUGINS
 /* Functions in plugins.c */
-extern void load_plugins();
+extern void load_plugin  (GtkWidget *, gpointer);
+extern void unload_plugin(GtkWidget *, gpointer);
+extern void show_plugins (GtkWidget *, gpointer);
 #endif
 
 /* Functions in prefs.c */
@@ -556,9 +557,6 @@
 extern void save_prefs();
 
 
-/*Functions in plugins.c */
-extern void show_plugins();
-
 /* Functions in dialogs.c */
 extern void show_warn_dialog(char *);
 extern void do_error_dialog(char *, char *);
--- a/src/plugins.c	Fri Apr 07 07:51:14 2000 +0000
+++ b/src/plugins.c	Fri Apr 07 17:43:29 2000 +0000
@@ -23,8 +23,13 @@
  * Plugin support is currently being maintained by Mike Saraf
  * msaraf@dwc.edu
  *
+ * Well, I didn't see any work done on it for a while, so I'm going to try
+ * my hand at it. - Eric warmenhoven@yahoo.com
+ *
  */
 
+#ifdef GAIM_PLUGINS
+
 #include <string.h>
 #include <sys/time.h>
 
@@ -37,59 +42,245 @@
 #include <gtk/gtk.h>
 #include "gaim.h"
 
+#include <dlfcn.h>
+
 /* ------------------ Local Variables -------------------------*/
 
-static GtkWidget *plugins=NULL;
+static GtkWidget *plugin_dialog = NULL;
+static GList     *plugins = NULL;
+
+static GtkWidget *pluglist;
+static GtkWidget *plugtext;
 
 /* --------------- Function Declarations -------------------- */
 
-static void destroy_plugins();
-       void do_plugins(GtkWidget *, void *);
+       void load_plugin  (GtkWidget *, gpointer);
+       void unload_plugin(GtkWidget *, gpointer);
+       void show_plugins (GtkWidget *, gpointer);
+
+static void destroy_plugins  (GtkWidget *, gpointer);
+static void load_which_plugin(GtkWidget *, gpointer);
+static void unload           (GtkWidget *, gpointer);
+static void list_clicked     (GtkWidget *, struct gaim_plugin *);
+
 /* ------------------ Code Below ---------------------------- */
 
-void show_plugins()
+static void destroy_plugins(GtkWidget *w, gpointer data) {
+	if (plugin_dialog)
+		gtk_widget_destroy(plugin_dialog);
+	plugin_dialog = NULL;
+}
+
+void load_plugin(GtkWidget *w, gpointer data)
 {
- char *buf = g_malloc(BUF_LEN);
+	char *buf = g_malloc(BUF_LEN);
  
- if (!plugins) 
-    {
-     plugins = gtk_file_selection_new("Gaim - Plugin List");
+	if (!plugin_dialog) {
+		plugin_dialog = gtk_file_selection_new("Gaim - Plugin List");
+
+		gtk_file_selection_hide_fileop_buttons(
+					GTK_FILE_SELECTION(plugin_dialog));
+
+	if(getenv("PLUGIN_DIR") == NULL) {
+		g_snprintf(buf, BUF_LEN - 1, "%s/%s", getenv("HOME"), PLUGIN_DIR);
+	} else {
+		g_snprintf(buf, BUF_LEN - 1, "%s/", getenv("PLUGIN_DIR"));
+	}
 
-     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(plugins));
+	gtk_file_selection_set_filename(GTK_FILE_SELECTION(plugin_dialog), buf);
+	gtk_signal_connect(GTK_OBJECT(plugin_dialog), "destroy",
+			GTK_SIGNAL_FUNC(destroy_plugins), plugin_dialog);
+
+	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugin_dialog)->ok_button),
+			"clicked", GTK_SIGNAL_FUNC(load_which_plugin), NULL);
+    
+	gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugin_dialog)->cancel_button),
+			"clicked", GTK_SIGNAL_FUNC(destroy_plugins), NULL);
+
+	}
+
+	g_free(buf);
+	gtk_widget_show(plugin_dialog);
+	gdk_window_raise(plugin_dialog->window);   
+}
 
-     if(getenv("PLUGIN_DIR") == NULL)
-        {
-         g_snprintf(buf, BUF_LEN - 1, "%s/", getenv("HOME"));
-        }
-     else
-        {
-         g_snprintf(buf, BUF_LEN - 1, "%s/", getenv("PLUGIN_DIR"));
-        }
+void load_which_plugin(GtkWidget *w, gpointer data) {
+	struct gaim_plugin *plug;
+	void (*gaim_plugin_init)();
+	char *(*cfunc)();
+	int (*nfunc)();
+	char *error;
+
+	plug = g_malloc(sizeof *plug);
+	plug->filename = gtk_file_selection_get_filename(
+					GTK_FILE_SELECTION(plugin_dialog));
+	/* do NOT OR with RTLD_GLOBAL, otherwise plugins may conflict
+	 * (it's really just a way to work around other people's bad
+	 * programming, by not using RTLD_GLOBAL :P ) */
+	plug->handle = dlopen(plug->filename, RTLD_LAZY);
+	if (!plug->handle) {
+		error = dlerror();
+		do_error_dialog(error, "Plugin Error");
+		g_free(plug);
+		return;
+	}
+
+	if (plugin_dialog)
+		gtk_widget_destroy(plugin_dialog);
+	plugin_dialog = NULL;
 
-     gtk_file_selection_set_filename(GTK_FILE_SELECTION(plugins), buf);
-     gtk_signal_connect(GTK_OBJECT(plugins), "destroy",
-                        GTK_SIGNAL_FUNC(destroy_plugins), plugins);
+	gaim_plugin_init = dlsym(plug->handle, "gaim_plugin_init");
+	if ((error = dlerror()) != NULL) {
+		do_error_dialog(error, "Plugin Error");
+		dlclose(plug->handle);
+		g_free(plug);
+		return;
+	}
+
+	plugins = g_list_append(plugins, plug);
+	(*gaim_plugin_init)();
 
-    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugins)->ok_button),
-                       "clicked", GTK_SIGNAL_FUNC(do_plugins), NULL);
-    
-    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugins)->cancel_button),
-                       "clicked", GTK_SIGNAL_FUNC(destroy_plugins),plugins );
+	cfunc = dlsym(plug->handle, "name");
+	if ((error = dlerror()) == NULL)
+		plug->name = (*cfunc)();
+	else
+		plug->name = NULL;
 
-   }
+	cfunc = dlsym(plug->handle, "description");
+	if ((error = dlerror()) == NULL)
+		plug->description = (*cfunc)();
+	else
+		plug->description = NULL;
+}
 
- gtk_widget_show(plugins);
- gdk_window_raise(plugins->window);   
+void unload_plugin(GtkWidget *w, gpointer data) {
+	/* FIXME */
 }
 
-void do_plugins(GtkWidget *w, void *dummy)
-{
+void show_plugins(GtkWidget *w, gpointer data) {
+	/* most of this code was shamelessly stolen from prefs.c */
+	GtkWidget *window;
+	GtkWidget *page;
+	GtkWidget *topbox;
+	GtkWidget *botbox;
+	GtkWidget *sw;
+	GtkWidget *label;
+	GtkWidget *list_item;
+	GtkWidget *sw2;
+	GtkWidget *add;
+	GtkWidget *remove;
+	GList     *plugs = plugins;
+	struct gaim_plugin *p;
+	gchar buffer[1024];
+
+	window = gtk_window_new(GTK_WINDOW_DIALOG);
+	gtk_widget_realize(window);
+	aol_icon(window->window);
+	gtk_container_border_width(GTK_CONTAINER(window), 10);
+	gtk_window_set_title(GTK_WINDOW(window), "Gaim - Plugins");
+
+	page = gtk_vbox_new(FALSE, 0);
+	topbox = gtk_hbox_new(FALSE, 0);
+	botbox = gtk_hbox_new(FALSE, 0);
+
+	sw2 = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2),
+				       GTK_POLICY_AUTOMATIC,
+				       GTK_POLICY_AUTOMATIC);
+
+	pluglist = gtk_list_new();
+	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), pluglist);
+	gtk_box_pack_start(GTK_BOX(topbox), sw2, TRUE, TRUE, 0);
+
+	sw = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
+				       GTK_POLICY_AUTOMATIC,
+				       GTK_POLICY_AUTOMATIC);
+
+	plugtext = gtk_text_new(NULL, NULL);
+	gtk_container_add(GTK_CONTAINER(sw), plugtext);
+	gtk_box_pack_start(GTK_BOX(topbox), sw, TRUE, TRUE, 0);
+	gtk_text_set_word_wrap(GTK_TEXT(plugtext), TRUE);
+	gtk_text_set_editable(GTK_TEXT(plugtext), FALSE);
+
+	add = gtk_button_new_with_label("Load Plugin");
+	gtk_signal_connect(GTK_OBJECT(add), "clicked",
+			   GTK_SIGNAL_FUNC(load_plugin), NULL);
+	gtk_box_pack_start(GTK_BOX(botbox), add, TRUE, FALSE, 5);
+
+	remove = gtk_button_new_with_label("Unload Plugin");
+	gtk_signal_connect(GTK_OBJECT(remove), "clicked",
+			   GTK_SIGNAL_FUNC(unload), pluglist);
+	gtk_box_pack_start(GTK_BOX(botbox), remove, TRUE, FALSE, 5);
+
+	gtk_box_pack_start(GTK_BOX(page), topbox, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(page), botbox, FALSE, FALSE, 0);
+
+	if (plugs != NULL) {
+		p = (struct gaim_plugin *)plugs->data;
+		g_snprintf(buffer, sizeof(buffer), "%s", p->filename);
+		gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, buffer, -1);
+	}
+
+	while (plugs) {
+		p = (struct gaim_plugin *)plugs->data;
+		label = gtk_label_new(p->filename);
+		list_item = gtk_list_item_new();
+		gtk_container_add(GTK_CONTAINER(list_item), label);
+		gtk_signal_connect(GTK_OBJECT(list_item), "select",
+				   GTK_SIGNAL_FUNC(list_clicked), p);
+		gtk_object_set_user_data(GTK_OBJECT(list_item), p);
+
+		gtk_widget_show(label);
+		gtk_container_add(GTK_CONTAINER(pluglist), list_item);
+		gtk_widget_show(list_item);
+
+		plugs = plugs->next;
+	}
+
+	gtk_widget_show(page);
+	gtk_widget_show(topbox);
+	gtk_widget_show(botbox);
+	gtk_widget_show(sw);
+	gtk_widget_show(sw2);
+	gtk_widget_show(pluglist);
+	gtk_widget_show(plugtext);
+	gtk_widget_show(add);
+	gtk_widget_show(remove);
+
+	gtk_container_add(GTK_CONTAINER(window), page);
+	gtk_widget_show(window);
 }
 
-static void destroy_plugins()
-{
- if (plugins)
-    gtk_widget_destroy(plugins);
+void unload(GtkWidget *w, gpointer data) {
+	GList *i;
+	struct gaim_plugin *p;
+	void (*gaim_plugin_remove)();
+	char *error;
+
+	i = GTK_LIST(pluglist)->selection;
+
+	p = gtk_object_get_user_data(GTK_OBJECT(i->data));
+
+	g_list_remove(plugins, p);
 
- plugins = NULL;
-}                  
+	gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove");
+	if ((error = dlerror()) == NULL)
+		(*gaim_plugin_remove)();
+	dlclose(p->handle);
+	g_free(p);
+}
+
+void list_clicked(GtkWidget *w, struct gaim_plugin *p) {
+	gchar buffer[2048];
+	guint text_len;
+
+	text_len = gtk_text_get_length(GTK_TEXT(plugtext));
+	gtk_text_set_point(GTK_TEXT(plugtext), 0);
+	gtk_text_forward_delete(GTK_TEXT(plugtext), text_len);
+
+	g_snprintf(buffer, sizeof buffer, "%s\n%s", p->name, p->description);
+	gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, buffer, -1);
+}
+
+#endif /* GAIM_PLUGINS */