Use enum for file types
[platform/upstream/libxkbcommon.git] / src / xkbcomp / xkbcomp.c
1 /*
2 Copyright 2009  Dan Nicholson
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the names of the authors or their
22 institutions shall not be used in advertising or otherwise to promote the
23 sale, use or other dealings in this Software without prior written
24 authorization from the authors.
25 */
26
27 #include "xkbcomp-priv.h"
28 #include "rules.h"
29 #include "parseutils.h"
30
31 /* Global warning level */
32 unsigned int warningLevel = 0;
33
34 #define ISEMPTY(str) (!(str) || (strlen(str) == 0))
35
36 static XkbFile *
37 XkbKeymapFileFromComponents(struct xkb_context *ctx,
38                             const struct xkb_component_names *ktcsg)
39 {
40     XkbFile *keycodes, *types, *compat, *symbols;
41     IncludeStmt *inc;
42
43     inc = IncludeCreate(ktcsg->keycodes, MergeDefault);
44     keycodes = CreateXKBFile(ctx, FILE_TYPE_KEYCODES, NULL,
45                              (ParseCommon *)inc, 0);
46
47     inc = IncludeCreate(ktcsg->types, MergeDefault);
48     types = CreateXKBFile(ctx, FILE_TYPE_TYPES, NULL,
49                           (ParseCommon *)inc, 0);
50     AppendStmt(&keycodes->common, &types->common);
51
52     inc = IncludeCreate(ktcsg->compat, MergeDefault);
53     compat = CreateXKBFile(ctx, FILE_TYPE_COMPAT, NULL,
54                            (ParseCommon *)inc, 0);
55     AppendStmt(&keycodes->common, &compat->common);
56
57     inc = IncludeCreate(ktcsg->symbols, MergeDefault);
58     symbols = CreateXKBFile(ctx, FILE_TYPE_SYMBOLS, NULL,
59                             (ParseCommon *)inc, 0);
60     AppendStmt(&keycodes->common, &symbols->common);
61
62     return CreateXKBFile(ctx, FILE_TYPE_KEYMAP,
63                          ktcsg->keymap ? ktcsg->keymap : strdup(""),
64                          &keycodes->common, 0);
65 }
66
67 _X_EXPORT struct xkb_keymap *
68 xkb_map_new_from_names(struct xkb_context *ctx,
69                        const struct xkb_rule_names *rmlvo,
70                        enum xkb_map_compile_flags flags)
71 {
72     struct xkb_component_names *kkctgs;
73     struct xkb_keymap *keymap;
74
75     if (!rmlvo || ISEMPTY(rmlvo->rules) || ISEMPTY(rmlvo->layout)) {
76         ERROR("rules and layout required to generate XKB keymap\n");
77         return NULL;
78     }
79
80     kkctgs = xkb_components_from_rules(ctx, rmlvo);
81     if (!kkctgs) {
82         ERROR("failed to generate XKB components from rules \"%s\"\n",
83               rmlvo->rules);
84         return NULL;
85     }
86
87     keymap = xkb_map_new_from_kccgst(ctx, kkctgs, 0);
88
89     free(kkctgs->keymap);
90     free(kkctgs->keycodes);
91     free(kkctgs->types);
92     free(kkctgs->compat);
93     free(kkctgs->symbols);
94     free(kkctgs);
95
96     return keymap;
97 }
98
99 static XkbFile *
100 XkbChooseMap(XkbFile *file, const char *name)
101 {
102     XkbFile *map = file;
103
104     /* map specified? */
105     if (name) {
106         while (map) {
107             if (map->name && strcmp(map->name, name) == 0)
108                 break;
109             map = (XkbFile *) map->common.next;
110         }
111
112         if (!map)
113             ERROR("no map named \"%s\" in input file\n", name);
114     }
115     else if (file->common.next) {
116         /* look for map with XkbLC_Default flag. */
117         for (; map; map = (XkbFile *) map->common.next) {
118             if (map->flags & XkbLC_Default)
119                 break;
120         }
121
122         if (!map) {
123             map = file;
124             WARN("no map specified, but components have several\n");
125             WARN("using the first defined map, \"%s\"\n",
126                  map->name ? map->name : "");
127         }
128     }
129
130     return map;
131 }
132
133 static struct xkb_keymap *
134 compile_keymap(struct xkb_context *ctx, XkbFile *file)
135 {
136     XkbFile *mapToUse;
137     struct xkb_keymap *keymap = NULL;
138
139     /* Find map to use */
140     mapToUse = XkbChooseMap(file, NULL);
141     if (!mapToUse)
142         goto err;
143
144     if (mapToUse->type != FILE_TYPE_KEYMAP) {
145         ERROR("file type %d not handled\n", mapToUse->type);
146         goto err;
147     }
148
149     keymap = CompileKeymap(ctx, mapToUse);
150     if (!keymap)
151         goto err;
152
153 err:
154     FreeXKBFile(file);
155     return keymap;
156 }
157
158 _X_EXPORT struct xkb_keymap *
159 xkb_map_new_from_kccgst(struct xkb_context *ctx,
160                         const struct xkb_component_names *kccgst,
161                         enum xkb_map_compile_flags flags)
162 {
163     XkbFile *file;
164
165     if (!kccgst) {
166         ERROR("no components specified\n");
167         return NULL;
168     }
169
170     if (ISEMPTY(kccgst->keycodes)) {
171         ERROR("keycodes required to generate XKB keymap\n");
172         return NULL;
173     }
174
175     if (ISEMPTY(kccgst->compat)) {
176         ERROR("compat map required to generate XKB keymap\n");
177         return NULL;
178     }
179
180     if (ISEMPTY(kccgst->types)) {
181         ERROR("types required to generate XKB keymap\n");
182         return NULL;
183     }
184
185     if (ISEMPTY(kccgst->symbols)) {
186         ERROR("symbols required to generate XKB keymap\n");
187         return NULL;
188     }
189
190     if (!(file = XkbKeymapFileFromComponents(ctx, kccgst))) {
191         ERROR("failed to generate parsed XKB file from components\n");
192         return NULL;
193     }
194
195     return compile_keymap(ctx, file);
196 }
197
198 _X_EXPORT struct xkb_keymap *
199 xkb_map_new_from_string(struct xkb_context *ctx,
200                         const char *string,
201                         enum xkb_keymap_format format,
202                         enum xkb_map_compile_flags flags)
203 {
204     XkbFile *file;
205
206     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
207         ERROR("unsupported keymap format %d\n", format);
208         return NULL;
209     }
210
211     if (!string) {
212         ERROR("no string specified to generate XKB keymap\n");
213         return NULL;
214     }
215
216     if (!XKBParseString(ctx, string, "input", &file)) {
217         ERROR("failed to parse input xkb file\n");
218         return NULL;
219     }
220
221     return compile_keymap(ctx, file);
222 }
223
224 _X_EXPORT struct xkb_keymap *
225 xkb_map_new_from_file(struct xkb_context *ctx,
226                       FILE *file,
227                       enum xkb_keymap_format format,
228                       enum xkb_map_compile_flags flags)
229 {
230     XkbFile *xkb_file;
231
232     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
233         ERROR("unsupported keymap format %d\n", format);
234         return NULL;
235     }
236
237     if (!file) {
238         ERROR("no file specified to generate XKB keymap\n");
239         return NULL;
240     }
241
242     if (!XKBParseFile(ctx, file, "(unknown file)", &xkb_file)) {
243         ERROR("failed to parse input xkb file\n");
244         return NULL;
245     }
246
247     return compile_keymap(ctx, xkb_file);
248 }
249
250 _X_EXPORT struct xkb_keymap *
251 xkb_map_ref(struct xkb_keymap *keymap)
252 {
253     keymap->refcnt++;
254     return keymap;
255 }
256
257 _X_EXPORT void
258 xkb_map_unref(struct xkb_keymap *keymap)
259 {
260     if (--keymap->refcnt > 0)
261         return;
262
263     XkbcFreeKeyboard(keymap);
264 }