xref: /aosp_15_r20/external/libxkbcommon/src/xkbcomp/keymap.c (revision 2b949d0487e80d67f1fda82db69e101e761f8064)
1*2b949d04SAndroid Build Coastguard Worker /*
2*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2009 Dan Nicholson
3*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2012 Intel Corporation
4*2b949d04SAndroid Build Coastguard Worker  * Copyright © 2012 Ran Benita <[email protected]>
5*2b949d04SAndroid Build Coastguard Worker  *
6*2b949d04SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*2b949d04SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*2b949d04SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*2b949d04SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*2b949d04SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*2b949d04SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*2b949d04SAndroid Build Coastguard Worker  *
13*2b949d04SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
14*2b949d04SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
15*2b949d04SAndroid Build Coastguard Worker  * Software.
16*2b949d04SAndroid Build Coastguard Worker  *
17*2b949d04SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*2b949d04SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*2b949d04SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20*2b949d04SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*2b949d04SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22*2b949d04SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*2b949d04SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
24*2b949d04SAndroid Build Coastguard Worker  *
25*2b949d04SAndroid Build Coastguard Worker  * Author: Dan Nicholson <[email protected]>
26*2b949d04SAndroid Build Coastguard Worker  *         Daniel Stone <[email protected]>
27*2b949d04SAndroid Build Coastguard Worker  *         Ran Benita <[email protected]>
28*2b949d04SAndroid Build Coastguard Worker  */
29*2b949d04SAndroid Build Coastguard Worker 
30*2b949d04SAndroid Build Coastguard Worker #include "config.h"
31*2b949d04SAndroid Build Coastguard Worker 
32*2b949d04SAndroid Build Coastguard Worker #include "xkbcomp-priv.h"
33*2b949d04SAndroid Build Coastguard Worker 
34*2b949d04SAndroid Build Coastguard Worker static void
ComputeEffectiveMask(struct xkb_keymap * keymap,struct xkb_mods * mods)35*2b949d04SAndroid Build Coastguard Worker ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
36*2b949d04SAndroid Build Coastguard Worker {
37*2b949d04SAndroid Build Coastguard Worker     mods->mask = mod_mask_get_effective(keymap, mods->mods);
38*2b949d04SAndroid Build Coastguard Worker }
39*2b949d04SAndroid Build Coastguard Worker 
40*2b949d04SAndroid Build Coastguard Worker static void
UpdateActionMods(struct xkb_keymap * keymap,union xkb_action * act,xkb_mod_mask_t modmap)41*2b949d04SAndroid Build Coastguard Worker UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
42*2b949d04SAndroid Build Coastguard Worker                  xkb_mod_mask_t modmap)
43*2b949d04SAndroid Build Coastguard Worker {
44*2b949d04SAndroid Build Coastguard Worker     switch (act->type) {
45*2b949d04SAndroid Build Coastguard Worker     case ACTION_TYPE_MOD_SET:
46*2b949d04SAndroid Build Coastguard Worker     case ACTION_TYPE_MOD_LATCH:
47*2b949d04SAndroid Build Coastguard Worker     case ACTION_TYPE_MOD_LOCK:
48*2b949d04SAndroid Build Coastguard Worker         if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
49*2b949d04SAndroid Build Coastguard Worker             act->mods.mods.mods = modmap;
50*2b949d04SAndroid Build Coastguard Worker         ComputeEffectiveMask(keymap, &act->mods.mods);
51*2b949d04SAndroid Build Coastguard Worker         break;
52*2b949d04SAndroid Build Coastguard Worker     default:
53*2b949d04SAndroid Build Coastguard Worker         break;
54*2b949d04SAndroid Build Coastguard Worker     }
55*2b949d04SAndroid Build Coastguard Worker }
56*2b949d04SAndroid Build Coastguard Worker 
57*2b949d04SAndroid Build Coastguard Worker static const struct xkb_sym_interpret default_interpret = {
58*2b949d04SAndroid Build Coastguard Worker     .sym = XKB_KEY_NoSymbol,
59*2b949d04SAndroid Build Coastguard Worker     .repeat = true,
60*2b949d04SAndroid Build Coastguard Worker     .match = MATCH_ANY_OR_NONE,
61*2b949d04SAndroid Build Coastguard Worker     .mods = 0,
62*2b949d04SAndroid Build Coastguard Worker     .virtual_mod = XKB_MOD_INVALID,
63*2b949d04SAndroid Build Coastguard Worker     .action = { .type = ACTION_TYPE_NONE },
64*2b949d04SAndroid Build Coastguard Worker };
65*2b949d04SAndroid Build Coastguard Worker 
66*2b949d04SAndroid Build Coastguard Worker /**
67*2b949d04SAndroid Build Coastguard Worker  * Find an interpretation which applies to this particular level, either by
68*2b949d04SAndroid Build Coastguard Worker  * finding an exact match for the symbol and modifier combination, or a
69*2b949d04SAndroid Build Coastguard Worker  * generic XKB_KEY_NoSymbol match.
70*2b949d04SAndroid Build Coastguard Worker  */
71*2b949d04SAndroid Build Coastguard Worker static const struct xkb_sym_interpret *
FindInterpForKey(struct xkb_keymap * keymap,const struct xkb_key * key,xkb_layout_index_t group,xkb_level_index_t level)72*2b949d04SAndroid Build Coastguard Worker FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
73*2b949d04SAndroid Build Coastguard Worker                  xkb_layout_index_t group, xkb_level_index_t level)
74*2b949d04SAndroid Build Coastguard Worker {
75*2b949d04SAndroid Build Coastguard Worker     const xkb_keysym_t *syms;
76*2b949d04SAndroid Build Coastguard Worker     int num_syms;
77*2b949d04SAndroid Build Coastguard Worker 
78*2b949d04SAndroid Build Coastguard Worker     num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group,
79*2b949d04SAndroid Build Coastguard Worker                                                 level, &syms);
80*2b949d04SAndroid Build Coastguard Worker     if (num_syms == 0)
81*2b949d04SAndroid Build Coastguard Worker         return NULL;
82*2b949d04SAndroid Build Coastguard Worker 
83*2b949d04SAndroid Build Coastguard Worker     /*
84*2b949d04SAndroid Build Coastguard Worker      * There may be multiple matchings interprets; we should always return
85*2b949d04SAndroid Build Coastguard Worker      * the most specific. Here we rely on compat.c to set up the
86*2b949d04SAndroid Build Coastguard Worker      * sym_interprets array from the most specific to the least specific,
87*2b949d04SAndroid Build Coastguard Worker      * such that when we find a match we return immediately.
88*2b949d04SAndroid Build Coastguard Worker      */
89*2b949d04SAndroid Build Coastguard Worker     for (unsigned i = 0; i < keymap->num_sym_interprets; i++) {
90*2b949d04SAndroid Build Coastguard Worker         const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
91*2b949d04SAndroid Build Coastguard Worker 
92*2b949d04SAndroid Build Coastguard Worker         xkb_mod_mask_t mods;
93*2b949d04SAndroid Build Coastguard Worker         bool found = false;
94*2b949d04SAndroid Build Coastguard Worker 
95*2b949d04SAndroid Build Coastguard Worker         if ((num_syms > 1 || interp->sym != syms[0]) &&
96*2b949d04SAndroid Build Coastguard Worker             interp->sym != XKB_KEY_NoSymbol)
97*2b949d04SAndroid Build Coastguard Worker             continue;
98*2b949d04SAndroid Build Coastguard Worker 
99*2b949d04SAndroid Build Coastguard Worker         if (interp->level_one_only && level != 0)
100*2b949d04SAndroid Build Coastguard Worker             mods = 0;
101*2b949d04SAndroid Build Coastguard Worker         else
102*2b949d04SAndroid Build Coastguard Worker             mods = key->modmap;
103*2b949d04SAndroid Build Coastguard Worker 
104*2b949d04SAndroid Build Coastguard Worker         switch (interp->match) {
105*2b949d04SAndroid Build Coastguard Worker         case MATCH_NONE:
106*2b949d04SAndroid Build Coastguard Worker             found = !(interp->mods & mods);
107*2b949d04SAndroid Build Coastguard Worker             break;
108*2b949d04SAndroid Build Coastguard Worker         case MATCH_ANY_OR_NONE:
109*2b949d04SAndroid Build Coastguard Worker             found = (!mods || (interp->mods & mods));
110*2b949d04SAndroid Build Coastguard Worker             break;
111*2b949d04SAndroid Build Coastguard Worker         case MATCH_ANY:
112*2b949d04SAndroid Build Coastguard Worker             found = (interp->mods & mods);
113*2b949d04SAndroid Build Coastguard Worker             break;
114*2b949d04SAndroid Build Coastguard Worker         case MATCH_ALL:
115*2b949d04SAndroid Build Coastguard Worker             found = ((interp->mods & mods) == interp->mods);
116*2b949d04SAndroid Build Coastguard Worker             break;
117*2b949d04SAndroid Build Coastguard Worker         case MATCH_EXACTLY:
118*2b949d04SAndroid Build Coastguard Worker             found = (interp->mods == mods);
119*2b949d04SAndroid Build Coastguard Worker             break;
120*2b949d04SAndroid Build Coastguard Worker         }
121*2b949d04SAndroid Build Coastguard Worker 
122*2b949d04SAndroid Build Coastguard Worker         if (found)
123*2b949d04SAndroid Build Coastguard Worker             return interp;
124*2b949d04SAndroid Build Coastguard Worker     }
125*2b949d04SAndroid Build Coastguard Worker 
126*2b949d04SAndroid Build Coastguard Worker     return &default_interpret;
127*2b949d04SAndroid Build Coastguard Worker }
128*2b949d04SAndroid Build Coastguard Worker 
129*2b949d04SAndroid Build Coastguard Worker static bool
ApplyInterpsToKey(struct xkb_keymap * keymap,struct xkb_key * key)130*2b949d04SAndroid Build Coastguard Worker ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
131*2b949d04SAndroid Build Coastguard Worker {
132*2b949d04SAndroid Build Coastguard Worker     xkb_mod_mask_t vmodmap = 0;
133*2b949d04SAndroid Build Coastguard Worker     xkb_layout_index_t group;
134*2b949d04SAndroid Build Coastguard Worker     xkb_level_index_t level;
135*2b949d04SAndroid Build Coastguard Worker 
136*2b949d04SAndroid Build Coastguard Worker     /* If we've been told not to bind interps to this key, then don't. */
137*2b949d04SAndroid Build Coastguard Worker     if (key->explicit & EXPLICIT_INTERP)
138*2b949d04SAndroid Build Coastguard Worker         return true;
139*2b949d04SAndroid Build Coastguard Worker 
140*2b949d04SAndroid Build Coastguard Worker     for (group = 0; group < key->num_groups; group++) {
141*2b949d04SAndroid Build Coastguard Worker         for (level = 0; level < XkbKeyNumLevels(key, group); level++) {
142*2b949d04SAndroid Build Coastguard Worker             const struct xkb_sym_interpret *interp;
143*2b949d04SAndroid Build Coastguard Worker 
144*2b949d04SAndroid Build Coastguard Worker             interp = FindInterpForKey(keymap, key, group, level);
145*2b949d04SAndroid Build Coastguard Worker             if (!interp)
146*2b949d04SAndroid Build Coastguard Worker                 continue;
147*2b949d04SAndroid Build Coastguard Worker 
148*2b949d04SAndroid Build Coastguard Worker             /* Infer default key behaviours from the base level. */
149*2b949d04SAndroid Build Coastguard Worker             if (group == 0 && level == 0)
150*2b949d04SAndroid Build Coastguard Worker                 if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat)
151*2b949d04SAndroid Build Coastguard Worker                     key->repeats = true;
152*2b949d04SAndroid Build Coastguard Worker 
153*2b949d04SAndroid Build Coastguard Worker             if ((group == 0 && level == 0) || !interp->level_one_only)
154*2b949d04SAndroid Build Coastguard Worker                 if (interp->virtual_mod != XKB_MOD_INVALID)
155*2b949d04SAndroid Build Coastguard Worker                     vmodmap |= (1u << interp->virtual_mod);
156*2b949d04SAndroid Build Coastguard Worker 
157*2b949d04SAndroid Build Coastguard Worker             if (interp->action.type != ACTION_TYPE_NONE)
158*2b949d04SAndroid Build Coastguard Worker                 key->groups[group].levels[level].action = interp->action;
159*2b949d04SAndroid Build Coastguard Worker         }
160*2b949d04SAndroid Build Coastguard Worker     }
161*2b949d04SAndroid Build Coastguard Worker 
162*2b949d04SAndroid Build Coastguard Worker     if (!(key->explicit & EXPLICIT_VMODMAP))
163*2b949d04SAndroid Build Coastguard Worker         key->vmodmap = vmodmap;
164*2b949d04SAndroid Build Coastguard Worker 
165*2b949d04SAndroid Build Coastguard Worker     return true;
166*2b949d04SAndroid Build Coastguard Worker }
167*2b949d04SAndroid Build Coastguard Worker 
168*2b949d04SAndroid Build Coastguard Worker /**
169*2b949d04SAndroid Build Coastguard Worker  * This collects a bunch of disparate functions which was done in the server
170*2b949d04SAndroid Build Coastguard Worker  * at various points that really should've been done within xkbcomp.  Turns out
171*2b949d04SAndroid Build Coastguard Worker  * your actions and types are a lot more useful when any of your modifiers
172*2b949d04SAndroid Build Coastguard Worker  * other than Shift actually do something ...
173*2b949d04SAndroid Build Coastguard Worker  */
174*2b949d04SAndroid Build Coastguard Worker static bool
UpdateDerivedKeymapFields(struct xkb_keymap * keymap)175*2b949d04SAndroid Build Coastguard Worker UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
176*2b949d04SAndroid Build Coastguard Worker {
177*2b949d04SAndroid Build Coastguard Worker     struct xkb_key *key;
178*2b949d04SAndroid Build Coastguard Worker     struct xkb_mod *mod;
179*2b949d04SAndroid Build Coastguard Worker     struct xkb_led *led;
180*2b949d04SAndroid Build Coastguard Worker     unsigned int i, j;
181*2b949d04SAndroid Build Coastguard Worker 
182*2b949d04SAndroid Build Coastguard Worker     /* Find all the interprets for the key and bind them to actions,
183*2b949d04SAndroid Build Coastguard Worker      * which will also update the vmodmap. */
184*2b949d04SAndroid Build Coastguard Worker     xkb_keys_foreach(key, keymap)
185*2b949d04SAndroid Build Coastguard Worker         if (!ApplyInterpsToKey(keymap, key))
186*2b949d04SAndroid Build Coastguard Worker             return false;
187*2b949d04SAndroid Build Coastguard Worker 
188*2b949d04SAndroid Build Coastguard Worker     /* Update keymap->mods, the virtual -> real mod mapping. */
189*2b949d04SAndroid Build Coastguard Worker     xkb_keys_foreach(key, keymap)
190*2b949d04SAndroid Build Coastguard Worker         xkb_mods_enumerate(i, mod, &keymap->mods)
191*2b949d04SAndroid Build Coastguard Worker             if (key->vmodmap & (1u << i))
192*2b949d04SAndroid Build Coastguard Worker                 mod->mapping |= key->modmap;
193*2b949d04SAndroid Build Coastguard Worker 
194*2b949d04SAndroid Build Coastguard Worker     /* Now update the level masks for all the types to reflect the vmods. */
195*2b949d04SAndroid Build Coastguard Worker     for (i = 0; i < keymap->num_types; i++) {
196*2b949d04SAndroid Build Coastguard Worker         ComputeEffectiveMask(keymap, &keymap->types[i].mods);
197*2b949d04SAndroid Build Coastguard Worker 
198*2b949d04SAndroid Build Coastguard Worker         for (j = 0; j < keymap->types[i].num_entries; j++) {
199*2b949d04SAndroid Build Coastguard Worker             ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods);
200*2b949d04SAndroid Build Coastguard Worker             ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve);
201*2b949d04SAndroid Build Coastguard Worker         }
202*2b949d04SAndroid Build Coastguard Worker     }
203*2b949d04SAndroid Build Coastguard Worker 
204*2b949d04SAndroid Build Coastguard Worker     /* Update action modifiers. */
205*2b949d04SAndroid Build Coastguard Worker     xkb_keys_foreach(key, keymap)
206*2b949d04SAndroid Build Coastguard Worker         for (i = 0; i < key->num_groups; i++)
207*2b949d04SAndroid Build Coastguard Worker             for (j = 0; j < XkbKeyNumLevels(key, i); j++)
208*2b949d04SAndroid Build Coastguard Worker                 UpdateActionMods(keymap, &key->groups[i].levels[j].action,
209*2b949d04SAndroid Build Coastguard Worker                                  key->modmap);
210*2b949d04SAndroid Build Coastguard Worker 
211*2b949d04SAndroid Build Coastguard Worker     /* Update vmod -> led maps. */
212*2b949d04SAndroid Build Coastguard Worker     xkb_leds_foreach(led, keymap)
213*2b949d04SAndroid Build Coastguard Worker         ComputeEffectiveMask(keymap, &led->mods);
214*2b949d04SAndroid Build Coastguard Worker 
215*2b949d04SAndroid Build Coastguard Worker     /* Find maximum number of groups out of all keys in the keymap. */
216*2b949d04SAndroid Build Coastguard Worker     xkb_keys_foreach(key, keymap)
217*2b949d04SAndroid Build Coastguard Worker         keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
218*2b949d04SAndroid Build Coastguard Worker 
219*2b949d04SAndroid Build Coastguard Worker     return true;
220*2b949d04SAndroid Build Coastguard Worker }
221*2b949d04SAndroid Build Coastguard Worker 
222*2b949d04SAndroid Build Coastguard Worker typedef bool (*compile_file_fn)(XkbFile *file,
223*2b949d04SAndroid Build Coastguard Worker                                 struct xkb_keymap *keymap,
224*2b949d04SAndroid Build Coastguard Worker                                 enum merge_mode merge);
225*2b949d04SAndroid Build Coastguard Worker 
226*2b949d04SAndroid Build Coastguard Worker static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
227*2b949d04SAndroid Build Coastguard Worker     [FILE_TYPE_KEYCODES] = CompileKeycodes,
228*2b949d04SAndroid Build Coastguard Worker     [FILE_TYPE_TYPES] = CompileKeyTypes,
229*2b949d04SAndroid Build Coastguard Worker     [FILE_TYPE_COMPAT] = CompileCompatMap,
230*2b949d04SAndroid Build Coastguard Worker     [FILE_TYPE_SYMBOLS] = CompileSymbols,
231*2b949d04SAndroid Build Coastguard Worker };
232*2b949d04SAndroid Build Coastguard Worker 
233*2b949d04SAndroid Build Coastguard Worker bool
CompileKeymap(XkbFile * file,struct xkb_keymap * keymap,enum merge_mode merge)234*2b949d04SAndroid Build Coastguard Worker CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
235*2b949d04SAndroid Build Coastguard Worker {
236*2b949d04SAndroid Build Coastguard Worker     bool ok;
237*2b949d04SAndroid Build Coastguard Worker     XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
238*2b949d04SAndroid Build Coastguard Worker     enum xkb_file_type type;
239*2b949d04SAndroid Build Coastguard Worker     struct xkb_context *ctx = keymap->ctx;
240*2b949d04SAndroid Build Coastguard Worker 
241*2b949d04SAndroid Build Coastguard Worker     /* Collect section files and check for duplicates. */
242*2b949d04SAndroid Build Coastguard Worker     for (file = (XkbFile *) file->defs; file;
243*2b949d04SAndroid Build Coastguard Worker          file = (XkbFile *) file->common.next) {
244*2b949d04SAndroid Build Coastguard Worker         if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
245*2b949d04SAndroid Build Coastguard Worker             file->file_type > LAST_KEYMAP_FILE_TYPE) {
246*2b949d04SAndroid Build Coastguard Worker             if (file->file_type == FILE_TYPE_GEOMETRY) {
247*2b949d04SAndroid Build Coastguard Worker                 log_vrb(ctx, 1,
248*2b949d04SAndroid Build Coastguard Worker                         "Geometry sections are not supported; ignoring\n");
249*2b949d04SAndroid Build Coastguard Worker             } else {
250*2b949d04SAndroid Build Coastguard Worker                 log_err(ctx, "Cannot define %s in a keymap file\n",
251*2b949d04SAndroid Build Coastguard Worker                         xkb_file_type_to_string(file->file_type));
252*2b949d04SAndroid Build Coastguard Worker             }
253*2b949d04SAndroid Build Coastguard Worker             continue;
254*2b949d04SAndroid Build Coastguard Worker         }
255*2b949d04SAndroid Build Coastguard Worker 
256*2b949d04SAndroid Build Coastguard Worker         if (files[file->file_type]) {
257*2b949d04SAndroid Build Coastguard Worker             log_err(ctx,
258*2b949d04SAndroid Build Coastguard Worker                     "More than one %s section in keymap file; "
259*2b949d04SAndroid Build Coastguard Worker                     "All sections after the first ignored\n",
260*2b949d04SAndroid Build Coastguard Worker                     xkb_file_type_to_string(file->file_type));
261*2b949d04SAndroid Build Coastguard Worker             continue;
262*2b949d04SAndroid Build Coastguard Worker         }
263*2b949d04SAndroid Build Coastguard Worker 
264*2b949d04SAndroid Build Coastguard Worker         files[file->file_type] = file;
265*2b949d04SAndroid Build Coastguard Worker     }
266*2b949d04SAndroid Build Coastguard Worker 
267*2b949d04SAndroid Build Coastguard Worker     /*
268*2b949d04SAndroid Build Coastguard Worker      * Check that all required section were provided.
269*2b949d04SAndroid Build Coastguard Worker      * Report everything before failing.
270*2b949d04SAndroid Build Coastguard Worker      */
271*2b949d04SAndroid Build Coastguard Worker     ok = true;
272*2b949d04SAndroid Build Coastguard Worker     for (type = FIRST_KEYMAP_FILE_TYPE;
273*2b949d04SAndroid Build Coastguard Worker          type <= LAST_KEYMAP_FILE_TYPE;
274*2b949d04SAndroid Build Coastguard Worker          type++) {
275*2b949d04SAndroid Build Coastguard Worker         if (files[type] == NULL) {
276*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Required section %s missing from keymap\n",
277*2b949d04SAndroid Build Coastguard Worker                     xkb_file_type_to_string(type));
278*2b949d04SAndroid Build Coastguard Worker             ok = false;
279*2b949d04SAndroid Build Coastguard Worker         }
280*2b949d04SAndroid Build Coastguard Worker     }
281*2b949d04SAndroid Build Coastguard Worker     if (!ok)
282*2b949d04SAndroid Build Coastguard Worker         return false;
283*2b949d04SAndroid Build Coastguard Worker 
284*2b949d04SAndroid Build Coastguard Worker     /* Compile sections. */
285*2b949d04SAndroid Build Coastguard Worker     for (type = FIRST_KEYMAP_FILE_TYPE;
286*2b949d04SAndroid Build Coastguard Worker          type <= LAST_KEYMAP_FILE_TYPE;
287*2b949d04SAndroid Build Coastguard Worker          type++) {
288*2b949d04SAndroid Build Coastguard Worker         log_dbg(ctx, "Compiling %s \"%s\"\n",
289*2b949d04SAndroid Build Coastguard Worker                 xkb_file_type_to_string(type), files[type]->name);
290*2b949d04SAndroid Build Coastguard Worker 
291*2b949d04SAndroid Build Coastguard Worker         ok = compile_file_fns[type](files[type], keymap, merge);
292*2b949d04SAndroid Build Coastguard Worker         if (!ok) {
293*2b949d04SAndroid Build Coastguard Worker             log_err(ctx, "Failed to compile %s\n",
294*2b949d04SAndroid Build Coastguard Worker                     xkb_file_type_to_string(type));
295*2b949d04SAndroid Build Coastguard Worker             return false;
296*2b949d04SAndroid Build Coastguard Worker         }
297*2b949d04SAndroid Build Coastguard Worker     }
298*2b949d04SAndroid Build Coastguard Worker 
299*2b949d04SAndroid Build Coastguard Worker     return UpdateDerivedKeymapFields(keymap);
300*2b949d04SAndroid Build Coastguard Worker }
301