Add interface to compile keyboard description from keymap files We need to support generating a keyboard description from a keymap file because there are just some cases where RMLVO or ktcsg is not enough. The map choosing logic has been refactored into its own function and now supports choosing a named or default keymap.
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
diff --git a/include/X11/extensions/XKBcommon.h b/include/X11/extensions/XKBcommon.h
index 1bc0f35..1a53658 100644
--- a/include/X11/extensions/XKBcommon.h
+++ b/include/X11/extensions/XKBcommon.h
@@ -28,6 +28,7 @@ authorization from the authors.
#ifndef _XKBCOMMON_H_
#define _XKBCOMMON_H_
+#include <stdio.h>
#include <X11/Xfuncproto.h>
/* Action structures used in the server */
@@ -134,6 +135,9 @@ XkbcCompileKeymapFromRules(const XkbRMLVOSet *rmlvo);
extern XkbcDescPtr
XkbcCompileKeymapFromComponents(const XkbComponentNamesPtr ktcsg);
+extern XkbcDescPtr
+XkbcCompileKeymapFromFile(FILE *inputFile, const char *mapName);
+
_XFUNCPROTOEND
#endif /* _XKBCOMMON_H_ */
diff --git a/src/xkbcomp/xkbcomp.c b/src/xkbcomp/xkbcomp.c
index 89753da..cfd73c5 100644
--- a/src/xkbcomp/xkbcomp.c
+++ b/src/xkbcomp/xkbcomp.c
@@ -156,6 +156,40 @@ XkbcCompileKeymapFromRules(const XkbRMLVOSet *rmlvo)
return xkb;
}
+static XkbFile *
+XkbChooseMap(XkbFile *file, const char *name)
+{
+ XkbFile *map = file;
+
+ /* map specified? */
+ if (name) {
+ while (map) {
+ if (map->name && strcmp(map->name, name) == 0)
+ break;
+ map = (XkbFile *) map->common.next;
+ }
+
+ 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 (!map) {
+ map = file;
+ WARN("no map specified, but components have several\n");
+ WARN("using the first defined map, \"%s\"\n",
+ map->name ? map->name : "");
+ }
+ }
+
+ return map;
+}
+
XkbcDescPtr
XkbcCompileKeymapFromComponents(const XkbComponentNamesPtr ktcsg)
{
@@ -173,16 +207,58 @@ XkbcCompileKeymapFromComponents(const XkbComponentNamesPtr ktcsg)
}
/* Find map to use */
- mapToUse = file;
- if (file->common.next) {
- for (; mapToUse; mapToUse = (XkbFile *)mapToUse->common.next) {
- if (mapToUse->flags & XkbLC_Default)
- break;
- }
- if (!mapToUse) {
- mapToUse = file;
- WARN("no map specified, but components have several\n");
- }
+ if (!(mapToUse = XkbChooseMap(file, NULL)))
+ goto unwind_file;
+
+ /* Compile the keyboard */
+ if (!(xkb = XkbcAllocKeyboard())) {
+ ERROR("could not allocate keyboard description\n");
+ goto unwind_file;
+ }
+
+ if (!CompileKeymap(mapToUse, xkb, MergeReplace)) {
+ ERROR("failed to compile keymap\n");
+ goto unwind_xkb;
+ }
+
+ return xkb;
+unwind_xkb:
+ XkbcFreeKeyboard(xkb, XkbAllComponentsMask, True);
+unwind_file:
+ /* XXX: here's where we would free the XkbFile */
+fail:
+ return NULL;
+}
+
+XkbcDescPtr
+XkbcCompileKeymapFromFile(FILE *inputFile, const char *mapName)
+{
+ XkbFile *file, *mapToUse;
+ XkbcDescPtr xkb;
+
+ if (!inputFile) {
+ ERROR("no file specified to generate XKB keymap\n");
+ goto fail;
+ }
+
+ setScanState("input", 1);
+ if (!XKBParseFile(inputFile, &file) || !file) {
+ ERROR("failed to parse input xkb file\n");
+ goto fail;
+ }
+
+ /* Find map to use */
+ if (!(mapToUse = XkbChooseMap(file, mapName)))
+ goto unwind_file;
+
+ switch (mapToUse->type) {
+ case XkmSemanticsFile:
+ case XkmLayoutFile:
+ case XkmKeymapFile:
+ break;
+ default:
+ ERROR("file type %d not handled\n", mapToUse->type);
+ goto unwind_file;
}
/* Compile the keyboard */