[gspell/wip/icu: 1/5] icu: implement get_language_name_from_code()
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gspell/wip/icu: 1/5] icu: implement get_language_name_from_code()
- Date: Tue, 6 Oct 2020 00:23:29 +0000 (UTC)
commit 5dec44989801bab9aef8093d6e0e8b410018b8d1
Author: Sébastien Wilmet <swilmet gnome org>
Date: Wed Sep 30 00:56:34 2020 +0200
icu: implement get_language_name_from_code()
Some functions are copied from Tepl. But use the Gspell namespace, to
avoid potential symbol clashes on certain platforms (see also the
comment in update-sourceregion.sh).
https://gitlab.gnome.org/GNOME/gspell/-/issues/14
README | 1 +
configure.ac | 2 +-
docs/reference/Makefile.am | 1 +
gspell/Makefile.am | 2 +
gspell/gspell-icu.c | 229 +++++++++++++++++++++++++++++++++++++++++++++
gspell/gspell-icu.h | 58 ++++++++++++
po/POTFILES.in | 1 +
testsuite/Makefile.am | 3 +
testsuite/test-icu.c | 49 ++++++++++
9 files changed, 345 insertions(+), 1 deletion(-)
---
diff --git a/README b/README
index e39b98a..1d98258 100644
--- a/README
+++ b/README
@@ -28,6 +28,7 @@ Dependencies
* GTK >= 3.20
* Enchant >= 2.1.3
* iso-codes
+* ICU - http://site.icu-project.org/
Notes for packagers
-------------------
diff --git a/configure.ac b/configure.ac
index 4141157..5d87a1f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,7 +91,7 @@ AX_COMPILER_FLAGS([WARN_CFLAGS], [WARN_LDFLAGS], [yes])
AX_REQUIRE_DEFINED([AX_PKG_CHECK_MODULES])
AX_PKG_CHECK_MODULES([DEP],
[glib-2.0 >= $glib_req gtk+-3.0 >= $gtk_req enchant-2 >= $enchant_req],
- [])
+ [icu-uc])
# iso-codes
AX_REQUIRE_DEFINED([PKG_CHECK_EXISTS])
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index d9c2fd2..b5fa4e8 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -36,6 +36,7 @@ IGNORE_HFILES = \
gspell-current-word-policy.h \
gspell-entry-private.h \
gspell-entry-utils.h \
+ gspell-icu.h \
gspell-init.h \
gspell-inline-checker-text-buffer.h \
gspell-osx.h \
diff --git a/gspell/Makefile.am b/gspell/Makefile.am
index c4e15a4..d12a551 100644
--- a/gspell/Makefile.am
+++ b/gspell/Makefile.am
@@ -53,6 +53,7 @@ gspell_private_headers = \
gspell-current-word-policy.h \
gspell-entry-private.h \
gspell-entry-utils.h \
+ gspell-icu.h \
gspell-init.h \
gspell-inline-checker-text-buffer.h \
gspell-text-iter.h \
@@ -63,6 +64,7 @@ gspell_private_c_files = \
gspell-context-menu.c \
gspell-current-word-policy.c \
gspell-entry-utils.c \
+ gspell-icu.c \
gspell-init.c \
gspell-inline-checker-text-buffer.c \
gspell-text-iter.c \
diff --git a/gspell/gspell-icu.c b/gspell/gspell-icu.c
new file mode 100644
index 0000000..e915c5f
--- /dev/null
+++ b/gspell/gspell-icu.c
@@ -0,0 +1,229 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2020 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gspell-icu.h"
+#include <unicode/uloc.h>
+
+/* Some of these functions are copied from the Tepl library. */
+
+/* Wrapper around u_strToUTF8() that handles the pre-flighting.
+ *
+ * Returns: (transfer full) (nullable): the newly-allocated string with the
+ * right size. Free with g_free() when no longer needed.
+ */
+char *
+_gspell_icu_strToUTF8 (int32_t *pDestLength,
+ const UChar *src,
+ int32_t srcLength,
+ UErrorCode *pErrorCode)
+{
+ int32_t my_DestLength = 0;
+ UErrorCode my_ErrorCode = U_ZERO_ERROR;
+ char *dest = NULL;
+
+ u_strToUTF8 (NULL, 0, &my_DestLength,
+ src, srcLength,
+ &my_ErrorCode);
+
+ if (my_ErrorCode != U_BUFFER_OVERFLOW_ERROR &&
+ my_ErrorCode != U_STRING_NOT_TERMINATED_WARNING)
+ {
+ if (pDestLength != NULL)
+ {
+ *pDestLength = my_DestLength;
+ }
+ if (pErrorCode != NULL)
+ {
+ *pErrorCode = my_ErrorCode;
+ }
+
+ return NULL;
+ }
+
+ dest = g_malloc0 (my_DestLength + 1);
+
+ u_strToUTF8 (dest, my_DestLength + 1, pDestLength,
+ src, srcLength,
+ pErrorCode);
+
+ return dest;
+}
+
+/* Returns: (transfer full) (nullable): a nul-terminated UTF-8 string. Free with
+ * g_free() when no longer needed.
+ */
+char *
+_gspell_icu_strToUTF8Simple (const UChar *uchars)
+{
+ char *utf8_str;
+ UErrorCode error_code = U_ZERO_ERROR;
+
+ utf8_str = _gspell_icu_strToUTF8 (NULL, uchars, -1, &error_code);
+
+ if (U_FAILURE (error_code))
+ {
+ g_free (utf8_str);
+ return NULL;
+ }
+
+ return utf8_str;
+}
+
+/* Wrapper around uloc_getDisplayName() that handles the pre-flighting.
+ *
+ * Returns: (transfer full) (nullable): the result as a newly-allocated buffer
+ * with the right size. Free with g_free() when no longer needed.
+ */
+UChar *
+_gspell_icu_loc_getDisplayName (const char *localeID,
+ const char *inLocaleID,
+ UErrorCode *err)
+{
+ UChar *result = NULL;
+ int32_t result_size;
+ UErrorCode my_err = U_ZERO_ERROR;
+
+ result_size = uloc_getDisplayName (localeID,
+ inLocaleID,
+ NULL, 0,
+ &my_err);
+
+ if (my_err != U_BUFFER_OVERFLOW_ERROR &&
+ my_err != U_STRING_NOT_TERMINATED_WARNING)
+ {
+ if (err != NULL)
+ {
+ *err = my_err;
+ }
+
+ return NULL;
+ }
+
+ result = g_new0 (UChar, result_size + 1);
+
+ uloc_getDisplayName (localeID,
+ inLocaleID,
+ result, result_size + 1,
+ err);
+
+ return result;
+}
+
+/* Returns: (transfer full) (nullable): the result as a UTF-8 string. Free with
+ * g_free() when no longer needed.
+ */
+char *
+_gspell_icu_loc_getDisplayNameSimple (const char *localeID,
+ const char *inLocaleID)
+{
+ UChar *result;
+ char *utf8_result;
+ UErrorCode err = U_ZERO_ERROR;
+
+ result = _gspell_icu_loc_getDisplayName (localeID, inLocaleID, &err);
+
+ if (U_FAILURE (err))
+ {
+ g_free (result);
+ return NULL;
+ }
+
+ utf8_result = _gspell_icu_strToUTF8Simple (result);
+ g_free (result);
+ return utf8_result;
+}
+
+/* Wrapper around uloc_canonicalize() that handles the pre-flighting.
+ *
+ * Returns: (transfer full) (nullable): the result as a newly-allocated buffer
+ * with the right size. Free with g_free() when no longer needed.
+ */
+char *
+_gspell_icu_loc_canonicalize (const char *localeID,
+ UErrorCode *err)
+{
+ char *result = NULL;
+ int32_t result_size;
+ UErrorCode my_err = U_ZERO_ERROR;
+
+ result_size = uloc_canonicalize (localeID, NULL, 0, &my_err);
+
+ if (my_err != U_BUFFER_OVERFLOW_ERROR &&
+ my_err != U_STRING_NOT_TERMINATED_WARNING)
+ {
+ if (err != NULL)
+ {
+ *err = my_err;
+ }
+
+ return NULL;
+ }
+
+ result = g_new0 (char, result_size + 1);
+ uloc_canonicalize (localeID, result, result_size + 1, err);
+ return result;
+}
+
+/* Returns: (transfer full) (nullable): the result, or %NULL in case of error.
+ * Free with g_free() when no longer needed.
+ */
+char *
+_gspell_icu_loc_canonicalizeSimple (const char *localeID)
+{
+ char *result;
+ UErrorCode err = U_ZERO_ERROR;
+
+ result = _gspell_icu_loc_canonicalize (localeID, &err);
+
+ if (U_FAILURE (err))
+ {
+ g_free (result);
+ return NULL;
+ }
+
+ return result;
+}
+
+/* This function uses gspell's terminology:
+ * "Language code": as in gspell_language_get_code().
+ * "Language name": as in gspell_language_get_name().
+ *
+ * Returns: (transfer full) (nullable): the language name, or %NULL in case of
+ * error. Free with g_free() when no longer needed.
+ */
+char *
+_gspell_icu_get_language_name_from_code (const char *language_code)
+{
+ char *canonicalized_language_code;
+ char *language_name;
+
+ /* language_code can come from an outside/foreign source, so it's better
+ * to pass it through level 2 canonicalization.
+ */
+ canonicalized_language_code = _gspell_icu_loc_canonicalizeSimple (language_code);
+ if (canonicalized_language_code == NULL)
+ {
+ return NULL;
+ }
+
+ /* NULL: for the default locale. */
+ language_name = _gspell_icu_loc_getDisplayNameSimple (canonicalized_language_code, NULL);
+ g_free (canonicalized_language_code);
+ return language_name;
+}
diff --git a/gspell/gspell-icu.h b/gspell/gspell-icu.h
new file mode 100644
index 0000000..381fa33
--- /dev/null
+++ b/gspell/gspell-icu.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2020 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GSPELL_ICU_H
+#define GSPELL_ICU_H
+
+#include <glib.h>
+#include <unicode/ustring.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL
+char * _gspell_icu_strToUTF8 (int32_t *pDestLength,
+ const UChar *src,
+ int32_t srcLength,
+ UErrorCode *pErrorCode);
+
+G_GNUC_INTERNAL
+char * _gspell_icu_strToUTF8Simple (const UChar *uchars);
+
+G_GNUC_INTERNAL
+UChar * _gspell_icu_loc_getDisplayName (const char *localeID,
+ const char *inLocaleID,
+ UErrorCode *err);
+
+G_GNUC_INTERNAL
+char * _gspell_icu_loc_getDisplayNameSimple (const char *localeID,
+ const char *inLocaleID);
+
+G_GNUC_INTERNAL
+char * _gspell_icu_loc_canonicalize (const char *localeID,
+ UErrorCode *err);
+
+G_GNUC_INTERNAL
+char * _gspell_icu_loc_canonicalizeSimple (const char *localeID);
+
+G_GNUC_INTERNAL
+char * _gspell_icu_get_language_name_from_code (const char *language_code);
+
+G_END_DECLS
+
+#endif /* GSPELL_ICU_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f10bd5a..8cc92b9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,6 +6,7 @@ gspell/gspell-current-word-policy.c
gspell/gspell-entry.c
gspell/gspell-entry-buffer.c
gspell/gspell-entry-utils.c
+gspell/gspell-icu.c
gspell/gspell-inline-checker-text-buffer.c
gspell/gspell-language.c
gspell/gspell-language-chooser.c
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index c58a176..4bda3f6 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -31,6 +31,9 @@ test_checker_SOURCES = test-checker.c
UNIT_TEST_PROGS += test-entry
test_entry_SOURCES = test-entry.c
+UNIT_TEST_PROGS += test-icu
+test_icu_SOURCES = test-icu.c
+
UNIT_TEST_PROGS += test-inline-checker-text-buffer
test_inline_checker_text_buffer_SOURCES = test-inline-checker-text-buffer.c
diff --git a/testsuite/test-icu.c b/testsuite/test-icu.c
new file mode 100644
index 0000000..363575e
--- /dev/null
+++ b/testsuite/test-icu.c
@@ -0,0 +1,49 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2020 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gtk/gtk.h>
+#include "gspell/gspell-icu.h"
+
+static void
+check_loc_getDisplayNameSimple (const char *localeID,
+ const char *expected_display_name)
+{
+ char *received_display_name;
+
+ received_display_name = _gspell_icu_loc_getDisplayNameSimple (localeID, "en_US");
+ g_assert_cmpstr (received_display_name, ==, expected_display_name);
+ g_free (received_display_name);
+}
+
+static void
+test_loc_getDisplayNameSimple (void)
+{
+ check_loc_getDisplayNameSimple ("en_US", "English (United States)");
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ gtk_test_init (&argc, &argv);
+
+ g_test_add_func ("/icu/loc_getDisplayNameSimple", test_loc_getDisplayNameSimple);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]