SF.net SVN: geany:[4115] trunk
ntrel at users.sourceforge.net
ntrel at xxxxx
Mon Aug 24 11:35:13 UTC 2009
Revision: 4115
http://geany.svn.sourceforge.net/geany/?rev=4115&view=rev
Author: ntrel
Date: 2009-08-24 11:35:13 +0000 (Mon, 24 Aug 2009)
Log Message:
-----------
Update PLUGIN_KEY_GROUP() macro so it doesn't allocate any
GeanyKeyBinding or GeanyKeyGroup structs, so we don't need to break
the ABI when adding fields to them.
Add plugin_set_key_group() for plugins to dynamically set a
keybinding group (e.g. for the Lua script plugin). Used in Split
Window plugin as an example.
Improve keybinding docs a little.
Modified Paths:
--------------
trunk/ChangeLog
trunk/doc/pluginsymbols.c
trunk/plugins/geanyfunctions.h
trunk/plugins/splitwindow.c
trunk/src/keybindings.c
trunk/src/keybindings.h
trunk/src/plugindata.h
trunk/src/plugins.c
trunk/src/pluginutils.c
trunk/src/pluginutils.h
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/ChangeLog 2009-08-24 11:35:13 UTC (rev 4115)
@@ -1,3 +1,18 @@
+2009-08-24 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+
+ * src/keybindings.c, src/keybindings.h, src/plugindata.h,
+ src/pluginutils.c, src/plugins.c, src/pluginutils.h,
+ doc/pluginsymbols.c, plugins/geanyfunctions.h,
+ plugins/splitwindow.c:
+ Update PLUGIN_KEY_GROUP() macro so it doesn't allocate any
+ GeanyKeyBinding or GeanyKeyGroup structs, so we don't need to break
+ the ABI when adding fields to them.
+ Add plugin_set_key_group() for plugins to dynamically set a
+ keybinding group (e.g. for the Lua script plugin). Used in Split
+ Window plugin as an example.
+ Improve keybinding docs a little.
+
+
2009-08-20 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
* doc/Doxyfile.in, plugins/geanyfunctions.h, plugins/genapi.py:
Modified: trunk/doc/pluginsymbols.c
===================================================================
--- trunk/doc/pluginsymbols.c 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/doc/pluginsymbols.c 2009-08-24 11:35:13 UTC (rev 4115)
@@ -70,16 +70,10 @@
* @see plugin_signal_connect(). */
PluginCallback plugin_callbacks[];
-/** Most plugins should use the PLUGIN_KEY_GROUP() macro to define it. However,
- * its fields are not read until after plugin_init() is called for the plugin, so it
- * is possible to setup a variable number of keybindings, e.g. based on the
- * plugin's configuration file settings.
- * - The @c name field must not be empty or match Geany's default group name.
- * - The @c label field is set by Geany after plugin_init() is called to the name of the
- * plugin.
- * @note This is a single element array for implementation reasons,
- * but you can treat it like a pointer. */
-KeyBindingGroup plugin_key_group[1];
+/** Plugins must use the PLUGIN_KEY_GROUP() macro to define it.
+ * To setup a variable number of keybindings, e.g. based on the
+ * plugin's configuration file settings, use plugin_set_key_group() instead. */
+KeyBindingGroup *plugin_key_group;
/** Called before showing the plugin preferences dialog to let the user set some basic
Modified: trunk/plugins/geanyfunctions.h
===================================================================
--- trunk/plugins/geanyfunctions.h 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/plugins/geanyfunctions.h 2009-08-24 11:35:13 UTC (rev 4115)
@@ -22,6 +22,8 @@
geany_functions->p_plugin->module_make_resident
#define plugin_signal_connect \
geany_functions->p_plugin->signal_connect
+#define plugin_set_key_group \
+ geany_functions->p_plugin->set_key_group
#define document_new_file \
geany_functions->p_document->new_file
#define document_get_current \
Modified: trunk/plugins/splitwindow.c
===================================================================
--- trunk/plugins/splitwindow.c 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/plugins/splitwindow.c 2009-08-24 11:35:13 UTC (rev 4115)
@@ -39,6 +39,7 @@
GeanyData *geany_data;
GeanyFunctions *geany_functions;
+GeanyPlugin *geany_plugin;
/* Keybinding(s) */
@@ -50,9 +51,6 @@
KB_COUNT
};
-PLUGIN_KEY_GROUP(split_window, KB_COUNT);
-
-
enum State
{
STATE_SPLIT_HORIZONTAL,
@@ -396,6 +394,7 @@
void plugin_init(GeanyData *data)
{
GtkWidget *item, *menu;
+ GeanyKeyGroup *key_group;
menu_items.main = item = gtk_menu_item_new_with_mnemonic(_("_Split Window"));
gtk_menu_shell_append(GTK_MENU_SHELL(geany_data->main_widgets->tools_menu), item);
@@ -424,11 +423,12 @@
set_state(STATE_UNSPLIT);
/* setup keybindings */
- keybindings_set_item(plugin_key_group, KB_SPLIT_HORIZONTAL, kb_activate,
+ key_group = plugin_set_key_group(geany_plugin, "split_window", KB_COUNT, NULL);
+ keybindings_set_item(key_group, KB_SPLIT_HORIZONTAL, kb_activate,
0, 0, "split_horizontal", _("Split Horizontally"), menu_items.horizontal);
- keybindings_set_item(plugin_key_group, KB_SPLIT_VERTICAL, kb_activate,
+ keybindings_set_item(key_group, KB_SPLIT_VERTICAL, kb_activate,
0, 0, "split_vertical", _("Split Vertically"), menu_items.vertical);
- keybindings_set_item(plugin_key_group, KB_SPLIT_UNSPLIT, kb_activate,
+ keybindings_set_item(key_group, KB_SPLIT_UNSPLIT, kb_activate,
0, 0, "split_unsplit", _("Unsplit"), menu_items.unsplit);
}
Modified: trunk/src/keybindings.c
===================================================================
--- trunk/src/keybindings.c 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/keybindings.c 2009-08-24 11:35:13 UTC (rev 4115)
@@ -114,11 +114,11 @@
/** Simple convenience function to fill a GeanyKeyBinding struct item.
* @param group Group.
* @param key_id Keybinding index for the group.
- * @param callback Function to call when activated.
+ * @param callback Function to call when activated, or @c NULL.
* @param key (Lower case) default key, e.g. @c GDK_j, but usually 0 for unset.
* @param mod Default modifier, e.g. @c GDK_CONTROL_MASK, but usually 0 for unset.
- * @param name Not duplicated - use a static string.
- * @param label Currently not duplicated - use a static or heap-allocated (e.g. translated) string.
+ * @param name Key name for the configuration file, such as @c "menu_new".
+ * @param label Label used in the preferences dialog keybindings tab.
* @param menu_item Optional widget to set an accelerator for, or @c NULL. */
void keybindings_set_item(GeanyKeyGroup *group, gsize key_id,
GeanyKeyCallback callback, guint key, GdkModifierType mod,
Modified: trunk/src/keybindings.h
===================================================================
--- trunk/src/keybindings.h 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/keybindings.h 2009-08-24 11:35:13 UTC (rev 4115)
@@ -31,30 +31,30 @@
#define GEANY_KEYBINDINGS_H 1
-/** Function pointer type used for keybinding callbacks */
+/** Function pointer type used for keybinding callbacks. */
typedef void (*GeanyKeyCallback) (guint key_id);
-/** Represents a single keybinding action */
+/** Represents a single keybinding action. */
/* Note: name and label are not const strings so plugins can set them to malloc'd strings
* and free them in cleanup(). */
typedef struct GeanyKeyBinding
{
- guint key; /**< Key value in lower-case, such as @c GDK_a */
- GdkModifierType mods; /**< Modifier keys, such as @c GDK_CONTROL_MASK */
+ guint key; /**< Key value in lower-case, such as @c GDK_a or 0 */
+ GdkModifierType mods; /**< Modifier keys, such as @c GDK_CONTROL_MASK or 0 */
gchar *name; /**< Key name for the configuration file, such as @c "menu_new" */
gchar *label; /**< Label used in the preferences dialog keybindings tab */
- GeanyKeyCallback callback; /**< Callback function called when the key combination is pressed */
- GtkWidget *menu_item; /**< Menu item widget for setting the menu accelerator */
+ GeanyKeyCallback callback; /**< Function called when the key combination is pressed, or @c NULL */
+ GtkWidget *menu_item; /**< Optional widget to set an accelerator for, or @c NULL */
} GeanyKeyBinding;
-/** A collection of keybindings grouped together. */
+/** A collection of keybindings grouped together. Plugins should not set these fields. */
typedef struct GeanyKeyGroup
{
const gchar *name; /**< Group name used in the configuration file, such as @c "html_chars" */
- const gchar *label; /**< Group label used in the preferences dialog keybindings tab */
- gsize count; /**< Count of GeanyKeyBinding structs in @c keys */
- GeanyKeyBinding *keys; /**< Fixed array of GeanyKeyBinding structs */
+ const gchar *label; /* Group label used in the preferences dialog keybindings tab */
+ gsize count; /**< The number of keybindings the group holds */
+ GeanyKeyBinding *keys; /* array of GeanyKeyBinding structs */
}
GeanyKeyGroup;
Modified: trunk/src/plugindata.h
===================================================================
--- trunk/src/plugindata.h 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/plugindata.h 2009-08-24 11:35:13 UTC (rev 4115)
@@ -50,13 +50,13 @@
enum {
/** The Application Programming Interface (API) version, incremented
* whenever any plugin data types are modified or appended to. */
- GEANY_API_VERSION = 150,
+ GEANY_API_VERSION = 151,
/** The Application Binary Interface (ABI) version, incremented whenever
* existing fields in the plugin data types have to be changed or reordered. */
/* This should usually stay the same if fields are only appended, assuming only pointers to
* structs and not structs themselves are declared by plugins. */
- GEANY_ABI_VERSION = 63
+ GEANY_ABI_VERSION = 64
};
/** Check the plugin can be loaded by Geany.
@@ -119,23 +119,32 @@
}
+/** @see PLUGIN_KEY_GROUP() macro. */
+typedef struct GeanyKeyGroupInfo
+{
+ const gchar *name; /**< Group name used in the configuration file, such as @c "html_chars" */
+ gsize count; /**< The number of keybindings the group will hold */
+}
+GeanyKeyGroupInfo;
+
/** Declare and initialise a keybinding group.
- * @code GeanyKeyGroup plugin_key_group[1]; @endcode
- * You must then set the @c plugin_key_group::keys[] entries for the group in plugin_init().
+ * @code GeanyKeyGroup *plugin_key_group; @endcode
+ * You must then set the @c plugin_key_group::keys[] entries for the group in plugin_init(),
+ * normally using keybindings_set_item().
* The @c plugin_key_group::label field is set by Geany after @c plugin_init()
* is called, to the name of the plugin.
* @param group_name A unique group name (without quotes) to be used in the
* configuration file, such as @c html_chars.
- * @param key_count The number of keybindings the group will hold. */
+ * @param key_count The number of keybindings the group will hold.
+ * @see plugin_set_key_group() to set the group size dynamically. */
#define PLUGIN_KEY_GROUP(group_name, key_count) \
- static GeanyKeyBinding plugin_keys[key_count]; \
- \
- /* We have to declare plugin_key_group as a single element array.
+ /* We have to declare this as a single element array.
* Declaring as a pointer to a struct doesn't work with g_module_symbol(). */ \
- GeanyKeyGroup plugin_key_group[1] = \
+ GeanyKeyGroupInfo plugin_key_group_info[1] = \
{ \
- {G_STRINGIFY(group_name), NULL, key_count, plugin_keys} \
- };
+ {G_STRINGIFY(group_name), key_count} \
+ };\
+ GeanyKeyGroup *plugin_key_group = NULL;
/** Callback array entry type used with the @ref plugin_callbacks symbol. */
@@ -225,7 +234,7 @@
struct NavQueueFuncs *p_navqueue; /**< See navqueue.h */
struct EditorFuncs *p_editor; /**< See editor.h */
struct MainFuncs *p_main; /**< See main.h */
- struct PluginFuncs *p_plugin; /**< See plugins.c */
+ struct PluginFuncs *p_plugin; /**< See pluginutils.c */
struct ScintillaFuncs *p_scintilla; /**< See ScintillaFuncs */
struct MsgWinFuncs *p_msgwin; /**< See msgwindow.h */
}
@@ -541,7 +550,10 @@
EditorFuncs;
-/* See plugins.c */
+/* avoid including keybindings.h */
+typedef gboolean (*_GeanyKeyGroupCallback) (guint key_id);
+
+/* See pluginutils.c */
typedef struct PluginFuncs
{
void (*add_toolbar_item)(GeanyPlugin *plugin, GtkToolItem *item);
@@ -549,6 +561,8 @@
void (*signal_connect) (GeanyPlugin *plugin,
GObject *object, gchar *signal_name, gboolean after,
GCallback callback, gpointer user_data);
+ struct GeanyKeyGroup* (*set_key_group)(GeanyPlugin *plugin,
+ const gchar *section_name, gsize count, _GeanyKeyGroupCallback callback);
}
PluginFuncs;
@@ -556,7 +570,8 @@
/* Deprecated aliases */
#ifndef GEANY_DISABLE_DEPRECATED
-/** @c NULL-safe way to get the index of @a doc_ptr in the documents array. */
+/** @deprecated - copy into your plugin code if needed.
+ * @c NULL-safe way to get the index of @a doc_ptr in the documents array. */
#define DOC_IDX(doc_ptr) \
(doc_ptr ? doc_ptr->index : -1)
#define DOC_IDX_VALID(doc_idx) \
Modified: trunk/src/plugins.c
===================================================================
--- trunk/src/plugins.c 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/plugins.c 2009-08-24 11:35:13 UTC (rev 4115)
@@ -82,7 +82,8 @@
static PluginFuncs plugin_funcs = {
&plugin_add_toolbar_item,
&plugin_module_make_resident,
- &plugin_signal_connect
+ &plugin_signal_connect,
+ &plugin_set_key_group
};
static DocumentFuncs doc_funcs = {
@@ -447,42 +448,36 @@
}
-static void
-add_kb_group(Plugin *plugin)
+static void read_key_group(Plugin *plugin)
{
- guint i;
+ GeanyKeyGroupInfo *p_key_info;
+ GeanyKeyGroup **p_key_group;
- if (!NZV(plugin->key_group->name))
+ g_module_symbol(plugin->module, "plugin_key_group_info", (void *) &p_key_info);
+ g_module_symbol(plugin->module, "plugin_key_group", (void *) &p_key_group);
+ if (p_key_info && p_key_group)
{
- geany_debug("Plugin \"%s\" has not set a name for its keybinding group"
- " - ignoring all keybindings!",
- plugin->info.name);
- return;
- }
- g_return_if_fail(! g_str_equal(plugin->key_group->name, keybindings_keyfile_group_name));
+ GeanyKeyGroupInfo *key_info = p_key_info;
- for (i = 0; i < plugin->key_group->count; i++)
- {
- GeanyKeyBinding *kb = &plugin->key_group->keys[i];
-
- if (!NZV(kb->name))
+ if (*p_key_group)
+ geany_debug("Ignoring plugin_key_group symbol for plugin '%s' - "
+ "use plugin_set_key_group() instead to allocate keybindings dynamically.",
+ plugin->info.name);
+ else
{
- geany_debug("Plugin \"%s\" has not set a name for keybinding %d"
- " - ignoring all keybindings!",
- plugin->info.name, i);
- plugin->key_group->count = 0;
- break;
+ if (key_info->count)
+ {
+ GeanyKeyGroup *key_group =
+ plugin_set_key_group(&plugin->public, key_info->name, key_info->count, NULL);
+ if (key_group)
+ *p_key_group = key_group;
+ }
+ else
+ geany_debug("Ignoring plugin_key_group_info symbol for plugin '%s' - "
+ "count field is zero. Maybe use plugin_set_key_group() instead?",
+ plugin->info.name);
}
}
- if (plugin->key_group->count == 0)
- {
- plugin->key_group = NULL; /* Ignore the group (maybe the plugin has optional KB) */
- return;
- }
-
- plugin->key_group->label = plugin->info.name;
-
- g_ptr_array_add(keybinding_groups, plugin->key_group);
}
@@ -512,6 +507,7 @@
g_module_symbol(plugin->module, "plugin_fields", (void *) &plugin_fields);
if (plugin_fields)
*plugin_fields = &plugin->fields;
+ read_key_group(plugin);
/* start the plugin */
g_return_if_fail(plugin->init);
@@ -539,10 +535,6 @@
if (callbacks)
add_callbacks(plugin, callbacks);
- g_module_symbol(plugin->module, "plugin_key_group", (void *) &plugin->key_group);
- if (plugin->key_group)
- add_kb_group(plugin);
-
/* remember which plugins are active */
active_plugin_list = g_list_append(active_plugin_list, plugin);
@@ -692,8 +684,11 @@
remove_callbacks(plugin);
if (plugin->key_group)
+ {
+ g_free(plugin->key_group->keys);
g_ptr_array_remove_fast(keybinding_groups, plugin->key_group);
-
+ setptr(plugin->key_group, NULL);
+ }
widget = plugin->toolbar_separator.widget;
if (widget)
gtk_widget_destroy(widget);
Modified: trunk/src/pluginutils.c
===================================================================
--- trunk/src/pluginutils.c 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/pluginutils.c 2009-08-24 11:35:13 UTC (rev 4115)
@@ -27,11 +27,15 @@
* These functions all take the @ref geany_plugin symbol as their first argument. */
#include "geany.h"
+
+#include <string.h>
+
#include "pluginutils.h"
#include "pluginprivate.h"
#include "ui_utils.h"
#include "toolbar.h"
+#include "utils.h"
/** Insert a toolbar item before the Quit button, or after the previous plugin toolbar item.
@@ -125,3 +129,51 @@
}
+/** Setup or resize a keybinding group for the plugin.
+ * You should then call keybindings_set_item() for each keybinding in the group.
+ * @param plugin Must be @ref geany_plugin.
+ * @param section_name Name used in the configuration file, such as @c "html_chars".
+ * @param count Number of keybindings for the group.
+ * @param callback Unused, must be @c NULL.
+ * @return The plugin's keybinding group.
+ * @since 0.19. */
+GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin,
+ const gchar *section_name, gsize count, GeanyKeyGroupCallback callback)
+{
+ GeanyKeyGroup *group;
+ GeanyPluginPrivate *priv = plugin->priv;
+
+ g_return_val_if_fail(section_name, NULL);
+ g_return_val_if_fail(count, NULL);
+ g_return_val_if_fail(!callback, NULL);
+
+ if (!priv->key_group)
+ priv->key_group = g_new0(GeanyKeyGroup, 1);
+ group = priv->key_group;
+
+ group->name = section_name;
+
+ if (!group->keys || count > group->count)
+ {
+ group->keys = g_renew(GeanyKeyBinding, group->keys, count);
+ memset(group->keys + group->count, 0, (count - group->count) * sizeof(GeanyKeyBinding));
+ }
+ group->count = count;
+
+ if (!NZV(group->name))
+ {
+ geany_debug("Plugin \"%s\" has not set the name field for its keybinding group"
+ " - ignoring all keybindings!",
+ priv->info.name);
+ return NULL;
+ }
+ /* prevent conflict with core bindings */
+ g_return_val_if_fail(! g_str_equal(group->name, keybindings_keyfile_group_name), NULL);
+
+ group->label = priv->info.name;
+
+ g_ptr_array_add(keybinding_groups, group);
+ return group;
+}
+
+
Modified: trunk/src/pluginutils.h
===================================================================
--- trunk/src/pluginutils.h 2009-08-24 09:41:17 UTC (rev 4114)
+++ trunk/src/pluginutils.h 2009-08-24 11:35:13 UTC (rev 4115)
@@ -26,7 +26,7 @@
#ifndef PLUGINUTILS_H
#define PLUGINUTILS_H
-#include "plugindata.h"
+#include "plugindata.h" /* GeanyPlugin */
void plugin_add_toolbar_item(GeanyPlugin *plugin, GtkToolItem *item);
@@ -36,4 +36,11 @@
GObject *object, gchar *signal_name, gboolean after,
GCallback callback, gpointer user_data);
+
+/** Function pointer type used for keybinding group callbacks. */
+typedef gboolean (*GeanyKeyGroupCallback) (guint key_id);
+
+struct GeanyKeyGroup *plugin_set_key_group(GeanyPlugin *plugin,
+ const gchar *section_name, gsize count, GeanyKeyGroupCallback callback);
+
#endif /* PLUGINUTILS_H */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list