2 * shl - Miscellaneous small helpers
4 * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
5 * Copyright (c) 2011 University of Tuebingen
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Miscellaneous helpers
43 #include <xkbcommon/xkbcommon.h>
45 #define SHL_EXPORT __attribute__((visibility("default")))
46 #define SHL_HAS_BITS(_bitmask, _bits) (((_bitmask) & (_bits)) == (_bits))
47 #define SHL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
48 #define SHL_ULONG_BITS (sizeof(unsigned long) * 8)
50 static inline int shl_dirent(const char *path, struct dirent **ent)
55 len = offsetof(struct dirent, d_name) +
56 pathconf(path, _PC_NAME_MAX) + 1;
65 static inline int shl_strtou(const char *input, unsigned int *output)
71 if (!input || !*input)
75 val = strtoul(input, &tmp, 0);
78 if (!tmp || *tmp || errno || (unsigned long)res != val)
86 static inline int shl_dup(void **out, const void *data, size_t size)
97 memcpy(cpy, data, size);
102 static inline bool shl_ends_with(const char *str, const char *suffix)
107 slen = strlen(suffix);
112 return !memcmp(str + len - slen, suffix, slen);
115 static inline unsigned long shl_next_pow2(unsigned long num)
123 for (i = 1; i < sizeof(unsigned long) * CHAR_BIT; i <<= 1)
124 num = num | num >> i;
129 /* This parses \arg and splits the string into a new allocated array. The array
130 * is stored in \out and is NULL terminated. Empty entries are removed from the
131 * array if \keep_empty is false. \out_num is the number of entries in the
132 * array. You can set it to NULL to not retrieve this value.
133 * \sep is the separator character which must be a valid ASCII character,
134 * otherwise this will not be UTF8 safe. */
135 static inline int shl_split_string(const char *arg, char ***out,
136 unsigned int *out_num, char sep,
140 unsigned int num, len, size, pos;
143 if (!arg || !out || !sep)
149 for (i = 0; arg[i]; ++i) {
155 if (keep_empty || len) {
162 if (len > 0 || (keep_empty && (!i || arg[i - 1] == sep))) {
167 list = malloc(sizeof(char*) * (num + 1) + size);
171 off = (void*)(((char*)list) + (sizeof(char*) * (num + 1)));
173 for (pos = 0; pos < num; ) {
175 while (arg[i] && arg[i] != sep)
179 if (list[pos] == off && !keep_empty)
192 static inline int shl_dup_array_size(char ***out, char **argv, size_t len)
195 unsigned int size, i;
201 for (i = 0; i < len; ++i) {
204 size += strlen(argv[i]);
208 size += i * sizeof(char*);
215 off = (char*)t + i * sizeof(char*);
218 for (i = 0; *argv && argv[0][i]; ++i)
228 static inline int shl_dup_array(char ***out, char **argv)
235 for (i = 0; argv[i]; ++i)
238 return shl_dup_array_size(out, argv, i);
241 /* returns true if the string-list contains only a single entry \entry */
242 static inline bool shl_string_list_is(char **list, const char *entry)
246 if (!list[0] || list[1])
248 return !strcmp(list[0], entry);
251 static inline unsigned int shl_string_list_count(char **list, bool ignore_empty)
258 for (num = 0; *list; ++list)
259 if (**list || !ignore_empty)
265 /* TODO: xkbcommon should provide these flags!
266 * We currently copy them into each library API we use so we need to keep
267 * them in sync. Currently, they're used in uterm-input and tsm-vte. */
269 SHL_SHIFT_MASK = (1 << 0),
270 SHL_LOCK_MASK = (1 << 1),
271 SHL_CONTROL_MASK = (1 << 2),
272 SHL_ALT_MASK = (1 << 3),
273 SHL_LOGO_MASK = (1 << 4),
276 static inline unsigned int shl_get_xkb_mods(struct xkb_state *state)
278 unsigned int mods = 0;
280 if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT,
281 XKB_STATE_MODS_EFFECTIVE) > 0)
282 mods |= SHL_SHIFT_MASK;
283 if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS,
284 XKB_STATE_MODS_EFFECTIVE) > 0)
285 mods |= SHL_LOCK_MASK;
286 if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL,
287 XKB_STATE_MODS_EFFECTIVE) > 0)
288 mods |= SHL_CONTROL_MASK;
289 if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT,
290 XKB_STATE_MODS_EFFECTIVE) > 0)
291 mods |= SHL_ALT_MASK;
292 if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO,
293 XKB_STATE_MODS_EFFECTIVE) > 0)
294 mods |= SHL_LOGO_MASK;
299 static inline uint32_t shl_get_ascii(struct xkb_state *state, uint32_t keycode,
300 const uint32_t *keysyms,
301 unsigned int num_keysyms)
303 struct xkb_keymap *keymap;
304 xkb_layout_index_t num_layouts;
305 xkb_layout_index_t layout;
306 xkb_level_index_t level;
307 const xkb_keysym_t *syms;
310 if (num_keysyms == 1 && keysyms[0] < 128)
313 keymap = xkb_state_get_keymap(state);
314 num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode);
316 for (layout = 0; layout < num_layouts; layout++) {
317 level = xkb_state_key_get_level(state, keycode, layout);
318 num_syms = xkb_keymap_key_get_syms_by_level(keymap, keycode,
319 layout, level, &syms);
327 return XKB_KEY_NoSymbol;
330 static inline bool shl_grab_matches(unsigned int ev_mods,
331 unsigned int ev_num_syms,
332 const uint32_t *ev_syms,
333 unsigned int grab_mods,
334 unsigned int grab_num_syms,
335 const uint32_t *grab_syms)
337 if (!SHL_HAS_BITS(ev_mods, grab_mods))
340 if (grab_num_syms != 0) {
341 if (ev_num_syms != grab_num_syms)
343 if (memcmp(ev_syms, grab_syms, sizeof(uint32_t) * ev_num_syms))
350 static inline bool shl_grab_has_match(unsigned int ev_mods,
351 unsigned int ev_num_syms,
352 const uint32_t *ev_syms,
353 unsigned int grab_num,
354 const unsigned int *grab_mods,
355 const unsigned int *grab_num_syms,
356 uint32_t **grab_syms)
360 for (i = 0; i < grab_num; ++i) {
361 if (shl_grab_matches(ev_mods, ev_num_syms, ev_syms,
362 grab_mods[i], grab_num_syms[i],
370 #endif /* SHL_MISC_H */