• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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