9967f0e8c14dca439c597e7203f909dbbaf76c8f
[platform/upstream/libxkbcommon.git] / src / xkbcomp / keymap.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-priv.h"
28 #include "indicators.h"
29
30 /**
31  * Compile the given file and store the output in xkb.
32  * @param file A list of XkbFiles, each denoting one type (e.g.
33  * XkmKeyNamesIdx, etc.)
34  */
35 struct xkb_keymap *
36 CompileKeymap(struct xkb_ctx *ctx, XkbFile *file)
37 {
38     unsigned have;
39     bool ok;
40     unsigned required, legal;
41     unsigned mainType;
42     const char *mainName;
43     LEDInfo *unbound = NULL, *next;
44     struct xkb_keymap *keymap = XkbcAllocKeyboard(ctx);
45     struct {
46         XkbFile *keycodes;
47         XkbFile *types;
48         XkbFile *compat;
49         XkbFile *symbols;
50     } sections;
51
52     if (!keymap)
53         return NULL;
54
55     memset(&sections, 0, sizeof(sections));
56     mainType = file->type;
57     mainName = file->name ? file->name : "(unnamed)";
58     switch (mainType)
59     {
60     case XkmKeymapFile:
61         required = XkmKeyNamesIndex | XkmTypesIndex | XkmSymbolsIndex |
62                    XkmCompatMapIndex;
63         legal = XkmKeymapLegal;
64         break;
65     default:
66         ERROR("Cannot compile %s alone into an XKM file\n",
67                XkbcConfigText(mainType));
68         return false;
69     }
70     have = 0;
71     ok = 1;
72     /* Check for duplicate entries in the input file */
73     for (file = (XkbFile *) file->defs; file; file = (XkbFile *) file->common.next)
74     {
75         if ((have & (1 << file->type)) != 0)
76         {
77             ERROR("More than one %s section in a %s file\n",
78                    XkbcConfigText(file->type), XkbcConfigText(mainType));
79             ACTION("All sections after the first ignored\n");
80             continue;
81         }
82         else if ((1 << file->type) & (~legal))
83         {
84             ERROR("Cannot define %s in a %s file\n",
85                    XkbcConfigText(file->type), XkbcConfigText(mainType));
86             continue;
87         }
88
89         switch (file->type)
90         {
91         case XkmKeyNamesIndex:
92             sections.keycodes = file;
93             break;
94         case XkmTypesIndex:
95             sections.types = file;
96             break;
97         case XkmSymbolsIndex:
98             sections.symbols = file;
99             break;
100         case XkmCompatMapIndex:
101             sections.compat = file;
102             break;
103         case XkmGeometryIndex:
104             continue;
105         default:
106             WSGO("Unknown file type %d\n", file->type);
107             ACTION("Ignored\n");
108             continue;
109         case XkmKeymapFile:
110             WSGO("Illegal %s configuration in a %s file\n",
111                   XkbcConfigText(file->type), XkbcConfigText(mainType));
112             ACTION("Ignored\n");
113             continue;
114         }
115
116         if (!file->topName || strcmp(file->topName, mainName) != 0) {
117             free(file->topName);
118             file->topName = strdup(mainName);
119         }
120
121         have |= (1 << file->type);
122     }
123
124     if (required & (~have))
125     {
126         int i, bit;
127         unsigned missing;
128         missing = required & (~have);
129         for (i = 0, bit = 1; missing != 0; i++, bit <<= 1)
130         {
131             if (missing & bit)
132             {
133                 ERROR("Required section %s missing from keymap\n", XkbcConfigText(i));
134                 missing &= ~bit;
135             }
136         }
137         goto err;
138     }
139
140     /* compile the sections we have in the file one-by-one, or fail. */
141     if (sections.keycodes == NULL ||
142         !CompileKeycodes(sections.keycodes, keymap, MergeOverride))
143     {
144         ERROR("Failed to compile keycodes\n");
145         goto err;
146     }
147     if (sections.types == NULL ||
148         !CompileKeyTypes(sections.types, keymap, MergeOverride))
149     {
150         ERROR("Failed to compile key types\n");
151         goto err;
152     }
153     if (sections.compat == NULL ||
154         !CompileCompatMap(sections.compat, keymap, MergeOverride, &unbound))
155     {
156         ERROR("Failed to compile compat map\n");
157         goto err;
158     }
159     if (sections.symbols == NULL ||
160         !CompileSymbols(sections.symbols, keymap, MergeOverride))
161     {
162         ERROR("Failed to compile symbols\n");
163         goto err;
164     }
165
166     ok = BindIndicators(keymap, true, unbound, NULL);
167     if (!ok)
168         goto err;
169
170     ok = UpdateModifiersFromCompat(keymap);
171     if (!ok)
172         goto err;
173
174     return keymap;
175
176 err:
177     ACTION("Failed to compile keymap\n");
178     xkb_map_unref(keymap);
179     while (unbound) {
180         next = (LEDInfo *) unbound->defs.next;
181         free(unbound);
182         unbound = next;
183     }
184     return NULL;
185 }