--- gtkspell2/configure.ac 2004-08-22 17:30:52.000000000 +0100 +++ gtkspell2/configure.ac 2004-10-14 00:29:29.000000000 +0100 @@ -4,18 +4,12 @@ AC_CONFIG_SRCDIR(gtkspell/gtkspell.c) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) AC_CONFIG_HEADERS([config.h]) -AC_CHECK_HEADER(aspell.h, [AC_DEFINE(HAVE_ASPELL_H,1, - [Define to 1 if you have the header file.] )] ) -AC_CHECK_HEADER(pspell/pspell.h, [AC_DEFINE(HAVE_PSPELL_H,1, - [Define to 1 if you have the header file.] )] ) -AC_CHECK_LIB(aspell, new_aspell_speller, SPELLER_LIB="-laspell", - [AC_CHECK_LIB(pspell, new_pspell_manager, SPELLER_LIB="-lpspell", - [AC_MSG_ERROR([You must have the aspell or pspell dev libraries to build gtkspell.]) ] ) ] ) +SPELLER_LIB=-lenchant AC_SUBST(SPELLER_LIB) GTKSPELL_PACKAGES=gtk+-2.0 AC_SUBST(GTKSPELL_PACKAGES) -PKG_CHECK_MODULES(GTKSPELL, $GTKSPELL_PACKAGES) +PKG_CHECK_MODULES(GTKSPELL, $GTKSPELL_PACKAGES enchant >= 0.4.0) AC_SUBST(GTKSPELL_CFLAGS) AC_SUBST(GTKSPELL_LIBS) --- gtkspell2/gtkspell/deprecated.c 2002-12-12 05:18:49.000000000 +0000 +++ gtkspell2/gtkspell/deprecated.c 2004-08-27 03:26:38.000000000 +0100 @@ -1,5 +1,22 @@ -/* gtkspell - a spell-checking addon for GTK's TextView widget +/* gtkspell * Copyright (c) 2002 Evan Martin. + * Copyright (c) 2004 Nathan Fredrickson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * */ /* vim: set ts=4 sw=4 wm=5 : */ --- gtkspell2/gtkspell/gtkspell.c 2004-08-16 19:59:31.000000000 +0100 +++ gtkspell2/gtkspell/gtkspell.c 2004-08-27 03:26:38.000000000 +0100 @@ -1,5 +1,22 @@ -/* gtkspell - a spell-checking addon for GTK's TextView widget +/* gtkspell * Copyright (c) 2002 Evan Martin. + * Copyright (c) 2004 Nathan Fredrickson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * */ /* vim: set ts=4 sw=4 wm=5 : */ @@ -7,42 +24,12 @@ #include #include #include +#include #include "../config.h" #include "gtkspell.h" -#define _(String) dgettext (PACKAGE, String) - -#ifdef HAVE_ASPELL_H - #define USING_ASPELL - #include -#elif defined HAVE_PSPELL_H - #define USING_PSPELL - #include - #define AspellSpeller PspellManager - #define speller manager - #define aspell_speller_check pspell_manager_check - #define aspell_speller_add_to_session pspell_manager_add_to_session - #define aspell_speller_add_to_personal pspell_manager_add_to_personal - #define aspell_speller_save_all_word_lists pspell_manager_save_all_word_lists - #define aspell_speller_store_replacement pspell_manager_store_replacement - #define AspellWordList PspellWordList - #define AspellStringEnumeration PspellStringEmulation - #define aspell_speller_suggest pspell_manager_suggest - #define aspell_word_list_elements pspell_word_list_elements - #define aspell_string_enumeration_next pspell_string_emulation_next - #define delete_aspell_string_enumeration delete_pspell_string_emulation - #define AspellConfig PspellConfig - #define AspellCanHaveError PspellCanHaveError - #define new_aspell_config new_pspell_config - #define aspell_config_replace pspell_config_replace - #define new_aspell_speller new_pspell_manager - #define delete_aspell_config delete_pspell_config - #define aspell_error_message pspell_error_message - #define delete_aspell_speller delete_pspell_manager - #define to_aspell_speller to_pspell_manager - #define aspell_error_number pspell_error_number - #define aspell pspell -#endif +#define _(String) dgettext(PACKAGE, String) +#define N_(String) (String) const int debug = 0; const int quiet = 0; @@ -53,8 +40,10 @@ struct _GtkSpell { GtkTextMark *mark_insert_start; GtkTextMark *mark_insert_end; gboolean deferred_check; - AspellSpeller *speller; + EnchantBroker *broker; + EnchantDict *speller; GtkTextMark *mark_click; + gchar *lang; }; static void gtkspell_free(GtkSpell *spell); @@ -122,10 +111,14 @@ static void check_word(GtkSpell *spell, GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end) { char *text; + + if (!spell->speller) + return; + text = gtk_text_buffer_get_text(buffer, start, end, FALSE); if (debug) g_print("checking: %s\n", text); if (g_unichar_isdigit(*text) == FALSE) /* don't check numbers */ - if (aspell_speller_check(spell->speller, text, -1) == FALSE) + if (enchant_dict_check(spell->speller, text, strlen(text)) != 0) gtk_text_buffer_apply_tag(buffer, spell->tag_highlight, start, end); g_free(text); } @@ -295,13 +288,15 @@ add_to_dictionary(GtkWidget *menuitem, G GtkTextIter start, end; GtkTextBuffer *buffer; + if (!spell->speller) + return; + buffer = gtk_text_view_get_buffer(spell->view); get_word_extents_from_mark(buffer, &start, &end, spell->mark_click); word = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); - - aspell_speller_add_to_personal(spell->speller, word, strlen(word)); - aspell_speller_save_all_word_lists(spell->speller); + + enchant_dict_add_to_personal(spell->speller, word, strlen(word)); gtkspell_recheck_all(spell); @@ -319,7 +314,7 @@ ignore_all(GtkWidget *menuitem, GtkSpell get_word_extents_from_mark(buffer, &start, &end, spell->mark_click); word = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); - aspell_speller_add_to_session(spell->speller, word, strlen(word)); + enchant_dict_add_to_session(spell->speller, word, strlen(word)); gtkspell_recheck_all(spell); @@ -332,6 +327,9 @@ replace_word(GtkWidget *menuitem, GtkSpe const char *newword; GtkTextIter start, end; GtkTextBuffer *buffer; + + if (!spell->speller) + return; buffer = gtk_text_view_get_buffer(spell->view); @@ -348,33 +346,126 @@ replace_word(GtkWidget *menuitem, GtkSpe gtk_text_buffer_delete(buffer, &start, &end); gtk_text_buffer_insert(buffer, &start, newword, -1); - aspell_speller_store_replacement(spell->speller, - oldword, strlen(oldword), - newword, strlen(newword)); + enchant_dict_store_replacement(spell->speller, + oldword, strlen(oldword), + newword, strlen(newword)); g_free(oldword); } -GtkWidget* +#define KNOWN_LANGUAGES 39 +static gchar *known_languages [KNOWN_LANGUAGES * 2 + 1] = { + "br", N_("Breton"), + "ca", N_("Catalan"), + "cs", N_("Czech"), + "da", N_("Danish"), + "de-DE", N_("German (Germany)"), + "de-AT", N_("German (Austria)"), + "de-CH", N_("German (Swiss)"), + "el", N_("Greek"), + "en", N_("English"), + "en-US", N_("English (American)"), + "en-GB", N_("English (British)"), + "en-CA", N_("English (Canadian)"), + "eo", N_("Esperanto"), + "es", N_("Spanish"), + "fi", N_("Finnish"), + "fo", N_("Faroese"), + "fr-FR", N_("French (France)"), + "fr-CH", N_("French (Swiss)"), + "hu", N_("Hungarian"), + "ga", N_("Irish"), + "gl", N_("Galician"), + "he", N_("Hebrew"), + "it", N_("Italian"), + "la", N_("Latin"), + "lt", N_("Lithuanian"), + "nb-NO", N_("Norwegian (Bokmal)"), + "nl", N_("Dutch"), + "nn-NO", N_("Norwegian (Nyorsk)"), + "no", N_("Norwegian"), + "pl", N_("Polish"), + "pt-PT", N_("Portuguese (Portugal)"), + "pt-BR", N_("Portuguese (Brazilian)"), + "ru", N_("Russian"), + "sc", N_("Sardinian"), + "sk", N_("Slovak"), + "sl", N_("Slovenian"), + "sv", N_("Swedish"), + "uk", N_("Ukrainian"), + "yi", N_("Yiddish"), + NULL +}; + +static void +dict_describe (const char * const lang_tag, + const char * const provider_name, + const char * const provider_desc, + const char * const provider_file, + void * user_data) { + printf("%s | %s | %s | %s\n", lang_tag, provider_name, provider_desc, provider_file); +} + +/* replace any 1 hyphen with an underscore. converts en-US to en_US */ +static gchar * +normalize_language (const gchar *language) { + gchar *dup, *hyphen; + + dup = g_strdup(language); + hyphen = strchr(dup, '-'); + if (hyphen) + *hyphen = '_'; + return dup; +} + +static GSList * +get_languages (GtkSpell *spell) { + EnchantBroker *broker = spell->broker; + gchar * lang; + + GSList *langs; + gint i; + + langs = NULL; + + for (i=0; known_languages[i]; i++) { + lang = normalize_language(known_languages [i]); + i++; + + if (enchant_broker_dict_exists(spell->broker, lang)) { + /* + enchant_dict_describe(spell->speller, dict_describe, NULL); + printf("Language: %s (%s)\n", known_languages[i], lang); + */ + langs = g_slist_append(langs, GINT_TO_POINTER(i - 1)); + } + + g_free(lang); + } + + return langs; +} + +static GtkWidget* build_suggestion_menu(GtkSpell *spell, GtkTextBuffer *buffer, const char *word) { const char *suggestion; GtkWidget *topmenu, *menu; GtkWidget *mi; GtkWidget *hbox; - int count = 0; void *spelldata; - const AspellWordList *suggestions; - AspellStringEnumeration *elements; + char ** suggestions; + size_t n_suggs, i; char *label; topmenu = menu = gtk_menu_new(); - suggestions = aspell_speller_suggest(spell->speller, word, -1); - elements = aspell_word_list_elements(suggestions); + if (!spell->speller) + return topmenu; - suggestion = aspell_string_enumeration_next(elements); - if (suggestion == NULL) { + suggestions = enchant_dict_suggest(spell->speller, word, strlen(word), &n_suggs); + + if (suggestions == NULL || !n_suggs) { /* no suggestions. put something in the menu anyway... */ GtkWidget *label; label = gtk_label_new(""); @@ -386,8 +477,8 @@ build_suggestion_menu(GtkSpell *spell, G gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), mi); } else { /* build a set of menus with suggestions. */ - while (suggestion != NULL) { - if (count == 10) { + for (i = 0; i < n_suggs; i++) { + if (i != 0 && i % 10 == 0) { mi = gtk_menu_item_new(); gtk_widget_show(mi); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); @@ -398,20 +489,16 @@ build_suggestion_menu(GtkSpell *spell, G menu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), menu); - count = 0; } - mi = gtk_menu_item_new_with_label(suggestion); + + mi = gtk_menu_item_new_with_label(suggestions[i]); g_signal_connect(G_OBJECT(mi), "activate", - G_CALLBACK(replace_word), spell); + G_CALLBACK(replace_word), spell); gtk_widget_show(mi); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); - count++; - suggestion = aspell_string_enumeration_next(elements); } } - delete_aspell_string_enumeration(elements); - /* Separator */ mi = gtk_menu_item_new(); gtk_widget_show(mi); @@ -437,6 +524,8 @@ build_suggestion_menu(GtkSpell *spell, G gtk_widget_show_all(mi); gtk_menu_shell_append(GTK_MENU_SHELL(topmenu), mi); + enchant_dict_free_suggestions(spell->speller, suggestions); + return topmenu; } @@ -515,9 +604,6 @@ popup_menu_event(GtkTextView *view, GtkS static gboolean gtkspell_set_language_internal(GtkSpell *spell, const gchar *lang, GError **error) { - AspellConfig *config; - AspellCanHaveError *err; - AspellSpeller *speller; if (lang == NULL) { lang = g_getenv("LANG"); @@ -529,26 +615,28 @@ gtkspell_set_language_internal(GtkSpell } } - config = new_aspell_config(); - if (lang) - aspell_config_replace(config, "language-tag", lang); - aspell_config_replace(config, "encoding", "utf-8"); - err = new_aspell_speller(config); - delete_aspell_config(config); + if (!spell->broker) + spell->broker = enchant_broker_init(); - if (aspell_error_number(err) != 0) { -#ifdef USING_ASPELL - g_set_error(error, GTKSPELL_ERROR, GTKSPELL_ERROR_BACKEND, - "aspell: %s", aspell_error_message(err)); -#elif defined USING_PSPELL + if (spell->speller) { + enchant_broker_free_dict(spell->broker, spell->speller); + spell->speller = NULL; + } + + if (!lang) + lang = "en"; + + spell->speller = enchant_broker_request_dict (spell->broker, lang); + if (!spell->speller) { g_set_error(error, GTKSPELL_ERROR, GTKSPELL_ERROR_BACKEND, - "pspell: %s", aspell_error_message(err)); -#endif + _("enchant error for language: %s"), lang); return FALSE; - } - if (spell->speller) - delete_aspell_speller(spell->speller); - spell->speller = to_aspell_speller(err); + } + + if (spell->lang) + g_free(spell->lang); + + spell->lang = g_strdup(lang); return TRUE; } @@ -705,8 +793,17 @@ gtkspell_free(GtkSpell *spell) { gtk_text_buffer_delete_mark(buffer, spell->mark_insert_end); gtk_text_buffer_delete_mark(buffer, spell->mark_click); - delete_aspell_speller(spell->speller); + if (spell->broker) { + if (spell->speller) + enchant_broker_free_dict (spell->broker, spell->speller); + + enchant_broker_free (spell->broker); + } + if (spell->lang) { + g_free(spell->lang); + } + g_signal_handlers_disconnect_matched(spell->view, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, --- gtkspell2/gtkspell/gtkspell.h 2002-12-12 05:18:49.000000000 +0000 +++ gtkspell2/gtkspell/gtkspell.h 2004-08-27 03:26:38.000000000 +0100 @@ -1,5 +1,22 @@ -/* gtkspell - a spell-checking addon for GTK's TextView widget +/* gtkspell * Copyright (c) 2002 Evan Martin. + * Copyright (c) 2004 Nathan Fredrickson. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * */ /* vim: set ts=4 sw=4 wm=5 : */