diff src/plugins.c @ 425:ae7c762775cd

[gaim-migrate @ 435] More mods to how plugins work. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 23 Jun 2000 04:15:51 +0000
parents d6f02d7f78d8
children 11cbf8b403b6
line wrap: on
line diff
--- a/src/plugins.c	Wed Jun 21 19:43:05 2000 +0000
+++ b/src/plugins.c	Fri Jun 23 04:15:51 2000 +0000
@@ -61,7 +61,7 @@
 static GtkWidget *plugtext;
 static GtkWidget *plugwindow;
 
-static GtkWidget *config;
+static GtkWidget *config = NULL;
 static guint confighandle = 0;
 
 /* --------------- Function Declarations --------------------- */
@@ -71,6 +71,7 @@
 
        void gaim_signal_connect   (void *, enum gaim_event, void *, void *);
        void gaim_signal_disconnect(void *, enum gaim_event, void *);
+       void gaim_plugin_unload    (void *);
 
 static void destroy_plugins  (GtkWidget *, gpointer);
 static void load_file        (GtkWidget *, gpointer);
@@ -139,6 +140,7 @@
 
 void load_plugin(char *filename) {
 	struct gaim_plugin *plug;
+	GList *c = plugins;
 	int (*gaim_plugin_init)();
 	char *(*gaim_plugin_error)(int);
 	char *(*cfunc)();
@@ -147,6 +149,17 @@
 	char *plugin_error;
 
 	if (filename == NULL) return;
+	/* i shouldn't be checking based solely on path, but i'm lazy */
+	while (c) {
+		plug = (struct gaim_plugin *)c->data;
+		if (!strcmp(filename, plug->filename)) {
+			sprintf(debug_buff, _("Already loaded %s, "
+						"not reloading.\n"), filename);
+			debug_print(debug_buff);
+			return;
+		}
+		c = c->next;
+	}
 	plug = g_malloc(sizeof *plug);
 	if (filename[0] != '/') {
 		char *buf = g_malloc(BUF_LEN);
@@ -157,7 +170,7 @@
 		plug->filename = g_strdup(filename);
 	sprintf(debug_buff, "Loading %s\n", filename);
 	debug_print(debug_buff);
-	/* do NOT OR with RTLD_GLOBAL, otherwise plugins may conflict
+	/* 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);
@@ -345,7 +358,7 @@
 	GtkWidget *label;
 	GtkWidget *list_item;
 
-	if (pluglist == NULL) return;
+	if (plugwindow == NULL) return;
 
 	gtk_list_clear_items(GTK_LIST(pluglist), 0, -1);
 	while (plugs) {
@@ -376,20 +389,49 @@
 	struct gaim_plugin *p;
 	void (*gaim_plugin_remove)();
 	char *error;
-	GList *c = callbacks;
-	struct gaim_callback *g;
 
 	i = GTK_LIST(pluglist)->selection;
 
 	if (i == NULL) return;
 
 	p = gtk_object_get_user_data(GTK_OBJECT(i->data));
-	sprintf(debug_buff, "Unloading %s\n", p->filename);
-	debug_print(debug_buff);
 
 	gaim_plugin_remove = dlsym(p->handle, "gaim_plugin_remove");
 	if ((error = (char *)dlerror()) == NULL)
 		(*gaim_plugin_remove)();
+
+	gaim_plugin_unload(p->handle);
+}
+
+static void remove_callback(struct gaim_plugin *p) {
+	gtk_timeout_remove(p->remove);
+	dlclose(p->handle);
+	g_free(p);
+}
+
+/* gaim_plugin_unload serves 2 purposes: 1. so plugins can unload themselves
+ * 					 2. to make my life easier */
+void gaim_plugin_unload(void *handle) {
+	GList *i;
+	struct gaim_plugin *p = NULL;
+	GList *c = callbacks;
+	struct gaim_callback *g;
+
+	i = plugins;
+	while (i) {
+		p = (struct gaim_plugin *)i->data;
+		if (handle == p->handle)
+			break;
+		p = NULL;
+		i = i->next;
+	}
+
+	if (!p)
+		return;
+
+	sprintf(debug_buff, "Unloading %s\n", p->filename);
+	debug_print(debug_buff);
+
 	sprintf(debug_buff, "%d callbacks to search\n", g_list_length(callbacks));
 	debug_print(debug_buff);
 	while (c) {
@@ -408,12 +450,11 @@
 			c = c->next;
 		}
 	}
-	dlclose(p->handle);
+	p->remove = gtk_timeout_add(5000, (GtkFunction)remove_callback, p);
 
 	plugins = g_list_remove(plugins, p);
 	g_free(p->filename);
-	g_free(p);
-	gtk_widget_set_sensitive(config, 0);
+	if (config) gtk_widget_set_sensitive(config, 0);
 	update_show_plugins();
 	save_prefs();
 }
@@ -448,6 +489,7 @@
 	if (plugwindow)
 		gtk_widget_destroy(plugwindow);
 	plugwindow = NULL;
+	config = NULL;
 }
 
 void gaim_signal_connect(void *handle, enum gaim_event which,