Home | History | Annotate | Download | only in src
      1 /**
      2  * Copyright  2012 Intel Corporation
      3  * Copyright  2012 Ran Benita <ran234 (at) 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 (at) 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 < 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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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
    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 *
    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
    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
    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 *
    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
    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
    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
    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
    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 *
    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
    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
    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
    452 xkb_keymap_min_keycode(struct xkb_keymap *keymap)
    453 {
    454     return keymap->min_key_code;
    455 }
    456 
    457 XKB_EXPORT xkb_keycode_t
    458 xkb_keymap_max_keycode(struct xkb_keymap *keymap)
    459 {
    460     return keymap->max_key_code;
    461 }
    462 
    463 XKB_EXPORT void
    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
    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