static bool
write_vmods(struct xkb_keymap *keymap, struct buf *buf)
{
- xkb_mod_index_t i, num_vmods = 0;
+ const struct xkb_vmod *vmod;
+ xkb_mod_index_t num_vmods = 0;
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if (!keymap->vmod_names[i])
- continue;
+ darray_foreach(vmod, keymap->vmods) {
if (num_vmods == 0)
write_buf(buf, "\t\tvirtual_modifiers ");
else
write_buf(buf, ",");
- write_buf(buf, "%s",
- xkb_atom_text(keymap->ctx, keymap->vmod_names[i]));
+ write_buf(buf, "%s", xkb_atom_text(keymap->ctx, vmod->name));
num_vmods++;
}
if (interp->virtual_mod != XKB_MOD_INVALID) {
write_buf(buf, "\t\t\tvirtualModifier= %s;\n",
xkb_atom_text(keymap->ctx,
- keymap->vmod_names[interp->virtual_mod]));
+ darray_item(keymap->vmods,
+ interp->virtual_mod).name));
}
if (interp->match & MATCH_LEVEL_ONE_ONLY)
darray_free(keymap->sym_interpret);
darray_free(keymap->key_aliases);
darray_free(keymap->group_names);
+ darray_free(keymap->vmods);
free(keymap->keycodes_section_name);
free(keymap->symbols_section_name);
free(keymap->types_section_name);
XKB_EXPORT xkb_mod_index_t
xkb_keymap_num_mods(struct xkb_keymap *keymap)
{
- xkb_mod_index_t i;
-
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++)
- if (!keymap->vmod_names[i])
- break;
-
/* We always have all the core modifiers (for now), plus any virtual
* modifiers we may have defined. */
- return i + XKB_NUM_CORE_MODS;
+ return XKB_NUM_CORE_MODS + darray_size(keymap->vmods);
}
/**
xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
{
const char *name;
+ const struct xkb_vmod *vmod;
if (idx >= xkb_keymap_num_mods(keymap))
return NULL;
/* First try to find a legacy modifier name. If that fails, try to
* find a virtual mod name. */
name = ModIndexToName(idx);
- if (!name)
- name = xkb_atom_text(keymap->ctx,
- keymap->vmod_names[idx - XKB_NUM_CORE_MODS]);
+ if (name)
+ return name;
- return name;
+ vmod = &darray_item(keymap->vmods, idx - XKB_NUM_CORE_MODS);
+ return xkb_atom_text(keymap->ctx, vmod->name);
}
/**
{
xkb_mod_index_t i;
xkb_atom_t atom;
+ const struct xkb_vmod *vmod;
i = ModNameToIndex(name);
if (i != XKB_MOD_INVALID)
if (atom == XKB_ATOM_NONE)
return XKB_MOD_INVALID;
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if (keymap->vmod_names[i] == XKB_ATOM_NONE)
- break;
- if (keymap->vmod_names[i] == atom)
+ darray_enumerate(i, vmod, keymap->vmods)
+ if (vmod->name == atom)
return i + XKB_NUM_CORE_MODS;
- }
return XKB_MOD_INVALID;
}
*/
#define XKB_NUM_GROUPS 4
+/* Don't allow more vmods than we can hold in xkb_mod_mask_t. */
+#define XKB_MAX_VIRTUAL_MODS \
+ ((xkb_mod_index_t) (sizeof(xkb_mod_mask_t) * 8 - XKB_NUM_CORE_MODS))
+
/* These should all be dynamic. */
#define XKB_NUM_INDICATORS 32
-#define XKB_NUM_VIRTUAL_MODS 16
#define XKB_NUM_CORE_MODS 8
enum xkb_action_type {
typedef darray(xkb_atom_t) darray_xkb_atom_t;
+struct xkb_vmod {
+ xkb_atom_t name;
+ xkb_mod_mask_t mapping; /* vmod -> real mod mapping */
+};
+
/* Common keyboard description structure */
struct xkb_keymap {
struct xkb_context *ctx;
darray(struct xkb_sym_interpret) sym_interpret;
- /* vmod -> mod mapping */
- xkb_mod_mask_t vmods[XKB_NUM_VIRTUAL_MODS];
- xkb_atom_t vmod_names[XKB_NUM_VIRTUAL_MODS];
+ darray(struct xkb_vmod) vmods;
/* Number of groups in the key with the most groups. */
xkb_layout_index_t num_groups;
return rtrn;
}
-/*
- * Get a vmod name's text, where the vmod index is zero based
- * (0..XKB_NUM_VIRTUAL_MODS-1).
- */
+/* Get a vmod name's text, where the vmod index is zero based. */
static const char *
VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
{
- int len;
- char *rtrn;
- const char *tmp = NULL;
- char buf[20];
-
- if (ndx >= XKB_NUM_VIRTUAL_MODS)
- tmp = "illegal";
- else
- tmp = xkb_atom_text(keymap->ctx, keymap->vmod_names[ndx]);
-
- if (!tmp) {
- snprintf(buf, sizeof(buf) - 1, "%d", ndx);
- tmp = buf;
- }
-
- len = strlen(tmp) + 1;
- if (len >= BUFFER_SIZE)
- len = BUFFER_SIZE - 1;
-
- rtrn = GetBuffer(len);
- strncpy(rtrn, tmp, len);
-
- return rtrn;
+ if (ndx >= darray_size(keymap->vmods))
+ return "illegal";
+ return xkb_atom_text(keymap->ctx,
+ darray_item(keymap->vmods, ndx).name);
}
/* Get a mod mask's text, where the mask is in rmods+vmods format. */
VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
{
xkb_mod_index_t i;
- xkb_mod_mask_t bit;
xkb_mod_mask_t rmask, vmask;
int len, rem;
const char *mm = NULL;
rem = BUFFER_SIZE;
if (vmask != 0) {
- for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS && rem > 1; i++, bit <<=
- 1) {
- if (!(vmask & bit))
+ for (i = 0; i < darray_size(keymap->vmods) && rem > 1; i++) {
+ if (!(vmask & (1 << i)))
continue;
len = snprintf(str, rem, "%s%s",
static void
ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
{
+ const struct xkb_vmod *vmod;
xkb_mod_index_t i;
xkb_mod_mask_t vmask = mods->mods >> XKB_NUM_CORE_MODS;
/* The effective mask is only real mods for now. */
mods->mask = mods->mods & 0xff;
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if (!(vmask & (1 << i)))
- continue;
- mods->mask |= keymap->vmods[i];
- }
+ darray_enumerate(i, vmod, keymap->vmods)
+ if (vmask & (1 << i))
+ mods->mask |= vmod->mapping;
}
static void
static bool
UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
{
- xkb_mod_index_t vmod;
+ struct xkb_vmod *vmod;
xkb_led_index_t led;
unsigned int i, j;
struct xkb_key *key;
return false;
/* Update keymap->vmods, the virtual -> real mod mapping. */
- for (vmod = 0; vmod < XKB_NUM_VIRTUAL_MODS; vmod++)
- keymap->vmods[vmod] = 0;
-
- xkb_foreach_key(key, keymap) {
- if (!key->vmodmap)
- continue;
-
- for (vmod = 0; vmod < XKB_NUM_VIRTUAL_MODS; vmod++) {
- if (!(key->vmodmap & (1 << vmod)))
- continue;
- keymap->vmods[vmod] |= key->modmap;
- }
- }
+ xkb_foreach_key(key, keymap)
+ darray_enumerate(i, vmod, keymap->vmods)
+ if (key->vmodmap & (1 << i))
+ vmod->mapping |= key->modmap;
/* Now update the level masks for all the types to reflect the vmods. */
for (i = 0; i < keymap->num_types; i++) {
xkb_mod_index_t i;
memset(info, 0, sizeof(*info));
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++)
- if (keymap->vmod_names[i])
- info->defined |= (1 << i);
+ for (i = 0; i < darray_size(keymap->vmods); i++)
+ info->defined |= (1 << i);
}
bool
enum merge_mode mergeMode, VModInfo *info)
{
xkb_mod_index_t i;
- int nextFree;
- xkb_mod_mask_t bit;
+ const struct xkb_vmod *vmod;
+ struct xkb_vmod new;
if (stmt->value)
log_err(keymap->ctx,
"Support for setting a value in a virtual_modifiers statement has been removed; "
"Value ignored\n");
- nextFree = -1;
- for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS; i++, bit <<= 1) {
- if (!(info->defined & bit)) {
- if (nextFree < 0)
- nextFree = i;
- continue;
+ darray_enumerate(i, vmod, keymap->vmods) {
+ if (vmod->name == stmt->name) {
+ info->available |= 1 << i;
+ return true;
}
-
- /* Already defined. */
- if (!keymap->vmod_names[i])
- continue;
-
- if (keymap->vmod_names[i] != stmt->name)
- continue;
-
- info->available |= bit;
- return true;
}
- if (nextFree < 0) {
+ if (darray_size(keymap->vmods) >= XKB_MAX_VIRTUAL_MODS) {
log_err(keymap->ctx,
"Too many virtual modifiers defined (maximum %d)\n",
- XKB_NUM_VIRTUAL_MODS);
+ XKB_MAX_VIRTUAL_MODS);
return false;
}
- info->defined |= (1 << nextFree);
- info->available |= (1 << nextFree);
-
- keymap->vmod_names[nextFree] = stmt->name;
+ new.name = stmt->name;
+ new.mapping = 0;
+ darray_append(keymap->vmods, new);
+ info->available |= (1 << (darray_size(keymap->vmods) - 1));
return true;
}
LookupVModIndex(const struct xkb_keymap *keymap, xkb_atom_t field,
enum expr_value_type type, xkb_mod_index_t *val_rtrn)
{
+ const struct xkb_vmod *vmod;
xkb_mod_index_t i;
if (type != EXPR_TYPE_INT)
return false;
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if (keymap->vmod_names[i] == field) {
+ darray_enumerate(i, vmod, keymap->vmods) {
+ if (vmod->name == field) {
*val_rtrn = i;
return true;
}
ResolveVirtualModifier(ExprDef *def, struct xkb_keymap *keymap,
xkb_mod_index_t *ndx_rtrn, VModInfo *info)
{
+ const struct xkb_vmod *vmod;
xkb_mod_index_t i;
xkb_atom_t name = def->value.str;
return false;
}
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if ((info->available & (1 << i)) && keymap->vmod_names[i] == name) {
+ darray_enumerate(i, vmod, keymap->vmods) {
+ if ((info->available & (1 << i)) && vmod->name == name) {
*ndx_rtrn = i;
return true;
}