2 Copyright 2009 Dan Nicholson
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
27 #include "xkbcomp-priv.h"
29 #include "parseutils.h"
31 /* Global warning level */
32 unsigned int warningLevel = 0;
34 #define ISEMPTY(str) (!(str) || (strlen(str) == 0))
37 keymap_file_from_components(struct xkb_context *ctx,
38 const struct xkb_component_names *ktcsg)
40 XkbFile *keycodes, *types, *compat, *symbols;
43 inc = IncludeCreate(ktcsg->keycodes, MERGE_DEFAULT);
44 keycodes = CreateXKBFile(ctx, FILE_TYPE_KEYCODES, NULL,
45 (ParseCommon *)inc, 0);
47 inc = IncludeCreate(ktcsg->types, MERGE_DEFAULT);
48 types = CreateXKBFile(ctx, FILE_TYPE_TYPES, NULL,
49 (ParseCommon *)inc, 0);
50 AppendStmt(&keycodes->common, &types->common);
52 inc = IncludeCreate(ktcsg->compat, MERGE_DEFAULT);
53 compat = CreateXKBFile(ctx, FILE_TYPE_COMPAT, NULL,
54 (ParseCommon *)inc, 0);
55 AppendStmt(&keycodes->common, &compat->common);
57 inc = IncludeCreate(ktcsg->symbols, MERGE_DEFAULT);
58 symbols = CreateXKBFile(ctx, FILE_TYPE_SYMBOLS, NULL,
59 (ParseCommon *)inc, 0);
60 AppendStmt(&keycodes->common, &symbols->common);
62 return CreateXKBFile(ctx, FILE_TYPE_KEYMAP, strdup(""),
63 &keycodes->common, 0);
67 * Compile the given file and store the output in keymap.
68 * @param file A list of XkbFiles, each denoting one type (e.g.
69 * FILE_TYPE_KEYCODES, etc.)
71 static struct xkb_keymap *
72 compile_keymap(struct xkb_context *ctx, XkbFile *file)
76 enum xkb_file_type main_type;
77 const char *main_name;
78 struct xkb_keymap *keymap = XkbcAllocKeyboard(ctx);
84 } sections = { NULL };
89 main_type = file->type;
90 main_name = file->name ? file->name : "(unnamed)";
93 * Other aggregate file types are converted to FILE_TYPE_KEYMAP
96 if (main_type != FILE_TYPE_KEYMAP) {
97 ERROR("Cannot compile a %s file alone into a keymap\n",
98 XkbcFileTypeText(main_type));
102 /* Check for duplicate entries in the input file */
103 for (file = (XkbFile *)file->defs; file;
104 file = (XkbFile *)file->common.next) {
105 if (have & file->type) {
106 ERROR("More than one %s section in a %s file\n",
107 XkbcFileTypeText(file->type), XkbcFileTypeText(main_type));
108 ACTION("All sections after the first ignored\n");
111 else if (!(file->type & LEGAL_FILE_TYPES)) {
112 ERROR("Cannot define %s in a %s file\n",
113 XkbcFileTypeText(file->type), XkbcFileTypeText(main_type));
117 switch (file->type) {
118 case FILE_TYPE_KEYCODES:
119 sections.keycodes = file;
121 case FILE_TYPE_TYPES:
122 sections.types = file;
124 case FILE_TYPE_SYMBOLS:
125 sections.symbols = file;
127 case FILE_TYPE_COMPAT:
128 sections.compat = file;
134 if (!file->topName || strcmp(file->topName, main_name) != 0) {
136 file->topName = strdup(main_name);
142 if (REQUIRED_FILE_TYPES & (~have)) {
143 enum xkb_file_type bit;
144 enum xkb_file_type missing;
146 missing = REQUIRED_FILE_TYPES & (~have);
148 for (bit = 1; missing != 0; bit <<= 1) {
150 ERROR("Required section %s missing from keymap\n",
151 XkbcFileTypeText(bit));
159 /* compile the sections we have in the file one-by-one, or fail. */
160 if (sections.keycodes == NULL ||
161 !CompileKeycodes(sections.keycodes, keymap, MERGE_OVERRIDE))
163 ERROR("Failed to compile keycodes\n");
166 if (sections.types == NULL ||
167 !CompileKeyTypes(sections.types, keymap, MERGE_OVERRIDE))
169 ERROR("Failed to compile key types\n");
172 if (sections.compat == NULL ||
173 !CompileCompatMap(sections.compat, keymap, MERGE_OVERRIDE))
175 ERROR("Failed to compile compat map\n");
178 if (sections.symbols == NULL ||
179 !CompileSymbols(sections.symbols, keymap, MERGE_OVERRIDE))
181 ERROR("Failed to compile symbols\n");
185 ok = UpdateModifiersFromCompat(keymap);
193 ACTION("Failed to compile keymap\n");
194 xkb_map_unref(keymap);
200 xkb_map_new_from_kccgst(struct xkb_context *ctx,
201 const struct xkb_component_names *kccgst,
202 enum xkb_map_compile_flags flags)
207 ERROR("no components specified\n");
211 if (ISEMPTY(kccgst->keycodes)) {
212 ERROR("keycodes required to generate XKB keymap\n");
216 if (ISEMPTY(kccgst->compat)) {
217 ERROR("compat map required to generate XKB keymap\n");
221 if (ISEMPTY(kccgst->types)) {
222 ERROR("types required to generate XKB keymap\n");
226 if (ISEMPTY(kccgst->symbols)) {
227 ERROR("symbols required to generate XKB keymap\n");
231 file = keymap_file_from_components(ctx, kccgst);
233 ERROR("failed to generate parsed XKB file from components\n");
237 return compile_keymap(ctx, file);
240 _X_EXPORT struct xkb_keymap *
241 xkb_map_new_from_names(struct xkb_context *ctx,
242 const struct xkb_rule_names *rmlvo,
243 enum xkb_map_compile_flags flags)
245 struct xkb_component_names *kkctgs;
246 struct xkb_keymap *keymap;
248 if (!rmlvo || ISEMPTY(rmlvo->rules) || ISEMPTY(rmlvo->layout)) {
249 ERROR("rules and layout required to generate XKB keymap\n");
253 kkctgs = xkb_components_from_rules(ctx, rmlvo);
255 ERROR("failed to generate XKB components from rules \"%s\"\n",
260 keymap = xkb_map_new_from_kccgst(ctx, kkctgs, 0);
262 free(kkctgs->keycodes);
264 free(kkctgs->compat);
265 free(kkctgs->symbols);
271 _X_EXPORT struct xkb_keymap *
272 xkb_map_new_from_string(struct xkb_context *ctx,
274 enum xkb_keymap_format format,
275 enum xkb_map_compile_flags flags)
279 if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
280 ERROR("unsupported keymap format %d\n", format);
285 ERROR("no string specified to generate XKB keymap\n");
289 if (!XKBParseString(ctx, string, "input", &file)) {
290 ERROR("failed to parse input xkb file\n");
294 return compile_keymap(ctx, file);
297 _X_EXPORT struct xkb_keymap *
298 xkb_map_new_from_file(struct xkb_context *ctx,
300 enum xkb_keymap_format format,
301 enum xkb_map_compile_flags flags)
305 if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
306 ERROR("unsupported keymap format %d\n", format);
311 ERROR("no file specified to generate XKB keymap\n");
315 if (!XKBParseFile(ctx, file, "(unknown file)", &xkb_file)) {
316 ERROR("failed to parse input xkb file\n");
320 return compile_keymap(ctx, xkb_file);
323 _X_EXPORT struct xkb_keymap *
324 xkb_map_ref(struct xkb_keymap *keymap)
331 xkb_map_unref(struct xkb_keymap *keymap)
333 if (--keymap->refcnt > 0)
336 XkbcFreeKeyboard(keymap);