1 /* 2 * Copyright 2013 Ran Benita <ran234 (at) gmail.com> 3 * 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: 10 * 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 13 * Software. 14 * 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. 22 */ 23 24 #include "utils.h" 25 #include "table.h" 26 #include "parser.h" 27 #include "paths.h" 28 29 static struct xkb_compose_table * 30 xkb_compose_table_new(struct xkb_context *ctx, 31 const char *locale, 32 enum xkb_compose_format format, 33 enum xkb_compose_compile_flags flags) 34 { 35 char *resolved_locale; 36 struct xkb_compose_table *table; 37 struct compose_node root; 38 39 resolved_locale = resolve_locale(locale); 40 if (!resolved_locale) 41 return NULL; 42 43 table = calloc(1, sizeof(*table)); 44 if (!table) { 45 free(resolved_locale); 46 return NULL; 47 } 48 49 table->refcnt = 1; 50 table->ctx = xkb_context_ref(ctx); 51 52 table->locale = resolved_locale; 53 table->format = format; 54 table->flags = flags; 55 56 darray_init(table->nodes); 57 darray_init(table->utf8); 58 59 root.keysym = XKB_KEY_NoSymbol; 60 root.next = 0; 61 root.is_leaf = true; 62 root.u.leaf.utf8 = 0; 63 root.u.leaf.keysym = XKB_KEY_NoSymbol; 64 darray_append(table->nodes, root); 65 66 darray_append(table->utf8, '\0'); 67 68 return table; 69 } 70 71 XKB_EXPORT struct xkb_compose_table * 72 xkb_compose_table_ref(struct xkb_compose_table *table) 73 { 74 table->refcnt++; 75 return table; 76 } 77 78 XKB_EXPORT void 79 xkb_compose_table_unref(struct xkb_compose_table *table) 80 { 81 if (!table || --table->refcnt > 0) 82 return; 83 free(table->locale); 84 darray_free(table->nodes); 85 darray_free(table->utf8); 86 xkb_context_unref(table->ctx); 87 free(table); 88 } 89 90 XKB_EXPORT struct xkb_compose_table * 91 xkb_compose_table_new_from_file(struct xkb_context *ctx, 92 FILE *file, 93 const char *locale, 94 enum xkb_compose_format format, 95 enum xkb_compose_compile_flags flags) 96 { 97 struct xkb_compose_table *table; 98 bool ok; 99 100 if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { 101 log_err_func(ctx, "unrecognized flags: %#x\n", flags); 102 return NULL; 103 } 104 105 if (format != XKB_COMPOSE_FORMAT_TEXT_V1) { 106 log_err_func(ctx, "unsupported compose format: %d\n", format); 107 return NULL; 108 } 109 110 table = xkb_compose_table_new(ctx, locale, format, flags); 111 if (!table) 112 return NULL; 113 114 ok = parse_file(table, file, "(unknown file)"); 115 if (!ok) { 116 xkb_compose_table_unref(table); 117 return NULL; 118 } 119 120 return table; 121 } 122 123 XKB_EXPORT struct xkb_compose_table * 124 xkb_compose_table_new_from_buffer(struct xkb_context *ctx, 125 const char *buffer, size_t length, 126 const char *locale, 127 enum xkb_compose_format format, 128 enum xkb_compose_compile_flags flags) 129 { 130 struct xkb_compose_table *table; 131 bool ok; 132 133 if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { 134 log_err_func(ctx, "unrecognized flags: %#x\n", flags); 135 return NULL; 136 } 137 138 if (format != XKB_COMPOSE_FORMAT_TEXT_V1) { 139 log_err_func(ctx, "unsupported compose format: %d\n", format); 140 return NULL; 141 } 142 143 table = xkb_compose_table_new(ctx, locale, format, flags); 144 if (!table) 145 return NULL; 146 147 ok = parse_string(table, buffer, length, "(input string)"); 148 if (!ok) { 149 xkb_compose_table_unref(table); 150 return NULL; 151 } 152 153 return table; 154 } 155 156 XKB_EXPORT struct xkb_compose_table * 157 xkb_compose_table_new_from_locale(struct xkb_context *ctx, 158 const char *locale, 159 enum xkb_compose_compile_flags flags) 160 { 161 struct xkb_compose_table *table; 162 char *path = NULL; 163 const char *cpath; 164 FILE *file; 165 bool ok; 166 167 if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { 168 log_err_func(ctx, "unrecognized flags: %#x\n", flags); 169 return NULL; 170 } 171 172 table = xkb_compose_table_new(ctx, locale, XKB_COMPOSE_FORMAT_TEXT_V1, 173 flags); 174 if (!table) 175 return NULL; 176 177 cpath = get_xcomposefile_path(); 178 if (cpath) { 179 file = fopen(cpath, "r"); 180 if (file) 181 goto found_path; 182 } 183 184 cpath = path = get_home_xcompose_file_path(); 185 if (path) { 186 file = fopen(path, "r"); 187 if (file) 188 goto found_path; 189 } 190 free(path); 191 path = NULL; 192 193 cpath = path = get_locale_compose_file_path(table->locale); 194 if (path) { 195 file = fopen(path, "r"); 196 if (file) 197 goto found_path; 198 } 199 free(path); 200 path = NULL; 201 202 log_err(ctx, "couldn't find a Compose file for locale \"%s\"\n", locale); 203 xkb_compose_table_unref(table); 204 return NULL; 205 206 found_path: 207 ok = parse_file(table, file, cpath); 208 fclose(file); 209 if (!ok) { 210 xkb_compose_table_unref(table); 211 return NULL; 212 } 213 214 log_dbg(ctx, "created compose table from locale %s with path %s\n", 215 table->locale, path); 216 217 free(path); 218 return table; 219 } 220