SF.net SVN: geany-plugins:[212] trunk/spellcheck
eht16 at users.sourceforge.net
eht16 at xxxxx
Fri Oct 17 15:20:12 UTC 2008
Revision: 212
http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=212&view=rev
Author: eht16
Date: 2008-10-17 15:20:12 +0000 (Fri, 17 Oct 2008)
Log Message:
-----------
Split spellcheck.c into three source files.
Modified Paths:
--------------
trunk/spellcheck/ChangeLog
trunk/spellcheck/po/POTFILES.in
trunk/spellcheck/src/Makefile.am
Added Paths:
-----------
trunk/spellcheck/src/gui.c
trunk/spellcheck/src/gui.h
trunk/spellcheck/src/scplugin.c
trunk/spellcheck/src/scplugin.h
trunk/spellcheck/src/speller.c
trunk/spellcheck/src/speller.h
Removed Paths:
-------------
trunk/spellcheck/src/spellcheck.c
Modified: trunk/spellcheck/ChangeLog
===================================================================
--- trunk/spellcheck/ChangeLog 2008-10-16 16:21:41 UTC (rev 211)
+++ trunk/spellcheck/ChangeLog 2008-10-17 15:20:12 UTC (rev 212)
@@ -1,3 +1,11 @@
+2008-10-17 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+
+ * src/spellcheck.c, src/scplugin.c, src/gui.c, src/speller.c,
+ src/scplugin.h, src/gui.h, src/speller.h, src/Makefile.am,
+ po/POTFILES.in:
+ Split spellcheck.c into three source files.
+
+
2008-10-16 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/spellcheck.c:
Modified: trunk/spellcheck/po/POTFILES.in
===================================================================
--- trunk/spellcheck/po/POTFILES.in 2008-10-16 16:21:41 UTC (rev 211)
+++ trunk/spellcheck/po/POTFILES.in 2008-10-17 15:20:12 UTC (rev 212)
@@ -1,3 +1,5 @@
# List of source files containing translatable strings.
-src/spellcheck.c
+src/scplugin.c
+src/gui.c
+src/speller.c
Modified: trunk/spellcheck/src/Makefile.am
===================================================================
--- trunk/spellcheck/src/Makefile.am 2008-10-16 16:21:41 UTC (rev 211)
+++ trunk/spellcheck/src/Makefile.am 2008-10-17 15:20:12 UTC (rev 212)
@@ -1,6 +1,6 @@
lib_LTLIBRARIES = spellcheck.la
-spellcheck_la_SOURCES = spellcheck.c
+spellcheck_la_SOURCES = speller.c speller.h scplugin.c scplugin.h gui.c gui.h
spellcheck_la_LDFLAGS = -module -avoid-version
spellcheck_la_LIBADD = @GEANY_LIBS@ $(INTLLIBS) @ENCHANT_LIBS@
Added: trunk/spellcheck/src/gui.c
===================================================================
--- trunk/spellcheck/src/gui.c (rev 0)
+++ trunk/spellcheck/src/gui.c 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,377 @@
+/*
+ * gui.c - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#include "geany.h"
+#include "support.h"
+
+
+#include "plugindata.h"
+
+#include "document.h"
+#include "editor.h"
+#include "msgwindow.h"
+#include "utils.h"
+#include "ui_utils.h"
+
+#include "pluginmacros.h"
+
+#include "gui.h"
+#include "scplugin.h"
+#include "speller.h"
+
+
+
+/* Flag to indicate that a callback function will be triggered by generating the appropriate event
+ * but the callback should be ignored. */
+static gboolean ignore_sc_callback = FALSE;
+
+
+
+void gui_perform_check(GeanyDocument *doc)
+{
+ p_editor->clear_indicators(doc->editor);
+ if (sc->use_msgwin)
+ {
+ p_msgwindow->clear_tab(MSG_MESSAGE);
+ p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
+ }
+
+ speller_check_document(doc);
+}
+
+
+static void toolbar_item_toggled_cb(GtkToggleToolButton *button, gpointer user_data)
+{
+ if (ignore_sc_callback)
+ return;
+
+ sc->check_while_typing = gtk_toggle_tool_button_get_active(button);
+
+ p_ui->set_statusbar(FALSE, _("Spell checking while typing is now %s"),
+ (sc->check_while_typing) ? _("enabled") : _("disabled"));
+}
+
+
+void gui_toolbar_update(void)
+{
+ /* toolbar item is not requested, so remove the item if it exists */
+ if (! sc->show_toolbar_item)
+ {
+ if (sc->toolbar_button != NULL)
+ {
+ gtk_widget_destroy(GTK_WIDGET(sc->toolbar_button));
+ sc->toolbar_button = NULL;
+ }
+ }
+ else
+ {
+ if (sc->toolbar_button == NULL)
+ {
+ sc->toolbar_button = gtk_toggle_tool_button_new_from_stock("gtk-spell-check");
+#if GTK_CHECK_VERSION(2, 12, 0)
+ gtk_widget_set_tooltip_text(GTK_WIDGET(sc->toolbar_button),
+ _("Toggle spell check while typing."));
+#endif
+ gtk_widget_show(GTK_WIDGET(sc->toolbar_button));
+ p_plugin->add_toolbar_item(geany_plugin, sc->toolbar_button);
+ p_ui->add_document_sensitive(GTK_WIDGET(sc->toolbar_button));
+
+ g_signal_connect(sc->toolbar_button, "toggled",
+ G_CALLBACK(toolbar_item_toggled_cb), NULL);
+ }
+
+ ignore_sc_callback = TRUE;
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(sc->toolbar_button), sc->check_while_typing);
+ ignore_sc_callback = FALSE;
+ }
+}
+
+
+static void clear_indicators_on_range(GeanyDocument *doc, gint start, gint len)
+{
+ g_return_if_fail(doc != NULL);
+
+ if (len > 0)
+ {
+ p_sci->indicator_clear(doc->editor->sci, start, start + len);
+ }
+}
+
+
+static void clear_indicators_on_line(GeanyDocument *doc, gint line_number)
+{
+ gint start_pos, length;
+
+ g_return_if_fail(doc != NULL);
+
+ start_pos = p_sci->get_position_from_line(doc->editor->sci, line_number);
+ length = p_sci->get_line_length(doc->editor->sci, line_number);
+
+ clear_indicators_on_range(doc, start_pos, length);
+}
+
+
+
+static void menu_suggestion_item_activate_cb(GtkMenuItem *menuitem, gpointer gdata)
+{
+ gchar *sugg = gdata;
+ gint startword, endword;
+
+ if (clickinfo.doc == NULL || clickinfo.pos == -1)
+ {
+ g_free(sugg);
+ return;
+ }
+
+ startword = p_sci->send_message(
+ clickinfo.doc->editor->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
+ endword = p_sci->send_message(
+ clickinfo.doc->editor->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
+
+ if (startword != endword)
+ {
+ p_sci->set_selection_start(clickinfo.doc->editor->sci, startword);
+ p_sci->set_selection_end(clickinfo.doc->editor->sci, endword);
+ p_sci->replace_sel(clickinfo.doc->editor->sci, sugg);
+
+ clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
+ }
+}
+
+
+static void on_menu_addword_item_activate(GtkMenuItem *menuitem, gpointer gdata)
+{
+ gint startword, endword;
+
+ if (clickinfo.doc == NULL || clickinfo.word == NULL || clickinfo.pos == -1)
+ return;
+
+ /** TODO re-check the whole document */
+ speller_add_word(clickinfo.word);
+
+ startword = p_sci->send_message(
+ clickinfo.doc->editor->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
+ endword = p_sci->send_message(
+ clickinfo.doc->editor->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
+ if (startword != endword)
+ {
+ clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
+ }
+}
+
+
+void gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
+ GeanyDocument *doc, gpointer user_data)
+{
+ gsize n_suggs, i;
+ gchar **tmp_suggs;
+
+ g_return_if_fail(doc != NULL && doc->is_valid);
+
+ /* hide the submenu in any case, we will reshow it again if we actually found something */
+ gtk_widget_hide(sc->edit_menu);
+ gtk_widget_hide(sc->edit_menu_sep);
+
+ if (! NZV(word) || speller_dict_check(word) == 0)
+ return;
+
+ tmp_suggs = speller_dict_suggest(word, &n_suggs);
+
+ if (tmp_suggs != NULL)
+ {
+ GtkWidget *menu_item, *image;
+ gchar *label;
+
+ clickinfo.pos = pos;
+ clickinfo.doc = doc;
+ setptr(clickinfo.word, g_strdup(word));
+
+ if (GTK_IS_WIDGET(sc->edit_menu_sub))
+ gtk_widget_destroy(sc->edit_menu_sub);
+
+ sc->edit_menu_sub = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(sc->edit_menu), sc->edit_menu_sub);
+
+ /* TODO do we need more than 10 suggestions? gtkspell offers additional suggestions
+ * in another sub menu, should we too? */
+ for (i = 0; i < MIN(n_suggs, MAX_MENU_SUGGESTIONS); i++)
+ {
+ /* keep the suggestions in a static array for the callback function */
+ g_free(clickinfo.suggs[i]);
+ clickinfo.suggs[i] = g_strdup(tmp_suggs[i]);
+
+ menu_item = gtk_menu_item_new_with_label(clickinfo.suggs[i]);
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+ g_signal_connect((gpointer) menu_item, "activate",
+ G_CALLBACK(menu_suggestion_item_activate_cb), clickinfo.suggs[i]);
+ }
+ menu_item = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+
+ image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+
+ label = g_strdup_printf(_("Add \"%s\" to Dictionary"), word);
+ menu_item = gtk_image_menu_item_new_with_label(label);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
+ gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
+ g_signal_connect((gpointer) menu_item, "activate",
+ G_CALLBACK(on_menu_addword_item_activate), NULL);
+
+ gtk_widget_show(sc->edit_menu);
+ gtk_widget_show(sc->edit_menu_sep);
+ gtk_widget_show_all(sc->edit_menu_sub);
+
+ speller_dict_free_string_list(tmp_suggs);
+
+ g_free(label);
+ }
+}
+
+
+/* Checks only the last word before the current cursor position -> check as you type. */
+gboolean gui_key_release_cb(GtkWidget *widget, GdkEventKey *ev, gpointer user_data)
+{
+ 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);
+ GtkWidget *focusw;
+
+ 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;
+
+ doc = p_document->get_current();
+ /* bail out if we don't have a document or if we are not in the editor widget */
+ focusw = gtk_window_get_focus(GTK_WINDOW(geany->main_widgets->window));
+ if (doc == NULL || focusw != GTK_WIDGET(doc->editor->sci))
+ return FALSE;
+
+ if (ev->keyval == '\r' &&
+ p_sci->send_message(doc->editor->sci, SCI_GETEOLMODE, 0, 0) == SC_EOL_CRLF)
+ { /* prevent double line checking */
+ return FALSE;
+ }
+
+ line_number = p_sci->get_current_line(doc->editor->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->editor->sci, line_number);
+
+ clear_indicators_on_line(doc, line_number);
+ if (speller_process_line(doc, line_number, line) != 0)
+ {
+ if (sc->use_msgwin)
+ p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
+ }
+
+ g_string_free(str, TRUE);
+ g_free(line);
+
+ return FALSE;
+}
+
+
+static void menu_item_activate_cb(GtkMenuItem *menuitem, gpointer gdata)
+{
+ GeanyDocument *doc;
+
+ doc = p_document->get_current();
+
+ /* 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));
+
+ speller_reinit_enchant_dict();
+
+ p_editor->clear_indicators(doc->editor);
+ if (sc->use_msgwin)
+ {
+ p_msgwindow->clear_tab(MSG_MESSAGE);
+ p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
+ }
+
+ speller_check_document(doc);
+}
+
+
+void gui_kb_activate_cb(guint key_id)
+{
+ menu_item_activate_cb(NULL, NULL);
+}
+
+
+void gui_create_edit_menu(void)
+{
+ sc->edit_menu = gtk_image_menu_item_new_from_stock(GTK_STOCK_SPELL_CHECK, NULL);
+ gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc->edit_menu);
+ gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc->edit_menu, 0);
+
+ sc->edit_menu_sep = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc->edit_menu_sep);
+ gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc->edit_menu_sep, 1);
+
+ gtk_widget_show_all(sc->edit_menu);
+}
+
+
+GtkWidget *gui_create_menu(GtkWidget *sp_item)
+{
+ GtkWidget *menu, *subitem;
+ guint i;
+
+ gtk_container_add(GTK_CONTAINER(geany->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(menu_item_activate_cb), 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(menu_item_activate_cb), g_ptr_array_index(sc->dicts, i));
+ }
+
+ return sp_item;
+}
+
+
Property changes on: trunk/spellcheck/src/gui.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
Added: trunk/spellcheck/src/gui.h
===================================================================
--- trunk/spellcheck/src/gui.h (rev 0)
+++ trunk/spellcheck/src/gui.h 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,48 @@
+/*
+ * gui.h - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#ifndef SC_GUI_H
+#define SC_GUI_H 1
+
+
+
+void gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
+ GeanyDocument *doc, gpointer user_data);
+
+gboolean gui_key_release_cb(GtkWidget *widget, GdkEventKey *ev, gpointer user_data);
+
+void gui_kb_activate_cb(guint key_id);
+
+
+void gui_create_edit_menu(void);
+
+GtkWidget *gui_create_menu(GtkWidget *sp_item);
+
+void gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
+ GeanyDocument *doc, gpointer user_data);
+
+void gui_toolbar_update(void);
+
+#endif
Property changes on: trunk/spellcheck/src/gui.h
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
Added: trunk/spellcheck/src/scplugin.c
===================================================================
--- trunk/spellcheck/src/scplugin.c (rev 0)
+++ trunk/spellcheck/src/scplugin.c 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,312 @@
+/*
+ * scplugin.c - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#include "geany.h"
+#include "support.h"
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+/*
+#ifdef G_OS_WIN32
+# include <windows.h>
+#endif
+*/
+
+#include "plugindata.h"
+
+#include "keybindings.h"
+#include "utils.h"
+#include "ui_utils.h"
+
+#include "pluginmacros.h"
+
+#include "scplugin.h"
+#include "gui.h"
+#include "speller.h"
+
+
+GeanyPlugin *geany_plugin;
+GeanyData *geany_data;
+GeanyFunctions *geany_functions;
+
+
+PLUGIN_VERSION_CHECK(100)
+PLUGIN_SET_INFO(_("Spell Check"), _("Checks the spelling of the current document."), "0.2",
+ _("The Geany developer team"))
+
+
+SpellCheck *sc = NULL;
+SpellClickInfo clickinfo;
+
+
+
+/* Keybinding(s) */
+enum
+{
+ KB_SPELL_CHECK,
+ KB_COUNT
+};
+PLUGIN_KEY_GROUP(spellcheck, KB_COUNT)
+
+
+
+PluginCallback plugin_callbacks[] =
+{
+ { "update-editor-menu", (GCallback) &gui_update_editor_menu_cb, FALSE, NULL },
+ { NULL, NULL, FALSE, NULL }
+};
+
+
+/* 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)
+{
+ 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 locale_init(void)
+{
+#ifdef ENABLE_NLS
+ gchar *locale_dir = NULL;
+
+#ifdef HAVE_LOCALE_H
+ setlocale(LC_ALL, "");
+#endif
+
+#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, "\\share\\locale", NULL);
+ g_free(install_dir);
+#else
+ locale_dir = g_strdup(LOCALEDIR);
+#endif
+
+ bindtextdomain(GETTEXT_PACKAGE, locale_dir);
+ bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
+ textdomain(GETTEXT_PACKAGE);
+ g_free(locale_dir);
+#endif
+}
+
+
+static void configure_response_cb(GtkDialog *dialog, gint response, gpointer user_data)
+{
+ if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
+ {
+ GKeyFile *config = g_key_file_new();
+ gchar *data;
+ gchar *config_dir = g_path_get_dirname(sc->config_file);
+
+ setptr(sc->default_language, gtk_combo_box_get_active_text(GTK_COMBO_BOX(
+ g_object_get_data(G_OBJECT(dialog), "combo"))));
+ speller_reinit_enchant_dict();
+
+ sc->check_while_typing = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_type"))));
+
+ sc->use_msgwin = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_msgwin"))));
+
+ sc->show_toolbar_item = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_toolbar"))));
+
+ g_key_file_load_from_file(config, sc->config_file, G_KEY_FILE_NONE, NULL);
+ if (sc->default_language != NULL) /* lang may be 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);
+ g_key_file_set_boolean(config, "spellcheck", "use_msgwin", sc->use_msgwin);
+ g_key_file_set_boolean(config, "spellcheck", "show_toolbar_item", sc->show_toolbar_item);
+
+ gui_toolbar_update();
+
+ 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,
+ _("Plugin configuration directory could not be created."));
+ }
+ else
+ {
+ /* write config to file */
+ data = g_key_file_to_data(config, NULL, NULL);
+ p_utils->write_file(sc->config_file, data);
+ g_free(data);
+ }
+ g_free(config_dir);
+ g_key_file_free(config);
+ }
+}
+
+
+void plugin_init(GeanyData *data)
+{
+ GtkWidget *sp_item;
+ GKeyFile *config = g_key_file_new();
+ guint i;
+
+ sc = g_new0(SpellCheck, 1);
+
+ sc->config_file = g_strconcat(geany->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, sc->config_file, G_KEY_FILE_NONE, NULL);
+ sc->default_language = p_utils->get_setting_string(config,
+ "spellcheck", "language", speller_get_default_lang());
+ sc->check_while_typing = p_utils->get_setting_boolean(config,
+ "spellcheck", "check_while_typing", FALSE);
+ sc->show_toolbar_item = p_utils->get_setting_boolean(config,
+ "spellcheck", "show_toolbar_item", TRUE);
+ sc->use_msgwin = p_utils->get_setting_boolean(config, "spellcheck", "use_msgwin", FALSE);
+ g_key_file_free(config);
+
+ locale_init();
+
+ sc->menu_item = gtk_image_menu_item_new_from_stock("gtk-spell-check", NULL);
+ p_ui->add_document_sensitive(sc->menu_item);
+
+ gui_toolbar_update();
+
+ speller_init();
+
+ for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
+ {
+ clickinfo.suggs[i] = NULL;
+ }
+ clickinfo.word = NULL;
+
+ gui_create_edit_menu();
+ sp_item = gui_create_menu(sc->menu_item);
+ gtk_widget_show_all(sp_item);
+
+ sc->signal_id = g_signal_connect(geany->main_widgets->window,
+ "key-release-event", G_CALLBACK(gui_key_release_cb), NULL);
+
+ /* setup keybindings */
+ p_keybindings->set_item(plugin_key_group, KB_SPELL_CHECK, gui_kb_activate_cb,
+ 0, 0, "spell_check", _("Run Spell Check"), NULL);
+}
+
+
+GtkWidget *plugin_configure(GtkDialog *dialog)
+{
+ GtkWidget *label, *vbox, *combo, *check_type, *check_msgwin, *check_toolbar;
+ guint i;
+
+ vbox = gtk_vbox_new(FALSE, 6);
+
+ check_type = gtk_check_button_new_with_label(_("Check spelling while typing"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_type), sc->check_while_typing);
+ gtk_box_pack_start(GTK_BOX(vbox), check_type, FALSE, FALSE, 6);
+
+ check_toolbar = gtk_check_button_new_with_label(_("Show toolbar item to toggle spell checking"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_toolbar), sc->show_toolbar_item);
+ gtk_box_pack_start(GTK_BOX(vbox), check_toolbar, FALSE, FALSE, 3);
+
+ check_msgwin = gtk_check_button_new_with_label(
+ _("Print misspelled words and suggestions in the messages window"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_msgwin), sc->use_msgwin);
+ gtk_box_pack_start(GTK_BOX(vbox), check_msgwin, FALSE, FALSE, 3);
+
+ label = gtk_label_new(_("Language to use for the spell check:"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 3);
+
+ combo = gtk_combo_box_new_text();
+
+ 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 the default language couldn't be selected, select the first available language */
+ if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) == -1)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
+
+ 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, 6);
+
+ g_object_set_data(G_OBJECT(dialog), "combo", combo);
+ g_object_set_data(G_OBJECT(dialog), "check_type", check_type);
+ g_object_set_data(G_OBJECT(dialog), "check_msgwin", check_msgwin);
+ g_object_set_data(G_OBJECT(dialog), "check_toolbar", check_toolbar);
+ g_signal_connect(dialog, "response", G_CALLBACK(configure_response_cb), NULL);
+
+ gtk_widget_show_all(vbox);
+
+ return vbox;
+}
+
+
+void plugin_cleanup(void)
+{
+ guint i;
+ for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
+ {
+ clickinfo.suggs[i] = NULL;
+ }
+ g_free(clickinfo.word);
+ 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(geany->main_widgets->window, sc->signal_id);
+
+ gtk_widget_destroy(sc->edit_menu);
+ gtk_widget_destroy(sc->edit_menu_sep);
+ if (sc->toolbar_button != NULL)
+ gtk_widget_destroy(GTK_WIDGET(sc->toolbar_button));
+
+ speller_free();
+
+ g_free(sc->default_language);
+ g_free(sc->config_file);
+ gtk_widget_destroy(sc->menu_item);
+ g_free(sc);
+}
Property changes on: trunk/spellcheck/src/scplugin.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
Added: trunk/spellcheck/src/scplugin.h
===================================================================
--- trunk/spellcheck/src/scplugin.h (rev 0)
+++ trunk/spellcheck/src/scplugin.h 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,67 @@
+/*
+ * scplugin.h - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#ifndef SC_PLUGIN_H
+#define SC_PLUGIN_H 1
+
+
+
+typedef struct
+{
+ gchar *config_file;
+ gchar *default_language;
+ gboolean use_msgwin;
+ gboolean check_while_typing;
+ gboolean show_toolbar_item;
+ gulong signal_id;
+ GPtrArray *dicts;
+ GtkWidget *menu_item;
+ GtkWidget *edit_menu;
+ GtkWidget *edit_menu_sep;
+ GtkWidget *edit_menu_sub;
+ GtkToolItem *toolbar_button;
+} SpellCheck;
+
+
+#define MAX_MENU_SUGGESTIONS 10
+
+typedef struct
+{
+ gint pos;
+ GeanyDocument *doc;
+ /* static array to keep suggestions for use as callback user data for the editing menu items */
+ gchar *suggs[MAX_MENU_SUGGESTIONS];
+ /* static storage for the misspelled word under the cursor when using the editing menu */
+ gchar *word;
+} SpellClickInfo;
+
+
+extern SpellCheck *sc;
+extern SpellClickInfo clickinfo;
+extern GeanyPlugin *geany_plugin;
+extern GeanyData *geany_data;
+extern GeanyFunctions *geany_functions;
+
+#endif
Property changes on: trunk/spellcheck/src/scplugin.h
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
Deleted: trunk/spellcheck/src/spellcheck.c
===================================================================
--- trunk/spellcheck/src/spellcheck.c 2008-10-16 16:21:41 UTC (rev 211)
+++ trunk/spellcheck/src/spellcheck.c 2008-10-17 15:20:12 UTC (rev 212)
@@ -1,934 +0,0 @@
-/*
- * spellcheck.c - this file is part of Geany, a fast and lightweight IDE
- *
- * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
- * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- *
- * $Id$
- */
-
-
-#include "geany.h"
-#include "support.h"
-
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-
-#ifdef G_OS_WIN32
-# include <windows.h>
-#endif
-
-#include <string.h>
-#include <ctype.h>
-#include <enchant.h>
-
-#include "plugindata.h"
-
-#include "document.h"
-#include "editor.h"
-#include "msgwindow.h"
-#include "keybindings.h"
-#include "utils.h"
-#include "ui_utils.h"
-
-#include "pluginmacros.h"
-
-
-GeanyPlugin *geany_plugin;
-GeanyData *geany_data;
-GeanyFunctions *geany_functions;
-
-
-PLUGIN_VERSION_CHECK(100)
-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 use_msgwin;
- gboolean check_while_typing;
- gboolean show_toolbar_item;
- gulong signal_id;
- GPtrArray *dicts;
- GtkWidget *menu_item;
- GtkWidget *edit_menu;
- GtkWidget *edit_menu_sep;
- GtkWidget *edit_menu_sub;
- GtkToolItem *toolbar_button;
- EnchantBroker *broker;
- EnchantDict *dict;
-} SpellCheck;
-static SpellCheck *sc;
-
-
-#define MAX_MENU_SUGGESTIONS 10
-typedef struct
-{
- gint pos;
- GeanyDocument *doc;
- /* static array to keep suggestions for use as callback user data for the editing menu items */
- gchar *suggs[MAX_MENU_SUGGESTIONS];
- /* static storage for the misspelled word under the cursor when using the editing menu */
- gchar *word;
-} SpellClickInfo;
-static SpellClickInfo clickinfo;
-
-
-/* Flag to indicate that a callback function will be triggered by generating the appropriate event
- * but the callback should be ignored. */
-static gboolean ignore_sc_callback = FALSE;
-
-
-static void on_update_editor_menu(GObject *obj, const gchar *word, gint pos,
- GeanyDocument *doc, gpointer user_data);
-
-/* Keybinding(s) */
-enum
-{
- KB_SPELL_CHECK,
- KB_COUNT
-};
-PLUGIN_KEY_GROUP(spellcheck, KB_COUNT)
-
-
-
-PluginCallback plugin_callbacks[] =
-{
- { "update-editor-menu", (GCallback) &on_update_editor_menu, FALSE, NULL },
- { NULL, NULL, FALSE, NULL }
-};
-
-
-/* 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)
-{
- 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 toolbar_item_toggled_cb(GtkToggleToolButton *button, gpointer user_data)
-{
- if (ignore_sc_callback)
- return;
-
- sc->check_while_typing = gtk_toggle_tool_button_get_active(button);
-
- p_ui->set_statusbar(FALSE, _("Spell checking while typing is now %s"),
- (sc->check_while_typing) ? _("enabled") : _("disabled"));
-}
-
-
-static void toolbar_update(void)
-{
- /* toolbar item is not requested, so remove the item if it exists */
- if (! sc->show_toolbar_item)
- {
- if (sc->toolbar_button != NULL)
- {
- gtk_widget_destroy(GTK_WIDGET(sc->toolbar_button));
- sc->toolbar_button = NULL;
- }
- }
- else
- {
- if (sc->toolbar_button == NULL)
- {
- sc->toolbar_button = gtk_toggle_tool_button_new_from_stock("gtk-spell-check");
- #if GTK_CHECK_VERSION(2, 12, 0)
- gtk_widget_set_tooltip_text(GTK_WIDGET(sc->toolbar_button),
- _("Toggle spell check while typing."));
- #endif
- gtk_widget_show(GTK_WIDGET(sc->toolbar_button));
- p_plugin->add_toolbar_item(geany_plugin, sc->toolbar_button);
- p_ui->add_document_sensitive(GTK_WIDGET(sc->toolbar_button));
-
- g_signal_connect(sc->toolbar_button, "toggled",
- G_CALLBACK(toolbar_item_toggled_cb), NULL);
- }
-
- ignore_sc_callback = TRUE;
- gtk_toggle_tool_button_set_active(
- GTK_TOGGLE_TOOL_BUTTON(sc->toolbar_button), sc->check_while_typing);
- ignore_sc_callback = FALSE;
- }
-}
-
-
-static void clear_indicators_on_range(GeanyDocument *doc, gint start, gint len)
-{
- g_return_if_fail(doc != NULL);
-
- if (len > 0)
- {
- p_sci->indicator_clear(doc->editor->sci, start, start + len);
- }
-}
-
-
-static void clear_indicators_on_line(GeanyDocument *doc, gint line_number)
-{
- gint start_pos, length;
-
- g_return_if_fail(doc != NULL);
-
- start_pos = p_sci->get_position_from_line(doc->editor->sci, line_number);
- length = p_sci->get_line_length(doc->editor->sci, line_number);
-
- clear_indicators_on_range(doc, start_pos, length);
-}
-
-
-
-static void on_menu_suggestion_item_activate(GtkMenuItem *menuitem, gpointer gdata)
-{
- gchar *sugg = gdata;
- gint startword, endword;
-
- if (clickinfo.doc == NULL || clickinfo.pos == -1)
- {
- g_free(sugg);
- return;
- }
-
- startword = p_sci->send_message(
- clickinfo.doc->editor->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
- endword = p_sci->send_message(
- clickinfo.doc->editor->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
-
- if (startword != endword)
- {
- p_sci->set_selection_start(clickinfo.doc->editor->sci, startword);
- p_sci->set_selection_end(clickinfo.doc->editor->sci, endword);
- p_sci->replace_sel(clickinfo.doc->editor->sci, sugg);
-
- clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
- }
-}
-
-
-static void on_menu_addword_item_activate(GtkMenuItem *menuitem, gpointer gdata)
-{
- gint startword, endword;
-
- if (clickinfo.doc == NULL || clickinfo.word == NULL || clickinfo.pos == -1)
- return;
-
- enchant_dict_add_to_pwl(sc->dict, clickinfo.word, -1);
-
- startword = p_sci->send_message(
- clickinfo.doc->editor->sci, SCI_WORDSTARTPOSITION, clickinfo.pos, 0);
- endword = p_sci->send_message(
- clickinfo.doc->editor->sci, SCI_WORDENDPOSITION, clickinfo.pos, 0);
- if (startword != endword)
- {
- clear_indicators_on_range(clickinfo.doc, startword, endword - startword);
- }
-}
-
-
-static void on_update_editor_menu(GObject *obj, const gchar *word, gint pos,
- GeanyDocument *doc, gpointer user_data)
-{
- gsize n_suggs, i;
- gchar **tmp_suggs;
-
- g_return_if_fail(doc != NULL && doc->is_valid);
-
- /* hide the submenu in any case, we will reshow it again if we actually found something */
- gtk_widget_hide(sc->edit_menu);
- gtk_widget_hide(sc->edit_menu_sep);
-
- if (! NZV(word) || enchant_dict_check(sc->dict, word, -1) == 0)
- return;
-
- tmp_suggs = enchant_dict_suggest(sc->dict, word, -1, &n_suggs);
-
- if (tmp_suggs != NULL)
- {
- GtkWidget *menu_item, *image;
- gchar *label;
-
- clickinfo.pos = pos;
- clickinfo.doc = doc;
- setptr(clickinfo.word, g_strdup(word));
-
- if (GTK_IS_WIDGET(sc->edit_menu_sub))
- gtk_widget_destroy(sc->edit_menu_sub);
-
- sc->edit_menu_sub = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(sc->edit_menu), sc->edit_menu_sub);
-
- /* TODO do we need more than 10 suggestions? gtkspell offers additional suggestions
- * in another sub menu, should we too? */
- for (i = 0; i < MIN(n_suggs, MAX_MENU_SUGGESTIONS); i++)
- {
- /* keep the suggestions in a static array for the callback function */
- g_free(clickinfo.suggs[i]);
- clickinfo.suggs[i] = g_strdup(tmp_suggs[i]);
-
- menu_item = gtk_menu_item_new_with_label(clickinfo.suggs[i]);
- gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
- g_signal_connect((gpointer) menu_item, "activate",
- G_CALLBACK(on_menu_suggestion_item_activate), clickinfo.suggs[i]);
- }
- menu_item = gtk_separator_menu_item_new();
- gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
-
- image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
-
- label = g_strdup_printf(_("Add \"%s\" to Dictionary"), word);
- menu_item = gtk_image_menu_item_new_with_label(label);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
- gtk_container_add(GTK_CONTAINER(sc->edit_menu_sub), menu_item);
- g_signal_connect((gpointer) menu_item, "activate",
- G_CALLBACK(on_menu_addword_item_activate), NULL);
-
- gtk_widget_show(sc->edit_menu);
- gtk_widget_show(sc->edit_menu_sep);
- gtk_widget_show_all(sc->edit_menu_sub);
-
- enchant_dict_free_string_list(sc->dict, tmp_suggs);
- g_free(label);
- }
-}
-
-
-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 gint check_word(GeanyDocument *doc, gint line_number, const gchar *word,
- gint start_pos, gint end_pos)
-{
- gsize j;
- gsize n_suggs = 0;
- gchar **suggs;
- GString *str = g_string_sized_new(256);
-
- /* ignore numbers or words starting with digits */
- if (isdigit(*word))
- return 0;
-
- /* early out if the word is spelled correctly */
- if (enchant_dict_check(sc->dict, word, -1) == 0)
- return 0;
-
- suggs = enchant_dict_suggest(sc->dict, word, -1, &n_suggs);
-
- if (suggs != NULL)
- {
- g_string_append_printf(str, "line %d: %s | ", line_number + 1, word);
-
- 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, suggs[j]);
- g_string_append_c(str, ' ');
- }
-
- if (start_pos == -1)
- start_pos = end_pos - strlen(word);
-
- p_editor->set_indicator(doc->editor, start_pos, end_pos);
- if (sc->use_msgwin)
- 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_string_free(str, TRUE);
-
- return n_suggs;
-}
-
-
-static gint process_line(GeanyDocument *doc, gint line_number, const gchar *line)
-{
- gint pos_start, pos_end;
- gint wstart, wend;
- GString *str = g_string_sized_new(256);
- gint suggestions_found = 0;
- gchar c;
-
- pos_start = p_sci->get_position_from_line(doc->editor->sci, line_number);
- /* TODO use SCI_GETLINEENDPOSITION */
- pos_end = p_sci->get_position_from_line(doc->editor->sci, line_number + 1);
-
- while (pos_start < pos_end)
- {
- wstart = p_sci->send_message(doc->editor->sci, SCI_WORDSTARTPOSITION, pos_start, TRUE);
- wend = p_sci->send_message(doc->editor->sci, SCI_WORDENDPOSITION, wstart, FALSE);
- if (wstart == wend)
- break;
- c = p_sci->get_char_at(doc->editor->sci, wstart);
- /* hopefully it's enough to check for these both */
- if (ispunct(c) || isspace(c))
- {
- pos_start++;
- continue;
- }
-
- /* ensure the string has enough allocated memory */
- if (str->len < (guint)(wend - wstart))
- g_string_set_size(str, wend - wstart);
-
- p_sci->get_text_range(doc->editor->sci, wstart, wend, str->str);
-
- suggestions_found += check_word(doc, line_number, str->str, wstart, wend);
-
- pos_start = wend + 1;
- }
-
- g_string_free(str, TRUE);
- return suggestions_found;
-}
-
-
-static void check_document(GeanyDocument *doc)
-{
- gchar *line;
- gint i;
- gint first_line, last_line;
- gchar *dict_string = NULL;
- gint suggestions_found = 0;
-
- enchant_dict_describe(sc->dict, dict_describe, &dict_string);
-
- if (p_sci->has_selection(doc->editor->sci))
- {
- first_line = p_sci->get_line_from_position(
- doc->editor->sci, p_sci->get_selection_start(doc->editor->sci));
- last_line = p_sci->get_line_from_position(
- doc->editor->sci, p_sci->get_selection_end(doc->editor->sci));
-
- if (sc->use_msgwin)
- 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);
- g_message("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(doc->editor->sci);
- if (sc->use_msgwin)
- p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("Checking file \"%s\" (using %s):"),
- DOC_FILENAME(doc), dict_string);
- g_message("Checking file \"%s\" (using %s):", DOC_FILENAME(doc), dict_string);
- }
- g_free(dict_string);
-
- for (i = first_line; i < last_line; i++)
- {
- line = p_sci->get_line(doc->editor->sci, i);
-
- suggestions_found += process_line(doc, i, line);
-
- g_free(line);
- }
-
- if (suggestions_found == 0 && sc->use_msgwin)
- p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("The checked text is spelled correctly."));
-}
-
-
-static void perform_check(GeanyDocument *doc)
-{
- p_editor->clear_indicators(doc->editor);
- if (sc->use_msgwin)
- {
- p_msgwindow->clear_tab(MSG_MESSAGE);
- p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
- }
-
- check_document(doc);
-}
-
-
-/* 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)
-{
- 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);
- GtkWidget *focusw;
-
- 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;
-
- doc = p_document->get_current();
- /* bail out if we don't have a document or if we are not in the editor widget */
- focusw = gtk_window_get_focus(GTK_WINDOW(geany->main_widgets->window));
- if (doc == NULL || focusw != GTK_WIDGET(doc->editor->sci))
- return FALSE;
-
- if (ev->keyval == '\r' &&
- p_sci->send_message(doc->editor->sci, SCI_GETEOLMODE, 0, 0) == SC_EOL_CRLF)
- { /* prevent double line checking */
- return FALSE;
- }
-
- line_number = p_sci->get_current_line(doc->editor->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->editor->sci, line_number);
-
- clear_indicators_on_line(doc, line_number);
- if (process_line(doc, line_number, line) != 0)
- {
- if (sc->use_msgwin)
- p_msgwindow->switch_tab(MSG_MESSAGE, FALSE);
- }
-
- g_string_free(str, TRUE);
- g_free(line);
-
- return FALSE;
-}
-
-
-static void broker_init_failed(void)
-{
- 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 (maybe the chosen language is not available)"));
-}
-
-
-static void dict_compare(gpointer data, gpointer user_data)
-{
- gboolean *supported = user_data;
-
- if (p_utils->str_equal(sc->default_language, data))
- *supported = TRUE;
-}
-
-
-static gboolean check_default_lang(void)
-{
- gboolean supported = FALSE;
-
- g_ptr_array_foreach(sc->dicts, dict_compare, &supported);
-
- return supported;
-}
-
-
-static void init_enchant_dict(void)
-{
- gchar *lang = sc->default_language;
-
- /* Release a previous dict object */
- if (sc->dict != NULL)
- enchant_broker_free_dict(sc->broker, sc->dict);
-
- /* Check if the stored default dictionary is (still) avaiable, fall back to the first
- * one in the list if not */
- if (! check_default_lang())
- {
- lang = g_ptr_array_index(sc->dicts, 0);
- g_warning("Stored language ('%s') could not be loaded. Falling back to '%s'",
- sc->default_language, lang);
- }
-
- /* Request new dict object */
- sc->dict = enchant_broker_request_dict(sc->broker, lang);
- if (sc->dict == NULL)
- {
- broker_init_failed();
- gtk_widget_set_sensitive(sc->menu_item, FALSE);
- }
- else
- {
- gtk_widget_set_sensitive(sc->menu_item, TRUE);
- }
-}
-
-
-static void on_menu_item_activate(GtkMenuItem *menuitem, gpointer gdata)
-{
- GeanyDocument *doc;
-
- if (sc->dict == NULL)
- return;
-
- doc = p_document->get_current();
-
- /* 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));
-
- init_enchant_dict();
-
- perform_check(doc);
-}
-
-
-static void kb_activate(guint key_id)
-{
- on_menu_item_activate(NULL, NULL);
-}
-
-
-static void locale_init(void)
-{
-#ifdef ENABLE_NLS
- gchar *locale_dir = NULL;
-
-#ifdef HAVE_LOCALE_H
- setlocale(LC_ALL, "");
-#endif
-
-#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, "\\share\\locale", NULL);
- g_free(install_dir);
-#else
- locale_dir = g_strdup(LOCALEDIR);
-#endif
-
- bindtextdomain(GETTEXT_PACKAGE, locale_dir);
- bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- textdomain(GETTEXT_PACKAGE);
- g_free(locale_dir);
-#endif
-}
-
-
-static const gchar *get_default_lang(void)
-{
- const gchar *lang = g_getenv("LANG");
- if (NZV(lang))
- {
- if (g_ascii_strncasecmp(lang, "C", 1) == 0)
- lang = "en";
- }
- else
- lang = "en";
-
- return lang;
-}
-
-
-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)
-{
- guint i;
- gchar *result = g_strdup(lang_tag);
-
- /* 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] = '_';
- }
-
- /* find duplicates and skip them */
- for (i = 0; i < sc->dicts->len; i++)
- {
- if (p_utils->str_equal(g_ptr_array_index(sc->dicts, i), result))
- return;
- }
-
- g_ptr_array_add(sc->dicts, result);
-}
-
-
-static void on_configure_response(GtkDialog *dialog, gint response, gpointer user_data)
-{
- if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
- {
- GKeyFile *config = g_key_file_new();
- gchar *data;
- gchar *config_dir = g_path_get_dirname(sc->config_file);
-
- setptr(sc->default_language, gtk_combo_box_get_active_text(GTK_COMBO_BOX(
- g_object_get_data(G_OBJECT(dialog), "combo"))));
- init_enchant_dict();
-
- sc->check_while_typing = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- g_object_get_data(G_OBJECT(dialog), "check_type"))));
-
- sc->use_msgwin = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- g_object_get_data(G_OBJECT(dialog), "check_msgwin"))));
-
- sc->show_toolbar_item = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- g_object_get_data(G_OBJECT(dialog), "check_toolbar"))));
-
- g_key_file_load_from_file(config, sc->config_file, G_KEY_FILE_NONE, NULL);
- if (sc->default_language != NULL) /* lang may be 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);
- g_key_file_set_boolean(config, "spellcheck", "use_msgwin", sc->use_msgwin);
- g_key_file_set_boolean(config, "spellcheck", "show_toolbar_item", sc->show_toolbar_item);
-
- toolbar_update();
-
- 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,
- _("Plugin configuration directory could not be created."));
- }
- else
- {
- /* write config to file */
- data = g_key_file_to_data(config, NULL, NULL);
- p_utils->write_file(sc->config_file, data);
- g_free(data);
- }
- g_free(config_dir);
- g_key_file_free(config);
- }
-}
-
-
-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(void)
-{
- 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 void create_edit_menu(void)
-{
- sc->edit_menu = gtk_image_menu_item_new_from_stock(GTK_STOCK_SPELL_CHECK, NULL);
- gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc->edit_menu);
- gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc->edit_menu, 0);
-
- sc->edit_menu_sep = gtk_separator_menu_item_new();
- gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc->edit_menu_sep);
- gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc->edit_menu_sep, 1);
-
- gtk_widget_show_all(sc->edit_menu);
-}
-
-
-static GtkWidget *create_menu(GtkWidget *sp_item)
-{
- GtkWidget *menu, *subitem;
- guint i;
-
- gtk_container_add(GTK_CONTAINER(geany->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();
- guint i;
-
- sc = g_new0(SpellCheck, 1);
-
- sc->config_file = g_strconcat(geany->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, 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);
- sc->show_toolbar_item = p_utils->get_setting_boolean(config,
- "spellcheck", "show_toolbar_item", TRUE);
- sc->use_msgwin = p_utils->get_setting_boolean(config, "spellcheck", "use_msgwin", FALSE);
- g_key_file_free(config);
-
- locale_init();
-
- sc->menu_item = gtk_image_menu_item_new_from_stock("gtk-spell-check", NULL);
- p_ui->add_document_sensitive(sc->menu_item);
-
- toolbar_update();
-
- sc->broker = enchant_broker_init();
- create_dicts_array();
- init_enchant_dict();
-
- for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
- {
- clickinfo.suggs[i] = NULL;
- }
- clickinfo.word = NULL;
-
- create_edit_menu();
- sp_item = create_menu(sc->menu_item);
- gtk_widget_show_all(sp_item);
-
- sc->signal_id = g_signal_connect(geany->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);
-}
-
-
-GtkWidget *plugin_configure(GtkDialog *dialog)
-{
- GtkWidget *label, *vbox, *combo, *check_type, *check_msgwin, *check_toolbar;
- guint i;
-
- vbox = gtk_vbox_new(FALSE, 6);
-
- check_type = gtk_check_button_new_with_label(_("Check spelling while typing"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_type), sc->check_while_typing);
- gtk_box_pack_start(GTK_BOX(vbox), check_type, FALSE, FALSE, 6);
-
- check_toolbar = gtk_check_button_new_with_label(_("Show toolbar item to toggle spell checking"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_toolbar), sc->show_toolbar_item);
- gtk_box_pack_start(GTK_BOX(vbox), check_toolbar, FALSE, FALSE, 3);
-
- check_msgwin = gtk_check_button_new_with_label(
- _("Print misspelled words and suggestions in the messages window"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_msgwin), sc->use_msgwin);
- gtk_box_pack_start(GTK_BOX(vbox), check_msgwin, FALSE, FALSE, 3);
-
- label = gtk_label_new(_("Language to use for the spell check:"));
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 3);
-
- combo = gtk_combo_box_new_text();
-
- 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 the default language couldn't be selected, select the first available language */
- if (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)) == -1)
- gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
-
- 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, 6);
-
- g_object_set_data(G_OBJECT(dialog), "combo", combo);
- g_object_set_data(G_OBJECT(dialog), "check_type", check_type);
- g_object_set_data(G_OBJECT(dialog), "check_msgwin", check_msgwin);
- g_object_set_data(G_OBJECT(dialog), "check_toolbar", check_toolbar);
- g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
-
- gtk_widget_show_all(vbox);
-
- return vbox;
-}
-
-
-void plugin_cleanup(void)
-{
- guint i;
- for (i = 0; i < MAX_MENU_SUGGESTIONS; i++)
- {
- clickinfo.suggs[i] = NULL;
- }
- g_free(clickinfo.word);
- 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(geany->main_widgets->window, sc->signal_id);
-
- gtk_widget_destroy(sc->edit_menu);
- gtk_widget_destroy(sc->edit_menu_sep);
- if (sc->toolbar_button != NULL)
- gtk_widget_destroy(GTK_WIDGET(sc->toolbar_button));
-
- enchant_broker_free_dict(sc->broker, sc->dict);
- enchant_broker_free(sc->broker);
-
- g_free(sc->default_language);
- g_free(sc->config_file);
- gtk_widget_destroy(sc->menu_item);
- g_free(sc);
-}
Added: trunk/spellcheck/src/speller.c
===================================================================
--- trunk/spellcheck/src/speller.c (rev 0)
+++ trunk/spellcheck/src/speller.c 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,352 @@
+/*
+ * speller.c - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#include "geany.h"
+#include "support.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <enchant.h>
+
+#include "plugindata.h"
+
+#include "document.h"
+#include "editor.h"
+#include "msgwindow.h"
+#include "utils.h"
+
+#include "pluginmacros.h"
+
+#include "speller.h"
+#include "scplugin.h"
+
+
+
+static EnchantBroker *speller_broker = NULL;
+static EnchantDict *speller_dict = NULL;
+
+
+
+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);
+}
+
+
+gint speller_check_word(GeanyDocument *doc, gint line_number, const gchar *word,
+ gint start_pos, gint end_pos)
+{
+ gsize j;
+ gsize n_suggs = 0;
+ gchar **suggs;
+ GString *str = g_string_sized_new(256);
+
+ /* ignore numbers or words starting with digits */
+ if (isdigit(*word))
+ return 0;
+
+ /* early out if the word is spelled correctly */
+ if (enchant_dict_check(speller_dict, word, -1) == 0)
+ return 0;
+
+ suggs = enchant_dict_suggest(speller_dict, word, -1, &n_suggs);
+
+ if (suggs != NULL)
+ {
+ g_string_append_printf(str, "line %d: %s | ", line_number + 1, word);
+
+ 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, suggs[j]);
+ g_string_append_c(str, ' ');
+ }
+
+ if (start_pos == -1)
+ start_pos = end_pos - strlen(word);
+
+ p_editor->set_indicator(doc->editor, start_pos, end_pos);
+ if (sc->use_msgwin)
+ p_msgwindow->msg_add(COLOR_RED, line_number + 1, doc, "%s", str->str);
+
+ if (suggs != NULL && n_suggs)
+ enchant_dict_free_string_list(speller_dict, suggs);
+ }
+ g_string_free(str, TRUE);
+
+ return n_suggs;
+}
+
+
+gint speller_process_line(GeanyDocument *doc, gint line_number, const gchar *line)
+{
+ gint pos_start, pos_end;
+ gint wstart, wend;
+ GString *str = g_string_sized_new(256);
+ gint suggestions_found = 0;
+ gchar c;
+
+ pos_start = p_sci->get_position_from_line(doc->editor->sci, line_number);
+ /* TODO use SCI_GETLINEENDPOSITION */
+ pos_end = p_sci->get_position_from_line(doc->editor->sci, line_number + 1);
+
+ while (pos_start < pos_end)
+ {
+ wstart = p_sci->send_message(doc->editor->sci, SCI_WORDSTARTPOSITION, pos_start, TRUE);
+ wend = p_sci->send_message(doc->editor->sci, SCI_WORDENDPOSITION, wstart, FALSE);
+ if (wstart == wend)
+ break;
+ c = p_sci->get_char_at(doc->editor->sci, wstart);
+ /* hopefully it's enough to check for these both */
+ if (ispunct(c) || isspace(c))
+ {
+ pos_start++;
+ continue;
+ }
+
+ /* ensure the string has enough allocated memory */
+ if (str->len < (guint)(wend - wstart))
+ g_string_set_size(str, wend - wstart);
+
+ p_sci->get_text_range(doc->editor->sci, wstart, wend, str->str);
+
+ suggestions_found += speller_check_word(doc, line_number, str->str, wstart, wend);
+
+ pos_start = wend + 1;
+ }
+
+ g_string_free(str, TRUE);
+ return suggestions_found;
+}
+
+
+void speller_check_document(GeanyDocument *doc)
+{
+ gchar *line;
+ gint i;
+ gint first_line, last_line;
+ gchar *dict_string = NULL;
+ gint suggestions_found = 0;
+
+ enchant_dict_describe(speller_dict, dict_describe, &dict_string);
+
+ if (p_sci->has_selection(doc->editor->sci))
+ {
+ first_line = p_sci->get_line_from_position(
+ doc->editor->sci, p_sci->get_selection_start(doc->editor->sci));
+ last_line = p_sci->get_line_from_position(
+ doc->editor->sci, p_sci->get_selection_end(doc->editor->sci));
+
+ if (sc->use_msgwin)
+ 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);
+ g_message("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(doc->editor->sci);
+ if (sc->use_msgwin)
+ p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("Checking file \"%s\" (using %s):"),
+ DOC_FILENAME(doc), dict_string);
+ g_message("Checking file \"%s\" (using %s):", DOC_FILENAME(doc), dict_string);
+ }
+ g_free(dict_string);
+
+ for (i = first_line; i < last_line; i++)
+ {
+ line = p_sci->get_line(doc->editor->sci, i);
+
+ suggestions_found += speller_process_line(doc, i, line);
+
+ g_free(line);
+ }
+
+ if (suggestions_found == 0 && sc->use_msgwin)
+ p_msgwindow->msg_add(COLOR_BLUE, -1, NULL, _("The checked text is spelled correctly."));
+}
+
+
+static void broker_init_failed(void)
+{
+ const gchar *err = enchant_broker_get_error(speller_broker);
+ p_dialogs->show_msgbox(GTK_MESSAGE_ERROR,
+ _("The Enchant library couldn't be initialized (%s)."),
+ (err != NULL) ? err : _("unknown error (maybe the chosen language is not available)"));
+}
+
+
+static void dict_compare(gpointer data, gpointer user_data)
+{
+ gboolean *supported = user_data;
+
+ if (p_utils->str_equal(sc->default_language, data))
+ *supported = TRUE;
+}
+
+
+static gboolean check_default_lang(void)
+{
+ gboolean supported = FALSE;
+
+ g_ptr_array_foreach(sc->dicts, dict_compare, &supported);
+
+ return supported;
+}
+
+
+void speller_reinit_enchant_dict(void)
+{
+ gchar *lang = sc->default_language;
+
+ /* Release a previous dict object */
+ if (speller_dict != NULL)
+ enchant_broker_free_dict(speller_broker, speller_dict);
+
+ /* Check if the stored default dictionary is (still) avaiable, fall back to the first
+ * one in the list if not */
+ if (! check_default_lang())
+ {
+ lang = g_ptr_array_index(sc->dicts, 0);
+ g_warning("Stored language ('%s') could not be loaded. Falling back to '%s'",
+ sc->default_language, lang);
+ }
+
+ /* Request new dict object */
+ speller_dict = enchant_broker_request_dict(speller_broker, lang);
+ if (speller_dict == NULL)
+ {
+ broker_init_failed();
+ gtk_widget_set_sensitive(sc->menu_item, FALSE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive(sc->menu_item, TRUE);
+ }
+}
+
+
+const gchar *speller_get_default_lang(void)
+{
+ const gchar *lang = g_getenv("LANG");
+ if (NZV(lang))
+ {
+ if (g_ascii_strncasecmp(lang, "C", 1) == 0)
+ lang = "en";
+ }
+ else
+ lang = "en";
+
+ return lang;
+}
+
+
+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)
+{
+ guint i;
+ gchar *result = g_strdup(lang_tag);
+
+ /* 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] = '_';
+ }
+
+ /* find duplicates and skip them */
+ for (i = 0; i < sc->dicts->len; i++)
+ {
+ if (p_utils->str_equal(g_ptr_array_index(sc->dicts, i), result))
+ return;
+ }
+
+ g_ptr_array_add(sc->dicts, result);
+}
+
+
+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(void)
+{
+ sc->dicts = g_ptr_array_new();
+
+ enchant_broker_list_dicts(speller_broker, add_dict_array, sc->dicts);
+
+ g_ptr_array_sort(sc->dicts, sort_dicts);
+}
+
+
+void speller_dict_free_string_list(gchar **tmp_suggs)
+{
+ enchant_dict_free_string_list(speller_dict, tmp_suggs);
+}
+
+
+void speller_add_word(const gchar *word)
+{
+ enchant_dict_add_to_pwl(speller_dict, clickinfo.word, -1);
+
+}
+
+gboolean speller_dict_check(const gchar *word)
+{
+ return enchant_dict_check(speller_dict, word, -1);
+}
+
+
+gchar **speller_dict_suggest(const gchar *word, gsize *n_suggs)
+{
+ return enchant_dict_suggest(speller_dict, word, -1, n_suggs);
+}
+
+
+void speller_init(void)
+{
+ speller_broker = enchant_broker_init();
+
+ create_dicts_array();
+
+ speller_reinit_enchant_dict();
+}
+
+
+void speller_free(void)
+{
+ enchant_broker_free_dict(speller_broker, speller_dict);
+ enchant_broker_free(speller_broker);
+}
Property changes on: trunk/spellcheck/src/speller.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
Added: trunk/spellcheck/src/speller.h
===================================================================
--- trunk/spellcheck/src/speller.h (rev 0)
+++ trunk/spellcheck/src/speller.h 2008-10-17 15:20:12 UTC (rev 212)
@@ -0,0 +1,53 @@
+/*
+ * speller.h - this file is part of Spellcheck, a Geany plugin
+ *
+ * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ * Copyright 2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+
+#ifndef SC_SPELLER_H
+#define SC_SPELLER_H 1
+
+
+gint speller_check_word(GeanyDocument *doc, gint line_number, const gchar *word,
+ gint start_pos, gint end_pos);
+
+gint speller_process_line(GeanyDocument *doc, gint line_number, const gchar *line);
+
+void speller_check_document(GeanyDocument *doc);
+
+void speller_reinit_enchant_dict(void);
+
+const gchar *speller_get_default_lang(void);
+
+void speller_dict_free_string_list(gchar **tmp_suggs);
+
+void speller_add_word(const gchar *word);
+
+gboolean speller_dict_check(const gchar *word);
+
+gchar **speller_dict_suggest(const gchar *word, gsize *n_suggs);
+
+void speller_init(void);
+
+void speller_free(void);
+
+#endif
Property changes on: trunk/spellcheck/src/speller.h
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision
Added: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Plugins-Commits
mailing list