1 /************************************************************
2 * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of Silicon Graphics not be
10 * used in advertising or publicity pertaining to distribution
11 * of the software without specific prior written permission.
12 * Silicon Graphics makes no representation about the suitability
13 * of this software for any purpose. It is provided "as is"
14 * without any express or implied warranty.
16 * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 * THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
27 #include "xkbcomp-priv.h"
28 #include "parseutils.h"
31 typedef struct _PreserveInfo {
33 short matchingMapIndex;
34 unsigned char indexMods;
35 unsigned char preMods;
36 unsigned short indexVMods;
37 unsigned short preVMods;
40 #define _KT_Name (1 << 0)
41 #define _KT_Mask (1 << 1)
42 #define _KT_Map (1 << 2)
43 #define _KT_Preserve (1 << 3)
44 #define _KT_LevelNames (1 << 4)
46 typedef struct _KeyTypeInfo {
47 unsigned short defined;
49 enum merge_mode merge;
56 darray(struct xkb_kt_map_entry) entries;
57 struct list preserves;
58 darray(xkb_atom_t) lvlNames;
61 typedef struct _KeyTypesInfo {
70 struct xkb_keymap *keymap;
72 xkb_atom_t tok_ONE_LEVEL;
73 xkb_atom_t tok_TWO_LEVEL;
74 xkb_atom_t tok_ALPHABETIC;
75 xkb_atom_t tok_KEYPAD;
78 /***====================================================================***/
80 static inline const char *
81 MapEntryTxt(KeyTypesInfo *info, struct xkb_kt_map_entry *entry)
83 return VModMaskText(info->keymap, entry->mods.real_mods,
87 static inline const char *
88 PreserveIndexTxt(KeyTypesInfo *info, PreserveInfo *pi)
90 return VModMaskText(info->keymap, pi->indexMods, pi->indexVMods);
93 static inline const char *
94 PreserveTxt(KeyTypesInfo *info, PreserveInfo *pi)
96 return VModMaskText(info->keymap, pi->preMods, pi->preVMods);
99 static inline const char *
100 TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
102 return xkb_atom_text(info->keymap->ctx, type->name);
105 static inline const char *
106 TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
108 return VModMaskText(info->keymap, type->mask, type->vmask);
112 ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
115 return ReportShouldBeArray(info->keymap, "key type", field,
116 TypeTxt(info, type));
120 ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
121 const char *field, const char *wanted)
123 return ReportBadType(info->keymap, "key type", field, TypeTxt(info, type),
128 ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
130 log_err(info->keymap->ctx,
131 "Key type \"%s\" has %d levels, must have %d; "
132 "Illegal type definition ignored\n",
137 /***====================================================================***/
140 InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
141 KeyTypesInfo *from, unsigned file_id)
143 PreserveInfo *old, *new;
145 info->tok_ONE_LEVEL = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
146 info->tok_TWO_LEVEL = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
147 info->tok_ALPHABETIC = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
148 info->tok_KEYPAD = xkb_atom_intern(keymap->ctx, "KEYPAD");
149 info->name = strdup("default");
150 info->errorCount = 0;
151 info->stdPresent = 0;
153 list_init(&info->types);
154 info->file_id = file_id;
155 info->dflt.defined = 0;
156 info->dflt.file_id = file_id;
157 info->dflt.merge = MERGE_OVERRIDE;
158 info->dflt.name = XKB_ATOM_NONE;
160 info->dflt.vmask = 0;
161 info->dflt.numLevels = 1;
162 darray_init(info->dflt.entries);
163 darray_init(info->dflt.lvlNames);
164 list_init(&info->dflt.preserves);
165 InitVModInfo(&info->vmods, keymap);
166 info->keymap = keymap;
171 info->dflt = from->dflt;
173 darray_copy(info->dflt.entries, from->dflt.entries);
174 darray_copy(info->dflt.lvlNames, from->dflt.lvlNames);
176 list_init(&info->dflt.preserves);
177 list_foreach(old, &from->dflt.preserves, entry) {
178 new = malloc(sizeof(*new));
183 list_append(&new->entry, &info->dflt.preserves);
188 FreeKeyTypeInfo(KeyTypeInfo * type)
190 PreserveInfo *pi, *next_pi;
191 darray_free(type->entries);
192 darray_free(type->lvlNames);
193 list_foreach_safe(pi, next_pi, &type->preserves, entry)
195 list_init(&type->preserves);
199 FreeKeyTypesInfo(KeyTypesInfo * info)
201 KeyTypeInfo *type, *next_type;
204 list_foreach_safe(type, next_type, &info->types, entry) {
205 FreeKeyTypeInfo(type);
208 FreeKeyTypeInfo(&info->dflt);
212 NextKeyType(KeyTypesInfo * info)
216 type = calloc(1, sizeof(*type));
220 list_init(&type->preserves);
221 type->file_id = info->file_id;
223 list_append(&type->entry, &info->types);
229 FindMatchingKeyType(KeyTypesInfo * info, KeyTypeInfo * new)
233 list_foreach(old, &info->types, entry)
234 if (old->name == new->name)
241 AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
244 struct list type_entry, preserves_entry;
245 int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
247 if (new->name == info->tok_ONE_LEVEL) {
248 if (new->numLevels > 1)
249 return ReportTypeBadWidth(info, "ONE_LEVEL", new->numLevels, 1);
250 info->stdPresent |= XkbOneLevelMask;
252 else if (new->name == info->tok_TWO_LEVEL) {
253 if (new->numLevels > 2)
254 return ReportTypeBadWidth(info, "TWO_LEVEL", new->numLevels, 2);
255 else if (new->numLevels < 2)
257 info->stdPresent |= XkbTwoLevelMask;
259 else if (new->name == info->tok_ALPHABETIC) {
260 if (new->numLevels > 2)
261 return ReportTypeBadWidth(info, "ALPHABETIC", new->numLevels, 2);
262 else if (new->numLevels < 2)
264 info->stdPresent |= XkbAlphabeticMask;
266 else if (new->name == info->tok_KEYPAD) {
267 if (new->numLevels > 2)
268 return ReportTypeBadWidth(info, "KEYPAD", new->numLevels, 2);
269 else if (new->numLevels < 2)
271 info->stdPresent |= XkbKeypadMask;
274 old = FindMatchingKeyType(info, new);
276 if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
277 if ((old->file_id == new->file_id && verbosity > 0) ||
279 log_warn(info->keymap->ctx,
280 "Multiple definitions of the %s key type; "
281 "Earlier definition ignored\n",
282 xkb_atom_text(info->keymap->ctx, new->name));
285 type_entry = old->entry;
286 FreeKeyTypeInfo(old);
288 old->entry = type_entry;
289 darray_init(new->entries);
290 darray_init(new->lvlNames);
291 list_init(&new->preserves);
295 if (old->file_id == new->file_id)
296 log_lvl(info->keymap->ctx, 4,
297 "Multiple definitions of the %s key type; "
298 "Later definition ignored\n",
299 xkb_atom_text(info->keymap->ctx, new->name));
301 FreeKeyTypeInfo(new);
305 old = NextKeyType(info);
308 list_replace(&new->preserves, &old->preserves);
309 type_entry = old->entry;
310 preserves_entry = old->preserves;
312 old->preserves = preserves_entry;
313 old->entry = type_entry;
314 darray_init(new->entries);
315 darray_init(new->lvlNames);
316 list_init(&new->preserves);
320 /***====================================================================***/
323 MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
324 enum merge_mode merge)
326 KeyTypeInfo *type, *next_type;
328 if (from->errorCount > 0) {
329 into->errorCount += from->errorCount;
333 if (into->name == NULL) {
334 into->name = from->name;
338 list_foreach_safe(type, next_type, &from->types, entry) {
339 type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
340 if (!AddKeyType(into, type))
344 into->stdPresent |= from->stdPresent;
348 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
351 HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt)
353 enum merge_mode merge = MERGE_DEFAULT;
355 KeyTypesInfo included, next_incl;
357 InitKeyTypesInfo(&included, info->keymap, info, info->file_id);
360 included.name = stmt->stmt;
364 for (; stmt; stmt = stmt->next_incl) {
365 if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES,
367 info->errorCount += 10;
368 FreeKeyTypesInfo(&included);
372 InitKeyTypesInfo(&next_incl, info->keymap, &included, rtrn->id);
373 next_incl.dflt.merge = merge;
375 HandleKeyTypesFile(&next_incl, rtrn, merge);
377 MergeIncludedKeyTypes(&included, &next_incl, merge);
379 FreeKeyTypesInfo(&next_incl);
383 MergeIncludedKeyTypes(info, &included, merge);
384 FreeKeyTypesInfo(&included);
386 return (info->errorCount == 0);
389 /***====================================================================***/
391 static struct xkb_kt_map_entry *
392 FindMatchingMapEntry(KeyTypeInfo * type, unsigned mask, unsigned vmask)
394 struct xkb_kt_map_entry *entry;
396 darray_foreach(entry, type->entries)
397 if (entry->mods.real_mods == mask && entry->mods.vmods == vmask)
404 DeleteLevel1MapEntries(KeyTypeInfo * type)
408 /* TODO: Be just a bit more clever here. */
409 for (i = 0; i < darray_size(type->entries); i++) {
410 if (darray_item(type->entries, i).level == 0) {
411 for (n = i; n < darray_size(type->entries) - 1; n++)
412 darray_item(type->entries, n) =
413 darray_item(type->entries, n + 1);
414 (void) darray_pop(type->entries);
419 static struct xkb_kt_map_entry *
420 NextMapEntry(KeyTypesInfo *info, KeyTypeInfo * type)
422 darray_resize0(type->entries, darray_size(type->entries) + 1);
423 return &darray_item(type->entries, darray_size(type->entries) - 1);
427 AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
428 PreserveInfo *new, bool clobber, bool report)
432 list_foreach(old, &type->preserves, entry) {
433 if (old->indexMods != new->indexMods ||
434 old->indexVMods != new->indexVMods)
437 if (old->preMods == new->preMods && old->preVMods == new->preVMods) {
438 log_lvl(info->keymap->ctx, 10,
439 "Identical definitions for preserve[%s] in %s; "
441 PreserveIndexTxt(info, old), TypeTxt(info, type));
446 log_lvl(info->keymap->ctx, 1,
447 "Multiple definitions for preserve[%s] in %s; "
448 "Using %s, ignoring %s\n",
449 PreserveIndexTxt(info, old), TypeTxt(info, type),
450 PreserveTxt(info, clobber ? new : old),
451 PreserveTxt(info, clobber ? old : new));
454 old->preMods = new->preMods;
455 old->preVMods = new->preVMods;
461 old = malloc(sizeof(*old));
463 log_wsgo(info->keymap->ctx,
464 "Couldn't allocate preserve in %s; Preserve[%s] lost\n",
465 TypeTxt(info, type), PreserveIndexTxt(info, new));
470 old->matchingMapIndex = -1;
471 list_append(&old->entry, &type->preserves);
477 * Add a new KTMapEntry to the given key type. If an entry with the same mods
478 * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
481 * @param clobber Overwrite existing entry.
482 * @param report true if a warning is to be printed on.
485 AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
486 struct xkb_kt_map_entry *new, bool clobber, bool report)
488 struct xkb_kt_map_entry * old;
490 if ((old = FindMatchingMapEntry(type, new->mods.real_mods,
492 if (report && (old->level != new->level)) {
493 unsigned use, ignore;
495 use = new->level + 1;
496 ignore = old->level + 1;
499 use = old->level + 1;
500 ignore = new->level + 1;
502 log_warn(info->keymap->ctx,
503 "Multiple map entries for %s in %s; "
504 "Using %d, ignoring %d\n",
505 MapEntryTxt(info, new), TypeTxt(info, type), use,
509 log_lvl(info->keymap->ctx, 10,
510 "Multiple occurences of map[%s]= %d in %s; Ignored\n",
511 MapEntryTxt(info, new), new->level + 1,
512 TypeTxt(info, type));
516 old->level = new->level;
519 if ((old = NextMapEntry(info, type)) == NULL)
520 return false; /* allocation failure, already reported */
521 if (new->level >= type->numLevels)
522 type->numLevels = new->level + 1;
523 old->mods.mask = new->mods.real_mods;
524 old->mods.real_mods = new->mods.real_mods;
525 old->mods.vmods = new->mods.vmods;
526 old->level = new->level;
531 SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
535 struct xkb_kt_map_entry entry;
537 if (arrayNdx == NULL)
538 return ReportTypeShouldBeArray(info, type, "map entry");
540 if (!ExprResolveVModMask(info->keymap, arrayNdx, &rtrn))
541 return ReportTypeBadType(info, type, "map entry", "modifier mask");
543 entry.mods.real_mods = rtrn.uval & 0xff; /* modifiers < 512 */
544 entry.mods.vmods = (rtrn.uval >> 8) & 0xffff; /* modifiers > 512 */
546 if ((entry.mods.real_mods & (~type->mask)) ||
547 ((entry.mods.vmods & (~type->vmask)) != 0)) {
548 log_lvl(info->keymap->ctx, 1,
549 "Map entry for unused modifiers in %s; "
550 "Using %s instead of %s\n",
552 VModMaskText(info->keymap,
553 entry.mods.real_mods & type->mask,
554 entry.mods.vmods & type->vmask),
555 MapEntryTxt(info, &entry));
556 entry.mods.real_mods &= type->mask;
557 entry.mods.vmods &= type->vmask;
560 if (!ExprResolveLevel(info->keymap->ctx, value, &rtrn)) {
561 log_err(info->keymap->ctx,
562 "Level specifications in a key type must be integer; "
563 "Ignoring malformed level specification\n");
567 entry.level = rtrn.ival - 1;
568 return AddMapEntry(info, type, &entry, true, true);
572 SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
578 if (arrayNdx == NULL)
579 return ReportTypeShouldBeArray(info, type, "preserve entry");
581 if (!ExprResolveVModMask(info->keymap, arrayNdx, &rtrn))
582 return ReportTypeBadType(info, type, "preserve entry",
585 new.indexMods = rtrn.uval & 0xff;
586 new.indexVMods = (rtrn.uval >> 8) & 0xffff;
588 if ((new.indexMods & (~type->mask)) ||
589 (new.indexVMods & (~type->vmask))) {
590 const char *before = PreserveIndexTxt(info, &new);
592 new.indexMods &= type->mask;
593 new.indexVMods &= type->vmask;
595 log_lvl(info->keymap->ctx, 1,
596 "Preserve for modifiers not used by the %s type; "
597 "Index %s converted to %s\n",
598 TypeTxt(info, type), before,
599 PreserveIndexTxt(info, &new));
602 if (!ExprResolveVModMask(info->keymap, value, &rtrn)) {
603 log_err(info->keymap->ctx,
604 "Preserve value in a key type is not a modifier mask; "
605 "Ignoring preserve[%s] in type %s\n",
606 PreserveIndexTxt(info, &new), TypeTxt(info, type));
610 new.preMods = rtrn.uval & 0xff;
611 new.preVMods = (rtrn.uval >> 16) & 0xffff;
613 if ((new.preMods & (~new.indexMods)) ||
614 (new.preVMods & (~new.indexVMods))) {
615 const char *before = PreserveIndexTxt(info, &new);
617 new.preMods &= new.indexMods;
618 new.preVMods &= new.indexVMods;
620 log_lvl(info->keymap->ctx, 1,
621 "Illegal value for preserve[%s] in type %s; "
622 "Converted %s to %s\n",
623 PreserveTxt(info, &new), TypeTxt(info, type),
624 before, PreserveIndexTxt(info, &new));
627 return AddPreserve(info, type, &new, true, true);
630 /***====================================================================***/
633 AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
634 unsigned level, xkb_atom_t name, bool clobber)
636 if (level >= darray_size(type->lvlNames))
637 darray_resize0(type->lvlNames, level + 1);
639 if (darray_item(type->lvlNames, level) == name) {
640 log_lvl(info->keymap->ctx, 10,
641 "Duplicate names for level %d of key type %s; Ignored\n",
642 level + 1, TypeTxt(info, type));
645 else if (darray_item(type->lvlNames, level) != XKB_ATOM_NONE) {
646 if (xkb_get_log_verbosity(info->keymap->ctx) > 0) {
647 const char *old, *new;
648 old = xkb_atom_text(info->keymap->ctx,
649 darray_item(type->lvlNames, level));
650 new = xkb_atom_text(info->keymap->ctx, name);
651 log_lvl(info->keymap->ctx, 1,
652 "Multiple names for level %d of key type %s; "
653 "Using %s, ignoring %s\n",
654 level + 1, TypeTxt(info, type),
655 (clobber ? new : old), (clobber ? old : new));
662 darray_item(type->lvlNames, level) = name;
667 SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
672 xkb_atom_t level_name;
673 struct xkb_context *ctx = info->keymap->ctx;
676 if (arrayNdx == NULL)
677 return ReportTypeShouldBeArray(info, type, "level name");
679 if (!ExprResolveLevel(ctx, arrayNdx, &rtrn))
680 return ReportTypeBadType(info, type, "level name", "integer");
681 level = rtrn.ival - 1;
683 if (!ExprResolveString(ctx, value, &str)) {
684 log_err(info->keymap->ctx,
685 "Non-string name for level %d in key type %s; "
686 "Ignoring illegal level name definition\n",
687 level + 1, xkb_atom_text(ctx, type->name));
691 level_name = xkb_atom_intern(ctx, str);
693 return AddLevelName(info, type, level, level_name, true);
696 /***====================================================================***/
699 * Parses the fields in a type "..." { } description.
701 * @param field The field to parse (e.g. modifiers, map, level_name)
704 SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
705 const char *field, ExprDef *arrayNdx, ExprDef *value)
709 if (istreq(field, "modifiers")) {
710 unsigned mods, vmods;
711 if (arrayNdx != NULL)
712 log_warn(info->keymap->ctx,
713 "The modifiers field of a key type is not an array; "
714 "Illegal array subscript ignored\n");
715 /* get modifier mask for current type */
716 if (!ExprResolveVModMask(info->keymap, value, &tmp)) {
717 log_err(info->keymap->ctx,
718 "Key type mask field must be a modifier mask; "
719 "Key type definition ignored\n");
722 mods = tmp.uval & 0xff; /* core mods */
723 vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */
724 if (type->defined & _KT_Mask) {
725 log_warn(info->keymap->ctx,
726 "Multiple modifier mask definitions for key type %s; "
727 "Using %s, ignoring %s\n",
728 xkb_atom_text(info->keymap->ctx, type->name),
729 TypeMaskTxt(info, type),
730 VModMaskText(info->keymap, mods, vmods));
735 type->defined |= _KT_Mask;
738 else if (istreq(field, "map")) {
739 type->defined |= _KT_Map;
740 return SetMapEntry(info, type, arrayNdx, value);
742 else if (istreq(field, "preserve")) {
743 type->defined |= _KT_Preserve;
744 return SetPreserve(info, type, arrayNdx, value);
746 else if (istreq(field, "levelname") || istreq(field, "level_name")) {
747 type->defined |= _KT_LevelNames;
748 return SetLevelName(info, type, arrayNdx, value);
751 log_err(info->keymap->ctx,
752 "Unknown field %s in key type %s; Definition ignored\n",
753 field, TypeTxt(info, type));
759 HandleKeyTypeVar(KeyTypesInfo *info, VarDef *stmt)
761 const char *elem, *field;
764 if (!ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field,
766 return false; /* internal error, already reported */
768 if (elem && istreq(elem, "type"))
769 return SetKeyTypeField(info, &info->dflt, field, arrayNdx,
773 log_err(info->keymap->ctx,
774 "Default for unknown element %s; "
775 "Value for field %s ignored\n", field, elem);
778 log_err(info->keymap->ctx,
779 "Default defined for unknown field %s; Ignored\n", field);
786 HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
789 const char *elem, *field;
792 for (; def; def = (VarDef *) def->common.next) {
793 if (def->name && def->name->op == EXPR_FIELD_REF) {
794 ok = HandleKeyTypeVar(info, def);
797 ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
800 ok = SetKeyTypeField(info, type, field, arrayNdx,
809 * Process a type "XYZ" { } specification in the xkb_types section.
813 HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
817 struct xkb_kt_map_entry *entry;
818 PreserveInfo *pi, *pi_next;
820 if (def->merge != MERGE_DEFAULT)
824 type.file_id = info->file_id;
826 type.name = def->name;
827 type.mask = info->dflt.mask;
828 type.vmask = info->dflt.vmask;
830 darray_init(type.entries);
831 darray_init(type.lvlNames);
832 list_init(&type.preserves);
834 /* Parse the actual content. */
835 if (!HandleKeyTypeBody(info, def->body, &type)) {
840 /* now copy any appropriate map, preserve or level names from the */
842 darray_foreach(entry, info->dflt.entries) {
843 if ((entry->mods.real_mods & type.mask) == entry->mods.real_mods &&
844 (entry->mods.vmods & type.vmask) == entry->mods.vmods)
845 AddMapEntry(info, &type, entry, false, false);
848 list_foreach_safe(pi, pi_next, &info->dflt.preserves, entry) {
849 if ((pi->indexMods & type.mask) == pi->indexMods &&
850 (pi->indexVMods & type.vmask) == pi->indexVMods)
851 AddPreserve(info, &type, pi, false, false);
854 for (i = 0; i < darray_size(info->dflt.lvlNames); i++) {
855 if (i < type.numLevels &&
856 darray_item(info->dflt.lvlNames, i) != XKB_ATOM_NONE) {
857 AddLevelName(info, &type, i,
858 darray_item(info->dflt.lvlNames, i), false);
862 /* Now add the new keytype to the info struct */
863 if (!AddKeyType(info, &type)) {
871 * Process an xkb_types section.
873 * @param file The parsed xkb_types section.
874 * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
875 * @param info Pointer to memory where the outcome will be stored.
878 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
883 info->name = strdup_safe(file->name);
887 switch (stmt->type) {
889 if (!HandleIncludeKeyTypes(info, (IncludeStmt *) stmt))
892 case STMT_TYPE: /* e.g. type "ONE_LEVEL" */
893 if (!HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge))
897 if (!HandleKeyTypeVar(info, (VarDef *) stmt))
900 case STMT_VMOD: /* virtual_modifiers NumLock, ... */
901 if (!HandleVModDef((VModDef *) stmt, info->keymap, merge,
906 log_err(info->keymap->ctx,
907 "Key type files may not include other declarations; "
908 "Ignoring definition of key alias\n");
912 log_err(info->keymap->ctx,
913 "Key type files may not include other declarations; "
914 "Ignoring definition of key name\n");
918 log_err(info->keymap->ctx,
919 "Key type files may not include other declarations; "
920 "Ignoring definition of symbol interpretation\n");
924 log_wsgo(info->keymap->ctx,
925 "Unexpected statement type %d in HandleKeyTypesFile\n",
930 if (info->errorCount > 10) {
931 log_err(info->keymap->ctx,
932 "Abandoning keytypes file \"%s\"\n", file->topName);
939 ComputeEffectiveMap(struct xkb_keymap *keymap, struct xkb_key_type *type)
942 struct xkb_kt_map_entry *entry = NULL;
944 if (type->mods.vmods != 0) {
945 tmp = VModsToReal(keymap, type->mods.vmods);
946 type->mods.mask = tmp | type->mods.real_mods;
947 darray_foreach(entry, type->map) {
949 if (entry->mods.vmods != 0) {
950 tmp = VModsToReal(keymap, entry->mods.vmods);
955 (entry->mods.real_mods | tmp) & type->mods.mask;
959 type->mods.mask = type->mods.real_mods;
965 CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
966 struct xkb_key_type *type)
970 struct xkb_keymap *keymap = info->keymap;
972 list_foreach(pre, &def->preserves, entry) {
973 struct xkb_kt_map_entry * match;
974 struct xkb_kt_map_entry tmp;
975 tmp.mods.real_mods = pre->indexMods;
976 tmp.mods.vmods = pre->indexVMods;
978 AddMapEntry(info, def, &tmp, false, false);
979 match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods);
981 log_wsgo(info->keymap->ctx,
982 "Couldn't find matching entry for preserve; Aborting\n");
985 pre->matchingMapIndex = match - &darray_item(def->entries, 0);
987 type->mods.real_mods = def->mask;
988 type->mods.vmods = def->vmask;
989 type->num_levels = def->numLevels;
990 memcpy(&type->map, &def->entries, sizeof(def->entries));
991 if (!list_empty(&def->preserves)) {
992 type->preserve = calloc(darray_size(type->map),
993 sizeof(*type->preserve));
994 if (!type->preserve) {
995 log_warn(info->keymap->ctx,
996 "Couldn't allocate preserve array in CopyDefToKeyType; "
997 "Preserve setting for type %s lost\n",
998 xkb_atom_text(keymap->ctx, def->name));
1001 list_foreach(pre, &def->preserves, entry) {
1002 int ndx = pre->matchingMapIndex;
1003 type->preserve[ndx].mask = pre->preMods;
1004 type->preserve[ndx].real_mods = pre->preMods;
1005 type->preserve[ndx].vmods = pre->preVMods;
1010 type->preserve = NULL;
1011 type->name = xkb_atom_text(keymap->ctx, def->name);
1013 if (!darray_empty(def->lvlNames)) {
1014 type->level_names = calloc(darray_size(def->lvlNames),
1015 sizeof(*type->level_names));
1017 /* assert def->szNames<=def->numLevels */
1018 for (i = 0; i < darray_size(def->lvlNames); i++)
1019 type->level_names[i] =
1020 xkb_atom_text(keymap->ctx, darray_item(def->lvlNames, i));
1023 type->level_names = NULL;
1026 darray_init(def->entries);
1027 return ComputeEffectiveMap(keymap, type);
1030 static struct xkb_kt_map_entry map2Level[] = {
1033 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1037 static struct xkb_kt_map_entry mapAlpha[] = {
1040 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1044 .mods = { .mask = 0, .vmods = LockMask, .real_mods = 0 }
1048 static struct xkb_mods preAlpha[] = {
1049 { .mask = 0, .vmods = 0, .real_mods = 0 },
1050 { .mask = LockMask, .vmods = LockMask, .real_mods = 0 }
1053 static struct xkb_kt_map_entry mapKeypad[] = {
1056 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1060 .mods = { .mask = 1, .vmods = 0, .real_mods = 0 }
1064 static const struct xkb_key_type canonicalTypes[XkbNumRequiredTypes] = {
1065 [XkbOneLevelIndex] = {
1066 .mods = { .mask = 0, .vmods = 0, .real_mods = 0 },
1072 [XkbTwoLevelIndex] = {
1073 .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1075 .map = darray_lit(map2Level),
1080 [XkbAlphabeticIndex] = {
1082 .mask = ShiftMask | LockMask,
1083 .vmods = ShiftMask | LockMask,
1087 .map = darray_lit(mapAlpha),
1088 .preserve = preAlpha,
1092 [XkbKeypadIndex] = {
1093 .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1095 .map = darray_lit(mapKeypad),
1103 CopyKeyType(const struct xkb_key_type *from, struct xkb_key_type *into)
1107 darray_free(into->map);
1108 free(into->preserve);
1109 free(into->level_names);
1112 darray_init(into->map);
1114 darray_copy(into->map, from->map);
1116 if (from->preserve && !darray_empty(into->map)) {
1117 into->preserve = calloc(darray_size(into->map),
1118 sizeof(*into->preserve));
1119 if (!into->preserve)
1121 memcpy(into->preserve, from->preserve,
1122 darray_size(into->map) * sizeof(*into->preserve));
1125 if (from->level_names && into->num_levels > 0) {
1126 into->level_names = calloc(into->num_levels,
1127 sizeof(*into->level_names));
1128 if (!into->level_names)
1131 for (i = 0; i < into->num_levels; i++)
1132 into->level_names[i] = strdup(from->level_names[i]);
1139 InitCanonicalKeyTypes(struct xkb_keymap *keymap, unsigned which,
1142 const struct xkb_key_type *from;
1145 darray_growalloc(keymap->types, XkbNumRequiredTypes);
1147 if ((which & XkbAllRequiredTypes) == 0)
1151 from = canonicalTypes;
1153 if (which & XkbOneLevelMask)
1154 rtrn = CopyKeyType(&from[XkbOneLevelIndex],
1155 &darray_item(keymap->types, XkbOneLevelIndex));
1157 if ((which & XkbTwoLevelMask) && rtrn == Success)
1158 rtrn = CopyKeyType(&from[XkbTwoLevelIndex],
1159 &darray_item(keymap->types, XkbTwoLevelIndex));
1161 if ((which & XkbAlphabeticMask) && rtrn == Success)
1162 rtrn = CopyKeyType(&from[XkbAlphabeticIndex],
1163 &darray_item(keymap->types, XkbAlphabeticIndex));
1165 if ((which & XkbKeypadMask) && rtrn == Success) {
1166 struct xkb_key_type *type;
1168 rtrn = CopyKeyType(&from[XkbKeypadIndex],
1169 &darray_item(keymap->types, XkbKeypadIndex));
1170 type = &darray_item(keymap->types, XkbKeypadIndex);
1172 if (keypadVMod >= 0 && keypadVMod < XkbNumVirtualMods &&
1174 struct xkb_kt_map_entry *entry;
1175 type->mods.vmods = (1 << keypadVMod);
1177 entry = &darray_item(type->map, 0);
1178 entry->mods.mask = ShiftMask;
1179 entry->mods.real_mods = ShiftMask;
1180 entry->mods.vmods = 0;
1183 entry = &darray_item(type->map, 1);
1184 entry->mods.mask = 0;
1185 entry->mods.real_mods = 0;
1186 entry->mods.vmods = (1 << keypadVMod);
1195 CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
1196 enum merge_mode merge)
1199 struct xkb_key_type *type, *next;
1203 InitKeyTypesInfo(&info, keymap, NULL, file->id);
1205 HandleKeyTypesFile(&info, file, merge);
1207 if (info.errorCount != 0)
1211 keymap->types_section_name = strdup(info.name);
1214 if ((info.stdPresent & XkbOneLevelMask) == 0)
1216 if ((info.stdPresent & XkbTwoLevelMask) == 0)
1218 if ((info.stdPresent & XkbKeypadMask) == 0)
1220 if ((info.stdPresent & XkbAlphabeticMask) == 0)
1223 darray_resize0(keymap->types, i);
1225 if (XkbAllRequiredTypes & (~info.stdPresent)) {
1226 unsigned missing, keypadVMod;
1228 missing = XkbAllRequiredTypes & (~info.stdPresent);
1229 keypadVMod = FindKeypadVMod(keymap);
1231 if (InitCanonicalKeyTypes(keymap, missing, keypadVMod) != Success) {
1232 log_wsgo(info.keymap->ctx,
1233 "Couldn't initialize canonical key types\n");
1237 if (missing & XkbOneLevelMask)
1238 darray_item(keymap->types, XkbOneLevelIndex).name =
1239 xkb_atom_text(keymap->ctx, info.tok_ONE_LEVEL);
1240 if (missing & XkbTwoLevelMask)
1241 darray_item(keymap->types, XkbTwoLevelIndex).name =
1242 xkb_atom_text(keymap->ctx, info.tok_TWO_LEVEL);
1243 if (missing & XkbAlphabeticMask)
1244 darray_item(keymap->types, XkbAlphabeticIndex).name =
1245 xkb_atom_text(keymap->ctx, info.tok_ALPHABETIC);
1246 if (missing & XkbKeypadMask)
1247 darray_item(keymap->types, XkbKeypadIndex).name =
1248 xkb_atom_text(keymap->ctx, info.tok_KEYPAD);
1251 next = &darray_item(keymap->types, XkbLastRequiredType + 1);
1252 list_foreach(def, &info.types, entry) {
1253 if (def->name == info.tok_ONE_LEVEL)
1254 type = &darray_item(keymap->types, XkbOneLevelIndex);
1255 else if (def->name == info.tok_TWO_LEVEL)
1256 type = &darray_item(keymap->types, XkbTwoLevelIndex);
1257 else if (def->name == info.tok_ALPHABETIC)
1258 type = &darray_item(keymap->types, XkbAlphabeticIndex);
1259 else if (def->name == info.tok_KEYPAD)
1260 type = &darray_item(keymap->types, XkbKeypadIndex);
1264 DeleteLevel1MapEntries(def);
1266 if (!CopyDefToKeyType(&info, def, type))
1270 FreeKeyTypesInfo(&info);
1274 FreeKeyTypesInfo(&info);