Run source tree through uncrustify
[platform/upstream/libxkbcommon.git] / src / map.c
index c54f227..a3dc648 100644 (file)
--- a/src/map.c
+++ b/src/map.c
  *
  * ********************************************************/
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "xkb-priv.h"
 
-#include "xkbcommon/xkbcommon.h"
-#include "XKBcommonint.h"
-#include "xkballoc.h"
-#include <X11/X.h>
+/**
+ * Returns the total number of modifiers active in the keymap.
+ */
+_X_EXPORT xkb_mod_index_t
+xkb_map_num_mods(struct xkb_keymap *keymap)
+{
+    xkb_mod_index_t i;
+
+    for (i = 0; i < XkbNumVirtualMods; i++)
+        if (!keymap->names->vmods[i])
+            break;
+
+    /* We always have all the core modifiers (for now), plus any virtual
+     * modifiers we may have defined, and then shift to one-based indexing. */
+    return i + Mod5MapIndex + 1;
+}
+
+/**
+ * Return the name for a given modifier.
+ */
+_X_EXPORT const char *
+xkb_map_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
+{
+    if (idx >= xkb_map_num_mods(keymap))
+        return NULL;
+
+    /* First try to find a legacy modifier name. */
+    switch (idx) {
+    case ShiftMapIndex:
+        return "Shift";
+    case ControlMapIndex:
+        return "Control";
+    case LockMapIndex:
+        return "Caps Lock";
+    case Mod1MapIndex:
+        return "Mod1";
+    case Mod2MapIndex:
+        return "Mod2";
+    case Mod3MapIndex:
+        return "Mod3";
+    case Mod4MapIndex:
+        return "Mod4";
+    case Mod5MapIndex:
+        return "Mod5";
+    default:
+        break;
+    }
+
+    /* If that fails, try to find a virtual mod name. */
+    return keymap->names->vmods[idx - Mod5MapIndex];
+}
+
+/**
+ * Returns the index for a named modifier.
+ */
+_X_EXPORT xkb_mod_index_t
+xkb_map_mod_get_index(struct xkb_keymap *keymap, const char *name)
+{
+    xkb_mod_index_t i;
+
+    if (strcasecmp(name, "Shift") == 0)
+        return ShiftMapIndex;
+    if (strcasecmp(name, "Control") == 0)
+        return ControlMapIndex;
+    if (strcasecmp(name, "Caps Lock") == 0)
+        return LockMapIndex;
+    if (strcasecmp(name, "Mod1") == 0)
+        return Mod1MapIndex;
+    if (strcasecmp(name, "Mod2") == 0)
+        return Mod2MapIndex;
+    if (strcasecmp(name, "Mod3") == 0)
+        return Mod3MapIndex;
+    if (strcasecmp(name, "Mod4") == 0)
+        return Mod4MapIndex;
+    if (strcasecmp(name, "Mod5") == 0)
+        return Mod5MapIndex;
+
+    for (i = 0; i < XkbNumVirtualMods && keymap->names->vmods[i]; i++) {
+        if (strcasecmp(name, keymap->names->vmods[i]) == 0)
+            return i + Mod5MapIndex;
+    }
+
+    return XKB_GROUP_INVALID;
+}
+
+/**
+ * Return the total number of active groups in the keymap.
+ */
+_X_EXPORT xkb_group_index_t
+xkb_map_num_groups(struct xkb_keymap *keymap)
+{
+    xkb_group_index_t ret = 0;
+    xkb_group_index_t i;
+
+    for (i = 0; i < XkbNumKbdGroups; i++)
+        if (keymap->compat->groups[i].mask)
+            ret++;
+
+    return ret;
+}
+
+/**
+ * Returns the name for a given group.
+ */
+_X_EXPORT const char *
+xkb_map_group_get_name(struct xkb_keymap *keymap, xkb_group_index_t idx)
+{
+    if (idx >= xkb_map_num_groups(keymap))
+        return NULL;
+
+    return keymap->names->groups[idx];
+}
+
+/**
+ * Returns the index for a named group.
+ */
+_X_EXPORT xkb_group_index_t
+xkb_map_group_get_index(struct xkb_keymap *keymap, const char *name)
+{
+    xkb_group_index_t num_groups = xkb_map_num_groups(keymap);
+    xkb_group_index_t i;
+
+    for (i = 0; i < num_groups; i++) {
+        if (strcasecmp(keymap->names->groups[i], name) == 0)
+            return i;
+    }
+
+    return XKB_GROUP_INVALID;
+}
+
+/**
+ * Returns the number of groups active for a particular key.
+ */
+_X_EXPORT xkb_group_index_t
+xkb_key_num_groups(struct xkb_keymap *keymap, xkb_keycode_t key)
+{
+    return XkbKeyNumGroups(keymap, key);
+}
+
+/**
+ * Return the total number of active LEDs in the keymap.
+ */
+_X_EXPORT xkb_led_index_t
+xkb_map_num_leds(struct xkb_keymap *keymap)
+{
+    xkb_led_index_t ret = 0;
+    xkb_led_index_t i;
+
+    for (i = 0; i < XkbNumIndicators; i++)
+        if (keymap->indicators->maps[i].which_groups ||
+            keymap->indicators->maps[i].which_mods ||
+            keymap->indicators->maps[i].ctrls)
+            ret++;
+
+    return ret;
+}
+
+/**
+ * Returns the name for a given group.
+ */
+_X_EXPORT const char *
+xkb_map_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
+{
+    if (idx >= xkb_map_num_leds(keymap))
+        return NULL;
+
+    return keymap->names->indicators[idx];
+}
+
+/**
+ * Returns the index for a named group.
+ */
+_X_EXPORT xkb_group_index_t
+xkb_map_led_get_index(struct xkb_keymap *keymap, const char *name)
+{
+    xkb_led_index_t num_leds = xkb_map_num_leds(keymap);
+    xkb_led_index_t i;
+
+    for (i = 0; i < num_leds; i++) {
+        if (strcasecmp(keymap->names->indicators[i], name) == 0)
+            return i;
+    }
+
+    return XKB_LED_INVALID;
+}
 
 /**
  * Returns the level to use for the given key and state, or -1 if invalid.
  */
-static int
-xkb_key_get_level(struct xkb_desc *xkb, struct xkb_state *state,
-                  xkb_keycode_t key, unsigned int group)
+_X_EXPORT unsigned int
+xkb_key_get_level(struct xkb_state *state, xkb_keycode_t key,
+                  unsigned int group)
 {
-    struct xkb_key_type *type = XkbKeyType(xkb, key, group);
-    unsigned int active_mods = state->mods & type->mods.mask;
-    int i;
-
-    fprintf(stderr, "get_level: %s, %d entries, mods %x, mask %x (v%x r%x)\n",
-            type->name, type->map_count, state->mods, type->mods.mask,
-            type->mods.vmods, type->mods.real_mods);
-
-    for (i = 0; i < type->map_count; i++) {
-        if (!type->map[i].active)
-            continue;
-        fprintf(stderr, "    type active, level %d (%s), mask %x (v%x r%x), active %x\n",
-                type->map[i].level, type->level_names[i], type->map[i].mods.mask,
-                type->map[i].mods.real_mods, type->map[i].mods.vmods, active_mods);
-        if (type->map[i].mods.mask == active_mods)
-            return type->map[i].level;
+    struct xkb_keymap *keymap = xkb_state_get_map(state);
+    struct xkb_key_type *type = XkbKeyType(keymap, key, group);
+    struct xkb_kt_map_entry *entry;
+    unsigned int active_mods;
+
+    active_mods = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE);
+    active_mods &= type->mods.mask;
+
+    darray_foreach(entry, type->map) {
+        if (entry->mods.mask == active_mods)
+            return entry->level;
     }
 
     return 0;
 }
 
 /**
- * Returns the group to use for the given key and state, or -1 if invalid,
- * taking wrapping/clamping/etc into account.
+ * Returns the group to use for the given key and state, taking
+ * wrapping/clamping/etc into account.
  */
-static int
-xkb_key_get_group(struct xkb_desc *xkb, struct xkb_state *state,
-                  xkb_keycode_t key)
+_X_EXPORT unsigned int
+xkb_key_get_group(struct xkb_state *state, xkb_keycode_t key)
 {
-    unsigned int info = XkbKeyGroupInfo(xkb, key);
-    unsigned int num_groups = XkbKeyNumGroups(xkb, key);
-    int ret = state->group;
+    struct xkb_keymap *keymap = xkb_state_get_map(state);
+    unsigned int info = XkbKeyGroupInfo(keymap, key);
+    unsigned int num_groups = XkbKeyNumGroups(keymap, key);
+    unsigned int ret = xkb_state_serialize_group(state, XKB_STATE_EFFECTIVE);
 
-    if (ret < XkbKeyNumGroups(xkb, key))
+    if (ret < XkbKeyNumGroups(keymap, key))
         return ret;
 
     switch (XkbOutOfRangeGroupAction(info)) {
     case XkbRedirectIntoRange:
-        ret = XkbOutOfRangeGroupInfo(info);
+        ret = XkbOutOfRangeGroupNumber(info);
         if (ret >= num_groups)
             ret = 0;
         break;
+
     case XkbClampIntoRange:
         ret = num_groups - 1;
         break;
+
     case XkbWrapIntoRange:
     default:
         ret %= num_groups;
@@ -122,15 +298,24 @@ xkb_key_get_group(struct xkb_desc *xkb, struct xkb_state *state,
 /**
  * As below, but takes an explicit group/level rather than state.
  */
-unsigned int
-xkb_key_get_syms_by_level(struct xkb_desc *xkb, xkb_keycode_t key, unsigned int group,
-                          unsigned int level, xkb_keysym_t **syms_out)
+int
+xkb_key_get_syms_by_level(struct xkb_keymap *keymap, xkb_keycode_t key,
+                          unsigned int group, unsigned int level,
+                          const xkb_keysym_t **syms_out)
 {
-    *syms_out = &(XkbKeySymEntry(xkb, key, level, group));
-    if (**syms_out == NoSymbol)
+    int num_syms;
+
+    if (group >= XkbKeyNumGroups(keymap, key))
+        goto err;
+    if (level >= XkbKeyGroupWidth(keymap, key, group))
+        goto err;
+
+    num_syms = XkbKeyNumSyms(keymap, key, group, level);
+    if (num_syms == 0)
         goto err;
 
-    return 1;
+    *syms_out = XkbKeySymEntry(keymap, key, group, level);
+    return num_syms;
 
 err:
     *syms_out = NULL;
@@ -141,26 +326,36 @@ err:
  * Provides the symbols to use for the given key and state.  Returns the
  * number of symbols pointed to in syms_out.
  */
-unsigned int
-xkb_key_get_syms(struct xkb_desc *xkb, struct xkb_state *state,
-                 xkb_keycode_t key, xkb_keysym_t **syms_out)
+_X_EXPORT int
+xkb_key_get_syms(struct xkb_state *state, xkb_keycode_t key,
+                 const xkb_keysym_t **syms_out)
 {
+    struct xkb_keymap *keymap = xkb_state_get_map(state);
     int group;
     int level;
 
-    if (!xkb || !state || key < xkb->min_key_code || key > xkb->max_key_code)
+    if (!state || key < keymap->min_key_code || key > keymap->max_key_code)
         return -1;
 
-    group = xkb_key_get_group(xkb, state, key);
+    group = xkb_key_get_group(state, key);
     if (group == -1)
         goto err;
-    level = xkb_key_get_level(xkb, state, key, group);
+    level = xkb_key_get_level(state, key, group);
     if (level == -1)
         goto err;
 
-    return xkb_key_get_syms_by_level(xkb, key, group, level, syms_out);
+    return xkb_key_get_syms_by_level(keymap, key, group, level, syms_out);
 
 err:
     *syms_out = NULL;
     return 0;
 }
+
+/**
+ * Simple boolean specifying whether or not the key should repeat.
+ */
+_X_EXPORT int
+xkb_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t key)
+{
+    return !!(keymap->ctrls->per_key_repeat[key / 8] & (1 << (key % 8)));
+}