2 * Copyright © 2014 Ran Benita <ran234@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
29 enum resolve_name_direction {
35 get_xlocaledir_path(void)
37 const char *dir = secure_getenv("XLOCALEDIR");
44 * Files like compose.dir have the format LEFT: RIGHT. Lookup @name in
45 * such a file and return its matching value, according to @direction.
46 * @filename is relative to the xlocaledir.
49 resolve_name(const char *filename, enum resolve_name_direction direction,
54 const char *xlocaledir;
60 const char *s, *left, *right;
62 size_t left_len, right_len, name_len;
64 xlocaledir = get_xlocaledir_path();
66 ret = snprintf(path, sizeof(path), "%s/%s", xlocaledir, filename);
67 if (ret < 0 || (size_t) ret >= sizeof(path))
70 file = fopen(path, "rb");
74 ok = map_file(file, &string, &string_size);
80 end = string + string_size;
81 name_len = strlen(name);
86 while (s < end && is_space(*s))
90 if (s < end && *s == '#') {
91 while (s < end && *s != '\n')
96 /* Get the left value. */
98 while (s < end && !is_space(*s) && *s != ':')
102 /* There's an optional colon between left and right. */
103 if (s < end && *s == ':')
107 while (s < end && is_space(*s))
110 /* Get the right value. */
112 while (s < end && !is_space(*s))
114 right_len = s - right;
116 /* Discard rest of line. */
117 while (s < end && *s != '\n')
120 if (direction == LEFT_TO_RIGHT) {
121 if (left_len == name_len && memcmp(left, name, left_len) == 0) {
122 match = strndup(right, right_len);
126 else if (direction == RIGHT_TO_LEFT) {
127 if (right_len == name_len && memcmp(right, name, right_len) == 0) {
128 match = strndup(left, left_len);
134 unmap_file(string, string_size);
139 resolve_locale(const char *locale)
141 char *alias = resolve_name("locale.alias", LEFT_TO_RIGHT, locale);
142 return alias ? alias : strdup(locale);
146 get_xcomposefile_path(void)
148 return secure_getenv("XCOMPOSEFILE");
152 get_home_xcompose_file_path(void)
158 home = secure_getenv("HOME");
162 ret = asprintf(&path, "%s/.XCompose", home);
170 get_locale_compose_file_path(const char *locale)
176 * WARNING: Random workaround ahead.
178 * We currently do not support non-UTF-8 Compose files. The C/POSIX
179 * locale is specified to be the default fallback locale with an
180 * ASCII charset. But for some reason the compose.dir points the C
181 * locale to the iso8859-1/Compose file, which is not ASCII but
182 * ISO8859-1. Since this is bound to happen a lot, and since our API
183 * is UTF-8 based, and since 99% of the time a C locale is really just
184 * a misconfiguration for UTF-8, let's do the most helpful thing.
186 if (streq(locale, "C"))
187 locale = "en_US.UTF-8";
189 resolved = resolve_name("compose.dir", RIGHT_TO_LEFT, locale);
193 if (resolved[0] == '/') {
197 const char *xlocaledir = get_xlocaledir_path();
198 int ret = asprintf(&path, "%s/%s", xlocaledir, resolved);