diff --git a/ChangeLog b/ChangeLog index 19540ed5a..a1e08d472 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,15 @@ * data/filetypes.markdown: Add filetypes.markdown for configuration (thanks to Jon Strait). + * src/build.c, src/keybindings.c, src/keybindings.h, src/plugindata.h, + src/pluginutils.c, src/plugins.c, src/pluginutils.h, + plugins/geanyfunctions.h: + Remove GeanyKeyGroup struct from the API - plugins should not set + these fields. + Make keybindings_set_item() duplicate the name and label fields + (needed by GeanyLua) and return a keybinding pointer. + Add keybindings_get_item() to the API (in case it's useful). + Move some keybinding code out of plugin source files. 2009-08-24 Nick Treleaven diff --git a/plugins/geanyfunctions.h b/plugins/geanyfunctions.h index a19f19bfa..9a8391a62 100644 --- a/plugins/geanyfunctions.h +++ b/plugins/geanyfunctions.h @@ -254,6 +254,8 @@ geany_functions->p_keybindings->send_command #define keybindings_set_item \ geany_functions->p_keybindings->set_item +#define keybindings_get_item \ + geany_functions->p_keybindings->get_item #define tm_get_real_path \ geany_functions->p_tm->get_real_path #define tm_source_file_new \ diff --git a/src/build.c b/src/build.c index 70769a4b2..9a1304800 100644 --- a/src/build.c +++ b/src/build.c @@ -139,7 +139,7 @@ void build_finalize(void) static void add_menu_accel(GeanyKeyGroup *group, guint kb_id, GtkAccelGroup *accel_group, GtkWidget *menuitem) { - GeanyKeyBinding *kb = &group->keys[kb_id]; + GeanyKeyBinding *kb = keybindings_get_item(group, kb_id); if (kb->key != 0) gtk_widget_add_accelerator(menuitem, "activate", accel_group, diff --git a/src/keybindings.c b/src/keybindings.c index f15d77493..185e9c640 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -25,9 +25,12 @@ * Configurable keyboard shortcuts. */ -#include #include "geany.h" + +#include +#include + #include "keybindings.h" #include "support.h" #include "utils.h" @@ -109,6 +112,19 @@ static void cb_func_move_tab(guint key_id); static void add_popup_menu_accels(void); +/** Lookup a keybinding item. + * @param group Group. + * @param key_id Keybinding index for the group. + * @return The keybinding. + * @since 0.19. */ +GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id) +{ + g_assert(key_id < group->count); + + return &group->keys[key_id]; +} + + /* This is used to set default keybindings on startup. * Menu accels are set in apply_kb_accel(). */ /** Simple convenience function to fill a GeanyKeyBinding struct item. @@ -117,25 +133,32 @@ static void add_popup_menu_accels(void); * @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 Key name for the configuration file, such as @c "menu_new". + * @param kf_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, + * @param menu_item Optional widget to set an accelerator for, or @c NULL. + * @return The keybinding - normally this is ignored. */ +GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, GeanyKeyCallback callback, guint key, GdkModifierType mod, - gchar *name, gchar *label, GtkWidget *menu_item) + gchar *kf_name, gchar *label, GtkWidget *menu_item) { - GeanyKeyBinding *kb; + GeanyKeyBinding *kb = keybindings_get_item(group, key_id); - g_assert(key_id < group->count); - - kb = &group->keys[key_id]; - - kb->name = name; - kb->label = label; + if (group->plugin) + { + /* some plugins e.g. GeanyLua need these fields duplicated */ + setptr(kb->name, g_strdup(kf_name)); + setptr(kb->label, g_strdup(label)); + } + else + { + kb->name = kf_name; + kb->label = label; + } kb->key = key; kb->mods = mod; kb->callback = callback; kb->menu_item = menu_item; + return kb; } @@ -2271,3 +2294,46 @@ void keybindings_update_combo(GeanyKeyBinding *kb, guint key, GdkModifierType mo kb->key, kb->mods, GTK_ACCEL_VISIBLE); } + +/* used for plugins */ +GeanyKeyGroup *keybindings_set_group(GeanyKeyGroup *group, const gchar *section_name, + const gchar *label, gsize count, GeanyKeyGroupCallback callback) +{ + g_return_val_if_fail(section_name, NULL); + g_return_val_if_fail(count, NULL); + g_return_val_if_fail(!callback, NULL); + + /* prevent conflict with core bindings */ + g_return_val_if_fail(!g_str_equal(section_name, keybindings_keyfile_group_name), NULL); + + if (!group) + group = g_new0(GeanyKeyGroup, 1); + + if (!group->keys || count > group->count) + { + /* allow resizing existing array of keys */ + group->keys = g_renew(GeanyKeyBinding, group->keys, count); + memset(group->keys + group->count, 0, (count - group->count) * sizeof(GeanyKeyBinding)); + } + group->plugin = TRUE; + add_kb_group(group, section_name, label, count, group->keys); + return group; +} + + +/* used for plugins */ +void keybindings_free_group(GeanyKeyGroup *group) +{ + GeanyKeyBinding *kb; + + g_assert(group->plugin); + + foreach_c_array(kb, group->keys, group->count) + { + g_free(kb->name); + g_free(kb->label); + } + g_free(group->keys); + g_ptr_array_remove_fast(keybinding_groups, group); + g_free(group); +} diff --git a/src/keybindings.h b/src/keybindings.h index bd3ac4f23..2b38cc75d 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -34,9 +34,8 @@ /** Function pointer type used for keybinding callbacks. */ typedef void (*GeanyKeyCallback) (guint key_id); -/** 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(). */ +/** Represents a single keybinding action. + * Use keybindings_set_item() to set. */ typedef struct GeanyKeyBinding { guint key; /**< Key value in lower-case, such as @c GDK_a or 0 */ @@ -45,18 +44,22 @@ typedef struct GeanyKeyBinding gchar *label; /**< Label used in the preferences dialog keybindings tab */ 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. 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; /**< The number of keybindings the group holds */ - GeanyKeyBinding *keys; /* array of GeanyKeyBinding structs */ } -GeanyKeyGroup; +GeanyKeyBinding; + +/** A collection of keybindings grouped together. */ +typedef struct GeanyKeyGroup GeanyKeyGroup; + +/* Plugins should not set these fields. */ +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; /* number of keybindings the group holds */ + GeanyKeyBinding *keys; /* array of GeanyKeyBinding structs */ + gboolean plugin; /* used by plugin */ +}; + extern GPtrArray *keybinding_groups; /* array of GeanyKeyGroup pointers */ @@ -318,10 +321,20 @@ void keybindings_load_keyfile(void); void keybindings_free(void); -void keybindings_set_item(GeanyKeyGroup *group, gsize key_id, +/** Function pointer type used for keybinding group callbacks. */ +typedef gboolean (*GeanyKeyGroupCallback) (guint key_id); + +GeanyKeyGroup *keybindings_set_group(GeanyKeyGroup *group, const gchar *section_name, + const gchar *label, gsize count, GeanyKeyGroupCallback callback) G_GNUC_WARN_UNUSED_RESULT; + +void keybindings_free_group(GeanyKeyGroup *group); + +GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, GeanyKeyCallback callback, guint key, GdkModifierType mod, gchar *name, gchar *label, GtkWidget *menu_item); +GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id); + void keybindings_update_combo(GeanyKeyBinding *kb, guint key, GdkModifierType mods); void keybindings_send_command(guint group_id, guint key_id); diff --git a/src/plugindata.h b/src/plugindata.h index 3dab9cf4c..030543281 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -50,7 +50,7 @@ enum { /** The Application Programming Interface (API) version, incremented * whenever any plugin data types are modified or appended to. */ - GEANY_API_VERSION = 152, + GEANY_API_VERSION = 153, /** The Application Binary Interface (ABI) version, incremented whenever * existing fields in the plugin data types have to be changed or reordered. */ @@ -471,9 +471,11 @@ typedef void (*_GeanyKeyCallback) (guint key_id); typedef struct KeybindingFuncs { void (*send_command) (guint group_id, guint key_id); - void (*set_item) (struct GeanyKeyGroup *group, gsize key_id, + struct GeanyKeyBinding* (*set_item) (struct GeanyKeyGroup *group, gsize key_id, _GeanyKeyCallback callback, guint key, GdkModifierType mod, gchar *name, gchar *label, GtkWidget *menu_item); + struct GeanyKeyBinding* (*get_item)(struct GeanyKeyGroup *group, gsize key_id); + } KeybindingFuncs; diff --git a/src/plugins.c b/src/plugins.c index 419e54d49..583afef10 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -243,7 +243,8 @@ static EncodingFuncs encoding_funcs = { static KeybindingFuncs keybindings_funcs = { &keybindings_send_command, - &keybindings_set_item + &keybindings_set_item, + &keybindings_get_item }; static TagManagerFuncs tagmanager_funcs = { @@ -684,11 +685,8 @@ plugin_cleanup(Plugin *plugin) 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); - } + keybindings_free_group(plugin->key_group); + widget = plugin->toolbar_separator.widget; if (widget) gtk_widget_destroy(widget); diff --git a/src/pluginutils.c b/src/pluginutils.c index 7e21100f5..d551ce9b2 100644 --- a/src/pluginutils.c +++ b/src/pluginutils.c @@ -28,8 +28,6 @@ #include "geany.h" -#include - #include "pluginutils.h" #include "pluginprivate.h" @@ -140,40 +138,11 @@ void plugin_signal_connect(GeanyPlugin *plugin, 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; + priv->key_group = keybindings_set_group(priv->key_group, section_name, + priv->info.name, count, callback); + return priv->key_group; } diff --git a/src/pluginutils.h b/src/pluginutils.h index 3c9982a80..055a2069e 100644 --- a/src/pluginutils.h +++ b/src/pluginutils.h @@ -26,7 +26,9 @@ #ifndef PLUGINUTILS_H #define PLUGINUTILS_H -#include "plugindata.h" /* GeanyPlugin */ +#include "plugindata.h" /* GeanyPlugin */ +#include "keybindings.h" /* GeanyKeyGroupCallback */ + void plugin_add_toolbar_item(GeanyPlugin *plugin, GtkToolItem *item); @@ -36,10 +38,6 @@ void plugin_signal_connect(GeanyPlugin *plugin, 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);