merging Emacs.app (NeXTstep port)
[bpt/emacs.git] / src / keyboard.c
index b987085..b908b8a 100644 (file)
@@ -1,14 +1,14 @@
 /* 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.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <signal.h>
@@ -33,7 +31,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"
@@ -82,6 +80,11 @@ Boston, MA 02110-1301, USA.  */
 #include "macterm.h"
 #endif
 
+#ifdef HAVE_NS
+#include "nsterm.h"
+extern Lisp_Object Qsuper;
+#endif
+
 #ifndef USE_CRT_DLL
 extern int errno;
 #endif
@@ -95,33 +98,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 */
-
-/* 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;
@@ -158,6 +135,9 @@ 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)                   \
    raw_keybuf = larger_vector (raw_keybuf, raw_keybuf_count * 2, Qnil)  \
@@ -175,18 +155,11 @@ 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.  */
 
 Lisp_Object Vshow_help_function;
 
-/* If a string, the message displayed before displaying a help-echo
-   in the echo area.  */
-
-Lisp_Object Vpre_help_message;
-
 /* Nonzero means do menu prompting.  */
 
 static int menu_prompting;
@@ -422,6 +395,7 @@ Lisp_Object Vinput_method_previous_message;
 
 /* Non-nil means deactivate the mark at end of this command.  */
 Lisp_Object Vdeactivate_mark;
+Lisp_Object Qdeactivate_mark;
 
 /* Menu bar specified in Lucid Emacs fashion.  */
 
@@ -514,7 +488,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.  */
@@ -944,7 +920,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;
 }
 
@@ -961,7 +937,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,
@@ -1246,7 +1222,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
@@ -1422,7 +1398,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
@@ -1545,7 +1521,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;
@@ -1563,14 +1539,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;
@@ -1623,8 +1598,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,
@@ -1632,17 +1605,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);
@@ -1679,6 +1650,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],
@@ -1785,14 +1757,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));
@@ -1817,7 +1791,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)
@@ -1832,7 +1806,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));
@@ -1874,7 +1850,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))
@@ -1922,7 +1898,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
@@ -1938,7 +1914,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.
@@ -1992,25 +1968,16 @@ 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.  */
-
+         /* In Emacs 22, setting transient-mark-mode to `only' was a
+            way of turning it on for just one command.  This usage is
+            obsolete, but support it anyway.  */
          if (EQ (Vtransient_mark_mode, Qidentity))
            Vtransient_mark_mode = Qnil;
-         if (EQ (Vtransient_mark_mode, Qonly))
+         else if (EQ (Vtransient_mark_mode, Qonly))
            Vtransient_mark_mode = Qidentity;
 
-         if (!NILP (Vdeactivate_mark) && !NILP (Vtransient_mark_mode))
-           {
-             /* We could also call `deactivate'mark'.  */
-             if (EQ (Vtransient_mark_mode, Qlambda))
-               Vtransient_mark_mode = Qnil;
-             else
-               {
-                 current_buffer->mark_active = Qnil;
-                 call1 (Vrun_hooks, intern ("deactivate-mark-hook"));
-               }
-           }
+         if (!NILP (Vdeactivate_mark))
+           call0 (Qdeactivate_mark);
          else if (current_buffer != prev_buffer || MODIFF != prev_modiff)
            call1 (Vrun_hooks, intern ("activate-mark-hook"));
        }
@@ -2053,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;
@@ -2062,6 +2029,7 @@ adjust_point_for_property (last_pt, modified)
      can't be usefully combined anyway.  */
   while (check_composition || check_display || check_invisible)
     {
+      /* FIXME: check `intangible'.  */
       if (check_composition
          && PT > BEGV && PT < ZV
          && get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
@@ -2383,6 +2351,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
@@ -2485,37 +2456,6 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo)
     {
       if (!NILP (Vshow_help_function))
        call1 (Vshow_help_function, help);
-      else if (/* Don't overwrite minibuffer contents.  */
-              !MINI_WINDOW_P (XWINDOW (selected_window))
-              /* Don't overwrite a keystroke echo.  */
-              && (NILP (echo_message_buffer)
-                  || ok_to_overwrite_keystroke_echo)
-              /* Don't overwrite a prompt.  */
-              && !cursor_in_echo_area)
-       {
-         if (STRINGP (help))
-           {
-             int count = SPECPDL_INDEX ();
-
-             if (!help_echo_showing_p)
-               Vpre_help_message = current_message ();
-
-             specbind (Qmessage_truncate_lines, Qt);
-             message3_nolog (help, SBYTES (help),
-                             STRING_MULTIBYTE (help));
-             unbind_to (count, Qnil);
-           }
-         else if (STRINGP (Vpre_help_message))
-           {
-             message3_nolog (Vpre_help_message,
-                             SBYTES (Vpre_help_message),
-                             STRING_MULTIBYTE (Vpre_help_message));
-             Vpre_help_message = Qnil;
-           }
-         else
-           message (0);
-       }
-
       help_echo_showing_p = STRINGP (help);
     }
 }
@@ -2566,7 +2506,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
@@ -2733,6 +2673,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
@@ -2756,6 +2698,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.
@@ -3181,7 +3129,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);
 
@@ -3214,7 +3162,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);
@@ -4017,9 +3965,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,7 +4045,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
         events.  */
       if (CONSP (Vunread_command_events))
        break;
-      
+
       if (kbd_fetch_ptr != kbd_store_ptr)
        break;
 #if defined (HAVE_MOUSE) || defined (HAVE_GPM)
@@ -4207,7 +4152,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
 #endif
        }
 
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (HAVE_NS)
       else if (event->kind == DELETE_WINDOW_EVENT)
        {
          /* Make an event (delete-frame (FRAME)).  */
@@ -4216,7 +4162,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          kbd_fetch_ptr = event + 1;
        }
 #endif
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
+    || defined (HAVE_NS)
       else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
@@ -4239,7 +4186,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
          kbd_fetch_ptr = event + 1;
        }
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+    || defined(HAVE_NS) || defined (USE_GTK)
       else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
        {
          kbd_fetch_ptr = event + 1;
@@ -4312,6 +4259,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
@@ -4342,7 +4296,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
              obj = make_lispy_event (event);
 
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
-    || defined (USE_GTK)
+    || defined(HAVE_NS) || defined (USE_GTK)
              /* If this was a menu selection, then set the flag to inhibit
                 writing to last_nonmenu_event.  Don't do this if the event
                 we're returning is (menu-bar), though; that indicates the
@@ -4521,6 +4475,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.
@@ -4557,6 +4518,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);
@@ -4913,13 +4882,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 */
@@ -4952,9 +4925,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 */
@@ -5001,7 +4973,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 */
@@ -5021,19 +4995,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 */
@@ -5046,6 +5048,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
@@ -5460,41 +5521,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;
@@ -5563,6 +5615,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.  */
@@ -5583,7 +5650,7 @@ make_lispy_event (event)
        if (event->kind == MOUSE_CLICK_EVENT)
          {
            struct frame *f = XFRAME (event->frame_or_window);
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            int row, column;
 #endif
 
@@ -5592,7 +5659,7 @@ make_lispy_event (event)
            if (! FRAME_LIVE_P (f))
              return Qnil;
 
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
            /* EVENT->x and EVENT->y are frame-relative pixel
               coordinates at this place.  Under old redisplay, COLUMN
               and ROW are set to frame relative glyph coordinates
@@ -5652,7 +5719,7 @@ make_lispy_event (event)
 
                return Fcons (item, Fcons (position, Qnil));
              }
-#endif /* not USE_X_TOOLKIT && not USE_GTK */
+#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
 
            position = make_lispy_position (f, &event->x, &event->y,
                                            event->timestamp);
@@ -6003,52 +6070,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;
@@ -6078,7 +6099,7 @@ make_lispy_event (event)
 #endif /* HAVE_MOUSE */
 
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
-    || defined (USE_GTK)
+    || defined(HAVE_NS) || defined (USE_GTK)
     case MENU_BAR_EVENT:
       if (EQ (event->arg, event->frame_or_window))
        /* This is the prefix key.  We translate this to
@@ -6129,6 +6150,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:
       {
@@ -6447,12 +6475,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;
@@ -6487,6 +6524,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.
 
@@ -6506,6 +6557,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));
@@ -6917,6 +6971,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)
@@ -7036,7 +7095,7 @@ read_avail_input (expected)
               nread += nr;
               expected = 0;
             }
-          
+
           if (nr == -1)          /* Not OK to read input now. */
             {
               err = 1;
@@ -7044,7 +7103,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
@@ -7056,12 +7115,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)
@@ -7097,7 +7157,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 ();
@@ -7158,7 +7218,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);
@@ -7179,7 +7239,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,
@@ -7208,9 +7268,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)
@@ -7229,14 +7289,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.  */
@@ -7750,11 +7810,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);
 
@@ -7763,12 +7823,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);
        }
@@ -7783,27 +7843,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. */
@@ -7822,9 +7882,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)
                {
@@ -7835,7 +7895,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))
@@ -7850,7 +7910,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)))
                {
@@ -7859,10 +7919,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);
@@ -7882,7 +7941,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.  */
@@ -7892,7 +7951,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.  */
@@ -7905,7 +7964,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
@@ -7919,8 +7978,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;
     }
 
@@ -7934,9 +7993,18 @@ parse_menu_item (item, notreal, inmenubar)
   if (NILP (cachelist))
     {
       /* We have to create a cachelist.  */
-      CHECK_IMPURE (start);
-      XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
-      cachelist = XCAR (XCDR (start));
+      /* With the introduction of where_is_cache, the computation
+         of equivalent key bindings is sufficiently fast that we
+         do not need to cache it here any more. */
+/*PENDING: under NS this effect does not hold, perhaps due to the
+           modifier-preference changes to where-is-internal.. */
+#ifdef HAVE_NS
+       CHECK_IMPURE (start);
+       XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
+       cachelist = XCAR (XCDR (start));
+#else
+      cachelist = Fcons (Qnil, Qnil);
+#endif
       newcache = 1;
       tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
       if (!NILP (keyhint))
@@ -8002,7 +8070,12 @@ parse_menu_item (item, notreal, inmenubar)
              && SYMBOLP (XSYMBOL (def)->function)
              && ! NILP (Fget (def, Qmenu_alias)))
            def = XSYMBOL (def)->function;
+#ifdef HAVE_NS
+          /* prefer 'super' bindings */
+         tem = Fwhere_is_internal (def, Qnil, Qsuper, Qt, Qt);
+#else
          tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt);
+#endif
          XSETCAR (cachelist, tem);
          if (NILP (tem))
            {
@@ -8034,7 +8107,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);
     }
 
@@ -8043,7 +8117,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];
@@ -8059,8 +8133,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;
 }
@@ -9119,6 +9193,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   /* 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.
      While we're reading, we keep the event here.  */
@@ -9152,7 +9231,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
-  
+
   if (INTERACTIVE)
     {
       if (!NILP (prompt))
@@ -9227,8 +9306,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
          nmaps_allocated = 2;
        }
-      if (!NILP (current_kboard->Voverriding_terminal_local_map))
-       submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
+      submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
     }
   else if (!NILP (Voverriding_local_map))
     {
@@ -9238,8 +9316,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          defs    = (Lisp_Object *) alloca (2 * sizeof (defs[0]));
          nmaps_allocated = 2;
        }
-      if (!NILP (Voverriding_local_map))
-       submaps[nmaps++] = Voverriding_local_map;
+      submaps[nmaps++] = Voverriding_local_map;
     }
   else
     {
@@ -9514,7 +9591,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
@@ -9541,7 +9619,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)
@@ -10016,9 +10094,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       if (first_binding >= nmaps
          && /* 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;
@@ -10029,14 +10106,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;
        }
@@ -10045,32 +10123,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
-         && /* indec.start >= t && 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]
@@ -10084,7 +10175,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
@@ -10103,8 +10200,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       add_command_key (keybuf[t]);
     }
 
-
-
   UNGCPRO;
   return t;
 }
@@ -10186,7 +10281,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
@@ -10198,7 +10293,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
@@ -10246,7 +10341,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
@@ -10255,7 +10350,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
@@ -10285,7 +10380,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;
@@ -10351,20 +10445,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;
 }
 
@@ -10388,7 +10473,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.
@@ -10428,7 +10513,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
 
@@ -10475,7 +10560,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.  */
@@ -11187,7 +11272,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 ();
@@ -11267,7 +11352,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;
@@ -11279,7 +11364,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 */
@@ -11287,7 +11372,7 @@ See also `current-input-mode'.  */)
 #endif
 
       tty->meta_key = new_meta;
-  
+
 #ifndef DOS_NT
       init_sys_modes (tty);
 #endif
@@ -11319,7 +11404,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);
 
@@ -11329,7 +11414,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;
@@ -11507,8 +11592,7 @@ static void
 wipe_kboard (kb)
      KBOARD *kb;
 {
-  if (kb->kbd_macro_buffer)
-    xfree (kb->kbd_macro_buffer);
+  xfree (kb->kbd_macro_buffer);
 }
 
 #ifdef MULTI_KBOARD
@@ -11572,9 +11656,12 @@ init_keyboard ()
 #ifdef MULTI_KBOARD
   current_kboard = initial_kboard;
 #endif
+  /* Re-initialize the keyboard again.  */
   wipe_kboard (current_kboard);
   init_kboard (current_kboard);
-  /* Leave Vwindow_system at its `t' default for now.  */
+  /* 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)
     {
@@ -11646,8 +11733,7 @@ struct event_head head_table[] = {
 void
 syms_of_keyboard ()
 {
-  Vpre_help_message = Qnil;
-  staticpro (&Vpre_help_message);
+  pending_funcalls = Qnil;
 
   Vlispy_mouse_stem = build_string ("mouse");
   staticpro (&Vlispy_mouse_stem);
@@ -11725,6 +11811,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");
@@ -11885,6 +11976,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);
@@ -11997,6 +12089,14 @@ 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
@@ -12153,6 +12253,8 @@ The command loop sets this to nil before each command,
 and tests the value when the command returns.
 Buffer modification stores t in this variable.  */);
   Vdeactivate_mark = Qnil;
+  Qdeactivate_mark = intern ("deactivate-mark");
+  staticpro (&Qdeactivate_mark);
 
   DEFVAR_LISP ("command-hook-internal", &Vcommand_hook_internal,
               doc: /* Temporary storage of pre-command-hook or post-command-hook.  */);
@@ -12286,7 +12388,7 @@ 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_LISP ("key-translation-map", &Vkey_translation_map,
                doc: /* Keymap of key translations that can override keymaps.
 This keymap works like `function-key-map', but comes after that,
@@ -12400,6 +12502,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
@@ -12444,6 +12555,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.