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

1 by Damián Viano
Import upstream version 0.8
1
/*
2
 *      filetypes.c - this file is part of Geany, a fast and lightweight IDE
3
 *
1.1.16 by Evgeni Golov
Import upstream version 0.21
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>
1 by Damián Viano
Import upstream version 0.8
6
 *
7
 *      This program is free software; you can redistribute it and/or modify
8
 *      it under the terms of the GNU General Public License as published by
9
 *      the Free Software Foundation; either version 2 of the License, or
10
 *      (at your option) any later version.
11
 *
12
 *      This program is distributed in the hope that it will be useful,
13
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *      GNU General Public License for more details.
16
 *
17
 *      You should have received a copy of the GNU General Public License
18
 *      along with this program; if not, write to the Free Software
19
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
 *
1.1.16 by Evgeni Golov
Import upstream version 0.21
21
 * $Id: filetypes.c 5964 2011-09-28 10:47:43Z ntrel $
1 by Damián Viano
Import upstream version 0.8
22
 */
23
1.2.2 by Damián Viano
Import upstream version 0.15
24
/**
25
 * @file filetypes.h
1.1.4 by Damián Viano
Import upstream version 0.11
26
 * Filetype detection, file extensions and filetype menu items.
27
 */
1 by Damián Viano
Import upstream version 0.8
28
1.4.3 by Damián Viano
Import upstream version 0.19
29
/* Note: we use filetype_id for some function arguments, but GeanyFiletype is better; we should
30
 * only use GeanyFiletype for API functions. */
31
1 by Damián Viano
Import upstream version 0.8
32
#include <string.h>
1.2.1 by Damián Viano
Import upstream version 0.14
33
#include <glib/gstdio.h>
1 by Damián Viano
Import upstream version 0.8
34
35
#include "geany.h"
36
#include "filetypes.h"
1.1.15 by Chow Loong Jin
Import upstream version 0.20
37
#include "filetypesprivate.h"
1 by Damián Viano
Import upstream version 0.8
38
#include "highlighting.h"
39
#include "support.h"
40
#include "templates.h"
1.2.2 by Damián Viano
Import upstream version 0.15
41
#include "document.h"
42
#include "editor.h"
1 by Damián Viano
Import upstream version 0.8
43
#include "msgwindow.h"
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
44
#include "utils.h"
45
#include "sciwrappers.h"
1.2.2 by Damián Viano
Import upstream version 0.15
46
#include "ui_utils.h"
1.1.15 by Chow Loong Jin
Import upstream version 0.20
47
#include "symbols.h"
1.2.2 by Damián Viano
Import upstream version 0.15
48
49
#include <stdlib.h>
50
51
52
GPtrArray *filetypes_array = NULL;	/* Dynamic array of filetype pointers */
53
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
54
static GHashTable *filetypes_hash = NULL;	/* Hash of filetype pointers based on name keys */
55
56
/** List of filetype pointers sorted by name, but with @c filetypes_index(GEANY_FILETYPES_NONE)
57
 * first, as this is usually treated specially.
58
 * The list does not change (after filetypes have been initialized), so you can use
1.1.16 by Evgeni Golov
Import upstream version 0.21
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(). */
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
61
GSList *filetypes_by_title = NULL;
62
63
64
static void create_radio_menu_item(GtkWidget *menu, GeanyFiletype *ftype);
1.2.2 by Damián Viano
Import upstream version 0.15
65
1.1.16 by Evgeni Golov
Import upstream version 0.21
66
static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft);
67
static void read_filetype_config(void);
68
1.2.2 by Damián Viano
Import upstream version 0.15
69
1.4.1 by Damian Viano
Import upstream version 0.18
70
enum TitleType
71
{
72
	TITLE_SOURCE_FILE,
73
	TITLE_FILE
74
};
75
76
/* Save adding many translation strings if the filetype name doesn't need translating */
77
static void filetype_make_title(GeanyFiletype *ft, enum TitleType type)
78
{
79
	const gchar *fmt = NULL;
80
81
	switch (type)
82
	{
83
		default:
84
		case TITLE_SOURCE_FILE:	fmt = _("%s source file"); break;
85
		case TITLE_FILE:		fmt = _("%s file"); break;
86
	}
87
	g_assert(!ft->title);
88
	g_assert(ft->name);
89
	ft->title = g_strdup_printf(fmt, ft->name);
90
}
91
92
1.2.2 by Damián Viano
Import upstream version 0.15
93
/* Note: remember to update HACKING if this function is renamed. */
94
static void init_builtin_filetypes(void)
95
{
96
	GeanyFiletype *ft;
1.2.1 by Damián Viano
Import upstream version 0.14
97
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
98
#define NONE	/* these macros are only to ease navigation */
99
	ft = filetypes[GEANY_FILETYPES_NONE];
1.1.15 by Chow Loong Jin
Import upstream version 0.20
100
	/* ft->name must not be translated as it is used for filetype lookup.
101
	 * Use filetypes_get_display_name() instead. */
102
	ft->name = g_strdup("None");
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
103
	ft->title = g_strdup(_("None"));
104
	ft->group = GEANY_FILETYPE_GROUP_NONE;
105
106
#define C
1.2.2 by Damián Viano
Import upstream version 0.15
107
	ft = filetypes[GEANY_FILETYPES_C];
108
	ft->lang = 0;
109
	ft->name = g_strdup("C");
1.4.1 by Damian Viano
Import upstream version 0.18
110
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
111
	ft->mime_type = g_strdup("text/x-csrc");
1.2.2 by Damián Viano
Import upstream version 0.15
112
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1 by Damián Viano
Import upstream version 0.8
113
114
#define CPP
1.2.2 by Damián Viano
Import upstream version 0.15
115
	ft = filetypes[GEANY_FILETYPES_CPP];
116
	ft->lang = 1;
117
	ft->name = g_strdup("C++");
1.1.15 by Chow Loong Jin
Import upstream version 0.20
118
	filetype_make_title(ft, TITLE_SOURCE_FILE);
119
	ft->mime_type = g_strdup("text/x-c++src");
1.2.2 by Damián Viano
Import upstream version 0.15
120
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.2.1 by Damián Viano
Import upstream version 0.14
121
1.1.5 by Damián Viano
Import upstream version 0.12
122
#define CS
1.2.2 by Damián Viano
Import upstream version 0.15
123
	ft = filetypes[GEANY_FILETYPES_CS];
124
	ft->lang = 25;
125
	ft->name = g_strdup("C#");
1.1.15 by Chow Loong Jin
Import upstream version 0.20
126
	filetype_make_title(ft, TITLE_SOURCE_FILE);
127
	ft->mime_type = g_strdup("text/x-csharp");
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
128
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
129
130
#define VALA
131
	ft = filetypes[GEANY_FILETYPES_VALA];
132
	ft->lang = 33;
133
	ft->name = g_strdup("Vala");
1.4.1 by Damian Viano
Import upstream version 0.18
134
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
135
	ft->mime_type = g_strdup("text/x-vala");
1.2.2 by Damián Viano
Import upstream version 0.15
136
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.5 by Damián Viano
Import upstream version 0.12
137
1 by Damián Viano
Import upstream version 0.8
138
#define D
1.2.2 by Damián Viano
Import upstream version 0.15
139
	ft = filetypes[GEANY_FILETYPES_D];
140
	ft->lang = 17;
141
	ft->name = g_strdup("D");
1.4.1 by Damian Viano
Import upstream version 0.18
142
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
143
	ft->mime_type = g_strdup("text/x-dsrc");
1.2.2 by Damián Viano
Import upstream version 0.15
144
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1 by Damián Viano
Import upstream version 0.8
145
146
#define JAVA
1.2.2 by Damián Viano
Import upstream version 0.15
147
	ft = filetypes[GEANY_FILETYPES_JAVA];
148
	ft->lang = 2;
149
	ft->name = g_strdup("Java");
1.4.1 by Damian Viano
Import upstream version 0.18
150
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
151
	ft->mime_type = g_strdup("text/x-java");
1.2.2 by Damián Viano
Import upstream version 0.15
152
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1 by Damián Viano
Import upstream version 0.8
153
1.2.1 by Damián Viano
Import upstream version 0.14
154
#define PAS /* to avoid warnings when building under Windows, the symbol PASCAL is there defined */
1.2.2 by Damián Viano
Import upstream version 0.15
155
	ft = filetypes[GEANY_FILETYPES_PASCAL];
156
	ft->lang = 4;
157
	ft->name = g_strdup("Pascal");
1.4.1 by Damian Viano
Import upstream version 0.18
158
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
159
	ft->mime_type = g_strdup("text/x-pascal");
1.2.2 by Damián Viano
Import upstream version 0.15
160
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1 by Damián Viano
Import upstream version 0.8
161
162
#define ASM
1.2.2 by Damián Viano
Import upstream version 0.15
163
	ft = filetypes[GEANY_FILETYPES_ASM];
164
	ft->lang = 9;
165
	ft->name = g_strdup("ASM");
166
	ft->title = g_strdup_printf(_("%s source file"), "Assembler");
167
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.2.1 by Damián Viano
Import upstream version 0.14
168
1.1.5 by Damián Viano
Import upstream version 0.12
169
#define BASIC
1.2.2 by Damián Viano
Import upstream version 0.15
170
	ft = filetypes[GEANY_FILETYPES_BASIC];
171
	ft->lang = 26;
172
	ft->name = g_strdup("FreeBasic");
1.4.1 by Damian Viano
Import upstream version 0.18
173
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.2.2 by Damián Viano
Import upstream version 0.15
174
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.5 by Damián Viano
Import upstream version 0.12
175
1.1.1 by Damián Viano
Import upstream version 0.9
176
#define FORTRAN
1.2.2 by Damián Viano
Import upstream version 0.15
177
	ft = filetypes[GEANY_FILETYPES_FORTRAN];
178
	ft->lang = 18;
179
	ft->name = g_strdup("Fortran");
180
	ft->title = g_strdup_printf(_("%s source file"), "Fortran (F90)");
1.1.15 by Chow Loong Jin
Import upstream version 0.20
181
	ft->mime_type = g_strdup("text/x-fortran");
1.2.2 by Damián Viano
Import upstream version 0.15
182
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
183
184
#define F77
185
	ft = filetypes[GEANY_FILETYPES_F77];
186
	ft->lang = 30;
187
	ft->name = g_strdup("F77");
188
	ft->title = g_strdup_printf(_("%s source file"), "Fortran (F77)");
1.1.15 by Chow Loong Jin
Import upstream version 0.20
189
	ft->mime_type = g_strdup("text/x-fortran");
1.2.2 by Damián Viano
Import upstream version 0.15
190
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
191
192
#define GLSL
193
	ft = filetypes[GEANY_FILETYPES_GLSL];
194
	ft->lang = 31;
195
	ft->name = g_strdup("GLSL");
1.4.1 by Damian Viano
Import upstream version 0.18
196
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.2.2 by Damián Viano
Import upstream version 0.15
197
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.1 by Damián Viano
Import upstream version 0.9
198
1 by Damián Viano
Import upstream version 0.8
199
#define CAML
1.2.2 by Damián Viano
Import upstream version 0.15
200
	ft = filetypes[GEANY_FILETYPES_CAML];
201
	ft->name = g_strdup("CAML");
202
	ft->title = g_strdup_printf(_("%s source file"), "(O)Caml");
1.1.15 by Chow Loong Jin
Import upstream version 0.20
203
	ft->mime_type = g_strdup("text/x-ocaml");
1.2.2 by Damián Viano
Import upstream version 0.15
204
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1 by Damián Viano
Import upstream version 0.8
205
206
#define PERL
1.2.2 by Damián Viano
Import upstream version 0.15
207
	ft = filetypes[GEANY_FILETYPES_PERL];
208
	ft->lang = 5;
209
	ft->name = g_strdup("Perl");
1.4.1 by Damian Viano
Import upstream version 0.18
210
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
211
	ft->mime_type = g_strdup("application/x-perl");
1.2.2 by Damián Viano
Import upstream version 0.15
212
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
213
214
#define PHP
1.2.2 by Damián Viano
Import upstream version 0.15
215
	ft = filetypes[GEANY_FILETYPES_PHP];
216
	ft->lang = 6;
217
	ft->name = g_strdup("PHP");
1.4.1 by Damian Viano
Import upstream version 0.18
218
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
219
	ft->mime_type = g_strdup("application/x-php");
1.2.2 by Damián Viano
Import upstream version 0.15
220
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.4 by Damián Viano
Import upstream version 0.11
221
222
#define JAVASCRIPT
1.2.2 by Damián Viano
Import upstream version 0.15
223
	ft = filetypes[GEANY_FILETYPES_JS];
224
	ft->lang = 23;
225
	ft->name = g_strdup("Javascript");
1.4.1 by Damian Viano
Import upstream version 0.18
226
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
227
	ft->mime_type = g_strdup("application/javascript");
1.2.2 by Damián Viano
Import upstream version 0.15
228
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
229
230
#define PYTHON
1.2.2 by Damián Viano
Import upstream version 0.15
231
	ft = filetypes[GEANY_FILETYPES_PYTHON];
232
	ft->lang = 7;
233
	ft->name = g_strdup("Python");
1.4.1 by Damian Viano
Import upstream version 0.18
234
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
235
	ft->mime_type = g_strdup("text/x-python");
1.2.2 by Damián Viano
Import upstream version 0.15
236
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
237
238
#define RUBY
1.2.2 by Damián Viano
Import upstream version 0.15
239
	ft = filetypes[GEANY_FILETYPES_RUBY];
240
	ft->lang = 14;
241
	ft->name = g_strdup("Ruby");
1.4.1 by Damian Viano
Import upstream version 0.18
242
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
243
	ft->mime_type = g_strdup("application/x-ruby");
1.2.2 by Damián Viano
Import upstream version 0.15
244
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
245
246
#define TCL
1.2.2 by Damián Viano
Import upstream version 0.15
247
	ft = filetypes[GEANY_FILETYPES_TCL];
248
	ft->lang = 15;
249
	ft->name = g_strdup("Tcl");
1.4.1 by Damian Viano
Import upstream version 0.18
250
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
251
	ft->mime_type = g_strdup("text/x-tcl");
1.2.2 by Damián Viano
Import upstream version 0.15
252
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.4 by Damián Viano
Import upstream version 0.11
253
254
#define LUA
1.2.2 by Damián Viano
Import upstream version 0.15
255
	ft = filetypes[GEANY_FILETYPES_LUA];
256
	ft->lang = 22;
257
	ft->name = g_strdup("Lua");
1.4.1 by Damian Viano
Import upstream version 0.18
258
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
259
	ft->mime_type = g_strdup("text/x-lua");
1.2.2 by Damián Viano
Import upstream version 0.15
260
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
261
1.1.1 by Damián Viano
Import upstream version 0.9
262
#define FERITE
1.2.2 by Damián Viano
Import upstream version 0.15
263
	ft = filetypes[GEANY_FILETYPES_FERITE];
264
	ft->lang = 19;
265
	ft->name = g_strdup("Ferite");
1.4.1 by Damian Viano
Import upstream version 0.18
266
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.2.2 by Damián Viano
Import upstream version 0.15
267
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.4 by Damián Viano
Import upstream version 0.11
268
269
#define HASKELL
1.2.2 by Damián Viano
Import upstream version 0.15
270
	ft = filetypes[GEANY_FILETYPES_HASKELL];
271
	ft->lang = 24;
272
	ft->name = g_strdup("Haskell");
1.4.1 by Damian Viano
Import upstream version 0.18
273
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
274
	ft->mime_type = g_strdup("text/x-haskell");
1.2.2 by Damián Viano
Import upstream version 0.15
275
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.1 by Damián Viano
Import upstream version 0.9
276
1.4.1 by Damian Viano
Import upstream version 0.18
277
#define MARKDOWN
278
	ft = filetypes[GEANY_FILETYPES_MARKDOWN];
279
	ft->lang = 36;
280
	ft->name = g_strdup("Markdown");
281
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.16 by Evgeni Golov
Import upstream version 0.21
282
	ft->mime_type = g_strdup("text/x-markdown");
283
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1.4.1 by Damian Viano
Import upstream version 0.18
284
1.4.3 by Damián Viano
Import upstream version 0.19
285
#define TXT2TAGS
286
	ft = filetypes[GEANY_FILETYPES_TXT2TAGS];
287
	ft->lang = 37;
288
	ft->name = g_strdup("Txt2tags");
289
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
290
	ft->mime_type = g_strdup("text/x-txt2tags");
1.1.16 by Evgeni Golov
Import upstream version 0.21
291
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1.4.3 by Damián Viano
Import upstream version 0.19
292
293
#define ABC
294
	ft = filetypes[GEANY_FILETYPES_ABC];
295
	ft->lang = 38;
296
	ft->name = g_strdup("Abc");
1.1.16 by Evgeni Golov
Import upstream version 0.21
297
	filetype_make_title(ft, TITLE_FILE);
1.4.3 by Damián Viano
Import upstream version 0.19
298
	ft->group = GEANY_FILETYPE_GROUP_MISC;
299
1 by Damián Viano
Import upstream version 0.8
300
#define SH
1.2.2 by Damián Viano
Import upstream version 0.15
301
	ft = filetypes[GEANY_FILETYPES_SH];
302
	ft->lang = 16;
303
	ft->name = g_strdup("Sh");
1.1.16 by Evgeni Golov
Import upstream version 0.21
304
	ft->title = g_strdup(_("Shell script"));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
305
	ft->mime_type = g_strdup("application/x-shellscript");
1.2.2 by Damián Viano
Import upstream version 0.15
306
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
307
308
#define MAKE
1.2.2 by Damián Viano
Import upstream version 0.15
309
	ft = filetypes[GEANY_FILETYPES_MAKE];
310
	ft->lang = 3;
311
	ft->name = g_strdup("Make");
312
	ft->title = g_strdup(_("Makefile"));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
313
	ft->mime_type = g_strdup("text/x-makefile");
1.2.2 by Damián Viano
Import upstream version 0.15
314
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1 by Damián Viano
Import upstream version 0.8
315
316
#define XML
1.2.2 by Damián Viano
Import upstream version 0.15
317
	ft = filetypes[GEANY_FILETYPES_XML];
318
	ft->name = g_strdup("XML");
319
	ft->title = g_strdup(_("XML document"));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
320
	ft->mime_type = g_strdup("application/xml");
1.2.2 by Damián Viano
Import upstream version 0.15
321
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1 by Damián Viano
Import upstream version 0.8
322
323
#define DOCBOOK
1.2.2 by Damián Viano
Import upstream version 0.15
324
	ft = filetypes[GEANY_FILETYPES_DOCBOOK];
325
	ft->lang = 12;
326
	ft->name = g_strdup("Docbook");
1.4.1 by Damian Viano
Import upstream version 0.18
327
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
328
	ft->mime_type = g_strdup("application/docbook+xml");
1.2.2 by Damián Viano
Import upstream version 0.15
329
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1 by Damián Viano
Import upstream version 0.8
330
1.1.1 by Damián Viano
Import upstream version 0.9
331
#define HTML
1.2.2 by Damián Viano
Import upstream version 0.15
332
	ft = filetypes[GEANY_FILETYPES_HTML];
333
	ft->lang = 29;
334
	ft->name = g_strdup("HTML");
1.4.1 by Damian Viano
Import upstream version 0.18
335
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
336
	ft->mime_type = g_strdup("text/html");
1.2.2 by Damián Viano
Import upstream version 0.15
337
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1.1.1 by Damián Viano
Import upstream version 0.9
338
1 by Damián Viano
Import upstream version 0.8
339
#define CSS
1.2.2 by Damián Viano
Import upstream version 0.15
340
	ft = filetypes[GEANY_FILETYPES_CSS];
341
	ft->lang = 13;
342
	ft->name = g_strdup("CSS");
343
	ft->title = g_strdup(_("Cascading StyleSheet"));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
344
	ft->mime_type = g_strdup("text/css");
1.2.2 by Damián Viano
Import upstream version 0.15
345
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;	/* not really markup but fit quite well to HTML */
1 by Damián Viano
Import upstream version 0.8
346
347
#define SQL
1.2.2 by Damián Viano
Import upstream version 0.15
348
	ft = filetypes[GEANY_FILETYPES_SQL];
349
	ft->lang = 11;
350
	ft->name = g_strdup("SQL");
1.1.16 by Evgeni Golov
Import upstream version 0.21
351
	filetype_make_title(ft, TITLE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
352
	ft->mime_type = g_strdup("text/x-sql");
1.2.2 by Damián Viano
Import upstream version 0.15
353
	ft->group = GEANY_FILETYPE_GROUP_MISC;
1 by Damián Viano
Import upstream version 0.8
354
1.1.16 by Evgeni Golov
Import upstream version 0.21
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
1 by Damián Viano
Import upstream version 0.8
363
#define LATEX
1.2.2 by Damián Viano
Import upstream version 0.15
364
	ft = filetypes[GEANY_FILETYPES_LATEX];
365
	ft->lang = 8;
366
	ft->name = g_strdup("LaTeX");
1.4.1 by Damian Viano
Import upstream version 0.18
367
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
368
	ft->mime_type = g_strdup("text/x-tex");
1.1.16 by Evgeni Golov
Import upstream version 0.21
369
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1 by Damián Viano
Import upstream version 0.8
370
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
371
#define VHDL
1.2.2 by Damián Viano
Import upstream version 0.15
372
	ft = filetypes[GEANY_FILETYPES_VHDL];
373
	ft->lang = 21;
374
	ft->name = g_strdup("VHDL");
1.4.1 by Damian Viano
Import upstream version 0.18
375
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
376
	ft->mime_type = g_strdup("text/x-vhdl");
1.2.2 by Damián Viano
Import upstream version 0.15
377
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
378
1.4.3 by Damián Viano
Import upstream version 0.19
379
#define VERILOG
380
	ft = filetypes[GEANY_FILETYPES_VERILOG];
381
	ft->lang = 39;
382
	ft->name = g_strdup("Verilog");
383
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.16 by Evgeni Golov
Import upstream version 0.21
384
	ft->mime_type = g_strdup("text/x-verilog");
1.4.3 by Damián Viano
Import upstream version 0.19
385
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
386
1.1.1 by Damián Viano
Import upstream version 0.9
387
#define DIFF
1.2.2 by Damián Viano
Import upstream version 0.15
388
	ft = filetypes[GEANY_FILETYPES_DIFF];
389
	ft->lang = 20;
390
	ft->name = g_strdup("Diff");
1.4.1 by Damian Viano
Import upstream version 0.18
391
	filetype_make_title(ft, TITLE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
392
	ft->mime_type = g_strdup("text/x-patch");
1.2.2 by Damián Viano
Import upstream version 0.15
393
	ft->group = GEANY_FILETYPE_GROUP_MISC;
1.1.1 by Damián Viano
Import upstream version 0.9
394
1.1.15 by Chow Loong Jin
Import upstream version 0.20
395
#define LISP
396
	ft = filetypes[GEANY_FILETYPES_LISP];
397
	ft->name = g_strdup("Lisp");
398
	filetype_make_title(ft, TITLE_SOURCE_FILE);
399
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
400
401
#define ERLANG
402
	ft = filetypes[GEANY_FILETYPES_ERLANG];
403
	ft->name = g_strdup("Erlang");
404
	filetype_make_title(ft, TITLE_SOURCE_FILE);
405
	ft->mime_type = g_strdup("text/x-erlang");
406
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
407
1 by Damián Viano
Import upstream version 0.8
408
#define CONF
1.2.2 by Damián Viano
Import upstream version 0.15
409
	ft = filetypes[GEANY_FILETYPES_CONF];
410
	ft->lang = 10;
411
	ft->name = g_strdup("Conf");
412
	ft->title = g_strdup(_("Config file"));
413
	ft->group = GEANY_FILETYPE_GROUP_MISC;
414
415
#define PO
416
	ft = filetypes[GEANY_FILETYPES_PO];
417
	ft->name = g_strdup("Po");
418
	ft->title = g_strdup(_("Gettext translation file"));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
419
	ft->mime_type = g_strdup("text/x-gettext-translation");
1.2.2 by Damián Viano
Import upstream version 0.15
420
	ft->group = GEANY_FILETYPE_GROUP_MISC;
1.2.1 by Damián Viano
Import upstream version 0.14
421
1.1.5 by Damián Viano
Import upstream version 0.12
422
#define HAXE
1.2.2 by Damián Viano
Import upstream version 0.15
423
	ft = filetypes[GEANY_FILETYPES_HAXE];
424
	ft->lang = 27;
425
	ft->name = g_strdup("Haxe");
1.4.1 by Damian Viano
Import upstream version 0.18
426
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.2.2 by Damián Viano
Import upstream version 0.15
427
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
428
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
429
#define ACTIONSCRIPT
430
	ft = filetypes[GEANY_FILETYPES_AS];
431
	ft->lang = 34;
432
	ft->name = g_strdup("ActionScript");
1.4.1 by Damian Viano
Import upstream version 0.18
433
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
434
	ft->mime_type = g_strdup("application/ecmascript");
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
435
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
436
1.2.2 by Damián Viano
Import upstream version 0.15
437
#define R
438
	ft = filetypes[GEANY_FILETYPES_R];
1.4.3 by Damián Viano
Import upstream version 0.19
439
	ft->lang = 40;
1.2.2 by Damián Viano
Import upstream version 0.15
440
	ft->name = g_strdup("R");
1.1.16 by Evgeni Golov
Import upstream version 0.21
441
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.2.2 by Damián Viano
Import upstream version 0.15
442
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.5 by Damián Viano
Import upstream version 0.12
443
444
#define REST
1.2.2 by Damián Viano
Import upstream version 0.15
445
	ft = filetypes[GEANY_FILETYPES_REST];
446
	ft->lang = 28;
447
	ft->name = g_strdup("reStructuredText");
1.1.16 by Evgeni Golov
Import upstream version 0.21
448
	filetype_make_title(ft, TITLE_SOURCE_FILE);
449
	ft->group = GEANY_FILETYPE_GROUP_MARKUP;
1.1.5 by Damián Viano
Import upstream version 0.12
450
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
451
#define MATLAB
452
	ft = filetypes[GEANY_FILETYPES_MATLAB];
453
	ft->lang = 32;
1.1.15 by Chow Loong Jin
Import upstream version 0.20
454
	ft->name = g_strdup("Matlab/Octave");
1.4.1 by Damian Viano
Import upstream version 0.18
455
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
456
	ft->mime_type = g_strdup("text/x-matlab");
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
457
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
458
459
#define YAML
460
	ft = filetypes[GEANY_FILETYPES_YAML];
461
	ft->name = g_strdup("YAML");
1.1.16 by Evgeni Golov
Import upstream version 0.21
462
	filetype_make_title(ft, TITLE_FILE);
463
	ft->mime_type = g_strdup("application/x-yaml");
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
464
	ft->group = GEANY_FILETYPE_GROUP_MISC;
465
466
#define CMAKE
467
	ft = filetypes[GEANY_FILETYPES_CMAKE];
468
	ft->name = g_strdup("CMake");
1.4.1 by Damian Viano
Import upstream version 0.18
469
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
470
	ft->mime_type = g_strdup("text/x-cmake");
1.1.16 by Evgeni Golov
Import upstream version 0.21
471
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
472
473
#define NSIS
474
	ft = filetypes[GEANY_FILETYPES_NSIS];
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
475
	ft->lang = 35;
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
476
	ft->name = g_strdup("NSIS");
1.4.1 by Damian Viano
Import upstream version 0.18
477
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.16 by Evgeni Golov
Import upstream version 0.21
478
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
479
480
#define ADA
481
	ft = filetypes[GEANY_FILETYPES_ADA];
482
	ft->name = g_strdup("Ada");
1.4.1 by Damian Viano
Import upstream version 0.18
483
	filetype_make_title(ft, TITLE_SOURCE_FILE);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
484
	ft->mime_type = g_strdup("text/x-adasrc");
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
485
	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
1.1.15 by Chow Loong Jin
Import upstream version 0.20
486
487
#define FORTH
488
	ft = filetypes[GEANY_FILETYPES_FORTH];
489
	ft->name = g_strdup("Forth");
490
	filetype_make_title(ft, TITLE_SOURCE_FILE);
491
	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
1.2.2 by Damián Viano
Import upstream version 0.15
492
}
493
494
495
/* initialize fields. */
496
static GeanyFiletype *filetype_new(void)
497
{
498
	GeanyFiletype *ft = g_new0(GeanyFiletype, 1);
499
1.1.16 by Evgeni Golov
Import upstream version 0.21
500
	ft->group = GEANY_FILETYPE_GROUP_NONE;
1.2.2 by Damián Viano
Import upstream version 0.15
501
	ft->lang = -2;	/* assume no tagmanager parser */
1.1.15 by Chow Loong Jin
Import upstream version 0.20
502
	/* pattern must not be null */
503
	ft->pattern = g_new0(gchar*, 1);
1.4.3 by Damián Viano
Import upstream version 0.19
504
	ft->project_list_entry = -1; /* no entry */
1.1.16 by Evgeni Golov
Import upstream version 0.21
505
	ft->indent_width = -1;
506
	ft->indent_type = -1;
1.2.2 by Damián Viano
Import upstream version 0.15
507
508
	ft->priv = g_new0(GeanyFiletypePrivate, 1);
509
	return ft;
510
}
511
512
1.1.16 by Evgeni Golov
Import upstream version 0.21
513
static gint cmp_filetype(gconstpointer pft1, gconstpointer pft2, gpointer data)
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
514
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
515
	gboolean by_name = GPOINTER_TO_INT(data);
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
516
	const GeanyFiletype *ft1 = pft1, *ft2 = pft2;
517
518
	if (G_UNLIKELY(ft1->id == GEANY_FILETYPES_NONE))
519
		return -1;
520
	if (G_UNLIKELY(ft2->id == GEANY_FILETYPES_NONE))
521
		return 1;
522
1.1.16 by Evgeni Golov
Import upstream version 0.21
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;
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
545
}
546
547
548
/* Add a filetype pointer to the lists of available filetypes,
1.2.2 by Damián Viano
Import upstream version 0.15
549
 * and set the filetype::id field. */
550
static void filetype_add(GeanyFiletype *ft)
551
{
552
	g_return_if_fail(ft);
553
	g_return_if_fail(ft->name);
554
555
	ft->id = filetypes_array->len;	/* len will be the index for filetype_array */
556
	g_ptr_array_add(filetypes_array, ft);
557
	g_hash_table_insert(filetypes_hash, ft->name, ft);
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
558
1.1.15 by Chow Loong Jin
Import upstream version 0.20
559
	/* list will be sorted later */
560
	filetypes_by_title = g_slist_prepend(filetypes_by_title, ft);
561
562
	if (!ft->mime_type)
563
		ft->mime_type = g_strdup("text/plain");
1.2.2 by Damián Viano
Import upstream version 0.15
564
}
565
566
1.4.3 by Damián Viano
Import upstream version 0.19
567
static void add_custom_filetype(const gchar *filename)
568
{
569
	gchar *fn = utils_strdupa(strstr(filename, ".") + 1);
570
	gchar *dot = g_strrstr(fn, ".conf");
571
	GeanyFiletype *ft;
572
573
	g_return_if_fail(dot);
574
575
	*dot = 0x0;
576
577
	if (g_hash_table_lookup(filetypes_hash, fn))
578
		return;
579
580
	ft = filetype_new();
581
	ft->name = g_strdup(fn);
582
	filetype_make_title(ft, TITLE_FILE);
583
	ft->priv->custom = TRUE;
584
	filetype_add(ft);
585
	geany_debug("Added filetype %s (%d).", ft->name, ft->id);
586
}
587
588
589
static void init_custom_filetypes(const gchar *path)
590
{
591
	GDir *dir;
592
	const gchar *filename;
593
594
	g_return_if_fail(path);
595
596
	dir = g_dir_open(path, 0, NULL);
597
	if (dir == NULL)
598
		return;
599
600
	foreach_dir(filename, dir)
601
	{
602
		const gchar prefix[] = "filetypes.";
603
604
		if (g_str_has_prefix(filename, prefix) &&
605
			g_str_has_suffix(filename + strlen(prefix), ".conf"))
606
		{
607
			add_custom_filetype(filename);
608
		}
609
	}
610
	g_dir_close(dir);
611
}
612
613
1.1.16 by Evgeni Golov
Import upstream version 0.21
614
/* Create the filetypes array and fill it with the known filetypes.
615
 * Warning: GTK isn't necessarily initialized yet. */
1.2.2 by Damián Viano
Import upstream version 0.15
616
void filetypes_init_types()
617
{
618
	filetype_id ft_id;
1.1.16 by Evgeni Golov
Import upstream version 0.21
619
	gchar *f;
1.2.2 by Damián Viano
Import upstream version 0.15
620
621
	g_return_if_fail(filetypes_array == NULL);
622
	g_return_if_fail(filetypes_hash == NULL);
623
624
	filetypes_array = g_ptr_array_sized_new(GEANY_MAX_BUILT_IN_FILETYPES);
625
	filetypes_hash = g_hash_table_new(g_str_hash, g_str_equal);
626
627
	/* Create built-in filetypes */
628
	for (ft_id = 0; ft_id < GEANY_MAX_BUILT_IN_FILETYPES; ft_id++)
629
	{
630
		filetypes[ft_id] = filetype_new();
631
	}
632
	init_builtin_filetypes();
633
634
	/* Add built-in filetypes to the hash now the name fields are set */
635
	for (ft_id = 0; ft_id < GEANY_MAX_BUILT_IN_FILETYPES; ft_id++)
636
	{
637
		filetype_add(filetypes[ft_id]);
638
	}
1.4.3 by Damián Viano
Import upstream version 0.19
639
	init_custom_filetypes(app->datadir);
1.1.16 by Evgeni Golov
Import upstream version 0.21
640
	f = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, NULL);
641
	init_custom_filetypes(f);
642
	g_free(f);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
643
644
	/* sort last instead of on insertion to prevent exponential time */
1.1.16 by Evgeni Golov
Import upstream version 0.21
645
	filetypes_by_title = g_slist_sort_with_data(filetypes_by_title,
646
		cmp_filetype, GINT_TO_POINTER(FALSE));
647
648
	read_filetype_config();
1.2.1 by Damián Viano
Import upstream version 0.14
649
}
650
651
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
652
static void on_document_save(G_GNUC_UNUSED GObject *object, GeanyDocument *doc)
653
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
654
	gchar *f;
655
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
656
	g_return_if_fail(NZV(doc->real_path));
657
1.1.16 by Evgeni Golov
Import upstream version 0.21
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))
1.4.1 by Damian Viano
Import upstream version 0.18
665
	{
666
		guint i;
667
668
		/* Note: we don't reload other filetypes, even though the named styles may have changed.
669
		 * The user can do this manually with 'Tools->Reload Configuration' */
670
		filetypes_load_config(GEANY_FILETYPES_NONE, TRUE);
671
1.4.3 by Damián Viano
Import upstream version 0.19
672
		foreach_document(i)
1.4.1 by Damian Viano
Import upstream version 0.18
673
			document_reload_config(documents[i]);
674
	}
1.1.16 by Evgeni Golov
Import upstream version 0.21
675
	g_free(f);
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
676
}
677
678
679
static void setup_config_file_menus(void)
680
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
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);
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
688
689
	g_signal_connect(geany_object, "document-save", G_CALLBACK(on_document_save), NULL);
690
}
691
692
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
693
static GtkWidget *group_menus[GEANY_FILETYPE_GROUP_COUNT] = {NULL};
694
695
static void create_sub_menu(GtkWidget *parent, gsize group_id, const gchar *title)
696
{
697
	GtkWidget *menu, *item;
698
699
	menu = gtk_menu_new();
700
	item = gtk_menu_item_new_with_mnemonic((title));
701
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
702
	gtk_container_add(GTK_CONTAINER(parent), item);
703
	gtk_widget_show(item);
704
	group_menus[group_id] = menu;
705
}
706
707
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
708
static void create_set_filetype_menu(void)
1.3.1 by Damián Viano
Import upstream version 0.17
709
{
1.4.1 by Damian Viano
Import upstream version 0.18
710
	GSList *node;
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
711
	GtkWidget *filetype_menu = ui_lookup_widget(main_widgets.window, "set_filetype1_menu");
1.1.4 by Damián Viano
Import upstream version 0.11
712
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
713
	create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_COMPILED, _("_Programming Languages"));
714
	create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_SCRIPT, _("_Scripting Languages"));
715
	create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MARKUP, _("_Markup Languages"));
1.1.16 by Evgeni Golov
Import upstream version 0.21
716
	create_sub_menu(filetype_menu, GEANY_FILETYPE_GROUP_MISC, _("M_iscellaneous"));
1.1.5 by Damián Viano
Import upstream version 0.12
717
1.2.1 by Damián Viano
Import upstream version 0.14
718
	/* Append all filetypes to the filetype menu */
1.4.1 by Damian Viano
Import upstream version 0.18
719
	foreach_slist(node, filetypes_by_title)
720
	{
721
		GeanyFiletype *ft = node->data;
722
1.4.3 by Damián Viano
Import upstream version 0.19
723
		if (ft->group != GEANY_FILETYPE_GROUP_NONE)
1.4.1 by Damian Viano
Import upstream version 0.18
724
			create_radio_menu_item(group_menus[ft->group], ft);
1.4.3 by Damián Viano
Import upstream version 0.19
725
		else
726
			create_radio_menu_item(filetype_menu, ft);
1.4.1 by Damian Viano
Import upstream version 0.18
727
	}
1.1.5 by Damián Viano
Import upstream version 0.12
728
}
729
730
1.2.2 by Damián Viano
Import upstream version 0.15
731
void filetypes_init()
732
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
733
	GSList *node;
734
1.2.2 by Damián Viano
Import upstream version 0.15
735
	filetypes_init_types();
1.4.3 by Damián Viano
Import upstream version 0.19
736
1.1.16 by Evgeni Golov
Import upstream version 0.21
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
	}
1.2.2 by Damián Viano
Import upstream version 0.15
743
	create_set_filetype_menu();
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
744
	setup_config_file_menus();
1.2.2 by Damián Viano
Import upstream version 0.15
745
}
746
747
748
/* Find a filetype that predicate returns TRUE for, otherwise return NULL. */
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
749
GeanyFiletype *filetypes_find(GCompareFunc predicate, gpointer user_data)
1.2.2 by Damián Viano
Import upstream version 0.15
750
{
751
	guint i;
752
753
	for (i = 0; i < filetypes_array->len; i++)
1.1.5 by Damián Viano
Import upstream version 0.12
754
	{
1.2.2 by Damián Viano
Import upstream version 0.15
755
		GeanyFiletype *ft = filetypes[i];
756
757
		if (predicate(ft, user_data))
1.1.5 by Damián Viano
Import upstream version 0.12
758
			return ft;
759
	}
760
	return NULL;
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
761
}
762
763
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
764
static gboolean match_basename(gconstpointer pft, gconstpointer user_data)
1.2.2 by Damián Viano
Import upstream version 0.15
765
{
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
766
	const GeanyFiletype *ft = pft;
1.2.2 by Damián Viano
Import upstream version 0.15
767
	const gchar *base_filename = user_data;
768
	gint j;
769
	gboolean ret = FALSE;
770
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
771
	if (G_UNLIKELY(ft->id == GEANY_FILETYPES_NONE))
772
		return FALSE;
773
1.2.2 by Damián Viano
Import upstream version 0.15
774
	for (j = 0; ft->pattern[j] != NULL; j++)
775
	{
776
		GPatternSpec *pattern = g_pattern_spec_new(ft->pattern[j]);
777
778
		if (g_pattern_match_string(pattern, base_filename))
779
		{
780
			ret = TRUE;
781
			g_pattern_spec_free(pattern);
782
			break;
783
		}
784
		g_pattern_spec_free(pattern);
785
	}
786
	return ret;
787
}
788
789
1.1.15 by Chow Loong Jin
Import upstream version 0.20
790
static GeanyFiletype *check_builtin_filenames(const gchar *utf8_filename)
791
{
792
	gchar *lfn = NULL;
1.1.16 by Evgeni Golov
Import upstream version 0.21
793
	gchar *path;
1.1.15 by Chow Loong Jin
Import upstream version 0.20
794
	gboolean found = FALSE;
795
796
#ifdef G_OS_WIN32
797
	/* use lower case basename */
798
	lfn = g_utf8_strdown(utf8_filename, -1);
799
#else
800
	lfn = g_strdup(utf8_filename);
801
#endif
802
	setptr(lfn, utils_get_locale_from_utf8(lfn));
803
804
	path = utils_build_path(app->configdir, GEANY_FILEDEFS_SUBDIR, "filetypes.", NULL);
805
	if (g_str_has_prefix(lfn, path))
806
		found = TRUE;
807
1.1.16 by Evgeni Golov
Import upstream version 0.21
808
	setptr(path, utils_build_path(app->datadir, "filetypes.", NULL));
1.1.15 by Chow Loong Jin
Import upstream version 0.20
809
	if (g_str_has_prefix(lfn, path))
810
		found = TRUE;
811
1.1.16 by Evgeni Golov
Import upstream version 0.21
812
	g_free(path);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
813
	g_free(lfn);
814
	return found ? filetypes[GEANY_FILETYPES_CONF] : NULL;
815
}
816
817
1.2.1 by Damián Viano
Import upstream version 0.14
818
/* Detect filetype only based on the filename extension.
819
 * utf8_filename can include the full path. */
1.2.2 by Damián Viano
Import upstream version 0.15
820
GeanyFiletype *filetypes_detect_from_extension(const gchar *utf8_filename)
1 by Damián Viano
Import upstream version 0.8
821
{
1.2.1 by Damián Viano
Import upstream version 0.14
822
	gchar *base_filename;
1.2.2 by Damián Viano
Import upstream version 0.15
823
	GeanyFiletype *ft;
1 by Damián Viano
Import upstream version 0.8
824
1.1.15 by Chow Loong Jin
Import upstream version 0.20
825
	ft = check_builtin_filenames(utf8_filename);
826
	if (ft)
827
		return ft;
828
1.2.2 by Damián Viano
Import upstream version 0.15
829
	/* to match against the basename of the file (because of Makefile*) */
1 by Damián Viano
Import upstream version 0.8
830
	base_filename = g_path_get_basename(utf8_filename);
1.2.1 by Damián Viano
Import upstream version 0.14
831
#ifdef G_OS_WIN32
832
	/* use lower case basename */
833
	setptr(base_filename, g_utf8_strdown(base_filename, -1));
834
#endif
1 by Damián Viano
Import upstream version 0.8
835
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
836
	ft = filetypes_find(match_basename, base_filename);
1.2.2 by Damián Viano
Import upstream version 0.15
837
	if (ft == NULL)
838
		ft = filetypes[GEANY_FILETYPES_NONE];
1 by Damián Viano
Import upstream version 0.8
839
840
	g_free(base_filename);
1.2.2 by Damián Viano
Import upstream version 0.15
841
	return ft;
1 by Damián Viano
Import upstream version 0.8
842
}
843
844
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
845
/* This detects the filetype of the file pointed by 'utf8_filename' and a list of filetype id's,
846
 * terminated by -1.
847
 * The detected filetype of the file is checked against every id in the passed list and if
848
 * there is a match, TRUE is returned. */
849
static gboolean shebang_find_and_match_filetype(const gchar *utf8_filename, gint first, ...)
850
{
851
	GeanyFiletype *ft = NULL;
852
	gint test;
853
	gboolean result = FALSE;
854
	va_list args;
855
856
	ft = filetypes_detect_from_extension(utf8_filename);
857
	if (ft == NULL || ft->id >= filetypes_array->len)
858
		return FALSE;
859
860
	va_start(args, first);
1.4.1 by Damian Viano
Import upstream version 0.18
861
	test = first;
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
862
	while (1)
863
	{
864
		if (test == -1)
865
			break;
866
867
		if (ft->id == (guint) test)
868
		{
869
			result = TRUE;
870
			break;
871
		}
1.4.1 by Damian Viano
Import upstream version 0.18
872
		test = va_arg(args, gint);
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
873
	}
874
	va_end(args);
875
876
	return result;
877
}
878
879
1.2.2 by Damián Viano
Import upstream version 0.15
880
static GeanyFiletype *find_shebang(const gchar *utf8_filename, const gchar *line)
1.2.1 by Damián Viano
Import upstream version 0.14
881
{
1.2.2 by Damián Viano
Import upstream version 0.15
882
	GeanyFiletype *ft = NULL;
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
883
1.1.5 by Damián Viano
Import upstream version 0.12
884
	if (strlen(line) > 2 && line[0] == '#' && line[1] == '!')
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
885
	{
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
886
		gchar *tmp = g_path_get_basename(line + 2);
887
		gchar *basename_interpreter = tmp;
888
889
		if (strncmp(tmp, "env ", 4) == 0 && strlen(tmp) > 4)
1.2.1 by Damián Viano
Import upstream version 0.14
890
		{	/* skip "env" and read the following interpreter */
1.4.3 by Damián Viano
Import upstream version 0.19
891
			basename_interpreter += 4;
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
892
		}
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
893
894
		if (strncmp(basename_interpreter, "sh", 2) == 0)
895
			ft = filetypes[GEANY_FILETYPES_SH];
896
		else if (strncmp(basename_interpreter, "bash", 4) == 0)
897
			ft = filetypes[GEANY_FILETYPES_SH];
898
		else if (strncmp(basename_interpreter, "perl", 4) == 0)
899
			ft = filetypes[GEANY_FILETYPES_PERL];
900
		else if (strncmp(basename_interpreter, "python", 6) == 0)
901
			ft = filetypes[GEANY_FILETYPES_PYTHON];
902
		else if (strncmp(basename_interpreter, "php", 3) == 0)
903
			ft = filetypes[GEANY_FILETYPES_PHP];
904
		else if (strncmp(basename_interpreter, "ruby", 4) == 0)
905
			ft = filetypes[GEANY_FILETYPES_RUBY];
906
		else if (strncmp(basename_interpreter, "tcl", 3) == 0)
907
			ft = filetypes[GEANY_FILETYPES_TCL];
1.2.2 by Damián Viano
Import upstream version 0.15
908
		else if (strncmp(basename_interpreter, "make", 4) == 0)
909
			ft = filetypes[GEANY_FILETYPES_MAKE];
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
910
		else if (strncmp(basename_interpreter, "zsh", 3) == 0)
911
			ft = filetypes[GEANY_FILETYPES_SH];
912
		else if (strncmp(basename_interpreter, "ksh", 3) == 0)
913
			ft = filetypes[GEANY_FILETYPES_SH];
914
		else if (strncmp(basename_interpreter, "csh", 3) == 0)
915
			ft = filetypes[GEANY_FILETYPES_SH];
1.1.5 by Damián Viano
Import upstream version 0.12
916
		else if (strncmp(basename_interpreter, "ash", 3) == 0)
917
			ft = filetypes[GEANY_FILETYPES_SH];
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
918
		else if (strncmp(basename_interpreter, "dmd", 3) == 0)
919
			ft = filetypes[GEANY_FILETYPES_D];
1.1.5 by Damián Viano
Import upstream version 0.12
920
		else if (strncmp(basename_interpreter, "wish", 4) == 0)
921
			ft = filetypes[GEANY_FILETYPES_TCL];
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
922
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
923
		g_free(tmp);
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
924
	}
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
925
	/* detect HTML files */
926
	if (strncmp(line, "<!DOCTYPE html", 14) == 0 || strncmp(line, "<html", 5) == 0)
927
	{
928
		/* PHP, Perl and Python files might also start with <html, so detect them based on filename
929
		 * extension and use the detected filetype, else assume HTML */
930
		if (! shebang_find_and_match_filetype(utf8_filename,
931
				GEANY_FILETYPES_PERL, GEANY_FILETYPES_PHP, GEANY_FILETYPES_PYTHON, -1))
932
		{
933
			ft = filetypes[GEANY_FILETYPES_HTML];
934
		}
935
	}
1.2.1 by Damián Viano
Import upstream version 0.14
936
	/* detect XML files */
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
937
	else if (utf8_filename && strncmp(line, "<?xml", 5) == 0)
1.1.5 by Damián Viano
Import upstream version 0.12
938
	{
1.2.1 by Damián Viano
Import upstream version 0.14
939
		/* HTML and DocBook files might also start with <?xml, so detect them based on filename
940
		 * extension and use the detected filetype, else assume XML */
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
941
		if (! shebang_find_and_match_filetype(utf8_filename,
942
				GEANY_FILETYPES_HTML, GEANY_FILETYPES_DOCBOOK,
943
				/* Perl, Python and PHP only to be safe */
944
				GEANY_FILETYPES_PERL, GEANY_FILETYPES_PHP, GEANY_FILETYPES_PYTHON, -1))
1.2.1 by Damián Viano
Import upstream version 0.14
945
		{
1.1.5 by Damián Viano
Import upstream version 0.12
946
			ft = filetypes[GEANY_FILETYPES_XML];
1.2.1 by Damián Viano
Import upstream version 0.14
947
		}
1.1.5 by Damián Viano
Import upstream version 0.12
948
	}
949
	else if (strncmp(line, "<?php", 5) == 0)
950
	{
951
		ft = filetypes[GEANY_FILETYPES_PHP];
952
	}
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
953
954
	return ft;
1.2.1 by Damián Viano
Import upstream version 0.14
955
}
956
957
958
/* Detect the filetype checking for a shebang, then filename extension. */
1.2.2 by Damián Viano
Import upstream version 0.15
959
static GeanyFiletype *filetypes_detect_from_file_internal(const gchar *utf8_filename,
960
														  const gchar *line)
1.2.1 by Damián Viano
Import upstream version 0.14
961
{
1.2.2 by Damián Viano
Import upstream version 0.15
962
	GeanyFiletype *ft;
1.2.1 by Damián Viano
Import upstream version 0.14
963
964
	/* try to find a shebang and if found use it prior to the filename extension
965
	 * also checks for <?xml */
966
	ft = find_shebang(utf8_filename, line);
967
	if (ft != NULL)
968
		return ft;
969
970
	if (utf8_filename == NULL)
1.2.2 by Damián Viano
Import upstream version 0.15
971
		return filetypes[GEANY_FILETYPES_NONE];
1.2.1 by Damián Viano
Import upstream version 0.14
972
973
	return filetypes_detect_from_extension(utf8_filename);
974
}
975
976
1.2.2 by Damián Viano
Import upstream version 0.15
977
/* Detect the filetype for the document, checking for a shebang, then filename extension. */
978
GeanyFiletype *filetypes_detect_from_document(GeanyDocument *doc)
1.2.1 by Damián Viano
Import upstream version 0.14
979
{
1.2.2 by Damián Viano
Import upstream version 0.15
980
	GeanyFiletype *ft;
1.2.1 by Damián Viano
Import upstream version 0.14
981
	gchar *line;
982
1.2.2 by Damián Viano
Import upstream version 0.15
983
	if (doc == NULL)
984
		return filetypes[GEANY_FILETYPES_NONE];
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
985
1.2.2 by Damián Viano
Import upstream version 0.15
986
	line = sci_get_line(doc->editor->sci, 0);
987
	ft = filetypes_detect_from_file_internal(doc->file_name, line);
1.2.1 by Damián Viano
Import upstream version 0.14
988
	g_free(line);
989
	return ft;
1.1.4 by Damián Viano
Import upstream version 0.11
990
}
991
992
1.2.2 by Damián Viano
Import upstream version 0.15
993
#ifdef HAVE_PLUGINS
994
/* Currently only used by external plugins (e.g. geanyprj). */
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
995
/**
1.4.3 by Damián Viano
Import upstream version 0.19
996
 *  Detects filetype based on a shebang line in the file or the filename extension.
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
997
 *
998
 *  @param utf8_filename The filename in UTF-8 encoding.
999
 *
1.4.1 by Damian Viano
Import upstream version 0.18
1000
 *  @return The detected filetype for @a utf8_filename or @c filetypes[GEANY_FILETYPES_NONE]
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1001
 *          if it could not be detected.
1002
 **/
1.2.2 by Damián Viano
Import upstream version 0.15
1003
GeanyFiletype *filetypes_detect_from_file(const gchar *utf8_filename)
1.1.4 by Damián Viano
Import upstream version 0.11
1004
{
1.2.1 by Damián Viano
Import upstream version 0.14
1005
	gchar line[1024];
1006
	FILE *f;
1007
	gchar *locale_name = utils_get_locale_from_utf8(utf8_filename);
1008
1009
	f = g_fopen(locale_name, "r");
1010
	g_free(locale_name);
1011
	if (f != NULL)
1012
	{
1013
		if (fgets(line, sizeof(line), f) != NULL)
1014
		{
1015
			fclose(f);
1016
			return filetypes_detect_from_file_internal(utf8_filename, line);
1017
		}
1018
		fclose(f);
1019
	}
1020
	return filetypes_detect_from_extension(utf8_filename);
1021
}
1.2.2 by Damián Viano
Import upstream version 0.15
1022
#endif
1023
1024
1025
void filetypes_select_radio_item(const GeanyFiletype *ft)
1 by Damián Viano
Import upstream version 0.8
1026
{
1.2.2 by Damián Viano
Import upstream version 0.15
1027
	/* ignore_callback has to be set by the caller */
1028
	g_return_if_fail(ignore_callback);
1029
1 by Damián Viano
Import upstream version 0.8
1030
	if (ft == NULL)
1.2.2 by Damián Viano
Import upstream version 0.15
1031
		ft = filetypes[GEANY_FILETYPES_NONE];
1032
1033
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ft->priv->menu_item), TRUE);
1 by Damián Viano
Import upstream version 0.8
1034
}
1035
1036
1.1.4 by Damián Viano
Import upstream version 0.11
1037
static void
1.1.16 by Evgeni Golov
Import upstream version 0.21
1038
on_filetype_change(GtkCheckMenuItem *menuitem, gpointer user_data)
1.1.4 by Damián Viano
Import upstream version 0.11
1039
{
1.2.2 by Damián Viano
Import upstream version 0.15
1040
	GeanyDocument *doc = document_get_current();
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1041
	if (ignore_callback || doc == NULL || ! gtk_check_menu_item_get_active(menuitem))
1.2.2 by Damián Viano
Import upstream version 0.15
1042
		return;
1.1.4 by Damián Viano
Import upstream version 0.11
1043
1.2.2 by Damián Viano
Import upstream version 0.15
1044
	document_set_filetype(doc, (GeanyFiletype*)user_data);
1.1.4 by Damián Viano
Import upstream version 0.11
1045
}
1046
1047
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1048
static void create_radio_menu_item(GtkWidget *menu, GeanyFiletype *ftype)
1 by Damián Viano
Import upstream version 0.8
1049
{
1050
	static GSList *group = NULL;
1051
	GtkWidget *tmp;
1.1.4 by Damián Viano
Import upstream version 0.11
1052
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1053
	tmp = gtk_radio_menu_item_new_with_label(group, ftype->title);
1 by Damián Viano
Import upstream version 0.8
1054
	group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(tmp));
1.2.2 by Damián Viano
Import upstream version 0.15
1055
	ftype->priv->menu_item = tmp;
1 by Damián Viano
Import upstream version 0.8
1056
	gtk_widget_show(tmp);
1057
	gtk_container_add(GTK_CONTAINER(menu), tmp);
1.2.2 by Damián Viano
Import upstream version 0.15
1058
	g_signal_connect(tmp, "activate", G_CALLBACK(on_filetype_change), (gpointer) ftype);
1059
}
1060
1061
1062
static void set_error_regex(GeanyFiletype *ft, gchar *string)
1063
{
1064
	setptr(ft->error_regex_string, string);
1065
1066
	if (ft->priv->error_regex_compiled)
1067
		regfree(&ft->priv->error_regex);
1068
1069
	ft->priv->error_regex_compiled = FALSE;
1070
	/* regex will be compiled when needed */
1071
}
1072
1073
1074
static void filetype_free(gpointer data, G_GNUC_UNUSED gpointer user_data)
1075
{
1076
	GeanyFiletype *ft = data;
1077
1078
	g_return_if_fail(ft != NULL);
1079
1080
	g_free(ft->name);
1081
	g_free(ft->title);
1082
	g_free(ft->extension);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1083
	g_free(ft->mime_type);
1.2.2 by Damián Viano
Import upstream version 0.15
1084
	g_free(ft->comment_open);
1085
	g_free(ft->comment_close);
1.1.16 by Evgeni Golov
Import upstream version 0.21
1086
	g_free(ft->comment_single);
1.2.2 by Damián Viano
Import upstream version 0.15
1087
	g_free(ft->context_action_cmd);
1.4.3 by Damián Viano
Import upstream version 0.19
1088
	g_free(ft->filecmds);
1089
	g_free(ft->ftdefcmds);
1090
	g_free(ft->execcmds);
1.2.2 by Damián Viano
Import upstream version 0.15
1091
	set_error_regex(ft, NULL);
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1092
	if (ft->icon)
1093
		g_object_unref(ft->icon);
1.2.2 by Damián Viano
Import upstream version 0.15
1094
1095
	g_strfreev(ft->pattern);
1.4.1 by Damian Viano
Import upstream version 0.18
1096
	g_free(ft->priv);
1.2.2 by Damián Viano
Import upstream version 0.15
1097
	g_free(ft);
1 by Damián Viano
Import upstream version 0.8
1098
}
1099
1100
1101
/* frees the array and all related pointers */
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1102
void filetypes_free_types(void)
1 by Damián Viano
Import upstream version 0.8
1103
{
1.2.2 by Damián Viano
Import upstream version 0.15
1104
	g_return_if_fail(filetypes_array != NULL);
1105
	g_return_if_fail(filetypes_hash != NULL);
1106
1107
	g_ptr_array_foreach(filetypes_array, filetype_free, NULL);
1108
	g_ptr_array_free(filetypes_array, TRUE);
1109
	g_hash_table_destroy(filetypes_hash);
1 by Damián Viano
Import upstream version 0.8
1110
}
1111
1112
1.1.16 by Evgeni Golov
Import upstream version 0.21
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
1.2.2 by Damián Viano
Import upstream version 0.15
1134
static void load_settings(gint ft_id, GKeyFile *config, GKeyFile *configh)
1 by Damián Viano
Import upstream version 0.8
1135
{
1.2.2 by Damián Viano
Import upstream version 0.15
1136
	GeanyFiletype *ft = filetypes[ft_id];
1 by Damián Viano
Import upstream version 0.8
1137
	gchar *result;
1138
1.2.1 by Damián Viano
Import upstream version 0.14
1139
	/* default extension */
1.1.16 by Evgeni Golov
Import upstream version 0.21
1140
	result = utils_get_setting(string, configh, config, "settings", "extension", NULL);
1141
	if (result != NULL)
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1142
	{
1.2.2 by Damián Viano
Import upstream version 0.15
1143
		setptr(filetypes[ft_id]->extension, result);
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1144
	}
1 by Damián Viano
Import upstream version 0.8
1145
1.2.1 by Damián Viano
Import upstream version 0.14
1146
	/* read comment notes */
1.1.16 by Evgeni Golov
Import upstream version 0.21
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);
1 by Damián Viano
Import upstream version 0.8
1173
1.2.1 by Damián Viano
Import upstream version 0.14
1174
	/* read context action */
1.1.16 by Evgeni Golov
Import upstream version 0.21
1175
	result = utils_get_setting(string, configh, config, "settings", "context_action_cmd", NULL);
1176
	if (result != NULL)
1.1.4 by Damián Viano
Import upstream version 0.11
1177
	{
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1178
		setptr(filetypes[ft_id]->context_action_cmd, result);
1.1.4 by Damián Viano
Import upstream version 0.11
1179
	}
1180
1.1.16 by Evgeni Golov
Import upstream version 0.21
1181
	result = utils_get_setting(string, configh, config, "settings", "tag_parser", NULL);
1182
	if (result != NULL)
1.4.3 by Damián Viano
Import upstream version 0.19
1183
	{
1184
		ft->lang = tm_source_file_get_named_lang(result);
1185
		if (ft->lang < 0)
1186
			geany_debug("Cannot find tag parser '%s' for custom filetype '%s'.", result, ft->name);
1187
		g_free(result);
1188
	}
1189
1.1.16 by Evgeni Golov
Import upstream version 0.21
1190
	result = utils_get_setting(string, configh, config, "settings", "lexer_filetype", NULL);
1191
	if (result != NULL)
1.4.3 by Damián Viano
Import upstream version 0.19
1192
	{
1193
		ft->lexer_filetype = filetypes_lookup_by_name(result);
1194
		if (!ft->lexer_filetype)
1195
			geany_debug("Cannot find lexer filetype '%s' for custom filetype '%s'.", result, ft->name);
1196
		g_free(result);
1197
	}
1198
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1199
	ft->priv->symbol_list_sort_mode = utils_get_setting(integer, configh, config, "settings",
1200
		"symbol_list_sort_mode", SYMBOLS_SORT_BY_NAME);
1201
	ft->priv->xml_indent_tags = utils_get_setting(boolean, configh, config, "settings",
1202
		"xml_indent_tags", FALSE);
1203
1.1.16 by Evgeni Golov
Import upstream version 0.21
1204
	/* read indent settings */
1205
	load_indent_settings(ft, config, configh);
1206
1.2.1 by Damián Viano
Import upstream version 0.14
1207
	/* read build settings */
1.4.3 by Damián Viano
Import upstream version 0.19
1208
	build_load_menu(config, GEANY_BCS_FT, (gpointer)ft);
1209
	build_load_menu(configh, GEANY_BCS_HOME_FT, (gpointer)ft);
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1210
}
1211
1212
1.1.16 by Evgeni Golov
Import upstream version 0.21
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
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1303
/* simple wrapper function to print file errors in DEBUG mode */
1304
static void load_system_keyfile(GKeyFile *key_file, const gchar *file, GKeyFileFlags flags,
1.4.3 by Damián Viano
Import upstream version 0.19
1305
		GeanyFiletype *ft)
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1306
{
1307
	GError *error = NULL;
1308
	gboolean done = g_key_file_load_from_file(key_file, file, flags, &error);
1.4.3 by Damián Viano
Import upstream version 0.19
1309
1310
	if (error != NULL)
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1311
	{
1.4.3 by Damián Viano
Import upstream version 0.19
1312
		if (!done && !ft->priv->custom)
1313
			geany_debug("Failed to open %s (%s)", file, error->message);
1314
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1315
		g_error_free(error);
1316
		error = NULL;
1317
	}
1318
}
1319
1320
1321
/* Load the configuration file for the associated filetype id.
1322
 * This should only be called when the filetype is needed, to save loading
1323
 * 20+ configuration files all at once. */
1.2.2 by Damián Viano
Import upstream version 0.15
1324
void filetypes_load_config(gint ft_id, gboolean reload)
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1325
{
1326
	GKeyFile *config, *config_home;
1.2.2 by Damián Viano
Import upstream version 0.15
1327
	GeanyFiletypePrivate *pft;
1.4.3 by Damián Viano
Import upstream version 0.19
1328
	GeanyFiletype *ft;
1.2.2 by Damián Viano
Import upstream version 0.15
1329
1330
	g_return_if_fail(ft_id >= 0 && ft_id < (gint) filetypes_array->len);
1331
1.4.3 by Damián Viano
Import upstream version 0.19
1332
	ft = filetypes[ft_id];
1333
	pft = ft->priv;
1.2.2 by Damián Viano
Import upstream version 0.15
1334
1335
	/* when reloading, proceed only if the settings were already loaded */
1.1.16 by Evgeni Golov
Import upstream version 0.21
1336
	if (G_UNLIKELY(reload && ! pft->keyfile_loaded))
1.2.2 by Damián Viano
Import upstream version 0.15
1337
		return;
1338
1339
	/* when not reloading, load the settings only once */
1.1.16 by Evgeni Golov
Import upstream version 0.21
1340
	if (G_LIKELY(! reload && pft->keyfile_loaded))
1.2.2 by Damián Viano
Import upstream version 0.15
1341
		return;
1342
	pft->keyfile_loaded = TRUE;
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1343
1344
	config = g_key_file_new();
1345
	config_home = g_key_file_new();
1346
	{
1.2.2 by Damián Viano
Import upstream version 0.15
1347
		/* highlighting uses GEANY_FILETYPES_NONE for common settings */
1.1.16 by Evgeni Golov
Import upstream version 0.21
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));
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1354
		g_key_file_load_from_file(config_home, f, G_KEY_FILE_KEEP_COMMENTS, NULL);
1355
		g_free(f);
1356
	}
1.1.16 by Evgeni Golov
Import upstream version 0.21
1357
	/* Copy keys for any groups with [group=C] from system keyfile */
1358
	copy_ft_groups(config);
1359
	copy_ft_groups(config_home);
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1360
1361
	load_settings(ft_id, config, config_home);
1.4.1 by Damian Viano
Import upstream version 0.18
1362
	highlighting_init_styles(ft_id, config, config_home);
1.1.6 by Gauvain Pocentek
Import upstream version 0.13
1363
1364
	g_key_file_free(config);
1365
	g_key_file_free(config_home);
1366
}
1367
1368
1.1.16 by Evgeni Golov
Import upstream version 0.21
1369
static gchar *filetypes_get_conf_extension(const GeanyFiletype *ft)
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1370
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
1371
	gchar *result;
1.4.3 by Damián Viano
Import upstream version 0.19
1372
1373
	if (ft->priv->custom)
1374
		return g_strconcat(ft->name, ".conf", NULL);
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1375
1.2.1 by Damián Viano
Import upstream version 0.14
1376
	/* Handle any special extensions different from lowercase filetype->name */
1.1.16 by Evgeni Golov
Import upstream version 0.21
1377
	switch (ft->id)
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1378
	{
1379
		case GEANY_FILETYPES_CPP: result = g_strdup("cpp"); break;
1.1.5 by Damián Viano
Import upstream version 0.12
1380
		case GEANY_FILETYPES_CS: result = g_strdup("cs"); break;
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1381
		case GEANY_FILETYPES_MAKE: result = g_strdup("makefile"); break;
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1382
		case GEANY_FILETYPES_NONE: result = g_strdup("common"); break;
1.1.16 by Evgeni Golov
Import upstream version 0.21
1383
		/* name is Matlab/Octave */
1384
		case GEANY_FILETYPES_MATLAB: result = g_strdup("matlab"); break;
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1385
		default:
1386
			result = g_ascii_strdown(ft->name, -1);
1387
			break;
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1388
	}
1389
	return result;
1390
}
1391
1392
1.1.16 by Evgeni Golov
Import upstream version 0.21
1393
void filetypes_save_commands(GeanyFiletype *ft)
1.1.2 by Gauvain Pocentek
Import upstream version 0.10
1394
{
1.1.16 by Evgeni Golov
Import upstream version 0.21
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);
1.2.1 by Damián Viano
Import upstream version 0.14
1407
}
1408
1409
1.1.4 by Damián Viano
Import upstream version 0.11
1410
/* create one file filter which has each file pattern of each filetype */
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1411
GtkFileFilter *filetypes_create_file_filter_all_source(void)
1.1.4 by Damián Viano
Import upstream version 0.11
1412
{
1413
	GtkFileFilter *new_filter;
1.2.2 by Damián Viano
Import upstream version 0.15
1414
	guint i, j;
1.1.4 by Damián Viano
Import upstream version 0.11
1415
1416
	new_filter = gtk_file_filter_new();
1417
	gtk_file_filter_set_name(new_filter, _("All Source"));
1418
1.2.2 by Damián Viano
Import upstream version 0.15
1419
	for (i = 0; i < filetypes_array->len; i++)
1.1.4 by Damián Viano
Import upstream version 0.11
1420
	{
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1421
		if (G_UNLIKELY(i == GEANY_FILETYPES_NONE))
1.2.2 by Damián Viano
Import upstream version 0.15
1422
			continue;
1423
1.1.4 by Damián Viano
Import upstream version 0.11
1424
		for (j = 0; filetypes[i]->pattern[j]; j++)
1425
		{
1426
			gtk_file_filter_add_pattern(new_filter, filetypes[i]->pattern[j]);
1427
		}
1428
	}
1429
	return new_filter;
1430
}
1431
1432
1.2.2 by Damián Viano
Import upstream version 0.15
1433
GtkFileFilter *filetypes_create_file_filter(const GeanyFiletype *ft)
1.1.1 by Damián Viano
Import upstream version 0.9
1434
{
1435
	GtkFileFilter *new_filter;
1436
	gint i;
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1437
	const gchar *title;
1.1.1 by Damián Viano
Import upstream version 0.9
1438
1.1.4 by Damián Viano
Import upstream version 0.11
1439
	g_return_val_if_fail(ft != NULL, NULL);
1440
1.1.1 by Damián Viano
Import upstream version 0.9
1441
	new_filter = gtk_file_filter_new();
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1442
	title = ft->id == GEANY_FILETYPES_NONE ? _("All files") : ft->title;
1443
	gtk_file_filter_set_name(new_filter, title);
1.1.1 by Damián Viano
Import upstream version 0.9
1444
1445
	for (i = 0; ft->pattern[i]; i++)
1446
	{
1447
		gtk_file_filter_add_pattern(new_filter, ft->pattern[i]);
1448
	}
1449
1450
	return new_filter;
1451
}
1452
1453
1.4.3 by Damián Viano
Import upstream version 0.19
1454
/* Indicates whether there is a tag parser for the filetype or not.
1455
 * Only works for custom filetypes if the filetype settings have been loaded. */
1.2.2 by Damián Viano
Import upstream version 0.15
1456
gboolean filetype_has_tags(GeanyFiletype *ft)
1.1.5 by Damián Viano
Import upstream version 0.12
1457
{
1458
	g_return_val_if_fail(ft != NULL, FALSE);
1459
1460
	return ft->lang >= 0;
1461
}
1462
1463
1.4.3 by Damián Viano
Import upstream version 0.19
1464
/** Finds a filetype pointer from its @a name field.
1.2.2 by Damián Viano
Import upstream version 0.15
1465
 * @param name Filetype name.
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1466
 * @return The filetype found, or @c NULL.
1467
 *
1468
 * @since 0.15
1469
 **/
1.2.2 by Damián Viano
Import upstream version 0.15
1470
GeanyFiletype *filetypes_lookup_by_name(const gchar *name)
1471
{
1472
	GeanyFiletype *ft;
1473
1474
	g_return_val_if_fail(NZV(name), NULL);
1475
1476
	ft = g_hash_table_lookup(filetypes_hash, name);
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1477
	if (G_UNLIKELY(ft == NULL))
1.2.2 by Damián Viano
Import upstream version 0.15
1478
		geany_debug("Could not find filetype '%s'.", name);
1479
	return ft;
1480
}
1481
1482
1483
static gchar *get_regex_match_string(const gchar *message, regmatch_t *pmatch, gint match_idx)
1484
{
1485
	return g_strndup(&message[pmatch[match_idx].rm_so],
1486
		pmatch[match_idx].rm_eo - pmatch[match_idx].rm_so);
1487
}
1488
1489
1.4.3 by Damián Viano
Import upstream version 0.19
1490
static void compile_regex(GeanyFiletype *ft, regex_t *regex, gchar *regstr)
1.2.2 by Damián Viano
Import upstream version 0.15
1491
{
1.4.3 by Damián Viano
Import upstream version 0.19
1492
	gint retval = regcomp(regex, regstr, REG_EXTENDED);
1.2.2 by Damián Viano
Import upstream version 0.15
1493
1494
	ft->priv->error_regex_compiled = (retval == 0);	/* prevent recompilation */
1495
1.1.10 by Jérôme Guelfucci
Import upstream version 0.17
1496
	if (G_UNLIKELY(retval != 0))
1.2.2 by Damián Viano
Import upstream version 0.15
1497
	{
1498
		gchar buf[256];
1499
		regerror(retval, regex, buf, sizeof buf);
1500
		ui_set_statusbar(TRUE, _("Bad regex for filetype %s: %s"),
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1501
			filetypes_get_display_name(ft), buf);
1.2.2 by Damián Viano
Import upstream version 0.15
1502
	}
1503
	/* regex will be freed in set_error_regex(). */
1504
}
1505
1506
1507
gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message,
1508
		gchar **filename, gint *line)
1509
{
1.4.3 by Damián Viano
Import upstream version 0.19
1510
	gchar *regstr;
1511
	gchar **tmp;
1512
	GeanyDocument *doc;
1513
	regex_t *regex;
1514
	regmatch_t pmatch[3];
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1515
1.4.3 by Damián Viano
Import upstream version 0.19
1516
	if (ft == NULL)
1517
	{
1518
		doc = document_get_current();
1519
		if (doc != NULL)
1520
			ft = doc->file_type;
1521
	}
1522
	tmp = build_get_regex(build_info.grp, ft, NULL);
1523
	if (tmp == NULL)
1524
		return FALSE;
1525
	regstr = *tmp;
1526
	regex = &ft->priv->error_regex;
1.2.2 by Damián Viano
Import upstream version 0.15
1527
1528
	*filename = NULL;
1529
	*line = -1;
1530
1.1.16 by Evgeni Golov
Import upstream version 0.21
1531
	if (G_UNLIKELY(! NZV(regstr)))
1.2.2 by Damián Viano
Import upstream version 0.15
1532
		return FALSE;
1533
1.4.3 by Damián Viano
Import upstream version 0.19
1534
	if (!ft->priv->error_regex_compiled || regstr != ft->priv->last_string)
1535
	{
1536
		compile_regex(ft, regex, regstr);
1537
		ft->priv->last_string = regstr;
1538
	}
1.2.2 by Damián Viano
Import upstream version 0.15
1539
	if (!ft->priv->error_regex_compiled)	/* regex error */
1540
		return FALSE;
1541
1542
	if (regexec(regex, message, G_N_ELEMENTS(pmatch), pmatch, 0) != 0)
1543
		return FALSE;
1544
1545
	if (pmatch[0].rm_so != -1 && pmatch[1].rm_so != -1 && pmatch[2].rm_so != -1)
1546
	{
1547
		gchar *first, *second, *end;
1548
		glong l;
1549
1550
		first = get_regex_match_string(message, pmatch, 1);
1551
		second = get_regex_match_string(message, pmatch, 2);
1552
		l = strtol(first, &end, 10);
1553
		if (*end == '\0')	/* first is purely decimals */
1554
		{
1555
			*line = l;
1556
			g_free(first);
1557
			*filename = second;
1558
		}
1559
		else
1560
		{
1561
			l = strtol(second, &end, 10);
1562
			if (*end == '\0')
1563
			{
1564
				*line = l;
1565
				g_free(second);
1566
				*filename = first;
1567
			}
1568
			else
1569
			{
1570
				g_free(first);
1571
				g_free(second);
1572
			}
1573
		}
1574
	}
1575
	return *filename != NULL;
1576
}
1577
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1578
1.4.4 by Damián Viano
Import upstream version 0.19.1
1579
#ifdef G_OS_WIN32
1580
static void convert_filetype_extensions_to_lower_case(gchar **patterns, gsize len)
1581
{
1582
	guint i;
1583
	for (i = 0; i < len; i++)
1584
	{
1585
		setptr(patterns[i], g_ascii_strdown(patterns[i], -1));
1586
	}
1587
}
1588
#endif
1589
1590
1.1.16 by Evgeni Golov
Import upstream version 0.21
1591
static void read_extensions(GKeyFile *sysconfig, GKeyFile *userconfig)
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1592
{
1593
	guint i;
1594
	gsize len = 0;
1595
1596
	/* read the keys */
1597
	for (i = 0; i < filetypes_array->len; i++)
1598
	{
1599
		gboolean userset =
1600
			g_key_file_has_key(userconfig, "Extensions", filetypes[i]->name, NULL);
1.4.3 by Damián Viano
Import upstream version 0.19
1601
		gchar **list = g_key_file_get_string_list(
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1602
			(userset) ? userconfig : sysconfig, "Extensions", filetypes[i]->name, &len, NULL);
1.4.3 by Damián Viano
Import upstream version 0.19
1603
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1604
		g_strfreev(filetypes[i]->pattern);
1605
		/* Note: we allow 'Foo=' to remove all patterns */
1606
		if (!list)
1607
			list = g_new0(gchar*, 1);
1608
		filetypes[i]->pattern = list;
1609
1.4.4 by Damián Viano
Import upstream version 0.19.1
1610
#ifdef G_OS_WIN32
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1611
		convert_filetype_extensions_to_lower_case(filetypes[i]->pattern, len);
1.4.4 by Damián Viano
Import upstream version 0.19.1
1612
#endif
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1613
	}
1.1.16 by Evgeni Golov
Import upstream version 0.21
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);
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1668
1669
	g_free(sysconfigfile);
1670
	g_free(userconfigfile);
1671
	g_key_file_free(sysconfig);
1672
	g_key_file_free(userconfig);
1.1.16 by Evgeni Golov
Import upstream version 0.21
1673
}
1674
1675
1676
void filetypes_reload_extensions(void)
1677
{
1678
	guint i;
1679
1680
	read_filetype_config();
1.4.3 by Damián Viano
Import upstream version 0.19
1681
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1682
	/* Redetect filetype of any documents with none set */
1.4.3 by Damián Viano
Import upstream version 0.19
1683
	foreach_document(i)
1684
	{
1685
		GeanyDocument *doc = documents[i];
1686
		if (doc->file_type->id != GEANY_FILETYPES_NONE)
1687
			continue;
1688
		document_set_filetype(doc, filetypes_detect_from_document(doc));
1689
	}
1.1.9 by Jérôme Guelfucci
Import upstream version 0.16
1690
}
1691
1692
1693
/** Accessor function for @ref GeanyData::filetypes_array items.
1694
 * Example: @code ft = filetypes_index(GEANY_FILETYPES_C); @endcode
1695
 * @param idx @c filetypes_array index.
1696
 * @return The filetype, or @c NULL if @a idx is out of range.
1697
 *
1698
 *  @since 0.16
1699
 */
1700
GeanyFiletype *filetypes_index(gint idx)
1701
{
1702
	return (idx >= 0 && idx < (gint) filetypes_array->len) ? filetypes[idx] : NULL;
1703
}
1.4.3 by Damián Viano
Import upstream version 0.19
1704
1705
1706
void filetypes_reload(void)
1707
{
1708
	guint i;
1709
	GeanyDocument *current_doc;
1710
1711
	/* reload filetype configs */
1712
	for (i = 0; i < filetypes_array->len; i++)
1713
	{
1714
		/* filetypes_load_config() will skip not loaded filetypes */
1715
		filetypes_load_config(i, TRUE);
1716
	}
1.4.4 by Damián Viano
Import upstream version 0.19.1
1717
1718
	current_doc = document_get_current();
1719
	if (!current_doc)
1720
		return;
1721
1.4.3 by Damián Viano
Import upstream version 0.19
1722
	/* update document styling */
1723
	foreach_document(i)
1724
	{
1725
		if (current_doc != documents[i])
1726
			document_reload_config(documents[i]);
1727
	}
1728
	/* process the current document at last */
1729
	document_reload_config(current_doc);
1730
}
1731
1732
1.1.15 by Chow Loong Jin
Import upstream version 0.20
1733
/** Gets @c ft->name or a translation for filetype None.
1734
 * @param ft .
1735
 * @return .
1736
 * @since Geany 0.20 */
1737
const gchar *filetypes_get_display_name(GeanyFiletype *ft)
1738
{
1739
	return ft->id == GEANY_FILETYPES_NONE ? _("None") : ft->name;
1740
}
1741