|
|
#include "Spell.h" | #include "Spell.h" |
#include "dictionary.h" | #include "dictionary.h" |
| |
|
#include <enchant.h> |
|
|
|
typedef struct { |
|
EnchantBroker * config; |
|
EnchantDict * speller; |
|
} SpellEngine; |
|
|
static BonoboObjectClass *dictionary_parent_class; | static BonoboObjectClass *dictionary_parent_class; |
| |
#define DICT_DEBUG(x) | #define DICT_DEBUG(x) |
|
|
{ | { |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (object); | GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (object); |
| |
dict->changed = TRUE; |
|
dict->engines = NULL; | dict->engines = NULL; |
dict->languages = g_hash_table_new (g_str_hash, g_str_equal); | dict->languages = g_hash_table_new (g_str_hash, g_str_equal); |
dict->engines_ht = g_hash_table_new (NULL, NULL); | dict->engines_ht = g_hash_table_new (NULL, NULL); |
} | } |
| |
|
static char ** |
|
dup_string_list (char ** str_list, size_t list_len) |
|
{ |
|
char ** new_str_list; |
|
size_t i; |
|
|
|
new_str_list = g_new0 (char *, list_len + 1); |
|
for (i = 0; i < list_len; i++) |
|
new_str_list [i] = g_strdup (str_list [i]); |
|
|
|
return new_str_list; |
|
} |
|
|
static void | static void |
dictionary_finalize (GObject *object) | dictionary_finalize (GObject *object) |
{ | { |
|
|
} | } |
| |
static SpellEngine * | static SpellEngine * |
new_engine (const gchar *language) |
new_engine (const gchar *language, CORBA_Environment *ev) |
{ | { |
SpellEngine *se; | SpellEngine *se; |
| |
se = g_new0 (SpellEngine, 1); | se = g_new0 (SpellEngine, 1); |
se->config = new_aspell_config (); |
se->config = enchant_broker_init (); |
aspell_config_replace (se->config, "language-tag", language); |
se->speller = enchant_broker_request_dict (se->config, language); |
aspell_config_replace (se->config, "encoding", "utf-8"); |
|
se->changed = TRUE; |
if(se->speller == NULL) |
|
raise_error (ev, enchant_broker_get_error (se->config)); |
| |
return se; | return se; |
} | } |
|
|
SpellEngine *se = dict->engines->data; | SpellEngine *se = dict->engines->data; |
| |
if (se->speller) | if (se->speller) |
delete_aspell_speller (se->speller); |
enchant_broker_free_dict (se->config, se->speller); |
if (se->config) | if (se->config) |
delete_aspell_config (se->config); |
enchant_broker_free (se->config); |
g_free (se); | g_free (se); |
dict->engines = g_slist_remove (dict->engines, se); | dict->engines = g_slist_remove (dict->engines, se); |
} | } |
|
|
g_hash_table_foreach_remove (dict->languages, remove_engine_ht, NULL); | g_hash_table_foreach_remove (dict->languages, remove_engine_ht, NULL); |
| |
dict->engines = NULL; | dict->engines = NULL; |
dict->changed = TRUE; |
|
} | } |
| |
static LangInfo known_languages [] = { | static LangInfo known_languages [] = { |
|
|
get_languages_real (gint *ln) | get_languages_real (gint *ln) |
{ | { |
GSList *langs; | GSList *langs; |
AspellCanHaveError *err; |
EnchantBroker *broker; |
AspellConfig *config; |
|
AspellSpeller *speller; |
|
gint i; | gint i; |
| |
DICT_DEBUG (printf ("get_languages_real\n")); | DICT_DEBUG (printf ("get_languages_real\n")); |
| |
|
/* todo: this could probably be better done by enchant_broker_list_dicts(), but let's keep |
|
the initial code change to a minimum */ |
|
|
|
broker = enchant_broker_init (); |
langs = NULL; | langs = NULL; |
*ln = 0; | *ln = 0; |
for (i=0; i < G_N_ELEMENTS (known_languages); i++) { | for (i=0; i < G_N_ELEMENTS (known_languages); i++) { |
config = new_aspell_config (); |
if (enchant_broker_dict_exists (broker, known_languages [i].abbreviation)) { |
aspell_config_replace (config, "language-tag", known_languages [i].abbreviation); |
|
err = new_aspell_speller (config); |
|
if (aspell_error_number (err) == 0) { |
|
speller = to_aspell_speller (err); |
|
DICT_DEBUG (printf ("Language: %s\n", known_languages [i].name)); | DICT_DEBUG (printf ("Language: %s\n", known_languages [i].name)); |
delete_aspell_speller (speller); |
|
langs = g_slist_prepend (langs, GINT_TO_POINTER (i)); | langs = g_slist_prepend (langs, GINT_TO_POINTER (i)); |
(*ln) ++; | (*ln) ++; |
} | } |
} | } |
| |
|
enchant_broker_free (broker); |
|
|
return langs; | return langs; |
} | } |
| |
|
|
{ | { |
GSList *langs, *l; | GSList *langs, *l; |
GConfClient *gc; | GConfClient *gc; |
time_t mtime; |
|
struct stat buf; |
|
gint i, kl; | gint i, kl; |
| |
gc = gconf_client_get_default (); | gc = gconf_client_get_default (); |
| |
mtime = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/mtime", NULL); |
|
kl = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", NULL); | kl = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", NULL); |
| |
if (stat (ASPELL_DICT, &buf) || buf.st_mtime != mtime || kl != G_N_ELEMENTS(known_languages)) { |
if (kl != G_N_ELEMENTS(known_languages)) { |
GString *str; | GString *str; |
langs = get_languages_real (ln); | langs = get_languages_real (ln); |
| |
|
|
gconf_client_set_int (gc, str->str, GPOINTER_TO_INT (l->data), NULL); | gconf_client_set_int (gc, str->str, GPOINTER_TO_INT (l->data), NULL); |
l = l->next; | l = l->next; |
} | } |
gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/mtime", buf.st_mtime, NULL); |
|
gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", G_N_ELEMENTS(known_languages), NULL); | gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", G_N_ELEMENTS(known_languages), NULL); |
g_string_free (str, TRUE); | g_string_free (str, TRUE); |
gnome_config_sync (); | gnome_config_sync (); |
|
|
SpellEngine *se; | SpellEngine *se; |
| |
one_language = g_strndup (begin, len); | one_language = g_strndup (begin, len); |
se = new_engine (one_language); |
se = new_engine (one_language, ev); |
dict->engines = g_slist_prepend (dict->engines, se); | dict->engines = g_slist_prepend (dict->engines, se); |
g_hash_table_insert (dict->languages, one_language, se); | g_hash_table_insert (dict->languages, one_language, se); |
g_hash_table_insert (dict->engines_ht, se, g_strdup (one_language)); | g_hash_table_insert (dict->engines_ht, se, g_strdup (one_language)); |
|
|
dict->changed = TRUE; |
|
} |
|
} |
|
} |
|
|
|
static void |
|
update_engine (SpellEngine *se, CORBA_Environment * ev) |
|
{ |
|
AspellCanHaveError *err; |
|
|
|
DICT_DEBUG (printf ("Dictionary: creating new aspell speller\n")); |
|
|
|
if (se->changed) { |
|
if (se->speller) |
|
delete_aspell_speller (se->speller); |
|
err = new_aspell_speller (se->config); |
|
if (aspell_error_number (err) != 0) { |
|
g_warning ("aspell error: %s\n", aspell_error_message (err)); |
|
se->speller = NULL; |
|
raise_error (ev, aspell_error_message (err)); |
|
} else { |
|
se->speller = to_aspell_speller (err); |
|
se->changed = FALSE; |
|
} |
|
} |
|
} |
|
|
|
static void |
|
update_engines (GNOMESpellDictionary *dict, CORBA_Environment * ev) |
|
{ |
|
g_return_if_fail (IS_GNOME_SPELL_DICTIONARY (dict)); |
|
|
|
if (dict->changed) { |
|
GSList *l; |
|
|
|
for (l = dict->engines; l; l = l->next) { |
|
update_engine ((SpellEngine *) l->data, ev); |
|
} | } |
|
|
dict->changed = FALSE; |
|
} | } |
} | } |
| |
|
|
engine_check_word (SpellEngine *se, const gchar *word, CORBA_Environment *ev) | engine_check_word (SpellEngine *se, const gchar *word, CORBA_Environment *ev) |
{ | { |
CORBA_boolean result = CORBA_TRUE; | CORBA_boolean result = CORBA_TRUE; |
gint aspell_result; |
gint enchant_result; |
| |
#ifndef G_DISABLE_CHECKS | #ifndef G_DISABLE_CHECKS |
g_return_val_if_fail (se->speller, CORBA_TRUE); | g_return_val_if_fail (se->speller, CORBA_TRUE); |
|
|
if (!se->speller) | if (!se->speller) |
return CORBA_TRUE; | return CORBA_TRUE; |
#endif | #endif |
aspell_result = aspell_speller_check (se->speller, word, strlen (word)); |
enchant_result = enchant_dict_check (se->speller, word, strlen (word)); |
if (aspell_result == 0) |
if (enchant_result == 0) |
result = CORBA_FALSE; | result = CORBA_FALSE; |
if (aspell_result == -1) { |
if (enchant_result == -1) { |
g_warning ("aspell error: %s\n", aspell_speller_error_message (se->speller)); |
g_warning ("enchant error: %s\n", enchant_dict_get_error (se->speller)); |
raise_error (ev, aspell_speller_error_message (se->speller)); |
raise_error (ev, enchant_dict_get_error (se->speller)); |
} | } |
| |
return result; | return result; |
|
|
if (!strcmp (word, "Ximian")) | if (!strcmp (word, "Ximian")) |
return CORBA_TRUE; | return CORBA_TRUE; |
| |
update_engines (dict, ev); |
|
for (l = dict->engines; l; l = l->next) { | for (l = dict->engines; l; l = l->next) { |
if (((SpellEngine *) l->data)->speller) { | if (((SpellEngine *) l->data)->speller) { |
valid_speller = TRUE; | valid_speller = TRUE; |
|
|
if (!word) | if (!word) |
return; | return; |
#endif | #endif |
update_engines (dict, ev); |
|
DICT_DEBUG (printf ("Dictionary add_word_to_session: %s\n", word)); | DICT_DEBUG (printf ("Dictionary add_word_to_session: %s\n", word)); |
for (l = dict->engines; l; l = l->next) { | for (l = dict->engines; l; l = l->next) { |
if (((SpellEngine *) l->data)->speller) | if (((SpellEngine *) l->data)->speller) |
aspell_speller_add_to_session (((SpellEngine *) l->data)->speller, word, strlen (word)); |
enchant_dict_add_to_session (((SpellEngine *) l->data)->speller, word, strlen (word)); |
} | } |
} | } |
| |
|
|
if (!word || !language) | if (!word || !language) |
return; | return; |
#endif | #endif |
update_engines (dict, ev); |
|
DICT_DEBUG (printf ("Dictionary add_word_to_personal: %s (%s)\n", word, language)); | DICT_DEBUG (printf ("Dictionary add_word_to_personal: %s (%s)\n", word, language)); |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); | se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
| |
|
|
if (!word || !replacement) | if (!word || !replacement) |
return; | return; |
#endif | #endif |
update_engines (dict, ev); |
|
DICT_DEBUG (printf ("Dictionary correction: %s <-- %s\n", word, replacement)); | DICT_DEBUG (printf ("Dictionary correction: %s <-- %s\n", word, replacement)); |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); | se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
| |
|
|
const CORBA_char *word, CORBA_Environment *ev) | const CORBA_char *word, CORBA_Environment *ev) |
{ | { |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (bonobo_object_from_servant (servant)); | GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (bonobo_object_from_servant (servant)); |
const AspellWordList *suggestions; |
char **suggestions; |
AspellStringEnumeration *elements; |
size_t number_of_suggestions; |
GNOME_Spell_StringSeq *seq = NULL; | GNOME_Spell_StringSeq *seq = NULL; |
GSList *l, *suggestion_list = NULL; | GSList *l, *suggestion_list = NULL; |
gint i, len, pos; | gint i, len, pos; |
|
|
return NULL; | return NULL; |
#endif | #endif |
DICT_DEBUG (printf ("Dictionary correction: %s\n", word)); | DICT_DEBUG (printf ("Dictionary correction: %s\n", word)); |
update_engines (dict, ev); |
|
| |
len = 0; | len = 0; |
for (l = dict->engines; l; l = l->next) { | for (l = dict->engines; l; l = l->next) { |
SpellEngine *se = (SpellEngine *) l->data; | SpellEngine *se = (SpellEngine *) l->data; |
| |
if (se->speller) { | if (se->speller) { |
suggestions = aspell_speller_suggest (se->speller, word, strlen (word)); |
suggestions = enchant_dict_suggest (se->speller, word, strlen (word), &number_of_suggestions); |
suggestion_list = g_slist_prepend (suggestion_list, (gpointer) suggestions); |
suggestion_list = g_slist_prepend (suggestion_list, |
len += 2*aspell_word_list_size (suggestions); |
(gpointer) dup_string_list (suggestions, number_of_suggestions)); |
|
len += 2*number_of_suggestions; |
suggestion_list = g_slist_prepend (suggestion_list, engine_to_language (dict, se)); | suggestion_list = g_slist_prepend (suggestion_list, engine_to_language (dict, se)); |
|
suggestion_list = g_slist_prepend (suggestion_list, GINT_TO_POINTER (number_of_suggestions)); |
|
enchant_dict_free_string_list (se->speller, suggestions); |
} | } |
} | } |
| |
|
|
gint list_len; | gint list_len; |
gchar *language; | gchar *language; |
| |
|
list_len = GPOINTER_TO_INT (l->data); |
|
l = l->next; |
language = (gchar *) l->data; | language = (gchar *) l->data; |
l = l->next; | l = l->next; |
suggestions = (const AspellWordList *) l->data; |
suggestions = (char **) l->data; |
elements = aspell_word_list_elements (suggestions); |
|
list_len = aspell_word_list_size (suggestions); |
|
for (i = 0; i < list_len; i ++, pos ++) { | for (i = 0; i < list_len; i ++, pos ++) { |
seq->_buffer [pos] = CORBA_string_dup (aspell_string_enumeration_next (elements)); |
seq->_buffer [pos] = CORBA_string_dup (suggestions [i]); |
pos ++; | pos ++; |
seq->_buffer [pos] = CORBA_string_dup (language); | seq->_buffer [pos] = CORBA_string_dup (language); |
} | } |
delete_aspell_string_enumeration (elements); |
|
|
g_strfreev (suggestions); |
} | } |
CORBA_sequence_set_release (seq, CORBA_TRUE); | CORBA_sequence_set_release (seq, CORBA_TRUE); |
g_slist_free (suggestion_list); | g_slist_free (suggestion_list); |