| /* |
| * Copyright © 2014 Ran Benita <ran234@gmail.com> |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include "config.h" |
| |
| #include "xkbcommon/xkbcommon-compose.h" |
| |
| #include "test.h" |
| |
| static const char * |
| compose_status_string(enum xkb_compose_status status) |
| { |
| switch (status) { |
| case XKB_COMPOSE_NOTHING: |
| return "nothing"; |
| case XKB_COMPOSE_COMPOSING: |
| return "composing"; |
| case XKB_COMPOSE_COMPOSED: |
| return "composed"; |
| case XKB_COMPOSE_CANCELLED: |
| return "cancelled"; |
| } |
| |
| return "<invalid-status>"; |
| } |
| |
| static const char * |
| feed_result_string(enum xkb_compose_feed_result result) |
| { |
| switch (result) { |
| case XKB_COMPOSE_FEED_IGNORED: |
| return "ignored"; |
| case XKB_COMPOSE_FEED_ACCEPTED: |
| return "accepted"; |
| } |
| |
| return "<invalid-result>"; |
| } |
| |
| /* |
| * Feed a sequence of keysyms to a fresh compose state and test the outcome. |
| * |
| * The varargs consists of lines in the following format: |
| * <input keysym> <expected feed result> <expected status> <expected string> <expected keysym> |
| * Terminated by a line consisting only of XKB_KEY_NoSymbol. |
| */ |
| static bool |
| test_compose_seq_va(struct xkb_compose_table *table, va_list ap) |
| { |
| int ret; |
| struct xkb_compose_state *state; |
| char buffer[64]; |
| |
| state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); |
| assert(state); |
| |
| for (int i = 1; ; i++) { |
| xkb_keysym_t input_keysym; |
| enum xkb_compose_feed_result result, expected_result; |
| enum xkb_compose_status status, expected_status; |
| const char *expected_string; |
| xkb_keysym_t keysym, expected_keysym; |
| |
| input_keysym = va_arg(ap, xkb_keysym_t); |
| if (input_keysym == XKB_KEY_NoSymbol) |
| break; |
| |
| expected_result = va_arg(ap, enum xkb_compose_feed_result); |
| expected_status = va_arg(ap, enum xkb_compose_status); |
| expected_string = va_arg(ap, const char *); |
| expected_keysym = va_arg(ap, xkb_keysym_t); |
| |
| result = xkb_compose_state_feed(state, input_keysym); |
| |
| if (result != expected_result) { |
| fprintf(stderr, "after feeding %d keysyms:\n", i); |
| fprintf(stderr, "expected feed result: %s\n", |
| feed_result_string(expected_result)); |
| fprintf(stderr, "got feed result: %s\n", |
| feed_result_string(result)); |
| goto fail; |
| } |
| |
| status = xkb_compose_state_get_status(state); |
| if (status != expected_status) { |
| fprintf(stderr, "after feeding %d keysyms:\n", i); |
| fprintf(stderr, "expected status: %s\n", |
| compose_status_string(expected_status)); |
| fprintf(stderr, "got status: %s\n", |
| compose_status_string(status)); |
| goto fail; |
| } |
| |
| ret = xkb_compose_state_get_utf8(state, buffer, sizeof(buffer)); |
| if (ret < 0 || (size_t) ret >= sizeof(buffer)) { |
| fprintf(stderr, "after feeding %d keysyms:\n", i); |
| fprintf(stderr, "expected string: %s\n", expected_string); |
| fprintf(stderr, "got error: %d\n", ret); |
| goto fail; |
| } |
| if (!streq(buffer, expected_string)) { |
| fprintf(stderr, "after feeding %d keysyms:\n", i); |
| fprintf(stderr, "expected string: %s\n", strempty(expected_string)); |
| fprintf(stderr, "got string: %s\n", buffer); |
| goto fail; |
| } |
| |
| keysym = xkb_compose_state_get_one_sym(state); |
| if (keysym != expected_keysym) { |
| fprintf(stderr, "after feeding %d keysyms:\n", i); |
| xkb_keysym_get_name(expected_keysym, buffer, sizeof(buffer)); |
| fprintf(stderr, "expected keysym: %s\n", buffer); |
| xkb_keysym_get_name(keysym, buffer, sizeof(buffer)); |
| fprintf(stderr, "got keysym (%#x): %s\n", keysym, buffer); |
| goto fail; |
| } |
| } |
| |
| xkb_compose_state_unref(state); |
| return true; |
| |
| fail: |
| xkb_compose_state_unref(state); |
| return false; |
| } |
| |
| static bool |
| test_compose_seq(struct xkb_compose_table *table, ...) |
| { |
| va_list ap; |
| bool ok; |
| va_start(ap, table); |
| ok = test_compose_seq_va(table, ap); |
| va_end(ap); |
| return ok; |
| } |
| |
| static bool |
| test_compose_seq_buffer(struct xkb_context *ctx, const char *buffer, ...) |
| { |
| va_list ap; |
| bool ok; |
| struct xkb_compose_table *table; |
| table = xkb_compose_table_new_from_buffer(ctx, buffer, strlen(buffer), "", |
| XKB_COMPOSE_FORMAT_TEXT_V1, |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| va_start(ap, buffer); |
| ok = test_compose_seq_va(table, ap); |
| va_end(ap); |
| xkb_compose_table_unref(table); |
| return ok; |
| } |
| |
| static void |
| test_seqs(struct xkb_context *ctx) |
| { |
| struct xkb_compose_table *table; |
| char *path; |
| FILE *file; |
| |
| path = test_get_path("locale/en_US.UTF-8/Compose"); |
| file = fopen(path, "rb"); |
| assert(file); |
| free(path); |
| |
| table = xkb_compose_table_new_from_file(ctx, file, "", |
| XKB_COMPOSE_FORMAT_TEXT_V1, |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| fclose(file); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, |
| XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_Shift_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_Control_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_T, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "@", XKB_KEY_at, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_NoSymbol)); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_apostrophe, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, |
| XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_NoSymbol)); |
| |
| xkb_compose_table_unref(table); |
| |
| /* Make sure one-keysym sequences work. */ |
| assert(test_compose_seq_buffer(ctx, |
| "<A> : \"foo\" X \n" |
| "<B> <A> : \"baz\" Y \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "baz", XKB_KEY_Y, |
| XKB_KEY_NoSymbol)); |
| |
| /* No sequences at all. */ |
| assert(test_compose_seq_buffer(ctx, |
| "", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_NoSymbol)); |
| |
| /* Only keysym - string derived from keysym. */ |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : X \n" |
| "<B> <A> : dollar \n" |
| "<C> : dead_acute \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "X", XKB_KEY_X, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "$", XKB_KEY_dollar, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_dead_acute, |
| XKB_KEY_NoSymbol)); |
| |
| /* Make sure a cancelling keysym doesn't start a new sequence. */ |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : X \n" |
| "<C> <D> : Y \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, |
| XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "Y", XKB_KEY_Y, |
| XKB_KEY_NoSymbol)); |
| } |
| |
| static void |
| test_conflicting(struct xkb_context *ctx) |
| { |
| // new is prefix of old |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> <C> : \"foo\" A \n" |
| "<A> <B> : \"bar\" B \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A, |
| XKB_KEY_NoSymbol)); |
| |
| // old is a prefix of new |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : \"bar\" B \n" |
| "<A> <B> <C> : \"foo\" A \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A, |
| XKB_KEY_NoSymbol)); |
| |
| // new duplicate of old |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : \"bar\" B \n" |
| "<A> <B> : \"bar\" B \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, |
| XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_NoSymbol)); |
| |
| // new same length as old #1 |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : \"foo\" A \n" |
| "<A> <B> : \"bar\" B \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, |
| XKB_KEY_NoSymbol)); |
| |
| // new same length as old #2 |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : \"foo\" A \n" |
| "<A> <B> : \"foo\" B \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_B, |
| XKB_KEY_NoSymbol)); |
| |
| // new same length as old #3 |
| assert(test_compose_seq_buffer(ctx, |
| "<A> <B> : \"foo\" A \n" |
| "<A> <B> : \"bar\" A \n", |
| XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_A, |
| XKB_KEY_NoSymbol)); |
| } |
| |
| static void |
| test_state(struct xkb_context *ctx) |
| { |
| struct xkb_compose_table *table; |
| struct xkb_compose_state *state; |
| char *path; |
| FILE *file; |
| |
| path = test_get_path("locale/en_US.UTF-8/Compose"); |
| file = fopen(path, "rb"); |
| assert(file); |
| free(path); |
| |
| table = xkb_compose_table_new_from_file(ctx, file, "", |
| XKB_COMPOSE_FORMAT_TEXT_V1, |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| fclose(file); |
| |
| state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); |
| assert(state); |
| |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_reset(state); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_feed(state, XKB_KEY_NoSymbol); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_feed(state, XKB_KEY_Multi_key); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); |
| xkb_compose_state_reset(state); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_feed(state, XKB_KEY_Multi_key); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); |
| xkb_compose_state_feed(state, XKB_KEY_Multi_key); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); |
| xkb_compose_state_feed(state, XKB_KEY_Multi_key); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); |
| xkb_compose_state_feed(state, XKB_KEY_Multi_key); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); |
| xkb_compose_state_reset(state); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_feed(state, XKB_KEY_dead_acute); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); |
| xkb_compose_state_feed(state, XKB_KEY_A); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); |
| xkb_compose_state_reset(state); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| xkb_compose_state_feed(state, XKB_KEY_dead_acute); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); |
| xkb_compose_state_feed(state, XKB_KEY_A); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); |
| xkb_compose_state_reset(state); |
| xkb_compose_state_feed(state, XKB_KEY_NoSymbol); |
| assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); |
| |
| xkb_compose_state_unref(state); |
| xkb_compose_table_unref(table); |
| } |
| |
| static void |
| test_XCOMPOSEFILE(struct xkb_context *ctx) |
| { |
| struct xkb_compose_table *table; |
| char *path; |
| |
| path = test_get_path("locale/en_US.UTF-8/Compose"); |
| setenv("XCOMPOSEFILE", path, 1); |
| free(path); |
| |
| table = xkb_compose_table_new_from_locale(ctx, "blabla", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| |
| unsetenv("XCOMPOSEFILE"); |
| |
| assert(test_compose_seq(table, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| XKB_KEY_NoSymbol)); |
| |
| xkb_compose_table_unref(table); |
| } |
| |
| static void |
| test_from_locale(struct xkb_context *ctx) |
| { |
| struct xkb_compose_table *table; |
| char *path; |
| |
| path = test_get_path("locale"); |
| setenv("XLOCALEDIR", path, 1); |
| free(path); |
| |
| /* Direct directory name match. */ |
| table = xkb_compose_table_new_from_locale(ctx, "en_US.UTF-8", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| xkb_compose_table_unref(table); |
| |
| /* Direct locale name match. */ |
| table = xkb_compose_table_new_from_locale(ctx, "C.UTF-8", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| xkb_compose_table_unref(table); |
| |
| /* Alias. */ |
| table = xkb_compose_table_new_from_locale(ctx, "univ.utf8", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| xkb_compose_table_unref(table); |
| |
| /* Special case - C. */ |
| table = xkb_compose_table_new_from_locale(ctx, "C", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(table); |
| xkb_compose_table_unref(table); |
| |
| /* Bogus - not found. */ |
| table = xkb_compose_table_new_from_locale(ctx, "blabla", |
| XKB_COMPOSE_COMPILE_NO_FLAGS); |
| assert(!table); |
| |
| unsetenv("XLOCALEDIR"); |
| } |
| |
| |
| static void |
| test_modifier_syntax(struct xkb_context *ctx) |
| { |
| const char *table_string; |
| |
| /* We don't do anything with the modifiers, but make sure we can parse |
| * them. */ |
| |
| assert(test_compose_seq_buffer(ctx, |
| "None <A> : X \n" |
| "Shift <B> : Y \n" |
| "Ctrl <C> : Y \n" |
| "Alt <D> : Y \n" |
| "Caps <E> : Y \n" |
| "Lock <F> : Y \n" |
| "Shift Ctrl <G> : Y \n" |
| "~Shift <H> : Y \n" |
| "~Shift Ctrl <I> : Y \n" |
| "Shift ~Ctrl <J> : Y \n" |
| "Shift ~Ctrl ~Alt <K> : Y \n" |
| "! Shift <B> : Y \n" |
| "! Ctrl <C> : Y \n" |
| "! Alt <D> : Y \n" |
| "! Caps <E> : Y \n" |
| "! Lock <F> : Y \n" |
| "! Shift Ctrl <G> : Y \n" |
| "! ~Shift <H> : Y \n" |
| "! ~Shift Ctrl <I> : Y \n" |
| "! Shift ~Ctrl <J> : Y \n" |
| "! Shift ~Ctrl ~Alt <K> : Y \n" |
| "<L> ! Shift <M> : Y \n" |
| "None <N> ! Shift <O> : Y \n" |
| "None <P> ! Shift <Q> : Y \n", |
| XKB_KEY_NoSymbol)); |
| |
| fprintf(stderr, "<START bad input string>\n"); |
| table_string = |
| "! None <A> : X \n" |
| "! Foo <B> : X \n" |
| "None ! Shift <C> : X \n" |
| "! ! <D> : X \n" |
| "! ~ <E> : X \n" |
| "! ! <F> : X \n" |
| "! Ctrl ! Ctrl <G> : X \n" |
| "<H> ! : X \n" |
| "<I> None : X \n" |
| "None None <J> : X \n" |
| "<K> : !Shift X \n"; |
| assert(!xkb_compose_table_new_from_buffer(ctx, table_string, |
| strlen(table_string), "C", |
| XKB_COMPOSE_FORMAT_TEXT_V1, |
| XKB_COMPOSE_COMPILE_NO_FLAGS)); |
| fprintf(stderr, "<END bad input string>\n"); |
| } |
| |
| static void |
| test_include(struct xkb_context *ctx) |
| { |
| char *path, *table_string; |
| |
| path = test_get_path("locale/en_US.UTF-8/Compose"); |
| assert(path); |
| |
| /* We don't have a mechanism to change the include paths like we |
| * have for keymaps. So we must include the full path. */ |
| table_string = asprintf_safe("<dead_tilde> <space> : \"foo\" X\n" |
| "include \"%s\"\n" |
| "<dead_tilde> <dead_tilde> : \"bar\" Y\n", path); |
| assert(table_string); |
| |
| assert(test_compose_seq_buffer(ctx, table_string, |
| /* No conflict. */ |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute, |
| |
| /* Comes before - doesn't override. */ |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, |
| |
| /* Comes after - does override. */ |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, |
| XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_Y, |
| |
| XKB_KEY_NoSymbol)); |
| |
| free(path); |
| free(table_string); |
| } |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct xkb_context *ctx; |
| |
| ctx = test_get_context(CONTEXT_NO_FLAG); |
| assert(ctx); |
| |
| test_seqs(ctx); |
| test_conflicting(ctx); |
| test_XCOMPOSEFILE(ctx); |
| test_from_locale(ctx); |
| test_state(ctx); |
| test_modifier_syntax(ctx); |
| test_include(ctx); |
| |
| xkb_context_unref(ctx); |
| return 0; |
| } |