[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