expr: take xkb_mod_set instead of the entire keymap
[platform/upstream/libxkbcommon.git] / src / keymap.c
index 9c581d5..678bd01 100644 (file)
 #include "keymap.h"
 #include "text.h"
 
-static struct xkb_keymap *
-xkb_keymap_new(struct xkb_context *ctx,
-               enum xkb_keymap_format format,
-               enum xkb_keymap_compile_flags flags)
-{
-    struct xkb_keymap *keymap;
-
-    keymap = calloc(1, sizeof(*keymap));
-    if (!keymap)
-        return NULL;
-
-    keymap->refcnt = 1;
-    keymap->ctx = xkb_context_ref(ctx);
-
-    keymap->format = format;
-    keymap->flags = flags;
-
-    return keymap;
-}
-
 XKB_EXPORT struct xkb_keymap *
 xkb_keymap_ref(struct xkb_keymap *keymap)
 {
@@ -83,33 +63,37 @@ xkb_keymap_ref(struct xkb_keymap *keymap)
 XKB_EXPORT void
 xkb_keymap_unref(struct xkb_keymap *keymap)
 {
-    unsigned int i, j;
-    struct xkb_key *key;
-
     if (!keymap || --keymap->refcnt > 0)
         return;
 
     if (keymap->keys) {
+        struct xkb_key *key;
         xkb_foreach_key(key, keymap) {
-            for (i = 0; i < key->num_groups; i++) {
-                for (j = 0; j < XkbKeyGroupWidth(key, i); j++)
-                    if (key->groups[i].levels[j].num_syms > 1)
-                        free(key->groups[i].levels[j].u.syms);
-                free(key->groups[i].levels);
+            if (key->groups) {
+                for (unsigned i = 0; i < key->num_groups; i++) {
+                    if (key->groups[i].levels) {
+                        for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++)
+                            if (key->groups[i].levels[j].num_syms > 1)
+                                free(key->groups[i].levels[j].u.syms);
+                        free(key->groups[i].levels);
+                    }
+                }
+                free(key->groups);
             }
-            free(key->groups);
         }
         free(keymap->keys);
     }
-    for (i = 0; i < keymap->num_types; i++) {
-        free(keymap->types[i].map);
-        free(keymap->types[i].level_names);
+    if (keymap->types) {
+        for (unsigned i = 0; i < keymap->num_types; i++) {
+            free(keymap->types[i].entries);
+            free(keymap->types[i].level_names);
+        }
+        free(keymap->types);
     }
-    free(keymap->types);
-    darray_free(keymap->sym_interprets);
-    darray_free(keymap->key_aliases);
+    free(keymap->sym_interprets);
+    free(keymap->key_aliases);
     free(keymap->group_names);
-    darray_free(keymap->mods);
+    darray_free(keymap->mods.mods);
     darray_free(keymap->leds);
     free(keymap->keycodes_section_name);
     free(keymap->symbols_section_name);
@@ -126,10 +110,10 @@ get_keymap_format_ops(enum xkb_keymap_format format)
         [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
     };
 
-    if ((int) format < 0 || (int) format >= ARRAY_SIZE(keymap_format_ops))
+    if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
         return NULL;
 
-    return keymap_format_ops[format];
+    return keymap_format_ops[(int) format];
 }
 
 XKB_EXPORT struct xkb_keymap *
@@ -148,23 +132,21 @@ xkb_keymap_new_from_names(struct xkb_context *ctx,
         return NULL;
     }
 
-    if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
+    if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
         return NULL;
     }
 
-    rmlvo = *rmlvo_in;
-    if (isempty(rmlvo.rules))
-        rmlvo.rules = DEFAULT_XKB_RULES;
-    if (isempty(rmlvo.model))
-        rmlvo.model = DEFAULT_XKB_MODEL;
-    if (isempty(rmlvo.layout))
-        rmlvo.layout = DEFAULT_XKB_LAYOUT;
-
     keymap = xkb_keymap_new(ctx, format, flags);
     if (!keymap)
         return NULL;
 
+    if (rmlvo_in)
+        rmlvo = *rmlvo_in;
+    else
+        memset(&rmlvo, 0, sizeof(rmlvo));
+    xkb_context_sanitize_rule_names(ctx, &rmlvo);
+
     if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
         xkb_keymap_unref(keymap);
         return NULL;
@@ -179,6 +161,16 @@ xkb_keymap_new_from_string(struct xkb_context *ctx,
                            enum xkb_keymap_format format,
                            enum xkb_keymap_compile_flags flags)
 {
+    return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
+                                      format, flags);
+}
+
+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)
+{
     struct xkb_keymap *keymap;
     const struct xkb_keymap_format_ops *ops;
 
@@ -188,13 +180,13 @@ xkb_keymap_new_from_string(struct xkb_context *ctx,
         return NULL;
     }
 
-    if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
+    if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
         return NULL;
     }
 
-    if (!string) {
-        log_err_func1(ctx, "no string specified\n");
+    if (!buffer) {
+        log_err_func1(ctx, "no buffer specified\n");
         return NULL;
     }
 
@@ -202,7 +194,7 @@ xkb_keymap_new_from_string(struct xkb_context *ctx,
     if (!keymap)
         return NULL;
 
-    if (!ops->keymap_new_from_string(keymap, string)) {
+    if (!ops->keymap_new_from_string(keymap, buffer, length)) {
         xkb_keymap_unref(keymap);
         return NULL;
     }
@@ -225,7 +217,7 @@ xkb_keymap_new_from_file(struct xkb_context *ctx,
         return NULL;
     }
 
-    if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
+    if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
         return NULL;
     }
@@ -271,7 +263,7 @@ xkb_keymap_get_as_string(struct xkb_keymap *keymap,
 XKB_EXPORT xkb_mod_index_t
 xkb_keymap_num_mods(struct xkb_keymap *keymap)
 {
-    return darray_size(keymap->mods);
+    return darray_size(keymap->mods.mods);
 }
 
 /**
@@ -280,10 +272,11 @@ xkb_keymap_num_mods(struct xkb_keymap *keymap)
 XKB_EXPORT const char *
 xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
 {
-    if (idx >= darray_size(keymap->mods))
+    if (idx >= darray_size(keymap->mods.mods))
         return NULL;
 
-    return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, idx).name);
+    return xkb_atom_text(keymap->ctx,
+                         darray_item(keymap->mods.mods, idx).name);
 }
 
 /**
@@ -292,19 +285,13 @@ xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
 XKB_EXPORT xkb_mod_index_t
 xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
 {
-    xkb_mod_index_t i;
     xkb_atom_t atom;
-    const struct xkb_mod *mod;
 
     atom = xkb_atom_lookup(keymap->ctx, name);
     if (atom == XKB_ATOM_NONE)
         return XKB_MOD_INVALID;
 
-    darray_enumerate(i, mod, keymap->mods)
-        if (mod->name == atom)
-            return i;
-
-    return XKB_MOD_INVALID;
+    return XkbModNameToIndex(&keymap->mods, atom, MOD_BOTH);
 }
 
 /**
@@ -373,7 +360,7 @@ xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc,
     if (!key)
         return 0;
 
-    layout = wrap_group_into_range(layout, key->num_groups,
+    layout = XkbWrapGroupIntoRange(layout, key->num_groups,
                                    key->out_of_range_group_action,
                                    key->out_of_range_group_number);
     if (layout == XKB_LAYOUT_INVALID)
@@ -439,7 +426,7 @@ xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
     if (!key)
         goto err;
 
-    layout = wrap_group_into_range(layout, key->num_groups,
+    layout = XkbWrapGroupIntoRange(layout, key->num_groups,
                                    key->out_of_range_group_action,
                                    key->out_of_range_group_number);
     if (layout == XKB_LAYOUT_INVALID)
@@ -464,6 +451,28 @@ err:
     return 0;
 }
 
+XKB_EXPORT xkb_keycode_t
+xkb_keymap_min_keycode(struct xkb_keymap *keymap)
+{
+    return keymap->min_key_code;
+}
+
+XKB_EXPORT xkb_keycode_t
+xkb_keymap_max_keycode(struct xkb_keymap *keymap)
+{
+    return keymap->max_key_code;
+}
+
+XKB_EXPORT void
+xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
+                        void *data)
+{
+    struct xkb_key *key;
+
+    xkb_foreach_key(key, keymap)
+        iter(keymap, key->keycode, data);
+}
+
 /**
  * Simple boolean specifying whether or not the key should repeat.
  */