2 * Copyright © 2012 Intel Corporation
3 * Copyright © 2012 Ran Benita
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
24 * Author: Daniel Stone <daniel@fooishbar.org>
27 #include <sys/types.h>
33 #include "xkbcommon/xkbcommon.h"
40 ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx,
41 enum xkb_log_level level,
42 const char *fmt, va_list args);
43 enum xkb_log_level log_level;
47 struct xkb_rule_names names_dflt;
49 darray(char *) includes;
50 darray(char *) failed_includes;
52 struct atom_table *atom_table;
54 /* Buffer for the *Text() functions. */
55 char text_buffer[2048];
58 unsigned int use_environment_names : 1;
62 * Append one directory to the context's include path.
65 xkb_context_include_path_append(struct xkb_context *ctx, const char *path)
75 err = stat(path, &stat_buf);
78 if (!S_ISDIR(stat_buf.st_mode))
81 #if defined(HAVE_EACCESS)
82 if (eaccess(path, R_OK | X_OK) != 0)
84 #elif defined(HAVE_EUIDACCESS)
85 if (euidaccess(path, R_OK | X_OK) != 0)
89 darray_append(ctx->includes, tmp);
93 darray_append(ctx->failed_includes, tmp);
98 * Append the default include directories to the context.
101 xkb_context_include_path_append_default(struct xkb_context *ctx)
108 ret |= xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
110 home = getenv("HOME");
113 err = asprintf(&user_path, "%s/.xkb", home);
116 ret |= xkb_context_include_path_append(ctx, user_path);
123 * Remove all entries in the context's include path.
126 xkb_context_include_path_clear(struct xkb_context *ctx)
130 darray_foreach(path, ctx->includes)
132 darray_free(ctx->includes);
134 darray_foreach(path, ctx->failed_includes)
136 darray_free(ctx->failed_includes);
140 * xkb_context_include_path_clear() + xkb_context_include_path_append_default()
143 xkb_context_include_path_reset_defaults(struct xkb_context *ctx)
145 xkb_context_include_path_clear(ctx);
146 return xkb_context_include_path_append_default(ctx);
150 * Returns the number of entries in the context's include path.
152 XKB_EXPORT unsigned int
153 xkb_context_num_include_paths(struct xkb_context *ctx)
155 return darray_size(ctx->includes);
159 xkb_context_num_failed_include_paths(struct xkb_context *ctx)
161 return darray_size(ctx->failed_includes);
165 * Returns the given entry in the context's include path, or NULL if an
166 * invalid index is passed.
168 XKB_EXPORT const char *
169 xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx)
171 if (idx >= xkb_context_num_include_paths(ctx))
174 return darray_item(ctx->includes, idx);
178 xkb_context_failed_include_path_get(struct xkb_context *ctx,
181 if (idx >= xkb_context_num_failed_include_paths(ctx))
184 return darray_item(ctx->failed_includes, idx);
188 * Take a new reference on the context.
190 XKB_EXPORT struct xkb_context *
191 xkb_context_ref(struct xkb_context *ctx)
198 * Drop an existing reference on the context, and free it if the refcnt is
202 xkb_context_unref(struct xkb_context *ctx)
204 if (!ctx || --ctx->refcnt > 0)
207 xkb_context_include_path_clear(ctx);
208 atom_table_free(ctx->atom_table);
213 log_level_to_prefix(enum xkb_log_level level)
216 case XKB_LOG_LEVEL_DEBUG:
218 case XKB_LOG_LEVEL_INFO:
220 case XKB_LOG_LEVEL_WARNING:
222 case XKB_LOG_LEVEL_ERROR:
224 case XKB_LOG_LEVEL_CRITICAL:
231 ATTR_PRINTF(3, 0) static void
232 default_log_fn(struct xkb_context *ctx, enum xkb_log_level level,
233 const char *fmt, va_list args)
235 const char *prefix = log_level_to_prefix(level);
238 fprintf(stderr, "%-10s", prefix);
239 vfprintf(stderr, fmt, args);
242 static enum xkb_log_level
243 log_level(const char *level) {
245 enum xkb_log_level lvl;
248 lvl = strtol(level, &endptr, 10);
249 if (errno == 0 && (endptr[0] == '\0' || isspace(endptr[0])))
251 if (istreq_prefix("crit", level))
252 return XKB_LOG_LEVEL_CRITICAL;
253 if (istreq_prefix("err", level))
254 return XKB_LOG_LEVEL_ERROR;
255 if (istreq_prefix("warn", level))
256 return XKB_LOG_LEVEL_WARNING;
257 if (istreq_prefix("info", level))
258 return XKB_LOG_LEVEL_INFO;
259 if (istreq_prefix("debug", level) || istreq_prefix("dbg", level))
260 return XKB_LOG_LEVEL_DEBUG;
262 return XKB_LOG_LEVEL_ERROR;
266 log_verbosity(const char *verbosity) {
271 v = strtol(verbosity, &endptr, 10);
278 #ifndef DEFAULT_XKB_VARIANT
279 #define DEFAULT_XKB_VARIANT NULL
282 #ifndef DEFAULT_XKB_OPTIONS
283 #define DEFAULT_XKB_OPTIONS NULL
287 * Create a new context.
289 XKB_EXPORT struct xkb_context *
290 xkb_context_new(enum xkb_context_flags flags)
293 struct xkb_context *ctx = calloc(1, sizeof(*ctx));
299 ctx->log_fn = default_log_fn;
300 ctx->log_level = XKB_LOG_LEVEL_ERROR;
301 ctx->log_verbosity = 0;
303 /* Environment overwrites defaults. */
304 env = getenv("XKB_LOG_LEVEL");
306 xkb_context_set_log_level(ctx, log_level(env));
308 env = getenv("XKB_LOG_VERBOSITY");
310 xkb_context_set_log_verbosity(ctx, log_verbosity(env));
312 if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) &&
313 !xkb_context_include_path_append_default(ctx)) {
314 log_err(ctx, "failed to add default include path %s\n",
315 DFLT_XKB_CONFIG_ROOT);
316 xkb_context_unref(ctx);
320 ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
322 ctx->atom_table = atom_table_new();
323 if (!ctx->atom_table) {
324 xkb_context_unref(ctx);
332 xkb_atom_lookup(struct xkb_context *ctx, const char *string)
334 return atom_lookup(ctx->atom_table, string, strlen(string));
338 xkb_atom_intern(struct xkb_context *ctx, const char *string)
340 return atom_intern(ctx->atom_table, string, strlen(string), false);
344 xkb_atom_steal(struct xkb_context *ctx, char *string)
346 return atom_intern(ctx->atom_table, string, strlen(string), true);
350 xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom)
352 return atom_strdup(ctx->atom_table, atom);
356 xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom)
358 return atom_text(ctx->atom_table, atom);
362 xkb_log(struct xkb_context *ctx, enum xkb_log_level level,
363 const char *fmt, ...)
368 ctx->log_fn(ctx, level, fmt, args);
373 xkb_context_set_log_fn(struct xkb_context *ctx,
374 void (*log_fn)(struct xkb_context *ctx,
375 enum xkb_log_level level,
376 const char *fmt, va_list args))
378 ctx->log_fn = (log_fn ? log_fn : default_log_fn);
381 XKB_EXPORT enum xkb_log_level
382 xkb_context_get_log_level(struct xkb_context *ctx)
384 return ctx->log_level;
388 xkb_context_set_log_level(struct xkb_context *ctx, enum xkb_log_level level)
390 ctx->log_level = level;
394 xkb_context_get_log_verbosity(struct xkb_context *ctx)
396 return ctx->log_verbosity;
400 xkb_context_set_log_verbosity(struct xkb_context *ctx, int verbosity)
402 ctx->log_verbosity = verbosity;
406 xkb_context_get_user_data(struct xkb_context *ctx)
409 return ctx->user_data;
414 xkb_context_set_user_data(struct xkb_context *ctx, void *user_data)
416 ctx->user_data = user_data;
420 xkb_context_get_buffer(struct xkb_context *ctx, size_t size)
424 if (size >= sizeof(ctx->text_buffer))
427 if (sizeof(ctx->text_buffer) - ctx->text_next <= size)
430 rtrn = &ctx->text_buffer[ctx->text_next];
431 ctx->text_next += size;
437 xkb_context_get_default_rules(struct xkb_context *ctx)
439 const char *env = NULL;
441 if (ctx->use_environment_names)
442 env = getenv("XKB_DEFAULT_RULES");
444 return env ? env : DEFAULT_XKB_RULES;
448 xkb_context_get_default_model(struct xkb_context *ctx)
450 const char *env = NULL;
452 if (ctx->use_environment_names)
453 env = getenv("XKB_DEFAULT_MODEL");
455 return env ? env : DEFAULT_XKB_MODEL;
459 xkb_context_get_default_layout(struct xkb_context *ctx)
461 const char *env = NULL;
463 if (ctx->use_environment_names)
464 env = getenv("XKB_DEFAULT_LAYOUT");
466 return env ? env : DEFAULT_XKB_LAYOUT;
470 xkb_context_get_default_variant(struct xkb_context *ctx)
472 const char *env = NULL;
473 const char *layout = getenv("XKB_DEFAULT_VARIANT");
475 /* We don't want to inherit the variant if they haven't also set a
476 * layout, since they're so closely paired. */
477 if (layout && ctx->use_environment_names)
478 env = getenv("XKB_DEFAULT_VARIANT");
480 return env ? env : DEFAULT_XKB_VARIANT;
484 xkb_context_get_default_options(struct xkb_context *ctx)
486 const char *env = NULL;
488 if (ctx->use_environment_names)
489 env = getenv("XKB_DEFAULT_OPTIONS");
491 return env ? env : DEFAULT_XKB_OPTIONS;