(menu_bar_one_keymap):
[bpt/emacs.git] / src / keyboard.c
index 434d019..7179e3a 100644 (file)
@@ -1,5 +1,5 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985,86,87,88,89,93,94 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -179,7 +179,7 @@ Lisp_Object last_nonmenu_event;
 Lisp_Object last_input_char;
 
 /* If not Qnil, a list of objects to be read as subsequent command input.  */
-Lisp_Object unread_command_events;
+Lisp_Object Vunread_command_events;
 
 /* If not -1, an event to be read as subsequent command input.  */
 int unread_command_char;
@@ -235,6 +235,9 @@ Lisp_Object this_command;
 /* The value of point when the last command was executed.  */
 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
@@ -242,12 +245,12 @@ int last_point_position;
    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;
-#endif
 
 /* The timestamp of the last input event we received from the X server.
    X Windows wants this for selection ownership.  */
@@ -416,6 +419,8 @@ Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
 Lisp_Object Qextended_command_history;
 
+Lisp_Object Qpolling_period;
+
 /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
    happens.  */
 EMACS_TIME *input_available_clear_time;
@@ -579,7 +584,13 @@ echo ()
       immediate_echo = 1;
 
       for (i = 0; i < this_command_key_count; i++)
-       echo_char (XVECTOR (this_command_keys)->contents[i]);
+       {
+         Lisp_Object c;
+         c = XVECTOR (this_command_keys)->contents[i];
+         if (! (EVENT_HAS_PARAMETERS (c)
+                && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+           echo_char (c);
+       }
       echo_dash ();
     }
 
@@ -663,10 +674,20 @@ recursive_edit_1 ()
 }
 
 /* When an auto-save happens, record the "time", and don't do again soon.  */
+
 record_auto_save ()
 {
   last_auto_save = num_nonmacro_input_chars;
 }
+
+/* Make an auto save happen as soon as possible at command level.  */
+
+force_auto_save_soon ()
+{
+  last_auto_save = - auto_save_interval - 1;
+
+  record_asynch_buffer_change ();
+}
 \f
 DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
   "Invoke the editor command loop recursively.\n\
@@ -887,6 +908,7 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0,
 
 Lisp_Object Fcommand_execute ();
 static int read_key_sequence ();
+static void safe_run_hooks ();
 
 Lisp_Object
 command_loop_1 ()
@@ -913,16 +935,7 @@ command_loop_1 ()
   /* Make sure this hook runs after commands that get errors and
      throw to top level.  */
   if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
-    {
-      /* If we get an error during the post-command-hook,
-        cause post-command-hook to be nil.  */
-      Vcommand_hook_internal = Vpost_command_hook;
-      Vpost_command_hook = Qnil;
-
-      call1 (Vrun_hooks, Qcommand_hook_internal);
-      
-      Vpost_command_hook = Vcommand_hook_internal;
-    }
+    safe_run_hooks (&Vpost_command_hook);
 
   /* Do this after running Vpost_command_hook, for consistency.  */
   last_command = this_command;
@@ -965,7 +978,7 @@ command_loop_1 ()
          if (!NILP (Vquit_flag))
            {
              Vquit_flag = Qnil;
-             unread_command_events = Fcons (make_number (quit_char), Qnil);
+             Vunread_command_events = Fcons (make_number (quit_char), Qnil);
            }
        }
 
@@ -1038,21 +1051,13 @@ command_loop_1 ()
       prev_buffer = current_buffer;
       prev_modiff = MODIFF;
       last_point_position = PT;
+      XSET (last_point_position_buffer, Lisp_Buffer, prev_buffer);
 
       /* Execute the command.  */
 
       this_command = cmd;
       if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks))
-       {
-         /* If we get an error during the pre-command-hook,
-            cause pre-command-hook to be nil.  */
-         Vcommand_hook_internal = Vpre_command_hook;
-         Vpre_command_hook = Qnil;
-
-         call1 (Vrun_hooks, Qcommand_hook_internal);
-
-         Vpre_command_hook = Vcommand_hook_internal;
-       }
+       safe_run_hooks (&Vpre_command_hook);
 
       if (NILP (this_command))
        {
@@ -1069,12 +1074,12 @@ command_loop_1 ()
            {
              /* Recognize some common commands in common situations and
                 do them directly.  */
-             if (EQ (this_command, Qforward_char) && point < ZV)
+             if (EQ (this_command, Qforward_char) && PT < ZV)
                {
                   struct Lisp_Vector *dp
                    = window_display_table (XWINDOW (selected_window));
-                 lose = FETCH_CHAR (point);
-                 SET_PT (point + 1);
+                 lose = FETCH_CHAR (PT);
+                 SET_PT (PT + 1);
                  if ((dp
                       ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
                          && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
@@ -1082,7 +1087,7 @@ command_loop_1 ()
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_point)
-                         == point - 1)
+                         == PT - 1)
                      && !windows_or_buffers_changed
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
@@ -1090,20 +1095,20 @@ command_loop_1 ()
                    no_redisplay = direct_output_forward_char (1);
                  goto directly_done;
                }
-             else if (EQ (this_command, Qbackward_char) && point > BEGV)
+             else if (EQ (this_command, Qbackward_char) && PT > BEGV)
                {
                   struct Lisp_Vector *dp
                    = window_display_table (XWINDOW (selected_window));
-                 SET_PT (point - 1);
-                 lose = FETCH_CHAR (point);
+                 SET_PT (PT - 1);
+                 lose = FETCH_CHAR (PT);
                  if ((dp
-                      ? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector
+                      ? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
                          && XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
                       : (lose >= 0x20 && lose < 0x7f))
                      && (XFASTINT (XWINDOW (selected_window)->last_modified)
                          >= MODIFF)
                      && (XFASTINT (XWINDOW (selected_window)->last_point)
-                         == point + 1)
+                         == PT + 1)
                      && !windows_or_buffers_changed
                      && EQ (current_buffer->selective_display, Qnil)
                      && !detect_input_pending ()
@@ -1129,8 +1134,7 @@ command_loop_1 ()
                    }
                  lose = (XFASTINT (XWINDOW (selected_window)->last_modified)
                          < MODIFF)
-                   || (XFASTINT (XWINDOW (selected_window)->last_point)
-                         != point)
+                   || (XFASTINT (XWINDOW (selected_window)->last_point) != PT)
                    || MODIFF <= current_buffer->save_modified
                    || windows_or_buffers_changed
                    || !EQ (current_buffer->selective_display, Qnil)
@@ -1142,7 +1146,7 @@ command_loop_1 ()
                      nonundocount = 0;
                    }
                  if (!lose &&
-                     (point == ZV || FETCH_CHAR (point) == '\n'))
+                     (PT == ZV || FETCH_CHAR (PT) == '\n'))
                    {
                      struct Lisp_Vector *dp
                        = window_display_table (XWINDOW (selected_window));
@@ -1181,16 +1185,7 @@ command_loop_1 ()
     directly_done: ;
 
       if (!NILP (Vpost_command_hook) && !NILP (Vrun_hooks))
-       {
-         /* If we get an error during the post-command-hook,
-            cause post-command-hook to be nil.  */
-         Vcommand_hook_internal = Vpost_command_hook;
-         Vpost_command_hook = Qnil;
-
-         call1 (Vrun_hooks, Qcommand_hook_internal);
-
-         Vpost_command_hook = Vcommand_hook_internal;
-       }
+       safe_run_hooks (&Vpost_command_hook);
 
       /* If there is a prefix argument,
         1) We don't want last_command to be ``universal-argument''
@@ -1220,6 +1215,24 @@ command_loop_1 ()
        }
     }
 }
+
+/* If we get an error while running the hook, cause the hook variable
+   to be nil.  Also inhibit quits, so that C-g won't cause the hook
+   to mysteriously evaporate.  */
+static void
+safe_run_hooks (hook)
+     Lisp_Object *hook;
+{
+  int count = specpdl_ptr - specpdl;
+  specbind (Qinhibit_quit, Qt);
+
+  Vcommand_hook_internal = *hook;
+  *hook = Qnil;
+  call1 (Vrun_hooks, Qcommand_hook_internal);
+  *hook = Vcommand_hook_internal;
+
+  unbind_to (count, Qnil);
+}
 \f
 /* Number of seconds between polling for input.  */
 int polling_period;
@@ -1301,6 +1314,25 @@ set_poll_suppress_count (count)
   poll_suppress_count = count;
 #endif
 }
+
+/* Bind polling_period to a value at least N.
+   But don't decrease it.  */
+
+bind_polling_period (n)
+     int n;
+{
+#ifdef POLL_FOR_INPUT
+  int new = polling_period;
+
+  if (n > new)
+    new = n;
+
+  stop_polling ();
+  specbind (Qpolling_period, make_number (new));
+  /* Start a new alarm with the new period.  */
+  start_polling ();
+#endif
+}
 \f
 /* Applying the control modifier to CHARACTER.  */
 int
@@ -1375,10 +1407,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   int count;
   jmp_buf save_jump;
 
-  if (CONSP (unread_command_events))
+  if (CONSP (Vunread_command_events))
     {
-      c = XCONS (unread_command_events)->car;
-      unread_command_events = XCONS (unread_command_events)->cdr;
+      c = XCONS (Vunread_command_events)->car;
+      Vunread_command_events = XCONS (Vunread_command_events)->cdr;
 
       if (this_command_key_count == 0)
        goto reread_first;
@@ -1443,7 +1475,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       goto reread_first;
     }
 
-  if (commandflag >= 0 && !input_pending && !detect_input_pending ())
+  /* Don't bother updating menu bars while doing mouse tracking.
+     We get events very rapidly then, and the menu bar won't be changing.
+     We do update the menu bar once on entry to Ftrack_mouse.  */
+  if (commandflag > 0 && !input_pending && !detect_input_pending ())
     prepare_menu_bars ();
 
   /* Save outer setjmp data, in case called recursively.  */
@@ -1482,11 +1517,16 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
      menu prompting. If EVENT_HAS_PARAMETERS then we are reading
      after a mouse event so don't try a minibuf menu. */
   c = Qnil;
-  if (nmaps > 0 && INTERACTIVE && 
-      !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event))
+  if (nmaps > 0 && INTERACTIVE
+      && !NILP (prev_event) && ! EVENT_HAS_PARAMETERS (prev_event)
+      /* Don't bring up a menu if we already have another event.  */
+      && NILP (Vunread_command_events)
+      && unread_command_char < 0
+      && !detect_input_pending ())
     {
       c = read_char_minibuf_menu_prompt (commandflag, nmaps, maps);
-      if ( ! NILP(c) ) return c ;
+      if (! NILP (c))
+       return c;
     }
 
   /* If in middle of key sequence and minibuffer not active,
@@ -1525,11 +1565,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     }
 
   /* Try reading using an X menu.
-     This is never confused with reading using the minibuf because the recursive
-     call of read_char in read_char_minibuf_menu_prompt does not pass on
-     any keys maps */
-  if (nmaps > 0 && INTERACTIVE &&
-      !NILP (prev_event) && EVENT_HAS_PARAMETERS (prev_event))
+     This is never confused with reading using the minibuf
+     because the recursive call of read_char in read_char_minibuf_menu_prompt
+     does not pass on any keymaps.  */
+  if (nmaps > 0 && INTERACTIVE
+      && !NILP (prev_event) && EVENT_HAS_PARAMETERS (prev_event)
+      /* Don't bring up a menu if we already have another event.  */
+      && NILP (Vunread_command_events)
+      && unread_command_char < 0)
     c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
 
   /* Slow down auto saves logarithmically in size of current buffer,
@@ -1613,7 +1656,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
   start_polling ();
 
-  echo_area_glyphs = 0;
+  /* Don't wipe the echo area for a trivial event.  */
+  if (XTYPE (c) != Lisp_Buffer)
+    echo_area_glyphs = 0;
 
   /* Handle things that only apply to characters.  */
   if (XTYPE (c) == Lisp_Int)
@@ -1666,14 +1711,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
  from_macro:
  reread_first:
 
-  /* Record this character as part of the current key.
-     Don't record mouse motion; it should never matter.  */
+  /* Don't echo mouse motion events.  */
   if (! (EVENT_HAS_PARAMETERS (c)
         && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
-    {
-      echo_char (c);
-      add_command_key (c);
-    }
+    echo_char (c);
+
+  /* Record this character as part of the current key.  */
+  add_command_key (c);
 
   /* Re-reading in the middle of a command */
  reread:
@@ -1777,6 +1821,9 @@ Normally, mouse motion is ignored.")
   XSET (val, Lisp_Int, do_mouse_tracking);
   record_unwind_protect (tracking_off, val);
 
+  if (!input_pending && !detect_input_pending ())
+    prepare_menu_bars ();
+
   do_mouse_tracking = 1;
   
   val = Fprogn (args);
@@ -2008,6 +2055,12 @@ kbd_buffer_get_event ()
          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;
+         kbd_fetch_ptr = event + 1;
+       }
       else if (event->kind == buffer_switch_event)
        {
          /* The value doesn't matter here; only the type is tested.  */
@@ -2304,7 +2357,7 @@ static char *lispy_function_keys[] =
     "help",
     "break",                   /* 0xff6b */
 
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, "backtab", 0,
     0,                         /* 0xff76 */
     0, 0, 0, 0, 0, 0, 0, 0, "kp-numlock",      /* 0xff7f */
     "kp-space",                        /* 0xff80 */    /* IsKeypadKey */
@@ -2317,8 +2370,19 @@ static char *lispy_function_keys[] =
     "kp-f2",
     "kp-f3",
     "kp-f4",
-    0,         /* 0xff95 */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    "kp-home",                 /* 0xff95 */
+    "kp-left",
+    "kp-up",
+    "kp-right",
+    "kp-down",
+    "kp-prior",                        /* kp-page-up */
+    "kp-next",                 /* kp-page-down */
+    "kp-end",
+    "kp-begin",
+    "kp-insert",
+    "kp-delete",
+    0,                         /* 0xffa0 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0,
     "kp-multiply",             /* 0xffaa */
     "kp-add",
     "kp-separator",
@@ -2464,7 +2528,7 @@ make_lispy_event (event)
                                   / sizeof (lispy_function_keys[0])));
       break;
 
-#ifdef MULTI_FRAME
+#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:
@@ -2488,6 +2552,11 @@ make_lispy_event (event)
            Lisp_Object posn;
            int row, column;
 
+           /* Ignore mouse events that were made on frame that
+              have been deleted.  */
+           if (! FRAME_LIVE_P (f))
+             return Qnil;
+
            pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
                                   &column, &row, 0, 0);
 
@@ -2693,7 +2762,7 @@ make_lispy_event (event)
                                 Qnil));
        }
       }
-#endif /* MULTI_FRAME */
+#endif /* MULTI_FRAME or HAVE_MOUSE */
 
       /* The 'kind' field of the event is something we don't recognize.  */
     default:
@@ -2735,10 +2804,12 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
       Lisp_Object posn;
       int column, row;
 
-      pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row, 0, 1);
-
       if (frame)
-       window = window_from_coordinates (frame, column, row, &area);
+       {
+         /* It's in a frame; which window on that frame?  */
+         pixel_to_glyph_coords (frame, XINT (x), XINT (y), &column, &row, 0, 1);
+         window = window_from_coordinates (frame, column, row, &area);
+       }
       else
        window = Qnil;
 
@@ -3265,12 +3336,31 @@ gobble_input (expected)
 #endif
 }
 
+/* Put a buffer_switch_event in the buffer
+   so that read_key_sequence will notice the new current buffer.  */
+
 record_asynch_buffer_change ()
 {
   struct input_event event;
   event.kind = buffer_switch_event;
   event.frame_or_window = Qnil;
-  kbd_buffer_store_event (&event);
+
+  /* Make sure no interrupt happens while storing the event.  */
+#ifdef SIGIO
+  if (interrupt_input)
+    {
+      SIGMASKTYPE mask;
+      mask = sigblockx (SIGIO);
+      kbd_buffer_store_event (&event);
+      sigsetmask (mask);
+    }
+  else
+#endif
+    {
+      stop_polling ();
+      kbd_buffer_store_event (&event);
+      start_polling ();
+    }
 }
 \f
 #ifndef VMS
@@ -3339,7 +3429,7 @@ read_avail_input (expected)
 
       /* Now read; for one reason or another, this will not block.
         NREAD is set to the number of chars read.  */
-      while (1)
+      do
        {
 #ifdef MSDOS
          cbuf[0] = dos_keyread();
@@ -3355,18 +3445,25 @@ read_avail_input (expected)
          if (nread == 0)
            kill (0, SIGHUP);
 #endif
-         /* Retry the read if it was interrupted.  */
-         if (nread >= 0
-             || ! (errno == EAGAIN 
+       }
+      while (
+            /* We used to retry the read if it was interrupted.
+               But this does the wrong thing when O_NDELAY causes
+               an EAGAIN error.  Does anybody know of a situation
+               where a retry is actually needed?  */
+#if 0
+            nread < 0 && (errno == EAGAIN
 #ifdef EFAULT
-                   || errno == EFAULT
+                          || errno == EFAULT
 #endif
 #ifdef EBADSLT
-                   || errno == EBADSLT
+                          || errno == EBADSLT
 #endif
-                   ))
-           break;
-       }
+                          )
+#else
+            0
+#endif
+            );
 
 #ifndef FIONREAD
 #if defined (USG) || defined (DGUX)
@@ -3500,7 +3597,7 @@ static Lisp_Object 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:
-   KEY STRING nil.
+   KEY STRING MAPLIST.
 
    OLD is an old vector we can optionally reuse, or nil.  */
 
@@ -3638,9 +3735,7 @@ menu_bar_items (old)
 }
 \f
 /* Scan one map KEYMAP, accumulating any menu items it defines
-   that have not yet been seen in RESULT.  Return the updated RESULT.
-   *OLD is the frame's old menu bar list; we swipe elts from that
-   to avoid consing.  */
+   in menu_bar_items_vector.  */
 
 static void
 menu_bar_one_keymap (keymap)
@@ -3663,7 +3758,7 @@ menu_bar_one_keymap (keymap)
                menu_bar_item (key, item_string, Fcdr (binding));
            }
          else if (EQ (binding, Qundefined))
-           menu_bar_item (key, item_string, binding);
+           menu_bar_item (key, Qnil, binding);
        }
       else if (XTYPE (item) == Lisp_Vector)
        {
@@ -3682,7 +3777,7 @@ menu_bar_one_keymap (keymap)
                    menu_bar_item (key, item_string, Fcdr (binding));
                }
              else if (EQ (binding, Qundefined))
-               menu_bar_item (key, item_string, binding);
+               menu_bar_item (key, Qnil, binding);
            }
        }
     }
@@ -3697,6 +3792,9 @@ menu_bar_item_1 (arg)
   return Qnil;
 }
 
+/* Add one item to menu_bar_items_vector, for KEY, ITEM_STRING and DEF.
+   If there's already an item for KEY, add this DEF to it.  */
+
 static void
 menu_bar_item (key, item_string, def)
      Lisp_Object key, item_string, def;
@@ -3707,7 +3805,7 @@ menu_bar_item (key, item_string, def)
 
   if (EQ (def, Qundefined))
     {
-      /* If a map has an explicit nil as definition,
+      /* If a map has an explicit `undefined' as definition,
         discard any previously made menu bar item.  */
 
       for (i = 0; i < menu_bar_items_index; i += 3)
@@ -3720,6 +3818,10 @@ menu_bar_item (key, item_string, def)
            menu_bar_items_index -= 3;
            return;
          }
+
+      /* If there's no definition for this key yet,
+        just ignore `undefined'.  */
+      return;
     }
 
   /* See if this entry is enabled.  */
@@ -3741,12 +3843,12 @@ menu_bar_item (key, item_string, def)
   if (NILP (enabled))
     return;
 
-  /* If there's already such an item, don't make another.  */
+  /* Find any existing item for this KEY.  */
   for (i = 0; i < menu_bar_items_index; i += 3)
     if (EQ (key, XVECTOR (menu_bar_items_vector)->contents[i]))
       break;
 
-  /* If we did not find this item, add it at the end.  */
+  /* If we did not find this KEY, add it at the end.  */
   if (i == menu_bar_items_index)
     {
       /* If vector is too small, get a bigger one.  */
@@ -3762,9 +3864,16 @@ menu_bar_item (key, item_string, def)
       /* Add this item.  */
       XVECTOR (menu_bar_items_vector)->contents[i++] = key;
       XVECTOR (menu_bar_items_vector)->contents[i++] = item_string;
-      XVECTOR (menu_bar_items_vector)->contents[i++] = Qnil;
+      XVECTOR (menu_bar_items_vector)->contents[i++] = Fcons (def, Qnil);
       menu_bar_items_index = i;
     }
+  /* We did find an item for this KEY.  Add DEF to its list of maps.  */
+  else
+    {
+      Lisp_Object old;
+      old = XVECTOR (menu_bar_items_vector)->contents[i + 2];
+      XVECTOR (menu_bar_items_vector)->contents[i + 2] = Fcons (def, old);
+    }
 }
 \f
 /* Read a character using menus based on maps in the array MAPS.
@@ -3841,8 +3950,8 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
          /* If we got more than one event, put all but the first
             onto this list to be read later.
             Return just the first event now.  */
-         unread_command_events
-           = nconc2 (XCONS (value)->cdr, unread_command_events);
+         Vunread_command_events
+           = nconc2 (XCONS (value)->cdr, Vunread_command_events);
          value = XCONS (value)->car;
        }
       else if (NILP (value))
@@ -3857,7 +3966,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
 }
 
 static Lisp_Object
-read_char_minibuf_menu_prompt(commandflag, nmaps, maps)
+read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
      int commandflag ;
      int nmaps;
      Lisp_Object *maps;
@@ -3868,7 +3977,7 @@ read_char_minibuf_menu_prompt(commandflag, nmaps, maps)
   int width = FRAME_WIDTH (selected_frame) - 4;
   char *menu = (char *) alloca (width + 4);
   int idx = -1;
-  int nobindings ;
+  int nobindings = 1;
   Lisp_Object rest, vector;
 
   if (! menu_prompting)
@@ -5176,7 +5285,7 @@ DEFUN ("input-pending-p", Finput_pending_p, Sinput_pending_p, 0, 0, 0,
 Actually, the value is nil only if we can be sure that no input is available.")
   ()
 {
-  if (!NILP (unread_command_events) || unread_command_char != -1)
+  if (!NILP (Vunread_command_events) || unread_command_char != -1)
     return (Qt);
 
   return detect_input_pending () ? Qt : Qnil;
@@ -5250,7 +5359,7 @@ Also cancel any kbd macro being defined.")
   defining_kbd_macro = 0;
   update_mode_lines++;
 
-  unread_command_events = Qnil;
+  Vunread_command_events = Qnil;
   unread_command_char = -1;
 
   discard_tty_input ();
@@ -5511,7 +5620,7 @@ quit_throw_to_read_char ()
   clear_waiting_for_input ();
   input_pending = 0;
 
-  unread_command_events = Qnil;
+  Vunread_command_events = Qnil;
   unread_command_char = -1;
 
 #ifdef POLL_FOR_INPUT
@@ -5620,7 +5729,7 @@ init_keyboard ()
   command_loop_level = -1;
   immediate_quit = 0;
   quit_char = Ctl ('g');
-  unread_command_events = Qnil;
+  Vunread_command_events = Qnil;
   unread_command_char = -1;
   total_keys = 0;
   recent_keys_index = 0;
@@ -5766,6 +5875,9 @@ syms_of_keyboard ()
   Qactivate_menubar_hook = intern ("activate-menubar-hook");
   staticpro (&Qactivate_menubar_hook);
 
+  Qpolling_period = intern ("polling-period");
+  staticpro (&Qpolling_period);
+
   {
     struct event_head *p;
 
@@ -5808,6 +5920,9 @@ syms_of_keyboard ()
     = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
   staticpro (&kbd_buffer_frame_or_window);
 
+  accent_key_syms = Qnil;
+  staticpro (&accent_key_syms);
+
   func_key_syms = Qnil;
   staticpro (&func_key_syms);
 
@@ -5856,7 +5971,7 @@ so that you can determine whether the command was run by mouse or not.");
   DEFVAR_LISP ("last-input-event", &last_input_char,
     "Last input event.");
 
-  DEFVAR_LISP ("unread-command-events", &unread_command_events,
+  DEFVAR_LISP ("unread-command-events", &Vunread_command_events,
     "List of objects to be read as next command input events.");
 
   DEFVAR_INT ("unread-command-char", &unread_command_char,
@@ -5913,12 +6028,10 @@ by position only.");
     "*Number of complete keys read from the keyboard so far.");
   num_input_keys = 0;
 
-#ifdef MULTI_FRAME
   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;
-#endif
 
   DEFVAR_LISP ("help-char", &Vhelp_char,
     "Character to recognize as meaning Help.\n\
@@ -6000,11 +6113,21 @@ Buffer modification stores t in this variable.");
   Vcommand_hook_internal = Qnil;
 
   DEFVAR_LISP ("pre-command-hook", &Vpre_command_hook,
-    "Normal hook run before each command is executed.");
+    "Normal hook run before each command is executed.\n\
+While the hook is run, its value is temporarily set to nil\n\
+to avoid an unbreakable infinite loop if a hook function gets an error.\n\
+As a result, a hook function cannot straightforwardly alter the value of\n\
+`pre-command-hook'.  See the Emacs Lisp manual for a way of\n\
+implementing hook functions that alter the set of hook functions.");
   Vpre_command_hook = Qnil;
 
   DEFVAR_LISP ("post-command-hook", &Vpost_command_hook,
-    "Normal hook run after each command is executed.");
+    "Normal hook run after each command is executed.\n\
+While the hook is run, its value is temporarily set to nil\n\
+to avoid an unbreakable infinite loop if a hook function gets an error.\n\
+As a result, a hook function cannot straightforwardly alter the value of\n\
+`post-command-hook'.  See the Emacs Lisp manual for a way of\n\
+implementing hook functions that alter the set of hook functions.");
   Vpost_command_hook = Qnil;
 
   DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,