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