[gnome-text-editor] spellchecker: connect plumbing to check words
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-text-editor] spellchecker: connect plumbing to check words
- Date: Sat, 26 Jun 2021 00:55:36 +0000 (UTC)
commit 16d82887d736677f1dab713fdeb0f736c2e15342
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 25 17:53:43 2021 -0700
spellchecker: connect plumbing to check words
We still need to ignore words that are not in contexts we care about.
src/editor-spell-checker.c | 32 +++++++++++--
src/editor-spell-checker.h | 3 ++
src/editor-spell-language.c | 3 ++
src/editor-spell-provider.c | 32 +++++++++++++
src/editor-spell-provider.h | 2 +
src/editor-text-buffer-spell-adapter.c | 85 +++++++++++++++++++++++++++++++++-
6 files changed, 151 insertions(+), 6 deletions(-)
---
diff --git a/src/editor-spell-checker.c b/src/editor-spell-checker.c
index ee5e491..cd9c07b 100644
--- a/src/editor-spell-checker.c
+++ b/src/editor-spell-checker.c
@@ -21,13 +21,14 @@
#include "config.h"
#include "editor-spell-checker.h"
+#include "editor-spell-language.h"
#include "editor-spell-provider.h"
struct _EditorSpellChecker
{
GObject parent_instance;
EditorSpellProvider *provider;
- const char *language;
+ EditorSpellLanguage *language;
};
G_DEFINE_TYPE (EditorSpellChecker, editor_spell_checker, G_TYPE_OBJECT)
@@ -54,6 +55,12 @@ editor_spell_checker_new (EditorSpellProvider *provider,
{
g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (provider) || !provider, NULL);
+ if (provider == NULL)
+ provider = editor_spell_provider_get_default ();
+
+ if (language == NULL)
+ language = editor_spell_provider_get_default_code (provider);
+
return g_object_new (EDITOR_TYPE_SPELL_CHECKER,
"provider", provider,
"language", language,
@@ -79,6 +86,7 @@ editor_spell_checker_finalize (GObject *object)
EditorSpellChecker *self = (EditorSpellChecker *)object;
g_clear_object (&self->provider);
+ g_clear_object (&self->language);
G_OBJECT_CLASS (editor_spell_checker_parent_class)->finalize (object);
}
@@ -189,7 +197,7 @@ editor_spell_checker_get_language (EditorSpellChecker *self)
{
g_return_val_if_fail (EDITOR_IS_SPELL_CHECKER (self), NULL);
- return self->language;
+ return self->language ? editor_spell_language_get_code (self->language) : NULL;
}
/**
@@ -206,9 +214,9 @@ editor_spell_checker_set_language (EditorSpellChecker *self,
{
g_return_if_fail (EDITOR_IS_SPELL_CHECKER (self));
- if (g_strcmp0 (language, self->language) != 0)
+ if (g_strcmp0 (language, editor_spell_checker_get_language (self)) != 0)
{
- self->language = g_intern_string (language);
+ self->language = editor_spell_provider_get_language (self->provider, language);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LANGUAGE]);
}
}
@@ -229,3 +237,19 @@ editor_spell_checker_get_provider (EditorSpellChecker *self)
return self->provider;
}
+
+gboolean
+editor_spell_checker_check_word (EditorSpellChecker *self,
+ const char *word,
+ gssize word_len)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_CHECKER (self), FALSE);
+
+ if (word == NULL || word_len == 0)
+ return FALSE;
+
+ if (self->language == NULL)
+ return TRUE;
+
+ return editor_spell_language_contains_word (self->language, word, word_len);
+}
diff --git a/src/editor-spell-checker.h b/src/editor-spell-checker.h
index f29b5fe..dc53c42 100644
--- a/src/editor-spell-checker.h
+++ b/src/editor-spell-checker.h
@@ -34,5 +34,8 @@ EditorSpellProvider *editor_spell_checker_get_provider (EditorSpellChecker *sel
const char *editor_spell_checker_get_language (EditorSpellChecker *self);
void editor_spell_checker_set_language (EditorSpellChecker *self,
const char *language);
+gboolean editor_spell_checker_check_word (EditorSpellChecker *self,
+ const char *word,
+ gssize word_len);
G_END_DECLS
diff --git a/src/editor-spell-language.c b/src/editor-spell-language.c
index 23c5b02..33344f1 100644
--- a/src/editor-spell-language.c
+++ b/src/editor-spell-language.c
@@ -119,6 +119,9 @@ editor_spell_language_contains_word (EditorSpellLanguage *self,
g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE (self), FALSE);
g_return_val_if_fail (word != NULL, FALSE);
+ if (word_len < 0)
+ word_len = strlen (word);
+
return EDITOR_SPELL_LANGUAGE_GET_CLASS (self)->contains_word (self, word, word_len);
}
diff --git a/src/editor-spell-provider.c b/src/editor-spell-provider.c
index 053d568..60bd112 100644
--- a/src/editor-spell-provider.c
+++ b/src/editor-spell-provider.c
@@ -199,3 +199,35 @@ editor_spell_provider_get_language (EditorSpellProvider *self,
return EDITOR_SPELL_PROVIDER_GET_CLASS (self)->get_language (self, language);
}
+
+const char *
+editor_spell_provider_get_default_code (EditorSpellProvider *self)
+{
+ const char * const *langs;
+ const char *ret;
+
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), NULL);
+
+ if (EDITOR_SPELL_PROVIDER_GET_CLASS (self)->get_default_code &&
+ (ret = EDITOR_SPELL_PROVIDER_GET_CLASS (self)->get_default_code (self)))
+ return ret;
+
+ langs = g_get_language_names ();
+
+ if (langs != NULL)
+ {
+ for (guint i = 0; langs[i]; i++)
+ {
+ if (editor_spell_provider_supports_language (self, langs[i]))
+ return langs[i];
+ }
+ }
+
+ if (editor_spell_provider_supports_language (self, "en_US"))
+ return "en_US";
+
+ if (editor_spell_provider_supports_language (self, "C"))
+ return "C";
+
+ return NULL;
+}
diff --git a/src/editor-spell-provider.h b/src/editor-spell-provider.h
index 293e4b1..40f9144 100644
--- a/src/editor-spell-provider.h
+++ b/src/editor-spell-provider.h
@@ -37,12 +37,14 @@ struct _EditorSpellProviderClass
const char *language);
EditorSpellLanguage *(*get_language) (EditorSpellProvider *self,
const char *language);
+ const char *(*get_default_code) (EditorSpellProvider *self);
/*< private >*/
gpointer _reserved[8];
};
EditorSpellProvider *editor_spell_provider_get_default (void);
+const char *editor_spell_provider_get_default_code (EditorSpellProvider *self);
const char *editor_spell_provider_get_display_name (EditorSpellProvider *self);
gboolean editor_spell_provider_supports_language (EditorSpellProvider *self,
const char *language);
diff --git a/src/editor-text-buffer-spell-adapter.c b/src/editor-text-buffer-spell-adapter.c
index ffe69c3..e412eb6 100644
--- a/src/editor-text-buffer-spell-adapter.c
+++ b/src/editor-text-buffer-spell-adapter.c
@@ -29,6 +29,18 @@
#define CHECKED GSIZE_TO_POINTER(1)
#define UPDATE_DELAY_MSECS 200
+typedef struct
+{
+ gint64 deadline;
+ guint has_unchecked : 1;
+} Update;
+
+typedef struct
+{
+ gsize offset;
+ guint found : 1;
+} ScanForUnchecked;
+
struct _EditorTextBufferSpellAdapter
{
GObject parent_instance;
@@ -67,14 +79,83 @@ editor_text_buffer_spell_adapter_new (GtkTextBuffer *buffer,
NULL);
}
+static gboolean
+scan_for_next_unchecked_cb (gsize offset,
+ const CjhTextRegionRun *run,
+ gpointer user_data)
+{
+ ScanForUnchecked *state = user_data;
+
+ if (run->data == UNCHECKED)
+ {
+ state->offset = offset;
+ state->found = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+scan_for_next_unchecked (CjhTextRegion *region,
+ gsize begin,
+ gsize end,
+ gsize *position)
+{
+ ScanForUnchecked state = {0};
+ _cjh_text_region_foreach_in_range (region, begin, end, scan_for_next_unchecked_cb, &state);
+ *position = state.offset;
+ return state.found;
+}
+
static gboolean
editor_text_buffer_spell_adapter_update_range (EditorTextBufferSpellAdapter *self,
- gsize begin,
- gsize end,
+ gsize begin_offset,
+ gsize end_offset,
gint64 deadline)
{
+ GtkTextIter iter, begin, end;
+ gsize position;
+
g_assert (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ if (begin_offset == end_offset)
+ return FALSE;
+
+ if (!scan_for_next_unchecked (self->region, begin_offset, end_offset, &position))
+ return FALSE;
+
+ gtk_text_buffer_get_iter_at_offset (self->buffer, &begin, position);
+ gtk_text_buffer_get_iter_at_offset (self->buffer, &end, end_offset);
+ iter = begin;
+
+ if (!gtk_text_iter_starts_word (&iter))
+ gtk_text_iter_backward_word_start (&iter);
+
+ while (gtk_text_iter_compare (&iter, &end) < 0)
+ {
+ GtkTextIter word_end = iter;
+ char *word;
+
+ if (!gtk_text_iter_forward_word_end (&word_end))
+ break;
+
+ word = gtk_text_iter_get_slice (&iter, &word_end);
+ if (!editor_spell_checker_check_word (self->checker, word, -1))
+ gtk_text_buffer_apply_tag (self->buffer, self->tag, &iter, &word_end);
+ g_free (word);
+
+ if (!gtk_text_iter_forward_word_end (&word_end))
+ break;
+
+ iter = word_end;
+
+ if (!gtk_text_iter_backward_word_start (&iter))
+ break;
+ }
+
+ _cjh_text_region_replace (self->region, begin_offset, end_offset - begin_offset, CHECKED);
+
return FALSE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]