diff --git a/ChangeLog b/ChangeLog index 39781ef6..01754af0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-08-10 Nick Treleaven + + * src/keybindings.c, src/keybindings.h, src/prefs.c, src/plugindata.h: + Use single binding_ids keybinding array instead of individual + arrays for core keybindings. This allows the keybinding IDs to be + merged into one enum; the order of keybindings is now just the + order they are added to each group. Keybindings can be reordered + without breaking the plugin ABI but groups must stay the same. + + 2010-08-05 Enrico Tröger * src/ui_utils.c, src/ui_utils.h: diff --git a/src/keybindings.c b/src/keybindings.c index 7c0beb4d..630fb92e 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -24,7 +24,7 @@ /** * @file keybindings.h * Configurable keyboard shortcuts. - * - keybindings_send_command() mimics a built-in keybinding. + * - keybindings_send_command() mimics a built-in keybinding action. * - @ref GeanyKeyGroupID lists groups of built-in keybindings. * @see plugin_set_key_group(). **/ @@ -65,12 +65,15 @@ GPtrArray *keybinding_groups; /* array of GeanyKeyGroup pointers */ /* keyfile group name for non-plugin KB groups */ -const gchar keybindings_keyfile_group_name[] = "Bindings"; +static const gchar keybindings_keyfile_group_name[] = "Bindings"; + +/* core keybindings */ +static GeanyKeyBinding binding_ids[GEANY_KEYS_COUNT]; static GtkAccelGroup *kb_accel_group = NULL; static const gboolean swap_alt_tab_order = FALSE; -const gsize MAX_MRU_DOCS = 20; +static const gsize MAX_MRU_DOCS = 20; static GQueue *mru_docs = NULL; static guint mru_pos = 0; @@ -125,9 +128,13 @@ static void add_popup_menu_accels(void); * @since 0.19. */ GeanyKeyBinding *keybindings_get_item(GeanyKeyGroup *group, gsize key_id) { - g_assert(key_id < group->count); - - return &group->keys[key_id]; + if (group->plugin) + { + g_assert(key_id < group->plugin_key_count); + return &group->plugin_keys[key_id]; + } + g_assert(key_id < GEANY_KEYS_COUNT); + return &binding_ids[key_id]; } @@ -149,7 +156,12 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, GeanyKeyCallback callback, guint key, GdkModifierType mod, const gchar *kf_name, const gchar *label, GtkWidget *menu_item) { - GeanyKeyBinding *kb = keybindings_get_item(group, key_id); + GeanyKeyBinding *kb; + + g_assert(group->name); + kb = keybindings_get_item(group, key_id); + g_assert(!kb->name); + g_ptr_array_add(group->key_items, kb); if (group->plugin) { @@ -159,7 +171,7 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, } else { - /* we don't touch them unless group->plugin is set, cast is safe */ + /* we don't touch these strings unless group->plugin is set, const cast is safe */ kb->name = (gchar *)kf_name; kb->label = (gchar *)label; } @@ -167,21 +179,21 @@ GeanyKeyBinding *keybindings_set_item(GeanyKeyGroup *group, gsize key_id, kb->mods = mod; kb->callback = callback; kb->menu_item = menu_item; + kb->id = key_id; return kb; } static GeanyKeyGroup *add_kb_group(GeanyKeyGroup *group, - const gchar *name, const gchar *label, gsize count, GeanyKeyBinding *keys, - GeanyKeyGroupCallback callback) + const gchar *name, const gchar *label, GeanyKeyGroupCallback callback, gboolean plugin) { g_ptr_array_add(keybinding_groups, group); group->name = name; group->label = label; - group->count = count; - group->keys = keys; group->callback = callback; + group->plugin = plugin; + group->key_items = g_ptr_array_new(); return group; } @@ -191,16 +203,11 @@ static GeanyKeyGroup *add_kb_group(GeanyKeyGroup *group, ui_lookup_widget(main_widgets.window, G_STRINGIFY(widget_name)) /* Expansion for group_id = FILE: - * static GeanyKeyBinding FILE_keys[GEANY_KEYS_FILE_COUNT]; */ -#define DECLARE_KEYS(group_id) \ - static GeanyKeyBinding group_id ## _keys[GEANY_KEYS_ ## group_id ## _COUNT] - -/* Expansion for group_id = FILE: - * add_kb_group(&groups[GEANY_KEY_GROUP_FILE], NULL, _("File menu"), - * GEANY_KEYS_FILE_COUNT, FILE_keys, callback); */ + * add_kb_group(&groups[GEANY_KEY_GROUP_FILE], + * keybindings_keyfile_group_name, _("File menu"), callback); */ #define ADD_KB_GROUP(group_id, label, callback) \ - add_kb_group(&groups[GEANY_KEY_GROUP_ ## group_id], keybindings_keyfile_group_name, label, \ - GEANY_KEYS_ ## group_id ## _COUNT, group_id ## _keys, callback) + add_kb_group(&groups[GEANY_KEY_GROUP_ ## group_id],\ + keybindings_keyfile_group_name, label, callback, FALSE) /* Init all fields of keys with default values. * The menu_item field is always the main menu item, popup menu accelerators are @@ -209,23 +216,6 @@ static void init_default_kb(void) { static GeanyKeyGroup groups[GEANY_KEY_GROUP_COUNT]; GeanyKeyGroup *group; - DECLARE_KEYS(FILE); - DECLARE_KEYS(PROJECT); - DECLARE_KEYS(EDITOR); - DECLARE_KEYS(CLIPBOARD); - DECLARE_KEYS(SELECT); - DECLARE_KEYS(FORMAT); - DECLARE_KEYS(INSERT); - DECLARE_KEYS(SETTINGS); - DECLARE_KEYS(SEARCH); - DECLARE_KEYS(GOTO); - DECLARE_KEYS(VIEW); - DECLARE_KEYS(FOCUS); - DECLARE_KEYS(NOTEBOOK); - DECLARE_KEYS(DOCUMENT); - DECLARE_KEYS(BUILD); - DECLARE_KEYS(TOOLS); - DECLARE_KEYS(HELP); group = ADD_KB_GROUP(FILE, _("File"), cb_func_file_action); @@ -477,6 +467,7 @@ static void init_default_kb(void) group = ADD_KB_GROUP(FOCUS, _("Focus"), cb_func_switch_action); + /* TODO rearrange these keybindings */ keybindings_set_item(group, GEANY_KEYS_FOCUS_EDITOR, NULL, GDK_F2, 0, "switch_editor", _("Switch to Editor"), NULL); keybindings_set_item(group, GEANY_KEYS_FOCUS_SCRIBBLE, NULL, @@ -621,12 +612,11 @@ void keybindings_init(void) g_signal_connect(geany_object, "document-close", G_CALLBACK(on_document_close), NULL); + memset(binding_ids, 0, sizeof binding_ids); keybinding_groups = g_ptr_array_sized_new(GEANY_KEY_GROUP_COUNT); - kb_accel_group = gtk_accel_group_new(); init_default_kb(); - gtk_window_add_accel_group(GTK_WINDOW(main_widgets.window), kb_accel_group); g_signal_connect(main_widgets.window, "key-press-event", G_CALLBACK(on_key_press_event), NULL); @@ -643,15 +633,10 @@ static void keybindings_foreach(KBItemCallback cb, gpointer user_data) GeanyKeyGroup *group; GeanyKeyBinding *kb; - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - group = g_ptr_array_index(keybinding_groups, g); - for (i = 0; i < group->count; i++) - { - kb = &group->keys[i]; - + foreach_ptr_array(kb, i, group->key_items) cb(group, kb, user_data); - } } } @@ -711,7 +696,7 @@ void keybindings_load_keyfile(void) static void add_menu_accel(GeanyKeyGroup *group, guint kb_id, 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", kb_accel_group, @@ -795,6 +780,12 @@ void keybindings_write_to_file(void) void keybindings_free(void) { + GeanyKeyGroup *group; + gsize g; + + foreach_ptr_array(group, g, keybinding_groups) + keybindings_free_group(group); + g_ptr_array_free(keybinding_groups, TRUE); g_queue_free(mru_docs); } @@ -816,24 +807,20 @@ static void fill_shortcut_labels_treeview(GtkWidget *tree) store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, PANGO_TYPE_WEIGHT); - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - group = g_ptr_array_index(keybinding_groups, g); - if (g > 0) { gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, -1); } - gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, group->label, 2, PANGO_WEIGHT_BOLD, -1); - for (i = 0; i < group->count; i++) + foreach_ptr_array(kb, i, group->key_items) { gchar *shortcut, *label; - kb = &group->keys[i]; label = keybindings_get_label(kb); shortcut = gtk_accelerator_get_label(kb->key, kb->mods); @@ -844,7 +831,6 @@ static void fill_shortcut_labels_treeview(GtkWidget *tree) g_free(label); } } - gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); g_object_unref(store); } @@ -1082,6 +1068,8 @@ static gboolean set_sensitive(gpointer widget) static gboolean check_vte(GdkModifierType state, guint keyval) { guint i; + GeanyKeyBinding *kb; + GeanyKeyGroup *group; GtkWidget *widget; if (! vc->enable_bash_keys) @@ -1095,10 +1083,9 @@ static gboolean check_vte(GdkModifierType state, guint keyval) return FALSE; /* make focus commands override any bash commands */ - for (i = 0; i < GEANY_KEYS_FOCUS_COUNT; i++) + group = g_ptr_array_index(keybinding_groups, GEANY_KEY_GROUP_FOCUS); + foreach_ptr_array(kb, i, group->key_items) { - GeanyKeyBinding *kb = keybindings_lookup_item(GEANY_KEY_GROUP_FOCUS, i); - if (state == kb->mods && keyval == kb->key) return FALSE; } @@ -1179,19 +1166,16 @@ const GeanyKeyBinding *keybindings_check_event(GdkEventKey *ev, gint *group_id, if (keyval >= GDK_KP_Space && keyval < GDK_KP_Equal) keyval = key_kp_translate(keyval); - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - group = g_ptr_array_index(keybinding_groups, g); - - for (i = 0; i < group->count; i++) + foreach_ptr_array(kb, i, group->key_items) { - kb = &group->keys[i]; if (keyval == kb->key && state == kb->mods) { if (group_id != NULL) *group_id = g; if (binding_id != NULL) - *binding_id = i; + *binding_id = kb->id; return kb; } } @@ -1236,24 +1220,21 @@ static gboolean on_key_press_event(GtkWidget *widget, GdkEventKey *ev, gpointer if (check_menu_key(doc, keyval, state, ev->time)) return TRUE; - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - group = g_ptr_array_index(keybinding_groups, g); - - for (i = 0; i < group->count; i++) + foreach_ptr_array(kb, i, group->key_items) { - kb = &group->keys[i]; if (keyval == kb->key && state == kb->mods) { /* call the corresponding callback function for this shortcut */ if (kb->callback) { - kb->callback(i); + kb->callback(kb->id); return TRUE; } else if (group->callback) { - if (group->callback(i)) + if (group->callback(kb->id)) return TRUE; else continue; /* not handled */ @@ -1301,16 +1282,14 @@ GeanyKeyBinding *keybindings_lookup_item(guint group_id, guint key_id) group = g_ptr_array_index(keybinding_groups, group_id); g_return_val_if_fail(group, NULL); - g_return_val_if_fail(key_id < group->count, NULL); - - return &group->keys[key_id]; + return keybindings_get_item(group, key_id); } /** Mimics a (built-in only) keybinding action. * Example: @code keybindings_send_command(GEANY_KEY_GROUP_FILE, GEANY_KEYS_FILE_OPEN); @endcode - * @param group_id The index for the key group that contains the @a key_id keybinding. - * @param key_id The keybinding command index. */ + * @param group_id @ref GeanyKeyGroupID keybinding group index that contains the @a key_id keybinding. + * @param key_id @ref GeanyKeyBindingID keybinding index. */ void keybindings_send_command(guint group_id, guint key_id) { GeanyKeyBinding *kb; @@ -2624,7 +2603,7 @@ void keybindings_update_combo(GeanyKeyBinding *kb, guint key, GdkModifierType mo } -/* used for plugins */ +/* used for plugins, can be called repeatedly. */ GeanyKeyGroup *keybindings_set_group(GeanyKeyGroup *group, const gchar *section_name, const gchar *label, gsize count, GeanyKeyGroupCallback callback) { @@ -2635,33 +2614,33 @@ GeanyKeyGroup *keybindings_set_group(GeanyKeyGroup *group, const gchar *section_ 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 = g_new0(GeanyKeyGroup, 1); + add_kb_group(group, section_name, label, callback, TRUE); } - group->plugin = TRUE; - add_kb_group(group, section_name, label, count, group->keys, callback); + g_free(group->plugin_keys); + group->plugin_keys = g_new0(GeanyKeyBinding, count); + group->plugin_key_count = count; + g_ptr_array_set_size(group->key_items, 0); return group; } -/* used for plugins */ void keybindings_free_group(GeanyKeyGroup *group) { GeanyKeyBinding *kb; - g_assert(group->plugin); + g_ptr_array_free(group->key_items, TRUE); - foreach_c_array(kb, group->keys, group->count) + if (group->plugin) { - g_free(kb->name); - g_free(kb->label); + foreach_c_array(kb, group->plugin_keys, group->plugin_key_count) + { + g_free(kb->name); + g_free(kb->label); + } + g_free(group->plugin_keys); + g_ptr_array_remove_fast(keybinding_groups, group); + g_free(group); } - 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 b876b610..9bf6047c 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -41,6 +41,7 @@ typedef struct GeanyKeyBinding * (preferred). @see plugin_set_key_group(). */ GeanyKeyCallback callback; GtkWidget *menu_item; /**< Optional widget to set an accelerator for, or @c NULL */ + guint id; } GeanyKeyBinding; @@ -60,74 +61,62 @@ 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 */ GeanyKeyGroupCallback callback; /* use this or individual keybinding callbacks */ + gboolean plugin; /* used by plugin */ + GPtrArray *key_items; /* pointers to GeanyKeyBinding structs */ + gsize plugin_key_count; /* number of keybindings the group holds */ + GeanyKeyBinding *plugin_keys; /* array of GeanyKeyBinding structs */ }; #endif extern GPtrArray *keybinding_groups; /* array of GeanyKeyGroup pointers */ -extern const gchar keybindings_keyfile_group_name[]; +/* Note: we don't need to break the plugin ABI when appending keybinding or keygroup IDs, + * just make sure to insert immediately before the _COUNT item, so + * the existing enum values stay the same. */ -/* Note: we don't need to increment the plugin ABI when appending keybindings or keygroups, - * just make sure to only insert keybindings/groups immediately before the _COUNT item, so - * the existing enum values stay the same. - * The _COUNT item should not be used by plugins, as it may well change. */ - -/** Keybinding group IDs */ +/** Keybinding group IDs for use with keybindings_send_command(). */ +/* Groups must be added in this order. */ enum GeanyKeyGroupID { - GEANY_KEY_GROUP_FILE, /**< Group for @ref GeanyKeysFileID. */ - GEANY_KEY_GROUP_PROJECT, /**< Group for @ref GeanyKeysProjectID. */ - GEANY_KEY_GROUP_EDITOR, /**< Group for @ref GeanyKeysEditorID. */ - GEANY_KEY_GROUP_CLIPBOARD, /**< Group for @ref GeanyKeysClipboardID. */ - GEANY_KEY_GROUP_SELECT, /**< Group for @ref GeanyKeysSelectID. */ - GEANY_KEY_GROUP_FORMAT, /**< Group for @ref GeanyKeysFormatID. */ - GEANY_KEY_GROUP_INSERT, /**< Group for @ref GeanyKeysInsertID. */ - GEANY_KEY_GROUP_SETTINGS, /**< Group for @ref GeanyKeysSettingsID. */ - GEANY_KEY_GROUP_SEARCH, /**< Group for @ref GeanyKeysSearchID. */ - GEANY_KEY_GROUP_GOTO, /**< Group for @ref GeanyKeysGoToID. */ - GEANY_KEY_GROUP_VIEW, /**< Group for @ref GeanyKeysViewID. */ - GEANY_KEY_GROUP_FOCUS, /**< Group for @ref GeanyKeysFocusID. */ - GEANY_KEY_GROUP_NOTEBOOK, /**< Group for @ref GeanyKeysNotebookTabID. */ - GEANY_KEY_GROUP_DOCUMENT, /**< Group for @ref GeanyKeysDocumentID. */ - GEANY_KEY_GROUP_BUILD, /**< Group for @ref GeanyKeysBuildID. */ - GEANY_KEY_GROUP_TOOLS, /**< Group for @ref GeanyKeysToolsID. */ - GEANY_KEY_GROUP_HELP, /**< Group for @ref GeanyKeysHelpID. */ - GEANY_KEY_GROUP_COUNT + GEANY_KEY_GROUP_FILE, /**< Group. */ + GEANY_KEY_GROUP_PROJECT, /**< Group. */ + GEANY_KEY_GROUP_EDITOR, /**< Group. */ + GEANY_KEY_GROUP_CLIPBOARD, /**< Group. */ + GEANY_KEY_GROUP_SELECT, /**< Group. */ + GEANY_KEY_GROUP_FORMAT, /**< Group. */ + GEANY_KEY_GROUP_INSERT, /**< Group. */ + GEANY_KEY_GROUP_SETTINGS, /**< Group. */ + GEANY_KEY_GROUP_SEARCH, /**< Group. */ + GEANY_KEY_GROUP_GOTO, /**< Group. */ + GEANY_KEY_GROUP_VIEW, /**< Group. */ + GEANY_KEY_GROUP_FOCUS, /**< Group. */ + GEANY_KEY_GROUP_NOTEBOOK, /**< Group. */ + GEANY_KEY_GROUP_DOCUMENT, /**< Group. */ + GEANY_KEY_GROUP_BUILD, /**< Group. */ + GEANY_KEY_GROUP_TOOLS, /**< Group. */ + GEANY_KEY_GROUP_HELP, /**< Group. */ + GEANY_KEY_GROUP_COUNT /* must not be used by plugins */ }; -/** File group keybinding command IDs */ -enum GeanyKeysFileID -{ - GEANY_KEYS_FILE_NEW, /**< Keybinding. */ - GEANY_KEYS_FILE_OPEN, /**< Keybinding. */ - GEANY_KEYS_FILE_OPENSELECTED, /**< Keybinding. */ - GEANY_KEYS_FILE_SAVE, /**< Keybinding. */ - GEANY_KEYS_FILE_SAVEAS, /**< Keybinding. */ - GEANY_KEYS_FILE_SAVEALL, /**< Keybinding. */ - GEANY_KEYS_FILE_PRINT, /**< Keybinding. */ - GEANY_KEYS_FILE_CLOSE, /**< Keybinding. */ - GEANY_KEYS_FILE_CLOSEALL, /**< Keybinding. */ - GEANY_KEYS_FILE_RELOAD, /**< Keybinding. */ - GEANY_KEYS_FILE_OPENLASTTAB, /**< Keybinding. */ - GEANY_KEYS_FILE_COUNT -}; - -/** Project group keybinding command IDs */ -enum GeanyKeysProjectID -{ - GEANY_KEYS_PROJECT_PROPERTIES, /**< Keybinding. */ - GEANY_KEYS_PROJECT_COUNT -}; - -/** Editor group keybinding command IDs */ -enum GeanyKeysEditorID +/** Keybinding command IDs for use with keybindings_send_command(). */ +/* These IDs are used to lookup a keybinding; keybindings can be added in any order. */ +enum GeanyKeyBindingID { + GEANY_KEYS_FILE_NEW, /**< Keybinding. */ + GEANY_KEYS_FILE_OPEN, /**< Keybinding. */ + GEANY_KEYS_FILE_OPENSELECTED, /**< Keybinding. */ + GEANY_KEYS_FILE_SAVE, /**< Keybinding. */ + GEANY_KEYS_FILE_SAVEAS, /**< Keybinding. */ + GEANY_KEYS_FILE_SAVEALL, /**< Keybinding. */ + GEANY_KEYS_FILE_PRINT, /**< Keybinding. */ + GEANY_KEYS_FILE_CLOSE, /**< Keybinding. */ + GEANY_KEYS_FILE_CLOSEALL, /**< Keybinding. */ + GEANY_KEYS_FILE_RELOAD, /**< Keybinding. */ + GEANY_KEYS_FILE_OPENLASTTAB, /**< Keybinding. */ + GEANY_KEYS_PROJECT_PROPERTIES, /**< Keybinding. */ GEANY_KEYS_EDITOR_UNDO, /**< Keybinding. */ GEANY_KEYS_EDITOR_REDO, /**< Keybinding. */ GEANY_KEYS_EDITOR_DELETELINE, /**< Keybinding. */ @@ -147,36 +136,17 @@ enum GeanyKeysEditorID GEANY_KEYS_EDITOR_WORDPARTCOMPLETION, /**< Keybinding. */ GEANY_KEYS_EDITOR_MOVELINEUP, /**< Keybinding. */ GEANY_KEYS_EDITOR_MOVELINEDOWN, /**< Keybinding. */ - GEANY_KEYS_EDITOR_COUNT -}; - -/** Clipboard group keybinding command IDs */ -enum GeanyKeysClipboardID -{ - GEANY_KEYS_CLIPBOARD_CUT, /**< Keybinding. */ - GEANY_KEYS_CLIPBOARD_COPY, /**< Keybinding. */ - GEANY_KEYS_CLIPBOARD_PASTE, /**< Keybinding. */ - GEANY_KEYS_CLIPBOARD_CUTLINE, /**< Keybinding. */ - GEANY_KEYS_CLIPBOARD_COPYLINE, /**< Keybinding. */ - GEANY_KEYS_CLIPBOARD_COUNT -}; - -/** Select group keybinding command IDs */ -enum GeanyKeysSelectID -{ - - GEANY_KEYS_SELECT_ALL, /**< Keybinding. */ - GEANY_KEYS_SELECT_WORD, /**< Keybinding. */ - GEANY_KEYS_SELECT_LINE, /**< Keybinding. */ - GEANY_KEYS_SELECT_PARAGRAPH, /**< Keybinding. */ - GEANY_KEYS_SELECT_WORDPARTLEFT, /**< Keybinding. */ - GEANY_KEYS_SELECT_WORDPARTRIGHT, /**< Keybinding. */ - GEANY_KEYS_SELECT_COUNT -}; - -/** Format group keybinding command IDs */ -enum GeanyKeysFormatID -{ + GEANY_KEYS_CLIPBOARD_CUT, /**< Keybinding. */ + GEANY_KEYS_CLIPBOARD_COPY, /**< Keybinding. */ + GEANY_KEYS_CLIPBOARD_PASTE, /**< Keybinding. */ + GEANY_KEYS_CLIPBOARD_CUTLINE, /**< Keybinding. */ + GEANY_KEYS_CLIPBOARD_COPYLINE, /**< Keybinding. */ + GEANY_KEYS_SELECT_ALL, /**< Keybinding. */ + GEANY_KEYS_SELECT_WORD, /**< Keybinding. */ + GEANY_KEYS_SELECT_LINE, /**< Keybinding. */ + GEANY_KEYS_SELECT_PARAGRAPH, /**< Keybinding. */ + GEANY_KEYS_SELECT_WORDPARTLEFT, /**< Keybinding. */ + GEANY_KEYS_SELECT_WORDPARTRIGHT, /**< Keybinding. */ GEANY_KEYS_FORMAT_TOGGLECASE, /**< Keybinding. */ GEANY_KEYS_FORMAT_COMMENTLINETOGGLE, /**< Keybinding. */ GEANY_KEYS_FORMAT_COMMENTLINE, /**< Keybinding. */ @@ -191,96 +161,53 @@ enum GeanyKeysFormatID GEANY_KEYS_FORMAT_SENDTOCMD3, /**< Keybinding. */ GEANY_KEYS_FORMAT_SENDTOVTE, /**< Keybinding. */ GEANY_KEYS_FORMAT_REFLOWPARAGRAPH, /**< Keybinding. */ - GEANY_KEYS_FORMAT_COUNT -}; - -/** Insert group keybinding command IDs */ -enum GeanyKeysInsertID -{ - GEANY_KEYS_INSERT_DATE, /**< Keybinding. */ - GEANY_KEYS_INSERT_ALTWHITESPACE, /**< Keybinding. */ - GEANY_KEYS_INSERT_COUNT -}; - -/** Settings group keybinding command IDs */ -enum GeanyKeysSettingsID -{ - GEANY_KEYS_SETTINGS_PREFERENCES, /**< Keybinding. */ - GEANY_KEYS_SETTINGS_PLUGINPREFERENCES, /**< Keybinding. */ - GEANY_KEYS_SETTINGS_COUNT -}; - -/** Search group keybinding command IDs */ -enum GeanyKeysSearchID -{ - GEANY_KEYS_SEARCH_FIND, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDNEXT, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDPREVIOUS, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDINFILES, /**< Keybinding. */ - GEANY_KEYS_SEARCH_REPLACE, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDNEXTSEL, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDPREVSEL, /**< Keybinding. */ - GEANY_KEYS_SEARCH_NEXTMESSAGE, /**< Keybinding. */ - GEANY_KEYS_SEARCH_PREVIOUSMESSAGE, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDUSAGE, /**< Keybinding. */ - GEANY_KEYS_SEARCH_FINDDOCUMENTUSAGE, /**< Keybinding. */ - GEANY_KEYS_SEARCH_MARKALL, /**< Keybinding. */ - GEANY_KEYS_SEARCH_COUNT -}; - -/** Go To group keybinding command IDs */ -enum GeanyKeysGoToID -{ - GEANY_KEYS_GOTO_FORWARD, /**< Keybinding. */ - GEANY_KEYS_GOTO_BACK, /**< Keybinding. */ - GEANY_KEYS_GOTO_LINE, /**< Keybinding. */ - GEANY_KEYS_GOTO_LINESTART, /**< Keybinding. */ - GEANY_KEYS_GOTO_LINEEND, /**< Keybinding. */ - GEANY_KEYS_GOTO_MATCHINGBRACE, /**< Keybinding. */ - GEANY_KEYS_GOTO_TOGGLEMARKER, /**< Keybinding. */ - GEANY_KEYS_GOTO_NEXTMARKER, /**< Keybinding. */ - GEANY_KEYS_GOTO_PREVIOUSMARKER, /**< Keybinding. */ - GEANY_KEYS_GOTO_PREVWORDPART, /**< Keybinding. */ - GEANY_KEYS_GOTO_NEXTWORDPART, /**< Keybinding. */ - GEANY_KEYS_GOTO_TAGDEFINITION, /**< Keybinding. */ - GEANY_KEYS_GOTO_TAGDECLARATION, /**< Keybinding. */ - GEANY_KEYS_GOTO_LINEENDVISUAL, /**< Keybinding. */ - GEANY_KEYS_GOTO_COUNT -}; - -/** View group keybinding command IDs */ -enum GeanyKeysViewID -{ - GEANY_KEYS_VIEW_TOGGLEALL, /**< Keybinding. */ - GEANY_KEYS_VIEW_FULLSCREEN, /**< Keybinding. */ - GEANY_KEYS_VIEW_MESSAGEWINDOW, /**< Keybinding. */ - GEANY_KEYS_VIEW_SIDEBAR, /**< Keybinding. */ - GEANY_KEYS_VIEW_ZOOMIN, /**< Keybinding. */ - GEANY_KEYS_VIEW_ZOOMOUT, /**< Keybinding. */ - GEANY_KEYS_VIEW_ZOOMRESET, /**< Keybinding. */ - GEANY_KEYS_VIEW_COUNT -}; - -/** Focus group keybinding command IDs */ -/* TODO when the plugin ABI get increased the next time, rearrange these keybindings */ -enum GeanyKeysFocusID -{ - GEANY_KEYS_FOCUS_EDITOR, /**< Keybinding. */ - GEANY_KEYS_FOCUS_SCRIBBLE, /**< Keybinding. */ - GEANY_KEYS_FOCUS_VTE, /**< Keybinding. */ - GEANY_KEYS_FOCUS_SEARCHBAR, /**< Keybinding. */ - GEANY_KEYS_FOCUS_SIDEBAR, /**< Keybinding. */ - GEANY_KEYS_FOCUS_COMPILER, /**< Keybinding. */ - GEANY_KEYS_FOCUS_MESSAGES, /**< Keybinding. */ - GEANY_KEYS_FOCUS_MESSAGE_WINDOW, /**< Keybinding. */ - GEANY_KEYS_FOCUS_SIDEBAR_DOCUMENT_LIST, /**< Keybinding. */ - GEANY_KEYS_FOCUS_SIDEBAR_SYMBOL_LIST, /**< Keybinding. */ - GEANY_KEYS_FOCUS_COUNT -}; - -/** Notebook Tab group keybinding command IDs */ -enum GeanyKeysNotebookTabID -{ + GEANY_KEYS_INSERT_DATE, /**< Keybinding. */ + GEANY_KEYS_INSERT_ALTWHITESPACE, /**< Keybinding. */ + GEANY_KEYS_SETTINGS_PREFERENCES, /**< Keybinding. */ + GEANY_KEYS_SETTINGS_PLUGINPREFERENCES, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FIND, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDNEXT, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDPREVIOUS, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDINFILES, /**< Keybinding. */ + GEANY_KEYS_SEARCH_REPLACE, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDNEXTSEL, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDPREVSEL, /**< Keybinding. */ + GEANY_KEYS_SEARCH_NEXTMESSAGE, /**< Keybinding. */ + GEANY_KEYS_SEARCH_PREVIOUSMESSAGE, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDUSAGE, /**< Keybinding. */ + GEANY_KEYS_SEARCH_FINDDOCUMENTUSAGE, /**< Keybinding. */ + GEANY_KEYS_SEARCH_MARKALL, /**< Keybinding. */ + GEANY_KEYS_GOTO_FORWARD, /**< Keybinding. */ + GEANY_KEYS_GOTO_BACK, /**< Keybinding. */ + GEANY_KEYS_GOTO_LINE, /**< Keybinding. */ + GEANY_KEYS_GOTO_LINESTART, /**< Keybinding. */ + GEANY_KEYS_GOTO_LINEEND, /**< Keybinding. */ + GEANY_KEYS_GOTO_MATCHINGBRACE, /**< Keybinding. */ + GEANY_KEYS_GOTO_TOGGLEMARKER, /**< Keybinding. */ + GEANY_KEYS_GOTO_NEXTMARKER, /**< Keybinding. */ + GEANY_KEYS_GOTO_PREVIOUSMARKER, /**< Keybinding. */ + GEANY_KEYS_GOTO_PREVWORDPART, /**< Keybinding. */ + GEANY_KEYS_GOTO_NEXTWORDPART, /**< Keybinding. */ + GEANY_KEYS_GOTO_TAGDEFINITION, /**< Keybinding. */ + GEANY_KEYS_GOTO_TAGDECLARATION, /**< Keybinding. */ + GEANY_KEYS_GOTO_LINEENDVISUAL, /**< Keybinding. */ + GEANY_KEYS_VIEW_TOGGLEALL, /**< Keybinding. */ + GEANY_KEYS_VIEW_FULLSCREEN, /**< Keybinding. */ + GEANY_KEYS_VIEW_MESSAGEWINDOW, /**< Keybinding. */ + GEANY_KEYS_VIEW_SIDEBAR, /**< Keybinding. */ + GEANY_KEYS_VIEW_ZOOMIN, /**< Keybinding. */ + GEANY_KEYS_VIEW_ZOOMOUT, /**< Keybinding. */ + GEANY_KEYS_VIEW_ZOOMRESET, /**< Keybinding. */ + GEANY_KEYS_FOCUS_EDITOR, /**< Keybinding. */ + GEANY_KEYS_FOCUS_SCRIBBLE, /**< Keybinding. */ + GEANY_KEYS_FOCUS_VTE, /**< Keybinding. */ + GEANY_KEYS_FOCUS_SEARCHBAR, /**< Keybinding. */ + GEANY_KEYS_FOCUS_SIDEBAR, /**< Keybinding. */ + GEANY_KEYS_FOCUS_COMPILER, /**< Keybinding. */ + GEANY_KEYS_FOCUS_MESSAGES, /**< Keybinding. */ + GEANY_KEYS_FOCUS_MESSAGE_WINDOW, /**< Keybinding. */ + GEANY_KEYS_FOCUS_SIDEBAR_DOCUMENT_LIST, /**< Keybinding. */ + GEANY_KEYS_FOCUS_SIDEBAR_SYMBOL_LIST, /**< Keybinding. */ GEANY_KEYS_NOTEBOOK_SWITCHTABLEFT, /**< Keybinding. */ GEANY_KEYS_NOTEBOOK_SWITCHTABRIGHT, /**< Keybinding. */ GEANY_KEYS_NOTEBOOK_SWITCHTABLASTUSED, /**< Keybinding. */ @@ -288,52 +215,28 @@ enum GeanyKeysNotebookTabID GEANY_KEYS_NOTEBOOK_MOVETABRIGHT, /**< Keybinding. */ GEANY_KEYS_NOTEBOOK_MOVETABFIRST, /**< Keybinding. */ GEANY_KEYS_NOTEBOOK_MOVETABLAST, /**< Keybinding. */ - GEANY_KEYS_NOTEBOOK_COUNT -}; - -/** Document group keybinding command IDs */ -enum GeanyKeysDocumentID -{ - GEANY_KEYS_DOCUMENT_REPLACETABS, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_REPLACESPACES, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_TOGGLEFOLD, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_FOLDALL, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_UNFOLDALL, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_RELOADTAGLIST, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_LINEWRAP, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_LINEBREAK, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_REMOVE_MARKERS, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_REMOVE_ERROR_INDICATORS, /**< Keybinding. */ - GEANY_KEYS_DOCUMENT_COUNT -}; - -/** Build group keybinding command IDs */ -enum GeanyKeysBuildID -{ - GEANY_KEYS_BUILD_COMPILE, /**< Keybinding. */ - GEANY_KEYS_BUILD_LINK, /**< Keybinding. */ - GEANY_KEYS_BUILD_MAKE, /**< Keybinding. */ - GEANY_KEYS_BUILD_MAKEOWNTARGET, /**< Keybinding. */ - GEANY_KEYS_BUILD_MAKEOBJECT, /**< Keybinding. */ - GEANY_KEYS_BUILD_NEXTERROR, /**< Keybinding. */ - GEANY_KEYS_BUILD_PREVIOUSERROR, /**< Keybinding. */ - GEANY_KEYS_BUILD_RUN, /**< Keybinding. */ - GEANY_KEYS_BUILD_OPTIONS, /**< Keybinding. */ - GEANY_KEYS_BUILD_COUNT -}; - -/** Tools group keybinding command IDs */ -enum GeanyKeysToolsID -{ - GEANY_KEYS_TOOLS_OPENCOLORCHOOSER, /**< Keybinding. */ - GEANY_KEYS_TOOLS_COUNT -}; - -/** Help group keybinding command IDs */ -enum GeanyKeysHelpID -{ - GEANY_KEYS_HELP_HELP, /**< Keybinding. */ - GEANY_KEYS_HELP_COUNT + GEANY_KEYS_DOCUMENT_REPLACETABS, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_REPLACESPACES, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_TOGGLEFOLD, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_FOLDALL, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_UNFOLDALL, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_RELOADTAGLIST, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_LINEWRAP, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_LINEBREAK, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_REMOVE_MARKERS, /**< Keybinding. */ + GEANY_KEYS_DOCUMENT_REMOVE_ERROR_INDICATORS, /**< Keybinding. */ + GEANY_KEYS_BUILD_COMPILE, /**< Keybinding. */ + GEANY_KEYS_BUILD_LINK, /**< Keybinding. */ + GEANY_KEYS_BUILD_MAKE, /**< Keybinding. */ + GEANY_KEYS_BUILD_MAKEOWNTARGET, /**< Keybinding. */ + GEANY_KEYS_BUILD_MAKEOBJECT, /**< Keybinding. */ + GEANY_KEYS_BUILD_NEXTERROR, /**< Keybinding. */ + GEANY_KEYS_BUILD_PREVIOUSERROR, /**< Keybinding. */ + GEANY_KEYS_BUILD_RUN, /**< Keybinding. */ + GEANY_KEYS_BUILD_OPTIONS, /**< Keybinding. */ + GEANY_KEYS_TOOLS_OPENCOLORCHOOSER, /**< Keybinding. */ + GEANY_KEYS_HELP_HELP, /**< Keybinding. */ + GEANY_KEYS_COUNT /* must not be used by plugins */ }; diff --git a/src/plugindata.h b/src/plugindata.h index 4bd87738..793d4ee5 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -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 = 191, + GEANY_API_VERSION = 192, /** 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 = 66 + GEANY_ABI_VERSION = 67 }; /** Defines a function to check the plugin is safe to load. diff --git a/src/prefs.c b/src/prefs.c index 2578bbc3..d6cb2308 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -303,23 +303,19 @@ static void kb_init(void) if (store == NULL) kb_init_tree(); - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - group = g_ptr_array_index(keybinding_groups, g); - gtk_tree_store_append(store, &parent, NULL); gtk_tree_store_set(store, &parent, KB_TREE_ACTION, group->label, KB_TREE_INDEX, g, -1); - for (i = 0; i < group->count; i++) + foreach_ptr_array(kb, i, group->key_items) { - kb = &group->keys[i]; - label = keybindings_get_label(kb); key_string = gtk_accelerator_name(kb->key, kb->mods); gtk_tree_store_append(store, &iter, &parent); gtk_tree_store_set(store, &iter, KB_TREE_ACTION, label, - KB_TREE_SHORTCUT, key_string, KB_TREE_INDEX, i, -1); + KB_TREE_SHORTCUT, key_string, KB_TREE_INDEX, kb->id, -1); g_free(key_string); g_free(label); } @@ -1311,7 +1307,6 @@ static void kb_dialog_response_cb(GtkWidget *dialog, gint response, G_GNUC_UNUSE GeanyKeyBinding *kb; kb = kb_lookup_kb_from_iter(GTK_TREE_MODEL(store), &g_iter); - gtk_accelerator_parse(gtk_label_get_text(GTK_LABEL(dialog_label)), &lkey, &lmods); if (kb_find_duplicate(dialog, kb, lkey, lmods, gtk_label_get_text(GTK_LABEL(dialog_label)))) @@ -1375,22 +1370,19 @@ static gboolean kb_find_duplicate(GtkWidget *parent, GeanyKeyBinding *search_kb, guint key, GdkModifierType mods, const gchar *action) { gsize g, i; + GeanyKeyGroup *group; + GeanyKeyBinding *kb; /* allow duplicate if there is no key combination */ if (key == 0 && mods == 0) return FALSE; - for (g = 0; g < keybinding_groups->len; g++) + foreach_ptr_array(group, g, keybinding_groups) { - GeanyKeyGroup *group = g_ptr_array_index(keybinding_groups, g); - - for (i = 0; i < group->count; i++) + foreach_ptr_array(kb, i, group->key_items) { - GeanyKeyBinding *keys = group->keys; - GeanyKeyBinding *kb = &keys[i]; - /* search another item with the same key, - * but don't search the key we're looking for keys[idx] */ + * but don't search the key we're looking for(!) */ if (kb->key == key && kb->mods == mods && ! (kb->key == search_kb->key && kb->mods == search_kb->mods)) { @@ -1408,7 +1400,7 @@ static gboolean kb_find_duplicate(GtkWidget *parent, GeanyKeyBinding *search_kb, if (ret == GTK_RESPONSE_YES) { keybindings_update_combo(kb, 0, 0); - kb_clear_tree_shortcut(g, i); + kb_clear_tree_shortcut(g, kb->id); /* carry on looking for other duplicates if overriding */ continue; }