types: get rid of PreserveInfo

We don't need the indirection. We store the preserve mask directly in
the entry, and create a new one if it doesn't exists (which is exactly
what the current code does in a roundabout way).

Incidentally this fixes a bug where the effective modifier mask of the
entries' preserve[] wasn't calculated, so the virtual modifiers had no
effect there.

Signed-off-by: Ran Benita <ran234@gmail.com>
master
Ran Benita 2012-08-08 19:53:55 +03:00
parent 0f1ca360f1
commit fafc1132d2
1 changed files with 120 additions and 181 deletions

View File

@ -124,14 +124,6 @@
* TODO
*/
typedef struct _PreserveInfo {
struct list entry;
xkb_mod_mask_t indexMods;
xkb_mod_mask_t preMods;
xkb_mod_mask_t indexVMods;
xkb_mod_mask_t preVMods;
} PreserveInfo;
enum type_field {
TYPE_FIELD_MASK = (1 << 0),
TYPE_FIELD_MAP = (1 << 1),
@ -150,7 +142,6 @@ typedef struct _KeyTypeInfo {
xkb_mod_mask_t vmask;
xkb_level_index_t num_levels;
darray(struct xkb_kt_map_entry) entries;
struct list preserves;
darray(xkb_atom_t) level_names;
} KeyTypeInfo;
@ -173,18 +164,6 @@ MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry)
entry->mods.vmods);
}
static inline const char *
PreserveIndexTxt(KeyTypesInfo *info, PreserveInfo *pi)
{
return VModMaskText(info->keymap, pi->indexMods, pi->indexVMods);
}
static inline const char *
PreserveTxt(KeyTypesInfo *info, PreserveInfo *pi)
{
return VModMaskText(info->keymap, pi->preMods, pi->preVMods);
}
static inline const char *
TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
{
@ -241,12 +220,8 @@ InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
static void
FreeKeyTypeInfo(KeyTypeInfo * type)
{
PreserveInfo *pi, *next_pi;
darray_free(type->entries);
darray_free(type->level_names);
list_foreach_safe(pi, next_pi, &type->preserves, entry)
free(pi);
list_init(&type->preserves);
}
static void
@ -270,7 +245,6 @@ NextKeyType(KeyTypesInfo * info)
if (!type)
return NULL;
list_init(&type->preserves);
type->file_id = info->file_id;
list_append(&type->entry, &info->types);
@ -294,7 +268,7 @@ static bool
AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
{
KeyTypeInfo *old;
struct list type_entry, preserves_entry;
struct list entry;
int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
old = FindMatchingKeyType(info, new->name);
@ -308,13 +282,12 @@ AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
xkb_atom_text(info->keymap->ctx, new->name));
}
type_entry = old->entry;
entry = old->entry;
FreeKeyTypeInfo(old);
*old = *new;
old->entry = type_entry;
old->entry = entry;
darray_init(new->entries);
darray_init(new->level_names);
list_init(&new->preserves);
return true;
}
@ -332,15 +305,11 @@ AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
if (!old)
return false;
list_replace(&new->preserves, &old->preserves);
type_entry = old->entry;
preserves_entry = old->preserves;
entry = old->entry;
*old = *new;
old->preserves = preserves_entry;
old->entry = type_entry;
old->entry = entry;
darray_init(new->entries);
darray_init(new->level_names);
list_init(&new->preserves);
return true;
}
@ -463,62 +432,6 @@ FindMatchingMapEntry(KeyTypeInfo * type, unsigned mask, unsigned vmask)
return NULL;
}
static struct xkb_kt_map_entry *
NextMapEntry(KeyTypesInfo *info, KeyTypeInfo * type)
{
darray_resize0(type->entries, darray_size(type->entries) + 1);
return &darray_item(type->entries, darray_size(type->entries) - 1);
}
static bool
AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
PreserveInfo *new, bool clobber, bool report)
{
PreserveInfo *old;
list_foreach(old, &type->preserves, entry) {
if (old->indexMods != new->indexMods ||
old->indexVMods != new->indexVMods)
continue;
if (old->preMods == new->preMods && old->preVMods == new->preVMods) {
log_lvl(info->keymap->ctx, 10,
"Identical definitions for preserve[%s] in %s; "
"Ignored\n",
PreserveIndexTxt(info, old), TypeTxt(info, type));
return true;
}
if (report)
log_lvl(info->keymap->ctx, 1,
"Multiple definitions for preserve[%s] in %s; "
"Using %s, ignoring %s\n",
PreserveIndexTxt(info, old), TypeTxt(info, type),
PreserveTxt(info, clobber ? new : old),
PreserveTxt(info, clobber ? old : new));
if (clobber) {
old->preMods = new->preMods;
old->preVMods = new->preVMods;
}
return true;
}
old = malloc(sizeof(*old));
if (!old) {
log_wsgo(info->keymap->ctx,
"Couldn't allocate preserve in %s; Preserve[%s] lost\n",
TypeTxt(info, type), PreserveIndexTxt(info, new));
return false;
}
*old = *new;
list_append(&old->entry, &type->preserves);
return true;
}
/**
* Add a new KTMapEntry to the given key type. If an entry with the same mods
* already exists, the level is updated (if clobber is TRUE). Otherwise, a new
@ -536,22 +449,12 @@ AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
old = FindMatchingMapEntry(type, new->mods.real_mods, new->mods.vmods);
if (old) {
if (report && old->level != new->level) {
xkb_level_index_t use, ignore;
if (clobber) {
use = new->level + 1;
ignore = old->level + 1;
}
else {
use = old->level + 1;
ignore = new->level + 1;
}
log_warn(info->keymap->ctx,
"Multiple map entries for %s in %s; "
"Using %d, ignoring %d\n",
MapEntryTxt(info, new), TypeTxt(info, type), use,
ignore);
MapEntryTxt(info, new), TypeTxt(info, type),
(clobber ? new->level : old->level) + 1,
(clobber ? old->level : new->level) + 1);
}
else {
log_lvl(info->keymap->ctx, 10,
@ -561,22 +464,19 @@ AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
return true;
}
if (clobber)
if (clobber) {
if (new->level >= type->num_levels)
type->num_levels = new->level + 1;
old->level = new->level;
}
return true;
}
old = NextMapEntry(info, type);
if (!old)
return false;
if (new->level >= type->num_levels)
type->num_levels = new->level + 1;
old->mods.mask = new->mods.real_mods;
old->mods.real_mods = new->mods.real_mods;
old->mods.vmods = new->mods.vmods;
old->level = new->level;
darray_append(type->entries, *new);
return true;
}
@ -617,15 +517,87 @@ SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
return false;
}
entry.preserve.real_mods = 0;
entry.preserve.vmods = 0;
return AddMapEntry(info, type, &entry, true, true);
}
/***====================================================================***/
static bool
AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
xkb_mod_mask_t rmods, xkb_mod_mask_t vmods,
xkb_mod_mask_t preserve_rmods, xkb_mod_mask_t preserve_vmods)
{
struct xkb_kt_map_entry *entry;
struct xkb_mods mods = {
.real_mods = rmods,
.vmods = vmods,
};
struct xkb_mods preserve = {
.real_mods = preserve_rmods,
.vmods = preserve_vmods,
};
struct xkb_kt_map_entry new;
darray_foreach(entry, type->entries) {
if (entry->mods.real_mods != mods.real_mods ||
entry->mods.vmods != mods.vmods)
continue;
/* Map exists without previous preserve (or "None"); override. */
if (entry->preserve.real_mods == 0 && entry->preserve.vmods == 0) {
entry->preserve = preserve;
return true;
}
/* Map exists with same preserve; do nothing. */
if (entry->preserve.real_mods == preserve.real_mods &&
entry->preserve.vmods == preserve.vmods) {
log_lvl(info->keymap->ctx, 10,
"Identical definitions for preserve[%s] in %s; "
"Ignored\n",
VModMaskText(info->keymap, rmods, vmods),
TypeTxt(info, type));
return true;
}
/* Map exists with different preserve; latter wins. */
log_lvl(info->keymap->ctx, 1,
"Multiple definitions for preserve[%s] in %s; "
"Using %s, ignoring %s\n",
VModMaskText(info->keymap, mods.real_mods, mods.vmods),
TypeTxt(info, type),
VModMaskText(info->keymap,
preserve.real_mods,
preserve.vmods),
VModMaskText(info->keymap,
entry->preserve.real_mods,
entry->preserve.vmods));
entry->preserve = preserve;
return true;
}
/*
* Map does not exist, i.e. preserve[] came before map[].
* Create a map with the specified mask mapping to Level1. The level
* may be overriden later with an explicit map[] statement.
*/
new.level = 0;
new.mods = mods;
new.preserve = preserve;
darray_append(type->entries, new);
return true;
}
static bool
SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
ExprDef *value)
{
xkb_mod_mask_t mask;
PreserveInfo new;
xkb_mod_mask_t rmods, vmods, preserve_rmods, preserve_vmods;
if (arrayNdx == NULL)
return ReportTypeShouldBeArray(info, type, "preserve entry");
@ -634,49 +606,52 @@ SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
return ReportTypeBadType(info, type, "preserve entry",
"modifier mask");
new.indexMods = mask & 0xff;
new.indexVMods = (mask >> XkbNumModifiers) & 0xffff;
rmods = mask & 0xff;
vmods = (mask >> XkbNumModifiers) & 0xffff;
if ((new.indexMods & (~type->mask)) ||
(new.indexVMods & (~type->vmask))) {
const char *before = PreserveIndexTxt(info, &new);
if ((rmods & (~type->mask)) || (vmods & (~type->vmask))) {
const char *before, *after;
new.indexMods &= type->mask;
new.indexVMods &= type->vmask;
before = VModMaskText(info->keymap, rmods, vmods);
rmods &= type->mask;
vmods &= type->vmask;
after = VModMaskText(info->keymap, rmods, vmods);
log_lvl(info->keymap->ctx, 1,
"Preserve for modifiers not used by the %s type; "
"Index %s converted to %s\n",
TypeTxt(info, type), before,
PreserveIndexTxt(info, &new));
TypeTxt(info, type), before, after);
}
if (!ExprResolveVModMask(info->keymap, value, &mask)) {
log_err(info->keymap->ctx,
"Preserve value in a key type is not a modifier mask; "
"Ignoring preserve[%s] in type %s\n",
PreserveIndexTxt(info, &new), TypeTxt(info, type));
VModMaskText(info->keymap, rmods, vmods),
TypeTxt(info, type));
return false;
}
new.preMods = mask & 0xff;
new.preVMods = (mask >> XkbNumModifiers) & 0xffff;
preserve_rmods = mask & 0xff;
preserve_vmods = (mask >> XkbNumModifiers) & 0xffff;
if ((new.preMods & (~new.indexMods)) ||
(new.preVMods & (~new.indexVMods))) {
const char *before = PreserveIndexTxt(info, &new);
if ((preserve_rmods & ~rmods) || (preserve_vmods & ~vmods)) {
const char *before, *after;
new.preMods &= new.indexMods;
new.preVMods &= new.indexVMods;
before = VModMaskText(info->keymap, preserve_rmods, preserve_vmods);
preserve_rmods &= rmods;
preserve_vmods &= vmods;
after = VModMaskText(info->keymap, preserve_rmods, preserve_vmods);
log_lvl(info->keymap->ctx, 1,
"Illegal value for preserve[%s] in type %s; "
"Converted %s to %s\n",
PreserveTxt(info, &new), TypeTxt(info, type),
before, PreserveIndexTxt(info, &new));
VModMaskText(info->keymap, rmods, vmods),
TypeTxt(info, type), before, after);
}
return AddPreserve(info, type, &new, true, true);
return AddPreserve(info, type, rmods, vmods,
preserve_rmods, preserve_vmods);
}
/***====================================================================***/
@ -832,7 +807,6 @@ HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
.entries = darray_new(),
.level_names = darray_new(),
};
list_init(&type.preserves);
/* Parse the actual content. */
if (!HandleKeyTypeBody(info, def->body, &type)) {
@ -906,29 +880,19 @@ static bool
ComputeEffectiveMap(struct xkb_keymap *keymap, struct xkb_key_type *type)
{
unsigned int i;
xkb_mod_mask_t tmp;
struct xkb_kt_map_entry *entry = NULL;
struct xkb_kt_map_entry *entry;
if (type->mods.vmods != 0) {
tmp = VModsToReal(keymap, type->mods.vmods);
type->mods.mask = tmp | type->mods.real_mods;
type->mods.mask = type->mods.real_mods;
type->mods.mask |= VModsToReal(keymap, type->mods.vmods);
for (i = 0; i < type->num_entries; i++) {
entry = &type->map[i];
tmp = 0;
if (entry->mods.vmods != 0) {
tmp = VModsToReal(keymap, entry->mods.vmods);
if (tmp == 0)
continue;
}
entry->mods.mask = entry->mods.real_mods;
entry->mods.mask |= VModsToReal(keymap, entry->mods.vmods);
entry->mods.mask =
(entry->mods.real_mods | tmp) & type->mods.mask;
}
}
else {
type->mods.mask = type->mods.real_mods;
entry->preserve.mask = entry->preserve.real_mods;
entry->preserve.mask |= VModsToReal(keymap, entry->preserve.vmods);
}
return true;
@ -938,30 +902,6 @@ static bool
CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
struct xkb_key_type *type)
{
PreserveInfo *pre;
struct xkb_keymap *keymap = info->keymap;
list_foreach(pre, &def->preserves, entry) {
struct xkb_kt_map_entry *match;
struct xkb_kt_map_entry tmp;
tmp.mods.real_mods = pre->indexMods;
tmp.mods.vmods = pre->indexVMods;
tmp.level = 0;
(void) AddMapEntry(info, def, &tmp, false, false);
match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods);
if (!match) {
log_wsgo(info->keymap->ctx,
"Couldn't find matching entry for preserve; Aborting\n");
return false;
}
match->preserve.mask = pre->preMods;
match->preserve.real_mods = pre->preMods;
match->preserve.vmods = pre->preVMods;
}
type->mods.real_mods = def->mask;
type->mods.vmods = def->vmask;
type->num_levels = def->num_levels;
@ -972,7 +912,7 @@ CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
type->level_names = darray_mem(def->level_names, 0);
darray_init(def->level_names);
return ComputeEffectiveMap(keymap, type);
return ComputeEffectiveMap(info->keymap, type);
}
bool
@ -1012,7 +952,6 @@ CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
.entries = darray_new(),
.level_names = darray_new(),
};
list_init(&dflt.preserves);
if (!CopyDefToKeyType(&info, &dflt, &keymap->types[0]))
goto err_info;