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. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@3681 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
commit
1681861fa1
14
ChangeLog
14
ChangeLog
@ -3,6 +3,20 @@
|
|||||||
* src/filetypes.c, doc/geany.txt:
|
* src/filetypes.c, doc/geany.txt:
|
||||||
Move ActionScript to the Script group.
|
Move ActionScript to the Script group.
|
||||||
Fix wording & typo.
|
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 <enrico(dot)troeger(at)uvena(dot)de>
|
2009-03-31 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
/* HTML Characters plugin (Inserts HTML character entities like '&') */
|
/* HTML Characters plugin (Inserts HTML character entities like '&') */
|
||||||
|
|
||||||
#include "geany.h"
|
#include "geany.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "plugindata.h"
|
#include "plugindata.h"
|
||||||
#include "document.h"
|
#include "document.h"
|
||||||
|
@ -603,6 +603,8 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
|
|||||||
{
|
{
|
||||||
GtkWidget *combo;
|
GtkWidget *combo;
|
||||||
guint i;
|
guint i;
|
||||||
|
GSList *node;
|
||||||
|
GeanyFiletype *ft;
|
||||||
|
|
||||||
notebook_vbox = gtk_vbox_new(FALSE, 2);
|
notebook_vbox = gtk_vbox_new(FALSE, 2);
|
||||||
inner_vbox = gtk_vbox_new(FALSE, 5);
|
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);
|
gtk_box_pack_start(GTK_BOX(inner_vbox), label, FALSE, FALSE, 0);
|
||||||
|
|
||||||
pref_widgets.instantsave_ft_combo = combo = gtk_combo_box_new_text();
|
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);
|
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), ft->name);
|
||||||
|
|
||||||
if (utils_str_equal(ft->name, instantsave_default_ft))
|
if (utils_str_equal(ft->name, instantsave_default_ft))
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
|
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3);
|
gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3);
|
||||||
gtk_label_set_mnemonic_widget(GTK_LABEL(label), combo);
|
gtk_label_set_mnemonic_widget(GTK_LABEL(label), combo);
|
||||||
|
@ -90,8 +90,8 @@ on_file_open_dialog_response (GtkDialog *dialog,
|
|||||||
gboolean ro = (response == GEANY_RESPONSE_VIEW); /* View clicked */
|
gboolean ro = (response == GEANY_RESPONSE_VIEW); /* View clicked */
|
||||||
|
|
||||||
/* ignore detect from file item */
|
/* ignore detect from file item */
|
||||||
if (filetype_idx >= 0 && filetype_idx < GEANY_FILETYPES_NONE)
|
if (filetype_idx > 0 && filetype_idx < GEANY_MAX_BUILT_IN_FILETYPES)
|
||||||
ft = filetypes[filetype_idx];
|
ft = g_slist_nth_data(filetypes_by_title, filetype_idx);
|
||||||
if (encoding_idx >= 0 && encoding_idx < GEANY_ENCODINGS_MAX)
|
if (encoding_idx >= 0 && encoding_idx < GEANY_ENCODINGS_MAX)
|
||||||
charset = encodings[encoding_idx].charset;
|
charset = encodings[encoding_idx].charset;
|
||||||
|
|
||||||
@ -177,6 +177,8 @@ static void create_open_file_dialog(void)
|
|||||||
GtkWidget *viewbtn;
|
GtkWidget *viewbtn;
|
||||||
guint i;
|
guint i;
|
||||||
gchar *encoding_string;
|
gchar *encoding_string;
|
||||||
|
GeanyFiletype *ft;
|
||||||
|
GSList *node;
|
||||||
|
|
||||||
ui_widgets.open_filesel = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window),
|
ui_widgets.open_filesel = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window),
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
|
GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
|
||||||
@ -207,23 +209,22 @@ static void create_open_file_dialog(void)
|
|||||||
add_file_open_extra_widget());
|
add_file_open_extra_widget());
|
||||||
filetype_combo = ui_lookup_widget(ui_widgets.open_filesel, "filetype_combo");
|
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") */
|
/* add FileFilters(start with "All Files") */
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel),
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel),
|
||||||
filetypes_create_file_filter(filetypes[GEANY_FILETYPES_NONE]));
|
filetypes_create_file_filter(filetypes[GEANY_FILETYPES_NONE]));
|
||||||
/* now create meta filter "All Source" */
|
/* now create meta filter "All Source" */
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel),
|
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel),
|
||||||
filetypes_create_file_filter_all_source());
|
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;
|
continue;
|
||||||
|
gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), ft->title);
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(filetype_combo), filetypes[i]->title);
|
|
||||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(ui_widgets.open_filesel),
|
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), 0);
|
||||||
gtk_combo_box_set_active(GTK_COMBO_BOX(filetype_combo), filetypes_array->len - 1);
|
|
||||||
|
|
||||||
/* fill encoding combo box */
|
/* fill encoding combo box */
|
||||||
encoding_combo = ui_lookup_widget(ui_widgets.open_filesel, "encoding_combo");
|
encoding_combo = ui_lookup_widget(ui_widgets.open_filesel, "encoding_combo");
|
||||||
|
164
src/filetypes.c
164
src/filetypes.c
@ -67,10 +67,16 @@ GeanyFiletypePrivate;
|
|||||||
|
|
||||||
GPtrArray *filetypes_array = NULL; /* Dynamic array of filetype pointers */
|
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. */
|
/* Note: remember to update HACKING if this function is renamed. */
|
||||||
@ -78,7 +84,18 @@ static void init_builtin_filetypes(void)
|
|||||||
{
|
{
|
||||||
GeanyFiletype *ft;
|
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 = filetypes[GEANY_FILETYPES_C];
|
||||||
ft->lang = 0;
|
ft->lang = 0;
|
||||||
ft->name = g_strdup("C");
|
ft->name = g_strdup("C");
|
||||||
@ -560,17 +577,6 @@ static void init_builtin_filetypes(void)
|
|||||||
ft->comment_open = g_strdup("--");
|
ft->comment_open = g_strdup("--");
|
||||||
ft->comment_close = NULL;
|
ft->comment_close = NULL;
|
||||||
ft->group = GEANY_FILETYPE_GROUP_COMPILED;
|
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. */
|
* and set the filetype::id field. */
|
||||||
static void filetype_add(GeanyFiletype *ft)
|
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 */
|
ft->id = filetypes_array->len; /* len will be the index for filetype_array */
|
||||||
g_ptr_array_add(filetypes_array, ft);
|
g_ptr_array_add(filetypes_array, ft);
|
||||||
g_hash_table_insert(filetypes_hash, ft->name, 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) \
|
static GtkWidget *group_menus[GEANY_FILETYPE_GROUP_COUNT] = {NULL};
|
||||||
(menu) = gtk_menu_new(); \
|
|
||||||
(item) = gtk_menu_item_new_with_mnemonic((title)); \
|
static void create_sub_menu(GtkWidget *parent, gsize group_id, const gchar *title)
|
||||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM((item)), (menu)); \
|
{
|
||||||
gtk_container_add(GTK_CONTAINER(filetype_menu), (item)); \
|
GtkWidget *menu, *item;
|
||||||
gtk_widget_show((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)
|
static void create_set_filetype_menu(void)
|
||||||
{
|
{
|
||||||
filetype_id ft_id;
|
|
||||||
GtkWidget *filetype_menu = ui_lookup_widget(main_widgets.window, "set_filetype1_menu");
|
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(filetype_menu, GEANY_FILETYPE_GROUP_COMPILED, _("_Programming Languages"));
|
||||||
create_sub_menu(sub_menu_scripts, sub_item_scripts, _("_Scripting Languages"));
|
create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_SCRIPT, _("_Scripting Languages"));
|
||||||
create_sub_menu(sub_menu_markup, sub_item_markup, _("_Markup Languages"));
|
create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MARKUP, _("_Markup Languages"));
|
||||||
create_sub_menu(sub_menu_misc, sub_item_misc, _("M_iscellaneous Languages"));
|
create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MISC, _("M_iscellaneous Languages"));
|
||||||
|
|
||||||
/* Append all filetypes to the filetype menu */
|
/* Append all filetypes to the filetype menu */
|
||||||
for (ft_id = 0; ft_id < filetypes_array->len; ft_id++)
|
filetypes_foreach_named(add_ft_menu_item, NULL);
|
||||||
{
|
create_radio_menu_item(filetype_menu, filetypes[GEANY_FILETYPES_NONE]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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. */
|
/* Find a filetype that predicate returns TRUE for, otherwise return NULL. */
|
||||||
static GeanyFiletype *filetypes_find(gboolean source_only,
|
GeanyFiletype *filetypes_find(GCompareFunc predicate, gpointer user_data)
|
||||||
FileTypesPredicate predicate, gpointer user_data)
|
|
||||||
{
|
{
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
@ -724,9 +722,6 @@ static GeanyFiletype *filetypes_find(gboolean source_only,
|
|||||||
{
|
{
|
||||||
GeanyFiletype *ft = filetypes[i];
|
GeanyFiletype *ft = filetypes[i];
|
||||||
|
|
||||||
if (source_only && i == GEANY_FILETYPES_NONE)
|
|
||||||
continue; /* None is not for source files */
|
|
||||||
|
|
||||||
if (predicate(ft, user_data))
|
if (predicate(ft, user_data))
|
||||||
return ft;
|
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;
|
const gchar *base_filename = user_data;
|
||||||
gint j;
|
gint j;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
if (ft->id == GEANY_FILETYPES_NONE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
for (j = 0; ft->pattern[j] != NULL; j++)
|
for (j = 0; ft->pattern[j] != NULL; j++)
|
||||||
{
|
{
|
||||||
GPatternSpec *pattern = g_pattern_spec_new(ft->pattern[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));
|
setptr(base_filename, g_utf8_strdown(base_filename, -1));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ft = filetypes_find(TRUE, match_basename, base_filename);
|
ft = filetypes_find(match_basename, base_filename);
|
||||||
if (ft == NULL)
|
if (ft == NULL)
|
||||||
ft = filetypes[GEANY_FILETYPES_NONE];
|
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;
|
static GSList *group = NULL;
|
||||||
GtkWidget *tmp;
|
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));
|
group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(tmp));
|
||||||
ftype->priv->menu_item = tmp;
|
ftype->priv->menu_item = tmp;
|
||||||
gtk_widget_show(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);
|
G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", NULL);
|
||||||
gint i;
|
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;
|
struct build_programs *bp = filetypes[i]->programs;
|
||||||
GKeyFile *config_home;
|
GKeyFile *config_home;
|
||||||
@ -1301,11 +1300,13 @@ GtkFileFilter *filetypes_create_file_filter(const GeanyFiletype *ft)
|
|||||||
{
|
{
|
||||||
GtkFileFilter *new_filter;
|
GtkFileFilter *new_filter;
|
||||||
gint i;
|
gint i;
|
||||||
|
const gchar *title;
|
||||||
|
|
||||||
g_return_val_if_fail(ft != NULL, NULL);
|
g_return_val_if_fail(ft != NULL, NULL);
|
||||||
|
|
||||||
new_filter = gtk_file_filter_new();
|
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++)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
107
src/filetypes.h
107
src/filetypes.h
@ -29,66 +29,58 @@
|
|||||||
#include "ScintillaWidget.h"
|
#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
|
typedef enum
|
||||||
{
|
{
|
||||||
/* normally compiled languages */
|
GEANY_FILETYPES_NONE = 0, /* first filetype is always None */
|
||||||
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,
|
|
||||||
|
|
||||||
/* 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_PHP,
|
||||||
GEANY_FILETYPES_PYTHON,
|
GEANY_FILETYPES_BASIC, /* FreeBasic */
|
||||||
GEANY_FILETYPES_R,
|
GEANY_FILETYPES_MATLAB,
|
||||||
GEANY_FILETYPES_RUBY,
|
GEANY_FILETYPES_RUBY,
|
||||||
GEANY_FILETYPES_SH,
|
GEANY_FILETYPES_LUA,
|
||||||
GEANY_FILETYPES_TCL,
|
GEANY_FILETYPES_FERITE,
|
||||||
|
|
||||||
/* 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_YAML,
|
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 */
|
/* ^ append items here */
|
||||||
GEANY_MAX_BUILT_IN_FILETYPES /* Use filetypes_array->len instead */
|
GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */
|
||||||
} filetype_id;
|
}
|
||||||
|
filetype_id;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -96,7 +88,8 @@ typedef enum
|
|||||||
GEANY_FILETYPE_GROUP_COMPILED,
|
GEANY_FILETYPE_GROUP_COMPILED,
|
||||||
GEANY_FILETYPE_GROUP_SCRIPT,
|
GEANY_FILETYPE_GROUP_SCRIPT,
|
||||||
GEANY_FILETYPE_GROUP_MARKUP,
|
GEANY_FILETYPE_GROUP_MARKUP,
|
||||||
GEANY_FILETYPE_GROUP_MISC
|
GEANY_FILETYPE_GROUP_MISC,
|
||||||
|
GEANY_FILETYPE_GROUP_COUNT
|
||||||
}
|
}
|
||||||
GeanyFiletypeGroupID;
|
GeanyFiletypeGroupID;
|
||||||
|
|
||||||
@ -151,9 +144,15 @@ extern GPtrArray *filetypes_array;
|
|||||||
* Example: filetypes[GEANY_FILETYPES_C]->name = ...; */
|
* Example: filetypes[GEANY_FILETYPES_C]->name = ...; */
|
||||||
#define filetypes ((GeanyFiletype **)filetypes_array->pdata)
|
#define filetypes ((GeanyFiletype **)filetypes_array->pdata)
|
||||||
|
|
||||||
|
extern GSList *filetypes_by_title;
|
||||||
|
|
||||||
|
|
||||||
GeanyFiletype *filetypes_lookup_by_name(const gchar *name);
|
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);
|
void filetypes_init(void);
|
||||||
|
|
||||||
|
@ -3435,7 +3435,7 @@ void highlighting_set_styles(ScintillaObject *sci, gint filetype_idx)
|
|||||||
filetypes_load_config(filetype_idx, FALSE); /* load filetypes.ext */
|
filetypes_load_config(filetype_idx, FALSE); /* load filetypes.ext */
|
||||||
|
|
||||||
/* load tags files (some lexers highlight global typenames) */
|
/* 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);
|
symbols_global_tags_loaded(filetype_idx);
|
||||||
|
|
||||||
switch (filetype_idx)
|
switch (filetype_idx)
|
||||||
|
@ -45,13 +45,13 @@
|
|||||||
enum {
|
enum {
|
||||||
/** The Application Programming Interface (API) version, incremented
|
/** The Application Programming Interface (API) version, incremented
|
||||||
* whenever any plugin data types are modified or appended to. */
|
* 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
|
/** The Application Binary Interface (ABI) version, incremented whenever
|
||||||
* existing fields in the plugin data types have to be changed or reordered. */
|
* 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
|
/* This should usually stay the same if fields are only appended, assuming only pointers to
|
||||||
* structs and not structs themselves are declared by plugins. */
|
* 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.
|
/** Check the plugin can be loaded by Geany.
|
||||||
@ -188,6 +188,7 @@ typedef struct GeanyData
|
|||||||
struct GeanyToolPrefs *tool_prefs; /**< Tool settings */
|
struct GeanyToolPrefs *tool_prefs; /**< Tool settings */
|
||||||
struct GeanyTemplatePrefs *template_prefs; /**< Template settings */
|
struct GeanyTemplatePrefs *template_prefs; /**< Template settings */
|
||||||
struct GeanyBuildInfo *build_info; /**< Current build information */
|
struct GeanyBuildInfo *build_info; /**< Current build information */
|
||||||
|
GSList *filetypes_by_title; /**< See filetypes.h#filetypes_by_title. */
|
||||||
}
|
}
|
||||||
GeanyData;
|
GeanyData;
|
||||||
|
|
||||||
|
@ -351,7 +351,8 @@ geany_data_init(void)
|
|||||||
&search_prefs,
|
&search_prefs,
|
||||||
&tool_prefs,
|
&tool_prefs,
|
||||||
&template_prefs,
|
&template_prefs,
|
||||||
&build_info
|
&build_info,
|
||||||
|
filetypes_by_title
|
||||||
};
|
};
|
||||||
memcpy(&geany_data, &gd, sizeof(GeanyData));
|
memcpy(&geany_data, &gd, sizeof(GeanyData));
|
||||||
}
|
}
|
||||||
|
@ -1381,7 +1381,7 @@ static GHashTable *get_tagfile_hash(const GSList *file_list)
|
|||||||
|
|
||||||
g_free(utf8_fname);
|
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_hash_table_lookup(hash, ft); /* may be NULL */
|
||||||
fnames = g_list_append(fnames, fname);
|
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 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;
|
static GHashTable *lang_hash = NULL;
|
||||||
GList *fnames;
|
GList *fnames;
|
||||||
const GList *node;
|
const GList *node;
|
||||||
const GeanyFiletype *ft = filetypes[ft_id];
|
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])
|
if (tags_loaded[ft_id])
|
||||||
return;
|
return;
|
||||||
|
@ -362,18 +362,17 @@ on_new_with_template (GtkMenuItem *menuitem,
|
|||||||
/* template items for the new file menu */
|
/* template items for the new file menu */
|
||||||
static void create_new_menu_items(void)
|
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;
|
GtkWidget *tmp_menu, *tmp_button;
|
||||||
GeanyFiletype *ft = filetypes[ft_id];
|
|
||||||
const gchar *label = ft->title;
|
const gchar *label = ft->title;
|
||||||
|
|
||||||
if (ft_templates[ft_id] == NULL)
|
if (ft_templates[ft_id] == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (ft_id == GEANY_FILETYPES_NONE)
|
|
||||||
label = _("None");
|
|
||||||
|
|
||||||
tmp_menu = gtk_menu_item_new_with_label(label);
|
tmp_menu = gtk_menu_item_new_with_label(label);
|
||||||
gtk_widget_show(tmp_menu);
|
gtk_widget_show(tmp_menu);
|
||||||
|
@ -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 */
|
/* updates the status bar document statistics */
|
||||||
void ui_update_statusbar(GeanyDocument *doc, gint pos)
|
void ui_update_statusbar(GeanyDocument *doc, gint pos)
|
||||||
{
|
{
|
||||||
@ -149,13 +157,7 @@ void ui_update_statusbar(GeanyDocument *doc, gint pos)
|
|||||||
const gchar sp[] = " ";
|
const gchar sp[] = " ";
|
||||||
guint line, col;
|
guint line, col;
|
||||||
const gchar *cur_tag;
|
const gchar *cur_tag;
|
||||||
gchar *filetype_name;
|
gchar *filetype_name = document_get_filetype(doc)->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;
|
|
||||||
|
|
||||||
if (stats_str == NULL)
|
if (stats_str == NULL)
|
||||||
stats_str = g_string_sized_new(120);
|
stats_str = g_string_sized_new(120);
|
||||||
|
@ -57,6 +57,11 @@
|
|||||||
for (ptr = ptr_array->pdata, item = *ptr; \
|
for (ptr = ptr_array->pdata, item = *ptr; \
|
||||||
ptr < &ptr_array->pdata[ptr_array->len]; ++ptr, 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);
|
void utils_open_browser(const gchar *uri);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user