*
* ********************************************************/
-#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;
/**
* 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;
* 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)));
+}