index fdbe562fec09b052ff7cab5322f4631f525729d3..4712d99265b781222c7ae07201863f00991b9c6a 100644 (file)
*/
/* Authors:
* bulia byak <bulia@users.sf.net>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Abhishek Sharma
*
* Copyright (C) 2009 Authors
*
#include "widgets/icon.h"
#include "message-stack.h"
-#include <aspell.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
#include <xml/repr.h>
#include "display/canvas-bpath.h"
#include "display/curve.h"
+#include "document-undo.h"
+
+#ifdef HAVE_ASPELL
+#include <aspell.h>
#ifdef WIN32
#include <windows.h>
#endif
+using Inkscape::DocumentUndo;
+
#define MIN_ONSCREEN_DISTANCE 50
static GtkWidget *dlg = NULL;
// plain-C GTK callbacks.
static SPDesktop *_desktop = NULL;
-static AspellSpeller *_speller = NULL;
static SPObject *_root;
+static AspellSpeller *_speller = NULL;
+static AspellSpeller *_speller2 = NULL;
+static AspellSpeller *_speller3 = NULL;
+
// list of canvasitems (currently just rects) that mark misspelled things on canvas
static GSList *_rects = NULL;
// true if the spell checker dialog has changed text, to suppress modified callback
static bool _local_change = false;
+static Inkscape::Preferences *_prefs = NULL;
+
+static gchar *_lang = NULL;
+static gchar *_lang2 = NULL;
+static gchar *_lang3 = NULL;
void spellcheck_clear_rects()
_rects = NULL;
}
+void spellcheck_clear_langs()
+{
+ if (_lang) {
+ g_free(_lang);
+ _lang = NULL;
+ }
+ if (_lang2) {
+ g_free(_lang2);
+ _lang2 = NULL;
+ }
+ if (_lang3) {
+ g_free(_lang3);
+ _lang3 = NULL;
+ }
+}
+
void
spellcheck_disconnect()
{
static void sp_spellcheck_dialog_destroy(GtkObject *object, gpointer)
{
spellcheck_clear_rects();
+ spellcheck_clear_langs();
spellcheck_disconnect();
sp_signal_disconnect_by_data (INKSCAPE, object);
static gboolean sp_spellcheck_dialog_delete(GtkObject *, GdkEvent *, gpointer /*data*/)
{
spellcheck_clear_rects();
+ spellcheck_clear_langs();
spellcheck_disconnect();
gtk_window_get_position (GTK_WINDOW (dlg), &x, &y);
@@ -142,11 +175,10 @@ static gboolean sp_spellcheck_dialog_delete(GtkObject *, GdkEvent *, gpointer /*
if (x<0) x=0;
if (y<0) y=0;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setInt(prefs_path + "x", x);
- prefs->setInt(prefs_path + "y", y);
- prefs->setInt(prefs_path + "w", w);
- prefs->setInt(prefs_path + "h", h);
+ _prefs->setInt(prefs_path + "x", x);
+ _prefs->setInt(prefs_path + "y", y);
+ _prefs->setInt(prefs_path + "w", w);
+ _prefs->setInt(prefs_path + "h", h);
return FALSE; // which means, go ahead and destroy it
}
if (SP_IS_DEFS(r))
return l; // we're not interested in items in defs
- if (!strcmp (SP_OBJECT_REPR (r)->name(), "svg:metadata"))
+ if (!strcmp(r->getRepr()->name(), "svg:metadata")) {
return l; // we're not interested in metadata
+ }
- for (SPObject *child = sp_object_first_child(r); child; child = SP_OBJECT_NEXT (child)) {
+ for (SPObject *child = r->firstChild(); child; child = child->next) {
if (SP_IS_ITEM (child) && !SP_OBJECT_IS_CLONED (child) && !_desktop->isLayer(SP_ITEM(child))) {
if ((hidden || !_desktop->itemIsHidden(SP_ITEM(child))) && (locked || !SP_ITEM(child)->isLocked())) {
if (SP_IS_TEXT(child) || SP_IS_FLOWTEXT(child))
SPItem *i1 = SP_ITEM(a);
SPItem *i2 = SP_ITEM(b);
- Geom::OptRect bbox1 = i1->getBounds(sp_item_i2d_affine(i1));
- Geom::OptRect bbox2 = i2->getBounds(sp_item_i2d_affine(i2));
+ Geom::OptRect bbox1 = i1->getBounds(i1->i2d_affine());
+ Geom::OptRect bbox2 = i2->getBounds(i2->i2d_affine());
if (!bbox1 || !bbox2) {
return 0;
}
spellcheck_sensitive("suggestions", FALSE);
spellcheck_sensitive("b_accept", FALSE);
spellcheck_sensitive("b_ignore", FALSE);
+ spellcheck_sensitive("b_ignore_once", FALSE);
spellcheck_sensitive("b_add", FALSE);
+ spellcheck_sensitive("addto_langs", FALSE);
spellcheck_sensitive("b_start", FALSE);
- _stops = 0;
- _adds = 0;
-
- spellcheck_clear_rects();
-
- AspellConfig *config = new_aspell_config();
-
#ifdef WIN32
// on windows, dictionaries are in a lib/aspell-0.60 subdir off inkscape's executable dir;
// this is some black magick to find out the executable path to give it to aspell
if (slashPos)
*slashPos = '\0';
g_print ("%s\n", exeName);
- aspell_config_replace(config, "prefix", exeName);
#endif
- // take language from prefs
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring lang = prefs->getString(prefs_path + "lang");
- if (lang != "")
- aspell_config_replace(config, "lang", lang.c_str());
- else
- aspell_config_replace(config, "lang", "en_US");
+ _stops = 0;
+ _adds = 0;
+ spellcheck_clear_rects();
+ {
+ AspellConfig *config = new_aspell_config();
+#ifdef WIN32
+ aspell_config_replace(config, "prefix", exeName);
+#endif
+ aspell_config_replace(config, "lang", _lang);
aspell_config_replace(config, "encoding", "UTF-8");
-
- // create speller
AspellCanHaveError *ret = new_aspell_speller(config);
delete_aspell_config(config);
if (aspell_error(ret) != 0) {
return false;
}
_speller = to_aspell_speller(ret);
+ }
+
+ if (_lang2) {
+ AspellConfig *config = new_aspell_config();
+#ifdef WIN32
+ aspell_config_replace(config, "prefix", exeName);
+#endif
+ aspell_config_replace(config, "lang", _lang2);
+ aspell_config_replace(config, "encoding", "UTF-8");
+ AspellCanHaveError *ret = new_aspell_speller(config);
+ delete_aspell_config(config);
+ if (aspell_error(ret) != 0) {
+ g_warning("Error: %s\n", aspell_error_message(ret));
+ delete_aspell_can_have_error(ret);
+ return false;
+ }
+ _speller2 = to_aspell_speller(ret);
+ }
+
+ if (_lang3) {
+ AspellConfig *config = new_aspell_config();
+#ifdef WIN32
+ aspell_config_replace(config, "prefix", exeName);
+#endif
+ aspell_config_replace(config, "lang", _lang3);
+ aspell_config_replace(config, "encoding", "UTF-8");
+ AspellCanHaveError *ret = new_aspell_speller(config);
+ delete_aspell_config(config);
+ if (aspell_error(ret) != 0) {
+ g_warning("Error: %s\n", aspell_error_message(ret));
+ delete_aspell_can_have_error(ret);
+ return false;
+ }
+ _speller3 = to_aspell_speller(ret);
+ }
- _root = SP_DOCUMENT_ROOT (sp_desktop_document (desktop));
+ _root = sp_desktop_document(desktop)->getRoot();
// empty the list of objects we've checked
g_slist_free (_seen_objects);
aspell_speller_save_all_word_lists(_speller);
delete_aspell_speller(_speller);
_speller = NULL;
+ if (_speller2) {
+ aspell_speller_save_all_word_lists(_speller2);
+ delete_aspell_speller(_speller2);
+ _speller2 = NULL;
+ }
+ if (_speller3) {
+ aspell_speller_save_all_word_lists(_speller3);
+ delete_aspell_speller(_speller3);
+ _speller3 = NULL;
+ }
spellcheck_clear_rects();
spellcheck_disconnect();
spellcheck_sensitive("suggestions", FALSE);
spellcheck_sensitive("b_accept", FALSE);
spellcheck_sensitive("b_ignore", FALSE);
+ spellcheck_sensitive("b_ignore_once", FALSE);
spellcheck_sensitive("b_add", FALSE);
+ spellcheck_sensitive("addto_langs", FALSE);
spellcheck_sensitive("b_stop", FALSE);
spellcheck_sensitive("b_start", TRUE);
}
// skip words containing digits
- bool digits = false;
- for (gchar *c = (gchar *) _word.c_str(); *c; c++) {
- if (g_ascii_isdigit(*c)) {
- digits = true;
+ if (_prefs->getInt(prefs_path + "ignorenumbers") != 0) {
+ bool digits = false;
+ for (unsigned int i = 0; i < _word.size(); i++) {
+ if (g_unichar_isdigit(_word[i])) {
+ digits = true;
+ break;
+ }
+ }
+ if (digits) {
+ return false;
}
- }
- if (digits) {
- return false;
}
- //g_print ("%s\n", word.c_str());
+ // skip ALL-CAPS words
+ if (_prefs->getInt(prefs_path + "ignoreallcaps") != 0) {
+ bool allcaps = true;
+ for (unsigned int i = 0; i < _word.size(); i++) {
+ if (!g_unichar_isupper(_word[i])) {
+ allcaps = false;
+ break;
+ }
+ }
+ if (allcaps) {
+ return false;
+ }
+ }
+ // run it by all active spellers
int have = aspell_speller_check(_speller, _word.c_str(), -1);
- if (have == 0) { // not found
+ if (_speller2)
+ have += aspell_speller_check(_speller2, _word.c_str(), -1);
+ if (_speller3)
+ have += aspell_speller_check(_speller3, _word.c_str(), -1);
+
+ if (have == 0) { // not found in any!
_stops ++;
_desktop->clearWaitingCursor();
// display it in window
{
GtkWidget *l = GTK_WIDGET(gtk_object_get_data (GTK_OBJECT (dlg), "banner"));
- gchar *label = g_strdup_printf(_("Not in dictionary: <b>%s</b>"), _word.c_str());
+ Glib::ustring langs = _lang;
+ if (_lang2)
+ langs = langs + ", " + _lang2;
+ if (_lang3)
+ langs = langs + ", " + _lang3;
+ gchar *label = g_strdup_printf(_("Not in dictionary (%s): <b>%s</b>"), langs.c_str(), _word.c_str());
gtk_label_set_markup (GTK_LABEL(l), label);
g_free(label);
}
spellcheck_sensitive("suggestions", TRUE);
spellcheck_sensitive("b_ignore", TRUE);
+ spellcheck_sensitive("b_ignore_once", TRUE);
spellcheck_sensitive("b_add", TRUE);
+ spellcheck_sensitive("addto_langs", TRUE);
spellcheck_sensitive("b_stop", TRUE);
// draw rect
std::vector<Geom::Point> points =
- _layout->createSelectionShape(_begin_w, _end_w, sp_item_i2d_affine(_text));
+ _layout->createSelectionShape(_begin_w, _end_w, _text->i2d_affine());
Geom::Point tl, br;
tl = br = points.front();
for (unsigned i = 0 ; i < points.size() ; i ++) {
}
_desktop->scroll_to_point (scrollto, 1.0);
- // if in Text tool, position cursor to the beginnign of word
+ // select text; if in Text tool, position cursor to the beginning of word
// unless it is already in the word
+ if (_desktop->selection->singleItem() != _text)
+ _desktop->selection->set (_text);
if (tools_isactive(_desktop, TOOLS_TEXT)) {
Inkscape::Text::Layout::iterator *cursor =
sp_text_context_get_cursor_position(SP_TEXT_CONTEXT(_desktop->event_context), _text);
_desktop->selection->set (_text);
else if (*cursor <= _begin_w || *cursor >= _end_w)
sp_text_context_place_cursor (SP_TEXT_CONTEXT(_desktop->event_context), _text, _begin_w);
- } else { // just select the object
- _desktop->selection->set (_text);
- }
+ }
// get suggestions
{
- const AspellWordList *wl = aspell_speller_suggest(_speller, _word.c_str(), -1);
- AspellStringEnumeration * els = aspell_word_list_elements(wl);
- const char *sugg;
GtkTreeView *tree_view =
GTK_TREE_VIEW(gtk_object_get_data (GTK_OBJECT (dlg), "suggestions"));
GtkListStore *model = gtk_list_store_new (1, G_TYPE_STRING);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
+
+ {
+ const AspellWordList *wl = aspell_speller_suggest(_speller, _word.c_str(), -1);
+ AspellStringEnumeration * els = aspell_word_list_elements(wl);
+ const char *sugg;
+ GtkTreeIter iter;
+ while ((sugg = aspell_string_enumeration_next(els)) != 0) {
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ 0, sugg,
+ -1);
+ }
+ delete_aspell_string_enumeration(els);
+ }
+
+ if (_speller2) {
+ const AspellWordList *wl = aspell_speller_suggest(_speller2, _word.c_str(), -1);
+ AspellStringEnumeration * els = aspell_word_list_elements(wl);
+ const char *sugg;
GtkTreeIter iter;
while ((sugg = aspell_string_enumeration_next(els)) != 0) {
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-1);
}
delete_aspell_string_enumeration(els);
+ }
+
+ if (_speller3) {
+ const AspellWordList *wl = aspell_speller_suggest(_speller3, _word.c_str(), -1);
+ AspellStringEnumeration * els = aspell_word_list_elements(wl);
+ const char *sugg;
+ GtkTreeIter iter;
+ while ((sugg = aspell_string_enumeration_next(els)) != 0) {
+ gtk_list_store_append (GTK_LIST_STORE (model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (model),
+ &iter,
+ 0, sugg,
+ -1);
+ }
+ delete_aspell_string_enumeration(els);
+ }
+
spellcheck_sensitive("b_accept", FALSE); // gray it out until something is chosen
}
// find the end of the word anew
_end_w = _begin_w;
_end_w.nextEndOfWord();
- sp_document_done (sp_desktop_document(_desktop), SP_VERB_CONTEXT_TEXT,
- _("Fix spelling"));
+ DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_TEXT,
+ _("Fix spelling"));
}
}
sp_spellcheck_ignore (GObject */*obj*/, GObject */*dlg*/)
{
aspell_speller_add_to_session(_speller, _word.c_str(), -1);
+ if (_speller2)
+ aspell_speller_add_to_session(_speller2, _word.c_str(), -1);
+ if (_speller3)
+ aspell_speller_add_to_session(_speller3, _word.c_str(), -1);
+ spellcheck_delete_last_rect ();
+
+ do_spellcheck(); // next word or end
+}
+
+void
+sp_spellcheck_ignore_once (GObject */*obj*/, GObject */*dlg*/)
+{
spellcheck_delete_last_rect ();
do_spellcheck(); // next word or end
sp_spellcheck_add (GObject */*obj*/, GObject */*dlg*/)
{
_adds++;
- aspell_speller_add_to_personal(_speller, _word.c_str(), -1);
+ GtkComboBox *cbox =
+ GTK_COMBO_BOX(gtk_object_get_data (GTK_OBJECT (dlg), "addto_langs"));
+ gint num = gtk_combo_box_get_active(cbox);
+ switch (num) {
+ case 0:
+ aspell_speller_add_to_personal(_speller, _word.c_str(), -1);
+ break;
+ case 1:
+ if (_speller2)
+ aspell_speller_add_to_personal(_speller2, _word.c_str(), -1);
+ break;
+ case 2:
+ if (_speller3)
+ aspell_speller_add_to_personal(_speller3, _word.c_str(), -1);
+ break;
+ default:
+ break;
+ }
+
spellcheck_delete_last_rect ();
do_spellcheck(); // next word or end
@@ -703,20 +869,35 @@ static gboolean spellcheck_desktop_deactivated(Inkscape::Application */*applicat
void
sp_spellcheck_dialog (void)
{
+ _prefs = Inkscape::Preferences::get();
+
+ // take languages from prefs
+ _lang = _lang2 = _lang3 = NULL;
+ Glib::ustring lang = _prefs->getString(prefs_path + "lang");
+ if (lang != "")
+ _lang = g_strdup(lang.c_str());
+ else
+ _lang = g_strdup("en");
+ lang = _prefs->getString(prefs_path + "lang2");
+ if (lang != "")
+ _lang2 = g_strdup(lang.c_str());
+ lang = _prefs->getString(prefs_path + "lang3");
+ if (lang != "")
+ _lang3 = g_strdup(lang.c_str());
+
if (!dlg)
{
gchar title[500];
sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_DIALOG_SPELLCHECK), title);
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
dlg = sp_window_new (title, TRUE);
if (x == -1000 || y == -1000) {
- x = prefs->getInt(prefs_path + "x", -1000);
- y = prefs->getInt(prefs_path + "y", -1000);
+ x = _prefs->getInt(prefs_path + "x", -1000);
+ y = _prefs->getInt(prefs_path + "y", -1000);
}
if (w ==0 || h == 0) {
- w = prefs->getInt(prefs_path + "w", 0);
- h = prefs->getInt(prefs_path + "h", 0);
+ w = _prefs->getInt(prefs_path + "w", 0);
+ h = _prefs->getInt(prefs_path + "h", 0);
}
if (w && h)
GtkWidget *hb = gtk_hbox_new (FALSE, 0);
sp_spellcheck_new_button (dlg, hb, _("_Accept"), tt, _("Accept the chosen suggestion"),
sp_spellcheck_accept, "b_accept");
+ sp_spellcheck_new_button (dlg, hb, _("_Ignore once"), tt, _("Ignore this word only once"),
+ sp_spellcheck_ignore_once, "b_ignore_once");
sp_spellcheck_new_button (dlg, hb, _("_Ignore"), tt, _("Ignore this word in this session"),
sp_spellcheck_ignore, "b_ignore");
- sp_spellcheck_new_button (dlg, hb, _("A_dd"), tt, _("Add this word to the dictionary"),
+ gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
+ }
+
+ {
+ GtkWidget *hb = gtk_hbox_new (FALSE, 0);
+ sp_spellcheck_new_button (dlg, hb, _("A_dd to dictionary:"), tt, _("Add this word to the chosen dictionary"),
sp_spellcheck_add, "b_add");
+ GtkComboBox *cbox = GTK_COMBO_BOX (gtk_combo_box_new_text());
+ gtk_combo_box_append_text (cbox, _lang);
+ if (_lang2) {
+ gtk_combo_box_append_text (cbox, _lang2);
+ }
+ if (_lang3) {
+ gtk_combo_box_append_text (cbox, _lang3);
+ }
+ gtk_combo_box_set_active (cbox, 0);
+ gtk_widget_show_all (GTK_WIDGET(cbox));
+ g_object_set_data (G_OBJECT (dlg), "addto_langs", cbox);
+ gtk_box_pack_start (GTK_BOX (hb), GTK_WIDGET(cbox), TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
}
sp_spellcheck_start (NULL, NULL);
}
+#else
+
+void sp_spellcheck_dialog (void) {}
+
+#endif // HAVE_ASPELL
+
/*
Local Variables:
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :