---
 plugins/keyboard/gsd-keyboard-xkb.c |  172 ++++++++++++++++++++++++++++++++----
 1 file changed, 157 insertions(+), 15 deletions(-)

--- a/plugins/keyboard/gsd-keyboard-xkb.c
+++ b/plugins/keyboard/gsd-keyboard-xkb.c
@@ -24,6 +24,7 @@
 
 #include <string.h>
 #include <time.h>
+#include <ctype.h>
 
 #include <glib/gi18n.h>
 #include <gdk/gdk.h>
@@ -343,6 +344,125 @@
         return ret;
 }
 
+/* get a variable content of the key defined in the sysconfig file;
+ * return value is a malloced string
+ */
+static gchar *
+_load_sysconfig_file_value (const gchar *file_name, const gchar *key)
+{
+        GIOChannel *channel;
+        gchar      *str;
+        gchar      *value;
+        gint        keylen;
+
+        channel = g_io_channel_new_file (file_name, "r", NULL);
+        if (!channel)
+                return NULL;
+
+        keylen = strlen (key);
+        value = NULL;
+        while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
+                gchar *p, *end;
+
+                if (!str)
+                        continue;
+                for (p = str; *p && isspace (*p); p++)
+                        ;
+                if (strncmp (p, key, keylen) != 0 || p[keylen] != '=') {
+                        g_free (str);
+                        continue;
+                }
+                p += keylen + 1;
+                /* FIXME: this is no perfect! */
+                if (*p == '"' || *p == '\'') {
+                        gchar delim = *p++;
+                        end = strrchr (p, delim);
+                } else {
+                        for (end = p; *end && !isspace (*end) && *end != '\n'; end++)
+                                ;
+                }
+                if (end)
+                        *end = 0;
+                value = g_strdup (p);
+                g_free (str);
+                break;
+        }
+
+        g_io_channel_shutdown (channel, FALSE, NULL);
+        g_io_channel_unref (channel);
+
+        return value;
+}
+
+/* read out the keyboard layouts defined in sax keymap file corresponding
+ * to the given key console layout; the return value is a string array,
+ * to be freed via g_strfreev().
+ */
+static gchar **
+_get_layouts_from_sax_map (const char *layout)
+{
+        gchar  *map_file;
+        gchar **lines;
+        gchar **fields;
+        gint    i;
+        gchar **retval;
+
+        if (!layout)
+                return NULL;
+
+        if (!g_file_get_contents ("/usr/share/sax/sysp/maps/Keyboard.map",
+                                  &map_file, NULL, NULL))
+                return NULL;
+
+        lines = g_strsplit (map_file, "\n", 0);
+        g_free (map_file);
+
+        retval = NULL;
+        for (i = 0; lines[i] != NULL; i++) {
+                if (lines[i][0] == '\n' || lines[i][0] == '#')
+                        continue;
+
+                fields = g_strsplit (lines[i], ":", 0);
+
+                g_strstrip (fields[0]);
+                if (fields[0] && fields[1] && fields[2] &&
+                    strcmp (fields[0], layout) == 0) {
+                        g_strstrip (fields[2]);
+                        retval = g_strsplit (fields[2], ",", 0);
+                        g_strfreev (fields);
+                        break;
+                }
+
+                g_strfreev (fields);
+        }
+
+        g_strfreev (lines);
+
+        return retval;
+}
+
+/* get keyboard layouts of the current system setup */
+static gchar **
+_get_sax_layouts_from_sysconfig (void)
+{
+        gchar *keytable;
+        gchar **layouts;
+
+        keytable = _load_sysconfig_file_value ("/etc/sysconfig/keyboard", "KEYTABLE");
+        if (!keytable)
+                return NULL;
+
+        if (g_str_has_suffix (keytable, ".gz"))
+                *(keytable + strlen (keytable) - strlen (".gz")) = '\0';
+        if (g_str_has_suffix (keytable, ".map"))
+                *(keytable + strlen (keytable) - strlen (".map")) = '\0';
+
+        layouts = _get_layouts_from_sax_map (keytable);
+        g_free (keytable);
+
+        return layouts;
+}
+
 static GSList *
 _maybe_setup_additional_layout (const char  *gdm_layout,
                                 GSList      *layouts,
@@ -350,6 +470,8 @@
 {
         char *layout;
         char *p;
+        char **sax_layouts = NULL;
+        char *secondary_layout = NULL;
 
         layout = g_strdup (gdm_layout);
         p = strchr (layout, '\t');
@@ -362,30 +484,50 @@
          * similar patch in gdm.
          * See https://bugzilla.novell.com/show_bug.cgi?id=509920#c13 */
 
-        if (strcmp (layout, "ara") != 0 &&
-            strcmp (layout, "cz")  != 0 &&
-            strcmp (layout, "gr")  != 0 &&
-            strcmp (layout, "kh")  != 0 &&
-            strcmp (layout, "sk")  != 0 &&
-            strcmp (layout, "ru")  != 0) {
-                g_free (layout);
-                return layouts;
+        if (strcmp (layout, "ara") == 0 ||
+            strcmp (layout, "cz")  == 0 ||
+            strcmp (layout, "gr")  == 0 ||
+            strcmp (layout, "kh")  == 0 ||
+            strcmp (layout, "sk")  == 0 ||
+            strcmp (layout, "ru")  == 0)
+                secondary_layout = "us";
+
+        if (! secondary_layout) {
+                /* check the additional layout from sax keyboard map
+                 * in the case of US layout, if the console keymap is
+                 * set in sysconfig/keyboard file (bnc#606617)
+                 */
+                if (strcmp (layout, "us") != 0)
+                        goto out;
+                sax_layouts = _get_sax_layouts_from_sysconfig ();
+                if (! sax_layouts || ! sax_layouts [0] || ! sax_layouts [1])
+                        goto out;
+                if (! strcmp (layout, sax_layouts [0]))
+                        secondary_layout = sax_layouts [1];
+                else if (! strcmp (layout, sax_layouts [1]))
+                        secondary_layout = sax_layouts [0];
+                else
+                        goto out;
         }
 
-        g_free (layout);
-
         /* adding "us" while there are already max layouts means we'd lose
          * another layout, from the user configuration. We don't want to do
          * this. */
         if (g_slist_length (layouts) >= max_groups)
-                return layouts;
+                goto out;
 
         /* do not add the layout if it's already there */
-        if (g_slist_find_custom (layouts, "us", _xkb_layout_strcmp))
-                return layouts;
+        if (g_slist_find_custom (layouts, secondary_layout, _xkb_layout_strcmp))
+                goto out;
 
         /* insert in last slot or at the end of list, whichever comes first */
-        return g_slist_insert (layouts, g_strdup ("us"), max_groups - 1);
+        layouts = g_slist_insert (layouts, g_strdup (secondary_layout), max_groups - 1);
+
+ out:
+        if (sax_layouts)
+                g_strfreev (sax_layouts);
+        g_free (layout);
+        return layouts;
 }
 
 static void
