(display_locked): New var to indicate when we're in the run state.
[bpt/emacs.git] / src / keyboard.c
index 96f0c65..5680040 100644 (file)
@@ -1,5 +1,5 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94 Free Software Foundation, Inc.
+   Copyright (C) 1985,86,87,88,89,93,94,95 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -22,7 +22,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include <config.h>
 #include <stdio.h>
-#undef NULL
 #include "termchar.h"
 #include "termopts.h"
 #include "lisp.h"
@@ -72,9 +71,10 @@ int interrupt_input_blocked;
 int interrupt_input_pending;
 
 
-#ifdef HAVE_X_WINDOWS
-extern Lisp_Object Vmouse_grabbed;
+/* File descriptor to use for input.  */
+extern int input_fd;
 
+#ifdef HAVE_X_WINDOWS
 /* Make all keyboard buffers much bigger when using X windows.  */
 #define KBD_BUFFER_SIZE 4096
 #else  /* No X-windows, character input */
@@ -94,6 +94,14 @@ struct backtrace
     char evalargs;
   };
 
+#ifdef MULTI_PERDISPLAY
+PERDISPLAY *current_perdisplay;
+PERDISPLAY *all_perdisplays;
+int display_locked;
+#else
+PERDISPLAY the_only_perdisplay;
+#endif
+
 /* Non-nil disable property on a command means
    do not execute it; call disabled-command-hook's value instead.  */
 Lisp_Object Qdisabled, Qdisabled_command_hook;
@@ -130,6 +138,9 @@ int waiting_for_input;
 /* True while displaying for echoing.   Delays C-g throwing.  */
 static int echoing;
 
+/* Nonzero means disregard local maps for the menu bar.  */
+static int inhibit_local_menu_bar_menus;
+
 /* Nonzero means C-g should cause immediate error-signal.  */
 int immediate_quit;
 
@@ -169,6 +180,9 @@ extern int minibuf_level;
 /* If non-nil, this is a map that overrides all other local maps.  */
 Lisp_Object Voverriding_local_map;
 
+/* If non-nil, Voverriding_local_map applies to the menu bar.  */
+Lisp_Object Voverriding_local_map_menu_flag;
+
 /* Current depth in recursive edits.  */
 int command_loop_level;
 
@@ -245,20 +259,6 @@ int last_point_position;
 /* The buffer that was current when the last command was started.  */
 Lisp_Object last_point_position_buffer;
 
-#ifdef MULTI_FRAME
-/* The frame in which the last input event occurred, or Qmacro if the
-   last event came from a macro.  We use this to determine when to
-   generate switch-frame events.  This may be cleared by functions
-   like Fselect_frame, to make sure that a switch-frame event is
-   generated by the next character.  */
-Lisp_Object internal_last_event_frame;
-#endif
-
-/* A user-visible version of the above, intended to allow users to
-   figure out where the last event came from, if the event doesn't
-   carry that information itself (i.e. if it was a character).  */
-Lisp_Object Vlast_event_frame;
-
 /* The timestamp of the last input event we received from the X server.
    X Windows wants this for selection ownership.  */
 unsigned long last_event_timestamp;
@@ -303,6 +303,7 @@ Lisp_Object Vdeferred_action_list;
 
 /* Function to call to handle deferred actions, when there are any.  */
 Lisp_Object Vdeferred_action_function;
+Lisp_Object Qdeferred_action_function;
 
 /* File in which we write all commands we read.  */
 FILE *dribble;
@@ -357,24 +358,22 @@ static struct input_event *kbd_fetch_ptr;
 /* Pointer to next place to store character in kbd_buffer.  This
    may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next
    character should go in kbd_buffer[0].  */
-#ifdef __STDC__
-volatile
-#endif
-static struct input_event *kbd_store_ptr;
+static volatile struct input_event *kbd_store_ptr;
 
 /* The above pair of variables forms a "queue empty" flag.  When we
-   enqueue a non-hook event, we increment kbd_write_count.  When we
-   dequeue a non-hook event, we increment kbd_read_count.  We say that
-   there is input available iff the two counters are not equal.
+   enqueue a non-hook event, we increment kbd_store_ptr.  When we
+   dequeue a non-hook event, we increment kbd_fetch_ptr.  We say that
+   there is input available iff the two pointers are not equal.
 
    Why not just have a flag set and cleared by the enqueuing and
    dequeuing functions?  Such a flag could be screwed up by interrupts
    at inopportune times.  */
 
-/* If this flag is non-zero, we check mouse_moved to see when the
-   mouse moves, and motion events will appear in the input stream.  If
-   it is zero, mouse motion is ignored.  */
-static int do_mouse_tracking;
+#ifdef HAVE_MOUSE
+/* If this flag is a frame, we check mouse_moved to see when the
+   mouse moves, and motion events will appear in the input stream.
+   Otherwise, mouse motion is ignored.  */
+static Lisp_Object do_mouse_tracking;
 
 /* The window system handling code should set this if the mouse has
    moved since the last call to the mouse_position_hook.  Calling that
@@ -382,20 +381,15 @@ static int do_mouse_tracking;
    call mouse_position_hook to get the promised position, so don't set
    it unless you're prepared to substantiate the claim!  */
 int mouse_moved;
-
-/* True iff there is an event in kbd_buffer, or if mouse tracking is
-   enabled and there is a new mouse position in the mouse movement
-   buffer.  Note that if this is false, that doesn't mean that there
-   is readable input; all the events in the queue might be button-up
-   events, and do_mouse_tracking might be off.  */
-#define EVENT_QUEUES_EMPTY \
-  ((kbd_fetch_ptr == kbd_store_ptr) && (!do_mouse_tracking || !mouse_moved))
-
+#endif /* HAVE_MOUSE.  */
 
 /* Symbols to head events.  */
 Lisp_Object Qmouse_movement;
 Lisp_Object Qscroll_bar_movement;
 Lisp_Object Qswitch_frame;
+Lisp_Object Qdelete_frame;
+Lisp_Object Qiconify_frame;
+Lisp_Object Qmake_frame_visible;
 
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
@@ -486,20 +480,6 @@ static Lisp_Object make_lispy_switch_frame ();
 /* > 0 if we are to echo keystrokes.  */
 static int echo_keystrokes;
 
-/* Nonzero means echo each character as typed.  */
-static int immediate_echo;
-
-/* The text we're echoing in the modeline - partial key sequences,
-   usually.  '\0'-terminated.  This really shouldn't have a fixed size.  */
-static char echobuf[300];
-
-/* Where to append more text to echobuf if we want to.  */
-static char *echoptr;
-
-/* If we have echoed a prompt string specified by the user,
-   this is its length.  Otherwise this is -1.  */
-static int echo_after_prompt;
-
 /* Nonzero means don't try to suspend even if the operating system seems
    to support it.  */
 static int cannot_suspend;
@@ -516,13 +496,13 @@ echo_prompt (str)
 {
   int len = strlen (str);
 
-  if (len > sizeof echobuf - 4)
-    len = sizeof echobuf - 4;
-  bcopy (str, echobuf, len);
-  echoptr = echobuf + len;
-  *echoptr = '\0';
+  if (len > ECHOBUFSIZE - 4)
+    len = ECHOBUFSIZE - 4;
+  bcopy (str, current_perdisplay->echobuf, len);
+  current_perdisplay->echoptr = current_perdisplay->echobuf + len;
+  *current_perdisplay->echoptr = '\0';
 
-  echo_after_prompt = len;
+  current_perdisplay->echo_after_prompt = len;
 
   echo ();
 }
@@ -536,40 +516,42 @@ echo_char (c)
 {
   extern char *push_key_description ();
 
-  if (immediate_echo)
+  if (current_perdisplay->immediate_echo)
     {
-      char *ptr = echoptr;
+      char *ptr = current_perdisplay->echoptr;
       
-      if (ptr != echobuf)
+      if (ptr != current_perdisplay->echobuf)
        *ptr++ = ' ';
 
       /* If someone has passed us a composite event, use its head symbol.  */
       c = EVENT_HEAD (c);
 
-      if (XTYPE (c) == Lisp_Int)
+      if (INTEGERP (c))
        {
-         if (ptr - echobuf > sizeof echobuf - 6)
+         if (ptr - current_perdisplay->echobuf > ECHOBUFSIZE - 6)
            return;
 
          ptr = push_key_description (XINT (c), ptr);
        }
-      else if (XTYPE (c) == Lisp_Symbol)
+      else if (SYMBOLP (c))
        {
          struct Lisp_String *name = XSYMBOL (c)->name;
-         if (((ptr - echobuf) + name->size + 4) > sizeof echobuf)
+         if (((ptr - current_perdisplay->echobuf) + name->size + 4)
+             > ECHOBUFSIZE)
            return;
          bcopy (name->data, ptr, name->size);
          ptr += name->size;
        }
 
-      if (echoptr == echobuf && EQ (c, Vhelp_char))
+      if (current_perdisplay->echoptr == current_perdisplay->echobuf
+         && EQ (c, Vhelp_char))
        {
          strcpy (ptr, " (Type ? for further options)");
          ptr += strlen (ptr);
        }
 
       *ptr = 0;
-      echoptr = ptr;
+      current_perdisplay->echoptr = ptr;
 
       echo ();
     }
@@ -580,19 +562,21 @@ echo_char (c)
 
 echo_dash ()
 {
-  if (!immediate_echo && echoptr == echobuf)
+  if (!current_perdisplay->immediate_echo
+      && current_perdisplay->echoptr == current_perdisplay->echobuf)
     return;
   /* Do nothing if we just printed a prompt.  */
-  if (echo_after_prompt == echoptr - echobuf)
+  if (current_perdisplay->echo_after_prompt
+      == current_perdisplay->echoptr - current_perdisplay->echobuf)
     return;
   /* Do nothing if not echoing at all.  */
-  if (echoptr == 0)
+  if (current_perdisplay->echoptr == 0)
     return;
 
   /* Put a dash at the end of the buffer temporarily,
      but make it go away when the next character is added.  */
-  echoptr[0] = '-';
-  echoptr[1] = 0;
+  current_perdisplay->echoptr[0] = '-';
+  current_perdisplay->echoptr[1] = 0;
 
   echo ();
 }
@@ -602,10 +586,10 @@ echo_dash ()
 
 echo ()
 {
-  if (!immediate_echo)
+  if (!current_perdisplay->immediate_echo)
     {
       int i;
-      immediate_echo = 1;
+      current_perdisplay->immediate_echo = 1;
 
       for (i = 0; i < this_command_key_count; i++)
        {
@@ -619,7 +603,7 @@ echo ()
     }
 
   echoing = 1;
-  message1 (echobuf);
+  message1_nolog (current_perdisplay->echobuf);
   echoing = 0;
 
   if (waiting_for_input && !NILP (Vquit_flag))
@@ -630,9 +614,9 @@ echo ()
 
 cancel_echoing ()
 {
-  immediate_echo = 0;
-  echoptr = echobuf;
-  echo_after_prompt = -1;
+  current_perdisplay->immediate_echo = 0;
+  current_perdisplay->echoptr = current_perdisplay->echobuf;
+  current_perdisplay->echo_after_prompt = -1;
 }
 
 /* Return the length of the current echo string.  */
@@ -640,7 +624,7 @@ cancel_echoing ()
 static int
 echo_length ()
 {
-  return echoptr - echobuf;
+  return current_perdisplay->echoptr - current_perdisplay->echobuf;
 }
 
 /* Truncate the current echo message to its first LEN chars.
@@ -651,8 +635,8 @@ static void
 echo_truncate (len)
      int len;
 {
-  echobuf[len] = '\0';
-  echoptr = echobuf + len;
+  current_perdisplay->echobuf[len] = '\0';
+  current_perdisplay->echoptr = current_perdisplay->echobuf + len;
   truncate_echo_area (len);
 }
 
@@ -752,6 +736,30 @@ recursive_edit_unwind (buffer)
 Lisp_Object
 cmd_error (data)
      Lisp_Object data;
+{
+  Vstandard_output = Qt;
+  Vstandard_input = Qt;
+  Vexecuting_macro = Qnil;
+  if (!current_perdisplay)
+    abort ();
+  current_perdisplay->Vprefix_arg = Qnil;
+  cancel_echoing ();
+  cmd_error_internal (data, 0);
+
+  Vquit_flag = Qnil;
+
+  Vinhibit_quit = Qnil;
+#ifdef MULTI_PERDISPLAY
+  current_perdisplay = 0;
+  display_locked = 0;
+#endif
+
+  return make_number (0);
+}
+
+cmd_error_internal (data, context)
+     Lisp_Object data;
+     char *context;
 {
   Lisp_Object errmsg, tail, errname, file_error;
   Lisp_Object stream;
@@ -760,9 +768,6 @@ cmd_error (data)
 
   Vquit_flag = Qnil;
   Vinhibit_quit = Qt;
-  Vstandard_output = Qt;
-  Vstandard_input = Qt;
-  Vexecuting_macro = Qnil;
   echo_area_glyphs = 0;
 
   /* If the window system or terminal frame hasn't been initialized
@@ -778,6 +783,9 @@ cmd_error (data)
       stream = Qt;
     }
 
+  if (context != 0)
+    write_string_1 (context, -1, stream);
+
   errname = Fcar (data);
 
   if (EQ (errname, Qerror))
@@ -807,7 +815,7 @@ cmd_error (data)
   if (!NILP (file_error) && !NILP (tail))
     errmsg = XCONS (tail)->car, tail = XCONS (tail)->cdr;
 
-  if (XTYPE (errmsg) == Lisp_String)
+  if (STRINGP (errmsg))
     Fprinc (errmsg, stream);
   else
     write_string_1 ("peculiar error", -1, stream);
@@ -830,11 +838,6 @@ cmd_error (data)
       Fterpri (stream);
       Fkill_emacs (make_number (-1));
     }
-
-  Vquit_flag = Qnil;
-
-  Vinhibit_quit = Qnil;
-  return make_number (0);
 }
 \f
 Lisp_Object command_loop_1 ();
@@ -947,11 +950,14 @@ command_loop_1 ()
   int no_direct;
   int prev_modiff;
   struct buffer *prev_buffer;
+#ifdef MULTI_PERDISPLAY
+  PERDISPLAY *outer_perdisplay = current_perdisplay;
+#endif
 
-  Vprefix_arg = Qnil;
   Vdeactivate_mark = Qnil;
   waiting_for_input = 0;
-  cancel_echoing ();
+  if (current_perdisplay)
+    cancel_echoing ();
 
   nonundocount = 0;
   no_redisplay = 0;
@@ -972,11 +978,6 @@ command_loop_1 ()
 
   while (1)
     {
-      /* Install chars successfully executed in kbd macro.  */
-
-      if (defining_kbd_macro && NILP (Vprefix_arg))
-       finalize_kbd_macro_chars ();
-
       /* Make sure the current window's buffer is selected.  */
       if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
        set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
@@ -1013,7 +1014,7 @@ command_loop_1 ()
        }
 
 #ifdef C_ALLOCA
-         alloca (0);           /* Cause a garbage collection now */
+      alloca (0);              /* Cause a garbage collection now */
                                /* Since we can free the most stuff here.  */
 #endif /* C_ALLOCA */
 
@@ -1023,7 +1024,7 @@ command_loop_1 ()
         switch-frame events will take care of this, but if some lisp
         code swallows a switch-frame event, we'll fix things up here.
         Is this a good idea?  */
-      if (XTYPE (internal_last_event_frame) == Lisp_Frame
+      if (FRAMEP (internal_last_event_frame)
          && XFRAME (internal_last_event_frame) != selected_frame)
        Fselect_frame (internal_last_event_frame, Qnil);
 #endif
@@ -1035,7 +1036,7 @@ command_loop_1 ()
        call0 (Qrecompute_lucid_menubar);
 
       /* Read next key sequence; i gets its length.  */
-      i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil);
+      i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0], Qnil, 0);
 
       ++num_input_keys;
 
@@ -1050,7 +1051,7 @@ command_loop_1 ()
        {
          cancel_echoing ();
          this_command_key_count = 0;
-         continue;
+         goto finalize;
        }
 
       last_command_char = keybuf[i - 1];
@@ -1075,13 +1076,13 @@ command_loop_1 ()
         cases identified below that set no_redisplay to 1.
         (actually, there's currently no way to prevent the redisplay,
         and no_redisplay is ignored.
-        Perhaps someday we will really implement it.  */
+        Perhaps someday we will really implement it.)  */
       no_redisplay = 0;
 
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
-      XSET (last_point_position_buffer, Lisp_Buffer, prev_buffer);
+      XSETBUFFER (last_point_position_buffer, prev_buffer);
 
       /* Execute the command.  */
 
@@ -1097,12 +1098,12 @@ command_loop_1 ()
          bitch_at_user ();
          defining_kbd_macro = 0;
          update_mode_lines = 1;
-         Vprefix_arg = Qnil;
+         current_perdisplay->Vprefix_arg = Qnil;
 
        }
       else
        {
-         if (NILP (Vprefix_arg) && ! no_direct)
+         if (NILP (current_perdisplay->Vprefix_arg) && ! no_direct)
            {
              /* Recognize some common commands in common situations and
                 do them directly.  */
@@ -1154,7 +1155,7 @@ command_loop_1 ()
                }
              else if (EQ (this_command, Qself_insert_command)
                       /* Try this optimization only on ascii keystrokes.  */
-                      && XTYPE (last_command_char) == Lisp_Int)
+                      && INTEGERP (last_command_char))
                {
                  unsigned char c = XINT (last_command_char);
                  int value;
@@ -1173,7 +1174,7 @@ command_loop_1 ()
                           < MODIFF)
                          || (XFASTINT (XWINDOW (selected_window)->last_point)
                              != PT)
-                         || MODIFF <= current_buffer->save_modified
+                         || MODIFF <= SAVE_MODIFF
                          || windows_or_buffers_changed
                          || !EQ (current_buffer->selective_display, Qnil)
                          || detect_input_pending ()
@@ -1203,10 +1204,10 @@ command_loop_1 ()
                              if (lose >= 0x20 && lose <= 0x7e)
                                no_redisplay = direct_output_for_insert (lose);
                            }
-                         else if (XTYPE (obj) == Lisp_Vector
+                         else if (VECTORP (obj)
                                   && XVECTOR (obj)->size == 1
-                                  && (XTYPE (obj = XVECTOR (obj)->contents[0])
-                                      == Lisp_Int)
+                                  && (obj = XVECTOR (obj)->contents[0],
+                                      INTEGERP (obj))
                                   /* Insist face not specified in glyph.  */
                                   && (XINT (obj) & ((-1) << 8)) == 0)
                            no_redisplay
@@ -1225,7 +1226,7 @@ command_loop_1 ()
          /* Here for a command that isn't executed directly */
 
          nonundocount = 0;
-         if (NILP (Vprefix_arg))
+         if (NILP (current_perdisplay->Vprefix_arg))
            Fundo_boundary ();
          Fcommand_execute (this_command, Qnil);
 
@@ -1238,7 +1239,7 @@ command_loop_1 ()
        safe_run_hooks (Qpost_command_hook);
 
       if (!NILP (Vdeferred_action_list))
-       call0 (Vdeferred_action_function);
+       safe_run_hooks (Qdeferred_action_function);
 
       /* If there is a prefix argument,
         1) We don't want last_command to be ``universal-argument''
@@ -1249,7 +1250,7 @@ command_loop_1 ()
         3) we want to leave this_command_key_count non-zero, so that
         read_char will realize that it is re-reading a character, and
         not echo it a second time.  */
-      if (NILP (Vprefix_arg))
+      if (NILP (current_perdisplay->Vprefix_arg))
        {
          last_command = this_command;
          cancel_echoing ();
@@ -1266,6 +1267,17 @@ command_loop_1 ()
          else if (current_buffer != prev_buffer || MODIFF != prev_modiff)
            call1 (Vrun_hooks, intern ("activate-mark-hook"));
        }
+
+    finalize:
+      /* Install chars successfully executed in kbd macro.  */
+
+      if (defining_kbd_macro && NILP (current_perdisplay->Vprefix_arg))
+       finalize_kbd_macro_chars ();
+
+#ifdef MULTI_PERDISPLAY
+      current_perdisplay = outer_perdisplay;
+      display_locked = (current_perdisplay != 0);
+#endif
     }
 }
 
@@ -1305,7 +1317,8 @@ int polling_for_input;
    so as to handle a C-g if it comces in.  */
 
 SIGTYPE
-input_poll_signal ()
+input_poll_signal (signalnum)  /* If we don't have an argument, */
+     int signalnum;            /* some compilers complain in signal calls. */
 {
   if (interrupt_input_blocked == 0
       && !waiting_for_input)
@@ -1447,6 +1460,11 @@ make_ctrl_char (c)
 
 Lisp_Object print_help ();
 static Lisp_Object kbd_buffer_get_event ();
+static void record_char ();
+
+#ifdef MULTI_PERDISPLAY
+static jmp_buf wrong_display_jmpbuf;
+#endif
 
 /* read a character from the keyboard; call the redisplay if needed */
 /* commandflag 0 means do not do auto-saving, but do do redisplay.
@@ -1476,6 +1494,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   register Lisp_Object c;
   int count;
   jmp_buf save_jump;
+  int key_already_recorded = 0;
+  Lisp_Object also_record;
+  also_record = Qnil;
 
   if (CONSP (Vunread_command_events))
     {
@@ -1490,7 +1511,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   if (unread_command_char != -1)
     {
-      XSET (c, Lisp_Int, unread_command_char);
+      XSETINT (c, unread_command_char);
       unread_command_char = -1;
 
       if (this_command_key_count == 0)
@@ -1512,7 +1533,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
         internal_last_event_frame after each command is read, but
         events read from a macro should never cause a new frame to be
         selected. */
-      Vlast_event_frame = internal_last_event_frame = Qmacro;
+      if (!current_perdisplay)
+       abort ();
+      current_perdisplay->internal_last_event_frame = Qmacro;
+      current_perdisplay->Vlast_event_frame = Qmacro;
 #endif
 
       /* Exit the macro if we are at the end.
@@ -1521,14 +1545,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       if (EQ (Vexecuting_macro, Qt)
          || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
        {
-         XSET (c, Lisp_Int, -1);
+         XSETINT (c, -1);
          return c;
        }
       
       c = Faref (Vexecuting_macro, make_number (executing_macro_index));
-      if (XTYPE (Vexecuting_macro) == Lisp_String
+      if (STRINGP (Vexecuting_macro)
          && (XINT (c) & 0x80))
-       XFASTINT (c) = CHAR_META | (XINT (c) & ~0x80);
+       XSETFASTINT (c, CHAR_META | (XINT (c) & ~0x80));
 
       executing_macro_index++;
 
@@ -1561,10 +1585,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   if (_setjmp (getcjmp))
     {
-      XSET (c, Lisp_Int, quit_char);
+      XSETINT (c, quit_char);
 #ifdef MULTI_FRAME
-      XSET (internal_last_event_frame, Lisp_Frame, selected_frame);
-      Vlast_event_frame = internal_last_event_frame;
+      XSETFRAME (current_perdisplay->internal_last_event_frame,
+                selected_frame);
+      current_perdisplay->Vlast_event_frame
+       = current_perdisplay->internal_last_event_frame;
 #endif
       /* If we report the quit char as an event,
         don't do so more than once.  */
@@ -1575,7 +1601,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     }
 
   /* Message turns off echoing unless more keystrokes turn it on again. */
-  if (echo_area_glyphs && *echo_area_glyphs && echo_area_glyphs != echobuf)
+  if (echo_area_glyphs && *echo_area_glyphs
+      && echo_area_glyphs != current_perdisplay->echobuf)
     cancel_echoing ();
   else
     /* If already echoing, continue.  */
@@ -1596,12 +1623,16 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
       if (! NILP (c))
-       goto non_reread;
+       {
+         key_already_recorded = 1;
+         goto non_reread;
+       }
     }
 
   /* If in middle of key sequence and minibuffer not active,
      start echoing if enough time elapses.  */
-  if (minibuf_level == 0 && !immediate_echo && this_command_key_count > 0
+  if (minibuf_level == 0 && !current_perdisplay->immediate_echo
+      && this_command_key_count > 0
       && ! noninteractive
       && echo_keystrokes > 0
       && (echo_area_glyphs == 0 || *echo_area_glyphs == 0))
@@ -1631,6 +1662,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       jmp_buf temp;
       save_getcjmp (temp);
       Fdo_auto_save (Qnil, Qnil);
+      /* Hooks can actually change some buffers in auto save.  */
+      redisplay ();
       restore_getcjmp (temp);
     }
 
@@ -1664,7 +1697,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       /* Auto save if enough time goes by without input.  */
       if (commandflag != 0
          && num_nonmacro_input_chars > last_auto_save
-         && XTYPE (Vauto_save_timeout) == Lisp_Int
+         && INTEGERP (Vauto_save_timeout)
          && XINT (Vauto_save_timeout) > 0)
        {
          Lisp_Object tem0;
@@ -1682,34 +1715,83 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
                 consing going on to make it worthwhile.  */
              if (!detect_input_pending ()
                  && consing_since_gc > gc_cons_threshold / 2)
-               {
-                 Fgarbage_collect ();
-                 /* prepare_menu_bars isn't safe here, but it should
-                    also be unnecessary.  */
-                 redisplay ();
-               }
+               Fgarbage_collect ();
+             /* prepare_menu_bars isn't safe here, but it should
+                also be unnecessary.  */
+             redisplay ();
            }
        }
     }
 
-  /* Actually read a character, waiting if necessary.  */
-  while (NILP (c))
+  if (NILP (c))
     {
-      c = kbd_buffer_get_event ();
-      if (!NILP (c))
-       break;
-      if (commandflag >= 0 && !input_pending && !detect_input_pending ())
+      PERDISPLAY *perd;
+      /* Check for something on one of the side queues.  Give priority to
+        the current display, but if we're not locked, then check the other
+        displays as well.  */
+      if (current_perdisplay && CONSP (current_perdisplay->kbd_queue))
+       perd = current_perdisplay;
+      else if (!display_locked)
        {
-         prepare_menu_bars ();
-         redisplay ();
+         for (perd = all_perdisplays; perd; perd = perd->next_perdisplay)
+           if (CONSP (perd->kbd_queue))
+             break;
        }
-    }
+      else
+       perd = 0;
 
+      /* If we found something on a side queue, use that.
+        Otherwise, read from the main queue, and if that gives us
+        something we can't use yet, put it on the side queue and
+        try again.  */
+      if (perd)
+       {
+         c = XCONS (perd->kbd_queue)->car;
+         perd->kbd_queue = XCONS (perd->kbd_queue)->cdr;
+       }
+      else
+       {
+       wrong_display:
+         /* Actually read a character, waiting if necessary.  */
+         while (c = kbd_buffer_get_event (&perd), NILP (c))
+           {
+             if (commandflag >= 0
+                 && !input_pending && !detect_input_pending ())
+               {
+                 prepare_menu_bars ();
+                 redisplay ();
+               }
+           }
+         if (display_locked && perd != current_perdisplay)
+           {
+             Lisp_Object *tailp = &perd->kbd_queue;
+             while (CONSP (*tailp))
+               tailp = &XCONS (*tailp)->cdr;
+             if (!NILP (*tailp))
+               abort ();
+             *tailp = Fcons (c, Qnil);
+             goto wrong_display;
+           }
+       }
+#ifdef MULTI_PERDISPLAY
+      if (!current_perdisplay)
+       current_perdisplay = perd;
+      if (perd != current_perdisplay)
+       {
+         /* We shouldn't get here if we were locked onto one display!  */
+         if (display_locked)
+           abort ();
+         perd->kbd_queue = Fcons (c, perd->kbd_queue);
+         current_perdisplay = perd;
+         longjmp (wrong_display_jmpbuf, 1);
+       }
+#endif
+    }
   /* Terminate Emacs in batch mode if at eof.  */
-  if (noninteractive && XTYPE (c) == Lisp_Int && XINT (c) < 0)
+  if (noninteractive && INTEGERP (c) && XINT (c) < 0)
     Fkill_emacs (make_number (1));
 
-  if (XTYPE (c) == Lisp_Int)
+  if (INTEGERP (c))
     {
       /* Add in any extra modifiers, where appropriate.  */
       if ((extra_keyboard_modifiers & CHAR_CTL)
@@ -1731,75 +1813,72 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   /* Buffer switch events are only for internal wakeups
      so don't show them to the user.  */
-  if (XTYPE (c) == Lisp_Buffer)
+  if (BUFFERP (c))
+    return c;
+
+  if (key_already_recorded)
     return c;
 
   /* Wipe the echo area.  */
   echo_area_glyphs = 0;
 
   /* Handle things that only apply to characters.  */
-  if (XTYPE (c) == Lisp_Int)
+  if (INTEGERP (c))
     {
       /* If kbd_buffer_get_event gave us an EOF, return that.  */
       if (XINT (c) == -1)
        return c;
 
-      if (XTYPE (Vkeyboard_translate_table) == Lisp_String
+      if (STRINGP (Vkeyboard_translate_table)
          && XSTRING (Vkeyboard_translate_table)->size > XFASTINT (c))
        XSETINT (c, XSTRING (Vkeyboard_translate_table)->data[XFASTINT (c)]);
     }
 
-  total_keys++;
-  XVECTOR (recent_keys)->contents[recent_keys_index] = c;
-  if (++recent_keys_index >= NUM_RECENT_KEYS)
-    recent_keys_index = 0;
-
-  /* Write c to the dribble file.  If c is a lispy event, write
-     the event's symbol to the dribble file, in <brackets>.  Bleaugh.
-     If you, dear reader, have a better idea, you've got the source.  :-) */
-  if (dribble)
+  /* If this event is a mouse click in the menu bar,
+     return just menu-bar for now.  Modify the mouse click event
+     so we won't do this twice, then queue it up.  */
+  if (EVENT_HAS_PARAMETERS (c)
+      && CONSP (XCONS (c)->cdr)
+      && CONSP (EVENT_START (c))
+      && CONSP (XCONS (EVENT_START (c))->cdr))
     {
-      if (XTYPE (c) == Lisp_Int)
-       {
-         if (XUINT (c) < 0x100)
-           putc (XINT (c), dribble);
-         else
-           fprintf (dribble, " 0x%x", XUINT (c));
-       }
-      else
-       {
-         Lisp_Object dribblee;
+      Lisp_Object posn;
 
-         /* If it's a structured event, take the event header.  */
-         dribblee = EVENT_HEAD (c);
+      posn = POSN_BUFFER_POSN (EVENT_START (c));
+      /* Handle menu-bar events:
+        insert the dummy prefix event `menu-bar'.  */
+      if (EQ (posn, Qmenu_bar))
+       {
+         /* Change menu-bar to (menu-bar) as the event "position".  */
+         POSN_BUFFER_POSN (EVENT_START (c)) = Fcons (posn, Qnil);
 
-         if (XTYPE (dribblee) == Lisp_Symbol)
-           {
-             putc ('<', dribble);
-             fwrite (XSYMBOL (dribblee)->name->data, sizeof (char),
-                     XSYMBOL (dribblee)->name->size,
-                     dribble);
-             putc ('>', dribble);
-           }
+         also_record = c;
+         Vunread_command_events = Fcons (c, Vunread_command_events);
+         c = posn;
        }
-
-      fflush (dribble);
     }
 
-  store_kbd_macro_char (c);
-
-  num_nonmacro_input_chars++;
+  record_char (c);
+  if (! NILP (also_record))
+    record_char (also_record);
 
  from_macro:
  reread_first:
 
   /* Don't echo mouse motion events.  */
-  if (! (EVENT_HAS_PARAMETERS (c)
-        && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
-    echo_char (c);
+  if (echo_keystrokes
+      && ! (EVENT_HAS_PARAMETERS (c)
+           && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+    {
+      echo_char (c);
+      if (! NILP (also_record))
+       echo_char (also_record);
+    }
 
   /* Record this character as part of the current key.  */
   add_command_key (c);
+  if (! NILP (also_record))
+    add_command_key (also_record);
 
   /* Re-reading in the middle of a command */
  reread:
@@ -1816,13 +1895,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
                             Fcurrent_window_configuration (Qnil));
 
       tem0 = Feval (Vhelp_form);
-      if (XTYPE (tem0) == Lisp_String)
+      if (STRINGP (tem0))
        internal_with_output_to_temp_buffer ("*Help*", print_help, tem0);
 
       cancel_echoing ();
       do
        c = read_char (0, 0, 0, Qnil, 0);
-      while (XTYPE (c) == Lisp_Buffer);
+      while (BUFFERP (c));
       /* Remove the help from the frame */
       unbind_to (count, Qnil);
       prepare_menu_bars ();
@@ -1832,18 +1911,70 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          cancel_echoing ();
          do
            c = read_char (0, 0, 0, Qnil, 0);
-         while (XTYPE (c) == Lisp_Buffer);
+         while (BUFFERP (c));
        }
     }
 
   return c;
 }
 
+/* Record the input event C in various ways.  */
+
+static void
+record_char (c)
+     Lisp_Object c;
+{
+  total_keys++;
+  XVECTOR (recent_keys)->contents[recent_keys_index] = c;
+  if (++recent_keys_index >= NUM_RECENT_KEYS)
+    recent_keys_index = 0;
+
+  /* Write c to the dribble file.  If c is a lispy event, write
+     the event's symbol to the dribble file, in <brackets>.  Bleaugh.
+     If you, dear reader, have a better idea, you've got the source.  :-) */
+  if (dribble)
+    {
+      if (INTEGERP (c))
+       {
+         if (XUINT (c) < 0x100)
+           putc (XINT (c), dribble);
+         else
+           fprintf (dribble, " 0x%x", XUINT (c));
+       }
+      else
+       {
+         Lisp_Object dribblee;
+
+         /* If it's a structured event, take the event header.  */
+         dribblee = EVENT_HEAD (c);
+
+         if (SYMBOLP (dribblee))
+           {
+             putc ('<', dribble);
+             fwrite (XSYMBOL (dribblee)->name->data, sizeof (char),
+                     XSYMBOL (dribblee)->name->size,
+                     dribble);
+             putc ('>', dribble);
+           }
+       }
+
+      fflush (dribble);
+    }
+
+  store_kbd_macro_char (c);
+
+  num_nonmacro_input_chars++;
+}
+
 Lisp_Object
 print_help (object)
      Lisp_Object object;
 {
+  struct buffer *old = current_buffer;
   Fprinc (object, Qnil);
+  set_buffer_internal (XBUFFER (Vstandard_output));
+  call0 (intern ("help-mode"));
+  set_buffer_internal (old);
   return Qnil;
 }
 
@@ -1865,16 +1996,18 @@ restore_getcjmp (temp)
 }
 
 \f
+#ifdef HAVE_MOUSE
+
 /* Restore mouse tracking enablement.  See Ftrack_mouse for the only use
    of this function.  */
+
 static Lisp_Object
 tracking_off (old_value)
      Lisp_Object old_value;
 {
-  if (! XFASTINT (old_value))
+  do_mouse_tracking = old_value;
+  if (NILP (old_value))
     {
-      do_mouse_tracking = 0;
-
       /* Redisplay may have been preempted because there was input
         available, and it assumes it will be called again after the
         input has been processed.  If the only input available was
@@ -1900,17 +2033,18 @@ Normally, mouse motion is ignored.")
   int count = specpdl_ptr - specpdl;
   Lisp_Object val;
 
-  XSET (val, Lisp_Int, do_mouse_tracking);
-  record_unwind_protect (tracking_off, val);
+  record_unwind_protect (tracking_off, do_mouse_tracking);
 
   if (!input_pending && !detect_input_pending ())
     prepare_menu_bars ();
 
-  do_mouse_tracking = 1;
+  XSETFRAME (do_mouse_tracking, selected_frame);
   
   val = Fprogn (args);
   return unbind_to (count, val);
 }
+
+#endif /* HAVE_MOUSE */
 \f
 /* Low level keyboard/mouse input.
    kbd_buffer_store_event places events in kbd_buffer, and
@@ -1923,7 +2057,13 @@ Normally, mouse motion is ignored.")
 static int
 readable_events ()
 {
-  return ! EVENT_QUEUES_EMPTY;
+  if (kbd_fetch_ptr != kbd_store_ptr)
+    return 1;
+#ifdef HAVE_MOUSE
+  if (FRAMEP (do_mouse_tracking) && mouse_moved)
+    return 1;
+#endif
+  return 0;
 }
 
 /* Set this for debugging, to have a way to get out */
@@ -1960,13 +2100,14 @@ kbd_buffer_store_event (event)
             will set Vlast_event_frame again, so this is safe to do.  */
          {
            Lisp_Object focus;
+           PERDISPLAY *perd;
 
            focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
            if (NILP (focus))
-             internal_last_event_frame = event->frame_or_window;
-           else
-             internal_last_event_frame = focus;
-           Vlast_event_frame = internal_last_event_frame;
+             focus = event->frame_or_window;
+           perd = get_perdisplay (XFRAME (focus));
+           perd->internal_last_event_frame = focus;
+           perd->Vlast_event_frame = focus;
          }
 #endif
 
@@ -1991,23 +2132,24 @@ kbd_buffer_store_event (event)
      Discard the event if it would fill the last slot.  */
   if (kbd_fetch_ptr - 1 != kbd_store_ptr)
     {
-      kbd_store_ptr->kind = event->kind;
+      volatile struct input_event *sp = kbd_store_ptr;
+      sp->kind = event->kind;
       if (event->kind == selection_request_event)
        {
          /* We must not use the ordinary copying code for this case,
             since `part' is an enum and copying it might not copy enough
             in this case.  */
-         bcopy (event, kbd_store_ptr, sizeof (*event));
+         bcopy (event, (char *) sp, sizeof (*event));
        }
       else
        {
-         kbd_store_ptr->code = event->code;
-         kbd_store_ptr->part = event->part;
-         kbd_store_ptr->frame_or_window = event->frame_or_window;
-         kbd_store_ptr->modifiers = event->modifiers;
-         kbd_store_ptr->x = event->x;
-         kbd_store_ptr->y = event->y;
-         kbd_store_ptr->timestamp = event->timestamp;
+         sp->code = event->code;
+         sp->part = event->part;
+         sp->frame_or_window = event->frame_or_window;
+         sp->modifiers = event->modifiers;
+         sp->x = event->x;
+         sp->y = event->y;
+         sp->timestamp = event->timestamp;
        }
       (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_store_ptr
                                                      - kbd_buffer]
@@ -2024,7 +2166,7 @@ kbd_buffer_store_event (event)
    We always read and discard one event.  */
 
 static Lisp_Object
-kbd_buffer_get_event ()
+kbd_buffer_get_event (PERDISPLAY **perdp)
 {
   register int c;
   Lisp_Object obj;
@@ -2032,15 +2174,20 @@ kbd_buffer_get_event ()
   if (noninteractive)
     {
       c = getchar ();
-      XSET (obj, Lisp_Int, c);
+      XSETINT (obj, c);
+      *perdp = all_perdisplays;  /* There'd better be exactly one!  */
       return obj;
     }
 
   /* Wait until there is input available.  */
   for (;;)
     {
-      if (!EVENT_QUEUES_EMPTY)
+      if (kbd_fetch_ptr != kbd_store_ptr)
+       break;
+#ifdef HAVE_MOUSE
+      if (FRAMEP (do_mouse_tracking) && mouse_moved)
        break;
+#endif
 
       /* If the quit flag is set, then read_char will return
         quit_char, so that counts as "available input."  */
@@ -2057,17 +2204,22 @@ kbd_buffer_get_event ()
 #ifdef SIGIO
       gobble_input (0);
 #endif /* SIGIO */
-      if (EVENT_QUEUES_EMPTY)
-       {
-         Lisp_Object minus_one;
+      if (kbd_fetch_ptr != kbd_store_ptr)
+       break;
+#ifdef HAVE_MOUSE
+      if (FRAMEP (do_mouse_tracking) && mouse_moved)
+       break;
+#endif
+      {
+       Lisp_Object minus_one;
 
-         XSET (minus_one, Lisp_Int, -1);
-         wait_reading_process_input (0, 0, minus_one, 1);
+       XSETINT (minus_one, -1);
+       wait_reading_process_input (0, 0, minus_one, 1);
 
-         if (!interrupt_input && EVENT_QUEUES_EMPTY)
-           /* Pass 1 for EXPECT since we just waited to have input.  */
-           read_avail_input (1);
-       }
+       if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
+         /* Pass 1 for EXPECT since we just waited to have input.  */
+         read_avail_input (1);
+      }
 #endif /* not VMS */
     }
 
@@ -2084,6 +2236,18 @@ kbd_buffer_get_event ()
 
       last_event_timestamp = event->timestamp;
 
+      {
+       Lisp_Object frame;
+       frame = event->frame_or_window;
+       if (CONSP (frame))
+         frame = XCONS (frame)->car;
+       else if (WINDOWP (frame))
+         frame = WINDOW_FRAME (XWINDOW (frame));
+       if (!FRAMEP (frame))
+         abort ();
+       *perdp = get_perdisplay (XFRAME (frame));
+      }
+
       obj = Qnil;
 
       /* These two kinds of events get special handling
@@ -2092,8 +2256,12 @@ kbd_buffer_get_event ()
       if (event->kind == selection_request_event)
        {
 #ifdef HAVE_X11
-         x_handle_selection_request (event);
+         struct input_event copy = *event;
+         /* Remove it from the buffer before processing it,
+            since otherwise swallow_events will see it
+            and process it again.  */
          kbd_fetch_ptr = event + 1;
+         x_handle_selection_request (&copy);
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
@@ -2115,38 +2283,38 @@ kbd_buffer_get_event ()
 #ifdef HAVE_X11
       else if (event->kind == delete_window_event)
        {
-         Lisp_Object tail, frame;
-         struct frame *f;
-       
-         /* If the user destroys the only frame, Emacs should exit.
-            Count visible frames and iconified frames.  */
-         for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-           {
-             frame = XCONS (tail)->car;
-             if (XTYPE (frame) != Lisp_Frame || EQ (frame, event->frame_or_window))
-               continue;
-             f = XFRAME (frame);
-             if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
-               break;
-           }
-
-         if (! CONSP (tail))
-           Fkill_emacs (Qnil);
-
-         Fdelete_frame (event->frame_or_window, Qt);
+         /* Make an event (delete-frame (FRAME)).  */
+         obj = Fcons (event->frame_or_window, Qnil);
+         obj = Fcons (Qdelete_frame, Fcons (obj, Qnil));
+         kbd_fetch_ptr = event + 1;
+       }
+      else if (event->kind == iconify_event)
+       {
+         /* Make an event (iconify-frame (FRAME)).  */
+         obj = Fcons (event->frame_or_window, Qnil);
+         obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
+         kbd_fetch_ptr = event + 1;
+       }
+      else if (event->kind == deiconify_event)
+       {
+         /* Make an event (make-frame-visible (FRAME)).  */
+         obj = Fcons (event->frame_or_window, Qnil);
+         obj = Fcons (Qmake_frame_visible, Fcons (obj, Qnil));
          kbd_fetch_ptr = event + 1;
        }
 #endif
       else if (event->kind == menu_bar_event)
        {
-         /* The event value is in the frame_or_window slot.  */
-         obj = event->frame_or_window;
+         /* The event value is in the cdr of the frame_or_window slot.  */
+         if (!CONSP (event->frame_or_window))
+           abort ();
+         obj = XCONS (event->frame_or_window)->cdr;
          kbd_fetch_ptr = event + 1;
        }
       else if (event->kind == buffer_switch_event)
        {
          /* The value doesn't matter here; only the type is tested.  */
-         XSET (obj, Lisp_Buffer, current_buffer);
+         XSETBUFFER (obj, current_buffer);
          kbd_fetch_ptr = event + 1;
        }
       /* Just discard these, by returning nil.
@@ -2164,17 +2332,17 @@ kbd_buffer_get_event ()
          Lisp_Object focus;
 
          frame = event->frame_or_window;
-         if (XTYPE (frame) == Lisp_Window)
+         if (WINDOWP (frame))
            frame = WINDOW_FRAME (XWINDOW (frame));
 
          focus = FRAME_FOCUS_FRAME (XFRAME (frame));
          if (! NILP (focus))
            frame = focus;
 
-         if (! EQ (frame, internal_last_event_frame)
+         if (! EQ (frame, (*perdp)->internal_last_event_frame)
              && XFRAME (frame) != selected_frame)
            obj = make_lispy_switch_frame (frame);
-         internal_last_event_frame = frame;
+         (*perdp)->internal_last_event_frame = frame;
 #endif /* MULTI_FRAME */
 
          /* If we didn't decide to make a switch-frame event, go ahead
@@ -2186,22 +2354,30 @@ kbd_buffer_get_event ()
 
              /* Wipe out this event, to catch bugs.  */
              event->kind = no_event;
-             (XVECTOR (kbd_buffer_frame_or_window)->contents[event - kbd_buffer]
-              = Qnil);
+             XVECTOR (kbd_buffer_frame_or_window)->contents[event - kbd_buffer] = Qnil;
 
              kbd_fetch_ptr = event + 1;
            }
        }
     }
+#ifdef HAVE_MOUSE
   /* Try generating a mouse motion event.  */
-  else if (do_mouse_tracking && mouse_moved)
+  else if (FRAMEP (do_mouse_tracking) && mouse_moved)
     {
-      FRAME_PTR f = 0;
+      FRAME_PTR f = XFRAME (do_mouse_tracking);
       Lisp_Object bar_window;
       enum scroll_bar_part part;
       Lisp_Object x, y;
       unsigned long time;
 
+      if (!current_perdisplay)
+       abort ();
+
+      *perdp = current_perdisplay;
+      /* Note that this uses F to determine which display to look at.
+        If there is no valid info, it does not store anything
+        so x remains nil.  */
+      x = Qnil;
       (*mouse_position_hook) (&f, &bar_window, &part, &x, &y, &time);
 
       obj = Qnil;
@@ -2210,28 +2386,27 @@ kbd_buffer_get_event ()
       /* Decide if we should generate a switch-frame event.  Don't
         generate switch-frame events for motion outside of all Emacs
         frames.  */
-      if (f)
+      if (!NILP (x) && f)
        {
          Lisp_Object frame;
 
          frame = FRAME_FOCUS_FRAME (f);
          if (NILP (frame))
-           XSET (frame, Lisp_Frame, f);
+           XSETFRAME (frame, f);
 
-         if (! EQ (frame, internal_last_event_frame)
+         if (! EQ (frame, (*perdp)->internal_last_event_frame)
              && XFRAME (frame) != selected_frame)
            obj = make_lispy_switch_frame (frame);
-         internal_last_event_frame = frame;
+         (*perdp)->internal_last_event_frame = frame;
        }
 #endif
 
-#if defined(MULTI_FRAME) || defined(HAVE_MOUSE)
       /* If we didn't decide to make a switch-frame event, go ahead and 
         return a mouse-motion event.  */
-      if (NILP (obj))
+      if (!NILP (x) && NILP (obj))
        obj = make_lispy_movement (f, bar_window, part, x, y, time);
-#endif
     }
+#endif /* HAVE_MOUSE */
   else
     /* We were promised by the above while loop that there was
        something for us to read!  */
@@ -2240,7 +2415,7 @@ kbd_buffer_get_event ()
   input_pending = readable_events ();
 
 #ifdef MULTI_FRAME
-  Vlast_event_frame = internal_last_event_frame;
+  (*perdp)->Vlast_event_frame = (*perdp)->internal_last_event_frame;
 #endif
 
   return (obj);
@@ -2267,8 +2442,10 @@ swallow_events ()
       if (event->kind == selection_request_event)
        {
 #ifdef HAVE_X11
-         x_handle_selection_request (event);
+         struct input_event copy;
+         copy = *event;
          kbd_fetch_ptr = event + 1;
+         x_handle_selection_request (&copy);
 #else
          /* We're getting selection request events, but we don't have
              a window system.  */
@@ -2552,15 +2729,12 @@ make_lispy_event (event)
 {
   int i;
 
-#ifdef SWITCH_ENUM_BUG
-  switch ((int) event->kind)
-#else
-  switch (event->kind)
-#endif
+  switch (SWITCH_ENUM_CAST (event->kind))
     {
       /* A simple keystroke.  */
     case ascii_keystroke:
       {
+       Lisp_Object lispy_c;
        int c = event->code & 0377;
        /* Turn ASCII characters into control characters
           when proper.  */
@@ -2574,7 +2748,8 @@ make_lispy_event (event)
              & (meta_modifier | alt_modifier
                 | hyper_modifier | super_modifier));
        button_down_time = 0;
-       return c;
+       XSETFASTINT (lispy_c, c);
+       return lispy_c;
       }
 
       /* A function key.  The symbol may need to have modifier prefixes
@@ -2612,7 +2787,7 @@ make_lispy_event (event)
                                   / sizeof (lispy_function_keys[0])));
       break;
 
-#if defined(MULTI_FRAME) || defined(HAVE_MOUSE)
+#if defined (MULTI_FRAME) || defined (HAVE_MOUSE)
       /* A mouse click.  Figure out where it is, decide whether it's 
          a press, click or drag, and build the appropriate structure.  */
     case mouse_click:
@@ -2642,13 +2817,17 @@ make_lispy_event (event)
              return Qnil;
 
            pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
-                                  &column, &row, 0, 0);
+                                  &column, &row, 0, 1);
 
-#ifdef USE_X_TOOLKIT
-           if (FRAME_EXTERNAL_MENU_BAR (f) && XINT (event->y) == -1)
-#else
-           if (row < FRAME_MENU_BAR_LINES (f))
-#endif
+#ifndef USE_X_TOOLKIT
+           /* In the non-toolkit version, clicks on the menu bar
+              are ordinary button events in the event buffer.
+              Distinguish them, and invoke the menu.
+
+              (In the toolkit version, the toolkit handles the menu bar
+              and Emacs doesn't know about it until after the user
+              makes a selection.)  */
+           if (row >= 0 && row < FRAME_MENU_BAR_LINES (f))
              {
                Lisp_Object items, item;
                int hpos;
@@ -2660,13 +2839,6 @@ make_lispy_event (event)
                if (! (event->modifiers & down_modifier))
                  return Qnil;
 
-#ifdef USE_X_TOOLKIT
-               /* The click happened in the menubar.
-                  Look for the menu item selected.  */
-               item = map_event_to_object (event, f);
-
-               XFASTINT (event->y) = 1;
-#else /* not USE_X_TOOLKIT  */
                item = Qnil;
                items = FRAME_MENU_BAR_ITEMS (f);
                for (i = 0; i < XVECTOR (items)->size; i += 3)
@@ -2683,7 +2855,6 @@ make_lispy_event (event)
                        break;
                      }
                  }
-#endif /* not USE_X_TOOLKIT  */
 
                position
                  = Fcons (event->frame_or_window,
@@ -2694,10 +2865,11 @@ make_lispy_event (event)
 
                return Fcons (item, Fcons (position, Qnil));
              }
+#endif /* not USE_X_TOOLKIT */
 
            window = window_from_coordinates (f, column, row, &part);
 
-           if (XTYPE (window) != Lisp_Window)
+           if (!WINDOWP (window))
              {
                window = event->frame_or_window;
                posn = Qnil;
@@ -2716,9 +2888,9 @@ make_lispy_event (event)
                else if (part == 2)
                  posn = Qvertical_line;
                else
-                 XSET (posn, Lisp_Int,
-                       buffer_posn_from_coords (XWINDOW (window),
-                                                column, row));
+                 XSETINT (posn,
+                          buffer_posn_from_coords (XWINDOW (window),
+                                                   column, row));
              }
 
            position
@@ -2791,12 +2963,12 @@ make_lispy_event (event)
               of the button that chose the menu item
               as a separate event.  */
 
-           if (XTYPE (start_pos) != Lisp_Cons)
+           if (!CONSP (start_pos))
              return Qnil;
 
            event->modifiers &= ~up_modifier;
 #if 0 /* Formerly we treated an up with no down as a click event.  */
-           if (XTYPE (start_pos) != Lisp_Cons)
+           if (!CONSP (start_pos))
              event->modifiers |= click_modifier;
            else
 #endif
@@ -2809,18 +2981,19 @@ make_lispy_event (event)
                if (EQ (event->x, XCONS (down)->car)
                    && EQ (event->y, XCONS (down)->cdr))
                  {
-                   if (is_double && double_click_count > 1)
-                     event->modifiers |= ((double_click_count > 2)
-                                          ? triple_modifier
-                                          : double_modifier);
-                   else
-                     event->modifiers |= click_modifier;
+                   event->modifiers |= click_modifier;
                  }
                else
                  {
                    button_down_time = 0;
                    event->modifiers |= drag_modifier;
                  }
+               /* Don't check is_double; treat this as multiple
+                  if the down-event was multiple.  */
+               if (double_click_count > 1)
+                 event->modifiers |= ((double_click_count > 2)
+                                      ? triple_modifier
+                                      : double_modifier);
              }
          }
        else
@@ -2862,7 +3035,7 @@ make_lispy_event (event)
     }
 }
 
-#if defined(MULTI_FRAME) || defined(HAVE_MOUSE)
+#if defined (MULTI_FRAME) || defined (HAVE_MOUSE)
 
 static Lisp_Object
 make_lispy_movement (frame, bar_window, part, x, y, time)
@@ -2911,7 +3084,7 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
       else
        window = Qnil;
 
-      if (XTYPE (window) == Lisp_Window)
+      if (WINDOWP (window))
        {
          int pixcolumn, pixrow;
          column -= XINT (XWINDOW (window)->left);
@@ -2925,13 +3098,13 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
          else if (area == 2)
            posn = Qvertical_line;
          else
-           XSET (posn, Lisp_Int,
-                 buffer_posn_from_coords (XWINDOW (window), column, row));
+           XSETINT (posn,
+                    buffer_posn_from_coords (XWINDOW (window), column, row));
        }
 #ifdef MULTI_FRAME
       else if (frame != 0)
        {
-         XSET (window, Lisp_Frame, frame);
+         XSETFRAME (window, frame);
          posn = Qnil;
        }
 #endif
@@ -2939,8 +3112,8 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
        {
          window = Qnil;
          posn = Qnil;
-         XFASTINT (x) = 0;
-         XFASTINT (y) = 0;
+         XSETFASTINT (x, 0);
+         XSETFASTINT (y, 0);
        }
 
       return Fcons (Qmouse_movement,
@@ -3186,7 +3359,7 @@ parse_modifiers (symbol)
 
       if (modifiers & ~((1<<VALBITS) - 1))
        abort ();
-      XFASTINT (mask) = modifiers;
+      XSETFASTINT (mask, modifiers);
       elements = Fcons (unmodified, Fcons (mask, Qnil));
 
       /* Cache the parsing results on SYMBOL.  */
@@ -3225,7 +3398,7 @@ apply_modifiers (modifiers, base)
 
   /* The click modifier never figures into cache indices.  */
   cache = Fget (base, Qmodifier_cache);
-  XFASTINT (index) = (modifiers & ~click_modifier);
+  XSETFASTINT (index, (modifiers & ~click_modifier));
   entry = assq_no_quit (index, cache);
 
   if (CONSP (entry))
@@ -3242,7 +3415,7 @@ apply_modifiers (modifiers, base)
       Fput (base, Qmodifier_cache, Fcons (entry, cache));
 
       /* We have the parsing info now for free, so add it to the caches.  */
-      XFASTINT (index) = modifiers;
+      XSETFASTINT (index, modifiers);
       Fput (new_symbol, Qevent_symbol_element_mask,
            Fcons (base, Fcons (index, Qnil)));
       Fput (new_symbol, Qevent_symbol_elements,
@@ -3334,7 +3507,7 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist,
   Lisp_Object value;
   Lisp_Object symbol_int;
 
-  XSET (symbol_int, Lisp_Int, symbol_num);
+  XSETINT (symbol_int, symbol_num);
 
   /* Is this a request for a valid symbol?  */
   if (symbol_num < 0 || symbol_num >= table_size)
@@ -3354,7 +3527,7 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist,
        {
          Lisp_Object size;
 
-         XFASTINT (size) = table_size;
+         XSETFASTINT (size, table_size);
          *symbol_table = Fmake_vector (size, Qnil);
        }
 
@@ -3415,7 +3588,7 @@ get_input_pending (addr)
   *addr = !NILP (Vquit_flag) || readable_events ();
 }
 
-/* Interface to read_avail_input, blocking SIGIO if necessary.  */
+/* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary.  */
 
 int
 gobble_input (expected)
@@ -3431,6 +3604,16 @@ gobble_input (expected)
       sigsetmask (mask);
     }
   else
+#ifdef POLL_FOR_INPUT
+  if (read_socket_hook && !interrupt_input && poll_suppress_count == 0)
+    {
+      SIGMASKTYPE mask;
+      mask = sigblockx (SIGALRM);
+      read_avail_input (expected);
+      sigsetmask (mask);
+    }
+  else
+#endif
 #endif
     read_avail_input (expected);
 #endif
@@ -3502,7 +3685,8 @@ read_avail_input (expected)
 
   if (read_socket_hook)
     /* No need for FIONREAD or fcntl; just say don't wait.  */
-    nread = (*read_socket_hook) (0, buf, KBD_BUFFER_SIZE, expected, expected);
+    nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE,
+                                expected, expected);
   else
     {
       /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
@@ -3512,6 +3696,9 @@ read_avail_input (expected)
       int n_to_read;
 
       /* Determine how many characters we should *try* to read.  */
+#ifdef WINDOWSNT
+      return 0;
+#else /* not WINDOWSNT */
 #ifdef MSDOS
       n_to_read = dos_keysns ();
       if (n_to_read == 0)
@@ -3519,7 +3706,7 @@ read_avail_input (expected)
 #else /* not MSDOS */
 #ifdef FIONREAD
       /* Find out how much input is available.  */
-      if (ioctl (0, FIONREAD, &n_to_read) < 0)
+      if (ioctl (input_fd, FIONREAD, &n_to_read) < 0)
        /* Formerly simply reported no input, but that sometimes led to
           a failure of Emacs to terminate.
           SIGHUP seems appropriate if we can't reach the terminal.  */
@@ -3535,12 +3722,13 @@ read_avail_input (expected)
 #if defined(USG) || defined(DGUX)
       /* Read some input if available, but don't wait.  */
       n_to_read = sizeof cbuf;
-      fcntl (fileno (stdin), F_SETFL, O_NDELAY);
+      fcntl (input_fd, F_SETFL, O_NDELAY);
 #else
       you lose;
 #endif
 #endif
 #endif /* not MSDOS */
+#endif /* not WINDOWSNT */
 
       /* Now read; for one reason or another, this will not block.
         NREAD is set to the number of chars read.  */
@@ -3550,7 +3738,7 @@ read_avail_input (expected)
          cbuf[0] = dos_keyread();
          nread = 1;
 #else
-         nread = read (fileno (stdin), cbuf, n_to_read);
+         nread = read (input_fd, cbuf, n_to_read);
 #endif
 #if defined (AIX) && (! defined (aix386) && defined (_BSD))
          /* The kernel sometimes fails to deliver SIGHUP for ptys.
@@ -3582,7 +3770,7 @@ read_avail_input (expected)
 
 #ifndef FIONREAD
 #if defined (USG) || defined (DGUX)
-      fcntl (fileno (stdin), F_SETFL, 0);
+      fcntl (input_fd, F_SETFL, 0);
 #endif /* USG or DGUX */
 #endif /* no FIONREAD */
       for (i = 0; i < nread; i++)
@@ -3593,10 +3781,10 @@ read_avail_input (expected)
            buf[i].modifiers = meta_modifier;
          if (meta_key != 2)
            cbuf[i] &= ~0x80;
-           
-         XSET (buf[i].code,            Lisp_Int,   cbuf[i]);
+
+         buf[i].code = cbuf[i];
 #ifdef MULTI_FRAME
-         XSET (buf[i].frame_or_window, Lisp_Frame, selected_frame);
+         XSETFRAME (buf[i].frame_or_window, selected_frame);
 #else
          buf[i].frame_or_window = Qnil;
 #endif
@@ -3610,7 +3798,7 @@ read_avail_input (expected)
       /* Don't look at input that follows a C-g too closely.
         This reduces lossage due to autorepeat on C-g.  */
       if (buf[i].kind == ascii_keystroke
-         && XINT(buf[i].code) == quit_char)
+         && buf[i].code == quit_char)
        break;
     }
 
@@ -3694,7 +3882,7 @@ map_prompt (map)
     {
       register Lisp_Object tem;
       tem = Fcar (map);
-      if (XTYPE (tem) == Lisp_String)
+      if (STRINGP (tem))
        return tem;
       map = Fcdr (map);
     }
@@ -3708,7 +3896,7 @@ static void menu_bar_one_keymap ();
    menu_bar_items and its subroutines, and the current index
    for storing into that vector.  */
 static Lisp_Object menu_bar_items_vector;
-static Lisp_Object menu_bar_items_index;
+static int menu_bar_items_index;
 
 /* Return a vector of menu items for a menu bar, appropriate
    to the current buffer.  Each item has three elements in the vector:
@@ -3764,14 +3952,26 @@ menu_bar_items (old)
   { 
     Lisp_Object *tmaps;
 
-    if (!NILP (Voverriding_local_map))
+    /* Should overriding-local-map apply, here?  */
+    if (!NILP (Voverriding_local_map_menu_flag))
       {
-       nmaps = 2;
-       maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
-       maps[0] = Voverriding_local_map;
+       if (NILP (Voverriding_local_map))
+         {
+           /* Yes, and it is nil.  Use just global map.  */
+           nmaps = 1;
+           maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+         }
+       else
+         {
+           /* Yes, and it is non-nil.  Use it and the global map.  */
+           nmaps = 2;
+           maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
+           maps[0] = Voverriding_local_map;
+         }
       }
     else
       {
+       /* No, so use major and minor mode keymaps.  */
        nmaps = current_minor_maps (0, &tmaps) + 2;
        maps = (Lisp_Object *) alloca (nmaps * sizeof (maps[0]));
        bcopy (tmaps, maps, (nmaps - 2) * sizeof (maps[0]));
@@ -3859,23 +4059,23 @@ menu_bar_one_keymap (keymap)
   Lisp_Object tail, item, key, binding, item_string, table;
 
   /* Loop over all keymap entries that have menu strings.  */
-  for (tail = keymap; XTYPE (tail) == Lisp_Cons; tail = XCONS (tail)->cdr)
+  for (tail = keymap; CONSP (tail); tail = XCONS (tail)->cdr)
     {
       item = XCONS (tail)->car;
-      if (XTYPE (item) == Lisp_Cons)
+      if (CONSP (item))
        {
          key = XCONS (item)->car;
          binding = XCONS (item)->cdr;
-         if (XTYPE (binding) == Lisp_Cons)
+         if (CONSP (binding))
            {
              item_string = XCONS (binding)->car;
-             if (XTYPE (item_string) == Lisp_String)
+             if (STRINGP (item_string))
                menu_bar_item (key, item_string, Fcdr (binding));
            }
          else if (EQ (binding, Qundefined))
            menu_bar_item (key, Qnil, binding);
        }
-      else if (XTYPE (item) == Lisp_Vector)
+      else if (VECTORP (item))
        {
          /* Loop over the char values represented in the vector.  */
          int len = XVECTOR (item)->size;
@@ -3883,12 +4083,12 @@ menu_bar_one_keymap (keymap)
          for (c = 0; c < len; c++)
            {
              Lisp_Object character;
-             XFASTINT (character) = c;
+             XSETFASTINT (character, c);
              binding = XVECTOR (item)->contents[c];
-             if (XTYPE (binding) == Lisp_Cons)
+             if (CONSP (binding))
                {
                  item_string = XCONS (binding)->car;
-                 if (XTYPE (item_string) == Lisp_String)
+                 if (STRINGP (item_string))
                    menu_bar_item (key, item_string, Fcdr (binding));
                }
              else if (EQ (binding, Qundefined))
@@ -3942,7 +4142,7 @@ menu_bar_item (key, item_string, def)
   /* See if this entry is enabled.  */
   enabled = Qt;
 
-  if (XTYPE (def) == Lisp_Symbol)
+  if (SYMBOLP (def))
     {
       /* No property, or nil, means enable.
         Otherwise, enable if value is not nil.  */
@@ -4030,6 +4230,13 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
   if (! menu_prompting)
     return Qnil;
 
+  /* Optionally disregard all but the global map.  */
+  if (inhibit_local_menu_bar_menus)
+    {
+      maps += (nmaps - 1);
+      nmaps = 1;
+    }
+
   /* Get the menu name from the first map that has one (a prompt string).  */
   for (mapno = 0; mapno < nmaps; mapno++)
     {
@@ -4042,8 +4249,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
   if (mapno >= nmaps)
     return Qnil;
 
-#ifdef HAVE_X_WINDOWS
-#ifdef HAVE_X_MENU
+#if (defined (HAVE_X_WINDOWS) && defined (HAVE_X_MENU)) || defined (MSDOS)
   /* If we got to this point via a mouse click,
      use a real menu for mouse selection.  */
   if (EVENT_HAS_PARAMETERS (prev_event))
@@ -4075,8 +4281,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
        *used_mouse_menu = 1;
       return value;
     }
-#endif /* HAVE_X_MENU */
-#endif /* HAVE_X_WINDOWS */
+#endif /* (HAVE_X_WINDOWS && HAVE_X_MENU) || MSDOS */
   return Qnil ;
 }
 
@@ -4155,7 +4360,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
          else
            elt = Fcar_safe (rest);
 
-         if (idx < 0 && XTYPE (elt) == Lisp_Vector)
+         if (idx < 0 && VECTORP (elt))
            {
              /* If we found a dense table in the keymap,
                 advanced past it, but start scanning its contents.  */
@@ -4170,7 +4375,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
                s = Fcar_safe (Fcdr_safe (elt));        /* alist */
              else
                s = Fcar_safe(elt);                     /* vector */
-             if (XTYPE (s) != Lisp_String)
+             if (!STRINGP (s))
                /* Ignore the element if it has no prompt string.  */
                ;
              /* If we have room for the prompt string, add it to this line.
@@ -4227,16 +4432,16 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
       defining_kbd_macro = 0 ;
       do
        obj = read_char (commandflag, 0, 0, Qnil, 0);
-      while (XTYPE (obj) == Lisp_Buffer);
+      while (BUFFERP (obj));
       defining_kbd_macro = orig_defn_macro ;
 
-      if (XTYPE (obj) != Lisp_Int)
+      if (!INTEGERP (obj))
        return obj;
       else
        ch = XINT (obj);
 
       if (! EQ (obj, menu_prompt_more_char)
-         && (XTYPE (menu_prompt_more_char) != Lisp_Int
+         && (!INTEGERP (menu_prompt_more_char)
              || ! EQ (obj, make_number (Ctl (XINT (menu_prompt_more_char))))))
        {
          if ( defining_kbd_macro )
@@ -4274,7 +4479,7 @@ follow_key (key, nmaps, current, defs, next)
 
   /* If KEY is a meta ASCII character, treat it like meta-prefix-char
      followed by the corresponding non-meta character.  */
-  if (XTYPE (key) == Lisp_Int && (XINT (key) & CHAR_META))
+  if (INTEGERP (key) && (XINT (key) & CHAR_META))
     {
       for (i = 0; i < nmaps; i++)
        if (! NILP (current[i]))
@@ -4291,7 +4496,7 @@ follow_key (key, nmaps, current, defs, next)
          next[i] = Qnil;
 
       current = next;
-      XSET (key, Lisp_Int, XFASTINT (key) & ~CHAR_META);
+      XSETINT (key, XFASTINT (key) & ~CHAR_META);
     }
 
   first_binding = nmaps;
@@ -4350,10 +4555,11 @@ follow_key (key, nmaps, current, defs, next)
    read_char will return it.  */
 
 static int
-read_key_sequence (keybuf, bufsize, prompt)
+read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last)
      Lisp_Object *keybuf;
      int bufsize;
      Lisp_Object prompt;
+     int dont_downcase_last;
 {
   int count = specpdl_ptr - specpdl;
 
@@ -4378,6 +4584,13 @@ read_key_sequence (keybuf, bufsize, prompt)
      in the current keymaps, or nil where it is not a prefix.  */
   Lisp_Object *submaps;
 
+  /* The local map to start out with at start of key sequence.  */
+  Lisp_Object orig_local_map;
+
+  /* 1 if we have already considered switching to the local-map property
+     of the place where a mouse click occurred.  */
+  int localized_local_map = 0;
+
   /* The index in defs[] of the first keymap that has a binding for
      this key sequence.  In other words, the lowest i such that
      defs[i] is non-nil.  */
@@ -4422,11 +4635,18 @@ read_key_sequence (keybuf, bufsize, prompt)
   Lisp_Object first_event;
 #endif
 
+  Lisp_Object original_uppercase;
+  int original_uppercase_position = -1;
+
+  /* Gets around Microsoft compiler limitations.  */
+  int dummyflag = 0;
+
   struct buffer *starting_buffer;
 
   /* Nonzero if we seem to have got the beginning of a binding
      in function_key_map.  */
   int function_key_possible = 0;
+  int key_translation_possible = 0;
 
   int junk;
 
@@ -4471,6 +4691,8 @@ read_key_sequence (keybuf, bufsize, prompt)
                           &junk);
 #endif /* GOBBLE_FIRST_EVENT */
 
+  orig_local_map = get_local_map (PT, current_buffer);
+
   /* 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.  */
@@ -4478,6 +4700,7 @@ read_key_sequence (keybuf, bufsize, prompt)
 
   starting_buffer = current_buffer;
   function_key_possible = 0;
+  key_translation_possible = 0;
 
   /* Build our list of keymaps.
      If we recognize a function key and replace its escape sequence in
@@ -4509,7 +4732,7 @@ read_key_sequence (keybuf, bufsize, prompt)
          }
        bcopy (maps, submaps, (nmaps - 2) * sizeof (submaps[0]));
 #ifdef USE_TEXT_PROPERTIES
-       submaps[nmaps-2] = get_local_map (PT, current_buffer);
+       submaps[nmaps-2] = orig_local_map;
 #else
        submaps[nmaps-2] = current_buffer->keymap;
 #endif
@@ -4540,9 +4763,7 @@ read_key_sequence (keybuf, bufsize, prompt)
             /* mock input is never part of a function key's sequence.  */
             && mock_input <= fkey_start)
         || (first_binding >= nmaps
-            && keytran_start < t
-            /* mock input is never part of a function key's sequence.  */
-            && mock_input <= keytran_start)
+            && keytran_start < t && key_translation_possible)
         /* Don't return in the middle of a possible function key sequence,
            if the only bindings we found were via case conversion.
            Thus, if ESC O a has a function-key-map translation
@@ -4601,8 +4822,21 @@ read_key_sequence (keybuf, bufsize, prompt)
        {
          struct buffer *buf = current_buffer;
 
-         key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event,
-                          &used_mouse_menu);
+         {
+#ifdef MULTI_PERDISPLAY
+           PERDISPLAY *interrupted_perdisplay = current_perdisplay;
+           if (setjmp (wrong_display_jmpbuf))
+             {
+               while (t > 0)
+                 interrupted_perdisplay->kbd_queue
+                   = Fcons (keybuf[--t], interrupted_perdisplay->kbd_queue);
+               mock_input = 0;
+               goto replay_sequence;
+             }
+#endif
+           key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event,
+                            &used_mouse_menu);
+         }
 
          /* read_char returns t when it shows a menu and the user rejects it.
             Just return -1.  */
@@ -4612,15 +4846,18 @@ read_key_sequence (keybuf, bufsize, prompt)
          /* read_char returns -1 at the end of a macro.
             Emacs 18 handles this by returning immediately with a
             zero, so that's what we'll do.  */
-         if (XTYPE (key) == Lisp_Int && XINT (key) == -1)
+         if (INTEGERP (key) && XINT (key) == -1)
            {
              t = 0;
-             goto done;
+             /* The Microsoft C compiler can't handle the goto that
+                would go here.  */
+             dummyflag = 1;
+             break;
            }
          
          /* If the current buffer has been changed from under us, the
             keymap may have changed, so replay the sequence.  */
-         if (XTYPE (key) == Lisp_Buffer)
+         if (BUFFERP (key))
            {
              mock_input = t;
              goto replay_sequence;
@@ -4629,7 +4866,7 @@ read_key_sequence (keybuf, bufsize, prompt)
          /* If we have a quit that was typed in another frame, and
             quit_throw_to_read_char switched buffers,
             replay to get the right keymap.  */
-         if (EQ (key, quit_char) && current_buffer != starting_buffer)
+         if (XINT (key) == quit_char && current_buffer != starting_buffer)
            {
              keybuf[t++] = key;
              mock_input = t;
@@ -4665,7 +4902,7 @@ read_key_sequence (keybuf, bufsize, prompt)
 
              window = POSN_WINDOW      (EVENT_START (key));
              posn   = POSN_BUFFER_POSN (EVENT_START (key));
-             if (XTYPE (posn) == Lisp_Cons)
+             if (CONSP (posn))
                {
                  /* We're looking at the second event of a
                     sequence which we expanded before.  Set
@@ -4679,8 +4916,8 @@ read_key_sequence (keybuf, bufsize, prompt)
                 not the current buffer.  If we're at the
                 beginning of a key sequence, switch buffers.  */
              if (last_real_key_start == 0
-                 && XTYPE (window) == Lisp_Window
-                 && XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer
+                 && WINDOWP (window)
+                 && BUFFERP (XWINDOW (window)->buffer)
                  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
                {
                  keybuf[t] = key;
@@ -4699,13 +4936,40 @@ read_key_sequence (keybuf, bufsize, prompt)
                  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
 
                  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
+                 orig_local_map = get_local_map (PT, current_buffer);
                  goto replay_sequence;
                }
-             else if (XTYPE (posn) == Lisp_Symbol)
+             /* For a mouse click, get the local text-property keymap
+                of the place clicked on, rather than point.  */
+             if (last_real_key_start == 0 && CONSP (XCONS (key)->cdr)
+                 && ! localized_local_map)
                {
-                 /* Expand mode-line and scroll-bar events into two events:
-                    use posn as a fake prefix key.  */
+                 Lisp_Object map_here, start, pos;
 
+                 localized_local_map = 1;
+                 start = EVENT_START (key);
+                 if (CONSP (start) && CONSP (XCONS (start)->cdr))
+                   {
+                     pos = POSN_BUFFER_POSN (start);
+                     if (INTEGERP (pos))
+                       {
+                         map_here = get_local_map (XINT (pos), current_buffer);
+                         if (!EQ (map_here, orig_local_map))
+                           {
+                             orig_local_map = map_here;
+                             keybuf[t] = key;
+                             mock_input = t + 1;
+
+                             goto replay_sequence;
+                           }
+                       }
+                   }
+               }
+
+             /* Expand mode-line and scroll-bar events into two events:
+                use posn as a fake prefix key.  */
+             if (SYMBOLP (posn))
+               {
                  if (t + 1 >= bufsize)
                    error ("key sequence too long");
                  keybuf[t] = posn;
@@ -4761,7 +5025,7 @@ read_key_sequence (keybuf, bufsize, prompt)
                  mock_input = t + 2;
                  goto replay_sequence;
                }
-             else if (XTYPE (posn) == Lisp_Cons)
+             else if (CONSP (posn))
                {
                  /* We're looking at the second event of a
                     sequence which we expanded before.  Set
@@ -4792,10 +5056,13 @@ read_key_sequence (keybuf, bufsize, prompt)
              read_key_sequence_cmd = Vprefix_help_command;
              keybuf[t++] = key;
              last_nonmenu_event = key;
-             goto done;
+             /* The Microsoft C compiler can't handle the goto that
+                would go here.  */
+             dummyflag = 1;
+             break;
            }
 
-         if (XTYPE (head) == Lisp_Symbol)
+         if (SYMBOLP (head))
            {
              Lisp_Object breakdown;
              int modifiers;
@@ -4820,8 +5087,10 @@ read_key_sequence (keybuf, bufsize, prompt)
                      Lisp_Object new_head, new_click;
                      if (modifiers & triple_modifier)
                        modifiers ^= (double_modifier | triple_modifier);
-                     else if (modifiers & (drag_modifier | double_modifier))
-                       modifiers &= ~(drag_modifier | double_modifier);
+                     else if (modifiers & double_modifier)
+                       modifiers &= ~double_modifier;
+                     else if (modifiers & drag_modifier)
+                       modifiers &= ~drag_modifier;
                      else
                        {
                          /* Dispose of this `down' event by simply jumping
@@ -4922,14 +5191,14 @@ read_key_sequence (keybuf, bufsize, prompt)
              key = keybuf[fkey_end++];
              /* Look up meta-characters by prefixing them
                 with meta_prefix_char.  I hate this.  */
-             if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier)
+             if (INTEGERP (key) && XINT (key) & meta_modifier)
                {
                  fkey_next
                    = get_keymap_1
                      (get_keyelt
                       (access_keymap (fkey_map, meta_prefix_char, 1, 0)),
                       0, 1);
-                 XFASTINT (key) = XFASTINT (key) & ~meta_modifier;
+                 XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
                }
              else
                fkey_next = fkey_map;
@@ -4990,14 +5259,18 @@ read_key_sequence (keybuf, bufsize, prompt)
                      int i;
 
                      for (i = 0; i < len; i++)
-                       XFASTINT (keybuf[fkey_start + i])
-                         = XSTRING (fkey_next)->data[i];
+                       XSETFASTINT (keybuf[fkey_start + i],
+                                    XSTRING (fkey_next)->data[i]);
                    }
                  
                  mock_input = t;
                  fkey_start = fkey_end = t;
                  fkey_map = Vfunction_key_map;
 
+                 /* Do pass the results through key-translation-map.  */
+                 keytran_start = keytran_end = 0;
+                 keytran_map = Vkey_translation_map;
+
                  goto replay_sequence;
                }
              
@@ -5026,14 +5299,14 @@ read_key_sequence (keybuf, bufsize, prompt)
            key = keybuf[keytran_end++];
            /* Look up meta-characters by prefixing them
               with meta_prefix_char.  I hate this.  */
-           if (XTYPE (key) == Lisp_Int && XINT (key) & meta_modifier)
+           if (INTEGERP (key) && XINT (key) & meta_modifier)
              {
                keytran_next
                  = get_keymap_1
                    (get_keyelt
                     (access_keymap (keytran_map, meta_prefix_char, 1, 0)),
                     0, 1);
-               XFASTINT (key) = XFASTINT (key) & ~meta_modifier;
+               XSETFASTINT (key, XFASTINT (key) & ~meta_modifier);
              }
            else
              keytran_next = keytran_map;
@@ -5062,6 +5335,8 @@ read_key_sequence (keybuf, bufsize, prompt)
                  error ("Function in key-translation-map returns invalid key sequence");
              }
 
+           key_translation_possible = ! NILP (keytran_next);
+
            /* If keybuf[keytran_start..keytran_end] is bound in the
               key translation map and it's a suffix of the current
               sequence (i.e. keytran_end == t), replace it with
@@ -5084,14 +5359,19 @@ read_key_sequence (keybuf, bufsize, prompt)
                    int i;
 
                    for (i = 0; i < len; i++)
-                     XFASTINT (keybuf[keytran_start + i])
-                       = XSTRING (keytran_next)->data[i];
+                     XSETFASTINT (keybuf[keytran_start + i],
+                                  XSTRING (keytran_next)->data[i]);
                  }
 
                mock_input = t;
                keytran_start = keytran_end = t;
                keytran_map = Vkey_translation_map;
 
+               /* Don't pass the results of key-translation-map
+                  through function-key-map.  */
+               fkey_start = fkey_end = t;
+               fkey_map = Vkey_translation_map;
+
                goto replay_sequence;
              }
 
@@ -5103,6 +5383,7 @@ read_key_sequence (keybuf, bufsize, prompt)
              {
                keytran_end = ++keytran_start;
                keytran_map = Vkey_translation_map;
+               key_translation_possible = 0;
              }
          }
       }
@@ -5112,12 +5393,16 @@ read_key_sequence (keybuf, bufsize, prompt)
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
       if (first_binding == nmaps && ! function_key_possible
-         && XTYPE (key) == Lisp_Int
+         && ! key_translation_possible
+         && INTEGERP (key)
          && ((((XINT (key) & 0x3ffff)
                < XSTRING (current_buffer->downcase_table)->size)
               && UPPERCASEP (XINT (key) & 0x3ffff))
              || (XINT (key) & shift_modifier)))
        {
+         original_uppercase = key;
+         original_uppercase_position = t - 1;
+
          if (XINT (key) & shift_modifier)
            XSETINT (key, XINT (key) & ~shift_modifier);
          else
@@ -5128,16 +5413,46 @@ read_key_sequence (keybuf, bufsize, prompt)
          mock_input = t;
          goto replay_sequence;
        }
+      /* If KEY is not defined in any of the keymaps,
+        and cannot be part of a function key or translation,
+        and is a shifted function key,
+        use the corresponding unshifted function key instead.  */
+      if (first_binding == nmaps && ! function_key_possible
+         && ! key_translation_possible
+         && SYMBOLP (key))
+       {
+         Lisp_Object breakdown;
+         int modifiers;
+
+         original_uppercase = key;
+         original_uppercase_position = t - 1;
+
+         breakdown = parse_modifiers (key);
+         modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car);
+         if (modifiers & shift_modifier)
+           {
+             modifiers &= ~shift_modifier;
+             key = apply_modifiers (make_number (modifiers),
+                                    XCONS (breakdown)->car);
+
+             keybuf[t - 1] = key;
+             mock_input = t;
+             goto replay_sequence;
+           }
+       }
     }
 
-  read_key_sequence_cmd = (first_binding < nmaps
-                          ? defs[first_binding]
-                          : Qnil);
+  if (!dummyflag)
+    read_key_sequence_cmd = (first_binding < nmaps
+                            ? defs[first_binding]
+                            : Qnil);
 
- done:
   unread_switch_frame = delayed_switch_frame;
   unbind_to (count, Qnil);
 
+  if (dont_downcase_last && t - 1 == original_uppercase_position)
+    keybuf[t - 1] = original_uppercase;
+
   /* Occasionally we fabricate events, perhaps by expanding something
      according to function-key-map, or by adding a prefix symbol to a
      mouse click in the scroll bar or modeline.  In this cases, return
@@ -5168,6 +5483,12 @@ First arg PROMPT is a prompt string.  If nil, do not prompt specially.\n\
 Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos\n\
 as a continuation of the previous key.\n\
 \n\
+The third (optional) arg DONT-DOWNCASE-LAST, if non-nil, means do not\n\
+convert the last event to lower case.  (Normally any upper case event\n\
+is converted to lower case if the original event is undefined and the lower\n\
+case equivalent is defined.)  A non-nil value is appropriate for reading\n\
+a key sequence to be defined.\n\
+\n\
 A C-g typed while in this function is treated like any other character,\n\
 and `quit-flag' is not set.\n\
 \n\
@@ -5195,10 +5516,10 @@ sequences, where they wouldn't conflict with ordinary bindings.  See\n\
   (prompt, continue_echo)
 #endif
 
-DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 2, 0,
+DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 3, 0,
   0)
-  (prompt, continue_echo)
-     Lisp_Object prompt, continue_echo;
+  (prompt, continue_echo, dont_downcase_last)
+     Lisp_Object prompt, continue_echo, dont_downcase_last;
 {
   Lisp_Object keybuf[30];
   register int i;
@@ -5215,7 +5536,8 @@ DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 2, 0,
   if (NILP (continue_echo))
     this_command_key_count = 0;
 
-  i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), prompt);
+  i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])),
+                        prompt, ! NILP (dont_downcase_last));
 
   if (i == -1)
     {
@@ -5241,11 +5563,12 @@ Otherwise, that is done only if an arg is read using the minibuffer.")
   struct backtrace backtrace;
   extern int debug_on_next_call;
 
-  prefixarg = Vprefix_arg, Vprefix_arg = Qnil;
-  Vcurrent_prefix_arg = prefixarg;
+  prefixarg = current_perdisplay->Vprefix_arg;
+  current_perdisplay->Vprefix_arg = Qnil;
+  current_perdisplay->Vcurrent_prefix_arg = prefixarg;
   debug_on_next_call = 0;
 
-  if (XTYPE (cmd) == Lisp_Symbol)
+  if (SYMBOLP (cmd))
     {
       tem = Fget (cmd, Qdisabled);
       if (!NILP (tem) && !NILP (Vrun_hooks))
@@ -5262,8 +5585,7 @@ Otherwise, that is done only if an arg is read using the minibuffer.")
        break;
     }
 
-  if (XTYPE (final) == Lisp_String
-      || XTYPE (final) == Lisp_Vector)
+  if (STRINGP (final) || VECTORP (final))
     {
       /* If requested, place the macro in the command history.  For
         other sorts of commands, call-interactively takes care of
@@ -5276,8 +5598,7 @@ Otherwise, that is done only if an arg is read using the minibuffer.")
 
       return Fexecute_kbd_macro (final, prefixarg);
     }
-  if (CONSP (final) || XTYPE (final) == Lisp_Subr
-      || XTYPE (final) == Lisp_Compiled)
+  if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
     {
       backtrace.next = backtrace_list;
       backtrace_list = &backtrace;
@@ -5314,9 +5635,9 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
     strcpy (buf, "- ");
   else if (CONSP (prefixarg) && XINT (XCONS (prefixarg)->car) == 4)
     strcpy (buf, "C-u ");
-  else if (CONSP (prefixarg) && XTYPE (XCONS (prefixarg)->car) == Lisp_Int)
+  else if (CONSP (prefixarg) && INTEGERP (XCONS (prefixarg)->car))
     sprintf (buf, "%d ", XINT (XCONS (prefixarg)->car));
-  else if (XTYPE (prefixarg) == Lisp_Int)
+  else if (INTEGERP (prefixarg))
     sprintf (buf, "%d ", XINT (prefixarg));
 
   /* This isn't strictly correct if execute-extended-command
@@ -5349,18 +5670,18 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
     str = XSTRING (function);
     for (i = 0; i < str->size; i++)
       {
-       XFASTINT (tem) = str->data[i];
+       XSETFASTINT (tem, str->data[i]);
        add_command_key (tem);
       }
 
-    XFASTINT (tem) = '\015';
+    XSETFASTINT (tem, '\015');
     add_command_key (tem);
   }
 
   UNGCPRO;
 
   function = Fintern (function, Qnil);
-  Vprefix_arg = prefixarg;
+  current_perdisplay->Vprefix_arg = prefixarg;
   this_command = function;
 
   return Fcommand_execute (function, Qt);
@@ -5430,7 +5751,7 @@ DEFUN ("recursion-depth", Frecursion_depth, Srecursion_depth, 0, 0, 0,
   ()
 {
   Lisp_Object temp;
-  XFASTINT (temp) = command_loop_level + minibuf_level;
+  XSETFASTINT (temp, command_loop_level + minibuf_level);
   return temp;
 }
 
@@ -5443,8 +5764,11 @@ If FILE is nil, close any open dribble file.")
 {
   if (NILP (file))
     {
-      fclose (dribble);
-      dribble = 0;
+      if (dribble)
+       {
+         fclose (dribble);
+         dribble = 0;
+       }
     }
   else
     {
@@ -5484,10 +5808,8 @@ control, run a subshell instead.\n\n\
 If optional arg STUFFSTRING is non-nil, its characters are stuffed\n\
 to be read as terminal input by Emacs's parent, after suspension.\n\
 \n\
-Before suspending, call the functions in `suspend-hook' with no args.\n\
-If any of them returns nil, don't call the rest and don't suspend.\n\
-Otherwise, suspend normally and after resumption run the normal hook\n\
-`suspend-resume-hook' if that is bound and non-nil.\n\
+Before suspending, run the normal hook `suspend-hook'.\n\
+After resumption run the normal hook `suspend-resume-hook'.\n\
 \n\
 Some operating systems cannot stop the Emacs process and resume it later.\n\
 On such systems, Emacs starts a subshell instead of suspending.")
@@ -5542,12 +5864,12 @@ On such systems, Emacs starts a subshell instead of suspending.")
 stuff_buffered_input (stuffstring)
      Lisp_Object stuffstring;
 {
-  register unsigned char *p;
-
 /* stuff_char works only in BSD, versions 4.2 and up.  */
 #ifdef BSD
 #ifndef BSD4_1
-  if (XTYPE (stuffstring) == Lisp_String)
+  register unsigned char *p;
+
+  if (STRINGP (stuffstring))
     {
       register int count;
 
@@ -5558,7 +5880,9 @@ stuff_buffered_input (stuffstring)
       stuff_char ('\n');
     }
   /* Anything we have read ahead, put back for the shell to read.  */
-  while (kbd_fetch_ptr != kbd_store_ptr)
+  /* ?? What should this do when we have multiple keyboards??
+     Should we ignore anything that was typed in at the "wrong" display?  */
+  for (; kbd_fetch_ptr != kbd_store_ptr; kbd_fetch_ptr++)
     {
       if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
        kbd_fetch_ptr = kbd_buffer;
@@ -5566,9 +5890,8 @@ stuff_buffered_input (stuffstring)
        stuff_char (kbd_fetch_ptr->code);
       kbd_fetch_ptr->kind = no_event;
       (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
-                                                    - kbd_buffer]
+                                                     - kbd_buffer]
        = Qnil);
-      kbd_fetch_ptr++;
     }
   input_pending = 0;
 #endif
@@ -5609,7 +5932,8 @@ clear_waiting_for_input ()
  If  quit-flag  is already non-nil, it stops the job right away.  */
 
 SIGTYPE
-interrupt_signal ()
+interrupt_signal (signalnum)   /* If we don't have an argument, */
+     int signalnum;            /* some compilers complain in signal calls. */
 {
   char c;
   /* Must preserve main program's value of errno.  */
@@ -5735,9 +6059,15 @@ quit_throw_to_read_char ()
     abort ();
 #endif
 #ifdef MULTI_FRAME
-  if (XTYPE (internal_last_event_frame) == Lisp_Frame
-      && XFRAME (internal_last_event_frame) != selected_frame)
-    Fhandle_switch_frame (make_lispy_switch_frame (internal_last_event_frame));
+  {
+    Lisp_Object frame;
+
+    if (!current_perdisplay)
+      abort ();
+    frame = current_perdisplay->internal_last_event_frame;
+    if (FRAMEP (frame) && XFRAME (frame) != selected_frame)
+      Fhandle_switch_frame (make_lispy_switch_frame (frame));
+  }
 #endif
 
   _longjmp (getcjmp, 1);
@@ -5758,8 +6088,7 @@ See also `current-input-mode'.")
      Lisp_Object interrupt, flow, meta, quit;
 {
   if (!NILP (quit)
-      && (XTYPE (quit) != Lisp_Int
-         || XINT (quit) < 0 || XINT (quit) > 0400))
+      && (!INTEGERP (quit) || XINT (quit) < 0 || XINT (quit) > 0400))
     error ("set-input-mode: QUIT must be an ASCII character");
 
 #ifdef POLL_FOR_INPUT
@@ -5823,12 +6152,46 @@ The elements of this list correspond to the arguments of\n\
   val[0] = interrupt_input ? Qt : Qnil;
   val[1] = flow_control ? Qt : Qnil;
   val[2] = meta_key == 2 ? make_number (0) : meta_key == 1 ? Qt : Qnil;
-  XFASTINT (val[3]) = quit_char;
+  XSETFASTINT (val[3], quit_char);
 
   return Flist (sizeof (val) / sizeof (val[0]), val);
 }
 
 \f
+/*
+ * Set up a perdisplay object with reasonable initial values.
+ */
+void
+init_perdisplay (perd)
+     PERDISPLAY *perd;
+{
+  perd->Vprefix_arg = Qnil;
+  perd->Vcurrent_prefix_arg = Qnil;
+#ifdef MULTI_FRAME
+  /* This means that command_loop_1 won't try to select anything the first
+     time through.  */
+  perd->internal_last_event_frame = Qnil;
+#endif
+  perd->kbd_queue = Qnil;
+  perd->Vlast_event_frame = Qnil;
+  perd->immediate_echo = 0;
+  perd->echoptr = perd->echobuf;
+  perd->echo_after_prompt = -1;
+}
+
+/*
+ * Destroy the contents of a perdisplay object, but not the object itself.
+ * We use this just before deleteing it, or if we're going to initialize
+ * it a second time.
+ */
+void
+wipe_perdisplay (perd)
+     PERDISPLAY *perd;
+{
+  /* Free anything that was malloc'd in init_perdisplay.  */
+  /* Placeholder -- currently no action required.  */
+}
+
 init_keyboard ()
 {
   /* This is correct before outermost invocation of the editor loop */
@@ -5841,25 +6204,24 @@ init_keyboard ()
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
   kbd_store_ptr = kbd_buffer;
-  do_mouse_tracking = 0;
+  kbd_buffer_frame_or_window
+    = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
+#ifdef HAVE_MOUSE
+  do_mouse_tracking = Qnil;
+#endif
   input_pending = 0;
 
-#ifdef MULTI_FRAME
-  /* This means that command_loop_1 won't try to select anything the first
-     time through.  */
-  internal_last_event_frame = Qnil;
-  Vlast_event_frame = internal_last_event_frame;
+#ifndef MULTI_PERDISPLAY
+  if (initialized)
+    wipe_perdisplay (&the_only_perdisplay);
+  init_perdisplay (&the_only_perdisplay);
 #endif
 
-  /* If we're running a dumped Emacs, we need to clear out
-     kbd_buffer_frame_or_window, in case some events got into it
-     before we dumped.
-
-     If we're running an undumped Emacs, it hasn't been initialized by
-     syms_of_keyboard yet.  */
   if (initialized)
     Ffillarray (kbd_buffer_frame_or_window, Qnil);
 
+  kbd_buffer_frame_or_window
+    = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
   if (!noninteractive && !read_socket_hook && NILP (Vwindow_system))
     {
       signal (SIGINT, interrupt_signal);
@@ -5913,6 +6275,9 @@ struct event_head head_table[] = {
   &Qmouse_movement,    "mouse-movement",       &Qmouse_movement,
   &Qscroll_bar_movement, "scroll-bar-movement",        &Qmouse_movement,
   &Qswitch_frame,      "switch-frame",         &Qswitch_frame,
+  &Qdelete_frame,      "delete-frame",         &Qdelete_frame,
+  &Qiconify_frame,     "iconify-frame",        &Qiconify_frame,
+  &Qmake_frame_visible,        "make-frame-visible",   &Qmake_frame_visible,
 };
 
 syms_of_keyboard ()
@@ -5941,6 +6306,9 @@ syms_of_keyboard ()
   Qpost_command_hook = intern ("post-command-hook");
   staticpro (&Qpost_command_hook);
 
+  Qdeferred_action_function = intern ("deferred-action-function");
+  staticpro (&Qdeferred_action_function);
+
   Qcommand_hook_internal = intern ("command-hook-internal");
   staticpro (&Qcommand_hook_internal);
 
@@ -6044,7 +6412,9 @@ syms_of_keyboard ()
 
   defsubr (&Sread_key_sequence);
   defsubr (&Srecursive_edit);
+#ifdef HAVE_MOUSE
   defsubr (&Strack_mouse);
+#endif
   defsubr (&Sinput_pending_p);
   defsubr (&Scommand_execute);
   defsubr (&Srecent_keys);
@@ -6087,12 +6457,20 @@ so that you can determine whether the command was run by mouse or not.");
   DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char,
     "Meta-prefix character code.  Meta-foo as command input\n\
 turns into this character followed by foo.");
-  XSET (meta_prefix_char, Lisp_Int, 033);
+  XSETINT (meta_prefix_char, 033);
 
   DEFVAR_LISP ("last-command", &last_command,
     "The last command executed.  Normally a symbol with a function definition,\n\
 but can be whatever was found in the keymap, or whatever the variable\n\
-`this-command' was set to by that command.");
+`this-command' was set to by that command.\n\
+\n\
+The value `mode-exit' is special; it means that the previous command\n\
+read an event that told it to exit, and it did so and unread that event.\n\
+In other words, the present command is the event that made the previous\n\
+command exit.\n\
+\n\
+The value `kill-region' is special; it means that the previous command\n\
+was a kill command.");
   last_command = Qnil;
 
   DEFVAR_LISP ("this-command", &this_command,
@@ -6111,7 +6489,7 @@ Zero means disable autosaving due to number of characters typed.");
 Zero or nil means disable auto-saving due to idleness.\n\
 After auto-saving due to this many seconds of idle time,\n\
 Emacs also does a garbage collection if that seems to be warranted.");
-  XFASTINT (Vauto_save_timeout) = 30;
+  XSETFASTINT (Vauto_save_timeout, 30);
 
   DEFVAR_INT ("echo-keystrokes", &echo_keystrokes,
     "*Nonzero means echo unfinished commands after this many seconds of pause.");
@@ -6131,20 +6509,19 @@ t means double-clicks have no time limit and are detected\n\
 by position only.");
   Vdouble_click_time = make_number (500);
 
+  DEFVAR_BOOL ("inhibit-local-menu-bar-menus", &inhibit_local_menu_bar_menus,
+    "*Non-nil means inhibit local map menu bar menus.");
+  inhibit_local_menu_bar_menus = 0;
+
   DEFVAR_INT ("num-input-keys", &num_input_keys,
-    "*Number of complete keys read from the keyboard so far.");
+    "Number of complete keys read from the keyboard so far.");
   num_input_keys = 0;
 
-  DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
-    "*The frame in which the most recently read event occurred.\n\
-If the last event came from a keyboard macro, this is set to `macro'.");
-  Vlast_event_frame = Qnil;
-
   DEFVAR_LISP ("help-char", &Vhelp_char,
     "Character to recognize as meaning Help.\n\
 When it is read, do `(eval help-form)', and display result if it's a string.\n\
 If the value of `help-form' is nil, this char can be read normally.");
-  XSET (Vhelp_char, Lisp_Int, Ctl ('H'));
+  XSETINT (Vhelp_char, Ctl ('H'));
 
   DEFVAR_LISP ("help-form", &Vhelp_form,
     "Form to execute when character `help-char' is read.\n\
@@ -6193,16 +6570,16 @@ Otherwise, menu prompting uses the echo area.");
   DEFVAR_LISP ("menu-prompt-more-char", &menu_prompt_more_char,
     "Character to see next line of menu prompt.\n\
 Type this character while in a menu prompt to rotate around the lines of it.");
-  XSET (menu_prompt_more_char, Lisp_Int, ' ');
+  XSETINT (menu_prompt_more_char, ' ');
 
   DEFVAR_INT ("extra-keyboard-modifiers", &extra_keyboard_modifiers,
     "A mask of additional modifier keys to use with every keyboard character.\n\
 Emacs applies the modifiers of the character stored here to each keyboard\n\
 character it reads.  For example, after evaluating the expression\n\
-    (setq extra-keyboard-modifiers ?\C-x)\n\
+    (setq extra-keyboard-modifiers ?\\C-x)\n\
 all input characters will have the control modifier applied to them.\n\
 \n\
-Note that the character ?\C-@, equivalent to the integer zero, does\n\
+Note that the character ?\\C-@, equivalent to the integer zero, does\n\
 not count as a control character; rather, it counts as a character\n\
 with no modifiers; thus, setting `extra-keyboard-modifiers' to zero\n\
 cancels any modification.");
@@ -6252,8 +6629,16 @@ If this variable is non-nil, it is used as a keymap instead of the\n\
 buffer's local map, and the minor mode keymaps and text property keymaps.");
   Voverriding_local_map = Qnil;
 
-  DEFVAR_BOOL ("track-mouse", &do_mouse_tracking,
+  DEFVAR_LISP ("overriding-local-map-menu-flag", &Voverriding_local_map_menu_flag,
+    "Non-nil means `overriding-local-map' applies to the menu bar.\n\
+Otherwise, the menu bar continues to reflect the buffer's local map\n\
+and the minor mode maps regardless of `overriding-local-map'.");
+  Voverriding_local_map_menu_flag = Qnil;
+
+#ifdef HAVE_MOUSE
+  DEFVAR_LISP ("track-mouse", &do_mouse_tracking,
               "*Non-nil means generate motion events for mouse motion.");
+#endif
 
   DEFVAR_LISP ("system-key-alist", &Vsystem_key_alist,
     "Alist of system-specific X windows key symbols.\n\
@@ -6272,6 +6657,28 @@ The precise format isn't relevant here; we just check whether it is nil.");
 This function is called with no arguments after each command\n\
 whenever `deferred-action-list' is non-nil.");
   Vdeferred_action_function = Qnil;
+
+  DEFVAR_DISPLAY ("prefix-arg", Vprefix_arg,
+    "The value of the prefix argument for the next editing command.\n\
+It may be a number, or the symbol `-' for just a minus sign as arg,\n\
+or a list whose car is a number for just one or more C-U's\n\
+or nil if no argument has been specified.\n\
+\n\
+You cannot examine this variable to find the argument for this command\n\
+since it has been set to nil by the time you can look.\n\
+Instead, you should use the variable `current-prefix-arg', although\n\
+normally commands can get this prefix argument with (interactive \"P\").");
+
+  DEFVAR_DISPLAY ("current-prefix-arg", Vcurrent_prefix_arg,
+    "The value of the prefix argument for this editing command.\n\
+It may be a number, or the symbol `-' for just a minus sign as arg,\n\
+or a list whose car is a number for just one or more C-U's\n\
+or nil if no argument has been specified.\n\
+This is what `(interactive \"P\")' returns.");
+
+  DEFVAR_DISPLAY ("last-event-frame", Vlast_event_frame,
+    "The frame in which the most recently read event occurred.\n\
+If the last event came from a keyboard macro, this is set to `macro'.");
 }
 
 keys_of_keyboard ()