|
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); |