[gedit/wip/spell-checking] spell: factor out a SpellNavigator
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit/wip/spell-checking] spell: factor out a SpellNavigator
- Date: Sun, 2 Aug 2015 13:01:42 +0000 (UTC)
commit 648282110f6309e205d9990963569e8fbab660da
Author: Sébastien Wilmet <swilmet gnome org>
Date: Sat Aug 1 20:00:33 2015 +0200
spell: factor out a SpellNavigator
The idea is to make more code reusable. gedit-spell-plugin is specific
to gedit.
GeditSpellNavigator is an interface.
GeditSpellNavigatorGtv implements the interface for a GtkTextView.
A later commit will remove the SpellCheckerDialog signals, and use
directly a SpellNavigator. That way, to support other types of buffers
(e.g. for WebKitGTK+), one just need to implement a new SpellNavigator.
Implementing a new spell checker widget is also easy, for example
instead of a dialog window, one can implement a new widget that could be
packed below an headerbar.
The UI and the logic are separated.
plugins/spell/Makefile.am | 4 +
plugins/spell/gedit-spell-navigator-gtv.c | 289 +++++++++++++++++
plugins/spell/gedit-spell-navigator-gtv.h | 47 +++
plugins/spell/gedit-spell-navigator.c | 97 ++++++
plugins/spell/gedit-spell-navigator.h | 62 ++++
plugins/spell/gedit-spell-plugin.c | 487 ++---------------------------
6 files changed, 522 insertions(+), 464 deletions(-)
---
diff --git a/plugins/spell/Makefile.am b/plugins/spell/Makefile.am
index c80ef77..5d6d667 100644
--- a/plugins/spell/Makefile.am
+++ b/plugins/spell/Makefile.am
@@ -34,6 +34,10 @@ plugins_spell_libspell_la_SOURCES = \
plugins/spell/gedit-spell-checker-language.h \
plugins/spell/gedit-spell-language-dialog.c \
plugins/spell/gedit-spell-language-dialog.h \
+ plugins/spell/gedit-spell-navigator.c \
+ plugins/spell/gedit-spell-navigator.h \
+ plugins/spell/gedit-spell-navigator-gtv.c \
+ plugins/spell/gedit-spell-navigator-gtv.h \
plugins/spell/gedit-automatic-spell-checker.c \
plugins/spell/gedit-automatic-spell-checker.h \
plugins/spell/gedit-spell-utils.c \
diff --git a/plugins/spell/gedit-spell-navigator-gtv.c b/plugins/spell/gedit-spell-navigator-gtv.c
new file mode 100644
index 0000000..986bbd0
--- /dev/null
+++ b/plugins/spell/gedit-spell-navigator-gtv.c
@@ -0,0 +1,289 @@
+/*
+ * gedit-spell-navigator-gtv.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-spell-navigator-gtv.h"
+#include "gedit-spell-utils.h"
+
+typedef struct _GeditSpellNavigatorGtvPrivate GeditSpellNavigatorGtvPrivate;
+
+struct _GeditSpellNavigatorGtvPrivate
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GeditSpellChecker *spell_checker;
+
+ /* Delimit the region to spell check. */
+ GtkTextMark *start_mark;
+ GtkTextMark *end_mark;
+
+ /* Current location, at the start of a misspelled word. */
+ GtkTextMark *current_mark;
+};
+
+enum
+{
+ PROP_0,
+ PROP_VIEW,
+ PROP_SPELL_CHECKER,
+};
+
+static void gedit_spell_navigator_iface_init (gpointer g_iface, gpointer iface_data);
+
+G_DEFINE_TYPE_WITH_CODE (GeditSpellNavigatorGtv,
+ gedit_spell_navigator_gtv,
+ G_TYPE_OBJECT,
+ G_ADD_PRIVATE (GeditSpellNavigatorGtv)
+ G_IMPLEMENT_INTERFACE (GEDIT_TYPE_SPELL_NAVIGATOR,
+ gedit_spell_navigator_iface_init))
+
+static void
+init_boundaries (GeditSpellNavigatorGtv *navigator)
+{
+ GeditSpellNavigatorGtvPrivate *priv;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ priv = gedit_spell_navigator_gtv_get_instance_private (navigator);
+
+ g_return_if_fail (priv->start_mark == NULL);
+ g_return_if_fail (priv->end_mark == NULL);
+
+ if (!gtk_text_buffer_get_selection_bounds (priv->buffer, &start, &end))
+ {
+ /* No selection, take the whole buffer. */
+ gtk_text_buffer_get_bounds (priv->buffer, &start, &end);
+ }
+
+ if (gtk_text_iter_inside_word (&start) &&
+ !gtk_text_iter_starts_word (&start))
+ {
+ gtk_text_iter_backward_word_start (&start);
+ }
+
+ if (gtk_text_iter_inside_word (&end))
+ {
+ gtk_text_iter_forward_word_end (&end);
+ }
+
+ priv->start_mark = gtk_text_buffer_create_mark (priv->buffer, NULL, &start, TRUE);
+ priv->end_mark = gtk_text_buffer_create_mark (priv->buffer, NULL, &end, FALSE);
+}
+
+static void
+set_view (GeditSpellNavigatorGtv *navigator,
+ GtkTextView *view)
+{
+ GeditSpellNavigatorGtvPrivate *priv;
+
+ priv = gedit_spell_navigator_gtv_get_instance_private (navigator);
+
+ g_return_if_fail (priv->view == NULL);
+ g_return_if_fail (priv->buffer == NULL);
+
+ priv->view = g_object_ref (view);
+ priv->buffer = g_object_ref (gtk_text_view_get_buffer (view));
+
+ init_boundaries (navigator);
+
+ g_object_notify (G_OBJECT (navigator), "view");
+}
+
+static void
+set_spell_checker (GeditSpellNavigatorGtv *navigator,
+ GeditSpellChecker *spell_checker)
+{
+ GeditSpellNavigatorGtvPrivate *priv;
+
+ priv = gedit_spell_navigator_gtv_get_instance_private (navigator);
+
+ if (g_set_object (&priv->spell_checker, spell_checker))
+ {
+ g_object_notify (G_OBJECT (navigator), "spell-checker");
+ }
+}
+
+static void
+gedit_spell_navigator_gtv_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeditSpellNavigatorGtvPrivate *priv;
+
+ priv = gedit_spell_navigator_gtv_get_instance_private (GEDIT_SPELL_NAVIGATOR_GTV (object));
+
+ switch (prop_id)
+ {
+ case PROP_VIEW:
+ g_value_set_object (value, priv->view);
+ break;
+
+ case PROP_SPELL_CHECKER:
+ g_value_set_object (value, priv->spell_checker);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_spell_navigator_gtv_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeditSpellNavigatorGtv *navigator = GEDIT_SPELL_NAVIGATOR_GTV (object);
+
+ switch (prop_id)
+ {
+ case PROP_VIEW:
+ set_view (navigator, g_value_get_object (value));
+ break;
+
+ case PROP_SPELL_CHECKER:
+ set_spell_checker (navigator, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gedit_spell_navigator_gtv_dispose (GObject *object)
+{
+ GeditSpellNavigatorGtvPrivate *priv;
+
+ priv = gedit_spell_navigator_gtv_get_instance_private (GEDIT_SPELL_NAVIGATOR_GTV (object));
+
+ g_clear_object (&priv->view);
+ g_clear_object (&priv->spell_checker);
+
+ if (priv->buffer != NULL)
+ {
+ if (priv->start_mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (priv->buffer, priv->start_mark);
+ priv->start_mark = NULL;
+ }
+
+ if (priv->end_mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (priv->buffer, priv->end_mark);
+ priv->end_mark = NULL;
+ }
+
+ if (priv->current_mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (priv->buffer, priv->current_mark);
+ priv->current_mark = NULL;
+ }
+
+ g_object_unref (priv->buffer);
+ priv->buffer = NULL;
+ }
+
+ G_OBJECT_CLASS (gedit_spell_navigator_gtv_parent_class)->dispose (object);
+}
+
+#if 0
+static void
+gedit_spell_navigator_gtv_finalize (GObject *object)
+{
+
+ G_OBJECT_CLASS (gedit_spell_navigator_gtv_parent_class)->finalize (object);
+}
+#endif
+
+static void
+gedit_spell_navigator_gtv_class_init (GeditSpellNavigatorGtvClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gedit_spell_navigator_gtv_get_property;
+ object_class->set_property = gedit_spell_navigator_gtv_set_property;
+ object_class->dispose = gedit_spell_navigator_gtv_dispose;
+
+ g_object_class_install_property (object_class,
+ PROP_VIEW,
+ g_param_spec_object ("view",
+ "View",
+ "",
+ GTK_TYPE_TEXT_VIEW,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_override_property (object_class, PROP_SPELL_CHECKER, "spell-checker");
+}
+
+static void
+gedit_spell_navigator_gtv_init (GeditSpellNavigatorGtv *self)
+{
+}
+
+static gchar *
+gedit_spell_navigator_gtv_get_next_misspelled_word (GeditSpellNavigator *navigator)
+{
+ return NULL;
+}
+
+static void
+gedit_spell_navigator_gtv_change (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+}
+
+static void
+gedit_spell_navigator_gtv_change_all (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+}
+
+static void
+gedit_spell_navigator_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GeditSpellNavigatorInterface *iface = g_iface;
+
+ iface->get_next_misspelled_word = gedit_spell_navigator_gtv_get_next_misspelled_word;
+ iface->change = gedit_spell_navigator_gtv_change;
+ iface->change_all = gedit_spell_navigator_gtv_change_all;
+}
+
+GeditSpellNavigator *
+gedit_spell_navigator_gtv_new (GtkTextView *view,
+ GeditSpellChecker *spell_checker)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (view), NULL);
+ g_return_val_if_fail (GEDIT_IS_SPELL_CHECKER (spell_checker), NULL);
+
+ return g_object_new (GEDIT_TYPE_SPELL_NAVIGATOR_GTV,
+ "view", view,
+ "spell-checker", spell_checker,
+ NULL);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/plugins/spell/gedit-spell-navigator-gtv.h b/plugins/spell/gedit-spell-navigator-gtv.h
new file mode 100644
index 0000000..487e3fd
--- /dev/null
+++ b/plugins/spell/gedit-spell-navigator-gtv.h
@@ -0,0 +1,47 @@
+/*
+ * gedit-spell-navigator-gtv.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_SPELL_NAVIGATOR_GTV_H__
+#define __GEDIT_SPELL_NAVIGATOR_GTV_H__
+
+#include <gtk/gtk.h>
+#include "gedit-spell-navigator.h"
+#include "gedit-spell-checker.h"
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_SPELL_NAVIGATOR_GTV (gedit_spell_navigator_gtv_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GeditSpellNavigatorGtv, gedit_spell_navigator_gtv,
+ GEDIT, SPELL_NAVIGATOR_GTV,
+ GObject)
+
+struct _GeditSpellNavigatorGtvClass
+{
+ GObjectClass parent_class;
+};
+
+GeditSpellNavigator * gedit_spell_navigator_gtv_new (GtkTextView *view,
+ GeditSpellChecker *spell_checker);
+
+G_END_DECLS
+
+#endif /* __GEDIT_SPELL_NAVIGATOR_GTV_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/plugins/spell/gedit-spell-navigator.c b/plugins/spell/gedit-spell-navigator.c
new file mode 100644
index 0000000..0189525
--- /dev/null
+++ b/plugins/spell/gedit-spell-navigator.c
@@ -0,0 +1,97 @@
+/*
+ * gedit-spell-navigator.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-spell-navigator.h"
+#include "gedit-spell-checker.h"
+
+G_DEFINE_INTERFACE (GeditSpellNavigator, gedit_spell_navigator, G_TYPE_OBJECT)
+
+static gchar *
+gedit_spell_navigator_get_next_misspelled_word_default (GeditSpellNavigator *navigator)
+{
+ return NULL;
+}
+
+static void
+gedit_spell_navigator_change_default (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+}
+
+static void
+gedit_spell_navigator_change_all_default (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+}
+
+static void
+gedit_spell_navigator_default_init (GeditSpellNavigatorInterface *iface)
+{
+ iface->get_next_misspelled_word = gedit_spell_navigator_get_next_misspelled_word_default;
+ iface->change = gedit_spell_navigator_change_default;
+ iface->change_all = gedit_spell_navigator_change_all_default;
+
+ g_object_interface_install_property (iface,
+ g_param_spec_object ("spell-checker",
+ "Spell Checker",
+ "",
+ GEDIT_TYPE_SPELL_CHECKER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * gedit_spell_navigator_get_next_misspelled_word:
+ * @navigator: a #GeditSpellNavigator.
+ *
+ * Returns: the next misspelled word, or %NULL if finished.
+ */
+gchar *
+gedit_spell_navigator_get_next_misspelled_word (GeditSpellNavigator *navigator)
+{
+ g_return_val_if_fail (GEDIT_IS_SPELL_NAVIGATOR (navigator), NULL);
+
+ return GEDIT_SPELL_NAVIGATOR_GET_IFACE (navigator)->get_next_misspelled_word (navigator);
+}
+
+void
+gedit_spell_navigator_change (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+ g_return_if_fail (GEDIT_IS_SPELL_NAVIGATOR (navigator));
+
+ GEDIT_SPELL_NAVIGATOR_GET_IFACE (navigator)->change (navigator, word, change_to);
+}
+
+void
+gedit_spell_navigator_change_all (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to)
+{
+ g_return_if_fail (GEDIT_IS_SPELL_NAVIGATOR (navigator));
+
+ GEDIT_SPELL_NAVIGATOR_GET_IFACE (navigator)->change_all (navigator, word, change_to);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/plugins/spell/gedit-spell-navigator.h b/plugins/spell/gedit-spell-navigator.h
new file mode 100644
index 0000000..87d394b
--- /dev/null
+++ b/plugins/spell/gedit-spell-navigator.h
@@ -0,0 +1,62 @@
+/*
+ * gedit-spell-navigator.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_SPELL_NAVIGATOR_H__
+#define __GEDIT_SPELL_NAVIGATOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_SPELL_NAVIGATOR (gedit_spell_navigator_get_type ())
+G_DECLARE_INTERFACE (GeditSpellNavigator, gedit_spell_navigator,
+ GEDIT, SPELL_NAVIGATOR,
+ GObject)
+
+struct _GeditSpellNavigatorInterface
+{
+ GTypeInterface parent_interface;
+
+ gchar * (* get_next_misspelled_word) (GeditSpellNavigator *navigator);
+
+ void (* change) (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to);
+
+ void (* change_all) (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to);
+};
+
+gchar * gedit_spell_navigator_get_next_misspelled_word (GeditSpellNavigator *navigator);
+
+void gedit_spell_navigator_change (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to);
+
+void gedit_spell_navigator_change_all (GeditSpellNavigator *navigator,
+ const gchar *word,
+ const gchar *change_to);
+
+G_END_DECLS
+
+#endif /* __GEDIT_SPELL_NAVIGATOR_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/plugins/spell/gedit-spell-plugin.c b/plugins/spell/gedit-spell-plugin.c
index e174ae7..4738989 100644
--- a/plugins/spell/gedit-spell-plugin.c
+++ b/plugins/spell/gedit-spell-plugin.c
@@ -33,6 +33,7 @@
#include "gedit-spell-checker.h"
#include "gedit-spell-checker-dialog.h"
#include "gedit-spell-language-dialog.h"
+#include "gedit-spell-navigator-gtv.h"
#include "gedit-spell-utils.h"
#ifdef G_OS_WIN32
@@ -46,6 +47,7 @@
#define SPELL_ENABLED_STR "1"
#define VIEW_DATA_KEY "GeditSpellPlugin-ViewData"
+#define NAVIGATOR_KEY "GeditSpellPlugin-Navigator"
static void gedit_window_activatable_iface_init (GeditWindowActivatableInterface *iface);
@@ -58,19 +60,6 @@ struct _GeditSpellPluginPrivate
gulong tab_removed_id;
};
-typedef struct _CheckRange CheckRange;
-
-struct _CheckRange
-{
- GtkTextMark *start_mark;
- GtkTextMark *end_mark;
-
- gint mw_start; /* misspelled word start */
- gint mw_end; /* end */
-
- GtkTextMark *current_mark;
-};
-
typedef struct _ViewData ViewData;
struct _ViewData
@@ -116,7 +105,6 @@ static GActionEntry action_entries[] =
};
static GQuark spell_checker_id = 0;
-static GQuark check_range_id = 0;
static ViewData *
view_data_new (GeditSpellPlugin *plugin,
@@ -312,456 +300,41 @@ get_spell_checker_from_document (GeditDocument *doc)
return checker;
}
-static CheckRange *
-get_check_range (GeditDocument *doc)
-{
- gedit_debug (DEBUG_PLUGINS);
-
- g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
-
- return g_object_get_qdata (G_OBJECT (doc), check_range_id);
-}
-
-static void
-update_current (GeditDocument *doc,
- gint current_offset)
-{
- CheckRange *range;
- GtkTextIter iter;
- GtkTextIter end_iter;
-
- gedit_debug (DEBUG_PLUGINS);
-
- g_return_if_fail (GEDIT_IS_DOCUMENT (doc));
- g_return_if_fail (current_offset >= 0);
-
- range = get_check_range (doc);
- g_return_if_fail (range != NULL);
-
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc),
- &iter, current_offset);
-
- if (!gtk_text_iter_inside_word (&iter))
- {
- /* if we're not inside a word,
- * we must be in some spaces.
- * skip forward to the beginning of the next word. */
- if (!gtk_text_iter_is_end (&iter))
- {
- gtk_text_iter_forward_word_end (&iter);
- gtk_text_iter_backward_word_start (&iter);
- }
- }
- else if (!gtk_text_iter_starts_word (&iter))
- {
- gtk_text_iter_backward_word_start (&iter);
- }
-
- gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
- &end_iter,
- range->end_mark);
-
- if (gtk_text_iter_compare (&end_iter, &iter) < 0)
- {
- gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
- range->current_mark,
- &end_iter);
- }
- else
- {
- gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
- range->current_mark,
- &iter);
- }
-}
-
static void
-set_check_range (GeditDocument *doc,
- GtkTextIter *start,
- GtkTextIter *end)
-{
- CheckRange *range;
- GtkTextIter iter;
-
- gedit_debug (DEBUG_PLUGINS);
-
- range = get_check_range (doc);
-
- if (range == NULL)
- {
- gedit_debug_message (DEBUG_PLUGINS, "There was not a previous check range");
-
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &iter);
-
- range = g_new0 (CheckRange, 1);
-
- range->start_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
- NULL,
- &iter,
- TRUE);
-
- range->end_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
- NULL,
- &iter,
- FALSE);
-
- range->current_mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
- NULL,
- &iter,
- TRUE);
-
- g_object_set_qdata_full (G_OBJECT (doc),
- check_range_id,
- range,
- g_free);
- }
-
- if (gedit_spell_utils_skip_no_spell_check (start, end))
- {
- if (!gtk_text_iter_inside_word (end))
- {
- /* if we're neither inside a word,
- * we must be in some spaces.
- * skip backward to the end of the previous word. */
- if (!gtk_text_iter_is_end (end))
- {
- gtk_text_iter_backward_word_start (end);
- gtk_text_iter_forward_word_end (end);
- }
- }
- else
- {
- if (!gtk_text_iter_ends_word (end))
- {
- gtk_text_iter_forward_word_end (end);
- }
- }
- }
- else
- {
- /* no spell checking in the specified range */
- start = end;
- }
-
- gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
- range->start_mark,
- start);
-
- gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc),
- range->end_mark,
- end);
-
- range->mw_start = -1;
- range->mw_end = -1;
-
- update_current (doc, gtk_text_iter_get_offset (start));
-}
-
-static gchar *
-get_current_word (GeditDocument *doc,
- gint *start,
- gint *end)
-{
- const CheckRange *range;
- GtkTextIter end_iter;
- GtkTextIter current_iter;
- gint range_end;
-
- gedit_debug (DEBUG_PLUGINS);
-
- g_return_val_if_fail (GEDIT_IS_DOCUMENT (doc), NULL);
- g_return_val_if_fail (start != NULL, NULL);
- g_return_val_if_fail (end != NULL, NULL);
-
- range = get_check_range (doc);
- g_return_val_if_fail (range != NULL, NULL);
-
- gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
- &end_iter,
- range->end_mark);
-
- range_end = gtk_text_iter_get_offset (&end_iter);
-
- gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
- ¤t_iter,
- range->current_mark);
-
- end_iter = current_iter;
-
- if (!gtk_text_iter_is_end (&end_iter))
- {
- gedit_debug_message (DEBUG_PLUGINS, "Current is not end");
-
- gtk_text_iter_forward_word_end (&end_iter);
- }
-
- *start = gtk_text_iter_get_offset (¤t_iter);
- *end = MIN (gtk_text_iter_get_offset (&end_iter), range_end);
-
- gedit_debug_message (DEBUG_PLUGINS, "Current word extends [%d, %d]", *start, *end);
-
- if (*start >= *end)
- {
- return NULL;
- }
-
- return gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc),
- ¤t_iter,
- &end_iter,
- TRUE);
-}
-
-static gboolean
-goto_next_word (GeditDocument *doc)
-{
- CheckRange *range;
- GtkTextIter current_iter;
- GtkTextIter old_current_iter;
- GtkTextIter end_iter;
-
- gedit_debug (DEBUG_PLUGINS);
-
- g_return_val_if_fail (doc != NULL, FALSE);
-
- range = get_check_range (doc);
- g_return_val_if_fail (range != NULL, FALSE);
-
- gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (doc),
- ¤t_iter,
- range->current_mark);
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end_iter);
-
- old_current_iter = current_iter;
-
- gtk_text_iter_forward_word_ends (¤t_iter, 2);
- gtk_text_iter_backward_word_start (¤t_iter);
-
- if (gedit_spell_utils_skip_no_spell_check (¤t_iter, &end_iter) &&
- (gtk_text_iter_compare (&old_current_iter, ¤t_iter) < 0) &&
- (gtk_text_iter_compare (¤t_iter, &end_iter) < 0))
- {
- update_current (doc, gtk_text_iter_get_offset (¤t_iter));
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gchar *
-get_next_misspelled_word (GeditView *view,
- gint *word_start_offset,
- gint *word_end_offset)
+goto_next_cb (GeditSpellCheckerDialog *dialog,
+ GeditSpellNavigator *navigator)
{
- GeditDocument *doc;
- CheckRange *range;
- gint start, end;
gchar *word;
- GeditSpellChecker *checker;
- GError *error = NULL;
-
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
-
- range = get_check_range (doc);
- g_return_val_if_fail (range != NULL, NULL);
-
- checker = get_spell_checker_from_document (doc);
- g_return_val_if_fail (checker != NULL, NULL);
-
- word = get_current_word (doc, &start, &end);
- if (word == NULL)
- {
- return NULL;
- }
-
- gedit_debug_message (DEBUG_PLUGINS, "Word to check: %s", word);
-
- while (gedit_spell_checker_check_word (checker, word, &error))
- {
- g_free (word);
-
- if (!goto_next_word (doc))
- {
- return NULL;
- }
-
- /* may return null if we reached the end of the selection */
- word = get_current_word (doc, &start, &end);
- if (word == NULL)
- {
- return NULL;
- }
-
- gedit_debug_message (DEBUG_PLUGINS, "Word to check: %s", word);
- }
- if (error != NULL)
- {
- g_warning ("Spell checking plugin: %s", error->message);
- g_error_free (error);
- return NULL;
- }
-
- if (!goto_next_word (doc))
- {
- update_current (doc, gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (doc)));
- }
+ word = gedit_spell_navigator_get_next_misspelled_word (navigator);
if (word != NULL)
{
- range->mw_start = start;
- range->mw_end = end;
- *word_start_offset = start;
- *word_end_offset = end;
+ gedit_spell_checker_dialog_set_misspelled_word (dialog, word);
+ g_free (word);
}
else
{
- range->mw_start = -1;
- range->mw_end = -1;
- *word_start_offset = -1;
- *word_end_offset = -1;
- }
-
- return word;
-}
-
-static void
-select_misspelled_word (GeditView *view,
- gint word_start_offset,
- gint word_end_offset)
-{
- GtkTextBuffer *buffer;
- GtkTextIter word_start_iter;
- GtkTextIter word_end_iter;
-
- buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
-
- gtk_text_buffer_get_iter_at_offset (buffer, &word_start_iter, word_start_offset);
- gtk_text_buffer_get_iter_at_offset (buffer, &word_end_iter, word_end_offset);
-
- gedit_debug_message (DEBUG_PLUGINS, "Select [%d, %d]", word_start_offset, word_end_offset);
- gtk_text_buffer_select_range (buffer, &word_start_iter, &word_end_iter);
-
- gedit_view_scroll_to_cursor (view);
-}
-
-static void
-goto_next_cb (GeditSpellCheckerDialog *dialog,
- GeditView *view)
-{
- gchar *word = NULL;
- gint word_start_offset;
- gint word_end_offset;
-
- gedit_debug (DEBUG_PLUGINS);
-
- word = get_next_misspelled_word (view, &word_start_offset, &word_end_offset);
- if (word == NULL)
- {
gedit_spell_checker_dialog_set_completed (dialog);
- return;
}
-
- select_misspelled_word (view, word_start_offset, word_end_offset);
-
- gedit_spell_checker_dialog_set_misspelled_word (dialog, word);
-
- g_free (word);
}
static void
change_cb (GeditSpellCheckerDialog *dialog,
const gchar *word,
const gchar *change_to,
- GeditView *view)
+ GeditSpellNavigator *navigator)
{
- GeditDocument *doc;
- CheckRange *range;
- GtkTextIter start;
- GtkTextIter end;
- gchar *word_in_buffer = NULL;
-
- gedit_debug (DEBUG_PLUGINS);
-
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- range = get_check_range (doc);
- g_return_if_fail (range != NULL);
-
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start);
- if (range->mw_end < 0)
- {
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end);
- }
- else
- {
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end);
- }
-
- word_in_buffer = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE);
- g_return_if_fail (word_in_buffer != NULL);
- g_return_if_fail (g_strcmp0 (word_in_buffer, word) == 0);
- g_free (word_in_buffer);
-
- gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (doc));
-
- gtk_text_buffer_delete (GTK_TEXT_BUFFER (doc), &start, &end);
- gtk_text_buffer_insert (GTK_TEXT_BUFFER (doc), &start, change_to, -1);
-
- gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (doc));
-
- update_current (doc, range->mw_start + g_utf8_strlen (change_to, -1));
+ gedit_spell_navigator_change (navigator, word, change_to);
}
static void
change_all_cb (GeditSpellCheckerDialog *dialog,
const gchar *word,
const gchar *change_to,
- GeditView *view)
+ GeditSpellNavigator *navigator)
{
- GeditDocument *doc;
- CheckRange *range;
- GtkTextIter start;
- GtkTextIter end;
- gchar *word_in_buffer = NULL;
- GtkSourceSearchSettings *search_settings;
- GtkSourceSearchContext *search_context;
-
- gedit_debug (DEBUG_PLUGINS);
-
- doc = GEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
- range = get_check_range (doc);
- g_return_if_fail (range != NULL);
-
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &start, range->mw_start);
- if (range->mw_end < 0)
- {
- gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (doc), &end);
- }
- else
- {
- gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (doc), &end, range->mw_end);
- }
-
- word_in_buffer = gtk_text_buffer_get_slice (GTK_TEXT_BUFFER (doc), &start, &end, TRUE);
- g_return_if_fail (word_in_buffer != NULL);
- g_return_if_fail (g_strcmp0 (word_in_buffer, word) == 0);
- g_free (word_in_buffer);
-
- search_settings = gtk_source_search_settings_new ();
- gtk_source_search_settings_set_case_sensitive (search_settings, TRUE);
- gtk_source_search_settings_set_at_word_boundaries (search_settings, TRUE);
- gtk_source_search_settings_set_search_text (search_settings, word);
-
- search_context = gtk_source_search_context_new (GTK_SOURCE_BUFFER (doc),
- search_settings);
-
- gtk_source_search_context_set_highlight (search_context, FALSE);
-
- gtk_source_search_context_replace_all (search_context, change_to, -1, NULL);
-
- update_current (doc, range->mw_start + g_utf8_strlen (change_to, -1));
-
- g_object_unref (search_settings);
- g_object_unref (search_context);
+ gedit_spell_navigator_change_all (navigator, word, change_to);
}
static void
@@ -847,11 +420,8 @@ spell_cb (GSimpleAction *action,
GeditView *view;
GeditDocument *doc;
GeditSpellChecker *checker;
+ GeditSpellNavigator *navigator;
GtkWidget *dialog;
- GtkTextIter start;
- GtkTextIter end;
- gint word_start_offset;
- gint word_end_offset;
gchar *word;
gedit_debug (DEBUG_PLUGINS);
@@ -878,19 +448,9 @@ spell_cb (GSimpleAction *action,
return;
}
- if (!gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
- &start,
- &end))
- {
- /* no selection, get the whole doc */
- gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc),
- &start,
- &end);
- }
-
- set_check_range (doc, &start, &end);
+ navigator = gedit_spell_navigator_gtv_new (GTK_TEXT_VIEW (view), checker);
- word = get_next_misspelled_word (view, &word_start_offset, &word_end_offset);
+ word = gedit_spell_navigator_get_next_misspelled_word (navigator);
if (word == NULL)
{
GtkWidget *statusbar;
@@ -900,33 +460,37 @@ spell_cb (GSimpleAction *action,
priv->statusbar_context_id,
_("No misspelled words"));
+ g_object_unref (navigator);
return;
}
dialog = gedit_spell_checker_dialog_new (GTK_WINDOW (priv->window), checker);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ g_object_set_data_full (G_OBJECT (dialog),
+ NAVIGATOR_KEY,
+ navigator,
+ g_object_unref);
+
g_signal_connect (dialog,
"change",
G_CALLBACK (change_cb),
- view);
+ navigator);
g_signal_connect (dialog,
"change-all",
G_CALLBACK (change_all_cb),
- view);
+ navigator);
g_signal_connect (dialog,
"goto-next",
G_CALLBACK (goto_next_cb),
- view);
+ navigator);
gedit_spell_checker_dialog_set_misspelled_word (GEDIT_SPELL_CHECKER_DIALOG (dialog), word);
-
g_free (word);
gtk_widget_show (dialog);
- select_misspelled_word (view, word_start_offset, word_end_offset);
}
static void
@@ -1297,11 +861,6 @@ gedit_spell_plugin_class_init (GeditSpellPluginClass *klass)
spell_checker_id = g_quark_from_string ("GeditSpellCheckerID");
}
- if (check_range_id == 0)
- {
- check_range_id = g_quark_from_string ("CheckRangeID");
- }
-
g_object_class_override_property (object_class, PROP_WINDOW, "window");
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]