]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(Vthis_command_keys_shift_translated): New var.
[gnu-emacs] / src / keyboard.c
index 1a09436557e3028d69eb211b8d4b41c1a5c9b700..526586f17f22a11ac43774dd7dd29e02277619d0 100644 (file)
@@ -1,7 +1,7 @@
 /* Keyboard and mouse input; editor command loop.
    Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993, 1994, 1995,
                  1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -33,7 +33,7 @@ Boston, MA 02110-1301, USA.  */
 #include "window.h"
 #include "commands.h"
 #include "buffer.h"
-#include "charset.h"
+#include "character.h"
 #include "disptab.h"
 #include "dispextern.h"
 #include "syntax.h"
@@ -95,35 +95,7 @@ volatile int interrupt_input_blocked;
    during the current critical section.  */
 int interrupt_input_pending;
 
-
-#ifdef HAVE_WINDOW_SYSTEM
-/* Make all keyboard buffers much bigger when using X windows.  */
-#ifdef MAC_OS8
-/* But not too big (local data > 32K error) if on Mac OS Classic.  */
-#define KBD_BUFFER_SIZE 512
-#else
-#define KBD_BUFFER_SIZE 4096
-#endif
-#else  /* No X-windows, character input */
 #define KBD_BUFFER_SIZE 4096
-#endif /* No X-windows */
-
-#define abs(x)         ((x) >= 0 ? (x) : -(x))
-
-/* Following definition copied from eval.c */
-
-struct backtrace
-  {
-    struct backtrace *next;
-    Lisp_Object *function;
-    Lisp_Object *args; /* Points to vector of args. */
-    int nargs;         /* length of vector.  If nargs is UNEVALLED,
-                          args points to slot holding list of
-                          unevalled args */
-    char evalargs;
-    /* Nonzero means call value of debugger when done with this operation. */
-    char debug_on_exit;
-  };
 
 #ifdef MULTI_KBOARD
 KBOARD *initial_kboard;
@@ -160,16 +132,12 @@ int this_command_key_count_reset;
 Lisp_Object raw_keybuf;
 int raw_keybuf_count;
 
+/* Non-nil if the present key sequence was obtained by shift translation.  */
+Lisp_Object Vthis_command_keys_shift_translated;
+
 #define GROW_RAW_KEYBUF                                                        \
  if (raw_keybuf_count == XVECTOR (raw_keybuf)->size)                   \
-  {                                                                    \
-    int newsize = 2 * XVECTOR (raw_keybuf)->size;                      \
-    Lisp_Object new;                                                   \
-    new = Fmake_vector (make_number (newsize), Qnil);                  \
-    bcopy (XVECTOR (raw_keybuf)->contents, XVECTOR (new)->contents,    \
-          raw_keybuf_count * sizeof (Lisp_Object));                    \
-    raw_keybuf = new;                                                  \
-  }
+   raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
 
 /* Number of elements of this_command_keys
    that precede this key sequence.  */
@@ -184,8 +152,6 @@ extern int minbuf_level;
 
 extern int message_enable_multibyte;
 
-extern struct backtrace *backtrace_list;
-
 /* If non-nil, the function that implements the display of help.
    It's called with one argument, the help string to display.  */
 
@@ -447,7 +413,7 @@ Lisp_Object Qcommand_hook_internal, Vcommand_hook_internal;
 /* Parent keymap of terminal-local function-key-map instances.  */
 Lisp_Object Vfunction_key_map;
 
-/* Parent keymap of terminal-local key-translation-map instances.  */
+/* Keymap of key translations that can override keymaps.  */
 Lisp_Object Vkey_translation_map;
 
 /* List of deferred actions to be performed at a later time.
@@ -523,7 +489,9 @@ Lisp_Object Qsave_session;
 #ifdef MAC_OS
 Lisp_Object Qmac_apple_event;
 #endif
-
+#ifdef HAVE_DBUS
+Lisp_Object Qdbus_event;
+#endif
 /* Lisp_Object Qmouse_movement; - also an event header */
 
 /* Properties of event headers.  */
@@ -693,8 +661,6 @@ static int store_user_signal_events P_ ((void));
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
 static int cannot_suspend;
-
-extern Lisp_Object Qidentity, Qonly;
 \f
 /* Install the string STR as the beginning of the string of echoing,
    so that it serves as a prompt for the next character.
@@ -953,7 +919,7 @@ add_command_key (key)
                                       2 * ASIZE (this_command_keys),
                                       Qnil);
 
-  AREF (this_command_keys, this_command_key_count) = key;
+  ASET (this_command_keys, this_command_key_count, key);
   ++this_command_key_count;
 }
 
@@ -970,7 +936,7 @@ recursive_edit_1 ()
       specbind (Qstandard_input, Qt);
     }
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   /* The command loop has started an hourglass timer, so we have to
      cancel it here, otherwise it will fire because the recursive edit
      can take some time.  Do not check for display_hourglass_p here,
@@ -1255,7 +1221,7 @@ cmd_error (data)
   Lisp_Object old_level, old_length;
   char macroerror[50];
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
@@ -1431,7 +1397,7 @@ DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
        doc: /* Exit all recursive editing levels.  */)
      ()
 {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
@@ -1554,7 +1520,7 @@ static void adjust_point_for_property P_ ((int, int));
 
 /* Cancel hourglass from protect_unwind.
    ARG is not used.  */
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
 static Lisp_Object
 cancel_hourglass_unwind (arg)
      Lisp_Object arg;
@@ -1572,14 +1538,13 @@ command_loop_1 ()
   int nonundocount;
   Lisp_Object keybuf[30];
   int i;
-  int no_direct;
   int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
 #if 0 /* This shouldn't be necessary anymore.  --lorentey  */
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
 #endif
-#endif  
+#endif
   int already_adjusted = 0;
 
   current_kboard->Vprefix_arg = Qnil;
@@ -1614,6 +1579,8 @@ command_loop_1 ()
   /* Do this after running Vpost_command_hook, for consistency.  */
   current_kboard->Vlast_command = Vthis_command;
   current_kboard->Vreal_last_command = real_this_command;
+  if (!CONSP (last_command_char))
+    current_kboard->Vlast_repeatable_command = real_this_command;
 
   while (1)
     {
@@ -1630,8 +1597,6 @@ command_loop_1 ()
       while (pending_malloc_warning)
        display_malloc_warning ();
 
-      no_direct = 0;
-
       Vdeactivate_mark = Qnil;
 
       /* If minibuffer on and echo area in use,
@@ -1639,17 +1604,15 @@ command_loop_1 ()
 
       if (minibuf_level
          && !NILP (echo_area_buffer[0])
-         && EQ (minibuf_window, echo_area_window))
+         && EQ (minibuf_window, echo_area_window)
+         && NUMBERP (Vminibuffer_message_timeout))
        {
          /* Bind inhibit-quit to t so that C-g gets read in
             rather than quitting back to the minibuffer.  */
          int count = SPECPDL_INDEX ();
          specbind (Qinhibit_quit, Qt);
 
-         if (NUMBERP (Vminibuffer_message_timeout))
-           sit_for (Vminibuffer_message_timeout, 0, 2);
-         else
-           sit_for (Qt, 0, 2);
+         sit_for (Vminibuffer_message_timeout, 0, 2);
 
          /* Clear the echo area.  */
          message2 (0, 0, 0);
@@ -1686,6 +1649,7 @@ command_loop_1 ()
       Vthis_command = Qnil;
       real_this_command = Qnil;
       Vthis_original_command = Qnil;
+      Vthis_command_keys_shift_translated = Qnil;
 
       /* Read next key sequence; i gets its length.  */
       i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
@@ -1792,14 +1756,16 @@ command_loop_1 ()
        }
       else
        {
-         if (NILP (current_kboard->Vprefix_arg) && ! no_direct)
+         if (NILP (current_kboard->Vprefix_arg))
            {
              /* In case we jump to directly_done.  */
              Vcurrent_prefix_arg = current_kboard->Vprefix_arg;
 
              /* Recognize some common commands in common situations and
                 do them directly.  */
-             if (EQ (Vthis_command, Qforward_char) && PT < ZV)
+             if (EQ (Vthis_command, Qforward_char) && PT < ZV
+                 && NILP (Vthis_command_keys_shift_translated)
+                 && !CONSP (Vtransient_mark_mode))
                {
                   struct Lisp_Char_Table *dp
                    = window_display_table (XWINDOW (selected_window));
@@ -1824,7 +1790,7 @@ command_loop_1 ()
                          : (lose >= 0x20 && lose < 0x7f))
                      /* To extract the case of continuation on
                          wide-column characters.  */
-                     && (WIDTH_BY_CHAR_HEAD (FETCH_BYTE (PT_BYTE)) == 1)
+                     && ASCII_BYTE_P (lose)
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_overlay_modified)
@@ -1839,7 +1805,9 @@ command_loop_1 ()
                    direct_output_forward_char (1);
                  goto directly_done;
                }
-             else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV)
+             else if (EQ (Vthis_command, Qbackward_char) && PT > BEGV
+                      && NILP (Vthis_command_keys_shift_translated)
+                      && !CONSP (Vtransient_mark_mode))
                {
                   struct Lisp_Char_Table *dp
                    = window_display_table (XWINDOW (selected_window));
@@ -1881,7 +1849,7 @@ command_loop_1 ()
                {
                  unsigned int c
                    = translate_char (Vtranslation_table_for_input,
-                                     XFASTINT (last_command_char), 0, 0, 0);
+                                     XFASTINT (last_command_char));
                  int value;
                  if (NILP (Vexecuting_kbd_macro)
                      && !EQ (minibuf_window, selected_window))
@@ -1929,7 +1897,7 @@ command_loop_1 ()
          /* Here for a command that isn't executed directly */
 
           {
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
             int scount = SPECPDL_INDEX ();
 
             if (display_hourglass_p
@@ -1945,7 +1913,7 @@ command_loop_1 ()
               Fundo_boundary ();
             Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil);
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
          /* Do not check display_hourglass_p here, because
             Fcommand_execute could change it, but we should cancel
             hourglass cursor anyway.
@@ -1989,6 +1957,8 @@ command_loop_1 ()
        {
          current_kboard->Vlast_command = Vthis_command;
          current_kboard->Vreal_last_command = real_this_command;
+         if (!CONSP (last_command_char))
+           current_kboard->Vlast_repeatable_command = real_this_command;
          cancel_echoing ();
          this_command_key_count = 0;
          this_command_key_count_reset = 0;
@@ -1997,14 +1967,6 @@ command_loop_1 ()
 
       if (!NILP (current_buffer->mark_active) && !NILP (Vrun_hooks))
        {
-         /* Setting transient-mark-mode to `only' is a way of
-            turning it on for just one command.  */
-
-         if (EQ (Vtransient_mark_mode, Qidentity))
-           Vtransient_mark_mode = Qnil;
-         if (EQ (Vtransient_mark_mode, Qonly))
-           Vtransient_mark_mode = Qidentity;
-
          if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
            {
              /* We could also call `deactivate'mark'.  */
@@ -2058,7 +2020,7 @@ adjust_point_for_property (last_pt, modified)
      int last_pt;
      int modified;
 {
-  int beg, end;
+  EMACS_INT beg, end;
   Lisp_Object val, overlay, tmp;
   int check_composition = 1, check_display = 1, check_invisible = 1;
   int orig_pt = PT;
@@ -2388,6 +2350,9 @@ make_ctrl_char (c)
   /* Save the upper bits here.  */
   int upper = c & ~0177;
 
+  if (! ASCII_BYTE_P (c))
+    return c |= ctrl_modifier;
+
   c &= 0177;
 
   /* Everything in the columns containing the upper-case letters
@@ -2571,7 +2536,7 @@ do { if (polling_stopped_here) start_polling ();  \
    USED_MOUSE_MENU is null, we don't dereference it.
 
    Value is -2 when we find input on another keyboard.  A second call
-   to read_char will read it. 
+   to read_char will read it.
 
    If END_TIME is non-null, it is a pointer to an EMACS_TIME
    specifying the maximum time to wait until.  If no input arrives by
@@ -2738,6 +2703,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
   /* if redisplay was requested */
   if (commandflag >= 0)
     {
+      int echo_current = EQ (echo_message_buffer, echo_area_buffer[0]);
+
        /* If there is pending input, process any events which are not
           user-visible, such as X selection_request events.  */
       if (input_pending
@@ -2761,6 +2728,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
          swallow_events (0);
          /* If that cleared input_pending, try again to redisplay.  */
        }
+
+      /* Prevent the redisplay we just did
+        from messing up echoing of the input after the prompt.  */
+      if (commandflag == 0 && echo_current)
+       echo_message_buffer = echo_area_buffer[0];
+
     }
 
   /* Message turns off echoing unless more keystrokes turn it on again.
@@ -3186,7 +3159,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
       int count = SPECPDL_INDEX ();
       record_single_kboard_state ();
 #endif
-      
+
       last_input_char = c;
       Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
 
@@ -3219,7 +3192,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time)
          || (VECTORP (current_kboard->Vkeyboard_translate_table)
              && XVECTOR (current_kboard->Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
          || (CHAR_TABLE_P (current_kboard->Vkeyboard_translate_table)
-             && CHAR_VALID_P (XINT (c), 0)))
+             && CHARACTERP (c)))
        {
          Lisp_Object d;
          d = Faref (current_kboard->Vkeyboard_translate_table, c);
@@ -4022,9 +3995,6 @@ discard_mouse_events ()
       if (sp->kind == MOUSE_CLICK_EVENT
          || sp->kind == WHEEL_EVENT
           || sp->kind == HORIZ_WHEEL_EVENT
-#ifdef WINDOWSNT
-         || sp->kind == W32_SCROLL_BAR_CLICK_EVENT
-#endif
 #ifdef HAVE_GPM
          || sp->kind == GPM_CLICK_EVENT
 #endif
@@ -4100,6 +4070,12 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
   /* Wait until there is input available.  */
   for (;;)
     {
+      /* Break loop if there's an unread command event.  Needed in
+        moused window autoselection which uses a timer to insert such
+        events.  */
+      if (CONSP (Vunread_command_events))
+       break;
+
       if (kbd_fetch_ptr != kbd_store_ptr)
        break;
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
@@ -4311,6 +4287,13 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          internal_last_event_frame = frame;
          kbd_fetch_ptr = event + 1;
        }
+#ifdef HAVE_DBUS
+      else if (event->kind == DBUS_EVENT)
+       {
+         obj = make_lispy_event (event);
+         kbd_fetch_ptr = event + 1;
+       }
+#endif
       else
        {
          /* If this event is on a different frame, return a switch-frame this
@@ -4520,6 +4503,13 @@ timer_resume_idle ()
 /* This is only for debugging.  */
 struct input_event last_timer_event;
 
+/* List of elisp functions to call, delayed because they were generated in
+   a context where Elisp could not be safely run (e.g. redisplay, signal,
+   ...).  Each lement has the form (FUN . ARGS).  */
+Lisp_Object pending_funcalls;
+
+extern Lisp_Object Qapply;
+
 /* Check whether a timer has fired.  To prevent larger problems we simply
    disregard elements that are not proper timers.  Do not make a circular
    timer list for the time being.
@@ -4556,6 +4546,14 @@ timer_check (do_it_now)
   chosen_timer = Qnil;
   GCPRO3 (timers, idle_timers, chosen_timer);
 
+  /* First run the code that was delayed.  */
+  while (CONSP (pending_funcalls))
+    {
+      Lisp_Object funcall = XCAR (pending_funcalls);
+      pending_funcalls = XCDR (pending_funcalls);
+      safe_call2 (Qapply, XCAR (funcall), XCDR (funcall));
+    }
+
   if (CONSP (timers) || CONSP (idle_timers))
     {
       EMACS_GET_TIME (now);
@@ -4715,12 +4713,14 @@ timer_check (do_it_now)
 }
 
 DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0,
-       doc: /* Return the current length of Emacs idleness.
-The value is returned as a list of three integers.  The first has the
+       doc: /* Return the current length of Emacs idleness, or nil.
+The value when Emacs is idle is a list of three integers.  The first has the
 most significant 16 bits of the seconds, while the second has the
 least significant 16 bits.  The third integer gives the microsecond
 count.
 
+The value when Emacs is not idle is nil.
+
 The microsecond count is zero on systems that do not provide
 resolution finer than a second.  */)
   ()
@@ -4910,13 +4910,17 @@ char *lispy_function_keys[] =
     0,                /* VK_MENU           0x12 */
     "pause",          /* VK_PAUSE          0x13 */
     "capslock",       /* VK_CAPITAL        0x14 */
-
-    0, 0, 0, 0, 0, 0, /*    0x15 .. 0x1A        */
-
+    "kana",           /* VK_KANA/VK_HANGUL 0x15 */
+    0,                /*    0x16                */
+    "junja",          /* VK_JUNJA          0x17 */
+    "final",          /* VK_FINAL          0x18 */
+    "kanji",          /* VK_KANJI/VK_HANJA 0x19 */
+    0,                /*    0x1A                */
     "escape",         /* VK_ESCAPE         0x1B */
-
-    0, 0, 0, 0,       /*    0x1C .. 0x1F        */
-
+    "convert",        /* VK_CONVERT        0x1C */
+    "non-convert",    /* VK_NONCONVERT     0x1D */
+    "accept",         /* VK_ACCEPT         0x1E */
+    "mode-change",    /* VK_MODECHANGE     0x1F */
     0,                /* VK_SPACE          0x20 */
     "prior",          /* VK_PRIOR          0x21 */
     "next",           /* VK_NEXT           0x22 */
@@ -4949,9 +4953,8 @@ char *lispy_function_keys[] =
     "lwindow",       /* VK_LWIN           0x5B */
     "rwindow",       /* VK_RWIN           0x5C */
     "apps",          /* VK_APPS           0x5D */
-
-    0, 0,            /*    0x5E .. 0x5F        */
-
+    0,               /*    0x5E                */
+    "sleep",
     "kp-0",          /* VK_NUMPAD0        0x60 */
     "kp-1",          /* VK_NUMPAD1        0x61 */
     "kp-2",          /* VK_NUMPAD2        0x62 */
@@ -4998,7 +5001,9 @@ char *lispy_function_keys[] =
 
     "kp-numlock",    /* VK_NUMLOCK        0x90 */
     "scroll",        /* VK_SCROLL         0x91 */
-
+    /* Not sure where the following block comes from.
+       Windows headers have NEC and Fujitsu specific keys in
+       this block, but nothing generic.  */
     "kp-space",             /* VK_NUMPAD_CLEAR   0x92 */
     "kp-enter",             /* VK_NUMPAD_ENTER   0x93 */
     "kp-prior",             /* VK_NUMPAD_PRIOR   0x94 */
@@ -5018,19 +5023,47 @@ char *lispy_function_keys[] =
      * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
      * Used only as parameters to GetAsyncKeyState and GetKeyState.
      * No other API or message will distinguish left and right keys this way.
+     * 0xA0 .. 0xA5
      */
-    /* 0xA0 .. 0xEF */
+    0, 0, 0, 0, 0, 0,
 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    /* Multimedia keys. These are handled as WM_APPCOMMAND, which allows us
+       to enable them selectively, and gives access to a few more functions.
+       See lispy_multimedia_keys below.  */
+    0, 0, 0, 0, 0, 0, 0, /* 0xA6 .. 0xAC        Browser */
+    0, 0, 0,             /* 0xAD .. 0xAF         Volume */
+    0, 0, 0, 0,          /* 0xB0 .. 0xB3          Media */
+    0, 0, 0, 0,          /* 0xB4 .. 0xB7           Apps */
 
-    /* 0xF0 .. 0xF5 */
+    /* 0xB8 .. 0xC0 "OEM" keys - all seem to be punctuation.  */
+    0, 0, 0, 0, 0, 0, 0, 0, 0,
 
-    0, 0, 0, 0, 0, 0,
+    /* 0xC1 - 0xDA unallocated, 0xDB-0xDF more OEM keys */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
+    0,               /* 0xE0                   */
+    "ax",            /* VK_OEM_AX         0xE1 */
+    0,               /* VK_OEM_102        0xE2 */
+    "ico-help",      /* VK_ICO_HELP       0xE3 */
+    "ico-00",        /* VK_ICO_00         0xE4 */
+    0,               /* VK_PROCESSKEY     0xE5 */
+    "ico-clear",     /* VK_ICO_CLEAR      0xE6 */
+    "packet",        /* VK_PACKET         0xE7 */
+    0,               /*                   0xE8 */
+    "reset",         /* VK_OEM_RESET      0xE9 */
+    "jump",          /* VK_OEM_JUMP       0xEA */
+    "oem-pa1",       /* VK_OEM_PA1        0xEB */
+    "oem-pa2",       /* VK_OEM_PA2        0xEC */
+    "oem-pa3",       /* VK_OEM_PA3        0xED */
+    "wsctrl",        /* VK_OEM_WSCTRL     0xEE */
+    "cusel",         /* VK_OEM_CUSEL      0xEF */
+    "oem-attn",      /* VK_OEM_ATTN       0xF0 */
+    "finish",        /* VK_OEM_FINISH     0xF1 */
+    "copy",          /* VK_OEM_COPY       0xF2 */
+    "auto",          /* VK_OEM_AUTO       0xF3 */
+    "enlw",          /* VK_OEM_ENLW       0xF4 */
+    "backtab",       /* VK_OEM_BACKTAB    0xF5 */
     "attn",          /* VK_ATTN           0xF6 */
     "crsel",         /* VK_CRSEL          0xF7 */
     "exsel",         /* VK_EXSEL          0xF8 */
@@ -5043,6 +5076,65 @@ char *lispy_function_keys[] =
     0 /* 0xFF */
   };
 
+/* Some of these duplicate the "Media keys" on newer keyboards,
+   but they are delivered to the application in a different way.  */
+static char *lispy_multimedia_keys[] =
+  {
+    0,
+    "browser-back",
+    "browser-forward",
+    "browser-refresh",
+    "browser-stop",
+    "browser-search",
+    "browser-favorites",
+    "browser-home",
+    "volume-mute",
+    "volume-down",
+    "volume-up",
+    "media-next",
+    "media-previous",
+    "media-stop",
+    "media-play-pause",
+    "mail",
+    "media-select",
+    "app-1",
+    "app-2",
+    "bass-down",
+    "bass-boost",
+    "bass-up",
+    "treble-down",
+    "treble-up",
+    "mic-volume-mute",
+    "mic-volume-down",
+    "mic-volume-up",
+    "help",
+    "find",
+    "new",
+    "open",
+    "close",
+    "save",
+    "print",
+    "undo",
+    "redo",
+    "copy",
+    "cut",
+    "paste",
+    "mail-reply",
+    "mail-forward",
+    "mail-send",
+    "spell-check",
+    "toggle-dictate-command",
+    "mic-toggle",
+    "correction-list",
+    "media-play",
+    "media-pause",
+    "media-record",
+    "media-fast-forward",
+    "media-rewind",
+    "media-channel-up",
+    "media-channel-down"
+  };
+
 #else /* not HAVE_NTGUI */
 
 /* This should be dealt with in XTread_socket now, and that doesn't
@@ -5457,41 +5549,32 @@ make_lispy_event (event)
     {
       /* A simple keystroke.  */
     case ASCII_KEYSTROKE_EVENT:
-      {
-       Lisp_Object lispy_c;
-       int c = event->code & 0377;
-       /* Turn ASCII characters into control characters
-          when proper.  */
-       if (event->modifiers & ctrl_modifier)
-         c = make_ctrl_char (c);
-
-       /* Add in the other modifier bits.  We took care of ctrl_modifier
-          just above, and the shift key was taken care of by the X code,
-          and applied to control characters by make_ctrl_char.  */
-       c |= (event->modifiers
-             & (meta_modifier | alt_modifier
-                | hyper_modifier | super_modifier));
-       /* Distinguish Shift-SPC from SPC.  */
-       if ((event->code & 0377) == 040
-           && event->modifiers & shift_modifier)
-         c |= shift_modifier;
-       button_down_time = 0;
-       XSETFASTINT (lispy_c, c);
-       return lispy_c;
-      }
-
     case MULTIBYTE_CHAR_KEYSTROKE_EVENT:
       {
        Lisp_Object lispy_c;
        int c = event->code;
+       if (event->kind == ASCII_KEYSTROKE_EVENT)
+         {
+           c &= 0377;
+           eassert (c == event->code);
+           /* Turn ASCII characters into control characters
+              when proper.  */
+           if (event->modifiers & ctrl_modifier)
+             {
+               c = make_ctrl_char (c);
+               event->modifiers &= ~ctrl_modifier;
+             }
+         }
 
-       /* Add in the other modifier bits.  We took care of ctrl_modifier
-          just above, and the shift key was taken care of by the X code,
-          and applied to control characters by make_ctrl_char.  */
+       /* Add in the other modifier bits.  The shift key was taken care
+          of by the X code.  */
        c |= (event->modifiers
              & (meta_modifier | alt_modifier
                 | hyper_modifier | super_modifier | ctrl_modifier));
-       /* What about the `shift' modifier ?  */
+       /* Distinguish Shift-SPC from SPC.  */
+       if ((event->code) == 040
+           && event->modifiers & shift_modifier)
+         c |= shift_modifier;
        button_down_time = 0;
        XSETFASTINT (lispy_c, c);
        return lispy_c;
@@ -5560,6 +5643,21 @@ make_lispy_event (event)
                                  (sizeof (lispy_function_keys)
                                   / sizeof (lispy_function_keys[0])));
 
+#ifdef WINDOWSNT
+    case MULTIMEDIA_KEY_EVENT:
+      if (event->code < (sizeof (lispy_multimedia_keys)
+                         / sizeof (lispy_multimedia_keys[0]))
+          && event->code > 0 && lispy_multimedia_keys[event->code])
+        {
+          return modify_event_symbol (event->code, event->modifiers,
+                                      Qfunction_key, Qnil,
+                                      lispy_multimedia_keys, &func_key_syms,
+                                      (sizeof (lispy_multimedia_keys)
+                                       / sizeof (lispy_multimedia_keys[0])));
+        }
+      return Qnil;
+#endif
+
 #ifdef HAVE_MOUSE
       /* A mouse click.  Figure out where it is, decide whether it's
          a press, click or drag, and build the appropriate structure.  */
@@ -5706,8 +5804,8 @@ make_lispy_event (event)
            fuzz = double_click_fuzz / 8;
 
          is_double = (button == last_mouse_button
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
@@ -5875,8 +5973,8 @@ make_lispy_event (event)
            fuzz = double_click_fuzz / 8;
 
          is_double = (last_mouse_button < 0
-                      && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
-                      && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+                      && (eabs (XINT (event->x) - last_mouse_x) <= fuzz)
+                      && (eabs (XINT (event->y) - last_mouse_y) <= fuzz)
                       && button_down_time != 0
                       && (EQ (Vdouble_click_time, Qt)
                           || (INTEGERP (Vdouble_click_time)
@@ -6000,52 +6098,6 @@ make_lispy_event (event)
 
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
-#ifdef WINDOWSNT
-    case W32_SCROLL_BAR_CLICK_EVENT:
-      {
-       int button = event->code;
-       int is_double;
-       Lisp_Object position;
-       Lisp_Object *start_pos_ptr;
-       Lisp_Object start_pos;
-
-       {
-         Lisp_Object window;
-         Lisp_Object portion_whole;
-         Lisp_Object part;
-
-         window = event->frame_or_window;
-         portion_whole = Fcons (event->x, event->y);
-         part = *scroll_bar_parts[(int) event->part];
-
-         position
-           = Fcons (window,
-                    Fcons (Qvertical_scroll_bar,
-                           Fcons (portion_whole,
-                                  Fcons (make_number (event->timestamp),
-                                         Fcons (part, Qnil)))));
-       }
-
-       /* Always treat W32 scroll bar events as clicks. */
-       event->modifiers |= click_modifier;
-
-       {
-         /* Get the symbol we should use for the mouse click.  */
-         Lisp_Object head;
-
-         head = modify_event_symbol (button,
-                                     event->modifiers,
-                                     Qmouse_click,
-                                     Vlispy_mouse_stem,
-                                     NULL, &mouse_syms,
-                                     XVECTOR (mouse_syms)->size);
-         return Fcons (head,
-                       Fcons (position,
-                              Qnil));
-       }
-      }
-#endif /* WINDOWSNT */
-
     case DRAG_N_DROP_EVENT:
       {
        FRAME_PTR f;
@@ -6126,6 +6178,13 @@ make_lispy_event (event)
       }
 #endif
 
+#ifdef HAVE_DBUS
+    case DBUS_EVENT:
+      {
+       return Fcons (Qdbus_event, event->arg);
+      }
+#endif /* HAVE_DBUS */
+
 #ifdef HAVE_GPM
     case GPM_CLICK_EVENT:
       {
@@ -6444,12 +6503,21 @@ lispy_modifier_list (modifiers)
    SYMBOL's Qevent_symbol_element_mask property, and maintains the
    Qevent_symbol_elements property.  */
 
+#define KEY_TO_CHAR(k) (XINT (k) & ((1 << CHARACTERBITS) - 1))
+
 Lisp_Object
 parse_modifiers (symbol)
      Lisp_Object symbol;
 {
   Lisp_Object elements;
 
+  if (INTEGERP (symbol))
+    return (Fcons (make_number (KEY_TO_CHAR (symbol)),
+                  Fcons (make_number (XINT (symbol) & CHAR_MODIFIER_MASK),
+                         Qnil)));
+  else if (!SYMBOLP (symbol))
+    return Qnil;
+
   elements = Fget (symbol, Qevent_symbol_element_mask);
   if (CONSP (elements))
     return elements;
@@ -6484,6 +6552,20 @@ parse_modifiers (symbol)
     }
 }
 
+DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,
+       Sevent_symbol_parse_modifiers, 1, 1, 0,
+       doc: /* Parse the event symbol.  For internal use.  */)
+     (symbol)
+     Lisp_Object symbol;
+{
+  /* Fill the cache if needed.  */
+  parse_modifiers (symbol);
+  /* Ignore the result (which is stored on Qevent_symbol_element_mask)
+     and use the Lispier representation stored on Qevent_symbol_elements
+     instead.  */
+  return Fget (symbol, Qevent_symbol_elements);
+}
+
 /* Apply the modifiers MODIFIERS to the symbol BASE.
    BASE must be unmodified.
 
@@ -6503,6 +6585,9 @@ apply_modifiers (modifiers, base)
   /* Mask out upper bits.  We don't know where this value's been.  */
   modifiers &= INTMASK;
 
+  if (INTEGERP (base))
+    return make_number (XINT (base) | modifiers);
+
   /* The click modifier never figures into cache indices.  */
   cache = Fget (base, Qmodifier_cache);
   XSETFASTINT (index, (modifiers & ~click_modifier));
@@ -6914,6 +6999,11 @@ void
 gobble_input (expected)
      int expected;
 {
+#ifdef HAVE_DBUS
+  /* Check whether a D-Bus message has arrived.  */
+  xd_read_queued_messages ();
+#endif /* HAVE_DBUS */
+
 #ifndef VMS
 #ifdef SIGIO
   if (interrupt_input)
@@ -7033,7 +7123,7 @@ read_avail_input (expected)
               nread += nr;
               expected = 0;
             }
-          
+
           if (nr == -1)          /* Not OK to read input now. */
             {
               err = 1;
@@ -7041,7 +7131,7 @@ read_avail_input (expected)
           else if (nr == -2)          /* Non-transient error. */
             {
               /* The terminal device terminated; it should be closed. */
-              
+
               /* Kill Emacs if this was our last terminal. */
               if (!terminal_list->next_terminal)
                 /* Formerly simply reported no input, but that
@@ -7053,12 +7143,13 @@ read_avail_input (expected)
                    group?  Perhaps on systems with FIONREAD Emacs is
                    alone in its group.  */
                 kill (getpid (), SIGHUP);
-              
+
               /* XXX Is calling delete_terminal safe here?  It calls Fdelete_frame. */
-              if (t->delete_terminal_hook)
-                (*t->delete_terminal_hook) (t);
-              else
-                delete_terminal (t);
+             {
+               Lisp_Object tmp;
+               XSETTERMINAL (tmp, t);
+               Fdelete_terminal (tmp, Qnoelisp);
+             }
             }
 
           if (hold_quit.kind != NO_EVENT)
@@ -7094,7 +7185,7 @@ tty_read_avail_input (struct terminal *terminal,
   int nread = 0;
 
   if (!terminal->name)         /* Don't read from a dead terminal. */
-    return;
+    return 0;
 
   if (terminal->type != output_termcap)
     abort ();
@@ -7121,7 +7212,7 @@ tty_read_avail_input (struct terminal *terminal,
     return 0;                   /* The terminal is suspended. */
 
 #ifdef HAVE_GPM
-  if (term_gpm && gpm_tty == tty->terminal->id)
+  if (gpm_tty == tty)
   {
       Gpm_Event event;
       struct input_event hold_quit;
@@ -7155,7 +7246,7 @@ tty_read_avail_input (struct terminal *terminal,
   if (n_to_read > sizeof cbuf)
     n_to_read = sizeof cbuf;
 #else /* no FIONREAD */
-#if defined (USG) || defined (DGUX) || defined(CYGWIN)
+#if defined (USG) || defined(CYGWIN)
   /* Read some input if available, but don't wait.  */
   n_to_read = sizeof cbuf;
   fcntl (fileno (tty->input), F_SETFL, O_NDELAY);
@@ -7176,7 +7267,7 @@ tty_read_avail_input (struct terminal *terminal,
          Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
       if (nread == -1 && errno == EIO)
         return -2;          /* Close this terminal. */
-#if defined (AIX) && (! defined (aix386) && defined (_BSD))
+#if defined (AIX) && defined (_BSD)
       /* The kernel sometimes fails to deliver SIGHUP for ptys.
          This looks incorrect, but it isn't, because _BSD causes
          O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
@@ -7205,9 +7296,9 @@ tty_read_avail_input (struct terminal *terminal,
          );
 
 #ifndef FIONREAD
-#if defined (USG) || defined (DGUX) || defined (CYGWIN)
+#if defined (USG) || defined (CYGWIN)
   fcntl (fileno (tty->input), F_SETFL, 0);
-#endif /* USG or DGUX or CYGWIN */
+#endif /* USG or CYGWIN */
 #endif /* no FIONREAD */
 
   if (nread <= 0)
@@ -7226,14 +7317,14 @@ tty_read_avail_input (struct terminal *terminal,
         buf.modifiers = meta_modifier;
       if (tty->meta_key != 2)
         cbuf[i] &= ~0x80;
-      
+
       buf.code = cbuf[i];
       /* Set the frame corresponding to the active tty.  Note that the
          value of selected_frame is not reliable here, redisplay tends
          to temporarily change it. */
       buf.frame_or_window = tty->top_frame;
       buf.arg = Qnil;
-      
+
       kbd_buffer_store_event (&buf);
       /* Don't look at input that follows a C-g too closely.
          This reduces lossage due to autorepeat on C-g.  */
@@ -7590,13 +7681,7 @@ menu_bar_items (old)
   /* Add nil, nil, nil, nil at the end.  */
   i = menu_bar_items_index;
   if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-    {
-      Lisp_Object tem;
-      tem = Fmake_vector (make_number (2 * i), Qnil);
-      bcopy (XVECTOR (menu_bar_items_vector)->contents,
-            XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-      menu_bar_items_vector = tem;
-    }
+    menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
   /* Add this item.  */
   XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
   XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
@@ -7668,14 +7753,7 @@ menu_bar_item (key, item, dummy1, dummy2)
     {
       /* If vector is too small, get a bigger one.  */
       if (i + 4 > XVECTOR (menu_bar_items_vector)->size)
-       {
-         Lisp_Object tem;
-         tem = Fmake_vector (make_number (2 * i), Qnil);
-         bcopy (XVECTOR (menu_bar_items_vector)->contents,
-                XVECTOR (tem)->contents, i * sizeof (Lisp_Object));
-         menu_bar_items_vector = tem;
-       }
-
+       menu_bar_items_vector = larger_vector (menu_bar_items_vector, 2 * i, Qnil);
       /* Add this item.  */
       XVECTOR (menu_bar_items_vector)->contents[i++] = key;
       XVECTOR (menu_bar_items_vector)->contents[i++]
@@ -7760,11 +7838,11 @@ parse_menu_item (item, notreal, inmenubar)
 
   /* Initialize optional entries.  */
   for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++)
-    AREF (item_properties, i) = Qnil;
-  AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+    ASET (item_properties, i, Qnil);
+  ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
 
   /* Save the item here to protect it from GC.  */
-  AREF (item_properties, ITEM_PROPERTY_ITEM) = item;
+  ASET (item_properties, ITEM_PROPERTY_ITEM, item);
 
   item_string = XCAR (item);
 
@@ -7773,12 +7851,12 @@ parse_menu_item (item, notreal, inmenubar)
   if (STRINGP (item_string))
     {
       /* Old format menu item.  */
-      AREF (item_properties, ITEM_PROPERTY_NAME) = item_string;
+      ASET (item_properties, ITEM_PROPERTY_NAME, item_string);
 
       /* Maybe help string.  */
       if (CONSP (item) && STRINGP (XCAR (item)))
        {
-         AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item);
+         ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item));
          start = item;
          item = XCDR (item);
        }
@@ -7793,27 +7871,27 @@ parse_menu_item (item, notreal, inmenubar)
        }
 
       /* This is the real definition--the function to run.  */
-      AREF (item_properties, ITEM_PROPERTY_DEF) = item;
+      ASET (item_properties, ITEM_PROPERTY_DEF, item);
 
       /* Get enable property, if any.  */
       if (SYMBOLP (item))
        {
          tem = Fget (item, Qmenu_enable);
          if (!NILP (Venable_disabled_menus_and_buttons))
-           AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+           ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
          else if (!NILP (tem))
-           AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
+           ASET (item_properties, ITEM_PROPERTY_ENABLE, tem);
        }
     }
   else if (EQ (item_string, Qmenu_item) && CONSP (item))
     {
       /* New format menu item.  */
-      AREF (item_properties, ITEM_PROPERTY_NAME) = XCAR (item);
+      ASET (item_properties, ITEM_PROPERTY_NAME, XCAR (item));
       start = XCDR (item);
       if (CONSP (start))
        {
          /* We have a real binding.  */
-         AREF (item_properties, ITEM_PROPERTY_DEF) = XCAR (start);
+         ASET (item_properties, ITEM_PROPERTY_DEF, XCAR (start));
 
          item = XCDR (start);
          /* Is there a cache list with key equivalences. */
@@ -7832,9 +7910,9 @@ parse_menu_item (item, notreal, inmenubar)
              if (EQ (tem, QCenable))
                {
                  if (!NILP (Venable_disabled_menus_and_buttons))
-                   AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt;
+                   ASET (item_properties, ITEM_PROPERTY_ENABLE, Qt);
                  else
-                   AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item);
+                   ASET (item_properties, ITEM_PROPERTY_ENABLE, XCAR (item));
                }
              else if (EQ (tem, QCvisible) && !notreal)
                {
@@ -7845,7 +7923,7 @@ parse_menu_item (item, notreal, inmenubar)
                    return 0;
                }
              else if (EQ (tem, QChelp))
-               AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item);
+               ASET (item_properties, ITEM_PROPERTY_HELP, XCAR (item));
              else if (EQ (tem, QCfilter))
                filter = item;
              else if (EQ (tem, QCkey_sequence))
@@ -7860,7 +7938,7 @@ parse_menu_item (item, notreal, inmenubar)
                {
                  tem = XCAR (item);
                  if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist)))
-                   AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem;
+                   ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
                }
              else if (EQ (tem, QCbutton) && CONSP (XCAR (item)))
                {
@@ -7869,10 +7947,9 @@ parse_menu_item (item, notreal, inmenubar)
                  type = XCAR (tem);
                  if (EQ (type, QCtoggle) || EQ (type, QCradio))
                    {
-                     AREF (item_properties, ITEM_PROPERTY_SELECTED)
-                       = XCDR (tem);
-                     AREF (item_properties, ITEM_PROPERTY_TYPE)
-                       = type;
+                     ASET (item_properties, ITEM_PROPERTY_SELECTED,
+                           XCDR (tem));
+                     ASET (item_properties, ITEM_PROPERTY_TYPE, type);
                    }
                }
              item = XCDR (item);
@@ -7892,7 +7969,7 @@ parse_menu_item (item, notreal, inmenubar)
       item_string = menu_item_eval_property (item_string);
       if (!STRINGP (item_string))
        return 0;
-      AREF (item_properties, ITEM_PROPERTY_NAME) = item_string;
+      ASET (item_properties, ITEM_PROPERTY_NAME, item_string);
     }
 
   /* If got a filter apply it on definition.  */
@@ -7902,7 +7979,7 @@ parse_menu_item (item, notreal, inmenubar)
       def = menu_item_eval_property (list2 (XCAR (filter),
                                            list2 (Qquote, def)));
 
-      AREF (item_properties, ITEM_PROPERTY_DEF) = def;
+      ASET (item_properties, ITEM_PROPERTY_DEF, def);
     }
 
   /* Enable or disable selection of item.  */
@@ -7915,7 +7992,7 @@ parse_menu_item (item, notreal, inmenubar)
        tem = menu_item_eval_property (tem);
       if (inmenubar && NILP (tem))
        return 0;               /* Ignore disabled items in menu bar.  */
-      AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem;
+      ASET (item_properties, ITEM_PROPERTY_ENABLE, tem);
     }
 
   /* If we got no definition, this item is just unselectable text which
@@ -7929,8 +8006,8 @@ parse_menu_item (item, notreal, inmenubar)
   /* For a subkeymap, just record its details and exit.  */
   if (CONSP (tem))
     {
-      AREF (item_properties, ITEM_PROPERTY_MAP) = tem;
-      AREF (item_properties, ITEM_PROPERTY_DEF) = tem;
+      ASET (item_properties, ITEM_PROPERTY_MAP, tem);
+      ASET (item_properties, ITEM_PROPERTY_DEF, tem);
       return 1;
     }
 
@@ -8044,7 +8121,8 @@ parse_menu_item (item, notreal, inmenubar)
   tem = XCDR (cachelist);
   if (newcache && !NILP (tem))
     {
-      tem = concat3 (build_string ("  ("), tem, build_string (")"));
+      tem = concat2 (build_string ("  "), tem);
+      // tem = concat3 (build_string ("  ("), tem, build_string (")"));
       XSETCDR (cachelist, tem);
     }
 
@@ -8053,7 +8131,7 @@ parse_menu_item (item, notreal, inmenubar)
     return 1;
 
   /* If we have an equivalent key binding, use that.  */
-  AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem;
+  ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
 
   /* Include this when menu help is implemented.
   tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP];
@@ -8069,8 +8147,8 @@ parse_menu_item (item, notreal, inmenubar)
   /* Handle radio buttons or toggle boxes.  */
   tem = AREF (item_properties, ITEM_PROPERTY_SELECTED);
   if (!NILP (tem))
-    AREF (item_properties, ITEM_PROPERTY_SELECTED)
-      = menu_item_eval_property (tem);
+    ASET (item_properties, ITEM_PROPERTY_SELECTED,
+         menu_item_eval_property (tem));
 
   return 1;
 }
@@ -8444,16 +8522,9 @@ append_tool_bar_item ()
   /* Enlarge tool_bar_items_vector if necessary.  */
   if (ntool_bar_items + TOOL_BAR_ITEM_NSLOTS
       >= XVECTOR (tool_bar_items_vector)->size)
-    {
-      Lisp_Object new_vector;
-      int old_size = XVECTOR (tool_bar_items_vector)->size;
-
-      new_vector = Fmake_vector (make_number (2 * old_size), Qnil);
-      bcopy (XVECTOR (tool_bar_items_vector)->contents,
-            XVECTOR (new_vector)->contents,
-            old_size * sizeof (Lisp_Object));
-      tool_bar_items_vector = new_vector;
-    }
+    tool_bar_items_vector
+      = larger_vector (tool_bar_items_vector,
+                      2 * XVECTOR (tool_bar_items_vector)->size, Qnil);
 
   /* Append entries from tool_bar_item_properties to the end of
      tool_bar_items_vector.  */
@@ -8557,7 +8628,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
             to indicate that they came from a mouse menu,
             so that when present in last_nonmenu_event
             they won't confuse things.  */
-         for (tem = XCDR (value); !NILP (tem); tem = XCDR (tem))
+         for (tem = XCDR (value); CONSP (tem); tem = XCDR (tem))
            {
              record_menu_key (XCAR (tem));
              if (SYMBOLP (XCAR (tem))
@@ -9133,8 +9204,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      key's again in Vfunction_key_map.  */
   volatile keyremap fkey;
 
-  /* Likewise, for key_translation_map.  */
-  volatile keyremap keytran;
+  /* Likewise, for key_translation_map and input-decode-map.  */
+  volatile keyremap keytran, indec;
+
+  /* Non-zero if we are trying to map a key by changing an upper-case
+     letter to lower case, or a shifted function key to an unshifted
+     one. */
+  volatile int shift_translated = 0;
 
   /* If we receive a `switch-frame' or `select-window' event in the middle of
      a key sequence, we put it off for later.
@@ -9169,7 +9245,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
-  
+
   if (INTERACTIVE)
     {
       if (!NILP (prompt))
@@ -9204,18 +9280,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
   from_string = Qnil;
 
+  /* The multi-tty merge moved the code below to right after
+   `replay_sequence' which caused all these translation maps to be applied
+   repeatedly, even tho their doc says very clearly they are not applied to
+   their own output.
+   The reason for this move was: "We may switch keyboards between rescans,
+   so we need to reinitialize fkey and keytran before each replay".
+   This move was wrong (even if we switch keyboards, keybuf still holds the
+   keys we've read already from the original keyboard and some of those keys
+   may have already been translated).  So there may still be a bug out there
+   lurking.  */
+  indec.map = indec.parent = current_kboard->Vinput_decode_map;
+  fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
+  keytran.map = keytran.parent = Vkey_translation_map;
+  indec.start = indec.end = 0;
+  fkey.start = fkey.end = 0;
+  keytran.start = keytran.end = 0;
+
   /* We jump here when the key sequence has been thoroughly changed, and
      we need to rescan it starting from the beginning.  When we jump here,
      keybuf[0..mock_input] holds the sequence we should reread.  */
  replay_sequence:
 
-  /* We may switch keyboards between rescans, so we need to
-     reinitialize fkey and keytran before each replay.  */
-  fkey.map = fkey.parent = current_kboard->Vlocal_function_key_map;
-  keytran.map = keytran.parent = current_kboard->Vlocal_key_translation_map;
-  fkey.start = fkey.end = 0;
-  keytran.start = keytran.end = 0;
-
   starting_buffer = current_buffer;
   first_unbound = bufsize + 1;
 
@@ -9301,7 +9387,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            Thus, if ESC O a has a function-key-map translation
            and ESC o has a binding, don't return after ESC O,
            so that we can translate ESC O plus the next character.  */
-        : (fkey.start < t || keytran.start < t))
+        : (/* indec.start < t || fkey.start < t || */ keytran.start < t))
     {
       Lisp_Object key;
       int used_mouse_menu = 0;
@@ -9319,13 +9405,17 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         just one key.  */
       volatile int echo_local_start, keys_local_start, local_first_binding;
 
-      eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input));
+      eassert (indec.end == t || (indec.end > t && indec.end <= mock_input));
+      eassert (indec.start <= indec.end);
       eassert (fkey.start <= fkey.end);
       eassert (keytran.start <= keytran.end);
-      /* key-translation-map is applied *after* function-key-map.  */
+      /* key-translation-map is applied *after* function-key-map
+        which is itself applied *after* input-decode-map.  */
+      eassert (fkey.end <= indec.start);
       eassert (keytran.end <= fkey.start);
 
-      if (first_unbound < fkey.start && first_unbound < keytran.start)
+      if (/* first_unbound < indec.start && first_unbound < fkey.start && */
+         first_unbound < keytran.start)
        { /* The prefix upto first_unbound has no binding and has
             no translation left to do either, so we know it's unbound.
             If we don't stop now, we risk staying here indefinitely
@@ -9335,6 +9425,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          for (i = first_unbound + 1; i < t; i++)
            keybuf[i - first_unbound - 1] = keybuf[i];
          mock_input = t - first_unbound - 1;
+         indec.end = indec.start -= first_unbound + 1;
+         indec.map = indec.parent;
          fkey.end = fkey.start -= first_unbound + 1;
          fkey.map = fkey.parent;
          keytran.end = keytran.start -= first_unbound + 1;
@@ -9515,7 +9607,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            }
 
          GROW_RAW_KEYBUF;
-         XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
+         ASET (raw_keybuf, raw_keybuf_count, key);
+         raw_keybuf_count++;
        }
 
       /* Clicks in non-text areas get prefixed by the symbol
@@ -9542,7 +9635,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            {
              Lisp_Object window, posn;
 
-             window = POSN_WINDOW      (EVENT_START (key));
+             window = POSN_WINDOW (EVENT_START (key));
              posn   = POSN_POSN (EVENT_START (key));
 
              if (CONSP (posn)
@@ -9760,15 +9853,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        /* This is needed for the following scenario:
           event 0: a down-event that gets dropped by calling replay_key.
           event 1: some normal prefix like C-h.
-          After event 0, first_unbound is 0, after event 1 fkey.start
-          and keytran.start are both 1, so when we see that C-h is bound,
-          we need to update first_unbound.  */
+          After event 0, first_unbound is 0, after event 1 indec.start,
+          fkey.start, and keytran.start are all 1, so when we see that
+          C-h is bound, we need to update first_unbound.  */
        first_unbound = max (t + 1, first_unbound);
       else
        {
          Lisp_Object head;
 
-         /* Remember the position to put an upper bound on fkey.start.  */
+         /* Remember the position to put an upper bound on indec.start.  */
          first_unbound = min (t, first_unbound);
 
          head = EVENT_HEAD (key);
@@ -9853,21 +9946,27 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                          /* If mock_input > t + 1, the above simplification
                             will actually end up dropping keys on the floor.
                             This is probably OK for now, but even
-                            if mock_input <= t + 1, we need to adjust fkey
-                            and keytran.
+                            if mock_input <= t + 1, we need to adjust indec,
+                            fkey, and keytran.
                             Typical case [header-line down-mouse-N]:
                             mock_input = 2, t = 1, fkey.end = 1,
                             last_real_key_start = 0.  */
-                         if (fkey.end > last_real_key_start)
+                         if (indec.end > last_real_key_start)
                            {
-                             fkey.end = fkey.start
-                               = min (last_real_key_start, fkey.start);
-                             fkey.map = fkey.parent;
-                             if (keytran.end > last_real_key_start)
+                             indec.end = indec.start
+                               = min (last_real_key_start, indec.start);
+                             indec.map = indec.parent;
+                             if (fkey.end > last_real_key_start)
                                {
-                                 keytran.end = keytran.start
-                                   = min (last_real_key_start, keytran.start);
-                                 keytran.map = keytran.parent;
+                                 fkey.end = fkey.start
+                                   = min (last_real_key_start, fkey.start);
+                                 fkey.map = fkey.parent;
+                                 if (keytran.end > last_real_key_start)
+                                   {
+                                     keytran.end = keytran.start
+                                       = min (last_real_key_start, keytran.start);
+                                     keytran.map = keytran.parent;
+                                   }
                                }
                            }
                          if (t == last_real_key_start)
@@ -9921,8 +10020,28 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       /* Record what part of this_command_keys is the current key sequence.  */
       this_single_command_key_start = this_command_key_count - t;
 
-      if (first_binding < nmaps && NILP (submaps[first_binding]))
+      /* Look for this sequence in input-decode-map.
+        Scan from indec.end until we find a bound suffix.  */
+      while (indec.end < t)
+       {
+         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+         int done, diff;
+
+         GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
+         done = keyremap_step (keybuf, bufsize, &indec, max (t, mock_input),
+                               1, &diff, prompt);
+         UNGCPRO;
+         if (done)
+           {
+             mock_input = diff + max (t, mock_input);
+             goto replay_sequence;
+           }
+       }
+
+      if (first_binding < nmaps && NILP (submaps[first_binding])
+         && indec.start >= t)
        /* There is a binding and it's not a prefix.
+          (and it doesn't have any input-decode-map translation pending).
           There is thus no function-key in this sequence.
           Moving fkey.start is important in this case to allow keytran.start
           to go over the sequence before we return (since we keep the
@@ -9935,12 +10054,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        /* If the sequence is unbound, see if we can hang a function key
           off the end of it.  */
        /* Continue scan from fkey.end until we find a bound suffix.  */
-       while (fkey.end < t)
+       while (fkey.end < indec.start)
          {
-           struct gcpro gcpro1, gcpro2, gcpro3;
+           struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
            int done, diff;
 
-           GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+           GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
            done = keyremap_step (keybuf, bufsize, &fkey,
                                  max (t, mock_input),
                                  /* If there's a binding (i.e.
@@ -9952,6 +10071,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
            if (done)
              {
                mock_input = diff + max (t, mock_input);
+               /* Adjust the input-decode-map counters.  */
+               indec.end += diff;
+               indec.start += diff;
+
                goto replay_sequence;
              }
          }
@@ -9960,17 +10083,19 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         Scan from keytran.end until we find a bound suffix.  */
       while (keytran.end < fkey.start)
        {
-         struct gcpro gcpro1, gcpro2, gcpro3;
+         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
          int done, diff;
 
-         GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+         GCPRO4 (indec.map, fkey.map, keytran.map, delayed_switch_frame);
          done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
                                1, &diff, prompt);
          UNGCPRO;
          if (done)
            {
              mock_input = diff + max (t, mock_input);
-             /* Adjust the function-key-map counters.  */
+             /* Adjust the function-key-map and input-decode-map counters.  */
+             indec.end += diff;
+             indec.start += diff;
              fkey.end += diff;
              fkey.start += diff;
 
@@ -9983,11 +10108,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
       if (first_binding >= nmaps
-         && fkey.start >= t && keytran.start >= t
+         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
          && INTEGERP (key)
-         && ((((XINT (key) & 0x3ffff)
-               < XCHAR_TABLE (current_buffer->downcase_table)->size)
-              && UPPERCASEP (XINT (key) & 0x3ffff))
+         && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
+              && UPPERCASEP (XINT (key) & ~CHAR_MODIFIER_MASK))
              || (XINT (key) & shift_modifier)))
        {
          Lisp_Object new_key;
@@ -9998,14 +10122,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          if (XINT (key) & shift_modifier)
            XSETINT (new_key, XINT (key) & ~shift_modifier);
          else
-           XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff)
-                              | (XINT (key) & ~0x3ffff)));
+           XSETINT (new_key, (DOWNCASE (XINT (key) & ~CHAR_MODIFIER_MASK)
+                              | (XINT (key) & CHAR_MODIFIER_MASK)));
 
          /* We have to do this unconditionally, regardless of whether
             the lower-case char is defined in the keymaps, because they
             might get translated through function-key-map.  */
          keybuf[t - 1] = new_key;
          mock_input = max (t, mock_input);
+         shift_translated = 1;
 
          goto replay_sequence;
        }
@@ -10014,35 +10139,45 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is a shifted function key,
         use the corresponding unshifted function key instead.  */
       if (first_binding >= nmaps
-         && fkey.start >= t && keytran.start >= t
-         && SYMBOLP (key))
-       {
-         Lisp_Object breakdown;
-         int modifiers;
-
-         breakdown = parse_modifiers (key);
-         modifiers = XINT (XCAR (XCDR (breakdown)));
-         if (modifiers & shift_modifier)
+         && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t)
+       {
+         Lisp_Object breakdown = parse_modifiers (key);
+         int modifiers
+           = CONSP (breakdown) ? (XINT (XCAR (XCDR (breakdown)))) : 0;
+
+         if (modifiers & shift_modifier
+             /* Treat uppercase keys as shifted.  */
+             || (INTEGERP (key)
+                 && (KEY_TO_CHAR (key)
+                     < XCHAR_TABLE (current_buffer->downcase_table)->size)
+                 && UPPERCASEP (KEY_TO_CHAR (key))))
            {
-             Lisp_Object new_key;
+             Lisp_Object new_key
+               = (modifiers & shift_modifier
+                  ? apply_modifiers (modifiers & ~shift_modifier,
+                                     XCAR (breakdown))
+                  : make_number (DOWNCASE (KEY_TO_CHAR (key)) | modifiers));
 
              original_uppercase = key;
              original_uppercase_position = t - 1;
 
-             modifiers &= ~shift_modifier;
-             new_key = apply_modifiers (modifiers,
-                                        XCAR (breakdown));
-
+             /* We have to do this unconditionally, regardless of whether
+                the lower-case char is defined in the keymaps, because they
+                might get translated through function-key-map.  */
              keybuf[t - 1] = new_key;
              mock_input = max (t, mock_input);
+             /* Reset fkey (and consequently keytran) to apply
+                function-key-map on the result, so that S-backspace is
+                correctly mapped to DEL (via backspace).  OTOH,
+                input-decode-map doesn't need to go through it again.  */
              fkey.start = fkey.end = 0;
              keytran.start = keytran.end = 0;
+             shift_translated = 1;
 
              goto replay_sequence;
            }
        }
     }
-
   if (!dummyflag)
     read_key_sequence_cmd = (first_binding < nmaps
                             ? defs[first_binding]
@@ -10056,7 +10191,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   if ((dont_downcase_last || first_binding >= nmaps)
       && t > 0
       && t - 1 == original_uppercase_position)
-    keybuf[t - 1] = original_uppercase;
+    {
+      keybuf[t - 1] = original_uppercase;
+      shift_translated = 0;
+    }
+
+  if (shift_translated)
+    Vthis_command_keys_shift_translated = Qt;
 
   /* Occasionally we fabricate events, perhaps by expanding something
      according to function-key-map, or by adding a prefix symbol to a
@@ -10075,8 +10216,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       add_command_key (keybuf[t]);
     }
 
-
-
   UNGCPRO;
   return t;
 }
@@ -10158,7 +10297,7 @@ will read just one key sequence.  */)
       this_single_command_key_start = 0;
     }
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
@@ -10170,7 +10309,7 @@ will read just one key sequence.  */)
 #if 0  /* The following is fine for code reading a key sequence and
          then proceeding with a lenghty computation, but it's not good
          for code reading keys in a loop, like an input method.  */
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     start_hourglass ();
 #endif
@@ -10218,7 +10357,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
       this_single_command_key_start = 0;
     }
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     cancel_hourglass ();
 #endif
@@ -10227,7 +10366,7 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,
                         prompt, ! NILP (dont_downcase_last),
                         ! NILP (can_return_switch_frame), 0);
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
     start_hourglass ();
 #endif
@@ -10257,7 +10396,6 @@ a special event, so ignore the prefix argument and don't clear it.  */)
   register Lisp_Object final;
   register Lisp_Object tem;
   Lisp_Object prefixarg;
-  struct backtrace backtrace;
   extern int debug_on_next_call;
 
   debug_on_next_call = 0;
@@ -10323,20 +10461,11 @@ a special event, so ignore the prefix argument and don't clear it.  */)
     }
 
   if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
-    {
-      backtrace.next = backtrace_list;
-      backtrace_list = &backtrace;
-      backtrace.function = &Qcall_interactively;
-      backtrace.args = &cmd;
-      backtrace.nargs = 1;
-      backtrace.evalargs = 0;
-      backtrace.debug_on_exit = 0;
+    /* Don't call Fcall_interactively directly because we want to make
+       sure the backtrace has an entry for `call-interactively'.
+       For the same reason, pass `cmd' rather than `final'.  */
+      return call3 (Qcall_interactively, cmd, record_flag, keys);
 
-      tem = Fcall_interactively (cmd, record_flag, keys);
-
-      backtrace_list = backtrace.next;
-      return tem;
-    }
   return Qnil;
 }
 
@@ -10360,7 +10489,7 @@ give to the command you invoke, if it asks for an argument.  */)
   Lisp_Object saved_keys, saved_last_point_position_buffer;
   Lisp_Object bindings, value;
   struct gcpro gcpro1, gcpro2, gcpro3;
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   /* The call to Fcompleting_read wil start and cancel the hourglass,
      but if the hourglass was already scheduled, this means that no
      hourglass will be shown for the actual M-x command itself.
@@ -10400,7 +10529,7 @@ give to the command you invoke, if it asks for an argument.  */)
                               Qt, Qnil, Qextended_command_history, Qnil,
                               Qnil);
 
-#ifdef HAVE_X_WINDOWS
+#ifdef HAVE_WINDOW_SYSTEM
   if (hstarted) start_hourglass ();
 #endif
 
@@ -10447,7 +10576,7 @@ give to the command you invoke, if it asks for an argument.  */)
     bindings = Qnil;
 
   value = Qnil;
-  GCPRO2 (bindings, value);
+  GCPRO3 (bindings, value, function);
   value = Fcommand_execute (function, Qt, Qnil, Qnil);
 
   /* If the command has a key binding, print it now.  */
@@ -11159,7 +11288,7 @@ See also `current-input-mode'.  */)
   new_interrupt_input = 1;
 #endif
 
-  if (new_interrupt_input != interrupt_input) 
+  if (new_interrupt_input != interrupt_input)
     {
 #ifdef POLL_FOR_INPUT
       stop_polling ();
@@ -11239,7 +11368,7 @@ See also `current-input-mode'.  */)
   struct terminal *t = get_terminal (terminal, 1);
   struct tty_display_info *tty;
   int new_meta;
-  
+
   if (t == NULL || t->type != output_termcap)
     return Qnil;
   tty = t->display_info.tty;
@@ -11251,7 +11380,7 @@ See also `current-input-mode'.  */)
   else
     new_meta = 2;
 
-  if (tty->meta_key != new_meta) 
+  if (tty->meta_key != new_meta)
     {
 #ifndef DOS_NT
       /* this causes startup screen to be restored and messes with the mouse */
@@ -11259,7 +11388,7 @@ See also `current-input-mode'.  */)
 #endif
 
       tty->meta_key = new_meta;
-  
+
 #ifndef DOS_NT
       init_sys_modes (tty);
 #endif
@@ -11291,7 +11420,7 @@ See also `current-input-mode'.  */)
   /* this causes startup screen to be restored and messes with the mouse */
   reset_sys_modes (tty);
 #endif
-  
+
   /* Don't let this value be out of range.  */
   quit_char = XINT (quit) & (tty->meta_key == 0 ? 0177 : 0377);
 
@@ -11301,7 +11430,7 @@ See also `current-input-mode'.  */)
 
   return Qnil;
 }
-       
+
 DEFUN ("set-input-mode", Fset_input_mode, Sset_input_mode, 3, 4, 0,
        doc: /* Set mode of reading keyboard input.
 First arg INTERRUPT non-nil means use input interrupts;
@@ -11448,6 +11577,7 @@ init_kboard (kb)
   kb->Vlast_command = Qnil;
   kb->Vreal_last_command = Qnil;
   kb->Vkeyboard_translate_table = Qnil;
+  kb->Vlast_repeatable_command = Qnil;
   kb->Vprefix_arg = Qnil;
   kb->Vlast_prefix_arg = Qnil;
   kb->kbd_queue = Qnil;
@@ -11462,10 +11592,10 @@ init_kboard (kb)
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
+  kb->Vwindow_system = Qt;     /* Unset.  */
+  kb->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
   kb->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
   Fset_keymap_parent (kb->Vlocal_function_key_map, Vfunction_key_map);
-  kb->Vlocal_key_translation_map = Fmake_sparse_keymap (Qnil);
-  Fset_keymap_parent (kb->Vlocal_key_translation_map, Vkey_translation_map);
   kb->Vdefault_minibuffer_frame = Qnil;
 }
 
@@ -11543,8 +11673,12 @@ init_keyboard ()
 #ifdef MULTI_KBOARD
   current_kboard = initial_kboard;
 #endif
+  /* Re-initialize the keyboard again.  */
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
+  /* A value of nil for Vwindow_system normally means a tty, but we also use
+     it for the initial terminal since there is no window system there.  */
+  current_kboard->Vwindow_system = Qnil;
 
   if (!noninteractive)
     {
@@ -11616,6 +11750,8 @@ struct event_head head_table[] = {
 void
 syms_of_keyboard ()
 {
+  pending_funcalls = Qnil;
+
   Vpre_help_message = Qnil;
   staticpro (&Vpre_help_message);
 
@@ -11695,6 +11831,11 @@ syms_of_keyboard ()
   staticpro (&Qmac_apple_event);
 #endif
 
+#ifdef HAVE_DBUS
+  Qdbus_event = intern ("dbus-event");
+  staticpro (&Qdbus_event);
+#endif
+
   Qmenu_enable = intern ("menu-enable");
   staticpro (&Qmenu_enable);
   Qmenu_alias = intern ("menu-alias");
@@ -11855,6 +11996,7 @@ syms_of_keyboard ()
   staticpro (&help_form_saved_window_configs);
 
   defsubr (&Scurrent_idle_time);
+  defsubr (&Sevent_symbol_parse_modifiers);
   defsubr (&Sevent_convert_list);
   defsubr (&Sread_key_sequence);
   defsubr (&Sread_key_sequence_vector);
@@ -11956,12 +12098,25 @@ See Info node `(elisp)Multiple displays'.  */);
   DEFVAR_KBOARD ("real-last-command", Vreal_last_command,
                 doc: /* Same as `last-command', but never altered by Lisp code.  */);
 
+  DEFVAR_KBOARD ("last-repeatable-command", Vlast_repeatable_command,
+                doc: /* Last command that may be repeated.
+The last command executed that was not bound to an input event.
+This is the command `repeat' will try to repeat.  */);
+
   DEFVAR_LISP ("this-command", &Vthis_command,
               doc: /* The command now being executed.
 The command can set this variable; whatever is put here
 will be in `last-command' during the following command.  */);
   Vthis_command = Qnil;
 
+  DEFVAR_LISP ("this-command-keys-shift-translated",
+              &Vthis_command_keys_shift_translated,
+              doc: /* Non-nil if the key sequence activating this command was shift-translated.
+Shift-translation occurs when there is no binding for the key sequence
+as entered, but a binding was found by changing an upper-case letter
+to lower-case, or a shifted function key to an unshifted one.  */);
+  Vthis_command_keys_shift_translated = Qnil;
+
   DEFVAR_LISP ("this-original-command", &Vthis_original_command,
               doc: /* The command bound to the current key sequence before remapping.
 It equals `this-command' if the original command was not remapped through
@@ -12198,8 +12353,8 @@ See Info node `(elisp)Multiple displays'.  */);
 
   DEFVAR_KBOARD ("local-function-key-map", Vlocal_function_key_map,
                  doc: /* Keymap that translates key sequences to key sequences during input.
-This is used mainly for mapping ASCII function key sequences into
-real Emacs function key events (symbols).
+This is used mainly for mapping key sequences into some preferred
+key events (symbols).
 
 The `read-key-sequence' function replaces any subsequence bound by
 `local-function-key-map' with its binding.  More precisely, when the
@@ -12225,6 +12380,25 @@ define a binding on all terminals, change `function-key-map'
 instead.  Initially, `local-function-key-map' is an empty keymap that
 has `function-key-map' as its parent on all terminal devices.  */);
 
+  DEFVAR_KBOARD ("input-decode-map", Vinput_decode_map,
+                doc: /* Keymap that decodes input escape sequences.
+This is used mainly for mapping ASCII function key sequences into
+real Emacs function key events (symbols).
+
+The `read-key-sequence' function replaces any subsequence bound by
+`local-function-key-map' with its binding.  Contrary to `function-key-map',
+this map applies its rebinding regardless of the presence of an ordinary
+binding.  So it is more like `key-translation-map' except that it applies
+before `function-key-map' rather than after.
+
+If the binding is a function, it is called with one argument (the prompt)
+and its return value (a key sequence) is used.
+
+The events that come from bindings in `input-decode-map' are not
+themselves looked up in `input-decode-map'.
+
+This variable is keyboard-local.  */);
+
   DEFVAR_LISP ("function-key-map", &Vfunction_key_map,
                doc: /* The parent keymap of all `local-function-key-map' instances.
 Function key definitions that apply to all terminal devices should go
@@ -12232,19 +12406,12 @@ here.  If a mapping is defined in both the current
 `local-function-key-map' binding and this variable, then the local
 definition will take precendence.  */);
   Vfunction_key_map = Fmake_sparse_keymap (Qnil);
-                    
-  DEFVAR_KBOARD ("local-key-translation-map", Vlocal_key_translation_map,
-              doc: /* Keymap of key translations that can override keymaps.
-This keymap works like `function-key-map', but comes after that,
-and its non-prefix bindings override ordinary bindings.
-
-`key-translation-map' has a separate binding for each terminal device.
-(See Info node `(elisp)Multiple displays'.)  If you need to set a key
-translation on all terminals, change `global-key-translation-map' instead.  */);
 
   DEFVAR_LISP ("key-translation-map", &Vkey_translation_map,
-               doc: /* The parent keymap of all `local-key-translation-map' instances.
-Key translations that apply to all terminal devices should go here.  */);
+               doc: /* Keymap of key translations that can override keymaps.
+This keymap works like `function-key-map', but comes after that,
+and its non-prefix bindings override ordinary bindings.
+Another difference is that it is global rather than keyboard-local.  */);
   Vkey_translation_map = Fmake_sparse_keymap (Qnil);
 
   DEFVAR_LISP ("deferred-action-list", &Vdeferred_action_list,
@@ -12353,6 +12520,15 @@ and the Lisp function within which the error was signaled.  */);
 Help functions bind this to allow help on disabled menu items
 and tool-bar buttons.  */);
   Venable_disabled_menus_and_buttons = Qnil;
+
+#ifdef MULTI_KBOARD
+  /* Create the initial keyboard. */
+  initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (initial_kboard);
+  /* Vwindow_system is left at t for now.  */
+  initial_kboard->next_kboard = all_kboards;
+  all_kboards = initial_kboard;
+#endif
 }
 
 void
@@ -12397,6 +12573,13 @@ keys_of_keyboard ()
    *                       "handle-select-window"); */
   initial_define_lispy_key (Vspecial_event_map, "save-session",
                            "handle-save-session");
+
+#ifdef HAVE_DBUS
+  /* Define a special event which is raised for dbus callback
+     functions.  */
+  initial_define_lispy_key (Vspecial_event_map, "dbus-event",
+                           "dbus-handle-event");
+#endif
 }
 
 /* Mark the pointers in the kboard objects.
@@ -12415,6 +12598,7 @@ mark_kboards ()
       mark_object (kb->Vlast_command);
       mark_object (kb->Vreal_last_command);
       mark_object (kb->Vkeyboard_translate_table);
+      mark_object (kb->Vlast_repeatable_command);
       mark_object (kb->Vprefix_arg);
       mark_object (kb->Vlast_prefix_arg);
       mark_object (kb->kbd_queue);
@@ -12422,8 +12606,9 @@ mark_kboards ()
       mark_object (kb->Vlast_kbd_macro);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
+      mark_object (kb->Vwindow_system);
+      mark_object (kb->Vinput_decode_map);
       mark_object (kb->Vlocal_function_key_map);
-      mark_object (kb->Vlocal_key_translation_map);
       mark_object (kb->Vdefault_minibuffer_frame);
       mark_object (kb->echo_string);
     }