]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
KEyboard layout support
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 19 Aug 2010 00:57:05 +0000 (02:57 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 19 Aug 2010 00:57:05 +0000 (02:57 +0200)
commands/keylayouts.c

index 58baabe6760496a91e3c627de6ed5ad8ccfaf3d7..05595f8d13d9225df37f1a4177f1efdc7efbcafc 100644 (file)
 #include <grub/time.h>
 #include <grub/dl.h>
 #include <grub/at_keyboard.h>
+#include <grub/keyboard_layouts.h>
+#include <grub/command.h>
+#include <grub/gzio.h>
+#include <grub/i18n.h>
 
 GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map);
 
@@ -73,20 +77,21 @@ get_abstract_code (grub_term_input_t term, int in)
     }
 }
 
+static grub_uint32_t mapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE];
+
 static int
-map (grub_term_input_t term, int in)
+map (grub_term_input_t term __attribute__ ((unused)), int in)
 {
-  /* No match with AltGr. Interpret it as Alt rather than as L3 modifier then.  
-   */
+  /* AltGr isn't supported yet.  */
   if (in & GRUB_TERM_ALT_GR)
-    return map (term, in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR;
+    in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR;
 
-  if (in == GRUB_TERM_KEY_102)
-    return '\\';
-  if (in == GRUB_TERM_KEY_SHIFT_102)
-    return '|';
+  if ((in & GRUB_TERM_EXTENDED) || (in & GRUB_TERM_KEY_MASK) == '\b'
+      || (in & GRUB_TERM_KEY_MASK) == '\t' || (in & GRUB_TERM_KEY_MASK) == '\e'
+      || (in & GRUB_TERM_KEY_MASK) >= ARRAY_SIZE (mapping))
+    return in;
 
-  return in;
+  return mapping[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK);
 }
 
 static int
@@ -152,15 +157,104 @@ grub_checkkey (void)
   return -1;
 }
 
+static grub_err_t
+grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
+                int argc, char *argv[])
+{
+  char *filename;
+  grub_file_t file;
+  grub_uint32_t version;
+  grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE];
+  grub_uint32_t newmapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE];
+  unsigned i;
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required");
+  if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+')
+    {
+      const char *prefix = grub_env_get ("prefix");
+      if (!prefix)
+       return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set");     
+      filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]);
+      if (!filename)
+       return grub_errno;
+    }
+  else
+    filename = argv[0];
+
+  file = grub_gzfile_open (filename, 1);
+  if (! file)
+    goto fail;
+
+  if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic))
+    {
+      if (!grub_errno)
+       grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+      goto fail;
+    }
+
+  if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC,
+                  GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic");
+      goto fail;
+    }
+
+  if (grub_file_read (file, &version, sizeof (version)) != sizeof (version))
+    {
+      if (!grub_errno)
+       grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+      goto fail;
+    }
+
+  if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION)
+    {
+      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version");
+      goto fail;
+    }
+
+  if (grub_file_read (file, newmapping, sizeof (newmapping))
+      != sizeof (newmapping))
+    {
+      if (!grub_errno)
+       grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
+      goto fail;
+    }
+
+  for (i = 0; i < ARRAY_SIZE (mapping); i++)
+    mapping[i] = grub_le_to_cpu32(newmapping[i]);
+
+  return GRUB_ERR_NONE;
+
+ fail:
+  if (filename != argv[0])
+    grub_free (filename);
+  if (file)
+    grub_file_close (file);
+  return grub_errno;
+}
+
 static int (*grub_getkey_saved) (void);
 
+static grub_command_t cmd;
+
 GRUB_MOD_INIT(keylayouts)
 {
+  unsigned i;
+  for (i = 0; i < ARRAY_SIZE (mapping); i++)
+    mapping[i] = i;
+  mapping[GRUB_TERM_KEY_102] = '\\';
+  mapping[GRUB_TERM_KEY_SHIFT_102] = '|';
+
   grub_getkey_saved = grub_getkey;
   grub_getkey = grub_getkey_smart;
+
+  cmd = grub_register_command ("keymap", grub_cmd_keymap,
+                              0, N_("Load a keyboard layout."));
 }
 
 GRUB_MOD_FINI(keylayouts)
 {
   grub_getkey = grub_getkey_saved;
+  grub_unregister_command (cmd);
 }