Update bundled libxkbcommon version to 0.4.1

This is the latest version, released on Mar 27 2014. It includes:

https://bugs.freedesktop.org/show_bug.cgi?id=75798
https://bugs.freedesktop.org/show_bug.cgi?id=75892

Required for fixing input when running Qt application on Mac OS X
with XQuartz and for fixing QTBUG-36281.

Change-Id: Idc4d3c99a4008a10b91ab51c8910b36909974703
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Gatis Paeglis 2014-03-28 16:22:14 +01:00 committed by The Qt Project
parent 151cf2047a
commit bd40a7cc44
45 changed files with 1709 additions and 1903 deletions

5
configure vendored
View File

@ -5053,11 +5053,12 @@ if [ "$CFG_KMS" != "no" ]; then
fi
# Detect libxkbcommon
MIN_REQ_XKBCOMMON="0.4.1"
ORIG_CFG_XKBCOMMON="$CFG_XKBCOMMON"
# 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
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon xkbcommon-x11 >= $MIN_REQ_XKBCOMMON" 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`"
@ -6564,7 +6565,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo
fi
if [ "$ORIG_CFG_XKBCOMMON" != qt ] && [ "$CFG_XKBCOMMON" = qt ]; then
echo "NOTE: libxkbcommon and libxkbcommon-x11 0.4.0 or higher not found on the system, will use "
echo "NOTE: libxkbcommon and libxkbcommon-x11 $MIN_REQ_XKBCOMMON 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

@ -26,7 +26,8 @@ SOURCES += \
$$PWD/xkbcommon/src/text.c \
$$PWD/xkbcommon/src/context-priv.c \
$$PWD/xkbcommon/src/keymap-priv.c \
$$PWD/xkbcommon/src/utils.c
$$PWD/xkbcommon/src/utils.c \
$$PWD/xkbcommon/src/utf8.c
SOURCES += \
$$PWD/xkbcommon/src/xkbcomp/action.c \
@ -54,7 +55,7 @@ SOURCES += \
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
$$PWD/xkbcommon/src/x11/x11-state.c # renamed: state.c -> x11-state.c
}
TR_EXCLUDE += $$PWD/*

View File

@ -1,3 +1,46 @@
libxkbcommon 0.4.1
==================
- Converted README to markdown and added a Quick Guide to the
documentation, which breezes through the most common parts of
xkbcommon.
- Added two new functions, xkb_state_key_get_utf{8,32}(). They
combine the operations of xkb_state_key_get_syms() and
xkb_keysym_to_utf{8,32}(), and provide a nicer interface for it
(espcially for multiple-keysyms-per-level).
- The xkb_state_key_get_utf{8,32}() functions now apply Control
transformation: when the Control modifier is active, the string
is converted to an appropriate control character.
This matches the behavior of libX11's XLookupString(3), and
required by the XKB specification:
http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
https://bugs.freedesktop.org/show_bug.cgi?id=75892
- The consumed modifiers for a key are now calculated similarly
to libX11. The previous behavior caused a bug where Shift would
not cancel an active Caps Lock.
- Make xkbcommon-x11 work with the keymap reported by the XQuartz
X server.
https://bugs.freedesktop.org/show_bug.cgi?id=75798
- Reduce memory usage during keymap compilation some more.
- New API:
xkb_state_key_get_consumed_mods()
xkb_state_key_get_utf8()
xkb_state_key_get_utf32()
- Deprecated API:
XKB_MAP_COMPILE_PLACEHOLDER, XKB_MAP_NO_FLAGS
use XKB_KEYMAP_NO_FLAGS instead.
- Bug fixes.
libxkbcommon 0.4.0
==================

View File

@ -1,114 +0,0 @@
Overview {#mainpage}
========
xkbcommon is a keymap compiler and support library which processes a
reduced subset of keymaps as defined by the XKB specification. Primarily,
a keymap is created from a set of Rules/Model/Layout/Variant/Options names,
processed through an XKB ruleset, and compiled into a struct xkb_keymap,
which is the base type for all xkbcommon operations.
From an xkb_keymap, an xkb_state object is created which holds the current
state of all modifiers, groups, LEDs, etc, relating to that keymap. All
key events must be fed into the xkb_state object using xkb_state_update_key().
Once this is done, the xkb_state object will be properly updated, and the
keysyms to use can be obtained with xkb_state_key_get_syms().
libxkbcommon does not distribute a dataset itself, other than for testing
purposes. The most common dataset is xkeyboard-config, as used by all
current distributions for their X11 XKB data. More information on
xkeyboard-config is available here:
http://www.freedesktop.org/wiki/Software/XKeyboardConfig
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 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>.
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
===============
Relative to the XKB 1.1 specification implemented in current X servers,
xkbcommon has removed support for some parts of the specification which
introduced unnecessary complications. Many of these removals were in fact
not implemented, or half-implemented at best, as well as being totally
unused in the standard dataset.
Notable removals:
- geometry support
+ there were very few geometry definitions available, and while
xkbcommon was responsible for parsing this insanely complex format,
it never actually did anything with it
+ hopefully someone will develop a companion library which supports
keyboard geometries in a more useful format
- KcCGST (keycodes/compat/geometry/symbols/types) API
+ use RMLVO instead; KcCGST is now an implementation detail
+ including pre-defined keymap files
- XKM support
+ may come in an optional X11 support/compatibility library
- around half of the interpret actions
+ pointer device, message and redirect actions in particular
- non-virtual modifiers
+ core and virtual modifiers have been collapsed into the same
namespace, with a 'significant' flag that largely parallels the
core/virtual split
- radio groups
+ completely unused in current keymaps, never fully implemented
- overlays
+ almost completely unused in current keymaps
- key behaviors
+ used to implement radio groups and overlays, and to deal with things
like keys that physically lock; unused in current keymaps
- indicator behaviours such as LED-controls-key
+ the only supported LED behaviour is key-controls-LED; again this
was never really used in current keymaps
Notable additions:
- 32-bit keycodes
- extended number of modifiers
- extended number of groups
- multiple keysyms per level
+ this requires incompatible dataset changes, such that X11 would
not be able to parse these
Development
===========
An extremely rudimentary homepage can be found at:
http://xkbcommon.org
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:
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.

109
src/3rdparty/xkbcommon/README.md vendored Normal file
View File

@ -0,0 +1,109 @@
# libxkbcommon
xkbcommon is a keymap compiler and support library which processes a
reduced subset of keymaps as defined by the XKB specification. Primarily,
a keymap is created from a set of Rules/Model/Layout/Variant/Options names,
processed through an XKB ruleset, and compiled into a struct xkb_keymap,
which is the base type for all xkbcommon operations.
From an xkb_keymap, an xkb_state object is created which holds the current
state of all modifiers, groups, LEDs, etc, relating to that keymap. All
key events must be fed into the xkb_state object using xkb_state_update_key().
Once this is done, the xkb_state object will be properly updated, and the
keysyms to use can be obtained with xkb_state_key_get_syms().
libxkbcommon does not distribute a dataset itself, other than for testing
purposes. The most common dataset is xkeyboard-config, as used by all
current distributions for their X11 XKB data. More information on
xkeyboard-config is available here:
http://www.freedesktop.org/wiki/Software/XKeyboardConfig
## Quick Guide
See [Quick Guide](doc/quick-guide.md).
## 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 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.
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
Relative to the XKB 1.1 specification implemented in current X servers,
xkbcommon has removed support for some parts of the specification which
introduced unnecessary complications. Many of these removals were in fact
not implemented, or half-implemented at best, as well as being totally
unused in the standard dataset.
Notable removals:
- geometry support
+ there were very few geometry definitions available, and while
xkbcommon was responsible for parsing this insanely complex format,
it never actually did anything with it
+ hopefully someone will develop a companion library which supports
keyboard geometries in a more useful format
- KcCGST (keycodes/compat/geometry/symbols/types) API
+ use RMLVO instead; KcCGST is now an implementation detail
+ including pre-defined keymap files
- XKM support
+ may come in an optional X11 support/compatibility library
- around half of the interpret actions
+ pointer device, message and redirect actions in particular
- non-virtual modifiers
+ core and virtual modifiers have been collapsed into the same
namespace, with a 'significant' flag that largely parallels the
core/virtual split
- radio groups
+ completely unused in current keymaps, never fully implemented
- overlays
+ almost completely unused in current keymaps
- key behaviors
+ used to implement radio groups and overlays, and to deal with things
like keys that physically lock; unused in current keymaps
- indicator behaviours such as LED-controls-key
+ the only supported LED behaviour is key-controls-LED; again this
was never really used in current keymaps
Notable additions:
- 32-bit keycodes
- extended number of modifiers
- extended number of groups
- multiple keysyms per level
+ this requires incompatible dataset changes, such that X11 would
not be able to parse these
## Development
An extremely rudimentary homepage can be found at
http://xkbcommon.org
xkbcommon is maintained in git at
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 also welcome, and may be reported either at
Bugzilla https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon
or
Github https://github.com/xkbcommon/libxkbcommon/issues
The maintainers are
- Daniel Stone <daniel@fooishbar.org>
- Ran Benita <ran234@gmail.com>
## Credits
Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon
off the ground initially.

View File

@ -112,60 +112,79 @@ xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
#define DEFAULT_XKB_OPTIONS NULL
#endif
const char *
static 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");
env = secure_getenv("XKB_DEFAULT_RULES");
return env ? env : DEFAULT_XKB_RULES;
}
const char *
static 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");
env = secure_getenv("XKB_DEFAULT_MODEL");
return env ? env : DEFAULT_XKB_MODEL;
}
const char *
static 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");
env = secure_getenv("XKB_DEFAULT_LAYOUT");
return env ? env : DEFAULT_XKB_LAYOUT;
}
const char *
static const char *
xkb_context_get_default_variant(struct xkb_context *ctx)
{
const char *env = NULL;
const char *layout = getenv("XKB_DEFAULT_VARIANT");
const char *layout = secure_getenv("XKB_DEFAULT_LAYOUT");
/* 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");
env = secure_getenv("XKB_DEFAULT_VARIANT");
return env ? env : DEFAULT_XKB_VARIANT;
}
const char *
static 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");
env = secure_getenv("XKB_DEFAULT_OPTIONS");
return env ? env : DEFAULT_XKB_OPTIONS;
}
void
xkb_context_sanitize_rule_names(struct xkb_context *ctx,
struct xkb_rule_names *rmlvo)
{
if (isempty(rmlvo->rules))
rmlvo->rules = xkb_context_get_default_rules(ctx);
if (isempty(rmlvo->model))
rmlvo->model = xkb_context_get_default_model(ctx);
/* Layout and variant are tied together, so don't try to use one from
* the caller and one from the environment. */
if (isempty(rmlvo->layout)) {
rmlvo->layout = xkb_context_get_default_layout(ctx);
rmlvo->variant = xkb_context_get_default_variant(ctx);
}
/* Options can be empty, so respect that if passed in. */
if (rmlvo->options == NULL)
rmlvo->options = xkb_context_get_default_options(ctx);
}

View File

@ -82,7 +82,7 @@ xkb_context_include_path_append_default(struct xkb_context *ctx)
ret |= xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
home = getenv("HOME");
home = secure_getenv("HOME");
if (!home)
return ret;
err = asprintf(&user_path, "%s/.xkb", home);
@ -252,11 +252,11 @@ xkb_context_new(enum xkb_context_flags flags)
ctx->log_verbosity = 0;
/* Environment overwrites defaults. */
env = getenv("XKB_LOG_LEVEL");
env = secure_getenv("XKB_LOG_LEVEL");
if (env)
xkb_context_set_log_level(ctx, log_level(env));
env = getenv("XKB_LOG_VERBOSITY");
env = secure_getenv("XKB_LOG_VERBOSITY");
if (env)
xkb_context_set_log_verbosity(ctx, log_verbosity(env));

View File

@ -91,20 +91,9 @@ ATTR_PRINTF(4, 5) void
xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity,
const char *fmt, ...);
const char *
xkb_context_get_default_rules(struct xkb_context *ctx);
const char *
xkb_context_get_default_model(struct xkb_context *ctx);
const char *
xkb_context_get_default_layout(struct xkb_context *ctx);
const char *
xkb_context_get_default_variant(struct xkb_context *ctx);
const char *
xkb_context_get_default_options(struct xkb_context *ctx);
void
xkb_context_sanitize_rule_names(struct xkb_context *ctx,
struct xkb_rule_names *rmlvo);
/*
* The format is not part of the argument list in order to avoid the

View File

@ -23,93 +23,15 @@
#ifndef CCAN_DARRAY_H
#define CCAN_DARRAY_H
/* Originally taken from: http://ccodearchive.net/info/darray.html
* But modified for libxkbcommon. */
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
/*
* SYNOPSIS
*
* Life cycle of a darray (dynamically-allocated array):
*
* darray(int) a = darray_new();
* darray_free(a);
*
* struct {darray(int) a;} foo;
* darray_init(foo.a);
* darray_free(foo.a);
*
* Typedefs for darrays of common types:
*
* darray_char, darray_schar, darray_uchar
* darray_short, darray_int, darray_long
* darray_ushort, darray_uint, darray_ulong
*
* Access:
*
* T darray_item(darray(T) arr, size_t index);
* size_t darray_size(darray(T) arr);
* size_t darray_alloc(darray(T) arr);
* bool darray_empty(darray(T) arr);
*
* // Access raw memory, starting from the item in offset.
* // Not safe, be careful, etc.
* T* darray_mem(darray(T) arr, size_t offset);
*
* Insertion (single item):
*
* void darray_append(darray(T) arr, T item);
* void darray_prepend(darray(T) arr, T item);
* void darray_push(darray(T) arr, T item); // same as darray_append
*
* Insertion (multiple items):
*
* void darray_append_items(darray(T) arr, T *items, size_t count);
* void darray_prepend_items(darray(T) arr, T *items, size_t count);
*
* void darray_appends(darray(T) arr, [T item, [...]]);
* void darray_prepends(darray(T) arr, [T item, [...]]);
*
* Removal:
*
* T darray_pop(darray(T) arr | darray_size(arr) != 0);
* T* darray_pop_check(darray(T*) arr);
*
* Replacement:
*
* void darray_from_items(darray(T) arr, T *items, size_t count);
* void darray_from_c(darray(T) arr, T c_array[N]);
*
* String buffer:
*
* void darray_append_string(darray(char) arr, const char *str);
* void darray_append_lit(darray(char) arr, char stringLiteral[N+1]);
*
* void darray_prepend_string(darray(char) arr, const char *str);
* void darray_prepend_lit(darray(char) arr, char stringLiteral[N+1]);
*
* void darray_from_string(darray(T) arr, const char *str);
* void darray_from_lit(darray(char) arr, char stringLiteral[N+1]);
*
* Size management:
*
* void darray_resize(darray(T) arr, size_t newSize);
* void darray_resize0(darray(T) arr, size_t newSize);
*
* void darray_realloc(darray(T) arr, size_t newAlloc);
* void darray_growalloc(darray(T) arr, size_t newAlloc);
*
* Traversal:
*
* darray_foreach(T *&i, darray(T) arr) {...}
* darray_foreach_reverse(T *&i, darray(T) arr) {...}
*
* Except for darray_foreach and darray_foreach_reverse,
* all macros evaluate their non-darray arguments only once.
*/
/*** Life cycle ***/
#define darray(type) struct { type *item; size_t size; size_t alloc; }
#define darray(type) struct { type *item; unsigned size; unsigned alloc; }
#define darray_new() { 0, 0, 0 }
@ -118,7 +40,8 @@
} while (0)
#define darray_free(arr) do { \
free((arr).item); darray_init(arr); \
free((arr).item); \
darray_init(arr); \
} while (0)
/*
@ -154,11 +77,8 @@ typedef darray (unsigned long) darray_ulong;
#define darray_item(arr, i) ((arr).item[i])
#define darray_size(arr) ((arr).size)
#define darray_alloc(arr) ((arr).alloc)
#define darray_empty(arr) ((arr).size == 0)
#define darray_mem(arr, offset) ((arr).item + (offset))
#define darray_same(arr1, arr2) ((arr1).item == (arr2).item)
/*** Insertion (single item) ***/
@ -167,74 +87,20 @@ typedef darray (unsigned long) darray_ulong;
(arr).item[(arr).size - 1] = (__VA_ARGS__); \
} while (0)
#define darray_prepend(arr, ...) do { \
darray_resize(arr, (arr).size + 1); \
memmove((arr).item + 1, (arr).item, \
((arr).size - 1) * sizeof(*(arr).item)); \
(arr).item[0] = (__VA_ARGS__); \
} while (0)
#define darray_push(arr, ...) darray_append(arr, __VA_ARGS__)
/*** Insertion (multiple items) ***/
#define darray_append_items(arr, items, count) do { \
size_t __count = (count), __oldSize = (arr).size; \
unsigned __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __oldSize + __count); \
memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \
} while (0)
#define darray_prepend_items(arr, items, count) do { \
size_t __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __count + __oldSize); \
memmove((arr).item + __count, (arr).item, \
__oldSize * sizeof(*(arr).item)); \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
} while (0)
#define darray_append_items_nullterminate(arr, items, count) do { \
size_t __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __oldSize + __count + 1); \
memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \
(arr).item[--(arr).size] = 0; \
} while (0)
#define darray_prepend_items_nullterminate(arr, items, count) do { \
size_t __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __count + __oldSize + 1); \
memmove((arr).item + __count, (arr).item, \
__oldSize * sizeof(*(arr).item)); \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
(arr).item[--(arr).size] = 0; \
} while (0)
#define darray_appends_t(arr, type, ...) do { \
type __src[] = { __VA_ARGS__ }; \
darray_append_items(arr, __src, sizeof(__src) / sizeof(*__src)); \
} while (0)
#define darray_prepends_t(arr, type, ...) do { \
type __src[] = { __VA_ARGS__ }; \
darray_prepend_items(arr, __src, sizeof(__src) / sizeof(*__src)); \
} while (0)
/*** Removal ***/
/* Warning: Do not call darray_pop on an empty darray. */
#define darray_pop(arr) ((arr).item[--(arr).size])
#define darray_pop_check(arr) ((arr).size ? darray_pop(arr) : NULL)
/*** Replacement ***/
#define darray_from_items(arr, items, count) do { \
size_t __count = (count); \
unsigned __count = (count); \
darray_resize(arr, __count); \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
} while (0)
#define darray_from_c(arr, c_array) \
darray_from_items(arr, c_array, sizeof(c_array) / sizeof(*(c_array)))
#define darray_copy(arr_to, arr_from) \
darray_from_items((arr_to), (arr_from).item, (arr_from).size)
@ -251,24 +117,20 @@ typedef darray (unsigned long) darray_ulong;
(arr).size--; \
} while (0)
#define darray_prepend_string(arr, str) do { \
const char *__str = (str); \
darray_prepend_items_nullterminate(arr, __str, strlen(__str)); \
#define darray_appends_nullterminate(arr, items, count) do { \
unsigned __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __oldSize + __count + 1); \
memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \
(arr).item[--(arr).size] = 0; \
} while (0)
#define darray_prepend_lit(arr, stringLiteral) \
darray_prepend_items_nullterminate(arr, stringLiteral, \
sizeof(stringLiteral) - 1)
#define darray_from_string(arr, str) do { \
const char *__str = (str); \
darray_from_items(arr, __str, strlen(__str) + 1); \
(arr).size--; \
} while (0)
#define darray_from_lit(arr, stringLiteral) do { \
darray_from_items(arr, stringLiteral, sizeof(stringLiteral)); \
(arr).size--; \
#define darray_prepends_nullterminate(arr, items, count) do { \
unsigned __count = (count), __oldSize = (arr).size; \
darray_resize(arr, __count + __oldSize + 1); \
memmove((arr).item + __count, (arr).item, \
__oldSize * sizeof(*(arr).item)); \
memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
(arr).item[--(arr).size] = 0; \
} while (0)
/*** Size management ***/
@ -277,7 +139,7 @@ typedef darray (unsigned long) darray_ulong;
darray_growalloc(arr, (arr).size = (newSize))
#define darray_resize0(arr, newSize) do { \
size_t __oldSize = (arr).size, __newSize = (newSize); \
unsigned __oldSize = (arr).size, __newSize = (newSize); \
(arr).size = __newSize; \
if (__newSize > __oldSize) { \
darray_growalloc(arr, __newSize); \
@ -292,14 +154,16 @@ typedef darray (unsigned long) darray_ulong;
} while (0)
#define darray_growalloc(arr, need) do { \
size_t __need = (need); \
unsigned __need = (need); \
if (__need > (arr).alloc) \
darray_realloc(arr, darray_next_alloc((arr).alloc, __need)); \
darray_realloc(arr, darray_next_alloc((arr).alloc, __need, \
sizeof(*(arr).item))); \
} while (0)
static inline size_t
darray_next_alloc(size_t alloc, size_t need)
static inline unsigned
darray_next_alloc(unsigned alloc, unsigned need, unsigned itemSize)
{
assert(need < UINT_MAX / itemSize / 2); /* Overflow. */
if (alloc == 0)
alloc = 4;
while (alloc < need)
@ -309,11 +173,6 @@ darray_next_alloc(size_t alloc, size_t need)
/*** Traversal ***/
/*
* darray_foreach(T *&i, darray(T) arr) {...}
*
* Traverse a darray. `i` must be declared in advance as a pointer to an item.
*/
#define darray_foreach(i, arr) \
for ((i) = &(arr).item[0]; (i) < &(arr).item[(arr).size]; (i)++)
@ -331,58 +190,7 @@ darray_next_alloc(size_t alloc, size_t need)
(idx) < (arr).size; \
(idx)++, (val)++)
/*
* darray_foreach_reverse(T *&i, darray(T) arr) {...}
*
* Like darray_foreach, but traverse in reverse order.
*/
#define darray_foreach_reverse(i, arr) \
for ((i) = &(arr).item[(arr).size]; (i)-- > &(arr).item[0]; )
#endif /* CCAN_DARRAY_H */
/*
*
* darray_growalloc(arr, newAlloc) sees if the darray can currently hold newAlloc items;
* if not, it increases the alloc to satisfy this requirement, allocating slack
* space to avoid having to reallocate for every size increment.
*
* darray_from_string(arr, str) copies a string to an darray_char.
*
* darray_push(arr, item) pushes an item to the end of the darray.
* darray_pop(arr) pops it back out. Be sure there is at least one item in the darray before calling.
* darray_pop_check(arr) does the same as darray_pop, but returns NULL if there are no more items left in the darray.
*
* darray_make_room(arr, room) ensures there's 'room' elements of space after the end of the darray, and it returns a pointer to this space.
* Currently requires HAVE_STATEMENT_EXPR, but I plan to remove this dependency by creating an inline function.
*
* The following require HAVE_TYPEOF==1 :
*
* darray_appends(arr, item0, item1...) appends a collection of comma-delimited items to the darray.
* darray_prepends(arr, item0, item1...) prepends a collection of comma-delimited items to the darray.\
*
*
* Examples:
*
* darray(int) arr;
* int *i;
*
* darray_appends(arr, 0,1,2,3,4);
* darray_appends(arr, -5,-4,-3,-2,-1);
* darray_foreach(i, arr)
* printf("%d ", *i);
* printf("\n");
*
* darray_free(arr);
*
*
* typedef struct {int n,d;} Fraction;
* darray(Fraction) fractions;
* Fraction *i;
*
* darray_appends(fractions, {3,4}, {3,5}, {2,1});
* darray_foreach(i, fractions)
* printf("%d/%d\n", i->n, i->d);
*
* darray_free(fractions);
*/

View File

@ -30,12 +30,7 @@ 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,
const struct xkb_mod builtin_mods[] = {
{ .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 },
@ -43,7 +38,14 @@ update_builtin_keymap_fields(struct xkb_keymap *keymap)
{ .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 });
{ .name = xkb_atom_intern_literal(ctx, "Mod5"), .type = MOD_REAL },
};
/*
* Add predefined (AKA real, core, X11) modifiers.
* The order is important!
*/
darray_append_items(keymap->mods, builtin_mods, ARRAY_SIZE(builtin_mods));
}
struct xkb_keymap *

View File

@ -146,7 +146,7 @@ enum xkb_action_flags {
ACTION_ABSOLUTE_SWITCH = (1 << 5),
ACTION_ABSOLUTE_X = (1 << 6),
ACTION_ABSOLUTE_Y = (1 << 7),
ACTION_NO_ACCEL = (1 << 8),
ACTION_ACCEL = (1 << 8),
ACTION_SAME_SCREEN = (1 << 9),
};
@ -223,7 +223,7 @@ struct xkb_pointer_button_action {
enum xkb_action_type type;
enum xkb_action_flags flags;
uint8_t count;
int8_t button;
uint8_t button;
};
struct xkb_private_action {
@ -262,10 +262,10 @@ struct xkb_key_type {
struct xkb_sym_interpret {
xkb_keysym_t sym;
enum xkb_match_operation match;
bool level_one_only;
xkb_mod_mask_t mods;
xkb_mod_index_t virtual_mod;
union xkb_action action;
bool level_one_only;
bool repeat;
};

View File

@ -37,6 +37,7 @@
#include "xkbcommon/xkbcommon.h"
#include "utils.h"
#include "utf8.h"
/* We don't use the uint32_t types here, to save some space. */
struct codepair {
@ -838,15 +839,15 @@ static const struct codepair keysymtab[] = {
static uint32_t
bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym)
{
int first = 0;
int last = length;
size_t first = 0;
size_t last = length;
if (keysym < table[0].keysym || keysym > table[length].keysym)
return 0;
/* binary search in table */
while (last >= first) {
int mid = (first + last) / 2;
size_t mid = (first + last) / 2;
if (table[mid].keysym < keysym)
first = mid + 1;
else if (table[mid].keysym > keysym)
@ -912,47 +913,6 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym)
* Author: Rob Bradford <rob@linux.intel.com>
*/
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;
}
XKB_EXPORT int
xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size)
{

View File

@ -64,7 +64,11 @@ compare_by_keysym(const void *a, const void *b)
{
const xkb_keysym_t *key = a;
const struct name_keysym *entry = b;
return *key - (int32_t) entry->keysym;
if (*key < entry->keysym)
return -1;
if (*key > entry->keysym)
return 1;
return 0;
}
static int

View File

@ -49,13 +49,25 @@ struct scanner {
size_t len;
char buf[1024];
size_t buf_pos;
int line, column;
unsigned line, column;
/* The line/column of the start of the current token. */
int token_line, token_column;
unsigned token_line, token_column;
const char *file_name;
struct xkb_context *ctx;
};
#define scanner_log(scanner, level, fmt, ...) \
xkb_log((scanner)->ctx, (level), 0, \
"%s:%u:%u: " fmt "\n", \
(scanner)->file_name, \
(scanner)->token_line, (scanner)->token_column, ##__VA_ARGS__)
#define scanner_err(scanner, fmt, ...) \
scanner_log(scanner, XKB_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
#define scanner_warn(scanner, fmt, ...) \
scanner_log(scanner, XKB_LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
static inline void
scanner_init(struct scanner *s, struct xkb_context *ctx,
const char *string, size_t len, const char *file_name)
@ -72,7 +84,9 @@ scanner_init(struct scanner *s, struct xkb_context *ctx,
static inline char
peek(struct scanner *s)
{
return s->pos < s->len ? s->s[s->pos] : '\0';
if (unlikely(s->pos >= s->len))
return '\0';
return s->s[s->pos];
}
static inline bool
@ -90,9 +104,9 @@ eol(struct scanner *s)
static inline char
next(struct scanner *s)
{
if (eof(s))
if (unlikely(eof(s)))
return '\0';
if (eol(s)) {
if (unlikely(eol(s))) {
s->line++;
s->column = 1;
}
@ -105,7 +119,7 @@ next(struct scanner *s)
static inline bool
chr(struct scanner *s, char ch)
{
if (peek(s) != ch)
if (likely(peek(s) != ch))
return false;
s->pos++; s->column++;
return true;

View File

@ -61,6 +61,7 @@
#include "keymap.h"
#include "keysym.h"
#include "utf8.h"
struct xkb_filter {
union xkb_action action;
@ -108,7 +109,7 @@ struct xkb_state {
* < Left Shift down, Right Shift down, Left Shift Up >
* the modifier should still be set. This keeps the count.
*/
int16_t mod_key_count[sizeof(xkb_mod_mask_t) * 8];
int16_t mod_key_count[XKB_MAX_MODS];
int refcnt;
darray(struct xkb_filter) filters;
@ -121,9 +122,8 @@ get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
{
const struct xkb_key_type *type = key->groups[group].type;
xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask;
unsigned int i;
for (i = 0; i < type->num_entries; i++) {
for (unsigned i = 0; i < type->num_entries; i++) {
/*
* If the virtual modifiers are not bound to anything, we're
* supposed to skip the entry (xserver does this with cached
@ -170,7 +170,7 @@ wrap_group_into_range(int32_t group,
if (num_groups == 0)
return XKB_LAYOUT_INVALID;
if (group < num_groups)
if (group >= 0 && (xkb_layout_index_t) group < num_groups)
return group;
switch (out_of_range_group_action) {
@ -623,30 +623,42 @@ xkb_state_led_update_all(struct xkb_state *state)
xkb_mod_mask_t mod_mask = 0;
xkb_layout_mask_t group_mask = 0;
if (led->which_mods & XKB_STATE_MODS_EFFECTIVE)
mod_mask |= state->components.mods;
if (led->which_mods & XKB_STATE_MODS_DEPRESSED)
mod_mask |= state->components.base_mods;
if (led->which_mods & XKB_STATE_MODS_LATCHED)
mod_mask |= state->components.latched_mods;
if (led->which_mods & XKB_STATE_MODS_LOCKED)
mod_mask |= state->components.locked_mods;
if (led->mods.mask & mod_mask)
state->components.leds |= (1 << idx);
if (led->which_mods != 0 && led->mods.mask != 0) {
if (led->which_mods & XKB_STATE_MODS_EFFECTIVE)
mod_mask |= state->components.mods;
if (led->which_mods & XKB_STATE_MODS_DEPRESSED)
mod_mask |= state->components.base_mods;
if (led->which_mods & XKB_STATE_MODS_LATCHED)
mod_mask |= state->components.latched_mods;
if (led->which_mods & XKB_STATE_MODS_LOCKED)
mod_mask |= state->components.locked_mods;
if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
group_mask |= (1 << state->components.group);
if (led->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
group_mask |= (1 << state->components.base_group);
if (led->which_groups & XKB_STATE_LAYOUT_LATCHED)
group_mask |= (1 << state->components.latched_group);
if (led->which_groups & XKB_STATE_LAYOUT_LOCKED)
group_mask |= (1 << state->components.locked_group);
if (led->groups & group_mask)
state->components.leds |= (1 << idx);
if (led->mods.mask & mod_mask) {
state->components.leds |= (1u << idx);
continue;
}
}
if (led->ctrls & state->keymap->enabled_ctrls)
state->components.leds |= (1 << idx);
if (led->which_groups != 0 && led->groups != 0) {
if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
group_mask |= (1u << state->components.group);
if (led->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
group_mask |= (1u << state->components.base_group);
if (led->which_groups & XKB_STATE_LAYOUT_LATCHED)
group_mask |= (1u << state->components.latched_group);
if (led->which_groups & XKB_STATE_LAYOUT_LOCKED)
group_mask |= (1u << state->components.locked_group);
if (led->groups & group_mask) {
state->components.leds |= (1u << idx);
continue;
}
}
if (led->ctrls & state->keymap->enabled_ctrls) {
state->components.leds |= (1u << idx);
continue;
}
}
}
@ -657,23 +669,27 @@ xkb_state_led_update_all(struct xkb_state *state)
static void
xkb_state_update_derived(struct xkb_state *state)
{
xkb_layout_index_t wrapped;
state->components.mods = (state->components.base_mods |
state->components.latched_mods |
state->components.locked_mods);
/* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
wrapped = wrap_group_into_range(state->components.locked_group,
state->keymap->num_groups,
RANGE_WRAP, 0);
state->components.locked_group =
wrap_group_into_range(state->components.locked_group,
state->keymap->num_groups,
RANGE_WRAP, 0);
(wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
wrapped = wrap_group_into_range(state->components.base_group +
state->components.latched_group +
state->components.locked_group,
state->keymap->num_groups,
RANGE_WRAP, 0);
state->components.group =
wrap_group_into_range(state->components.base_group +
state->components.latched_group +
state->components.locked_group,
state->keymap->num_groups,
RANGE_WRAP, 0);
(wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
xkb_state_led_update_all(state);
}
@ -781,7 +797,7 @@ xkb_state_update_mask(struct xkb_state *state,
num_mods = xkb_keymap_num_mods(state->keymap);
for (idx = 0; idx < num_mods; idx++) {
xkb_mod_mask_t mod = (1 << idx);
xkb_mod_mask_t mod = (1u << idx);
if (base_mods & mod)
state->components.base_mods |= mod;
if (latched_mods & mod)
@ -826,6 +842,53 @@ err:
return 0;
}
/*
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
*/
static bool
should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
{
xkb_mod_index_t caps =
xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS);
return
xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 &&
xkb_state_mod_index_is_consumed(state, kc, caps) == 0;
}
/*
* http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
*/
static bool
should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
{
xkb_mod_index_t ctrl =
xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CTRL);
return
xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0 &&
xkb_state_mod_index_is_consumed(state, kc, ctrl) == 0;
}
/* Verbatim from libX11:src/xkb/XKBBind.c */
static char
XkbToControl(char ch)
{
char c = ch;
if ((c >= '@' && c < '\177') || c == ' ')
c &= 0x1F;
else if (c == '2')
c = '\000';
else if (c >= '3' && c <= '7')
c -= ('3' - '\033');
else if (c == '8')
c = '\177';
else if (c == '/')
c = '_' & 0x1F;
return c;
}
/**
* Provides either exactly one symbol, or XKB_KEY_NoSymbol.
*/
@ -835,7 +898,6 @@ 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)
@ -843,18 +905,135 @@ xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
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)
if (should_do_caps_transformation(state, kc))
sym = xkb_keysym_to_upper(sym);
return sym;
}
/*
* The caps and ctrl transformations require some special handling,
* so we cannot simply use xkb_state_get_one_sym() for them.
* In particular, if Control is set, we must try very hard to find
* some layout in which the keysym is ASCII and thus can be (maybe)
* converted to a control character. libX11 allows to disable this
* behavior with the XkbLC_ControlFallback (see XkbSetXlibControls(3)),
* but it is enabled by default, yippee.
*/
static xkb_keysym_t
get_one_sym_for_string(struct xkb_state *state, xkb_keycode_t kc)
{
xkb_level_index_t level;
xkb_layout_index_t layout, num_layouts;
const xkb_keysym_t *syms;
int nsyms;
xkb_keysym_t sym;
layout = xkb_state_key_get_layout(state, kc);
num_layouts = xkb_keymap_num_layouts_for_key(state->keymap, kc);
level = xkb_state_key_get_level(state, kc, layout);
if (layout == XKB_LAYOUT_INVALID || num_layouts == 0 ||
level == XKB_LEVEL_INVALID)
return XKB_KEY_NoSymbol;
nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
layout, level, &syms);
if (nsyms != 1)
return XKB_KEY_NoSymbol;
sym = syms[0];
if (should_do_ctrl_transformation(state, kc) && sym > 127u) {
for (xkb_layout_index_t i = 0; i < num_layouts; i++) {
level = xkb_state_key_get_level(state, kc, i);
if (level == XKB_LEVEL_INVALID)
continue;
nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
i, level, &syms);
if (nsyms == 1 && syms[0] <= 127u) {
sym = syms[0];
break;
}
}
}
if (should_do_caps_transformation(state, kc)) {
sym = xkb_keysym_to_upper(sym);
}
return sym;
}
XKB_EXPORT int
xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t kc,
char *buffer, size_t size)
{
xkb_keysym_t sym;
const xkb_keysym_t *syms;
int nsyms;
int offset;
char tmp[7];
sym = get_one_sym_for_string(state, kc);
if (sym != XKB_KEY_NoSymbol) {
nsyms = 1; syms = &sym;
}
else {
nsyms = xkb_state_key_get_syms(state, kc, &syms);
}
/* Make sure not to truncate in the middle of a UTF-8 sequence. */
offset = 0;
for (int i = 0; i < nsyms; i++) {
int ret = xkb_keysym_to_utf8(syms[i], tmp, sizeof(tmp));
if (ret <= 0)
goto err_bad;
ret--;
if ((size_t) (offset + ret) <= size)
memcpy(buffer + offset, tmp, ret);
offset += ret;
}
if ((size_t) offset >= size)
goto err_trunc;
buffer[offset] = '\0';
if (!is_valid_utf8(buffer, offset))
goto err_bad;
if (offset == 1 && (unsigned int) buffer[0] <= 127u &&
should_do_ctrl_transformation(state, kc))
buffer[0] = XkbToControl(buffer[0]);
return offset;
err_trunc:
if (size > 0)
buffer[size - 1] = '\0';
return offset;
err_bad:
if (size > 0)
buffer[0] = '\0';
return 0;
}
XKB_EXPORT uint32_t
xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t kc)
{
xkb_keysym_t sym;
uint32_t cp;
sym = get_one_sym_for_string(state, kc);
cp = xkb_keysym_to_utf32(sym);
if (cp <= 127u && should_do_ctrl_transformation(state, kc))
cp = (uint32_t) XkbToControl((char) cp);
return cp;
}
/**
* Serialises the requested modifier state into an xkb_mod_mask_t, with all
* the same disclaimers as in xkb_state_update_mask.
@ -913,7 +1092,7 @@ xkb_state_mod_index_is_active(struct xkb_state *state,
if (idx >= xkb_keymap_num_mods(state->keymap))
return -1;
return !!(xkb_state_serialize_mods(state, type) & (1 << idx));
return !!(xkb_state_serialize_mods(state, type) & (1u << idx));
}
/**
@ -964,7 +1143,7 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
ret = -1;
break;
}
wanted |= (1 << idx);
wanted |= (1u << idx);
}
va_end(ap);
@ -1015,7 +1194,7 @@ xkb_state_mod_names_are_active(struct xkb_state *state,
ret = -1;
break;
}
wanted |= (1 << idx);
wanted |= (1u << idx);
}
va_end(ap);
@ -1042,11 +1221,11 @@ xkb_state_layout_index_is_active(struct xkb_state *state,
if (type & XKB_STATE_LAYOUT_EFFECTIVE)
ret |= (state->components.group == idx);
if (type & XKB_STATE_LAYOUT_DEPRESSED)
ret |= (state->components.base_group == idx);
ret |= (state->components.base_group == (int32_t) idx);
if (type & XKB_STATE_LAYOUT_LATCHED)
ret |= (state->components.latched_group == idx);
ret |= (state->components.latched_group == (int32_t) idx);
if (type & XKB_STATE_LAYOUT_LOCKED)
ret |= (state->components.locked_group == idx);
ret |= (state->components.locked_group == (int32_t) idx);
return ret;
}
@ -1077,7 +1256,7 @@ xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
darray_item(state->keymap->leds, idx).name == XKB_ATOM_NONE)
return -1;
return !!(state->components.leds & (1 << idx));
return !!(state->components.leds & (1u << idx));
}
/**
@ -1097,18 +1276,24 @@ xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
static xkb_mod_mask_t
key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
{
const struct xkb_key_type *type;
const struct xkb_key_type_entry *entry;
xkb_mod_mask_t preserve;
xkb_layout_index_t group;
group = xkb_state_key_get_layout(state, key->keycode);
if (group == XKB_LAYOUT_INVALID)
return 0;
entry = get_entry_for_key_state(state, key, group);
if (!entry)
return 0;
type = key->groups[group].type;
return entry->mods.mask & ~entry->preserve.mask;
entry = get_entry_for_key_state(state, key, group);
if (entry)
preserve = entry->preserve.mask;
else
preserve = 0;
return type->mods.mask & ~preserve;
}
/**
@ -1132,7 +1317,7 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
if (!key || idx >= xkb_keymap_num_mods(state->keymap))
return -1;
return !!((1 << idx) & key_get_consumed(state, key));
return !!((1u << idx) & key_get_consumed(state, key));
}
/**
@ -1154,3 +1339,14 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
return mask & ~key_get_consumed(state, key);
}
XKB_EXPORT xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
{
const struct xkb_key *key = XkbKey(state->keymap, kc);
if (!key)
return 0;
return key_get_consumed(state, key);
}

View File

@ -280,7 +280,7 @@ ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
darray_enumerate(i, mod, keymap->mods) {
int ret;
if (!(mask & (1 << i)))
if (!(mask & (1u << i)))
continue;
ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
@ -307,14 +307,14 @@ LedStateMaskText(struct xkb_context *ctx, enum xkb_state_component mask)
for (unsigned i = 0; mask; i++) {
int ret;
if (!(mask & (1 << i)))
if (!(mask & (1u << i)))
continue;
mask &= ~(1 << i);
mask &= ~(1u << i);
ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
pos == 0 ? "" : "+",
LookupValue(modComponentMaskNames, 1 << i));
LookupValue(modComponentMaskNames, 1u << i));
if (ret <= 0 || pos + ret >= sizeof(buf))
break;
else
@ -339,14 +339,14 @@ ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask)
for (unsigned i = 0; mask; i++) {
int ret;
if (!(mask & (1 << i)))
if (!(mask & (1u << i)))
continue;
mask &= ~(1 << i);
mask &= ~(1u << i);
ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
pos == 0 ? "" : "+",
LookupValue(ctrlMaskNames, 1 << i));
LookupValue(ctrlMaskNames, 1u << i));
if (ret <= 0 || pos + ret >= sizeof(buf))
break;
else

142
src/3rdparty/xkbcommon/src/utf8.c vendored Normal file
View File

@ -0,0 +1,142 @@
/*
* Copyright © 2012 Intel Corporation
* Copyright © 2014 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Rob Bradford <rob@linux.intel.com>
*/
#include <stddef.h>
#include <stdbool.h>
#include <inttypes.h>
#include "utf8.h"
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;
}
bool
is_valid_utf8(const char *ss, size_t len)
{
size_t i = 0;
size_t tail_bytes = 0;
const uint8_t *s = (const uint8_t *) ss;
/* This beauty is from:
* The Unicode Standard Version 6.2 - Core Specification, Table 3.7
* http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
* We can optimize if needed. */
while (i < len)
{
if (s[i] <= 0x7F) {
tail_bytes = 0;
}
else if (s[i] >= 0xC2 && s[i] <= 0xDF) {
tail_bytes = 1;
}
else if (s[i] == 0xE0) {
i++;
if (i >= len || !(s[i] >= 0xA0 && s[i] <= 0xBF))
return false;
tail_bytes = 1;
}
else if (s[i] >= 0xE1 && s[i] <= 0xEC) {
tail_bytes = 2;
}
else if (s[i] == 0xED) {
i++;
if (i >= len || !(s[i] >= 0x80 && s[i] <= 0x9F))
return false;
tail_bytes = 1;
}
else if (s[i] >= 0xEE && s[i] <= 0xEF) {
tail_bytes = 2;
}
else if (s[i] == 0xF0) {
i++;
if (i >= len || !(s[i] >= 0x90 && s[i] <= 0xBF))
return false;
tail_bytes = 2;
}
else if (s[i] >= 0xF1 && s[i] <= 0xF3) {
tail_bytes = 3;
}
else if (s[i] == 0xF4) {
i++;
if (i >= len || !(s[i] >= 0x80 && s[i] <= 0x8F))
return false;
tail_bytes = 2;
}
else {
return false;
}
i++;
while (i < len && tail_bytes > 0 && s[i] >= 0x80 && s[i] <= 0xBF) {
i++;
tail_bytes--;
}
if (tail_bytes != 0)
return false;
}
return true;
}

36
src/3rdparty/xkbcommon/src/utf8.h vendored Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright © 2012 Intel Corporation
* Copyright © 2014 Ran Benita <ran234@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Author: Rob Bradford <rob@linux.intel.com>
*/
#ifndef XKBCOMMON_UTF8_H
#define XKBCOMMON_UTF8_H
int
utf32_to_utf8(uint32_t unichar, char *buffer);
bool
is_valid_utf8(const char *ss, size_t len);
#endif

View File

@ -163,13 +163,13 @@ is_graph(char ch)
* Note: this is 1-based! It's more useful this way, and returns 0 when
* mask is all 0s.
*/
static inline int
static inline unsigned
msb_pos(uint32_t mask)
{
int pos = 0;
unsigned pos = 0;
while (mask) {
pos++;
mask >>= 1;
mask >>= 1u;
}
return pos;
}
@ -187,6 +187,22 @@ unmap_file(const char *str, size_t size);
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(MAX((a), (b)), (c))
#if defined(HAVE_SECURE_GETENV)
# define secure_getenv secure_getenv
#elif defined(HAVE___SECURE_GETENV)
# define secure_getenv __secure_getenv
#else
# define secure_getenv getenv
#endif
#if defined(HAVE___BUILTIN_EXPECT)
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
/* Compiler Attributes */
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__)

View File

@ -43,13 +43,13 @@
/* Constants from /usr/include/X11/extensions/XKB.h */
/* XkbNumModifiers. */
#define NUM_REAL_MODS 8
#define NUM_REAL_MODS 8u
/* XkbNumVirtualMods. */
#define NUM_VMODS 16
#define NUM_VMODS 16u
/* XkbNoModifier. */
#define NO_MODIFIER 0xff
/* XkbNumIndicators. */
#define NUM_INDICATORS 32
#define NUM_INDICATORS 32u
/* XkbAllIndicatorsMask. */
#define ALL_INDICATORS_MASK 0xffffffff
@ -92,11 +92,14 @@ translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high)
{
/* We represent mod masks in a single uint32_t value, with real mods
* first and vmods after (though we don't make these distinctions). */
return rmods | (vmods_low << 8) | (vmods_high << 16);
return
((xkb_mod_mask_t) rmods) |
((xkb_mod_mask_t) vmods_low << 8) |
((xkb_mod_mask_t) vmods_high << 16);
}
static enum xkb_action_controls
translate_controls_mask(uint16_t wire)
translate_controls_mask(uint32_t wire)
{
enum xkb_action_controls ret = 0;
if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS)
@ -218,8 +221,8 @@ translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
action->ptr.x = (wire->moveptr.xLow | (wire->moveptr.xHigh << 8));
action->ptr.y = (wire->moveptr.yLow | (wire->moveptr.yHigh << 8));
if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION)
action->ptr.flags |= ACTION_NO_ACCEL;
if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION))
action->ptr.flags |= ACTION_ACCEL;
if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_X)
action->ptr.flags |= ACTION_ABSOLUTE_X;
if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_Y)
@ -263,7 +266,7 @@ translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
action->screen.screen = wire->switchscreen.newScreen;
if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION)
if (!(wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION))
action->screen.flags |= ACTION_SAME_SCREEN;
if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_ABSOLUTE)
action->screen.flags |= ACTION_ABSOLUTE_SWITCH;
@ -351,7 +354,7 @@ get_types(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_xkb_mod_def_iterator_t preserves_iter =
xcb_xkb_key_type_preserve_iterator(wire_type);
FAIL_UNLESS(preserves_length <= type->num_entries);
FAIL_UNLESS((unsigned) preserves_length <= type->num_entries);
for (int j = 0; j < preserves_length; j++) {
xcb_xkb_mod_def_t *wire_preserve = preserves_iter.data;
@ -402,7 +405,7 @@ get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn,
FAIL_UNLESS(key->num_groups <= ARRAY_SIZE(wire_sym_map->kt_index));
ALLOC_OR_FAIL(key->groups, key->num_groups);
for (int j = 0; j < key->num_groups; j++) {
for (unsigned j = 0; j < key->num_groups; j++) {
FAIL_UNLESS(wire_sym_map->kt_index[j] < keymap->num_types);
key->groups[j].type = &keymap->types[wire_sym_map->kt_index[j]];
@ -424,7 +427,7 @@ get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn,
int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map);
xcb_keysym_t *syms_iter = xcb_xkb_key_sym_map_syms(wire_sym_map);
FAIL_UNLESS(syms_length == wire_sym_map->width * key->num_groups);
FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
for (int j = 0; j < syms_length; j++) {
xcb_keysym_t wire_keysym = *syms_iter;
@ -468,9 +471,12 @@ get_actions(struct xkb_keymap *keymap, xcb_connection_t *conn,
for (int i = 0; i < acts_count_length; i++) {
xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data;
int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map);
uint8_t wire_count = *acts_count_iter;
struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i];
FAIL_UNLESS(wire_count == 0 || wire_count == syms_length);
for (int j = 0; j < wire_count; j++) {
xcb_xkb_action_t *wire_action = acts_iter.data;
const xkb_layout_index_t group = j / wire_sym_map->width;
@ -505,8 +511,8 @@ get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn,
darray_resize0(keymap->mods,
NUM_REAL_MODS + msb_pos(reply->virtualMods));
for (int i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1 << i)) {
for (unsigned i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1u << i)) {
uint8_t wire = *iter;
struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
@ -530,11 +536,13 @@ get_explicits(struct xkb_keymap *keymap, xcb_connection_t *conn,
for (int i = 0; i < length; i++) {
xcb_xkb_set_explicit_t *wire = iter.data;
struct xkb_key *key = &keymap->keys[wire->keycode];
struct xkb_key *key;
FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
wire->keycode <= keymap->max_key_code);
key = &keymap->keys[wire->keycode];
if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_1) &&
key->num_groups > 0)
key->groups[0].explicit_type = true;
@ -573,11 +581,12 @@ get_modmaps(struct xkb_keymap *keymap, xcb_connection_t *conn,
for (int i = 0; i < length; i++) {
xcb_xkb_key_mod_map_t *wire = iter.data;
struct xkb_key *key = &keymap->keys[wire->keycode];
struct xkb_key *key;
FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
wire->keycode <= keymap->max_key_code);
key = &keymap->keys[wire->keycode];
key->modmap = wire->mods;
xcb_xkb_key_mod_map_next(&iter);
@ -599,11 +608,12 @@ get_vmodmaps(struct xkb_keymap *keymap, xcb_connection_t *conn,
for (int i = 0; i < length; i++) {
xcb_xkb_key_v_mod_map_t *wire = iter.data;
struct xkb_key *key = &keymap->keys[wire->keycode];
struct xkb_key *key;
FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
wire->keycode <= keymap->max_key_code);
key = &keymap->keys[wire->keycode];
key->vmodmap = translate_mods(0, wire->vmods, 0);
xcb_xkb_key_v_mod_map_next(&iter);
@ -677,8 +687,8 @@ get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn,
darray_resize0(keymap->leds, msb_pos(reply->which));
for (int i = 0; i < NUM_INDICATORS; i++) {
if (reply->which & (1 << i)) {
for (unsigned i = 0; i < NUM_INDICATORS; i++) {
if (reply->which & (1u << i)) {
xcb_xkb_indicator_map_t *wire = iter.data;
struct xkb_led *led = &darray_item(keymap->leds, i);
@ -879,8 +889,8 @@ get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
FAIL_UNLESS(msb_pos(reply->indicators) <= darray_size(keymap->leds));
for (int i = 0; i < NUM_INDICATORS; i++) {
if (reply->indicators & (1 << i)) {
for (unsigned i = 0; i < NUM_INDICATORS; i++) {
if (reply->indicators & (1u << i)) {
xcb_atom_t wire = *iter;
struct xkb_led *led = &darray_item(keymap->leds, i);
@ -911,8 +921,8 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
*/
darray_resize0(keymap->mods, NUM_REAL_MODS + msb_pos(reply->virtualMods));
for (int i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1 << i)) {
for (unsigned i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1u << i)) {
xcb_atom_t wire = *iter;
struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
@ -959,7 +969,7 @@ get_key_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
FAIL_UNLESS(reply->minKeyCode == keymap->min_key_code);
FAIL_UNLESS(reply->maxKeyCode == keymap->max_key_code);
FAIL_UNLESS(reply->firstKey == keymap->min_key_code);
FAIL_UNLESS(reply->firstKey + reply->nKeys - 1 == keymap->max_key_code);
FAIL_UNLESS(reply->firstKey + reply->nKeys - 1U == keymap->max_key_code);
for (int i = 0; i < length; i++) {
xcb_xkb_key_name_t *wire = iter.data;
@ -1023,7 +1033,7 @@ static bool
get_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
uint16_t device_id)
{
static const xcb_xkb_name_detail_t required_names =
static const xcb_xkb_name_detail_t wanted =
(XCB_XKB_NAME_DETAIL_KEYCODES |
XCB_XKB_NAME_DETAIL_SYMBOLS |
XCB_XKB_NAME_DETAIL_TYPES |
@ -1035,17 +1045,21 @@ get_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
XCB_XKB_NAME_DETAIL_KEY_ALIASES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES |
XCB_XKB_NAME_DETAIL_GROUP_NAMES);
static const xcb_xkb_name_detail_t required =
(XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
XCB_XKB_NAME_DETAIL_KEY_NAMES |
XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
xcb_xkb_get_names_cookie_t cookie =
xcb_xkb_get_names(conn, device_id, required_names);
xcb_xkb_get_names(conn, device_id, wanted);
xcb_xkb_get_names_reply_t *reply =
xcb_xkb_get_names_reply(conn, cookie, NULL);
xcb_xkb_get_names_value_list_t list;
FAIL_IF_BAD_REPLY(reply, "XkbGetNames");
if ((reply->which & required_names) != required_names)
goto fail;
FAIL_UNLESS((reply->which & required) == required);
xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply),
reply->nTypes,
@ -1093,13 +1107,14 @@ get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_xkb_get_controls_reply(conn, cookie, NULL);
FAIL_IF_BAD_REPLY(reply, "XkbGetControls");
FAIL_UNLESS(reply->numGroups > 0 && reply->numGroups <= 4);
keymap->enabled_ctrls = translate_controls_mask(reply->enabledControls);
keymap->num_groups = reply->numGroups;
FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8);
for (int i = keymap->min_key_code; i <= keymap->max_key_code; i++)
for (xkb_keycode_t i = keymap->min_key_code; i <= keymap->max_key_code; i++)
keymap->keys[i].repeats = !!(reply->perKeyRepeat[i / 8] & (1 << (i % 8)));
free(reply);
@ -1119,7 +1134,7 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx,
struct xkb_keymap *keymap;
const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}

View File

@ -26,8 +26,8 @@
#include <xcb/xkb.h>
#include "xkbcommon/xkbcommon-x11.h"
#include "keymap.h"
#include "xkbcommon/xkbcommon-x11.h"
/* Get a strdup'd name of an X atom. */
bool

View File

@ -110,10 +110,10 @@ get_keymap_format_ops(enum xkb_keymap_format format)
[XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
};
if ((int) format < 0 || (int) format >= ARRAY_SIZE(keymap_format_ops))
if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
return NULL;
return keymap_format_ops[format];
return keymap_format_ops[(int) format];
}
XKB_EXPORT struct xkb_keymap *
@ -132,33 +132,20 @@ xkb_keymap_new_from_names(struct xkb_context *ctx,
return NULL;
}
if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}
keymap = xkb_keymap_new(ctx, format, flags);
if (!keymap)
return NULL;
if (rmlvo_in)
rmlvo = *rmlvo_in;
else
memset(&rmlvo, 0, sizeof(rmlvo));
if (isempty(rmlvo.rules))
rmlvo.rules = xkb_context_get_default_rules(ctx);
if (isempty(rmlvo.model))
rmlvo.model = xkb_context_get_default_model(ctx);
/* Layout and variant are tied together, so don't try to use one from
* the caller and one from the environment. */
if (isempty(rmlvo.layout)) {
rmlvo.layout = xkb_context_get_default_layout(ctx);
rmlvo.variant = xkb_context_get_default_variant(ctx);
}
/* Options can be empty, so respect that if passed in. */
if (rmlvo.options == NULL)
rmlvo.options = xkb_context_get_default_options(ctx);
keymap = xkb_keymap_new(ctx, format, flags);
if (!keymap)
return NULL;
xkb_context_sanitize_rule_names(ctx, &rmlvo);
if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
xkb_keymap_unref(keymap);
@ -193,7 +180,7 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx,
return NULL;
}
if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}
@ -230,7 +217,7 @@ xkb_keymap_new_from_file(struct xkb_context *ctx,
return NULL;
}
if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}

View File

@ -118,6 +118,8 @@ NewActionsInfo(void)
/* Increment default button. */
info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.flags = 0;
info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.value = 1;
info->actions[ACTION_TYPE_PTR_MOVE].ptr.flags = ACTION_ACCEL;
info->actions[ACTION_TYPE_SWITCH_VT].screen.flags = ACTION_SAME_SCREEN;
return info;
}
@ -186,10 +188,10 @@ fieldText(enum action_field field)
/***====================================================================***/
static inline bool
ReportMismatch(struct xkb_keymap *keymap, enum xkb_action_type action,
ReportMismatch(struct xkb_context *ctx, enum xkb_action_type action,
enum action_field field, const char *type)
{
log_err(keymap->ctx,
log_err(ctx,
"Value of %s field must be of type %s; "
"Action %s definition ignored\n",
fieldText(field), type, ActionTypeText(action));
@ -197,10 +199,10 @@ ReportMismatch(struct xkb_keymap *keymap, enum xkb_action_type action,
}
static inline bool
ReportIllegal(struct xkb_keymap *keymap, enum xkb_action_type action,
ReportIllegal(struct xkb_context *ctx, enum xkb_action_type action,
enum action_field field)
{
log_err(keymap->ctx,
log_err(ctx,
"Field %s is not defined for an action of type %s; "
"Action definition ignored\n",
fieldText(field), ActionTypeText(action));
@ -208,10 +210,10 @@ ReportIllegal(struct xkb_keymap *keymap, enum xkb_action_type action,
}
static inline bool
ReportActionNotArray(struct xkb_keymap *keymap, enum xkb_action_type action,
ReportActionNotArray(struct xkb_context *ctx, enum xkb_action_type action,
enum action_field field)
{
log_err(keymap->ctx,
log_err(ctx,
"The %s field in the %s action is not an array; "
"Action definition ignored\n",
fieldText(field), ActionTypeText(action));
@ -228,42 +230,40 @@ HandleNoAction(struct xkb_keymap *keymap, union xkb_action *action,
}
static bool
CheckLatchLockFlags(struct xkb_keymap *keymap, enum xkb_action_type action,
enum action_field field, const ExprDef *value,
enum xkb_action_flags *flags_inout)
CheckBooleanFlag(struct xkb_context *ctx, enum xkb_action_type action,
enum action_field field, enum xkb_action_flags flag,
const ExprDef *array_ndx, const ExprDef *value,
enum xkb_action_flags *flags_inout)
{
enum xkb_action_flags tmp;
bool result;
bool set;
if (field == ACTION_FIELD_CLEAR_LOCKS)
tmp = ACTION_LOCK_CLEAR;
else if (field == ACTION_FIELD_LATCH_TO_LOCK)
tmp = ACTION_LATCH_TO_LOCK;
if (array_ndx)
return ReportActionNotArray(ctx, action, field);
if (!ExprResolveBoolean(ctx, value, &set))
return ReportMismatch(ctx, action, field, "boolean");
if (set)
*flags_inout |= flag;
else
return false; /* WSGO! */
if (!ExprResolveBoolean(keymap->ctx, value, &result))
return ReportMismatch(keymap, action, field, "boolean");
if (result)
*flags_inout |= tmp;
else
*flags_inout &= ~tmp;
*flags_inout &= ~flag;
return true;
}
static bool
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)
const ExprDef *array_ndx, const ExprDef *value,
enum xkb_action_flags *flags_inout, xkb_mod_mask_t *mods_rtrn)
{
if (array_ndx)
return ReportActionNotArray(keymap->ctx, action, ACTION_FIELD_MODIFIERS);
if (value->expr.op == EXPR_IDENT) {
const char *valStr;
valStr = xkb_atom_text(keymap->ctx, value->ident.ident);
if (valStr && (istreq(valStr, "usemodmapmods") ||
istreq(valStr, "modmapmods"))) {
*mods_rtrn = 0;
*flags_inout |= ACTION_MODS_LOOKUP_MODMAP;
return true;
@ -271,232 +271,13 @@ CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action,
}
if (!ExprResolveModMask(keymap, value, MOD_BOTH, mods_rtrn))
return ReportMismatch(keymap, action,
return ReportMismatch(keymap->ctx, action,
ACTION_FIELD_MODIFIERS, "modifier mask");
*flags_inout &= ~ACTION_MODS_LOOKUP_MODMAP;
return true;
}
static bool
HandleSetLatchMods(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_mod_action *act = &action->mods;
enum xkb_action_flags rtrn, t1;
xkb_mod_mask_t t2;
if (array_ndx != NULL) {
switch (field) {
case ACTION_FIELD_CLEAR_LOCKS:
case ACTION_FIELD_LATCH_TO_LOCK:
case ACTION_FIELD_MODIFIERS:
return ReportActionNotArray(keymap, action->type, field);
default:
break;
}
}
switch (field) {
case ACTION_FIELD_CLEAR_LOCKS:
case ACTION_FIELD_LATCH_TO_LOCK:
rtrn = act->flags;
if (CheckLatchLockFlags(keymap, action->type, field, value, &rtrn)) {
act->flags = rtrn;
return true;
}
return false;
case ACTION_FIELD_MODIFIERS:
t1 = act->flags;
if (CheckModifierField(keymap, action->type, value, &t1, &t2)) {
act->flags = t1;
act->mods.mods = t2;
return true;
}
return false;
default:
break;
}
return ReportIllegal(keymap, action->type, field);
}
static bool
HandleLockMods(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_mod_action *act = &action->mods;
enum xkb_action_flags t1;
xkb_mod_mask_t t2;
if (array_ndx && field == ACTION_FIELD_MODIFIERS)
return ReportActionNotArray(keymap, action->type, field);
switch (field) {
case ACTION_FIELD_MODIFIERS:
t1 = act->flags;
if (CheckModifierField(keymap, action->type, value, &t1, &t2)) {
act->flags = t1;
act->mods.mods = t2;
return true;
}
return false;
default:
break;
}
return ReportIllegal(keymap, action->type, field);
}
static bool
CheckGroupField(struct xkb_keymap *keymap, unsigned action,
const ExprDef *value, enum xkb_action_flags *flags_inout,
xkb_layout_index_t *grp_rtrn)
{
const ExprDef *spec;
if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
*flags_inout &= ~ACTION_ABSOLUTE_SWITCH;
spec = value->unary.child;
}
else {
*flags_inout |= ACTION_ABSOLUTE_SWITCH;
spec = value;
}
if (!ExprResolveGroup(keymap->ctx, spec, grp_rtrn))
return ReportMismatch(keymap, action, ACTION_FIELD_GROUP,
"integer (range 1..8)");
if (value->expr.op == EXPR_NEGATE)
*grp_rtrn = -*grp_rtrn;
else if (value->expr.op != EXPR_UNARY_PLUS)
(*grp_rtrn)--;
return true;
}
static bool
HandleSetLatchGroup(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_group_action *act = &action->group;
enum xkb_action_flags rtrn, t1;
xkb_layout_index_t t2;
if (array_ndx != NULL) {
switch (field) {
case ACTION_FIELD_CLEAR_LOCKS:
case ACTION_FIELD_LATCH_TO_LOCK:
case ACTION_FIELD_GROUP:
return ReportActionNotArray(keymap, action->type, field);
default:
break;
}
}
switch (field) {
case ACTION_FIELD_CLEAR_LOCKS:
case ACTION_FIELD_LATCH_TO_LOCK:
rtrn = act->flags;
if (CheckLatchLockFlags(keymap, action->type, field, value, &rtrn)) {
act->flags = rtrn;
return true;
}
return false;
case ACTION_FIELD_GROUP:
t1 = act->flags;
if (CheckGroupField(keymap, action->type, value, &t1, &t2)) {
act->flags = t1;
act->group = t2;
return true;
}
return false;
default:
break;
}
return ReportIllegal(keymap, action->type, field);
}
static bool
HandleLockGroup(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_group_action *act = &action->group;
enum xkb_action_flags t1;
xkb_layout_index_t t2;
if ((array_ndx != NULL) && (field == ACTION_FIELD_GROUP))
return ReportActionNotArray(keymap, action->type, field);
if (field == ACTION_FIELD_GROUP) {
t1 = act->flags;
if (CheckGroupField(keymap, action->type, value, &t1, &t2)) {
act->flags = t1;
act->group = t2;
return true;
}
return false;
}
return ReportIllegal(keymap, action->type, field);
}
static bool
HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_pointer_action *act = &action->ptr;
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;
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");
if (field == ACTION_FIELD_X) {
if (absolute)
act->flags |= ACTION_ABSOLUTE_X;
act->x = val;
}
else {
if (absolute)
act->flags |= ACTION_ABSOLUTE_Y;
act->y = val;
}
return true;
}
else if (field == ACTION_FIELD_ACCEL) {
bool set;
if (!ExprResolveBoolean(keymap->ctx, value, &set))
return ReportMismatch(keymap, action->type, field, "boolean");
if (set)
act->flags &= ~ACTION_NO_ACCEL;
else
act->flags |= ACTION_NO_ACCEL;
}
return ReportIllegal(keymap, action->type, field);
}
static const LookupEntry lockWhich[] = {
{ "both", 0 },
{ "lock", ACTION_LOCK_NO_UNLOCK },
@ -505,6 +286,165 @@ static const LookupEntry lockWhich[] = {
{ NULL, 0 }
};
static bool
CheckAffectField(struct xkb_context *ctx, enum xkb_action_type action,
const ExprDef *array_ndx, const ExprDef *value,
enum xkb_action_flags *flags_inout)
{
enum xkb_action_flags flags;
if (array_ndx)
return ReportActionNotArray(ctx, action, ACTION_FIELD_AFFECT);
if (!ExprResolveEnum(ctx, value, &flags, lockWhich))
return ReportMismatch(ctx, action, ACTION_FIELD_AFFECT,
"lock, unlock, both, neither");
*flags_inout &= ~(ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK);
*flags_inout |= flags;
return true;
}
static bool
HandleSetLatchLockMods(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_mod_action *act = &action->mods;
const enum xkb_action_type type = action->type;
if (field == ACTION_FIELD_MODIFIERS)
return CheckModifierField(keymap, action->type, array_ndx, value,
&act->flags, &act->mods.mods);
if ((type == ACTION_TYPE_MOD_SET || type == ACTION_TYPE_MOD_LATCH) &&
field == ACTION_FIELD_CLEAR_LOCKS)
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_LOCK_CLEAR, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_MOD_LATCH &&
field == ACTION_FIELD_LATCH_TO_LOCK)
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_LATCH_TO_LOCK, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_MOD_LOCK &&
field == ACTION_FIELD_AFFECT)
return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
&act->flags);
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
CheckGroupField(struct xkb_context *ctx, unsigned action,
const ExprDef *array_ndx, const ExprDef *value,
enum xkb_action_flags *flags_inout, int32_t *group_rtrn)
{
const ExprDef *spec;
xkb_layout_index_t idx;
enum xkb_action_flags flags = *flags_inout;
if (array_ndx)
return ReportActionNotArray(ctx, action, ACTION_FIELD_GROUP);
if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
flags &= ~ACTION_ABSOLUTE_SWITCH;
spec = value->unary.child;
}
else {
flags |= ACTION_ABSOLUTE_SWITCH;
spec = value;
}
if (!ExprResolveGroup(ctx, spec, &idx))
return ReportMismatch(ctx, action, ACTION_FIELD_GROUP,
"integer (range 1..8)");
/* +n, -n are relative, n is absolute. */
if (value->expr.op == EXPR_NEGATE || value->expr.op == EXPR_UNARY_PLUS) {
*group_rtrn = (int32_t) idx;
if (value->expr.op == EXPR_NEGATE)
*group_rtrn = -*group_rtrn;
}
else {
*group_rtrn = (int32_t) (idx - 1);
}
*flags_inout = flags;
return true;
}
static bool
HandleSetLatchLockGroup(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_group_action *act = &action->group;
const enum xkb_action_type type = action->type;
if (field == ACTION_FIELD_GROUP)
return CheckGroupField(keymap->ctx, action->type, array_ndx, value,
&act->flags, &act->group);
if ((type == ACTION_TYPE_GROUP_SET || type == ACTION_TYPE_GROUP_LATCH) &&
field == ACTION_FIELD_CLEAR_LOCKS)
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_LOCK_CLEAR, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_GROUP_LATCH &&
field == ACTION_FIELD_LATCH_TO_LOCK)
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_LATCH_TO_LOCK, array_ndx, value,
&act->flags);
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
const ExprDef *value)
{
struct xkb_pointer_action *act = &action->ptr;
if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) {
int val;
const bool absolute = (value->expr.op != EXPR_NEGATE &&
value->expr.op != EXPR_UNARY_PLUS);
if (array_ndx)
return ReportActionNotArray(keymap->ctx, action->type, field);
if (!ExprResolveInteger(keymap->ctx, value, &val))
return ReportMismatch(keymap->ctx, action->type, field, "integer");
if (val < INT16_MIN || val > INT16_MAX) {
log_err(keymap->ctx,
"The %s field in the %s action must be in range %d..%d; "
"Action definition ignored\n",
fieldText(field), ActionTypeText(action->type),
INT16_MIN, INT16_MAX);
return false;
}
if (field == ACTION_FIELD_X) {
if (absolute)
act->flags |= ACTION_ABSOLUTE_X;
act->x = (int16_t) val;
}
else {
if (absolute)
act->flags |= ACTION_ABSOLUTE_Y;
act->y = (int16_t) val;
}
return true;
}
else if (field == ACTION_FIELD_ACCEL) {
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_ACCEL, array_ndx, value, &act->flags);
}
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
enum action_field field, const ExprDef *array_ndx,
@ -516,10 +456,10 @@ HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
int btn;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
if (!ExprResolveButton(keymap->ctx, value, &btn))
return ReportMismatch(keymap, action->type, field,
return ReportMismatch(keymap->ctx, action->type, field,
"integer (range 1..5)");
if (btn < 0 || btn > 5) {
@ -534,40 +474,30 @@ HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
}
else if (action->type == ACTION_TYPE_PTR_LOCK &&
field == ACTION_FIELD_AFFECT) {
enum xkb_action_flags val;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
if (!ExprResolveEnum(keymap->ctx, value, &val, lockWhich))
return ReportMismatch(keymap, action->type, field,
"lock or unlock");
act->flags &= ~(ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK);
act->flags |= val;
return true;
return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
&act->flags);
}
else if (field == ACTION_FIELD_COUNT) {
int btn;
int val;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
/* XXX: Should this actually be ResolveButton? */
if (!ExprResolveButton(keymap->ctx, value, &btn))
return ReportMismatch(keymap, action->type, field, "integer");
if (!ExprResolveInteger(keymap->ctx, value, &val))
return ReportMismatch(keymap->ctx, action->type, field, "integer");
if (btn < 0 || btn > 255) {
if (val < 0 || val > 255) {
log_err(keymap->ctx,
"The count field must have a value in the range 0..255; "
"Illegal count %d ignored\n", btn);
"Illegal count %d ignored\n", val);
return false;
}
act->count = btn;
act->count = (uint8_t) val;
return true;
}
return ReportIllegal(keymap, action->type, field);
return ReportIllegal(keymap->ctx, action->type, field);
}
static const LookupEntry ptrDflts[] = {
@ -588,10 +518,10 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
unsigned int val;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
if (!ExprResolveEnum(keymap->ctx, value, &val, ptrDflts))
return ReportMismatch(keymap, action->type, field,
return ReportMismatch(keymap->ctx, action->type, field,
"pointer component");
return true;
}
@ -600,7 +530,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
int btn;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
@ -613,7 +543,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
}
if (!ExprResolveButton(keymap->ctx, button, &btn))
return ReportMismatch(keymap, action->type, field,
return ReportMismatch(keymap->ctx, action->type, field,
"integer (range 1..5)");
if (btn < 0 || btn > 5) {
@ -633,7 +563,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
return ReportIllegal(keymap, action->type, field);
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
@ -648,7 +578,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
int val;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
@ -661,7 +591,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
}
if (!ExprResolveInteger(keymap->ctx, scrn, &val))
return ReportMismatch(keymap, action->type, field,
return ReportMismatch(keymap->ctx, action->type, field,
"integer (0..255)");
if (val < 0 || val > 255) {
@ -675,23 +605,12 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
else if (field == ACTION_FIELD_SAME) {
bool set;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
if (!ExprResolveBoolean(keymap->ctx, value, &set))
return ReportMismatch(keymap, action->type, field, "boolean");
if (set)
act->flags &= ~ACTION_SAME_SCREEN;
else
act->flags |= ACTION_SAME_SCREEN;
return true;
return CheckBooleanFlag(keymap->ctx, action->type, field,
ACTION_SAME_SCREEN, array_ndx, value,
&act->flags);
}
return ReportIllegal(keymap, action->type, field);
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
@ -705,17 +624,21 @@ HandleSetLockControls(struct xkb_keymap *keymap, union xkb_action *action,
unsigned int mask;
if (array_ndx)
return ReportActionNotArray(keymap, action->type, field);
return ReportActionNotArray(keymap->ctx, action->type, field);
if (!ExprResolveMask(keymap->ctx, value, &mask, ctrlMaskNames))
return ReportMismatch(keymap, action->type, field,
return ReportMismatch(keymap->ctx, action->type, field,
"controls mask");
act->ctrls = mask;
return true;
}
else if (field == ACTION_FIELD_AFFECT) {
return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
&act->flags);
}
return ReportIllegal(keymap, action->type, field);
return ReportIllegal(keymap->ctx, action->type, field);
}
static bool
@ -728,8 +651,11 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
if (field == ACTION_FIELD_TYPE) {
int type;
if (array_ndx)
return ReportActionNotArray(keymap->ctx, action->type, field);
if (!ExprResolveInteger(keymap->ctx, value, &type))
return ReportMismatch(keymap, ACTION_TYPE_PRIVATE, field, "integer");
return ReportMismatch(keymap->ctx, ACTION_TYPE_PRIVATE, field, "integer");
if (type < 0 || type > 255) {
log_err(keymap->ctx,
@ -764,17 +690,17 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
if (array_ndx == NULL) {
xkb_atom_t val;
const char *str;
int len;
size_t len;
if (!ExprResolveString(keymap->ctx, value, &val))
return ReportMismatch(keymap, action->type, field, "string");
return ReportMismatch(keymap->ctx, action->type, field, "string");
str = xkb_atom_text(keymap->ctx, val);
len = strlen(str);
if (len < 1 || len > 7) {
log_warn(keymap->ctx,
"A private action has 7 data bytes; "
"Extra %d bytes ignored\n", len - 6);
"Illegal data ignored\n");
return false;
}
@ -791,7 +717,7 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
return false;
}
if (ndx < 0 || ndx >= sizeof(act->data)) {
if (ndx < 0 || (size_t) ndx >= sizeof(act->data)) {
log_err(keymap->ctx,
"The data for a private action is %lu bytes long; "
"Attempt to use data[%d] ignored\n",
@ -800,7 +726,7 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
}
if (!ExprResolveInteger(keymap->ctx, value, &datum))
return ReportMismatch(keymap, act->type, field, "integer");
return ReportMismatch(keymap->ctx, act->type, field, "integer");
if (datum < 0 || datum > 255) {
log_err(keymap->ctx,
@ -814,7 +740,7 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
}
}
return ReportIllegal(keymap, ACTION_TYPE_NONE, field);
return ReportIllegal(keymap->ctx, ACTION_TYPE_NONE, field);
}
typedef bool (*actionHandler)(struct xkb_keymap *keymap,
@ -825,12 +751,12 @@ typedef bool (*actionHandler)(struct xkb_keymap *keymap,
static const actionHandler handleAction[_ACTION_TYPE_NUM_ENTRIES] = {
[ACTION_TYPE_NONE] = HandleNoAction,
[ACTION_TYPE_MOD_SET] = HandleSetLatchMods,
[ACTION_TYPE_MOD_LATCH] = HandleSetLatchMods,
[ACTION_TYPE_MOD_LOCK] = HandleLockMods,
[ACTION_TYPE_GROUP_SET] = HandleSetLatchGroup,
[ACTION_TYPE_GROUP_LATCH] = HandleSetLatchGroup,
[ACTION_TYPE_GROUP_LOCK] = HandleLockGroup,
[ACTION_TYPE_MOD_SET] = HandleSetLatchLockMods,
[ACTION_TYPE_MOD_LATCH] = HandleSetLatchLockMods,
[ACTION_TYPE_MOD_LOCK] = HandleSetLatchLockMods,
[ACTION_TYPE_GROUP_SET] = HandleSetLatchLockGroup,
[ACTION_TYPE_GROUP_LATCH] = HandleSetLatchLockGroup,
[ACTION_TYPE_GROUP_LOCK] = HandleSetLatchLockGroup,
[ACTION_TYPE_PTR_MOVE] = HandleMovePtr,
[ACTION_TYPE_PTR_BUTTON] = HandlePtrBtn,
[ACTION_TYPE_PTR_LOCK] = HandlePtrBtn,
@ -921,7 +847,6 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
return true;
}
bool
SetActionField(struct xkb_keymap *keymap, const char *elem, const char *field,
ExprDef *array_ndx, ExprDef *value, ActionsInfo *info)

View File

@ -53,7 +53,6 @@
#include "xkbcomp-priv.h"
#include "ast-build.h"
#include "parser-priv.h"
#include "include.h"
ParseCommon *
@ -202,7 +201,7 @@ ExprCreateKeysymList(xkb_keysym_t sym)
ExprDef *
ExprCreateMultiKeysymList(ExprDef *expr)
{
size_t nLevels = darray_size(expr->keysym_list.symsMapIndex);
unsigned nLevels = darray_size(expr->keysym_list.symsMapIndex);
darray_resize(expr->keysym_list.symsMapIndex, 1);
darray_resize(expr->keysym_list.symsNumEntries, 1);
@ -215,7 +214,7 @@ ExprCreateMultiKeysymList(ExprDef *expr)
ExprDef *
ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
{
size_t nSyms = darray_size(expr->keysym_list.syms);
unsigned nSyms = darray_size(expr->keysym_list.syms);
darray_append(expr->keysym_list.symsMapIndex, nSyms);
darray_append(expr->keysym_list.symsNumEntries, 1);
@ -227,8 +226,8 @@ ExprAppendKeysymList(ExprDef *expr, xkb_keysym_t sym)
ExprDef *
ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append)
{
size_t nSyms = darray_size(expr->keysym_list.syms);
size_t numEntries = darray_size(append->keysym_list.syms);
unsigned nSyms = darray_size(expr->keysym_list.syms);
unsigned numEntries = darray_size(append->keysym_list.syms);
darray_append(expr->keysym_list.symsMapIndex, nSyms);
darray_append(expr->keysym_list.symsNumEntries, numEntries);
@ -356,7 +355,7 @@ SymbolsCreate(xkb_atom_t keyName, VarDef *symbols)
}
GroupCompatDef *
GroupCompatCreate(int group, ExprDef *val)
GroupCompatCreate(unsigned group, ExprDef *val)
{
GroupCompatDef *def = malloc(sizeof(*def));
if (!def)
@ -372,7 +371,7 @@ GroupCompatCreate(int group, ExprDef *val)
}
ModMapDef *
ModMapCreate(uint32_t modifier, ExprDef *keys)
ModMapCreate(xkb_atom_t modifier, ExprDef *keys)
{
ModMapDef *def = malloc(sizeof(*def));
if (!def)
@ -404,7 +403,7 @@ LedMapCreate(xkb_atom_t name, VarDef *body)
}
LedNameDef *
LedNameCreate(int ndx, ExprDef *name, bool virtual)
LedNameCreate(unsigned ndx, ExprDef *name, bool virtual)
{
LedNameDef *def = malloc(sizeof(*def));
if (!def)
@ -496,8 +495,8 @@ err:
}
XkbFile *
XkbFileCreate(struct xkb_context *ctx, enum xkb_file_type type, char *name,
ParseCommon *defs, enum xkb_map_flags flags)
XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs,
enum xkb_map_flags flags)
{
XkbFile *file;
@ -533,7 +532,7 @@ XkbFileFromComponents(struct xkb_context *ctx,
if (!include)
goto err;
file = XkbFileCreate(ctx, type, NULL, &include->common, 0);
file = XkbFileCreate(type, NULL, (ParseCommon *) include, 0);
if (!file) {
FreeInclude(include);
goto err;
@ -542,7 +541,7 @@ XkbFileFromComponents(struct xkb_context *ctx,
defs = AppendStmt(defs, &file->common);
}
file = XkbFileCreate(ctx, FILE_TYPE_KEYMAP, NULL, defs, 0);
file = XkbFileCreate(FILE_TYPE_KEYMAP, NULL, defs, 0);
if (!file)
goto err;
@ -565,7 +564,7 @@ FreeExpr(ExprDef *expr)
case EXPR_UNARY_PLUS:
case EXPR_NOT:
case EXPR_INVERT:
FreeStmt(&expr->unary.child->common);
FreeStmt((ParseCommon *) expr->unary.child);
break;
case EXPR_DIVIDE:
@ -573,16 +572,16 @@ FreeExpr(ExprDef *expr)
case EXPR_SUBTRACT:
case EXPR_MULTIPLY:
case EXPR_ASSIGN:
FreeStmt(&expr->binary.left->common);
FreeStmt(&expr->binary.right->common);
FreeStmt((ParseCommon *) expr->binary.left);
FreeStmt((ParseCommon *) expr->binary.right);
break;
case EXPR_ACTION_DECL:
FreeStmt(&expr->action.args->common);
FreeStmt((ParseCommon *) expr->action.args);
break;
case EXPR_ARRAY_REF:
FreeStmt(&expr->array_ref.entry->common);
FreeStmt((ParseCommon *) expr->array_ref.entry);
break;
case EXPR_KEYSYM_LIST:
@ -619,12 +618,10 @@ void
FreeStmt(ParseCommon *stmt)
{
ParseCommon *next;
YYSTYPE u;
while (stmt)
{
next = stmt->next;
u.any = stmt;
switch (stmt->type) {
case STMT_INCLUDE:
@ -633,36 +630,36 @@ FreeStmt(ParseCommon *stmt)
stmt = NULL;
break;
case STMT_EXPR:
FreeExpr(u.expr);
FreeExpr((ExprDef *) stmt);
break;
case STMT_VAR:
FreeStmt(&u.var->name->common);
FreeStmt(&u.var->value->common);
FreeStmt((ParseCommon *) ((VarDef *) stmt)->name);
FreeStmt((ParseCommon *) ((VarDef *) stmt)->value);
break;
case STMT_TYPE:
FreeStmt(&u.keyType->body->common);
FreeStmt((ParseCommon *) ((KeyTypeDef *) stmt)->body);
break;
case STMT_INTERP:
FreeStmt(&u.interp->match->common);
FreeStmt(&u.interp->def->common);
FreeStmt((ParseCommon *) ((InterpDef *) stmt)->match);
FreeStmt((ParseCommon *) ((InterpDef *) stmt)->def);
break;
case STMT_VMOD:
FreeStmt(&u.vmod->value->common);
FreeStmt((ParseCommon *) ((VModDef *) stmt)->value);
break;
case STMT_SYMBOLS:
FreeStmt(&u.syms->symbols->common);
FreeStmt((ParseCommon *) ((SymbolsDef *) stmt)->symbols);
break;
case STMT_MODMAP:
FreeStmt(&u.modMask->keys->common);
FreeStmt((ParseCommon *) ((ModMapDef *) stmt)->keys);
break;
case STMT_GROUP_COMPAT:
FreeStmt(&u.groupCompat->def->common);
FreeStmt((ParseCommon *) ((GroupCompatDef *) stmt)->def);
break;
case STMT_LED_MAP:
FreeStmt(&u.ledMap->body->common);
FreeStmt((ParseCommon *) ((LedMapDef *) stmt)->body);
break;
case STMT_LED_NAME:
FreeStmt(&u.ledName->name->common);
FreeStmt((ParseCommon *) ((LedNameDef *) stmt)->name);
break;
default:
break;

View File

@ -98,23 +98,23 @@ SymbolsDef *
SymbolsCreate(xkb_atom_t keyName, VarDef *symbols);
GroupCompatDef *
GroupCompatCreate(int group, ExprDef *def);
GroupCompatCreate(unsigned group, ExprDef *def);
ModMapDef *
ModMapCreate(uint32_t modifier, ExprDef *keys);
ModMapCreate(xkb_atom_t modifier, ExprDef *keys);
LedMapDef *
LedMapCreate(xkb_atom_t name, VarDef *body);
LedNameDef *
LedNameCreate(int ndx, ExprDef *name, bool virtual);
LedNameCreate(unsigned ndx, ExprDef *name, bool virtual);
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, enum xkb_map_flags flags);
XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs,
enum xkb_map_flags flags);
void
FreeStmt(ParseCommon *stmt);

View File

@ -143,9 +143,7 @@ expr_op_type_to_string(enum expr_op_type type);
const char *
expr_value_type_to_string(enum expr_value_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 {
typedef struct _ParseCommon {
struct _ParseCommon *next;
enum stmt_type type;
} ParseCommon;
@ -226,7 +224,7 @@ typedef struct {
typedef struct {
ExprCommon expr;
darray(xkb_keysym_t) syms;
darray(int) symsMapIndex;
darray(unsigned int) symsMapIndex;
darray(unsigned int) symsNumEntries;
} ExprKeysymList;
@ -299,7 +297,7 @@ typedef struct {
typedef struct {
ParseCommon common;
enum merge_mode merge;
int group;
unsigned group;
ExprDef *def;
} GroupCompatDef;
@ -314,7 +312,7 @@ typedef struct {
typedef struct {
ParseCommon common;
enum merge_mode merge;
int ndx;
unsigned ndx;
ExprDef *name;
bool virtual;
} LedNameDef;

View File

@ -54,179 +54,6 @@
#include "vmod.h"
#include "include.h"
/*
* The xkb_compat section
* =====================
* This section is the third to be processed, after xkb_keycodes and
* xkb_types.
*
* Interpret statements
* --------------------
* Statements of the form:
* interpret Num_Lock+Any { ... }
* interpret Shift_Lock+AnyOf(Shift+Lock) { ... }
*
* The xkb_symbols section (see symbols.c) allows the keymap author to do,
* among other things, the following for each key:
* - Bind an action, like SetMods or LockGroup, to the key. Actions, like
* symbols, are specified for each level of each group in the key
* separately.
* - Add a virtual modifier to the key's virtual modifier mapping (vmodmap).
* - Specify whether the key should repeat or not.
*
* However, doing this for each key (or level) is tedious and inflexible.
* Interpret's are a mechanism to apply these settings to a bunch of
* keys/levels at once.
*
* Each interpret specifies a condition by which it attaches to certain
* levels. The condition consists of two parts:
* - A keysym. If the level has a different (or more than one) keysym, the
* match failes. Leaving out the keysym is equivalent to using the
* NoSymbol keysym, which always matches successfully.
* - A modifier predicate. The predicate consists of a matching operation
* and a mask of (real) modifiers. The modifers are matched against the
* key's modifier map (modmap). The matching operation can be one of the
* following:
* + AnyOfOrNone - The modmap must either be empty or include at least
* one of the specified modifiers.
* + AnyOf - The modmap must include at least one of the specified
* modifiers.
* + NoneOf - The modmap must not include any of the specified modifiers.
* + AllOf - The modmap must include all of the specified modifiers (but
* may include others as well).
* + Exactly - The modmap must be exactly the same as the specified
* modifiers.
* Leaving out the predicate is equivalent to usign AnyOfOrNone while
* specifying all modifiers. Leaving out just the matching condtition
* is equivalent to using Exactly.
* An interpret may also include "useModMapMods = level1;" - see below.
*
* If a level fulfils the conditions of several interpret's, only the
* most specific one is used:
* - A specific keysym will always match before a generic NoSymbol
* condition.
* - If the keysyms are the same, the interpret with the more specific
* matching operation is used. The above list is sorted from least to
* most specific.
* - If both the keysyms and the matching operations are the same (but the
* modifiers are different), the first interpret is used.
*
* As described above, once an interpret "attaches" to a level, it can bind
* an action to that level, add one virtual modifier to the key's vmodmap,
* or set the key's repeat setting. You should note the following:
* - The key repeat is a property of the entire key; it is not level-specific.
* In order to avoid confusion, it is only inspected for the first level of
* the first group; the interpret's repeat setting is ignored when applied
* to other levels.
* - If one of the above fields was set directly for a key in xkb_symbols,
* the explicit setting takes precedence over the interpret.
*
* The body of the statment may include statements of the following
* forms (all of which are optional):
*
* - useModMapMods statement:
* useModMapMods = level1;
*
* When set to 'level1', the interpret will only match levels which are
* the first level of the first group of the keys. This can be useful in
* conjunction with e.g. a virtualModifier statement.
*
* - action statement:
* action = LockMods(modifiers=NumLock);
*
* Bind this action to the matching levels.
*
* - virtual modifier statement:
* virtualModifier = NumLock;
*
* Add this virtual modifier to the key's vmodmap. The given virtual
* modifier must be declared at the top level of the file with a
* virtual_modifiers statement, e.g.:
* virtual_modifiers NumLock;
*
* - repeat statement:
* repeat = True;
*
* Set whether the key should repeat or not. Must be a boolean value.
*
* Led map statements
* ------------------------
* Statements of the form:
* indicator "Shift Lock" { ... }
*
* This statement specifies the behavior and binding of the LED (a.k.a
* indicator) with the given name ("Shift Lock" above). The name should
* have been declared previously in the xkb_keycodes section (see Led
* name statement), and given an index there. If it wasn't, it is created
* with the next free index.
* The body of the statement describes the conditions of the keyboard
* state which will cause the LED to be lit. It may include the following
* statements:
*
* - modifiers statment:
* modifiers = ScrollLock;
*
* If the given modifiers are in the required state (see below), the
* led is lit.
*
* - whichModifierState statment:
* whichModState = Latched + Locked;
*
* Can be any combination of:
* base, latched, locked, effective
* any (i.e. all of the above)
* none (i.e. none of the above)
* compat (legacy value, treated as effective)
* This will cause the respective portion of the modifer state (see
* struct xkb_state) to be matched against the modifiers given in the
* "modifiers" statement.
*
* Here's a simple example:
* indicator "Num Lock" {
* modifiers = NumLock;
* whichModState = Locked;
* };
* Whenever the NumLock modifier is locked, the Num Lock LED will light
* up.
*
* - groups statment:
* groups = All - group1;
*
* If the given groups are in the required state (see below), the led
* is lit.
*
* - whichGroupState statment:
* whichGroupState = Effective;
*
* Can be any combination of:
* base, latched, locked, effective
* any (i.e. all of the above)
* none (i.e. none of the above)
* This will cause the respective portion of the group state (see
* struct xkb_state) to be matched against the groups given in the
* "groups" statement.
*
* Note: the above conditions are disjunctive, i.e. if any of them are
* satisfied the led is lit.
*
* Virtual modifier statements
* ---------------------------
* Statements of the form:
* virtual_modifiers LControl;
*
* Can appear in the xkb_types, xkb_compat, xkb_symbols sections.
* TODO
*
* Effect on keymap
* ----------------
* After all of the xkb_compat sections have been compiled, the following
* members of struct xkb_keymap are finalized:
* darray(struct xkb_sym_interpret) sym_interprets;
* darray(struct xkb_led) leds;
* char *compat_section_name;
* TODO: virtual modifiers.
*/
enum si_field {
SI_FIELD_VIRTUAL_MOD = (1 << 0),
SI_FIELD_ACTION = (1 << 1),
@ -555,16 +382,28 @@ MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from,
from->name = NULL;
}
darray_foreach(si, from->interps) {
si->merge = (merge == MERGE_DEFAULT ? si->merge : merge);
if (!AddInterp(into, si, false))
into->errorCount++;
if (darray_empty(into->interps)) {
into->interps = from->interps;
darray_init(from->interps);
}
else {
darray_foreach(si, from->interps) {
si->merge = (merge == MERGE_DEFAULT ? si->merge : merge);
if (!AddInterp(into, si, false))
into->errorCount++;
}
}
darray_foreach(ledi, from->leds) {
ledi->merge = (merge == MERGE_DEFAULT ? ledi->merge : merge);
if (!AddLedMap(into, ledi, false))
into->errorCount++;
if (darray_empty(into->leds)) {
into->leds = from->leds;
darray_init(from->leds);
}
else {
darray_foreach(ledi, from->leds) {
ledi->merge = (merge == MERGE_DEFAULT ? ledi->merge : merge);
if (!AddLedMap(into, ledi, false))
into->errorCount++;
}
}
}
@ -929,7 +768,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
ok = HandleVModDef(info->keymap, (VModDef *) stmt);
ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
default:
log_err(info->keymap->ctx,

View File

@ -116,7 +116,7 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
if (ndx == XKB_MOD_INVALID)
return false;
*val_rtrn = (1 << ndx);
*val_rtrn = (1u << ndx);
return true;
}
@ -427,14 +427,8 @@ ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr,
bool
ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int *btn_rtrn)
{
int result;
if (!ExprResolveIntegerLookup(ctx, expr, &result, SimpleLookup,
buttonNames))
return false;
*btn_rtrn = result;
return true;
return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup,
buttonNames);
}
bool

View File

@ -29,79 +29,6 @@
#include "expr.h"
#include "include.h"
/*
* The xkb_keycodes section
* ========================
*
* This is the simplest section type, and is the first one to be
* compiled. The purpose of this is mostly to map between the
* hardware/evdev scancodes and xkb keycodes. Each key is given a name
* by which it can be referred to later, e.g. in the symbols section.
*
* Keycode statements
* ------------------
* Statements of the form:
* <TLDE> = 49;
* <AE01> = 10;
*
* The above would let 49 and 10 be valid keycodes in the keymap, and
* assign them the names TLDE and AE01 respectively. The format <WXYZ> is
* always used to refer to a key by name.
*
* [ The naming convention <AE01> just denoted the position of the key
* in the main alphanumric section of the keyboard, with the two letters
* specifying the row and the two digits specifying the column, from
* the bottom left.]
*
* In the common case this just maps to the evdev scancodes from
* /usr/include/linux/input.h, e.g. the following definitions:
* #define KEY_GRAVE 41
* #define KEY_1 2
* Similar definitions appear in the xf86-input-keyboard driver. Note
* that in all current keymaps there's a constant offset of 8 (for
* historical reasons).
*
* If there's a conflict, like the same name given to different keycodes,
* or same keycode given different names, it is resolved according to the
* merge mode which applies to the definitions.
*
* Alias statements
* ----------------
* Statements of the form:
* alias <MENU> = <COMP>;
*
* Allows to refer to a previously defined key (here <COMP>) by another
* name (here <MENU>). Conflicts are handled similarly.
*
* LED name statements
* -------------------------
* Statements of the form:
* indicator 1 = "Caps Lock";
* indicator 2 = "Num Lock";
* indicator 3 = "Scroll Lock";
*
* Assigns a name to the keyboard LED (a.k.a indicator) with the given index.
* The led may be referred by this name later in the compat section
* and by the user.
*
* Effect on the keymap
* --------------------
* After all of the xkb_keycodes sections have been compiled, the
* following members of struct xkb_keymap are finalized:
* xkb_keycode_t min_key_code;
* xkb_keycode_t max_key_code;
* unsigned int num_aliases;
* struct xkb_key_alias *key_aliases;
* char *keycodes_section_name;
* The 'name' field of leds declared in xkb_keycodes:
* darray(struct xkb_led) leds;
* Further, the array of keys:
* struct xkb_key *keys;
* had been resized to its final size (i.e. all of the xkb_key objects are
* referable by their keycode). However the objects themselves do not
* contain any useful information besides the key name at this point.
*/
typedef struct {
enum merge_mode merge;
@ -322,7 +249,7 @@ AddKeyName(KeyNamesInfo *info, xkb_keycode_t kc, xkb_atom_t name,
/***====================================================================***/
static int
static bool
HandleAliasDef(KeyNamesInfo *info, KeyAliasDef *def, enum merge_mode merge);
static void
@ -459,7 +386,7 @@ HandleKeycodeDef(KeyNamesInfo *info, KeycodeDef *stmt, enum merge_mode merge)
return AddKeyName(info, stmt->value, stmt->name, merge, false, true);
}
static int
static bool
HandleAliasDef(KeyNamesInfo *info, KeyAliasDef *def, enum merge_mode merge)
{
AliasInfo *old, new;
@ -499,7 +426,7 @@ HandleAliasDef(KeyNamesInfo *info, KeyAliasDef *def, enum merge_mode merge)
return true;
}
static int
static bool
HandleKeyNameVar(KeyNamesInfo *info, VarDef *stmt)
{
const char *elem, *field;
@ -524,7 +451,7 @@ HandleKeyNameVar(KeyNamesInfo *info, VarDef *stmt)
return true;
}
static int
static bool
HandleLedNameDef(KeyNamesInfo *info, LedNameDef *def,
enum merge_mode merge)
{

View File

@ -92,7 +92,7 @@ check_write_buf(struct buf *buf, const char *fmt, ...)
if (printed < 0)
goto err;
if (printed >= available)
if ((size_t) printed >= available)
if (!do_realloc(buf, printed))
goto err;
@ -103,7 +103,7 @@ check_write_buf(struct buf *buf, const char *fmt, ...)
printed = vsnprintf(buf->buf + buf->size, available, fmt, args);
va_end(args);
if (printed >= available || printed < 0)
if (printed < 0 || (size_t) printed >= available)
goto err;
buf->size += printed;
@ -273,6 +273,20 @@ write_led_map(struct xkb_keymap *keymap, struct buf *buf,
return true;
}
static const char *
affect_lock_text(enum xkb_action_flags flags)
{
switch (flags & (ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK)) {
case ACTION_LOCK_NO_UNLOCK:
return ",affect=lock";
case ACTION_LOCK_NO_LOCK:
return ",affect=unlock";
case ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK:
return ",affect=neither";
}
return "";
}
static bool
write_action(struct xkb_keymap *keymap, struct buf *buf,
const union xkb_action *action,
@ -289,20 +303,17 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
type = ActionTypeText(action->type);
switch (action->type) {
case ACTION_TYPE_MOD_LOCK:
case ACTION_TYPE_MOD_SET:
case ACTION_TYPE_MOD_LATCH:
case ACTION_TYPE_MOD_LOCK:
if (action->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
args = "modMapMods";
else
args = ModMaskText(keymap, action->mods.mods.mods);
write_buf(buf, "%s%s(modifiers=%s%s%s)%s", prefix, type, args,
(action->type != ACTION_TYPE_MOD_LOCK &&
(action->mods.flags & ACTION_LOCK_CLEAR)) ?
",clearLocks" : "",
(action->type != ACTION_TYPE_MOD_LOCK &&
(action->mods.flags & ACTION_LATCH_TO_LOCK)) ?
",latchToLock" : "",
write_buf(buf, "%s%s(modifiers=%s%s%s%s)%s", prefix, type, args,
(action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LOCK_CLEAR)) ? ",clearLocks" : "",
(action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LATCH_TO_LOCK)) ? ",latchToLock" : "",
(action->type == ACTION_TYPE_MOD_LOCK) ? affect_lock_text(action->mods.flags) : "",
suffix);
break;
@ -310,16 +321,10 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
case ACTION_TYPE_GROUP_LATCH:
case ACTION_TYPE_GROUP_LOCK:
write_buf(buf, "%s%s(group=%s%d%s%s)%s", prefix, type,
(!(action->group.flags & ACTION_ABSOLUTE_SWITCH) &&
action->group.group > 0) ? "+" : "",
(action->group.flags & ACTION_ABSOLUTE_SWITCH) ?
action->group.group + 1 : action->group.group,
(action->type != ACTION_TYPE_GROUP_LOCK &&
(action->group.flags & ACTION_LOCK_CLEAR)) ?
",clearLocks" : "",
(action->type != ACTION_TYPE_GROUP_LOCK &&
(action->group.flags & ACTION_LATCH_TO_LOCK)) ?
",latchToLock" : "",
(!(action->group.flags & ACTION_ABSOLUTE_SWITCH) && action->group.group > 0) ? "+" : "",
(action->group.flags & ACTION_ABSOLUTE_SWITCH) ? action->group.group + 1 : action->group.group,
(action->type != ACTION_TYPE_GROUP_LOCK && (action->group.flags & ACTION_LOCK_CLEAR)) ? ",clearLocks" : "",
(action->type != ACTION_TYPE_GROUP_LOCK && (action->group.flags & ACTION_LATCH_TO_LOCK)) ? ",latchToLock" : "",
suffix);
break;
@ -329,35 +334,17 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
case ACTION_TYPE_PTR_MOVE:
write_buf(buf, "%s%s(x=%s%d,y=%s%d%s)%s", prefix, type,
(!(action->ptr.flags & ACTION_ABSOLUTE_X) &&
action->ptr.x >= 0) ? "+" : "",
(!(action->ptr.flags & ACTION_ABSOLUTE_X) && action->ptr.x >= 0) ? "+" : "",
action->ptr.x,
(!(action->ptr.flags & ACTION_ABSOLUTE_Y) &&
action->ptr.y >= 0) ? "+" : "",
(!(action->ptr.flags & ACTION_ABSOLUTE_Y) && action->ptr.y >= 0) ? "+" : "",
action->ptr.y,
(action->ptr.flags & ACTION_NO_ACCEL) ? ",!accel" : "",
(action->ptr.flags & ACTION_ACCEL) ? "" : ",!accel",
suffix);
break;
case ACTION_TYPE_PTR_LOCK:
switch (action->btn.flags &
(ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK)) {
case ACTION_LOCK_NO_UNLOCK:
args = ",affect=lock";
break;
case ACTION_LOCK_NO_LOCK:
args = ",affect=unlock";
break;
case ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK:
args = ",affect=neither";
break;
default:
args = ",affect=both";
break;
}
args = affect_lock_text(action->btn.flags);
/* fallthrough */
case ACTION_TYPE_PTR_BUTTON:
write_buf(buf, "%s%s(button=", prefix, type);
if (action->btn.button > 0 && action->btn.button <= 5)
@ -374,25 +361,25 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
case ACTION_TYPE_PTR_DEFAULT:
write_buf(buf, "%s%s(", prefix, type);
write_buf(buf, "affect=button,button=%s%d",
(!(action->dflt.flags & ACTION_ABSOLUTE_SWITCH) &&
action->dflt.value >= 0) ? "+" : "",
(!(action->dflt.flags & ACTION_ABSOLUTE_SWITCH) && action->dflt.value >= 0) ? "+" : "",
action->dflt.value);
write_buf(buf, ")%s", suffix);
break;
case ACTION_TYPE_SWITCH_VT:
write_buf(buf, "%s%s(screen=%s%d,%ssame)%s", prefix, type,
(!(action->screen.flags & ACTION_ABSOLUTE_SWITCH) &&
action->screen.screen >= 0) ? "+" : "",
(!(action->screen.flags & ACTION_ABSOLUTE_SWITCH) && action->screen.screen >= 0) ? "+" : "",
action->screen.screen,
(action->screen.flags & ACTION_SAME_SCREEN) ? "!" : "",
(action->screen.flags & ACTION_SAME_SCREEN) ? "" : "!",
suffix);
break;
case ACTION_TYPE_CTRL_SET:
case ACTION_TYPE_CTRL_LOCK:
write_buf(buf, "%s%s(controls=%s)%s", prefix, type,
ControlMaskText(keymap->ctx, action->ctrls.ctrls), suffix);
write_buf(buf, "%s%s(controls=%s%s)%s", prefix, type,
ControlMaskText(keymap->ctx, action->ctrls.ctrls),
(action->type == ACTION_TYPE_CTRL_LOCK) ? affect_lock_text(action->ctrls.flags) : "",
suffix);
break;
case ACTION_TYPE_NONE:
@ -429,7 +416,7 @@ write_compat(struct xkb_keymap *keymap, struct buf *buf)
write_buf(buf, "\tinterpret.useModMapMods= AnyLevel;\n");
write_buf(buf, "\tinterpret.repeat= False;\n");
for (int i = 0; i < keymap->num_sym_interprets; i++) {
for (unsigned 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",
@ -635,7 +622,7 @@ write_symbols(struct xkb_keymap *keymap, struct buf *buf)
continue;
darray_enumerate(i, mod, keymap->mods)
if (key->modmap & (1 << i))
if (key->modmap & (1u << i))
write_buf(buf, "\tmodifier_map %s { %s };\n",
xkb_atom_text(keymap->ctx, mod->name),
KeyNameText(keymap->ctx, key->name));

View File

@ -39,7 +39,7 @@ ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
mods->mask = mods->mods & MOD_REAL_MASK_ALL;
darray_enumerate(i, mod, keymap->mods)
if (mods->mods & (1 << i))
if (mods->mods & (1u << i))
mods->mask |= mod->mapping;
}
@ -92,7 +92,7 @@ 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.
*/
for (int i = 0; i < keymap->num_sym_interprets; i++) {
for (unsigned i = 0; i < keymap->num_sym_interprets; i++) {
const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
xkb_mod_mask_t mods;
@ -158,7 +158,7 @@ ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
if ((group == 0 && level == 0) || !interp->level_one_only)
if (interp->virtual_mod != XKB_MOD_INVALID)
vmodmap |= (1 << interp->virtual_mod);
vmodmap |= (1u << interp->virtual_mod);
if (interp->action.type != ACTION_TYPE_NONE)
key->groups[group].levels[level].action = interp->action;
@ -194,7 +194,7 @@ UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
/* Update keymap->mods, the virtual -> real mod mapping. */
xkb_foreach_key(key, keymap)
darray_enumerate(i, mod, keymap->mods)
if (key->vmodmap & (1 << i))
if (key->vmodmap & (1u << i))
mod->mapping |= key->modmap;
/* Now update the level masks for all the types to reflect the vmods. */

View File

@ -339,10 +339,9 @@ keyword_gperf_lookup (register const char *str, register unsigned int len)
int
keyword_to_token(const char *string)
keyword_to_token(const char *string, unsigned int len)
{
const struct keyword_tok *kt;
kt = keyword_gperf_lookup(string, strlen(string));
const struct keyword_tok *kt = keyword_gperf_lookup(string, len);
if (!kt)
return -1;
return kt->tok;

View File

@ -27,24 +27,18 @@
#ifndef XKBCOMP_PARSER_PRIV_H
#define XKBCOMP_PARSER_PRIV_H
struct scanner;
struct parser_param;
#include "scanner-utils.h"
#include "parser.h"
int
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);
parse(struct xkb_context *ctx, struct scanner *scanner, const char *map);
int
keyword_to_token(const char *string);
keyword_to_token(const char *string, unsigned int len);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -175,7 +175,7 @@ typedef union YYSTYPE
{
/* Line 2068 of yacc.c */
#line 167 "parser.y"
#line 161 "parser.y"
int ival;
int64_t num;

View File

@ -52,84 +52,6 @@
#include "include.h"
#include "scanner-utils.h"
/*
* The rules file
* ==============
* The purpose of this file is to map between configuration values that
* are easy for a user to specify and understand, and the configuration
* values xkbcomp uses and understands.
* xkbcomp uses the xkb_component_names struct, which maps directly to
* include statements of the appropriate sections, called for short
* KcCGST (see keycodes.c, types.c, compat.c, symbols.c; geometry.c was
* removed). These are not really intuitive or straight-forward for
* the uninitiated.
* Instead, the user passes in a xkb_rule_names struct, which consists
* of the name of a rules file (in Linux this is usually "evdev"), a
* keyboard model (e.g. "pc105"), a set of layouts (which will end up
* in different groups, e.g. "us,fr"), variants (used to alter/augment
* the respective layout, e.g. "intl,dvorak"), and a set of options
* (used to tweak some general behavior of the keyboard, e.g.
* "ctrl:nocaps,compose:menu" to make the Caps Lock key act like Ctrl
* and the Menu key like Compose). We call these RMLVO.
*
* Format of the file
* ------------------
* The file consists of rule sets, each consisting of rules (one per
* line), which match the MLVO values on the left hand side, and, if
* the values match to the values the user passed in, results in the
* values on the right hand side being added to the resulting KcCGST.
* Since some values are related and repeated often, it is possible
* to group them together and refer to them by a group name in the
* rules.
* Along with matching values by simple string equality, and for
* membership in a group defined previously, rules may also contain
* "wildcard" values - "*" - which always match. These usually appear
* near the end.
*
* Grammer
* -------
* (It might be helpful to look at a file like rules/evdev along with
* this grammer. Comments, whitespace, etc. are not shown.)
*
* File ::= { "!" (Group | RuleSet) }
*
* Group ::= GroupName "=" { GroupElement } "\n"
* GroupName ::= "$"<ident>
* GroupElement ::= <ident>
*
* RuleSet ::= Mapping { Rule }
*
* Mapping ::= { Mlvo } "=" { Kccgst } "\n"
* Mlvo ::= "model" | "option" | ("layout" | "variant") [ Index ]
* Index ::= "[" 1..XKB_NUM_GROUPS "]"
* Kccgst ::= "keycodes" | "symbols" | "types" | "compat" | "geometry"
*
* Rule ::= { MlvoValue } "=" { KccgstValue } "\n"
* MlvoValue ::= "*" | GroupName | <ident>
* KccgstValue ::= <ident>
*
* Notes:
* - The order of values in a Rule must be the same as the Mapping it
* follows. The mapping line determines the meaning of the values in
* the rules which follow in the RuleSet.
* - If a Rule is matched, %-expansion is performed on the KccgstValue,
* as follows:
* %m, %l, %v:
* The model, layout or variant, if only one was given (e.g.
* %l for "us,il" is invalid).
* %l[1], %v[1]:
* Layout or variant for the specified group Index, if more than
* one was given (e.g. %l[1] for "us" is invalid).
* %+m, %+l, %+v, %+l[1], %+v[1]
* As above, but prefixed with '+'. Similarly, '|', '-', '_' may be
* used instead of '+'.
* %(m), %(l), %(l[1]), %(v), %(v[1]):
* As above, but prefixed by '(' and suffixed by ')'.
* In case the expansion is invalid, as described above, it is
* skipped (the rest of the string is still processed); this includes
* the prefix and suffix (that's why you shouldn't use e.g. "(%v[1])").
*/
/* Scanner / Lexer */
/* Values returned with some tokens, like yylval. */
@ -137,14 +59,6 @@ union lvalue {
struct sval string;
};
/*
* Holds the location in the file of the last processed token,
* like yylloc.
*/
struct location {
int line, column;
};
enum rules_token {
TOK_END_OF_FILE = 0,
TOK_END_OF_LINE,
@ -156,14 +70,6 @@ enum rules_token {
TOK_ERROR
};
/* 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: %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__)
static inline bool
is_ident(char ch)
{
@ -171,7 +77,7 @@ is_ident(char ch)
}
static enum rules_token
lex(struct scanner *s, union lvalue *val, struct location *loc)
lex(struct scanner *s, union lvalue *val)
{
skip_more_whitespace_and_comments:
/* Skip spaces. */
@ -191,8 +97,7 @@ skip_more_whitespace_and_comments:
/* Escaped line continuation. */
if (chr(s, '\\')) {
if (!eol(s)) {
scanner_error1(s, loc,
"illegal new line escape; must appear at end of line");
scanner_err(s, "illegal new line escape; must appear at end of line");
return TOK_ERROR;
}
next(s);
@ -203,8 +108,8 @@ skip_more_whitespace_and_comments:
if (eof(s)) return TOK_END_OF_FILE;
/* New token. */
loc->line = s->line;
loc->column = s->column;
s->token_line = s->line;
s->token_column = s->column;
/* Operators and punctuation. */
if (chr(s, '!')) return TOK_BANG;
@ -220,8 +125,7 @@ skip_more_whitespace_and_comments:
val->string.len++;
}
if (val->string.len == 0) {
scanner_error1(s, loc,
"unexpected character after \'$\'; expected name");
scanner_err(s, "unexpected character after \'$\'; expected name");
return TOK_ERROR;
}
return TOK_GROUP_NAME;
@ -238,7 +142,7 @@ skip_more_whitespace_and_comments:
return TOK_IDENTIFIER;
}
scanner_error1(s, loc, "unrecognized token");
scanner_err(s, "unrecognized token");
return TOK_ERROR;
}
@ -330,7 +234,6 @@ struct matcher {
struct xkb_context *ctx;
/* Input.*/
struct rule_names rmlvo;
struct location loc;
union lvalue val;
struct scanner scanner;
darray(struct group) groups;
@ -410,10 +313,8 @@ matcher_free(struct matcher *m)
free(m);
}
#define matcher_error1(matcher, msg) \
scanner_error1(&(matcher)->scanner, &(matcher)->loc, msg)
#define matcher_error(matcher, fmt, ...) \
scanner_error(&(matcher)->scanner, &(matcher)->loc, fmt, __VA_ARGS__)
#define matcher_err(matcher, fmt, ...) \
scanner_err(&(matcher)->scanner, fmt, ## __VA_ARGS__)
static void
matcher_group_start_new(struct matcher *m, struct sval name)
@ -474,19 +375,15 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident)
/* Not found. */
if (mlvo >= _MLVO_NUM_ENTRIES) {
matcher_error(m,
"invalid mapping: %.*s is not a valid value here; "
"ignoring rule set",
ident.len, ident.start);
matcher_err(m, "invalid mapping: %.*s is not a valid value here; ignoring rule set",
ident.len, ident.start);
m->mapping.skip = true;
return;
}
if (m->mapping.defined_mlvo_mask & (1 << mlvo)) {
matcher_error(m,
"invalid mapping: %.*s appears twice on the same line; "
"ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
if (m->mapping.defined_mlvo_mask & (1u << mlvo)) {
matcher_err(m, "invalid mapping: %.*s appears twice on the same line; ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
m->mapping.skip = true;
return;
}
@ -497,10 +394,8 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident)
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; "
"ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
matcher_err(m, "invalid mapping: \"%.*s\" may only be followed by a valid group index; ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
m->mapping.skip = true;
return;
}
@ -512,17 +407,15 @@ matcher_mapping_set_mlvo(struct matcher *m, struct sval ident)
m->mapping.variant_idx = idx;
}
else {
matcher_error(m,
"invalid mapping: \"%.*s\" cannot be followed by a group index; "
"ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
matcher_err(m, "invalid mapping: \"%.*s\" cannot be followed by a group index; ignoring rule set",
mlvo_sval.len, mlvo_sval.start);
m->mapping.skip = true;
return;
}
}
m->mapping.mlvo_at_pos[m->mapping.num_mlvo] = mlvo;
m->mapping.defined_mlvo_mask |= 1 << mlvo;
m->mapping.defined_mlvo_mask |= 1u << mlvo;
m->mapping.num_mlvo++;
}
@ -541,25 +434,21 @@ matcher_mapping_set_kccgst(struct matcher *m, struct sval ident)
/* Not found. */
if (kccgst >= _KCCGST_NUM_ENTRIES) {
matcher_error(m,
"invalid mapping: %.*s is not a valid value here; "
"ignoring rule set",
ident.len, ident.start);
matcher_err(m, "invalid mapping: %.*s is not a valid value here; ignoring rule set",
ident.len, ident.start);
m->mapping.skip = true;
return;
}
if (m->mapping.defined_kccgst_mask & (1 << kccgst)) {
matcher_error(m,
"invalid mapping: %.*s appears twice on the same line; "
"ignoring rule set",
kccgst_sval.len, kccgst_sval.start);
if (m->mapping.defined_kccgst_mask & (1u << kccgst)) {
matcher_err(m, "invalid mapping: %.*s appears twice on the same line; ignoring rule set",
kccgst_sval.len, kccgst_sval.start);
m->mapping.skip = true;
return;
}
m->mapping.kccgst_at_pos[m->mapping.num_kccgst] = kccgst;
m->mapping.defined_kccgst_mask |= 1 << kccgst;
m->mapping.defined_kccgst_mask |= 1u << kccgst;
m->mapping.num_kccgst++;
}
@ -567,16 +456,12 @@ static void
matcher_mapping_verify(struct matcher *m)
{
if (m->mapping.num_mlvo == 0) {
matcher_error1(m,
"invalid mapping: must have at least one value on the left hand side; "
"ignoring rule set");
matcher_err(m, "invalid mapping: must have at least one value on the left hand side; ignoring rule set");
goto skip;
}
if (m->mapping.num_kccgst == 0) {
matcher_error1(m,
"invalid mapping: must have at least one value on the right hand side; "
"ignoring rule set");
matcher_err(m, "invalid mapping: must have at least one value on the right hand side; ignoring rule set");
goto skip;
}
@ -585,7 +470,7 @@ matcher_mapping_verify(struct matcher *m)
* See the "Notes" section in the overview above.
*/
if (m->mapping.defined_mlvo_mask & (1 << MLVO_LAYOUT)) {
if (m->mapping.defined_mlvo_mask & (1u << MLVO_LAYOUT)) {
if (m->mapping.layout_idx == XKB_LAYOUT_INVALID) {
if (darray_size(m->rmlvo.layouts) > 1)
goto skip;
@ -597,7 +482,7 @@ matcher_mapping_verify(struct matcher *m)
}
}
if (m->mapping.defined_mlvo_mask & (1 << MLVO_VARIANT)) {
if (m->mapping.defined_mlvo_mask & (1u << MLVO_VARIANT)) {
if (m->mapping.variant_idx == XKB_LAYOUT_INVALID) {
if (darray_size(m->rmlvo.variants) > 1)
goto skip;
@ -627,9 +512,7 @@ matcher_rule_set_mlvo_common(struct matcher *m, struct sval ident,
enum mlvo_match_type match_type)
{
if (m->rule.num_mlvo_values + 1 > m->mapping.num_mlvo) {
matcher_error1(m,
"invalid rule: has more values than the mapping line; "
"ignoring rule");
matcher_err(m, "invalid rule: has more values than the mapping line; ignoring rule");
m->rule.skip = true;
return;
}
@ -661,9 +544,7 @@ static void
matcher_rule_set_kccgst(struct matcher *m, struct sval ident)
{
if (m->rule.num_kccgst_values + 1 > m->mapping.num_kccgst) {
matcher_error1(m,
"invalid rule: has more values than the mapping line; "
"ignoring rule");
matcher_err(m, "invalid rule: has more values than the mapping line; ignoring rule");
m->rule.skip = true;
return;
}
@ -720,20 +601,10 @@ static bool
append_expanded_kccgst_value(struct matcher *m, darray_char *to,
struct sval value)
{
const size_t original_size = darray_size(*to);
const char *s = value.start;
/*
* Appending bar to foo -> foo (not an error if this happens)
* Appending +bar to foo -> foo+bar
* Appending bar to +foo -> bar+foo
* Appending +bar to +foo -> +foo+bar
*/
if (!darray_empty(*to) && s[0] != '+' && s[0] != '|') {
if (darray_item(*to, 0) == '+' || darray_item(*to, 0) == '|')
darray_prepend_items_nullterminate(*to, value.start, value.len);
return true;
}
darray_char expanded = darray_new();
char ch;
bool expanded_plus, to_plus;
/*
* Some ugly hand-lexing here, but going through the scanner is more
@ -743,12 +614,12 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
enum rules_mlvo mlv;
xkb_layout_index_t idx;
char pfx, sfx;
struct sval expanded;
struct sval expanded_value;
/* Check if that's a start of an expansion. */
if (s[i] != '%') {
/* Just a normal character. */
darray_append_items_nullterminate(*to, &s[i++], 1);
darray_appends_nullterminate(expanded, &s[i++], 1);
continue;
}
if (++i >= value.len) goto error;
@ -777,9 +648,7 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
int consumed;
if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) {
matcher_error1(m,
"invalid index in %%-expansion; "
"may only index layout or variant");
matcher_err(m, "invalid index in %%-expansion; may only index layout or variant");
goto error;
}
@ -795,46 +664,65 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
}
/* Get the expanded value. */
expanded.len = 0;
expanded_value.len = 0;
if (mlv == MLVO_LAYOUT) {
if (idx != XKB_LAYOUT_INVALID &&
idx < darray_size(m->rmlvo.layouts) &&
darray_size(m->rmlvo.layouts) > 1)
expanded = darray_item(m->rmlvo.layouts, idx);
expanded_value = darray_item(m->rmlvo.layouts, idx);
else if (idx == XKB_LAYOUT_INVALID &&
darray_size(m->rmlvo.layouts) == 1)
expanded = darray_item(m->rmlvo.layouts, 0);
expanded_value = darray_item(m->rmlvo.layouts, 0);
}
else if (mlv == MLVO_VARIANT) {
if (idx != XKB_LAYOUT_INVALID &&
idx < darray_size(m->rmlvo.variants) &&
darray_size(m->rmlvo.variants) > 1)
expanded = darray_item(m->rmlvo.variants, idx);
expanded_value = darray_item(m->rmlvo.variants, idx);
else if (idx == XKB_LAYOUT_INVALID &&
darray_size(m->rmlvo.variants) == 1)
expanded = darray_item(m->rmlvo.variants, 0);
expanded_value = darray_item(m->rmlvo.variants, 0);
}
else if (mlv == MLVO_MODEL) {
expanded = m->rmlvo.model;
expanded_value = m->rmlvo.model;
}
/* If we didn't get one, skip silently. */
if (expanded.len <= 0)
if (expanded_value.len <= 0)
continue;
if (pfx != 0)
darray_append_items_nullterminate(*to, &pfx, 1);
darray_append_items_nullterminate(*to, expanded.start, expanded.len);
darray_appends_nullterminate(expanded, &pfx, 1);
darray_appends_nullterminate(expanded,
expanded_value.start, expanded_value.len);
if (sfx != 0)
darray_append_items_nullterminate(*to, &sfx, 1);
darray_appends_nullterminate(expanded, &sfx, 1);
}
/*
* Appending bar to foo -> foo (not an error if this happens)
* Appending +bar to foo -> foo+bar
* Appending bar to +foo -> bar+foo
* Appending +bar to +foo -> +foo+bar
*/
ch = (darray_empty(expanded) ? '\0' : darray_item(expanded, 0));
expanded_plus = (ch == '+' || ch == '|');
ch = (darray_empty(*to) ? '\0' : darray_item(*to, 0));
to_plus = (ch == '+' || ch == '|');
if (expanded_plus || darray_empty(*to))
darray_appends_nullterminate(*to, expanded.item, expanded.size);
else if (to_plus)
darray_prepends_nullterminate(*to, expanded.item, expanded.size);
darray_free(expanded);
return true;
error:
matcher_error1(m, "invalid %%-expansion in value; not used");
darray_resize(*to, original_size);
darray_free(expanded);
matcher_err(m, "invalid %%-expansion in value; not used");
return false;
}
@ -843,9 +731,7 @@ matcher_rule_verify(struct matcher *m)
{
if (m->rule.num_mlvo_values != m->mapping.num_mlvo ||
m->rule.num_kccgst_values != m->mapping.num_kccgst) {
matcher_error1(m,
"invalid rule: must have same number of values as mapping line;"
"ignoring rule");
matcher_err(m, "invalid rule: must have same number of values as mapping line; ignoring rule");
m->rule.skip = true;
}
}
@ -907,7 +793,7 @@ matcher_rule_apply_if_matches(struct matcher *m)
static enum rules_token
gettok(struct matcher *m)
{
return lex(&m->scanner, &m->val, &m->loc);
return lex(&m->scanner, &m->val);
}
static bool
@ -1068,7 +954,7 @@ finish:
return true;
state_error:
matcher_error1(m, "unexpected token");
matcher_err(m, "unexpected token");
error:
return false;
}
@ -1091,12 +977,13 @@ xkb_components_from_rules(struct xkb_context *ctx,
ret = map_file(file, &string, &size);
if (!ret) {
log_err(ctx, "Couldn't read rules file: %s\n", strerror(errno));
log_err(ctx, "Couldn't read rules file \"%s\": %s\n",
path, strerror(errno));
goto err_file;
}
matcher = matcher_new(ctx, rmlvo);
ret = matcher_match(matcher, string, size, rmlvo->rules, out);
ret = matcher_match(matcher, string, size, path, out);
if (!ret)
log_err(ctx, "No components returned from XKB rules \"%s\"\n", path);
matcher_free(matcher);

View File

@ -23,27 +23,6 @@
#include "xkbcomp-priv.h"
#include "parser-priv.h"
#include "scanner-utils.h"
static void
scanner_log(enum xkb_log_level level, struct scanner *s, const char *msg)
{
xkb_log(s->ctx, level, 0, "%s:%d:%d: %s\n", s->file_name,
s->token_line, s->token_column, msg);
}
int
scanner_error(struct scanner *s, const char *msg)
{
scanner_log(XKB_LOG_LEVEL_ERROR, s, msg);
return ERROR_TOK;
}
void
scanner_warn(struct scanner *s, const char *msg)
{
scanner_log(XKB_LOG_LEVEL_WARNING, s, msg);
}
static bool
number(struct scanner *s, int64_t *out, int *out_tok)
@ -123,11 +102,13 @@ skip_more_whitespace_and_comments:
buf_append(s, next(s));
}
}
if (!buf_append(s, '\0') || !chr(s, '\"'))
return scanner_error(s, "unterminated string literal");
if (!buf_append(s, '\0') || !chr(s, '\"')) {
scanner_err(s, "unterminated string literal");
return ERROR_TOK;
}
yylval->str = strdup(s->buf);
if (!yylval->str)
return scanner_error(s, "scanner out of memory");
return ERROR_TOK;
return STRING;
}
@ -135,8 +116,10 @@ skip_more_whitespace_and_comments:
if (chr(s, '<')) {
while (is_graph(peek(s)) && peek(s) != '>')
buf_append(s, next(s));
if (!buf_append(s, '\0') || !chr(s, '>'))
return scanner_error(s, "unterminated key name literal");
if (!buf_append(s, '\0') || !chr(s, '>')) {
scanner_err(s, "unterminated key name literal");
return ERROR_TOK;
}
/* Empty key name literals are allowed. */
yylval->sval = xkb_atom_intern(s->ctx, s->buf, s->buf_pos - 1);
return KEYNAME;
@ -165,27 +148,32 @@ skip_more_whitespace_and_comments:
s->buf_pos = 0;
while (is_alnum(peek(s)) || peek(s) == '_')
buf_append(s, next(s));
if (!buf_append(s, '\0'))
return scanner_error(s, "identifier too long");
if (!buf_append(s, '\0')) {
scanner_err(s, "identifier too long");
return ERROR_TOK;
}
/* Keyword. */
tok = keyword_to_token(s->buf);
tok = keyword_to_token(s->buf, s->buf_pos - 1);
if (tok != -1) return tok;
yylval->str = strdup(s->buf);
if (!yylval->str)
return scanner_error(s, "scanner out of memory");
return ERROR_TOK;
return IDENT;
}
/* Number literal (hexadecimal / decimal / float). */
if (number(s, &yylval->num, &tok)) {
if (tok == ERROR_TOK)
return scanner_error(s, "malformed number literal");
if (tok == ERROR_TOK) {
scanner_err(s, "malformed number literal");
return ERROR_TOK;
}
return tok;
}
return scanner_error(s, "unrecognized token");
scanner_err(s, "unrecognized token");
return ERROR_TOK;
}
XkbFile *

View File

@ -125,12 +125,11 @@ ClearGroupInfo(GroupInfo *groupi)
static void
CopyGroupInfo(GroupInfo *to, const GroupInfo *from)
{
xkb_level_index_t j;
to->defined = from->defined;
to->type = from->type;
darray_init(to->levels);
darray_copy(to->levels, from->levels);
for (j = 0; j < darray_size(to->levels); j++)
for (xkb_level_index_t j = 0; j < darray_size(to->levels); j++)
if (darray_item(from->levels, j).num_syms > 1)
darray_item(to->levels, j).u.syms =
memdup(darray_item(from->levels, j).u.syms,
@ -480,7 +479,6 @@ static void
MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
enum merge_mode merge)
{
unsigned int i;
KeyInfo *keyi;
ModMapEntry *mm;
xkb_atom_t *group_name;
@ -498,7 +496,7 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
group_names_in_both = MIN(darray_size(into->group_names),
darray_size(from->group_names));
for (i = 0; i < group_names_in_both; i++) {
for (xkb_layout_index_t i = 0; i < group_names_in_both; i++) {
if (!darray_item(from->group_names, i))
continue;
@ -511,16 +509,28 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
darray_foreach_from(group_name, from->group_names, group_names_in_both)
darray_append(into->group_names, *group_name);
darray_foreach(keyi, from->keys) {
keyi->merge = (merge == MERGE_DEFAULT ? keyi->merge : merge);
if (!AddKeySymbols(into, keyi, false))
into->errorCount++;
if (darray_empty(into->keys)) {
into->keys = from->keys;
darray_init(from->keys);
}
else {
darray_foreach(keyi, from->keys) {
keyi->merge = (merge == MERGE_DEFAULT ? keyi->merge : merge);
if (!AddKeySymbols(into, keyi, false))
into->errorCount++;
}
}
darray_foreach(mm, from->modmaps) {
mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
if (!AddModMapEntry(into, mm))
into->errorCount++;
if (darray_empty(into->modmaps)) {
into->modmaps = from->modmaps;
darray_init(from->modmaps);
}
else {
darray_foreach(mm, from->modmaps) {
mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
if (!AddModMapEntry(into, mm))
into->errorCount++;
}
}
}
@ -633,8 +643,6 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
xkb_layout_index_t ndx;
GroupInfo *groupi;
xkb_level_index_t nLevels;
xkb_level_index_t i;
int j;
if (!GetGroupIndex(info, keyi, arrayNdx, SYMBOLS, &ndx))
return false;
@ -669,7 +677,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
groupi->defined |= GROUP_FIELD_SYMS;
for (i = 0; i < nLevels; i++) {
for (xkb_level_index_t i = 0; i < nLevels; i++) {
unsigned int sym_index;
struct xkb_level *leveli = &darray_item(groupi->levels, i);
@ -678,7 +686,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
if (leveli->num_syms > 1)
leveli->u.syms = calloc(leveli->num_syms, sizeof(*leveli->u.syms));
for (j = 0; j < leveli->num_syms; j++) {
for (unsigned j = 0; j < leveli->num_syms; j++) {
xkb_keysym_t keysym = darray_item(value->keysym_list.syms,
sym_index + j);
@ -701,7 +709,6 @@ static bool
AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
ExprDef *value)
{
unsigned int i;
xkb_layout_index_t ndx;
GroupInfo *groupi;
unsigned int nActs;
@ -742,7 +749,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
groupi->defined |= GROUP_FIELD_ACTS;
act = value->unary.child;
for (i = 0; i < nActs; i++) {
for (unsigned i = 0; i < nActs; i++) {
union xkb_action *toAct = &darray_item(groupi->levels, i).action;
if (!HandleActionDef(act, info->keymap, toAct, info->actions))
@ -772,19 +779,20 @@ static bool
SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
ExprDef *arrayNdx, ExprDef *value)
{
bool ok = true;
struct xkb_context *ctx = info->keymap->ctx;
if (istreq(field, "type")) {
xkb_layout_index_t ndx;
xkb_atom_t val;
if (!ExprResolveString(ctx, value, &val))
log_vrb(ctx, 1,
if (!ExprResolveString(ctx, value, &val)) {
log_err(ctx,
"The type field of a key symbol map must be a string; "
"Ignoring illegal type definition\n");
return false;
}
if (arrayNdx == NULL) {
if (!arrayNdx) {
keyi->default_type = val;
keyi->defined |= KEY_FIELD_DEFAULT_TYPE;
}
@ -803,32 +811,33 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
darray_item(keyi->groups, ndx).defined |= GROUP_FIELD_TYPE;
}
}
else if (istreq(field, "symbols"))
else if (istreq(field, "symbols")) {
return AddSymbolsToKey(info, keyi, arrayNdx, value);
else if (istreq(field, "actions"))
}
else if (istreq(field, "actions")) {
return AddActionsToKey(info, keyi, arrayNdx, value);
}
else if (istreq(field, "vmods") ||
istreq(field, "virtualmods") ||
istreq(field, "virtualmodifiers")) {
xkb_mod_mask_t mask;
ok = ExprResolveModMask(info->keymap, value, MOD_VIRT, &mask);
if (ok) {
keyi->vmodmap = mask;
keyi->defined |= KEY_FIELD_VMODMAP;
}
else {
log_err(info->keymap->ctx,
if (!ExprResolveModMask(info->keymap, value, MOD_VIRT, &mask)) {
log_err(ctx,
"Expected a virtual modifier mask, found %s; "
"Ignoring virtual modifiers definition for key %s\n",
expr_op_type_to_string(value->expr.op),
KeyInfoText(info, keyi));
return false;
}
keyi->vmodmap = mask;
keyi->defined |= KEY_FIELD_VMODMAP;
}
else if (istreq(field, "locking") ||
istreq(field, "lock") ||
istreq(field, "locks")) {
log_err(info->keymap->ctx,
log_vrb(ctx, 1,
"Key behaviors not supported; "
"Ignoring locking specification for key %s\n",
KeyInfoText(info, keyi));
@ -836,14 +845,14 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
else if (istreq(field, "radiogroup") ||
istreq(field, "permanentradiogroup") ||
istreq(field, "allownone")) {
log_err(info->keymap->ctx,
log_vrb(ctx, 1,
"Radio groups not supported; "
"Ignoring radio group specification for key %s\n",
KeyInfoText(info, keyi));
}
else if (istreq_prefix("overlay", field) ||
istreq_prefix("permanentoverlay", field)) {
log_err(info->keymap->ctx,
log_vrb(ctx, 1,
"Overlays not supported; "
"Ignoring overlay specification for key %s\n",
KeyInfoText(info, keyi));
@ -853,14 +862,14 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "repeat")) {
unsigned int val;
ok = ExprResolveEnum(ctx, value, &val, repeatEntries);
if (!ok) {
log_err(info->keymap->ctx,
if (!ExprResolveEnum(ctx, value, &val, repeatEntries)) {
log_err(ctx,
"Illegal repeat setting for %s; "
"Non-boolean repeat setting ignored\n",
KeyInfoText(info, keyi));
return false;
}
keyi->repeat = val;
keyi->defined |= KEY_FIELD_REPEAT;
}
@ -869,18 +878,14 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
bool set;
if (!ExprResolveBoolean(ctx, value, &set)) {
log_err(info->keymap->ctx,
log_err(ctx,
"Illegal groupsWrap setting for %s; "
"Non-boolean value ignored\n",
KeyInfoText(info, keyi));
return false;
}
if (set)
keyi->out_of_range_group_action = RANGE_WRAP;
else
keyi->out_of_range_group_action = RANGE_SATURATE;
keyi->out_of_range_group_action = (set ? RANGE_WRAP : RANGE_SATURATE);
keyi->defined |= KEY_FIELD_GROUPINFO;
}
else if (istreq(field, "groupsclamp") ||
@ -888,18 +893,14 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
bool set;
if (!ExprResolveBoolean(ctx, value, &set)) {
log_err(info->keymap->ctx,
log_err(ctx,
"Illegal groupsClamp setting for %s; "
"Non-boolean value ignored\n",
KeyInfoText(info, keyi));
return false;
}
if (set)
keyi->out_of_range_group_action = RANGE_SATURATE;
else
keyi->out_of_range_group_action = RANGE_WRAP;
keyi->out_of_range_group_action = (set ? RANGE_SATURATE : RANGE_WRAP);
keyi->defined |= KEY_FIELD_GROUPINFO;
}
else if (istreq(field, "groupsredirect") ||
@ -907,7 +908,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
xkb_layout_index_t grp;
if (!ExprResolveGroup(ctx, value, &grp)) {
log_err(info->keymap->ctx,
log_err(ctx,
"Illegal group index for redirect of key %s; "
"Definition with non-integer group ignored\n",
KeyInfoText(info, keyi));
@ -919,17 +920,17 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
keyi->defined |= KEY_FIELD_GROUPINFO;
}
else {
log_err(info->keymap->ctx,
log_err(ctx,
"Unknown field %s in a symbol interpretation; "
"Definition ignored\n",
field);
ok = false;
return false;
}
return ok;
return true;
}
static int
static bool
SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
{
xkb_layout_index_t group, group_to_use;
@ -979,16 +980,16 @@ SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
return true;
}
static int
static bool
HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
{
const char *elem, *field;
ExprDef *arrayNdx;
bool ret;
if (ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field,
&arrayNdx) == 0)
return 0; /* internal error, already reported */
if (!ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field, &arrayNdx))
return false;
if (elem && istreq(elem, "key")) {
ret = SetSymbolsField(info, &info->default_key, field, arrayNdx,
stmt->value);
@ -1098,16 +1099,15 @@ SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
return true;
}
static int
static bool
HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
{
KeyInfo keyi;
xkb_layout_index_t i;
keyi = info->default_key;
darray_init(keyi.groups);
darray_copy(keyi.groups, info->default_key.groups);
for (i = 0; i < darray_size(keyi.groups); i++)
for (xkb_layout_index_t i = 0; i < darray_size(keyi.groups); i++)
CopyGroupInfo(&darray_item(keyi.groups, i),
&darray_item(info->default_key.groups, i));
keyi.merge = stmt->merge;
@ -1134,7 +1134,6 @@ HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
static bool
HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
{
ExprDef *key;
ModMapEntry tmp;
xkb_mod_index_t ndx;
bool ok;
@ -1153,7 +1152,7 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
tmp.modifier = ndx;
tmp.merge = def->merge;
for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
for (ExprDef *key = def->keys; key; key = (ExprDef *) key->common.next) {
xkb_keysym_t sym;
if (key->expr.op == EXPR_VALUE &&
@ -1198,7 +1197,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
ok = HandleVModDef(info->keymap, (VModDef *) stmt);
ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
case STMT_MODMAP:
ok = HandleModMapDef(info, (ModMapDef *) stmt);
@ -1518,7 +1517,7 @@ CopyModMapDef(SymbolsInfo *info, ModMapEntry *entry)
}
}
key->modmap |= (1 << entry->modifier);
key->modmap |= (1u << entry->modifier);
return true;
}

View File

@ -30,111 +30,6 @@
#include "expr.h"
#include "include.h"
/*
* The xkb_types section
* =====================
* This section is the second to be processesed, after xkb_keycodes.
* However, it is completely independent and could have been the first
* to be processed (it does not refer to specific keys as specified in
* the xkb_keycodes section).
*
* This section defines key types, which, given a key and a keyboard
* state (i.e. modifier state and group), determine the shift level to
* be used in translating the key to keysyms. These types are assigned
* to each group in each key, in the xkb_symbols section.
*
* Key types are called this way because, in a way, they really describe
* the "type" of the key (or more correctly, a specific group of the
* key). For example, an ordinary keymap will provide a type called
* "KEYPAD", which consists of two levels, with the second level being
* chosen according to the state of the Num Lock (or Shift) modifiers.
* Another example is a type called "ONE_LEVEL", which is usually
* assigned to keys such as Escape; these have just one level and are
* not affected by the modifier state. Yet more common examples are
* "TWO_LEVEL" (with Shift choosing the second level), "ALPHABETIC"
* (where Caps Lock may also choose the second level), etc.
*
* Type definitions
* ----------------
* Statements of the form:
* type "FOUR_LEVEL" { ... }
*
* The above would create a new type named "FOUR_LEVEL".
* The body of the definition may include statements of the following
* forms:
*
* - level_name statements (mandatory for each level in the type):
* level_name[Level1] = "Base";
*
* Gives each level in this type a descriptive name. It isn't used
* for any thing.
* Note: A level may be specified as Level[1-8] or just a number (can
* be more than 8).
*
* - modifiers statement (mandatory, should be specified only once):
* modifiers = Shift+Lock+LevelThree;
*
* A mask of real and virtual modifiers. These are the only modifiers
* being considered when matching the modifier state against the type.
* The other modifiers, whether active or not, are masked out in the
* calculation.
*
* - map entry statements (should have at least as many mappings as there
* are levels in the type):
* map[Shift+LevelThree] = Level4;
*
* If the active modifiers, masked with the type's modifiers (as stated
* above), match (i.e. equal) the modifiers inside the map[] statement,
* then the level in the right hand side is chosen. For example, in the
* above, if in the current keyboard state the Shift and LevelThree
* modifiers are active, while the Lock modifier is not, then the
* keysym(s) in the 4th level of the group will be returned to the
* user.
*
* - preserve statements:
* map[Shift+Lock+LevelThree] = Level5;
* preserve[Shift+Lock+LevelThree] = Lock;
*
* When a map entry matches the active modifiers and the level it
* specified is chosen, then these modifiers are said to be "consumed";
* for example, in a simple US keymap where the "g" key is assigned an
* ordinary ALPHABETIC key type, if the Lock (Caps Lock) modifier is
* active and the key is pressed, then a "G" keysym is produced (as
* opposed to lower-case "g"). This is because the type definition has
* a map entry like the following:
* map[Lock] = Level2;
* And as such the Lock modifier is consumed. This information is
* relevant for applications which further process the modifiers,
* since by then the consumed modifiers have already "done their part"
* and should be masked out.
*
* However, sometimes even if a modifier is actually used to choose
* the shift level (as Lock above), it should *not* be reported as
* consumed, for various reasons. In this case, a preserve[] statement
* can be used to augment the map entry. The modifiers inside the square
* brackets should match one of the map[] statements in the type. The
* right hand side should consists of modifiers from the left hand
* side; these modifiers are then "preserved" and not reported as
* consumed.
*
* Virtual modifier statements
* ---------------------------
* Statements of the form:
* virtual_modifiers LControl;
*
* Can appear in the xkb_types, xkb_compat, xkb_symbols sections.
* TODO
*
* Effect on keymap
* ----------------
* After all of the xkb_types sections have been compiled, the following
* members of struct xkb_keymap are finalized:
* struct xkb_key_type *types;
* unsigned int num_types;
* char *types_section_name;
* TODO: virtual modifiers.
*/
enum type_field {
TYPE_FIELD_MASK = (1 << 0),
TYPE_FIELD_MAP = (1 << 1),
@ -287,10 +182,16 @@ MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
from->name = NULL;
}
darray_foreach(type, from->types) {
type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
if (!AddKeyType(into, type, false))
into->errorCount++;
if (darray_empty(into->types)) {
into->types = from->types;
darray_init(from->types);
}
else {
darray_foreach(type, from->types) {
type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
if (!AddKeyType(into, type, false))
into->errorCount++;
}
}
}
@ -738,7 +639,7 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
ok = true;
break;
case STMT_VMOD:
ok = HandleVModDef(info->keymap, (VModDef *) stmt);
ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
default:
log_err(info->keymap->ctx,

View File

@ -30,27 +30,64 @@
#include "vmod.h"
bool
HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt)
HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
enum merge_mode merge)
{
xkb_mod_index_t i;
const struct xkb_mod *mod;
struct xkb_mod *mod;
xkb_mod_mask_t mapping;
struct xkb_mod new;
if (stmt->value)
log_err(keymap->ctx,
"Support for setting a value in a virtual_modifiers statement has been removed; "
"Value ignored\n");
merge = (merge == MERGE_DEFAULT ? stmt->merge : merge);
if (stmt->value) {
/*
* This is a statement such as 'virtualModifiers NumLock = Mod1';
* it sets the vmod-to-real-mod[s] mapping directly instead of going
* through modifier_map or some such.
*/
if (!ExprResolveModMask(keymap, stmt->value, MOD_REAL, &mapping)) {
log_err(keymap->ctx,
"Declaration of %s ignored\n",
xkb_atom_text(keymap->ctx, stmt->name));
return false;
}
}
else {
mapping = 0;
}
darray_enumerate(i, mod, keymap->mods) {
if (mod->name == stmt->name) {
if (mod->type == MOD_VIRT)
if (mod->type != MOD_VIRT) {
log_err(keymap->ctx,
"Can't add a virtual modifier named \"%s\"; "
"there is already a non-virtual modifier with this name! Ignored\n",
xkb_atom_text(keymap->ctx, mod->name));
return false;
}
if (mod->mapping == mapping)
return true;
log_err(keymap->ctx,
"Can't add a virtual modifier named \"%s\"; "
"there is already a non-virtual modifier with this name! Ignored\n",
xkb_atom_text(keymap->ctx, mod->name));
return false;
if (mod->mapping != 0) {
xkb_mod_mask_t use, ignore;
use = (merge == MERGE_OVERRIDE ? mapping : mod->mapping);
ignore = (merge == MERGE_OVERRIDE ? mod->mapping : mapping);
log_warn(keymap->ctx,
"Virtual modifier %s defined multiple times; "
"Using %s, ignoring %s\n",
xkb_atom_text(keymap->ctx, stmt->name),
ModMaskText(keymap, use),
ModMaskText(keymap, ignore));
mapping = use;
}
mod->mapping = mapping;
return true;
}
}
@ -62,7 +99,7 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt)
}
new.name = stmt->name;
new.mapping = 0;
new.mapping = mapping;
new.type = MOD_VIRT;
darray_append(keymap->mods, new);
return true;

View File

@ -28,6 +28,7 @@
#define XKBCOMP_VMOD_H
bool
HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt);
HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
enum merge_mode merge);
#endif

View File

@ -91,4 +91,8 @@
#define xkb_state_get_map(state) xkb_state_get_keymap(state)
/* Not needed anymore, since there's NO_FLAGS. */
#define XKB_MAP_COMPILE_PLACEHOLDER XKB_KEYMAP_COMPILE_NO_FLAGS
#define XKB_MAP_COMPILE_NO_FLAGS XKB_KEYMAP_COMPILE_NO_FLAGS
#endif

View File

@ -27,6 +27,10 @@
#include <xcb/xcb.h>
#include <xkbcommon/xkbcommon.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* libxkbcommon-x11 API - Additional X11 support for xkbcommon.
@ -163,4 +167,8 @@ xkb_x11_state_new_from_device(struct xkb_keymap *keymap,
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _XKBCOMMON_X11_H */

View File

@ -305,26 +305,60 @@ typedef uint32_t xkb_led_mask_t;
/**
* Names to compile a keymap with, also known as RMLVO.
*
* These names together are the primary identifier for a keymap.
* If any of the members is NULL or an empty string (""), a default value is
* used. It is recommended to use the system default by passing NULL for
* unspecified values, instead of providing your own defaults.
* The names are the common configuration values by which a user picks
* a keymap.
*
* If the entire struct is NULL, then each field is taken to be NULL.
* You should prefer passing NULL instead of choosing your own defaults.
*/
struct xkb_rule_names {
/** The rules file to use. The rules file describes how to interpret
* the values of the model, layout, variant and options fields. */
/**
* The rules file to use. The rules file describes how to interpret
* the values of the model, layout, variant and options fields.
*
* If NULL or the empty string "", a default value is used.
* If the XKB_DEFAULT_RULES environment variable is set, it is used
* as the default. Otherwise the system default is used.
*/
const char *rules;
/** The keyboard model by which to interpret keycodes and LEDs. */
/**
* The keyboard model by which to interpret keycodes and LEDs.
*
* If NULL or the empty string "", a default value is used.
* If the XKB_DEFAULT_MODEL environment variable is set, it is used
* as the default. Otherwise the system default is used.
*/
const char *model;
/** A comma separated list of layouts (languages) to include in the
* keymap. */
/**
* A comma separated list of layouts (languages) to include in the
* keymap.
*
* If NULL or the empty string "", a default value is used.
* If the XKB_DEFAULT_LAYOUT environment variable is set, it is used
* as the default. Otherwise the system default is used.
*/
const char *layout;
/** A comma separated list of variants, one per layout, which may
* modify or augment the respective layout in various ways. */
/**
* A comma separated list of variants, one per layout, which may
* modify or augment the respective layout in various ways.
*
* If NULL or the empty string "", and a default value is also used
* for the layout, a default value is used. Otherwise no variant is
* used.
* If the XKB_DEFAULT_VARIANT environment variable is set, it is used
* as the default. Otherwise the system default is used.
*/
const char *variant;
/** A comma separated list of options, through which the user specifies
* non-layout related preferences, like which key combinations are used
* for switching layouts, or which key is the Compose key. */
/**
* A comma separated list of options, through which the user specifies
* non-layout related preferences, like which key combinations are used
* for switching layouts, or which key is the Compose key.
*
* If NULL, a default value is used. If the empty string "", no
* options are used.
* If the XKB_DEFAULT_OPTIONS environment variable is set, it is used
* as the default. Otherwise the system default is used.
*/
const char *options;
};
@ -399,6 +433,11 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags);
* @returns The number of bytes written to the buffer (including the
* terminating byte). If the keysym does not have a Unicode
* representation, returns 0. If the buffer is too small, returns -1.
*
* Prefer not to use this function on keysyms obtained from an
* xkb_state. In this case, use xkb_state_key_get_utf8() instead.
*
* @sa xkb_state_key_get_utf8()
*/
int
xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size);
@ -409,6 +448,11 @@ xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size);
* @returns The Unicode/UTF-32 representation of keysym, which is also
* compatible with UCS-4. If the keysym does not have a Unicode
* representation, returns 0.
*
* Prefer not to use this function on keysyms obtained from an
* xkb_state. In this case, use xkb_state_key_get_utf32() instead.
*
* @sa xkb_state_key_get_utf32()
*/
uint32_t
xkb_keysym_to_utf32(xkb_keysym_t keysym);
@ -681,9 +725,7 @@ 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
XKB_KEYMAP_COMPILE_NO_FLAGS = 0
};
/**
@ -692,13 +734,8 @@ enum xkb_keymap_compile_flags {
* The primary keymap entry point: creates a new XKB keymap from a set of
* RMLVO (Rules + Model + Layouts + Variants + Options) names.
*
* You should almost certainly be using this and nothing else to create
* keymaps.
*
* @param context The context in which to create the keymap.
* @param names The RMLVO names to use. In xkbcommon versions prior
* to 0.2.1, this field must be non-NULL. In later
* versions, passing NULL will use the default keymap.
* @param names The RMLVO names to use. See xkb_rule_names.
* @param flags Optional flags for the keymap, or 0.
*
* @returns A keymap compiled according to the RMLVO names, or NULL if
@ -1159,6 +1196,13 @@ enum xkb_state_component {
* is pressed twice, it should be released twice; etc. Otherwise (e.g. due
* to missed input events), situations like "stuck modifiers" may occur.
*
* This function is often used in conjunction with the function
* xkb_state_key_get_syms() (or xkb_state_key_get_one_sym()), for example,
* when handling a key event. In this case, you should prefer to get the
* keysyms *before* updating the key, such that the keysyms reported for
* the key event are not affected by the event itself. This is the
* conventional behavior.
*
* @returns A mask of state components that have changed as a result of
* the update. If nothing in the state has changed, returns 0.
*
@ -1234,6 +1278,44 @@ int
xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key,
const xkb_keysym_t **syms_out);
/**
* Get the Unicode/UTF-8 string obtained from pressing a particular key
* in a given keyboard state.
*
* @param[in] state The keyboard state object.
* @param[in] key The keycode of the key.
* @param[out] buffer A buffer to write the string into.
* @param[in] size Size of the buffer.
*
* @warning If the buffer passed is too small, the string is truncated
* (though still NUL-terminated).
*
* @returns The number of bytes required for the string, excluding the
* NUL byte. If there is nothing to write, returns 0.
*
* You may check if truncation has occurred by comparing the return value
* with the size of @p buffer, similarly to the snprintf(3) function.
* You may safely pass NULL and 0 to @p buffer and @p size to find the
* required size (without the NUL-byte).
*
* @memberof xkb_state
*/
int
xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t key,
char *buffer, size_t size);
/**
* Get the Unicode/UTF-32 codepoint obtained from pressing a particular
* key in a a given keyboard state.
*
* @returns The UTF-32 representation for the key, if it consists of only
* a single codepoint. Otherwise, returns 0.
*
* @memberof xkb_state
*/
uint32_t
xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t key);
/**
* Get the single keysym obtained from pressing a particular key in a
* given keyboard state.
@ -1485,6 +1567,7 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
* index is not valid in the keymap, returns -1.
*
* @sa xkb_state_mod_mask_remove_consumed()
* @sa xkb_state_key_get_consumed_mods()
* @memberof xkb_state
*/
int
@ -1504,6 +1587,17 @@ xkb_mod_mask_t
xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key,
xkb_mod_mask_t mask);
/**
* Get the mask of modifiers consumed by translating a given key.
*
* @returns a mask of the consumed modifiers.
*
* @sa xkb_state_mod_index_is_consumed()
* @memberof xkb_state
*/
xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key);
/**
* Test whether a layout is active in a given keyboard state by name.
*

View File

@ -48,10 +48,7 @@
#include <xkbcommon/xkbcommon.h>
#ifndef QT_NO_XKB
// note: extern won't be needed from libxkbcommon 0.4.1 and above
extern "C" {
#include <xkbcommon/xkbcommon-x11.h>
}
#endif
#include <QEvent>