diff --git a/ChangeLog b/ChangeLog index 5d0e7a70..fced1352 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,20 @@ * src/filetypes.c, doc/geany.txt: Move ActionScript to the Script group. Fix wording & typo. + * src/templates.c, src/utils.h, src/highlighting.c, src/dialogs.c, + src/plugindata.h, src/filetypes.c, src/filetypes.h, src/plugins.c, + src/symbols.c, src/ui_utils.c, plugins/saveactions.c, + plugins/htmlchars.c: + Merge reorder-filetypes branch: + Make GEANY_FILETYPES_NONE = 0, sort filetype IDs randomly (so we can + append randomly without breaking the ABI). + Make None filetype name = title = _("None"). + Add foreach_slist() macro. + Add filetypes_by_title list to GeanyData for plugin API access + - a list of filetype pointers, which includes the None filetype + first. This list stays constant by the time plugins are initialized, + so you can use e.g. g_slist_nth_data(filetypes_by_title, n) to + index the sorted list. 2009-03-31 Enrico Tröger diff --git a/plugins/htmlchars.c b/plugins/htmlchars.c index 2b6ed1fe..d7981d5f 100644 --- a/plugins/htmlchars.c +++ b/plugins/htmlchars.c @@ -26,6 +26,8 @@ /* HTML Characters plugin (Inserts HTML character entities like '&') */ #include "geany.h" +#include + #include "support.h" #include "plugindata.h" #include "document.h" diff --git a/plugins/saveactions.c b/plugins/saveactions.c index 666eda2f..6e263765 100644 --- a/plugins/saveactions.c +++ b/plugins/saveactions.c @@ -603,6 +603,8 @@ GtkWidget *plugin_configure(GtkDialog *dialog) { GtkWidget *combo; guint i; + GSList *node; + GeanyFiletype *ft; notebook_vbox = gtk_vbox_new(FALSE, 2); inner_vbox = gtk_vbox_new(FALSE, 5); @@ -624,14 +626,14 @@ GtkWidget *plugin_configure(GtkDialog *dialog) gtk_box_pack_start(GTK_BOX(inner_vbox), label, FALSE, FALSE, 0); pref_widgets.instantsave_ft_combo = combo = gtk_combo_box_new_text(); - for (i = 0; i < geany->filetypes_array->len; i++) + i = 0; + foreach_slist(ft, node, geany->filetypes_by_title) { - GeanyFiletype *ft = filetypes_index(i); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), ft->name); if (utils_str_equal(ft->name, instantsave_default_ft)) gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i); + i++; } gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3); gtk_label_set_mnemonic_widget(GTK_LABEL(label), combo); diff --git a/src/dialogs.c b/src/dialogs.c index f53adde5..3377fc6e 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -90,8 +90,8 @@ on_file_open_dialog_response (GtkDialog *dialog, gboolean ro = (response == GEANY_RESPONSE_VIEW); /* View clicked */ /* ignore detect from file item */ - if (filetype_idx >= 0 && filetype_idx < GEANY_FILETYPES_NONE) - ft = filetypes[filetype_idx]; + if (filetype_idx > 0 && filetype_idx < GEANY_MAX_BUILT_IN_FILETYPES) + ft = g_slist_nth_data(filetypes_by_title, filetype_idx); if (encoding_idx >= 0 && encoding_idx < GEANY_ENCODINGS_MAX) charset = encodings[encoding_idx].charset; @@ -177,6 +177,8 @@ static void create_open_file_dialog(void) GtkWidget *viewbtn; guint i; gchar *encoding_string; + GeanyFiletype *ft; + GSList *node; ui_widgets.open_filesel = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL); @@ -207,23 +209,22 @@ static void create_open_file_dialog(void) add_file_open_extra_widget()); filetype_combo = ui_lookup_widget(ui_widgets.open_filesel, "filetype_combo"); + gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), _("Detect by file extension")); /* add FileFilters(start with "All Files") */ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel), filetypes_create_file_filter(filetypes[GEANY_FILETYPES_NONE])); /* now create meta filter "All Source" */ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel), filetypes_create_file_filter_all_source()); - for (i = 0; i < filetypes_array->len; i++) + foreach_slist(ft, node, filetypes_by_title) { - if (i == GEANY_FILETYPES_NONE) + if (ft->id == GEANY_FILETYPES_NONE) continue; - - gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), filetypes[i]->title); + gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), ft->title); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel), - filetypes_create_file_filter(filetypes[i])); + filetypes_create_file_filter(ft)); } - gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), _("Detect by file extension")); - gtk_combo_box_set_active(GTK_COMBO_BOX(filetype_combo), filetypes_array->len - 1); + gtk_combo_box_set_active(GTK_COMBO_BOX(filetype_combo), 0); /* fill encoding combo box */ encoding_combo = ui_lookup_widget(ui_widgets.open_filesel, "encoding_combo"); diff --git a/src/filetypes.c b/src/filetypes.c index a33d0a5a..684ac858 100644 --- a/src/filetypes.c +++ b/src/filetypes.c @@ -67,10 +67,16 @@ GeanyFiletypePrivate; GPtrArray *filetypes_array = NULL; /* Dynamic array of filetype pointers */ -GHashTable *filetypes_hash = NULL; /* Hash of filetype pointers based on name keys */ +static GHashTable *filetypes_hash = NULL; /* Hash of filetype pointers based on name keys */ + +/** List of filetype pointers sorted by name, but with @c filetypes_index(GEANY_FILETYPES_NONE) + * first, as this is usually treated specially. + * The list does not change (after filetypes have been initialized), so you can use + * @code g_slist_nth_data(filetypes_by_title, n) @endcode and expect the same result at different times. */ +GSList *filetypes_by_title = NULL; -static void create_radio_menu_item(GtkWidget *menu, const gchar *label, GeanyFiletype *ftype); +static void create_radio_menu_item(GtkWidget *menu, GeanyFiletype *ftype); /* Note: remember to update HACKING if this function is renamed. */ @@ -78,7 +84,18 @@ static void init_builtin_filetypes(void) { GeanyFiletype *ft; -#define C /* these macros are only to ease navigation */ +#define NONE /* these macros are only to ease navigation */ + ft = filetypes[GEANY_FILETYPES_NONE]; + ft->lang = -2; + ft->name = g_strdup(_("None")); + ft->title = g_strdup(_("None")); + ft->extension = g_strdup("*"); + ft->pattern = utils_strv_new("*", NULL); + ft->comment_open = NULL; + ft->comment_close = NULL; + ft->group = GEANY_FILETYPE_GROUP_NONE; + +#define C ft = filetypes[GEANY_FILETYPES_C]; ft->lang = 0; ft->name = g_strdup("C"); @@ -560,17 +577,6 @@ static void init_builtin_filetypes(void) ft->comment_open = g_strdup("--"); ft->comment_close = NULL; ft->group = GEANY_FILETYPE_GROUP_COMPILED; - -#define ALL - ft = filetypes[GEANY_FILETYPES_NONE]; - ft->lang = -2; - ft->name = g_strdup("None"); - ft->title = g_strdup(_("All files")); - ft->extension = g_strdup("*"); - ft->pattern = utils_strv_new("*", NULL); - ft->comment_open = NULL; - ft->comment_close = NULL; - ft->group = GEANY_FILETYPE_GROUP_NONE; } @@ -588,7 +594,20 @@ static GeanyFiletype *filetype_new(void) } -/* Add a filetype pointer to the list of available filetypes, +static gint cmp_filetype(gconstpointer pft1, gconstpointer pft2) +{ + const GeanyFiletype *ft1 = pft1, *ft2 = pft2; + + if (ft1->id == GEANY_FILETYPES_NONE) + return -1; + if (ft2->id == GEANY_FILETYPES_NONE) + return 1; + + return utils_str_casecmp(ft1->title, ft2->title); +} + + +/* Add a filetype pointer to the lists of available filetypes, * and set the filetype::id field. */ static void filetype_add(GeanyFiletype *ft) { @@ -598,6 +617,8 @@ static void filetype_add(GeanyFiletype *ft) ft->id = filetypes_array->len; /* len will be the index for filetype_array */ g_ptr_array_add(filetypes_array, ft); g_hash_table_insert(filetypes_hash, ft->name, ft); + + filetypes_by_title = g_slist_insert_sorted(filetypes_by_title, ft, cmp_filetype); } @@ -646,61 +667,41 @@ static void setup_config_file_menus(void) } -#define create_sub_menu(menu, item, title) \ - (menu) = gtk_menu_new(); \ - (item) = gtk_menu_item_new_with_mnemonic((title)); \ - gtk_menu_item_set_submenu(GTK_MENU_ITEM((item)), (menu)); \ - gtk_container_add(GTK_CONTAINER(filetype_menu), (item)); \ - gtk_widget_show((item)); +static GtkWidget *group_menus[GEANY_FILETYPE_GROUP_COUNT] = {NULL}; + +static void create_sub_menu(GtkWidget *parent, gsize group_id, const gchar *title) +{ + GtkWidget *menu, *item; + + menu = gtk_menu_new(); + item = gtk_menu_item_new_with_mnemonic((title)); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); + gtk_container_add(GTK_CONTAINER(parent), item); + gtk_widget_show(item); + group_menus[group_id] = menu; +} + + +static void add_ft_menu_item(gpointer pft, gpointer user_data) +{ + GeanyFiletype *ft = pft; + + create_radio_menu_item(group_menus[ft->group], ft); +} static void create_set_filetype_menu(void) { - filetype_id ft_id; GtkWidget *filetype_menu = ui_lookup_widget(main_widgets.window, "set_filetype1_menu"); - GtkWidget *sub_menu = filetype_menu; - GtkWidget *sub_menu_programming, *sub_menu_scripts, *sub_menu_markup, *sub_menu_misc; - GtkWidget *sub_item_programming, *sub_item_scripts, *sub_item_markup, *sub_item_misc; - create_sub_menu(sub_menu_programming, sub_item_programming, _("_Programming Languages")); - create_sub_menu(sub_menu_scripts, sub_item_scripts, _("_Scripting Languages")); - create_sub_menu(sub_menu_markup, sub_item_markup, _("_Markup Languages")); - create_sub_menu(sub_menu_misc, sub_item_misc, _("M_iscellaneous Languages")); + create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_COMPILED, _("_Programming Languages")); + create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_SCRIPT, _("_Scripting Languages")); + create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MARKUP, _("_Markup Languages")); + create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MISC, _("M_iscellaneous Languages")); /* Append all filetypes to the filetype menu */ - for (ft_id = 0; ft_id < filetypes_array->len; ft_id++) - { - GeanyFiletype *ft = filetypes[ft_id]; - const gchar *title = ft->title; - - /* insert separators for different filetype groups */ - switch (ft->group) - { - case GEANY_FILETYPE_GROUP_COMPILED: /* programming */ - sub_menu = sub_menu_programming; - break; - - case GEANY_FILETYPE_GROUP_SCRIPT: /* scripts */ - sub_menu = sub_menu_scripts; - break; - - case GEANY_FILETYPE_GROUP_MARKUP: /* markup */ - sub_menu = sub_menu_markup; - break; - - case GEANY_FILETYPE_GROUP_MISC: /* misc */ - sub_menu = sub_menu_misc; - break; - - case GEANY_FILETYPE_GROUP_NONE: /* none */ - sub_menu = filetype_menu; - title = _("None"); - break; - - default: break; - } - create_radio_menu_item(sub_menu, title, ft); - } + filetypes_foreach_named(add_ft_menu_item, NULL); + create_radio_menu_item(filetype_menu, filetypes[GEANY_FILETYPES_NONE]); } @@ -712,11 +713,8 @@ void filetypes_init() } -typedef gboolean FileTypesPredicate(GeanyFiletype *ft, gpointer user_data); - /* Find a filetype that predicate returns TRUE for, otherwise return NULL. */ -static GeanyFiletype *filetypes_find(gboolean source_only, - FileTypesPredicate predicate, gpointer user_data) +GeanyFiletype *filetypes_find(GCompareFunc predicate, gpointer user_data) { guint i; @@ -724,9 +722,6 @@ static GeanyFiletype *filetypes_find(gboolean source_only, { GeanyFiletype *ft = filetypes[i]; - if (source_only && i == GEANY_FILETYPES_NONE) - continue; /* None is not for source files */ - if (predicate(ft, user_data)) return ft; } @@ -734,12 +729,16 @@ static GeanyFiletype *filetypes_find(gboolean source_only, } -static gboolean match_basename(GeanyFiletype *ft, gpointer user_data) +static gboolean match_basename(gconstpointer pft, gconstpointer user_data) { + const GeanyFiletype *ft = pft; const gchar *base_filename = user_data; gint j; gboolean ret = FALSE; + if (ft->id == GEANY_FILETYPES_NONE) + return FALSE; + for (j = 0; ft->pattern[j] != NULL; j++) { GPatternSpec *pattern = g_pattern_spec_new(ft->pattern[j]); @@ -770,7 +769,7 @@ GeanyFiletype *filetypes_detect_from_extension(const gchar *utf8_filename) setptr(base_filename, g_utf8_strdown(base_filename, -1)); #endif - ft = filetypes_find(TRUE, match_basename, base_filename); + ft = filetypes_find(match_basename, base_filename); if (ft == NULL) ft = filetypes[GEANY_FILETYPES_NONE]; @@ -982,12 +981,12 @@ on_filetype_change (GtkMenuItem *menuitem, } -static void create_radio_menu_item(GtkWidget *menu, const gchar *label, GeanyFiletype *ftype) +static void create_radio_menu_item(GtkWidget *menu, GeanyFiletype *ftype) { static GSList *group = NULL; GtkWidget *tmp; - tmp = gtk_radio_menu_item_new_with_label(group, label); + tmp = gtk_radio_menu_item_new_with_label(group, ftype->title); group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(tmp)); ftype->priv->menu_item = tmp; gtk_widget_show(tmp); @@ -1240,7 +1239,7 @@ void filetypes_save_commands() G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", NULL); gint i; - for (i = 0; i < GEANY_FILETYPES_NONE; i++) + for (i = 1; i < GEANY_MAX_BUILT_IN_FILETYPES; i++) { struct build_programs *bp = filetypes[i]->programs; GKeyFile *config_home; @@ -1301,11 +1300,13 @@ GtkFileFilter *filetypes_create_file_filter(const GeanyFiletype *ft) { GtkFileFilter *new_filter; gint i; + const gchar *title; g_return_val_if_fail(ft != NULL, NULL); new_filter = gtk_file_filter_new(); - gtk_file_filter_set_name(new_filter, ft->title); + title = ft->id == GEANY_FILETYPES_NONE ? _("All files") : ft->title; + gtk_file_filter_set_name(new_filter, title); for (i = 0; ft->pattern[i]; i++) { @@ -1480,3 +1481,16 @@ GeanyFiletype *filetypes_index(gint idx) } +/* Does not include ft[GEANY_FILETYPES_NONE], as this is usually treated specially. */ +void filetypes_foreach_named(GFunc callback, gpointer user_data) +{ + GSList *node; + GeanyFiletype *ft; + + foreach_slist(ft, node, filetypes_by_title) + { + if (ft->id != GEANY_FILETYPES_NONE) + callback(ft, user_data); + } +} + diff --git a/src/filetypes.h b/src/filetypes.h index fa96e909..b54bdffb 100644 --- a/src/filetypes.h +++ b/src/filetypes.h @@ -29,66 +29,58 @@ #include "ScintillaWidget.h" -/* Each group should be alpha-sorted, based on filetype::name (not enum name). - * Warning: remember to break the plugin ABI when adding items. */ -/* TODO: for a stable ABI put GEANY_FILETYPES_NONE first, and use a sorted duplicate - * filetypes array for GUI elements. */ typedef enum { - /* normally compiled languages */ - GEANY_FILETYPES_ADA = 0, - GEANY_FILETYPES_AS, - GEANY_FILETYPES_ASM, - GEANY_FILETYPES_C, - GEANY_FILETYPES_CPP, - GEANY_FILETYPES_CS, - GEANY_FILETYPES_CAML, - GEANY_FILETYPES_D, - GEANY_FILETYPES_F77, - GEANY_FILETYPES_FORTRAN, - GEANY_FILETYPES_BASIC, /* FreeBasic */ - GEANY_FILETYPES_GLSL, - GEANY_FILETYPES_HASKELL, - GEANY_FILETYPES_HAXE, - GEANY_FILETYPES_JAVA, - GEANY_FILETYPES_PASCAL, - GEANY_FILETYPES_VALA, - GEANY_FILETYPES_VHDL, + GEANY_FILETYPES_NONE = 0, /* first filetype is always None */ - /* script languages */ - GEANY_FILETYPES_FERITE, - GEANY_FILETYPES_JS, - GEANY_FILETYPES_LUA, - GEANY_FILETYPES_MAKE, - GEANY_FILETYPES_MATLAB, - GEANY_FILETYPES_PERL, GEANY_FILETYPES_PHP, - GEANY_FILETYPES_PYTHON, - GEANY_FILETYPES_R, + GEANY_FILETYPES_BASIC, /* FreeBasic */ + GEANY_FILETYPES_MATLAB, GEANY_FILETYPES_RUBY, - GEANY_FILETYPES_SH, - GEANY_FILETYPES_TCL, - - /* markup languages */ - GEANY_FILETYPES_CSS, - GEANY_FILETYPES_DOCBOOK, - GEANY_FILETYPES_HTML, - GEANY_FILETYPES_XML, - - /* miscellaneous languages */ - GEANY_FILETYPES_CMAKE, - GEANY_FILETYPES_CONF, - GEANY_FILETYPES_DIFF, - GEANY_FILETYPES_NSIS, - GEANY_FILETYPES_PO, - GEANY_FILETYPES_LATEX, - GEANY_FILETYPES_REST, - GEANY_FILETYPES_SQL, + GEANY_FILETYPES_LUA, + GEANY_FILETYPES_FERITE, GEANY_FILETYPES_YAML, + GEANY_FILETYPES_C, + GEANY_FILETYPES_NSIS, + GEANY_FILETYPES_GLSL, + GEANY_FILETYPES_PO, + GEANY_FILETYPES_MAKE, + GEANY_FILETYPES_TCL, + GEANY_FILETYPES_XML, + GEANY_FILETYPES_CSS, + GEANY_FILETYPES_REST, + GEANY_FILETYPES_HASKELL, + GEANY_FILETYPES_JAVA, + GEANY_FILETYPES_CAML, + GEANY_FILETYPES_AS, + GEANY_FILETYPES_R, + GEANY_FILETYPES_DIFF, + GEANY_FILETYPES_HTML, + GEANY_FILETYPES_PYTHON, + GEANY_FILETYPES_CS, + GEANY_FILETYPES_PERL, + GEANY_FILETYPES_VALA, + GEANY_FILETYPES_PASCAL, + GEANY_FILETYPES_LATEX, + GEANY_FILETYPES_ASM, + GEANY_FILETYPES_CONF, + GEANY_FILETYPES_HAXE, + GEANY_FILETYPES_CPP, + GEANY_FILETYPES_SH, + GEANY_FILETYPES_FORTRAN, + GEANY_FILETYPES_SQL, + GEANY_FILETYPES_F77, + GEANY_FILETYPES_DOCBOOK, + GEANY_FILETYPES_D, + GEANY_FILETYPES_JS, + GEANY_FILETYPES_VHDL, + GEANY_FILETYPES_ADA, + GEANY_FILETYPES_CMAKE, - GEANY_FILETYPES_NONE, /* must be last filetype */ - GEANY_MAX_BUILT_IN_FILETYPES /* Use filetypes_array->len instead */ -} filetype_id; + /* ^ append items here */ + GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */ +} +filetype_id; typedef enum { @@ -96,7 +88,8 @@ typedef enum GEANY_FILETYPE_GROUP_COMPILED, GEANY_FILETYPE_GROUP_SCRIPT, GEANY_FILETYPE_GROUP_MARKUP, - GEANY_FILETYPE_GROUP_MISC + GEANY_FILETYPE_GROUP_MISC, + GEANY_FILETYPE_GROUP_COUNT } GeanyFiletypeGroupID; @@ -151,9 +144,15 @@ extern GPtrArray *filetypes_array; * Example: filetypes[GEANY_FILETYPES_C]->name = ...; */ #define filetypes ((GeanyFiletype **)filetypes_array->pdata) +extern GSList *filetypes_by_title; + GeanyFiletype *filetypes_lookup_by_name(const gchar *name); +void filetypes_foreach_named(GFunc callback, gpointer user_data); + +GeanyFiletype *filetypes_find(GCompareFunc predicate, gpointer user_data); + void filetypes_init(void); diff --git a/src/highlighting.c b/src/highlighting.c index b7a0d962..f3ac60b7 100644 --- a/src/highlighting.c +++ b/src/highlighting.c @@ -3435,7 +3435,7 @@ void highlighting_set_styles(ScintillaObject *sci, gint filetype_idx) filetypes_load_config(filetype_idx, FALSE); /* load filetypes.ext */ /* load tags files (some lexers highlight global typenames) */ - if (filetype_idx < GEANY_FILETYPES_NONE) + if (filetype_idx != GEANY_FILETYPES_NONE) symbols_global_tags_loaded(filetype_idx); switch (filetype_idx) diff --git a/src/plugindata.h b/src/plugindata.h index 27b5692d..4cd1306f 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -45,13 +45,13 @@ enum { /** The Application Programming Interface (API) version, incremented * whenever any plugin data types are modified or appended to. */ - GEANY_API_VERSION = 137, + GEANY_API_VERSION = 138, /** 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 = 59 + GEANY_ABI_VERSION = 62 }; /** Check the plugin can be loaded by Geany. @@ -188,6 +188,7 @@ typedef struct GeanyData struct GeanyToolPrefs *tool_prefs; /**< Tool settings */ struct GeanyTemplatePrefs *template_prefs; /**< Template settings */ struct GeanyBuildInfo *build_info; /**< Current build information */ + GSList *filetypes_by_title; /**< See filetypes.h#filetypes_by_title. */ } GeanyData; diff --git a/src/plugins.c b/src/plugins.c index 3a54ccbe..d9817ea5 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -351,7 +351,8 @@ geany_data_init(void) &search_prefs, &tool_prefs, &template_prefs, - &build_info + &build_info, + filetypes_by_title }; memcpy(&geany_data, &gd, sizeof(GeanyData)); } diff --git a/src/symbols.c b/src/symbols.c index 1641e5de..3495f7a1 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1381,7 +1381,7 @@ static GHashTable *get_tagfile_hash(const GSList *file_list) g_free(utf8_fname); - if (FILETYPE_ID(ft) < GEANY_FILETYPES_NONE) + if (FILETYPE_ID(ft) != GEANY_FILETYPES_NONE) { fnames = g_hash_table_lookup(hash, ft); /* may be NULL */ fnames = g_list_append(fnames, fname); @@ -1417,13 +1417,14 @@ static GHashTable *init_user_tags(void) static void load_user_tags(filetype_id ft_id) { - static guchar tags_loaded[GEANY_FILETYPES_NONE] = {0}; + static guchar tags_loaded[GEANY_MAX_BUILT_IN_FILETYPES - 1] = {0}; static GHashTable *lang_hash = NULL; GList *fnames; const GList *node; const GeanyFiletype *ft = filetypes[ft_id]; - g_return_if_fail(ft_id < GEANY_FILETYPES_NONE); + g_return_if_fail(ft_id > 0); + g_return_if_fail(ft_id < GEANY_MAX_BUILT_IN_FILETYPES); if (tags_loaded[ft_id]) return; diff --git a/src/templates.c b/src/templates.c index eb14ce22..7754d0a3 100644 --- a/src/templates.c +++ b/src/templates.c @@ -362,18 +362,17 @@ on_new_with_template (GtkMenuItem *menuitem, /* template items for the new file menu */ static void create_new_menu_items(void) { - filetype_id ft_id; + GeanyFiletype *ft; + GSList *node; - for (ft_id = 0; ft_id < GEANY_MAX_BUILT_IN_FILETYPES; ft_id++) + foreach_slist(ft, node, filetypes_by_title) { + filetype_id ft_id = ft->id; GtkWidget *tmp_menu, *tmp_button; - GeanyFiletype *ft = filetypes[ft_id]; const gchar *label = ft->title; if (ft_templates[ft_id] == NULL) continue; - if (ft_id == GEANY_FILETYPES_NONE) - label = _("None"); tmp_menu = gtk_menu_item_new_with_label(label); gtk_widget_show(tmp_menu); diff --git a/src/ui_utils.c b/src/ui_utils.c index 9d96ac2b..5ef1170a 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -134,6 +134,14 @@ void ui_set_statusbar(gboolean log, const gchar *format, ...) } +static GeanyFiletype *document_get_filetype(GeanyDocument *doc) +{ + g_return_val_if_fail(doc, NULL); + + return filetypes[FILETYPE_ID(doc->file_type)]; +} + + /* updates the status bar document statistics */ void ui_update_statusbar(GeanyDocument *doc, gint pos) { @@ -149,13 +157,7 @@ void ui_update_statusbar(GeanyDocument *doc, gint pos) const gchar sp[] = " "; guint line, col; const gchar *cur_tag; - gchar *filetype_name; - - /* workaround to make the name of filetype GEANY_FILETYPES_NONE translatable */ - if (doc->file_type == NULL || doc->file_type->id == GEANY_FILETYPES_NONE) - filetype_name = _("None"); - else - filetype_name = doc->file_type->name; + gchar *filetype_name = document_get_filetype(doc)->name; if (stats_str == NULL) stats_str = g_string_sized_new(120); diff --git a/src/utils.h b/src/utils.h index e2752a1a..1fe19125 100644 --- a/src/utils.h +++ b/src/utils.h @@ -57,6 +57,11 @@ for (ptr = ptr_array->pdata, item = *ptr; \ ptr < &ptr_array->pdata[ptr_array->len]; ++ptr, item = *ptr) +/* @param node should be a (GSList*), needed for implementation. */ +#define foreach_slist(data_ptr, node, list) \ + for (node = list, data_ptr = node ? node->data : NULL; node != NULL; \ + node = g_slist_next(node), data_ptr = node ? node->data : NULL) + void utils_open_browser(const gchar *uri);