Blame SOURCES/0004-xkb-Add-XkbCompileKeymapFromString.patch

70130e
From ae806ffa6b94bf75b9cb1b2db3e717fcaf13c8d0 Mon Sep 17 00:00:00 2001
70130e
From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net>
70130e
Date: Tue, 9 Apr 2013 17:45:08 -0400
70130e
Subject: [PATCH 04/39] xkb: Add XkbCompileKeymapFromString()
70130e
70130e
This new function compiles a keymap from an in-memory string.  We use it
70130e
to add a new keyooard device init function,
70130e
InitKeyboardDeviceStructFromString(), which inits a keyboard device with
70130e
a keymap specified as a string instead of a rmlvo set.
70130e
70130e
Reviewed-by: Daniel Stone <daniel@fooishbar.org>
70130e
---
70130e
 include/input.h  |   6 +++
70130e
 include/xkbsrv.h |   4 ++
70130e
 xkb/ddxLoad.c    | 129 ++++++++++++++++++++++++++++++++++++++++++-------------
70130e
 xkb/xkbInit.c    |  44 +++++++++++++++----
70130e
 4 files changed, 144 insertions(+), 39 deletions(-)
70130e
70130e
diff --git a/include/input.h b/include/input.h
70130e
index 350daba..6573a3a 100644
70130e
--- a/include/input.h
70130e
+++ b/include/input.h
70130e
@@ -385,6 +385,12 @@ extern _X_EXPORT Bool InitKeyboardDeviceStruct(DeviceIntPtr /*device */ ,
70130e
                                                KbdCtrlProcPtr /*controlProc */
70130e
                                                );
70130e
 
70130e
+extern _X_EXPORT Bool InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
70130e
+							 const char *keymap,
70130e
+							 int keymap_length,
70130e
+							 BellProcPtr bell_func,
70130e
+							 KbdCtrlProcPtr ctrl_func);
70130e
+
70130e
 extern int ApplyPointerMapping(DeviceIntPtr /* pDev */ ,
70130e
                                CARD8 * /* map */ ,
70130e
                                int /* len */ ,
70130e
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
70130e
index 346ebcc..bef98ef 100644
70130e
--- a/include/xkbsrv.h
70130e
+++ b/include/xkbsrv.h
70130e
@@ -861,4 +861,8 @@ extern _X_EXPORT XkbDescPtr XkbCompileKeymap(DeviceIntPtr /* dev */ ,
70130e
                                              XkbRMLVOSet *      /* rmlvo */
70130e
     );
70130e
 
70130e
+extern _X_EXPORT XkbDescPtr XkbCompileKeymapFromString(DeviceIntPtr dev,
70130e
+						       const char *keymap,
70130e
+						       int keymap_length);
70130e
+
70130e
 #endif                          /* _XKBSRV_H_ */
70130e
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
70130e
index 001ff46..7a7cf1e 100644
70130e
--- a/xkb/ddxLoad.c
70130e
+++ b/xkb/ddxLoad.c
70130e
@@ -262,6 +262,35 @@ XkbDDXOpenConfigFile(char *mapName, char *fileNameRtrn, int fileNameRtrnLen)
70130e
     return file;
70130e
 }
70130e
 
70130e
+static unsigned
70130e
+LoadXKM(unsigned want, unsigned need, XkbCompContextPtr ctx, XkbDescPtr *xkbRtrn)
70130e
+{
70130e
+    FILE *file;
70130e
+    char fileName[PATH_MAX];
70130e
+    unsigned missing;
70130e
+
70130e
+    file = XkbDDXOpenConfigFile(ctx->keymap, fileName, PATH_MAX);
70130e
+    if (file == NULL) {
70130e
+        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
70130e
+                   fileName);
70130e
+        return 0;
70130e
+    }
70130e
+    missing = XkmReadFile(file, need, want, xkbRtrn);
70130e
+    if (*xkbRtrn == NULL) {
70130e
+        LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
70130e
+        fclose(file);
70130e
+        (void) unlink(fileName);
70130e
+        return 0;
70130e
+    }
70130e
+    else {
70130e
+        DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
70130e
+               (*xkbRtrn)->defined);
70130e
+    }
70130e
+    fclose(file);
70130e
+    (void) unlink(fileName);
70130e
+    return (need | want) & (~missing);
70130e
+}
70130e
+
70130e
 unsigned
70130e
 XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
70130e
                         XkbComponentNamesPtr names,
70130e
@@ -270,9 +299,6 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
70130e
                         XkbDescPtr *xkbRtrn, char *nameRtrn, int nameRtrnLen)
70130e
 {
70130e
     XkbDescPtr xkb;
70130e
-    FILE *file;
70130e
-    char fileName[PATH_MAX];
70130e
-    unsigned missing;
70130e
     XkbCompContextRec ctx;
70130e
 
70130e
     *xkbRtrn = NULL;
70130e
@@ -292,26 +318,30 @@ XkbDDXLoadKeymapByNames(DeviceIntPtr keybd,
70130e
         LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
70130e
         return 0;
70130e
     }
70130e
-    file = XkbDDXOpenConfigFile(ctx.keymap, fileName, PATH_MAX);
70130e
-    if (file == NULL) {
70130e
-        LogMessage(X_ERROR, "Couldn't open compiled keymap file %s\n",
70130e
-                   fileName);
70130e
-        return 0;
70130e
-    }
70130e
-    missing = XkmReadFile(file, need, want, xkbRtrn);
70130e
-    if (*xkbRtrn == NULL) {
70130e
-        LogMessage(X_ERROR, "Error loading keymap %s\n", fileName);
70130e
-        fclose(file);
70130e
-        (void) unlink(fileName);
70130e
+
70130e
+    return LoadXKM(want, need, &ctx, xkbRtrn);
70130e
+}
70130e
+
70130e
+static unsigned
70130e
+XkbDDXLoadKeymapFromString(DeviceIntPtr keybd,
70130e
+			   const char *keymap, int keymap_length,
70130e
+			   unsigned want,
70130e
+			   unsigned need,
70130e
+			   XkbDescPtr *xkbRtrn)
70130e
+{
70130e
+    XkbCompContextRec ctx;
70130e
+
70130e
+    *xkbRtrn = NULL;
70130e
+
70130e
+    if (StartXkbComp(&ctx))
70130e
+	fwrite(keymap, keymap_length, 1, ctx.out);
70130e
+
70130e
+    if (!FinishXkbComp(&ctx)) {
70130e
+        LogMessage(X_ERROR, "XKB: Couldn't compile keymap\n");
70130e
         return 0;
70130e
     }
70130e
-    else {
70130e
-        DebugF("Loaded XKB keymap %s, defined=0x%x\n", fileName,
70130e
-               (*xkbRtrn)->defined);
70130e
-    }
70130e
-    fclose(file);
70130e
-    (void) unlink(fileName);
70130e
-    return (need | want) & (~missing);
70130e
+
70130e
+    return LoadXKM(want, need, &ctx, xkbRtrn);
70130e
 }
70130e
 
70130e
 Bool
70130e
@@ -407,6 +437,29 @@ XkbCompileKeymapForDevice(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, int need)
70130e
     return xkb;
70130e
 }
70130e
 
70130e
+static XkbDescPtr
70130e
+KeymapOrDefaults(DeviceIntPtr dev, XkbDescPtr xkb)
70130e
+{
70130e
+    XkbRMLVOSet dflts;
70130e
+
70130e
+    if (xkb)
70130e
+	return xkb;
70130e
+
70130e
+    /* we didn't get what we really needed. And that will likely leave
70130e
+     * us with a keyboard that doesn't work. Use the defaults instead */
70130e
+    LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
70130e
+	       "keymap instead.\n");
70130e
+
70130e
+    XkbGetRulesDflts(&dflts);
70130e
+
70130e
+    xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
70130e
+
70130e
+    XkbFreeRMLVOSet(&dflts, FALSE);
70130e
+
70130e
+    return xkb;
70130e
+}
70130e
+
70130e
+
70130e
 XkbDescPtr
70130e
 XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
70130e
 {
70130e
@@ -424,20 +477,34 @@ XkbCompileKeymap(DeviceIntPtr dev, XkbRMLVOSet * rmlvo)
70130e
 
70130e
     xkb = XkbCompileKeymapForDevice(dev, rmlvo, need);
70130e
 
70130e
-    if (!xkb) {
70130e
-        XkbRMLVOSet dflts;
70130e
+    return KeymapOrDefaults(dev, xkb);
70130e
+}
70130e
 
70130e
-        /* we didn't get what we really needed. And that will likely leave
70130e
-         * us with a keyboard that doesn't work. Use the defaults instead */
70130e
-        LogMessage(X_ERROR, "XKB: Failed to load keymap. Loading default "
70130e
-                   "keymap instead.\n");
70130e
+XkbDescPtr
70130e
+XkbCompileKeymapFromString(DeviceIntPtr dev,
70130e
+			   const char *keymap, int keymap_length)
70130e
+{
70130e
+    XkbDescPtr xkb;
70130e
+    unsigned int need, provided;
70130e
 
70130e
-        XkbGetRulesDflts(&dflts);
70130e
+    if (!dev || !keymap) {
70130e
+        LogMessage(X_ERROR, "XKB: No device or keymap specified\n");
70130e
+        return NULL;
70130e
+    }
70130e
 
70130e
-        xkb = XkbCompileKeymapForDevice(dev, &dflts, 0);
70130e
+    /* These are the components we really really need */
70130e
+    need = XkmSymbolsMask | XkmCompatMapMask | XkmTypesMask |
70130e
+        XkmKeyNamesMask | XkmVirtualModsMask;
70130e
 
70130e
-        XkbFreeRMLVOSet(&dflts, FALSE);
70130e
+    provided =
70130e
+	XkbDDXLoadKeymapFromString(dev, keymap, keymap_length,
70130e
+				   XkmAllIndicesMask, need, &xkb);
70130e
+    if ((need & provided) != need) {
70130e
+	if (xkb) {
70130e
+	    XkbFreeKeyboard(xkb, 0, TRUE);
70130e
+	    xkb = NULL;
70130e
+	}
70130e
     }
70130e
 
70130e
-    return xkb;
70130e
+    return KeymapOrDefaults(dev, xkb);
70130e
 }
70130e
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
70130e
index f72655f..f3f0d8f 100644
70130e
--- a/xkb/xkbInit.c
70130e
+++ b/xkb/xkbInit.c
70130e
@@ -490,9 +490,10 @@ XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
70130e
     return Success;
70130e
 }
70130e
 
70130e
-_X_EXPORT Bool
70130e
-InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
-                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
70130e
+static Bool
70130e
+InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
+				 const char *keymap, int keymap_length,
70130e
+				 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
70130e
 {
70130e
     int i;
70130e
     unsigned int check;
70130e
@@ -507,7 +508,7 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
     BUG_RETURN_VAL(dev->key != NULL, FALSE);
70130e
     BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
70130e
 
70130e
-    if (!rmlvo) {
70130e
+    if (!rmlvo && !keymap) {
70130e
         rmlvo = &rmlvo_dflts;
70130e
         XkbGetRulesDflts(rmlvo);
70130e
     }
70130e
@@ -535,19 +536,26 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
     }
70130e
     dev->key->xkbInfo = xkbi;
70130e
 
70130e
-    if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
70130e
+    if (xkb_cached_map && (keymap || (rmlvo && !XkbCompareUsedRMLVO(rmlvo)))) {
70130e
         XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
70130e
         xkb_cached_map = NULL;
70130e
     }
70130e
 
70130e
     if (xkb_cached_map)
70130e
         LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
70130e
-    else {
70130e
+    else if (rmlvo) {
70130e
         xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
70130e
         if (!xkb_cached_map) {
70130e
             ErrorF("XKB: Failed to compile keymap\n");
70130e
             goto unwind_info;
70130e
         }
70130e
+    } else {
70130e
+	xkb_cached_map = XkbCompileKeymapFromString(dev,
70130e
+						    keymap, keymap_length);
70130e
+        if (!xkb_cached_map) {
70130e
+            ErrorF("XKB: Failed to compile keymap from string\n");
70130e
+            goto unwind_info;
70130e
+        }
70130e
     }
70130e
 
70130e
     xkb = XkbAllocKeyboard();
70130e
@@ -612,8 +620,10 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
 
70130e
     dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
70130e
 
70130e
-    XkbSetRulesDflts(rmlvo);
70130e
-    XkbSetRulesUsed(rmlvo);
70130e
+    if (rmlvo) {
70130e
+	XkbSetRulesDflts(rmlvo);
70130e
+	XkbSetRulesUsed(rmlvo);
70130e
+    }
70130e
     XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
70130e
 
70130e
     return TRUE;
70130e
@@ -632,6 +642,24 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
     return FALSE;
70130e
 }
70130e
 
70130e
+_X_EXPORT Bool
70130e
+InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
70130e
+                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
70130e
+{
70130e
+    return InitKeyboardDeviceStructInternal(dev, rmlvo,
70130e
+					    NULL, 0, bell_func, ctrl_func);
70130e
+}
70130e
+
70130e
+_X_EXPORT Bool
70130e
+InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
70130e
+				   const char *keymap, int keymap_length,
70130e
+				   BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
70130e
+{
70130e
+    return InitKeyboardDeviceStructInternal(dev, NULL,
70130e
+					    keymap, keymap_length,
70130e
+					    bell_func, ctrl_func);
70130e
+}
70130e
+
70130e
 /***====================================================================***/
70130e
 
70130e
         /*
70130e
-- 
70130e
1.8.3.1
70130e