Update bundled libxkbcommon version to 0.4.0

This release comes with important bug fixes. Also we can now
remove the workaround code which was needed for libxkbcommon 0.2.0.

Task-number: QTBUG-31712
Task-number: QTBUG-33732
Task-number: QTBUG-34056

Change-Id: I57caf7f803b9a01a15541a5ad82e464de3b8abbb
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Gatis Paeglis 2014-02-05 16:25:06 +01:00 committed by The Qt Project
parent c6b555dac3
commit b19b080894
55 changed files with 11434 additions and 9374 deletions

87
configure vendored
View File

@ -3172,7 +3172,7 @@ if [ "$XPLATFORM_MAC" = "no" -a "$CFG_DEBUG_RELEASE" = "yes" ]; then
echo
fi
if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
if ( [ "$CFG_XCB" = "system" ] || [ "$CFG_XCB" = "qt" ] ) && [ "$CFG_XKBCOMMON" = "no" ]; then
echo "Error: -no-xkbcommon is not supported on XCB platform plugin."
exit 101
fi
@ -5213,26 +5213,30 @@ if [ "$CFG_XCB" != "no" ]; then
fi
QMakeVar set QMAKE_X11_PREFIX "$QMAKE_X11_PREFIX"
if compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
if [ "$CFG_XKBCOMMON" != no ] && compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
QT_CONFIG="$QT_CONFIG xcb-plugin"
if [ "$CFG_XCB" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xcb-qt"
else
CFG_XCB="system"
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xcb >= 1.5" 2>/dev/null; then
XCB_PACKAGES="xcb xcb-shm xcb-sync xcb-xfixes xcb-randr xcb-image xcb-keysyms xcb-icccm xcb-shape"
QMAKE_CFLAGS_XCB="`$PKG_CONFIG --cflags $XCB_PACKAGES 2>/dev/null`"
QMAKE_LIBS_XCB="`$PKG_CONFIG --libs $XCB_PACKAGES 2>/dev/null`"
# for xcb-xkb tests
QMAKE_CFLAGS_XKB="`$PKG_CONFIG --cflags xcb xcb-xkb 2>/dev/null`"
QMAKE_LIBS_XKB="`$PKG_CONFIG --libs xcb xcb-xkb 2>/dev/null`"
fi
if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
CFG_XKB=yes
else
CFG_XKB=no
# libxcb version 1.10 was the first version that enables xcb-xkb by default,
# therefore the minimal xcb-xkb version we support is 1.10
CFG_XKB=no
if $PKG_CONFIG --exists "xcb-xkb >= 1.10" 2>/dev/null; then
QMAKE_CFLAGS_XKB="`$PKG_CONFIG --cflags xcb xcb-xkb 2>/dev/null`"
QMAKE_LIBS_XKB="`$PKG_CONFIG --libs xcb xcb-xkb 2>/dev/null`"
if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
CFG_XKB=yes
fi
fi
if [ "$CFG_XKB" = "no" ]; then
QMakeVar add DEFINES QT_NO_XKB
fi
@ -5328,52 +5332,45 @@ fi
# Detect libxkbcommon
ORIG_CFG_XKBCOMMON="$CFG_XKBCOMMON"
if [ "$CFG_XKBCOMMON" != "qt" ]; then
# currently only xcb platform plugin requires xkbcommon, for other platforms it can be set to 'no'
if [ "$CFG_XKBCOMMON" != "no" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon >= 0.2.0" 2>/dev/null; then
QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon 2>/dev/null`"
QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon 2>/dev/null`"
QMAKE_VERSION_XKBCOMMON="`$PKG_CONFIG --modversion xkbcommon 2>/dev/null`"
# currently only xcb platform plugin supports building xkbcommon
if [ "$CFG_XCB" != "no" ]; then
if [ "$CFG_XKBCOMMON" = "auto" ] || [ "$CFG_XKBCOMMON" = "system" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon xkbcommon-x11 >= 0.4.0" 2>/dev/null; then
QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon xkbcommon-x11 2>/dev/null`"
QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon xkbcommon-x11 2>/dev/null`"
QMakeVar set QMAKE_CFLAGS_XKBCOMMON "$QMAKE_CFLAGS_XKBCOMMON"
QMakeVar set QMAKE_LIBS_XKBCOMMON "$QMAKE_LIBS_XKBCOMMON"
QMakeVar set QMAKE_VERSION_XKBCOMMON "$QMAKE_VERSION_XKBCOMMON"
CFG_XKBCOMMON=system
else
CFG_XKBCOMMON=no
fi
if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
# use the bundled version instead
CFG_XKBCOMMON=qt
fi
fi
fi
if [ "$CFG_XKBCOMMON" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xkbcommon-qt"
# detect XKB config root
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
else
# search for xkb configs in most probable locations
if [ -d "/usr/share/X11/xkb" ]; then
# Linux
CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
elif [ -d "/usr/local/share/X11/xkb" ]; then
# BSD UNIX
CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
if [ "$CFG_XKBCOMMON" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xkbcommon-qt"
# detect XKB config root
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
else
# search for xkb configs in most probable locations
if [ -d "/usr/share/X11/xkb" ]; then
# Linux
CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
elif [ -d "/usr/local/share/X11/xkb" ]; then
# BSD UNIX
CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
fi
fi
fi
QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
CFG_XKB_CONFIG_ROOT="not found"
fi
fi
QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
CFG_XKB_CONFIG_ROOT="not found"
fi
elif [ "$CFG_XKBCOMMON" = "no" ]; then
QMakeVar add DEFINES QT_NO_XKBCOMMON
else
CFG_XKBCOMMON=no
fi
# EGL Support
@ -6852,7 +6849,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo
fi
if [ "$ORIG_CFG_XKBCOMMON" != qt ] && [ "$CFG_XKBCOMMON" = qt ]; then
echo "NOTE: libxkbcommon 0.2.0 (or higher) not found on the system, will use "
echo "NOTE: libxkbcommon and libxkbcommon-x11 0.4.0 or higher not found on the system, will use "
echo "the bundled version from 3rd party directory."
fi
if [ "$CFG_XKBCOMMON" = "qt" ] && [ "$CFG_XKB_CONFIG_ROOT" = "not found" ]; then

View File

@ -1,15 +1,20 @@
QMAKE_CFLAGS += -std=gnu99 -w
INCLUDEPATH += $$PWD/xkbcommon $$PWD/xkbcommon/src $$PWD/xkbcommon/src/xkbcomp
INCLUDEPATH += $$PWD/xkbcommon \
$$PWD/xkbcommon/xkbcommon \
$$PWD/xkbcommon/src \
$$PWD/xkbcommon/src/xkbcomp
DEFINES += DFLT_XKB_CONFIG_ROOT='\\"$$QMAKE_XKB_CONFIG_ROOT\\"'
### RMLVO names can be overwritten with environmental variables (See libxkbcommon documentation)
### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation)
DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"'
DEFINES += DEFAULT_XKB_MODEL='\\"pc105\\"'
DEFINES += DEFAULT_XKB_LAYOUT='\\"us\\"'
# Need to rename several files, qmake has problems processing a project when
# sub-directories contain files with an equal names.
# Need to rename 2 files, qmake has problems processing a project when
# directories contain files with equal names.
# libxkbcommon generates some of these files while executing "./autogen.sh"
# and some while executing "make" (actually YACC)
SOURCES += \
$$PWD/xkbcommon/src/atom.c \
$$PWD/xkbcommon/src/xkb-compat.c \ # renamed: compat.c -> xkb-compat.c
@ -18,7 +23,10 @@ SOURCES += \
$$PWD/xkbcommon/src/keysym.c \
$$PWD/xkbcommon/src/keysym-utf.c \
$$PWD/xkbcommon/src/state.c \
$$PWD/xkbcommon/src/text.c
$$PWD/xkbcommon/src/text.c \
$$PWD/xkbcommon/src/context-priv.c \
$$PWD/xkbcommon/src/keymap-priv.c \
$$PWD/xkbcommon/src/utils.c
SOURCES += \
$$PWD/xkbcommon/src/xkbcomp/action.c \
@ -29,12 +37,24 @@ SOURCES += \
$$PWD/xkbcommon/src/xkbcomp/keycodes.c \
$$PWD/xkbcommon/src/xkbcomp/keymap-dump.c \
$$PWD/xkbcommon/src/xkbcomp/keymap.c \
$$PWD/xkbcommon/src/xkbcomp/parser.c \
$$PWD/xkbcommon/src/xkbcomp/keywords.c \
$$PWD/xkbcommon/src/xkbcomp/rules.c \
$$PWD/xkbcommon/src/xkbcomp/scanner.c \
$$PWD/xkbcommon/src/xkbcomp/symbols.c \
$$PWD/xkbcommon/src/xkbcomp/types.c \
$$PWD/xkbcommon/src/xkbcomp/vmod.c \
$$PWD/xkbcommon/src/xkbcomp/xkbcomp.c
$$PWD/xkbcommon/src/xkbcomp/xkbcomp.c \
$$PWD/xkbcommon/src/xkbcomp/parser.c
!contains(DEFINES, QT_NO_XKB):contains(QT_CONFIG, use-xkbcommon-x11support): {
# Build xkbcommon-x11 support library, it depends on -lxcb and -lxcb-xkb, linking is done
# in xcb-plugin.pro (linked to system libraries or if Qt was configured with -qt-xcb then
# linked to -lxcb-static).
INCLUDEPATH += $$PWD/xkbcommon/src/x11
SOURCES += \
$$PWD/xkbcommon/src/x11/util.c \
$$PWD/xkbcommon/src/x11/x11-keymap.c \ # renamed: keymap.c -> x11-keymap.c
$$PWD/xkbcommon/src/x11/x11-state.c # renamed: state.c -> x11-keymap.c
}
TR_EXCLUDE += $$PWD/*

86
src/3rdparty/xkbcommon/NEWS vendored Normal file
View File

@ -0,0 +1,86 @@
libxkbcommon 0.4.0
==================
- Add a new add-on library, xkbcommon-x11, to support creating keymaps
with the XKB X11 protocol, by querying the X server directly.
See the xkbcommon/xkbcommon-x11.h header file for more details.
This library requires libxcb-xkb >= 1.10, and is enabled by default.
It can be disabled with the --disable-x11 configure switch.
Distributions are encouraged to split the necessary files for this
library (libxkbcommon-x11.so, xkbcommon-x11.pc, xkbcommon/xkbcommon-x11.h)
to a separate package, such that the main package does not depend on
X11 libraries.
- Fix the keysym <-> name lookup table to not require huge amounts of
relocations.
- Fix a bug in the keysym <-> name lookup, whereby lookup might fail in
some rare cases.
- Reduce memory usage during keymap compilation.
- New API:
New keysyms from xproto 7.0.25 (German T3 layout keysyms).
XKB_MOD_NAME_NUM for the usual NumLock modifier.
xkb_x11_* types and functions, XKB_X11_* constants.
libxkbcommon 0.3.2
==================
- Log messages from the library now look like "xkbcommon: ERROR" by
default, instead of xkbcomp-like "Error: ".
- Apply capitalization transformation on keysyms in
xkb_keysym_get_one_sym(), to match the behavior specified in the XKB
specification:
http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
- Support byacc for generating the parser, in addition to Bison.
- New API:
XKB_KEY_XF86AudioMicMute keysym from xproto 7.0.24.
XKB_KEYSYM_NO_FLAGS
XKB_CONTEXT_NO_FLAGS
XKB_MAP_COMPILE_NO_FLAGS
- Bug fixes.
libxkbcommon 0.3.1
==================
- Replace the flex scanner with a hand-written one. flex is no longer
a build requirement.
- New API:
xkb_keymap_min_keycode()
xkb_keymap_max_keycode()
xkb_keymap_key_for_each()
libxkbcommon 0.3.0
==================
- Allow passing NULL to *_unref() functions; do nothing instead of
crashing.
- The functions xkb_keymap_num_levels_for_key() and
xkb_keymap_get_syms_by_level() now allow out-of-range values for the
'layout' parameter. The functions now wrap the value around the number
of layouts instead of failing.
- The function xkb_keysym_get_name() now types unicode keysyms in
uppercase and 0-padding, to match the format used by XKeysymToString().
- Building Linux-specific tests is no longer attempted on non-Linux
environments.
- The function xkb_keymap_new_from_names() now accepts a NULL value for
the 'names' parameter, instead of failing. This is equivalent to passing
a 'struct xkb_rule_names' with all fields set to NULL.
- New API:
xkb_keymap_new_from_buffer()
- Bug fixes.

View File

@ -25,27 +25,17 @@ API
While xkbcommon's API is somewhat derived from the classic XKB API as found
in <X11/extensions/XKB.h> and friends, it has been substantially reworked to
expose fewer internal details to clients. The only supported API is available
in <xkbcommon/xkbcommon.h>. Any definition not in this header (including
accessing internal structures through the old macros previously available)
should be regarded as an implementation detail and is liable to change at any
time.
expose fewer internal details to clients. The supported API is available
in the <xkbcommon/xkbcommon-*.h> files. Additional support is provided for
X11 (XCB) clients, in the xkbcommon-x11 library, <xkbcommon/xkbcommon-x11.h>.
During its early development, xkbcommon does not promise API or ABI stability.
Regardless, we will attempt to not break ABI during a minor release series,
so applications written against 0.1.0 should be completely compatible with
0.1.3, but not necessarily with 0.2.0. However, new symbols may be introduced
in any release. Thus, anyone packaging xkbcommon should make sure any package
depending on it depends on a release greater than or equal to the version it
was built against (or earlier, if it doesn't use any newly-introduced
symbols), but less than the next major release.
xkbcommon 1.x will offer full API and ABI stability for its lifetime, with a
soname of libxkbcommon.so.1. Any ABI breaks will wait until xkbcommon 2.0,
which will be libxkbcommon.so.2.
The xkbcomp command-line tool has also been removed, although this will
likely reappear in a later release.
The xkbcommon API and ABI are stable. We will attempt to not break ABI during
a minor release series, so applications written against 0.1.0 should be
completely compatible with 0.5.3, but not necessarily with 1.0.0. However, new
symbols may be introduced in any release. Thus, anyone packaging xkbcommon
should make sure any package depending on it depends on a release greater than
or equal to the version it was built against (or earlier, if it doesn't use
any newly-introduced symbols), but less than the next major release.
Relation to X11
@ -101,19 +91,24 @@ Development
An extremely rudimentary homepage can be found at:
http://xkbcommon.org
xkbcommon is maintained in git at freedesktop.org:
git://anongit.freedesktop.org/git/libxkbcommon
xkbcommon is maintained in git at github.com:
https://github.com/xkbcommon/libxkbcommon
Patches are always welcome, and may be sent to either xorg-devel@lists.x.org,
or wayland-devel@lists.freedesktop.org. Bugs are tracked in Bugzilla at:
http://bugs.freedesktop.org
or wayland-devel@lists.freedesktop.org.
The maintainer is Daniel Stone, who can be reached at:
Bugs are tracked in Bugzilla at:
https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon
Or in github at:
https://github.com/xkbcommon/libxkbcommon/issues
The maintainers are Daniel Stone and Ran Benita, who can be reached at:
<daniel@fooishbar.org>
<ran234@gmail.com>
Credits
=======
Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon
off the ground initially, as well as to Ran Benita for subsequent development.
off the ground initially.

View File

@ -74,15 +74,15 @@
#include "atom.h"
struct atom_node {
struct atom_node *left, *right;
xkb_atom_t left, right;
xkb_atom_t atom;
unsigned int fingerprint;
char *string;
};
struct atom_table {
struct atom_node *root;
darray(struct atom_node *) table;
xkb_atom_t root;
darray(struct atom_node) table;
};
struct atom_table *
@ -95,31 +95,22 @@ atom_table_new(void)
return NULL;
darray_init(table->table);
darray_growalloc(table->table, 100);
darray_append(table->table, NULL);
/* The original throw-away root is here, at the illegal atom 0. */
darray_resize0(table->table, 1);
return table;
}
static void
free_atom(struct atom_node *patom)
{
if (!patom)
return;
free_atom(patom->left);
free_atom(patom->right);
free(patom->string);
free(patom);
}
void
atom_table_free(struct atom_table *table)
{
struct atom_node *node;
if (!table)
return;
free_atom(table->root);
darray_foreach(node, table->table)
free(node->string);
darray_free(table->table);
free(table);
}
@ -127,52 +118,42 @@ atom_table_free(struct atom_table *table)
const char *
atom_text(struct atom_table *table, xkb_atom_t atom)
{
if (atom >= darray_size(table->table) ||
darray_item(table->table, atom) == NULL)
if (atom == XKB_ATOM_NONE || atom >= darray_size(table->table))
return NULL;
return darray_item(table->table, atom)->string;
}
char *
atom_strdup(struct atom_table *table, xkb_atom_t atom)
{
return strdup_safe(atom_text(table, atom));
return darray_item(table->table, atom).string;
}
static bool
find_node_pointer(struct atom_table *table, const char *string,
struct atom_node ***np_out, unsigned int *fingerprint_out)
find_atom_pointer(struct atom_table *table, const char *string, size_t len,
xkb_atom_t **atomp_out, unsigned int *fingerprint_out)
{
struct atom_node **np;
unsigned i;
int comp;
unsigned int fp = 0;
size_t len;
xkb_atom_t *atomp = &table->root;
unsigned int fingerprint = 0;
bool found = false;
len = strlen(string);
np = &table->root;
for (i = 0; i < (len + 1) / 2; i++) {
fp = fp * 27 + string[i];
fp = fp * 27 + string[len - 1 - i];
for (size_t i = 0; i < (len + 1) / 2; i++) {
fingerprint = fingerprint * 27 + string[i];
fingerprint = fingerprint * 27 + string[len - 1 - i];
}
while (*np) {
if (fp < (*np)->fingerprint) {
np = &((*np)->left);
while (*atomp != XKB_ATOM_NONE) {
struct atom_node *node = &darray_item(table->table, *atomp);
if (fingerprint < node->fingerprint) {
atomp = &node->left;
}
else if (fp > (*np)->fingerprint) {
np = &((*np)->right);
else if (fingerprint > node->fingerprint) {
atomp = &node->right;
}
else {
/* now start testing the strings */
comp = strncmp(string, (*np)->string, len);
if (comp < 0 || (comp == 0 && len < strlen((*np)->string))) {
np = &((*np)->left);
/* Now start testing the strings. */
const int cmp = strncmp(string, node->string, len);
if (cmp < 0 || (cmp == 0 && len < strlen(node->string))) {
atomp = &node->left;
}
else if (comp > 0) {
np = &((*np)->right);
else if (cmp > 0) {
atomp = &node->right;
}
else {
found = true;
@ -181,68 +162,64 @@ find_node_pointer(struct atom_table *table, const char *string,
}
}
*fingerprint_out = fp;
*np_out = np;
if (fingerprint_out)
*fingerprint_out = fingerprint;
if (atomp_out)
*atomp_out = atomp;
return found;
}
xkb_atom_t
atom_lookup(struct atom_table *table, const char *string)
atom_lookup(struct atom_table *table, const char *string, size_t len)
{
struct atom_node **np;
unsigned int fp;
xkb_atom_t *atomp;
if (!string)
return XKB_ATOM_NONE;
if (!find_node_pointer(table, string, &np, &fp))
if (!find_atom_pointer(table, string, len, &atomp, NULL))
return XKB_ATOM_NONE;
return (*np)->atom;
return *atomp;
}
/*
* If steal is true, we do not strdup @string; therefore it must be
* dynamically allocated, not be free'd by the caller and not be used
* afterwards. Use to avoid some redundant allocations.
* dynamically allocated, NUL-terminated, not be free'd by the caller
* and not be used afterwards. Use to avoid some redundant allocations.
*/
xkb_atom_t
atom_intern(struct atom_table *table, const char *string,
atom_intern(struct atom_table *table, const char *string, size_t len,
bool steal)
{
struct atom_node **np;
struct atom_node *nd;
unsigned int fp;
xkb_atom_t *atomp;
struct atom_node node;
unsigned int fingerprint;
if (!string)
return XKB_ATOM_NONE;
if (find_node_pointer(table, string, &np, &fp)) {
if (find_atom_pointer(table, string, len, &atomp, &fingerprint)) {
if (steal)
free(UNCONSTIFY(string));
return (*np)->atom;
return *atomp;
}
nd = malloc(sizeof(*nd));
if (!nd)
return XKB_ATOM_NONE;
if (steal) {
nd->string = UNCONSTIFY(string);
node.string = UNCONSTIFY(string);
}
else {
nd->string = strdup(string);
if (!nd->string) {
free(nd);
node.string = strndup(string, len);
if (!node.string)
return XKB_ATOM_NONE;
}
}
*np = nd;
nd->left = nd->right = NULL;
nd->fingerprint = fp;
nd->atom = darray_size(table->table);
darray_append(table->table, nd);
node.left = node.right = XKB_ATOM_NONE;
node.fingerprint = fingerprint;
node.atom = darray_size(table->table);
/* Do this before the append, as it may realloc and change the offsets. */
*atomp = node.atom;
darray_append(table->table, node);
return nd->atom;
return node.atom;
}

View File

@ -37,15 +37,12 @@ void
atom_table_free(struct atom_table *table);
xkb_atom_t
atom_lookup(struct atom_table *table, const char *string);
atom_lookup(struct atom_table *table, const char *string, size_t len);
xkb_atom_t
atom_intern(struct atom_table *table, const char *string,
atom_intern(struct atom_table *table, const char *string, size_t len,
bool steal);
char *
atom_strdup(struct atom_table *table, xkb_atom_t atom);
const char *
atom_text(struct atom_table *table, xkb_atom_t atom);

View File

@ -0,0 +1,171 @@
/*
* Copyright © 2012 Intel Corporation
* Copyright © 2012 Ran Benita
*
* 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.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
#include "context.h"
unsigned int
xkb_context_num_failed_include_paths(struct xkb_context *ctx)
{
return darray_size(ctx->failed_includes);
}
const char *
xkb_context_failed_include_path_get(struct xkb_context *ctx,
unsigned int idx)
{
if (idx >= xkb_context_num_failed_include_paths(ctx))
return NULL;
return darray_item(ctx->failed_includes, idx);
}
xkb_atom_t
xkb_atom_lookup(struct xkb_context *ctx, const char *string)
{
return atom_lookup(ctx->atom_table, string, strlen(string));
}
xkb_atom_t
xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len)
{
return atom_intern(ctx->atom_table, string, len, false);
}
xkb_atom_t
xkb_atom_steal(struct xkb_context *ctx, char *string)
{
return atom_intern(ctx->atom_table, string, strlen(string), true);
}
const char *
xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom)
{
return atom_text(ctx->atom_table, atom);
}
void
xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity,
const char *fmt, ...)
{
va_list args;
if (ctx->log_level < level || ctx->log_verbosity < verbosity)
return;
va_start(args, fmt);
ctx->log_fn(ctx, level, fmt, args);
va_end(args);
}
char *
xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
{
char *rtrn;
if (size >= sizeof(ctx->text_buffer))
return NULL;
if (sizeof(ctx->text_buffer) - ctx->text_next <= size)
ctx->text_next = 0;
rtrn = &ctx->text_buffer[ctx->text_next];
ctx->text_next += size;
return rtrn;
}
#ifndef DEFAULT_XKB_VARIANT
#define DEFAULT_XKB_VARIANT NULL
#endif
#ifndef DEFAULT_XKB_OPTIONS
#define DEFAULT_XKB_OPTIONS NULL
#endif
const char *
xkb_context_get_default_rules(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_RULES");
return env ? env : DEFAULT_XKB_RULES;
}
const char *
xkb_context_get_default_model(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_MODEL");
return env ? env : DEFAULT_XKB_MODEL;
}
const char *
xkb_context_get_default_layout(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_LAYOUT");
return env ? env : DEFAULT_XKB_LAYOUT;
}
const char *
xkb_context_get_default_variant(struct xkb_context *ctx)
{
const char *env = NULL;
const char *layout = getenv("XKB_DEFAULT_VARIANT");
/* We don't want to inherit the variant if they haven't also set a
* layout, since they're so closely paired. */
if (layout && ctx->use_environment_names)
env = getenv("XKB_DEFAULT_VARIANT");
return env ? env : DEFAULT_XKB_VARIANT;
}
const char *
xkb_context_get_default_options(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_OPTIONS");
return env ? env : DEFAULT_XKB_OPTIONS;
}

View File

@ -26,7 +26,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
@ -34,30 +33,6 @@
#include "utils.h"
#include "context.h"
struct xkb_context {
int refcnt;
ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx,
enum xkb_log_level level,
const char *fmt, va_list args);
enum xkb_log_level log_level;
int log_verbosity;
void *user_data;
struct xkb_rule_names names_dflt;
darray(char *) includes;
darray(char *) failed_includes;
struct atom_table *atom_table;
/* Buffer for the *Text() functions. */
char text_buffer[2048];
size_t text_next;
unsigned int use_environment_names : 1;
};
/**
* Append one directory to the context's include path.
*/
@ -155,12 +130,6 @@ xkb_context_num_include_paths(struct xkb_context *ctx)
return darray_size(ctx->includes);
}
unsigned int
xkb_context_num_failed_include_paths(struct xkb_context *ctx)
{
return darray_size(ctx->failed_includes);
}
/**
* Returns the given entry in the context's include path, or NULL if an
* invalid index is passed.
@ -174,16 +143,6 @@ xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx)
return darray_item(ctx->includes, idx);
}
const char *
xkb_context_failed_include_path_get(struct xkb_context *ctx,
unsigned int idx)
{
if (idx >= xkb_context_num_failed_include_paths(ctx))
return NULL;
return darray_item(ctx->failed_includes, idx);
}
/**
* Take a new reference on the context.
*/
@ -214,15 +173,15 @@ log_level_to_prefix(enum xkb_log_level level)
{
switch (level) {
case XKB_LOG_LEVEL_DEBUG:
return "Debug:";
return "xkbcommon: DEBUG: ";
case XKB_LOG_LEVEL_INFO:
return "Info:";
return "xkbcommon: INFO: ";
case XKB_LOG_LEVEL_WARNING:
return "Warning:";
return "xkbcommon: WARNING: ";
case XKB_LOG_LEVEL_ERROR:
return "Error:";
return "xkbcommon: ERROR: ";
case XKB_LOG_LEVEL_CRITICAL:
return "Critical:";
return "xkbcommon: CRITICAL: ";
default:
return NULL;
}
@ -235,7 +194,7 @@ default_log_fn(struct xkb_context *ctx, enum xkb_log_level level,
const char *prefix = log_level_to_prefix(level);
if (prefix)
fprintf(stderr, "%-10s", prefix);
fprintf(stderr, "%s", prefix);
vfprintf(stderr, fmt, args);
}
@ -246,7 +205,7 @@ log_level(const char *level) {
errno = 0;
lvl = strtol(level, &endptr, 10);
if (errno == 0 && (endptr[0] == '\0' || isspace(endptr[0])))
if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0])))
return lvl;
if (istreq_prefix("crit", level))
return XKB_LOG_LEVEL_CRITICAL;
@ -275,14 +234,6 @@ log_verbosity(const char *verbosity) {
return 0;
}
#ifndef DEFAULT_XKB_VARIANT
#define DEFAULT_XKB_VARIANT NULL
#endif
#ifndef DEFAULT_XKB_OPTIONS
#define DEFAULT_XKB_OPTIONS NULL
#endif
/**
* Create a new context.
*/
@ -328,47 +279,6 @@ xkb_context_new(enum xkb_context_flags flags)
return ctx;
}
xkb_atom_t
xkb_atom_lookup(struct xkb_context *ctx, const char *string)
{
return atom_lookup(ctx->atom_table, string);
}
xkb_atom_t
xkb_atom_intern(struct xkb_context *ctx, const char *string)
{
return atom_intern(ctx->atom_table, string, false);
}
xkb_atom_t
xkb_atom_steal(struct xkb_context *ctx, char *string)
{
return atom_intern(ctx->atom_table, string, true);
}
char *
xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom)
{
return atom_strdup(ctx->atom_table, atom);
}
const char *
xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom)
{
return atom_text(ctx->atom_table, atom);
}
void
xkb_log(struct xkb_context *ctx, enum xkb_log_level level,
const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
ctx->log_fn(ctx, level, fmt, args);
va_end(args);
}
XKB_EXPORT void
xkb_context_set_log_fn(struct xkb_context *ctx,
void (*log_fn)(struct xkb_context *ctx,
@ -415,78 +325,3 @@ xkb_context_set_user_data(struct xkb_context *ctx, void *user_data)
{
ctx->user_data = user_data;
}
char *
xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
{
char *rtrn;
if (size >= sizeof(ctx->text_buffer))
return NULL;
if (sizeof(ctx->text_buffer) - ctx->text_next <= size)
ctx->text_next = 0;
rtrn = &ctx->text_buffer[ctx->text_next];
ctx->text_next += size;
return rtrn;
}
const char *
xkb_context_get_default_rules(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_RULES");
return env ? env : DEFAULT_XKB_RULES;
}
const char *
xkb_context_get_default_model(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_MODEL");
return env ? env : DEFAULT_XKB_MODEL;
}
const char *
xkb_context_get_default_layout(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_LAYOUT");
return env ? env : DEFAULT_XKB_LAYOUT;
}
const char *
xkb_context_get_default_variant(struct xkb_context *ctx)
{
const char *env = NULL;
const char *layout = getenv("XKB_DEFAULT_VARIANT");
/* We don't want to inherit the variant if they haven't also set a
* layout, since they're so closely paired. */
if (layout && ctx->use_environment_names)
env = getenv("XKB_DEFAULT_VARIANT");
return env ? env : DEFAULT_XKB_VARIANT;
}
const char *
xkb_context_get_default_options(struct xkb_context *ctx)
{
const char *env = NULL;
if (ctx->use_environment_names)
env = getenv("XKB_DEFAULT_OPTIONS");
return env ? env : DEFAULT_XKB_OPTIONS;
}

View File

@ -28,6 +28,30 @@
#include "atom.h"
struct xkb_context {
int refcnt;
ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx,
enum xkb_log_level level,
const char *fmt, va_list args);
enum xkb_log_level log_level;
int log_verbosity;
void *user_data;
struct xkb_rule_names names_dflt;
darray(char *) includes;
darray(char *) failed_includes;
struct atom_table *atom_table;
/* Buffer for the *Text() functions. */
char text_buffer[2048];
size_t text_next;
unsigned int use_environment_names : 1;
};
unsigned int
xkb_context_num_failed_include_paths(struct xkb_context *ctx);
@ -43,40 +67,30 @@ xkb_atom_t
xkb_atom_lookup(struct xkb_context *ctx, const char *string);
xkb_atom_t
xkb_atom_intern(struct xkb_context *ctx, const char *string);
xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len);
#define xkb_atom_intern_literal(ctx, literal) \
xkb_atom_intern((ctx), (literal), sizeof(literal) - 1)
/**
* If @string is dynamically allocated, free'd immediately after
* being interned, and not used afterwards, use this function
* If @string is dynamically allocated, NUL-terminated, free'd immediately
* after being interned, and not used afterwards, use this function
* instead of xkb_atom_intern to avoid some unnecessary allocations.
* The caller should not use or free the passed in string afterwards.
*/
xkb_atom_t
xkb_atom_steal(struct xkb_context *ctx, char *string);
char *
xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom);
const char *
xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom);
char *
xkb_context_get_buffer(struct xkb_context *ctx, size_t size);
ATTR_PRINTF(3, 4) void
xkb_log(struct xkb_context *ctx, enum xkb_log_level level,
ATTR_PRINTF(4, 5) void
xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity,
const char *fmt, ...);
#define xkb_log_cond_level(ctx, level, ...) do { \
if (xkb_context_get_log_level(ctx) >= (level)) \
xkb_log((ctx), (level), __VA_ARGS__); \
} while (0)
#define xkb_log_cond_verbosity(ctx, level, vrb, ...) do { \
if (xkb_context_get_log_verbosity(ctx) >= (vrb)) \
xkb_log_cond_level((ctx), (level), __VA_ARGS__); \
} while (0)
const char *
xkb_context_get_default_rules(struct xkb_context *ctx);
@ -99,17 +113,17 @@ xkb_context_get_default_options(struct xkb_context *ctx);
* result in an error, though.
*/
#define log_dbg(ctx, ...) \
xkb_log_cond_level((ctx), XKB_LOG_LEVEL_DEBUG, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_DEBUG, 0, __VA_ARGS__)
#define log_info(ctx, ...) \
xkb_log_cond_level((ctx), XKB_LOG_LEVEL_INFO, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_INFO, 0, __VA_ARGS__)
#define log_warn(ctx, ...) \
xkb_log_cond_level((ctx), XKB_LOG_LEVEL_WARNING, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_WARNING, 0, __VA_ARGS__)
#define log_err(ctx, ...) \
xkb_log_cond_level((ctx), XKB_LOG_LEVEL_ERROR, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_ERROR, 0, __VA_ARGS__)
#define log_wsgo(ctx, ...) \
xkb_log_cond_level((ctx), XKB_LOG_LEVEL_CRITICAL, __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_CRITICAL, 0, __VA_ARGS__)
#define log_vrb(ctx, vrb, ...) \
xkb_log_cond_verbosity((ctx), XKB_LOG_LEVEL_WARNING, (vrb), __VA_ARGS__)
xkb_log((ctx), XKB_LOG_LEVEL_WARNING, (vrb), __VA_ARGS__)
/*
* Variants which are prefixed by the name of the function they're

121
src/3rdparty/xkbcommon/src/keymap-priv.c vendored Normal file
View File

@ -0,0 +1,121 @@
/**
* Copyright © 2012 Intel Corporation
* Copyright © 2012 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.
*
* Author: Daniel Stone <daniel@fooishbar.org>
*/
#include "keymap.h"
static void
update_builtin_keymap_fields(struct xkb_keymap *keymap)
{
struct xkb_context *ctx = keymap->ctx;
/*
* Add predefined (AKA real, core, X11) modifiers.
* The order is important!
*/
darray_appends_t(keymap->mods, struct xkb_mod,
{ .name = xkb_atom_intern_literal(ctx, "Shift"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Lock"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Control"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Mod1"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Mod2"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Mod3"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Mod4"), .type = MOD_REAL },
{ .name = xkb_atom_intern_literal(ctx, "Mod5"), .type = MOD_REAL });
}
struct xkb_keymap *
xkb_keymap_new(struct xkb_context *ctx,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags)
{
struct xkb_keymap *keymap;
keymap = calloc(1, sizeof(*keymap));
if (!keymap)
return NULL;
keymap->refcnt = 1;
keymap->ctx = xkb_context_ref(ctx);
keymap->format = format;
keymap->flags = flags;
update_builtin_keymap_fields(keymap);
return keymap;
}
struct xkb_key *
XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases)
{
struct xkb_key *key;
xkb_foreach_key(key, keymap)
if (key->name == name)
return key;
if (use_aliases) {
xkb_atom_t new_name = XkbResolveKeyAlias(keymap, name);
if (new_name != XKB_ATOM_NONE)
return XkbKeyByName(keymap, new_name, false);
}
return NULL;
}
xkb_atom_t
XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name)
{
for (unsigned i = 0; i < keymap->num_key_aliases; i++)
if (keymap->key_aliases[i].alias == name)
return keymap->key_aliases[i].real;
return XKB_ATOM_NONE;
}
void
XkbEscapeMapName(char *name)
{
/*
* All latin-1 alphanumerics, plus parens, slash, minus, underscore and
* wildcards.
*/
static const unsigned char legal[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
};
if (!name)
return;
while (*name) {
if (!(legal[*name / 8] & (1 << (*name % 8))))
*name = '_';
name++;
}
}

View File

@ -133,7 +133,6 @@ enum xkb_action_type {
ACTION_TYPE_SWITCH_VT,
ACTION_TYPE_CTRL_SET,
ACTION_TYPE_CTRL_LOCK,
ACTION_TYPE_KEY_REDIRECT,
ACTION_TYPE_PRIVATE,
_ACTION_TYPE_NUM_ENTRIES
};
@ -213,16 +212,6 @@ struct xkb_switch_screen_action {
int8_t screen;
};
struct xkb_redirect_key_action {
enum xkb_action_type type;
enum xkb_action_flags flags;
xkb_keycode_t new_kc;
uint8_t mods_mask;
uint8_t mods;
uint16_t vmods_mask;
uint16_t vmods;
};
struct xkb_pointer_action {
enum xkb_action_type type;
enum xkb_action_flags flags;
@ -250,7 +239,6 @@ union xkb_action {
struct xkb_controls_action ctrls;
struct xkb_pointer_default_action dflt;
struct xkb_switch_screen_action screen;
struct xkb_redirect_key_action redirect; /* XXX wholly unnecessary? */
struct xkb_pointer_action ptr;
struct xkb_pointer_button_action btn;
struct xkb_private_action priv;
@ -313,8 +301,8 @@ struct xkb_controls {
/* Such an awkward name. Oh well. */
enum xkb_range_exceed_type {
RANGE_WRAP = 0,
RANGE_SATURATE,
RANGE_WRAP,
RANGE_REDIRECT,
};
@ -386,7 +374,8 @@ struct xkb_keymap {
struct xkb_key_type *types;
unsigned int num_types;
darray(struct xkb_sym_interpret) sym_interprets;
unsigned int num_sym_interprets;
struct xkb_sym_interpret *sym_interprets;
darray(struct xkb_mod) mods;
@ -423,12 +412,20 @@ XkbKeyGroupWidth(const struct xkb_key *key, xkb_layout_index_t layout)
return key->groups[layout].type->num_levels;
}
struct xkb_keymap *
xkb_keymap_new(struct xkb_context *ctx,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags);
struct xkb_key *
XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases);
xkb_atom_t
XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name);
void
XkbEscapeMapName(char *name);
xkb_layout_index_t
wrap_group_into_range(int32_t group,
xkb_layout_index_t num_groups,
@ -439,9 +436,7 @@ struct xkb_keymap_format_ops {
bool (*keymap_new_from_names)(struct xkb_keymap *keymap,
const struct xkb_rule_names *names);
bool (*keymap_new_from_string)(struct xkb_keymap *keymap,
const char *string);
bool (*keymap_new_from_buffer)(struct xkb_keymap *keymap,
const char *buffer, size_t length);
const char *string, size_t length);
bool (*keymap_new_from_file)(struct xkb_keymap *keymap, FILE *file);
char *(*keymap_get_as_string)(struct xkb_keymap *keymap);
};

View File

@ -838,20 +838,19 @@ static const struct codepair keysymtab[] = {
static uint32_t
bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym)
{
int min = 0;
int max = length;
int mid;
int first = 0;
int last = length;
if (keysym < table[0].keysym || keysym > table[length].keysym)
return 0;
/* binary search in table */
while (max >= min) {
mid = (min + max) / 2;
while (last >= first) {
int mid = (first + last) / 2;
if (table[mid].keysym < keysym)
min = mid + 1;
first = mid + 1;
else if (table[mid].keysym > keysym)
max = mid - 1;
last = mid - 1;
else /* found it */
return table[mid].ucs;
}

View File

@ -53,24 +53,31 @@
#include "keysym.h"
#include "ks_tables.h"
static inline const char *
get_name(const struct name_keysym *entry)
{
return keysym_names + entry->offset;
}
static int
compare_by_keysym(const void *a, const void *b)
{
const struct name_keysym *key = a, *entry = b;
return key->keysym - (int32_t)entry->keysym;
const xkb_keysym_t *key = a;
const struct name_keysym *entry = b;
return *key - (int32_t) entry->keysym;
}
static int
compare_by_name(const void *a, const void *b)
{
const struct name_keysym *key = a, *entry = b;
return strcasecmp(key->name, entry->name);
const char *key = a;
const struct name_keysym *entry = b;
return strcasecmp(key, get_name(entry));
}
XKB_EXPORT int
xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
{
const struct name_keysym search = { .name = NULL, .keysym = ks };
const struct name_keysym *entry;
if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
@ -78,12 +85,12 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
return -1;
}
entry = bsearch(&search, keysym_to_name,
entry = bsearch(&ks, keysym_to_name,
ARRAY_SIZE(keysym_to_name),
sizeof(*keysym_to_name),
compare_by_keysym);
if (entry)
return snprintf(buffer, size, "%s", entry->name);
return snprintf(buffer, size, "%s", get_name(entry));
/* Unnamed Unicode codepoint. */
if (ks >= 0x01000100 && ks <= 0x0110ffff) {
@ -119,25 +126,25 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
if (!entry)
return NULL;
if (!icase && strcmp(entry->name, name) == 0)
if (!icase && strcmp(get_name(entry), name) == 0)
return entry;
if (icase && xkb_keysym_is_lower(entry->keysym))
return entry;
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (!icase && strcmp(iter->name, name) == 0)
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (strcasecmp(iter->name, entry->name) != 0)
if (strcasecmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
}
last = name_to_keysym + len;
for (iter = entry + 1; iter < last; --iter) {
if (!icase && strcmp(iter->name, name) == 0)
for (iter = entry + 1; iter < last; ++iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
if (strcasecmp(iter->name, entry->name) != 0)
if (strcasecmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
@ -151,7 +158,6 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
XKB_EXPORT xkb_keysym_t
xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
{
const struct name_keysym search = { .name = s, .keysym = 0 };
const struct name_keysym *entry;
char *tmp;
xkb_keysym_t val;
@ -160,7 +166,7 @@ xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
return XKB_KEY_NoSymbol;
entry = bsearch(&search, name_to_keysym,
entry = bsearch(s, name_to_keysym,
ARRAY_SIZE(name_to_keysym),
sizeof(*name_to_keysym),
compare_by_name);
@ -242,6 +248,26 @@ xkb_keysym_is_upper(xkb_keysym_t ks)
return (ks == upper ? true : false);
}
xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
XConvertCase(ks, &lower, &upper);
return lower;
}
xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
XConvertCase(ks, &lower, &upper);
return upper;
}
/*
* The following is copied verbatim from libX11:src/KeyBind.c, commit
* d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes:

View File

@ -59,4 +59,10 @@ xkb_keysym_is_upper(xkb_keysym_t keysym);
bool
xkb_keysym_is_keypad(xkb_keysym_t keysym);
xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks);
xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,7 @@
*/
#include "keymap.h"
#include "keysym.h"
struct xkb_filter {
union xkb_action action;
@ -405,7 +406,6 @@ xkb_action_breaks_latch(const union xkb_action *action)
case ACTION_TYPE_PTR_LOCK:
case ACTION_TYPE_CTRL_SET:
case ACTION_TYPE_CTRL_LOCK:
case ACTION_TYPE_KEY_REDIRECT:
case ACTION_TYPE_SWITCH_VT:
case ACTION_TYPE_TERMINATE:
return true;
@ -833,13 +833,26 @@ XKB_EXPORT xkb_keysym_t
xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
{
const xkb_keysym_t *syms;
xkb_keysym_t sym;
int num_syms;
xkb_mod_index_t caps;
num_syms = xkb_state_key_get_syms(state, kc, &syms);
if (num_syms != 1)
return XKB_KEY_NoSymbol;
return syms[0];
sym = syms[0];
/*
* Perform capitalization transformation, see:
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
*/
caps = xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS);
if (xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 &&
xkb_state_mod_index_is_consumed(state, kc, caps) == 0)
sym = xkb_keysym_to_upper(sym);
return sym;
}
/**
@ -989,13 +1002,12 @@ xkb_state_mod_names_are_active(struct xkb_state *state,
{
va_list ap;
xkb_mod_index_t idx = 0;
const char *str;
xkb_mod_mask_t wanted = 0;
int ret = 0;
va_start(ap, match);
while (1) {
str = va_arg(ap, const char *);
const char *str = va_arg(ap, const char *);
if (str == NULL)
break;
idx = xkb_keymap_mod_get_index(state->keymap, str);

View File

@ -175,10 +175,10 @@ const LookupEntry actionTypeNames[] = {
{ "SwitchScreen", ACTION_TYPE_SWITCH_VT },
{ "SetControls", ACTION_TYPE_CTRL_SET },
{ "LockControls", ACTION_TYPE_CTRL_LOCK },
{ "RedirectKey", ACTION_TYPE_KEY_REDIRECT },
{ "Redirect", ACTION_TYPE_KEY_REDIRECT },
{ "Private", ACTION_TYPE_PRIVATE },
/* deprecated actions below here - unused */
{ "RedirectKey", ACTION_TYPE_NONE },
{ "Redirect", ACTION_TYPE_NONE },
{ "ISOLock", ACTION_TYPE_NONE },
{ "ActionMessage", ACTION_TYPE_NONE },
{ "MessageAction", ACTION_TYPE_NONE },
@ -251,9 +251,9 @@ const char *
KeyNameText(struct xkb_context *ctx, xkb_atom_t name)
{
const char *sname = xkb_atom_text(ctx, name);
size_t len = strlen(sname) + 3;
size_t len = strlen_safe(sname) + 3;
char *buf = xkb_context_get_buffer(ctx, len);
snprintf(buf, len, "<%s>", sname);
snprintf(buf, len, "<%s>", strempty(sname));
return buf;
}

107
src/3rdparty/xkbcommon/src/utils.c vendored Normal file
View File

@ -0,0 +1,107 @@
/*
* Copyright © 2013 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 "utils.h"
#ifdef HAVE_MMAP
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
bool
map_file(FILE *file, const char **string_out, size_t *size_out)
{
struct stat stat_buf;
const int fd = fileno(file);
char *string;
/* Make sure to keep the errno on failure! */
if (fstat(fd, &stat_buf) != 0)
return false;
string = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (string == MAP_FAILED)
return false;
*string_out = string;
*size_out = stat_buf.st_size;
return true;
}
void
unmap_file(const char *str, size_t size)
{
munmap(UNCONSTIFY(str), size);
}
#else
bool
map_file(FILE *file, const char **string_out, size_t *size_out)
{
long ret;
size_t ret_s;
char *string;
size_t size;
/* Make sure to keep the errno on failure! */
ret = fseek(file, 0, SEEK_END);
if (ret != 0)
return false;
ret = ftell(file);
if (ret < 0)
return false;
size = (size_t) ret;
ret = fseek(file, 0, SEEK_SET);
if (ret < 0)
return false;
string = malloc(size);
if (!string)
return false;
ret_s = fread(string, 1, size, file);
if (ret_s < size) {
free(string);
return false;
}
*string_out = string;
*size_out = size;
return true;
}
void
unmap_file(const char *str, size_t size)
{
free(UNCONSTIFY(str));
}
#endif

View File

@ -24,8 +24,10 @@
#ifndef UTILS_H
#define UTILS_H 1
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
@ -70,6 +72,12 @@ strdup_safe(const char *s)
return s ? strdup(s) : NULL;
}
static inline size_t
strlen_safe(const char *s)
{
return s ? strlen(s) : 0;
}
static inline bool
isempty(const char *s)
{
@ -82,6 +90,12 @@ strnull(const char *s)
return s ? s : "(null)";
}
static inline const char *
strempty(const char *s)
{
return s ? s : "";
}
static inline void *
memdup(const void *mem, size_t nmemb, size_t size)
{
@ -91,6 +105,81 @@ memdup(const void *mem, size_t nmemb, size_t size)
return p;
}
static inline int
min(int misc, int other)
{
return (misc < other) ? misc : other;
}
static inline int
max(int misc, int other)
{
return (misc > other) ? misc : other;
}
/* ctype.h is locale-dependent and has other oddities. */
static inline bool
is_space(char ch)
{
return ch == ' ' || (ch >= '\t' && ch <= '\r');
}
static inline bool
is_alpha(char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}
static inline bool
is_digit(char ch)
{
return ch >= '0' && ch <= '9';
}
static inline bool
is_alnum(char ch)
{
return is_alpha(ch) || is_digit(ch);
}
static inline bool
is_xdigit(char ch)
{
return
(ch >= '0' && ch <= '9') ||
(ch >= 'a' && ch <= 'f') ||
(ch >= 'A' && ch <= 'F');
}
static inline bool
is_graph(char ch)
{
/* See table in ascii(7). */
return ch >= '!' && ch <= '~';
}
/*
* Return the bit position of the most significant bit.
* Note: this is 1-based! It's more useful this way, and returns 0 when
* mask is all 0s.
*/
static inline int
msb_pos(uint32_t mask)
{
int pos = 0;
while (mask) {
pos++;
mask >>= 1;
}
return pos;
}
bool
map_file(FILE *file, const char **string_out, size_t *size_out);
void
unmap_file(const char *str, size_t size);
#define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr))))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -133,4 +222,10 @@ memdup(const void *mem, size_t nmemb, size_t size)
# define ATTR_NULL_SENTINEL
#endif /* GNUC >= 4 */
#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 295)
#define ATTR_PACKED __attribute__((__packed__))
#else
#define ATTR_PACKED
#endif
#endif /* UTILS_H */

215
src/3rdparty/xkbcommon/src/x11/util.c vendored Normal file
View File

@ -0,0 +1,215 @@
/*
* Copyright © 2013 Ran Benita
*
* 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 "x11-priv.h"
XKB_EXPORT int
xkb_x11_setup_xkb_extension(xcb_connection_t *conn,
uint16_t major_xkb_version,
uint16_t minor_xkb_version,
enum xkb_x11_setup_xkb_extension_flags flags,
uint16_t *major_xkb_version_out,
uint16_t *minor_xkb_version_out,
uint8_t *base_event_out,
uint8_t *base_error_out)
{
uint8_t base_event, base_error;
uint16_t server_major, server_minor;
if (flags & ~(XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS)) {
/* log_err_func(ctx, "unrecognized flags: %#x\n", flags); */
return 0;
}
{
const xcb_query_extension_reply_t *reply =
xcb_get_extension_data(conn, &xcb_xkb_id);
if (!reply) {
/* log_err_func(ctx, "failed to query for XKB extension\n"); */
return 0;
}
if (!reply->present) {
/* log_err_func(ctx, "failed to start using XKB extension: not available in server\n"); */
return 0;
}
base_event = reply->first_event;
base_error = reply->first_error;
}
{
xcb_generic_error_t *error = NULL;
xcb_xkb_use_extension_cookie_t cookie =
xcb_xkb_use_extension(conn, major_xkb_version, minor_xkb_version);
xcb_xkb_use_extension_reply_t *reply =
xcb_xkb_use_extension_reply(conn, cookie, &error);
if (!reply) {
/* log_err_func(ctx, */
/* "failed to start using XKB extension: error code %d\n", */
/* error ? error->error_code : -1); */
free(error);
return 0;
}
if (!reply->supported) {
/* log_err_func(ctx, */
/* "failed to start using XKB extension: server doesn't support version %d.%d\n", */
/* major_xkb_version, minor_xkb_version); */
free(reply);
return 0;
}
server_major = reply->serverMajor;
server_minor = reply->serverMinor;
free(reply);
}
/*
* The XkbUseExtension() in libX11 has a *bunch* of legacy stuff, but
* it doesn't seem like any of it is useful to us.
*/
if (major_xkb_version_out)
*major_xkb_version_out = server_major;
if (minor_xkb_version_out)
*minor_xkb_version_out = server_minor;
if (base_event_out)
*base_event_out = base_event;
if (base_error_out)
*base_error_out = base_error;
return 1;
}
XKB_EXPORT int32_t
xkb_x11_get_core_keyboard_device_id(xcb_connection_t *conn)
{
int32_t device_id;
xcb_xkb_get_device_info_cookie_t cookie =
xcb_xkb_get_device_info(conn, XCB_XKB_ID_USE_CORE_KBD,
0, 0, 0, 0, 0, 0);
xcb_xkb_get_device_info_reply_t *reply =
xcb_xkb_get_device_info_reply(conn, cookie, NULL);
if (!reply)
return -1;
device_id = reply->deviceID;
free(reply);
return device_id;
}
bool
get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out)
{
xcb_get_atom_name_cookie_t cookie;
xcb_get_atom_name_reply_t *reply;
int length;
char *name;
if (atom == 0) {
*out = NULL;
return true;
}
cookie = xcb_get_atom_name(conn, atom);
reply = xcb_get_atom_name_reply(conn, cookie, NULL);
if (!reply)
return false;
length = xcb_get_atom_name_name_length(reply);
name = xcb_get_atom_name_name(reply);
*out = strndup(name, length);
if (!*out) {
free(reply);
return false;
}
free(reply);
return true;
}
bool
adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn,
const xcb_atom_t *from, xkb_atom_t *to, const size_t count)
{
enum { SIZE = 128 };
xcb_get_atom_name_cookie_t cookies[SIZE];
/* Send and collect the atoms in batches of reasonable SIZE. */
for (size_t batch = 0; batch <= count / SIZE; batch++) {
const size_t start = batch * SIZE;
const size_t stop = min((batch + 1) * SIZE, count);
/* Send. */
for (size_t i = start; i < stop; i++)
if (from[i] != XCB_ATOM_NONE)
cookies[i % SIZE] = xcb_get_atom_name(conn, from[i]);
/* Collect. */
for (size_t i = start; i < stop; i++) {
xcb_get_atom_name_reply_t *reply;
if (from[i] == XCB_ATOM_NONE) {
to[i] = XKB_ATOM_NONE;
continue;
}
reply = xcb_get_atom_name_reply(conn, cookies[i % SIZE], NULL);
if (!reply)
goto err_discard;
to[i] = xkb_atom_intern(ctx,
xcb_get_atom_name_name(reply),
xcb_get_atom_name_name_length(reply));
free(reply);
if (to[i] == XKB_ATOM_NONE)
goto err_discard;
continue;
/*
* If we don't discard the uncollected replies, they just
* sit there waiting. Sad.
*/
err_discard:
for (size_t j = i + 1; j < stop; j++)
xcb_discard_reply(conn, cookies[j].sequence);
return false;
}
}
return true;
}
bool
adopt_atom(struct xkb_context *ctx, xcb_connection_t *conn, xcb_atom_t atom,
xkb_atom_t *out)
{
return adopt_atoms(ctx, conn, &atom, out, 1);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
/*
* Copyright © 2013 Ran Benita
*
* 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.
*/
#ifndef _XKBCOMMON_X11_PRIV_H
#define _XKBCOMMON_X11_PRIV_H
#include <xcb/xkb.h>
#include "xkbcommon/xkbcommon-x11.h"
#include "keymap.h"
/* Get a strdup'd name of an X atom. */
bool
get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out);
/*
* Make a xkb_atom_t's from X atoms (prefer to send as many as possible
* at once, to avoid many roundtrips).
*
* TODO: We can make this more flexible, such that @to doesn't have to
* be sequential. Then we can convert most adopt_atom() calls to
* adopt_atoms().
* Atom caching would also likely be useful for avoiding quite a
* few requests.
*/
bool
adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn,
const xcb_atom_t *from, xkb_atom_t *to, size_t count);
bool
adopt_atom(struct xkb_context *ctx, xcb_connection_t *conn, xcb_atom_t atom,
xkb_atom_t *out);
#endif

View File

@ -0,0 +1,71 @@
/*
* Copyright © 2013 Ran Benita
*
* 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 "x11-priv.h"
static bool
update_initial_state(struct xkb_state *state, xcb_connection_t *conn,
uint16_t device_id)
{
xcb_xkb_get_state_cookie_t cookie =
xcb_xkb_get_state(conn, device_id);
xcb_xkb_get_state_reply_t *reply =
xcb_xkb_get_state_reply(conn, cookie, NULL);
if (!reply)
return false;
xkb_state_update_mask(state,
reply->baseMods,
reply->latchedMods,
reply->lockedMods,
reply->baseGroup,
reply->latchedGroup,
reply->lockedGroup);
free(reply);
return true;
}
XKB_EXPORT struct xkb_state *
xkb_x11_state_new_from_device(struct xkb_keymap *keymap,
xcb_connection_t *conn, int32_t device_id)
{
struct xkb_state *state;
if (device_id < 0 || device_id > 255) {
log_err_func(keymap->ctx, "illegal device ID: %d", device_id);
return NULL;
}
state = xkb_state_new(keymap);
if (!state)
return NULL;
if (!update_initial_state(state, conn, device_id)) {
xkb_state_unref(state);
return NULL;
}
return state;
}

View File

@ -53,26 +53,6 @@
#include "keymap.h"
#include "text.h"
static struct xkb_keymap *
xkb_keymap_new(struct xkb_context *ctx,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags)
{
struct xkb_keymap *keymap;
keymap = calloc(1, sizeof(*keymap));
if (!keymap)
return NULL;
keymap->refcnt = 1;
keymap->ctx = xkb_context_ref(ctx);
keymap->format = format;
keymap->flags = flags;
return keymap;
}
XKB_EXPORT struct xkb_keymap *
xkb_keymap_ref(struct xkb_keymap *keymap)
{
@ -83,30 +63,34 @@ xkb_keymap_ref(struct xkb_keymap *keymap)
XKB_EXPORT void
xkb_keymap_unref(struct xkb_keymap *keymap)
{
unsigned int i, j;
struct xkb_key *key;
if (!keymap || --keymap->refcnt > 0)
return;
if (keymap->keys) {
struct xkb_key *key;
xkb_foreach_key(key, keymap) {
for (i = 0; i < key->num_groups; i++) {
for (j = 0; j < XkbKeyGroupWidth(key, i); j++)
if (key->groups[i].levels[j].num_syms > 1)
free(key->groups[i].levels[j].u.syms);
free(key->groups[i].levels);
if (key->groups) {
for (unsigned i = 0; i < key->num_groups; i++) {
if (key->groups[i].levels) {
for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++)
if (key->groups[i].levels[j].num_syms > 1)
free(key->groups[i].levels[j].u.syms);
free(key->groups[i].levels);
}
}
free(key->groups);
}
free(key->groups);
}
free(keymap->keys);
}
for (i = 0; i < keymap->num_types; i++) {
free(keymap->types[i].entries);
free(keymap->types[i].level_names);
if (keymap->types) {
for (unsigned i = 0; i < keymap->num_types; i++) {
free(keymap->types[i].entries);
free(keymap->types[i].level_names);
}
free(keymap->types);
}
free(keymap->types);
darray_free(keymap->sym_interprets);
free(keymap->sym_interprets);
free(keymap->key_aliases);
free(keymap->group_names);
darray_free(keymap->mods);
@ -190,35 +174,8 @@ xkb_keymap_new_from_string(struct xkb_context *ctx,
enum xkb_keymap_format format,
enum xkb_keymap_compile_flags flags)
{
struct xkb_keymap *keymap;
const struct xkb_keymap_format_ops *ops;
ops = get_keymap_format_ops(format);
if (!ops || !ops->keymap_new_from_string) {
log_err_func(ctx, "unsupported keymap format: %d\n", format);
return NULL;
}
if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}
if (!string) {
log_err_func1(ctx, "no string specified\n");
return NULL;
}
keymap = xkb_keymap_new(ctx, format, flags);
if (!keymap)
return NULL;
if (!ops->keymap_new_from_string(keymap, string)) {
xkb_keymap_unref(keymap);
return NULL;
}
return keymap;
return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
format, flags);
}
XKB_EXPORT struct xkb_keymap *
@ -250,7 +207,7 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx,
if (!keymap)
return NULL;
if (!ops->keymap_new_from_buffer(keymap, buffer, length)) {
if (!ops->keymap_new_from_string(keymap, buffer, length)) {
xkb_keymap_unref(keymap);
return NULL;
}
@ -512,6 +469,28 @@ err:
return 0;
}
XKB_EXPORT xkb_keycode_t
xkb_keymap_min_keycode(struct xkb_keymap *keymap)
{
return keymap->min_key_code;
}
XKB_EXPORT xkb_keycode_t
xkb_keymap_max_keycode(struct xkb_keymap *keymap)
{
return keymap->max_key_code;
}
XKB_EXPORT void
xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
void *data)
{
struct xkb_key *key;
xkb_foreach_key(key, keymap)
iter(keymap, key->keycode, data);
}
/**
* Simple boolean specifying whether or not the key should repeat.
*/
@ -525,31 +504,3 @@ xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
return key->repeats;
}
struct xkb_key *
XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases)
{
struct xkb_key *key;
xkb_foreach_key(key, keymap)
if (key->name == name)
return key;
if (use_aliases) {
xkb_atom_t new_name = XkbResolveKeyAlias(keymap, name);
if (new_name != XKB_ATOM_NONE)
return XkbKeyByName(keymap, new_name, false);
}
return NULL;
}
xkb_atom_t
XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name)
{
for (unsigned i = 0; i < keymap->num_key_aliases; i++)
if (keymap->key_aliases[i].alias == name)
return keymap->key_aliases[i].real;
return XKB_ATOM_NONE;
}

View File

@ -56,18 +56,22 @@
#include "expr.h"
#include "action.h"
static const ExprDef constTrue = {
.common = { .type = STMT_EXPR, .next = NULL },
.op = EXPR_VALUE,
.value_type = EXPR_TYPE_BOOLEAN,
.value = { .ival = 1 },
static const ExprBoolean constTrue = {
.expr = {
.common = { .type = STMT_EXPR, .next = NULL },
.op = EXPR_VALUE,
.value_type = EXPR_TYPE_BOOLEAN,
},
.set = true,
};
static const ExprDef constFalse = {
.common = { .type = STMT_EXPR, .next = NULL },
.op = EXPR_VALUE,
.value_type = EXPR_TYPE_BOOLEAN,
.value = { .ival = 0 },
static const ExprBoolean constFalse = {
.expr = {
.common = { .type = STMT_EXPR, .next = NULL },
.op = EXPR_VALUE,
.value_type = EXPR_TYPE_BOOLEAN,
},
.set = false,
};
enum action_field {
@ -214,17 +218,6 @@ ReportActionNotArray(struct xkb_keymap *keymap, enum xkb_action_type action,
return false;
}
static inline bool
ReportNotFound(struct xkb_keymap *keymap, enum xkb_action_type action,
enum action_field field, const char *what, const char *bad)
{
log_err(keymap->ctx,
"%s named %s not found; "
"Ignoring the %s field of an %s action\n",
what, bad, fieldText(field), ActionTypeText(action));
return false;
}
static bool
HandleNoAction(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
@ -265,9 +258,9 @@ CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action,
const ExprDef *value, enum xkb_action_flags *flags_inout,
xkb_mod_mask_t *mods_rtrn)
{
if (value->op == EXPR_IDENT) {
if (value->expr.op == EXPR_IDENT) {
const char *valStr;
valStr = xkb_atom_text(keymap->ctx, value->value.str);
valStr = xkb_atom_text(keymap->ctx, value->ident.ident);
if (valStr && (istreq(valStr, "usemodmapmods") ||
istreq(valStr, "modmapmods"))) {
@ -367,9 +360,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action,
{
const ExprDef *spec;
if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
*flags_inout &= ~ACTION_ABSOLUTE_SWITCH;
spec = value->value.child;
spec = value->unary.child;
}
else {
*flags_inout |= ACTION_ABSOLUTE_SWITCH;
@ -380,9 +373,9 @@ CheckGroupField(struct xkb_keymap *keymap, unsigned action,
return ReportMismatch(keymap, action, ACTION_FIELD_GROUP,
"integer (range 1..8)");
if (value->op == EXPR_NEGATE)
if (value->expr.op == EXPR_NEGATE)
*grp_rtrn = -*grp_rtrn;
else if (value->op != EXPR_UNARY_PLUS)
else if (value->expr.op != EXPR_UNARY_PLUS)
(*grp_rtrn)--;
return true;
@ -464,18 +457,14 @@ HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
const ExprDef *value)
{
struct xkb_pointer_action *act = &action->ptr;
bool absolute;
if (array_ndx && (field == ACTION_FIELD_X || field == ACTION_FIELD_Y))
return ReportActionNotArray(keymap, action->type, field);
if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) {
int val;
if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS)
absolute = false;
else
absolute = true;
const bool absolute = (value->expr.op != EXPR_NEGATE &&
value->expr.op != EXPR_UNARY_PLUS);
if (!ExprResolveInteger(keymap->ctx, value, &val))
return ReportMismatch(keymap, action->type, field, "integer");
@ -613,9 +602,10 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
act->flags &= ~ACTION_ABSOLUTE_SWITCH;
button = value->value.child;
button = value->unary.child;
}
else {
act->flags |= ACTION_ABSOLUTE_SWITCH;
@ -639,7 +629,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
return false;
}
act->value = (value->op == EXPR_NEGATE ? -btn: btn);
act->value = (value->expr.op == EXPR_NEGATE ? -btn: btn);
return true;
}
@ -660,9 +650,10 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
if (value->op == EXPR_NEGATE || value->op == EXPR_UNARY_PLUS) {
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
act->flags &= ~ACTION_ABSOLUTE_SWITCH;
scrn = value->value.child;
scrn = value->unary.child;
}
else {
act->flags |= ACTION_ABSOLUTE_SWITCH;
@ -680,7 +671,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
return false;
}
act->screen = (value->op == EXPR_NEGATE ? -val : val);
act->screen = (value->expr.op == EXPR_NEGATE ? -val : val);
return true;
}
else if (field == ACTION_FIELD_SAME) {
@ -861,13 +852,13 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
const char *str;
unsigned handler_type;
if (def->op != EXPR_ACTION_DECL) {
if (def->expr.op != EXPR_ACTION_DECL) {
log_err(keymap->ctx, "Expected an action definition, found %s\n",
expr_op_type_to_string(def->op));
expr_op_type_to_string(def->expr.op));
return false;
}
str = xkb_atom_text(keymap->ctx, def->value.action.name);
str = xkb_atom_text(keymap->ctx, def->action.name);
if (!stringToAction(str, &handler_type)) {
log_err(keymap->ctx, "Unknown action %s\n", str);
return false;
@ -885,24 +876,24 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
* particular instance, e.g. "modifiers" and "clearLocks" in:
* SetMods(modifiers=Alt,clearLocks);
*/
for (arg = def->value.action.args; arg != NULL;
for (arg = def->action.args; arg != NULL;
arg = (ExprDef *) arg->common.next) {
const ExprDef *value;
ExprDef *field, *arrayRtrn;
const char *elemRtrn, *fieldRtrn;
enum action_field fieldNdx;
if (arg->op == EXPR_ASSIGN) {
field = arg->value.binary.left;
value = arg->value.binary.right;
if (arg->expr.op == EXPR_ASSIGN) {
field = arg->binary.left;
value = arg->binary.right;
}
else if (arg->op == EXPR_NOT || arg->op == EXPR_INVERT) {
field = arg->value.child;
value = &constFalse;
else if (arg->expr.op == EXPR_NOT || arg->expr.op == EXPR_INVERT) {
field = arg->unary.child;
value = (const ExprDef *) &constFalse;
}
else {
field = arg;
value = &constTrue;
value = (const ExprDef *) &constTrue;
}
if (!ExprResolveLhs(keymap->ctx, field, &elemRtrn, &fieldRtrn,

View File

@ -70,57 +70,173 @@ AppendStmt(ParseCommon *to, ParseCommon *append)
return to;
}
ExprDef *
ExprCreate(enum expr_op_type op, enum expr_value_type type)
static ExprDef *
ExprCreate(enum expr_op_type op, enum expr_value_type type, size_t size)
{
ExprDef *expr = malloc(sizeof(*expr));
ExprDef *expr = malloc(size);
if (!expr)
return NULL;
expr->common.type = STMT_EXPR;
expr->common.next = NULL;
expr->op = op;
expr->value_type = type;
expr->expr.op = op;
expr->expr.value_type = type;
return expr;
}
#define EXPR_CREATE(type_, name_, op_, value_type_) \
ExprDef *name_ = ExprCreate(op_, value_type_, sizeof(type_)); \
if (!name_) \
return NULL;
ExprDef *
ExprCreateString(xkb_atom_t str)
{
EXPR_CREATE(ExprString, expr, EXPR_VALUE, EXPR_TYPE_STRING);
expr->string.str = str;
return expr;
}
ExprDef *
ExprCreateInteger(int ival)
{
EXPR_CREATE(ExprInteger, expr, EXPR_VALUE, EXPR_TYPE_INT);
expr->integer.ival = ival;
return expr;
}
ExprDef *
ExprCreateBoolean(bool set)
{
EXPR_CREATE(ExprBoolean, expr, EXPR_VALUE, EXPR_TYPE_BOOLEAN);
expr->boolean.set = set;
return expr;
}
ExprDef *
ExprCreateKeyName(xkb_atom_t key_name)
{
EXPR_CREATE(ExprKeyName, expr, EXPR_VALUE, EXPR_TYPE_KEYNAME);
expr->key_name.key_name = key_name;
return expr;
}
ExprDef *
ExprCreateIdent(xkb_atom_t ident)
{
EXPR_CREATE(ExprIdent, expr, EXPR_IDENT, EXPR_TYPE_UNKNOWN);
expr->ident.ident = ident;
return expr;
}
ExprDef *
ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
ExprDef *child)
{
ExprDef *expr = malloc(sizeof(*expr));
if (!expr)
return NULL;
expr->common.type = STMT_EXPR;
expr->common.next = NULL;
expr->op = op;
expr->value_type = type;
expr->value.child = child;
EXPR_CREATE(ExprUnary, expr, op, type);
expr->unary.child = child;
return expr;
}
ExprDef *
ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right)
{
ExprDef *expr = malloc(sizeof(*expr));
if (!expr)
return NULL;
EXPR_CREATE(ExprBinary, expr, op, EXPR_TYPE_UNKNOWN);
expr->common.type = STMT_EXPR;
expr->common.next = NULL;
expr->op = op;
if (op == EXPR_ASSIGN || left->value_type == EXPR_TYPE_UNKNOWN)
expr->value_type = right->value_type;
else if (left->value_type == right->value_type ||
right->value_type == EXPR_TYPE_UNKNOWN)
expr->value_type = left->value_type;
else
expr->value_type = EXPR_TYPE_UNKNOWN;
expr->value.binary.left = left;
expr->value.binary.right = right;
if (op == EXPR_ASSIGN || left->expr.value_type == EXPR_TYPE_UNKNOWN)
expr->expr.value_type = right->expr.value_type;
else if (left->expr.value_type == right->expr.value_type ||
right->expr.value_type == EXPR_TYPE_UNKNOWN)
expr->expr.value_type = left->expr.value_type;
expr->binary.left = left;
expr->binary.right = right;
return expr;
}
ExprDef *
ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field)
{
EXPR_CREATE(ExprFieldRef, expr, EXPR_FIELD_REF, EXPR_TYPE_UNKNOWN);
expr->field_ref.element = element;
expr->field_ref.field = field;
return expr;
}
ExprDef *
ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry)
{
EXPR_CREATE(ExprArrayRef, expr, EXPR_ARRAY_REF, EXPR_TYPE_UNKNOWN);
expr->array_ref.element = element;
expr->array_ref.field = field;
expr->array_ref.entry = entry;
return expr;
}
ExprDef *
ExprCreateAction(xkb_atom_t name, ExprDef *args)
{
EXPR_CREATE(ExprAction, expr, EXPR_ACTION_DECL, EXPR_TYPE_UNKNOWN);
expr->action.name = name;
expr->action.args = args;
return expr;
}
ExprDef *
ExprCreateKeysymList(xkb_keysym_t sym)
{
EXPR_CREATE(ExprKeysymList, expr, EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
darray_init(expr->keysym_list.syms);
darray_init(expr->keysym_list.symsMapIndex);
darray_init(expr->keysym_list.symsNumEntries);
darray_append(expr->keysym_list.syms, sym);
darray_append(expr->keysym_list.symsMapIndex, 0);
darray_append(expr->keysym_list.symsNumEntries, 1);
return expr;
}
ExprDef *
ExprCreateMultiKeysymList(ExprDef *expr)
{
size_t nLevels = darray_size(expr->keysym_list.symsMapIndex);
darray_resize(expr->keysym_list.symsMapIndex, 1);
darray_resize(expr->keysym_list.symsNumEntries, 1);
darray_item(expr->keysym_list.symsMapIndex, 0) = 0;
darray_item(expr->keysym_list.symsNumEntries, 0) = nLevels;
return expr;
}
ExprDef *
ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
{
size_t nSyms = darray_size(expr->keysym_list.syms);
darray_append(expr->keysym_list.symsMapIndex, nSyms);
darray_append(expr->keysym_list.symsNumEntries, 1);
darray_append(expr->keysym_list.syms, sym);
return expr;
}
ExprDef *
ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append)
{
size_t nSyms = darray_size(expr->keysym_list.syms);
size_t numEntries = darray_size(append->keysym_list.syms);
darray_append(expr->keysym_list.symsMapIndex, nSyms);
darray_append(expr->keysym_list.symsNumEntries, numEntries);
darray_append_items(expr->keysym_list.syms,
darray_mem(append->keysym_list.syms, 0), numEntries);
darray_resize(append->keysym_list.syms, 0);
FreeStmt(&append->common);
return expr;
}
@ -186,22 +302,14 @@ VarCreate(ExprDef *name, ExprDef *value)
}
VarDef *
BoolVarCreate(xkb_atom_t nameToken, unsigned set)
BoolVarCreate(xkb_atom_t ident, bool set)
{
ExprDef *name, *value;
VarDef *def;
name = ExprCreate(EXPR_IDENT, EXPR_TYPE_UNKNOWN);
name->value.str = nameToken;
value = ExprCreate(EXPR_VALUE, EXPR_TYPE_BOOLEAN);
value->value.uval = set;
def = VarCreate(name, value);
return def;
return VarCreate((ExprDef *) ExprCreateIdent(ident),
(ExprDef *) ExprCreateBoolean(set));
}
InterpDef *
InterpCreate(char *sym, ExprDef *match)
InterpCreate(xkb_keysym_t sym, ExprDef *match)
{
InterpDef *def = malloc(sizeof(*def));
if (!def)
@ -232,7 +340,7 @@ KeyTypeCreate(xkb_atom_t name, VarDef *body)
}
SymbolsDef *
SymbolsCreate(xkb_atom_t keyName, ExprDef *symbols)
SymbolsCreate(xkb_atom_t keyName, VarDef *symbols)
{
SymbolsDef *def = malloc(sizeof(*def));
if (!def)
@ -312,83 +420,6 @@ LedNameCreate(int ndx, ExprDef *name, bool virtual)
return def;
}
ExprDef *
ActionCreate(xkb_atom_t name, ExprDef *args)
{
ExprDef *act = malloc(sizeof(*act));
if (!act)
return NULL;
act->common.type = STMT_EXPR;
act->common.next = NULL;
act->op = EXPR_ACTION_DECL;
act->value.action.name = name;
act->value.action.args = args;
return act;
}
ExprDef *
CreateKeysymList(char *sym)
{
ExprDef *def;
def = ExprCreate(EXPR_KEYSYM_LIST, EXPR_TYPE_SYMBOLS);
darray_init(def->value.list.syms);
darray_init(def->value.list.symsMapIndex);
darray_init(def->value.list.symsNumEntries);
darray_append(def->value.list.syms, sym);
darray_append(def->value.list.symsMapIndex, 0);
darray_append(def->value.list.symsNumEntries, 1);
return def;
}
ExprDef *
CreateMultiKeysymList(ExprDef *list)
{
size_t nLevels = darray_size(list->value.list.symsMapIndex);
darray_resize(list->value.list.symsMapIndex, 1);
darray_resize(list->value.list.symsNumEntries, 1);
darray_item(list->value.list.symsMapIndex, 0) = 0;
darray_item(list->value.list.symsNumEntries, 0) = nLevels;
return list;
}
ExprDef *
AppendKeysymList(ExprDef *list, char *sym)
{
size_t nSyms = darray_size(list->value.list.syms);
darray_append(list->value.list.symsMapIndex, nSyms);
darray_append(list->value.list.symsNumEntries, 1);
darray_append(list->value.list.syms, sym);
return list;
}
ExprDef *
AppendMultiKeysymList(ExprDef *list, ExprDef *append)
{
size_t nSyms = darray_size(list->value.list.syms);
size_t numEntries = darray_size(append->value.list.syms);
darray_append(list->value.list.symsMapIndex, nSyms);
darray_append(list->value.list.symsNumEntries, numEntries);
darray_append_items(list->value.list.syms,
darray_mem(append->value.list.syms, 0),
numEntries);
darray_resize(append->value.list.syms, 0);
FreeStmt(&append->common);
return list;
}
static void
FreeInclude(IncludeStmt *incl);
@ -464,30 +495,6 @@ err:
return NULL;
}
static void
EscapeMapName(char *name)
{
/*
* All latin-1 alphanumerics, plus parens, slash, minus, underscore and
* wildcards.
*/
static const unsigned char legal[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83,
0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
};
if (!name)
return;
while (*name) {
if (!(legal[*name / 8] & (1 << (*name % 8))))
*name = '_';
name++;
}
}
XkbFile *
XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
ParseCommon *defs, enum xkb_map_flags flags)
@ -498,7 +505,7 @@ XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
if (!file)
return NULL;
EscapeMapName(name);
XkbEscapeMapName(name);
file->file_type = type;
file->topName = strdup_safe(name);
file->name = name;
@ -549,18 +556,16 @@ err:
static void
FreeExpr(ExprDef *expr)
{
char **sym;
if (!expr)
return;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_ACTION_LIST:
case EXPR_NEGATE:
case EXPR_UNARY_PLUS:
case EXPR_NOT:
case EXPR_INVERT:
FreeStmt(&expr->value.child->common);
FreeStmt(&expr->unary.child->common);
break;
case EXPR_DIVIDE:
@ -568,24 +573,22 @@ FreeExpr(ExprDef *expr)
case EXPR_SUBTRACT:
case EXPR_MULTIPLY:
case EXPR_ASSIGN:
FreeStmt(&expr->value.binary.left->common);
FreeStmt(&expr->value.binary.right->common);
FreeStmt(&expr->binary.left->common);
FreeStmt(&expr->binary.right->common);
break;
case EXPR_ACTION_DECL:
FreeStmt(&expr->value.action.args->common);
FreeStmt(&expr->action.args->common);
break;
case EXPR_ARRAY_REF:
FreeStmt(&expr->value.array.entry->common);
FreeStmt(&expr->array_ref.entry->common);
break;
case EXPR_KEYSYM_LIST:
darray_foreach(sym, expr->value.list.syms)
free(*sym);
darray_free(expr->value.list.syms);
darray_free(expr->value.list.symsMapIndex);
darray_free(expr->value.list.symsNumEntries);
darray_free(expr->keysym_list.syms);
darray_free(expr->keysym_list.symsMapIndex);
darray_free(expr->keysym_list.symsNumEntries);
break;
default:
@ -640,7 +643,6 @@ FreeStmt(ParseCommon *stmt)
FreeStmt(&u.keyType->body->common);
break;
case STMT_INTERP:
free(u.interp->sym);
FreeStmt(&u.interp->match->common);
FreeStmt(&u.interp->def->common);
break;

View File

@ -31,7 +31,19 @@ ParseCommon *
AppendStmt(ParseCommon *to, ParseCommon *append);
ExprDef *
ExprCreate(enum expr_op_type op, enum expr_value_type type);
ExprCreateString(xkb_atom_t str);
ExprDef *
ExprCreateInteger(int ival);
ExprDef *
ExprCreateBoolean(bool set);
ExprDef *
ExprCreateKeyName(xkb_atom_t key_name);
ExprDef *
ExprCreateIdent(xkb_atom_t ident);
ExprDef *
ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
@ -40,6 +52,27 @@ ExprCreateUnary(enum expr_op_type op, enum expr_value_type type,
ExprDef *
ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right);
ExprDef *
ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field);
ExprDef *
ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry);
ExprDef *
ExprCreateAction(xkb_atom_t name, ExprDef *args);
ExprDef *
ExprCreateMultiKeysymList(ExprDef *list);
ExprDef *
ExprCreateKeysymList(xkb_keysym_t sym);
ExprDef *
ExprAppendMultiKeysymList(ExprDef *list, ExprDef *append);
ExprDef *
ExprAppendKeysymList(ExprDef *list, xkb_keysym_t sym);
KeycodeDef *
KeycodeCreate(xkb_atom_t name, int64_t value);
@ -53,16 +86,16 @@ VarDef *
VarCreate(ExprDef *name, ExprDef *value);
VarDef *
BoolVarCreate(xkb_atom_t nameToken, unsigned set);
BoolVarCreate(xkb_atom_t ident, bool set);
InterpDef *
InterpCreate(char *sym, ExprDef *match);
InterpCreate(xkb_keysym_t sym, ExprDef *match);
KeyTypeDef *
KeyTypeCreate(xkb_atom_t name, VarDef *body);
SymbolsDef *
SymbolsCreate(xkb_atom_t keyName, ExprDef *symbols);
SymbolsCreate(xkb_atom_t keyName, VarDef *symbols);
GroupCompatDef *
GroupCompatCreate(int group, ExprDef *def);
@ -76,27 +109,12 @@ LedMapCreate(xkb_atom_t name, VarDef *body);
LedNameDef *
LedNameCreate(int ndx, ExprDef *name, bool virtual);
ExprDef *
ActionCreate(xkb_atom_t name, ExprDef *args);
ExprDef *
CreateMultiKeysymList(ExprDef *list);
ExprDef *
CreateKeysymList(char *sym);
ExprDef *
AppendMultiKeysymList(ExprDef *list, ExprDef *append);
ExprDef *
AppendKeysymList(ExprDef *list, char *sym);
IncludeStmt *
IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge);
XkbFile *
XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
ParseCommon *defs, unsigned flags);
ParseCommon *defs, enum xkb_map_flags flags);
void
FreeStmt(ParseCommon *stmt);

View File

@ -143,9 +143,11 @@ expr_op_type_to_string(enum expr_op_type type);
const char *
expr_value_type_to_string(enum expr_value_type type);
typedef struct _ParseCommon {
enum stmt_type type;
/* This struct contains fields common to all other AST nodes. It is only
* ever embedded in other structs, so save some memory by packing it. */
typedef struct ATTR_PACKED _ParseCommon {
struct _ParseCommon *next;
enum stmt_type type;
} ParseCommon;
typedef struct _IncludeStmt {
@ -158,40 +160,92 @@ typedef struct _IncludeStmt {
struct _IncludeStmt *next_incl;
} IncludeStmt;
typedef struct _Expr {
typedef struct {
ParseCommon common;
enum expr_op_type op;
enum expr_value_type value_type;
union {
struct {
struct _Expr *left;
struct _Expr *right;
} binary;
struct {
xkb_atom_t element;
xkb_atom_t field;
} field;
struct {
xkb_atom_t element;
xkb_atom_t field;
struct _Expr *entry;
} array;
struct {
xkb_atom_t name;
struct _Expr *args;
} action;
struct {
darray(char *) syms;
darray(int) symsMapIndex;
darray(unsigned int) symsNumEntries;
} list;
struct _Expr *child;
xkb_atom_t str;
unsigned uval;
int ival;
xkb_atom_t keyName;
} value;
} ExprDef;
} ExprCommon;
typedef union ExprDef ExprDef;
typedef struct {
ExprCommon expr;
xkb_atom_t ident;
} ExprIdent;
typedef struct {
ExprCommon expr;
xkb_atom_t str;
} ExprString;
typedef struct {
ExprCommon expr;
bool set;
} ExprBoolean;
typedef struct {
ExprCommon expr;
int ival;
} ExprInteger;
typedef struct {
ExprCommon expr;
xkb_atom_t key_name;
} ExprKeyName;
typedef struct {
ExprCommon expr;
ExprDef *left;
ExprDef *right;
} ExprBinary;
typedef struct {
ExprCommon expr;
ExprDef *child;
} ExprUnary;
typedef struct {
ExprCommon expr;
xkb_atom_t element;
xkb_atom_t field;
} ExprFieldRef;
typedef struct {
ExprCommon expr;
xkb_atom_t element;
xkb_atom_t field;
ExprDef *entry;
} ExprArrayRef;
typedef struct {
ExprCommon expr;
xkb_atom_t name;
ExprDef *args;
} ExprAction;
typedef struct {
ExprCommon expr;
darray(xkb_keysym_t) syms;
darray(int) symsMapIndex;
darray(unsigned int) symsNumEntries;
} ExprKeysymList;
union ExprDef {
ParseCommon common;
/* Maybe someday we can use C11 anonymous struct for ExprCommon here. */
ExprCommon expr;
ExprIdent ident;
ExprString string;
ExprBoolean boolean;
ExprInteger integer;
ExprKeyName key_name;
ExprBinary binary;
ExprUnary unary;
ExprFieldRef field_ref;
ExprArrayRef array_ref;
ExprAction action;
ExprKeysymList keysym_list;
};
typedef struct {
ParseCommon common;
@ -232,7 +286,7 @@ typedef struct {
ParseCommon common;
enum merge_mode merge;
xkb_atom_t keyName;
ExprDef *symbols;
VarDef *symbols;
} SymbolsDef;
typedef struct {
@ -252,7 +306,7 @@ typedef struct {
typedef struct {
ParseCommon common;
enum merge_mode merge;
char *sym;
xkb_keysym_t sym;
ExprDef *match;
VarDef *def;
} InterpDef;

View File

@ -432,19 +432,19 @@ ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn,
}
*pred_rtrn = MATCH_EXACTLY;
if (expr->op == EXPR_ACTION_DECL) {
if (expr->expr.op == EXPR_ACTION_DECL) {
const char *pred_txt = xkb_atom_text(info->keymap->ctx,
expr->value.action.name);
expr->action.name);
if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn)) {
log_err(info->keymap->ctx,
"Illegal modifier predicate \"%s\"; Ignored\n", pred_txt);
return false;
}
expr = expr->value.action.args;
expr = expr->action.args;
}
else if (expr->op == EXPR_IDENT) {
else if (expr->expr.op == EXPR_IDENT) {
const char *pred_txt = xkb_atom_text(info->keymap->ctx,
expr->value.str);
expr->ident.ident);
if (pred_txt && istreq(pred_txt, "any")) {
*pred_rtrn = MATCH_ANY;
*mods_rtrn = MOD_REAL_MASK_ALL;
@ -805,7 +805,7 @@ HandleInterpBody(CompatInfo *info, VarDef *def, SymInterpInfo *si)
ExprDef *arrayNdx;
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->op == EXPR_FIELD_REF) {
if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
log_err(info->keymap->ctx,
"Cannot set a global default value from within an interpret statement; "
"Move statements to the global file scope\n");
@ -840,15 +840,7 @@ HandleInterpDef(CompatInfo *info, InterpDef *def, enum merge_mode merge)
si = info->default_interp;
si.merge = merge = (def->merge == MERGE_DEFAULT ? merge : def->merge);
if (!LookupKeysym(def->sym, &si.interp.sym)) {
log_err(info->keymap->ctx,
"Could not resolve keysym %s; "
"Symbol interpretation ignored\n",
def->sym);
return false;
}
si.interp.sym = def->sym;
si.interp.match = pred;
si.interp.mods = mods;
@ -941,7 +933,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
break;
default:
log_err(info->keymap->ctx,
"Interpretation files may not include other types; "
"Compat files may not include other types; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
break;
@ -958,15 +950,21 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
}
}
/* Temporary struct for CopyInterps. */
struct collect {
darray(struct xkb_sym_interpret) sym_interprets;
};
static void
CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred)
CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred,
struct collect *collect)
{
SymInterpInfo *si;
darray_foreach(si, info->interps)
if (si->interp.match == pred &&
(si->interp.sym != XKB_KEY_NoSymbol) == needSymbol)
darray_append(info->keymap->sym_interprets, si->interp);
darray_append(collect->sym_interprets, si->interp);
}
static void
@ -1025,19 +1023,26 @@ static bool
CopyCompatToKeymap(struct xkb_keymap *keymap, CompatInfo *info)
{
keymap->compat_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->compat_section_name);
if (!darray_empty(info->interps)) {
struct collect collect;
darray_init(collect.sym_interprets);
/* Most specific to least specific. */
CopyInterps(info, true, MATCH_EXACTLY);
CopyInterps(info, true, MATCH_ALL);
CopyInterps(info, true, MATCH_NONE);
CopyInterps(info, true, MATCH_ANY);
CopyInterps(info, true, MATCH_ANY_OR_NONE);
CopyInterps(info, false, MATCH_EXACTLY);
CopyInterps(info, false, MATCH_ALL);
CopyInterps(info, false, MATCH_NONE);
CopyInterps(info, false, MATCH_ANY);
CopyInterps(info, false, MATCH_ANY_OR_NONE);
CopyInterps(info, true, MATCH_EXACTLY, &collect);
CopyInterps(info, true, MATCH_ALL, &collect);
CopyInterps(info, true, MATCH_NONE, &collect);
CopyInterps(info, true, MATCH_ANY, &collect);
CopyInterps(info, true, MATCH_ANY_OR_NONE, &collect);
CopyInterps(info, false, MATCH_EXACTLY, &collect);
CopyInterps(info, false, MATCH_ALL, &collect);
CopyInterps(info, false, MATCH_NONE, &collect);
CopyInterps(info, false, MATCH_ANY, &collect);
CopyInterps(info, false, MATCH_ANY_OR_NONE, &collect);
keymap->num_sym_interprets = darray_size(collect.sym_interprets);
keymap->sym_interprets = darray_mem(collect.sym_interprets, 0);
}
CopyLedMapDefs(info);

View File

@ -37,26 +37,26 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
const char **elem_rtrn, const char **field_rtrn,
ExprDef **index_rtrn)
{
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_IDENT:
*elem_rtrn = NULL;
*field_rtrn = xkb_atom_text(ctx, expr->value.str);
*field_rtrn = xkb_atom_text(ctx, expr->ident.ident);
*index_rtrn = NULL;
return true;
case EXPR_FIELD_REF:
*elem_rtrn = xkb_atom_text(ctx, expr->value.field.element);
*field_rtrn = xkb_atom_text(ctx, expr->value.field.field);
*elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element);
*field_rtrn = xkb_atom_text(ctx, expr->field_ref.field);
*index_rtrn = NULL;
return true;
case EXPR_ARRAY_REF:
*elem_rtrn = xkb_atom_text(ctx, expr->value.array.element);
*field_rtrn = xkb_atom_text(ctx, expr->value.array.field);
*index_rtrn = expr->value.array.entry;
*elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element);
*field_rtrn = xkb_atom_text(ctx, expr->array_ref.field);
*index_rtrn = expr->array_ref.entry;
return true;
default:
break;
}
log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->op);
log_wsgo(ctx, "Unexpected operator %d in ResolveLhs\n", expr->expr.op);
return false;
}
@ -127,19 +127,19 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
bool ok = false;
const char *ident;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_VALUE:
if (expr->value_type != EXPR_TYPE_BOOLEAN) {
if (expr->expr.value_type != EXPR_TYPE_BOOLEAN) {
log_err(ctx,
"Found constant of type %s where boolean was expected\n",
expr_value_type_to_string(expr->value_type));
expr_value_type_to_string(expr->expr.value_type));
return false;
}
*set_rtrn = !!expr->value.ival;
*set_rtrn = expr->boolean.set;
return true;
case EXPR_IDENT:
ident = xkb_atom_text(ctx, expr->value.str);
ident = xkb_atom_text(ctx, expr->ident.ident);
if (ident) {
if (istreq(ident, "true") ||
istreq(ident, "yes") ||
@ -154,14 +154,13 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
return true;
}
}
log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n",
xkb_atom_text(ctx, expr->value.str));
log_err(ctx, "Identifier \"%s\" of type boolean is unknown\n", ident);
return false;
case EXPR_FIELD_REF:
log_err(ctx, "Default \"%s.%s\" of type boolean is unknown\n",
xkb_atom_text(ctx, expr->value.field.element),
xkb_atom_text(ctx, expr->value.field.field));
xkb_atom_text(ctx, expr->field_ref.element),
xkb_atom_text(ctx, expr->field_ref.field));
return false;
case EXPR_INVERT:
@ -178,11 +177,12 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_NEGATE:
case EXPR_UNARY_PLUS:
log_err(ctx, "%s of boolean values not permitted\n",
expr_op_type_to_string(expr->op));
expr_op_type_to_string(expr->expr.op));
break;
default:
log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n", expr->op);
log_wsgo(ctx, "Unknown operator %d in ResolveBoolean\n",
expr->expr.op);
break;
}
@ -194,32 +194,28 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
xkb_keycode_t *kc)
{
xkb_keycode_t leftRtrn, rightRtrn;
ExprDef *left, *right;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_VALUE:
if (expr->value_type != EXPR_TYPE_INT) {
if (expr->expr.value_type != EXPR_TYPE_INT) {
log_err(ctx,
"Found constant of type %s where an int was expected\n",
expr_value_type_to_string(expr->value_type));
expr_value_type_to_string(expr->expr.value_type));
return false;
}
*kc = expr->value.uval;
*kc = (xkb_keycode_t) expr->integer.ival;
return true;
case EXPR_ADD:
case EXPR_SUBTRACT:
case EXPR_MULTIPLY:
case EXPR_DIVIDE:
left = expr->value.binary.left;
right = expr->value.binary.right;
if (!ExprResolveKeyCode(ctx, left, &leftRtrn) ||
!ExprResolveKeyCode(ctx, right, &rightRtrn))
if (!ExprResolveKeyCode(ctx, expr->binary.left, &leftRtrn) ||
!ExprResolveKeyCode(ctx, expr->binary.right, &rightRtrn))
return false;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_ADD:
*kc = leftRtrn + rightRtrn;
break;
@ -245,19 +241,18 @@ ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr,
return true;
case EXPR_NEGATE:
left = expr->value.child;
if (!ExprResolveKeyCode(ctx, left, &leftRtrn))
if (!ExprResolveKeyCode(ctx, expr->unary.child, &leftRtrn))
return false;
*kc = ~leftRtrn;
return true;
case EXPR_UNARY_PLUS:
left = expr->value.child;
return ExprResolveKeyCode(ctx, left, kc);
return ExprResolveKeyCode(ctx, expr->unary.child, kc);
default:
log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n", expr->op);
log_wsgo(ctx, "Unknown operator %d in ResolveKeyCode\n",
expr->expr.op);
break;
}
@ -284,25 +279,25 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
unsigned u;
ExprDef *left, *right;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_VALUE:
if (expr->value_type != EXPR_TYPE_INT) {
if (expr->expr.value_type != EXPR_TYPE_INT) {
log_err(ctx,
"Found constant of type %s where an int was expected\n",
expr_value_type_to_string(expr->value_type));
expr_value_type_to_string(expr->expr.value_type));
return false;
}
*val_rtrn = expr->value.ival;
*val_rtrn = expr->integer.ival;
return true;
case EXPR_IDENT:
if (lookup)
ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT, &u);
ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT, &u);
if (!ok)
log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
xkb_atom_text(ctx, expr->value.str));
xkb_atom_text(ctx, expr->ident.ident));
else
*val_rtrn = (int) u;
@ -310,21 +305,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_FIELD_REF:
log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
xkb_atom_text(ctx, expr->value.field.element),
xkb_atom_text(ctx, expr->value.field.field));
xkb_atom_text(ctx, expr->field_ref.element),
xkb_atom_text(ctx, expr->field_ref.field));
return false;
case EXPR_ADD:
case EXPR_SUBTRACT:
case EXPR_MULTIPLY:
case EXPR_DIVIDE:
left = expr->value.binary.left;
right = expr->value.binary.right;
left = expr->binary.left;
right = expr->binary.right;
if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) ||
!ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv))
return false;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_ADD:
*val_rtrn = l + r;
break;
@ -357,20 +352,21 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_INVERT:
case EXPR_NEGATE:
left = expr->value.child;
left = expr->unary.child;
if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv))
return false;
*val_rtrn = (expr->op == EXPR_NEGATE ? -l : ~l);
*val_rtrn = (expr->expr.op == EXPR_NEGATE ? -l : ~l);
return true;
case EXPR_UNARY_PLUS:
left = expr->value.child;
left = expr->unary.child;
return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup,
lookupPriv);
default:
log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n", expr->op);
log_wsgo(ctx, "Unknown operator %d in ResolveInteger\n",
expr->expr.op);
break;
}
@ -445,26 +441,26 @@ bool
ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
xkb_atom_t *val_rtrn)
{
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_VALUE:
if (expr->value_type != EXPR_TYPE_STRING) {
if (expr->expr.value_type != EXPR_TYPE_STRING) {
log_err(ctx, "Found constant of type %s, expected a string\n",
expr_value_type_to_string(expr->value_type));
expr_value_type_to_string(expr->expr.value_type));
return false;
}
*val_rtrn = expr->value.str;
*val_rtrn = expr->string.str;
return true;
case EXPR_IDENT:
log_err(ctx, "Identifier \"%s\" of type string not found\n",
xkb_atom_text(ctx, expr->value.str));
xkb_atom_text(ctx, expr->ident.ident));
return false;
case EXPR_FIELD_REF:
log_err(ctx, "Default \"%s.%s\" of type string not found\n",
xkb_atom_text(ctx, expr->value.field.element),
xkb_atom_text(ctx, expr->value.field.field));
xkb_atom_text(ctx, expr->field_ref.element),
xkb_atom_text(ctx, expr->field_ref.field));
return false;
case EXPR_ADD:
@ -477,11 +473,12 @@ ExprResolveString(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_NOT:
case EXPR_UNARY_PLUS:
log_err(ctx, "%s of strings not permitted\n",
expr_op_type_to_string(expr->op));
expr_op_type_to_string(expr->expr.op));
return false;
default:
log_wsgo(ctx, "Unknown operator %d in ResolveString\n", expr->op);
log_wsgo(ctx, "Unknown operator %d in ResolveString\n",
expr->expr.op);
break;
}
return false;
@ -491,16 +488,16 @@ bool
ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr,
unsigned int *val_rtrn, const LookupEntry *values)
{
if (expr->op != EXPR_IDENT) {
if (expr->expr.op != EXPR_IDENT) {
log_err(ctx, "Found a %s where an enumerated value was expected\n",
expr_op_type_to_string(expr->op));
expr_op_type_to_string(expr->expr.op));
return false;
}
if (!SimpleLookup(ctx, values, expr->value.str, EXPR_TYPE_INT,
if (!SimpleLookup(ctx, values, expr->ident.ident, EXPR_TYPE_INT,
val_rtrn)) {
log_err(ctx, "Illegal identifier %s; expected one of:\n",
xkb_atom_text(ctx, expr->value.str));
xkb_atom_text(ctx, expr->ident.ident));
while (values && values->name)
{
log_err(ctx, "\t%s\n", values->name);
@ -523,29 +520,29 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
ExprDef *left, *right;
const char *bogus = NULL;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_VALUE:
if (expr->value_type != EXPR_TYPE_INT) {
if (expr->expr.value_type != EXPR_TYPE_INT) {
log_err(ctx,
"Found constant of type %s where a mask was expected\n",
expr_value_type_to_string(expr->value_type));
expr_value_type_to_string(expr->expr.value_type));
return false;
}
*val_rtrn = (unsigned int) expr->value.ival;
*val_rtrn = (unsigned int) expr->integer.ival;
return true;
case EXPR_IDENT:
ok = lookup(ctx, lookupPriv, expr->value.str, EXPR_TYPE_INT,
ok = lookup(ctx, lookupPriv, expr->ident.ident, EXPR_TYPE_INT,
val_rtrn);
if (!ok)
log_err(ctx, "Identifier \"%s\" of type int is unknown\n",
xkb_atom_text(ctx, expr->value.str));
xkb_atom_text(ctx, expr->ident.ident));
return ok;
case EXPR_FIELD_REF:
log_err(ctx, "Default \"%s.%s\" of type int is unknown\n",
xkb_atom_text(ctx, expr->value.field.element),
xkb_atom_text(ctx, expr->value.field.field));
xkb_atom_text(ctx, expr->field_ref.element),
xkb_atom_text(ctx, expr->field_ref.field));
return false;
case EXPR_ARRAY_REF:
@ -563,13 +560,13 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_SUBTRACT:
case EXPR_MULTIPLY:
case EXPR_DIVIDE:
left = expr->value.binary.left;
right = expr->value.binary.right;
left = expr->binary.left;
right = expr->binary.right;
if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) ||
!ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv))
return false;
switch (expr->op) {
switch (expr->expr.op) {
case EXPR_ADD:
*val_rtrn = l | r;
break;
@ -579,7 +576,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_MULTIPLY:
case EXPR_DIVIDE:
log_err(ctx, "Cannot %s masks; Illegal operation ignored\n",
(expr->op == EXPR_DIVIDE ? "divide" : "multiply"));
(expr->expr.op == EXPR_DIVIDE ? "divide" : "multiply"));
return false;
default:
break;
@ -592,7 +589,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
break;
case EXPR_INVERT:
left = expr->value.child;
left = expr->unary.child;
if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
return false;
@ -602,14 +599,15 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_UNARY_PLUS:
case EXPR_NEGATE:
case EXPR_NOT:
left = expr->value.child;
left = expr->unary.child;
if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv))
log_err(ctx, "The %s operator cannot be used with a mask\n",
(expr->op == EXPR_NEGATE ? "-" : "!"));
(expr->expr.op == EXPR_NEGATE ? "-" : "!"));
return false;
default:
log_wsgo(ctx, "Unknown operator %d in ResolveMask\n", expr->op);
log_wsgo(ctx, "Unknown operator %d in ResolveMask\n",
expr->expr.op);
break;
}
@ -638,9 +636,8 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
{
int val;
if (expr->op == EXPR_IDENT) {
const char *str;
str = xkb_atom_text(ctx, expr->value.str);
if (expr->expr.op == EXPR_IDENT) {
const char *str = xkb_atom_text(ctx, expr->ident.ident);
*sym_rtrn = xkb_keysym_from_name(str, 0);
if (*sym_rtrn != XKB_KEY_NoSymbol)
return true;
@ -652,7 +649,7 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
if (val < 0 || val >= 10)
return false;
*sym_rtrn = ((xkb_keysym_t) val) + '0';
*sym_rtrn = XKB_KEY_0 + (xkb_keysym_t) val;
return true;
}
@ -661,16 +658,17 @@ ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn)
{
xkb_mod_index_t ndx;
xkb_atom_t name = def->value.str;
xkb_atom_t name;
if (def->op != EXPR_IDENT) {
if (def->expr.op != EXPR_IDENT) {
log_err(keymap->ctx,
"Cannot resolve virtual modifier: "
"found %s where a virtual modifier name was expected\n",
expr_op_type_to_string(def->op));
expr_op_type_to_string(def->expr.op));
return false;
}
name = def->ident.ident;
ndx = ModNameToIndex(keymap, name, mod_type);
if (ndx == XKB_MOD_INVALID) {
log_err(keymap->ctx,

View File

@ -199,17 +199,34 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name,
{
unsigned int i;
FILE *file = NULL;
char buf[PATH_MAX];
char *buf = NULL;
const char *typeDir;
size_t buf_size = 0, typeDirLen, name_len;
typeDir = DirectoryForInclude(type);
typeDirLen = strlen(typeDir);
name_len = strlen(name);
for (i = 0; i < xkb_context_num_include_paths(ctx); i++) {
int ret = snprintf(buf, sizeof(buf), "%s/%s/%s",
xkb_context_include_path_get(ctx, i),
typeDir, name);
if (ret >= (ssize_t) sizeof(buf)) {
log_err(ctx, "File name (%s/%s/%s) too long\n",
size_t new_buf_size = strlen(xkb_context_include_path_get(ctx, i)) +
typeDirLen + name_len + 3;
int ret;
if (new_buf_size > buf_size) {
void *buf_new = realloc(buf, new_buf_size);
if (buf_new) {
buf_size = new_buf_size;
buf = buf_new;
} else {
log_err(ctx, "Cannot realloc for name (%s/%s/%s)\n",
xkb_context_include_path_get(ctx, i), typeDir, name);
continue;
}
}
ret = snprintf(buf, buf_size, "%s/%s/%s",
xkb_context_include_path_get(ctx, i),
typeDir, name);
if (ret < 0) {
log_err(ctx, "snprintf error (%s/%s/%s)\n",
xkb_context_include_path_get(ctx, i), typeDir, name);
continue;
}
@ -242,11 +259,14 @@ FindFileInXkbPath(struct xkb_context *ctx, const char *name,
xkb_context_failed_include_path_get(ctx, i));
}
free(buf);
return NULL;
}
if (pathRtrn)
*pathRtrn = strdup(buf);
*pathRtrn = buf;
else
free(buf);
return file;
}
@ -275,7 +295,7 @@ ProcessIncludeFile(struct xkb_context *ctx, IncludeStmt *stmt,
if (xkb_file->file_type != file_type) {
log_err(ctx,
"Include file wrong type (expected %s, got %s); "
"Include file of wrong type (expected %s, got %s); "
"Include file \"%s\" ignored\n",
xkb_file_type_to_string(file_type),
xkb_file_type_to_string(xkb_file->file_type), stmt->file);

View File

@ -231,7 +231,10 @@ InitKeyNamesInfo(KeyNamesInfo *info, struct xkb_context *ctx)
{
memset(info, 0, sizeof(*info));
info->ctx = ctx;
info->min_key_code = XKB_KEYCODE_MAX;
info->min_key_code = XKB_KEYCODE_INVALID;
#if XKB_KEYCODE_INVALID < XKB_KEYCODE_MAX
#error "Hey, you can't be changing stuff like that."
#endif
}
static xkb_keycode_t
@ -604,16 +607,28 @@ CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
unsigned i;
keymap->keycodes_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->keycodes_section_name);
keymap->min_key_code = info->min_key_code;
keymap->max_key_code = info->max_key_code;
if (info->min_key_code != XKB_KEYCODE_INVALID) {
keymap->min_key_code = info->min_key_code;
keymap->max_key_code = info->max_key_code;
}
else {
/*
* If the keymap has no keys, let's just use the safest pair
* we know.
*/
keymap->min_key_code = 8;
keymap->max_key_code = 255;
}
keymap->keys = calloc(keymap->max_key_code + 1, sizeof(*keymap->keys));
for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++)
keymap->keys[kc].keycode = kc;
/* Copy key names. */
keymap->keys = calloc(info->max_key_code + 1, sizeof(*keymap->keys));
for (kc = info->min_key_code; kc <= info->max_key_code; kc++) {
keymap->keys[kc].keycode = kc;
for (kc = info->min_key_code; kc <= info->max_key_code; kc++)
keymap->keys[kc].name = darray_item(info->key_names, kc);
}
/*
* Do some sanity checking on the aliases. We can't do it before

View File

@ -157,17 +157,24 @@ write_keycodes(struct xkb_keymap *keymap, struct buf *buf)
else
write_buf(buf, "xkb_keycodes {\n");
/* xkbcomp and X11 really want to see keymaps with a minimum of 8, and
* a maximum of at least 255, else XWayland really starts hating life.
* If this is a problem and people really need strictly bounded keymaps,
* we should probably control this with a flag. */
write_buf(buf, "\tminimum = %u;\n", min(keymap->min_key_code, 8));
write_buf(buf, "\tmaximum = %u;\n", max(keymap->max_key_code, 255));
xkb_foreach_key(key, keymap) {
if (key->name == XKB_ATOM_NONE)
continue;
write_buf(buf, "\t%-20s = %d;\n",
write_buf(buf, "\t%-20s = %u;\n",
KeyNameText(keymap->ctx, key->name), key->keycode);
}
darray_enumerate(idx, led, keymap->leds)
if (led->name != XKB_ATOM_NONE)
write_buf(buf, "\tindicator %d = \"%s\";\n",
write_buf(buf, "\tindicator %u = \"%s\";\n",
idx + 1, xkb_atom_text(keymap->ctx, led->name));
@ -212,7 +219,7 @@ write_types(struct xkb_keymap *keymap, struct buf *buf)
continue;
str = ModMaskText(keymap, entry->mods.mods);
write_buf(buf, "\t\tmap[%s]= Level%d;\n",
write_buf(buf, "\t\tmap[%s]= Level%u;\n",
str, entry->level + 1);
if (entry->preserve.mods)
@ -222,7 +229,7 @@ write_types(struct xkb_keymap *keymap, struct buf *buf)
for (xkb_level_index_t n = 0; n < type->num_levels; n++)
if (type->level_names[n])
write_buf(buf, "\t\tlevel_name[Level%d]= \"%s\";\n", n + 1,
write_buf(buf, "\t\tlevel_name[Level%u]= \"%s\";\n", n + 1,
xkb_atom_text(keymap->ctx, type->level_names[n]));
write_buf(buf, "\t};\n");
@ -409,7 +416,6 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
static bool
write_compat(struct xkb_keymap *keymap, struct buf *buf)
{
const struct xkb_sym_interpret *si;
const struct xkb_led *led;
if (keymap->compat_section_name)
@ -423,7 +429,9 @@ write_compat(struct xkb_keymap *keymap, struct buf *buf)
write_buf(buf, "\tinterpret.useModMapMods= AnyLevel;\n");
write_buf(buf, "\tinterpret.repeat= False;\n");
darray_foreach(si, keymap->sym_interprets) {
for (int i = 0; i < keymap->num_sym_interprets; i++) {
const struct xkb_sym_interpret *si = &keymap->sym_interprets[i];
write_buf(buf, "\tinterpret %s+%s(%s) {\n",
si->sym ? KeysymText(keymap->ctx, si->sym) : "Any",
SIMatchText(si->match),
@ -610,7 +618,7 @@ write_symbols(struct xkb_keymap *keymap, struct buf *buf)
for (group = 0; group < keymap->num_group_names; group++)
if (keymap->group_names[group])
write_buf(buf,
"\tname[group%d]=\"%s\";\n", group + 1,
"\tname[group%u]=\"%s\";\n", group + 1,
xkb_atom_text(keymap->ctx, keymap->group_names[group]));
if (group > 0)
write_buf(buf, "\n");

View File

@ -78,7 +78,6 @@ static const struct xkb_sym_interpret *
FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
xkb_layout_index_t group, xkb_level_index_t level)
{
const struct xkb_sym_interpret *interp;
const xkb_keysym_t *syms;
int num_syms;
@ -93,7 +92,9 @@ FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
* sym_interprets array from the most specific to the least specific,
* such that when we find a match we return immediately.
*/
darray_foreach(interp, keymap->sym_interprets) {
for (int i = 0; i < keymap->num_sym_interprets; i++) {
const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
xkb_mod_mask_t mods;
bool found = false;
@ -224,28 +225,6 @@ UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
return true;
}
static bool
UpdateBuiltinKeymapFields(struct xkb_keymap *keymap)
{
struct xkb_context *ctx = keymap->ctx;
/*
* Add predefined (AKA real, core, X11) modifiers.
* The order is important!
*/
darray_appends_t(keymap->mods, struct xkb_mod,
{ .name = xkb_atom_intern(ctx, "Shift"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Lock"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Control"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Mod1"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Mod2"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Mod3"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Mod4"), .type = MOD_REAL },
{ .name = xkb_atom_intern(ctx, "Mod5"), .type = MOD_REAL });
return true;
}
typedef bool (*compile_file_fn)(XkbFile *file,
struct xkb_keymap *keymap,
enum merge_mode merge);
@ -311,9 +290,6 @@ CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
if (!ok)
return false;
if (!UpdateBuiltinKeymapFields(keymap))
return false;
/* Compile sections. */
for (type = FIRST_KEYMAP_FILE_TYPE;
type <= LAST_KEYMAP_FILE_TYPE;

View File

@ -0,0 +1,349 @@
/* ANSI-C code produced by gperf version 3.0.4 */
/* Command-line: gperf */
/* Computed positions: -k'1-2,5' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
#endif
#include "xkbcomp-priv.h"
#include "parser-priv.h"
static unsigned int
keyword_gperf_hash(const char *str, unsigned int len);
static const struct keyword_tok *
keyword_gperf_lookup(const char *str, unsigned int len);
struct keyword_tok { int name; int tok; };
#include <string.h>
/* maximum key range = 70, duplicates = 0 */
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
static unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
255
};
#endif
#ifndef GPERF_CASE_STRCMP
#define GPERF_CASE_STRCMP 1
static int
gperf_case_strcmp (register const char *s1, register const char *s2)
{
for (;;)
{
unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
if (c1 != 0 && c1 == c2)
continue;
return (int)c1 - (int)c2;
}
}
#endif
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static unsigned int
keyword_gperf_hash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 0, 73, 5, 36, 0,
10, 1, 15, 15, 73, 0, 10, 20, 35, 20,
50, 73, 10, 10, 5, 0, 15, 73, 0, 15,
73, 73, 73, 73, 73, 73, 73, 0, 73, 5,
36, 0, 10, 1, 15, 15, 73, 0, 10, 20,
35, 20, 50, 73, 10, 10, 5, 0, 15, 73,
0, 15, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73
};
register int hval = len;
switch (hval)
{
default:
hval += asso_values[(unsigned char)str[4]];
/*FALLTHROUGH*/
case 4:
case 3:
case 2:
hval += asso_values[(unsigned char)str[1]];
/*FALLTHROUGH*/
case 1:
hval += asso_values[(unsigned char)str[0]];
break;
}
return hval;
}
struct stringpool_t
{
char stringpool_str3[sizeof("key")];
char stringpool_str4[sizeof("keys")];
char stringpool_str7[sizeof("augment")];
char stringpool_str9[sizeof("text")];
char stringpool_str10[sizeof("xkb_keymap")];
char stringpool_str11[sizeof("keypad_keys")];
char stringpool_str12[sizeof("xkb_keycodes")];
char stringpool_str13[sizeof("xkb_geometry")];
char stringpool_str14[sizeof("xkb_types")];
char stringpool_str15[sizeof("xkb_compat")];
char stringpool_str17[sizeof("replace")];
char stringpool_str19[sizeof("xkb_compat_map")];
char stringpool_str20[sizeof("xkb_layout")];
char stringpool_str21[sizeof("xkb_symbols")];
char stringpool_str22[sizeof("xkb_compatibility")];
char stringpool_str23[sizeof("xkb_semantics")];
char stringpool_str24[sizeof("type")];
char stringpool_str25[sizeof("alias")];
char stringpool_str26[sizeof("xkb_compatibility_map")];
char stringpool_str27[sizeof("alphanumeric_keys")];
char stringpool_str28[sizeof("function_keys")];
char stringpool_str29[sizeof("alternate")];
char stringpool_str30[sizeof("shape")];
char stringpool_str31[sizeof("action")];
char stringpool_str32[sizeof("section")];
char stringpool_str33[sizeof("row")];
char stringpool_str34[sizeof("logo")];
char stringpool_str35[sizeof("alternate_group")];
char stringpool_str36[sizeof("hidden")];
char stringpool_str37[sizeof("virtual")];
char stringpool_str42[sizeof("outline")];
char stringpool_str43[sizeof("default")];
char stringpool_str46[sizeof("modmap")];
char stringpool_str47[sizeof("virtual_modifiers")];
char stringpool_str52[sizeof("overlay")];
char stringpool_str53[sizeof("override")];
char stringpool_str57[sizeof("include")];
char stringpool_str62[sizeof("modifier_map")];
char stringpool_str63[sizeof("modifier_keys")];
char stringpool_str64[sizeof("indicator")];
char stringpool_str66[sizeof("group")];
char stringpool_str67[sizeof("mod_map")];
char stringpool_str69[sizeof("interpret")];
char stringpool_str71[sizeof("solid")];
char stringpool_str72[sizeof("partial")];
};
static const struct stringpool_t stringpool_contents =
{
"key",
"keys",
"augment",
"text",
"xkb_keymap",
"keypad_keys",
"xkb_keycodes",
"xkb_geometry",
"xkb_types",
"xkb_compat",
"replace",
"xkb_compat_map",
"xkb_layout",
"xkb_symbols",
"xkb_compatibility",
"xkb_semantics",
"type",
"alias",
"xkb_compatibility_map",
"alphanumeric_keys",
"function_keys",
"alternate",
"shape",
"action",
"section",
"row",
"logo",
"alternate_group",
"hidden",
"virtual",
"outline",
"default",
"modmap",
"virtual_modifiers",
"overlay",
"override",
"include",
"modifier_map",
"modifier_keys",
"indicator",
"group",
"mod_map",
"interpret",
"solid",
"partial"
};
#define stringpool ((const char *) &stringpool_contents)
#ifdef __GNUC__
__inline
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
const struct keyword_tok *
keyword_gperf_lookup (register const char *str, register unsigned int len)
{
enum
{
TOTAL_KEYWORDS = 45,
MIN_WORD_LENGTH = 3,
MAX_WORD_LENGTH = 21,
MIN_HASH_VALUE = 3,
MAX_HASH_VALUE = 72
};
static const struct keyword_tok wordlist[] =
{
{-1}, {-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3, KEY},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4, KEYS},
{-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str7, AUGMENT},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str9, TEXT},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str10, XKB_KEYMAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str11, KEYPAD_KEYS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str12, XKB_KEYCODES},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str13, XKB_GEOMETRY},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str14, XKB_TYPES},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str15, XKB_COMPATMAP},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str17, REPLACE},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str19, XKB_COMPATMAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str20, XKB_LAYOUT},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str21, XKB_SYMBOLS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str22, XKB_COMPATMAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str23, XKB_SEMANTICS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str24, TYPE},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str25, ALIAS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str26, XKB_COMPATMAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str27, ALPHANUMERIC_KEYS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str28, FUNCTION_KEYS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str29, ALTERNATE},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str30, SHAPE},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str31, ACTION_TOK},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str32, SECTION},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str33, ROW},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str34, LOGO},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str35, ALTERNATE_GROUP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str36, HIDDEN},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str37, VIRTUAL},
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str42, OUTLINE},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str43, DEFAULT},
{-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str46, MODIFIER_MAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str47, VIRTUAL_MODS},
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str52, OVERLAY},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str53, OVERRIDE},
{-1}, {-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str57, INCLUDE},
{-1}, {-1}, {-1}, {-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str62, MODIFIER_MAP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str63, MODIFIER_KEYS},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str64, INDICATOR},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str66, GROUP},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str67, MODIFIER_MAP},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str69, INTERPRET},
{-1},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str71, SOLID},
{(int)(long)&((struct stringpool_t *)0)->stringpool_str72, PARTIAL}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = keyword_gperf_hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register int o = wordlist[key].name;
if (o >= 0)
{
register const char *s = o + stringpool;
if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s))
return &wordlist[key];
}
}
}
return 0;
}
int
keyword_to_token(const char *string)
{
const struct keyword_tok *kt;
kt = keyword_gperf_lookup(string, strlen(string));
if (!kt)
return -1;
return kt->tok;
}

View File

@ -27,21 +27,24 @@
#ifndef XKBCOMP_PARSER_PRIV_H
#define XKBCOMP_PARSER_PRIV_H
struct scanner_extra;
struct scanner;
struct parser_param;
#pragma GCC diagnostic ignored "-Wredundant-decls"
#pragma GCC diagnostic push
#include "parser.h"
#pragma GCC diagnostic pop
void
scanner_error(YYLTYPE *loc, void *scanner, const char *msg);
int
_xkbcommon_lex(YYSTYPE *val, YYLTYPE *loc, void *scanner);
scanner_error(struct scanner *scanner, const char *msg);
void
scanner_warn(struct scanner *s, const char *msg);
int
_xkbcommon_lex(YYSTYPE *yylval, struct scanner *scanner);
XkbFile *
parse(struct xkb_context *ctx, void *scanner, const char *map);
int
keyword_to_token(const char *string);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -175,16 +175,16 @@ typedef union YYSTYPE
{
/* Line 2068 of yacc.c */
#line 127 "parser.y"
#line 167 "parser.y"
int ival;
unsigned uval;
int64_t num;
enum xkb_file_type file_type;
char *str;
xkb_atom_t sval;
enum merge_mode merge;
enum xkb_map_flags mapFlags;
xkb_keysym_t keysym;
ParseCommon *any;
ExprDef *expr;
VarDef *var;
@ -213,18 +213,4 @@ typedef union YYSTYPE
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
} YYLTYPE;
# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif

View File

@ -47,16 +47,10 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "xkbcomp-priv.h"
#include "rules.h"
#include "include.h"
#include "scanner-utils.h"
/*
* The rules file
@ -138,25 +132,6 @@
/* Scanner / Lexer */
/* Point to some substring in the file; used to avoid copying. */
struct sval {
const char *start;
unsigned int len;
};
typedef darray(struct sval) darray_sval;
static inline bool
svaleq(struct sval s1, struct sval s2)
{
return s1.len == s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
}
static inline bool
svaleq_prefix(struct sval s1, struct sval s2)
{
return s1.len <= s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
}
/* Values returned with some tokens, like yylval. */
union lvalue {
struct sval string;
@ -170,15 +145,6 @@ struct location {
int line, column;
};
struct scanner {
const char *s;
size_t pos;
size_t len;
int line, column;
const char *file_name;
struct xkb_context *ctx;
};
enum rules_token {
TOK_END_OF_FILE = 0,
TOK_END_OF_LINE,
@ -190,81 +156,20 @@ enum rules_token {
TOK_ERROR
};
static void
scanner_init(struct scanner *s, struct xkb_context *ctx,
const char *string, size_t len, const char *file_name)
{
s->s = string;
s->len = len;
s->pos = 0;
s->line = s->column = 1;
s->file_name = file_name;
s->ctx = ctx;
}
/* C99 is stupid. Just use the 1 variant when there are no args. */
#define scanner_error1(scanner, loc, msg) \
log_warn(scanner->ctx, "rules/%s:%d:%d: " msg "\n", \
scanner->file_name, loc->line, loc->column)
log_warn((scanner)->ctx, "rules/%s:%d:%d: %s\n", \
(scanner)->file_name, (loc)->line, (loc)->column, msg)
#define scanner_error(scanner, loc, fmt, ...) \
log_warn(scanner->ctx, "rules/%s:%d:%d: " fmt "\n", \
scanner->file_name, loc->line, loc->column, __VA_ARGS__)
log_warn((scanner)->ctx, "rules/%s:%d:%d: " fmt "\n", \
(scanner)->file_name, (loc)->line, (loc)->column, __VA_ARGS__)
static char
peek(struct scanner *s)
static inline bool
is_ident(char ch)
{
return s->pos < s->len ? s->s[s->pos] : '\0';
return is_graph(ch) && ch != '\\';
}
static bool
eof(struct scanner *s)
{
return peek(s) == '\0';
}
static bool
eol(struct scanner *s)
{
return peek(s) == '\n';
}
static char
next(struct scanner *s)
{
if (eof(s))
return '\0';
if (eol(s)) {
s->line++;
s->column = 1;
}
else {
s->column++;
}
return s->s[s->pos++];
}
static bool
chr(struct scanner *s, char ch)
{
if (peek(s) != ch)
return false;
s->pos++; s->column++;
return true;
}
static bool
str(struct scanner *s, const char *string, size_t len)
{
if (s->len - s->pos < len)
return false;
if (strncasecmp(s->s + s->pos, string, len) != 0)
return false;
s->pos += len; s->column += len;
return true;
}
#define lit(s, literal) str(s, literal, sizeof(literal) - 1)
static enum rules_token
lex(struct scanner *s, union lvalue *val, struct location *loc)
{
@ -310,7 +215,7 @@ skip_more_whitespace_and_comments:
if (chr(s, '$')) {
val->string.start = s->s + s->pos;
val->string.len = 0;
while (isgraph(peek(s))) {
while (is_ident(peek(s))) {
next(s);
val->string.len++;
}
@ -323,10 +228,10 @@ skip_more_whitespace_and_comments:
}
/* Identifier. */
if (isgraph(peek(s))) {
if (is_ident(peek(s))) {
val->string.start = s->s + s->pos;
val->string.len = 0;
while (isgraph(peek(s))) {
while (is_ident(peek(s))) {
next(s);
val->string.len++;
}
@ -440,8 +345,8 @@ struct matcher {
static struct sval
strip_spaces(struct sval v)
{
while (v.len > 0 && isspace(v.start[0])) { v.len--; v.start++; }
while (v.len > 0 && isspace(v.start[v.len - 1])) v.len--;
while (v.len > 0 && is_space(v.start[0])) { v.len--; v.start++; }
while (v.len > 0 && is_space(v.start[v.len - 1])) v.len--;
return v;
}
@ -449,7 +354,6 @@ static darray_sval
split_comma_separated_string(const char *s)
{
darray_sval arr = darray_new();
struct sval val = { NULL, 0 };
/*
* Make sure the array returned by this function always includes at
@ -457,12 +361,13 @@ split_comma_separated_string(const char *s)
*/
if (!s) {
struct sval val = { NULL, 0 };
darray_append(arr, val);
return arr;
}
while (true) {
val.start = s; val.len = 0;
struct sval val = { s, 0 };
while (*s != '\0' && *s != ',') { s++; val.len++; }
darray_append(arr, strip_spaces(val));
if (*s == '\0') break;
@ -482,7 +387,7 @@ matcher_new(struct xkb_context *ctx,
m->ctx = ctx;
m->rmlvo.model.start = rmlvo->model;
m->rmlvo.model.len = rmlvo->model ? strlen(rmlvo->model) : 0;
m->rmlvo.model.len = strlen_safe(rmlvo->model);
m->rmlvo.layouts = split_comma_separated_string(rmlvo->layout);
m->rmlvo.variants = split_comma_separated_string(rmlvo->variant);
m->rmlvo.options = split_comma_separated_string(rmlvo->options);
@ -505,15 +410,10 @@ matcher_free(struct matcher *m)
free(m);
}
/* C99 is stupid. Just use the 1 variant when there are no args. */
#define matcher_error1(matcher, msg) \
log_warn(matcher->ctx, "rules/%s:%d:%d: " msg "\n", \
matcher->scanner.file_name, matcher->loc.line, \
matcher->loc.column)
scanner_error1(&(matcher)->scanner, &(matcher)->loc, msg)
#define matcher_error(matcher, fmt, ...) \
log_warn(matcher->ctx, "rules/%s:%d:%d: " fmt "\n", \
matcher->scanner.file_name, matcher->loc.line, \
matcher->loc.column, __VA_ARGS__)
scanner_error(&(matcher)->scanner, &(matcher)->loc, fmt, __VA_ARGS__)
static void
matcher_group_start_new(struct matcher *m, struct sval name)
@ -532,10 +432,9 @@ matcher_group_add_element(struct matcher *m, struct sval element)
static void
matcher_mapping_start_new(struct matcher *m)
{
unsigned int i;
for (i = 0; i < _MLVO_NUM_ENTRIES; i++)
for (unsigned i = 0; i < _MLVO_NUM_ENTRIES; i++)
m->mapping.mlvo_at_pos[i] = -1;
for (i = 0; i < _KCCGST_NUM_ENTRIES; i++)
for (unsigned i = 0; i < _KCCGST_NUM_ENTRIES; i++)
m->mapping.kccgst_at_pos[i] = -1;
m->mapping.layout_idx = m->mapping.variant_idx = XKB_LAYOUT_INVALID;
m->mapping.num_mlvo = m->mapping.num_kccgst = 0;
@ -551,7 +450,7 @@ extract_layout_index(const char *s, size_t max_len, xkb_layout_index_t *out)
*out = XKB_LAYOUT_INVALID;
if (max_len < 3)
return -1;
if (s[0] != '[' || !isdigit(s[1]) || s[2] != ']')
if (s[0] != '[' || !is_digit(s[1]) || s[2] != ']')
return -1;
if (s[1] - '0' < 1 || s[1] - '0' > XKB_MAX_GROUPS)
return -1;
@ -565,8 +464,6 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident)
{
enum rules_mlvo mlvo;
struct sval mlvo_sval;
xkb_layout_index_t idx;
int consumed;
for (mlvo = 0; mlvo < _MLVO_NUM_ENTRIES; mlvo++) {
mlvo_sval = rules_mlvo_svals[mlvo];
@ -596,8 +493,9 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident)
/* If there are leftovers still, it must be an index. */
if (mlvo_sval.len < ident.len) {
consumed = extract_layout_index(ident.start + mlvo_sval.len,
ident.len - mlvo_sval.len, &idx);
xkb_layout_index_t idx;
int consumed = extract_layout_index(ident.start + mlvo_sval.len,
ident.len - mlvo_sval.len, &idx);
if ((int) (ident.len - mlvo_sval.len) != consumed) {
matcher_error(m,
"invalid mapping:\" %.*s\" may only be followed by a valid group index; "
@ -822,14 +720,8 @@ static bool
append_expanded_kccgst_value(struct matcher *m, darray_char *to,
struct sval value)
{
unsigned int i;
size_t original_size = darray_size(*to);
const size_t original_size = darray_size(*to);
const char *s = value.start;
xkb_layout_index_t idx;
int consumed;
enum rules_mlvo mlv;
struct sval expanded;
char pfx, sfx;
/*
* Appending bar to foo -> foo (not an error if this happens)
@ -847,7 +739,12 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
* Some ugly hand-lexing here, but going through the scanner is more
* trouble than it's worth, and the format is ugly on its own merit.
*/
for (i = 0; i < value.len; ) {
for (unsigned i = 0; i < value.len; ) {
enum rules_mlvo mlv;
xkb_layout_index_t idx;
char pfx, sfx;
struct sval expanded;
/* Check if that's a start of an expansion. */
if (s[i] != '%') {
/* Just a normal character. */
@ -876,22 +773,19 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
/* Check for index. */
idx = XKB_LAYOUT_INVALID;
if (i < value.len) {
if (s[i] == '[') {
if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) {
matcher_error1(m,
"invalid index in %%-expansion; "
"may only index layout or variant");
goto error;
}
if (i < value.len && s[i] == '[') {
int consumed;
consumed = extract_layout_index(s + i, value.len - i, &idx);
if (consumed == -1) goto error;
i += consumed;
}
else {
idx = XKB_LAYOUT_INVALID;
if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) {
matcher_error1(m,
"invalid index in %%-expansion; "
"may only index layout or variant");
goto error;
}
consumed = extract_layout_index(s + i, value.len - i, &idx);
if (consumed == -1) goto error;
i += consumed;
}
/* Check for suffix, if there supposed to be one. */
@ -959,37 +853,31 @@ matcher_rule_verify(struct matcher *m)
static void
matcher_rule_apply_if_matches(struct matcher *m)
{
unsigned int i;
enum rules_mlvo mlvo;
enum rules_kccgst kccgst;
struct sval value, *option;
enum mlvo_match_type match_type;
bool matched = false;
xkb_layout_index_t idx;
for (i = 0; i < m->mapping.num_mlvo; i++) {
mlvo = m->mapping.mlvo_at_pos[i];
value = m->rule.mlvo_value_at_pos[i];
match_type = m->rule.match_type_at_pos[i];
for (unsigned i = 0; i < m->mapping.num_mlvo; i++) {
enum rules_mlvo mlvo = m->mapping.mlvo_at_pos[i];
struct sval value = m->rule.mlvo_value_at_pos[i];
enum mlvo_match_type match_type = m->rule.match_type_at_pos[i];
bool matched = false;
if (mlvo == MLVO_MODEL) {
matched = match_value(m, value, m->rmlvo.model, match_type);
}
else if (mlvo == MLVO_LAYOUT) {
idx = m->mapping.layout_idx;
xkb_layout_index_t idx = m->mapping.layout_idx;
idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx);
matched = match_value(m, value,
darray_item(m->rmlvo.layouts, idx),
match_type);
}
else if (mlvo == MLVO_VARIANT) {
idx = m->mapping.layout_idx;
xkb_layout_index_t idx = m->mapping.layout_idx;
idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx);
matched = match_value(m, value,
darray_item(m->rmlvo.variants, idx),
match_type);
}
else if (mlvo == MLVO_OPTION) {
struct sval *option;
darray_foreach(option, m->rmlvo.options) {
matched = match_value(m, value, *option, match_type);
if (matched)
@ -1001,9 +889,9 @@ matcher_rule_apply_if_matches(struct matcher *m)
return;
}
for (i = 0; i < m->mapping.num_kccgst; i++) {
kccgst = m->mapping.kccgst_at_pos[i];
value = m->rule.kccgst_value_at_pos[i];
for (unsigned i = 0; i < m->mapping.num_kccgst; i++) {
enum rules_kccgst kccgst = m->mapping.kccgst_at_pos[i];
struct sval value = m->rule.kccgst_value_at_pos[i];
append_expanded_kccgst_value(m, &m->kccgst[kccgst], value);
}
@ -1193,36 +1081,27 @@ xkb_components_from_rules(struct xkb_context *ctx,
bool ret = false;
FILE *file;
char *path;
int fd;
struct stat stat_buf;
char *string;
const char *string;
size_t size;
struct matcher *matcher;
file = FindFileInXkbPath(ctx, rmlvo->rules, FILE_TYPE_RULES, &path);
if (!file)
goto err_out;
fd = fileno(file);
if (fstat(fd, &stat_buf) != 0) {
log_err(ctx, "Couldn't stat rules file\n");
goto err_file;
}
string = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (string == MAP_FAILED) {
log_err(ctx, "Couldn't mmap rules file (%lld bytes)\n",
(long long) stat_buf.st_size);
ret = map_file(file, &string, &size);
if (!ret) {
log_err(ctx, "Couldn't read rules file: %s\n", strerror(errno));
goto err_file;
}
matcher = matcher_new(ctx, rmlvo);
ret = matcher_match(matcher, string, stat_buf.st_size, rmlvo->rules, out);
ret = matcher_match(matcher, string, size, rmlvo->rules, out);
if (!ret)
log_err(ctx, "No components returned from XKB rules \"%s\"\n", path);
matcher_free(matcher);
munmap(string, stat_buf.st_size);
unmap_file(string, size);
err_file:
free(path);
fclose(file);

View File

@ -0,0 +1,145 @@
/*
* Copyright © 2012 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.
*/
#ifndef XKBCOMP_SCANNER_UTILS_H
#define XKBCOMP_SCANNER_UTILS_H
/* Point to some substring in the file; used to avoid copying. */
struct sval {
const char *start;
unsigned int len;
};
typedef darray(struct sval) darray_sval;
static inline bool
svaleq(struct sval s1, struct sval s2)
{
return s1.len == s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
}
static inline bool
svaleq_prefix(struct sval s1, struct sval s2)
{
return s1.len <= s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
}
struct scanner {
const char *s;
size_t pos;
size_t len;
char buf[1024];
size_t buf_pos;
int line, column;
/* The line/column of the start of the current token. */
int token_line, token_column;
const char *file_name;
struct xkb_context *ctx;
};
static inline void
scanner_init(struct scanner *s, struct xkb_context *ctx,
const char *string, size_t len, const char *file_name)
{
s->s = string;
s->len = len;
s->pos = 0;
s->line = s->column = 1;
s->token_line = s->token_column = 1;
s->file_name = file_name;
s->ctx = ctx;
}
static inline char
peek(struct scanner *s)
{
return s->pos < s->len ? s->s[s->pos] : '\0';
}
static inline bool
eof(struct scanner *s)
{
return s->pos >= s->len;
}
static inline bool
eol(struct scanner *s)
{
return peek(s) == '\n';
}
static inline char
next(struct scanner *s)
{
if (eof(s))
return '\0';
if (eol(s)) {
s->line++;
s->column = 1;
}
else {
s->column++;
}
return s->s[s->pos++];
}
static inline bool
chr(struct scanner *s, char ch)
{
if (peek(s) != ch)
return false;
s->pos++; s->column++;
return true;
}
static inline bool
str(struct scanner *s, const char *string, size_t len)
{
if (s->len - s->pos < len)
return false;
if (strncasecmp(s->s + s->pos, string, len) != 0)
return false;
s->pos += len; s->column += len;
return true;
}
#define lit(s, literal) str(s, literal, sizeof(literal) - 1)
static inline bool
buf_append(struct scanner *s, char ch)
{
if (s->buf_pos + 1 >= sizeof(s->buf))
return false;
s->buf[s->buf_pos++] = ch;
return true;
}
static inline bool
oct(struct scanner *s, uint8_t *out)
{
int i;
for (i = 0, *out = 0; peek(s) >= '0' && peek(s) <= '7' && i < 3; i++)
*out = *out * 8 + next(s) - '0';
return i > 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -143,7 +143,7 @@ InitKeyInfo(struct xkb_context *ctx, KeyInfo *keyi)
{
memset(keyi, 0, sizeof(*keyi));
keyi->merge = MERGE_OVERRIDE;
keyi->name = xkb_atom_intern(ctx, "*");
keyi->name = xkb_atom_intern_literal(ctx, "*");
keyi->out_of_range_group_action = RANGE_WRAP;
}
@ -177,7 +177,7 @@ typedef struct {
KeyInfo default_key;
ActionsInfo *actions;
darray(xkb_atom_t) group_names;
darray(ModMapEntry) modMaps;
darray(ModMapEntry) modmaps;
struct xkb_keymap *keymap;
} SymbolsInfo;
@ -203,7 +203,7 @@ ClearSymbolsInfo(SymbolsInfo *info)
ClearKeyInfo(keyi);
darray_free(info->keys);
darray_free(info->group_names);
darray_free(info->modMaps);
darray_free(info->modmaps);
ClearKeyInfo(&info->default_key);
}
@ -437,7 +437,7 @@ AddModMapEntry(SymbolsInfo *info, ModMapEntry *new)
ModMapEntry *old;
bool clobber = (new->merge != MERGE_AUGMENT);
darray_foreach(old, info->modMaps) {
darray_foreach(old, info->modmaps) {
xkb_mod_index_t use, ignore;
if ((new->haveSymbol != old->haveSymbol) ||
@ -470,7 +470,7 @@ AddModMapEntry(SymbolsInfo *info, ModMapEntry *new)
return true;
}
darray_append(info->modMaps, *new);
darray_append(info->modmaps, *new);
return true;
}
@ -517,7 +517,7 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
into->errorCount++;
}
darray_foreach(mm, from->modMaps) {
darray_foreach(mm, from->modmaps) {
mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
if (!AddModMapEntry(into, mm))
into->errorCount++;
@ -626,30 +626,6 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return true;
}
bool
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn)
{
xkb_keysym_t sym;
if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
*sym_rtrn = XKB_KEY_NoSymbol;
return 1;
}
if (istreq(str, "none") || istreq(str, "voidsymbol")) {
*sym_rtrn = XKB_KEY_VoidSymbol;
return 1;
}
sym = xkb_keysym_from_name(str, 0);
if (sym != XKB_KEY_NoSymbol) {
*sym_rtrn = sym;
return 1;
}
return 0;
}
static bool
AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
ExprDef *value)
@ -670,11 +646,11 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return true;
}
if (value->op != EXPR_KEYSYM_LIST) {
if (value->expr.op != EXPR_KEYSYM_LIST) {
log_err(info->keymap->ctx,
"Expected a list of symbols, found %s; "
"Ignoring symbols for group %u of %s\n",
expr_op_type_to_string(value->op), ndx + 1,
expr_op_type_to_string(value->expr.op), ndx + 1,
KeyInfoText(info, keyi));
return false;
}
@ -687,7 +663,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return false;
}
nLevels = darray_size(value->value.list.symsMapIndex);
nLevels = darray_size(value->keysym_list.symsMapIndex);
if (darray_size(groupi->levels) < nLevels)
darray_resize0(groupi->levels, nLevels);
@ -697,34 +673,14 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
unsigned int sym_index;
struct xkb_level *leveli = &darray_item(groupi->levels, i);
sym_index = darray_item(value->value.list.symsMapIndex, i);
leveli->num_syms = darray_item(value->value.list.symsNumEntries, i);
sym_index = darray_item(value->keysym_list.symsMapIndex, i);
leveli->num_syms = darray_item(value->keysym_list.symsNumEntries, i);
if (leveli->num_syms > 1)
leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms));
for (j = 0; j < leveli->num_syms; j++) {
char *sym_name = darray_item(value->value.list.syms,
sym_index + j);
xkb_keysym_t keysym;
if (!LookupKeysym(sym_name, &keysym)) {
const char *group_name = "unnamed";
if (ndx < darray_size(info->group_names) &&
darray_item(info->group_names, ndx))
group_name = xkb_atom_text(info->keymap->ctx,
darray_item(info->group_names,
ndx));
log_warn(info->keymap->ctx,
"Could not resolve keysym %s for key %s, group %u (%s), level %u\n",
sym_name, KeyInfoText(info, keyi), ndx + 1,
group_name, i);
ClearLevelInfo(leveli);
leveli->num_syms = 0;
break;
}
xkb_keysym_t keysym = darray_item(value->keysym_list.syms,
sym_index + j);
if (leveli->num_syms == 1) {
if (keysym == XKB_KEY_NoSymbol)
@ -750,7 +706,6 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
GroupInfo *groupi;
unsigned int nActs;
ExprDef *act;
union xkb_action *toAct;
if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx))
return false;
@ -762,11 +717,11 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return true;
}
if (value->op != EXPR_ACTION_LIST) {
if (value->expr.op != EXPR_ACTION_LIST) {
log_wsgo(info->keymap->ctx,
"Bad expression type (%d) for action list value; "
"Ignoring actions for group %u of %s\n",
value->op, ndx, KeyInfoText(info, keyi));
value->expr.op, ndx, KeyInfoText(info, keyi));
return false;
}
@ -778,7 +733,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
nActs = 0;
for (act = value->value.child; act; act = (ExprDef *) act->common.next)
for (act = value->unary.child; act; act = (ExprDef *) act->common.next)
nActs++;
if (darray_size(groupi->levels) < nActs)
@ -786,9 +741,9 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
groupi->defined |= GROUP_FIELD_ACTS;
act = value->value.child;
act = value->unary.child;
for (i = 0; i < nActs; i++) {
toAct = &darray_item(groupi->levels, i).action;
union xkb_action *toAct = &darray_item(groupi->levels, i).action;
if (!HandleActionDef(act, info->keymap, toAct, info->actions))
log_err(info->keymap->ctx,
@ -866,7 +821,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
log_err(info->keymap->ctx,
"Expected a virtual modifier mask, found %s; "
"Ignoring virtual modifiers definition for key %s\n",
expr_op_type_to_string(value->op),
expr_op_type_to_string(value->expr.op),
KeyInfoText(info, keyi));
}
}
@ -1082,7 +1037,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
ExprDef *arrayNdx;
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->op == EXPR_FIELD_REF) {
if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
log_err(info->keymap->ctx,
"Cannot set a global default value from within a key statement; "
"Move statements to the global file scope\n");
@ -1090,7 +1045,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
}
if (!def->name) {
if (!def->value || def->value->op == EXPR_KEYSYM_LIST)
if (!def->value || def->value->expr.op == EXPR_KEYSYM_LIST)
field = "symbols";
else
field = "actions";
@ -1158,7 +1113,7 @@ HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
keyi.merge = stmt->merge;
keyi.name = stmt->keyName;
if (!HandleSymbolsBody(info, (VarDef *) stmt->symbols, &keyi)) {
if (!HandleSymbolsBody(info, stmt->symbols, &keyi)) {
info->errorCount++;
return false;
}
@ -1196,13 +1151,15 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
ok = true;
tmp.modifier = ndx;
tmp.merge = def->merge;
for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
xkb_keysym_t sym;
if (key->op == EXPR_VALUE && key->value_type == EXPR_TYPE_KEYNAME) {
if (key->expr.op == EXPR_VALUE &&
key->expr.value_type == EXPR_TYPE_KEYNAME) {
tmp.haveSymbol = false;
tmp.u.keyName = key->value.keyName;
tmp.u.keyName = key->key_name.key_name;
}
else if (ExprResolveKeySym(ctx, key, &sym)) {
tmp.haveSymbol = true;
@ -1248,7 +1205,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
break;
default:
log_err(info->keymap->ctx,
"Interpretation files may not include other types; "
"Symbols files may not include other types; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
break;
@ -1339,19 +1296,19 @@ FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
darray_item(groupi->levels, level).u.syms[0])
if (width == 1 || width <= 0)
return xkb_atom_intern(ctx, "ONE_LEVEL");
return xkb_atom_intern_literal(ctx, "ONE_LEVEL");
sym0 = GET_SYM(0);
sym1 = GET_SYM(1);
if (width == 2) {
if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1))
return xkb_atom_intern(ctx, "ALPHABETIC");
return xkb_atom_intern_literal(ctx, "ALPHABETIC");
if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
return xkb_atom_intern(ctx, "KEYPAD");
return xkb_atom_intern_literal(ctx, "KEYPAD");
return xkb_atom_intern(ctx, "TWO_LEVEL");
return xkb_atom_intern_literal(ctx, "TWO_LEVEL");
}
if (width <= 4) {
@ -1360,15 +1317,15 @@ FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol);
if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper(sym3))
return xkb_atom_intern(ctx, "FOUR_LEVEL_ALPHABETIC");
return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC");
return xkb_atom_intern(ctx, "FOUR_LEVEL_SEMIALPHABETIC");
return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC");
}
if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
return xkb_atom_intern(ctx, "FOUR_LEVEL_KEYPAD");
return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD");
return xkb_atom_intern(ctx, "FOUR_LEVEL");
return xkb_atom_intern_literal(ctx, "FOUR_LEVEL");
}
return XKB_ATOM_NONE;
@ -1570,9 +1527,9 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
{
KeyInfo *keyi;
ModMapEntry *mm;
struct xkb_key *key;
keymap->symbols_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->symbols_section_name);
keymap->num_group_names = darray_size(info->group_names);
keymap->group_names = darray_mem(info->group_names, 0);
@ -1583,6 +1540,8 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
info->errorCount++;
if (xkb_context_get_log_verbosity(keymap->ctx) > 3) {
struct xkb_key *key;
xkb_foreach_key(key, keymap) {
if (key->name == XKB_ATOM_NONE)
continue;
@ -1594,7 +1553,7 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
}
}
darray_foreach(mm, info->modMaps)
darray_foreach(mm, info->modmaps)
if (!CopyModMapDef(info, mm))
info->errorCount++;
@ -1618,9 +1577,6 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
HandleSymbolsFile(&info, file, merge);
if (darray_empty(info.keys))
goto err_info;
if (info.errorCount != 0)
goto err_info;

View File

@ -197,16 +197,6 @@ ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
TypeTxt(info, type), wanted);
}
static inline bool
ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
{
log_err(info->keymap->ctx,
"Key type \"%s\" has %d levels, must have %d; "
"Illegal type definition ignored\n",
type, has, needs);
return false;
}
/***====================================================================***/
static void
@ -775,6 +765,7 @@ static bool
CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info)
{
keymap->types_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->types_section_name);
keymap->num_types = darray_size(info->types);
if (keymap->num_types == 0)
@ -793,7 +784,7 @@ CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info)
type->num_levels = 1;
type->entries = NULL;
type->num_entries = 0;
type->name = xkb_atom_intern(keymap->ctx, "default");
type->name = xkb_atom_intern_literal(keymap->ctx, "default");
type->level_names = NULL;
return true;

View File

@ -45,12 +45,9 @@ XkbParseFile(struct xkb_context *ctx, FILE *file,
const char *file_name, const char *map);
XkbFile *
XkbParseString(struct xkb_context *ctx, const char *string,
const char *file_name);
XkbFile *
XkbParseBuffer(struct xkb_context *ctx, char *buf, size_t length,
const char *file_name);
XkbParseString(struct xkb_context *ctx,
const char *string, size_t len,
const char *file_name, const char *map);
void
FreeXkbFile(XkbFile *file);
@ -79,9 +76,6 @@ bool
CompileKeymap(XkbFile *file, struct xkb_keymap *keymap,
enum merge_mode merge);
bool
LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn);
/***====================================================================***/
static inline bool

View File

@ -97,12 +97,13 @@ text_v1_keymap_new_from_names(struct xkb_keymap *keymap,
}
static bool
text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string)
text_v1_keymap_new_from_string(struct xkb_keymap *keymap,
const char *string, size_t len)
{
bool ok;
XkbFile *xkb_file;
xkb_file = XkbParseString(keymap->ctx, string, "(input string)");
xkb_file = XkbParseString(keymap->ctx, string, len, "(input string)", NULL);
if (!xkb_file) {
log_err(keymap->ctx, "Failed to parse input xkb string\n");
return NULL;
@ -113,38 +114,6 @@ text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string)
return ok;
}
static bool
text_v1_keymap_new_from_buffer(struct xkb_keymap *keymap,
const char *buffer, size_t length)
{
bool ok;
XkbFile *xkb_file;
char *buf;
buf = malloc(length + 2);
if (!buf) {
log_err(keymap->ctx, "Cannot allocate memory for keymap\n");
return NULL;
}
/* yy_scan_buffer requires two terminating zero bytes */
memcpy(buf, buffer, length);
buf[length] = 0;
buf[length + 1] = 0;
xkb_file = XkbParseBuffer(keymap->ctx, buf, length + 2, "input");
if (!xkb_file) {
log_err(keymap->ctx, "Failed to parse input xkb file\n");
free(buf);
return NULL;
}
ok = compile_keymap_file(keymap, xkb_file);
FreeXkbFile(xkb_file);
free(buf);
return ok;
}
static bool
text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file)
{
@ -165,7 +134,6 @@ text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file)
const struct xkb_keymap_format_ops text_v1_keymap_format_ops = {
.keymap_new_from_names = text_v1_keymap_new_from_names,
.keymap_new_from_string = text_v1_keymap_new_from_string,
.keymap_new_from_buffer = text_v1_keymap_new_from_buffer,
.keymap_new_from_file = text_v1_keymap_new_from_file,
.keymap_get_as_string = text_v1_keymap_get_as_string,
};

View File

@ -418,6 +418,12 @@ SOFTWARE.
#define XKB_KEY_dead_belowcomma 0xfe6e
#define XKB_KEY_dead_currency 0xfe6f
/* extra dead elements for German T3 layout */
#define XKB_KEY_dead_lowline 0xfe90
#define XKB_KEY_dead_aboveverticalline 0xfe91
#define XKB_KEY_dead_belowverticalline 0xfe92
#define XKB_KEY_dead_longsolidusoverlay 0xfe93
/* dead vowels for universal syllable entry */
#define XKB_KEY_dead_a 0xfe80
#define XKB_KEY_dead_A 0xfe81
@ -2652,6 +2658,8 @@ SOFTWARE.
#define XKB_KEY_XF86TouchpadOn 0x1008FFB0 /* The touchpad got switched on */
#define XKB_KEY_XF86TouchpadOff 0x1008FFB1 /* The touchpad got switched off */
#define XKB_KEY_XF86AudioMicMute 0x1008FFB2 /* Mute the Mic from the system */
/* Keys for special action keys (hot keys) */
/* Virtual terminals on some operating systems */
#define XKB_KEY_XF86Switch_VT_1 0x1008FE01

View File

@ -35,6 +35,7 @@
#define XKB_MOD_NAME_CAPS "Lock"
#define XKB_MOD_NAME_CTRL "Control"
#define XKB_MOD_NAME_ALT "Mod1"
#define XKB_MOD_NAME_NUM "Mod2"
#define XKB_MOD_NAME_LOGO "Mod4"
#define XKB_LED_NAME_CAPS "Caps Lock"

View File

@ -0,0 +1,166 @@
/*
* Copyright © 2013 Ran Benita
*
* 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.
*/
#ifndef _XKBCOMMON_X11_H
#define _XKBCOMMON_X11_H
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
/**
* @file
* libxkbcommon-x11 API - Additional X11 support for xkbcommon.
*/
/**
* @defgroup x11 X11 support
* Additional X11 support for xkbcommon.
*
* @{
*/
/**
* The minimal compatible major version of the XKB X11 extension which
* this library can use.
*/
#define XKB_X11_MIN_MAJOR_XKB_VERSION 1
/**
* The minimal compatible minor version of the XKB X11 extension which
* this library can use (for the minimal major version).
*/
#define XKB_X11_MIN_MINOR_XKB_VERSION 0
/** Flags for the xkb_x11_setup_xkb_extension() function. */
enum xkb_x11_setup_xkb_extension_flags {
/** Do not apply any flags. */
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0
};
/**
* Setup the XKB X11 extension for this X client.
*
* The xkbcommon-x11 library uses various XKB requests. Before doing so,
* an X client must notify the server that it will be using the extension.
* This function (or an XCB equivalent) must be called before any other
* function in this library is used.
*
* Some X servers may not support or disable the XKB extension. If you
* want to support such servers, you need to use a different fallback.
*
* You may call this function several times; it is idempotent.
*
* @param connection
* An XCB connection to the X server.
* @param major_xkb_version, minor_xkb_version
* The XKB extension version to request. To operate correctly, you
* must have (major_xkb_version, minor_xkb_version) >=
* (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION),
* though this is not enforced.
* @param flags
* Optional flags, or 0.
* @param[out] major_xkb_version_out, minor_xkb_version_out
* Backfilled with the compatible XKB extension version numbers picked
* by the server. Can be NULL.
* @param[out] base_event_out
* Backfilled with the XKB base (also known as first) event code, needed
* to distinguish XKB events. Can be NULL.
* @param[out] base_error_out
* Backfilled with the XKB base (also known as first) error code, needed
* to distinguish XKB errors. Can be NULL.
*
* @returns 1 on success, or 0 on failure.
*/
int
xkb_x11_setup_xkb_extension(xcb_connection_t *connection,
uint16_t major_xkb_version,
uint16_t minor_xkb_version,
enum xkb_x11_setup_xkb_extension_flags flags,
uint16_t *major_xkb_version_out,
uint16_t *minor_xkb_version_out,
uint8_t *base_event_out,
uint8_t *base_error_out);
/**
* Get the keyboard device ID of the core X11 keyboard.
*
* @param connection An XCB connection to the X server.
*
* @returns A device ID which may be used with other xkb_x11_* functions,
* or -1 on failure.
*/
int32_t
xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection);
/**
* Create a keymap from an X11 keyboard device.
*
* This function queries the X server with various requests, fetches the
* details of the active keymap on a keyboard device, and creates an
* xkb_keymap from these details.
*
* @param context
* The context in which to create the keymap.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
* @param flags
* Optional flags for the keymap, or 0.
*
* @returns A keymap retrieved from the X server, or NULL on failure.
*
* @memberof xkb_keymap
*/
struct xkb_keymap *
xkb_x11_keymap_new_from_device(struct xkb_context *context,
xcb_connection_t *connection,
int32_t device_id,
enum xkb_keymap_compile_flags flags);
/**
* Create a new keyboard state object from an X11 keyboard device.
*
* This function is the same as xkb_state_new(), only pre-initialized
* with the state of the device at the time this function is called.
*
* @param keymap
* The keymap for which to create the state.
* @param connection
* An XCB connection to the X server.
* @param device_id
* An XInput 1 device ID (in the range 0-255) with input class KEY.
* Passing values outside of this range is an error.
*
* @returns A new keyboard state object, or NULL on failure.
*
* @memberof xkb_state
*/
struct xkb_state *
xkb_x11_state_new_from_device(struct xkb_keymap *keymap,
xcb_connection_t *connection,
int32_t device_id);
/** @} */
#endif

View File

@ -197,7 +197,7 @@ typedef uint32_t xkb_keysym_t;
* layout</em> is active. These may be different alphabets, different key
* arrangements, etc.
*
* Layout indexes are consecutive. The first layout has index 0.
* Layout indices are consecutive. The first layout has index 0.
*
* Each layout is not required to have a name, and the names are not
* guaranteed to be unique (though they are usually provided and unique).
@ -209,13 +209,20 @@ typedef uint32_t xkb_keysym_t;
* @sa xkb_keymap_num_layouts() xkb_keymap_num_layouts_for_key()
*/
typedef uint32_t xkb_layout_index_t;
/** A mask of layout indexes. */
/** A mask of layout indices. */
typedef uint32_t xkb_layout_mask_t;
/**
* Index of a shift level.
*
* @todo Explain what are shift levels.
* Any key, in any layout, can have several <em>shift levels</em>. Each
* shift level can assign different keysyms to the key. The shift level
* to use is chosen according to the current keyboard state; for example,
* if no keys are pressed, the first level may be used; if the Left Shift
* key is pressed, the second; if Num Lock is pressed, the third; and
* many such combinations are possible (see xkb_mod_index_t).
*
* Level indices are consecutive. The first level has index 0.
*/
typedef uint32_t xkb_level_index_t;
@ -233,7 +240,7 @@ typedef uint32_t xkb_level_index_t;
* consulted; this detemines the correct shift level to use within the
* currently active layout (see xkb_level_index_t).
*
* Modifier indexes are consecutive. The first modifier has index 0.
* Modifier indices are consecutive. The first modifier has index 0.
*
* Each modifier must have a name, and the names are unique. Therefore, it
* is safe to use the name as a unique identifier for a modifier. The names
@ -243,15 +250,17 @@ typedef uint32_t xkb_level_index_t;
* @sa xkb_keymap_num_mods()
*/
typedef uint32_t xkb_mod_index_t;
/** A mask of modifier indexes. */
/** A mask of modifier indices. */
typedef uint32_t xkb_mod_mask_t;
/**
* Index of a keyboard LED.
*
* @todo Explain what are LEDs.
* LEDs are logical objects which may be @e active or @e inactive. They
* typically correspond to the lights on the keyboard. Their state is
* determined by the current keyboard state.
*
* LED indexes are non-consecutive. The first LED has index 0.
* LED indices are non-consecutive. The first LED has index 0.
*
* Each LED must have a name, and the names are unique. Therefore,
* it is safe to use the name as a unique identifier for a LED. The names
@ -261,7 +270,7 @@ typedef uint32_t xkb_mod_mask_t;
* @warning A given keymap may specify an exact index for a given LED.
* Therefore, LED indexing is not necessarily sequential, as opposed to
* modifiers and layouts. This means that when iterating over the LEDs
* in a keymap using e.g. xkb_keymap_num_leds(), some indexes might be
* in a keymap using e.g. xkb_keymap_num_leds(), some indices might be
* invalid. Given such an index, functions like xkb_keymap_led_get_name()
* will return NULL, and xkb_state_led_index_is_active() will return -1.
*
@ -270,7 +279,7 @@ typedef uint32_t xkb_mod_mask_t;
* @sa xkb_keymap_num_leds()
*/
typedef uint32_t xkb_led_index_t;
/** A mask of LED indexes. */
/** A mask of LED indices. */
typedef uint32_t xkb_led_mask_t;
#define XKB_KEYCODE_INVALID (0xffffffff)
@ -351,6 +360,8 @@ xkb_keysym_get_name(xkb_keysym_t keysym, char *buffer, size_t size);
/** Flags for xkb_keysym_from_name(). */
enum xkb_keysym_flags {
/** Do not apply any flags. */
XKB_KEYSYM_NO_FLAGS = 0,
/** Find keysym by case-insensitive search. */
XKB_KEYSYM_CASE_INSENSITIVE = (1 << 0)
};
@ -416,6 +427,8 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym);
/** Flags for context creation. */
enum xkb_context_flags {
/** Do not apply any context flags. */
XKB_CONTEXT_NO_FLAGS = 0,
/** Create this context with an empty include path. */
XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
/** Don't take RMLVO names from the environment. */
@ -667,6 +680,8 @@ xkb_context_set_log_fn(struct xkb_context *context,
/** Flags for keymap compilation. */
enum xkb_keymap_compile_flags {
/** Do not apply any flags. */
XKB_MAP_COMPILE_NO_FLAGS = 0,
/** Apparently you can't have empty enums. What a drag. */
XKB_MAP_COMPILE_PLACEHOLDER = 0
};
@ -811,6 +826,46 @@ xkb_keymap_get_as_string(struct xkb_keymap *keymap,
* @{
*/
/**
* Get the minimum keycode in the keymap.
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
*/
xkb_keycode_t
xkb_keymap_min_keycode(struct xkb_keymap *keymap);
/**
* Get the maximum keycode in the keymap.
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
*/
xkb_keycode_t
xkb_keymap_max_keycode(struct xkb_keymap *keymap);
/**
* The iterator used by xkb_keymap_key_for_each().
*
* @sa xkb_keymap_key_for_each
* @memberof xkb_keymap
*/
typedef void
(*xkb_keymap_key_iter_t)(struct xkb_keymap *keymap, xkb_keycode_t key,
void *data);
/**
* Run a specified function for every valid keycode in the keymap. If a
* keymap is sparse, this function may be called fewer than
* (max_keycode - min_keycode + 1) times.
*
* @sa xkb_keymap_min_keycode() xkb_keymap_max_keycode() xkb_keycode_t
* @memberof xkb_keymap
*/
void
xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
void *data);
/**
* Get the number of modifiers in the keymap.
*
@ -1001,9 +1056,9 @@ xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t key);
*/
/**
* Create a new keyboard state object for a keymap.
* Create a new keyboard state object.
*
* @param keymap The keymap for which to create the state.
* @param keymap The keymap which the state will use.
*
* @returns A new keyboard state object, or NULL on failure.
*
@ -1033,10 +1088,10 @@ void
xkb_state_unref(struct xkb_state *state);
/**
* Get the keymap from which a keyboard state object was created.
* Get the keymap which a keyboard state object is using.
*
* @returns The keymap which was used in xkb_state_new() to create this
* state object.
* @returns The keymap which was passed to xkb_state_new() when creating
* this state object.
*
* This function does not take a new reference on the keymap; you must
* explicitly reference it yourself if you plan to use it beyond the
@ -1070,7 +1125,8 @@ enum xkb_state_component {
* lock has been pressed again. */
XKB_STATE_MODS_LOCKED = (1 << 2),
/** Effective modifiers, i.e. currently active and affect key
* processing (derived from the other state components). */
* processing (derived from the other state components).
* Use this unless you explictly care how the state came about. */
XKB_STATE_MODS_EFFECTIVE = (1 << 3),
/** Depressed layout, i.e. a key is physically holding it. */
XKB_STATE_LAYOUT_DEPRESSED = (1 << 4),
@ -1081,7 +1137,8 @@ enum xkb_state_component {
* has been pressed again. */
XKB_STATE_LAYOUT_LOCKED = (1 << 6),
/** Effective layout, i.e. currently active and affects key processing
* (derived from the other state components). */
* (derived from the other state components).
* Use this unless you explictly care how the state came about. */
XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7),
/** LEDs (derived from the other state components). */
XKB_STATE_LEDS = (1 << 8)
@ -1091,15 +1148,64 @@ enum xkb_state_component {
* Update the keyboard state to reflect a given key being pressed or
* released.
*
* This entry point is intended for programs which track the keyboard state
* explictly (like an evdev client). If the state is serialized to you by
* a master process (like a Wayland compositor) using functions like
* xkb_state_serialize_mods(), you should use xkb_state_update_mask() instead.
* The two functins should not generally be used together.
*
* A series of calls to this function should be consistent; that is, a call
* with XKB_KEY_DOWN for a key should be matched by an XKB_KEY_UP; if a key
* is pressed twice, it should be released twice; etc. Otherwise (e.g. due
* to missed input events), situations like "stuck modifiers" may occur.
*
* @returns A mask of state components that have changed as a result of
* the update. If nothing in the state has changed, returns 0.
*
* @memberof xkb_state
*
* @sa xkb_state_update_mask()
*/
enum xkb_state_component
xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key,
enum xkb_key_direction direction);
/**
* Update a keyboard state from a set of explicit masks.
*
* This entry point is intended for window systems and the like, where a
* master process holds an xkb_state, then serializes it over a wire
* protocol, and clients then use the serialization to feed in to their own
* xkb_state.
*
* All parameters must always be passed, or the resulting state may be
* incoherent.
*
* The serialization is lossy and will not survive round trips; it must only
* be used to feed slave state objects, and must not be used to update the
* master state.
*
* If you do not fit the description above, you should use
* xkb_state_update_key() instead. The two functions should not generally be
* used together.
*
* @returns A mask of state components that have changed as a result of
* the update. If nothing in the state has changed, returns 0.
*
* @memberof xkb_state
*
* @sa xkb_state_component
* @sa xkb_state_update_key
*/
enum xkb_state_component
xkb_state_update_mask(struct xkb_state *state,
xkb_mod_mask_t depressed_mods,
xkb_mod_mask_t latched_mods,
xkb_mod_mask_t locked_mods,
xkb_layout_index_t depressed_layout,
xkb_layout_index_t latched_layout,
xkb_layout_index_t locked_layout);
/**
* Get the keysyms obtained from pressing a particular key in a given
* keyboard state.
@ -1114,8 +1220,9 @@ xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key,
* key in the given keyboard state.
*
* As an extension to XKB, this function can return more than one keysym.
* If you do not want to handle this case, you can use
* xkb_state_key_get_one_sym().
* If you do not want to handle this case, you should use
* xkb_state_key_get_one_sym(), which additionally performs transformations
* which are specific to the one-keysym case.
*
* @returns The number of keysyms in the syms_out array. If no keysyms
* are produced by the key in the given keyboard state, returns 0 and sets
@ -1131,9 +1238,10 @@ xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key,
* Get the single keysym obtained from pressing a particular key in a
* given keyboard state.
*
* This function is similar to xkb_state_key_get_syms(), but with a
* simplified interface for users which cannot or do not want to handle
* the case where multiple keysyms are returned.
* This function is similar to xkb_state_key_get_syms(), but intended
* for users which cannot or do not want to handle the case where
* multiple keysyms are returned (in which case this function is
* preferred).
*
* @returns The keysym. If the key does not have exactly one keysym,
* returns XKB_KEY_NoSymbol
@ -1203,39 +1311,6 @@ enum xkb_state_match {
XKB_STATE_MATCH_NON_EXCLUSIVE = (1 << 16)
};
/**
* Update a keyboard state from a set of explicit masks.
*
* This entry point is really only for window systems and the like, where a
* master process holds an xkb_state, then serializes it over a wire
* protocol, and clients then use the serialization to feed in to their own
* xkb_state.
*
* All parameters must always be passed, or the resulting state may be
* incoherent.
*
* The serialization is lossy and will not survive round trips; it must only
* be used to feed slave state objects, and must not be used to update the
* master state.
*
* Please do not use this unless you fit the description above.
*
* @returns A mask of state components that have changed as a result of
* the update. If nothing in the state has changed, returns 0.
*
* @memberof xkb_state
*
* @sa xkb_state_component
*/
enum xkb_state_component
xkb_state_update_mask(struct xkb_state *state,
xkb_mod_mask_t depressed_mods,
xkb_mod_mask_t latched_mods,
xkb_mod_mask_t locked_mods,
xkb_layout_index_t depressed_layout,
xkb_layout_index_t latched_layout,
xkb_layout_index_t locked_layout);
/**
* The counterpart to xkb_state_update_mask for modifiers, to be used on
* the server side of serialization.
@ -1336,11 +1411,11 @@ xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx,
* given modifiers.
* @param match The manner by which to match the state against the
* given modifiers.
* @param ... The set of of modifier indexes to test, terminated by a
* @param ... The set of of modifier indices to test, terminated by a
* XKB_MOD_INVALID argument (sentinel).
*
* @returns 1 if the modifiers are active, 0 if they are not. If any of
* the modifier indexes are invalid in the keymap, returns -1.
* the modifier indices are invalid in the keymap, returns -1.
*
* @memberof xkb_state
*/

View File

@ -1,105 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef XKBCOMMON_WORKAROUND_H
#define XKBCOMMON_WORKAROUND_H
// Function utf32_to_utf8() is borrowed from the libxkbcommon library,
// file keysym-utf.c. The workaround should be removed once the fix from
// https://bugs.freedesktop.org/show_bug.cgi?id=56780 gets released.
static int utf32_to_utf8(uint32_t unichar, char *buffer)
{
int count, shift, length;
uint8_t head;
if (unichar <= 0x007f) {
buffer[0] = unichar;
buffer[1] = '\0';
return 2;
}
else if (unichar <= 0x07FF) {
length = 2;
head = 0xc0;
}
else if (unichar <= 0xffff) {
length = 3;
head = 0xe0;
}
else if (unichar <= 0x1fffff) {
length = 4;
head = 0xf0;
}
else if (unichar <= 0x3ffffff) {
length = 5;
head = 0xf8;
}
else {
length = 6;
head = 0xfc;
}
for (count = length - 1, shift = 0; count > 0; count--, shift += 6)
buffer[count] = 0x80 | ((unichar >> shift) & 0x3f);
buffer[0] = head | ((unichar >> shift) & 0x3f);
buffer[length] = '\0';
return length + 1;
}
static bool needWorkaround(uint32_t sym)
{
/* patch encoding botch */
if (sym == XKB_KEY_KP_Space)
return true;
/* special keysyms */
if ((sym >= XKB_KEY_BackSpace && sym <= XKB_KEY_Clear) ||
(sym >= XKB_KEY_KP_Multiply && sym <= XKB_KEY_KP_9) ||
sym == XKB_KEY_Return || sym == XKB_KEY_Escape ||
sym == XKB_KEY_Delete || sym == XKB_KEY_KP_Tab ||
sym == XKB_KEY_KP_Enter || sym == XKB_KEY_KP_Equal)
return true;
return false;
}
#endif // XKBCOMMON_WORKAROUND_H

View File

@ -6,8 +6,6 @@ load(qt_plugin)
QT += gui-private
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
DEFINES += X11_PREFIX='\\"$$QMAKE_X11_PREFIX\\"'
SOURCES += $$PWD/main.cpp \
@ -19,14 +17,12 @@ HEADERS += $$PWD/qcomposeplatforminputcontext.h \
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
# dont't need x11 dependency for compose key plugin
QT_CONFIG -= use-xkbcommon-x11support
include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") {
DEFINES += XKBCOMMON_0_2_0
INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/
}
}
OTHER_FILES += $$PWD/compose.json

View File

@ -51,10 +51,6 @@
#include <xkbcommon/xkbcommon.h>
#ifdef XKBCOMMON_0_2_0
#include <xkbcommon_workaround.h>
#endif
#include <locale.h> // LC_CTYPE
#include <string.h> // strchr, strncmp, etc.
#include <strings.h> // strncasecmp
@ -326,23 +322,7 @@ ushort TableGenerator::keysymToUtf8(quint32 sym)
QByteArray chars;
int bytes;
chars.resize(8);
#ifdef XKBCOMMON_0_2_0
if (needWorkaround(sym)) {
quint32 codepoint;
if (sym == XKB_KEY_KP_Space)
codepoint = XKB_KEY_space & 0x7f;
else
codepoint = sym & 0x7f;
bytes = utf32_to_utf8(codepoint, chars.data());
} else {
bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
}
#else
bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
#endif
if (bytes == -1)
qWarning("TableGenerator::keysymToUtf8 - buffer too small");

View File

@ -4,7 +4,6 @@ qtHaveModule(dbus) {
!mac:!win32:SUBDIRS += ibus
}
unix:!macx:!contains(DEFINES, QT_NO_XKBCOMMON): {
SUBDIRS += compose
}
contains(QT_CONFIG, xcb-plugin): SUBDIRS += compose

View File

@ -53,10 +53,6 @@
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformcursor.h>
#ifdef XKBCOMMON_0_2_0
#include <xkbcommon_workaround.h>
#endif
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
@ -1398,23 +1394,7 @@ QString QXcbKeyboard::keysymToUnicode(xcb_keysym_t sym) const
QByteArray chars;
int bytes;
chars.resize(7);
#ifdef XKBCOMMON_0_2_0
if (needWorkaround(sym)) {
quint32 codepoint;
if (sym == XKB_KEY_KP_Space)
codepoint = XKB_KEY_space & 0x7f;
else
codepoint = sym & 0x7f;
bytes = utf32_to_utf8(codepoint, chars.data());
} else {
bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
}
#else
bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
#endif
if (bytes == -1)
qWarning("QXcbKeyboard::handleKeyEvent - buffer too small");
chars.resize(bytes-1);

View File

@ -131,12 +131,9 @@ contains(QT_CONFIG, xcb-qt) {
# libxkbcommon
contains(QT_CONFIG, xkbcommon-qt): {
QT_CONFIG += use-xkbcommon-x11support
include(../../../3rdparty/xkbcommon.pri)
} else {
LIBS += $$QMAKE_LIBS_XKBCOMMON
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON
equals(QMAKE_VERSION_XKBCOMMON, "0.2.0") {
DEFINES += XKBCOMMON_0_2_0
INCLUDEPATH += ../../../3rdparty/xkbcommon/xkbcommon/
}
}