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