X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fxkbcomp%2Fsymbols.c;h=a41249552ff6b55e12f78d7940a274e184429fd9;hb=6d97d0ce5e2d96f97038a153599cee8a46b7042f;hp=ff089e72984014c7efa64cf08b9c01695ea9a864;hpb=376e45eb6d2d93599980e52248531a8f2e83470f;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/xkbcomp/symbols.c b/src/xkbcomp/symbols.c index ff089e7..a412495 100644 --- a/src/xkbcomp/symbols.c +++ b/src/xkbcomp/symbols.c @@ -58,11 +58,12 @@ #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 { @@ -100,14 +101,14 @@ typedef struct _KeyInfo { 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 @@ -121,57 +122,27 @@ ClearGroupInfo(GroupInfo *groupi) { 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]); -} - -static bool -CopyKeyInfo(KeyInfo * old, KeyInfo * new, bool clearOld) -{ - xkb_group_index_t i; - - *new = *old; - - if (clearOld) { - for (i = 0; i < XKB_NUM_GROUPS; i++) { - InitGroupInfo(&old->groups[i]); - } - } - else { - for (i = 0; i < XKB_NUM_GROUPS; i++) { - darray_copy(new->groups[i].syms, old->groups[i].syms); - darray_copy(new->groups[i].levels, old->groups[i].levels); - } - } - - return true; + GroupInfo *groupi; + darray_foreach(groupi, keyi->groups) + ClearGroupInfo(groupi); + darray_free(keyi->groups); } /***====================================================================***/ @@ -191,12 +162,12 @@ typedef struct _SymbolsInfo { 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; @@ -206,40 +177,30 @@ static void 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; @@ -434,10 +395,11 @@ UseNewKeyField(enum key_field field, enum key_field old, enum key_field new, 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); @@ -450,9 +412,18 @@ MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from) 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)) { @@ -484,6 +455,7 @@ MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from) (clobber ? "first" : "last")); ClearKeyInfo(from); + InitKeyInfo(from, info->file_id); return true; } @@ -491,20 +463,24 @@ static bool AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi) { unsigned long real_name; - KeyInfo *iter, *new; + KeyInfo *iter; + + /* + * Don't keep aliases in the keys array; this guarantees that + * searching for keys to merge with by straight comparison (see the + * following loop) is enough, and we won't get multiple KeyInfo's + * for the same key because of aliases. + */ + if (FindKeyNameForAlias(info->keymap, keyi->name, &real_name)) + keyi->name = real_name; darray_foreach(iter, info->keys) if (iter->name == keyi->name) return MergeKeys(info, iter, keyi); - if (FindKeyNameForAlias(info->keymap, keyi->name, &real_name)) - darray_foreach(iter, info->keys) - if (iter->name == real_name) - return MergeKeys(info, iter, keyi); - - darray_resize0(info->keys, darray_size(info->keys) + 1); - new = &darray_item(info->keys, darray_size(info->keys) - 1); - return CopyKeyInfo(keyi, new, true); + darray_append(info->keys, *keyi); + InitKeyInfo(keyi, info->file_id); + return true; } static bool @@ -582,10 +558,10 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from, 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]; } } @@ -629,10 +605,19 @@ HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *stmt) 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); @@ -653,27 +638,34 @@ HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *stmt) 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)) { @@ -685,6 +677,9 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, } (*ndx_rtrn)--; + if (*ndx_rtrn >= darray_size(keyi->groups)) + darray_resize0(keyi->groups, *ndx_rtrn + 1); + return true; } @@ -716,7 +711,7 @@ static bool 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; @@ -726,7 +721,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, 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; @@ -778,7 +773,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, 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; @@ -806,7 +801,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, ExprDef *value) { unsigned int i; - xkb_group_index_t ndx; + xkb_layout_index_t ndx; GroupInfo *groupi; unsigned int nActs; ExprDef *act; @@ -815,7 +810,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, 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; @@ -881,7 +876,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, 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)) @@ -902,8 +897,10 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, } 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")) @@ -1007,7 +1004,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, } 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, @@ -1035,7 +1032,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, 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) { @@ -1059,12 +1056,12 @@ SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value) 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; @@ -1122,7 +1119,9 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi) 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; } @@ -1148,27 +1147,31 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi) 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; } @@ -1176,11 +1179,22 @@ static int HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt) { KeyInfo keyi; - - InitKeyInfo(&keyi, info->file_id); - CopyKeyInfo(&info->dflt, &keyi, false); + xkb_layout_index_t i; + + keyi = info->dflt; + 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); + if (!HandleSymbolsBody(info, (VarDef *) stmt->symbols, &keyi)) { info->errorCount++; return false; @@ -1195,6 +1209,7 @@ HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt) info->errorCount++; return false; } + return true; } @@ -1261,7 +1276,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge) 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, @@ -1303,7 +1318,7 @@ static struct xkb_key * 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) { @@ -1373,27 +1388,27 @@ FindNamedType(struct xkb_keymap *keymap, xkb_atom_t name, unsigned *type_rtrn) * symbol per level. */ static bool -FindAutomaticType(struct xkb_keymap *keymap, xkb_level_index_t width, +FindAutomaticType(struct xkb_context *ctx, xkb_level_index_t width, const xkb_keysym_t *syms, xkb_atom_t *typeNameRtrn, bool *autoType) { *autoType = false; if ((width == 1) || (width == 0)) { - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ONE_LEVEL"); + *typeNameRtrn = xkb_atom_intern(ctx, "ONE_LEVEL"); *autoType = true; } else if (width == 2) { if (syms && xkb_keysym_is_lower(syms[0]) && xkb_keysym_is_upper(syms[1])) { - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ALPHABETIC"); + *typeNameRtrn = xkb_atom_intern(ctx, "ALPHABETIC"); } else if (syms && (xkb_keysym_is_keypad(syms[0]) || xkb_keysym_is_keypad(syms[1]))) { - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "KEYPAD"); + *typeNameRtrn = xkb_atom_intern(ctx, "KEYPAD"); *autoType = true; } else { - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "TWO_LEVEL"); + *typeNameRtrn = xkb_atom_intern(ctx, "TWO_LEVEL"); *autoType = true; } } @@ -1402,49 +1417,63 @@ FindAutomaticType(struct xkb_keymap *keymap, xkb_level_index_t width, xkb_keysym_is_upper(syms[1])) if (xkb_keysym_is_lower(syms[2]) && xkb_keysym_is_upper(syms[3])) *typeNameRtrn = - xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_ALPHABETIC"); + xkb_atom_intern(ctx, "FOUR_LEVEL_ALPHABETIC"); else - *typeNameRtrn = xkb_atom_intern(keymap->ctx, + *typeNameRtrn = xkb_atom_intern(ctx, "FOUR_LEVEL_SEMIALPHABETIC"); else if (syms && (xkb_keysym_is_keypad(syms[0]) || xkb_keysym_is_keypad(syms[1]))) - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_KEYPAD"); + *typeNameRtrn = xkb_atom_intern(ctx, "FOUR_LEVEL_KEYPAD"); else - *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL"); + *typeNameRtrn = xkb_atom_intern(ctx, "FOUR_LEVEL"); /* XXX: why not set autoType here? */ } 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) +static bool +CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi) { - xkb_group_index_t i, lastGroup; + struct xkb_keymap *keymap = info->keymap; + struct xkb_key *key; + GroupInfo *groupi; const GroupInfo *group0; - bool identical; + xkb_layout_index_t i; + bool haveActions; + unsigned int sizeSyms; + unsigned int symIndex; - /* get highest group number */ - for (i = XKB_NUM_GROUPS - 1; i > 0; i--) - if (keyi->groups[i].defined) - break; - lastGroup = i; + /* + * The name is guaranteed to be real and not an alias (see + * AddKeySymbols), so 'false' is safe here. + */ + key = FindNamedKey(keymap, keyi->name, false); + if (!key) { + log_vrb(info->keymap->ctx, 5, + "Key %s not found in keycodes; Symbols ignored\n", + LongKeyNameText(keyi->name)); + return false; + } - if (lastGroup == 0) - return; + /* Find the range of groups we need. */ + key->num_groups = 0; + darray_enumerate(i, groupi, keyi->groups) + if (groupi->defined) + key->num_groups = i + 1; - group0 = &keyi->groups[0]; + if (key->num_groups <= 0) + return false; /* WSGO */ - /* 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]; + 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; @@ -1454,100 +1483,48 @@ PrepareKeyDef(KeyInfo *keyi) 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; - unsigned int sizeSyms = 0; - xkb_group_index_t i, nGroups; - xkb_level_index_t width, tmp; - struct xkb_key_type * type; - bool haveActions, autoType; - unsigned types[XKB_NUM_GROUPS]; - unsigned int symIndex = 0; - - key = FindNamedKey(keymap, keyi->name, true); - if (!key) { - log_vrb(info->keymap->ctx, 5, - "Key %s not found in keycodes; Symbols ignored\n", - LongKeyNameText(keyi->name)); - return false; - } - + /* See if we need to allocate an actions array. */ haveActions = false; - width = 0; - for (i = nGroups = 0; i < XKB_NUM_GROUPS; i++) { - GroupInfo *groupi = &keyi->groups[i]; - - if (i + 1 > nGroups && groupi->defined) - nGroups = i + 1; - - autoType = false; - - if (!haveActions) { - LevelInfo *leveli; - darray_foreach(leveli, groupi->levels) { - if (leveli->act.type != ACTION_TYPE_NONE) { - haveActions = true; - break; - } + darray_foreach(groupi, keyi->groups) { + LevelInfo *leveli; + darray_foreach(leveli, groupi->levels) { + if (leveli->act.type != ACTION_TYPE_NONE) { + haveActions = true; + goto out_of_loops; } } + } +out_of_loops: - /* Assign the type to the key, if it is missing. */ + /* + * 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; + darray_enumerate(i, groupi, keyi->groups) { + struct xkb_key_type *type; + bool autoType = false; + + /* Find the type of the group, if it is missing. */ if (groupi->type == XKB_ATOM_NONE) { if (keyi->dfltType != XKB_ATOM_NONE) groupi->type = keyi->dfltType; - else if (FindAutomaticType(keymap, darray_size(groupi->levels), + else if (FindAutomaticType(keymap->ctx, + darray_size(groupi->levels), darray_mem(groupi->syms, 0), &groupi->type, &autoType)) { } else 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)); } - if (FindNamedType(keymap, groupi->type, &types[i])) { + /* Find the type in the keymap, if it was defined in xkb_types. */ + if (FindNamedType(keymap, groupi->type, &key->kt_index[i])) { if (!autoType || darray_size(groupi->levels) > 2) key->explicit_groups |= (1 << i); } @@ -1561,11 +1538,11 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi) * Index 0 is guaranteed to contain something, usually * ONE_LEVEL or at least some default one-level type. */ - types[i] = 0; + key->kt_index[i] = 0; } - /* if the type specifies fewer levels than the key has, shrink the key */ - type = &keymap->types[types[i]]; + /* If the type specifies fewer levels than the key has, shrink the key. */ + type = &keymap->types[key->kt_index[i]]; if (type->num_levels < darray_size(groupi->levels)) { log_vrb(info->keymap->ctx, 1, "Type \"%s\" has %d levels, but %s has %d levels; " @@ -1573,69 +1550,39 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi) 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); } - width = MAX(width, type->num_levels); - sizeSyms += darray_size(groupi->syms); + /* + * Why type->num_levels and not darray_size(groupi->levels)? + * Because the type may have more levels, and each group must + * have at least as many levels as its type. Because the + * key->syms array is indexed by (group * width + level), we + * must take the largest one. + * Maybe we can change it to save some space. + */ + key->width = MAX(key->width, type->num_levels); } - key->syms = calloc(sizeSyms, sizeof(*key->syms)); - key->num_groups = nGroups; - key->width = width; - key->sym_index = calloc(nGroups * width, sizeof(*key->sym_index)); - key->num_syms = calloc(nGroups * width, sizeof(*key->num_syms)); - - if (haveActions) { - key->actions = calloc(nGroups * width, sizeof(*key->actions)); - key->explicit |= EXPLICIT_INTERP; - } + /* Find the size of the syms array. */ + sizeSyms = 0; + 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)); + key->sym_index = calloc(key->num_groups * key->width, + sizeof(*key->sym_index)); + key->num_syms = calloc(key->num_groups * key->width, + sizeof(*key->num_syms)); key->out_of_range_group_number = keyi->out_of_range_group_number; key->out_of_range_group_action = keyi->out_of_range_group_action; - - for (i = 0; i < nGroups; i++) { - GroupInfo *groupi = &keyi->groups[i]; - - /* assign kt_index[i] to the index of the type in map->types. - * kt_index[i] may have been set by a previous run (if we have two - * layouts specified). Let's not overwrite it with the ONE_LEVEL - * default group if we dont even have keys for this group anyway. - * - * FIXME: There should be a better fix for this. - */ - if (!darray_empty(groupi->levels)) - key->kt_index[i] = types[i]; - - if (!darray_empty(groupi->syms)) { - /* fill key to "width" symbols*/ - for (tmp = 0; tmp < width; tmp++) { - LevelInfo *leveli = NULL; - - if (tmp < darray_size(groupi->levels)) - leveli = &darray_item(groupi->levels, tmp); - - if (leveli && leveli->num_syms != 0) { - memcpy(&key->syms[symIndex], - &darray_item(groupi->syms, leveli->sym_index), - leveli->num_syms * sizeof(*key->syms)); - key->sym_index[(i * width) + tmp] = symIndex; - key->num_syms[(i * width) + tmp] = leveli->num_syms; - symIndex += key->num_syms[(i * width) + tmp]; - } - else { - key->sym_index[(i * width) + tmp] = 0; - key->num_syms[(i * width) + tmp] = 0; - } - - if (key->actions && leveli && - leveli->act.type != ACTION_TYPE_NONE) - key->actions[tmp] = leveli->act; - } - } + if (haveActions) { + key->actions = calloc(key->num_groups * key->width, + sizeof(*key->actions)); + key->explicit |= EXPLICIT_INTERP; } - if (keyi->defined & KEY_FIELD_VMODMAP) { key->vmodmap = keyi->vmodmap; key->explicit |= EXPLICIT_VMODMAP; @@ -1646,6 +1593,29 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi) key->explicit |= EXPLICIT_REPEAT; } + /* Copy keysyms and actions. */ + symIndex = 0; + 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. */ + darray_enumerate(j, leveli, groupi->levels) { + if (leveli->act.type != ACTION_TYPE_NONE) + key->actions[i * key->width + j] = leveli->act; + + if (leveli->num_syms <= 0) + continue; + + memcpy(&key->syms[symIndex], + &darray_item(groupi->syms, leveli->sym_index), + leveli->num_syms * sizeof(*key->syms)); + key->sym_index[i * key->width + j] = symIndex; + key->num_syms[i * key->width + j] = leveli->num_syms; + symIndex += key->num_syms[i * key->width + j]; + } + } + return true; } @@ -1682,23 +1652,50 @@ CopyModMapDef(SymbolsInfo *info, ModMapEntry *entry) return true; } -/** - * Handle the xkb_symbols section of an xkb file. - * - * @param file The parsed xkb_symbols section of the xkb file. - * @param keymap Handle to the keyboard description to store the symbols in. - * @param merge Merge strategy (e.g. MERGE_OVERRIDE). - */ +static bool +CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info) +{ + KeyInfo *keyi; + ModMapEntry *mm; + 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->group_names[i] != XKB_ATOM_NONE) + keymap->group_names[i] = info->group_names[i]; + + darray_foreach(keyi, info->keys) + if (!CopySymbolsDef(info, keyi)) + info->errorCount++; + + if (xkb_context_get_log_verbosity(keymap->ctx) > 3) { + xkb_foreach_key(key, keymap) { + if (key->name[0] == '\0') + continue; + + if (key->num_groups < 1) + log_info(keymap->ctx, + "No symbols defined for %s\n", + KeyNameText(key->name)); + } + } + + darray_foreach(mm, info->modMaps) + if (!CopyModMapDef(info, mm)) + info->errorCount++; + + /* XXX: If we don't ignore errorCount, things break. */ + return true; +} + bool CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge) { - xkb_group_index_t i; - struct xkb_key *key; SymbolsInfo info; ActionsInfo *actions; - KeyInfo *keyi; - ModMapEntry *mm; actions = NewActionsInfo(); if (!actions) @@ -1715,37 +1712,8 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, if (info.errorCount != 0) goto err_info; - if (info.name) - keymap->symbols_section_name = strdup(info.name); - - for (i = 0; i < XKB_NUM_GROUPS; i++) - if (info.groupNames[i] != XKB_ATOM_NONE) - keymap->group_names[i] = info.groupNames[i]; - - /* sanitize keys */ - darray_foreach(keyi, info.keys) - PrepareKeyDef(keyi); - - /* copy! */ - darray_foreach(keyi, info.keys) - if (!CopySymbolsDef(&info, keyi)) - info.errorCount++; - - if (xkb_get_log_verbosity(keymap->ctx) > 3) { - xkb_foreach_key(key, keymap) { - if (key->name[0] == '\0') - continue; - - if (key->num_groups < 1) - log_info(info.keymap->ctx, - "No symbols defined for %s\n", - KeyNameText(key->name)); - } - } - - darray_foreach(mm, info.modMaps) - if (!CopyModMapDef(&info, mm)) - info.errorCount++; + if (!CopySymbolsToKeymap(keymap, &info)) + goto err_info; ClearSymbolsInfo(&info); FreeActionsInfo(actions);