--- qemu-snapshot-2007-12-31_05/monitor.c	2007-12-31 05:11:10.000000000 +0200
+++ qemu/monitor.c	2007-12-31 18:24:14.000000000 +0200
@@ -763,119 +763,189 @@
 typedef struct {
     int keycode;
     const char *name;
+    int need_shift;
 } KeyDef;
 
 static const KeyDef key_defs[] = {
-    { 0x2a, "shift" },
-    { 0x36, "shift_r" },
+    { 0x2a, "shift", 0 },
+    { 0x36, "shift_r", 0 },
 
-    { 0x38, "alt" },
-    { 0xb8, "alt_r" },
-    { 0x1d, "ctrl" },
-    { 0x9d, "ctrl_r" },
-
-    { 0xdd, "menu" },
-
-    { 0x01, "esc" },
-
-    { 0x02, "1" },
-    { 0x03, "2" },
-    { 0x04, "3" },
-    { 0x05, "4" },
-    { 0x06, "5" },
-    { 0x07, "6" },
-    { 0x08, "7" },
-    { 0x09, "8" },
-    { 0x0a, "9" },
-    { 0x0b, "0" },
-    { 0x0c, "minus" },
-    { 0x0d, "equal" },
-    { 0x0e, "backspace" },
-
-    { 0x0f, "tab" },
-    { 0x10, "q" },
-    { 0x11, "w" },
-    { 0x12, "e" },
-    { 0x13, "r" },
-    { 0x14, "t" },
-    { 0x15, "y" },
-    { 0x16, "u" },
-    { 0x17, "i" },
-    { 0x18, "o" },
-    { 0x19, "p" },
-
-    { 0x1c, "ret" },
-
-    { 0x1e, "a" },
-    { 0x1f, "s" },
-    { 0x20, "d" },
-    { 0x21, "f" },
-    { 0x22, "g" },
-    { 0x23, "h" },
-    { 0x24, "j" },
-    { 0x25, "k" },
-    { 0x26, "l" },
-
-    { 0x2c, "z" },
-    { 0x2d, "x" },
-    { 0x2e, "c" },
-    { 0x2f, "v" },
-    { 0x30, "b" },
-    { 0x31, "n" },
-    { 0x32, "m" },
-
-    { 0x39, "spc" },
-    { 0x3a, "caps_lock" },
-    { 0x3b, "f1" },
-    { 0x3c, "f2" },
-    { 0x3d, "f3" },
-    { 0x3e, "f4" },
-    { 0x3f, "f5" },
-    { 0x40, "f6" },
-    { 0x41, "f7" },
-    { 0x42, "f8" },
-    { 0x43, "f9" },
-    { 0x44, "f10" },
-    { 0x45, "num_lock" },
-    { 0x46, "scroll_lock" },
-
-    { 0xb5, "kp_divide" },
-    { 0x37, "kp_multiply" },
-    { 0x4a, "kp_subtract" },
-    { 0x4e, "kp_add" },
-    { 0x9c, "kp_enter" },
-    { 0x53, "kp_decimal" },
-
-    { 0x52, "kp_0" },
-    { 0x4f, "kp_1" },
-    { 0x50, "kp_2" },
-    { 0x51, "kp_3" },
-    { 0x4b, "kp_4" },
-    { 0x4c, "kp_5" },
-    { 0x4d, "kp_6" },
-    { 0x47, "kp_7" },
-    { 0x48, "kp_8" },
-    { 0x49, "kp_9" },
-
-    { 0x56, "<" },
-
-    { 0x57, "f11" },
-    { 0x58, "f12" },
-
-    { 0xb7, "print" },
-
-    { 0xc7, "home" },
-    { 0xc9, "pgup" },
-    { 0xd1, "pgdn" },
-    { 0xcf, "end" },
-
-    { 0xcb, "left" },
-    { 0xc8, "up" },
-    { 0xd0, "down" },
-    { 0xcd, "right" },
+    { 0x38, "alt", 0 },
+    { 0xb8, "alt_r", 0 },
+    { 0x1d, "ctrl", 0 },
+    { 0x9d, "ctrl_r", 0 },
+
+    { 0xdd, "menu", 0 },
+
+    { 0x01, "esc", 0 },
+
+    { 0x02, "1", 0 },
+    { 0x03, "2", 0 },
+    { 0x04, "3", 0 },
+    { 0x05, "4", 0 },
+    { 0x06, "5", 0 },
+    { 0x07, "6", 0 },
+    { 0x08, "7", 0 },
+    { 0x09, "8", 0 },
+    { 0x0a, "9", 0 },
+    { 0x0b, "0", 0 },
+
+    { 0x02, "!", 1 },
+    { 0x03, "@", 1 },
+    { 0x04, "#", 1 },
+    { 0x05, "$", 1 },
+    { 0x06, "%", 1 },
+    { 0x07, "^", 1 },
+    { 0x08, "&", 1 },
+    { 0x09, "*", 1 },
+    { 0x0a, "(", 1 },
+    { 0x0b, ")", 1 },
+
+    { 0x0c, "minus", 0 },
+    { 0x0d, "equal", 0 },
+    { 0x0d, "=", 0 },
+    { 0x0e, "backspace", 0 },
+
+    { 0x0c, "_", 1 },
+
+    { 0x0f, "tab", 0 },
+    { 0x10, "q", 0 },
+    { 0x11, "w", 0 },
+    { 0x12, "e", 0 },
+    { 0x13, "r", 0 },
+    { 0x14, "t", 0 },
+    { 0x15, "y", 0 },
+    { 0x16, "u", 0 },
+    { 0x17, "i", 0 },
+    { 0x18, "o", 0 },
+    { 0x19, "p", 0 },
+
+    { 0x1c, "ret", 0 },
+
+    { 0x1e, "a", 0 },
+    { 0x1f, "s", 0 },
+    { 0x20, "d", 0 },
+    { 0x21, "f", 0 },
+    { 0x22, "g", 0 },
+    { 0x23, "h", 0 },
+    { 0x24, "j", 0 },
+    { 0x25, "k", 0 },
+    { 0x26, "l", 0 },
+
+    { 0x2c, "z", 0 },
+    { 0x2d, "x", 0 },
+    { 0x2e, "c", 0 },
+    { 0x2f, "v", 0 },
+    { 0x30, "b", 0 },
+    { 0x31, "n", 0 },
+    { 0x32, "m", 0 },
+
+    { 0x10, "Q", 1 },
+    { 0x11, "W", 1 },
+    { 0x12, "E", 1 },
+    { 0x13, "R", 1 },
+    { 0x14, "T", 1 },
+    { 0x15, "Y", 1 },
+    { 0x16, "U", 1 },
+    { 0x17, "I", 1 },
+    { 0x18, "O", 1 },
+    { 0x19, "P", 1 },
+
+    { 0x1e, "A", 1 },
+    { 0x1f, "S", 1 },
+    { 0x20, "D", 1 },
+    { 0x21, "F", 1 },
+    { 0x22, "G", 1 },
+    { 0x23, "H", 1 },
+    { 0x24, "J", 1 },
+    { 0x25, "K", 1 },
+    { 0x26, "L", 1 },
+
+    { 0x2c, "Z", 1 },
+    { 0x2d, "X", 1 },
+    { 0x2e, "C", 1 },
+    { 0x2f, "V", 1 },
+    { 0x30, "B", 1 },
+    { 0x31, "N", 1 },
+    { 0x32, "M", 1 },
+
+
+    { 0x1a, "[", 0 },
+    { 0x1b, "]", 0 },
+    { 0x1a, "{", 1 },
+    { 0x1b, "}", 1 },
+
+    { 0x27, ";", 0 },
+    { 0x28, "'", 0 },
+    { 0x29, "`", 0 },
+    { 0x2b, "\\", 0 },
+
+    { 0x27, ":", 1 },
+    { 0x28, "\"", 1 },
+    { 0x29, "~", 1 },
+    { 0x2b, "|", 1 },
+
+    { 0x33, ",", 0 },
+    { 0x34, ".", 0 },
+    { 0x35, "/", 0 },
+    { 0x33, "<", 1 },
+    { 0x34, ">", 1 },
+    { 0x35, "?", 1 },
+
+    { 0x39, "spc", 0 },
+    { 0x39, " ", 0 },
+    { 0x3a, "caps_lock", 0 },
+    { 0x3b, "f1", 0 },
+    { 0x3c, "f2", 0 },
+    { 0x3d, "f3", 0 },
+    { 0x3e, "f4", 0 },
+    { 0x3f, "f5", 0 },
+    { 0x40, "f6", 0 },
+    { 0x41, "f7", 0 },
+    { 0x42, "f8", 0 },
+    { 0x43, "f9", 0 },
+    { 0x44, "f10", 0 },
+    { 0x45, "num_lock", 0 },
+    { 0x46, "scroll_lock", 0 },
+
+    { 0x4a, "-", 0},
+    { 0x4e, "+", 0},
+
+    { 0xb5, "kp_divide", 0 },
+    { 0x37, "kp_multiply", 0 },
+    { 0x4a, "kp_subtract", 0 },
+    { 0x4e, "kp_add", 0 },
+    { 0x9c, "kp_enter", 0 },
+    { 0x53, "kp_decimal", 0 },
+
+    { 0x52, "kp_0", 0 },
+    { 0x4f, "kp_1", 0 },
+    { 0x50, "kp_2", 0 },
+    { 0x51, "kp_3", 0 },
+    { 0x4b, "kp_4", 0 },
+    { 0x4c, "kp_5", 0 },
+    { 0x4d, "kp_6", 0 },
+    { 0x47, "kp_7", 0 },
+    { 0x48, "kp_8", 0 },
+    { 0x49, "kp_9", 0 },
+
+    { 0x57, "f11", 0 },
+    { 0x58, "f12", 0 },
+
+    { 0xb7, "print", 0 },
+
+    { 0xc7, "home", 0 },
+    { 0xc9, "pgup", 0 },
+    { 0xd1, "pgdn", 0 },
+    { 0xcf, "end", 0 },
+
+    { 0xcb, "left", 0 },
+    { 0xc8, "up", 0 },
+    { 0xd0, "down", 0 },
+    { 0xcd, "right", 0 },
 
-    { 0xd2, "insert" },
-    { 0xd3, "delete" },
+    { 0xd2, "insert", 0 },
+    { 0xd3, "delete", 0 },
     { 0, NULL },
 };
 
@@ -897,6 +967,17 @@
     return -1;
 }
 
+static int is_shift_needed(const char *key)
+{
+    const KeyDef *p;
+
+    for(p = key_defs; p->name != NULL; p++) {
+        if (!strcmp(key, p->name))
+            return p->need_shift;
+    }
+    return -1;
+}
+
 static void do_send_key(const char *string)
 {
     char keybuf[16], *q;
@@ -941,6 +1022,50 @@
     }
 }
 
+static void do_send_string(const char *str)
+{
+    char keybuf[2];
+    const char *p = str;
+    int keycode;
+
+    keybuf[0] = '\0';
+    keybuf[1] = '\0';
+
+    while (*p != '\0') {
+        keybuf[0] = *p;
+        keycode = get_keycode(keybuf);
+        int shift_needed = is_shift_needed(keybuf);
+        if (keycode < 0) {
+            term_printf("unknown key: '%s'\n", keybuf);
+            return;
+        }
+
+        // Press shift if needed
+        if (shift_needed)
+        {
+            kbd_put_keycode(0x2a & 0x7f);
+        }
+
+        // Key down event
+        if (keycode & 0x80)
+            kbd_put_keycode(0xe0);
+        kbd_put_keycode(keycode & 0x7f);
+
+        // Key up event
+        if (keycode & 0x80)
+            kbd_put_keycode(0xe0);
+        kbd_put_keycode(keycode | 0x80);
+
+        // Release shift if needed
+        if (shift_needed)
+        {
+            kbd_put_keycode(0x2a | 0x80);
+        }
+
+        p++;
+    }
+}
+
 static int mouse_button_state;
 
 static void do_mouse_move(const char *dx_str, const char *dy_str,
@@ -1299,6 +1424,8 @@
 
     { "sendkey", "s", do_send_key,
       "keys", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1')" },
+    { "sendstring", "s", do_send_string,
+      "string", "send strings to the VM (e.g. 'sendstring abc')" },
     { "system_reset", "", do_system_reset,
       "", "reset the system" },
     { "system_powerdown", "", do_system_powerdown,
