[gnome-text-editor] spellcheck: add plumbing for spellcheckers
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-text-editor] spellcheck: add plumbing for spellcheckers
- Date: Fri, 25 Jun 2021 20:43:37 +0000 (UTC)
commit 07ba65135fb87482e6bef58b0d1b01d49e469d36
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 25 13:42:43 2021 -0700
spellcheck: add plumbing for spellcheckers
meson.build | 3 +
src/editor-spell-checker.c | 231 ++++++++++++++++++++++++++++
src/editor-spell-checker.h | 38 +++++
src/editor-spell-language.c | 141 +++++++++++++++++
src/editor-spell-language.h | 54 +++++++
src/editor-spell-provider.c | 201 ++++++++++++++++++++++++
src/editor-spell-provider.h | 53 +++++++
src/editor-types.h | 3 +
src/enchant/editor-enchant-spell-language.c | 179 +++++++++++++++++++++
src/enchant/editor-enchant-spell-language.h | 35 +++++
src/enchant/editor-enchant-spell-provider.c | 136 ++++++++++++++++
src/enchant/editor-enchant-spell-provider.h | 33 ++++
src/enchant/meson.build | 5 +
src/meson.build | 4 +
14 files changed, 1116 insertions(+)
---
diff --git a/meson.build b/meson.build
index 153525d..7532983 100644
--- a/meson.build
+++ b/meson.build
@@ -21,15 +21,18 @@ endif
glib_req_version = '2.69'
gtk_req_version = '4.3'
gtksourceview_req_version = '5.0'
+enchant_req_version = '2.2.0'
glib_req = '>= @0@'.format(glib_req_version)
gtk_req = '>= @0@'.format(gtk_req_version)
gtksourceview_req = '>= @0@'.format(gtksourceview_req_version)
+enchant_req = '>= @0@'.format(enchant_req_version)
libglib_dep = dependency('gio-unix-2.0', version: glib_req)
libgtk_dep = dependency('gtk4', version: gtk_req)
libgtksourceview_dep = dependency('gtksourceview-5', version: gtksourceview_req)
libadwaita_dep = dependency('libadwaita-1')
+libenchant_dep = dependency('enchant-2', version: enchant_req)
# Specify minimum library versions
glib_major = glib_req_version.split('.')[0].to_int()
diff --git a/src/editor-spell-checker.c b/src/editor-spell-checker.c
new file mode 100644
index 0000000..ee5e491
--- /dev/null
+++ b/src/editor-spell-checker.c
@@ -0,0 +1,231 @@
+/* editor-spell-checker.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "editor-spell-checker.h"
+#include "editor-spell-provider.h"
+
+struct _EditorSpellChecker
+{
+ GObject parent_instance;
+ EditorSpellProvider *provider;
+ const char *language;
+};
+
+G_DEFINE_TYPE (EditorSpellChecker, editor_spell_checker, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_LANGUAGE,
+ PROP_PROVIDER,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/**
+ * editor_spell_checker_new:
+ *
+ * Create a new #EditorSpellChecker.
+ *
+ * Returns: (transfer full): a newly created #EditorSpellChecker
+ */
+EditorSpellChecker *
+editor_spell_checker_new (EditorSpellProvider *provider,
+ const char *language)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (provider) || !provider, NULL);
+
+ return g_object_new (EDITOR_TYPE_SPELL_CHECKER,
+ "provider", provider,
+ "language", language,
+ NULL);
+}
+
+static void
+editor_spell_checker_constructed (GObject *object)
+{
+ EditorSpellChecker *self = (EditorSpellChecker *)object;
+
+ g_assert (EDITOR_IS_SPELL_CHECKER (self));
+
+ G_OBJECT_CLASS (editor_spell_checker_parent_class)->constructed (object);
+
+ if (self->provider == NULL)
+ self->provider = editor_spell_provider_get_default ();
+}
+
+static void
+editor_spell_checker_finalize (GObject *object)
+{
+ EditorSpellChecker *self = (EditorSpellChecker *)object;
+
+ g_clear_object (&self->provider);
+
+ G_OBJECT_CLASS (editor_spell_checker_parent_class)->finalize (object);
+}
+
+static void
+editor_spell_checker_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellChecker *self = EDITOR_SPELL_CHECKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROVIDER:
+ g_value_set_object (value, editor_spell_checker_get_provider (self));
+ break;
+
+ case PROP_LANGUAGE:
+ g_value_set_string (value, editor_spell_checker_get_language (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_checker_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellChecker *self = EDITOR_SPELL_CHECKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_PROVIDER:
+ self->provider = g_value_dup_object (value);
+ break;
+
+ case PROP_LANGUAGE:
+ editor_spell_checker_set_language (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_checker_class_init (EditorSpellCheckerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = editor_spell_checker_constructed;
+ object_class->finalize = editor_spell_checker_finalize;
+ object_class->get_property = editor_spell_checker_get_property;
+ object_class->set_property = editor_spell_checker_set_property;
+
+ /**
+ * EditorSpellChecker:language:
+ *
+ * The "language" to use when checking words with the configured
+ * #EditorSpellProvider. For example, `en_US`.
+ */
+ properties [PROP_LANGUAGE] =
+ g_param_spec_string ("language",
+ "Language",
+ "The language code",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * EditorSpellChecker:provider:
+ *
+ * The "provider" property contains the provider that is providing
+ * information to the spell checker.
+ *
+ * Currently, only Enchant is supported, and requires using the
+ * #EditorEnchantSpellProvider. Setting this to %NULL will get
+ * the default provider.
+ */
+ properties [PROP_PROVIDER] =
+ g_param_spec_object ("provider",
+ "Provider",
+ "The spell check provider",
+ EDITOR_TYPE_SPELL_PROVIDER,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_spell_checker_init (EditorSpellChecker *self)
+{
+}
+
+/**
+ * editor_spell_checker_get_language:
+ *
+ * Gets the language being used by the spell checker.
+ *
+ * Returns: (nullable): a string describing the current language.
+ */
+const char *
+editor_spell_checker_get_language (EditorSpellChecker *self)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_CHECKER (self), NULL);
+
+ return self->language;
+}
+
+/**
+ * editor_spell_checker_set_language:
+ * @self: an #EditorSpellChecker
+ * @language: the language to use
+ *
+ * Sets the language code to use when communicating with the provider,
+ * such as `en_US`.
+ */
+void
+editor_spell_checker_set_language (EditorSpellChecker *self,
+ const char *language)
+{
+ g_return_if_fail (EDITOR_IS_SPELL_CHECKER (self));
+
+ if (g_strcmp0 (language, self->language) != 0)
+ {
+ self->language = g_intern_string (language);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LANGUAGE]);
+ }
+}
+
+/**
+ * editor_spell_checker_get_provider:
+ *
+ * Gets the spell provider used by the spell checker.
+ *
+ * Currently, only Enchant-2 is supported.
+ *
+ * Returns: (transfer none) (not nullable): an #EditorSpellProvider
+ */
+EditorSpellProvider *
+editor_spell_checker_get_provider (EditorSpellChecker *self)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_CHECKER (self), NULL);
+
+ return self->provider;
+}
diff --git a/src/editor-spell-checker.h b/src/editor-spell-checker.h
new file mode 100644
index 0000000..f29b5fe
--- /dev/null
+++ b/src/editor-spell-checker.h
@@ -0,0 +1,38 @@
+/* editor-spell-checker.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "editor-types.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_SPELL_CHECKER (editor_spell_checker_get_type())
+
+G_DECLARE_FINAL_TYPE (EditorSpellChecker, editor_spell_checker, EDITOR, SPELL_CHECKER, GObject)
+
+EditorSpellChecker *editor_spell_checker_new (EditorSpellProvider *provider,
+ const char *language);
+EditorSpellProvider *editor_spell_checker_get_provider (EditorSpellChecker *self);
+const char *editor_spell_checker_get_language (EditorSpellChecker *self);
+void editor_spell_checker_set_language (EditorSpellChecker *self,
+ const char *language);
+
+G_END_DECLS
diff --git a/src/editor-spell-language.c b/src/editor-spell-language.c
new file mode 100644
index 0000000..23c5b02
--- /dev/null
+++ b/src/editor-spell-language.c
@@ -0,0 +1,141 @@
+/* editor-spell-language.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "editor-spell-language.h"
+
+typedef struct
+{
+ const char *code;
+} EditorSpellLanguagePrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EditorSpellLanguage, editor_spell_language, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_CODE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+editor_spell_language_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellLanguage *self = EDITOR_SPELL_LANGUAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_CODE:
+ g_value_set_string (value, editor_spell_language_get_code (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_language_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellLanguage *self = EDITOR_SPELL_LANGUAGE (object);
+ EditorSpellLanguagePrivate *priv = editor_spell_language_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_CODE:
+ priv->code = g_intern_string (g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_language_class_init (EditorSpellLanguageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = editor_spell_language_get_property;
+ object_class->set_property = editor_spell_language_set_property;
+
+ properties [PROP_CODE] =
+ g_param_spec_string ("code",
+ "Code",
+ "The language code",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_spell_language_init (EditorSpellLanguage *self)
+{
+}
+
+const char *
+editor_spell_language_get_code (EditorSpellLanguage *self)
+{
+ EditorSpellLanguagePrivate *priv = editor_spell_language_get_instance_private (self);
+
+ g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE (self), NULL);
+
+ return priv->code;
+}
+
+gboolean
+editor_spell_language_contains_word (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE (self), FALSE);
+ g_return_val_if_fail (word != NULL, FALSE);
+
+ return EDITOR_SPELL_LANGUAGE_GET_CLASS (self)->contains_word (self, word, word_len);
+}
+
+char **
+editor_spell_language_list_corrections (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE (self), NULL);
+ g_return_val_if_fail (word != NULL, NULL);
+ g_return_val_if_fail (word != NULL || word_len == 0, NULL);
+
+ if (word_len < 0)
+ word_len = strlen (word);
+
+ if (word_len == 0)
+ return NULL;
+
+ return EDITOR_SPELL_LANGUAGE_GET_CLASS (self)->list_corrections (self, word, word_len);
+}
diff --git a/src/editor-spell-language.h b/src/editor-spell-language.h
new file mode 100644
index 0000000..adfe37e
--- /dev/null
+++ b/src/editor-spell-language.h
@@ -0,0 +1,54 @@
+/* editor-spell-language.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "editor-types.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_SPELL_LANGUAGE (editor_spell_language_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (EditorSpellLanguage, editor_spell_language, EDITOR, SPELL_LANGUAGE, GObject)
+
+struct _EditorSpellLanguageClass
+{
+ GObjectClass parent_class;
+
+ gboolean (*contains_word) (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len);
+ char **(*list_corrections) (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len);
+
+ /*< private >*/
+ gpointer _reserved[8];
+};
+
+const char *editor_spell_language_get_code (EditorSpellLanguage *self);
+gboolean editor_spell_language_contains_word (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len);
+char **editor_spell_language_list_corrections (EditorSpellLanguage *self,
+ const char *word,
+ gssize word_len);
+
+G_END_DECLS
diff --git a/src/editor-spell-provider.c b/src/editor-spell-provider.c
new file mode 100644
index 0000000..053d568
--- /dev/null
+++ b/src/editor-spell-provider.c
@@ -0,0 +1,201 @@
+/* editor-spell-provider.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "editor-spell-provider.h"
+
+#include "enchant/editor-enchant-spell-provider.h"
+
+typedef struct
+{
+ char *display_name;
+} EditorSpellProviderPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (EditorSpellProvider, editor_spell_provider, G_TYPE_OBJECT,
+ G_ADD_PRIVATE (EditorSpellProvider))
+
+enum {
+ PROP_0,
+ PROP_DISPLAY_NAME,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+editor_spell_provider_finalize (GObject *object)
+{
+ EditorSpellProvider *self = (EditorSpellProvider *)object;
+ EditorSpellProviderPrivate *priv = editor_spell_provider_get_instance_private (self);
+
+ g_clear_pointer (&priv->display_name, g_free);
+
+ G_OBJECT_CLASS (editor_spell_provider_parent_class)->finalize (object);
+}
+
+static void
+editor_spell_provider_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellProvider *self = EDITOR_SPELL_PROVIDER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, editor_spell_provider_get_display_name (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_provider_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EditorSpellProvider *self = EDITOR_SPELL_PROVIDER (object);
+ EditorSpellProviderPrivate *priv = editor_spell_provider_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY_NAME:
+ priv->display_name = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_spell_provider_class_init (EditorSpellProviderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = editor_spell_provider_finalize;
+ object_class->get_property = editor_spell_provider_get_property;
+ object_class->set_property = editor_spell_provider_set_property;
+
+ properties [PROP_DISPLAY_NAME] =
+ g_param_spec_string ("display-name",
+ "Display Name",
+ "Display Name",
+ NULL,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_spell_provider_init (EditorSpellProvider *self)
+{
+}
+
+const char *
+editor_spell_provider_get_display_name (EditorSpellProvider *self)
+{
+ EditorSpellProviderPrivate *priv = editor_spell_provider_get_instance_private (self);
+
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), NULL);
+
+ return priv->display_name;
+}
+
+/**
+ * editor_spell_provider_get_default:
+ *
+ * Gets the default spell provider.
+ *
+ * Returns: (transfer none): an #EditorSpellProvider
+ */
+EditorSpellProvider *
+editor_spell_provider_get_default (void)
+{
+ static EditorSpellProvider *instance;
+
+ if (instance == NULL)
+ {
+ instance = editor_enchant_spell_provider_new ();
+ g_set_weak_pointer (&instance, instance);
+ }
+
+ return instance;
+}
+
+/**
+ * editor_spell_provider_supports_language:
+ * @self: an #EditorSpellProvider
+ * @language: the language such as `en_US`.
+ *
+ * Checks of @language is supported by the provider.
+ *
+ * Returns: %TRUE if @language is supported, otherwise %FALSE
+ */
+gboolean
+editor_spell_provider_supports_language (EditorSpellProvider *self,
+ const char *language)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), FALSE);
+ g_return_val_if_fail (language != NULL, FALSE);
+
+ return EDITOR_SPELL_PROVIDER_GET_CLASS (self)->supports_language (self, language);
+}
+
+/**
+ * editor_spell_provider_list_languages:
+ * @self: an #EditorSpellProvider
+ *
+ * Gets a list of the languages supported by the provider.
+ *
+ * Returns: (transfer full) (array zero-terminated=1): an array of language codes
+ */
+char **
+editor_spell_provider_list_languages (EditorSpellProvider *self)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), NULL);
+
+ return EDITOR_SPELL_PROVIDER_GET_CLASS (self)->list_languages (self);
+}
+
+/**
+ * editor_spell_provider_get_language:
+ * @self: an #EditorSpellProvider
+ * @language: the language to load such as `en_US`.
+ *
+ * Gets an #EditorSpellLanguage for the requested language, or %NULL
+ * if the language is not supported.
+ *
+ * Returns: (transfer full) (nullable): an #EditorSpellProvider or %NULL
+ */
+EditorSpellLanguage *
+editor_spell_provider_get_language (EditorSpellProvider *self,
+ const char *language)
+{
+ g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), NULL);
+ g_return_val_if_fail (language != NULL, NULL);
+
+ return EDITOR_SPELL_PROVIDER_GET_CLASS (self)->get_language (self, language);
+}
diff --git a/src/editor-spell-provider.h b/src/editor-spell-provider.h
new file mode 100644
index 0000000..293e4b1
--- /dev/null
+++ b/src/editor-spell-provider.h
@@ -0,0 +1,53 @@
+/* editor-spell-provider.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "editor-types.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_SPELL_PROVIDER (editor_spell_provider_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (EditorSpellProvider, editor_spell_provider, EDITOR, SPELL_PROVIDER, GObject)
+
+struct _EditorSpellProviderClass
+{
+ GObjectClass parent_class;
+
+ char **(*list_languages) (EditorSpellProvider *self);
+ gboolean (*supports_language) (EditorSpellProvider *self,
+ const char *language);
+ EditorSpellLanguage *(*get_language) (EditorSpellProvider *self,
+ const char *language);
+
+ /*< private >*/
+ gpointer _reserved[8];
+};
+
+EditorSpellProvider *editor_spell_provider_get_default (void);
+const char *editor_spell_provider_get_display_name (EditorSpellProvider *self);
+gboolean editor_spell_provider_supports_language (EditorSpellProvider *self,
+ const char *language);
+char **editor_spell_provider_list_languages (EditorSpellProvider *self);
+EditorSpellLanguage *editor_spell_provider_get_language (EditorSpellProvider *self,
+ const char *language);
+
+G_END_DECLS
diff --git a/src/editor-types.h b/src/editor-types.h
index 8f4dfdf..2941653 100644
--- a/src/editor-types.h
+++ b/src/editor-types.h
@@ -41,6 +41,9 @@ typedef struct _EditorPreferencesWindow EditorPreferencesWindow;
typedef struct _EditorSession EditorSession;
typedef struct _EditorSidebar EditorSidebar;
typedef struct _EditorSignalGroup EditorSignalGroup;
+typedef struct _EditorSpellChecker EditorSpellChecker;
+typedef struct _EditorSpellLanguage EditorSpellLanguage;
+typedef struct _EditorSpellProvider EditorSpellProvider;
typedef struct _EditorTab EditorTab;
typedef struct _EditorWindow EditorWindow;
diff --git a/src/enchant/editor-enchant-spell-language.c b/src/enchant/editor-enchant-spell-language.c
new file mode 100644
index 0000000..4b8736a
--- /dev/null
+++ b/src/enchant/editor-enchant-spell-language.c
@@ -0,0 +1,179 @@
+/* editor-enchant-spell-language.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <enchant.h>
+
+#include "editor-enchant-spell-language.h"
+
+struct _EditorEnchantSpellLanguage
+{
+ EditorSpellLanguage parent_instance;
+ EnchantDict *native;
+};
+
+G_DEFINE_TYPE (EditorEnchantSpellLanguage, editor_enchant_spell_language, EDITOR_TYPE_SPELL_LANGUAGE)
+
+enum {
+ PROP_0,
+ PROP_NATIVE,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/**
+ * editor_enchant_spell_language_new:
+ *
+ * Create a new #EditorEnchantSpellLanguage.
+ *
+ * Returns: (transfer full): a newly created #EditorEnchantSpellLanguage
+ */
+EditorSpellLanguage *
+editor_enchant_spell_language_new (const char *code,
+ gpointer native)
+{
+ return g_object_new (EDITOR_TYPE_ENCHANT_SPELL_LANGUAGE,
+ "code", code,
+ "native", native,
+ NULL);
+}
+
+static gboolean
+editor_enchant_spell_language_contains_word (EditorSpellLanguage *language,
+ const char *word,
+ gssize word_len)
+{
+ EditorEnchantSpellLanguage *self = (EditorEnchantSpellLanguage *)language;
+
+ g_assert (EDITOR_IS_ENCHANT_SPELL_LANGUAGE (self));
+ g_assert (word != NULL);
+ g_assert (word_len > 0);
+
+ return enchant_dict_check (self->native, word, word_len) == 0;
+}
+
+static char **
+editor_enchant_spell_language_list_corrections (EditorSpellLanguage *language,
+ const char *word,
+ gssize word_len)
+{
+ EditorEnchantSpellLanguage *self = (EditorEnchantSpellLanguage *)language;
+ size_t count = 0;
+ char **tmp;
+ char **ret = NULL;
+
+ g_assert (EDITOR_IS_ENCHANT_SPELL_LANGUAGE (self));
+ g_assert (word != NULL);
+ g_assert (word_len > 0);
+
+ if ((tmp = enchant_dict_suggest (self->native, word, word_len, &count)) && count > 0)
+ {
+ ret = g_strdupv (tmp);
+ enchant_dict_free_string_list (self->native, tmp);
+ }
+
+ return g_steal_pointer (&ret);
+}
+
+static void
+editor_enchant_spell_language_finalize (GObject *object)
+{
+ EditorEnchantSpellLanguage *self = (EditorEnchantSpellLanguage *)object;
+
+ /* Owned by provider */
+ self->native = NULL;
+
+ G_OBJECT_CLASS (editor_enchant_spell_language_parent_class)->finalize (object);
+}
+
+static void
+editor_enchant_spell_language_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EditorEnchantSpellLanguage *self = EDITOR_ENCHANT_SPELL_LANGUAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_NATIVE:
+ g_value_set_pointer (value, self->native);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_enchant_spell_language_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EditorEnchantSpellLanguage *self = EDITOR_ENCHANT_SPELL_LANGUAGE (object);
+
+ switch (prop_id)
+ {
+ case PROP_NATIVE:
+ self->native = g_value_get_pointer (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_enchant_spell_language_class_init (EditorEnchantSpellLanguageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EditorSpellLanguageClass *spell_language_class = EDITOR_SPELL_LANGUAGE_CLASS (klass);
+
+ object_class->finalize = editor_enchant_spell_language_finalize;
+ object_class->get_property = editor_enchant_spell_language_get_property;
+ object_class->set_property = editor_enchant_spell_language_set_property;
+
+ spell_language_class->contains_word = editor_enchant_spell_language_contains_word;
+ spell_language_class->list_corrections = editor_enchant_spell_language_list_corrections;
+
+ properties [PROP_NATIVE] =
+ g_param_spec_pointer ("native",
+ "Native",
+ "The native enchant dictionary",
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_enchant_spell_language_init (EditorEnchantSpellLanguage *self)
+{
+}
+
+gpointer
+editor_enchant_spell_language_get_native (EditorEnchantSpellLanguage *self)
+{
+ g_return_val_if_fail (EDITOR_IS_ENCHANT_SPELL_LANGUAGE (self), NULL);
+
+ return self->native;
+}
diff --git a/src/enchant/editor-enchant-spell-language.h b/src/enchant/editor-enchant-spell-language.h
new file mode 100644
index 0000000..4b0d0f6
--- /dev/null
+++ b/src/enchant/editor-enchant-spell-language.h
@@ -0,0 +1,35 @@
+/* editor-enchant-spell-language.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "editor-spell-language.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_ENCHANT_SPELL_LANGUAGE (editor_enchant_spell_language_get_type())
+
+G_DECLARE_FINAL_TYPE (EditorEnchantSpellLanguage, editor_enchant_spell_language, EDITOR,
ENCHANT_SPELL_LANGUAGE, EditorSpellLanguage)
+
+EditorSpellLanguage *editor_enchant_spell_language_new (const char *code,
+ gpointer native);
+gpointer editor_enchant_spell_language_get_native (EditorEnchantSpellLanguage *self);
+
+G_END_DECLS
diff --git a/src/enchant/editor-enchant-spell-provider.c b/src/enchant/editor-enchant-spell-provider.c
new file mode 100644
index 0000000..93b1e1c
--- /dev/null
+++ b/src/enchant/editor-enchant-spell-provider.c
@@ -0,0 +1,136 @@
+/* editor-enchant-spell-provider.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <enchant.h>
+
+#include "editor-enchant-spell-language.h"
+#include "editor-enchant-spell-provider.h"
+
+struct _EditorEnchantSpellProvider
+{
+ EditorSpellProvider parent_instance;
+};
+
+G_DEFINE_TYPE (EditorEnchantSpellProvider, editor_enchant_spell_provider, EDITOR_TYPE_SPELL_PROVIDER)
+
+static GHashTable *languages;
+
+static EnchantBroker *
+get_broker (void)
+{
+ static EnchantBroker *broker;
+
+ if (broker == NULL)
+ broker = enchant_broker_init ();
+
+ return broker;
+}
+
+/**
+ * editor_enchant_spell_provider_new:
+ *
+ * Create a new #EditorEnchantSpellProvider.
+ *
+ * Returns: (transfer full): a newly created #EditorEnchantSpellProvider
+ */
+EditorSpellProvider *
+editor_enchant_spell_provider_new (void)
+{
+ return g_object_new (EDITOR_TYPE_ENCHANT_SPELL_PROVIDER,
+ "display-name", _("Enchant 2"),
+ NULL);
+}
+
+static gboolean
+editor_enchant_spell_provider_supports_language (EditorSpellProvider *provider,
+ const char *language)
+{
+ EditorEnchantSpellProvider *self = (EditorEnchantSpellProvider *)provider;
+
+ g_assert (EDITOR_IS_ENCHANT_SPELL_PROVIDER (self));
+ g_assert (language != NULL);
+
+ return enchant_broker_dict_exists (get_broker (), language);
+}
+
+static void
+list_languages_cb (const char * const lang_tag,
+ const char * const provider_name,
+ const char * const provider_desc,
+ const char * const provider_file,
+ void *user_data)
+{
+ GArray *ar = user_data;
+ char *code = g_strdup (lang_tag);
+ g_array_append_val (ar, code);
+}
+
+static char **
+editor_enchant_spell_provider_list_languages (EditorSpellProvider *provider)
+{
+ EnchantBroker *broker = get_broker ();
+ GArray *ar = g_array_new (TRUE, FALSE, sizeof (char *));
+ enchant_broker_list_dicts (broker, list_languages_cb, ar);
+ return (char **)(gpointer)g_array_free (ar, FALSE);
+}
+
+static EditorSpellLanguage *
+editor_enchant_spell_provider_get_language (EditorSpellProvider *provider,
+ const char *language)
+{
+ EditorSpellLanguage *ret;
+
+ g_assert (EDITOR_IS_ENCHANT_SPELL_PROVIDER (provider));
+ g_assert (language != NULL);
+
+ if (languages == NULL)
+ languages = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+
+ if (!(ret = g_hash_table_lookup (languages, language)))
+ {
+ EnchantDict *dict = enchant_broker_request_dict (get_broker (), language);
+
+ if (dict == NULL)
+ return NULL;
+
+ ret = editor_enchant_spell_language_new (language, dict);
+ g_hash_table_insert (languages, (char *)g_intern_string (language), ret);
+ }
+
+ return ret ? g_object_ref (ret) : NULL;
+}
+
+static void
+editor_enchant_spell_provider_class_init (EditorEnchantSpellProviderClass *klass)
+{
+ EditorSpellProviderClass *spell_provider_class = EDITOR_SPELL_PROVIDER_CLASS (klass);
+
+ spell_provider_class->supports_language = editor_enchant_spell_provider_supports_language;
+ spell_provider_class->list_languages = editor_enchant_spell_provider_list_languages;
+ spell_provider_class->get_language = editor_enchant_spell_provider_get_language;
+}
+
+static void
+editor_enchant_spell_provider_init (EditorEnchantSpellProvider *self)
+{
+}
diff --git a/src/enchant/editor-enchant-spell-provider.h b/src/enchant/editor-enchant-spell-provider.h
new file mode 100644
index 0000000..8ae6c63
--- /dev/null
+++ b/src/enchant/editor-enchant-spell-provider.h
@@ -0,0 +1,33 @@
+/* editor-enchant-spell-provider.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat 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 3 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "editor-spell-provider.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_ENCHANT_SPELL_PROVIDER (editor_enchant_spell_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (EditorEnchantSpellProvider, editor_enchant_spell_provider, EDITOR,
ENCHANT_SPELL_PROVIDER, EditorSpellProvider)
+
+EditorSpellProvider *editor_enchant_spell_provider_new (void);
+
+G_END_DECLS
diff --git a/src/enchant/meson.build b/src/enchant/meson.build
new file mode 100644
index 0000000..3d88a29
--- /dev/null
+++ b/src/enchant/meson.build
@@ -0,0 +1,5 @@
+editor_deps += [libenchant_dep]
+editor_sources += files([
+ 'editor-enchant-spell-language.c',
+ 'editor-enchant-spell-provider.c',
+])
diff --git a/src/meson.build b/src/meson.build
index 732f3e0..c4e462b 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -30,6 +30,9 @@ editor_sources = [
'editor-sidebar-model.c',
'editor-sidebar-row.c',
'editor-signal-group.c',
+ 'editor-spell-checker.c',
+ 'editor-spell-language.c',
+ 'editor-spell-provider.c',
'editor-theme-selector.c',
'editor-utils.c',
'editor-window.c',
@@ -68,6 +71,7 @@ build_ident_h = vcs_tag(
output: 'build-ident.h',
)
+subdir('enchant')
subdir('defaults')
subdir('modelines')
subdir('editorconfig')
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]