1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * plugin.c
4  * Copyright (C) Johannes Schmid 2007 <jhs@gnome.org>
5  *
6  * plugin.c is free software.
7  *
8  * You may redistribute it and/or modify it under the terms of the
9  * GNU General Public License, as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * plugin.c is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with plugin.c.  If not, write to:
20  * 	The Free Software Foundation, Inc.,
21  * 	51 Franklin Street, Fifth Floor
22  * 	Boston, MA  02110-1301, USA.
23  */
24 
25 #include <config.h>
26 #include <libanjuta/anjuta-shell.h>
27 #include <libanjuta/anjuta-debug.h>
28 #include <libanjuta/interfaces/ianjuta-language.h>
29 
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 
33 #include "plugin.h"
34 #define LANG_FILE PACKAGE_DATA_DIR"/languages.xml"
35 
36 #define LANGUAGE_MANAGER(o) (LanguageManager*) (o)
37 
38 typedef struct _Language Language;
39 
40 struct _Language
41 {
42 	IAnjutaLanguageId id;
43 	gchar* name;
44 	gchar* make_target;
45 	GList* strings;
46 	GList* mime_types;
47 };
48 
49 
50 static gpointer parent_class;
51 
52 
53 static void
language_destroy(gpointer data)54 language_destroy (gpointer data)
55 {
56 	Language* lang = (Language*) data;
57 
58 	g_free(lang->name);
59 	g_list_foreach(lang->strings, (GFunc) g_free, NULL);
60 	g_list_foreach(lang->mime_types, (GFunc) g_free, NULL);
61 
62 	g_free(lang);
63 }
64 
65 static void
load_languages(LanguageManager * language_manager)66 load_languages (LanguageManager* language_manager)
67 {
68 	xmlDocPtr doc;
69 	xmlNodePtr root;
70 	xmlNodePtr cur_node;
71 
72 	LIBXML_TEST_VERSION
73 
74 	doc = xmlReadFile (LANG_FILE, NULL, 0);
75 	if (!doc)
76 	{
77 		DEBUG_PRINT("Could not read language xml file %s!", LANG_FILE);
78 		return;
79 	}
80 	root = xmlDocGetRootElement (doc);
81 
82 	if (!g_str_equal (root->name, "languages"))
83 	{
84 		DEBUG_PRINT ("%s", "Invalid languages.xml file");
85 	}
86 
87 	for (cur_node = root->children; cur_node != NULL; cur_node = cur_node->next)
88 	{
89 		Language* lang = g_new0(Language, 1);
90 		gchar* id;
91 		gchar* mime_types;
92 		gchar* strings;
93 
94 		if (!g_str_equal (cur_node->name, (const xmlChar*) "language"))
95 			continue;
96 
97 		id = (gchar*) xmlGetProp (cur_node, (const xmlChar*) "id");
98 		lang->id = atoi(id);
99 		lang->name = (gchar*) xmlGetProp(cur_node, (const xmlChar*) "name");
100 		lang->make_target = (gchar*) xmlGetProp (cur_node, (const xmlChar*) "make-target");
101 		mime_types = (gchar*) xmlGetProp (cur_node, (const xmlChar*) "mime-types");
102 		strings = (gchar*) xmlGetProp (cur_node, (const xmlChar*) "strings");
103 		if (lang->id != 0 && lang->name && mime_types && strings)
104 		{
105 			GStrv mime_typesv = g_strsplit(mime_types, ",", -1);
106 			GStrv stringsv = g_strsplit (strings, ",", -1);
107 			GStrv type;
108 			GStrv string;
109 
110 			for (type = mime_typesv; *type != NULL; type++)
111 			{
112 				lang->mime_types = g_list_append (lang->mime_types, g_strdup(*type));
113 			}
114 			g_strfreev(mime_typesv);
115 
116 			for (string = stringsv; *string != NULL; string++)
117 			{
118 				lang->strings = g_list_append (lang->strings, g_strdup(*string));
119 			}
120 			g_strfreev(stringsv);
121 
122 			g_hash_table_insert (language_manager->languages, GINT_TO_POINTER(lang->id), lang);
123 		}
124 		else
125 		{
126 			g_free(lang);
127 		}
128 		g_free (id);
129 		g_free (mime_types);
130 		g_free (strings);
131 	}
132 	xmlFreeDoc(doc);
133 }
134 
135 static gboolean
language_manager_activate(AnjutaPlugin * plugin)136 language_manager_activate (AnjutaPlugin *plugin)
137 {
138 	LanguageManager *language_manager;
139 
140 	DEBUG_PRINT ("%s", "LanguageManager: Activating LanguageManager plugin ...");
141 	language_manager = (LanguageManager*) plugin;
142 
143 	load_languages(language_manager);
144 
145 	return TRUE;
146 }
147 
148 static gboolean
language_manager_deactivate(AnjutaPlugin * plugin)149 language_manager_deactivate (AnjutaPlugin *plugin)
150 {
151 	DEBUG_PRINT ("%s", "LanguageManager: Dectivating LanguageManager plugin ...");
152 
153 	return TRUE;
154 }
155 
156 static void
language_manager_finalize(GObject * obj)157 language_manager_finalize (GObject *obj)
158 {
159 	/* Finalization codes here */
160 	G_OBJECT_CLASS (parent_class)->finalize (obj);
161 }
162 
163 static void
language_manager_dispose(GObject * obj)164 language_manager_dispose (GObject *obj)
165 {
166 	/* Disposition codes */
167 	LanguageManager* lang = LANGUAGE_MANAGER (obj);
168 
169 	g_hash_table_unref (lang->languages);
170 	G_OBJECT_CLASS (parent_class)->dispose (obj);
171 }
172 
173 static void
language_manager_instance_init(GObject * obj)174 language_manager_instance_init (GObject *obj)
175 {
176 	LanguageManager *plugin = (LanguageManager*)obj;
177 	plugin->languages = g_hash_table_new_full (NULL, NULL,
178 											   NULL, language_destroy);
179 
180 }
181 
182 static void
language_manager_class_init(GObjectClass * klass)183 language_manager_class_init (GObjectClass *klass)
184 {
185 	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
186 
187 	parent_class = g_type_class_peek_parent (klass);
188 
189 	plugin_class->activate = language_manager_activate;
190 	plugin_class->deactivate = language_manager_deactivate;
191 	klass->finalize = language_manager_finalize;
192 	klass->dispose = language_manager_dispose;
193 }
194 
195 typedef struct
196 {
197 	LanguageManager* lang;
198 	const gchar* target;
199 	IAnjutaLanguageId result_id;
200 	gboolean found;
201 } LangData;
202 
203 static void
language_manager_find_mime_type(gpointer key,Language * language,LangData * data)204 language_manager_find_mime_type (gpointer key, Language* language, LangData* data)
205 {
206 	if (data->found)
207 		return;
208 	if (g_list_find_custom (language->mime_types, data->target, (GCompareFunc) strcmp))
209 	{
210 		data->result_id = language->id;
211 		data->found = TRUE;
212 	}
213 }
214 
215 static void
language_manager_find_string(gpointer key,Language * language,LangData * data)216 language_manager_find_string (gpointer key, Language* language, LangData* data)
217 {
218 	if (data->found)
219 		return;
220 	if (g_list_find_custom (language->strings, data->target, (GCompareFunc) g_ascii_strcasecmp))
221 	{
222 		DEBUG_PRINT ("Found language %i: %s", language->id, language->name);
223 		data->result_id = language->id;
224 		data->found = TRUE;
225 	}
226 }
227 
228 static IAnjutaLanguageId
ilanguage_get_from_mime_type(IAnjutaLanguage * ilang,const gchar * mime_type,GError ** e)229 ilanguage_get_from_mime_type (IAnjutaLanguage* ilang, const gchar* mime_type, GError** e)
230 {
231 	if (!mime_type)
232 		return 0;
233 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
234 	LangData* data = g_new0(LangData, 1);
235 	IAnjutaLanguageId ret_id;
236 	data->target = mime_type;
237 	g_hash_table_foreach (lang->languages, (GHFunc)language_manager_find_mime_type, data);
238 	if (data->found)
239 	{
240 		ret_id = data->result_id;
241 	}
242 	else
243 	{
244 		DEBUG_PRINT ("Unknown mime-type = %s", mime_type);
245 		ret_id = 0;
246 	}
247 	g_free(data);
248 	return ret_id;
249 }
250 
251 static IAnjutaLanguageId
ilanguage_get_from_string(IAnjutaLanguage * ilang,const gchar * string,GError ** e)252 ilanguage_get_from_string (IAnjutaLanguage* ilang, const gchar* string, GError** e)
253 {
254 	if (!string)
255 		return 0;
256 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
257 	LangData* data = g_new0(LangData, 1);
258 	IAnjutaLanguageId ret_id;
259 	data->target = string;
260 	g_hash_table_foreach (lang->languages, (GHFunc)language_manager_find_string, data);
261 	if (data->found)
262 	{
263 		ret_id = data->result_id;
264 	}
265 	else
266 	{
267 		DEBUG_PRINT ("Unknown language string = %s", string);
268 		ret_id = 0;
269 	}
270 	g_free(data);
271 	return ret_id;
272 }
273 
274 static const gchar*
ilanguage_get_name(IAnjutaLanguage * ilang,IAnjutaLanguageId id,GError ** e)275 ilanguage_get_name (IAnjutaLanguage* ilang, IAnjutaLanguageId id, GError** e)
276 {
277 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
278 	Language* language = g_hash_table_lookup (lang->languages,
279 											   GINT_TO_POINTER(id));
280 
281 	if (language)
282 	{
283 		return language->name;
284 		DEBUG_PRINT ("Found language: %s", language->name);
285 	}
286 	else
287 		return NULL;
288 }
289 
290 static GList*
ilanguage_get_strings(IAnjutaLanguage * ilang,IAnjutaLanguageId id,GError ** e)291 ilanguage_get_strings (IAnjutaLanguage* ilang, IAnjutaLanguageId id, GError** e)
292 {
293 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
294 	Language* language = g_hash_table_lookup (lang->languages,
295 											   GINT_TO_POINTER(id));
296 	if (language)
297 		return language->strings;
298 	else
299 		return NULL;
300 }
301 
302 static const char*
ilanguage_get_make_target(IAnjutaLanguage * ilang,IAnjutaLanguageId id,GError ** e)303 ilanguage_get_make_target (IAnjutaLanguage* ilang, IAnjutaLanguageId id, GError** e)
304 {
305 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
306 	Language* language = g_hash_table_lookup (lang->languages,
307 	                                          GINT_TO_POINTER(id));
308 	if (language)
309 		return language->make_target;
310 	else
311 		return NULL;
312 
313 }
314 
315 static IAnjutaLanguageId
ilanguage_get_from_editor(IAnjutaLanguage * ilang,IAnjutaEditorLanguage * editor,GError ** e)316 ilanguage_get_from_editor (IAnjutaLanguage* ilang, IAnjutaEditorLanguage* editor, GError** e)
317 {
318 	const gchar* language =
319 			ianjuta_editor_language_get_language (editor, e);
320 
321 	IAnjutaLanguageId id =
322 			ilanguage_get_from_string (ilang, language, e);
323 
324 	return id;
325 }
326 
327 static const gchar*
ilanguage_get_name_from_editor(IAnjutaLanguage * ilang,IAnjutaEditorLanguage * editor,GError ** e)328 ilanguage_get_name_from_editor (IAnjutaLanguage* ilang, IAnjutaEditorLanguage* editor, GError** e)
329 {
330 	return ilanguage_get_name (ilang,
331 							   ilanguage_get_from_editor (ilang, editor, e), e);
332 }
333 
334 static GList*
ilanguage_get_languages(IAnjutaLanguage * ilang,GError ** e)335 ilanguage_get_languages (IAnjutaLanguage* ilang, GError** e)
336 {
337 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
338 	return g_hash_table_get_keys (lang->languages);
339 }
340 
341 static GList*
ilanguage_get_mime_types(IAnjutaLanguage * ilang,IAnjutaLanguageId id,GError ** e)342 ilanguage_get_mime_types(IAnjutaLanguage* ilang, IAnjutaLanguageId id, GError** e)
343 {
344 	LanguageManager* lang = LANGUAGE_MANAGER(ilang);
345 	Language* language = g_hash_table_lookup (lang->languages,
346 	                                          GINT_TO_POINTER(id));
347 	if (language)
348 	{
349 		return language->mime_types;
350 	}
351 	return NULL;
352 }
353 
354 static void
ilanguage_iface_init(IAnjutaLanguageIface * iface)355 ilanguage_iface_init (IAnjutaLanguageIface* iface)
356 {
357 	iface->get_from_mime_type = ilanguage_get_from_mime_type;
358 	iface->get_from_string = ilanguage_get_from_string;
359 	iface->get_name = ilanguage_get_name;
360 	iface->get_strings = ilanguage_get_strings;
361 	iface->get_mime_types = ilanguage_get_mime_types;
362 	iface->get_make_target = ilanguage_get_make_target;
363 	iface->get_from_editor = ilanguage_get_from_editor;
364 	iface->get_name_from_editor = ilanguage_get_name_from_editor;
365 	iface->get_languages = ilanguage_get_languages;
366 };
367 
368 ANJUTA_PLUGIN_BEGIN (LanguageManager, language_manager);
369 ANJUTA_PLUGIN_ADD_INTERFACE (ilanguage, IANJUTA_TYPE_LANGUAGE);
370 ANJUTA_PLUGIN_END
371 
372 ANJUTA_SIMPLE_PLUGIN (LanguageManager, language_manager);
373