state: separate group wrapping/clamping to a function We'll need this function for wrapping our global effective group as well. Signed-off-by: Ran Benita <ran234@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
diff --git a/src/state.c b/src/state.c
index 41a719d..695db2c 100644
--- a/src/state.c
+++ b/src/state.c
@@ -142,41 +142,50 @@ xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
return entry->level;
}
-/**
- * Returns the layout to use for the given key and state, taking
- * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
- */
-XKB_EXPORT xkb_layout_index_t
-xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
+static xkb_layout_index_t
+wrap_group_into_range(xkb_layout_index_t group,
+ xkb_layout_index_t num_groups,
+ enum xkb_range_exceed_type out_of_range_group_action,
+ xkb_layout_index_t out_of_range_group_number)
{
- xkb_layout_index_t ret =
- xkb_state_serialize_layout(state, XKB_STATE_EFFECTIVE);
- const struct xkb_key *key = XkbKey(state->keymap, kc);
-
- if (!key || key->num_groups == 0)
+ if (num_groups == 0)
return XKB_LAYOUT_INVALID;
- if (ret < key->num_groups)
- return ret;
+ if (group < num_groups)
+ return group;
- switch (key->out_of_range_group_action) {
+ switch (out_of_range_group_action) {
case RANGE_REDIRECT:
- ret = key->out_of_range_group_number;
- if (ret >= key->num_groups)
- ret = 0;
- break;
+ if (out_of_range_group_number >= num_groups)
+ return 0;
+ return out_of_range_group_number;
case RANGE_SATURATE:
- ret = key->num_groups - 1;
- break;
+ return num_groups - 1;
case RANGE_WRAP:
default:
- ret %= key->num_groups;
- break;
+ return group % num_groups;
}
+}
- return ret;
+/**
+ * Returns the layout to use for the given key and state, taking
+ * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
+ */
+XKB_EXPORT xkb_layout_index_t
+xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
+{
+ xkb_layout_index_t group =
+ xkb_state_serialize_layout(state, XKB_STATE_EFFECTIVE);
+ const struct xkb_key *key = XkbKey(state->keymap, kc);
+
+ if (!key)
+ return XKB_LAYOUT_INVALID;
+
+ return wrap_group_into_range(group, key->num_groups,
+ key->out_of_range_group_action,
+ key->out_of_range_group_number);
}
static const union xkb_action fake = { .type = ACTION_TYPE_NONE };