1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2004-2007 Imendio AB
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Martyn Russell <martyn@imendio.com>
21 * Richard Hult <richard@imendio.com>
29 #include <glib/gi18n-lib.h>
35 #include "empathy-spell.h"
36 #include "empathy-conf.h"
38 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
39 #include <libempathy/empathy-debug.h>
44 EnchantBroker *config;
48 #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes"
49 #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale"
51 static GHashTable *iso_code_names = NULL;
52 static GList *languages = NULL;
53 static gboolean empathy_conf_notify_inited = FALSE;
56 spell_iso_codes_parse_start_tag (GMarkupParseContext *ctx,
57 const gchar *element_name,
58 const gchar **attr_names,
59 const gchar **attr_values,
63 const gchar *ccode_longB, *ccode_longT, *ccode;
64 const gchar *lang_name;
66 if (!g_str_equal (element_name, "iso_639_entry") ||
67 attr_names == NULL || attr_values == NULL) {
76 while (*attr_names && *attr_values) {
77 if (g_str_equal (*attr_names, "iso_639_1_code")) {
82 else if (g_str_equal (*attr_names, "iso_639_2B_code")) {
84 ccode_longB = *attr_values;
87 else if (g_str_equal (*attr_names, "iso_639_2T_code")) {
89 ccode_longT = *attr_values;
92 else if (g_str_equal (*attr_names, "name")) {
93 lang_name = *attr_values;
105 g_hash_table_insert (iso_code_names,
107 g_strdup (lang_name));
111 g_hash_table_insert (iso_code_names,
112 g_strdup (ccode_longB),
113 g_strdup (lang_name));
117 g_hash_table_insert (iso_code_names,
118 g_strdup (ccode_longT),
119 g_strdup (lang_name));
124 spell_iso_code_names_init (void)
130 iso_code_names = g_hash_table_new_full (g_str_hash, g_str_equal,
133 bindtextdomain ("iso_639", ISO_CODES_LOCALESDIR);
134 bind_textdomain_codeset ("iso_639", "UTF-8");
136 /* FIXME: We should read this in chunks and pass to the parser. */
137 if (g_file_get_contents (ISO_CODES_DATADIR "/iso_639.xml", &buf, &buf_len, &err)) {
138 GMarkupParseContext *ctx;
139 GMarkupParser parser = {
140 spell_iso_codes_parse_start_tag,
141 NULL, NULL, NULL, NULL
144 ctx = g_markup_parse_context_new (&parser, 0, NULL, NULL);
145 if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err)) {
146 g_warning ("Failed to parse '%s': %s",
147 ISO_CODES_DATADIR"/iso_639.xml",
152 g_markup_parse_context_free (ctx);
155 g_warning ("Failed to load '%s': %s",
156 ISO_CODES_DATADIR"/iso_639.xml", err->message);
162 spell_notify_languages_cb (EmpathyConf *conf,
168 DEBUG ("Resetting languages due to config change");
170 /* We just reset the languages list. */
171 for (l = languages; l; l = l->next) {
176 enchant_broker_free_dict (lang->config, lang->speller);
177 enchant_broker_free (lang->config);
179 g_slice_free (SpellLanguage, lang);
182 g_list_free (languages);
187 spell_setup_languages (void)
191 if (!empathy_conf_notify_inited) {
192 empathy_conf_notify_add (empathy_conf_get (),
193 EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
194 spell_notify_languages_cb, NULL);
196 empathy_conf_notify_inited = TRUE;
203 if (empathy_conf_get_string (empathy_conf_get (),
204 EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
209 strv = g_strsplit (str, ",", -1);
212 while (strv && strv[i]) {
215 DEBUG ("Setting up language:'%s'", strv[i]);
217 lang = g_slice_new0 (SpellLanguage);
219 lang->config = enchant_broker_init ();
220 lang->speller = enchant_broker_request_dict (lang->config, strv[i]);
222 languages = g_list_append (languages, lang);
235 empathy_spell_get_language_name (const gchar *code)
239 g_return_val_if_fail (code != NULL, NULL);
241 if (!iso_code_names) {
242 spell_iso_code_names_init ();
245 name = g_hash_table_lookup (iso_code_names, code);
250 return dgettext ("iso_639", name);
254 enumerate_dicts (const gchar * const lang_tag,
255 const gchar * const provider_name,
256 const gchar * const provider_desc,
257 const gchar * const provider_file,
260 GList **list = user_data;
261 gchar *lang = g_strdup (lang_tag);
263 if (strchr (lang, '_')) {
264 /* cut country part out of language */
265 strchr (lang, '_')[0] = '\0';
268 if (g_list_find_custom (*list, lang, (GCompareFunc) strcmp)) {
269 /* this language is already part of the list */
274 *list = g_list_append (*list, g_strdup (lang));
278 empathy_spell_get_language_codes (void)
280 EnchantBroker *broker;
281 GList *list_langs = NULL;
283 broker = enchant_broker_init ();
284 enchant_broker_list_dicts (broker, enumerate_dicts, &list_langs);
285 enchant_broker_free (broker);
291 empathy_spell_free_language_codes (GList *codes)
293 g_list_foreach (codes, (GFunc) g_free, NULL);
298 empathy_spell_check (const gchar *word)
300 gint enchant_result = 1;
307 g_return_val_if_fail (word != NULL, FALSE);
309 spell_setup_languages ();
312 DEBUG ("No languages to check against");
316 /* Ignore certain cases like numbers, etc. */
317 for (p = word, digit = TRUE; *p && digit; p = g_utf8_next_char (p)) {
318 c = g_utf8_get_char (p);
319 digit = g_unichar_isdigit (c);
323 /* We don't spell check digits. */
324 DEBUG ("Not spell checking word:'%s', it is all digits", word);
329 for (l = languages; l; l = l->next) {
334 enchant_result = enchant_dict_check (lang->speller, word, len);
336 if (enchant_result == 0) {
341 return (enchant_result == 0);
345 empathy_spell_get_suggestions (const gchar *word)
349 GList *suggestion_list = NULL;
351 g_return_val_if_fail (word != NULL, NULL);
353 spell_setup_languages ();
357 for (l1 = languages; l1; l1 = l1->next) {
360 gsize i, number_of_suggestions;
364 suggestions = enchant_dict_suggest (lang->speller, word, len,
365 &number_of_suggestions);
367 for (i = 0; i < number_of_suggestions; i++) {
368 suggestion_list = g_list_append (suggestion_list,
369 g_strdup (suggestions[i]));
373 enchant_dict_free_string_list (lang->speller, suggestions);
377 return suggestion_list;
381 empathy_spell_supported (void)
383 if (g_getenv ("EMPATHY_SPELL_DISABLED")) {
384 DEBUG ("EMPATHY_SPELL_DISABLE env variable defined");
391 #else /* not HAVE_ENCHANT */
394 empathy_spell_supported (void)
400 empathy_spell_get_suggestions (const gchar *word)
402 DEBUG ("Support disabled, could not get suggestions");
408 empathy_spell_check (const gchar *word)
410 DEBUG ("Support disabled, could not check spelling");
416 empathy_spell_get_language_name (const gchar *lang)
418 DEBUG ("Support disabled, could not get language name");
424 empathy_spell_get_language_codes (void)
426 DEBUG ("Support disabled, could not get language codes");
432 empathy_spell_free_language_codes (GList *codes)
436 #endif /* HAVE_ENCHANT */
440 empathy_spell_free_suggestions (GList *suggestions)
442 g_list_foreach (suggestions, (GFunc) g_free, NULL);
443 g_list_free (suggestions);