[geany/geany] 75827c: plugins: Refactor legacy plugin support

Thomas Martitz git-noreply at xxxxx
Sun Aug 23 18:01:38 UTC 2015


Branch:      refs/heads/master
Author:      Thomas Martitz <kugel at rockbox.org>
Committer:   Thomas Martitz <kugel at rockbox.org>
Date:        Sun, 23 Aug 2015 18:01:38 UTC
Commit:      75827c69c0ba5c1b01cd0992fc6ef6354a9b0c38
             https://github.com/geany/geany/commit/75827c69c0ba5c1b01cd0992fc6ef6354a9b0c38

Log Message:
-----------
plugins: Refactor legacy plugin support

With geany_plugin_set_data() the legacy plugin support can be made
more transparent by using wrapper functions that call the actual plugin_*
functions. This allows to remove the differentiation in code that's not
directly concerned with actually loading plugins.

This commit doesn't change anything except for one thing: legacy plugins now
cannot call geany_plugin_set_data(). But it is meant for new-style plugins
anyway.


Modified Paths:
--------------
    src/pluginprivate.h
    src/plugins.c
    src/pluginutils.c

Modified: src/pluginprivate.h
22 lines changed, 2 insertions(+), 20 deletions(-)
===================================================================
@@ -32,8 +32,6 @@
 
 G_BEGIN_DECLS
 
-typedef struct GeanyData GeanyData;
-
 typedef struct SignalConnection
 {
 	GObject	*object;
@@ -41,17 +39,6 @@ typedef struct SignalConnection
 }
 SignalConnection;
 
-typedef struct _GeanyPluginFuncsLegacy
-{
-	void		(*init) (GeanyData *data);			/* Called when the plugin is enabled */
-	GtkWidget*	(*configure) (GtkDialog *dialog);	/* plugins configure dialog, optional */
-	void		(*configure_single) (GtkWidget *parent); /* plugin configure dialog, optional */
-	void		(*help) (void);						/* Called when the plugin should show some help, optional */
-	void		(*cleanup) (void);					/* Called when the plugin is disabled or when Geany exits */
-	void		(*set_info) (PluginInfo *info);		/* Called to let the plugin provide metadata for the PM dialog */
-}
-GeanyPluginFuncsLegacy;
-
 typedef enum _LoadedFlags {
 	LOADED_OK = 0x01,
 	IS_LEGACY = 0x02,
@@ -65,13 +52,8 @@ typedef struct GeanyPluginPrivate
 	PluginInfo		info;				/* plugin name, description, etc */
 	GeanyPlugin		public;				/* fields the plugin can read */
 
-	union {
-		GeanyPluginFuncs n;					/* new-style callbacks, set by geany_plugin_register()
-											 * NULL for legacy plugins (they do not call
-											 * geany_plugin_register()) */
-		GeanyPluginFuncsLegacy l;			/* old callbacks, complete with set_info(), version_check()
-											 * and configure_single. Deprecated */
-	} cbs;
+	GeanyPluginFuncs cbs;					/* Callbacks set by geany_plugin_register() */
+	void		(*configure_single) (GtkWidget *parent); /* plugin configure dialog, optional and deprecated */
 
 	/* extra stuff */
 	PluginFields	fields;


Modified: src/plugins.c
125 lines changed, 75 insertions(+), 50 deletions(-)
===================================================================
@@ -321,6 +321,45 @@ gboolean geany_plugin_register(GeanyPlugin *plugin, gint api_version, gint min_a
 	return PLUGIN_LOADED_OK(p);
 }
 
+struct LegacyRealFuncs
+{
+	void       (*init) (GeanyData *data);
+	GtkWidget* (*configure) (GtkDialog *dialog);
+	void       (*help) (void);
+	void       (*cleanup) (void);
+};
+
+/* Wrappers to support legacy plugins are below */
+static void legacy_init(GeanyPlugin *plugin, gpointer pdata)
+{
+	struct LegacyRealFuncs *h = pdata;
+	h->init(plugin->geany_data);
+}
+
+static void legacy_cleanup(GeanyPlugin *plugin, gpointer pdata)
+{
+	struct LegacyRealFuncs *h = pdata;
+	/* Can be NULL because it's optional for legacy plugins */
+	if (h->cleanup)
+		h->cleanup();
+}
+
+static void legacy_help(GeanyPlugin *plugin, gpointer pdata)
+{
+	struct LegacyRealFuncs *h = pdata;
+	h->help();
+}
+
+static GtkWidget *legacy_configure(GeanyPlugin *plugin, GtkDialog *parent, gpointer pdata)
+{
+	struct LegacyRealFuncs *h = pdata;
+	return h->configure(parent);
+}
+
+static void free_legacy_cbs(gpointer data)
+{
+	g_slice_free(struct LegacyRealFuncs, data);
+}
 
 /* This function is the equivalent of geany_plugin_register() for legacy-style
  * plugins which we continue to load for the time being. */
@@ -328,18 +367,20 @@ static void register_legacy_plugin(Plugin *plugin, GModule *module)
 {
 	gint (*p_version_check) (gint abi_version);
 	void (*p_set_info) (PluginInfo *info);
+	void (*p_init) (GeanyData *geany_data);
 	GeanyData **p_geany_data;
+	struct LegacyRealFuncs *h;
 
-#define CHECK_FUNC(__x, p)                                                                \
-	if (! g_module_symbol(module, "plugin_" #__x, (void *) (p)))                          \
+#define CHECK_FUNC(__x)                                                                   \
+	if (! g_module_symbol(module, "plugin_" #__x, (void *) (&p_##__x)))                   \
 	{                                                                                     \
 		geany_debug("Plugin \"%s\" has no plugin_" #__x "() function - ignoring plugin!", \
 				g_module_name(plugin->module));                                           \
 		return;                                                                           \
 	}
-	CHECK_FUNC(version_check, &p_version_check);
-	CHECK_FUNC(set_info, &p_set_info);
-	CHECK_FUNC(init, &plugin->cbs.l.init);
+	CHECK_FUNC(version_check);
+	CHECK_FUNC(set_info);
+	CHECK_FUNC(init);
 #undef CHECK_FUNC
 
 	/* We must verify the version first. If the plugin has become incompatible any
@@ -347,6 +388,8 @@ static void register_legacy_plugin(Plugin *plugin, GModule *module)
 	if (! plugin_check_version(plugin, p_version_check(GEANY_ABI_VERSION)))
 		return;
 
+	h = g_slice_new(struct LegacyRealFuncs);
+
 	/* Since the version check passed we can proceed with setting basic fields and
 	 * calling its set_info() (which might want to call Geany functions already). */
 	g_module_symbol(module, "geany_data", (void *) &p_geany_data);
@@ -356,31 +399,38 @@ static void register_legacy_plugin(Plugin *plugin, GModule *module)
 	p_set_info(&plugin->info);
 
 	/* If all went well we can set the remaining callbacks and let it go for good. */
-	g_module_symbol(module, "plugin_configure", (void *) &plugin->cbs.l.configure);
-	g_module_symbol(module, "plugin_configure_single", (void *) &plugin->cbs.l.configure_single);
-	g_module_symbol(module, "plugin_help", (void *) &plugin->cbs.l.help);
-	g_module_symbol(module, "plugin_cleanup", (void *) &plugin->cbs.l.cleanup);
-
+	h->init = p_init;
+	g_module_symbol(module, "plugin_configure", (void *) &h->configure);
+	g_module_symbol(module, "plugin_configure_single", (void *) &plugin->configure_single);
+	g_module_symbol(module, "plugin_help", (void *) &h->help);
+	g_module_symbol(module, "plugin_cleanup", (void *) &h->cleanup);
+	/* pointer to callbacks struct can be stored directly, no wrapper necessary */
+	g_module_symbol(module, "plugin_callbacks", (void *) &plugin->cbs.callbacks);
 	if (app->debug_mode)
 	{
-		if (plugin->cbs.l.configure && plugin->cbs.l.configure_single)
+		if (h->configure && plugin->configure_single)
 			g_warning("Plugin '%s' implements plugin_configure_single() unnecessarily - "
 				"only plugin_configure() will be used!",
 				plugin->info.name);
-		if (plugin->cbs.l.cleanup == NULL)
+		if (h->cleanup == NULL)
 			g_warning("Plugin '%s' has no plugin_cleanup() function - there may be memory leaks!",
 				plugin->info.name);
 	}
 
+	plugin->cbs.init = legacy_init;
+	plugin->cbs.cleanup = legacy_cleanup;
+	plugin->cbs.configure = h->configure ? legacy_configure : NULL;
+	plugin->cbs.help = h->help ? legacy_help : NULL;
+
 	plugin->flags = LOADED_OK | IS_LEGACY;
+	geany_plugin_set_data(&plugin->public, h, free_legacy_cbs);
 }
 
 
 static void
 plugin_load(Plugin *plugin)
 {
-	PluginCallback *callbacks;
-
+	/* Start the plugin. Legacy plugins require additional cruft. */
 	if (PLUGIN_IS_LEGACY(plugin))
 	{
 		GeanyPlugin **p_geany_plugin;
@@ -399,26 +449,22 @@ plugin_load(Plugin *plugin)
 			*plugin_fields = &plugin->fields;
 		read_key_group(plugin);
 
-		/* start the plugin */
-		plugin->cbs.l.init(&geany_data);
+		plugin->cbs.init(&plugin->public, plugin->cb_data);
 
 		/* now read any plugin-owned data that might have been set in plugin_init() */
 		if (plugin->fields.flags & PLUGIN_IS_DOCUMENT_SENSITIVE)
 		{
 			ui_add_document_sensitive(plugin->fields.menu_item);
 		}
-
-		g_module_symbol(plugin->module, "plugin_callbacks", (void *) &callbacks);
 	}
 	else
 	{
-		plugin->cbs.n.init(&plugin->public, plugin->cb_data);
-		callbacks = plugin->cbs.n.callbacks;
+		plugin->cbs.init(&plugin->public, plugin->cb_data);
 	}
 
 	/* new-style plugins set their callbacks in geany_load_module() */
-	if (callbacks)
-		add_callbacks(plugin, callbacks);
+	if (plugin->cbs.callbacks)
+		add_callbacks(plugin, plugin->cbs.callbacks);
 
 	/* remember which plugins are active.
 	 * keep list sorted so tools menu items and plugin preference tabs are
@@ -490,7 +536,7 @@ plugin_new(const gchar *fname, gboolean load_plugin, gboolean add_to_list)
 	plugin->public.priv = plugin;
 	/* Fields of plugin->info/funcs must to be initialized by the plugin */
 	plugin->public.info = &plugin->info;
-	plugin->public.funcs = &plugin->cbs.n;
+	plugin->public.funcs = &plugin->cbs;
 
 	g_module_symbol(module, "geany_load_module", (void *) &p_geany_load_module);
 	if (p_geany_load_module)
@@ -617,11 +663,8 @@ plugin_cleanup(Plugin *plugin)
 {
 	GtkWidget *widget;
 
-	/* With geany_plugin_register() cleanup is mandatory */
-	if (! PLUGIN_IS_LEGACY(plugin))
-		plugin->cbs.n.cleanup(&plugin->public, plugin->cb_data);
-	else if (plugin->cbs.l.cleanup)
-		plugin->cbs.l.cleanup();
+	/* With geany_register_plugin cleanup is mandatory */
+	plugin->cbs.cleanup(&plugin->public, plugin->cb_data);
 
 	remove_callbacks(plugin);
 	remove_sources(plugin);
@@ -945,12 +988,7 @@ gboolean plugins_have_preferences(void)
 	foreach_list(item, active_plugin_list)
 	{
 		Plugin *plugin = item->data;
-		gboolean result;
-		if (! PLUGIN_IS_LEGACY(plugin))
-			result = plugin->cbs.n.configure != NULL;
-		else
-			result = plugin->cbs.l.configure != NULL || plugin->cbs.l.configure_single != NULL;
-		if (result)
+		if (plugin->configure_single != NULL || plugin->cbs.configure != NULL)
 			return TRUE;
 	}
 
@@ -997,16 +1035,8 @@ static void pm_update_buttons(Plugin *p)
 
 	if (p != NULL && is_active_plugin(p))
 	{
-		if (PLUGIN_IS_LEGACY(p))
-		{
-			has_configure = p->cbs.l.configure || p->cbs.l.configure_single;
-			has_help = p->cbs.l.help != NULL;
-		}
-		else
-		{
-			has_configure = p->cbs.n.configure != NULL;
-			has_help = p->cbs.n.help != NULL;
-		}
+		has_configure = p->cbs.configure || p->configure_single;
+		has_help = p->cbs.help != NULL;
 		has_keybindings = p->key_group && p->key_group->plugin_key_count;
 	}
 
@@ -1345,12 +1375,7 @@ static void pm_on_plugin_button_clicked(G_GNUC_UNUSED GtkButton *button, gpointe
 			if (GPOINTER_TO_INT(user_data) == PM_BUTTON_CONFIGURE)
 				plugin_show_configure(&p->public);
 			else if (GPOINTER_TO_INT(user_data) == PM_BUTTON_HELP)
-			{
-				if (PLUGIN_IS_LEGACY(p))
-					p->cbs.l.help();
-				else
-					p->cbs.n.help(&p->public, p->cb_data);
-			}
+				p->cbs.help(&p->public, p->cb_data);
 			else if (GPOINTER_TO_INT(user_data) == PM_BUTTON_KEYBINDINGS && p->key_group && p->key_group->plugin_key_count > 0)
 				keybindings_dialog_show_prefs_scroll(p->info.name);
 		}


Modified: src/pluginutils.c
24 lines changed, 9 insertions(+), 15 deletions(-)
===================================================================
@@ -310,7 +310,7 @@ GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin,
 
 static void on_pref_btn_clicked(gpointer btn, Plugin *p)
 {
-	p->cbs.l.configure_single(main_widgets.window);
+	p->configure_single(main_widgets.window);
 }
 
 
@@ -318,16 +318,9 @@ static GtkWidget *create_pref_page(Plugin *p, GtkWidget *dialog)
 {
 	GtkWidget *page = NULL;	/* some plugins don't have prefs */
 
-	if (!PLUGIN_IS_LEGACY(p))
-	{
-		if (p->cbs.n.configure)
-			page = p->cbs.n.configure(&p->public, GTK_DIALOG(dialog), p->cb_data);
-	}
-	else if (p->cbs.l.configure)
-		page = p->cbs.l.configure(GTK_DIALOG(dialog));
-
-	if (page)
+	if (p->cbs.configure)
 	{
+		page = p->cbs.configure(&p->public, GTK_DIALOG(dialog), p->cb_data);
 		if (! GTK_IS_WIDGET(page))
 		{
 			geany_debug("Invalid widget returned from plugin_configure() in plugin \"%s\"!",
@@ -344,7 +337,7 @@ static GtkWidget *create_pref_page(Plugin *p, GtkWidget *dialog)
 			gtk_box_pack_start(GTK_BOX(page), align, TRUE, TRUE, 0);
 		}
 	}
-	else if (PLUGIN_IS_LEGACY(p) && p->cbs.l.configure_single)
+	else if (p->configure_single)
 	{
 		GtkWidget *align = gtk_alignment_new(0.5, 0.5, 0, 0);
 		GtkWidget *btn;
@@ -427,12 +420,12 @@ void plugin_show_configure(GeanyPlugin *plugin)
 	}
 	p = plugin->priv;
 
-	if (!PLUGIN_IS_LEGACY(p) || p->cbs.l.configure)
+	if (p->cbs.configure)
 		configure_plugins(p);
 	else
 	{
-		g_return_if_fail(p->cbs.l.configure_single);
-		p->cbs.l.configure_single(main_widgets.window);
+		g_return_if_fail(p->configure_single);
+		p->configure_single(main_widgets.window);
 	}
 }
 
@@ -531,7 +524,8 @@ void plugin_builder_connect_signals(GeanyPlugin *plugin,
  * by passing g_object_unref() as @a free_func, so that member functions can be used
  * for the @ref GeanyPluginFuncs (via wrappers) but you can set completely custom data.
  *
- * Be aware that this can only be called once.
+ * Be aware that this can only be called once and only by plugins registered via
+ * @ref geany_plugin_register(). So-called legacy plugins cannot use this function.
  *
  * @param plugin The plugin provided by Geany
  * @param pdata The plugin's data to associate, must not be @c NULL



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list