1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* bus - The Input Bus
4 * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
5 * Copyright (C) 2010-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
6 * Copyright (C) 2008-2016 Red Hat, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <glib.h>
28 #include <glib/gstdio.h>
29 #include <gio/gio.h>
30 #include <string.h>
31 #include "ibusxml.h"
32
33 #ifdef ENABLE_NLS
34 #include <libintl.h>
35 #endif
36
37 /* gettext macro */
38 #define N_(t) t
39
40 static GHashTable *__languages_dict;
41
42 static gboolean
_iso_codes_parse_xml_node(XMLNode * node)43 _iso_codes_parse_xml_node (XMLNode *node)
44 {
45 GList *p;
46 g_assert (node);
47
48 if (G_UNLIKELY (g_strcmp0 (node->name, "iso_639_3_entries") != 0)) {
49 return FALSE;
50 }
51
52 for (p = node->sub_nodes; p != NULL; p = p->next) {
53 XMLNode *sub_node = (XMLNode *)p->data;
54 gchar **attributes = NULL;
55 int i, j;
56 gboolean has_common_name = FALSE;
57 struct {
58 const gchar *key;
59 gchar *value;
60 } entries[] = {
61 { "id", NULL },
62 { "part1_code", NULL },
63 { "part2_code", NULL },
64 };
65
66 if (sub_node->attributes == NULL) {
67 continue;
68 }
69
70 attributes = sub_node->attributes;
71 for (i = 0; attributes[i]; i += 2) {
72 if (!g_strcmp0 (attributes[i], "common_name")) {
73 for (j = 0; j < G_N_ELEMENTS (entries); j++) {
74 if (entries[j].value == NULL)
75 continue;
76 g_hash_table_replace (__languages_dict,
77 g_strdup (entries[j].value),
78 g_strdup (attributes[i + 1]));
79 }
80 has_common_name = TRUE;
81 } else if (!g_strcmp0 (attributes[i], "name")) {
82 if (has_common_name)
83 continue;
84 for (j = 0; j < G_N_ELEMENTS (entries); j++) {
85 if (entries[j].value == NULL)
86 continue;
87 g_hash_table_replace (__languages_dict,
88 g_strdup (entries[j].value),
89 g_strdup (attributes[i + 1]));
90 }
91 } else {
92 for (j = 0; j < G_N_ELEMENTS (entries); j++) {
93 if (g_strcmp0 (attributes[i], entries[j].key) == 0 &&
94 attributes[i + 1] != NULL) {
95 entries[j].value = attributes[i + 1];
96 }
97 }
98 }
99 }
100 }
101
102 return TRUE;
103 }
104
105 void
_load_lang()106 _load_lang()
107 {
108 gchar *filename;
109 XMLNode *node;
110 struct stat buf;
111
112 #ifdef ENABLE_NLS
113 bindtextdomain ("iso_639_3", LOCALEDIR);
114 bind_textdomain_codeset ("iso_639_3", "UTF-8");
115 #endif
116
117 __languages_dict = g_hash_table_new_full (g_str_hash,
118 g_str_equal, g_free, g_free);
119 filename = g_build_filename (ISOCODES_PREFIX,
120 "share/xml/iso-codes/iso_639_3.xml",
121 NULL);
122 if (g_stat (filename, &buf) != 0) {
123 g_warning ("Can not get stat of file %s", filename);
124 g_free (filename);
125 return;
126 }
127
128 node = ibus_xml_parse_file (filename);
129 g_free (filename);
130
131 if (!node) {
132 return;
133 }
134
135 _iso_codes_parse_xml_node (node);
136 ibus_xml_free (node);
137 }
138
139 const static gchar *
ibus_get_untranslated_raw_language_name(const gchar * _locale)140 ibus_get_untranslated_raw_language_name (const gchar *_locale)
141 {
142 const gchar *retval;
143 gchar *p = NULL;
144 gchar *lang = NULL;
145
146 if (__languages_dict == NULL )
147 _load_lang();
148 if ((p = strchr (_locale, '_')) != NULL)
149 p = g_strndup (_locale, p - _locale);
150 else
151 p = g_strdup (_locale);
152 lang = g_ascii_strdown (p, -1);
153 g_free (p);
154 retval = (const gchar *) g_hash_table_lookup (__languages_dict, lang);
155 g_free (lang);
156 if (retval != NULL)
157 return retval;
158 else
159 return "Other";
160 }
161
162 static char *
get_first_item_in_semicolon_list(const char * list)163 get_first_item_in_semicolon_list (const char *list)
164 {
165 char **items;
166 char *item;
167
168 items = g_strsplit (list, "; ", 2);
169
170 item = g_strdup (items[0]);
171 g_strfreev (items);
172
173 return item;
174 }
175
176 static char *
capitalize_utf8_string(const char * str)177 capitalize_utf8_string (const char *str)
178 {
179 char first[8] = { 0 };
180
181 if (!str)
182 return NULL;
183
184 g_unichar_to_utf8 (g_unichar_totitle (g_utf8_get_char (str)), first);
185
186 return g_strconcat (first, g_utf8_offset_to_pointer (str, 1), NULL);
187 }
188
189 gchar *
ibus_get_untranslated_language_name(const gchar * _locale)190 ibus_get_untranslated_language_name (const gchar *_locale)
191 {
192 const gchar *raw = ibus_get_untranslated_raw_language_name (_locale);
193 gchar *tmp = get_first_item_in_semicolon_list (raw);
194 gchar *retval = capitalize_utf8_string (tmp);
195 g_free (tmp);
196 return retval;
197 }
198
199 gchar *
ibus_get_language_name(const gchar * _locale)200 ibus_get_language_name (const gchar *_locale)
201 {
202 const gchar *raw = ibus_get_untranslated_raw_language_name (_locale);
203 const gchar *translation = NULL;
204 gchar *tmp;
205 gchar *retval;
206
207 #ifdef ENABLE_NLS
208 if (g_strcmp0 (raw, "Other") == 0)
209 return g_strdup (dgettext (GETTEXT_PACKAGE, N_("Other")));
210 else
211 translation = dgettext ("iso_639_3", raw);
212 #else
213 translation = raw;
214 #endif
215
216 tmp = get_first_item_in_semicolon_list (translation);
217 retval = capitalize_utf8_string (tmp);
218 g_free (tmp);
219 return retval;
220 }
221
222 void
ibus_g_variant_get_child_string(GVariant * variant,gsize index,char ** str)223 ibus_g_variant_get_child_string (GVariant *variant, gsize index, char **str)
224 {
225 g_return_if_fail (str != NULL);
226
227 g_free (*str);
228 g_variant_get_child (variant, index, "s", str);
229 }
230