Fix some cppcheck warnings
[platform/upstream/libxkbcommon.git] / src / keymap.c
1 /**
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2012 Ran Benita <ran234@gmail.com>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Author: Daniel Stone <daniel@fooishbar.org>
25  */
26
27 /************************************************************
28  * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
29  *
30  * Permission to use, copy, modify, and distribute this
31  * software and its documentation for any purpose and without
32  * fee is hereby granted, provided that the above copyright
33  * notice appear in all copies and that both that copyright
34  * notice and this permission notice appear in supporting
35  * documentation, and that the name of Silicon Graphics not be
36  * used in advertising or publicity pertaining to distribution
37  * of the software without specific prior written permission.
38  * Silicon Graphics makes no representation about the suitability
39  * of this software for any purpose. It is provided "as is"
40  * without any express or implied warranty.
41  *
42  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
43  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
44  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
45  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
46  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
47  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
48  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
49  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
50  *
51  * ********************************************************/
52
53 #include "keymap.h"
54 #include "text.h"
55
56 static void
57 update_builtin_keymap_fields(struct xkb_keymap *keymap)
58 {
59     struct xkb_context *ctx = keymap->ctx;
60
61     /*
62      * Add predefined (AKA real, core, X11) modifiers.
63      * The order is important!
64      */
65     darray_appends_t(keymap->mods, struct xkb_mod,
66         { .name = xkb_atom_intern_literal(ctx, "Shift"),   .type = MOD_REAL },
67         { .name = xkb_atom_intern_literal(ctx, "Lock"),    .type = MOD_REAL },
68         { .name = xkb_atom_intern_literal(ctx, "Control"), .type = MOD_REAL },
69         { .name = xkb_atom_intern_literal(ctx, "Mod1"),    .type = MOD_REAL },
70         { .name = xkb_atom_intern_literal(ctx, "Mod2"),    .type = MOD_REAL },
71         { .name = xkb_atom_intern_literal(ctx, "Mod3"),    .type = MOD_REAL },
72         { .name = xkb_atom_intern_literal(ctx, "Mod4"),    .type = MOD_REAL },
73         { .name = xkb_atom_intern_literal(ctx, "Mod5"),    .type = MOD_REAL });
74 }
75
76 static struct xkb_keymap *
77 xkb_keymap_new(struct xkb_context *ctx,
78                enum xkb_keymap_format format,
79                enum xkb_keymap_compile_flags flags)
80 {
81     struct xkb_keymap *keymap;
82
83     keymap = calloc(1, sizeof(*keymap));
84     if (!keymap)
85         return NULL;
86
87     keymap->refcnt = 1;
88     keymap->ctx = xkb_context_ref(ctx);
89
90     keymap->format = format;
91     keymap->flags = flags;
92
93     update_builtin_keymap_fields(keymap);
94
95     return keymap;
96 }
97
98 XKB_EXPORT struct xkb_keymap *
99 xkb_keymap_ref(struct xkb_keymap *keymap)
100 {
101     keymap->refcnt++;
102     return keymap;
103 }
104
105 XKB_EXPORT void
106 xkb_keymap_unref(struct xkb_keymap *keymap)
107 {
108     if (!keymap || --keymap->refcnt > 0)
109         return;
110
111     if (keymap->keys) {
112         struct xkb_key *key;
113         xkb_foreach_key(key, keymap) {
114             if (key->groups) {
115                 for (unsigned i = 0; i < key->num_groups; i++) {
116                     if (key->groups[i].levels) {
117                         for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++)
118                             if (key->groups[i].levels[j].num_syms > 1)
119                                 free(key->groups[i].levels[j].u.syms);
120                         free(key->groups[i].levels);
121                     }
122                 }
123                 free(key->groups);
124             }
125         }
126         free(keymap->keys);
127     }
128     if (keymap->types) {
129         for (unsigned i = 0; i < keymap->num_types; i++) {
130             free(keymap->types[i].entries);
131             free(keymap->types[i].level_names);
132         }
133         free(keymap->types);
134     }
135     free(keymap->sym_interprets);
136     free(keymap->key_aliases);
137     free(keymap->group_names);
138     darray_free(keymap->mods);
139     darray_free(keymap->leds);
140     free(keymap->keycodes_section_name);
141     free(keymap->symbols_section_name);
142     free(keymap->types_section_name);
143     free(keymap->compat_section_name);
144     xkb_context_unref(keymap->ctx);
145     free(keymap);
146 }
147
148 static const struct xkb_keymap_format_ops *
149 get_keymap_format_ops(enum xkb_keymap_format format)
150 {
151     static const struct xkb_keymap_format_ops *keymap_format_ops[] = {
152         [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
153     };
154
155     if ((int) format < 0 || (int) format >= ARRAY_SIZE(keymap_format_ops))
156         return NULL;
157
158     return keymap_format_ops[format];
159 }
160
161 XKB_EXPORT struct xkb_keymap *
162 xkb_keymap_new_from_names(struct xkb_context *ctx,
163                           const struct xkb_rule_names *rmlvo_in,
164                           enum xkb_keymap_compile_flags flags)
165 {
166     struct xkb_keymap *keymap;
167     struct xkb_rule_names rmlvo;
168     const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
169     const struct xkb_keymap_format_ops *ops;
170
171     ops = get_keymap_format_ops(format);
172     if (!ops || !ops->keymap_new_from_names) {
173         log_err_func(ctx, "unsupported keymap format: %d\n", format);
174         return NULL;
175     }
176
177     if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
178         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
179         return NULL;
180     }
181
182     if (rmlvo_in)
183         rmlvo = *rmlvo_in;
184     else
185         memset(&rmlvo, 0, sizeof(rmlvo));
186
187     if (isempty(rmlvo.rules))
188         rmlvo.rules = xkb_context_get_default_rules(ctx);
189     if (isempty(rmlvo.model))
190         rmlvo.model = xkb_context_get_default_model(ctx);
191     /* Layout and variant are tied together, so don't try to use one from
192      * the caller and one from the environment. */
193     if (isempty(rmlvo.layout)) {
194         rmlvo.layout = xkb_context_get_default_layout(ctx);
195         rmlvo.variant = xkb_context_get_default_variant(ctx);
196     }
197     /* Options can be empty, so respect that if passed in. */
198     if (rmlvo.options == NULL)
199         rmlvo.options = xkb_context_get_default_options(ctx);
200
201     keymap = xkb_keymap_new(ctx, format, flags);
202     if (!keymap)
203         return NULL;
204
205     if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
206         xkb_keymap_unref(keymap);
207         return NULL;
208     }
209
210     return keymap;
211 }
212
213 XKB_EXPORT struct xkb_keymap *
214 xkb_keymap_new_from_string(struct xkb_context *ctx,
215                            const char *string,
216                            enum xkb_keymap_format format,
217                            enum xkb_keymap_compile_flags flags)
218 {
219     return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
220                                       format, flags);
221 }
222
223 XKB_EXPORT struct xkb_keymap *
224 xkb_keymap_new_from_buffer(struct xkb_context *ctx,
225                            const char *buffer, size_t length,
226                            enum xkb_keymap_format format,
227                            enum xkb_keymap_compile_flags flags)
228 {
229     struct xkb_keymap *keymap;
230     const struct xkb_keymap_format_ops *ops;
231
232     ops = get_keymap_format_ops(format);
233     if (!ops || !ops->keymap_new_from_string) {
234         log_err_func(ctx, "unsupported keymap format: %d\n", format);
235         return NULL;
236     }
237
238     if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
239         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
240         return NULL;
241     }
242
243     if (!buffer) {
244         log_err_func1(ctx, "no buffer specified\n");
245         return NULL;
246     }
247
248     keymap = xkb_keymap_new(ctx, format, flags);
249     if (!keymap)
250         return NULL;
251
252     if (!ops->keymap_new_from_string(keymap, buffer, length)) {
253         xkb_keymap_unref(keymap);
254         return NULL;
255     }
256
257     return keymap;
258 }
259
260 XKB_EXPORT struct xkb_keymap *
261 xkb_keymap_new_from_file(struct xkb_context *ctx,
262                          FILE *file,
263                          enum xkb_keymap_format format,
264                          enum xkb_keymap_compile_flags flags)
265 {
266     struct xkb_keymap *keymap;
267     const struct xkb_keymap_format_ops *ops;
268
269     ops = get_keymap_format_ops(format);
270     if (!ops || !ops->keymap_new_from_file) {
271         log_err_func(ctx, "unsupported keymap format: %d\n", format);
272         return NULL;
273     }
274
275     if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
276         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
277         return NULL;
278     }
279
280     if (!file) {
281         log_err_func1(ctx, "no file specified\n");
282         return NULL;
283     }
284
285     keymap = xkb_keymap_new(ctx, format, flags);
286     if (!keymap)
287         return NULL;
288
289     if (!ops->keymap_new_from_file(keymap, file)) {
290         xkb_keymap_unref(keymap);
291         return NULL;
292     }
293
294     return keymap;
295 }
296
297 XKB_EXPORT char *
298 xkb_keymap_get_as_string(struct xkb_keymap *keymap,
299                          enum xkb_keymap_format format)
300 {
301     const struct xkb_keymap_format_ops *ops;
302
303     if (format == XKB_KEYMAP_USE_ORIGINAL_FORMAT)
304         format = keymap->format;
305
306     ops = get_keymap_format_ops(format);
307     if (!ops || !ops->keymap_get_as_string) {
308         log_err_func(keymap->ctx, "unsupported keymap format: %d\n", format);
309         return NULL;
310     }
311
312     return ops->keymap_get_as_string(keymap);
313 }
314
315 /**
316  * Returns the total number of modifiers active in the keymap.
317  */
318 XKB_EXPORT xkb_mod_index_t
319 xkb_keymap_num_mods(struct xkb_keymap *keymap)
320 {
321     return darray_size(keymap->mods);
322 }
323
324 /**
325  * Return the name for a given modifier.
326  */
327 XKB_EXPORT const char *
328 xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
329 {
330     if (idx >= darray_size(keymap->mods))
331         return NULL;
332
333     return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, idx).name);
334 }
335
336 /**
337  * Returns the index for a named modifier.
338  */
339 XKB_EXPORT xkb_mod_index_t
340 xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
341 {
342     xkb_mod_index_t i;
343     xkb_atom_t atom;
344     const struct xkb_mod *mod;
345
346     atom = xkb_atom_lookup(keymap->ctx, name);
347     if (atom == XKB_ATOM_NONE)
348         return XKB_MOD_INVALID;
349
350     darray_enumerate(i, mod, keymap->mods)
351         if (mod->name == atom)
352             return i;
353
354     return XKB_MOD_INVALID;
355 }
356
357 /**
358  * Return the total number of active groups in the keymap.
359  */
360 XKB_EXPORT xkb_layout_index_t
361 xkb_keymap_num_layouts(struct xkb_keymap *keymap)
362 {
363     return keymap->num_groups;
364 }
365
366 /**
367  * Returns the name for a given group.
368  */
369 XKB_EXPORT const char *
370 xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
371 {
372     if (idx >= keymap->num_group_names)
373         return NULL;
374
375     return xkb_atom_text(keymap->ctx, keymap->group_names[idx]);
376 }
377
378 /**
379  * Returns the index for a named layout.
380  */
381 XKB_EXPORT xkb_layout_index_t
382 xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name)
383 {
384     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
385     xkb_layout_index_t i;
386
387     if (atom == XKB_ATOM_NONE)
388         return XKB_LAYOUT_INVALID;
389
390     for (i = 0; i < keymap->num_group_names; i++)
391         if (keymap->group_names[i] == atom)
392             return i;
393
394     return XKB_LAYOUT_INVALID;
395 }
396
397 /**
398  * Returns the number of layouts active for a particular key.
399  */
400 XKB_EXPORT xkb_layout_index_t
401 xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc)
402 {
403     const struct xkb_key *key = XkbKey(keymap, kc);
404
405     if (!key)
406         return 0;
407
408     return key->num_groups;
409 }
410
411 /**
412  * Returns the number of levels active for a particular key and layout.
413  */
414 XKB_EXPORT xkb_level_index_t
415 xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc,
416                               xkb_layout_index_t layout)
417 {
418     const struct xkb_key *key = XkbKey(keymap, kc);
419
420     if (!key)
421         return 0;
422
423     layout = wrap_group_into_range(layout, key->num_groups,
424                                    key->out_of_range_group_action,
425                                    key->out_of_range_group_number);
426     if (layout == XKB_LAYOUT_INVALID)
427         return 0;
428
429     return XkbKeyGroupWidth(key, layout);
430 }
431
432 /**
433  * Return the total number of LEDs in the keymap.
434  */
435 XKB_EXPORT xkb_led_index_t
436 xkb_keymap_num_leds(struct xkb_keymap *keymap)
437 {
438     return darray_size(keymap->leds);
439 }
440
441 /**
442  * Returns the name for a given LED.
443  */
444 XKB_EXPORT const char *
445 xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
446 {
447     if (idx >= darray_size(keymap->leds))
448         return NULL;
449
450     return xkb_atom_text(keymap->ctx, darray_item(keymap->leds, idx).name);
451 }
452
453 /**
454  * Returns the index for a named LED.
455  */
456 XKB_EXPORT xkb_led_index_t
457 xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
458 {
459     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
460     xkb_led_index_t i;
461     const struct xkb_led *led;
462
463     if (atom == XKB_ATOM_NONE)
464         return XKB_LED_INVALID;
465
466     darray_enumerate(i, led, keymap->leds)
467         if (led->name == atom)
468             return i;
469
470     return XKB_LED_INVALID;
471 }
472
473 /**
474  * As below, but takes an explicit layout/level rather than state.
475  */
476 XKB_EXPORT int
477 xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
478                                  xkb_keycode_t kc,
479                                  xkb_layout_index_t layout,
480                                  xkb_level_index_t level,
481                                  const xkb_keysym_t **syms_out)
482 {
483     const struct xkb_key *key = XkbKey(keymap, kc);
484     int num_syms;
485
486     if (!key)
487         goto err;
488
489     layout = wrap_group_into_range(layout, key->num_groups,
490                                    key->out_of_range_group_action,
491                                    key->out_of_range_group_number);
492     if (layout == XKB_LAYOUT_INVALID)
493         goto err;
494
495     if (level >= XkbKeyGroupWidth(key, layout))
496         goto err;
497
498     num_syms = key->groups[layout].levels[level].num_syms;
499     if (num_syms == 0)
500         goto err;
501
502     if (num_syms == 1)
503         *syms_out = &key->groups[layout].levels[level].u.sym;
504     else
505         *syms_out = key->groups[layout].levels[level].u.syms;
506
507     return num_syms;
508
509 err:
510     *syms_out = NULL;
511     return 0;
512 }
513
514 XKB_EXPORT xkb_keycode_t
515 xkb_keymap_min_keycode(struct xkb_keymap *keymap)
516 {
517     return keymap->min_key_code;
518 }
519
520 XKB_EXPORT xkb_keycode_t
521 xkb_keymap_max_keycode(struct xkb_keymap *keymap)
522 {
523     return keymap->max_key_code;
524 }
525
526 XKB_EXPORT void
527 xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
528                         void *data)
529 {
530     struct xkb_key *key;
531
532     xkb_foreach_key(key, keymap)
533         iter(keymap, key->keycode, data);
534 }
535
536 /**
537  * Simple boolean specifying whether or not the key should repeat.
538  */
539 XKB_EXPORT int
540 xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
541 {
542     const struct xkb_key *key = XkbKey(keymap, kc);
543
544     if (!key)
545         return 0;
546
547     return key->repeats;
548 }
549
550 struct xkb_key *
551 XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases)
552 {
553     struct xkb_key *key;
554
555     xkb_foreach_key(key, keymap)
556         if (key->name == name)
557             return key;
558
559     if (use_aliases) {
560         xkb_atom_t new_name = XkbResolveKeyAlias(keymap, name);
561         if (new_name != XKB_ATOM_NONE)
562             return XkbKeyByName(keymap, new_name, false);
563     }
564
565     return NULL;
566 }
567
568 xkb_atom_t
569 XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name)
570 {
571     for (unsigned i = 0; i < keymap->num_key_aliases; i++)
572         if (keymap->key_aliases[i].alias == name)
573             return keymap->key_aliases[i].real;
574
575     return XKB_ATOM_NONE;
576 }