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 XkbcVModMaskText(info->keymap, entry->mods.real_mods,
87 static inline const char *
88 PreserveIndexTxt(KeyTypesInfo *info, PreserveInfo *pi)
90 return XkbcVModMaskText(info->keymap, pi->indexMods, pi->indexVMods);
93 static inline const char *
94 PreserveTxt(KeyTypesInfo *info, PreserveInfo *pi)
96 return XkbcVModMaskText(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 XkbcVModMaskText(info->keymap, type->mask, type->vmask);
112 ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
115 return ReportShouldBeArray("key type", field, TypeTxt(info, type));
119 ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
120 const char *field, const char *wanted)
122 return ReportBadType("key type", field, TypeTxt(info, type), wanted);
126 ReportTypeBadWidth(KeyTypesInfo *info, const char *type, int has, int needs)
128 log_err(info->keymap->ctx,
129 "Key type \"%s\" has %d levels, must have %d; "
130 "Illegal type definition ignored\n",
135 /***====================================================================***/
138 InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap,
139 KeyTypesInfo *from, unsigned file_id)
141 PreserveInfo *old, *new;
143 info->tok_ONE_LEVEL = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
144 info->tok_TWO_LEVEL = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
145 info->tok_ALPHABETIC = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
146 info->tok_KEYPAD = xkb_atom_intern(keymap->ctx, "KEYPAD");
147 info->name = strdup("default");
148 info->errorCount = 0;
149 info->stdPresent = 0;
151 list_init(&info->types);
152 info->file_id = file_id;
153 info->dflt.defined = 0;
154 info->dflt.file_id = file_id;
155 info->dflt.merge = MERGE_OVERRIDE;
156 info->dflt.name = XKB_ATOM_NONE;
158 info->dflt.vmask = 0;
159 info->dflt.numLevels = 1;
160 darray_init(info->dflt.entries);
161 darray_init(info->dflt.lvlNames);
162 list_init(&info->dflt.preserves);
163 InitVModInfo(&info->vmods, keymap);
164 info->keymap = keymap;
169 info->dflt = from->dflt;
171 darray_copy(info->dflt.entries, from->dflt.entries);
172 darray_copy(info->dflt.lvlNames, from->dflt.lvlNames);
174 list_init(&info->dflt.preserves);
175 list_foreach(old, &from->dflt.preserves, entry) {
176 new = malloc(sizeof(*new));
181 list_append(&new->entry, &info->dflt.preserves);
186 FreeKeyTypeInfo(KeyTypeInfo * type)
188 PreserveInfo *pi, *next_pi;
189 darray_free(type->entries);
190 darray_free(type->lvlNames);
191 list_foreach_safe(pi, next_pi, &type->preserves, entry)
193 list_init(&type->preserves);
197 FreeKeyTypesInfo(KeyTypesInfo * info)
199 KeyTypeInfo *type, *next_type;
202 list_foreach_safe(type, next_type, &info->types, entry) {
203 FreeKeyTypeInfo(type);
206 FreeKeyTypeInfo(&info->dflt);
210 NextKeyType(KeyTypesInfo * info)
214 type = calloc(1, sizeof(*type));
218 list_init(&type->preserves);
219 type->file_id = info->file_id;
221 list_append(&type->entry, &info->types);
227 FindMatchingKeyType(KeyTypesInfo * info, KeyTypeInfo * new)
231 list_foreach(old, &info->types, entry)
232 if (old->name == new->name)
239 AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new)
242 struct list type_entry, preserves_entry;
243 int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
245 if (new->name == info->tok_ONE_LEVEL) {
246 if (new->numLevels > 1)
247 return ReportTypeBadWidth(info, "ONE_LEVEL", new->numLevels, 1);
248 info->stdPresent |= XkbOneLevelMask;
250 else if (new->name == info->tok_TWO_LEVEL) {
251 if (new->numLevels > 2)
252 return ReportTypeBadWidth(info, "TWO_LEVEL", new->numLevels, 2);
253 else if (new->numLevels < 2)
255 info->stdPresent |= XkbTwoLevelMask;
257 else if (new->name == info->tok_ALPHABETIC) {
258 if (new->numLevels > 2)
259 return ReportTypeBadWidth(info, "ALPHABETIC", new->numLevels, 2);
260 else if (new->numLevels < 2)
262 info->stdPresent |= XkbAlphabeticMask;
264 else if (new->name == info->tok_KEYPAD) {
265 if (new->numLevels > 2)
266 return ReportTypeBadWidth(info, "KEYPAD", new->numLevels, 2);
267 else if (new->numLevels < 2)
269 info->stdPresent |= XkbKeypadMask;
272 old = FindMatchingKeyType(info, new);
274 if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
275 if ((old->file_id == new->file_id && verbosity > 0) ||
277 log_warn(info->keymap->ctx,
278 "Multiple definitions of the %s key type; "
279 "Earlier definition ignored\n",
280 xkb_atom_text(info->keymap->ctx, new->name));
283 type_entry = old->entry;
284 FreeKeyTypeInfo(old);
286 old->entry = type_entry;
287 darray_init(new->entries);
288 darray_init(new->lvlNames);
289 list_init(&new->preserves);
293 if (old->file_id == new->file_id)
294 log_lvl(info->keymap->ctx, 4,
295 "Multiple definitions of the %s key type; "
296 "Later definition ignored\n",
297 xkb_atom_text(info->keymap->ctx, new->name));
299 FreeKeyTypeInfo(new);
303 old = NextKeyType(info);
306 list_replace(&new->preserves, &old->preserves);
307 type_entry = old->entry;
308 preserves_entry = old->preserves;
310 old->preserves = preserves_entry;
311 old->entry = type_entry;
312 darray_init(new->entries);
313 darray_init(new->lvlNames);
314 list_init(&new->preserves);
318 /***====================================================================***/
321 MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
322 enum merge_mode merge)
324 KeyTypeInfo *type, *next_type;
326 if (from->errorCount > 0) {
327 into->errorCount += from->errorCount;
331 if (into->name == NULL) {
332 into->name = from->name;
336 list_foreach_safe(type, next_type, &from->types, entry) {
337 type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
338 if (!AddKeyType(into, type))
342 into->stdPresent |= from->stdPresent;
346 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge);
349 HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *stmt)
351 enum merge_mode merge = MERGE_DEFAULT;
353 KeyTypesInfo included, next_incl;
355 InitKeyTypesInfo(&included, info->keymap, info, info->file_id);
358 included.name = stmt->stmt;
362 for (; stmt; stmt = stmt->next) {
363 if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES,
365 info->errorCount += 10;
366 FreeKeyTypesInfo(&included);
370 InitKeyTypesInfo(&next_incl, info->keymap, &included, rtrn->id);
371 next_incl.dflt.merge = merge;
373 HandleKeyTypesFile(&next_incl, rtrn, merge);
375 MergeIncludedKeyTypes(&included, &next_incl, merge);
377 FreeKeyTypesInfo(&next_incl);
381 MergeIncludedKeyTypes(info, &included, merge);
382 FreeKeyTypesInfo(&included);
384 return (info->errorCount == 0);
387 /***====================================================================***/
389 static struct xkb_kt_map_entry *
390 FindMatchingMapEntry(KeyTypeInfo * type, unsigned mask, unsigned vmask)
392 struct xkb_kt_map_entry *entry;
394 darray_foreach(entry, type->entries)
395 if (entry->mods.real_mods == mask && entry->mods.vmods == vmask)
402 DeleteLevel1MapEntries(KeyTypeInfo * type)
406 /* TODO: Be just a bit more clever here. */
407 for (i = 0; i < darray_size(type->entries); i++) {
408 if (darray_item(type->entries, i).level == 0) {
409 for (n = i; n < darray_size(type->entries) - 1; n++)
410 darray_item(type->entries, n) =
411 darray_item(type->entries, n + 1);
412 (void) darray_pop(type->entries);
417 static struct xkb_kt_map_entry *
418 NextMapEntry(KeyTypesInfo *info, KeyTypeInfo * type)
420 darray_resize0(type->entries, darray_size(type->entries) + 1);
421 return &darray_item(type->entries, darray_size(type->entries) - 1);
425 AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
426 PreserveInfo *new, bool clobber, bool report)
430 list_foreach(old, &type->preserves, entry) {
431 if (old->indexMods != new->indexMods ||
432 old->indexVMods != new->indexVMods)
435 if (old->preMods == new->preMods && old->preVMods == new->preVMods) {
436 log_lvl(info->keymap->ctx, 10,
437 "Identical definitions for preserve[%s] in %s; "
439 PreserveIndexTxt(info, old), TypeTxt(info, type));
444 log_lvl(info->keymap->ctx, 1,
445 "Multiple definitions for preserve[%s] in %s; "
446 "Using %s, ignoring %s\n",
447 PreserveIndexTxt(info, old), TypeTxt(info, type),
448 PreserveTxt(info, clobber ? new : old),
449 PreserveTxt(info, clobber ? old : new));
452 old->preMods = new->preMods;
453 old->preVMods = new->preVMods;
459 old = malloc(sizeof(*old));
461 log_wsgo(info->keymap->ctx,
462 "Couldn't allocate preserve in %s; Preserve[%s] lost\n",
463 TypeTxt(info, type), PreserveIndexTxt(info, new));
468 old->matchingMapIndex = -1;
469 list_append(&old->entry, &type->preserves);
475 * Add a new KTMapEntry to the given key type. If an entry with the same mods
476 * already exists, the level is updated (if clobber is TRUE). Otherwise, a new
479 * @param clobber Overwrite existing entry.
480 * @param report true if a warning is to be printed on.
483 AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
484 struct xkb_kt_map_entry *new, bool clobber, bool report)
486 struct xkb_kt_map_entry * old;
488 if ((old = FindMatchingMapEntry(type, new->mods.real_mods,
490 if (report && (old->level != new->level)) {
491 unsigned use, ignore;
493 use = new->level + 1;
494 ignore = old->level + 1;
497 use = old->level + 1;
498 ignore = new->level + 1;
500 log_warn(info->keymap->ctx,
501 "Multiple map entries for %s in %s; "
502 "Using %d, ignoring %d\n",
503 MapEntryTxt(info, new), TypeTxt(info, type), use,
507 log_lvl(info->keymap->ctx, 10,
508 "Multiple occurences of map[%s]= %d in %s; Ignored\n",
509 MapEntryTxt(info, new), new->level + 1,
510 TypeTxt(info, type));
514 old->level = new->level;
517 if ((old = NextMapEntry(info, type)) == NULL)
518 return false; /* allocation failure, already reported */
519 if (new->level >= type->numLevels)
520 type->numLevels = new->level + 1;
521 old->mods.mask = new->mods.real_mods;
522 old->mods.real_mods = new->mods.real_mods;
523 old->mods.vmods = new->mods.vmods;
524 old->level = new->level;
529 SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
533 struct xkb_kt_map_entry entry;
535 if (arrayNdx == NULL)
536 return ReportTypeShouldBeArray(info, type, "map entry");
538 if (!ExprResolveVModMask(arrayNdx, &rtrn, info->keymap))
539 return ReportTypeBadType(info, type, "map entry", "modifier mask");
541 entry.mods.real_mods = rtrn.uval & 0xff; /* modifiers < 512 */
542 entry.mods.vmods = (rtrn.uval >> 8) & 0xffff; /* modifiers > 512 */
544 if ((entry.mods.real_mods & (~type->mask)) ||
545 ((entry.mods.vmods & (~type->vmask)) != 0)) {
546 log_lvl(info->keymap->ctx, 1,
547 "Map entry for unused modifiers in %s; "
548 "Using %s instead of %s\n",
550 XkbcVModMaskText(info->keymap,
551 entry.mods.real_mods & type->mask,
552 entry.mods.vmods & type->vmask),
553 MapEntryTxt(info, &entry));
554 entry.mods.real_mods &= type->mask;
555 entry.mods.vmods &= type->vmask;
558 if (!ExprResolveLevel(info->keymap->ctx, value, &rtrn)) {
559 log_err(info->keymap->ctx,
560 "Level specifications in a key type must be integer; "
561 "Ignoring malformed level specification\n");
565 entry.level = rtrn.ival - 1;
566 return AddMapEntry(info, type, &entry, true, true);
570 SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
576 if (arrayNdx == NULL)
577 return ReportTypeShouldBeArray(info, type, "preserve entry");
579 if (!ExprResolveVModMask(arrayNdx, &rtrn, info->keymap))
580 return ReportTypeBadType(info, type, "preserve entry",
583 new.indexMods = rtrn.uval & 0xff;
584 new.indexVMods = (rtrn.uval >> 8) & 0xffff;
586 if ((new.indexMods & (~type->mask)) ||
587 (new.indexVMods & (~type->vmask))) {
588 const char *before = PreserveIndexTxt(info, &new);
590 new.indexMods &= type->mask;
591 new.indexVMods &= type->vmask;
593 log_lvl(info->keymap->ctx, 1,
594 "Preserve for modifiers not used by the %s type; "
595 "Index %s converted to %s\n",
596 TypeTxt(info, type), before,
597 PreserveIndexTxt(info, &new));
600 if (!ExprResolveVModMask(value, &rtrn, info->keymap)) {
601 log_err(info->keymap->ctx,
602 "Preserve value in a key type is not a modifier mask; "
603 "Ignoring preserve[%s] in type %s\n",
604 PreserveIndexTxt(info, &new), TypeTxt(info, type));
608 new.preMods = rtrn.uval & 0xff;
609 new.preVMods = (rtrn.uval >> 16) & 0xffff;
611 if ((new.preMods & (~new.indexMods)) ||
612 (new.preVMods & (~new.indexVMods))) {
613 const char *before = PreserveIndexTxt(info, &new);
615 new.preMods &= new.indexMods;
616 new.preVMods &= new.indexVMods;
618 log_lvl(info->keymap->ctx, 1,
619 "Illegal value for preserve[%s] in type %s; "
620 "Converted %s to %s\n",
621 PreserveTxt(info, &new), TypeTxt(info, type),
622 before, PreserveIndexTxt(info, &new));
625 return AddPreserve(info, type, &new, true, true);
628 /***====================================================================***/
631 AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
632 unsigned level, xkb_atom_t name, bool clobber)
634 if (level >= darray_size(type->lvlNames))
635 darray_resize0(type->lvlNames, level + 1);
637 if (darray_item(type->lvlNames, level) == name) {
638 log_lvl(info->keymap->ctx, 10,
639 "Duplicate names for level %d of key type %s; Ignored\n",
640 level + 1, TypeTxt(info, type));
643 else if (darray_item(type->lvlNames, level) != XKB_ATOM_NONE) {
644 if (xkb_get_log_verbosity(info->keymap->ctx) > 0) {
645 const char *old, *new;
646 old = xkb_atom_text(info->keymap->ctx,
647 darray_item(type->lvlNames, level));
648 new = xkb_atom_text(info->keymap->ctx, name);
649 log_lvl(info->keymap->ctx, 1,
650 "Multiple names for level %d of key type %s; "
651 "Using %s, ignoring %s\n",
652 level + 1, TypeTxt(info, type),
653 (clobber ? new : old), (clobber ? old : new));
660 darray_item(type->lvlNames, level) = name;
665 SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
670 xkb_atom_t level_name;
671 struct xkb_context *ctx = info->keymap->ctx;
673 if (arrayNdx == NULL)
674 return ReportTypeShouldBeArray(info, type, "level name");
675 if (!ExprResolveLevel(ctx, arrayNdx, &rtrn))
676 return ReportTypeBadType(info, type, "level name", "integer");
677 level = rtrn.ival - 1;
678 if (!ExprResolveString(ctx, value, &rtrn)) {
679 log_err(info->keymap->ctx,
680 "Non-string name for level %d in key type %s; "
681 "Ignoring illegal level name definition\n",
682 level + 1, xkb_atom_text(ctx, type->name));
685 level_name = xkb_atom_intern(ctx, rtrn.str);
687 return AddLevelName(info, type, level, level_name, true);
690 /***====================================================================***/
693 * Parses the fields in a type "..." { } description.
695 * @param field The field to parse (e.g. modifiers, map, level_name)
698 SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
699 char *field, ExprDef *arrayNdx, ExprDef *value)
703 if (strcasecmp(field, "modifiers") == 0) {
704 unsigned mods, vmods;
705 if (arrayNdx != NULL)
706 log_warn(info->keymap->ctx,
707 "The modifiers field of a key type is not an array; "
708 "Illegal array subscript ignored\n");
709 /* get modifier mask for current type */
710 if (!ExprResolveVModMask(value, &tmp, info->keymap)) {
711 log_err(info->keymap->ctx,
712 "Key type mask field must be a modifier mask; "
713 "Key type definition ignored\n");
716 mods = tmp.uval & 0xff; /* core mods */
717 vmods = (tmp.uval >> 8) & 0xffff; /* xkb virtual mods */
718 if (type->defined & _KT_Mask) {
719 log_warn(info->keymap->ctx,
720 "Multiple modifier mask definitions for key type %s; "
721 "Using %s, ignoring %s\n",
722 xkb_atom_text(info->keymap->ctx, type->name),
723 TypeMaskTxt(info, type),
724 XkbcVModMaskText(info->keymap, mods, vmods));
729 type->defined |= _KT_Mask;
732 else if (strcasecmp(field, "map") == 0) {
733 type->defined |= _KT_Map;
734 return SetMapEntry(info, type, arrayNdx, value);
736 else if (strcasecmp(field, "preserve") == 0) {
737 type->defined |= _KT_Preserve;
738 return SetPreserve(info, type, arrayNdx, value);
740 else if ((strcasecmp(field, "levelname") == 0) ||
741 (strcasecmp(field, "level_name") == 0)) {
742 type->defined |= _KT_LevelNames;
743 return SetLevelName(info, type, arrayNdx, value);
746 log_err(info->keymap->ctx,
747 "Unknown field %s in key type %s; Definition ignored\n",
748 field, TypeTxt(info, type));
754 HandleKeyTypeVar(KeyTypesInfo *info, VarDef *stmt)
756 ExprResult elem, field;
759 if (!ExprResolveLhs(info->keymap, stmt->name, &elem, &field, &arrayNdx))
760 return false; /* internal error, already reported */
761 if (elem.str && (strcasecmp(elem.str, "type") == 0))
762 return SetKeyTypeField(info, &info->dflt, field.str, arrayNdx,
764 if (elem.str != NULL) {
765 log_err(info->keymap->ctx,
766 "Default for unknown element %s; "
767 "Value for field %s ignored\n",
768 field.str, elem.str);
770 else if (field.str != NULL) {
771 log_err(info->keymap->ctx,
772 "Default defined for unknown field %s; Ignored\n", field.str);
778 HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
781 ExprResult tmp, field;
784 for (; def != NULL; def = (VarDef *) def->common.next) {
785 if ((def->name) && (def->name->type == ExprFieldRef)) {
786 ok = HandleKeyTypeVar(info, def);
789 ok = ExprResolveLhs(info->keymap, def->name, &tmp, &field, &arrayNdx);
791 ok = SetKeyTypeField(info, type, field.str, arrayNdx,
800 * Process a type "XYZ" { } specification in the xkb_types section.
804 HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def, enum merge_mode merge)
808 struct xkb_kt_map_entry *entry;
809 PreserveInfo *pi, *pi_next;
811 if (def->merge != MERGE_DEFAULT)
815 type.file_id = info->file_id;
817 type.name = def->name;
818 type.mask = info->dflt.mask;
819 type.vmask = info->dflt.vmask;
821 darray_init(type.entries);
822 darray_init(type.lvlNames);
823 list_init(&type.preserves);
825 /* Parse the actual content. */
826 if (!HandleKeyTypeBody(info, def->body, &type)) {
831 /* now copy any appropriate map, preserve or level names from the */
833 darray_foreach(entry, info->dflt.entries) {
834 if ((entry->mods.real_mods & type.mask) == entry->mods.real_mods &&
835 (entry->mods.vmods & type.vmask) == entry->mods.vmods)
836 AddMapEntry(info, &type, entry, false, false);
839 list_foreach_safe(pi, pi_next, &info->dflt.preserves, entry) {
840 if ((pi->indexMods & type.mask) == pi->indexMods &&
841 (pi->indexVMods & type.vmask) == pi->indexVMods)
842 AddPreserve(info, &type, pi, false, false);
845 for (i = 0; i < darray_size(info->dflt.lvlNames); i++) {
846 if (i < type.numLevels &&
847 darray_item(info->dflt.lvlNames, i) != XKB_ATOM_NONE) {
848 AddLevelName(info, &type, i,
849 darray_item(info->dflt.lvlNames, i), false);
853 /* Now add the new keytype to the info struct */
854 if (!AddKeyType(info, &type)) {
862 * Process an xkb_types section.
864 * @param file The parsed xkb_types section.
865 * @param merge Merge Strategy (e.g. MERGE_OVERRIDE)
866 * @param info Pointer to memory where the outcome will be stored.
869 HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
874 info->name = uDupString(file->name);
878 switch (stmt->stmtType) {
880 if (!HandleIncludeKeyTypes(info, (IncludeStmt *) stmt))
883 case StmtKeyTypeDef: /* e.g. type "ONE_LEVEL" */
884 if (!HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge))
888 if (!HandleKeyTypeVar(info, (VarDef *) stmt))
891 case StmtVModDef: /* virtual_modifiers NumLock, ... */
892 if (!HandleVModDef((VModDef *) stmt, info->keymap, merge,
896 case StmtKeyAliasDef:
897 log_err(info->keymap->ctx,
898 "Key type files may not include other declarations; "
899 "Ignoring definition of key alias\n");
903 log_err(info->keymap->ctx,
904 "Key type files may not include other declarations; "
905 "Ignoring definition of key name\n");
909 log_err(info->keymap->ctx,
910 "Key type files may not include other declarations; "
911 "Ignoring definition of symbol interpretation\n");
915 log_wsgo(info->keymap->ctx,
916 "Unexpected statement type %d in HandleKeyTypesFile\n",
921 if (info->errorCount > 10) {
922 log_err(info->keymap->ctx,
923 "Abandoning keytypes file \"%s\"\n", file->topName);
930 ComputeEffectiveMap(struct xkb_keymap *keymap, struct xkb_key_type *type)
933 struct xkb_kt_map_entry *entry = NULL;
935 if (type->mods.vmods != 0) {
936 tmp = VModsToReal(keymap, type->mods.vmods);
937 type->mods.mask = tmp | type->mods.real_mods;
938 darray_foreach(entry, type->map) {
940 if (entry->mods.vmods != 0) {
941 tmp = VModsToReal(keymap, entry->mods.vmods);
946 (entry->mods.real_mods | tmp) & type->mods.mask;
950 type->mods.mask = type->mods.real_mods;
956 CopyDefToKeyType(KeyTypesInfo *info, KeyTypeInfo *def,
957 struct xkb_key_type *type)
961 struct xkb_keymap *keymap = info->keymap;
963 list_foreach(pre, &def->preserves, entry) {
964 struct xkb_kt_map_entry * match;
965 struct xkb_kt_map_entry tmp;
966 tmp.mods.real_mods = pre->indexMods;
967 tmp.mods.vmods = pre->indexVMods;
969 AddMapEntry(info, def, &tmp, false, false);
970 match = FindMatchingMapEntry(def, pre->indexMods, pre->indexVMods);
972 log_wsgo(info->keymap->ctx,
973 "Couldn't find matching entry for preserve; Aborting\n");
976 pre->matchingMapIndex = match - &darray_item(def->entries, 0);
978 type->mods.real_mods = def->mask;
979 type->mods.vmods = def->vmask;
980 type->num_levels = def->numLevels;
981 memcpy(&type->map, &def->entries, sizeof(def->entries));
982 if (!list_empty(&def->preserves)) {
983 type->preserve = calloc(darray_size(type->map),
984 sizeof(*type->preserve));
985 if (!type->preserve) {
986 log_warn(info->keymap->ctx,
987 "Couldn't allocate preserve array in CopyDefToKeyType; "
988 "Preserve setting for type %s lost\n",
989 xkb_atom_text(keymap->ctx, def->name));
992 list_foreach(pre, &def->preserves, entry) {
993 int ndx = pre->matchingMapIndex;
994 type->preserve[ndx].mask = pre->preMods;
995 type->preserve[ndx].real_mods = pre->preMods;
996 type->preserve[ndx].vmods = pre->preVMods;
1001 type->preserve = NULL;
1002 type->name = xkb_atom_strdup(keymap->ctx, def->name);
1004 if (!darray_empty(def->lvlNames)) {
1005 type->level_names = calloc(darray_size(def->lvlNames),
1006 sizeof(*type->level_names));
1008 /* assert def->szNames<=def->numLevels */
1009 for (i = 0; i < darray_size(def->lvlNames); i++)
1010 type->level_names[i] =
1011 xkb_atom_strdup(keymap->ctx, darray_item(def->lvlNames, i));
1014 type->level_names = NULL;
1017 darray_init(def->entries);
1018 return ComputeEffectiveMap(keymap, type);
1021 static struct xkb_kt_map_entry map2Level[] = {
1024 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1028 static struct xkb_kt_map_entry mapAlpha[] = {
1031 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1035 .mods = { .mask = 0, .vmods = LockMask, .real_mods = 0 }
1039 static struct xkb_mods preAlpha[] = {
1040 { .mask = 0, .vmods = 0, .real_mods = 0 },
1041 { .mask = LockMask, .vmods = LockMask, .real_mods = 0 }
1044 static struct xkb_kt_map_entry mapKeypad[] = {
1047 .mods = { .mask = 1, .vmods = ShiftMask, .real_mods = 0 }
1051 .mods = { .mask = 1, .vmods = 0, .real_mods = 0 }
1055 static const struct xkb_key_type canonicalTypes[XkbNumRequiredTypes] = {
1057 .mods = { .mask = 0, .vmods = 0, .real_mods = 0 },
1064 .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1066 .map = darray_lit(map2Level),
1073 .mask = ShiftMask | LockMask,
1074 .vmods = ShiftMask | LockMask,
1078 .map = darray_lit(mapAlpha),
1079 .preserve = preAlpha,
1084 .mods = { .mask = ShiftMask, .vmods = ShiftMask, .real_mods = 0 },
1086 .map = darray_lit(mapKeypad),
1094 InitCanonicalKeyTypes(struct xkb_keymap *keymap, unsigned which,
1097 const struct xkb_key_type *from;
1100 darray_growalloc(keymap->types, XkbNumRequiredTypes);
1102 if ((which & XkbAllRequiredTypes) == 0)
1106 from = canonicalTypes;
1108 if (which & XkbOneLevelMask)
1109 rtrn = XkbcCopyKeyType(&from[XkbOneLevelIndex],
1110 &darray_item(keymap->types, XkbOneLevelIndex));
1112 if ((which & XkbTwoLevelMask) && rtrn == Success)
1113 rtrn = XkbcCopyKeyType(&from[XkbTwoLevelIndex],
1114 &darray_item(keymap->types, XkbTwoLevelIndex));
1116 if ((which & XkbAlphabeticMask) && rtrn == Success)
1117 rtrn = XkbcCopyKeyType(&from[XkbAlphabeticIndex],
1118 &darray_item(keymap->types, XkbAlphabeticIndex));
1120 if ((which & XkbKeypadMask) && rtrn == Success) {
1121 struct xkb_key_type *type;
1123 rtrn = XkbcCopyKeyType(&from[XkbKeypadIndex],
1124 &darray_item(keymap->types, XkbKeypadIndex));
1125 type = &darray_item(keymap->types, XkbKeypadIndex);
1127 if (keypadVMod >= 0 && keypadVMod < XkbNumVirtualMods &&
1129 struct xkb_kt_map_entry *entry;
1130 type->mods.vmods = (1 << keypadVMod);
1132 entry = &darray_item(type->map, 0);
1133 entry->mods.mask = ShiftMask;
1134 entry->mods.real_mods = ShiftMask;
1135 entry->mods.vmods = 0;
1138 entry = &darray_item(type->map, 1);
1139 entry->mods.mask = 0;
1140 entry->mods.real_mods = 0;
1141 entry->mods.vmods = (1 << keypadVMod);
1150 CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
1151 enum merge_mode merge)
1154 struct xkb_key_type *type, *next;
1158 InitKeyTypesInfo(&info, keymap, NULL, file->id);
1160 HandleKeyTypesFile(&info, file, merge);
1162 if (info.errorCount != 0)
1166 keymap->types_section_name = strdup(info.name);
1169 if ((info.stdPresent & XkbOneLevelMask) == 0)
1171 if ((info.stdPresent & XkbTwoLevelMask) == 0)
1173 if ((info.stdPresent & XkbKeypadMask) == 0)
1175 if ((info.stdPresent & XkbAlphabeticMask) == 0)
1178 darray_resize0(keymap->types, i);
1180 if (XkbAllRequiredTypes & (~info.stdPresent)) {
1181 unsigned missing, keypadVMod;
1183 missing = XkbAllRequiredTypes & (~info.stdPresent);
1184 keypadVMod = FindKeypadVMod(keymap);
1186 if (InitCanonicalKeyTypes(keymap, missing, keypadVMod) != Success) {
1187 log_wsgo(info.keymap->ctx,
1188 "Couldn't initialize canonical key types\n");
1192 if (missing & XkbOneLevelMask)
1193 darray_item(keymap->types, XkbOneLevelIndex).name =
1194 xkb_atom_strdup(keymap->ctx, info.tok_ONE_LEVEL);
1195 if (missing & XkbTwoLevelMask)
1196 darray_item(keymap->types, XkbTwoLevelIndex).name =
1197 xkb_atom_strdup(keymap->ctx, info.tok_TWO_LEVEL);
1198 if (missing & XkbAlphabeticMask)
1199 darray_item(keymap->types, XkbAlphabeticIndex).name =
1200 xkb_atom_strdup(keymap->ctx, info.tok_ALPHABETIC);
1201 if (missing & XkbKeypadMask)
1202 darray_item(keymap->types, XkbKeypadIndex).name =
1203 xkb_atom_strdup(keymap->ctx, info.tok_KEYPAD);
1206 next = &darray_item(keymap->types, XkbLastRequiredType + 1);
1207 list_foreach(def, &info.types, entry) {
1208 if (def->name == info.tok_ONE_LEVEL)
1209 type = &darray_item(keymap->types, XkbOneLevelIndex);
1210 else if (def->name == info.tok_TWO_LEVEL)
1211 type = &darray_item(keymap->types, XkbTwoLevelIndex);
1212 else if (def->name == info.tok_ALPHABETIC)
1213 type = &darray_item(keymap->types, XkbAlphabeticIndex);
1214 else if (def->name == info.tok_KEYPAD)
1215 type = &darray_item(keymap->types, XkbKeypadIndex);
1219 DeleteLevel1MapEntries(def);
1221 if (!CopyDefToKeyType(&info, def, type))
1225 FreeKeyTypesInfo(&info);
1229 FreeKeyTypesInfo(&info);