Change all 'xkb' xkb_keymap names to 'keymap'
[profile/ivi/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(const struct xkb_component_names * ktcsg)
38 {
39     XkbFile *keycodes, *types, *compat, *symbols;
40     IncludeStmt *inc;
41
42     inc = IncludeCreate(ktcsg->keycodes, MergeDefault);
43     keycodes = CreateXKBFile(XkmKeyNamesIndex, NULL, (ParseCommon *)inc, 0);
44
45     inc = IncludeCreate(ktcsg->types, MergeDefault);
46     types = CreateXKBFile(XkmTypesIndex, NULL, (ParseCommon *)inc, 0);
47     AppendStmt(&keycodes->common, &types->common);
48
49     inc = IncludeCreate(ktcsg->compat, MergeDefault);
50     compat = CreateXKBFile(XkmCompatMapIndex, NULL, (ParseCommon *)inc, 0);
51     AppendStmt(&keycodes->common, &compat->common);
52
53     inc = IncludeCreate(ktcsg->symbols, MergeDefault);
54     symbols = CreateXKBFile(XkmSymbolsIndex, NULL, (ParseCommon *)inc, 0);
55     AppendStmt(&keycodes->common, &symbols->common);
56
57     return CreateXKBFile(XkmKeymapFile,
58                          ktcsg->keymap ? ktcsg->keymap : strdup(""),
59                          &keycodes->common, 0);
60 }
61
62 static struct xkb_component_names *
63 XkbComponentsFromRules(struct xkb_context *context,
64                        const char *rules,
65                        const XkbRF_VarDefsPtr defs)
66 {
67     FILE *rulesFile = NULL;
68     char *rulesPath = NULL;
69     XkbRF_RulesPtr loaded = NULL;
70     struct xkb_component_names * names = NULL;
71     int i;
72
73     rulesFile = XkbFindFileInPath(context, rules, XkmRulesFile, &rulesPath);
74     if (!rulesFile) {
75         ERROR("could not find \"%s\" rules in XKB path\n", rules);
76         ERROR("%d include paths searched:\n",
77               xkb_context_num_include_paths(context));
78         for (i = 0; i < xkb_context_num_include_paths(context); i++)
79             ERROR("\t%s\n", xkb_context_include_path_get(context, i));
80         return NULL;
81     }
82
83     if (!(loaded = uTypedCalloc(1, XkbRF_RulesRec))) {
84         ERROR("failed to allocate XKB rules\n");
85         goto unwind_file;
86     }
87
88     if (!XkbcRF_LoadRules(rulesFile, loaded)) {
89         ERROR("failed to load XKB rules \"%s\"\n", rulesPath);
90         goto unwind_file;
91     }
92
93     if (!(names = uTypedCalloc(1, struct xkb_component_names))) {
94         ERROR("failed to allocate XKB components\n");
95         goto unwind_file;
96     }
97
98     if (!XkbcRF_GetComponents(loaded, defs, names)) {
99         free(names->keymap);
100         free(names->keycodes);
101         free(names->types);
102         free(names->compat);
103         free(names->symbols);
104         free(names);
105         names = NULL;
106         ERROR("no components returned from XKB rules \"%s\"\n", rulesPath);
107     }
108
109 unwind_file:
110     XkbcRF_Free(loaded);
111     if (rulesFile)
112         fclose(rulesFile);
113     free(rulesPath);
114     return names;
115 }
116
117 _X_EXPORT struct xkb_keymap *
118 xkb_map_new_from_names(struct xkb_context *context,
119                        const struct xkb_rule_names *rmlvo,
120                        enum xkb_map_compile_flags flags)
121 {
122     XkbRF_VarDefsRec defs;
123     struct xkb_component_names *names;
124     struct xkb_keymap *keymap;
125
126     if (!rmlvo || ISEMPTY(rmlvo->rules) || ISEMPTY(rmlvo->layout)) {
127         ERROR("rules and layout required to generate XKB keymap\n");
128         return NULL;
129     }
130
131     defs.model = rmlvo->model;
132     defs.layout = rmlvo->layout;
133     defs.variant = rmlvo->variant;
134     defs.options = rmlvo->options;
135
136     names = XkbComponentsFromRules(context, rmlvo->rules, &defs);
137     if (!names) {
138         ERROR("failed to generate XKB components from rules \"%s\"\n",
139               rmlvo->rules);
140         return NULL;
141     }
142
143     keymap = xkb_map_new_from_kccgst(context, names, 0);
144
145     free(names->keymap);
146     free(names->keycodes);
147     free(names->types);
148     free(names->compat);
149     free(names->symbols);
150     free(names);
151
152     return keymap;
153 }
154
155 static XkbFile *
156 XkbChooseMap(XkbFile *file, const char *name)
157 {
158     XkbFile *map = file;
159
160     /* map specified? */
161     if (name) {
162         while (map) {
163             if (map->name && strcmp(map->name, name) == 0)
164                 break;
165             map = (XkbFile *) map->common.next;
166         }
167
168         if (!map)
169             ERROR("no map named \"%s\" in input file\n", name);
170     }
171     else if (file->common.next) {
172         /* look for map with XkbLC_Default flag. */
173         for (; map; map = (XkbFile *) map->common.next) {
174             if (map->flags & XkbLC_Default)
175                 break;
176         }
177
178         if (!map) {
179             map = file;
180             WARN("no map specified, but components have several\n");
181             WARN("using the first defined map, \"%s\"\n",
182                  map->name ? map->name : "");
183         }
184     }
185
186     return map;
187 }
188
189 static struct xkb_keymap *
190 compile_keymap(struct xkb_context *context, XkbFile *file)
191 {
192     XkbFile *mapToUse;
193     struct xkb_keymap *keymap = NULL;
194
195     /* Find map to use */
196     mapToUse = XkbChooseMap(file, NULL);
197     if (!mapToUse)
198         goto err;
199
200     switch (mapToUse->type) {
201     case XkmSemanticsFile:
202     case XkmLayoutFile:
203     case XkmKeymapFile:
204         break;
205     default:
206         ERROR("file type %d not handled\n", mapToUse->type);
207         goto err;
208     }
209
210     keymap = CompileKeymap(context, mapToUse);
211     if (!keymap)
212         goto err;
213
214 err:
215     FreeXKBFile(file);
216     XkbcFreeAllAtoms();
217     return keymap;
218 }
219
220 _X_EXPORT struct xkb_keymap *
221 xkb_map_new_from_kccgst(struct xkb_context *context,
222                         const struct xkb_component_names *kccgst,
223                         enum xkb_map_compile_flags flags)
224 {
225     XkbFile *file;
226
227     if (!kccgst) {
228         ERROR("no components specified\n");
229         return NULL;
230     }
231
232     if (ISEMPTY(kccgst->keycodes)) {
233         ERROR("keycodes required to generate XKB keymap\n");
234         return NULL;
235     }
236
237     if (ISEMPTY(kccgst->compat)) {
238         ERROR("compat map required to generate XKB keymap\n");
239         return NULL;
240     }
241
242     if (ISEMPTY(kccgst->types)) {
243         ERROR("types required to generate XKB keymap\n");
244         return NULL;
245     }
246
247     if (ISEMPTY(kccgst->symbols)) {
248         ERROR("symbols required to generate XKB keymap\n");
249         return NULL;
250     }
251
252     if (!(file = XkbKeymapFileFromComponents(kccgst))) {
253         ERROR("failed to generate parsed XKB file from components\n");
254         return NULL;
255     }
256
257     return compile_keymap(context, file);
258 }
259
260 _X_EXPORT struct xkb_keymap *
261 xkb_map_new_from_string(struct xkb_context *context,
262                         const char *string,
263                         enum xkb_keymap_format format,
264                         enum xkb_map_compile_flags flags)
265 {
266     XkbFile *file;
267
268     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
269         ERROR("unsupported keymap format %d\n", format);
270         return NULL;
271     }
272
273     if (!string) {
274         ERROR("no string specified to generate XKB keymap\n");
275         return NULL;
276     }
277
278     if (!XKBParseString(string, "input", &file) || !file) {
279         ERROR("failed to parse input xkb file\n");
280         return NULL;
281     }
282
283     return compile_keymap(context, file);
284 }
285
286 _X_EXPORT struct xkb_keymap *
287 xkb_map_new_from_fd(struct xkb_context *context,
288                     int fd,
289                     enum xkb_keymap_format format,
290                     enum xkb_map_compile_flags flags)
291 {
292     XkbFile *file;
293     FILE *fptr;
294
295     if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
296         ERROR("unsupported keymap format %d\n", format);
297         return NULL;
298     }
299
300     if (fd < 0) {
301         ERROR("no file specified to generate XKB keymap\n");
302         return NULL;
303     }
304
305     fptr = fdopen(fd, "r");
306     if (!fptr) {
307         ERROR("couldn't associate fd with file pointer\n");
308         return NULL;
309     }
310
311     if (!XKBParseFile(fptr, "(unknown file)", &file) || !file) {
312         ERROR("failed to parse input xkb file\n");
313         return NULL;
314     }
315
316     return compile_keymap(context, file);
317 }
318
319 _X_EXPORT struct xkb_keymap *
320 xkb_map_ref(struct xkb_keymap *keymap)
321 {
322     keymap->refcnt++;
323     return keymap;
324 }
325
326 _X_EXPORT void
327 xkb_map_unref(struct xkb_keymap *keymap)
328 {
329     if (--keymap->refcnt > 0)
330         return;
331
332     XkbcFreeKeyboard(keymap);
333 }