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