47b9c35ebfd4f49db785e4d0a9518112b0ff29db
[platform/upstream/libxkbcommon.git] / src / xkbcomp / keycodes.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 #include "xkbcomp.h"
28 #include "xkballoc.h"
29 #include "xkbmisc.h"
30 #include "expr.h"
31 #include "keycodes.h"
32 #include "misc.h"
33 #include "alias.h"
34
35 const char *
36 longText(unsigned long val)
37 {
38     char buf[4];
39
40     LongToKeyName(val, buf);
41     return XkbcKeyNameText(buf);
42 }
43
44 /***====================================================================***/
45
46 void
47 LongToKeyName(unsigned long val, char *name)
48 {
49     name[0] = ((val >> 24) & 0xff);
50     name[1] = ((val >> 16) & 0xff);
51     name[2] = ((val >> 8) & 0xff);
52     name[3] = (val & 0xff);
53 }
54
55 /***====================================================================***/
56
57 typedef struct _IndicatorNameInfo
58 {
59     CommonInfo defs;
60     int ndx;
61     uint32_t name;
62     Bool virtual;
63 } IndicatorNameInfo;
64
65 typedef struct _KeyNamesInfo
66 {
67     char *name;     /* e.g. evdev+aliases(qwerty) */
68     int errorCount;
69     unsigned fileID;
70     unsigned merge;
71     xkb_keycode_t computedMin; /* lowest keycode stored */
72     xkb_keycode_t computedMax; /* highest keycode stored */
73     xkb_keycode_t explicitMin;
74     xkb_keycode_t explicitMax;
75     xkb_keycode_t arraySize;
76     unsigned long *names;
77     unsigned *files;
78     unsigned char *has_alt_forms;
79     IndicatorNameInfo *leds;
80     AliasInfo *aliases;
81 } KeyNamesInfo;
82
83 static void HandleKeycodesFile(XkbFile * file,
84                                struct xkb_desc * xkb,
85                                unsigned merge,
86                                KeyNamesInfo * info);
87
88 static int
89 ResizeKeyNameArrays(KeyNamesInfo *info, int newMax)
90 {
91     void *tmp;
92     int i;
93
94     tmp = _XkbTypedRealloc(info->names, newMax + 1, unsigned long);
95     if (!tmp) {
96         ERROR
97             ("Couldn't reallocate for larger maximum keycode (%d)\n",
98              newMax);
99         ACTION("Maximum key value not changed\n");
100         return 0;
101     }
102     info->names = tmp;
103     for (i = info->arraySize + 1; i <= newMax; i++)
104         info->names[i] = 0;
105
106     tmp = _XkbTypedRealloc(info->files, newMax + 1, unsigned);
107     if (!tmp) {
108         ERROR
109             ("Couldn't reallocate for larger maximum keycode (%d)\n",
110              newMax);
111         ACTION("Maximum key value not changed\n");
112         return 0;
113     }
114     info->files = tmp;
115     for (i = info->arraySize + 1; i <= newMax; i++)
116         info->files[i] = 0;
117
118     tmp = _XkbTypedRealloc(info->has_alt_forms, newMax + 1, unsigned char);
119     if (!tmp) {
120         ERROR
121             ("Couldn't reallocate for larger maximum keycode (%d)\n",
122              newMax);
123         ACTION("Maximum key value not changed\n");
124         return 0;
125     }
126     info->has_alt_forms = tmp;
127     for (i = info->arraySize + 1; i <= newMax; i++)
128         info->has_alt_forms[i] = 0;
129
130     info->arraySize = newMax;
131
132     return 1;
133 }
134
135 static void
136 InitIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
137 {
138     ii->defs.defined = 0;
139     ii->defs.merge = info->merge;
140     ii->defs.fileID = info->fileID;
141     ii->defs.next = NULL;
142     ii->ndx = 0;
143     ii->name = None;
144     ii->virtual = False;
145 }
146
147 static void
148 ClearIndicatorNameInfo(IndicatorNameInfo * ii, KeyNamesInfo * info)
149 {
150     if (ii == info->leds)
151     {
152         ClearCommonInfo(&ii->defs);
153         info->leds = NULL;
154     }
155 }
156
157 static IndicatorNameInfo *
158 NextIndicatorName(KeyNamesInfo * info)
159 {
160     IndicatorNameInfo *ii;
161
162     ii = uTypedAlloc(IndicatorNameInfo);
163     if (ii)
164     {
165         InitIndicatorNameInfo(ii, info);
166         info->leds = (IndicatorNameInfo *) AddCommonInfo(&info->leds->defs,
167                                                          (CommonInfo *) ii);
168     }
169     return ii;
170 }
171
172 static IndicatorNameInfo *
173 FindIndicatorByIndex(KeyNamesInfo * info, int ndx)
174 {
175     IndicatorNameInfo *old;
176
177     for (old = info->leds; old != NULL;
178          old = (IndicatorNameInfo *) old->defs.next)
179     {
180         if (old->ndx == ndx)
181             return old;
182     }
183     return NULL;
184 }
185
186 static IndicatorNameInfo *
187 FindIndicatorByName(KeyNamesInfo * info, uint32_t name)
188 {
189     IndicatorNameInfo *old;
190
191     for (old = info->leds; old != NULL;
192          old = (IndicatorNameInfo *) old->defs.next)
193     {
194         if (old->name == name)
195             return old;
196     }
197     return NULL;
198 }
199
200 static Bool
201 AddIndicatorName(KeyNamesInfo * info, IndicatorNameInfo * new)
202 {
203     IndicatorNameInfo *old;
204     Bool replace;
205
206     replace = (new->defs.merge == MergeReplace) ||
207         (new->defs.merge == MergeOverride);
208     old = FindIndicatorByName(info, new->name);
209     if (old)
210     {
211         if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
212             || (warningLevel > 9))
213         {
214             WARN("Multiple indicators named %s\n", XkbcAtomText(new->name));
215             if (old->ndx == new->ndx)
216             {
217                 if (old->virtual != new->virtual)
218                 {
219                     if (replace)
220                         old->virtual = new->virtual;
221                     ACTION("Using %s instead of %s\n",
222                            (old->virtual ? "virtual" : "real"),
223                            (old->virtual ? "real" : "virtual"));
224                 }
225                 else
226                 {
227                     ACTION("Identical definitions ignored\n");
228                 }
229                 return True;
230             }
231             else
232             {
233                 if (replace)
234                     ACTION("Ignoring %d, using %d\n", old->ndx, new->ndx);
235                 else
236                     ACTION("Using %d, ignoring %d\n", old->ndx, new->ndx);
237             }
238             if (replace)
239             {
240                 if (info->leds == old)
241                     info->leds = (IndicatorNameInfo *) old->defs.next;
242                 else
243                 {
244                     IndicatorNameInfo *tmp;
245                     tmp = info->leds;
246                     for (; tmp != NULL;
247                          tmp = (IndicatorNameInfo *) tmp->defs.next)
248                     {
249                         if (tmp->defs.next == (CommonInfo *) old)
250                         {
251                             tmp->defs.next = old->defs.next;
252                             break;
253                         }
254                     }
255                 }
256                 free(old);
257             }
258         }
259     }
260     old = FindIndicatorByIndex(info, new->ndx);
261     if (old)
262     {
263         if (((old->defs.fileID == new->defs.fileID) && (warningLevel > 0))
264             || (warningLevel > 9))
265         {
266             WARN("Multiple names for indicator %d\n", new->ndx);
267             if ((old->name == new->name) && (old->virtual == new->virtual))
268                 ACTION("Identical definitions ignored\n");
269             else
270             {
271                 const char *oldType, *newType;
272                 uint32_t using, ignoring;
273                 if (old->virtual)
274                     oldType = "virtual indicator";
275                 else
276                     oldType = "real indicator";
277                 if (new->virtual)
278                     newType = "virtual indicator";
279                 else
280                     newType = "real indicator";
281                 if (replace)
282                 {
283                     using = new->name;
284                     ignoring = old->name;
285                 }
286                 else
287                 {
288                     using = old->name;
289                     ignoring = new->name;
290                 }
291                 ACTION("Using %s %s, ignoring %s %s\n",
292                         oldType, XkbcAtomText(using),
293                         newType, XkbcAtomText(ignoring));
294             }
295         }
296         if (replace)
297         {
298             old->name = new->name;
299             old->virtual = new->virtual;
300         }
301         return True;
302     }
303     old = new;
304     new = NextIndicatorName(info);
305     if (!new)
306     {
307         WSGO("Couldn't allocate name for indicator %d\n", old->ndx);
308         ACTION("Ignored\n");
309         return False;
310     }
311     new->name = old->name;
312     new->ndx = old->ndx;
313     new->virtual = old->virtual;
314     return True;
315 }
316
317 static void
318 ClearKeyNamesInfo(KeyNamesInfo * info)
319 {
320     free(info->name);
321     info->name = NULL;
322     info->computedMax = info->explicitMax = info->explicitMin = 0;
323     info->computedMin = XKB_KEYCODE_MAX;
324     info->arraySize = 0;
325     free(info->names);
326     info->names = NULL;
327     free(info->files);
328     info->files = NULL;
329     free(info->has_alt_forms);
330     info->has_alt_forms = NULL;
331     if (info->leds)
332         ClearIndicatorNameInfo(info->leds, info);
333     if (info->aliases)
334         ClearAliases(&info->aliases);
335 }
336
337 static void
338 InitKeyNamesInfo(KeyNamesInfo * info)
339 {
340     info->name = NULL;
341     info->leds = NULL;
342     info->aliases = NULL;
343     info->names = NULL;
344     info->files = NULL;
345     info->has_alt_forms = NULL;
346     ClearKeyNamesInfo(info);
347     info->errorCount = 0;
348 }
349
350 static int
351 FindKeyByLong(KeyNamesInfo * info, unsigned long name)
352 {
353     int i;
354
355     for (i = info->computedMin; i <= info->computedMax; i++)
356     {
357         if (info->names[i] == name)
358             return i;
359     }
360     return 0;
361 }
362
363 /**
364  * Store the name of the key as a long in the info struct under the given
365  * keycode. If the same keys is referred to twice, print a warning.
366  * Note that the key's name is stored as a long, the keycode is the index.
367  */
368 static Bool
369 AddKeyName(KeyNamesInfo * info,
370            xkb_keycode_t kc,
371            char *name, unsigned merge, unsigned fileID, Bool reportCollisions)
372 {
373     int old;
374     unsigned long lval;
375
376     if (kc > info->arraySize && !ResizeKeyNameArrays(info, kc)) {
377         ERROR("Couldn't resize KeyNames arrays for keycode %d\n", kc);
378         ACTION("Ignoring key %d\n", kc);
379         return False;
380     }
381     if (kc < info->computedMin)
382         info->computedMin = kc;
383     if (kc > info->computedMax)
384         info->computedMax = kc;
385     lval = KeyNameToLong(name);
386
387     if (reportCollisions)
388     {
389         reportCollisions = ((warningLevel > 7) ||
390                             ((warningLevel > 0)
391                              && (fileID == info->files[kc])));
392     }
393
394     if (info->names[kc] != 0)
395     {
396         char buf[6];
397
398         LongToKeyName(info->names[kc], buf);
399         buf[4] = '\0';
400         if (info->names[kc] == lval)
401         {
402             if (info->has_alt_forms[kc] || (merge == MergeAltForm))
403             {
404                 info->has_alt_forms[kc] = True;
405             }
406             else if (reportCollisions)
407             {
408                 WARN("Multiple identical key name definitions\n");
409                 ACTION("Later occurences of \"<%s> = %d\" ignored\n",
410                         buf, kc);
411             }
412             return True;
413         }
414         if (merge == MergeAugment)
415         {
416             if (reportCollisions)
417             {
418                 WARN("Multiple names for keycode %d\n", kc);
419                 ACTION("Using <%s>, ignoring <%s>\n", buf, name);
420             }
421             return True;
422         }
423         else
424         {
425             if (reportCollisions)
426             {
427                 WARN("Multiple names for keycode %d\n", kc);
428                 ACTION("Using <%s>, ignoring <%s>\n", name, buf);
429             }
430             info->names[kc] = 0;
431             info->files[kc] = 0;
432         }
433     }
434     old = FindKeyByLong(info, lval);
435     if ((old != 0) && (old != kc))
436     {
437         if (merge == MergeOverride)
438         {
439             info->names[old] = 0;
440             info->files[old] = 0;
441             info->has_alt_forms[old] = True;
442             if (reportCollisions)
443             {
444                 WARN("Key name <%s> assigned to multiple keys\n", name);
445                 ACTION("Using %d, ignoring %d\n", kc, old);
446             }
447         }
448         else if (merge != MergeAltForm)
449         {
450             if ((reportCollisions) && (warningLevel > 3))
451             {
452                 WARN("Key name <%s> assigned to multiple keys\n", name);
453                 ACTION("Using %d, ignoring %d\n", old, kc);
454                 ACTION
455                     ("Use 'alternate' keyword to assign the same name to multiple keys\n");
456             }
457             return True;
458         }
459         else
460         {
461             info->has_alt_forms[old] = True;
462         }
463     }
464     info->names[kc] = lval;
465     info->files[kc] = fileID;
466     info->has_alt_forms[kc] = (merge == MergeAltForm);
467     return True;
468 }
469
470 /***====================================================================***/
471
472 static void
473 MergeIncludedKeycodes(KeyNamesInfo * into, KeyNamesInfo * from,
474                       unsigned merge)
475 {
476     int i;
477     char buf[5];
478
479     if (from->errorCount > 0)
480     {
481         into->errorCount += from->errorCount;
482         return;
483     }
484     if (into->name == NULL)
485     {
486         into->name = from->name;
487         from->name = NULL;
488     }
489     if (from->computedMax > into->arraySize &&
490         !ResizeKeyNameArrays(into, from->computedMax)) {
491         ERROR("Couldn't resize KeyNames arrays for key %d\n",
492               from->computedMax);
493         ACTION("Ignoring include file %s\n", from->name);
494         into->errorCount += 10;
495         return;
496     }
497     for (i = from->computedMin; i <= from->computedMax; i++)
498     {
499         unsigned thisMerge;
500         if (from->names[i] == 0)
501             continue;
502         LongToKeyName(from->names[i], buf);
503         buf[4] = '\0';
504         if (from->has_alt_forms[i])
505             thisMerge = MergeAltForm;
506         else
507             thisMerge = merge;
508         if (!AddKeyName(into, i, buf, thisMerge, from->fileID, False))
509             into->errorCount++;
510     }
511     if (from->leds)
512     {
513         IndicatorNameInfo *led, *next;
514         for (led = from->leds; led != NULL; led = next)
515         {
516             if (merge != MergeDefault)
517                 led->defs.merge = merge;
518             if (!AddIndicatorName(into, led))
519                 into->errorCount++;
520             next = (IndicatorNameInfo *) led->defs.next;
521         }
522     }
523     if (!MergeAliases(&into->aliases, &from->aliases, merge))
524         into->errorCount++;
525     if (from->explicitMin != 0)
526     {
527         if ((into->explicitMin == 0)
528             || (into->explicitMin > from->explicitMin))
529             into->explicitMin = from->explicitMin;
530     }
531     if (from->explicitMax > 0)
532     {
533         if ((into->explicitMax == 0)
534             || (into->explicitMax < from->explicitMax))
535             into->explicitMax = from->explicitMax;
536     }
537 }
538
539 /**
540  * Handle the given include statement (e.g. "include "evdev+aliases(qwerty)").
541  *
542  * @param stmt The include statement from the keymap file.
543  * @param xkb Unused for all but the xkb->flags.
544  * @param info Struct to store the key info in.
545  */
546 static Bool
547 HandleIncludeKeycodes(IncludeStmt * stmt, struct xkb_desc * xkb, KeyNamesInfo * info)
548 {
549     unsigned newMerge;
550     XkbFile *rtrn;
551     KeyNamesInfo included = {NULL};
552     Bool haveSelf;
553
554     haveSelf = False;
555     if ((stmt->file == NULL) && (stmt->map == NULL))
556     {
557         haveSelf = True;
558         included = *info;
559         bzero(info, sizeof(KeyNamesInfo));
560     }
561     else if (stmt->file && strcmp(stmt->file, "computed") == 0)
562     {
563         xkb->flags |= AutoKeyNames;
564         info->explicitMin = 0;
565         info->explicitMax = XKB_KEYCODE_MAX;
566         return (info->errorCount == 0);
567     } /* parse file, store returned info in the xkb struct */
568     else if (ProcessIncludeFile(stmt, XkmKeyNamesIndex, &rtrn, &newMerge))
569     {
570         InitKeyNamesInfo(&included);
571         HandleKeycodesFile(rtrn, xkb, MergeOverride, &included);
572         if (stmt->stmt != NULL)
573         {
574             free(included.name);
575             included.name = stmt->stmt;
576             stmt->stmt = NULL;
577         }
578     }
579     else
580     {
581         info->errorCount += 10; /* XXX: why 10?? */
582         return False;
583     }
584     /* Do we have more than one include statement? */
585     if ((stmt->next != NULL) && (included.errorCount < 1))
586     {
587         IncludeStmt *next;
588         unsigned op;
589         KeyNamesInfo next_incl;
590
591         for (next = stmt->next; next != NULL; next = next->next)
592         {
593             if ((next->file == NULL) && (next->map == NULL))
594             {
595                 haveSelf = True;
596                 MergeIncludedKeycodes(&included, info, next->merge);
597                 ClearKeyNamesInfo(info);
598             }
599             else if (ProcessIncludeFile(next, XkmKeyNamesIndex, &rtrn, &op))
600             {
601                 InitKeyNamesInfo(&next_incl);
602                 HandleKeycodesFile(rtrn, xkb, MergeOverride, &next_incl);
603                 MergeIncludedKeycodes(&included, &next_incl, op);
604                 ClearKeyNamesInfo(&next_incl);
605             }
606             else
607             {
608                 info->errorCount += 10; /* XXX: Why 10?? */
609                 ClearKeyNamesInfo(&included);
610                 return False;
611             }
612         }
613     }
614     if (haveSelf)
615         *info = included;
616     else
617     {
618         MergeIncludedKeycodes(info, &included, newMerge);
619         ClearKeyNamesInfo(&included);
620     }
621     return (info->errorCount == 0);
622 }
623
624 /**
625  * Parse the given statement and store the output in the info struct.
626  * e.g. <ESC> = 9
627  */
628 static int
629 HandleKeycodeDef(KeycodeDef * stmt, unsigned merge, KeyNamesInfo * info)
630 {
631     if ((info->explicitMin != 0 && stmt->value < info->explicitMin) ||
632         (info->explicitMax != 0 && stmt->value > info->explicitMax))
633     {
634         ERROR("Illegal keycode %lu for name <%s>\n", stmt->value, stmt->name);
635         ACTION("Must be in the range %d-%d inclusive\n",
636                 info->explicitMin,
637                 info->explicitMax ? info->explicitMax : XKB_KEYCODE_MAX);
638         return 0;
639     }
640     if (stmt->merge != MergeDefault)
641     {
642         if (stmt->merge == MergeReplace)
643             merge = MergeOverride;
644         else
645             merge = stmt->merge;
646     }
647     return AddKeyName(info, stmt->value, stmt->name, merge, info->fileID,
648                       True);
649 }
650
651 #define MIN_KEYCODE_DEF         0
652 #define MAX_KEYCODE_DEF         1
653
654 /**
655  * Handle the minimum/maximum statement of the xkb file.
656  * Sets explicitMin/Max of the info struct.
657  *
658  * @return 1 on success, 0 otherwise.
659  */
660 static int
661 HandleKeyNameVar(VarDef * stmt, KeyNamesInfo * info)
662 {
663     ExprResult tmp, field;
664     ExprDef *arrayNdx;
665     int which;
666
667     if (ExprResolveLhs(stmt->name, &tmp, &field, &arrayNdx) == 0)
668         return 0;               /* internal error, already reported */
669
670     if (tmp.str != NULL)
671     {
672         ERROR("Unknown element %s encountered\n", tmp.str);
673         ACTION("Default for field %s ignored\n", field.str);
674         return 0;
675     }
676     if (uStrCaseCmp(field.str, "minimum") == 0)
677         which = MIN_KEYCODE_DEF;
678     else if (uStrCaseCmp(field.str, "maximum") == 0)
679         which = MAX_KEYCODE_DEF;
680     else
681     {
682         ERROR("Unknown field encountered\n");
683         ACTION("Assigment to field %s ignored\n", field.str);
684         return 0;
685     }
686     if (arrayNdx != NULL)
687     {
688         ERROR("The %s setting is not an array\n", field.str);
689         ACTION("Illegal array reference ignored\n");
690         return 0;
691     }
692
693     if (ExprResolveKeyCode(stmt->value, &tmp) == 0)
694     {
695         ACTION("Assignment to field %s ignored\n", field.str);
696         return 0;
697     }
698     if (tmp.uval > XKB_KEYCODE_MAX)
699     {
700         ERROR
701             ("Illegal keycode %d (must be in the range %d-%d inclusive)\n",
702              tmp.uval, 0, XKB_KEYCODE_MAX);
703         ACTION("Value of \"%s\" not changed\n", field.str);
704         return 0;
705     }
706     if (which == MIN_KEYCODE_DEF)
707     {
708         if ((info->explicitMax > 0) && (info->explicitMax < tmp.uval))
709         {
710             ERROR
711                 ("Minimum key code (%d) must be <= maximum key code (%d)\n",
712                  tmp.uval, info->explicitMax);
713             ACTION("Minimum key code value not changed\n");
714             return 0;
715         }
716         if ((info->computedMax > 0) && (info->computedMin < tmp.uval))
717         {
718             ERROR
719                 ("Minimum key code (%d) must be <= lowest defined key (%d)\n",
720                  tmp.uval, info->computedMin);
721             ACTION("Minimum key code value not changed\n");
722             return 0;
723         }
724         info->explicitMin = tmp.uval;
725     }
726     if (which == MAX_KEYCODE_DEF)
727     {
728         if ((info->explicitMin > 0) && (info->explicitMin > tmp.uval))
729         {
730             ERROR("Maximum code (%d) must be >= minimum key code (%d)\n",
731                    tmp.uval, info->explicitMin);
732             ACTION("Maximum code value not changed\n");
733             return 0;
734         }
735         if ((info->computedMax > 0) && (info->computedMax > tmp.uval))
736         {
737             ERROR
738                 ("Maximum code (%d) must be >= highest defined key (%d)\n",
739                  tmp.uval, info->computedMax);
740             ACTION("Maximum code value not changed\n");
741             return 0;
742         }
743         info->explicitMax = tmp.uval;
744     }
745     return 1;
746 }
747
748 static int
749 HandleIndicatorNameDef(IndicatorNameDef * def,
750                        unsigned merge, KeyNamesInfo * info)
751 {
752     IndicatorNameInfo ii;
753     ExprResult tmp;
754
755     if ((def->ndx < 1) || (def->ndx > XkbNumIndicators))
756     {
757         info->errorCount++;
758         ERROR("Name specified for illegal indicator index %d\n", def->ndx);
759         ACTION("Ignored\n");
760         return False;
761     }
762     InitIndicatorNameInfo(&ii, info);
763     ii.ndx = def->ndx;
764     if (!ExprResolveString(def->name, &tmp))
765     {
766         char buf[20];
767         snprintf(buf, sizeof(buf), "%d", def->ndx);
768         info->errorCount++;
769         return ReportBadType("indicator", "name", buf, "string");
770     }
771     ii.name = xkb_intern_atom(tmp.str);
772     free(tmp.str);
773     ii.virtual = def->virtual;
774     if (!AddIndicatorName(info, &ii))
775         return False;
776     return True;
777 }
778
779 /**
780  * Handle the xkb_keycodes section of a xkb file.
781  * All information about parsed keys is stored in the info struct.
782  *
783  * Such a section may have include statements, in which case this function is
784  * semi-recursive (it calls HandleIncludeKeycodes, which may call
785  * HandleKeycodesFile again).
786  *
787  * @param file The input file (parsed xkb_keycodes section)
788  * @param xkb Necessary to pass down, may have flags changed.
789  * @param merge Merge strategy (MergeOverride, etc.)
790  * @param info Struct to contain the fully parsed key information.
791  */
792 static void
793 HandleKeycodesFile(XkbFile * file,
794                    struct xkb_desc * xkb, unsigned merge, KeyNamesInfo * info)
795 {
796     ParseCommon *stmt;
797
798     info->name = _XkbDupString(file->name);
799     stmt = file->defs;
800     while (stmt)
801     {
802         switch (stmt->stmtType)
803         {
804         case StmtInclude:    /* e.g. include "evdev+aliases(qwerty)" */
805             if (!HandleIncludeKeycodes((IncludeStmt *) stmt, xkb, info))
806                 info->errorCount++;
807             break;
808         case StmtKeycodeDef: /* e.g. <ESC> = 9; */
809             if (!HandleKeycodeDef((KeycodeDef *) stmt, merge, info))
810                 info->errorCount++;
811             break;
812         case StmtKeyAliasDef: /* e.g. alias <MENU> = <COMP>; */
813             if (!HandleAliasDef((KeyAliasDef *) stmt,
814                                 merge, info->fileID, &info->aliases))
815                 info->errorCount++;
816             break;
817         case StmtVarDef: /* e.g. minimum, maximum */
818             if (!HandleKeyNameVar((VarDef *) stmt, info))
819                 info->errorCount++;
820             break;
821         case StmtIndicatorNameDef: /* e.g. indicator 1 = "Caps Lock"; */
822             if (!HandleIndicatorNameDef((IndicatorNameDef *) stmt,
823                                         merge, info))
824             {
825                 info->errorCount++;
826             }
827             break;
828         case StmtInterpDef:
829         case StmtVModDef:
830             ERROR("Keycode files may define key and indicator names only\n");
831             ACTION("Ignoring definition of %s\n",
832                     ((stmt->stmtType ==
833                       StmtInterpDef) ? "a symbol interpretation" :
834                      "virtual modifiers"));
835             info->errorCount++;
836             break;
837         default:
838             WSGO("Unexpected statement type %d in HandleKeycodesFile\n",
839                   stmt->stmtType);
840             break;
841         }
842         stmt = stmt->next;
843         if (info->errorCount > 10)
844         {
845 #ifdef NOISY
846             ERROR("Too many errors\n");
847 #endif
848             ACTION("Abandoning keycodes file \"%s\"\n", file->topName);
849             break;
850         }
851     }
852 }
853
854 /**
855  * Compile the xkb_keycodes section, parse it's output, return the results.
856  *
857  * @param file The parsed XKB file (may have include statements requiring
858  * further parsing)
859  * @param result The effective keycodes, as gathered from the file.
860  * @param merge Merge strategy.
861  *
862  * @return True on success, False otherwise.
863  */
864 Bool
865 CompileKeycodes(XkbFile *file, struct xkb_desc * xkb, unsigned merge)
866 {
867     KeyNamesInfo info; /* contains all the info after parsing */
868
869     InitKeyNamesInfo(&info);
870     HandleKeycodesFile(file, xkb, merge, &info);
871
872     /* all the keys are now stored in info */
873
874     if (info.errorCount == 0)
875     {
876         if (info.explicitMin > 0) /* if "minimum" statement was present */
877             xkb->min_key_code = info.explicitMin;
878         else
879             xkb->min_key_code = info.computedMin;
880         if (info.explicitMax > 0) /* if "maximum" statement was present */
881             xkb->max_key_code = info.explicitMax;
882         else
883             xkb->max_key_code = info.computedMax;
884         if (XkbcAllocNames(xkb, XkbKeyNamesMask | XkbIndicatorNamesMask, 0, 0)
885                 == Success)
886         {
887             int i;
888             xkb->names->keycodes = xkb_intern_atom(info.name);
889             for (i = info.computedMin; i <= info.computedMax; i++)
890             {
891                 LongToKeyName(info.names[i], xkb->names->keys[i].name);
892             }
893         }
894         else
895         {
896             WSGO("Cannot create struct xkb_names in CompileKeycodes\n");
897             return False;
898         }
899         if (info.leds)
900         {
901             IndicatorNameInfo *ii;
902             if (XkbcAllocIndicatorMaps(xkb) != Success)
903             {
904                 WSGO("Couldn't allocate IndicatorRec in CompileKeycodes\n");
905                 ACTION("Physical indicators not set\n");
906             }
907             for (ii = info.leds; ii != NULL;
908                  ii = (IndicatorNameInfo *) ii->defs.next)
909             {
910                 xkb->names->indicators[ii->ndx - 1] = ii->name;
911                 if (xkb->indicators != NULL)
912                 {
913                     unsigned bit;
914                     bit = 1 << (ii->ndx - 1);
915                     if (ii->virtual)
916                         xkb->indicators->phys_indicators &= ~bit;
917                     else
918                         xkb->indicators->phys_indicators |= bit;
919                 }
920             }
921         }
922         if (info.aliases)
923             ApplyAliases(xkb, False, &info.aliases);
924         return True;
925     }
926     ClearKeyNamesInfo(&info);
927     return False;
928 }