Lines 36-41
Link Here
|
36 |
#include "Spell.h" |
36 |
#include "Spell.h" |
37 |
#include "dictionary.h" |
37 |
#include "dictionary.h" |
38 |
|
38 |
|
|
|
39 |
#include <enchant.h> |
40 |
|
41 |
typedef struct { |
42 |
EnchantBroker * config; |
43 |
EnchantDict * speller; |
44 |
} SpellEngine; |
45 |
|
39 |
static BonoboObjectClass *dictionary_parent_class; |
46 |
static BonoboObjectClass *dictionary_parent_class; |
40 |
|
47 |
|
41 |
#define DICT_DEBUG(x) |
48 |
#define DICT_DEBUG(x) |
Lines 72-83
Link Here
|
72 |
{ |
79 |
{ |
73 |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (object); |
80 |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (object); |
74 |
|
81 |
|
75 |
dict->changed = TRUE; |
|
|
76 |
dict->engines = NULL; |
82 |
dict->engines = NULL; |
77 |
dict->languages = g_hash_table_new (g_str_hash, g_str_equal); |
83 |
dict->languages = g_hash_table_new (g_str_hash, g_str_equal); |
78 |
dict->engines_ht = g_hash_table_new (NULL, NULL); |
84 |
dict->engines_ht = g_hash_table_new (NULL, NULL); |
79 |
} |
85 |
} |
80 |
|
86 |
|
|
|
87 |
static char ** |
88 |
dup_string_list (char ** str_list, size_t list_len) |
89 |
{ |
90 |
char ** new_str_list; |
91 |
size_t i; |
92 |
|
93 |
new_str_list = g_new0 (char *, list_len + 1); |
94 |
for (i = 0; i < list_len; i++) |
95 |
new_str_list [i] = g_strdup (str_list [i]); |
96 |
|
97 |
return new_str_list; |
98 |
} |
99 |
|
81 |
static void |
100 |
static void |
82 |
dictionary_finalize (GObject *object) |
101 |
dictionary_finalize (GObject *object) |
83 |
{ |
102 |
{ |
Lines 93-107
Link Here
|
93 |
} |
112 |
} |
94 |
|
113 |
|
95 |
static SpellEngine * |
114 |
static SpellEngine * |
96 |
new_engine (const gchar *language) |
115 |
new_engine (const gchar *language, CORBA_Environment *ev) |
97 |
{ |
116 |
{ |
98 |
SpellEngine *se; |
117 |
SpellEngine *se; |
99 |
|
118 |
|
100 |
se = g_new0 (SpellEngine, 1); |
119 |
se = g_new0 (SpellEngine, 1); |
101 |
se->config = new_aspell_config (); |
120 |
se->config = enchant_broker_init (); |
102 |
aspell_config_replace (se->config, "language-tag", language); |
121 |
se->speller = enchant_broker_request_dict (se->config, language); |
103 |
aspell_config_replace (se->config, "encoding", "utf-8"); |
122 |
|
104 |
se->changed = TRUE; |
123 |
if(se->speller == NULL) |
|
|
124 |
raise_error (ev, enchant_broker_get_error (se->config)); |
105 |
|
125 |
|
106 |
return se; |
126 |
return se; |
107 |
} |
127 |
} |
Lines 129-137
Link Here
|
129 |
SpellEngine *se = dict->engines->data; |
149 |
SpellEngine *se = dict->engines->data; |
130 |
|
150 |
|
131 |
if (se->speller) |
151 |
if (se->speller) |
132 |
delete_aspell_speller (se->speller); |
152 |
enchant_broker_free_dict (se->config, se->speller); |
133 |
if (se->config) |
153 |
if (se->config) |
134 |
delete_aspell_config (se->config); |
154 |
enchant_broker_free (se->config); |
135 |
g_free (se); |
155 |
g_free (se); |
136 |
dict->engines = g_slist_remove (dict->engines, se); |
156 |
dict->engines = g_slist_remove (dict->engines, se); |
137 |
} |
157 |
} |
Lines 140-146
Link Here
|
140 |
g_hash_table_foreach_remove (dict->languages, remove_engine_ht, NULL); |
160 |
g_hash_table_foreach_remove (dict->languages, remove_engine_ht, NULL); |
141 |
|
161 |
|
142 |
dict->engines = NULL; |
162 |
dict->engines = NULL; |
143 |
dict->changed = TRUE; |
|
|
144 |
} |
163 |
} |
145 |
|
164 |
|
146 |
static LangInfo known_languages [] = { |
165 |
static LangInfo known_languages [] = { |
Lines 355-382
Link Here
|
355 |
get_languages_real (gint *ln) |
374 |
get_languages_real (gint *ln) |
356 |
{ |
375 |
{ |
357 |
GSList *langs; |
376 |
GSList *langs; |
358 |
AspellCanHaveError *err; |
377 |
EnchantBroker *broker; |
359 |
AspellConfig *config; |
|
|
360 |
AspellSpeller *speller; |
361 |
gint i; |
378 |
gint i; |
362 |
|
379 |
|
363 |
DICT_DEBUG (printf ("get_languages_real\n")); |
380 |
DICT_DEBUG (printf ("get_languages_real\n")); |
364 |
|
381 |
|
|
|
382 |
/* todo: this could probably be better done by enchant_broker_list_dicts(), but let's keep |
383 |
the initial code change to a minimum */ |
384 |
|
385 |
broker = enchant_broker_init (); |
365 |
langs = NULL; |
386 |
langs = NULL; |
366 |
*ln = 0; |
387 |
*ln = 0; |
367 |
for (i=0; i < G_N_ELEMENTS (known_languages); i++) { |
388 |
for (i=0; i < G_N_ELEMENTS (known_languages); i++) { |
368 |
config = new_aspell_config (); |
389 |
if (enchant_broker_dict_exists (broker, known_languages [i].abbreviation)) { |
369 |
aspell_config_replace (config, "language-tag", known_languages [i].abbreviation); |
|
|
370 |
err = new_aspell_speller (config); |
371 |
if (aspell_error_number (err) == 0) { |
372 |
speller = to_aspell_speller (err); |
373 |
DICT_DEBUG (printf ("Language: %s\n", known_languages [i].name)); |
390 |
DICT_DEBUG (printf ("Language: %s\n", known_languages [i].name)); |
374 |
delete_aspell_speller (speller); |
|
|
375 |
langs = g_slist_prepend (langs, GINT_TO_POINTER (i)); |
391 |
langs = g_slist_prepend (langs, GINT_TO_POINTER (i)); |
376 |
(*ln) ++; |
392 |
(*ln) ++; |
377 |
} |
393 |
} |
378 |
} |
394 |
} |
379 |
|
395 |
|
|
|
396 |
enchant_broker_free (broker); |
397 |
|
380 |
return langs; |
398 |
return langs; |
381 |
} |
399 |
} |
382 |
|
400 |
|
Lines 405-420
Link Here
|
405 |
{ |
423 |
{ |
406 |
GSList *langs, *l; |
424 |
GSList *langs, *l; |
407 |
GConfClient *gc; |
425 |
GConfClient *gc; |
408 |
time_t mtime; |
|
|
409 |
struct stat buf; |
410 |
gint i, kl; |
426 |
gint i, kl; |
411 |
|
427 |
|
412 |
gc = gconf_client_get_default (); |
428 |
gc = gconf_client_get_default (); |
413 |
|
429 |
|
414 |
mtime = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/mtime", NULL); |
|
|
415 |
kl = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", NULL); |
430 |
kl = gconf_client_get_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", NULL); |
416 |
|
431 |
|
417 |
if (stat (ASPELL_DICT, &buf) || buf.st_mtime != mtime || kl != G_N_ELEMENTS(known_languages)) { |
432 |
if (kl != G_N_ELEMENTS(known_languages)) { |
418 |
GString *str; |
433 |
GString *str; |
419 |
langs = get_languages_real (ln); |
434 |
langs = get_languages_real (ln); |
420 |
|
435 |
|
Lines 425-431
Link Here
|
425 |
gconf_client_set_int (gc, str->str, GPOINTER_TO_INT (l->data), NULL); |
440 |
gconf_client_set_int (gc, str->str, GPOINTER_TO_INT (l->data), NULL); |
426 |
l = l->next; |
441 |
l = l->next; |
427 |
} |
442 |
} |
428 |
gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/mtime", buf.st_mtime, NULL); |
443 |
|
429 |
gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", G_N_ELEMENTS(known_languages), NULL); |
444 |
gconf_client_set_int (gc, GNOME_SPELL_GCONF_DIR "/known_languages", G_N_ELEMENTS(known_languages), NULL); |
430 |
g_string_free (str, TRUE); |
445 |
g_string_free (str, TRUE); |
431 |
gnome_config_sync (); |
446 |
gnome_config_sync (); |
Lines 504-554
Link Here
|
504 |
SpellEngine *se; |
519 |
SpellEngine *se; |
505 |
|
520 |
|
506 |
one_language = g_strndup (begin, len); |
521 |
one_language = g_strndup (begin, len); |
507 |
se = new_engine (one_language); |
522 |
se = new_engine (one_language, ev); |
508 |
dict->engines = g_slist_prepend (dict->engines, se); |
523 |
dict->engines = g_slist_prepend (dict->engines, se); |
509 |
g_hash_table_insert (dict->languages, one_language, se); |
524 |
g_hash_table_insert (dict->languages, one_language, se); |
510 |
g_hash_table_insert (dict->engines_ht, se, g_strdup (one_language)); |
525 |
g_hash_table_insert (dict->engines_ht, se, g_strdup (one_language)); |
511 |
|
|
|
512 |
dict->changed = TRUE; |
513 |
} |
514 |
} |
515 |
} |
516 |
|
517 |
static void |
518 |
update_engine (SpellEngine *se, CORBA_Environment * ev) |
519 |
{ |
520 |
AspellCanHaveError *err; |
521 |
|
522 |
DICT_DEBUG (printf ("Dictionary: creating new aspell speller\n")); |
523 |
|
524 |
if (se->changed) { |
525 |
if (se->speller) |
526 |
delete_aspell_speller (se->speller); |
527 |
err = new_aspell_speller (se->config); |
528 |
if (aspell_error_number (err) != 0) { |
529 |
g_warning ("aspell error: %s\n", aspell_error_message (err)); |
530 |
se->speller = NULL; |
531 |
raise_error (ev, aspell_error_message (err)); |
532 |
} else { |
533 |
se->speller = to_aspell_speller (err); |
534 |
se->changed = FALSE; |
535 |
} |
536 |
} |
537 |
} |
538 |
|
539 |
static void |
540 |
update_engines (GNOMESpellDictionary *dict, CORBA_Environment * ev) |
541 |
{ |
542 |
g_return_if_fail (IS_GNOME_SPELL_DICTIONARY (dict)); |
543 |
|
544 |
if (dict->changed) { |
545 |
GSList *l; |
546 |
|
547 |
for (l = dict->engines; l; l = l->next) { |
548 |
update_engine ((SpellEngine *) l->data, ev); |
549 |
} |
526 |
} |
550 |
|
|
|
551 |
dict->changed = FALSE; |
552 |
} |
527 |
} |
553 |
} |
528 |
} |
554 |
|
529 |
|
Lines 556-562
Link Here
|
556 |
engine_check_word (SpellEngine *se, const gchar *word, CORBA_Environment *ev) |
531 |
engine_check_word (SpellEngine *se, const gchar *word, CORBA_Environment *ev) |
557 |
{ |
532 |
{ |
558 |
CORBA_boolean result = CORBA_TRUE; |
533 |
CORBA_boolean result = CORBA_TRUE; |
559 |
gint aspell_result; |
534 |
gint enchant_result; |
560 |
|
535 |
|
561 |
#ifndef G_DISABLE_CHECKS |
536 |
#ifndef G_DISABLE_CHECKS |
562 |
g_return_val_if_fail (se->speller, CORBA_TRUE); |
537 |
g_return_val_if_fail (se->speller, CORBA_TRUE); |
Lines 564-575
Link Here
|
564 |
if (!se->speller) |
539 |
if (!se->speller) |
565 |
return CORBA_TRUE; |
540 |
return CORBA_TRUE; |
566 |
#endif |
541 |
#endif |
567 |
aspell_result = aspell_speller_check (se->speller, word, strlen (word)); |
542 |
enchant_result = enchant_dict_check (se->speller, word, strlen (word)); |
568 |
if (aspell_result == 0) |
543 |
if (enchant_result == 0) |
569 |
result = CORBA_FALSE; |
544 |
result = CORBA_FALSE; |
570 |
if (aspell_result == -1) { |
545 |
if (enchant_result == -1) { |
571 |
g_warning ("aspell error: %s\n", aspell_speller_error_message (se->speller)); |
546 |
g_warning ("enchant error: %s\n", enchant_dict_get_error (se->speller)); |
572 |
raise_error (ev, aspell_speller_error_message (se->speller)); |
547 |
raise_error (ev, enchant_dict_get_error (se->speller)); |
573 |
} |
548 |
} |
574 |
|
549 |
|
575 |
return result; |
550 |
return result; |
Lines 592-598
Link Here
|
592 |
if (!strcmp (word, "Ximian")) |
567 |
if (!strcmp (word, "Ximian")) |
593 |
return CORBA_TRUE; |
568 |
return CORBA_TRUE; |
594 |
|
569 |
|
595 |
update_engines (dict, ev); |
|
|
596 |
for (l = dict->engines; l; l = l->next) { |
570 |
for (l = dict->engines; l; l = l->next) { |
597 |
if (((SpellEngine *) l->data)->speller) { |
571 |
if (((SpellEngine *) l->data)->speller) { |
598 |
valid_speller = TRUE; |
572 |
valid_speller = TRUE; |
Lines 621-631
Link Here
|
621 |
if (!word) |
595 |
if (!word) |
622 |
return; |
596 |
return; |
623 |
#endif |
597 |
#endif |
624 |
update_engines (dict, ev); |
|
|
625 |
DICT_DEBUG (printf ("Dictionary add_word_to_session: %s\n", word)); |
598 |
DICT_DEBUG (printf ("Dictionary add_word_to_session: %s\n", word)); |
626 |
for (l = dict->engines; l; l = l->next) { |
599 |
for (l = dict->engines; l; l = l->next) { |
627 |
if (((SpellEngine *) l->data)->speller) |
600 |
if (((SpellEngine *) l->data)->speller) |
628 |
aspell_speller_add_to_session (((SpellEngine *) l->data)->speller, word, strlen (word)); |
601 |
enchant_dict_add_to_session (((SpellEngine *) l->data)->speller, word, strlen (word)); |
629 |
} |
602 |
} |
630 |
} |
603 |
} |
631 |
|
604 |
|
Lines 642-648
Link Here
|
642 |
if (!word || !language) |
615 |
if (!word || !language) |
643 |
return; |
616 |
return; |
644 |
#endif |
617 |
#endif |
645 |
update_engines (dict, ev); |
|
|
646 |
DICT_DEBUG (printf ("Dictionary add_word_to_personal: %s (%s)\n", word, language)); |
618 |
DICT_DEBUG (printf ("Dictionary add_word_to_personal: %s (%s)\n", word, language)); |
647 |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
619 |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
648 |
|
620 |
|
Lines 666-672
Link Here
|
666 |
if (!word || !replacement) |
638 |
if (!word || !replacement) |
667 |
return; |
639 |
return; |
668 |
#endif |
640 |
#endif |
669 |
update_engines (dict, ev); |
|
|
670 |
DICT_DEBUG (printf ("Dictionary correction: %s <-- %s\n", word, replacement)); |
641 |
DICT_DEBUG (printf ("Dictionary correction: %s <-- %s\n", word, replacement)); |
671 |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
642 |
se = (SpellEngine *) g_hash_table_lookup (dict->languages, language); |
672 |
|
643 |
|
Lines 683-690
Link Here
|
683 |
const CORBA_char *word, CORBA_Environment *ev) |
654 |
const CORBA_char *word, CORBA_Environment *ev) |
684 |
{ |
655 |
{ |
685 |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (bonobo_object_from_servant (servant)); |
656 |
GNOMESpellDictionary *dict = GNOME_SPELL_DICTIONARY (bonobo_object_from_servant (servant)); |
686 |
const AspellWordList *suggestions; |
657 |
char **suggestions; |
687 |
AspellStringEnumeration *elements; |
658 |
size_t number_of_suggestions; |
688 |
GNOME_Spell_StringSeq *seq = NULL; |
659 |
GNOME_Spell_StringSeq *seq = NULL; |
689 |
GSList *l, *suggestion_list = NULL; |
660 |
GSList *l, *suggestion_list = NULL; |
690 |
gint i, len, pos; |
661 |
gint i, len, pos; |
Lines 696-712
Link Here
|
696 |
return NULL; |
667 |
return NULL; |
697 |
#endif |
668 |
#endif |
698 |
DICT_DEBUG (printf ("Dictionary correction: %s\n", word)); |
669 |
DICT_DEBUG (printf ("Dictionary correction: %s\n", word)); |
699 |
update_engines (dict, ev); |
|
|
700 |
|
670 |
|
701 |
len = 0; |
671 |
len = 0; |
702 |
for (l = dict->engines; l; l = l->next) { |
672 |
for (l = dict->engines; l; l = l->next) { |
703 |
SpellEngine *se = (SpellEngine *) l->data; |
673 |
SpellEngine *se = (SpellEngine *) l->data; |
704 |
|
674 |
|
705 |
if (se->speller) { |
675 |
if (se->speller) { |
706 |
suggestions = aspell_speller_suggest (se->speller, word, strlen (word)); |
676 |
suggestions = enchant_dict_suggest (se->speller, word, strlen (word), &number_of_suggestions); |
707 |
suggestion_list = g_slist_prepend (suggestion_list, (gpointer) suggestions); |
677 |
suggestion_list = g_slist_prepend (suggestion_list, |
708 |
len += 2*aspell_word_list_size (suggestions); |
678 |
(gpointer) dup_string_list (suggestions, number_of_suggestions)); |
|
|
679 |
len += 2*number_of_suggestions; |
709 |
suggestion_list = g_slist_prepend (suggestion_list, engine_to_language (dict, se)); |
680 |
suggestion_list = g_slist_prepend (suggestion_list, engine_to_language (dict, se)); |
|
|
681 |
suggestion_list = g_slist_prepend (suggestion_list, GINT_TO_POINTER (number_of_suggestions)); |
682 |
enchant_dict_free_string_list (se->speller, suggestions); |
710 |
} |
683 |
} |
711 |
} |
684 |
} |
712 |
|
685 |
|
Lines 723-739
Link Here
|
723 |
gint list_len; |
696 |
gint list_len; |
724 |
gchar *language; |
697 |
gchar *language; |
725 |
|
698 |
|
|
|
699 |
list_len = GPOINTER_TO_INT (l->data); |
700 |
l = l->next; |
726 |
language = (gchar *) l->data; |
701 |
language = (gchar *) l->data; |
727 |
l = l->next; |
702 |
l = l->next; |
728 |
suggestions = (const AspellWordList *) l->data; |
703 |
suggestions = (char **) l->data; |
729 |
elements = aspell_word_list_elements (suggestions); |
|
|
730 |
list_len = aspell_word_list_size (suggestions); |
731 |
for (i = 0; i < list_len; i ++, pos ++) { |
704 |
for (i = 0; i < list_len; i ++, pos ++) { |
732 |
seq->_buffer [pos] = CORBA_string_dup (aspell_string_enumeration_next (elements)); |
705 |
seq->_buffer [pos] = CORBA_string_dup (suggestions [i]); |
733 |
pos ++; |
706 |
pos ++; |
734 |
seq->_buffer [pos] = CORBA_string_dup (language); |
707 |
seq->_buffer [pos] = CORBA_string_dup (language); |
735 |
} |
708 |
} |
736 |
delete_aspell_string_enumeration (elements); |
709 |
|
|
|
710 |
g_strfreev (suggestions); |
737 |
} |
711 |
} |
738 |
CORBA_sequence_set_release (seq, CORBA_TRUE); |
712 |
CORBA_sequence_set_release (seq, CORBA_TRUE); |
739 |
g_slist_free (suggestion_list); |
713 |
g_slist_free (suggestion_list); |