1 /* 2 * Copyright 2014 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 "xkbcommon/xkbcommon-compose.h" 25 26 #include "test.h" 27 28 static const char * 29 compose_status_string(enum xkb_compose_status status) 30 { 31 switch (status) { 32 case XKB_COMPOSE_NOTHING: 33 return "nothing"; 34 case XKB_COMPOSE_COMPOSING: 35 return "composing"; 36 case XKB_COMPOSE_COMPOSED: 37 return "composed"; 38 case XKB_COMPOSE_CANCELLED: 39 return "cancelled"; 40 } 41 42 return "<invalid-status>"; 43 } 44 45 static const char * 46 feed_result_string(enum xkb_compose_feed_result result) 47 { 48 switch (result) { 49 case XKB_COMPOSE_FEED_IGNORED: 50 return "ignored"; 51 case XKB_COMPOSE_FEED_ACCEPTED: 52 return "accepted"; 53 } 54 55 return "<invalid-result>"; 56 } 57 58 /* 59 * Feed a sequence of keysyms to a fresh compose state and test the outcome. 60 * 61 * The varargs consists of lines in the following format: 62 * <input keysym> <expected feed result> <expected status> <expected string> <expected keysym> 63 * Terminated by a line consisting only of XKB_KEY_NoSymbol. 64 */ 65 static bool 66 test_compose_seq_va(struct xkb_compose_table *table, va_list ap) 67 { 68 int ret; 69 struct xkb_compose_state *state; 70 char buffer[64]; 71 72 state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); 73 assert(state); 74 75 for (int i = 1; ; i++) { 76 xkb_keysym_t input_keysym; 77 enum xkb_compose_feed_result result, expected_result; 78 enum xkb_compose_status status, expected_status; 79 const char *expected_string; 80 xkb_keysym_t keysym, expected_keysym; 81 82 input_keysym = va_arg(ap, xkb_keysym_t); 83 if (input_keysym == XKB_KEY_NoSymbol) 84 break; 85 86 expected_result = va_arg(ap, enum xkb_compose_feed_result); 87 expected_status = va_arg(ap, enum xkb_compose_status); 88 expected_string = va_arg(ap, const char *); 89 expected_keysym = va_arg(ap, xkb_keysym_t); 90 91 result = xkb_compose_state_feed(state, input_keysym); 92 93 if (result != expected_result) { 94 fprintf(stderr, "after feeding %d keysyms:\n", i); 95 fprintf(stderr, "expected feed result: %s\n", 96 feed_result_string(expected_result)); 97 fprintf(stderr, "got feed result: %s\n", 98 feed_result_string(result)); 99 goto fail; 100 } 101 102 status = xkb_compose_state_get_status(state); 103 if (status != expected_status) { 104 fprintf(stderr, "after feeding %d keysyms:\n", i); 105 fprintf(stderr, "expected status: %s\n", 106 compose_status_string(expected_status)); 107 fprintf(stderr, "got status: %s\n", 108 compose_status_string(status)); 109 goto fail; 110 } 111 112 ret = xkb_compose_state_get_utf8(state, buffer, sizeof(buffer)); 113 if (ret < 0 || (size_t) ret >= sizeof(buffer)) { 114 fprintf(stderr, "after feeding %d keysyms:\n", i); 115 fprintf(stderr, "expected string: %s\n", expected_string); 116 fprintf(stderr, "got error: %d\n", ret); 117 goto fail; 118 } 119 if (!streq(buffer, expected_string)) { 120 fprintf(stderr, "after feeding %d keysyms:\n", i); 121 fprintf(stderr, "expected string: %s\n", strempty(expected_string)); 122 fprintf(stderr, "got string: %s\n", buffer); 123 goto fail; 124 } 125 126 keysym = xkb_compose_state_get_one_sym(state); 127 if (keysym != expected_keysym) { 128 fprintf(stderr, "after feeding %d keysyms:\n", i); 129 xkb_keysym_get_name(expected_keysym, buffer, sizeof(buffer)); 130 fprintf(stderr, "expected keysym: %s\n", buffer); 131 xkb_keysym_get_name(keysym, buffer, sizeof(buffer)); 132 fprintf(stderr, "got keysym (%#x): %s\n", keysym, buffer); 133 goto fail; 134 } 135 } 136 137 xkb_compose_state_unref(state); 138 return true; 139 140 fail: 141 xkb_compose_state_unref(state); 142 return false; 143 } 144 145 static bool 146 test_compose_seq(struct xkb_compose_table *table, ...) 147 { 148 va_list ap; 149 bool ok; 150 va_start(ap, table); 151 ok = test_compose_seq_va(table, ap); 152 va_end(ap); 153 return ok; 154 } 155 156 static bool 157 test_compose_seq_buffer(struct xkb_context *ctx, const char *buffer, ...) 158 { 159 va_list ap; 160 bool ok; 161 struct xkb_compose_table *table; 162 table = xkb_compose_table_new_from_buffer(ctx, buffer, strlen(buffer), "", 163 XKB_COMPOSE_FORMAT_TEXT_V1, 164 XKB_COMPOSE_COMPILE_NO_FLAGS); 165 assert(table); 166 va_start(ap, buffer); 167 ok = test_compose_seq_va(table, ap); 168 va_end(ap); 169 xkb_compose_table_unref(table); 170 return ok; 171 } 172 173 static void 174 test_seqs(struct xkb_context *ctx) 175 { 176 struct xkb_compose_table *table; 177 char *path; 178 FILE *file; 179 180 path = test_get_path("compose/en_US.UTF-8/Compose"); 181 file = fopen(path, "r"); 182 assert(file); 183 free(path); 184 185 table = xkb_compose_table_new_from_file(ctx, file, "", 186 XKB_COMPOSE_FORMAT_TEXT_V1, 187 XKB_COMPOSE_COMPILE_NO_FLAGS); 188 assert(table); 189 fclose(file); 190 191 assert(test_compose_seq(table, 192 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 193 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 194 XKB_KEY_NoSymbol)); 195 196 assert(test_compose_seq(table, 197 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 198 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 199 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 200 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 201 XKB_KEY_NoSymbol)); 202 203 assert(test_compose_seq(table, 204 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 205 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 206 XKB_KEY_NoSymbol)); 207 208 assert(test_compose_seq(table, 209 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 210 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, 211 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, 212 XKB_KEY_NoSymbol)); 213 214 assert(test_compose_seq(table, 215 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 216 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_acute, 217 XKB_KEY_NoSymbol)); 218 219 assert(test_compose_seq(table, 220 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 221 XKB_KEY_Shift_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 222 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 223 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 224 XKB_KEY_Control_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 225 XKB_KEY_T, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "@", XKB_KEY_at, 226 XKB_KEY_NoSymbol)); 227 228 assert(test_compose_seq(table, 229 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 230 XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 231 XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 232 XKB_KEY_NoSymbol)); 233 234 assert(test_compose_seq(table, 235 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 236 XKB_KEY_apostrophe, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 237 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, 238 XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 239 XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 240 XKB_KEY_NoSymbol)); 241 242 xkb_compose_table_unref(table); 243 244 /* Make sure one-keysym sequences work. */ 245 assert(test_compose_seq_buffer(ctx, 246 "<A> : \"foo\" X \n" 247 "<B> <A> : \"baz\" Y \n", 248 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, 249 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, 250 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 251 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 252 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "baz", XKB_KEY_Y, 253 XKB_KEY_NoSymbol)); 254 255 /* No sequences at all. */ 256 assert(test_compose_seq_buffer(ctx, 257 "", 258 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 259 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 260 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 261 XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 262 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 263 XKB_KEY_NoSymbol)); 264 265 /* Only keysym - string derived from keysym. */ 266 assert(test_compose_seq_buffer(ctx, 267 "<A> <B> : X \n" 268 "<B> <A> : dollar \n" 269 "<C> : dead_acute \n", 270 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 271 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "X", XKB_KEY_X, 272 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 273 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "$", XKB_KEY_dollar, 274 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_dead_acute, 275 XKB_KEY_NoSymbol)); 276 277 /* Make sure a cancelling keysym doesn't start a new sequence. */ 278 assert(test_compose_seq_buffer(ctx, 279 "<A> <B> : X \n" 280 "<C> <D> : Y \n", 281 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 282 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, 283 XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 284 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 285 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, 286 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 287 XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "Y", XKB_KEY_Y, 288 XKB_KEY_NoSymbol)); 289 } 290 291 static void 292 test_conflicting(struct xkb_context *ctx) 293 { 294 // new is prefix of old 295 assert(test_compose_seq_buffer(ctx, 296 "<A> <B> <C> : \"foo\" A \n" 297 "<A> <B> : \"bar\" B \n", 298 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 299 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 300 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A, 301 XKB_KEY_NoSymbol)); 302 303 // old is a prefix of new 304 assert(test_compose_seq_buffer(ctx, 305 "<A> <B> : \"bar\" B \n" 306 "<A> <B> <C> : \"foo\" A \n", 307 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 308 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 309 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A, 310 XKB_KEY_NoSymbol)); 311 312 // new duplicate of old 313 assert(test_compose_seq_buffer(ctx, 314 "<A> <B> : \"bar\" B \n" 315 "<A> <B> : \"bar\" B \n", 316 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 317 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, 318 XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, 319 XKB_KEY_NoSymbol)); 320 321 // new same length as old #1 322 assert(test_compose_seq_buffer(ctx, 323 "<A> <B> : \"foo\" A \n" 324 "<A> <B> : \"bar\" B \n", 325 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 326 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, 327 XKB_KEY_NoSymbol)); 328 329 // new same length as old #2 330 assert(test_compose_seq_buffer(ctx, 331 "<A> <B> : \"foo\" A \n" 332 "<A> <B> : \"foo\" B \n", 333 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 334 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_B, 335 XKB_KEY_NoSymbol)); 336 337 // new same length as old #3 338 assert(test_compose_seq_buffer(ctx, 339 "<A> <B> : \"foo\" A \n" 340 "<A> <B> : \"bar\" A \n", 341 XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 342 XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_A, 343 XKB_KEY_NoSymbol)); 344 } 345 346 static void 347 test_state(struct xkb_context *ctx) 348 { 349 struct xkb_compose_table *table; 350 struct xkb_compose_state *state; 351 char *path; 352 FILE *file; 353 354 path = test_get_path("compose/en_US.UTF-8/Compose"); 355 file = fopen(path, "r"); 356 assert(file); 357 free(path); 358 359 table = xkb_compose_table_new_from_file(ctx, file, "", 360 XKB_COMPOSE_FORMAT_TEXT_V1, 361 XKB_COMPOSE_COMPILE_NO_FLAGS); 362 assert(table); 363 fclose(file); 364 365 state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); 366 assert(state); 367 368 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 369 xkb_compose_state_reset(state); 370 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 371 xkb_compose_state_feed(state, XKB_KEY_NoSymbol); 372 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 373 xkb_compose_state_feed(state, XKB_KEY_Multi_key); 374 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); 375 xkb_compose_state_reset(state); 376 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 377 xkb_compose_state_feed(state, XKB_KEY_Multi_key); 378 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); 379 xkb_compose_state_feed(state, XKB_KEY_Multi_key); 380 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); 381 xkb_compose_state_feed(state, XKB_KEY_Multi_key); 382 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); 383 xkb_compose_state_feed(state, XKB_KEY_Multi_key); 384 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); 385 xkb_compose_state_reset(state); 386 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 387 xkb_compose_state_feed(state, XKB_KEY_dead_acute); 388 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); 389 xkb_compose_state_feed(state, XKB_KEY_A); 390 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); 391 xkb_compose_state_reset(state); 392 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 393 xkb_compose_state_feed(state, XKB_KEY_dead_acute); 394 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); 395 xkb_compose_state_feed(state, XKB_KEY_A); 396 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); 397 xkb_compose_state_reset(state); 398 xkb_compose_state_feed(state, XKB_KEY_NoSymbol); 399 assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); 400 401 xkb_compose_state_unref(state); 402 xkb_compose_table_unref(table); 403 } 404 405 static void 406 test_XCOMPOSEFILE(struct xkb_context *ctx) 407 { 408 struct xkb_compose_table *table; 409 char *path; 410 411 path = test_get_path("compose/en_US.UTF-8/Compose"); 412 setenv("XCOMPOSEFILE", path, 1); 413 free(path); 414 415 table = xkb_compose_table_new_from_locale(ctx, "blabla", 416 XKB_COMPOSE_COMPILE_NO_FLAGS); 417 assert(table); 418 419 assert(test_compose_seq(table, 420 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 421 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 422 XKB_KEY_NoSymbol)); 423 424 xkb_compose_table_unref(table); 425 } 426 427 static void 428 test_modifier_syntax(struct xkb_context *ctx) 429 { 430 const char *table_string; 431 432 /* We don't do anything with the modifiers, but make sure we can parse 433 * them. */ 434 435 assert(test_compose_seq_buffer(ctx, 436 "None <A> : X \n" 437 "! Shift <B> : Y \n" 438 "! Ctrl <C> : Y \n" 439 "! Alt <D> : Y \n" 440 "! Caps <E> : Y \n" 441 "! Lock <F> : Y \n" 442 "! Shift Ctrl <G> : Y \n" 443 "! ~Shift <H> : Y \n" 444 "! ~Shift Ctrl <I> : Y \n" 445 "! Shift ~Ctrl <J> : Y \n" 446 "! Shift ~Ctrl ~Alt <K> : Y \n" 447 "<L> ! Shift <M> : Y \n" 448 "None <N> ! Shift <O> : Y \n" 449 "None <P> ! Shift <Q> : Y \n", 450 XKB_KEY_NoSymbol)); 451 452 fprintf(stderr, "<START bad input string>\n"); 453 table_string = 454 "! None <A> : X \n" 455 "! Foo <B> : X \n" 456 "None ! Shift <C> : X \n" 457 "! <D> : X \n" 458 "! ~ <E> : X \n" 459 "! ! <F> : X \n" 460 "! Ctrl ! Ctrl <G> : X \n" 461 "<H> ! : X \n" 462 "<I> None : X \n" 463 "None None <J> : X \n" 464 "<K> : !Shift X \n"; 465 assert(!xkb_compose_table_new_from_buffer(ctx, table_string, 466 strlen(table_string), "C", 467 XKB_COMPOSE_FORMAT_TEXT_V1, 468 XKB_COMPOSE_COMPILE_NO_FLAGS)); 469 fprintf(stderr, "<END bad input string>\n"); 470 } 471 472 static void 473 test_include(struct xkb_context *ctx) 474 { 475 char *path, *table_string; 476 int ret; 477 478 path = test_get_path("compose/en_US.UTF-8/Compose"); 479 assert(path); 480 481 /* We don't have a mechanism to change the include paths like we 482 * have for keymaps. So we must include the full path. */ 483 ret = asprintf(&table_string, 484 "<dead_tilde> <space> : \"foo\" X\n" 485 "include \"%s\"\n" 486 "<dead_tilde> <dead_tilde> : \"bar\" Y\n", path); 487 assert(ret >= 0); 488 489 assert(test_compose_seq_buffer(ctx, table_string, 490 /* No conflict. */ 491 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 492 XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_acute, 493 494 /* Comes before - doesn't override. */ 495 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 496 XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, 497 498 /* Comes after - does override. */ 499 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, 500 XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_Y, 501 502 XKB_KEY_NoSymbol)); 503 504 free(path); 505 free(table_string); 506 } 507 508 int 509 main(int argc, char *argv[]) 510 { 511 struct xkb_context *ctx; 512 513 ctx = test_get_context(CONTEXT_NO_FLAG); 514 assert(ctx); 515 516 test_seqs(ctx); 517 test_conflicting(ctx); 518 test_XCOMPOSEFILE(ctx); 519 test_state(ctx); 520 test_modifier_syntax(ctx); 521 test_include(ctx); 522 523 xkb_context_unref(ctx); 524 return 0; 525 } 526