(display_locked): New var to indicate when we're in the run state.
[bpt/emacs.git] / src / keyboard.c
index 2819328..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"
@@ -95,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;
@@ -252,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;
@@ -368,9 +361,9 @@ static struct input_event *kbd_fetch_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
@@ -388,18 +381,6 @@ static Lisp_Object 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) \
-   && (! FRAMEP (do_mouse_tracking) || !mouse_moved))
-
-#else /* Not HAVE_MOUSE.  */
-#define EVENT_QUEUES_EMPTY (kbd_fetch_ptr == kbd_store_ptr)
 #endif /* HAVE_MOUSE.  */
 
 /* Symbols to head events.  */
@@ -499,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;
@@ -529,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 ();
 }
@@ -549,11 +516,11 @@ 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.  */
@@ -561,7 +528,7 @@ echo_char (c)
 
       if (INTEGERP (c))
        {
-         if (ptr - echobuf > sizeof echobuf - 6)
+         if (ptr - current_perdisplay->echobuf > ECHOBUFSIZE - 6)
            return;
 
          ptr = push_key_description (XINT (c), ptr);
@@ -569,20 +536,22 @@ echo_char (c)
       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 ();
     }
@@ -593,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 ();
 }
@@ -615,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++)
        {
@@ -632,7 +603,7 @@ echo ()
     }
 
   echoing = 1;
-  message1 (echobuf);
+  message1_nolog (current_perdisplay->echobuf);
   echoing = 0;
 
   if (waiting_for_input && !NILP (Vquit_flag))
@@ -643,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.  */
@@ -653,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.
@@ -664,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);
 }
 
@@ -769,11 +740,19 @@ cmd_error (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);
 }
@@ -971,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;
@@ -996,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));
@@ -1037,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 */
 
@@ -1059,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;
 
@@ -1074,7 +1051,7 @@ command_loop_1 ()
        {
          cancel_echoing ();
          this_command_key_count = 0;
-         continue;
+         goto finalize;
        }
 
       last_command_char = keybuf[i - 1];
@@ -1099,7 +1076,7 @@ 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;
@@ -1121,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.  */
@@ -1197,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 ()
@@ -1249,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);
 
@@ -1273,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 ();
@@ -1290,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
     }
 }
 
@@ -1329,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)
@@ -1473,6 +1462,10 @@ 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.
    -1 means do not do redisplay, but do do autosaving.
@@ -1540,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.
@@ -1591,8 +1587,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       XSETINT (c, quit_char);
 #ifdef MULTI_FRAME
-      XSETFRAME (internal_last_event_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.  */
@@ -1603,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.  */
@@ -1632,7 +1631,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   /* 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))
@@ -1723,19 +1723,70 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        }
     }
 
-  /* 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 && INTEGERP (c) && XINT (c) < 0)
     Fkill_emacs (make_number (1));
@@ -1815,8 +1866,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
  reread_first:
 
   /* Don't echo mouse motion events.  */
-  if (! (EVENT_HAS_PARAMETERS (c)
-        && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+  if (echo_keystrokes
+      && ! (EVENT_HAS_PARAMETERS (c)
+           && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
     {
       echo_char (c);
       if (! NILP (also_record))
@@ -2005,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 */
@@ -2042,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
 
@@ -2073,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]
@@ -2106,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;
@@ -2115,14 +2175,19 @@ kbd_buffer_get_event ()
     {
       c = getchar ();
       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."  */
@@ -2139,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;
 
-         XSETINT (minus_one, -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 */
     }
 
@@ -2166,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
@@ -2174,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.  */
@@ -2219,8 +2305,10 @@ kbd_buffer_get_event ()
 #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)
@@ -2251,10 +2339,10 @@ kbd_buffer_get_event ()
          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
@@ -2266,8 +2354,7 @@ 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;
            }
@@ -2283,6 +2370,10 @@ kbd_buffer_get_event ()
       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.  */
@@ -2303,10 +2394,10 @@ kbd_buffer_get_event ()
          if (NILP (frame))
            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
 
@@ -2324,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);
@@ -2351,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.  */
@@ -2636,11 +2729,7 @@ 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:
@@ -2728,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;
@@ -2746,7 +2839,6 @@ make_lispy_event (event)
                if (! (event->modifiers & down_modifier))
                  return Qnil;
 
-#ifndef USE_X_TOOLKIT
                item = Qnil;
                items = FRAME_MENU_BAR_ITEMS (f);
                for (i = 0; i < XVECTOR (items)->size; i += 3)
@@ -2763,7 +2855,6 @@ make_lispy_event (event)
                        break;
                      }
                  }
-#endif /* not USE_X_TOOLKIT  */
 
                position
                  = Fcons (event->frame_or_window,
@@ -2774,6 +2865,7 @@ make_lispy_event (event)
 
                return Fcons (item, Fcons (position, Qnil));
              }
+#endif /* not USE_X_TOOLKIT */
 
            window = window_from_coordinates (f, column, row, &part);
 
@@ -4463,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;
 
@@ -4491,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.  */
@@ -4535,8 +4635,11 @@ 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;
+  int dummyflag = 0;
 
   struct buffer *starting_buffer;
 
@@ -4588,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.  */
@@ -4627,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
@@ -4657,7 +4762,8 @@ read_key_sequence (keybuf, bufsize, prompt)
             && fkey_start < t
             /* mock input is never part of a function key's sequence.  */
             && mock_input <= fkey_start)
-        || (keytran_start < t && key_translation_possible)
+        || (first_binding >= nmaps
+            && 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
@@ -4716,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.  */
@@ -4732,7 +4851,7 @@ read_key_sequence (keybuf, bufsize, prompt)
              t = 0;
              /* The Microsoft C compiler can't handle the goto that
                 would go here.  */
-             dummyFlag = 1;
+             dummyflag = 1;
              break;
            }
          
@@ -4817,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 (SYMBOLP (posn))
+             /* 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;
@@ -4912,7 +5058,8 @@ read_key_sequence (keybuf, bufsize, prompt)
              last_nonmenu_event = key;
              /* The Microsoft C compiler can't handle the goto that
                 would go here.  */
-             dummyFlag = 1;
+             dummyflag = 1;
+             break;
            }
 
          if (SYMBOLP (head))
@@ -5253,6 +5400,9 @@ read_key_sequence (keybuf, bufsize, prompt)
               && 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
@@ -5274,6 +5424,9 @@ read_key_sequence (keybuf, bufsize, prompt)
          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)
@@ -5289,7 +5442,7 @@ read_key_sequence (keybuf, bufsize, prompt)
        }
     }
 
-  if (!dummyFlag)
+  if (!dummyflag)
     read_key_sequence_cmd = (first_binding < nmaps
                             ? defs[first_binding]
                             : Qnil);
@@ -5297,6 +5450,9 @@ read_key_sequence (keybuf, bufsize, prompt)
   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
@@ -5327,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\
@@ -5354,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;
@@ -5374,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)
     {
@@ -5400,8 +5563,9 @@ 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 (SYMBOLP (cmd))
@@ -5517,7 +5681,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
   UNGCPRO;
 
   function = Fintern (function, Qnil);
-  Vprefix_arg = prefixarg;
+  current_perdisplay->Vprefix_arg = prefixarg;
   this_command = function;
 
   return Fcommand_execute (function, Qt);
@@ -5700,11 +5864,11 @@ 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
+  register unsigned char *p;
+
   if (STRINGP (stuffstring))
     {
       register int count;
@@ -5716,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;
@@ -5724,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
@@ -5767,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.  */
@@ -5893,9 +6059,15 @@ quit_throw_to_read_char ()
     abort ();
 #endif
 #ifdef MULTI_FRAME
-  if (FRAMEP (internal_last_event_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);
@@ -5986,6 +6158,40 @@ The elements of this list correspond to the arguments of\n\
 }
 
 \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 */
@@ -5998,27 +6204,24 @@ init_keyboard ()
   recent_keys_index = 0;
   kbd_fetch_ptr = kbd_buffer;
   kbd_store_ptr = kbd_buffer;
+  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);
@@ -6311,14 +6514,9 @@ by position only.");
   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\
@@ -6378,10 +6576,10 @@ Type this character while in a menu prompt to rotate around the lines of it.");
     "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.");
@@ -6459,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 ()