authorization from the authors.
*/
-#include <limits.h>
-#include "X11/extensions/XKBcommon.h"
-#include <X11/extensions/XKM.h>
-#include "XKBcommonint.h"
-#include "xkbcomp.h"
+#include "xkbcomp-priv.h"
+#include "rules.h"
#include "parseutils.h"
-#include "utils.h"
+#include "path.h"
-#ifndef DFLT_XKB_CONFIG_ROOT
-#define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb"
-#endif
+/* Global warning level */
+unsigned int warningLevel = 0;
-static int
-XkbFileFromComponents(const XkbComponentNamesPtr ktcsg, XkbFile **file)
+#define ISEMPTY(str) (!(str) || (strlen(str) == 0))
+
+static XkbFile *
+XkbKeymapFileFromComponents(struct xkb_context *ctx,
+ const struct xkb_component_names *ktcsg)
{
- XkbFile *keycodes, *types, *compat, *symbols, *geometry;
+ XkbFile *keycodes, *types, *compat, *symbols;
IncludeStmt *inc;
inc = IncludeCreate(ktcsg->keycodes, MergeDefault);
- keycodes = CreateXKBFile(XkmKeyNamesIndex, NULL, (ParseCommon *)inc, 0);
+ keycodes = CreateXKBFile(ctx, XkmKeyNamesIndex, NULL,
+ (ParseCommon *)inc, 0);
inc = IncludeCreate(ktcsg->types, MergeDefault);
- types = CreateXKBFile(XkmTypesIndex, NULL, (ParseCommon *)inc, 0);
+ types = CreateXKBFile(ctx, XkmTypesIndex, NULL,
+ (ParseCommon *)inc, 0);
AppendStmt(&keycodes->common, &types->common);
inc = IncludeCreate(ktcsg->compat, MergeDefault);
- compat = CreateXKBFile(XkmCompatMapIndex, NULL, (ParseCommon *)inc, 0);
+ compat = CreateXKBFile(ctx, XkmCompatMapIndex, NULL,
+ (ParseCommon *)inc, 0);
AppendStmt(&keycodes->common, &compat->common);
inc = IncludeCreate(ktcsg->symbols, MergeDefault);
- symbols = CreateXKBFile(XkmSymbolsIndex, NULL, (ParseCommon *)inc, 0);
+ symbols = CreateXKBFile(ctx, XkmSymbolsIndex, NULL,
+ (ParseCommon *)inc, 0);
AppendStmt(&keycodes->common, &symbols->common);
- inc = IncludeCreate(ktcsg->geometry, MergeDefault);
- geometry = CreateXKBFile(XkmGeometryIndex, NULL, (ParseCommon *)inc, 0);
- AppendStmt(&keycodes->common, &geometry->common);
-
- *file = CreateXKBFile(XkmKeymapFile, ktcsg->keymap, &keycodes->common, 0);
-
- return 1;
+ return CreateXKBFile(ctx, XkmKeymapFile,
+ ktcsg->keymap ? ktcsg->keymap : strdup(""),
+ &keycodes->common, 0);
}
-static XkbComponentNamesPtr
-XkbComponentsFromRules(const char *rulesPath, const XkbRF_VarDefsPtr defs)
+static struct xkb_component_names *
+XkbComponentsFromRules(struct xkb_context *ctx,
+ const char *rules,
+ const XkbRF_VarDefsPtr defs)
{
- XkbRF_RulesPtr rules;
- XkbComponentNamesPtr names = NULL;
+ FILE *rulesFile = NULL;
+ char *rulesPath = NULL;
+ XkbRF_RulesPtr loaded = NULL;
+ struct xkb_component_names * names = NULL;
+ int i;
+
+ rulesFile = XkbFindFileInPath(ctx, rules, XkmRulesFile, &rulesPath);
+ if (!rulesFile) {
+ ERROR("could not find \"%s\" rules in XKB path\n", rules);
+ ERROR("%d include paths searched:\n",
+ xkb_context_num_include_paths(ctx));
+ for (i = 0; i < xkb_context_num_include_paths(ctx); i++)
+ ERROR("\t%s\n", xkb_context_include_path_get(ctx, i));
+ return NULL;
+ }
- if (!(rules = XkbcRF_Load((char *)rulesPath, NULL, False, True))) {
- ERROR("Failed to load XKB rules \"%s\"\n", rulesPath);
- goto fail;
+ if (!(loaded = uTypedCalloc(1, XkbRF_RulesRec))) {
+ ERROR("failed to allocate XKB rules\n");
+ goto unwind_file;
}
- if (!(names = _XkbTypedCalloc(1, XkbComponentNamesRec))) {
- ERROR("Failed to allocate XKB components\n");
- goto unwind_rules;
+ if (!XkbcRF_LoadRules(rulesFile, loaded)) {
+ ERROR("failed to load XKB rules \"%s\"\n", rulesPath);
+ goto unwind_file;
}
- if (!XkbcRF_GetComponents(rules, defs, names))
- ERROR("No components returned from XKB rules \"%s\"\n", rulesPath);
+ if (!(names = uTypedCalloc(1, struct xkb_component_names))) {
+ ERROR("failed to allocate XKB components\n");
+ goto unwind_file;
+ }
+
+ if (!XkbcRF_GetComponents(loaded, defs, names)) {
+ free(names->keymap);
+ free(names->keycodes);
+ free(names->types);
+ free(names->compat);
+ free(names->symbols);
+ free(names);
+ names = NULL;
+ ERROR("no components returned from XKB rules \"%s\"\n", rulesPath);
+ }
-unwind_rules:
- XkbcRF_Free(rules, True);
-fail:
+unwind_file:
+ XkbcRF_Free(loaded);
+ if (rulesFile)
+ fclose(rulesFile);
+ free(rulesPath);
return names;
}
-XkbcDescPtr
-XkbcCompileKeymapFromRules(const char *rules, XkbRF_VarDefsPtr defs)
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_names(struct xkb_context *ctx,
+ const struct xkb_rule_names *rmlvo,
+ enum xkb_map_compile_flags flags)
{
- char rulesPath[PATH_MAX];
- int pathlen;
- XkbComponentNamesPtr names;
- XkbcDescPtr xkb;
-
- if (!rules)
- return NULL;
+ XkbRF_VarDefsRec defs;
+ struct xkb_component_names *names;
+ struct xkb_keymap *keymap;
- pathlen = snprintf(rulesPath, sizeof(rulesPath),
- DFLT_XKB_CONFIG_ROOT "/rules/%s", rules);
- if (pathlen >= sizeof(rulesPath)) {
- ERROR("XKB rules path truncated\n");
+ if (!rmlvo || ISEMPTY(rmlvo->rules) || ISEMPTY(rmlvo->layout)) {
+ ERROR("rules and layout required to generate XKB keymap\n");
return NULL;
}
- names = XkbComponentsFromRules(rulesPath, defs);
+ defs.model = rmlvo->model;
+ defs.layout = rmlvo->layout;
+ defs.variant = rmlvo->variant;
+ defs.options = rmlvo->options;
+
+ names = XkbComponentsFromRules(ctx, rmlvo->rules, &defs);
if (!names) {
- ERROR("Failed to generate XKB components from rules \"%s\"\n",
- rules);
+ ERROR("failed to generate XKB components from rules \"%s\"\n",
+ rmlvo->rules);
return NULL;
}
- xkb = XkbcCompileKeymapFromComponents(names);
+ keymap = xkb_map_new_from_kccgst(ctx, names, 0);
- _XkbFree(names->keymap);
- _XkbFree(names->keycodes);
- _XkbFree(names->types);
- _XkbFree(names->compat);
- _XkbFree(names->symbols);
- _XkbFree(names->geometry);
- _XkbFree(names);
+ free(names->keymap);
+ free(names->keycodes);
+ free(names->types);
+ free(names->compat);
+ free(names->symbols);
+ free(names);
- return xkb;
+ return keymap;
}
-XkbcDescPtr
-XkbcCompileKeymapFromComponents(XkbComponentNamesPtr ktcsg)
+static XkbFile *
+XkbChooseMap(XkbFile *file, const char *name)
{
- XkbFile *file, *mapToUse;
- XkbcDescPtr xkb;
+ XkbFile *map = file;
- if (!XkbFileFromComponents(ktcsg, &file)) {
- ERROR("failed to generate parsed XKB file from components");
- goto fail;
- }
+ /* map specified? */
+ if (name) {
+ while (map) {
+ if (map->name && strcmp(map->name, name) == 0)
+ break;
+ map = (XkbFile *) map->common.next;
+ }
- /* Find map to use */
- mapToUse = file;
- if (file->common.next) {
- for (; mapToUse; mapToUse = (XkbFile *)mapToUse->common.next) {
- if (mapToUse->flags & XkbLC_Default)
+ if (!map)
+ ERROR("no map named \"%s\" in input file\n", name);
+ }
+ else if (file->common.next) {
+ /* look for map with XkbLC_Default flag. */
+ for (; map; map = (XkbFile *) map->common.next) {
+ if (map->flags & XkbLC_Default)
break;
}
- if (!mapToUse) {
- mapToUse = file;
- WARN("no map specified, but components have several");
+
+ if (!map) {
+ map = file;
+ WARN("no map specified, but components have several\n");
+ WARN("using the first defined map, \"%s\"\n",
+ map->name ? map->name : "");
}
}
- /* Compile the keyboard */
- if (!(xkb = XkbcAllocKeyboard())) {
- ERROR("Could not allocate keyboard description");
- goto unwind_file;
+ return map;
+}
+
+static struct xkb_keymap *
+compile_keymap(struct xkb_context *ctx, XkbFile *file)
+{
+ XkbFile *mapToUse;
+ struct xkb_keymap *keymap = NULL;
+
+ /* Find map to use */
+ mapToUse = XkbChooseMap(file, NULL);
+ if (!mapToUse)
+ goto err;
+
+ if (mapToUse->type != XkmKeymapFile) {
+ ERROR("file type %d not handled\n", mapToUse->type);
+ goto err;
}
- if (!CompileKeymap(mapToUse, xkb, MergeReplace)) {
- ERROR("Failed to compile keymap");
- goto unwind_xkb;
+ keymap = CompileKeymap(ctx, mapToUse);
+ if (!keymap)
+ goto err;
+
+err:
+ FreeXKBFile(file);
+ return keymap;
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_kccgst(struct xkb_context *ctx,
+ const struct xkb_component_names *kccgst,
+ enum xkb_map_compile_flags flags)
+{
+ XkbFile *file;
+
+ if (!kccgst) {
+ ERROR("no components specified\n");
+ return NULL;
}
- return xkb;
-unwind_xkb:
- XkbcFreeKeyboard(xkb, XkbAllComponentsMask, True);
-unwind_file:
- /* XXX: here's where we would free the XkbFile */
-fail:
- return NULL;
+ if (ISEMPTY(kccgst->keycodes)) {
+ ERROR("keycodes required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->compat)) {
+ ERROR("compat map required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->types)) {
+ ERROR("types required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->symbols)) {
+ ERROR("symbols required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!(file = XkbKeymapFileFromComponents(ctx, kccgst))) {
+ ERROR("failed to generate parsed XKB file from components\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_string(struct xkb_context *ctx,
+ const char *string,
+ enum xkb_keymap_format format,
+ enum xkb_map_compile_flags flags)
+{
+ XkbFile *file;
+
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
+ if (!string) {
+ ERROR("no string specified to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!XKBParseString(ctx, string, "input", &file)) {
+ ERROR("failed to parse input xkb file\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_file(struct xkb_context *ctx,
+ FILE *file,
+ enum xkb_keymap_format format,
+ enum xkb_map_compile_flags flags)
+{
+ XkbFile *xkb_file;
+
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
+ if (!file) {
+ ERROR("no file specified to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!XKBParseFile(ctx, file, "(unknown file)", &xkb_file)) {
+ ERROR("failed to parse input xkb file\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, xkb_file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_ref(struct xkb_keymap *keymap)
+{
+ keymap->refcnt++;
+ return keymap;
+}
+
+_X_EXPORT void
+xkb_map_unref(struct xkb_keymap *keymap)
+{
+ if (--keymap->refcnt > 0)
+ return;
+
+ XkbcFreeKeyboard(keymap);
}