*
********************************************************/
+#include "config.h"
+
#include "xkbcomp-priv.h"
#include "text.h"
#include "expr.h"
#include "vmod.h"
-void
-InitVModInfo(VModInfo *info, struct xkb_keymap *keymap)
-{
- xkb_layout_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);
-}
-
bool
-HandleVModDef(VModDef *stmt, struct xkb_keymap *keymap,
- enum merge_mode mergeMode, VModInfo *info)
+HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods,
+ VModDef *stmt, enum merge_mode merge)
{
xkb_mod_index_t i;
- int nextFree;
- xkb_mod_mask_t bit;
-
- 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;
+ struct xkb_mod *mod;
+ xkb_mod_mask_t mapping;
+
+ 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(ctx, stmt->value, MOD_REAL, mods, &mapping)) {
+ log_err(ctx,
+ "Declaration of %s ignored\n",
+ xkb_atom_text(ctx, stmt->name));
+ return false;
}
-
- /* Already defined. */
- if (!keymap->vmod_names[i])
- continue;
-
- if (keymap->vmod_names[i] != stmt->name)
- continue;
-
- info->available |= bit;
- return true;
}
-
- if (nextFree < 0) {
- log_err(keymap->ctx,
- "Too many virtual modifiers defined (maximum %d)\n",
- XKB_NUM_VIRTUAL_MODS);
- return false;
+ else {
+ mapping = 0;
}
- info->defined |= (1 << nextFree);
- info->available |= (1 << nextFree);
+ xkb_mods_enumerate(i, mod, mods) {
+ if (mod->name == stmt->name) {
+ if (mod->type != MOD_VIRT) {
+ log_err(ctx,
+ "Can't add a virtual modifier named \"%s\"; "
+ "there is already a non-virtual modifier with this name! Ignored\n",
+ xkb_atom_text(ctx, mod->name));
+ return false;
+ }
- keymap->vmod_names[nextFree] = stmt->name;
- return true;
-}
+ if (mod->mapping == mapping)
+ return true;
-static bool
-LookupVModIndex(const struct xkb_keymap *keymap, xkb_atom_t field,
- enum expr_value_type type, xkb_mod_index_t *val_rtrn)
-{
- xkb_mod_index_t i;
-
- if (type != EXPR_TYPE_INT)
- return false;
+ if (mod->mapping != 0) {
+ xkb_mod_mask_t use, ignore;
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if (keymap->vmod_names[i] == field) {
- *val_rtrn = i;
- return true;
- }
- }
+ use = (merge == MERGE_OVERRIDE ? mapping : mod->mapping);
+ ignore = (merge == MERGE_OVERRIDE ? mod->mapping : mapping);
- return false;
-}
+ log_warn(ctx,
+ "Virtual modifier %s defined multiple times; "
+ "Using %s, ignoring %s\n",
+ xkb_atom_text(ctx, stmt->name),
+ ModMaskText(ctx, mods, use),
+ ModMaskText(ctx, mods, ignore));
-bool
-LookupVModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
- enum expr_value_type type, xkb_mod_mask_t *val_rtrn)
-{
- xkb_mod_index_t ndx;
+ mapping = use;
+ }
- if (LookupModMask(ctx, NULL, field, type, val_rtrn)) {
- return true;
- }
- else if (LookupVModIndex(priv, field, type, &ndx)) {
- *val_rtrn = (1 << (XKB_NUM_CORE_MODS + ndx));
- return true;
+ mod->mapping = mapping;
+ return true;
+ }
}
- return false;
-}
-
-bool
-ResolveVirtualModifier(ExprDef *def, struct xkb_keymap *keymap,
- xkb_mod_index_t *ndx_rtrn, VModInfo *info)
-{
- xkb_mod_index_t i;
- xkb_atom_t name = def->value.str;
-
- if (def->op != EXPR_IDENT) {
- log_err(keymap->ctx,
- "Cannot resolve virtual modifier: "
- "found %s where a virtual modifier name was expected\n",
- expr_op_type_to_string(def->op));
+ if (mods->num_mods >= XKB_MAX_MODS) {
+ log_err(ctx,
+ "Too many modifiers defined (maximum %d)\n",
+ XKB_MAX_MODS);
return false;
}
- for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
- if ((info->available & (1 << i)) && keymap->vmod_names[i] == name) {
- *ndx_rtrn = i;
- return true;
- }
- }
-
- log_err(keymap->ctx,
- "Cannot resolve virtual modifier: "
- "\"%s\" was not previously declared\n",
- xkb_atom_text(keymap->ctx, name));
- return false;
+ mods->mods[mods->num_mods].name = stmt->name;
+ mods->mods[mods->num_mods].type = MOD_VIRT;
+ mods->mods[mods->num_mods].mapping = mapping;
+ mods->num_mods++;
+ return true;
}