#include "vmod.h"
#include "keycodes.h"
#include "include.h"
+#include "keysym.h"
enum key_repeat {
+ KEY_REPEAT_UNDEFINED = 0,
KEY_REPEAT_YES = 1,
- KEY_REPEAT_NO = 0,
- KEY_REPEAT_UNDEFINED = -1
+ KEY_REPEAT_NO = 2,
};
enum group_field {
unsigned long name; /* the 4 chars of the key name, as long */
- GroupInfo groups[XKB_NUM_GROUPS];
+ darray(GroupInfo) groups;
enum key_repeat repeat;
xkb_mod_mask_t vmodmap;
xkb_atom_t dfltType;
enum xkb_range_exceed_type out_of_range_group_action;
- xkb_group_index_t out_of_range_group_number;
+ xkb_layout_index_t out_of_range_group_number;
} KeyInfo;
static void
{
darray_free(groupi->syms);
darray_free(groupi->levels);
- InitGroupInfo(groupi);
}
static void
InitKeyInfo(KeyInfo *keyi, unsigned file_id)
{
- xkb_group_index_t i;
- static const char dflt[4] = "*";
+ static const char dflt_key_name[XKB_KEY_NAME_LENGTH] = "*";
- keyi->defined = 0;
+ memset(keyi, 0, sizeof(*keyi));
keyi->file_id = file_id;
keyi->merge = MERGE_OVERRIDE;
- keyi->name = KeyNameToLong(dflt);
- for (i = 0; i < XKB_NUM_GROUPS; i++)
- InitGroupInfo(&keyi->groups[i]);
- keyi->dfltType = XKB_ATOM_NONE;
- keyi->vmodmap = 0;
- keyi->repeat = KEY_REPEAT_UNDEFINED;
+ keyi->name = KeyNameToLong(dflt_key_name);
keyi->out_of_range_group_action = RANGE_WRAP;
- keyi->out_of_range_group_number = 0;
}
static void
ClearKeyInfo(KeyInfo *keyi)
{
- xkb_group_index_t i;
-
- for (i = 0; i < XKB_NUM_GROUPS; i++)
- ClearGroupInfo(&keyi->groups[i]);
+ GroupInfo *groupi;
+ darray_foreach(groupi, keyi->groups)
+ ClearGroupInfo(groupi);
+ darray_free(keyi->groups);
}
/***====================================================================***/
int errorCount;
unsigned file_id;
enum merge_mode merge;
- xkb_group_index_t explicit_group;
+ xkb_layout_index_t explicit_group;
darray(KeyInfo) keys;
KeyInfo dflt;
VModInfo vmods;
ActionsInfo *actions;
- xkb_atom_t groupNames[XKB_NUM_GROUPS];
+ xkb_atom_t group_names[XKB_NUM_GROUPS];
darray(ModMapEntry) modMaps;
struct xkb_keymap *keymap;
InitSymbolsInfo(SymbolsInfo *info, struct xkb_keymap *keymap,
unsigned file_id, ActionsInfo *actions)
{
- xkb_group_index_t i;
-
- info->name = NULL;
- info->explicit_group = 0;
- info->errorCount = 0;
+ memset(info, 0, sizeof(*info));
+ info->keymap = keymap;
info->file_id = file_id;
info->merge = MERGE_OVERRIDE;
- darray_init(info->keys);
- darray_growalloc(info->keys, 110);
- darray_init(info->modMaps);
- for (i = 0; i < XKB_NUM_GROUPS; i++)
- info->groupNames[i] = XKB_ATOM_NONE;
InitKeyInfo(&info->dflt, file_id);
InitVModInfo(&info->vmods, keymap);
info->actions = actions;
- info->keymap = keymap;
}
static void
ClearSymbolsInfo(SymbolsInfo * info)
{
KeyInfo *keyi;
-
free(info->name);
darray_foreach(keyi, info->keys)
ClearKeyInfo(keyi);
darray_free(info->keys);
darray_free(info->modMaps);
- memset(info, 0, sizeof(SymbolsInfo));
+ ClearKeyInfo(&info->dflt);
}
static bool
MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
- bool report, xkb_group_index_t group, unsigned long key_name)
+ bool report, xkb_layout_index_t group, unsigned long key_name)
{
xkb_level_index_t i, numLevels;
enum { INTO = (1 << 0), FROM = (1 << 1) } using;
static bool
MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from)
{
- xkb_group_index_t i;
+ xkb_layout_index_t i;
+ xkb_layout_index_t groups_in_both;
enum key_field collide = 0;
bool clobber, report;
- int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
+ int verbosity = xkb_context_get_log_verbosity(info->keymap->ctx);
if (from->merge == MERGE_REPLACE) {
ClearKeyInfo(into);
report = (verbosity > 9 ||
(into->file_id == from->file_id && verbosity > 0));
- for (i = 0; i < XKB_NUM_GROUPS; i++)
- MergeGroups(info, &into->groups[i], &from->groups[i], clobber,
- report, i, into->name);
+ groups_in_both = MIN(darray_size(into->groups),
+ darray_size(from->groups));
+ for (i = 0; i < groups_in_both; i++)
+ MergeGroups(info,
+ &darray_item(into->groups, i),
+ &darray_item(from->groups, i),
+ clobber, report, i, into->name);
+ /* If @from has extra groups, just move them to @into. */
+ for (i = groups_in_both; i < darray_size(from->groups); i++) {
+ darray_append(into->groups, darray_item(from->groups, i));
+ InitGroupInfo(&darray_item(from->groups, i));
+ }
if (UseNewKeyField(KEY_FIELD_VMODMAP, into->defined, from->defined,
clobber, report, &collide)) {
(clobber ? "first" : "last"));
ClearKeyInfo(from);
+ InitKeyInfo(from, info->file_id);
return true;
}
from->name = NULL;
}
for (i = 0; i < XKB_NUM_GROUPS; i++) {
- if (from->groupNames[i] != XKB_ATOM_NONE) {
+ if (from->group_names[i] != XKB_ATOM_NONE) {
if ((merge != MERGE_AUGMENT) ||
- (into->groupNames[i] == XKB_ATOM_NONE))
- into->groupNames[i] = from->groupNames[i];
+ (into->group_names[i] == XKB_ATOM_NONE))
+ into->group_names[i] = from->group_names[i];
}
}
InitSymbolsInfo(&next_incl, info->keymap, rtrn->id, info->actions);
next_incl.merge = next_incl.dflt.merge = MERGE_OVERRIDE;
- if (stmt->modifier)
+ if (stmt->modifier) {
next_incl.explicit_group = atoi(stmt->modifier) - 1;
- else
+ if (next_incl.explicit_group >= XKB_NUM_GROUPS) {
+ log_err(info->keymap->ctx,
+ "Cannot set explicit group to %d - must be between 1..%d; "
+ "Ignoring group number\n",
+ next_incl.explicit_group + 1, XKB_NUM_GROUPS);
+ next_incl.explicit_group = info->explicit_group;
+ }
+ }
+ else {
next_incl.explicit_group = info->explicit_group;
+ }
HandleSymbolsFile(&next_incl, rtrn, MERGE_OVERRIDE);
static bool
GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
- unsigned what, xkb_group_index_t *ndx_rtrn)
+ unsigned what, xkb_layout_index_t *ndx_rtrn)
{
const char *name = (what == SYMBOLS ? "symbols" : "actions");
if (arrayNdx == NULL) {
- xkb_group_index_t i;
+ xkb_layout_index_t i;
+ GroupInfo *groupi;
enum group_field field = (what == SYMBOLS ?
GROUP_FIELD_SYMS : GROUP_FIELD_ACTS);
- for (i = 0; i < XKB_NUM_GROUPS; i++) {
- if (!(keyi->groups[i].defined & field)) {
+ darray_enumerate(i, groupi, keyi->groups) {
+ if (!(groupi->defined & field)) {
*ndx_rtrn = i;
return true;
}
}
- log_err(info->keymap->ctx,
- "Too many groups of %s for key %s (max %u); "
- "Ignoring %s defined for extra groups\n",
- name, LongKeyNameText(keyi->name), XKB_NUM_GROUPS + 1, name);
- return false;
+ if (i >= XKB_NUM_GROUPS) {
+ log_err(info->keymap->ctx,
+ "Too many groups of %s for key %s (max %u); "
+ "Ignoring %s defined for extra groups\n",
+ name, LongKeyNameText(keyi->name), XKB_NUM_GROUPS + 1, name);
+ return false;
+ }
+
+ darray_resize0(keyi->groups, darray_size(keyi->groups) + 1);
+ *ndx_rtrn = darray_size(keyi->groups) - 1;
+ return true;
}
if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, ndx_rtrn)) {
}
(*ndx_rtrn)--;
+ if (*ndx_rtrn >= darray_size(keyi->groups))
+ darray_resize0(keyi->groups, *ndx_rtrn + 1);
+
return true;
}
AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
ExprDef *value)
{
- xkb_group_index_t ndx;
+ xkb_layout_index_t ndx;
GroupInfo *groupi;
unsigned int nSyms;
xkb_level_index_t nLevels;
if (!GetGroupIndex(info, keyi, arrayNdx, SYMBOLS, &ndx))
return false;
- groupi = &keyi->groups[ndx];
+ groupi = &darray_item(keyi->groups, ndx);
if (value == NULL) {
groupi->defined |= GROUP_FIELD_SYMS;
LongKeyNameText(keyi->name),
ndx + 1,
xkb_atom_text(info->keymap->ctx,
- info->groupNames[ndx]),
+ info->group_names[ndx]),
nSyms);
leveli->sym_index = 0;
leveli->num_syms = 0;
ExprDef *value)
{
unsigned int i;
- xkb_group_index_t ndx;
+ xkb_layout_index_t ndx;
GroupInfo *groupi;
unsigned int nActs;
ExprDef *act;
if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx))
return false;
- groupi = &keyi->groups[ndx];
+ groupi = &darray_item(keyi->groups, ndx);
if (value == NULL) {
groupi->defined |= GROUP_FIELD_ACTS;
struct xkb_context *ctx = info->keymap->ctx;
if (istreq(field, "type")) {
- xkb_group_index_t ndx;
+ xkb_layout_index_t ndx;
xkb_atom_t val;
if (!ExprResolveString(ctx, value, &val))
}
else {
ndx--;
- keyi->groups[ndx].type = val;
- keyi->groups[ndx].defined |= GROUP_FIELD_TYPE;
+ if (ndx >= darray_size(keyi->groups))
+ darray_resize0(keyi->groups, ndx + 1);
+ darray_item(keyi->groups, ndx).type = val;
+ darray_item(keyi->groups, ndx).defined |= GROUP_FIELD_TYPE;
}
}
else if (istreq(field, "symbols"))
}
else if (istreq(field, "groupsredirect") ||
istreq(field, "redirectgroups")) {
- xkb_group_index_t grp;
+ xkb_layout_index_t grp;
if (!ExprResolveGroup(ctx, value, &grp)) {
log_err(info->keymap->ctx,
static int
SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
{
- xkb_group_index_t grp;
+ xkb_layout_index_t grp;
xkb_atom_t name;
if (!arrayNdx) {
return false;
}
- info->groupNames[grp - 1 + info->explicit_group] = name;
+ info->group_names[grp - 1 + info->explicit_group] = name;
return true;
}
static int
-HandleSymbolsVar(SymbolsInfo *info, VarDef *stmt)
+HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
{
const char *elem, *field;
ExprDef *arrayNdx;
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->op == EXPR_FIELD_REF) {
- ok = HandleSymbolsVar(info, def);
+ log_err(info->keymap->ctx,
+ "Cannot set a global default value from within a key statement; "
+ "Move statements to the global file scope\n");
continue;
}
static bool
SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
{
- xkb_group_index_t i;
+ xkb_layout_index_t i;
+ GroupInfo *groupi;
+ bool warn = false;
if (info->explicit_group == 0)
return true;
- for (i = 1; i < XKB_NUM_GROUPS; i++) {
- if (keyi->groups[i].defined) {
- log_warn(info->keymap->ctx,
- "For the map %s an explicit group specified, "
- "but key %s has more than one group defined; "
- "All groups except first one will be ignored\n",
- info->name, LongKeyNameText(keyi->name));
- break;
+ darray_enumerate_from(i, groupi, keyi->groups, 1) {
+ if (groupi->defined) {
+ warn = true;
+ ClearGroupInfo(groupi);
}
}
- if (i < XKB_NUM_GROUPS)
- for (i = 1; i < XKB_NUM_GROUPS; i++)
- ClearGroupInfo(&keyi->groups[i]);
- keyi->groups[info->explicit_group] = keyi->groups[0];
- InitGroupInfo(&keyi->groups[0]);
+ if (warn)
+ log_warn(info->keymap->ctx,
+ "For the map %s an explicit group specified, "
+ "but key %s has more than one group defined; "
+ "All groups except first one will be ignored\n",
+ info->name, LongKeyNameText(keyi->name));
+
+ darray_resize0(keyi->groups, info->explicit_group + 1);
+ darray_item(keyi->groups, info->explicit_group) =
+ darray_item(keyi->groups, 0);
+ InitGroupInfo(&darray_item(keyi->groups, 0));
return true;
}
HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
{
KeyInfo keyi;
- xkb_group_index_t i;
+ xkb_layout_index_t i;
keyi = info->dflt;
- for (i = 0; i < XKB_NUM_GROUPS; i++) {
- darray_copy(keyi.groups[i].syms, info->dflt.groups[i].syms);
- darray_copy(keyi.groups[i].levels, info->dflt.groups[i].levels);
+ darray_init(keyi.groups);
+ darray_copy(keyi.groups, info->dflt.groups);
+ for (i = 0; i < darray_size(keyi.groups); i++) {
+ darray_init(darray_item(keyi.groups, i).syms);
+ darray_copy(darray_item(keyi.groups, i).syms,
+ darray_item(info->dflt.groups, i).syms);
+ darray_init(darray_item(keyi.groups, i).levels);
+ darray_copy(darray_item(keyi.groups, i).levels,
+ darray_item(info->dflt.groups, i).levels);
}
keyi.merge = stmt->merge;
keyi.name = KeyNameToLong(stmt->keyName);
ok = HandleSymbolsDef(info, (SymbolsDef *) stmt);
break;
case STMT_VAR:
- ok = HandleSymbolsVar(info, (VarDef *) stmt);
+ ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
ok = HandleVModDef((VModDef *) stmt, info->keymap, merge,
FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
{
struct xkb_key *key, *ret = NULL;
- xkb_group_index_t group, min_group = UINT32_MAX;
+ xkb_layout_index_t group, min_group = UINT32_MAX;
xkb_level_index_t level, min_level = UINT16_MAX;
xkb_foreach_key(key, keymap) {
return width <= 4;
}
-/**
- * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
- * groups, and reduce to one group if all groups are identical anyway.
- */
-static void
-PrepareKeyDef(KeyInfo *keyi)
-{
- xkb_group_index_t i, lastGroup;
- const GroupInfo *group0;
- bool identical;
-
- /* get highest group number */
- for (i = XKB_NUM_GROUPS - 1; i > 0; i--)
- if (keyi->groups[i].defined)
- break;
- lastGroup = i;
-
- if (lastGroup == 0)
- return;
-
- group0 = &keyi->groups[0];
-
- /* If there are empty groups between non-empty ones fill them with data */
- /* from the first group. */
- /* We can make a wrong assumption here. But leaving gaps is worse. */
- for (i = lastGroup; i > 0; i--) {
- GroupInfo *groupi = &keyi->groups[i];
-
- if (groupi->defined)
- continue;
-
- groupi->type = group0->type;
- darray_copy(groupi->syms, group0->syms);
- darray_copy(groupi->levels, group0->levels);
- groupi->defined = group0->defined;
- }
-
- /* If all groups are completely identical remove them all */
- /* exept the first one. */
- /* XXX: This code needs testing... or removal. */
- identical = true;
- for (i = lastGroup; i > 0; i--) {
- GroupInfo *groupi = &keyi->groups[i];
-
- if (groupi->type != group0->type) {
- identical = false;
- break;
- }
- if (!darray_same(groupi->levels, group0->levels) &&
- (darray_empty(groupi->levels) || darray_empty(group0->levels) ||
- darray_size(groupi->levels) != darray_size(group0->levels) ||
- memcmp(darray_mem(groupi->levels, 0),
- darray_mem(group0->levels, 0),
- darray_size(group0->levels) * sizeof(LevelInfo)))) {
- identical = false;
- break;
- }
- if (!darray_same(groupi->syms, group0->syms) &&
- (darray_empty(groupi->syms) || darray_empty(group0->syms) ||
- darray_size(groupi->syms) != darray_size(group0->syms) ||
- memcmp(darray_mem(groupi->syms, 0),
- darray_mem(group0->syms, 0),
- darray_size(group0->syms) * sizeof(xkb_keysym_t)))) {
- identical = false;
- break;
- }
- }
-
- if (identical)
- for (i = lastGroup; i > 0; i--)
- ClearGroupInfo(&keyi->groups[i]);
-}
-
static bool
CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
{
struct xkb_keymap *keymap = info->keymap;
struct xkb_key *key;
- xkb_group_index_t i;
+ GroupInfo *groupi;
+ const GroupInfo *group0;
+ xkb_layout_index_t i;
bool haveActions;
unsigned int sizeSyms;
unsigned int symIndex;
return false;
}
- /*
- * Find the range of groups we need. (There shouldn't be any gaps,
- * see PrepareKeyDef).
- */
+ /* Find the range of groups we need. */
key->num_groups = 0;
- for (i = 0; i < XKB_NUM_GROUPS; i++)
- if (keyi->groups[i].defined)
+ darray_enumerate(i, groupi, keyi->groups)
+ if (groupi->defined)
key->num_groups = i + 1;
+ if (key->num_groups <= 0)
+ return false; /* WSGO */
+
+ darray_resize(keyi->groups, key->num_groups);
+
+ /*
+ * If there are empty groups between non-empty ones, fill them with data
+ * from the first group.
+ * We can make a wrong assumption here. But leaving gaps is worse.
+ */
+ group0 = &darray_item(keyi->groups, 0);
+ darray_foreach_from(groupi, keyi->groups, 1) {
+ if (groupi->defined)
+ continue;
+
+ groupi->type = group0->type;
+ darray_copy(groupi->syms, group0->syms);
+ darray_copy(groupi->levels, group0->levels);
+ groupi->defined = group0->defined;
+ }
+
/* See if we need to allocate an actions array. */
haveActions = false;
- for (i = 0; i < key->num_groups; i++) {
+ darray_foreach(groupi, keyi->groups) {
LevelInfo *leveli;
- darray_foreach(leveli, keyi->groups[i].levels) {
+ darray_foreach(leveli, groupi->levels) {
if (leveli->act.type != ACTION_TYPE_NONE) {
haveActions = true;
goto out_of_loops;
* Find and assign the groups' types in the keymap. Also find the
* key width according to the largest type.
*/
+ key->kt_index = calloc(key->num_groups, sizeof(*key->kt_index));
key->width = 0;
- for (i = 0; i < key->num_groups; i++) {
+ darray_enumerate(i, groupi, keyi->groups) {
struct xkb_key_type *type;
- GroupInfo *groupi = &keyi->groups[i];
bool autoType = false;
/* Find the type of the group, if it is missing. */
log_vrb(info->keymap->ctx, 5,
"No automatic type for %d levels; "
"Using %s for the %s key\n",
- darray_size(groupi->levels),
+ (int) darray_size(groupi->levels),
xkb_atom_text(keymap->ctx, groupi->type),
LongKeyNameText(keyi->name));
}
xkb_atom_text(keymap->ctx, type->name),
type->num_levels,
LongKeyNameText(keyi->name),
- darray_size(groupi->levels));
+ (int) darray_size(groupi->levels));
darray_resize(groupi->levels, type->num_levels);
}
/* Find the size of the syms array. */
sizeSyms = 0;
- for (i = 0; i < key->num_groups; i++)
- sizeSyms += darray_size(keyi->groups[i].syms);
+ darray_foreach(groupi, keyi->groups)
+ sizeSyms += darray_size(groupi->syms);
/* Initialize the xkb_key, now that we know the sizes. */
key->syms = calloc(sizeSyms, sizeof(*key->syms));
/* Copy keysyms and actions. */
symIndex = 0;
- for (i = 0; i < key->num_groups; i++) {
- GroupInfo *groupi = &keyi->groups[i];
+ darray_enumerate(i, groupi, keyi->groups) {
xkb_level_index_t j;
+ LevelInfo *leveli;
/* We rely on calloc having zeroized the arrays up to key->width. */
- for (j = 0; j < darray_size(groupi->levels); j++) {
- LevelInfo *leveli = &darray_item(groupi->levels, j);
-
+ darray_enumerate(j, leveli, groupi->levels) {
if (leveli->act.type != ACTION_TYPE_NONE)
key->actions[i * key->width + j] = leveli->act;
{
KeyInfo *keyi;
ModMapEntry *mm;
- xkb_group_index_t i;
+ xkb_layout_index_t i;
struct xkb_key *key;
keymap->symbols_section_name = strdup_safe(info->name);
for (i = 0; i < XKB_NUM_GROUPS; i++)
- if (info->groupNames[i] != XKB_ATOM_NONE)
- keymap->group_names[i] = info->groupNames[i];
+ if (info->group_names[i] != XKB_ATOM_NONE)
+ keymap->group_names[i] = info->group_names[i];
- darray_foreach(keyi, info->keys) {
- PrepareKeyDef(keyi);
+ darray_foreach(keyi, info->keys)
if (!CopySymbolsDef(info, keyi))
info->errorCount++;
- }
- if (xkb_get_log_verbosity(keymap->ctx) > 3) {
+ if (xkb_context_get_log_verbosity(keymap->ctx) > 3) {
xkb_foreach_key(key, keymap) {
if (key->name[0] == '\0')
continue;