API change: Rename xkb_map_* and group -> layout
[platform/upstream/libxkbcommon.git] / src / map.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 "map.h"
54 #include "text.h"
55
56 struct xkb_keymap *
57 xkb_map_new(struct xkb_context *ctx)
58 {
59     struct xkb_keymap *keymap;
60
61     keymap = calloc(1, sizeof(*keymap));
62     if (!keymap)
63         return NULL;
64
65     keymap->refcnt = 1;
66     keymap->ctx = xkb_context_ref(ctx);
67
68     return keymap;
69 }
70
71 XKB_EXPORT struct xkb_keymap *
72 xkb_keymap_ref(struct xkb_keymap *keymap)
73 {
74     keymap->refcnt++;
75     return keymap;
76 }
77
78 XKB_EXPORT void
79 xkb_keymap_unref(struct xkb_keymap *keymap)
80 {
81     unsigned int i;
82     struct xkb_key *key;
83
84     if (!keymap || --keymap->refcnt > 0)
85         return;
86
87     for (i = 0; i < keymap->num_types; i++) {
88         free(keymap->types[i].map);
89         free(keymap->types[i].level_names);
90     }
91     free(keymap->types);
92     darray_foreach(key, keymap->keys) {
93         free(key->sym_index);
94         free(key->num_syms);
95         free(key->syms);
96         free(key->actions);
97     }
98     darray_free(keymap->keys);
99     darray_free(keymap->sym_interpret);
100     darray_free(keymap->key_aliases);
101     free(keymap->keycodes_section_name);
102     free(keymap->symbols_section_name);
103     free(keymap->types_section_name);
104     free(keymap->compat_section_name);
105     xkb_context_unref(keymap->ctx);
106     free(keymap);
107 }
108
109 /**
110  * Returns the total number of modifiers active in the keymap.
111  */
112 XKB_EXPORT xkb_mod_index_t
113 xkb_keymap_num_mods(struct xkb_keymap *keymap)
114 {
115     xkb_mod_index_t i;
116
117     for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++)
118         if (!keymap->vmod_names[i])
119             break;
120
121     /* We always have all the core modifiers (for now), plus any virtual
122      * modifiers we may have defined. */
123     return i + XKB_NUM_CORE_MODS;
124 }
125
126 /**
127  * Return the name for a given modifier.
128  */
129 XKB_EXPORT const char *
130 xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
131 {
132     const char *name;
133
134     if (idx >= xkb_map_num_mods(keymap))
135         return NULL;
136
137     /* First try to find a legacy modifier name.  If that fails, try to
138      * find a virtual mod name. */
139     name = ModIndexToName(idx);
140     if (!name)
141         name = xkb_atom_text(keymap->ctx,
142                              keymap->vmod_names[idx - XKB_NUM_CORE_MODS]);
143
144     return name;
145 }
146
147 /**
148  * Returns the index for a named modifier.
149  */
150 XKB_EXPORT xkb_mod_index_t
151 xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
152 {
153     xkb_mod_index_t i;
154     xkb_atom_t atom;
155
156     i = ModNameToIndex(name);
157     if (i != XKB_MOD_INVALID)
158         return i;
159
160     atom = xkb_atom_lookup(keymap->ctx, name);
161     if (atom == XKB_ATOM_NONE)
162         return XKB_MOD_INVALID;
163
164     for (i = 0; i < XKB_NUM_VIRTUAL_MODS; i++) {
165         if (keymap->vmod_names[i] == XKB_ATOM_NONE)
166             break;
167         if (keymap->vmod_names[i] == atom)
168             return i + XKB_NUM_CORE_MODS;
169     }
170
171     return XKB_MOD_INVALID;
172 }
173
174 /**
175  * Return the total number of active groups in the keymap.
176  */
177 XKB_EXPORT xkb_layout_index_t
178 xkb_keymap_num_layouts(struct xkb_keymap *keymap)
179 {
180     return keymap->num_groups;
181 }
182
183 /**
184  * Returns the name for a given group.
185  */
186 XKB_EXPORT const char *
187 xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
188 {
189     if (idx >= xkb_keymap_num_layouts(keymap))
190         return NULL;
191
192     return xkb_atom_text(keymap->ctx, keymap->group_names[idx]);
193 }
194
195 /**
196  * Returns the index for a named layout.
197  */
198 XKB_EXPORT xkb_layout_index_t
199 xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name)
200 {
201     xkb_layout_index_t num_groups = xkb_keymap_num_layouts(keymap);
202     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
203     xkb_layout_index_t i;
204
205     if (atom == XKB_ATOM_NONE)
206         return XKB_GROUP_INVALID;
207
208     for (i = 0; i < num_groups; i++)
209         if (keymap->group_names[i] == atom)
210             return i;
211
212     return XKB_GROUP_INVALID;
213 }
214
215 /**
216  * Returns the number of layouts active for a particular key.
217  */
218 XKB_EXPORT xkb_layout_index_t
219 xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc)
220 {
221     const struct xkb_key *key = XkbKey(keymap, kc);
222     if (!key)
223         return 0;
224
225     return key->num_groups;
226 }
227
228 /**
229  * Return the total number of active LEDs in the keymap.
230  */
231 XKB_EXPORT xkb_led_index_t
232 xkb_keymap_num_leds(struct xkb_keymap *keymap)
233 {
234     xkb_led_index_t ret = 0;
235     xkb_led_index_t i;
236
237     for (i = 0; i < XKB_NUM_INDICATORS; i++)
238         if (keymap->indicators[i].which_groups ||
239             keymap->indicators[i].which_mods ||
240             keymap->indicators[i].ctrls)
241             ret++;
242
243     return ret;
244 }
245
246 /**
247  * Returns the name for a given group.
248  */
249 XKB_EXPORT const char *
250 xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
251 {
252     if (idx >= xkb_map_num_leds(keymap))
253         return NULL;
254
255     return xkb_atom_text(keymap->ctx, keymap->indicators[idx].name);
256 }
257
258 /**
259  * Returns the index for a named group.
260  */
261 XKB_EXPORT xkb_group_index_t
262 xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
263 {
264     xkb_led_index_t num_leds = xkb_map_num_leds(keymap);
265     xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
266     xkb_led_index_t i;
267
268     if (atom == XKB_ATOM_NONE)
269         return XKB_LED_INVALID;
270
271     for (i = 0; i < num_leds; i++)
272         if (keymap->indicators[i].name == atom)
273             return i;
274
275     return XKB_LED_INVALID;
276 }
277
278 static struct xkb_kt_map_entry *
279 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
280                         xkb_group_index_t group)
281 {
282     struct xkb_key_type *type;
283     xkb_mod_mask_t active_mods;
284     unsigned int i;
285
286     type = XkbKeyType(xkb_state_get_map(state), key, group);
287     active_mods = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE);
288     active_mods &= type->mods.mask;
289
290     for (i = 0; i < type->num_entries; i++)
291         if (type->map[i].mods.mask == active_mods)
292             return &type->map[i];
293
294     return NULL;
295 }
296
297 /**
298  * Returns the level to use for the given key and state, or
299  * XKB_LEVEL_INVALID.
300  */
301 xkb_level_index_t
302 xkb_key_get_level(struct xkb_state *state, const struct xkb_key *key,
303                   xkb_group_index_t group)
304 {
305     struct xkb_kt_map_entry *entry;
306
307     /* If we don't find an explicit match the default is 0. */
308     entry = get_entry_for_key_state(state, key, group);
309     if (!entry)
310         return 0;
311
312     return entry->level;
313 }
314
315 /**
316  * Returns the group to use for the given key and state, taking
317  * wrapping/clamping/etc into account, or XKB_GROUP_INVALID.
318  */
319 xkb_group_index_t
320 xkb_key_get_group(struct xkb_state *state, const struct xkb_key *key)
321 {
322     xkb_group_index_t ret = xkb_state_serialize_group(state,
323                                                       XKB_STATE_EFFECTIVE);
324
325     if (key->num_groups == 0)
326         return XKB_GROUP_INVALID;
327
328     if (ret < key->num_groups)
329         return ret;
330
331     switch (key->out_of_range_group_action) {
332     case RANGE_REDIRECT:
333         ret = key->out_of_range_group_number;
334         if (ret >= key->num_groups)
335             ret = 0;
336         break;
337
338     case RANGE_SATURATE:
339         ret = key->num_groups - 1;
340         break;
341
342     case RANGE_WRAP:
343     default:
344         ret %= key->num_groups;
345         break;
346     }
347
348     return ret;
349 }
350
351 /**
352  * As below, but takes an explicit group/level rather than state.
353  */
354 int
355 xkb_key_get_syms_by_level(struct xkb_keymap *keymap,
356                           const struct xkb_key *key,
357                           xkb_group_index_t group, xkb_level_index_t level,
358                           const xkb_keysym_t **syms_out)
359 {
360     int num_syms;
361
362     if (group >= key->num_groups)
363         goto err;
364     if (level >= XkbKeyGroupWidth(keymap, key, group))
365         goto err;
366
367     num_syms = XkbKeyNumSyms(key, group, level);
368     if (num_syms == 0)
369         goto err;
370
371     *syms_out = XkbKeySymEntry(key, group, level);
372     return num_syms;
373
374 err:
375     *syms_out = NULL;
376     return 0;
377 }
378
379 /**
380  * Provides the symbols to use for the given key and state.  Returns the
381  * number of symbols pointed to in syms_out.
382  */
383 XKB_EXPORT int
384 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
385                        const xkb_keysym_t **syms_out)
386 {
387     struct xkb_keymap *keymap = xkb_state_get_map(state);
388     xkb_group_index_t group;
389     xkb_level_index_t level;
390     const struct xkb_key *key = XkbKey(keymap, kc);
391     if (!key)
392         return -1;
393
394     group = xkb_key_get_group(state, key);
395     if (group == XKB_GROUP_INVALID)
396         goto err;
397
398     level = xkb_key_get_level(state, key, group);
399     if (level == XKB_LEVEL_INVALID)
400         goto err;
401
402     return xkb_key_get_syms_by_level(keymap, key, group, level, syms_out);
403
404 err:
405     *syms_out = NULL;
406     return 0;
407 }
408
409 /**
410  * Simple boolean specifying whether or not the key should repeat.
411  */
412 XKB_EXPORT int
413 xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
414 {
415     const struct xkb_key *key = XkbKey(keymap, kc);
416     if (!key)
417         return 0;
418
419     return key->repeats;
420 }
421
422 static xkb_mod_mask_t
423 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
424 {
425     struct xkb_kt_map_entry *entry;
426     xkb_group_index_t group;
427
428     group = xkb_key_get_group(state, key);
429     if (group == XKB_GROUP_INVALID)
430         return 0;
431
432     entry = get_entry_for_key_state(state, key, group);
433     if (!entry)
434         return 0;
435
436     return entry->mods.mask & ~entry->preserve.mask;
437 }
438
439 /**
440  * Tests to see if a modifier is used up by our translation of a
441  * keycode to keysyms, taking note of the current modifier state and
442  * the appropriate key type's preserve information, if any. This allows
443  * the user to mask out the modifier in later processing of the
444  * modifiers, e.g. when implementing hot keys or accelerators.
445  *
446  * See also, for example:
447  * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
448  * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
449  *   from gtk+.
450  */
451 XKB_EXPORT int
452 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
453                                 xkb_mod_index_t idx)
454 {
455     const struct xkb_key *key = XkbKey(xkb_state_get_map(state), kc);
456     if (!key)
457         return 0;
458
459     return !!((1 << idx) & key_get_consumed(state, key));
460 }
461
462 /**
463  * Calculates which modifiers should be consumed during key processing,
464  * and returns the mask with all these modifiers removed.  e.g. if
465  * given a state of Alt and Shift active for a two-level alphabetic
466  * key containing plus and equal on the first and second level
467  * respectively, will return a mask of only Alt, as Shift has been
468  * consumed by the type handling.
469  */
470 XKB_EXPORT xkb_mod_mask_t
471 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
472                                    xkb_mod_mask_t mask)
473 {
474     const struct xkb_key *key = XkbKey(xkb_state_get_map(state), kc);
475     if (!key)
476         return 0;
477
478     return mask & ~key_get_consumed(state, key);
479 }