Revision: 1645 http://svn.sourceforge.net/geany/?rev=1645&view=rev Author: ntrel Date: 2007-06-27 08:56:42 -0700 (Wed, 27 Jun 2007)
Log Message: ----------- Move plugin name and description into a separate struct, which is set by calling the PLUGIN_INFO() macro - this can be read before the plugin is initialized. Added more comments for plugin authors.
Modified Paths: -------------- trunk/ChangeLog trunk/plugins/demoplugin.c trunk/src/plugindata.h trunk/src/plugins.c
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2007-06-26 18:08:00 UTC (rev 1644) +++ trunk/ChangeLog 2007-06-27 15:56:42 UTC (rev 1645) @@ -1,3 +1,12 @@ +2007-06-27 Nick Treleaven nick.treleaven@btinternet.com + + * plugins/demoplugin.c, src/plugindata.h, src/plugins.c: + Move plugin name and description into a separate struct, which is set + by calling the PLUGIN_INFO() macro - this can be read before the + plugin is initialized. + Added more comments for plugin authors. + + 2007-06-26 Nick Treleaven nick.treleaven@btinternet.com
* plugins/demoplugin.c, plugins/Makefile.am, configure.in,
Modified: trunk/plugins/demoplugin.c =================================================================== --- trunk/plugins/demoplugin.c 2007-06-26 18:08:00 UTC (rev 1644) +++ trunk/plugins/demoplugin.c 2007-06-27 15:56:42 UTC (rev 1645) @@ -38,12 +38,15 @@ local_data;
-/* This performs runtime checks that try to ensure: - * 1. Geany ABI data types are compatible with this plugin. - * 2. Geany sources provide the required API for this plugin. */ -VERSION_CHECK(1) +/* Check that Geany supports plugin API version 2 or later, and check + * for binary compatibility. */ +VERSION_CHECK(2)
+/* All plugins must set name and description */ +PLUGIN_INFO(_("Demo"), _("Example plugin."))
+ +/* Callback when the menu item is clicked */ static void item_activate(GtkMenuItem *menuitem, gpointer gdata) { @@ -56,28 +59,35 @@ GTK_BUTTONS_OK, _("Hello World!")); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), - _("(From the %s plugin)"), my_data->name); + _("(From the %s plugin)"), info()->name);
gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); }
+/* Called by Geany to initialize the plugin */ void init(PluginData *data) { - my_data = data; - my_data->name = g_strdup("Demo"); + GtkWidget *demo_item;
- local_data.menu_item = gtk_menu_item_new_with_mnemonic(_("_Demo Plugin")); - gtk_widget_show(local_data.menu_item); - gtk_container_add(GTK_CONTAINER(my_data->tools_menu), local_data.menu_item); - g_signal_connect(G_OBJECT(local_data.menu_item), "activate", G_CALLBACK(item_activate), NULL); + my_data = data; // keep a pointer to the main application fields & functions + + // Add an item to the Tools menu + demo_item = gtk_menu_item_new_with_mnemonic(_("_Demo Plugin")); + gtk_widget_show(demo_item); + gtk_container_add(GTK_CONTAINER(my_data->tools_menu), demo_item); + g_signal_connect(G_OBJECT(demo_item), "activate", G_CALLBACK(item_activate), NULL); + + // keep a pointer to the menu item, so we can remove it when the plugin is unloaded + local_data.menu_item = demo_item; }
+/* Called by Geany before unloading the plugin. + * Here any UI changes should be removed, memory freed and any other finalization done */ void cleanup() { + // remove the menu item added in init() gtk_widget_destroy(local_data.menu_item); - - g_free(my_data->name); }
Modified: trunk/src/plugindata.h =================================================================== --- trunk/src/plugindata.h 2007-06-26 18:08:00 UTC (rev 1644) +++ trunk/src/plugindata.h 2007-06-27 15:56:42 UTC (rev 1645) @@ -27,14 +27,16 @@
/* The API version should be incremented whenever any plugin data types below are * modified. */ -static const gint api_version = 1; +static const gint api_version = 2;
/* The ABI version should be incremented whenever existing fields in the plugin * data types below have to be changed or reordered. It should stay the same if fields * are only appended, as this doesn't affect existing fields. */ -static const gint abi_version = 1; +static const gint abi_version = 2;
- +/* This performs runtime checks that try to ensure: + * 1. Geany ABI data types are compatible with this plugin. + * 2. Geany sources provide the required API for this plugin. */ /* TODO: if possible, the API version should be checked at compile time, not runtime. */ #define VERSION_CHECK(api_required) \ gint version_check(gint abi_ver) \ @@ -47,18 +49,37 @@ }
-typedef struct PluginData PluginData; - -struct PluginData +typedef struct PluginInfo { gchar *name; // name of plugin gchar *description; // description of plugin +} +PluginInfo;
+/* Sets the plugin name and a brief description of what it is. */ +#define PLUGIN_INFO(p_name, p_description) \ + PluginInfo *info() \ + { \ + static PluginInfo p_info; \ + \ + p_info.name = (p_name); \ + p_info.description = (p_description); \ + return &p_info; \ + } + + +/* These are fields and functions owned by Geany. + * Fields will be appended when needed by plugin authors. + * Note: Remember to increment api_version (and abi_version if necessary) when + * making changes. */ +typedef struct PluginData +{ MyApp *app; // Geany application data fields
/* Almost all plugins should add menu items to the Tools menu only */ GtkWidget *tools_menu; -}; +} +PluginData;
#endif
Modified: trunk/src/plugins.c =================================================================== --- trunk/src/plugins.c 2007-06-26 18:08:00 UTC (rev 1644) +++ trunk/src/plugins.c 2007-06-27 15:56:42 UTC (rev 1645) @@ -42,6 +42,7 @@ gchar *filename; // plugin filename (/path/libname.so) PluginData data;
+ PluginInfo* (*info) (); /* Returns plugin name, description */ void (*init) (PluginData *data); /* Called when the plugin is enabled */ void (*cleanup) (); /* Called when the plugin is disabled or when Geany exits */ }; @@ -102,6 +103,7 @@ { Plugin *plugin; GModule *module; + PluginInfo* (*info)();
g_return_val_if_fail(fname, NULL); g_return_val_if_fail(g_module_supported(), NULL); @@ -129,7 +131,20 @@ return NULL; }
+ g_module_symbol(module, "info", (void *) &info); + if (info == NULL) + { + geany_debug("Unknown plugin info for "%s"!", fname); + + if (! g_module_close(module)) + g_warning("%s: %s", fname, g_module_error()); + return NULL; + } + geany_debug("Initializing plugin '%s' (%s)", + info()->name, info()->description); + plugin = g_new0(Plugin, 1); + plugin->info = info; plugin->filename = g_strdup(fname); plugin->module = module;
@@ -143,7 +158,7 @@ plugin->init(&plugin->data);
geany_debug("Loaded: %s (%s)", fname, - NVL(plugin->data.name, "<Unknown>")); + NVL(plugin->info()->name, "<Unknown>")); return plugin; }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.