keymap: don't use darray in xkb_mod_set
[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 XKB_EXPORT struct xkb_keymap *
57 xkb_keymap_ref(struct xkb_keymap *keymap)
58 {
59     keymap->refcnt++;
60     return keymap;
61 }
62
63 XKB_EXPORT void
64 xkb_keymap_unref(struct xkb_keymap *keymap)
65 {
66     if (!keymap || --keymap->refcnt > 0)
67         return;
68
69     if (keymap->keys) {
70         struct xkb_key *key;
71         xkb_keys_foreach(key, keymap) {
72             if (key->groups) {
73                 for (unsigned i = 0; i < key->num_groups; i++) {
74                     if (key->groups[i].levels) {
75                         for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++)
76                             if (key->groups[i].levels[j].num_syms > 1)
77                                 free(key->groups[i].levels[j].u.syms);
78                         free(key->groups[i].levels);
79                     }
80                 }
81                 free(key->groups);
82             }
83         }
84         free(keymap->keys);
85     }
86     if (keymap->types) {
87         for (unsigned i = 0; i < keymap->num_types; i++) {
88             free(keymap->types[i].entries);
89             free(keymap->types[i].level_names);
90         }
91         free(keymap->types);
92     }
93     free(keymap->sym_interprets);
94     free(keymap->key_aliases);
95     free(keymap->group_names);
96     darray_free(keymap->leds);
97     free(keymap->keycodes_section_name);
98     free(keymap->symbols_section_name);
99     free(keymap->types_section_name);
100     free(keymap->compat_section_name);
101     xkb_context_unref(keymap->ctx);
102     free(keymap);
103 }
104
105 static const struct xkb_keymap_format_ops *
106 get_keymap_format_ops(enum xkb_keymap_format format)
107 {
108     static const struct xkb_keymap_format_ops *keymap_format_ops[] = {
109         [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
110     };
111
112     if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
113         return NULL;
114
115     return keymap_format_ops[(int) format];
116 }
117
118 XKB_EXPORT struct xkb_keymap *
119 xkb_keymap_new_from_names(struct xkb_context *ctx,
120                           const struct xkb_rule_names *rmlvo_in,
121                           enum xkb_keymap_compile_flags flags)
122 {
123     struct xkb_keymap *keymap;
124     struct xkb_rule_names rmlvo;
125     const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
126     const struct xkb_keymap_format_ops *ops;
127
128     ops = get_keymap_format_ops(format);
129     if (!ops || !ops->keymap_new_from_names) {
130         log_err_func(ctx, "unsupported keymap format: %d\n", format);
131         return NULL;
132     }
133
134     if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
135         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
136         return NULL;
137     }
138
139     keymap = xkb_keymap_new(ctx, format, flags);
140     if (!keymap)
141         return NULL;
142
143     if (rmlvo_in)
144         rmlvo = *rmlvo_in;
145     else
146         memset(&rmlvo, 0, sizeof(rmlvo));
147     xkb_context_sanitize_rule_names(ctx, &rmlvo);
148
149     if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
150         xkb_keymap_unref(keymap);
151         return NULL;
152     }
153
154     return keymap;
155 }
156
157 XKB_EXPORT struct xkb_keymap *
158 xkb_keymap_new_from_string(struct xkb_context *ctx,
159                            const char *string,
160                            enum xkb_keymap_format format,
161                            enum xkb_keymap_compile_flags flags)
162 {
163     return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
164                                       format, flags);
165 }
166
167 XKB_EXPORT struct xkb_keymap *
168 xkb_keymap_new_from_buffer(struct xkb_context *ctx,
169                            const char *buffer, size_t length,
170                            enum xkb_keymap_format format,
171                            enum xkb_keymap_compile_flags flags)
172 {
173     struct xkb_keymap *keymap;
174     const struct xkb_keymap_format_ops *ops;
175
176     ops = get_keymap_format_ops(format);
177     if (!ops || !ops->keymap_new_from_string) {
178         log_err_func(ctx, "unsupported keymap format: %d\n", format);
179         return NULL;
180     }
181
182     if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
183         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
184         return NULL;
185     }
186
187     if (!buffer) {
188         log_err_func1(ctx, "no buffer specified\n");
189         return NULL;
190     }
191
192     keymap = xkb_keymap_new(ctx, format, flags);
193     if (!keymap)
194         return NULL;
195
196     if (!ops->keymap_new_from_string(keymap, buffer, length)) {
197         xkb_keymap_unref(keymap);
198         return NULL;
199     }
200
201     return keymap;
202 }
203
204 XKB_EXPORT struct xkb_keymap *
205 xkb_keymap_new_from_file(struct xkb_context *ctx,
206                          FILE *file,
207                          enum xkb_keymap_format format,
208                          enum xkb_keymap_compile_flags flags)
209 {
210     struct xkb_keymap *keymap;
211     const struct xkb_keymap_format_ops *ops;
212
213     ops = get_keymap_format_ops(format);
214     if (!ops || !ops->keymap_new_from_file) {
215         log_err_func(ctx, "unsupported keymap format: %d\n", format);
216         return NULL;
217     }
218
219     if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
220         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
221         return NULL;
222     }
223
224     if (!file) {
225         log_err_func1(ctx, "no file specified\n");
226         return NULL;
227     }
228
229     keymap = xkb_keymap_new(ctx, format, flags);
230     if (!keymap)
231         return NULL;
232
233     if (!ops->keymap_new_from_file(keymap, file)) {
234         xkb_keymap_unref(keymap);
235         return NULL;
236     }
237
238     return keymap;
239 }
240
241 XKB_EXPORT char *
242 xkb_keymap_get_as_string(struct xkb_keymap *keymap,
243                          enum xkb_keymap_format format)
244 {
245     const struct xkb_keymap_format_ops *ops;
246
247     if (format == XKB_KEYMAP_USE_ORIGINAL_FORMAT)
248         format = keymap->format;
249
250     ops = get_keymap_format_ops(format);
251     if (!ops || !ops->keymap_get_as_string) {
252         log_err_func(keymap->ctx, "unsupported keymap format: %d\n", format);
253         return NULL;
254     }
255
256     return ops->keymap_get_as_string(keymap);
257 }
258
259 /**
260  * Returns the total number of modifiers active in the keymap.
261  */
262 XKB_EXPORT xkb_mod_index_t
263 xkb_keymap_num_mods(struct xkb_keymap *keymap)
264 {
265     return keymap->mods.num_mods;
266 }
267
268 /**
269  * Return the name for a given modifier.
270  */
271 XKB_EXPORT const char *
272 xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
273 {
274     if (idx >= keymap->mods.num_mods)
275         return NULL;
276
277     return xkb_atom_text(keymap->ctx, keymap->mods.mods[idx].name);
278 }
279
280 /**
281  * Returns the index for a named modifier.
282  */
283 XKB_EXPORT xkb_mod_index_t
284 xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
285 {
286     xkb_atom_t atom;
287
288     atom = xkb_atom_lookup(keymap->ctx, name);
289     if (atom == XKB_ATOM_NONE)
290         return XKB_MOD_INVALID;
291
292     return XkbModNameToIndex(&keymap->mods, atom, MOD_BOTH);
293 }
294
295 /**
296  * Return the total number of active groups in the keymap.
297  */
298 XKB_EXPORT xkb_layout_index_t
299 xkb_keymap_num_layouts(struct xkb_keymap *keymap)
300 {
301     return keymap->num_groups;
302 }
303
304 /**
305  * Returns the name for a given group.
306  */
307 XKB_EXPORT const char *
308 xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
309 {
310     if (idx >= keymap->num_group_names)
311         return NULL;
312
313     return xkb_atom_text(keymap->ctx, keymap->group_names[idx]);
314 }
315
316 /**
317  * Returns the index for a named layout.
318  */
319 XKB_EXPORT xkb_layout_index_t
320 xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name)
321 {
322     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
323     xkb_layout_index_t i;
324
325     if (atom == XKB_ATOM_NONE)
326         return XKB_LAYOUT_INVALID;
327
328     for (i = 0; i < keymap->num_group_names; i++)
329         if (keymap->group_names[i] == atom)
330             return i;
331
332     return XKB_LAYOUT_INVALID;
333 }
334
335 /**
336  * Returns the number of layouts active for a particular key.
337  */
338 XKB_EXPORT xkb_layout_index_t
339 xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc)
340 {
341     const struct xkb_key *key = XkbKey(keymap, kc);
342
343     if (!key)
344         return 0;
345
346     return key->num_groups;
347 }
348
349 /**
350  * Returns the number of levels active for a particular key and layout.
351  */
352 XKB_EXPORT xkb_level_index_t
353 xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc,
354                               xkb_layout_index_t layout)
355 {
356     const struct xkb_key *key = XkbKey(keymap, kc);
357
358     if (!key)
359         return 0;
360
361     layout = XkbWrapGroupIntoRange(layout, key->num_groups,
362                                    key->out_of_range_group_action,
363                                    key->out_of_range_group_number);
364     if (layout == XKB_LAYOUT_INVALID)
365         return 0;
366
367     return XkbKeyGroupWidth(key, layout);
368 }
369
370 /**
371  * Return the total number of LEDs in the keymap.
372  */
373 XKB_EXPORT xkb_led_index_t
374 xkb_keymap_num_leds(struct xkb_keymap *keymap)
375 {
376     return darray_size(keymap->leds);
377 }
378
379 /**
380  * Returns the name for a given LED.
381  */
382 XKB_EXPORT const char *
383 xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
384 {
385     if (idx >= darray_size(keymap->leds))
386         return NULL;
387
388     return xkb_atom_text(keymap->ctx, darray_item(keymap->leds, idx).name);
389 }
390
391 /**
392  * Returns the index for a named LED.
393  */
394 XKB_EXPORT xkb_led_index_t
395 xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
396 {
397     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
398     xkb_led_index_t i;
399     const struct xkb_led *led;
400
401     if (atom == XKB_ATOM_NONE)
402         return XKB_LED_INVALID;
403
404     darray_enumerate(i, led, keymap->leds)
405         if (led->name == atom)
406             return i;
407
408     return XKB_LED_INVALID;
409 }
410
411 /**
412  * As below, but takes an explicit layout/level rather than state.
413  */
414 XKB_EXPORT int
415 xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
416                                  xkb_keycode_t kc,
417                                  xkb_layout_index_t layout,
418                                  xkb_level_index_t level,
419                                  const xkb_keysym_t **syms_out)
420 {
421     const struct xkb_key *key = XkbKey(keymap, kc);
422     int num_syms;
423
424     if (!key)
425         goto err;
426
427     layout = XkbWrapGroupIntoRange(layout, key->num_groups,
428                                    key->out_of_range_group_action,
429                                    key->out_of_range_group_number);
430     if (layout == XKB_LAYOUT_INVALID)
431         goto err;
432
433     if (level >= XkbKeyGroupWidth(key, layout))
434         goto err;
435
436     num_syms = key->groups[layout].levels[level].num_syms;
437     if (num_syms == 0)
438         goto err;
439
440     if (num_syms == 1)
441         *syms_out = &key->groups[layout].levels[level].u.sym;
442     else
443         *syms_out = key->groups[layout].levels[level].u.syms;
444
445     return num_syms;
446
447 err:
448     *syms_out = NULL;
449     return 0;
450 }
451
452 XKB_EXPORT xkb_keycode_t
453 xkb_keymap_min_keycode(struct xkb_keymap *keymap)
454 {
455     return keymap->min_key_code;
456 }
457
458 XKB_EXPORT xkb_keycode_t
459 xkb_keymap_max_keycode(struct xkb_keymap *keymap)
460 {
461     return keymap->max_key_code;
462 }
463
464 XKB_EXPORT void
465 xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
466                         void *data)
467 {
468     struct xkb_key *key;
469
470     xkb_keys_foreach(key, keymap)
471         iter(keymap, key->keycode, data);
472 }
473
474 /**
475  * Simple boolean specifying whether or not the key should repeat.
476  */
477 XKB_EXPORT int
478 xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
479 {
480     const struct xkb_key *key = XkbKey(keymap, kc);
481
482     if (!key)
483         return 0;
484
485     return key->repeats;
486 }