X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fxkbcomp%2Ftypes.c;h=fa12c235f6955af111550b30149967157a577c9d;hb=efb93c3632c1671a098293c8c79cd21f9fe7a985;hp=290ba8d3b88a33929948db4832902e2b9f0a2edd;hpb=8f1ee629042a31e24eebc0310060446667562549;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/xkbcomp/types.c b/src/xkbcomp/types.c index 290ba8d..fa12c23 100644 --- a/src/xkbcomp/types.c +++ b/src/xkbcomp/types.c @@ -24,241 +24,101 @@ * ********************************************************/ +#include "config.h" + #include "xkbcomp-priv.h" #include "text.h" #include "vmod.h" #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), - TYPE_FIELD_PRESERVE = (1 << 2), + TYPE_FIELD_MASK = (1 << 0), + TYPE_FIELD_MAP = (1 << 1), + TYPE_FIELD_PRESERVE = (1 << 2), TYPE_FIELD_LEVEL_NAME = (1 << 3), }; -typedef struct _KeyTypeInfo { +typedef struct { enum type_field defined; - unsigned file_id; enum merge_mode merge; - struct list entry; xkb_atom_t name; xkb_mod_mask_t mods; xkb_level_index_t num_levels; - darray(struct xkb_kt_map_entry) entries; + darray(struct xkb_key_type_entry) entries; darray(xkb_atom_t) level_names; } KeyTypeInfo; -typedef struct _KeyTypesInfo { +typedef struct { char *name; int errorCount; - unsigned file_id; - unsigned num_types; - struct list types; - VModInfo vmods; - struct xkb_keymap *keymap; + + darray(KeyTypeInfo) types; + struct xkb_mod_set mods; + + struct xkb_context *ctx; } KeyTypesInfo; /***====================================================================***/ static inline const char * -MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry) +MapEntryTxt(KeyTypesInfo *info, struct xkb_key_type_entry *entry) { - return VModMaskText(info->keymap, entry->mods.mods); + return ModMaskText(info->ctx, &info->mods, entry->mods.mods); } static inline const char * TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type) { - return xkb_atom_text(info->keymap->ctx, type->name); + return xkb_atom_text(info->ctx, type->name); } static inline const char * TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type) { - return VModMaskText(info->keymap, type->mods); + return ModMaskText(info->ctx, &info->mods, type->mods); } static inline bool ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type, const char *field) { - return ReportShouldBeArray(info->keymap, "key type", field, + return ReportShouldBeArray(info->ctx, "key type", field, TypeTxt(info, type)); } static inline bool -ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type, - const char *field, const char *wanted) +ReportTypeBadType(KeyTypesInfo *info, xkb_message_code_t code, + KeyTypeInfo *type, const char *field, const char *wanted) { - return ReportBadType(info->keymap->ctx, "key type", field, + return ReportBadType(info->ctx, code, "key type", field, TypeTxt(info, type), wanted); } -static inline bool -ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs) -{ - log_err(info->keymap->ctx, - "Key type \"%s\" has %d levels, must have %d; " - "Illegal type definition ignored\n", - type, has, needs); - return false; -} - /***====================================================================***/ static void -InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap, - unsigned file_id) +InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_context *ctx, + const struct xkb_mod_set *mods) { - info->name = strdup("default"); - info->errorCount = 0; - info->num_types = 0; - list_init(&info->types); - info->file_id = file_id; - InitVModInfo(&info->vmods, keymap); - info->keymap = keymap; + memset(info, 0, sizeof(*info)); + info->ctx = ctx; + info->mods = *mods; } static void -FreeKeyTypeInfo(KeyTypeInfo * type) +ClearKeyTypeInfo(KeyTypeInfo *type) { darray_free(type->entries); darray_free(type->level_names); } static void -FreeKeyTypesInfo(KeyTypesInfo * info) +ClearKeyTypesInfo(KeyTypesInfo *info) { - KeyTypeInfo *type, *next_type; free(info->name); - info->name = NULL; - list_foreach_safe(type, next_type, &info->types, entry) { - FreeKeyTypeInfo(type); - free(type); - } -} - -static KeyTypeInfo * -NextKeyType(KeyTypesInfo * info) -{ - KeyTypeInfo *type; - - type = calloc(1, sizeof(*type)); - if (!type) - return NULL; - - type->file_id = info->file_id; - - list_append(&type->entry, &info->types); - info->num_types++; - return type; + darray_free(info->types); } static KeyTypeInfo * @@ -266,7 +126,7 @@ FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name) { KeyTypeInfo *old; - list_foreach(old, &info->types, entry) + darray_foreach(old, info->types) if (old->name == name) return old; @@ -274,51 +134,41 @@ FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name) } static bool -AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new) +AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new, bool same_file) { KeyTypeInfo *old; - struct list entry; - int verbosity = xkb_get_log_verbosity(info->keymap->ctx); + const int verbosity = xkb_context_get_log_verbosity(info->ctx); old = FindMatchingKeyType(info, new->name); if (old) { if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) { - if ((old->file_id == new->file_id && verbosity > 0) || - verbosity > 9) { - log_warn(info->keymap->ctx, + if ((same_file && verbosity > 0) || verbosity > 9) { + log_warn(info->ctx, + XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS, "Multiple definitions of the %s key type; " "Earlier definition ignored\n", - xkb_atom_text(info->keymap->ctx, new->name)); + xkb_atom_text(info->ctx, new->name)); } - entry = old->entry; - FreeKeyTypeInfo(old); + ClearKeyTypeInfo(old); *old = *new; - old->entry = entry; darray_init(new->entries); darray_init(new->level_names); return true; } - if (old->file_id == new->file_id) - log_lvl(info->keymap->ctx, 4, + if (same_file) + log_vrb(info->ctx, 4, + XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS, "Multiple definitions of the %s key type; " "Later definition ignored\n", - xkb_atom_text(info->keymap->ctx, new->name)); + xkb_atom_text(info->ctx, new->name)); - FreeKeyTypeInfo(new); + ClearKeyTypeInfo(new); return true; } - old = NextKeyType(info); - if (!old) - return false; - - entry = old->entry; - *old = *new; - old->entry = entry; - darray_init(new->entries); - darray_init(new->level_names); + darray_append(info->types, *new); return true; } @@ -328,22 +178,29 @@ static void MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from, enum merge_mode merge) { - KeyTypeInfo *type, *next_type; - if (from->errorCount > 0) { into->errorCount += from->errorCount; return; } + into->mods = from->mods; + if (into->name == NULL) { into->name = from->name; from->name = NULL; } - list_foreach_safe(type, next_type, &from->types, entry) { - type->merge = (merge == MERGE_DEFAULT ? type->merge : merge); - if (!AddKeyType(into, type)) - into->errorCount++; + if (darray_empty(into->types)) { + into->types = from->types; + darray_init(from->types); + } + else { + KeyTypeInfo *type; + darray_foreach(type, from->types) { + type->merge = (merge == MERGE_DEFAULT ? type->merge : merge); + if (!AddKeyType(into, type, false)) + into->errorCount++; + } } } @@ -351,39 +208,40 @@ static void HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge); static bool -HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt) +HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *include) { - enum merge_mode merge = MERGE_DEFAULT; - XkbFile *rtrn; - KeyTypesInfo included, next_incl; - - InitKeyTypesInfo(&included, info->keymap, info->file_id); - if (stmt->stmt) { - free(included.name); - included.name = stmt->stmt; - stmt->stmt = NULL; - } + KeyTypesInfo included; + + if (!include) + return false; - for (; stmt; stmt = stmt->next_incl) { - if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES, - &rtrn, &merge)) { + InitKeyTypesInfo(&included, info->ctx, &info->mods); + included.name = include->stmt; + include->stmt = NULL; + + for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { + KeyTypesInfo next_incl; + XkbFile *file; + + file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_TYPES); + if (!file) { info->errorCount += 10; - FreeKeyTypesInfo(&included); + ClearKeyTypesInfo(&included); return false; } - InitKeyTypesInfo(&next_incl, info->keymap, rtrn->id); + InitKeyTypesInfo(&next_incl, info->ctx, &included.mods); - HandleKeyTypesFile(&next_incl, rtrn, merge); + HandleKeyTypesFile(&next_incl, file, stmt->merge); - MergeIncludedKeyTypes(&included, &next_incl, merge); + MergeIncludedKeyTypes(&included, &next_incl, stmt->merge); - FreeKeyTypesInfo(&next_incl); - FreeXkbFile(rtrn); + ClearKeyTypesInfo(&next_incl); + FreeXkbFile(file); } - MergeIncludedKeyTypes(info, &included, merge); - FreeKeyTypesInfo(&included); + MergeIncludedKeyTypes(info, &included, include->merge); + ClearKeyTypesInfo(&included); return (info->errorCount == 0); } @@ -397,25 +255,25 @@ SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, xkb_mod_mask_t mods; if (arrayNdx) - log_warn(info->keymap->ctx, + log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The modifiers field of a key type is not an array; " "Illegal array subscript ignored\n"); - /* get modifier mask for current type */ - if (!ExprResolveVModMask(info->keymap, value, &mods)) { - log_err(info->keymap->ctx, + if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &mods)) { + log_err(info->ctx, + XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Key type mask field must be a modifier mask; " "Key type definition ignored\n"); return false; } if (type->defined & TYPE_FIELD_MASK) { - log_warn(info->keymap->ctx, + log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple modifier mask definitions for key type %s; " "Using %s, ignoring %s\n", - xkb_atom_text(info->keymap->ctx, type->name), + xkb_atom_text(info->ctx, type->name), TypeMaskTxt(info, type), - VModMaskText(info->keymap, mods)); + ModMaskText(info->ctx, &info->mods, mods)); return false; } @@ -425,10 +283,10 @@ SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, /***====================================================================***/ -static struct xkb_kt_map_entry * +static struct xkb_key_type_entry * FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods) { - struct xkb_kt_map_entry *entry; + struct xkb_key_type_entry *entry; darray_foreach(entry, type->entries) if (entry->mods.mods == mods) @@ -437,24 +295,17 @@ FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods) return NULL; } -/** - * 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 - * entry is created. - * - * @param clobber Overwrite existing entry. - * @param report true if a warning is to be printed on. - */ static bool AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, - struct xkb_kt_map_entry *new, bool clobber, bool report) + struct xkb_key_type_entry *new, bool clobber, bool report) { - struct xkb_kt_map_entry * old; + struct xkb_key_type_entry *old; old = FindMatchingMapEntry(type, new->mods.mods); if (old) { if (report && old->level != new->level) { - log_warn(info->keymap->ctx, + log_warn(info->ctx, + XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY, "Multiple map entries for %s in %s; " "Using %d, ignoring %d\n", MapEntryTxt(info, new), TypeTxt(info, type), @@ -462,8 +313,9 @@ AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, (clobber ? old->level : new->level) + 1); } else { - log_lvl(info->keymap->ctx, 10, - "Multiple occurences of map[%s]= %d in %s; Ignored\n", + log_vrb(info->ctx, 10, + XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY, + "Multiple occurrences of map[%s]= %d in %s; Ignored\n", MapEntryTxt(info, new), new->level + 1, TypeTxt(info, type)); return true; @@ -489,28 +341,32 @@ static bool SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, ExprDef *value) { - struct xkb_kt_map_entry entry; + struct xkb_key_type_entry entry; if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "map entry"); - if (!ExprResolveVModMask(info->keymap, arrayNdx, &entry.mods.mods)) - return ReportTypeBadType(info, type, "map entry", "modifier mask"); + if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, + &entry.mods.mods)) + return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, + type, "map entry", "modifier mask"); if (entry.mods.mods & (~type->mods)) { - log_lvl(info->keymap->ctx, 1, - "Map entry for unused modifiers in %s; " + log_vrb(info->ctx, 1, + XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE, + "Map entry for modifiers not used by type %s; " "Using %s instead of %s\n", TypeTxt(info, type), - VModMaskText(info->keymap, entry.mods.mods & type->mods), + ModMaskText(info->ctx, &info->mods, + entry.mods.mods & type->mods), MapEntryTxt(info, &entry)); entry.mods.mods &= type->mods; } - if (!ExprResolveLevel(info->keymap->ctx, value, &entry.level)) { - log_err(info->keymap->ctx, - "Level specifications in a key type must be integer; " - "Ignoring malformed level specification\n"); + if (!ExprResolveLevel(info->ctx, value, &entry.level)) { + log_err(info->ctx, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, + "Level specifications in a key type must be integer; " + "Ignoring malformed level specification\n"); return false; } @@ -525,8 +381,8 @@ static bool AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type, xkb_mod_mask_t mods, xkb_mod_mask_t preserve_mods) { - struct xkb_kt_map_entry *entry; - struct xkb_kt_map_entry new; + struct xkb_key_type_entry *entry; + struct xkb_key_type_entry new; darray_foreach(entry, type->entries) { if (entry->mods.mods != mods) @@ -540,22 +396,24 @@ AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type, /* Map exists with same preserve; do nothing. */ if (entry->preserve.mods == preserve_mods) { - log_lvl(info->keymap->ctx, 10, + log_vrb(info->ctx, 10, + XKB_WARNING_DUPLICATE_ENTRY, "Identical definitions for preserve[%s] in %s; " "Ignored\n", - VModMaskText(info->keymap, mods), + ModMaskText(info->ctx, &info->mods, mods), TypeTxt(info, type)); return true; } /* Map exists with different preserve; latter wins. */ - log_lvl(info->keymap->ctx, 1, + log_vrb(info->ctx, 1, + XKB_WARNING_CONFLICTING_KEY_TYPE_PRESERVE_ENTRIES, "Multiple definitions for preserve[%s] in %s; " "Using %s, ignoring %s\n", - VModMaskText(info->keymap, mods), + ModMaskText(info->ctx, &info->mods, mods), TypeTxt(info, type), - VModMaskText(info->keymap, preserve_mods), - VModMaskText(info->keymap, entry->preserve.mods)); + ModMaskText(info->ctx, &info->mods, preserve_mods), + ModMaskText(info->ctx, &info->mods, entry->preserve.mods)); entry->preserve.mods = preserve_mods; return true; @@ -564,7 +422,7 @@ AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type, /* * 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. + * may be overridden later with an explicit map[] statement. */ new.level = 0; new.mods.mods = mods; @@ -582,28 +440,31 @@ SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "preserve entry"); - if (!ExprResolveVModMask(info->keymap, arrayNdx, &mods)) - return ReportTypeBadType(info, type, "preserve entry", - "modifier mask"); + if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, &mods)) + return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, + type, "preserve entry", "modifier mask"); if (mods & ~type->mods) { const char *before, *after; - before = VModMaskText(info->keymap, mods); + before = ModMaskText(info->ctx, &info->mods, mods); mods &= type->mods; - after = VModMaskText(info->keymap, mods); + after = ModMaskText(info->ctx, &info->mods, mods); - log_lvl(info->keymap->ctx, 1, - "Preserve for modifiers not used by the %s type; " + log_vrb(info->ctx, 1, + XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE, + "Preserve entry for modifiers not used by the %s type; " "Index %s converted to %s\n", TypeTxt(info, type), before, after); } - if (!ExprResolveVModMask(info->keymap, value, &preserve_mods)) { - log_err(info->keymap->ctx, + if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, + &preserve_mods)) { + log_err(info->ctx, + XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Preserve value in a key type is not a modifier mask; " "Ignoring preserve[%s] in type %s\n", - VModMaskText(info->keymap, mods), + ModMaskText(info->ctx, &info->mods, mods), TypeTxt(info, type)); return false; } @@ -611,14 +472,15 @@ SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, if (preserve_mods & ~mods) { const char *before, *after; - before = VModMaskText(info->keymap, preserve_mods); + before = ModMaskText(info->ctx, &info->mods, preserve_mods); preserve_mods &= mods; - after = VModMaskText(info->keymap, preserve_mods); + after = ModMaskText(info->ctx, &info->mods, preserve_mods); - log_lvl(info->keymap->ctx, 1, + log_vrb(info->ctx, 1, + XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT, "Illegal value for preserve[%s] in type %s; " "Converted %s to %s\n", - VModMaskText(info->keymap, mods), + ModMaskText(info->ctx, &info->mods, mods), TypeTxt(info, type), before, after); } @@ -639,7 +501,8 @@ AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type, /* Same level, same name. */ if (darray_item(type->level_names, level) == name) { - log_lvl(info->keymap->ctx, 10, + log_vrb(info->ctx, 10, + XKB_WARNING_DUPLICATE_ENTRY, "Duplicate names for level %d of key type %s; Ignored\n", level + 1, TypeTxt(info, type)); return true; @@ -648,10 +511,11 @@ AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type, /* Same level, different name. */ if (darray_item(type->level_names, level) != XKB_ATOM_NONE) { const char *old, *new; - old = xkb_atom_text(info->keymap->ctx, + old = xkb_atom_text(info->ctx, darray_item(type->level_names, level)); - new = xkb_atom_text(info->keymap->ctx, name); - log_lvl(info->keymap->ctx, 1, + new = xkb_atom_text(info->ctx, name); + log_vrb(info->ctx, 1, + XKB_WARNING_CONFLICTING_KEY_TYPE_LEVEL_NAMES, "Multiple names for level %d of key type %s; " "Using %s, ignoring %s\n", level + 1, TypeTxt(info, type), @@ -674,35 +538,28 @@ SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, { xkb_level_index_t level; xkb_atom_t level_name; - struct xkb_context *ctx = info->keymap->ctx; - const char *str; if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "level name"); - if (!ExprResolveLevel(ctx, arrayNdx, &level)) - return ReportTypeBadType(info, type, "level name", "integer"); + if (!ExprResolveLevel(info->ctx, arrayNdx, &level)) + return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, + type, "level name", "integer"); - if (!ExprResolveString(ctx, value, &str)) { - log_err(info->keymap->ctx, + if (!ExprResolveString(info->ctx, value, &level_name)) { + log_err(info->ctx, + XKB_ERROR_WRONG_FIELD_TYPE, "Non-string name for level %d in key type %s; " "Ignoring illegal level name definition\n", - level + 1, xkb_atom_text(ctx, type->name)); + level + 1, xkb_atom_text(info->ctx, type->name)); return false; } - level_name = xkb_atom_intern(ctx, str); - return AddLevelName(info, type, level, level_name, true); } /***====================================================================***/ -/** - * Parses the fields in a type "..." { } description. - * - * @param field The field to parse (e.g. modifiers, map, level_name) - */ static bool SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type, const char *field, ExprDef *arrayNdx, ExprDef *value) @@ -726,7 +583,8 @@ SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type, type_field = TYPE_FIELD_LEVEL_NAME; ok = SetLevelName(info, type, arrayNdx, value); } else { - log_err(info->keymap->ctx, + log_err(info->ctx, + XKB_ERROR_UNKNOWN_FIELD, "Unknown field %s in key type %s; Definition ignored\n", field, TypeTxt(info, type)); } @@ -743,13 +601,14 @@ HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type) ExprDef *arrayNdx; for (; def; def = (VarDef *) def->common.next) { - ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field, + ok = ExprResolveLhs(info->ctx, def->name, &elem, &field, &arrayNdx); if (!ok) continue; if (elem && istreq(elem, "type")) { - log_err(info->keymap->ctx, + log_err(info->ctx, + XKB_ERROR_INVALID_SET_DEFAULT_STATEMENT, "Support for changing the default type has been removed; " "Statement ignored\n"); continue; @@ -761,16 +620,11 @@ HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type) return ok; } -/** - * Process a type "XYZ" { } specification in the xkb_types section. - * - */ static bool HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge) { KeyTypeInfo type = { .defined = 0, - .file_id = info->file_id, .merge = (def->merge == MERGE_DEFAULT ? merge : def->merge), .name = def->name, .mods = 0, @@ -779,14 +633,12 @@ HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge) .level_names = darray_new(), }; - /* Parse the actual content. */ if (!HandleKeyTypeBody(info, def->body, &type)) { info->errorCount++; return false; } - /* Now add the new keytype to the info struct */ - if (!AddKeyType(info, &type)) { + if (!AddKeyType(info, &type, true)) { info->errorCount++; return false; } @@ -794,44 +646,37 @@ HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge) return true; } -/** - * Process an xkb_types section. - * - * @param file The parsed xkb_types section. - * @param merge Merge Strategy (e.g. MERGE_OVERRIDE) - * @param info Pointer to memory where the outcome will be stored. - */ static void HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge) { bool ok; - ParseCommon *stmt; free(info->name); info->name = strdup_safe(file->name); - for (stmt = file->defs; stmt; stmt = stmt->next) { + for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) { switch (stmt->type) { case STMT_INCLUDE: ok = HandleIncludeKeyTypes(info, (IncludeStmt *) stmt); break; - case STMT_TYPE: /* e.g. type "ONE_LEVEL" */ + case STMT_TYPE: ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge); break; case STMT_VAR: - log_err(info->keymap->ctx, + log_err(info->ctx, + XKB_ERROR_WRONG_STATEMENT_TYPE, "Support for changing the default type has been removed; " "Statement ignored\n"); ok = true; break; - case STMT_VMOD: /* virtual_modifiers NumLock, ... */ - ok = HandleVModDef((VModDef *) stmt, info->keymap, merge, - &info->vmods); + case STMT_VMOD: + ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge); break; default: - log_err(info->keymap->ctx, + log_err(info->ctx, + XKB_ERROR_WRONG_STATEMENT_TYPE, "Key type files may not include other declarations; " - "Ignoring %s\n", StmtTypeToString(stmt->type)); + "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; } @@ -840,80 +685,84 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge) info->errorCount++; if (info->errorCount > 10) { - log_err(info->keymap->ctx, - "Abandoning keytypes file \"%s\"\n", file->topName); + log_err(info->ctx, + XKB_ERROR_INVALID_SYNTAX, + "Abandoning keytypes file \"%s\"\n", file->name); break; } } } +/***====================================================================***/ + static bool -CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def, - struct xkb_key_type *type) +CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info) { - type->mods.mods = def->mods; - type->num_levels = def->num_levels; - type->map = darray_mem(def->entries, 0); - type->num_entries = darray_size(def->entries); - darray_init(def->entries); - type->name = def->name; - type->level_names = darray_mem(def->level_names, 0); - darray_init(def->level_names); + unsigned num_types; + struct xkb_key_type *types; + + num_types = darray_empty(info->types) ? 1 : darray_size(info->types); + types = calloc(num_types, sizeof(*types)); + if (!types) + return false; + + /* + * If no types were specified, a default unnamed one-level type is + * used for all keys. + */ + if (darray_empty(info->types)) { + struct xkb_key_type *type = &types[0]; + + type->mods.mods = 0; + type->num_levels = 1; + type->entries = NULL; + type->num_entries = 0; + type->name = xkb_atom_intern_literal(keymap->ctx, "default"); + type->level_names = NULL; + type->num_level_names = 0; + } + else { + for (unsigned i = 0; i < num_types; i++) { + KeyTypeInfo *def = &darray_item(info->types, i); + struct xkb_key_type *type = &types[i]; + + type->name = def->name; + type->mods.mods = def->mods; + type->num_levels = def->num_levels; + darray_steal(def->level_names, &type->level_names, &type->num_level_names); + darray_steal(def->entries, &type->entries, &type->num_entries); + } + } + keymap->types_section_name = strdup_safe(info->name); + XkbEscapeMapName(keymap->types_section_name); + keymap->num_types = num_types; + keymap->types = types; + keymap->mods = info->mods; return true; } +/***====================================================================***/ + bool CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge) { - unsigned int i; - unsigned int num_types; KeyTypesInfo info; - KeyTypeInfo *def; - InitKeyTypesInfo(&info, keymap, file->id); + InitKeyTypesInfo(&info, keymap->ctx, &keymap->mods); HandleKeyTypesFile(&info, file, merge); - if (info.errorCount != 0) goto err_info; - if (info.name) - keymap->types_section_name = strdup(info.name); - - num_types = info.num_types ? info.num_types : 1; - keymap->types = calloc(num_types, sizeof(*keymap->types)); - if (!keymap->types) + if (!CopyKeyTypesToKeymap(keymap, &info)) goto err_info; - keymap->num_types = num_types; - - /* - * If no types were specified, a default unnamed one-level type is - * used for all keys. - */ - if (info.num_types == 0) { - KeyTypeInfo dflt = { - .name = xkb_atom_intern(keymap->ctx, "default"), - .mods = 0, - .num_levels = 1, - .entries = darray_new(), - .level_names = darray_new(), - }; - - if (!CopyDefToKeyType(&info, &dflt, &keymap->types[0])) - goto err_info; - } else { - i = 0; - list_foreach(def, &info.types, entry) - if (!CopyDefToKeyType(&info, def, &keymap->types[i++])) - goto err_info; - } - FreeKeyTypesInfo(&info); + ClearKeyTypesInfo(&info); return true; err_info: - FreeKeyTypesInfo(&info); + ClearKeyTypesInfo(&info); return false; }