diff --git a/ChangeLog b/ChangeLog index fe1f6114..2b8a4858 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2008-12-11 Nick Treleaven + + * src/utils.h, src/prefs.c, src/stash.c, src/stash.h, src/keyfile.c, + src/keyfile.h, src/symbols.c: + Add foreach_ptr_array() macro to utils.h. + Merge toggle button prefs code into keyfile.c Stash code. + Add toggle button support to Stash code. + + 2008-12-09 Enrico Tröger * tagmanager/c.c, tagmanager/get.h: diff --git a/src/keyfile.c b/src/keyfile.c index 1e99d634..68d39c32 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -85,11 +85,6 @@ #define GEANY_TOGGLE_MARK "~ " #define GEANY_MAX_AUTOCOMPLETE_WORDS 30 -/* @param ptr should be a (gpointer*), needed for implementation. */ -#define foreach_ptr_array(item, ptr, ptr_array) \ - for (ptr = ptr_array->pdata, item = *ptr; \ - ptr < &ptr_array->pdata[ptr_array->len]; ++ptr, item = *ptr) - static gchar *scribble_text = NULL; static GPtrArray *session_files = NULL; @@ -97,7 +92,7 @@ static gint session_notebook_page; static gint hpan_position; static gint vpan_position; -static GPtrArray *pref_groups = NULL; +GPtrArray *pref_groups = NULL; static void add_pref_group(GeanyPrefGroup *group) @@ -118,18 +113,18 @@ static void init_pref_groups(void) stash_group_add_string(group, &prefs.default_open_path, "default_open_path", ""); - stash_group_add_boolean(group, - &file_prefs.cmdline_new_files, "cmdline_new_files", TRUE); + stash_group_add_toggle_button(group, &file_prefs.cmdline_new_files, + "cmdline_new_files", TRUE, "check_cmdline_new_files"); - stash_group_add_boolean(group, - &search_prefs.suppress_dialogs, "pref_main_suppress_search_dialogs", FALSE); - stash_group_add_boolean(group, - &search_prefs.use_current_word, "pref_main_search_use_current_word", TRUE); + stash_group_add_toggle_button(group, &search_prefs.suppress_dialogs, + "pref_main_suppress_search_dialogs", FALSE, "check_ask_suppress_search_dialogs"); + stash_group_add_toggle_button(group, &search_prefs.use_current_word, + "pref_main_search_use_current_word", TRUE, "check_search_use_current_word"); - stash_group_add_boolean(group, - &editor_prefs.indentation->detect_type, "check_detect_indent", FALSE); - stash_group_add_boolean(group, - &editor_prefs.use_tab_to_indent, "use_tab_to_indent", TRUE); + stash_group_add_toggle_button(group, &editor_prefs.indentation->detect_type, + "check_detect_indent", FALSE, "check_detect_indent"); + stash_group_add_toggle_button(group, &editor_prefs.use_tab_to_indent, + "use_tab_to_indent", TRUE, "check_tab_key_indents"); stash_group_add_integer(group, &editor_prefs.indentation->width, "pref_editor_tab_width", 4); stash_group_add_integer(group, @@ -143,8 +138,8 @@ static void init_pref_groups(void) group = stash_group_new("search"); add_pref_group(group); - stash_group_add_boolean(group, - &search_prefs.use_current_file_dir, "pref_search_current_file_dir", TRUE); + stash_group_add_toggle_button(group, &search_prefs.use_current_file_dir, + "pref_search_current_file_dir", TRUE, "check_fif_current_dir"); /* hidden prefs (don't overwrite them so users can edit them manually) */ group = stash_group_new(PACKAGE); diff --git a/src/keyfile.h b/src/keyfile.h index eb78f941..8ed682ea 100644 --- a/src/keyfile.h +++ b/src/keyfile.h @@ -26,6 +26,9 @@ #define GEANY_KEYFILE_H 1 +extern GPtrArray *pref_groups; + + void configuration_init(void); void configuration_finalize(void); diff --git a/src/prefs.c b/src/prefs.c index c45c4e9e..e2775ac7 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -53,6 +53,8 @@ #include "templates.h" #include "search.h" #include "toolbar.h" +#include "stash.h" +#include "keyfile.h" #ifdef HAVE_VTE # include "vte.h" @@ -106,40 +108,6 @@ typedef struct PrefEntry PrefEntry; -static void toggle_prefs_foreach(PrefCallbackAction action) -{ - guint i; - PrefEntry items[] = - { - {"check_cmdline_new_files", &file_prefs.cmdline_new_files}, - - {"check_ask_suppress_search_dialogs", &search_prefs.suppress_dialogs}, - {"check_search_use_current_word", &search_prefs.use_current_word}, - {"check_fif_current_dir", &search_prefs.use_current_file_dir}, - - {"check_detect_indent", &editor_prefs.indentation->detect_type}, - {"check_tab_key_indents", &editor_prefs.use_tab_to_indent} - }; - - for (i = 0; i < G_N_ELEMENTS(items); i++) - { - PrefEntry *pe = &items[i]; - GtkWidget *widget = lookup_widget(ui_widgets.prefs_dialog, pe->widget_name); - gboolean *setting = pe->setting; - - switch (action) - { - case PREF_DISPLAY: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *setting); - break; - case PREF_UPDATE: - *setting = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - break; - } - } -} - - static void spin_prefs_foreach(PrefCallbackAction action) { guint i; @@ -240,7 +208,6 @@ typedef void (*PrefItemsCallback)(PrefCallbackAction action); /* List of functions which hold the PrefEntry arrays. These allow access to * runtime setting fields like EditorPrefs::indentation->width. */ PrefItemsCallback pref_item_callbacks[] = { - toggle_prefs_foreach, spin_prefs_foreach, radio_prefs_foreach, combo_prefs_foreach @@ -250,6 +217,21 @@ PrefItemsCallback pref_item_callbacks[] = { static void prefs_action(PrefCallbackAction action) { guint i; + GeanyPrefGroup *group; + gpointer *ptr; + + foreach_ptr_array(group, ptr, pref_groups) + { + switch (action) + { + case PREF_DISPLAY: + stash_group_display(group, ui_widgets.prefs_dialog); + break; + case PREF_UPDATE: + stash_group_update(group, ui_widgets.prefs_dialog); + break; + } + } for (i = 0; i < G_N_ELEMENTS(pref_item_callbacks); i++) pref_item_callbacks[i](action); diff --git a/src/stash.c b/src/stash.c index 39190f40..cef2daee 100644 --- a/src/stash.c +++ b/src/stash.c @@ -29,7 +29,7 @@ #include #include "stash.h" -#include "utils.h" +#include "utils.h" /* utils_get_setting_*() */ #define foreach_array(type, item, array) \ foreach_c_array(item, ((type*)(gpointer)array->data), array->len) @@ -41,7 +41,8 @@ struct GeanyPrefEntry gpointer setting; const gchar *key_name; gpointer default_value; - const gchar *widget_name; + GType widget_type; /* e.g. GTK_TYPE_TOGGLE_BUTTON */ + gpointer widget_id; /* can be GtkWidget or gchararray */ }; struct GeanyPrefGroup @@ -59,6 +60,12 @@ typedef enum SettingAction } SettingAction; +typedef enum PrefAction +{ + PREF_DISPLAY, + PREF_UPDATE +} +PrefAction; static void handle_boolean_setting(GeanyPrefGroup *group, GeanyPrefEntry *se, @@ -116,7 +123,7 @@ static void handle_string_setting(GeanyPrefGroup *group, GeanyPrefEntry *se, } -static void keyfile_action(GeanyPrefGroup *group, GKeyFile *keyfile, SettingAction action) +static void keyfile_action(SettingAction action, GeanyPrefGroup *group, GKeyFile *keyfile) { GeanyPrefEntry *entry; @@ -135,7 +142,8 @@ static void keyfile_action(GeanyPrefGroup *group, GKeyFile *keyfile, SettingActi case G_TYPE_STRING: handle_string_setting(group, entry, keyfile, action); break; default: - g_warning("Unhandled type for %s::%s!", group->name, entry->key_name); + g_warning("Unhandled type for %s::%s in %s!", group->name, entry->key_name, + G_GNUC_FUNCTION); } } } @@ -143,13 +151,13 @@ static void keyfile_action(GeanyPrefGroup *group, GKeyFile *keyfile, SettingActi void stash_group_load(GeanyPrefGroup *group, GKeyFile *keyfile) { - keyfile_action(group, keyfile, SETTING_READ); + keyfile_action(SETTING_READ, group, keyfile); } void stash_group_save(GeanyPrefGroup *group, GKeyFile *keyfile) { - keyfile_action(group, keyfile, SETTING_WRITE); + keyfile_action(SETTING_WRITE, group, keyfile); } @@ -176,12 +184,16 @@ void stash_group_set_write_once(GeanyPrefGroup *group, gboolean write_once) } -static void add_pref(GeanyPrefGroup *group, GType type, gpointer setting, +static GeanyPrefEntry * +add_pref(GeanyPrefGroup *group, GType type, gpointer setting, const gchar *key_name, gpointer default_value) { - GeanyPrefEntry entry = {type, setting, key_name, default_value, NULL}; + GeanyPrefEntry entry = {type, setting, key_name, default_value, G_TYPE_NONE, NULL}; + GArray *array = group->entries; - g_array_append_val(group->entries, entry); + g_array_append_val(array, entry); + + return &g_array_index(array, GeanyPrefEntry, array->len - 1); } @@ -206,3 +218,101 @@ void stash_group_add_string(GeanyPrefGroup *group, gchar **setting, } +static void handle_toggle_button(GtkWidget *widget, gboolean *setting, + PrefAction action) +{ + switch (action) + { + case PREF_DISPLAY: + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *setting); + break; + case PREF_UPDATE: + *setting = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + break; + } +} + + +/* taken from Glade 2.x generated support.c */ +static GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + + +static void pref_action(PrefAction action, GeanyPrefGroup *group, GtkWidget *owner) +{ + GeanyPrefEntry *entry; + + foreach_array(GeanyPrefEntry, entry, group->entries) + { + GtkWidget *widget = entry->widget_id; + const gchar *widget_name = entry->widget_id; + + if (entry->widget_type == G_TYPE_NONE) + continue; + + if (owner) + { + widget = lookup_widget(owner, widget_name); + } + if (!GTK_IS_WIDGET(widget)) + { + g_warning("Unknown widget for %s::%s in %s!", group->name, entry->key_name, + G_GNUC_FUNCTION); + continue; + } + + if (entry->widget_type == GTK_TYPE_TOGGLE_BUTTON) + handle_toggle_button(widget, entry->setting, action); + else + g_warning("Unhandled type for %s::%s in %s!", group->name, entry->key_name, + G_GNUC_FUNCTION); + } +} + + +/** @param owner If non-NULL, used to lookup widgets by name. */ +void stash_group_display(GeanyPrefGroup *group, GtkWidget *owner) +{ + pref_action(PREF_DISPLAY, group, owner); +} + + +void stash_group_update(GeanyPrefGroup *group, GtkWidget *owner) +{ + pref_action(PREF_UPDATE, group, owner); +} + + +void stash_group_add_toggle_button(GeanyPrefGroup *group, gboolean *setting, + const gchar *key_name, gboolean default_value, gpointer widget_id) +{ + GeanyPrefEntry *entry = + add_pref(group, G_TYPE_BOOLEAN, setting, key_name, GINT_TO_POINTER(default_value)); + + entry->widget_type = GTK_TYPE_TOGGLE_BUTTON; + entry->widget_id = widget_id; +} + + diff --git a/src/stash.h b/src/stash.h index 71f25a5f..9bcc01db 100644 --- a/src/stash.h +++ b/src/stash.h @@ -1,23 +1,23 @@ /* - * stash.h - this file is part of Geany, a fast and lightweight IDE + * stash.h - this file is part of Geany, a fast and lightweight IDE * - * Copyright 2008 Nick Treleaven - * Copyright 2008 Enrico Tröger + * Copyright 2008 Nick Treleaven + * Copyright 2008 Enrico Tröger * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. * * $Id$ */ @@ -35,18 +35,25 @@ GeanyPrefGroup *stash_group_new(const gchar *name); void stash_group_set_write_once(GeanyPrefGroup *group, gboolean write_once); void stash_group_add_boolean(GeanyPrefGroup *group, gboolean *setting, - const gchar *key_name, gboolean default_value); + const gchar *key_name, gboolean default_value); void stash_group_add_integer(GeanyPrefGroup *group, gint *setting, - const gchar *key_name, gint default_value); + const gchar *key_name, gint default_value); void stash_group_add_string(GeanyPrefGroup *group, gchar **setting, - const gchar *key_name, const gchar *default_value); + const gchar *key_name, const gchar *default_value); + +void stash_group_add_toggle_button(GeanyPrefGroup *group, gboolean *setting, + const gchar *key_name, gboolean default_value, gpointer widget_id); void stash_group_load(GeanyPrefGroup *group, GKeyFile *keyfile); void stash_group_save(GeanyPrefGroup *group, GKeyFile *keyfile); +void stash_group_display(GeanyPrefGroup *group, GtkWidget *owner); + +void stash_group_update(GeanyPrefGroup *group, GtkWidget *owner); + void stash_group_free(GeanyPrefGroup *group); #endif diff --git a/src/symbols.c b/src/symbols.c index dae3e753..16dd1b78 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1088,20 +1088,15 @@ static void add_tree_tags(GeanyDocument *doc, const GList *tags) } -/* @param item Must be a (gpointer*) for implementation reasons. - * @example gchar *name = *item; (for when the GPtrArray contains char pointers). */ -#define foreach_ptr_array(item, ptr_array) \ - for (item = ptr_array->pdata; item < &ptr_array->pdata[ptr_array->len]; item++) - /* we don't want to sort 1st-level nodes, but we can't return 0 because the tree sort * is not stable, so the order is already lost. */ static gint compare_top_level_names(const gchar *a, const gchar *b) { - gpointer *item; + gpointer *ptr; + const gchar *name; - foreach_ptr_array(item, top_level_iter_names) + foreach_ptr_array(name, ptr, top_level_iter_names) { - const gchar *name = *item; if (utils_str_equal(name, a)) return -1; diff --git a/src/utils.h b/src/utils.h index 5b157c2a..c2aa962c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -48,6 +48,11 @@ #define foreach_c_array(item, array, len) \ for (item = array; item < &array[len]; item++) +/* @param ptr should be a (gpointer*), needed for implementation. */ +#define foreach_ptr_array(item, ptr, ptr_array) \ + for (ptr = ptr_array->pdata, item = *ptr; \ + ptr < &ptr_array->pdata[ptr_array->len]; ++ptr, item = *ptr) + void utils_start_browser(const gchar *uri);