[gnome-text-editor] spellcheck: add EditorSpellLanguageInfo



commit db0dfd0947ec9bc81effff32e8268abc59bb6f81
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jun 30 19:59:41 2021 -0700

    spellcheck: add EditorSpellLanguageInfo
    
    This allows us to continue lazy loading languages, but also have the name
    of the language to display in menus.

 meson.build                                 |   1 +
 src/editor-spell-language-info.c            | 162 ++++++++++++++++++++++++++++
 src/editor-spell-language-info.h            |  36 +++++++
 src/editor-spell-provider.c                 |   5 +-
 src/editor-spell-provider.h                 |  28 ++---
 src/editor-types.h                          |   1 +
 src/enchant/editor-enchant-spell-provider.c |  45 ++++++--
 src/enchant/meson.build                     |   3 +-
 src/meson.build                             |   1 +
 9 files changed, 259 insertions(+), 23 deletions(-)
---
diff --git a/meson.build b/meson.build
index 7532983..cb8e1ee 100644
--- a/meson.build
+++ b/meson.build
@@ -33,6 +33,7 @@ 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)
+libicu_dep = dependency('icu-uc')
 
 # Specify minimum library versions
 glib_major = glib_req_version.split('.')[0].to_int()
diff --git a/src/editor-spell-language-info.c b/src/editor-spell-language-info.c
new file mode 100644
index 0000000..8bc4ceb
--- /dev/null
+++ b/src/editor-spell-language-info.c
@@ -0,0 +1,162 @@
+/* editor-spell-language-info.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-language-info.h"
+
+struct _EditorSpellLanguageInfo
+{
+  GObject parent_instance;
+  char *name;
+  char *code;
+};
+
+G_DEFINE_TYPE (EditorSpellLanguageInfo, editor_spell_language_info, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_CODE,
+  PROP_NAME,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/**
+ * editor_spell_language_info_new:
+ *
+ * Create a new #EditorSpellLanguageInfo.
+ *
+ * Returns: (transfer full): a newly created #EditorSpellLanguageInfo
+ */
+EditorSpellLanguageInfo *
+editor_spell_language_info_new (const char *name,
+                                const char *code)
+{
+  return g_object_new (EDITOR_TYPE_SPELL_LANGUAGE_INFO,
+                       "name", name,
+                       "code", code,
+                       NULL);
+}
+
+static void
+editor_spell_language_info_finalize (GObject *object)
+{
+  EditorSpellLanguageInfo *self = (EditorSpellLanguageInfo *)object;
+
+  g_clear_pointer (&self->name, g_free);
+  g_clear_pointer (&self->code, g_free);
+
+  G_OBJECT_CLASS (editor_spell_language_info_parent_class)->finalize (object);
+}
+
+static void
+editor_spell_language_info_get_property (GObject    *object,
+                                         guint       prop_id,
+                                         GValue     *value,
+                                         GParamSpec *pspec)
+{
+  EditorSpellLanguageInfo *self = EDITOR_SPELL_LANGUAGE_INFO (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      g_value_set_string (value, editor_spell_language_info_get_name (self));
+      break;
+
+    case PROP_CODE:
+      g_value_set_string (value, editor_spell_language_info_get_code (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+editor_spell_language_info_set_property (GObject      *object,
+                                         guint         prop_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec)
+{
+  EditorSpellLanguageInfo *self = EDITOR_SPELL_LANGUAGE_INFO (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      self->name = g_value_dup_string (value);
+      break;
+
+    case PROP_CODE:
+      self->code = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+editor_spell_language_info_class_init (EditorSpellLanguageInfoClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = editor_spell_language_info_finalize;
+  object_class->get_property = editor_spell_language_info_get_property;
+  object_class->set_property = editor_spell_language_info_set_property;
+
+  properties [PROP_NAME] =
+    g_param_spec_string ("name",
+                         "Name",
+                         "The name of the language",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_CODE] =
+    g_param_spec_string ("code",
+                         "Code",
+                         "The language code",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_spell_language_info_init (EditorSpellLanguageInfo *self)
+{
+}
+
+const char *
+editor_spell_language_info_get_name (EditorSpellLanguageInfo *self)
+{
+  g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE_INFO (self), NULL);
+
+  return self->name;
+}
+
+const char *
+editor_spell_language_info_get_code (EditorSpellLanguageInfo *self)
+{
+  g_return_val_if_fail (EDITOR_IS_SPELL_LANGUAGE_INFO (self), NULL);
+
+  return self->code;
+}
diff --git a/src/editor-spell-language-info.h b/src/editor-spell-language-info.h
new file mode 100644
index 0000000..a844261
--- /dev/null
+++ b/src/editor-spell-language-info.h
@@ -0,0 +1,36 @@
+/* editor-spell-language-info.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_INFO (editor_spell_language_info_get_type())
+
+G_DECLARE_FINAL_TYPE (EditorSpellLanguageInfo, editor_spell_language_info, EDITOR, SPELL_LANGUAGE_INFO, 
GObject)
+
+EditorSpellLanguageInfo *editor_spell_language_info_new      (const char              *name,
+                                                              const char              *code);
+const char              *editor_spell_language_info_get_name (EditorSpellLanguageInfo *self);
+const char              *editor_spell_language_info_get_code (EditorSpellLanguageInfo *self);
+
+G_END_DECLS
diff --git a/src/editor-spell-provider.c b/src/editor-spell-provider.c
index 60bd112..b46c64b 100644
--- a/src/editor-spell-provider.c
+++ b/src/editor-spell-provider.c
@@ -170,9 +170,10 @@ editor_spell_provider_supports_language (EditorSpellProvider *self,
  *
  * Gets a list of the languages supported by the provider.
  *
- * Returns: (transfer full) (array zero-terminated=1): an array of language codes
+ * Returns: (transfer container) (element-type EditorSpellLanguageInfo): an array of
+ *   #EditorSpellLanguageInfo.
  */
-char **
+GPtrArray *
 editor_spell_provider_list_languages (EditorSpellProvider *self)
 {
   g_return_val_if_fail (EDITOR_IS_SPELL_PROVIDER (self), NULL);
diff --git a/src/editor-spell-provider.h b/src/editor-spell-provider.h
index 40f9144..29c6d78 100644
--- a/src/editor-spell-provider.h
+++ b/src/editor-spell-provider.h
@@ -32,24 +32,24 @@ 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);
-  const char           *(*get_default_code)  (EditorSpellProvider *self);
+  GPtrArray           *(*list_languages)    (EditorSpellProvider *self);
+  gboolean             (*supports_language) (EditorSpellProvider *self,
+                                             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);
-char                **editor_spell_provider_list_languages    (EditorSpellProvider *self);
-EditorSpellLanguage  *editor_spell_provider_get_language      (EditorSpellProvider *self,
-                                                               const char          *language);
+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);
+GPtrArray           *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 2941653..9ee76f3 100644
--- a/src/editor-types.h
+++ b/src/editor-types.h
@@ -43,6 +43,7 @@ typedef struct _EditorSidebar              EditorSidebar;
 typedef struct _EditorSignalGroup          EditorSignalGroup;
 typedef struct _EditorSpellChecker         EditorSpellChecker;
 typedef struct _EditorSpellLanguage        EditorSpellLanguage;
+typedef struct _EditorSpellLanguageInfo    EditorSpellLanguageInfo;
 typedef struct _EditorSpellProvider        EditorSpellProvider;
 typedef struct _EditorTab                  EditorTab;
 typedef struct _EditorWindow               EditorWindow;
diff --git a/src/enchant/editor-enchant-spell-provider.c b/src/enchant/editor-enchant-spell-provider.c
index 93b1e1c..d228c73 100644
--- a/src/enchant/editor-enchant-spell-provider.c
+++ b/src/enchant/editor-enchant-spell-provider.c
@@ -22,6 +22,10 @@
 
 #include <glib/gi18n.h>
 #include <enchant.h>
+#include <locale.h>
+#include <unicode/uloc.h>
+
+#include "editor-spell-language-info.h"
 
 #include "editor-enchant-spell-language.h"
 #include "editor-enchant-spell-provider.h"
@@ -46,6 +50,34 @@ get_broker (void)
   return broker;
 }
 
+static char *
+get_display_name (const char *code)
+{
+  const char * const *names = g_get_language_names ();
+
+  for (guint i = 0; names[i]; i++)
+    {
+      UChar ret[256];
+      UErrorCode status = U_ZERO_ERROR;
+
+      ret[0] = 0;
+      uloc_getDisplayName (code, names[i], ret, sizeof ret, &status);
+      ret[sizeof ret-1] = 0;
+
+      if (status == U_ZERO_ERROR && ret[0] != 0)
+        {
+          GString *str = g_string_new (NULL);
+
+          for (guint j = 0; ret[j]; j++)
+            g_string_append_unichar (str, ret[j]);
+
+          return g_string_free (str, FALSE);
+        }
+    }
+
+  return NULL;
+}
+
 /**
  * editor_enchant_spell_provider_new:
  *
@@ -80,18 +112,19 @@ list_languages_cb (const char * const  lang_tag,
                    const char * const  provider_file,
                    void               *user_data)
 {
-  GArray *ar = user_data;
-  char *code = g_strdup (lang_tag);
-  g_array_append_val (ar, code);
+  GPtrArray *ar = user_data;
+  char *name = get_display_name (lang_tag);
+  g_ptr_array_add (ar, editor_spell_language_info_new (name, lang_tag));
+  g_free (name);
 }
 
-static char **
+static GPtrArray *
 editor_enchant_spell_provider_list_languages (EditorSpellProvider *provider)
 {
   EnchantBroker *broker = get_broker ();
-  GArray *ar = g_array_new (TRUE, FALSE, sizeof (char *));
+  GPtrArray *ar = g_ptr_array_new_with_free_func (g_object_unref);
   enchant_broker_list_dicts (broker, list_languages_cb, ar);
-  return (char **)(gpointer)g_array_free (ar, FALSE);
+  return ar;
 }
 
 static EditorSpellLanguage *
diff --git a/src/enchant/meson.build b/src/enchant/meson.build
index 3d88a29..b3d8c03 100644
--- a/src/enchant/meson.build
+++ b/src/enchant/meson.build
@@ -1,4 +1,5 @@
-editor_deps += [libenchant_dep]
+editor_deps += [libenchant_dep, libicu_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 dd63965..8d2e640 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -36,6 +36,7 @@ editor_sources = [
   'editor-spell-checker.c',
   'editor-spell-cursor.c',
   'editor-spell-language.c',
+  'editor-spell-language-info.c',
   'editor-spell-menu.c',
   'editor-spell-provider.c',
   'editor-text-buffer-spell-adapter.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]