symbols: store actions from symbols in the right offset
[platform/upstream/libxkbcommon.git] / src / xkbcomp / symbols.c
1 /************************************************************
2  * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3  *
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.
15  *
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.
24  *
25  ********************************************************/
26
27 /*
28  * Copyright © 2012 Intel Corporation
29  * Copyright © 2012 Ran Benita <ran234@gmail.com>
30  *
31  * Permission is hereby granted, free of charge, to any person obtaining a
32  * copy of this software and associated documentation files (the "Software"),
33  * to deal in the Software without restriction, including without limitation
34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35  * and/or sell copies of the Software, and to permit persons to whom the
36  * Software is furnished to do so, subject to the following conditions:
37  *
38  * The above copyright notice and this permission notice (including the next
39  * paragraph) shall be included in all copies or substantial portions of the
40  * Software.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
45  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48  * DEALINGS IN THE SOFTWARE.
49  *
50  * Author: Daniel Stone <daniel@fooishbar.org>
51  *         Ran Benita <ran234@gmail.com>
52  */
53
54 #include "xkbcomp-priv.h"
55 #include "text.h"
56 #include "expr.h"
57 #include "action.h"
58 #include "vmod.h"
59 #include "keycodes.h"
60 #include "include.h"
61
62 enum key_repeat {
63     KEY_REPEAT_YES = 1,
64     KEY_REPEAT_NO = 0,
65     KEY_REPEAT_UNDEFINED = -1
66 };
67
68 enum group_field {
69     GROUP_FIELD_SYMS = (1 << 0),
70     GROUP_FIELD_ACTS = (1 << 1),
71     GROUP_FIELD_TYPE = (1 << 2),
72 };
73
74 enum key_field {
75     KEY_FIELD_REPEAT    = (1 << 0),
76     KEY_FIELD_TYPE_DFLT = (1 << 1),
77     KEY_FIELD_GROUPINFO = (1 << 2),
78     KEY_FIELD_VMODMAP   = (1 << 3),
79 };
80
81 typedef struct {
82     unsigned int num_syms;
83     unsigned int sym_index;
84     union xkb_action act;
85 } LevelInfo;
86
87 typedef darray(xkb_keysym_t) darray_xkb_keysym_t;
88
89 typedef struct {
90     enum group_field defined;
91     darray_xkb_keysym_t syms;
92     darray(LevelInfo) levels;
93     xkb_atom_t type;
94 } GroupInfo;
95
96 typedef struct _KeyInfo {
97     enum key_field defined;
98     unsigned file_id;
99     enum merge_mode merge;
100
101     unsigned long name; /* the 4 chars of the key name, as long */
102
103     GroupInfo groups[XKB_NUM_GROUPS];
104
105     enum key_repeat repeat;
106     xkb_mod_mask_t vmodmap;
107     xkb_atom_t dfltType;
108
109     enum xkb_range_exceed_type out_of_range_group_action;
110     xkb_group_index_t out_of_range_group_number;
111 } KeyInfo;
112
113 static void
114 InitGroupInfo(GroupInfo *groupi)
115 {
116     memset(groupi, 0, sizeof(*groupi));
117 }
118
119 static void
120 ClearGroupInfo(GroupInfo *groupi)
121 {
122     darray_free(groupi->syms);
123     darray_free(groupi->levels);
124     InitGroupInfo(groupi);
125 }
126
127 static void
128 InitKeyInfo(KeyInfo *keyi, unsigned file_id)
129 {
130     xkb_group_index_t i;
131     static const char dflt[4] = "*";
132
133     keyi->defined = 0;
134     keyi->file_id = file_id;
135     keyi->merge = MERGE_OVERRIDE;
136     keyi->name = KeyNameToLong(dflt);
137     for (i = 0; i < XKB_NUM_GROUPS; i++)
138         InitGroupInfo(&keyi->groups[i]);
139     keyi->dfltType = XKB_ATOM_NONE;
140     keyi->vmodmap = 0;
141     keyi->repeat = KEY_REPEAT_UNDEFINED;
142     keyi->out_of_range_group_action = RANGE_WRAP;
143     keyi->out_of_range_group_number = 0;
144 }
145
146 static void
147 ClearKeyInfo(KeyInfo *keyi)
148 {
149     xkb_group_index_t i;
150
151     for (i = 0; i < XKB_NUM_GROUPS; i++)
152         ClearGroupInfo(&keyi->groups[i]);
153 }
154
155 /***====================================================================***/
156
157 typedef struct _ModMapEntry {
158     enum merge_mode merge;
159     bool haveSymbol;
160     int modifier;
161     union {
162         unsigned long keyName;
163         xkb_keysym_t keySym;
164     } u;
165 } ModMapEntry;
166
167 typedef struct _SymbolsInfo {
168     char *name;         /* e.g. pc+us+inet(evdev) */
169     int errorCount;
170     unsigned file_id;
171     enum merge_mode merge;
172     xkb_group_index_t explicit_group;
173     darray(KeyInfo) keys;
174     KeyInfo dflt;
175     VModInfo vmods;
176     ActionsInfo *actions;
177     xkb_atom_t groupNames[XKB_NUM_GROUPS];
178     darray(ModMapEntry) modMaps;
179
180     struct xkb_keymap *keymap;
181 } SymbolsInfo;
182
183 static void
184 InitSymbolsInfo(SymbolsInfo *info, struct xkb_keymap *keymap,
185                 unsigned file_id, ActionsInfo *actions)
186 {
187     xkb_group_index_t i;
188
189     info->name = NULL;
190     info->explicit_group = 0;
191     info->errorCount = 0;
192     info->file_id = file_id;
193     info->merge = MERGE_OVERRIDE;
194     darray_init(info->keys);
195     darray_growalloc(info->keys, 110);
196     darray_init(info->modMaps);
197     for (i = 0; i < XKB_NUM_GROUPS; i++)
198         info->groupNames[i] = XKB_ATOM_NONE;
199     InitKeyInfo(&info->dflt, file_id);
200     InitVModInfo(&info->vmods, keymap);
201     info->actions = actions;
202     info->keymap = keymap;
203 }
204
205 static void
206 ClearSymbolsInfo(SymbolsInfo * info)
207 {
208     KeyInfo *keyi;
209
210     free(info->name);
211     darray_foreach(keyi, info->keys)
212         ClearKeyInfo(keyi);
213     darray_free(info->keys);
214     darray_free(info->modMaps);
215     memset(info, 0, sizeof(SymbolsInfo));
216 }
217
218 static bool
219 MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
220             bool report, xkb_group_index_t group, unsigned long key_name)
221 {
222     xkb_level_index_t i, numLevels;
223     enum { INTO = (1 << 0), FROM = (1 << 1) } using;
224
225     /* First find the type of the merged group. */
226     if (into->type != from->type) {
227         if (from->type == XKB_ATOM_NONE) {
228         }
229         else if (into->type == XKB_ATOM_NONE) {
230             into->type = from->type;
231         }
232         else {
233             xkb_atom_t use = (clobber ? from->type : into->type);
234             xkb_atom_t ignore = (clobber ? into->type : from->type);
235
236             if (report)
237                 log_warn(info->keymap->ctx,
238                          "Multiple definitions for group %d type of key %s; "
239                          "Using %s, ignoring %s\n",
240                          group + 1, LongKeyNameText(key_name),
241                          xkb_atom_text(info->keymap->ctx, use),
242                          xkb_atom_text(info->keymap->ctx, ignore));
243
244             into->type = use;
245         }
246     }
247     into->defined |= (from->defined & GROUP_FIELD_TYPE);
248
249     /* Now look at the levels. */
250
251     if (darray_empty(from->levels)) {
252         InitGroupInfo(from);
253         return true;
254     }
255
256     if (darray_empty(into->levels)) {
257         from->type = into->type;
258         *into = *from;
259         InitGroupInfo(from);
260         return true;
261     }
262
263     /* First we merge the actions and ensure @into has all the levels. */
264     numLevels = MAX(darray_size(into->levels), darray_size(from->levels));
265     for (i = 0; i < numLevels; i++) {
266         union xkb_action *intoAct, *fromAct;
267
268         if (i >= darray_size(from->levels))
269             continue;
270
271         if (i >= darray_size(into->levels)) {
272             darray_append(into->levels, darray_item(from->levels, i));
273             darray_item(into->levels, i).num_syms = 0;
274             darray_item(into->levels, i).sym_index = 0;
275             continue;
276         }
277
278         intoAct = &darray_item(into->levels, i).act;
279         fromAct = &darray_item(from->levels, i).act;
280
281         if (fromAct->type == ACTION_TYPE_NONE) {
282         }
283         else if (intoAct->type == ACTION_TYPE_NONE) {
284             *intoAct = *fromAct;
285         }
286         else {
287             union xkb_action *use = (clobber ? fromAct : intoAct);
288             union xkb_action *ignore = (clobber ? intoAct : fromAct);
289
290             if (report)
291                 log_warn(info->keymap->ctx,
292                          "Multiple actions for level %d/group %u on key %s; "
293                          "Using %s, ignoring %s\n",
294                          i + 1, group + 1, LongKeyNameText(key_name),
295                          ActionTypeText(use->type),
296                          ActionTypeText(ignore->type));
297
298             *intoAct = *use;
299         }
300     }
301     into->defined |= (from->defined & GROUP_FIELD_ACTS);
302
303     /* Then merge the keysyms. */
304
305     /*
306      * We want to avoid copying and allocating if not necessary. So
307      * here we do a pre-scan of the levels to check if we'll only use
308      * @into's or @from's keysyms, and if so we'll just assign them.
309      * However if one level uses @into's and another uses @from's, we
310      * will need to construct a new syms array.
311      */
312     using = 0;
313     for (i = 0; i < numLevels; i++) {
314         unsigned int intoSize, fromSize;
315
316         intoSize = darray_item(into->levels, i).num_syms;
317         if (i < darray_size(from->levels))
318             fromSize = darray_item(from->levels, i).num_syms;
319         else
320             fromSize = 0;
321
322         if (intoSize == 0 && fromSize == 0)
323             using |= 0;
324         else if (intoSize == 0)
325             using |= FROM;
326         else if (fromSize == 0)
327             using |= INTO;
328         else
329             using |= (clobber ? FROM : INTO);
330     }
331
332     if (using == 0 || using == INTO) {
333     }
334     else if (using == FROM) {
335         darray_free(into->syms);
336         into->syms = from->syms;
337         darray_init(from->syms);
338         for (i = 0; i < darray_size(from->levels); i++) {
339             darray_item(into->levels, i).num_syms =
340                 darray_item(from->levels, i).num_syms;
341             darray_item(into->levels, i).sym_index =
342                 darray_item(from->levels, i).sym_index;
343         }
344     }
345     else {
346         darray_xkb_keysym_t syms = darray_new();
347
348         for (i = 0; i < numLevels; i++) {
349             unsigned int intoSize, fromSize;
350
351             intoSize = darray_item(into->levels, i).num_syms;
352             if (i < darray_size(from->levels))
353                 fromSize = darray_item(from->levels, i).num_syms;
354             else
355                 fromSize = 0;
356
357             /* Empty level. */
358             if (intoSize == 0 && fromSize == 0)
359                 continue;
360
361             if (intoSize != 0 && fromSize != 0 && report)
362                 log_info(info->keymap->ctx,
363                          "Multiple symbols for group %u, level %d on key %s; "
364                          "Using %s, ignoring %s\n",
365                          group + 1, i + 1, LongKeyNameText(key_name),
366                          (clobber ? "from" : "to"),
367                          (clobber ? "to" : "from"));
368
369             if (intoSize == 0 || (fromSize != 0 && clobber)) {
370                 unsigned sym_index = darray_item(from->levels, i).sym_index;
371                 darray_item(into->levels, i).sym_index = darray_size(syms);
372                 darray_item(into->levels, i).num_syms = fromSize;
373                 darray_append_items(syms, &darray_item(from->syms, sym_index),
374                                     fromSize);
375             }
376             else
377             {
378                 unsigned sym_index = darray_item(into->levels, i).sym_index;
379                 darray_item(into->levels, i).sym_index = darray_size(syms);
380                 darray_item(into->levels, i).num_syms = intoSize;
381                 darray_append_items(syms, &darray_item(into->syms, sym_index),
382                                     intoSize);
383             }
384         }
385         darray_free(into->syms);
386         into->syms = syms;
387     }
388     into->defined |= (from->defined & GROUP_FIELD_SYMS);
389
390     return true;
391 }
392
393 static bool
394 UseNewKeyField(enum key_field field, enum key_field old, enum key_field new,
395                bool clobber, bool report, enum key_field *collide)
396 {
397     if (!(old & field))
398         return (new & field);
399
400     if (new & field) {
401         if (report)
402             *collide |= field;
403
404         if (clobber)
405             return true;
406     }
407
408     return false;
409 }
410
411
412 static bool
413 MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from)
414 {
415     xkb_group_index_t i;
416     enum key_field collide = 0;
417     bool clobber, report;
418     int verbosity = xkb_get_log_verbosity(info->keymap->ctx);
419
420     if (from->merge == MERGE_REPLACE) {
421         ClearKeyInfo(into);
422         *into = *from;
423         InitKeyInfo(from, info->file_id);
424         return true;
425     }
426
427     clobber = (from->merge != MERGE_AUGMENT);
428     report = (verbosity > 9 ||
429               (into->file_id == from->file_id && verbosity > 0));
430
431     for (i = 0; i < XKB_NUM_GROUPS; i++)
432         MergeGroups(info, &into->groups[i], &from->groups[i], clobber,
433                     report, i, into->name);
434
435     if (UseNewKeyField(KEY_FIELD_VMODMAP, into->defined, from->defined,
436                        clobber, report, &collide)) {
437         into->vmodmap = from->vmodmap;
438         into->defined |= KEY_FIELD_VMODMAP;
439     }
440     if (UseNewKeyField(KEY_FIELD_REPEAT, into->defined, from->defined,
441                        clobber, report, &collide)) {
442         into->repeat = from->repeat;
443         into->defined |= KEY_FIELD_REPEAT;
444     }
445     if (UseNewKeyField(KEY_FIELD_TYPE_DFLT, into->defined, from->defined,
446                        clobber, report, &collide)) {
447         into->dfltType = from->dfltType;
448         into->defined |= KEY_FIELD_TYPE_DFLT;
449     }
450     if (UseNewKeyField(KEY_FIELD_GROUPINFO, into->defined, from->defined,
451                        clobber, report, &collide)) {
452         into->out_of_range_group_action = from->out_of_range_group_action;
453         into->out_of_range_group_number = from->out_of_range_group_number;
454         into->defined |= KEY_FIELD_GROUPINFO;
455     }
456
457     if (collide)
458         log_warn(info->keymap->ctx,
459                  "Symbol map for key %s redefined; "
460                  "Using %s definition for conflicting fields\n",
461                  LongKeyNameText(into->name),
462                  (clobber ? "first" : "last"));
463
464     ClearKeyInfo(from);
465     return true;
466 }
467
468 static bool
469 AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi)
470 {
471     unsigned long real_name;
472     KeyInfo *iter;
473
474     /*
475      * Don't keep aliases in the keys array; this guarantees that
476      * searching for keys to merge with by straight comparison (see the
477      * following loop) is enough, and we won't get multiple KeyInfo's
478      * for the same key because of aliases.
479      */
480     if (FindKeyNameForAlias(info->keymap, keyi->name, &real_name))
481         keyi->name = real_name;
482
483     darray_foreach(iter, info->keys)
484         if (iter->name == keyi->name)
485             return MergeKeys(info, iter, keyi);
486
487     darray_append(info->keys, *keyi);
488     InitKeyInfo(keyi, info->file_id);
489     return true;
490 }
491
492 static bool
493 AddModMapEntry(SymbolsInfo * info, ModMapEntry * new)
494 {
495     ModMapEntry *mm;
496     bool clobber;
497
498     clobber = (new->merge != MERGE_AUGMENT);
499     darray_foreach(mm, info->modMaps) {
500         if (new->haveSymbol && mm->haveSymbol
501             && (new->u.keySym == mm->u.keySym)) {
502             unsigned use, ignore;
503             if (mm->modifier != new->modifier) {
504                 if (clobber) {
505                     use = new->modifier;
506                     ignore = mm->modifier;
507                 }
508                 else {
509                     use = mm->modifier;
510                     ignore = new->modifier;
511                 }
512                 log_err(info->keymap->ctx,
513                         "%s added to symbol map for multiple modifiers; "
514                         "Using %s, ignoring %s.\n",
515                         KeysymText(new->u.keySym), ModIndexText(use),
516                         ModIndexText(ignore));
517                 mm->modifier = use;
518             }
519             return true;
520         }
521         if ((!new->haveSymbol) && (!mm->haveSymbol) &&
522             (new->u.keyName == mm->u.keyName)) {
523             unsigned use, ignore;
524             if (mm->modifier != new->modifier) {
525                 if (clobber) {
526                     use = new->modifier;
527                     ignore = mm->modifier;
528                 }
529                 else {
530                     use = mm->modifier;
531                     ignore = new->modifier;
532                 }
533                 log_err(info->keymap->ctx,
534                         "Key %s added to map for multiple modifiers; "
535                         "Using %s, ignoring %s.\n",
536                         LongKeyNameText(new->u.keyName), ModIndexText(use),
537                         ModIndexText(ignore));
538                 mm->modifier = use;
539             }
540             return true;
541         }
542     }
543
544     darray_append(info->modMaps, *new);
545     return true;
546 }
547
548 /***====================================================================***/
549
550 static void
551 MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
552                      enum merge_mode merge)
553 {
554     unsigned int i;
555     KeyInfo *keyi;
556     ModMapEntry *mm;
557
558     if (from->errorCount > 0) {
559         into->errorCount += from->errorCount;
560         return;
561     }
562     if (into->name == NULL) {
563         into->name = from->name;
564         from->name = NULL;
565     }
566     for (i = 0; i < XKB_NUM_GROUPS; i++) {
567         if (from->groupNames[i] != XKB_ATOM_NONE) {
568             if ((merge != MERGE_AUGMENT) ||
569                 (into->groupNames[i] == XKB_ATOM_NONE))
570                 into->groupNames[i] = from->groupNames[i];
571         }
572     }
573
574     darray_foreach(keyi, from->keys) {
575         merge = (merge == MERGE_DEFAULT ? keyi->merge : merge);
576         if (!AddKeySymbols(into, keyi))
577             into->errorCount++;
578     }
579
580     darray_foreach(mm, from->modMaps) {
581         mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
582         if (!AddModMapEntry(into, mm))
583             into->errorCount++;
584     }
585 }
586
587 static void
588 HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge);
589
590 static bool
591 HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *stmt)
592 {
593     enum merge_mode merge = MERGE_DEFAULT;
594     XkbFile *rtrn;
595     SymbolsInfo included, next_incl;
596
597     InitSymbolsInfo(&included, info->keymap, info->file_id, info->actions);
598     if (stmt->stmt) {
599         free(included.name);
600         included.name = stmt->stmt;
601         stmt->stmt = NULL;
602     }
603
604     for (; stmt; stmt = stmt->next_incl) {
605         if (!ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_SYMBOLS,
606                                 &rtrn, &merge)) {
607             info->errorCount += 10;
608             ClearSymbolsInfo(&included);
609             return false;
610         }
611
612         InitSymbolsInfo(&next_incl, info->keymap, rtrn->id, info->actions);
613         next_incl.merge = next_incl.dflt.merge = MERGE_OVERRIDE;
614         if (stmt->modifier)
615             next_incl.explicit_group = atoi(stmt->modifier) - 1;
616         else
617             next_incl.explicit_group = info->explicit_group;
618
619         HandleSymbolsFile(&next_incl, rtrn, MERGE_OVERRIDE);
620
621         MergeIncludedSymbols(&included, &next_incl, merge);
622
623         ClearSymbolsInfo(&next_incl);
624         FreeXkbFile(rtrn);
625     }
626
627     MergeIncludedSymbols(info, &included, merge);
628     ClearSymbolsInfo(&included);
629
630     return (info->errorCount == 0);
631 }
632
633 #define SYMBOLS 1
634 #define ACTIONS 2
635
636 static bool
637 GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
638               unsigned what, xkb_group_index_t *ndx_rtrn)
639 {
640     const char *name = (what == SYMBOLS ? "symbols" : "actions");
641
642     if (arrayNdx == NULL) {
643         xkb_group_index_t i;
644         enum group_field field = (what == SYMBOLS ?
645                                   GROUP_FIELD_SYMS : GROUP_FIELD_ACTS);
646
647         for (i = 0; i < XKB_NUM_GROUPS; i++) {
648             if (!(keyi->groups[i].defined & field)) {
649                 *ndx_rtrn = i;
650                 return true;
651             }
652         }
653
654         log_err(info->keymap->ctx,
655                 "Too many groups of %s for key %s (max %u); "
656                 "Ignoring %s defined for extra groups\n",
657                 name, LongKeyNameText(keyi->name), XKB_NUM_GROUPS + 1, name);
658         return false;
659     }
660
661     if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, ndx_rtrn)) {
662         log_err(info->keymap->ctx,
663                 "Illegal group index for %s of key %s\n"
664                 "Definition with non-integer array index ignored\n",
665                 name, LongKeyNameText(keyi->name));
666         return false;
667     }
668
669     (*ndx_rtrn)--;
670     return true;
671 }
672
673 bool
674 LookupKeysym(const char *str, xkb_keysym_t *sym_rtrn)
675 {
676     xkb_keysym_t sym;
677
678     if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
679         *sym_rtrn = XKB_KEY_NoSymbol;
680         return 1;
681     }
682
683     if (istreq(str, "none") || istreq(str, "voidsymbol")) {
684         *sym_rtrn = XKB_KEY_VoidSymbol;
685         return 1;
686     }
687
688     sym = xkb_keysym_from_name(str);
689     if (sym != XKB_KEY_NoSymbol) {
690         *sym_rtrn = sym;
691         return 1;
692     }
693
694     return 0;
695 }
696
697 static bool
698 AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
699                 ExprDef *value)
700 {
701     xkb_group_index_t ndx;
702     GroupInfo *groupi;
703     unsigned int nSyms;
704     xkb_level_index_t nLevels;
705     xkb_level_index_t i;
706     int j;
707
708     if (!GetGroupIndex(info, keyi, arrayNdx, SYMBOLS, &ndx))
709         return false;
710
711     groupi = &keyi->groups[ndx];
712
713     if (value == NULL) {
714         groupi->defined |= GROUP_FIELD_SYMS;
715         return true;
716     }
717
718     if (value->op != EXPR_KEYSYM_LIST) {
719         log_err(info->keymap->ctx,
720                 "Expected a list of symbols, found %s; "
721                 "Ignoring symbols for group %u of %s\n",
722                 expr_op_type_to_string(value->op), ndx + 1,
723                 LongKeyNameText(keyi->name));
724         return false;
725     }
726
727     if (groupi->defined & GROUP_FIELD_SYMS) {
728         log_err(info->keymap->ctx,
729                 "Symbols for key %s, group %u already defined; "
730                 "Ignoring duplicate definition\n",
731                 LongKeyNameText(keyi->name), ndx + 1);
732         return false;
733     }
734
735     nSyms = darray_size(value->value.list.syms);
736     nLevels = darray_size(value->value.list.symsMapIndex);
737
738     if (darray_size(groupi->syms) < nSyms)
739         darray_resize0(groupi->syms, nSyms);
740
741     if (darray_size(groupi->levels) < nLevels)
742         darray_resize0(groupi->levels, nLevels);
743
744     groupi->defined |= GROUP_FIELD_SYMS;
745
746     for (i = 0; i < nLevels; i++) {
747         LevelInfo *leveli = &darray_item(groupi->levels, i);
748
749         leveli->sym_index = darray_item(value->value.list.symsMapIndex, i);
750         leveli->num_syms = darray_item(value->value.list.symsNumEntries, i);
751
752         for (j = 0; j < leveli->num_syms; j++) {
753             if (!LookupKeysym(darray_item(value->value.list.syms,
754                                           leveli->sym_index + j),
755                               &darray_item(groupi->syms,
756                                            leveli->sym_index + j))) {
757                 log_warn(info->keymap->ctx,
758                          "Could not resolve keysym %s for key %s, group %u (%s), level %u\n",
759                          darray_item(value->value.list.syms, i),
760                          LongKeyNameText(keyi->name),
761                          ndx + 1,
762                          xkb_atom_text(info->keymap->ctx,
763                                        info->groupNames[ndx]),
764                          nSyms);
765                 leveli->sym_index = 0;
766                 leveli->num_syms = 0;
767                 break;
768             }
769
770             if (leveli->num_syms == 1 &&
771                 darray_item(groupi->syms,
772                             leveli->sym_index + j) == XKB_KEY_NoSymbol) {
773                 leveli->sym_index = 0;
774                 leveli->num_syms = 0;
775             }
776         }
777     }
778
779     for (j = darray_size(groupi->levels) - 1;
780          j >= 0 && darray_item(groupi->levels, j).num_syms == 0; j--)
781         (void) darray_pop(groupi->levels);
782
783     return true;
784 }
785
786 static bool
787 AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
788                 ExprDef *value)
789 {
790     unsigned int i;
791     xkb_group_index_t ndx;
792     GroupInfo *groupi;
793     unsigned int nActs;
794     ExprDef *act;
795     union xkb_action *toAct;
796
797     if (!GetGroupIndex(info, keyi, arrayNdx, ACTIONS, &ndx))
798         return false;
799
800     groupi = &keyi->groups[ndx];
801
802     if (value == NULL) {
803         groupi->defined |= GROUP_FIELD_ACTS;
804         return true;
805     }
806
807     if (value->op != EXPR_ACTION_LIST) {
808         log_wsgo(info->keymap->ctx,
809                  "Bad expression type (%d) for action list value; "
810                  "Ignoring actions for group %u of %s\n",
811                  value->op, ndx, LongKeyNameText(keyi->name));
812         return false;
813     }
814
815     if (groupi->defined & GROUP_FIELD_ACTS) {
816         log_wsgo(info->keymap->ctx,
817                  "Actions for key %s, group %u already defined\n",
818                  LongKeyNameText(keyi->name), ndx);
819         return false;
820     }
821
822     nActs = 0;
823     for (act = value->value.child; act; act = (ExprDef *) act->common.next)
824         nActs++;
825
826     if (darray_size(groupi->levels) < nActs)
827         darray_resize0(groupi->levels, nActs);
828
829     groupi->defined |= GROUP_FIELD_ACTS;
830
831     act = value->value.child;
832     for (i = 0; i < nActs; i++) {
833         toAct = &darray_item(groupi->levels, i).act;
834
835         if (!HandleActionDef(act, info->keymap, toAct, info->actions))
836             log_err(info->keymap->ctx,
837                     "Illegal action definition for %s; "
838                     "Action for group %u/level %u ignored\n",
839                     LongKeyNameText(keyi->name), ndx + 1, i + 1);
840
841         act = (ExprDef *) act->common.next;
842     }
843
844     return true;
845 }
846
847 static const LookupEntry repeatEntries[] = {
848     { "true", KEY_REPEAT_YES },
849     { "yes", KEY_REPEAT_YES },
850     { "on", KEY_REPEAT_YES },
851     { "false", KEY_REPEAT_NO },
852     { "no", KEY_REPEAT_NO },
853     { "off", KEY_REPEAT_NO },
854     { "default", KEY_REPEAT_UNDEFINED },
855     { NULL, 0 }
856 };
857
858 static bool
859 SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
860                 ExprDef *arrayNdx, ExprDef *value)
861 {
862     bool ok = true;
863     struct xkb_context *ctx = info->keymap->ctx;
864
865     if (istreq(field, "type")) {
866         xkb_group_index_t ndx;
867         xkb_atom_t val;
868
869         if (!ExprResolveString(ctx, value, &val))
870             log_vrb(ctx, 1,
871                     "The type field of a key symbol map must be a string; "
872                     "Ignoring illegal type definition\n");
873
874         if (arrayNdx == NULL) {
875             keyi->dfltType = val;
876             keyi->defined |= KEY_FIELD_TYPE_DFLT;
877         }
878         else if (!ExprResolveGroup(ctx, arrayNdx, &ndx)) {
879             log_err(ctx,
880                     "Illegal group index for type of key %s; "
881                     "Definition with non-integer array index ignored\n",
882                     LongKeyNameText(keyi->name));
883             return false;
884         }
885         else {
886             ndx--;
887             keyi->groups[ndx].type = val;
888             keyi->groups[ndx].defined |= GROUP_FIELD_TYPE;
889         }
890     }
891     else if (istreq(field, "symbols"))
892         return AddSymbolsToKey(info, keyi, arrayNdx, value);
893     else if (istreq(field, "actions"))
894         return AddActionsToKey(info, keyi, arrayNdx, value);
895     else if (istreq(field, "vmods") ||
896              istreq(field, "virtualmods") ||
897              istreq(field, "virtualmodifiers")) {
898         xkb_mod_mask_t mask;
899
900         ok = ExprResolveVModMask(info->keymap, value, &mask);
901         if (ok) {
902             keyi->vmodmap = (mask >> XKB_NUM_CORE_MODS) & 0xffff;
903             keyi->defined |= KEY_FIELD_VMODMAP;
904         }
905         else {
906             log_err(info->keymap->ctx,
907                     "Expected a virtual modifier mask, found %s; "
908                     "Ignoring virtual modifiers definition for key %s\n",
909                     expr_op_type_to_string(value->op),
910                     LongKeyNameText(keyi->name));
911         }
912     }
913     else if (istreq(field, "locking") ||
914              istreq(field, "lock") ||
915              istreq(field, "locks")) {
916         log_err(info->keymap->ctx,
917                 "Key behaviors not supported; "
918                 "Ignoring locking specification for key %s\n",
919                 LongKeyNameText(keyi->name));
920     }
921     else if (istreq(field, "radiogroup") ||
922              istreq(field, "permanentradiogroup") ||
923              istreq(field, "allownone")) {
924         log_err(info->keymap->ctx,
925                 "Radio groups not supported; "
926                 "Ignoring radio group specification for key %s\n",
927                 LongKeyNameText(keyi->name));
928     }
929     else if (istreq_prefix("overlay", field) ||
930              istreq_prefix("permanentoverlay", field)) {
931         log_err(info->keymap->ctx,
932                 "Overlays not supported; "
933                 "Ignoring overlay specification for key %s\n",
934                 LongKeyNameText(keyi->name));
935     }
936     else if (istreq(field, "repeating") ||
937              istreq(field, "repeats") ||
938              istreq(field, "repeat")) {
939         unsigned int val;
940
941         ok = ExprResolveEnum(ctx, value, &val, repeatEntries);
942         if (!ok) {
943             log_err(info->keymap->ctx,
944                     "Illegal repeat setting for %s; "
945                     "Non-boolean repeat setting ignored\n",
946                     LongKeyNameText(keyi->name));
947             return false;
948         }
949         keyi->repeat = val;
950         keyi->defined |= KEY_FIELD_REPEAT;
951     }
952     else if (istreq(field, "groupswrap") ||
953              istreq(field, "wrapgroups")) {
954         bool set;
955
956         if (!ExprResolveBoolean(ctx, value, &set)) {
957             log_err(info->keymap->ctx,
958                     "Illegal groupsWrap setting for %s; "
959                     "Non-boolean value ignored\n",
960                     LongKeyNameText(keyi->name));
961             return false;
962         }
963
964         if (set)
965             keyi->out_of_range_group_action = RANGE_WRAP;
966         else
967             keyi->out_of_range_group_action = RANGE_SATURATE;
968
969         keyi->defined |= KEY_FIELD_GROUPINFO;
970     }
971     else if (istreq(field, "groupsclamp") ||
972              istreq(field, "clampgroups")) {
973         bool set;
974
975         if (!ExprResolveBoolean(ctx, value, &set)) {
976             log_err(info->keymap->ctx,
977                     "Illegal groupsClamp setting for %s; "
978                     "Non-boolean value ignored\n",
979                     LongKeyNameText(keyi->name));
980             return false;
981         }
982
983         if (set)
984             keyi->out_of_range_group_action = RANGE_SATURATE;
985         else
986             keyi->out_of_range_group_action = RANGE_WRAP;
987
988         keyi->defined |= KEY_FIELD_GROUPINFO;
989     }
990     else if (istreq(field, "groupsredirect") ||
991              istreq(field, "redirectgroups")) {
992         xkb_group_index_t grp;
993
994         if (!ExprResolveGroup(ctx, value, &grp)) {
995             log_err(info->keymap->ctx,
996                     "Illegal group index for redirect of key %s; "
997                     "Definition with non-integer group ignored\n",
998                     LongKeyNameText(keyi->name));
999             return false;
1000         }
1001
1002         keyi->out_of_range_group_action = RANGE_REDIRECT;
1003         keyi->out_of_range_group_number = grp - 1;
1004         keyi->defined |= KEY_FIELD_GROUPINFO;
1005     }
1006     else {
1007         log_err(info->keymap->ctx,
1008                 "Unknown field %s in a symbol interpretation; "
1009                 "Definition ignored\n",
1010                 field);
1011         ok = false;
1012     }
1013
1014     return ok;
1015 }
1016
1017 static int
1018 SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
1019 {
1020     xkb_group_index_t grp;
1021     xkb_atom_t name;
1022
1023     if (!arrayNdx) {
1024         log_vrb(info->keymap->ctx, 1,
1025                 "You must specify an index when specifying a group name; "
1026                 "Group name definition without array subscript ignored\n");
1027         return false;
1028     }
1029
1030     if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, &grp)) {
1031         log_err(info->keymap->ctx,
1032                 "Illegal index in group name definition; "
1033                 "Definition with non-integer array index ignored\n");
1034         return false;
1035     }
1036
1037     if (!ExprResolveString(info->keymap->ctx, value, &name)) {
1038         log_err(info->keymap->ctx,
1039                 "Group name must be a string; "
1040                 "Illegal name for group %d ignored\n", grp);
1041         return false;
1042     }
1043
1044     info->groupNames[grp - 1 + info->explicit_group] = name;
1045     return true;
1046 }
1047
1048 static int
1049 HandleSymbolsVar(SymbolsInfo *info, VarDef *stmt)
1050 {
1051     const char *elem, *field;
1052     ExprDef *arrayNdx;
1053     bool ret;
1054
1055     if (ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field,
1056                        &arrayNdx) == 0)
1057         return 0;               /* internal error, already reported */
1058     if (elem && istreq(elem, "key")) {
1059         ret = SetSymbolsField(info, &info->dflt, field, arrayNdx,
1060                               stmt->value);
1061     }
1062     else if (!elem && (istreq(field, "name") ||
1063                        istreq(field, "groupname"))) {
1064         ret = SetGroupName(info, arrayNdx, stmt->value);
1065     }
1066     else if (!elem && (istreq(field, "groupswrap") ||
1067                        istreq(field, "wrapgroups"))) {
1068         log_err(info->keymap->ctx,
1069                 "Global \"groupswrap\" not supported; Ignored\n");
1070         ret = true;
1071     }
1072     else if (!elem && (istreq(field, "groupsclamp") ||
1073                        istreq(field, "clampgroups"))) {
1074         log_err(info->keymap->ctx,
1075                 "Global \"groupsclamp\" not supported; Ignored\n");
1076         ret = true;
1077     }
1078     else if (!elem && (istreq(field, "groupsredirect") ||
1079                        istreq(field, "redirectgroups"))) {
1080         log_err(info->keymap->ctx,
1081                 "Global \"groupsredirect\" not supported; Ignored\n");
1082         ret = true;
1083     }
1084     else if (!elem && istreq(field, "allownone")) {
1085         log_err(info->keymap->ctx,
1086                 "Radio groups not supported; "
1087                 "Ignoring \"allownone\" specification\n");
1088         ret = true;
1089     }
1090     else {
1091         ret = SetActionField(info->keymap, elem, field, arrayNdx, stmt->value,
1092                              info->actions);
1093     }
1094
1095     return ret;
1096 }
1097
1098 static bool
1099 HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
1100 {
1101     bool ok = true;
1102     const char *elem, *field;
1103     ExprDef *arrayNdx;
1104
1105     for (; def; def = (VarDef *) def->common.next) {
1106         if (def->name && def->name->op == EXPR_FIELD_REF) {
1107             ok = HandleSymbolsVar(info, def);
1108             continue;
1109         }
1110
1111         if (!def->name) {
1112             if (!def->value || def->value->op == EXPR_KEYSYM_LIST)
1113                 field = "symbols";
1114             else
1115                 field = "actions";
1116             arrayNdx = NULL;
1117         }
1118         else {
1119             ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
1120                                 &arrayNdx);
1121         }
1122
1123         if (ok)
1124             ok = SetSymbolsField(info, keyi, field, arrayNdx, def->value);
1125     }
1126
1127     return ok;
1128 }
1129
1130 static bool
1131 SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
1132 {
1133     xkb_group_index_t i;
1134
1135     if (info->explicit_group == 0)
1136         return true;
1137
1138     for (i = 1; i < XKB_NUM_GROUPS; i++) {
1139         if (keyi->groups[i].defined) {
1140             log_warn(info->keymap->ctx,
1141                      "For the map %s an explicit group specified, "
1142                      "but key %s has more than one group defined; "
1143                      "All groups except first one will be ignored\n",
1144                      info->name, LongKeyNameText(keyi->name));
1145             break;
1146         }
1147     }
1148     if (i < XKB_NUM_GROUPS)
1149         for (i = 1; i < XKB_NUM_GROUPS; i++)
1150             ClearGroupInfo(&keyi->groups[i]);
1151
1152     keyi->groups[info->explicit_group] = keyi->groups[0];
1153     InitGroupInfo(&keyi->groups[0]);
1154     return true;
1155 }
1156
1157 static int
1158 HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt)
1159 {
1160     KeyInfo keyi;
1161     xkb_group_index_t i;
1162
1163     keyi = info->dflt;
1164     for (i = 0; i < XKB_NUM_GROUPS; i++) {
1165         darray_copy(keyi.groups[i].syms, info->dflt.groups[i].syms);
1166         darray_copy(keyi.groups[i].levels, info->dflt.groups[i].levels);
1167     }
1168     keyi.merge = stmt->merge;
1169     keyi.name = KeyNameToLong(stmt->keyName);
1170
1171     if (!HandleSymbolsBody(info, (VarDef *) stmt->symbols, &keyi)) {
1172         info->errorCount++;
1173         return false;
1174     }
1175
1176     if (!SetExplicitGroup(info, &keyi)) {
1177         info->errorCount++;
1178         return false;
1179     }
1180
1181     if (!AddKeySymbols(info, &keyi)) {
1182         info->errorCount++;
1183         return false;
1184     }
1185
1186     return true;
1187 }
1188
1189 static bool
1190 HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
1191 {
1192     ExprDef *key;
1193     ModMapEntry tmp;
1194     xkb_mod_index_t ndx;
1195     bool ok;
1196     struct xkb_context *ctx = info->keymap->ctx;
1197
1198     if (!LookupModIndex(ctx, NULL, def->modifier, EXPR_TYPE_INT, &ndx)) {
1199         log_err(info->keymap->ctx,
1200                 "Illegal modifier map definition; "
1201                 "Ignoring map for non-modifier \"%s\"\n",
1202                 xkb_atom_text(ctx, def->modifier));
1203         return false;
1204     }
1205
1206     ok = true;
1207     tmp.modifier = ndx;
1208
1209     for (key = def->keys; key != NULL; key = (ExprDef *) key->common.next) {
1210         xkb_keysym_t sym;
1211
1212         if (key->op == EXPR_VALUE && key->value_type == EXPR_TYPE_KEYNAME) {
1213             tmp.haveSymbol = false;
1214             tmp.u.keyName = KeyNameToLong(key->value.keyName);
1215         }
1216         else if (ExprResolveKeySym(ctx, key, &sym)) {
1217             tmp.haveSymbol = true;
1218             tmp.u.keySym = sym;
1219         }
1220         else {
1221             log_err(info->keymap->ctx,
1222                     "Modmap entries may contain only key names or keysyms; "
1223                     "Illegal definition for %s modifier ignored\n",
1224                     ModIndexText(tmp.modifier));
1225             continue;
1226         }
1227
1228         ok = AddModMapEntry(info, &tmp) && ok;
1229     }
1230     return ok;
1231 }
1232
1233 static void
1234 HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
1235 {
1236     bool ok;
1237     ParseCommon *stmt;
1238
1239     free(info->name);
1240     info->name = strdup_safe(file->name);
1241
1242     stmt = file->defs;
1243     for (stmt = file->defs; stmt; stmt = stmt->next) {
1244         switch (stmt->type) {
1245         case STMT_INCLUDE:
1246             ok = HandleIncludeSymbols(info, (IncludeStmt *) stmt);
1247             break;
1248         case STMT_SYMBOLS:
1249             ok = HandleSymbolsDef(info, (SymbolsDef *) stmt);
1250             break;
1251         case STMT_VAR:
1252             ok = HandleSymbolsVar(info, (VarDef *) stmt);
1253             break;
1254         case STMT_VMOD:
1255             ok = HandleVModDef((VModDef *) stmt, info->keymap, merge,
1256                                &info->vmods);
1257             break;
1258         case STMT_MODMAP:
1259             ok = HandleModMapDef(info, (ModMapDef *) stmt);
1260             break;
1261         default:
1262             log_err(info->keymap->ctx,
1263                     "Interpretation files may not include other types; "
1264                     "Ignoring %s\n", stmt_type_to_string(stmt->type));
1265             ok = false;
1266             break;
1267         }
1268
1269         if (!ok)
1270             info->errorCount++;
1271
1272         if (info->errorCount > 10) {
1273             log_err(info->keymap->ctx, "Abandoning symbols file \"%s\"\n",
1274                     file->topName);
1275             break;
1276         }
1277     }
1278 }
1279
1280 /**
1281  * Given a keysym @sym, return a key which generates it, or NULL.
1282  * This is used for example in a modifier map definition, such as:
1283  *      modifier_map Lock           { Caps_Lock };
1284  * where we want to add the Lock modifier to the modmap of the key
1285  * which matches the keysym Caps_Lock.
1286  * Since there can be many keys which generates the keysym, the key
1287  * is chosen first by lowest group in which the keysym appears, than
1288  * by lowest level and than by lowest key code.
1289  */
1290 static struct xkb_key *
1291 FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
1292 {
1293     struct xkb_key *key, *ret = NULL;
1294     xkb_group_index_t group, min_group = UINT32_MAX;
1295     xkb_level_index_t level, min_level = UINT16_MAX;
1296
1297     xkb_foreach_key(key, keymap) {
1298         for (group = 0; group < key->num_groups; group++) {
1299             for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
1300                  level++) {
1301                 if (XkbKeyNumSyms(key, group, level) != 1 ||
1302                     (XkbKeySymEntry(key, group, level))[0] != sym)
1303                     continue;
1304
1305                 /*
1306                  * If the keysym was found in a group or level > 0, we must
1307                  * keep looking since we might find a key in which the keysym
1308                  * is in a lower group or level.
1309                  */
1310                 if (group < min_group ||
1311                     (group == min_group && level < min_level)) {
1312                     ret = key;
1313                     if (group == 0 && level == 0) {
1314                         return ret;
1315                     }
1316                     else {
1317                         min_group = group;
1318                         min_level = level;
1319                     }
1320                 }
1321             }
1322         }
1323     }
1324
1325     return ret;
1326 }
1327
1328 static bool
1329 FindNamedType(struct xkb_keymap *keymap, xkb_atom_t name, unsigned *type_rtrn)
1330 {
1331     unsigned int i;
1332
1333     for (i = 0; i < keymap->num_types; i++) {
1334         if (keymap->types[i].name == name) {
1335             *type_rtrn = i;
1336             return true;
1337         }
1338     }
1339
1340     return false;
1341 }
1342
1343 /**
1344  * Assign a type to the given sym and return the Atom for the type assigned.
1345  *
1346  * Simple recipe:
1347  * - ONE_LEVEL for width 0/1
1348  * - ALPHABETIC for 2 shift levels, with lower/upercase
1349  * - KEYPAD for keypad keys.
1350  * - TWO_LEVEL for other 2 shift level keys.
1351  * and the same for four level keys.
1352  *
1353  * @param width Number of sysms in syms.
1354  * @param syms The keysyms for the given key (must be size width).
1355  * @param typeNameRtrn Set to the Atom of the type name.
1356  *
1357  * @returns true if a type could be found, false otherwise.
1358  *
1359  * FIXME: I need to take the KeyInfo so I can look at symsMapIndex and
1360  *        all that fun stuff rather than just assuming there's always one
1361  *        symbol per level.
1362  */
1363 static bool
1364 FindAutomaticType(struct xkb_keymap *keymap, xkb_level_index_t width,
1365                   const xkb_keysym_t *syms, xkb_atom_t *typeNameRtrn,
1366                   bool *autoType)
1367 {
1368     *autoType = false;
1369     if ((width == 1) || (width == 0)) {
1370         *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ONE_LEVEL");
1371         *autoType = true;
1372     }
1373     else if (width == 2) {
1374         if (syms && xkb_keysym_is_lower(syms[0]) &&
1375             xkb_keysym_is_upper(syms[1])) {
1376             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "ALPHABETIC");
1377         }
1378         else if (syms && (xkb_keysym_is_keypad(syms[0]) ||
1379                           xkb_keysym_is_keypad(syms[1]))) {
1380             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "KEYPAD");
1381             *autoType = true;
1382         }
1383         else {
1384             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "TWO_LEVEL");
1385             *autoType = true;
1386         }
1387     }
1388     else if (width <= 4) {
1389         if (syms && xkb_keysym_is_lower(syms[0]) &&
1390             xkb_keysym_is_upper(syms[1]))
1391             if (xkb_keysym_is_lower(syms[2]) && xkb_keysym_is_upper(syms[3]))
1392                 *typeNameRtrn =
1393                     xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_ALPHABETIC");
1394             else
1395                 *typeNameRtrn = xkb_atom_intern(keymap->ctx,
1396                                                 "FOUR_LEVEL_SEMIALPHABETIC");
1397
1398         else if (syms && (xkb_keysym_is_keypad(syms[0]) ||
1399                           xkb_keysym_is_keypad(syms[1])))
1400             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL_KEYPAD");
1401         else
1402             *typeNameRtrn = xkb_atom_intern(keymap->ctx, "FOUR_LEVEL");
1403         /* XXX: why not set autoType here? */
1404     }
1405     return width <= 4;
1406 }
1407
1408 /**
1409  * Ensure the given KeyInfo is in a coherent state, i.e. no gaps between the
1410  * groups, and reduce to one group if all groups are identical anyway.
1411  */
1412 static void
1413 PrepareKeyDef(KeyInfo *keyi)
1414 {
1415     xkb_group_index_t i, lastGroup;
1416     const GroupInfo *group0;
1417     bool identical;
1418
1419     /* get highest group number */
1420     for (i = XKB_NUM_GROUPS - 1; i > 0; i--)
1421         if (keyi->groups[i].defined)
1422             break;
1423     lastGroup = i;
1424
1425     if (lastGroup == 0)
1426         return;
1427
1428     group0 = &keyi->groups[0];
1429
1430     /* If there are empty groups between non-empty ones fill them with data */
1431     /* from the first group. */
1432     /* We can make a wrong assumption here. But leaving gaps is worse. */
1433     for (i = lastGroup; i > 0; i--) {
1434         GroupInfo *groupi = &keyi->groups[i];
1435
1436         if (groupi->defined)
1437             continue;
1438
1439         groupi->type = group0->type;
1440         darray_copy(groupi->syms, group0->syms);
1441         darray_copy(groupi->levels, group0->levels);
1442         groupi->defined = group0->defined;
1443     }
1444
1445     /* If all groups are completely identical remove them all */
1446     /* exept the first one. */
1447     /* XXX: This code needs testing... or removal. */
1448     identical = true;
1449     for (i = lastGroup; i > 0; i--) {
1450         GroupInfo *groupi = &keyi->groups[i];
1451
1452         if (groupi->type != group0->type) {
1453             identical = false;
1454             break;
1455         }
1456         if (!darray_same(groupi->levels, group0->levels) &&
1457             (darray_empty(groupi->levels) || darray_empty(group0->levels) ||
1458              darray_size(groupi->levels) != darray_size(group0->levels) ||
1459              memcmp(darray_mem(groupi->levels, 0),
1460                     darray_mem(group0->levels, 0),
1461                     darray_size(group0->levels) * sizeof(LevelInfo)))) {
1462             identical = false;
1463             break;
1464         }
1465         if (!darray_same(groupi->syms, group0->syms) &&
1466             (darray_empty(groupi->syms) || darray_empty(group0->syms) ||
1467              darray_size(groupi->syms) != darray_size(group0->syms) ||
1468              memcmp(darray_mem(groupi->syms, 0),
1469                     darray_mem(group0->syms, 0),
1470                     darray_size(group0->syms) * sizeof(xkb_keysym_t)))) {
1471             identical = false;
1472             break;
1473         }
1474     }
1475
1476     if (identical)
1477         for (i = lastGroup; i > 0; i--)
1478             ClearGroupInfo(&keyi->groups[i]);
1479 }
1480
1481 static bool
1482 CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
1483 {
1484     struct xkb_keymap *keymap = info->keymap;
1485     struct xkb_key *key;
1486     unsigned int sizeSyms = 0;
1487     xkb_group_index_t i, nGroups;
1488     xkb_level_index_t width, tmp;
1489     struct xkb_key_type * type;
1490     bool haveActions;
1491     unsigned int symIndex = 0;
1492
1493     /*
1494      * The name is guaranteed to be real and not an alias (see
1495      * AddKeySymbols), so 'false' is safe here.
1496      */
1497     key = FindNamedKey(keymap, keyi->name, false);
1498     if (!key) {
1499         log_vrb(info->keymap->ctx, 5,
1500                 "Key %s not found in keycodes; Symbols ignored\n",
1501                 LongKeyNameText(keyi->name));
1502         return false;
1503     }
1504
1505     haveActions = false;
1506     width = 0;
1507     for (i = nGroups = 0; i < XKB_NUM_GROUPS; i++) {
1508         GroupInfo *groupi = &keyi->groups[i];
1509         bool autoType = false;
1510
1511         if (i + 1 > nGroups && groupi->defined)
1512             nGroups = i + 1;
1513
1514         if (!haveActions) {
1515             LevelInfo *leveli;
1516             darray_foreach(leveli, groupi->levels) {
1517                 if (leveli->act.type != ACTION_TYPE_NONE) {
1518                     haveActions = true;
1519                     break;
1520                 }
1521             }
1522         }
1523
1524         /* Assign the type to the key, if it is missing. */
1525         if (groupi->type == XKB_ATOM_NONE) {
1526             if (keyi->dfltType != XKB_ATOM_NONE)
1527                 groupi->type = keyi->dfltType;
1528             else if (FindAutomaticType(keymap, darray_size(groupi->levels),
1529                                        darray_mem(groupi->syms, 0),
1530                                        &groupi->type, &autoType)) { }
1531             else
1532                 log_vrb(info->keymap->ctx, 5,
1533                         "No automatic type for %d levels; "
1534                         "Using %s for the %s key\n",
1535                         darray_size(groupi->levels),
1536                         xkb_atom_text(keymap->ctx, groupi->type),
1537                         LongKeyNameText(keyi->name));
1538         }
1539
1540         if (FindNamedType(keymap, groupi->type, &key->kt_index[i])) {
1541             if (!autoType || darray_size(groupi->levels) > 2)
1542                 key->explicit_groups |= (1 << i);
1543         }
1544         else {
1545             log_vrb(info->keymap->ctx, 3,
1546                     "Type \"%s\" is not defined; "
1547                     "Using default type for the %s key\n",
1548                     xkb_atom_text(keymap->ctx, groupi->type),
1549                     LongKeyNameText(keyi->name));
1550             /*
1551              * Index 0 is guaranteed to contain something, usually
1552              * ONE_LEVEL or at least some default one-level type.
1553              */
1554             key->kt_index[i] = 0;
1555         }
1556
1557         /* if the type specifies fewer levels than the key has, shrink the key */
1558         type = &keymap->types[key->kt_index[i]];
1559         if (type->num_levels < darray_size(groupi->levels)) {
1560             log_vrb(info->keymap->ctx, 1,
1561                     "Type \"%s\" has %d levels, but %s has %d levels; "
1562                     "Ignoring extra symbols\n",
1563                     xkb_atom_text(keymap->ctx, type->name),
1564                     type->num_levels,
1565                     LongKeyNameText(keyi->name),
1566                     darray_size(groupi->levels));
1567             darray_resize(groupi->levels, type->num_levels);
1568         }
1569
1570         width = MAX(width, type->num_levels);
1571         sizeSyms += darray_size(groupi->syms);
1572     }
1573
1574     key->syms = calloc(sizeSyms, sizeof(*key->syms));
1575     key->num_groups = nGroups;
1576     key->width = width;
1577     key->sym_index = calloc(nGroups * width, sizeof(*key->sym_index));
1578     key->num_syms = calloc(nGroups * width, sizeof(*key->num_syms));
1579
1580     if (haveActions) {
1581         key->actions = calloc(nGroups * width, sizeof(*key->actions));
1582         key->explicit |= EXPLICIT_INTERP;
1583     }
1584
1585     key->out_of_range_group_number = keyi->out_of_range_group_number;
1586     key->out_of_range_group_action = keyi->out_of_range_group_action;
1587
1588     for (i = 0; i < nGroups; i++) {
1589         GroupInfo *groupi = &keyi->groups[i];
1590
1591         if (!darray_empty(groupi->syms)) {
1592             /* fill key to "width" symbols*/
1593             for (tmp = 0; tmp < width; tmp++) {
1594                 LevelInfo *leveli = NULL;
1595
1596                 if (tmp < darray_size(groupi->levels))
1597                     leveli = &darray_item(groupi->levels, tmp);
1598
1599                 if (leveli && leveli->num_syms != 0) {
1600                     memcpy(&key->syms[symIndex],
1601                            &darray_item(groupi->syms, leveli->sym_index),
1602                            leveli->num_syms * sizeof(*key->syms));
1603                     key->sym_index[(i * width) + tmp] = symIndex;
1604                     key->num_syms[(i * width) + tmp] = leveli->num_syms;
1605                     symIndex += key->num_syms[(i * width) + tmp];
1606                 }
1607                 else {
1608                     key->sym_index[(i * width) + tmp] = 0;
1609                     key->num_syms[(i * width) + tmp] = 0;
1610                 }
1611
1612                 if (key->actions && leveli &&
1613                     leveli->act.type != ACTION_TYPE_NONE)
1614                     key->actions[i * width + tmp] = leveli->act;
1615             }
1616         }
1617     }
1618
1619     if (keyi->defined & KEY_FIELD_VMODMAP) {
1620         key->vmodmap = keyi->vmodmap;
1621         key->explicit |= EXPLICIT_VMODMAP;
1622     }
1623
1624     if (keyi->repeat != KEY_REPEAT_UNDEFINED) {
1625         key->repeats = (keyi->repeat == KEY_REPEAT_YES);
1626         key->explicit |= EXPLICIT_REPEAT;
1627     }
1628
1629     return true;
1630 }
1631
1632 static bool
1633 CopyModMapDef(SymbolsInfo *info, ModMapEntry *entry)
1634 {
1635     struct xkb_key *key;
1636     struct xkb_keymap *keymap = info->keymap;
1637
1638     if (!entry->haveSymbol) {
1639         key = FindNamedKey(keymap, entry->u.keyName, true);
1640         if (!key) {
1641             log_vrb(info->keymap->ctx, 5,
1642                     "Key %s not found in keycodes; "
1643                     "Modifier map entry for %s not updated\n",
1644                     LongKeyNameText(entry->u.keyName),
1645                     ModIndexText(entry->modifier));
1646             return false;
1647         }
1648     }
1649     else {
1650         key = FindKeyForSymbol(keymap, entry->u.keySym);
1651         if (!key) {
1652             log_vrb(info->keymap->ctx, 5,
1653                     "Key \"%s\" not found in symbol map; "
1654                     "Modifier map entry for %s not updated\n",
1655                     KeysymText(entry->u.keySym),
1656                     ModIndexText(entry->modifier));
1657             return false;
1658         }
1659     }
1660
1661     key->modmap |= (1 << entry->modifier);
1662     return true;
1663 }
1664
1665 static bool
1666 CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
1667 {
1668     KeyInfo *keyi;
1669     ModMapEntry *mm;
1670     xkb_group_index_t i;
1671     struct xkb_key *key;
1672
1673     keymap->symbols_section_name = strdup_safe(info->name);
1674
1675     for (i = 0; i < XKB_NUM_GROUPS; i++)
1676         if (info->groupNames[i] != XKB_ATOM_NONE)
1677             keymap->group_names[i] = info->groupNames[i];
1678
1679     darray_foreach(keyi, info->keys) {
1680         PrepareKeyDef(keyi);
1681         if (!CopySymbolsDef(info, keyi))
1682             info->errorCount++;
1683     }
1684
1685     if (xkb_get_log_verbosity(keymap->ctx) > 3) {
1686         xkb_foreach_key(key, keymap) {
1687             if (key->name[0] == '\0')
1688                 continue;
1689
1690             if (key->num_groups < 1)
1691                 log_info(keymap->ctx,
1692                          "No symbols defined for %s\n",
1693                          KeyNameText(key->name));
1694         }
1695     }
1696
1697     darray_foreach(mm, info->modMaps)
1698         if (!CopyModMapDef(info, mm))
1699             info->errorCount++;
1700
1701     /* XXX: If we don't ignore errorCount, things break. */
1702     return true;
1703 }
1704
1705 bool
1706 CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
1707                enum merge_mode merge)
1708 {
1709     SymbolsInfo info;
1710     ActionsInfo *actions;
1711
1712     actions = NewActionsInfo();
1713     if (!actions)
1714         return false;
1715
1716     InitSymbolsInfo(&info, keymap, file->id, actions);
1717     info.dflt.merge = merge;
1718
1719     HandleSymbolsFile(&info, file, merge);
1720
1721     if (darray_empty(info.keys))
1722         goto err_info;
1723
1724     if (info.errorCount != 0)
1725         goto err_info;
1726
1727     if (!CopySymbolsToKeymap(keymap, &info))
1728         goto err_info;
1729
1730     ClearSymbolsInfo(&info);
1731     FreeActionsInfo(actions);
1732     return true;
1733
1734 err_info:
1735     FreeActionsInfo(actions);
1736     ClearSymbolsInfo(&info);
1737     return false;
1738 }