diff options
author | Etienne Brateau <etienne.brateau@gmail.com> | 2024-03-10 00:48:38 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-03-10 17:00:12 +0100 |
commit | 3358b1473f52876c21e3acafe8f7eac41d01a290 (patch) | |
tree | 660b679180fd5254cf41b9d7d3f82bbb0f5ad3b8 /console-client/xkb/compose.c | |
parent | 66c891b1cb9ba42bd1824ef0dbffba503697c405 (diff) | |
download | hurd-3358b1473f52876c21e3acafe8f7eac41d01a290.tar.gz hurd-3358b1473f52876c21e3acafe8f7eac41d01a290.tar.bz2 hurd-3358b1473f52876c21e3acafe8f7eac41d01a290.zip |
console-client: use xkbcommon instead of x11 for xkb extended support
This allow to reduce the dependencies, only xkbcommon (keyboard support
only) is required instead of the whole x11 library + lex + yacc.
This replacement allow to reduce the code size, now features are handled
by xkbcommon itself.
The functionnalites remain the sames (actions are reimplemented
but in the code directly as it’s impossible to add custom actions).
The custom xkb data files are removed as we can now directly use the
standard ones from xkeyboard-config.
The configuration to launch the console keyboard modules changed to now
directly configure the model+layout+variat+options directly.
Tested by compiling with and without xkbcommon.
Tested X11 (ran i3 correctly).
Composing is still working.
Message-ID: <20240309234838.31923-1-etienne.brateau@gmail.com>
Diffstat (limited to 'console-client/xkb/compose.c')
-rw-r--r-- | console-client/xkb/compose.c | 592 |
1 files changed, 0 insertions, 592 deletions
diff --git a/console-client/xkb/compose.c b/console-client/xkb/compose.c deleted file mode 100644 index 955c820c..00000000 --- a/console-client/xkb/compose.c +++ /dev/null @@ -1,592 +0,0 @@ -/* compose.c -- Keysym composing - - Copyright (C) 2003 Marco Gerards - - Written by Marco Gerards <metgerards@student.han.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <X11/keysymdef.h> -#include "xkb.h" -#include <ctype.h> -#include <string.h> -#include <fcntl.h> -#include <unistd.h> -#include <locale.h> -#include <assert-backtrace.h> - -/* Tokens that can be recognised by the scanner. */ -enum tokentype - { - UNKNOWN, - EOL, - REQKS, - SEMICOL, - STR, - PRODKS, - END - }; - -/* The current token. */ -struct token -{ - enum tokentype toktype; - char value[50]; -} tok; - -/* The linenumber of the line currently parsed, used for returning - errors and warnings. */ -static int linenum; - -/* Read a token from the file CF. */ -static void -read_token (FILE *cf) -{ - int c = fgetc (cf); - int pos = 0; - - /* Remove whitespaces. */ - while (c == ' ' || c == '\t') - c = fgetc (cf); - - /* Comment, remove until end of line and return a EOL token. */ - if (c == '#') - { - while (c != '\n') - c = fgetc (cf); - tok.toktype = EOL; - linenum++; - return; - } - - /* End of file. */ - if (c == EOF) - { - tok.toktype = END; - return; - } - - /* Semicolon. */ - if (c == ':') - { - tok.toktype = SEMICOL; - return; - } - - /* End of line. */ - if (c == '\n') - { - linenum++; - tok.toktype = EOL; - return; - } - - - /* Required keysym. */ - if (c == '<') - { - while ((c = fgetc (cf)) != '>') - tok.value[pos++] = c; - tok.value[pos] = '\0'; - tok.toktype = REQKS; - return; - } - - /* Character string. */ - if (c == '"') - { - while ((c = fgetc (cf)) != '"') - { - if (c == '\\') - c = fgetc (cf); - - tok.value[pos++] = c; - } - tok.value[pos] = '\0'; - tok.toktype = STR; - return; - } - - /* Produced keysym. */ - if (isalpha (c)) - { - tok.value[pos++] = c; - while (isgraph (c = fgetc (cf))) - tok.value[pos++] = c; - tok.value[pos] = '\0'; - tok.toktype = PRODKS; - ungetc (c, cf); - return; - } - - /* Unknown token. */ - tok.toktype = UNKNOWN; - return; -} - -/* Compose sequence. */ -struct compose -{ - struct compose *left; - struct compose *right; - symbol *expected; - symbol produced; -} *compose_tree; - - -/* Compare symbol sequence s1 to symbol sequence s1. This function - works just like the strcmp function. */ -static int -symbolscmp (symbol *s1, symbol *s2) -{ - while (*s1 && *s2 && (*s1 == *s2)) - { - s1++;s2++; - } - if (*s1 < *s2) - return -1; - if (*s1 > *s2) - return 1; - return 0; -} - -/* Compare symbol sequence s1 to symbol sequence s1, compare a maximum - of N symbols. This function works just like the strcmp function. - */ -static int -symbolsncmp (symbol *s1, symbol *s2, int n) -{ - int cnt = 0; - while (*s1 && *s2 && (*s1 == *s2)) - { - if (++cnt == n) - break; - s1++;s2++; - } - - if (*s1 < *s2) - return -1; - if (*s1 > *s2) - return 1; - return 0; -} - - -/* Add the compose sequence EXP to the binary tree, store RESULT as - the keysym produced by EXP. */ -static struct compose * -composetree_add (struct compose *tree, symbol *exp, symbol result) -{ - int cmp; - - if (tree == NULL) - { - tree = malloc (sizeof (struct compose)); - tree->expected = exp; - tree->produced = result; - tree->left = tree->right = NULL; - - return tree; - } - - cmp = symbolscmp (exp, tree->expected); - if (cmp == 0) - { - printf ("Warning: line %d: Double sequence.\n", linenum); - free (exp); - } - else if (cmp < 0) - tree->left = composetree_add (tree->left, exp, result); - else - tree->right = composetree_add (tree->right, exp, result); - return tree; -} - -/* Parse the composefile CF and put all sequences in the binary tree - COMPOSE_TREE. This function may never fail because of syntactical or - lexalical errors, generate a warning instead. */ -static error_t -parse_composefile (FILE *cf) -{ - void skip_line (void) - { - while (tok.toktype != EOL && tok.toktype != END) - read_token (cf); - } - - for (;;) - { - /* Expected keysyms. */ - symbol exp[50]; - symbol *exps; - size_t expcnt = 0; - symbol sym; - - read_token (cf); - /* Blank line. */ - if (tok.toktype == EOL) - continue; - - /* End of file, done parsing. */ - if (tok.toktype == END) - return 0; - - if (tok.toktype != REQKS) - { - printf ("Warning: line %d: Keysym expected on beginning of line.\n", - linenum); - skip_line (); - continue; - } - - /* Keysym was recognised, add it. */ - sym = XStringToKeysym (tok.value); - if (!sym) - { - printf ("Warning: line %d: Unknown keysym \"%s\".\n", linenum, - tok.value); - skip_line (); - continue; - } - exp[expcnt++] = sym; - - do - { - read_token (cf); - /* If another required keysym is recognised, add it. */ - if (tok.toktype == REQKS) - { - sym = XStringToKeysym (tok.value); - if (!sym) - { - printf ("Warning: line %d: Unknown keysym \"%s\".\n", - linenum, tok.value); - skip_line (); - continue; - } - exp[expcnt++] = sym; - } - } while (tok.toktype == REQKS); - - if (tok.toktype != SEMICOL) - { - printf ("Warning: line %d: Semicolon expected.\n", linenum); - skip_line (); - continue; - } - - read_token (cf); - /* Force token and ignore it. */ - if (tok.toktype != STR) - { - printf ("Warning: line %d: string expected.\n", linenum); - skip_line (); - continue; - } - - read_token (cf); - if (tok.toktype != PRODKS) - { - printf ("Warning: line %d: keysym expected.\n", linenum); - skip_line (); - continue; - } - sym = XStringToKeysym (tok.value); - if (!sym) - { - printf ("Warning: line %d: Unknown keysym \"%s\".\n", linenum, - tok.value); - skip_line (); - continue; - } - - read_token (cf); - if (tok.toktype != EOL && tok.toktype != END) - { - printf ("Warning: line %d: end of line or end of file expected.\n", - linenum); - skip_line (); - continue; - } - - /* Add the production rule. */ - exp[expcnt++] = 0; - exps = malloc (sizeof (symbol) * expcnt); - memcpy (exps, exp, sizeof (symbol) * expcnt); - compose_tree = composetree_add (compose_tree, exps, sym); - } - return 0; -} - -/* Read keysyms passed to this function by S until a keysym can be - composed. If the first keysym cannot start a compose sequence return - the keysym. */ -symbol -compose_symbols (symbol s) -{ - /* Current position in the compose tree. */ - static struct compose *treepos = NULL; - /* Current compose sequence. */ - static symbol syms[100]; - /* Current position in the compose sequence. */ - static int pos = 0; - int cmp; - - if (!treepos) - treepos = compose_tree; - - /* Maximum sequence length reached. Some idiot typed this many - symbols and now we throw it all away, wheee!!! */ - if (pos == 99) - { - treepos = compose_tree; - pos = 0; - } - - /* Put the keysym in the compose sequence array. */ - syms[pos++] = s; - syms[pos] = 0; - - /* Search the tree for a keysym sequence that can match the current one. */ - while (treepos) - { - cmp = symbolsncmp (syms, treepos->expected, pos); - if (cmp == 0) - { - /* The keysym sequence was partially recognised, check if it - can completely match. */ - if (!symbolscmp (syms, treepos->expected)) - { - symbol ret = treepos->produced; - treepos = compose_tree; - pos = 0; - return ret; - } - - /* The sequence was partially recognised. */ - return -1; - } - - if (cmp < 0) - treepos = treepos->left; - else - treepos = treepos->right; - } - - /* Nothing can be found. */ - treepos = compose_tree; - - /* This ks should've started a sequence but couldn't be found, - just return it. */ - if (pos == 1) - { - pos = 0; - return s; - } - - debug_printf ("Invalid\n"); - /* Invalid keysym sequence. */ - pos = 0; - return -1; -} - -struct map_entry -{ - const char *left; - const char *right; -}; - -enum callback_result - { - NEXT, - DONE - }; - -typedef enum callback_result (*map_callback) (void *context, struct map_entry *entry); - -static error_t -map_iterate(const char *map_path, map_callback action, void *context) -{ - FILE *map; - char *buffer = NULL; - size_t buffer_size = 0; - size_t line_length = 0; - - assert_backtrace (map_path != NULL); - assert_backtrace (action != NULL); - - map = fopen (map_path, "r"); - - if (map == NULL) - return errno; - - while ( (line_length = getline (&buffer, &buffer_size, map)) != -1) - { - /* skips empty lines and comments */ - if (line_length < 1 || buffer[0] == '#') - continue; - else - { - struct map_entry entry = {NULL, NULL}; - char *end = buffer + line_length; - char *p = buffer; - - while (p != end && isspace(*p)) p++; - - if (p == end) - continue; - - entry.left = p; - - while (p != end && !isspace(*p)) p++; - - if (p != end) - { - *(p++) = 0; - while (p != end && isspace(*p)) p++; - - if (p != end) - { - entry.right = p; - while (p != end && !isspace(*p)) p++; - if (p != end) - *p = 0; - } - } - - if (action (context, &entry) == DONE) - break; - } - } - free (buffer); - fclose (map); - return 0; -} - -struct matcher_context -{ - char *value; - char *result; -}; - -static enum callback_result -match_left_set_right (void *context, struct map_entry *entry) -{ - struct matcher_context *ctx = (struct matcher_context *) context; - - if (strcmp (ctx->value, entry->left) == 0) - { - ctx->result = strdup (entry->right); - return DONE; - } - return NEXT; -} - -static enum callback_result -match_right_set_left (void *context, struct map_entry *entry) -{ - struct matcher_context *ctx = (struct matcher_context *) context; - - if (strcmp (ctx->value, entry->right) == 0) - { - ctx->result = strdup (entry->left); - return DONE; - } - return NEXT; -} - -/* Search for a compose file. - - According to Compose(5) man page the compose file searched in the - following locations: - - XCOMPOSEFILE variable. - - .XCompose at $HOME. - - System wide compose file for the current locale. */ -static char * -get_compose_file_for_locale(void) -{ - struct matcher_context context = { NULL }; - char *xcomposefile; - char *to_be_freed; - char *home; - int err; - - xcomposefile = getenv ("XCOMPOSEFILE"); - if (xcomposefile != NULL) - return strdup (xcomposefile); - - home = getenv ("HOME"); - if (home != NULL) - { - err = asprintf (&xcomposefile, "%s/.XCompose", home); - if (err != -1) - { - if (faccessat(AT_FDCWD, xcomposefile, R_OK, AT_EACCESS) == 0) - return xcomposefile; - else - { - free (xcomposefile); - /* TODO: check and report whether the compose file doesn't exist or - read permission was not granted to us. */ - } - } - } - - context.value = setlocale (LC_ALL, NULL); - map_iterate (X11_PREFIX "/share/X11/locale/locale.alias", match_left_set_right, &context); - to_be_freed = context.result; - - if (context.result != NULL) - { - /* Current locale is an alias. Use the real name to index the database. */ - context.value = context.result; - } - context.result = NULL; - map_iterate (X11_PREFIX "/share/X11/locale/compose.dir", match_right_set_left, &context); - free (to_be_freed); - - /* compose.dir contains relative paths to compose files. */ - to_be_freed = context.result; - err = asprintf (&context.result, X11_PREFIX "/share/X11/locale/%s", context.result); - if (err == -1) - context.result = NULL; - - free (to_be_freed); - return context.result; -} - -/* Read a Compose file. */ -error_t -read_composefile (char *composefn) -{ - FILE *cf; - - error_t err; - - if (composefn == NULL) - composefn = get_compose_file_for_locale (); - - cf = fopen (composefn, "r"); - if (cf == NULL) - return errno; - - err = parse_composefile (cf); - fclose (cf); - - return err; -} |