gedit r6462 - branches/new_plugins/gedit



Author: jessevdk
Date: Wed Aug 27 09:06:26 2008
New Revision: 6462
URL: http://svn.gnome.org/viewvc/gedit?rev=6462&view=rev

Log:
Factored loading plugins in GeditPluginLoader
Cleaned up some stuff in the plugins engine
Changed gedit_message_bus_get to gedit_message_bus_get_default


Added:
   branches/new_plugins/gedit/gedit-object-module.c
   branches/new_plugins/gedit/gedit-object-module.h
   branches/new_plugins/gedit/gedit-plugin-loader-c.c
   branches/new_plugins/gedit/gedit-plugin-loader-c.h
   branches/new_plugins/gedit/gedit-plugin-loader.c
   branches/new_plugins/gedit/gedit-plugin-loader.h
Removed:
   branches/new_plugins/gedit/gedit-module.c
   branches/new_plugins/gedit/gedit-module.h
Modified:
   branches/new_plugins/gedit/Makefile.am
   branches/new_plugins/gedit/gedit-message-bus.c
   branches/new_plugins/gedit/gedit-message-bus.h
   branches/new_plugins/gedit/gedit-plugin-info-priv.h
   branches/new_plugins/gedit/gedit-plugin-info.c
   branches/new_plugins/gedit/gedit-plugin-info.h
   branches/new_plugins/gedit/gedit-plugin.h
   branches/new_plugins/gedit/gedit-plugins-engine.c

Modified: branches/new_plugins/gedit/Makefile.am
==============================================================================
--- branches/new_plugins/gedit/Makefile.am	(original)
+++ branches/new_plugins/gedit/Makefile.am	Wed Aug 27 09:06:26 2008
@@ -5,18 +5,19 @@
 
 noinst_LTLIBRARIES = libgedit.la
 
-INCLUDES =							\
-	-I$(top_srcdir)						\
-	-I$(srcdir)						\
-	-I$(srcdir)/smclient					\
-	$(GEDIT_CFLAGS)						\
-	$(WARN_CFLAGS)						\
-	$(DISABLE_DEPRECATED_CFLAGS)				\
-	-DDATADIR=\""$(datadir)"\"				\
-	-DGEDIT_DATADIR=\""$(datadir)/gedit-2"\"		\
-	-DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\"	\
-	-DGEDIT_UIDIR=\""$(datadir)/gedit-2/ui/"\"		\
-	-DGEDIT_PLUGINDIR=\""$(libdir)/gedit-2/plugins"\"	\
+INCLUDES =								\
+	-I$(top_srcdir)							\
+	-I$(srcdir)							\
+	-I$(srcdir)/smclient						\
+	$(GEDIT_CFLAGS)							\
+	$(WARN_CFLAGS)							\
+	$(DISABLE_DEPRECATED_CFLAGS)					\
+	-DDATADIR=\""$(datadir)"\"					\
+	-DGEDIT_DATADIR=\""$(datadir)/gedit-2"\"			\
+	-DGEDIT_LOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\"		\
+	-DGEDIT_UIDIR=\""$(datadir)/gedit-2/ui/"\"			\
+	-DGEDIT_PLUGINDIR=\""$(libdir)/gedit-2/plugins"\"		\
+	-DGEDIT_LOADERDIR=\""$(libdir)/gedit-2/plugin-loaders"\"	\
 	-DGEDIT_ICONDIR=\""$(datadir)/gedit-2/icons"\"
 
 if ENABLE_PYTHON
@@ -58,7 +59,7 @@
 	gedit-plugin-info-priv.h	\
 	gedit-plugin-manager.h		\
 	gedit-plugins-engine.h		\
-	gedit-module.h			\
+	gedit-object-module.h		\
 	gedit-ui.h			\
 	gedit-window-private.h		\
 	gedit-documents-panel.h		\
@@ -69,6 +70,7 @@
 	gedit-local-document-saver.h	\
 	gedit-gio-document-saver.h	\
 	gedit-history-entry.h		\
+	gedit-plugin-loader-c.h		\
 	gedit-print-job.h		\
 	gedit-print-preview.h		\
 	gedit-io-error-message-area.h	\
@@ -78,11 +80,11 @@
 	gedittextregion.h		\
 	gedit-session.h
 
-if ENABLE_PYTHON
-NOINST_H_FILES += \
-	gedit-python-module.h		\
-	gedit-python-plugin.h 
-endif
+# if ENABLE_PYTHON
+# NOINST_H_FILES += \
+#	gedit-python-module.h		\
+#	gedit-python-plugin.h 
+# endif
 
 INST_H_FILES =				\
 	gedit-app.h			\
@@ -100,6 +102,7 @@
 	gedit-notebook.h		\
 	gedit-panel.h			\
 	gedit-plugin.h			\
+	gedit-plugin-loader.h		\
 	gedit-prefs-manager-app.h	\
 	gedit-prefs-manager.h		\
 	gedit-progress-message-area.h	\
@@ -146,11 +149,13 @@
 	gedit-message-bus.c		\
 	gedit-message-area.c		\
 	gedit-metadata-manager.c	\
-	gedit-module.c			\
+	gedit-object-module.c		\
 	gedit-notebook.c		\
 	gedit-panel.c			\
 	gedit-plugin-info.c		\
 	gedit-plugin.c			\
+	gedit-plugin-loader.c		\
+	gedit-plugin-loader-c.c		\
 	gedit-plugin-manager.c		\
 	gedit-plugins-engine.c		\
 	gedit-prefs-manager-app.c	\
@@ -173,13 +178,13 @@
 	$(INST_H_FILES)
 
 
-if ENABLE_PYTHON
-libgedit_la_SOURCES += \
-	gedit-python-module.c		\
-	gedit-python-module.h		\
-	gedit-python-plugin.c		\
-	gedit-python-plugin.h	
-endif
+# if ENABLE_PYTHON
+# libgedit_la_SOURCES += \
+#	gedit-python-module.c		\
+#	gedit-python-module.h		\
+#	gedit-python-plugin.c		\
+#	gedit-python-plugin.h	
+# endif
 
 gedit-enum-types.h: gedit-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
 	(cd $(srcdir) && $(GLIB_MKENUMS) --template gedit-enum-types.h.template $(INST_H_FILES)) > $@

Modified: branches/new_plugins/gedit/gedit-message-bus.c
==============================================================================
--- branches/new_plugins/gedit/gedit-message-bus.c	(original)
+++ branches/new_plugins/gedit/gedit-message-bus.c	Wed Aug 27 09:06:26 2008
@@ -343,14 +343,18 @@
 }
 
 GeditMessageBus *
-gedit_message_bus_get (void)
+gedit_message_bus_get_default (void)
 {
-	static GeditMessageBus *bus = NULL;
+	static GeditMessageBus *default_bus = NULL;
 	
-	if (G_UNLIKELY (!bus))
-		bus = g_object_new (GEDIT_TYPE_MESSAGE_BUS, NULL);
+	if (G_UNLIKELY (default_bus == NULL))
+	{
+		default_bus = g_object_new (GEDIT_TYPE_MESSAGE_BUS, NULL);
+		g_object_add_weak_pointer (G_OBJECT (default_bus),
+				           (gpointer) &default_bus);
+	}
 	
-	return bus;
+	return default_bus;
 }
 
 guint

Modified: branches/new_plugins/gedit/gedit-message-bus.h
==============================================================================
--- branches/new_plugins/gedit/gedit-message-bus.h	(original)
+++ branches/new_plugins/gedit/gedit-message-bus.h	Wed Aug 27 09:06:26 2008
@@ -34,7 +34,7 @@
 
 GType gedit_message_bus_get_type (void) G_GNUC_CONST;
 
-GeditMessageBus *gedit_message_bus_get 	  (void);
+GeditMessageBus *gedit_message_bus_get_default 	  (void);
 guint gedit_message_bus_connect	 	  (GeditMessageBus	*bus, 
 					   const gchar		*domain,
 					   const gchar		*name,

Added: branches/new_plugins/gedit/gedit-object-module.c
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-object-module.c	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,315 @@
+/*
+ * gedit-object-module.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, 
+ * Boston, MA 02111-1307, USA. 
+ */
+ 
+/* This is a modified version of ephy-module.c from Epiphany source code.
+ * Here the original copyright assignment:
+ *
+ *  Copyright (C) 2003 Marco Pesenti Gritti
+ *  Copyright (C) 2003, 2004 Christian Persch
+ *
+ */
+
+/*
+ * Modified by the gedit Team, 2005. See the AUTHORS file for a 
+ * list of people on the gedit Team.  
+ * See the ChangeLog files for a list of changes. 
+ *
+ * $Id: gedit-module.c 6314 2008-06-05 12:57:53Z pborelli $
+ */
+
+#include "config.h"
+
+#include "gedit-object-module.h"
+#include "gedit-debug.h"
+
+typedef GType (*GeditObjectModuleRegisterFunc) (GTypeModule *);
+
+enum {
+	PROP_0,
+	PROP_MODULE_NAME,
+	PROP_PATH,
+	PROP_TYPE_REGISTRATION
+};
+
+struct _GeditObjectModulePrivate
+{
+	GModule *library;
+
+	GType type;
+	gchar *path;
+	gchar *module_name;
+	gchar *type_registration;
+};
+
+G_DEFINE_TYPE (GeditObjectModule, gedit_object_module, G_TYPE_TYPE_MODULE);
+
+static gboolean
+gedit_object_module_load (GTypeModule *gmodule)
+{
+	GeditObjectModule *module = GEDIT_OBJECT_MODULE (gmodule);
+	GeditObjectModuleRegisterFunc register_func;
+	gchar *path;
+
+	gedit_debug_message (DEBUG_PLUGINS, "Loading %s module from %s",
+			     module->priv->module_name, module->priv->path);
+
+	path = g_module_build_path (module->priv->path, module->priv->module_name);
+	g_return_val_if_fail (path != NULL, FALSE);
+	gedit_debug_message (DEBUG_PLUGINS, "Module filename: %s", path);
+
+	module->priv->library = g_module_open (path, 0);
+	g_free (path);
+
+	if (module->priv->library == NULL)
+	{
+		g_warning (g_module_error());
+
+		return FALSE;
+	}
+
+	/* extract symbols from the lib */
+	if (!g_module_symbol (module->priv->library, module->priv->type_registration,
+			      (void *) &register_func))
+	{
+		g_warning (g_module_error());
+		g_module_close (module->priv->library);
+
+		return FALSE;
+	}
+
+	/* symbol can still be NULL even though g_module_symbol
+	 * returned TRUE */
+	if (register_func == NULL)
+	{
+		g_warning ("Symbol '%s' should not be NULL", module->priv->type_registration);
+		g_module_close (module->priv->library);
+
+		return FALSE;
+	}
+
+	module->priv->type = register_func (gmodule);
+
+	if (module->priv->type == 0)
+	{
+		g_warning ("Invalid object contained by module %s", module->priv->module_name);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+gedit_object_module_unload (GTypeModule *gmodule)
+{
+	GeditObjectModule *module = GEDIT_OBJECT_MODULE (gmodule);
+
+	gedit_debug_message (DEBUG_PLUGINS, "Unloading %s", module->priv->path);
+
+	g_module_close (module->priv->library);
+
+	module->priv->library = NULL;
+	module->priv->type = 0;
+}
+
+static void
+gedit_object_module_init (GeditObjectModule *module)
+{
+	gedit_debug_message (DEBUG_PLUGINS, "GeditObjectModule %p initialising", module);
+	
+	module->priv = G_TYPE_INSTANCE_GET_PRIVATE (module,
+						    GEDIT_TYPE_OBJECT_MODULE,
+						    GeditObjectModulePrivate);
+}
+
+static void
+gedit_object_module_finalize (GObject *object)
+{
+	GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
+
+	gedit_debug_message (DEBUG_PLUGINS, "GeditObjectModule %p finalising", module);
+
+	g_free (module->priv->path);
+	g_free (module->priv->module_name);
+	g_free (module->priv->type_registration);
+
+	G_OBJECT_CLASS (gedit_object_module_parent_class)->finalize (object);
+}
+
+static void
+gedit_object_module_get_property (GObject    *object,
+			          guint       prop_id,
+			          GValue     *value,
+			          GParamSpec *pspec)
+{
+	GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
+
+	switch (prop_id)
+	{
+		case PROP_MODULE_NAME:
+			g_value_set_string (value, module->priv->module_name);
+			break;
+		case PROP_PATH:
+			g_value_set_string (value, module->priv->path);
+			break;
+		case PROP_TYPE_REGISTRATION:
+			g_value_set_string (value, module->priv->type_registration);
+		default:
+			g_return_if_reached ();
+	}
+}
+
+static void
+gedit_object_module_set_property (GObject      *object,
+			   guint         prop_id,
+			   const GValue *value,
+			   GParamSpec   *pspec)
+{
+	GeditObjectModule *module = GEDIT_OBJECT_MODULE (object);
+
+	switch (prop_id)
+	{
+		case PROP_MODULE_NAME:
+			module->priv->module_name = g_value_dup_string (value);
+			g_type_module_set_name (G_TYPE_MODULE (object),
+						module->priv->module_name);
+			break;
+		case PROP_PATH:
+			module->priv->path = g_value_dup_string (value);
+			break;
+		case PROP_TYPE_REGISTRATION:
+			module->priv->type_registration = g_value_dup_string (value);
+			break;
+		default:
+			g_return_if_reached ();
+	}
+}
+
+static void
+gedit_object_module_class_init (GeditObjectModuleClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
+
+	object_class->set_property = gedit_object_module_set_property;
+	object_class->get_property = gedit_object_module_get_property;
+	object_class->finalize = gedit_object_module_finalize;
+
+	module_class->load = gedit_object_module_load;
+	module_class->unload = gedit_object_module_unload;
+
+	g_object_class_install_property (object_class,
+					 PROP_MODULE_NAME,
+					 g_param_spec_string ("module-name",
+							      "Module Name",
+							      "The module to load for this object",
+							      NULL,
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+					 PROP_PATH,
+					 g_param_spec_string ("path",
+							      "Path",
+							      "The path to use when loading this module",
+							      NULL,
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT_ONLY));
+							      
+	g_object_class_install_property (object_class,
+					 PROP_TYPE_REGISTRATION,
+					 g_param_spec_string ("type-registration",
+							      "Type Registration",
+							      "The name of the type registration function",
+							      NULL,
+							      G_PARAM_READWRITE |
+							      G_PARAM_CONSTRUCT_ONLY));
+
+	g_type_class_add_private (klass, sizeof (GeditObjectModulePrivate));
+}
+
+GeditObjectModule *
+gedit_object_module_new (const gchar *module_name,
+			 const gchar *path,
+			 const gchar *type_registration)
+{
+	return (GeditObjectModule *)g_object_new (GEDIT_TYPE_OBJECT_MODULE,
+						  "module-name",
+						  module_name,
+						  "path",
+						  path,
+						  "type-registration",
+						  type_registration,
+						  NULL);
+}
+
+GObject *
+gedit_object_module_new_object (GeditObjectModule *module,
+				const gchar       *first_property_name,
+				...)
+{
+	va_list var_args;
+	GObject *result;
+	
+	g_return_val_if_fail (module->priv->type != 0, NULL);
+
+	gedit_debug_message (DEBUG_PLUGINS, "Creating object of type %s",
+			     g_type_name (module->priv->type));
+
+	va_start (var_args, first_property_name);
+	result = g_object_new_valist (module->priv->type, first_property_name, var_args);
+	va_end (var_args);
+	
+	return result;
+}
+
+const gchar *
+gedit_object_module_get_path (GeditObjectModule *module)
+{
+	g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
+
+	return module->priv->path;
+}
+
+const gchar *
+gedit_object_module_get_module_name (GeditObjectModule *module)
+{
+	g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
+
+	return module->priv->module_name;
+}
+
+const gchar *
+gedit_object_module_get_type_registration (GeditObjectModule *module)
+{
+	g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), NULL);
+
+	return module->priv->module_name;
+}
+
+GType
+gedit_object_module_get_object_type (GeditObjectModule *module)
+{
+	g_return_val_if_fail (GEDIT_IS_OBJECT_MODULE (module), 0);
+	
+	return module->priv->type;
+}

Added: branches/new_plugins/gedit/gedit-object-module.h
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-object-module.h	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,92 @@
+/*
+ * gedit-object-module.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2005 - Paolo Maggi
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, 
+ * Boston, MA 02111-1307, USA. 
+ */
+ 
+/* This is a modified version of gedit-module.h from Epiphany source code.
+ * Here the original copyright assignment:
+ *
+ *  Copyright (C) 2003 Marco Pesenti Gritti
+ *  Copyright (C) 2003, 2004 Christian Persch
+ *
+ */
+
+/*
+ * Modified by the gedit Team, 2005. See the AUTHORS file for a 
+ * list of people on the gedit Team.  
+ * See the ChangeLog files for a list of changes. 
+ *
+ * $Id: gedit-module.h 6263 2008-05-05 10:52:10Z sfre $
+ */
+ 
+#ifndef __GEDIT_OBJECT_MODULE_H__
+#define __GEDIT_OBJECT_MODULE_H__
+
+#include <glib-object.h>
+#include <gmodule.h>
+#include <stdarg.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OBJECT_MODULE		(gedit_object_module_get_type ())
+#define GEDIT_OBJECT_MODULE(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModule))
+#define GEDIT_OBJECT_MODULE_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModuleClass))
+#define GEDIT_IS_OBJECT_MODULE(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_OBJECT_MODULE))
+#define GEDIT_IS_OBJECT_MODULE_CLASS(klass)		(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_OBJECT_MODULE))
+#define GEDIT_OBJECT_MODULE_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), GEDIT_TYPE_OBJECT_MODULE, GeditObjectModuleClass))
+
+typedef struct _GeditObjectModule 		GeditObjectModule;
+typedef struct _GeditObjectModulePrivate	GeditObjectModulePrivate;
+
+struct _GeditObjectModule
+{
+	GTypeModule parent;
+
+	GeditObjectModulePrivate *priv;
+};
+
+typedef struct _GeditObjectModuleClass GeditObjectModuleClass;
+
+struct _GeditObjectModuleClass
+{
+	GTypeModuleClass parent_class;
+
+	/* Virtual class methods */
+	void		 (* garbage_collect)	();
+};
+
+GType		 gedit_object_module_get_type			(void) G_GNUC_CONST;
+GeditObjectModule *gedit_object_module_new			(const gchar *module_name,
+								 const gchar *path,
+								 const gchar *type_registration);
+
+GObject		*gedit_object_module_new_object			(GeditObjectModule *module, 
+								 const gchar	   *first_property_name,
+								 ...);
+
+GType		 gedit_object_module_get_object_type		(GeditObjectModule *module);
+const gchar	*gedit_object_module_get_path			(GeditObjectModule *module);
+const gchar	*gedit_object_module_get_module_name		(GeditObjectModule *module);
+const gchar 	*gedit_object_module_get_type_registration 	(GeditObjectModule *module);
+
+G_END_DECLS
+
+#endif

Modified: branches/new_plugins/gedit/gedit-plugin-info-priv.h
==============================================================================
--- branches/new_plugins/gedit/gedit-plugin-info-priv.h	(original)
+++ branches/new_plugins/gedit/gedit-plugin-info-priv.h	Wed Aug 27 09:06:26 2008
@@ -39,11 +39,11 @@
 {
 	gint               refcount;
 
+	GeditPlugin       *plugin;
 	gchar             *file;
 
 	gchar             *module_name;
-	GType              module_type;
-	GeditModule       *module;
+	gchar		  *loader;
 	gchar            **dependencies;
 
 	gchar             *name;
@@ -53,10 +53,6 @@
 	gchar             *copyright;
 	gchar             *website;
 
-	GeditPlugin       *plugin;
-
-	gint               active : 1;
-
 	/* A plugin is unavailable if it is not possible to activate it
 	   due to an error loading the plugin module (e.g. for Python plugins
 	   when the interpreter has not been correctly initializated) */

Modified: branches/new_plugins/gedit/gedit-plugin-info.c
==============================================================================
--- branches/new_plugins/gedit/gedit-plugin-info.c	(original)
+++ branches/new_plugins/gedit/gedit-plugin-info.c	Wed Aug 27 09:06:26 2008
@@ -70,9 +70,6 @@
 		gedit_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name);
 
 		g_object_unref (info->plugin);
-		
-		/* info->module must not be unref since it is not possible to finalize 
-		 * a type module */
 	}
 
 	g_free (info->file);
@@ -83,6 +80,7 @@
 	g_free (info->icon_name);
 	g_free (info->website);
 	g_free (info->copyright);
+	g_free (info->loader);
 	g_strfreev (info->authors);
 
 	g_free (info);
@@ -194,21 +192,16 @@
 				     "Gedit Plugin",
 				     "Loader",
 				     NULL);
-	if (str && strcmp(str, "python") == 0)
+	
+	if ((str != NULL) && (*str != '\0'))
 	{
-#ifndef ENABLE_PYTHON
-		g_warning ("Cannot load Python plugin '%s' since gedit was not "
-			   "compiled with Python support.", file);
-		goto error;
-#else
-		info->module_type = GEDIT_TYPE_PYTHON_MODULE;
-#endif
+		info->loader = str;
 	}
 	else
 	{
-		info->module_type = GEDIT_TYPE_MODULE;
+		/* default to the C loader */
+		info->loader = g_strdup("c");
 	}
-	g_free (str);
 
 	/* Get Name */
 	str = g_key_file_get_locale_string (plugin_file,
@@ -286,6 +279,7 @@
 	g_free (info->file);
 	g_free (info->module_name);
 	g_free (info->name);
+	g_free (info->loader);
 	g_free (info);
 	g_key_file_free (plugin_file);
 
@@ -297,7 +291,7 @@
 {
 	g_return_val_if_fail (info != NULL, FALSE);
 
-	return info->available && info->active;
+	return info->available && info->plugin != NULL;
 }
 
 gboolean
@@ -315,13 +309,21 @@
 
 	g_return_val_if_fail (info != NULL, FALSE);
 
-	if (info->plugin == NULL || !info->active || !info->available)
+	if (info->plugin == NULL || !info->available)
 		return FALSE;
 
 	return gedit_plugin_is_configurable (info->plugin);
 }
 
 const gchar *
+gedit_plugin_info_get_module_name (GeditPluginInfo *info)
+{
+	g_return_val_if_fail (info != NULL, NULL);
+
+	return info->module_name;
+}
+
+const gchar *
 gedit_plugin_info_get_name (GeditPluginInfo *info)
 {
 	g_return_val_if_fail (info != NULL, NULL);

Modified: branches/new_plugins/gedit/gedit-plugin-info.h
==============================================================================
--- branches/new_plugins/gedit/gedit-plugin-info.h	(original)
+++ branches/new_plugins/gedit/gedit-plugin-info.h	Wed Aug 27 09:06:26 2008
@@ -48,6 +48,8 @@
 gboolean 	 gedit_plugin_info_is_available		(GeditPluginInfo *info);
 gboolean	 gedit_plugin_info_is_configurable	(GeditPluginInfo *info);
 
+const gchar	*gedit_plugin_info_get_module_name	(GeditPluginInfo *info);
+
 const gchar	*gedit_plugin_info_get_name		(GeditPluginInfo *info);
 const gchar	*gedit_plugin_info_get_description	(GeditPluginInfo *info);
 const gchar	*gedit_plugin_info_get_icon_name	(GeditPluginInfo *info);

Added: branches/new_plugins/gedit/gedit-plugin-loader-c.c
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-plugin-loader-c.c	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,134 @@
+#include "gedit-plugin-loader-c.h"
+#include <gedit/gedit-object-module.h>
+
+#define GEDIT_PLUGIN_LOADER_C_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCPrivate))
+
+struct _GeditPluginLoaderCPrivate
+{
+	GHashTable *loaded_plugins;
+};
+
+static void gedit_plugin_loader_iface_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_EXTENDED (GeditPluginLoaderC, 
+			gedit_plugin_loader_c, 
+			G_TYPE_OBJECT,
+			0,
+			G_IMPLEMENT_INTERFACE (GEDIT_TYPE_PLUGIN_LOADER,
+					       gedit_plugin_loader_iface_init))
+
+static GeditPlugin *
+gedit_plugin_loader_iface_load (GeditPluginLoader *loader,
+				GeditPluginInfo   *info,
+				const gchar       *path)
+{
+	GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (loader);
+	GeditObjectModule *module;
+	GeditPlugin *result;
+	
+	module = (GeditObjectModule *)g_hash_table_lookup (cloader->priv->loaded_plugins, info);
+	
+	if (module == NULL)
+	{
+		module = gedit_object_module_new (gedit_plugin_info_get_module_name (info),
+						  path,
+						  "register_gedit_plugin");
+		g_hash_table_insert (cloader->priv->loaded_plugins, info, module);
+	}
+
+	if (!g_type_module_use (G_TYPE_MODULE (module)))
+	{
+		g_warning ("Could not load plugin module: %s", gedit_plugin_info_get_name (info));
+
+		return NULL;
+	}
+	
+	/* create new plugin object */
+	result = (GeditPlugin *)gedit_object_module_new_object (module, NULL);
+	
+	if (!result)
+	{
+		g_warning ("Could not create plugin object: %s", gedit_plugin_info_get_name (info));
+		g_type_module_unuse (G_TYPE_MODULE (module));
+		
+		return NULL;
+	}
+	
+	g_type_module_unuse (G_TYPE_MODULE (module));
+	
+	return result;
+}
+
+static void
+gedit_plugin_loader_iface_unload (GeditPluginLoader *loader,
+				  GeditPluginInfo   *info)
+{
+	//GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (loader);
+	
+	/* this is a no-op, since the type module will be properly unused as
+	   the last reference to the plugin dies. When the plugin is activated
+	   again, the library will be reloaded */
+}
+
+static void
+gedit_plugin_loader_iface_init (gpointer g_iface, 
+				gpointer iface_data)
+{
+	GeditPluginLoaderInterface *iface = (GeditPluginLoaderInterface *)g_iface;
+	
+	iface->load = gedit_plugin_loader_iface_load;
+	iface->unload = gedit_plugin_loader_iface_unload;
+}
+
+static void
+gedit_plugin_loader_c_finalize (GObject *object)
+{
+	GeditPluginLoaderC *cloader = GEDIT_PLUGIN_LOADER_C (object);
+	GList *infos;
+	GList *item;
+
+	infos = g_hash_table_get_keys (cloader->priv->loaded_plugins);
+	
+	for (item = infos; item; item = item->next)
+	{
+		GeditPluginInfo *info = (GeditPluginInfo *)item->data;
+		
+		if (gedit_plugin_info_is_active (info))
+		{
+			g_warning ("There are still C plugins loaded during destruction");
+			break;
+		}
+	}
+	
+	g_hash_table_destroy (cloader->priv->loaded_plugins);
+	
+	G_OBJECT_CLASS (gedit_plugin_loader_c_parent_class)->finalize (object);
+}
+
+static void
+gedit_plugin_loader_c_class_init (GeditPluginLoaderCClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	object_class->finalize = gedit_plugin_loader_c_finalize;
+
+	g_type_class_add_private (object_class, sizeof (GeditPluginLoaderCPrivate));
+}
+
+static void
+gedit_plugin_loader_c_init (GeditPluginLoaderC *self)
+{
+	self->priv = GEDIT_PLUGIN_LOADER_C_GET_PRIVATE (self);
+	
+	/* loaded_plugins maps GeditPluginInfo to a GeditObjectModule */
+	self->priv->loaded_plugins = g_hash_table_new (g_direct_hash,
+						       g_direct_equal);
+}
+
+GeditPluginLoaderC *
+gedit_plugin_loader_c_new ()
+{
+	GObject *loader = g_object_new (GEDIT_TYPE_PLUGIN_LOADER_C, NULL);
+
+	return GEDIT_PLUGIN_LOADER_C (loader);
+}

Added: branches/new_plugins/gedit/gedit-plugin-loader-c.h
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-plugin-loader-c.h	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,35 @@
+#ifndef __GEDIT_PLUGIN_LOADER_C_H__
+#define __GEDIT_PLUGIN_LOADER_C_H__
+
+#include <gedit/gedit-plugin-loader.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_PLUGIN_LOADER_C		(gedit_plugin_loader_c_get_type ())
+#define GEDIT_PLUGIN_LOADER_C(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderC))
+#define GEDIT_PLUGIN_LOADER_C_CONST(obj)	(G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderC const))
+#define GEDIT_PLUGIN_LOADER_C_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCClass))
+#define GEDIT_IS_PLUGIN_LOADER_C(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PLUGIN_LOADER_C))
+#define GEDIT_IS_PLUGIN_LOADER_C_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GEDIT_TYPE_PLUGIN_LOADER_C))
+#define GEDIT_PLUGIN_LOADER_C_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GEDIT_TYPE_PLUGIN_LOADER_C, GeditPluginLoaderCClass))
+
+typedef struct _GeditPluginLoaderC		GeditPluginLoaderC;
+typedef struct _GeditPluginLoaderCClass		GeditPluginLoaderCClass;
+typedef struct _GeditPluginLoaderCPrivate	GeditPluginLoaderCPrivate;
+
+struct _GeditPluginLoaderC {
+	GObject parent;
+	
+	GeditPluginLoaderCPrivate *priv;
+};
+
+struct _GeditPluginLoaderCClass {
+	GObjectClass parent_class;
+};
+
+GType gedit_plugin_loader_c_get_type (void) G_GNUC_CONST;
+GeditPluginLoaderC *gedit_plugin_loader_c_new(void);
+
+G_END_DECLS
+
+#endif /* __GEDIT_PLUGIN_LOADER_C_H__ */

Added: branches/new_plugins/gedit/gedit-plugin-loader.c
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-plugin-loader.c	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,103 @@
+/*
+ * gedit-plugin-loader.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, 
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#include "gedit-plugin-loader.h"
+
+static void
+gedit_plugin_loader_base_init (gpointer g_class)
+{
+	static gboolean initialized = FALSE;
+
+	if (G_UNLIKELY (!initialized))
+	{
+		/* create interface signals here. */
+		initialized = TRUE;
+	}
+}
+
+GType
+gedit_plugin_loader_get_type (void)
+{
+	static GType type = 0;
+	
+	if (type == 0)
+	{
+		static const GTypeInfo info =
+		{
+			sizeof (GeditPluginLoaderInterface),
+			gedit_plugin_loader_base_init,   /* base_init */
+			NULL,   /* base_finalize */
+			NULL,   /* class_init */
+			NULL,   /* class_finalize */
+			NULL,   /* class_data */
+			0,
+			0,      /* n_preallocs */
+			NULL    /* instance_init */
+		};
+		
+		type = g_type_register_static (G_TYPE_INTERFACE, "GeditPluginLoader", &info, 0);
+	}
+
+	return type;
+}
+
+GeditPlugin *
+gedit_plugin_loader_load (GeditPluginLoader *loader,
+			  GeditPluginInfo   *info,
+			  const gchar       *path)
+{
+	GeditPluginLoaderInterface *iface;
+	
+	g_return_val_if_fail (GEDIT_IS_PLUGIN_LOADER (loader), NULL);
+	
+	iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+	g_return_val_if_fail (iface->load != NULL, NULL);
+	
+	return iface->load (loader, info, path);
+}
+
+void
+gedit_plugin_loader_unload (GeditPluginLoader *loader,
+			    GeditPluginInfo   *info)
+{
+	GeditPluginLoaderInterface *iface;
+	
+	g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
+	
+	iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+	g_return_if_fail (iface->unload != NULL);
+	
+	iface->unload (loader, info);
+}
+
+void
+gedit_plugin_loader_garbage_collect (GeditPluginLoader *loader)
+{
+	GeditPluginLoaderInterface *iface;
+	
+	g_return_if_fail (GEDIT_IS_PLUGIN_LOADER (loader));
+	
+	iface = GEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
+	
+	if (iface->garbage_collect != NULL)
+		iface->garbage_collect (loader);
+}

Added: branches/new_plugins/gedit/gedit-plugin-loader.h
==============================================================================
--- (empty file)
+++ branches/new_plugins/gedit/gedit-plugin-loader.h	Wed Aug 27 09:06:26 2008
@@ -0,0 +1,60 @@
+/*
+ * gedit-plugin-loader.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2008 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, 
+ * Boston, MA 02111-1307, USA. 
+ */
+
+#ifndef __GEDIT_PLUGIN_LOADER_H__
+#define __GEDIT_PLUGIN_LOADER_H__
+
+#include <glib-object.h>
+#include <gedit/gedit-plugin.h>
+#include <gedit/gedit-plugin-info.h>
+
+#define GEDIT_TYPE_PLUGIN_LOADER                (gedit_plugin_loader_get_type ())
+#define GEDIT_PLUGIN_LOADER(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoader))
+#define GEDIT_IS_PLUGIN_LOADER(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEDIT_TYPE_PLUGIN_LOADER))
+#define GEDIT_PLUGIN_LOADER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GEDIT_TYPE_PLUGIN_LOADER, GeditPluginLoaderInterface))
+
+typedef struct _GeditPluginLoader GeditPluginLoader; /* dummy object */
+typedef struct _GeditPluginLoaderInterface GeditPluginLoaderInterface;
+
+struct _GeditPluginLoaderInterface {
+	GTypeInterface parent;
+
+	GeditPlugin *(*load) 	(GeditPluginLoader 	*loader,
+			     	 GeditPluginInfo	*info,
+			      	 const gchar       	*path);
+
+	void (*unload)		(GeditPluginLoader 	*loader,
+				 GeditPluginInfo       	*info);
+
+	void (*garbage_collect) (GeditPluginLoader	*loader);
+};
+
+GType gedit_plugin_loader_get_type (void);
+GeditPlugin *gedit_plugin_loader_load		(GeditPluginLoader 	*loader,
+						 GeditPluginInfo 	*info,
+						 const gchar		*path);
+void gedit_plugin_loader_unload			(GeditPluginLoader 	*loader,
+						 GeditPluginInfo	*info);
+
+void gedit_plugin_loader_garbage_collect	(GeditPluginLoader 	*loader);
+
+#endif /* __GEDIT_PLUGIN_LOADER_H__ */

Modified: branches/new_plugins/gedit/gedit-plugin.h
==============================================================================
--- branches/new_plugins/gedit/gedit-plugin.h	(original)
+++ branches/new_plugins/gedit/gedit-plugin.h	Wed Aug 27 09:06:26 2008
@@ -112,10 +112,10 @@
 GtkWidget	*gedit_plugin_create_configure_dialog		
 						(GeditPlugin *plugin);
 
-/*
- * Utility macro used to register plugins
+/**
+ * GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE):
  *
- * use: GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE)
+ * Utility macro used to register plugins with additional code.
  */
 #define GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE)	\
 										\
@@ -169,18 +169,18 @@
 	return plugin_name##_type;						\
 }
 
-/*
- * Utility macro used to register plugins
- *
- * use: GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name)
+/**
+ * GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name):
+ * 
+ * Utility macro used to register plugins.
  */
 #define GEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name)			\
 	GEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, ;)
 
-/*
- * Utility macro used to register gobject types in plugins with additional code
+/**
+ * GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE):
  *
- * use: GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE)
+ * Utility macro used to register gobject types in plugins with additional code.
  */
 #define GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE)	\
 										\
@@ -230,14 +230,32 @@
 	return g_define_type_id;						\
 }
 
-/*
- * Utility macro used to register gobject types in plugins
+/**
+ * GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE):
  *
- * use: GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE)
+ * Utility macro used to register gobject types in plugins.
  */
 #define GEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE)		\
 	GEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, ;)
 
+/**
+ * GEDIT_PLUGIN_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
+ *
+ * Utility macro used to register interfaces for gobject types in plugins.
+ */
+#define GEDIT_PLUGIN_IMPLEMENT_INTERFACE(object_name, TYPE_IFACE, iface_init)	\
+	const GInterfaceInfo object_name##_interface_info = 			\
+	{ 									\
+		(GInterfaceInitFunc) iface_init,				\
+		NULL, 								\
+		NULL								\
+	};									\
+										\
+	g_type_module_add_interface (module, 					\
+				     g_define_type_id, 				\
+				     TYPE_IFACE, 				\
+				     &object_name##_interface_info);		\
+
 G_END_DECLS
 
 #endif  /* __GEDIT_PLUGIN_H__ */

Modified: branches/new_plugins/gedit/gedit-plugins-engine.c
==============================================================================
--- branches/new_plugins/gedit/gedit-plugins-engine.c	(original)
+++ branches/new_plugins/gedit/gedit-plugins-engine.c	Wed Aug 27 09:06:26 2008
@@ -42,18 +42,23 @@
 #include "gedit-plugin.h"
 #include "gedit-debug.h"
 #include "gedit-app.h"
+#include "gedit-plugin-loader.h"
+#include "gedit-object-module.h"
+#include "gedit-plugin-loader-c.h"
 
-#include "gedit-module.h"
-#ifdef ENABLE_PYTHON
-#include "gedit-python-module.h"
-#endif
-
-#define USER_GEDIT_PLUGINS_LOCATION ".gnome2/gedit/plugins/"
+#define USER_GEDIT_LOCATION ".gnome2/gedit/"
 
 #define GEDIT_PLUGINS_ENGINE_BASE_KEY "/apps/gedit-2/plugins"
 #define GEDIT_PLUGINS_ENGINE_KEY GEDIT_PLUGINS_ENGINE_BASE_KEY "/active-plugins"
 
 #define PLUGIN_EXT	".gedit-plugin"
+#define LOADER_EXT	".gedit-plugin-loader"
+
+typedef struct
+{
+	GeditPluginLoader *loader;
+	GeditObjectModule *module;
+} LoaderInfo;
 
 /* Signals */
 enum
@@ -70,7 +75,10 @@
 struct _GeditPluginsEnginePrivate
 {
 	GList *plugin_list;
+	GHashTable *loaders;
+
 	GConfClient *gconf_client;
+	gboolean activate_from_gconf;
 };
 
 GeditPluginsEngine *default_engine = NULL;
@@ -84,86 +92,100 @@
 static void	gedit_plugins_engine_deactivate_plugin_real (GeditPluginsEngine *engine,
 							     GeditPluginInfo    *info);
 
-static void
-gedit_plugins_engine_load_dir (GeditPluginsEngine *engine,
-			       const gchar        *dir,
-			       GSList             *active_plugins)
+typedef gboolean (*LoadDirCallback)(GeditPluginsEngine *engine, const gchar *filename, gpointer userdata);
+
+static gboolean
+load_dir_real (GeditPluginsEngine *engine,
+	       const gchar        *dir,
+	       const gchar        *suffix,
+	       LoadDirCallback     callback,
+	       gpointer            userdata)
 {
 	GError *error = NULL;
 	GDir *d;
 	const gchar *dirent;
+	gboolean ret = TRUE;
 
-	g_return_if_fail (engine->priv->gconf_client != NULL);
-	g_return_if_fail (dir != NULL);
+	g_return_val_if_fail (dir != NULL, TRUE);
 
 	gedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir);
 
 	d = g_dir_open (dir, 0, &error);
+
 	if (!d)
 	{
 		g_warning (error->message);
 		g_error_free (error);
-		return;
+		return TRUE;
 	}
-
+	
 	while ((dirent = g_dir_read_name (d)))
 	{
-		if (g_str_has_suffix (dirent, PLUGIN_EXT))
-		{
-			gchar *plugin_file;
-			GeditPluginInfo *info;
-			
-			plugin_file = g_build_filename (dir, dirent, NULL);
-			info = _gedit_plugin_info_new (plugin_file);
-			g_free (plugin_file);
-
-			if (info == NULL)
-				continue;
-
-			/* If a plugin with this name has already been loaded
-			 * drop this one (user plugins override system plugins) */
-			if (gedit_plugins_engine_get_plugin_info (engine, info->module_name) != NULL)
-			{
-				g_warning ("Two or more plugins named '%s'. "
-					   "Only the first will be considered.\n",
-					   info->module_name);
-
-				_gedit_plugin_info_unref (info);
-
-				continue;
-			}
-
-			/* Actually, the plugin will be activated when reactivate_all
-			 * will be called for the first time. */
-			info->active = g_slist_find_custom (active_plugins,
-							    info->module_name,
-							    (GCompareFunc)strcmp) != NULL;
+		gchar *filename;
+		
+		if (!g_str_has_suffix (dirent, suffix))
+			continue;
+		
+		filename = g_build_filename (dir, dirent, NULL);
+
+		ret = callback (engine, filename, userdata);
+		
+		if (!ret)
+			break;
+	}
+	
+	g_dir_close (d);
+	return ret;
+}
 
-			engine->priv->plugin_list = g_list_prepend (engine->priv->plugin_list, info);
+static gboolean
+load_plugin_info (GeditPluginsEngine *engine,
+		  const gchar        *filename,
+		  gpointer            userdata)
+{
+	GeditPluginInfo *info;
+	
+	info = _gedit_plugin_info_new (filename);
 
-			gedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name);
-		}
+	if (info == NULL)
+		return TRUE;
+
+	/* If a plugin with this name has already been loaded
+	 * drop this one (user plugins override system plugins) */
+	if (gedit_plugins_engine_get_plugin_info (engine, gedit_plugin_info_get_module_name (info)) != NULL)
+	{
+		g_warning ("Two or more plugins named '%s'. "
+			   "Only the first will be considered.\n",
+			   gedit_plugin_info_get_module_name (info));
+
+		_gedit_plugin_info_unref (info);
+
+		return TRUE;
 	}
 
-	g_dir_close (d);
+	engine->priv->plugin_list = g_list_prepend (engine->priv->plugin_list, info);
+
+	gedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name);
+	return TRUE;
 }
 
 static void
-gedit_plugins_engine_load_all (GeditPluginsEngine *engine)
+load_all_real (GeditPluginsEngine *engine,
+               const gchar        *dir,
+               const gchar        *envname,
+               const gchar        *envdefault,
+               const gchar        *suffix,
+	       LoadDirCallback     callback,
+	       gpointer            userdata)
 {
-	GSList *active_plugins;
 	const gchar *home;
 	const gchar *pdirs_env;
 	gchar **pdirs;
 	int i;
 
-	active_plugins = gconf_client_get_list (engine->priv->gconf_client,
-						GEDIT_PLUGINS_ENGINE_KEY,
-						GCONF_VALUE_STRING,
-						NULL);
-
 	/* load user's plugins */
 	home = g_get_home_dir ();
+
 	if (home == NULL)
 	{
 		g_warning ("Could not get HOME directory\n");
@@ -171,32 +193,99 @@
 	else
 	{
 		gchar *pdir;
+		gboolean ret = TRUE;
 
 		pdir = g_build_filename (home,
-					 USER_GEDIT_PLUGINS_LOCATION,
+					 USER_GEDIT_LOCATION,
+					 dir,
 					 NULL);
 
 		if (g_file_test (pdir, G_FILE_TEST_IS_DIR))
-			gedit_plugins_engine_load_dir (engine, pdir, active_plugins);
+			ret = load_dir_real (engine, pdir, suffix, callback, userdata);
 		
 		g_free (pdir);
+		
+		if (!ret)
+			return;
 	}
 
-	pdirs_env = g_getenv ("GEDIT_PLUGINS_PATH");
+	pdirs_env = g_getenv (envname);
+
 	/* What if no env var is set? We use the default location(s)! */
 	if (pdirs_env == NULL)
-		pdirs_env = GEDIT_PLUGINDIR;
+		pdirs_env = envdefault;
 
-	gedit_debug_message (DEBUG_PLUGINS, "GEDIT_PLUGINS_PATH=%s", pdirs_env);
+	gedit_debug_message (DEBUG_PLUGINS, "%s=%s", envname, pdirs_env);
 	pdirs = g_strsplit (pdirs_env, G_SEARCHPATH_SEPARATOR_S, 0);
 
 	for (i = 0; pdirs[i] != NULL; i++)
-		gedit_plugins_engine_load_dir (engine, pdirs[i], active_plugins);
+	{
+		if (!load_dir_real (engine, pdirs[i], suffix, callback, userdata))
+			break;
+	}
 
 	g_strfreev (pdirs);
 }
 
 static void
+load_all_plugins (GeditPluginsEngine *engine)
+{
+	load_all_real (engine, 
+		       "plugins", 
+		       "GEDIT_PLUGINS_PATH", 
+		       GEDIT_PLUGINDIR,
+		       PLUGIN_EXT,
+		       load_plugin_info,
+		       NULL);
+}
+
+static guint
+hash_downcase (gconstpointer data)
+{
+	gchar *downcase;
+	guint ret;
+	
+	downcase = g_ascii_strdown ((const gchar *)data, -1);
+	ret = g_str_hash (downcase);
+	g_free (downcase);
+	
+	return ret;
+}
+
+static gboolean
+equal_downcase (gconstpointer a, gconstpointer b)
+{
+	return g_ascii_strcasecmp ((const gchar *)a, (const gchar *)b) == 0;
+}
+
+static void
+loader_destroy (LoaderInfo *info)
+{
+	if (!info)
+		return;
+	
+	if (info->loader)
+		g_object_unref (info->loader);
+	
+	g_free (info);
+}
+
+static void
+add_loader (GeditPluginsEngine *engine,
+	    const gchar        *loader_name,
+	    GeditPluginLoader  *loader,
+	    GeditObjectModule  *module)
+{
+	LoaderInfo *info;
+
+	info = g_new (LoaderInfo, 1);
+	info->loader = loader;
+	info->module = module;
+
+	g_hash_table_insert (engine->priv->loaders, g_strdup (loader_name), info);
+}
+
+static void
 gedit_plugins_engine_init (GeditPluginsEngine *engine)
 {
 	gedit_debug (DEBUG_PLUGINS);
@@ -224,46 +313,64 @@
 				 gedit_plugins_engine_active_plugins_changed,
 				 engine, NULL, NULL);
 
-	gedit_plugins_engine_load_all (engine);
+	load_all_plugins (engine);
+	
+	/* make sure that the first reactivation will read active plugins from
+	   gconf */
+	engine->priv->activate_from_gconf = TRUE;
+	
+	/* mapping from loadername -> loader object */
+	engine->priv->loaders = g_hash_table_new_full (hash_downcase,
+						       equal_downcase,
+						       (GDestroyNotify)g_free,
+						       (GDestroyNotify)loader_destroy);
+
+	/* add a c loader by default */
+	add_loader (engine, "c", GEDIT_PLUGIN_LOADER (gedit_plugin_loader_c_new ()), NULL);
 }
 
 void
 gedit_plugins_engine_garbage_collect (GeditPluginsEngine *engine)
 {
-	GType *module_types = g_type_children (GEDIT_TYPE_MODULE, NULL);
-	unsigned i;
-	for (i = 0; module_types[i] != 0; i++)
-	{
-		gpointer klass = g_type_class_peek (module_types[i]);
-		if (klass != NULL)
-			gedit_module_class_garbage_collect (klass);
+	GList *loaders;
+	GList *item;
+	
+	loaders = g_hash_table_get_values (engine->priv->loaders);
+	
+	for (item = loaders; item; item = item->next)
+	{
+		LoaderInfo *info = (LoaderInfo *)item->data;
+		
+		if (info->loader)
+			gedit_plugin_loader_garbage_collect (info->loader);
 	}
-	g_free (module_types);
+	
+	g_list_free (loaders);
 }
 
 static void
 gedit_plugins_engine_finalize (GObject *object)
 {
 	GeditPluginsEngine *engine = GEDIT_PLUGINS_ENGINE (object);
-
+	GList *item;
+	
 	gedit_debug (DEBUG_PLUGINS);
 
-#ifdef ENABLE_PYTHON
-	/* Note: that this may cause finalization of objects (typically
-	 * the GeditWindow) by running the garbage collector. Since some
-	 * of the plugin may have installed callbacks upon object
-	 * finalization (typically they need to free the WindowData)
-	 * it must run before we get rid of the plugins.
-	 */
-	gedit_python_shutdown ();
-#endif
-
 	g_return_if_fail (engine->priv->gconf_client != NULL);
 
-	g_list_foreach (engine->priv->plugin_list,
-			(GFunc) _gedit_plugin_info_unref, NULL);
+	for (item = engine->priv->plugin_list; item; item = item->next)
+	{
+		GeditPluginInfo *info = GEDIT_PLUGIN_INFO (item->data);
+		
+		if (gedit_plugin_info_is_active (info))
+			gedit_plugins_engine_deactivate_plugin_real (engine, info);
+		
+		_gedit_plugin_info_unref (info);
+	}
+	
 	g_list_free (engine->priv->plugin_list);
-
+	
+	g_hash_table_destroy (engine->priv->loaders);
 	g_object_unref (engine->priv->gconf_client);
 }
 
@@ -302,6 +409,124 @@
 	g_type_class_add_private (klass, sizeof (GeditPluginsEnginePrivate));
 }
 
+static gboolean
+load_loader (GeditPluginsEngine *engine,
+	     const gchar        *filename,
+	     const gchar        *loader_name)
+{
+	GKeyFile *loader_file;
+	GeditObjectModule *module;
+	gchar *str;
+	gchar *path;
+	GeditPluginLoader *loader;
+	
+	loader_file = g_key_file_new ();
+	
+	if (!g_key_file_load_from_file (loader_file, filename, G_KEY_FILE_NONE, NULL))
+	{
+		g_warning ("Bad loader file: %s", filename);
+		g_key_file_free (loader_file);
+		return TRUE;
+	}
+	
+	/* get loader name */
+	str = g_key_file_get_string (loader_file,
+				     "Gedit Plugin Loader",
+				     "Loader",
+				     NULL);
+	
+	/* check if this is the loader we need */
+	if (str == NULL || g_ascii_strcasecmp (str, loader_name) != 0)
+	{
+		if (str == NULL || *str == '\0')
+			g_warning ("Could not find 'Loader' in %s", filename);
+
+		g_key_file_free (loader_file);
+		g_free (str);
+		return TRUE;
+	}
+	
+	/* get module name */
+	str = g_key_file_get_string (loader_file,
+				     "Gedit Plugin Loader",
+				     "Module",
+				     NULL);
+
+	if ((str == NULL) || (*str == '\0'))
+	{
+		g_warning ("Could not find 'Module' in %s", filename);
+
+		g_key_file_free (loader_file);
+		g_free (str);
+		return TRUE;
+	}
+	
+	path = g_path_get_dirname (filename);
+	module = gedit_object_module_new (str, path, "gedit_plugin_loader_register");
+	
+	g_free (path);
+	g_free (str);
+	
+	/* make sure to load the type definition */
+	if (!g_type_module_use (G_TYPE_MODULE (module)))
+	{
+		g_object_unref (module);
+		g_warning ("Plugin loader module could not be loaded");
+		
+		add_loader (engine, loader_name, NULL, NULL);
+		return FALSE;
+	}
+	
+	/* create a new loader object */
+	loader = (GeditPluginLoader *)gedit_object_module_new_object (module, NULL);
+	
+	if (loader == NULL || !GEDIT_IS_PLUGIN_LOADER (loader))
+	{
+		g_warning ("Loader object is not a valid GeditPluginLoader instance");
+		
+		if (loader != NULL && G_IS_OBJECT (loader))
+			g_object_unref (loader);
+
+		g_type_module_unuse (G_TYPE_MODULE (module));
+		g_object_unref (module);
+		
+		add_loader (engine, loader_name, NULL, NULL);
+		return FALSE;
+	}
+	
+	/* add the loader to the hash */
+	add_loader (engine, loader_name, loader, module);
+	g_type_module_unuse (G_TYPE_MODULE (module));
+
+	return FALSE;
+}
+
+static GeditPluginLoader *
+get_plugin_loader (GeditPluginsEngine *engine, GeditPluginInfo *info)
+{
+	const gchar *loader_name;
+	LoaderInfo *loader_info;
+	
+	loader_name = info->loader;
+
+	loader_info = (LoaderInfo *)g_hash_table_lookup (engine->priv->loaders, loader_name);
+
+	if (loader_info)
+		return loader_info->loader;
+
+	/* loader could not be found in the hash, try to find it */
+	load_all_real (engine, 
+		       "plugin-loaders", 
+		       "GEDIT_LOADERS_PATH", 
+		       GEDIT_LOADERDIR,
+		       LOADER_EXT,
+		       (LoadDirCallback)load_loader,
+		       (gpointer)loader_name);
+	
+	loader_info = (LoaderInfo *)g_hash_table_lookup (engine->priv->loaders, loader_name);
+	return loader_info ? loader_info->loader : NULL;
+}
+
 GeditPluginsEngine *
 gedit_plugins_engine_get_default (void)
 {
@@ -326,7 +551,7 @@
 compare_plugin_info_and_name (GeditPluginInfo *info,
 			      const gchar *module_name)
 {
-	return strcmp (info->module_name, module_name);
+	return strcmp (gedit_plugin_info_get_module_name (info), module_name);
 }
 
 GeditPluginInfo *
@@ -339,67 +564,6 @@
 	return l == NULL ? NULL : (GeditPluginInfo *) l->data;
 }
 
-static gboolean
-load_plugin_module (GeditPluginInfo *info)
-{
-	gchar *dirname;
-
-	gedit_debug (DEBUG_PLUGINS);
-
-	g_return_val_if_fail (info != NULL, FALSE);
-	g_return_val_if_fail (info->file != NULL, FALSE);
-	g_return_val_if_fail (info->module_name != NULL, FALSE);
-	g_return_val_if_fail (info->plugin == NULL, FALSE);
-	g_return_val_if_fail (info->available, FALSE);
-
-	dirname = g_path_get_dirname (info->file);
-	g_return_val_if_fail (dirname != NULL, FALSE);
-
-#ifdef ENABLE_PYTHON
-	if (info->module_type == GEDIT_TYPE_PYTHON_MODULE)
-	{
-		if (!gedit_python_init ())
-		{
-			/* Mark plugin as unavailable and fail */
-			info->available = FALSE;
-			g_warning ("Cannot load Python plugin '%s' since gedit "
-			           "was not able to initialize the Python interpreter.",
-			           info->name);
-		}
-	}
-#endif
-
-	info->module = GEDIT_MODULE (g_object_new (info->module_type,
-						   "path", dirname,
-						   "module-name", info->module_name,
-						   NULL));
-
-	g_free (dirname);
-
-	if (!g_type_module_use (G_TYPE_MODULE (info->module)))
-	{
-		g_warning ("Cannot load plugin '%s' since file '%s' cannot be read.",
-			   gedit_module_get_module_name (info->module),
-			   gedit_module_get_path (info->module));
-
-		g_object_unref (G_OBJECT (info->module));
-		info->module = NULL;
-
-		/* Mark plugin as unavailable and fail. */
-		info->available = FALSE;
-		
-		return FALSE;
-	}
-
-	info->plugin = GEDIT_PLUGIN (gedit_module_new_object (info->module));
-
-	g_type_module_unuse (G_TYPE_MODULE (info->module));
-
-	gedit_debug_message (DEBUG_PLUGINS, "End");
-
-	return TRUE;
-}
-
 static void
 save_active_plugin_list (GeditPluginsEngine *engine)
 {
@@ -407,13 +571,16 @@
 	GList *l;
 	gboolean res;
 
+	return;
+
 	for (l = engine->priv->plugin_list; l != NULL; l = l->next)
 	{
-		const GeditPluginInfo *info = (const GeditPluginInfo *) l->data;
-		if (info->active)
+		GeditPluginInfo *info = (GeditPluginInfo *) l->data;
+
+		if (gedit_plugin_info_is_active (info))
 		{
 			active_plugins = g_slist_prepend (active_plugins,
-							  info->module_name);
+							  (gpointer)gedit_plugin_info_get_module_name (info));
 		}
 	}
 
@@ -429,28 +596,56 @@
 	g_slist_free (active_plugins);
 }
 
-static void
-gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
-					   GeditPluginInfo *info)
+static gboolean
+load_plugin (GeditPluginsEngine *engine,
+	     GeditPluginInfo    *info)
 {
-	gboolean res = TRUE;
+	GeditPluginLoader *loader;
+	gchar *path;
 
-	if (info->active || !info->available)
-		return;
-
-	if (info->plugin == NULL)
-		res = load_plugin_module (info);
+	if (gedit_plugin_info_is_active (info))
+		return TRUE;
+	
+	if (!gedit_plugin_info_is_available (info))
+		return FALSE;
 
-	if (res)
+	loader = get_plugin_loader (engine, info);
+	
+	if (loader == NULL)
 	{
-		const GList *wins = gedit_app_get_windows (gedit_app_get_default ());
-		for (; wins != NULL; wins = wins->next)
-			gedit_plugin_activate (info->plugin, GEDIT_WINDOW (wins->data));
+		g_warning ("Could not find loader `%s' for plugin `%s'", info->loader, info->name);
+		info->available = FALSE;
+		return FALSE;
+	}
+	
+	path = g_path_get_dirname (info->file);
+	g_return_val_if_fail (path != NULL, FALSE);
 
-		info->active = TRUE;
+	info->plugin = gedit_plugin_loader_load (loader, info, path);
+	
+	g_free (path);
+	
+	if (info->plugin == NULL)
+	{
+		g_warning ("Error loading plugin '%s'", info->name);
+		info->available = FALSE;
+		return FALSE;
 	}
-	else
-		g_warning ("Error activating plugin '%s'", info->name);
+	
+	return TRUE;
+}
+
+static void
+gedit_plugins_engine_activate_plugin_real (GeditPluginsEngine *engine,
+					   GeditPluginInfo *info)
+{
+	if (!load_plugin (engine, info))
+		return;
+
+	/* activate plugin for all windows */
+	const GList *wins = gedit_app_get_windows (gedit_app_get_default ());
+	for (; wins != NULL; wins = wins->next)
+		gedit_plugin_activate (info->plugin, GEDIT_WINDOW (wins->data));
 }
 
 gboolean
@@ -461,17 +656,17 @@
 
 	g_return_val_if_fail (info != NULL, FALSE);
 
-	if (!info->available)
+	if (!gedit_plugin_info_is_available (info))
 		return FALSE;
 		
-	if (info->active)
+	if (gedit_plugin_info_is_active (info))
 		return TRUE;
 
 	g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
-	if (info->active)
+	if (gedit_plugin_info_is_active (info))
 		save_active_plugin_list (engine);
 
-	return info->active;
+	return gedit_plugin_info_is_active (info);
 }
 
 static void
@@ -479,15 +674,26 @@
 					     GeditPluginInfo *info)
 {
 	const GList *wins;
+	GeditPluginLoader *loader;
 
-	if (!info->active || !info->available)
+	if (!gedit_plugin_info_is_active (info) || 
+	    !gedit_plugin_info_is_available (info))
 		return;
 
 	wins = gedit_app_get_windows (gedit_app_get_default ());
 	for (; wins != NULL; wins = wins->next)
 		gedit_plugin_deactivate (info->plugin, GEDIT_WINDOW (wins->data));
 
-	info->active = FALSE;
+	/* first unref the plugin (the loader still has one) */
+	g_object_unref (info->plugin);
+	
+	/* find the loader and tell it to gc and unload the plugin */
+	loader = get_plugin_loader (engine, info);
+	
+	gedit_plugin_loader_garbage_collect (loader);
+	gedit_plugin_loader_unload (loader, info);
+	
+	info->plugin = NULL;
 }
 
 gboolean
@@ -498,14 +704,14 @@
 
 	g_return_val_if_fail (info != NULL, FALSE);
 
-	if (!info->active || !info->available)
+	if (!gedit_plugin_info_is_active (info))
 		return TRUE;
 
 	g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
-	if (!info->active)
+	if (!gedit_plugin_info_is_active (info))
 		save_active_plugin_list (engine);
 
-	return !info->active;
+	return !gedit_plugin_info_is_active (info);
 }
 
 static void
@@ -513,25 +719,43 @@
 		GeditWindow        *window)
 {
 	GList *pl;
-
+	GSList *active_plugins = NULL;
+	
 	gedit_debug (DEBUG_PLUGINS);
+	
+	if (engine->priv->activate_from_gconf)
+	{
+		active_plugins = gconf_client_get_list (engine->priv->gconf_client,
+							GEDIT_PLUGINS_ENGINE_KEY,
+							GCONF_VALUE_STRING,
+							NULL);
+	}
 
 	for (pl = engine->priv->plugin_list; pl; pl = pl->next)
 	{
-		gboolean res = TRUE;
-		
 		GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
 
-		/* If plugin is not available, don't try to activate/load it */
-		if (info->available && info->active)
-		{		
-			if (info->plugin == NULL)
-				res = load_plugin_module (info);
-				
-			if (res)
-				gedit_plugin_activate (info->plugin,
-						       window);			
-		}
+		
+		if (engine->priv->activate_from_gconf && 
+		    g_slist_find_custom (active_plugins,
+					 gedit_plugin_info_get_module_name (info),
+					 (GCompareFunc)strcmp) == NULL)
+			continue;
+		
+		/* If plugin is not active, don't try to activate/load it */
+		if (!engine->priv->activate_from_gconf && 
+		    !gedit_plugin_info_is_active (info))
+			continue;
+
+		if (load_plugin (engine, info))
+			gedit_plugin_activate (info->plugin,
+					       window);
+	}
+	
+	if (engine->priv->activate_from_gconf)
+	{
+		g_slist_free (active_plugins);
+		engine->priv->activate_from_gconf = FALSE;
 	}
 	
 	gedit_debug_message (DEBUG_PLUGINS, "End");
@@ -556,7 +780,7 @@
 	{
 		GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
 
-		if (!info->available || !info->active)
+		if (!gedit_plugin_info_is_active (info))
 			continue;
 			
 	       	gedit_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name);
@@ -631,16 +855,16 @@
 	{
 		GeditPluginInfo *info = (GeditPluginInfo*)pl->data;
 
-		if (!info->available)
+		if (!gedit_plugin_info_is_available (info))
 			continue;
 
 		to_activate = (g_slist_find_custom (active_plugins,
-						    info->module_name,
+						    gedit_plugin_info_get_module_name (info),
 						    (GCompareFunc)strcmp) != NULL);
 
-		if (!info->active && to_activate)
+		if (!gedit_plugin_info_is_active (info) && to_activate)
 			g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
-		else if (info->active && !to_activate)
+		else if (gedit_plugin_info_is_active (info) && !to_activate)
 			g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
 	}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]