~ubuntu-branches/ubuntu/raring/geany/raring-proposed

« back to all changes in this revision

Viewing changes to src/filetypes.c

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-12-10 07:43:26 UTC
  • mfrom: (3.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20111210074326-s8yqbew5i20h33tf
Tags: 0.21-1ubuntu1
* Merge from Debian Unstable, remaining changes:
  - debian/patches/20_use_evince_viewer.patch:
     + use evince as viewer for pdf and dvi files
  - debian/patches/20_use_x_terminal_emulator.patch:
     + use x-terminal-emulator as terminal
  - debian/control
     + Add breaks on geany-plugins-common << 0.20
* Also fixes bugs:
  - Filter for MATLAB/Octave files filters everythign (LP: 885505)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *      filetypes.c - this file is part of Geany, a fast and lightweight IDE
3
3
 *
4
 
 *      Copyright 2005-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5
 
 *      Copyright 2006-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
 
4
 *      Copyright 2005-2011 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
 
5
 *      Copyright 2006-2011 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
6
6
 *
7
7
 *      This program is free software; you can redistribute it and/or modify
8
8
 *      it under the terms of the GNU General Public License as published by
18
18
 *      along with this program; if not, write to the Free Software
19
19
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
20
 *
21
 
 * $Id: filetypes.c 5393 2010-11-10 18:04:15Z ntrel $
 
21
 * $Id: filetypes.c 5964 2011-09-28 10:47:43Z ntrel $
22
22
 */
23
23
 
24
24
/**
56
56
/** List of filetype pointers sorted by name, but with @c filetypes_index(GEANY_FILETYPES_NONE)
57
57
 * first, as this is usually treated specially.
58
58
 * The list does not change (after filetypes have been initialized), so you can use
59
 
 * @code g_slist_nth_data(filetypes_by_title, n) @endcode and expect the same result at different times. */
 
59
 * @code g_slist_nth_data(filetypes_by_title, n) @endcode and expect the same result at different times.
 
60
 * @see filetypes_get_sorted_by_name(). */
60
61
GSList *filetypes_by_title = NULL;
61
62
 
62
63
 
63
64
static void create_radio_menu_item(GtkWidget *menu, GeanyFiletype *ftype);
64
65
 
 
66
static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft);
 
67
static void read_filetype_config(void);
 
68
 
65
69
 
66
70
enum TitleType
67
71
{
275
279
        ft->lang = 36;
276
280
        ft->name = g_strdup("Markdown");
277
281
        filetype_make_title(ft, TITLE_SOURCE_FILE);
278
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
282
        ft->mime_type = g_strdup("text/x-markdown");
 
283
        ft->group = GEANY_FILETYPE_GROUP_MARKUP;
279
284
 
280
285
#define TXT2TAGS
281
286
        ft = filetypes[GEANY_FILETYPES_TXT2TAGS];
283
288
        ft->name = g_strdup("Txt2tags");
284
289
        filetype_make_title(ft, TITLE_SOURCE_FILE);
285
290
        ft->mime_type = g_strdup("text/x-txt2tags");
286
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
291
        ft->group = GEANY_FILETYPE_GROUP_MARKUP;
287
292
 
288
293
#define ABC
289
294
        ft = filetypes[GEANY_FILETYPES_ABC];
290
295
        ft->lang = 38;
291
296
        ft->name = g_strdup("Abc");
292
 
        filetype_make_title(ft, TITLE_SOURCE_FILE);
 
297
        filetype_make_title(ft, TITLE_FILE);
293
298
        ft->group = GEANY_FILETYPE_GROUP_MISC;
294
299
 
295
300
#define SH
296
301
        ft = filetypes[GEANY_FILETYPES_SH];
297
302
        ft->lang = 16;
298
303
        ft->name = g_strdup("Sh");
299
 
        ft->title = g_strdup(_("Shell script file"));
 
304
        ft->title = g_strdup(_("Shell script"));
300
305
        ft->mime_type = g_strdup("application/x-shellscript");
301
306
        ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
302
307
 
343
348
        ft = filetypes[GEANY_FILETYPES_SQL];
344
349
        ft->lang = 11;
345
350
        ft->name = g_strdup("SQL");
346
 
        ft->title = g_strdup(_("SQL Dump file"));
 
351
        filetype_make_title(ft, TITLE_FILE);
347
352
        ft->mime_type = g_strdup("text/x-sql");
348
353
        ft->group = GEANY_FILETYPE_GROUP_MISC;
349
354
 
 
355
#define COBOL
 
356
        ft = filetypes[GEANY_FILETYPES_COBOL];
 
357
        ft->lang = 41;
 
358
        ft->name = g_strdup("COBOL");
 
359
        filetype_make_title(ft, TITLE_SOURCE_FILE);
 
360
        ft->mime_type = g_strdup("text/x-cobol");
 
361
        ft->group = GEANY_FILETYPE_GROUP_COMPILED;
 
362
 
350
363
#define LATEX
351
364
        ft = filetypes[GEANY_FILETYPES_LATEX];
352
365
        ft->lang = 8;
353
366
        ft->name = g_strdup("LaTeX");
354
367
        filetype_make_title(ft, TITLE_SOURCE_FILE);
355
368
        ft->mime_type = g_strdup("text/x-tex");
356
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
369
        ft->group = GEANY_FILETYPE_GROUP_MARKUP;
357
370
 
358
371
#define VHDL
359
372
        ft = filetypes[GEANY_FILETYPES_VHDL];
368
381
        ft->lang = 39;
369
382
        ft->name = g_strdup("Verilog");
370
383
        filetype_make_title(ft, TITLE_SOURCE_FILE);
 
384
        ft->mime_type = g_strdup("text/x-verilog");
371
385
        ft->group = GEANY_FILETYPE_GROUP_COMPILED;
372
386
 
373
387
#define DIFF
424
438
        ft = filetypes[GEANY_FILETYPES_R];
425
439
        ft->lang = 40;
426
440
        ft->name = g_strdup("R");
427
 
        ft->title = g_strdup_printf(_("%s script file"), "R");
 
441
        filetype_make_title(ft, TITLE_SOURCE_FILE);
428
442
        ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
429
443
 
430
444
#define REST
431
445
        ft = filetypes[GEANY_FILETYPES_REST];
432
446
        ft->lang = 28;
433
447
        ft->name = g_strdup("reStructuredText");
434
 
        filetype_make_title(ft, TITLE_FILE);
435
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
448
        filetype_make_title(ft, TITLE_SOURCE_FILE);
 
449
        ft->group = GEANY_FILETYPE_GROUP_MARKUP;
436
450
 
437
451
#define MATLAB
438
452
        ft = filetypes[GEANY_FILETYPES_MATLAB];
445
459
#define YAML
446
460
        ft = filetypes[GEANY_FILETYPES_YAML];
447
461
        ft->name = g_strdup("YAML");
448
 
        filetype_make_title(ft, TITLE_SOURCE_FILE);
 
462
        filetype_make_title(ft, TITLE_FILE);
 
463
        ft->mime_type = g_strdup("application/x-yaml");
449
464
        ft->group = GEANY_FILETYPE_GROUP_MISC;
450
465
 
451
466
#define CMAKE
453
468
        ft->name = g_strdup("CMake");
454
469
        filetype_make_title(ft, TITLE_SOURCE_FILE);
455
470
        ft->mime_type = g_strdup("text/x-cmake");
456
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
471
        ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
457
472
 
458
473
#define NSIS
459
474
        ft = filetypes[GEANY_FILETYPES_NSIS];
460
475
        ft->lang = 35;
461
476
        ft->name = g_strdup("NSIS");
462
477
        filetype_make_title(ft, TITLE_SOURCE_FILE);
463
 
        ft->group = GEANY_FILETYPE_GROUP_MISC;
 
478
        ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
464
479
 
465
480
#define ADA
466
481
        ft = filetypes[GEANY_FILETYPES_ADA];
482
497
{
483
498
        GeanyFiletype *ft = g_new0(GeanyFiletype, 1);
484
499
 
 
500
        ft->group = GEANY_FILETYPE_GROUP_NONE;
485
501
        ft->lang = -2;  /* assume no tagmanager parser */
486
502
        /* pattern must not be null */
487
503
        ft->pattern = g_new0(gchar*, 1);
488
504
        ft->project_list_entry = -1; /* no entry */
 
505
        ft->indent_width = -1;
 
506
        ft->indent_type = -1;
489
507
 
490
508
        ft->priv = g_new0(GeanyFiletypePrivate, 1);
491
509
        return ft;
492
510
}
493
511
 
494
512
 
495
 
static gint cmp_filetype(gconstpointer pft1, gconstpointer pft2)
 
513
static gint cmp_filetype(gconstpointer pft1, gconstpointer pft2, gpointer data)
496
514
{
 
515
        gboolean by_name = GPOINTER_TO_INT(data);
497
516
        const GeanyFiletype *ft1 = pft1, *ft2 = pft2;
498
517
 
499
518
        if (G_UNLIKELY(ft1->id == GEANY_FILETYPES_NONE))
501
520
        if (G_UNLIKELY(ft2->id == GEANY_FILETYPES_NONE))
502
521
                return 1;
503
522
 
504
 
        return utils_str_casecmp(ft1->title, ft2->title);
 
523
        return by_name ?
 
524
                utils_str_casecmp(ft1->name, ft2->name) :
 
525
                utils_str_casecmp(ft1->title, ft2->title);
 
526
}
 
527
 
 
528
 
 
529
/** Gets a list of filetype pointers sorted by name.
 
530
 * The list does not change on subsequent calls.
 
531
 * @return The list - do not free.
 
532
 * @see filetypes_by_title. */
 
533
const GSList *filetypes_get_sorted_by_name(void)
 
534
{
 
535
        static GSList *list = NULL;
 
536
 
 
537
        g_return_val_if_fail(filetypes_by_title, NULL);
 
538
 
 
539
        if (!list)
 
540
        {
 
541
                list = g_slist_copy(filetypes_by_title);
 
542
                list = g_slist_sort_with_data(list, cmp_filetype, GINT_TO_POINTER(TRUE));
 
543
        }
 
544
        return list;
505
545
}
506
546
 
507
547
 
521
561
 
522
562
        if (!ft->mime_type)
523
563
                ft->mime_type = g_strdup("text/plain");
524
 
 
525
 
        ft->icon = ui_get_mime_icon(ft->mime_type, GTK_ICON_SIZE_MENU);
526
564
}
527
565
 
528
566
 
542
580
        ft = filetype_new();
543
581
        ft->name = g_strdup(fn);
544
582
        filetype_make_title(ft, TITLE_FILE);
545
 
        ft->group = GEANY_FILETYPE_GROUP_CUSTOM;
546
583
        ft->priv->custom = TRUE;
547
584
        filetype_add(ft);
548
585
        geany_debug("Added filetype %s (%d).", ft->name, ft->id);
574
611
}
575
612
 
576
613
 
577
 
/* Create the filetypes array and fill it with the known filetypes. */
 
614
/* Create the filetypes array and fill it with the known filetypes.
 
615
 * Warning: GTK isn't necessarily initialized yet. */
578
616
void filetypes_init_types()
579
617
{
580
618
        filetype_id ft_id;
 
619
        gchar *f;
581
620
 
582
621
        g_return_if_fail(filetypes_array == NULL);
583
622
        g_return_if_fail(filetypes_hash == NULL);
598
637
                filetype_add(filetypes[ft_id]);
599
638
        }
600
639
        init_custom_filetypes(app->datadir);
601
 
        init_custom_filetypes(utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, NULL));
 
640
        f = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, NULL);
 
641
        init_custom_filetypes(f);
 
642
        g_free(f);
602
643
 
603
644
        /* sort last instead of on insertion to prevent exponential time */
604
 
        filetypes_by_title = g_slist_sort(filetypes_by_title, cmp_filetype);
 
645
        filetypes_by_title = g_slist_sort_with_data(filetypes_by_title,
 
646
                cmp_filetype, GINT_TO_POINTER(FALSE));
 
647
 
 
648
        read_filetype_config();
605
649
}
606
650
 
607
651
 
608
652
static void on_document_save(G_GNUC_UNUSED GObject *object, GeanyDocument *doc)
609
653
{
 
654
        gchar *f;
 
655
 
610
656
        g_return_if_fail(NZV(doc->real_path));
611
657
 
612
 
        if (utils_str_equal(doc->real_path,
613
 
                utils_build_path(app->configdir, "filetype_extensions.conf", NULL)))
614
 
                filetypes_read_extensions();
615
 
        else if (utils_str_equal(doc->real_path,
616
 
                utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL)))
 
658
        f = utils_build_path(app->configdir, "filetype_extensions.conf", NULL);
 
659
        if (utils_str_equal(doc->real_path, f))
 
660
                filetypes_reload_extensions();
 
661
 
 
662
        g_free(f);
 
663
        f = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL);
 
664
        if (utils_str_equal(doc->real_path, f))
617
665
        {
618
666
                guint i;
619
667
 
624
672
                foreach_document(i)
625
673
                        document_reload_config(documents[i]);
626
674
        }
 
675
        g_free(f);
627
676
}
628
677
 
629
678
 
630
679
static void setup_config_file_menus(void)
631
680
{
632
 
        ui_add_config_file_menu_item(
633
 
                utils_build_path(app->configdir, "filetype_extensions.conf", NULL), NULL, NULL);
634
 
        ui_add_config_file_menu_item(
635
 
                utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL), NULL, NULL);
 
681
        gchar *f;
 
682
 
 
683
        f = utils_build_path(app->configdir, "filetype_extensions.conf", NULL);
 
684
        ui_add_config_file_menu_item(f, NULL, NULL);
 
685
        setptr(f, utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.common", NULL));
 
686
        ui_add_config_file_menu_item(f, NULL, NULL);
 
687
        g_free(f);
636
688
 
637
689
        g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL);
638
690
}
661
713
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_COMPILED, _("_Programming Languages"));
662
714
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_SCRIPT, _("_Scripting Languages"));
663
715
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MARKUP, _("_Markup Languages"));
664
 
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MISC, _("M_iscellaneous Languages"));
665
 
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_CUSTOM, _("_Custom Filetypes"));
 
716
        create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MISC, _("M_iscellaneous"));
666
717
 
667
718
        /* Append all filetypes to the filetype menu */
668
719
        foreach_slist(node, filetypes_by_title)
679
730
 
680
731
void filetypes_init()
681
732
{
 
733
        GSList *node;
 
734
 
682
735
        filetypes_init_types();
683
736
 
 
737
        /* this has to be here as GTK isn't initialized in filetypes_init_types(). */
 
738
        foreach_slist(node, filetypes_by_title)
 
739
        {
 
740
                GeanyFiletype *ft = node->data;
 
741
                ft->icon = ui_get_mime_icon(ft->mime_type, GTK_ICON_SIZE_MENU);
 
742
        }
684
743
        create_set_filetype_menu();
685
744
        setup_config_file_menus();
686
745
}
731
790
static GeanyFiletype *check_builtin_filenames(const gchar *utf8_filename)
732
791
{
733
792
        gchar *lfn = NULL;
734
 
        const gchar *path;
 
793
        gchar *path;
735
794
        gboolean found = FALSE;
736
795
 
737
796
#ifdef G_OS_WIN32
746
805
        if (g_str_has_prefix(lfn, path))
747
806
                found = TRUE;
748
807
 
749
 
        path = utils_build_path(app->datadir, "filetypes.", NULL);
 
808
        setptr(path, utils_build_path(app->datadir, "filetypes.", NULL));
750
809
        if (g_str_has_prefix(lfn, path))
751
810
                found = TRUE;
752
811
 
 
812
        g_free(path);
753
813
        g_free(lfn);
754
814
        return found ? filetypes[GEANY_FILETYPES_CONF] : NULL;
755
815
}
975
1035
 
976
1036
 
977
1037
static void
978
 
on_filetype_change                     (GtkCheckMenuItem     *menuitem,
979
 
                                        gpointer         user_data)
 
1038
on_filetype_change(GtkCheckMenuItem *menuitem, gpointer user_data)
980
1039
{
981
1040
        GeanyDocument *doc = document_get_current();
982
1041
        if (ignore_callback || doc == NULL || ! gtk_check_menu_item_get_active(menuitem))
1000
1059
}
1001
1060
 
1002
1061
 
1003
 
#if 0
1004
 
/* Remove a filetype pointer from the list of available filetypes. */
1005
 
static void filetype_remove(GeanyFiletype *ft)
1006
 
{
1007
 
        g_return_if_fail(ft);
1008
 
 
1009
 
        g_ptr_array_remove(filetypes_array, ft);
1010
 
 
1011
 
        if (!g_hash_table_remove(filetypes_hash, ft))
1012
 
                g_warning("Could not remove filetype %p!", ft);
1013
 
}
1014
 
#endif
1015
 
 
1016
 
 
1017
1062
static void set_error_regex(GeanyFiletype *ft, gchar *string)
1018
1063
{
1019
1064
        setptr(ft->error_regex_string, string);
1038
1083
        g_free(ft->mime_type);
1039
1084
        g_free(ft->comment_open);
1040
1085
        g_free(ft->comment_close);
 
1086
        g_free(ft->comment_single);
1041
1087
        g_free(ft->context_action_cmd);
1042
1088
        g_free(ft->filecmds);
1043
1089
        g_free(ft->ftdefcmds);
1064
1110
}
1065
1111
 
1066
1112
 
 
1113
static void load_indent_settings(GeanyFiletype *ft, GKeyFile *config, GKeyFile *configh)
 
1114
{
 
1115
        ft->indent_width = utils_get_setting(integer, configh, config, "indentation", "width", -1);
 
1116
        ft->indent_type = utils_get_setting(integer, configh, config, "indentation", "type", -1);
 
1117
        /* check whether the indent type is OK */
 
1118
        switch (ft->indent_type)
 
1119
        {
 
1120
                case GEANY_INDENT_TYPE_TABS:
 
1121
                case GEANY_INDENT_TYPE_SPACES:
 
1122
                case GEANY_INDENT_TYPE_BOTH:
 
1123
                case -1:
 
1124
                        break;
 
1125
 
 
1126
                default:
 
1127
                        g_warning("Invalid indent type %d in file type %s", ft->indent_type, ft->name);
 
1128
                        ft->indent_type = -1;
 
1129
                        break;
 
1130
        }
 
1131
}
 
1132
 
 
1133
 
1067
1134
static void load_settings(gint ft_id, GKeyFile *config, GKeyFile *configh)
1068
1135
{
1069
1136
        GeanyFiletype *ft = filetypes[ft_id];
1070
1137
        gchar *result;
1071
 
        GError *error = NULL;
1072
 
        gboolean tmp;
1073
1138
 
1074
1139
        /* default extension */
1075
 
        result = g_key_file_get_string(configh, "settings", "extension", NULL);
1076
 
        if (result == NULL) result = g_key_file_get_string(config, "settings", "extension", NULL);
1077
 
        if (G_LIKELY(result != NULL))
 
1140
        result = utils_get_setting(string, configh, config, "settings", "extension", NULL);
 
1141
        if (result != NULL)
1078
1142
        {
1079
1143
                setptr(filetypes[ft_id]->extension, result);
1080
1144
        }
1081
1145
 
1082
1146
        /* read comment notes */
1083
 
        result = g_key_file_get_string(configh, "settings", "comment_open", NULL);
1084
 
        if (result == NULL) result = g_key_file_get_string(config, "settings", "comment_open", NULL);
1085
 
        if (G_LIKELY(result != NULL))
1086
 
        {
1087
 
                g_free(filetypes[ft_id]->comment_open);
1088
 
                filetypes[ft_id]->comment_open = result;
1089
 
        }
1090
 
 
1091
 
        result = g_key_file_get_string(configh, "settings", "comment_close", NULL);
1092
 
        if (result == NULL) result = g_key_file_get_string(config, "settings", "comment_close", NULL);
1093
 
        if (G_LIKELY(result != NULL))
1094
 
        {
1095
 
                g_free(filetypes[ft_id]->comment_close);
1096
 
                filetypes[ft_id]->comment_close = result;
1097
 
        }
1098
 
 
1099
 
        tmp = g_key_file_get_boolean(configh, "settings", "comment_use_indent", &error);
1100
 
        if (error)
1101
 
        {
1102
 
                g_error_free(error);
1103
 
                error = NULL;
1104
 
                tmp = g_key_file_get_boolean(config, "settings", "comment_use_indent", &error);
1105
 
                if (error) g_error_free(error);
1106
 
                else filetypes[ft_id]->comment_use_indent = tmp;
1107
 
        }
1108
 
        else filetypes[ft_id]->comment_use_indent = tmp;
 
1147
        result = utils_get_setting(string, configh, config, "settings", "comment_open", NULL);
 
1148
        if (result != NULL)
 
1149
        {
 
1150
                setptr(filetypes[ft_id]->comment_open, result);
 
1151
        }
 
1152
 
 
1153
        result = utils_get_setting(string, configh, config, "settings", "comment_close", NULL);
 
1154
        if (result != NULL)
 
1155
        {
 
1156
                setptr(filetypes[ft_id]->comment_close, result);
 
1157
        }
 
1158
 
 
1159
        result = utils_get_setting(string, configh, config, "settings", "comment_single", NULL);
 
1160
        if (result != NULL)
 
1161
        {
 
1162
                setptr(filetypes[ft_id]->comment_single, result);
 
1163
        }
 
1164
        /* import correctly filetypes that use old-style single comments */
 
1165
        else if (! NZV(filetypes[ft_id]->comment_close))
 
1166
        {
 
1167
                setptr(filetypes[ft_id]->comment_single, filetypes[ft_id]->comment_open);
 
1168
                filetypes[ft_id]->comment_open = NULL;
 
1169
        }
 
1170
 
 
1171
        filetypes[ft_id]->comment_use_indent = utils_get_setting(boolean, configh, config,
 
1172
                        "settings", "comment_use_indent", FALSE);
1109
1173
 
1110
1174
        /* read context action */
1111
 
        result = g_key_file_get_string(configh, "settings", "context_action_cmd", NULL);
1112
 
        if (result == NULL) result = g_key_file_get_string(config, "settings", "context_action_cmd", NULL);
1113
 
        if (G_LIKELY(result != NULL))
 
1175
        result = utils_get_setting(string, configh, config, "settings", "context_action_cmd", NULL);
 
1176
        if (result != NULL)
1114
1177
        {
1115
1178
                setptr(filetypes[ft_id]->context_action_cmd, result);
1116
1179
        }
1117
1180
 
1118
 
        result = utils_get_setting_string(configh, "settings", "tag_parser", NULL);
1119
 
        if (!result)
1120
 
                result = utils_get_setting_string(config, "settings", "tag_parser", NULL);
1121
 
        if (result)
 
1181
        result = utils_get_setting(string, configh, config, "settings", "tag_parser", NULL);
 
1182
        if (result != NULL)
1122
1183
        {
1123
1184
                ft->lang = tm_source_file_get_named_lang(result);
1124
1185
                if (ft->lang < 0)
1126
1187
                g_free(result);
1127
1188
        }
1128
1189
 
1129
 
        result = utils_get_setting_string(configh, "settings", "lexer_filetype", NULL);
1130
 
        if (!result)
1131
 
                result = utils_get_setting_string(config, "settings", "lexer_filetype", NULL);
1132
 
        if (result)
 
1190
        result = utils_get_setting(string, configh, config, "settings", "lexer_filetype", NULL);
 
1191
        if (result != NULL)
1133
1192
        {
1134
1193
                ft->lexer_filetype = filetypes_lookup_by_name(result);
1135
1194
                if (!ft->lexer_filetype)
1142
1201
        ft->priv->xml_indent_tags = utils_get_setting(boolean, configh, config, "settings",
1143
1202
                "xml_indent_tags", FALSE);
1144
1203
 
 
1204
        /* read indent settings */
 
1205
        load_indent_settings(ft, config, configh);
 
1206
 
1145
1207
        /* read build settings */
1146
1208
        build_load_menu(config, GEANY_BCS_FT, (gpointer)ft);
1147
1209
        build_load_menu(configh, GEANY_BCS_HOME_FT, (gpointer)ft);
1148
1210
}
1149
1211
 
1150
1212
 
 
1213
static void add_keys(GKeyFile *dest, const gchar *group, GKeyFile *src)
 
1214
{
 
1215
        gchar **keys = g_key_file_get_keys(src, group, NULL, NULL);
 
1216
        gchar **ptr;
 
1217
 
 
1218
        foreach_strv(ptr, keys)
 
1219
        {
 
1220
                gchar *key = *ptr;
 
1221
                gchar *value = g_key_file_get_value(src, group, key, NULL);
 
1222
 
 
1223
                g_key_file_set_value(dest, group, key, value);
 
1224
                g_free(value);
 
1225
        }
 
1226
        g_strfreev(keys);
 
1227
}
 
1228
 
 
1229
 
 
1230
static gchar *filetypes_get_filename(GeanyFiletype *ft, gboolean user)
 
1231
{
 
1232
        gchar *ext = filetypes_get_conf_extension(ft);
 
1233
        gchar *f;
 
1234
 
 
1235
        if (user)
 
1236
                f = utils_make_filename(app->configdir,
 
1237
                        GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S, "filetypes.", ext, NULL);
 
1238
        else
 
1239
                f = utils_make_filename(app->datadir, "filetypes.", ext, NULL);
 
1240
 
 
1241
        g_free(ext);
 
1242
        return f;
 
1243
}
 
1244
 
 
1245
 
 
1246
static void add_group_keys(GKeyFile *kf, const gchar *group, GeanyFiletype *ft)
 
1247
{
 
1248
        gchar *files[2];
 
1249
        gboolean loaded = FALSE;
 
1250
        guint i;
 
1251
 
 
1252
        files[0] = filetypes_get_filename(ft, FALSE);
 
1253
        files[1] = filetypes_get_filename(ft, TRUE);
 
1254
 
 
1255
        for (i = 0; i < G_N_ELEMENTS(files); i++)
 
1256
        {
 
1257
                GKeyFile *src = g_key_file_new();
 
1258
 
 
1259
                if (g_key_file_load_from_file(src, files[i], G_KEY_FILE_NONE, NULL))
 
1260
                {
 
1261
                        add_keys(kf, group, src);
 
1262
                        loaded = TRUE;
 
1263
                }
 
1264
                g_key_file_free(src);
 
1265
        }
 
1266
 
 
1267
        if (!loaded)
 
1268
                geany_debug("Could not read config file %s for [%s=%s]!", files[0], group, ft->name);
 
1269
 
 
1270
        g_free(files[0]);
 
1271
        g_free(files[1]);
 
1272
}
 
1273
 
 
1274
 
 
1275
static void copy_ft_groups(GKeyFile *kf)
 
1276
{
 
1277
        gchar **groups = g_key_file_get_groups(kf, NULL);
 
1278
        gchar **ptr;
 
1279
 
 
1280
        foreach_strv(ptr, groups)
 
1281
        {
 
1282
                gchar *group = *ptr;
 
1283
                gchar *name = strstr(*ptr, "=");
 
1284
                GeanyFiletype *ft;
 
1285
 
 
1286
                if (!name)
 
1287
                        continue;
 
1288
 
 
1289
                /* terminate group at '=' */
 
1290
                *name = 0;
 
1291
                name++;
 
1292
                if (!name[0])
 
1293
                        continue;
 
1294
 
 
1295
                ft = filetypes_lookup_by_name(name);
 
1296
                if (ft)
 
1297
                        add_group_keys(kf, group, ft);
 
1298
        }
 
1299
        g_strfreev(groups);
 
1300
}
 
1301
 
 
1302
 
1151
1303
/* simple wrapper function to print file errors in DEBUG mode */
1152
1304
static void load_system_keyfile(GKeyFile *key_file, const gchar *file, GKeyFileFlags flags,
1153
1305
                GeanyFiletype *ft)
1181
1333
        pft = ft->priv;
1182
1334
 
1183
1335
        /* when reloading, proceed only if the settings were already loaded */
1184
 
        if (reload && G_UNLIKELY(! pft->keyfile_loaded))
 
1336
        if (G_UNLIKELY(reload && ! pft->keyfile_loaded))
1185
1337
                return;
1186
1338
 
1187
1339
        /* when not reloading, load the settings only once */
1188
 
        if (! reload && G_LIKELY(pft->keyfile_loaded))
 
1340
        if (G_LIKELY(! reload && pft->keyfile_loaded))
1189
1341
                return;
1190
1342
        pft->keyfile_loaded = TRUE;
1191
1343
 
1193
1345
        config_home = g_key_file_new();
1194
1346
        {
1195
1347
                /* highlighting uses GEANY_FILETYPES_NONE for common settings */
1196
 
                gchar *ext = filetypes_get_conf_extension(ft_id);
1197
 
                gchar *f0 = g_strconcat(app->datadir, G_DIR_SEPARATOR_S "filetypes.", ext, NULL);
1198
 
                gchar *f = g_strconcat(app->configdir,
1199
 
                        G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", ext, NULL);
1200
 
 
1201
 
                load_system_keyfile(config, f0, G_KEY_FILE_KEEP_COMMENTS, ft);
 
1348
                gchar *f;
 
1349
 
 
1350
                f = filetypes_get_filename(ft, FALSE);
 
1351
                load_system_keyfile(config, f, G_KEY_FILE_KEEP_COMMENTS, ft);
 
1352
 
 
1353
                setptr(f, filetypes_get_filename(ft, TRUE));
1202
1354
                g_key_file_load_from_file(config_home, f, G_KEY_FILE_KEEP_COMMENTS, NULL);
1203
 
 
1204
 
                g_free(ext);
1205
1355
                g_free(f);
1206
 
                g_free(f0);
1207
1356
        }
 
1357
        /* Copy keys for any groups with [group=C] from system keyfile */
 
1358
        copy_ft_groups(config);
 
1359
        copy_ft_groups(config_home);
1208
1360
 
1209
1361
        load_settings(ft_id, config, config_home);
1210
1362
        highlighting_init_styles(ft_id, config, config_home);
1214
1366
}
1215
1367
 
1216
1368
 
1217
 
gchar *filetypes_get_conf_extension(gint filetype_idx)
 
1369
static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft)
1218
1370
{
1219
 
        gchar *result, *ptr;
1220
 
        GeanyFiletype *ft = filetypes[filetype_idx];
 
1371
        gchar *result;
1221
1372
 
1222
1373
        if (ft->priv->custom)
1223
1374
                return g_strconcat(ft->name, ".conf", NULL);
1224
1375
 
1225
1376
        /* Handle any special extensions different from lowercase filetype->name */
1226
 
        switch (filetype_idx)
 
1377
        switch (ft->id)
1227
1378
        {
1228
1379
                case GEANY_FILETYPES_CPP: result = g_strdup("cpp"); break;
1229
1380
                case GEANY_FILETYPES_CS: result = g_strdup("cs"); break;
1230
1381
                case GEANY_FILETYPES_MAKE: result = g_strdup("makefile"); break;
1231
1382
                case GEANY_FILETYPES_NONE: result = g_strdup("common"); break;
 
1383
                /* name is Matlab/Octave */
 
1384
                case GEANY_FILETYPES_MATLAB: result = g_strdup("matlab"); break;
1232
1385
                default:
1233
1386
                        result = g_ascii_strdown(ft->name, -1);
1234
 
                        /* truncate at slash (e.g. for Matlab/Octave) */
1235
 
                        ptr = strstr(result, "/");
1236
 
                        if (ptr)
1237
 
                                *ptr = 0x0;
1238
1387
                        break;
1239
1388
        }
1240
1389
        return result;
1241
1390
}
1242
1391
 
1243
1392
 
1244
 
void filetypes_save_commands(void)
 
1393
void filetypes_save_commands(GeanyFiletype *ft)
1245
1394
{
1246
 
        gchar *conf_prefix = g_strconcat(app->configdir,
1247
 
                G_DIR_SEPARATOR_S GEANY_FILEDEFS_SUBDIR G_DIR_SEPARATOR_S "filetypes.", NULL);
1248
 
        guint i;
1249
 
 
1250
 
        for (i = 0; i < filetypes_array->len; i++)
1251
 
        {
1252
 
                GKeyFile *config_home;
1253
 
                gchar *fname, *ext, *data;
1254
 
 
1255
 
                if (filetypes[i]->home_save_needed)
1256
 
                {
1257
 
                        ext = filetypes_get_conf_extension(i);
1258
 
                        fname = g_strconcat(conf_prefix, ext, NULL);
1259
 
                        g_free(ext);
1260
 
                        config_home = g_key_file_new();
1261
 
                        g_key_file_load_from_file(config_home, fname, G_KEY_FILE_KEEP_COMMENTS, NULL);
1262
 
                        build_save_menu(config_home, (gpointer)(filetypes[i]), GEANY_BCS_HOME_FT);
1263
 
                        data = g_key_file_to_data(config_home, NULL, NULL);
1264
 
                        utils_write_file(fname, data);
1265
 
                        g_free(data);
1266
 
                        g_key_file_free(config_home);
1267
 
                        g_free(fname);
1268
 
                }
1269
 
        }
1270
 
        g_free(conf_prefix);
 
1395
        GKeyFile *config_home;
 
1396
        gchar *fname, *data;
 
1397
 
 
1398
        fname = filetypes_get_filename(ft, TRUE);
 
1399
        config_home = g_key_file_new();
 
1400
        g_key_file_load_from_file(config_home, fname, G_KEY_FILE_KEEP_COMMENTS, NULL);
 
1401
        build_save_menu(config_home, ft, GEANY_BCS_HOME_FT);
 
1402
        data = g_key_file_to_data(config_home, NULL, NULL);
 
1403
        utils_write_file(fname, data);
 
1404
        g_free(data);
 
1405
        g_key_file_free(config_home);
 
1406
        g_free(fname);
1271
1407
}
1272
1408
 
1273
1409
 
1392
1528
        *filename = NULL;
1393
1529
        *line = -1;
1394
1530
 
1395
 
        if (!NZV(regstr))
 
1531
        if (G_UNLIKELY(! NZV(regstr)))
1396
1532
                return FALSE;
1397
1533
 
1398
1534
        if (!ft->priv->error_regex_compiled || regstr != ft->priv->last_string)
1452
1588
#endif
1453
1589
 
1454
1590
 
1455
 
void filetypes_read_extensions(void)
 
1591
static void read_extensions(GKeyFile *sysconfig, GKeyFile *userconfig)
1456
1592
{
1457
1593
        guint i;
1458
1594
        gsize len = 0;
1459
 
        gchar *sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S,
1460
 
                "filetype_extensions.conf", NULL);
1461
 
        gchar *userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S,
1462
 
                "filetype_extensions.conf", NULL);
1463
 
        GKeyFile *sysconfig = g_key_file_new();
1464
 
        GKeyFile *userconfig = g_key_file_new();
1465
 
 
1466
 
        g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
1467
 
        g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
1468
1595
 
1469
1596
        /* read the keys */
1470
1597
        for (i = 0; i < filetypes_array->len; i++)
1484
1611
                convert_filetype_extensions_to_lower_case(filetypes[i]->pattern, len);
1485
1612
#endif
1486
1613
        }
 
1614
}
 
1615
 
 
1616
 
 
1617
static void read_group(GKeyFile *config, const gchar *group_name, gint group_id)
 
1618
{
 
1619
        gchar **names = g_key_file_get_string_list(config, "Groups", group_name, NULL, NULL);
 
1620
        gchar **name;
 
1621
 
 
1622
        foreach_strv(name, names)
 
1623
        {
 
1624
                GeanyFiletype *ft = filetypes_lookup_by_name(*name);
 
1625
 
 
1626
                if (ft)
 
1627
                {
 
1628
                        ft->group = group_id;
 
1629
                        if (ft->priv->custom &&
 
1630
                                (group_id == GEANY_FILETYPE_GROUP_COMPILED || group_id == GEANY_FILETYPE_GROUP_SCRIPT))
 
1631
                        {
 
1632
                                setptr(ft->title, NULL);
 
1633
                                filetype_make_title(ft, TITLE_SOURCE_FILE);
 
1634
                        }
 
1635
                }
 
1636
                else
 
1637
                        geany_debug("Filetype '%s' not found for group '%s'!", *name, group_name);
 
1638
        }
 
1639
        g_strfreev(names);
 
1640
}
 
1641
 
 
1642
 
 
1643
static void read_groups(GKeyFile *config)
 
1644
{
 
1645
        read_group(config, "Programming", GEANY_FILETYPE_GROUP_COMPILED);
 
1646
        read_group(config, "Script", GEANY_FILETYPE_GROUP_SCRIPT);
 
1647
        read_group(config, "Markup", GEANY_FILETYPE_GROUP_MARKUP);
 
1648
        read_group(config, "Misc", GEANY_FILETYPE_GROUP_MISC);
 
1649
        read_group(config, "None", GEANY_FILETYPE_GROUP_NONE);
 
1650
}
 
1651
 
 
1652
 
 
1653
static void read_filetype_config(void)
 
1654
{
 
1655
        gchar *sysconfigfile = g_strconcat(app->datadir, G_DIR_SEPARATOR_S,
 
1656
                "filetype_extensions.conf", NULL);
 
1657
        gchar *userconfigfile = g_strconcat(app->configdir, G_DIR_SEPARATOR_S,
 
1658
                "filetype_extensions.conf", NULL);
 
1659
        GKeyFile *sysconfig = g_key_file_new();
 
1660
        GKeyFile *userconfig = g_key_file_new();
 
1661
 
 
1662
        g_key_file_load_from_file(sysconfig, sysconfigfile, G_KEY_FILE_NONE, NULL);
 
1663
        g_key_file_load_from_file(userconfig, userconfigfile, G_KEY_FILE_NONE, NULL);
 
1664
 
 
1665
        read_extensions(sysconfig, userconfig);
 
1666
        read_groups(sysconfig);
 
1667
        read_groups(userconfig);
1487
1668
 
1488
1669
        g_free(sysconfigfile);
1489
1670
        g_free(userconfigfile);
1490
1671
        g_key_file_free(sysconfig);
1491
1672
        g_key_file_free(userconfig);
 
1673
}
 
1674
 
 
1675
 
 
1676
void filetypes_reload_extensions(void)
 
1677
{
 
1678
        guint i;
 
1679
 
 
1680
        read_filetype_config();
1492
1681
 
1493
1682
        /* Redetect filetype of any documents with none set */
1494
1683
        foreach_document(i)
1519
1708
        guint i;
1520
1709
        GeanyDocument *current_doc;
1521
1710
 
1522
 
        /* save possibly changed commands before re-reading them */
1523
 
        filetypes_save_commands();
1524
 
 
1525
1711
        /* reload filetype configs */
1526
1712
        for (i = 0; i < filetypes_array->len; i++)
1527
1713
        {