Revision: 74 http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=74&view=rev Author: eht16 Date: 2008-06-19 14:34:52 -0700 (Thu, 19 Jun 2008)
Log Message: ----------- Use enchant as spell check engine instead of Aspell. Highlight only misspelled instead of whole the line. Add Tools->Spellcheck sub menu to easily change the language to use for spell checking. Add "check as you type" feature. Change doc pointer usage. Update Readme.
Modified Paths: -------------- trunk/spellcheck/ChangeLog trunk/spellcheck/README trunk/spellcheck/configure.in trunk/spellcheck/src/Makefile.am trunk/spellcheck/src/spellcheck.c
Modified: trunk/spellcheck/ChangeLog =================================================================== --- trunk/spellcheck/ChangeLog 2008-06-19 21:20:36 UTC (rev 73) +++ trunk/spellcheck/ChangeLog 2008-06-19 21:34:52 UTC (rev 74) @@ -1,3 +1,15 @@ +2008-06-19 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + + * README, configure.in, src/Makefile.am, src/spellcheck.c: + Use enchant as spell check engine instead of Aspell. + Highlight only misspelled instead of whole the line. + Add Tools->Spellcheck sub menu to easily change the language + to use for spell checking. + Add "check as you type" feature. + Change doc pointer usage. + Update Readme. + + 2008-06-03 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/spellcheck.c:
Modified: trunk/spellcheck/README =================================================================== --- trunk/spellcheck/README 2008-06-19 21:20:36 UTC (rev 73) +++ trunk/spellcheck/README 2008-06-19 21:34:52 UTC (rev 74) @@ -1,34 +1,63 @@ Spell Check Plugin ------------------- +==================
+.. contents::
+ About ----- This plugin checks the content of the current document in Geany with the spell -check program Aspell. You can also select a certain text passage, then the +check library Enchant. You can also select a certain text passage, then the plugin will only check the selected text. All lines with misspelled words are highlighted with a red squiggly underline and the wrong words are printed in the messages window at the bottom of Geany together with available -suggestions. For the plugin to work at all, you need to have the Aspell -library installed together with at least one dictionary. +suggestions. For the plugin to work at all, you need to have the Enchant +library installed together with at least one backend (Aspell, Myspell, +Hunspell, ...). The plugin's configure dialog lists all available languages/dictionaries which can be used for the spell check.
+Downloads +--------- + +Spellcheck 0.1 +^^^^^^^^^^^^^^ + +http://geany-plugins.sourceforge.net/spellcheck/spellcheck-0.1.tar.bz2 + +http://geany-plugins.sourceforge.net/spellcheck/spellcheck-0.1.tar.bz2.sig (GPG-Signature) + +or + +http://geany-plugins.sourceforge.net/spellcheck/spellcheck-0.1.tar.gz + +http://geany-plugins.sourceforge.net/spellcheck/spellcheck-0.1.tar.gz.sig (GPG-Signature) + + +Development Code +^^^^^^^^^^^^^^^^ + +Get the code from: + + svn checkout http://geany-plugins.svn.sourceforge.net/svnroot/geany-plugins/trunk/spellch... + + Requirements ------------ For compiling the plugin yourself, you will need the GTK (>= 2.6.0) libraries and header files. You will also need its dependency libraries and header files, such as Pango, Glib and ATK. All these files are available at http://www.gtk.org. -Furthermore, you need to have installed libaspell with its development files. +Furthermore, you need to have installed enchant with its development files +(libenchant-dev or enchant-devel).
And obviously, you will need have Geany installed. If you have Geany installed from the sources, you should be ready to go. If you used a preprared package e.g. from your distribution you probably need to install an additional package, this might be called geany-dev or geany-devel. Please note that in order to compile and use this plugin, you need a current SVN -version of Geany, at least SVN >= r2590. +version of Geany, at least SVN >= 2715.
Furthermore you need, of course, a C compiler and the Make tool. The GNU versions of these tools are recommended. @@ -68,3 +97,4 @@ Ideas, questions, patches and bug reports ----------------------------------------- Send it to me at enrico(dot)troeger(at)uvena(dot)de +or report them at http://sourceforge.net/tracker/?group_id=222729.
Modified: trunk/spellcheck/configure.in =================================================================== --- trunk/spellcheck/configure.in 2008-06-19 21:20:36 UTC (rev 73) +++ trunk/spellcheck/configure.in 2008-06-19 21:34:52 UTC (rev 74) @@ -16,20 +16,18 @@
# checking for Geany PKG_CHECK_MODULES(GEANY, [geany >= 0.15]) -AC_SUBST(GTK_CFLAGS) -AC_SUBST(GTK_LIBS) +AC_SUBST(GEANY_CFLAGS) +AC_SUBST(GEANY_LIBS)
+# checking for libenchant +PKG_CHECK_MODULES(ENCHANT, [enchant >= 1.3]) +AC_SUBST(ENCHANT_CFLAGS) +AC_SUBST(ENCHANT_LIBS) + GEANY_VERSION=`$PKG_CONFIG --modversion geany` GTK_VERSION=`$PKG_CONFIG --modversion gtk+-2.0` +ENCHANT_VERSION=`$PKG_CONFIG --modversion enchant`
-# checking for aspell -AC_CHECK_HEADER(aspell.h, [AC_DEFINE(HAVE_ASPELL_H, 1, - [Define to 1 if you have the <aspell.h> header file.] )], - [AC_MSG_ERROR([You must have the aspell dev library installed to build the spellcheck plugin.]) ] ) -AC_CHECK_LIB(aspell, new_aspell_speller, SPELLER_LIB="-laspell", - [AC_MSG_ERROR([You must have the aspell dev library installed to build the spellcheck plugin.]) ] ) -AC_SUBST(SPELLER_LIB) - # i18n GETTEXT_PACKAGE=spellcheck AC_SUBST(GETTEXT_PACKAGE) @@ -65,6 +63,7 @@ echo "Install Spell Check files in : ${prefix}" echo "Using Geany version : ${GEANY_VERSION}" echo "Using GTK version : ${GTK_VERSION}" +echo "Using libenchant version : ${ENCHANT_VERSION}" echo "" echo "Configuration is done OK." echo ""
Modified: trunk/spellcheck/src/Makefile.am =================================================================== --- trunk/spellcheck/src/Makefile.am 2008-06-19 21:20:36 UTC (rev 73) +++ trunk/spellcheck/src/Makefile.am 2008-06-19 21:34:52 UTC (rev 74) @@ -2,6 +2,6 @@ lib_LTLIBRARIES = spellcheck.la spellcheck_la_SOURCES = spellcheck.c spellcheck_la_LDFLAGS = -module -avoid-version -spellcheck_la_LIBADD = @GEANY_LIBS@ $(INTLLIBS) @SPELLER_LIB@ +spellcheck_la_LIBADD = @GEANY_LIBS@ $(INTLLIBS) @ENCHANT_LIBS@
-AM_CFLAGS = @GEANY_CFLAGS@ -DLOCALEDIR=""$(localedir)"" +AM_CFLAGS = @GEANY_CFLAGS@ @ENCHANT_CFLAGS@ -DLOCALEDIR=""$(localedir)""
Modified: trunk/spellcheck/src/spellcheck.c =================================================================== --- trunk/spellcheck/src/spellcheck.c 2008-06-19 21:20:36 UTC (rev 73) +++ trunk/spellcheck/src/spellcheck.c 2008-06-19 21:34:52 UTC (rev 74) @@ -35,7 +35,7 @@ #endif
#include <string.h> -#include <aspell.h> +#include <enchant.h>
#include "plugindata.h"
@@ -54,11 +54,24 @@ GeanyFunctions *geany_functions;
-PLUGIN_VERSION_CHECK(67) +PLUGIN_VERSION_CHECK(71) PLUGIN_SET_INFO(_("Spell Check"), _("Checks the spelling of the current document."), "0.2", _("The Geany developer team"))
+typedef struct +{ + gchar *config_file; + gchar *default_language; + gboolean check_while_typing; + gulong signal_id; + GPtrArray *dicts; + EnchantBroker *broker; + EnchantDict *dict; +} SpellCheck; +static SpellCheck *sc; + + /* Keybinding(s) */ enum { @@ -67,183 +80,260 @@ }; PLUGIN_KEY_GROUP(spellcheck, KB_COUNT)
-static gchar *config_file; -static gchar *language;
+/* currently unused */ +#ifdef G_OS_WIN32 +#warning TODO check Windows support /* On Windows we need to find the Aspell installation prefix via the Windows Registry * and then set the prefix in the Aspell config object. */ static void set_up_aspell_prefix(AspellConfig *config) { -#ifdef G_OS_WIN32 char sTemp[1024]; HKEY hkey; DWORD len = sizeof(sTemp); - + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\Aspell"), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) return; - + if (RegQueryValueEx(hkey, NULL, 0, NULL, (LPBYTE)sTemp, &len) == ERROR_SUCCESS) aspell_config_replace(config, "prefix", sTemp);
RegCloseKey(hkey); +} #endif + + +static void dict_describe(const gchar* const lang, const gchar* const name, + const gchar* const desc, const gchar* const file, void *target) +{ + gchar **result = (gchar**) target; + *result = g_strdup_printf(""%s" (%s)", lang, name); }
-static void print_word_list(AspellSpeller *speller, GString *str, const AspellWordList *wl) +static gint check_word(GeanyDocument *doc, gint line_number, GString *str, gint end_pos) { - if (wl == NULL) + gsize j; + gsize n_suggs = 0; + gchar **suggs; + gchar *word; + + /* early out if the word is spelled correctly */ + if (enchant_dict_check(sc->dict, str->str, -1) == 0) + return 0; + + word = g_strdup(str->str); + g_string_erase(str, 0, str->len); + suggs = enchant_dict_suggest(sc->dict, word, -1, &n_suggs); + + if (suggs != NULL) { - g_string_append_c(str, '?'); - } - else - { - AspellStringEnumeration *els = aspell_word_list_elements(wl); - const char *word; + g_string_append_printf(str, "line %d: %s | ", line_number + 1, word);
- while ((word = aspell_string_enumeration_next(els)) != 0) + g_string_append(str, _("Try: ")); + + /* Now find the misspellings in the line, limit suggestions to a maximum of 15 (for now) */ + for (j = 0; j < MIN(n_suggs, 15); j++) { - g_string_append(str, word); + g_string_append(str, suggs[j]); g_string_append_c(str, ' '); } - delete_aspell_string_enumeration(els); + + p_editor->set_indicator(doc, end_pos - strlen(word), end_pos); + p_msgwindow->msg_add(COLOR_RED, line_number + 1, doc, "%s", str->str); + + if (suggs != NULL && n_suggs) + enchant_dict_free_string_list(sc->dict, suggs); } + g_free(word); + + return n_suggs; }
-static gint check_document(AspellSpeller *speller, gint idx) +static gint process_line(GeanyDocument *doc, gint line_number, const gchar *line) { - AspellCanHaveError *ret; - AspellDocumentChecker *checker; - AspellToken token; - gchar *word_begin; + gint end_pos, char_len; + gunichar c; + GString *str = g_string_sized_new(256); + gint suggestions_found = 0; + + end_pos = p_sci->get_position_from_line(doc->sci, line_number); + /* split line into words */ + while ((c = g_utf8_get_char_validated(line, -1)) != (gunichar) -1 && c != 0) + { + if (g_unichar_isalpha(c) || c == ''') + { + /* part of a word */ + g_string_append_unichar(str, c); + } + else if (str->len > 0) + { + g_string_append_c(str, '\0'); + suggestions_found += check_word(doc, line_number, str, end_pos); + g_string_erase(str, 0, str->len); + } + + /* calculate byte len of c and add skip these in line */ + char_len = g_unichar_to_utf8(c, NULL); + line += char_len; + end_pos += char_len; + } + g_string_free(str, TRUE); + + return suggestions_found; +} + + +static void check_document(GeanyDocument *doc) +{ gchar *line; - gint linewidth; gint i; gint first_line, last_line; - gboolean suggestions_found = FALSE; - GString *str = g_string_sized_new(1024); + gchar *dict_string = NULL; + gint suggestions_found = 0;
- if (! DOC_IDX_VALID(idx)) - return 1; + enchant_dict_describe(sc->dict, dict_describe, &dict_string);
- str = g_string_sized_new(1024); - if (p_sci->can_copy(documents[idx]->sci)) + if (p_sci->can_copy(doc->sci)) { - first_line = p_sci->get_line_from_position( - documents[idx]->sci, p_sci->get_selection_start(documents[idx]->sci)); - last_line = p_sci->get_line_from_position( - documents[idx]->sci, p_sci->get_selection_end(documents[idx]->sci)); + first_line = p_sci->get_line_from_position(doc->sci, p_sci->get_selection_start(doc->sci)); + last_line = p_sci->get_line_from_position(doc->sci, p_sci->get_selection_end(doc->sci));
- p_msgwindow->msg_add(COLOR_BLUE, -1, -1, - _("Checking file "%s" (lines %d to %d):"), - DOC_FILENAME(idx), first_line + 1, last_line + 1); + p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, + _("Checking file "%s" (lines %d to %d using %s):"), + DOC_FILENAME(doc), first_line + 1, last_line + 1, dict_string); } else { first_line = 0; - last_line = p_sci->get_line_count(documents[idx]->sci); - p_msgwindow->msg_add(COLOR_BLUE, -1, -1, _("Checking file "%s":"), - DOC_FILENAME(idx)); + last_line = p_sci->get_line_count(doc->sci); + p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("Checking file "%s" (using %s):"), + DOC_FILENAME(doc), dict_string); } + g_free(dict_string);
- /* Set up the document checker */ - ret = new_aspell_document_checker(speller); - if (aspell_error(ret) != 0) + for (i = first_line; i < last_line; i++) { - g_warning("spellcheck: %s", aspell_error_message(ret)); - return 4; - } + line = p_sci->get_line(doc->sci, i);
- checker = to_aspell_document_checker(ret); + suggestions_found += process_line(doc, i, line);
- for (i = first_line; i < last_line; i++) - { - line = p_sci->get_line(documents[idx]->sci, i); - linewidth = strlen(line); + g_free(line); + }
- /* First process the line */ - aspell_document_checker_process(checker, line, -1); + if (suggestions_found == 0) + p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("The checked text is spelled correctly.")); +}
- /* Now find the misspellings in the line */ - while (token = aspell_document_checker_next_misspelling(checker), token.len != 0) - { - p_editor->set_indicator_on_line(idx, i); - /* Print out the misspelling and possible replacements */ - word_begin = line + token.offset;
- g_string_append_printf (str, "line %d: ", i + 1); - g_string_append_len(str, word_begin, token.len); +static void broker_init_failed() +{ + const gchar *err = enchant_broker_get_error(sc->broker); + p_dialogs->show_msgbox(GTK_MESSAGE_ERROR, + _("The Enchant library couldn't be initialized (%s)."), + (err != NULL) ? err : _("unknown error")); +}
- g_string_append(str, " | "); - g_string_append(str, _("Try: ")); - print_word_list(speller, str, aspell_speller_suggest(speller, word_begin, token.len));
- p_msgwindow->msg_add(COLOR_RED, i + 1, idx, "%s", str->str); - g_string_erase(str, 0, str->len); - suggestions_found = TRUE; - } +static void perform_check(GeanyDocument *doc) +{ + p_editor->clear_indicators(doc); + p_msgwindow->clear_tab(MSG_MESSAGE); + p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
- g_free(line); - } + check_document(doc); +}
- delete_aspell_document_checker(checker);
- g_string_free(str, TRUE); +static void clear_indicators_on_line(GeanyDocument *doc, gint line_number) +{ + glong start_pos, length;
- if (! suggestions_found) - p_msgwindow->msg_add(COLOR_BLUE, -1, -1, _("The checked text is spelled correctly.")); + g_return_if_fail(doc != NULL);
- return 0; + start_pos = p_sci->get_position_from_line(doc->sci, line_number); + length = p_sci->get_line_length(doc->sci, line_number); + if (length > 0) + { + p_sci->send_message(doc->sci, SCI_STARTSTYLING, start_pos, INDIC2_MASK); + p_sci->send_message(doc->sci, SCI_SETSTYLING, length, 0); + } }
-static void perform_check(gint idx) +/* Checks only the last word before the current cursor position -> check as you type. */ +static gboolean on_key_release(GtkWidget *widget, GdkEventKey *ev, gpointer user_data) { - AspellCanHaveError *ret; - AspellSpeller *speller; - AspellConfig *config; + gint line_number; + GString *str = g_string_sized_new(256); + gchar *line; + GeanyDocument *doc; + static time_t time_prev = 0; + time_t time_now = time(NULL);
- if (! DOC_IDX_VALID(idx)) - return; + if (! sc->check_while_typing) + return FALSE; + /* check only once a second */ + if (time_now == time_prev) + return FALSE; + /* set current time for the next key press */ + time_prev = time_now;
- p_editor->clear_indicators(idx); - p_msgwindow->clear_tab(MSG_MESSAGE); - p_msgwindow->switch_tab(MSG_MESSAGE, FALSE); + doc = p_document->get_current(); + if (doc == NULL) + return FALSE;
- config = new_aspell_config(); - aspell_config_replace(config, "lang", language); - aspell_config_replace(config, "encoding", "utf-8"); - set_up_aspell_prefix(config); + if (ev->keyval == '\r' && + p_sci->send_message(doc->sci, SCI_GETEOLMODE, 0, 0) == SC_EOL_CRLF) + { /* prevent double line checking */ + return FALSE; + }
- ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) + line_number = p_sci->get_current_line(doc->sci); + if (ev->keyval == '\n' || ev->keyval == '\r') + line_number--; /* check previous line if we start a new one */ + line = p_sci->get_line(doc->sci, line_number); + + clear_indicators_on_line(doc, line_number); + if (process_line(doc, line_number, line) != 0) { - delete_aspell_can_have_error(ret); - return; + p_msgwindow->switch_tab(MSG_MESSAGE, FALSE); }
- speller = to_aspell_speller(ret); - check_document(speller, idx); - delete_aspell_speller(speller); + g_string_free(str, TRUE); + g_free(line); + + return FALSE; }
-static void -item_activate(GtkMenuItem *menuitem, gpointer gdata) +static void on_menu_item_activate(GtkMenuItem *menuitem, gpointer gdata) { - gint idx = p_document->get_cur_idx(); + GeanyDocument *doc = p_document->get_current();
- perform_check(idx); + /* Another language was chosen from the menu item, so make it default for this session. */ + if (gdata != NULL) + setptr(sc->default_language, g_strdup(gdata)); + + /* Request new dict object */ + enchant_broker_free_dict(sc->broker, sc->dict); + sc->dict = enchant_broker_request_dict(sc->broker, sc->default_language); + if (sc->dict == NULL) + { + broker_init_failed(); + return; + } + + perform_check(doc); }
static void kb_activate(guint key_id) { - item_activate(NULL, NULL); + on_menu_item_activate(NULL, NULL); }
@@ -259,7 +349,7 @@ #ifdef G_OS_WIN32 gchar *install_dir = g_win32_get_package_installation_directory("geany", NULL); /* e.g. C:\Program Files\geany\lib\locale */ - locale_dir = g_strconcat(install_dir, "\lib\locale", NULL); + locale_dir = g_strconcat(install_dir, "\share\locale", NULL); g_free(install_dir); #else locale_dir = g_strdup(LOCALEDIR); @@ -285,34 +375,34 @@ } else lang = "en"; - + return lang; }
-static void fill_dicts_combo(GtkComboBox *combo) +static void add_dict_array(const gchar* const lang_tag, const gchar* const provider_name, + const gchar* const provider_desc, const gchar* const provider_file, + gpointer user_data) { - AspellConfig *config; - AspellDictInfoList *dlist; - AspellDictInfoEnumeration *dels; - const AspellDictInfo *entry; - guint i = 0; + guint i; + gchar *result = g_strdup(lang_tag);
- config = new_aspell_config(); - set_up_aspell_prefix(config); - dlist = get_aspell_dict_info_list(config); - delete_aspell_config(config); + /* sometimes dictionaries are named lang-LOCALE instead of lang_LOCALE, so replace the + * hyphen by a dash, enchant seems to not care about it. */ + for (i = 0; i < strlen(result); i++) + { + if (result[i] == '-') + result[i] = '_'; + }
- dels = aspell_dict_info_list_elements(dlist); - while ((entry = aspell_dict_info_enumeration_next(dels)) != 0) + /* find duplicates and skip them */ + for (i = 0; i < sc->dicts->len; i++) { - gtk_combo_box_append_text(combo, entry->name); + if (p_utils->str_equal(g_ptr_array_index(sc->dicts, i), result)) + return; + }
- if (p_utils->str_equal(entry->name, language)) - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i); - i++; - } - delete_aspell_dict_info_enumeration(dels); + g_ptr_array_add(sc->dicts, result); }
@@ -322,14 +412,18 @@ { GKeyFile *config = g_key_file_new(); gchar *data; - gchar *config_dir = g_path_get_dirname(config_file); + gchar *config_dir = g_path_get_dirname(sc->config_file);
- setptr(language, gtk_combo_box_get_active_text(GTK_COMBO_BOX( + setptr(sc->default_language, gtk_combo_box_get_active_text(GTK_COMBO_BOX( g_object_get_data(G_OBJECT(dialog), "combo"))));
- g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL); - g_key_file_set_string(config, "spellcheck", "language", language); + sc->check_while_typing = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + g_object_get_data(G_OBJECT(dialog), "check"))));
+ g_key_file_load_from_file(config, sc->config_file, G_KEY_FILE_NONE, NULL); + g_key_file_set_string(config, "spellcheck", "language", sc->default_language); + g_key_file_set_boolean(config, "spellcheck", "check_while_typing", sc->check_while_typing); + if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) && p_utils->mkdir(config_dir, TRUE) != 0) { p_dialogs->show_msgbox(GTK_MESSAGE_ERROR, @@ -339,7 +433,7 @@ { /* write config to file */ data = g_key_file_to_data(config, NULL, NULL); - p_utils->write_file(config_file, data); + p_utils->write_file(sc->config_file, data); g_free(data); } g_free(config_dir); @@ -348,28 +442,92 @@ }
+static gint sort_dicts(gconstpointer a, gconstpointer b) +{ /* casting mania ;-) */ + return strcmp((gchar*)((GPtrArray*)a)->pdata, (gchar*)((GPtrArray*)b)->pdata); +} + + +static void create_dicts_array() +{ + sc->dicts = g_ptr_array_new(); + + enchant_broker_list_dicts(sc->broker, add_dict_array, sc->dicts); + + g_ptr_array_sort(sc->dicts, sort_dicts); +} + + +static GtkWidget *create_menu() +{ + GtkWidget *sp_item, *menu, *subitem; + guint i; + + sp_item = gtk_menu_item_new_with_mnemonic(_("_Spell Check")); + gtk_container_add(GTK_CONTAINER(main_widgets->tools_menu), sp_item); + + menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(sp_item), menu); + + subitem = gtk_menu_item_new_with_mnemonic(_("Default")); + gtk_container_add(GTK_CONTAINER(menu), subitem); + g_signal_connect((gpointer) subitem, "activate", G_CALLBACK(on_menu_item_activate), NULL); + + subitem = gtk_separator_menu_item_new(); + gtk_container_add(GTK_CONTAINER(menu), subitem); + + for (i = 0; i < sc->dicts->len; i++) + { + GtkWidget *menu_item; + + menu_item = gtk_menu_item_new_with_label(g_ptr_array_index(sc->dicts, i)); + gtk_container_add(GTK_CONTAINER(menu), menu_item); + g_signal_connect((gpointer) menu_item, "activate", + G_CALLBACK(on_menu_item_activate), g_ptr_array_index(sc->dicts, i)); + } + + return sp_item; +} + + void plugin_init(GeanyData *data) { GtkWidget *sp_item; GKeyFile *config = g_key_file_new();
- config_file = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S, + sc = g_new0(SpellCheck, 1); + + sc->config_file = g_strconcat(app->configdir, G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S, "spellcheck", G_DIR_SEPARATOR_S, "spellcheck.conf", NULL);
- g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL); - language = p_utils->get_setting_string(config, "spellcheck", "language", get_default_lang()); + g_key_file_load_from_file(config, sc->config_file, G_KEY_FILE_NONE, NULL); + sc->default_language = p_utils->get_setting_string(config, + "spellcheck", "language", get_default_lang()); + sc->check_while_typing = p_utils->get_setting_boolean(config, + "spellcheck", "check_while_typing", FALSE); g_key_file_free(config);
locale_init();
- sp_item = gtk_menu_item_new_with_mnemonic(_("_Spell Check")); - gtk_widget_show(sp_item); - gtk_container_add(GTK_CONTAINER(main_widgets->tools_menu), sp_item); - g_signal_connect(G_OBJECT(sp_item), "activate", G_CALLBACK(item_activate), NULL); + sc->broker = enchant_broker_init(); + sc->dict = enchant_broker_request_dict(sc->broker, sc->default_language); + if (sc->dict == NULL) + { + broker_init_failed(); + return; + }
+ create_dicts_array(); + + sp_item = create_menu(); + gtk_widget_show_all(sp_item); + plugin_fields->menu_item = sp_item; plugin_fields->flags = PLUGIN_IS_DOCUMENT_SENSITIVE;
+ sc->signal_id = g_signal_connect(main_widgets->window, + "key-release-event", G_CALLBACK(on_key_release), NULL); + /* setup keybindings */ p_keybindings->set_item(plugin_key_group, KB_SPELL_CHECK, kb_activate, 0, 0, "spell_check", _("Run Spell Check"), NULL); @@ -378,7 +536,8 @@
GtkWidget *plugin_configure(GtkDialog *dialog) { - GtkWidget *label, *vbox, *combo; + GtkWidget *label, *vbox, *combo, *check; + guint i;
vbox = gtk_vbox_new(FALSE, 6);
@@ -387,12 +546,27 @@ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
combo = gtk_combo_box_new_text(); - fill_dicts_combo(GTK_COMBO_BOX(combo));
- gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3); + for (i = 0; i < sc->dicts->len; i++) + { + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), g_ptr_array_index(sc->dicts, i)); + + if (p_utils->str_equal(g_ptr_array_index(sc->dicts, i), sc->default_language)) + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i); + } + + if (sc->dicts->len > 20) + gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 3); + else if (sc->dicts->len > 10) + gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combo), 2); gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0);
+ check = gtk_check_button_new_with_label(_("Check spelling while typing")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), sc->check_while_typing); + gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(dialog), "combo", combo); + g_object_set_data(G_OBJECT(dialog), "check", check); g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
gtk_widget_show_all(vbox); @@ -403,7 +577,20 @@
void plugin_cleanup(void) { - g_free(language); - g_free(config_file); + guint i; + for (i = 0; i < sc->dicts->len; i++) + { + g_free(g_ptr_array_index(sc->dicts, i)); + } + g_ptr_array_free(sc->dicts, TRUE); + + g_signal_handler_disconnect(main_widgets->window, sc->signal_id); + + enchant_broker_free_dict(sc->broker, sc->dict); + enchant_broker_free(sc->broker); + + g_free(sc->default_language); + g_free(sc->config_file); + g_free(sc); gtk_widget_destroy(plugin_fields->menu_item); }
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.