(main): Don't call setpgrp if !initialized.
[bpt/emacs.git] / src / keyboard.c
index 1a7821a..7dd56e9 100644 (file)
@@ -20,7 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Allow config.h to undefine symbols found here.  */
 #include <signal.h>
 
-#include "config.h"
+#include <config.h>
 #include <stdio.h>
 #undef NULL
 #include "termchar.h"
@@ -402,6 +402,7 @@ extern Lisp_Object Qmenu_enable;
 
 Lisp_Object recursive_edit_unwind (), command_loop ();
 Lisp_Object Fthis_command_keys ();
+Lisp_Object Qextended_command_history;
 
 /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
    happens.  */
@@ -993,7 +994,7 @@ command_loop_1 ()
 #endif /* 0 */
 
       /* Read next key sequence; i gets its length.  */
-      i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), 0);
+      i = read_key_sequence (keybuf, (sizeof keybuf / sizeof (keybuf[0])), Qnil);
 
       ++num_input_keys;
 
@@ -1064,7 +1065,7 @@ command_loop_1 ()
                  lose = FETCH_CHAR (point);
                  SET_PT (point + 1);
                  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)
@@ -1421,6 +1422,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       goto reread_first;
     }
 
+  if (commandflag >= 0 && !input_pending && !detect_input_pending ())
+    prepare_menu_bars ();
+
   /* Save outer setjmp data, in case called recursively.  */
   save_getcjmp (save_jump);
 
@@ -1454,6 +1458,7 @@ 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
+      && ! noninteractive
       && echo_keystrokes > 0
       && (echo_area_glyphs == 0 || *echo_area_glyphs == 0))
     {
@@ -1532,6 +1537,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
                  && consing_since_gc > gc_cons_threshold / 2)
                {
                  Fgarbage_collect ();
+                 /* prepare_menu_bars isn't safe here, but it should
+                    also be unnecessary.  */
                  redisplay ();
                }
            }
@@ -1656,6 +1663,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       c = read_char (0, 0, 0, Qnil, 0);
       /* Remove the help from the frame */
       unbind_to (count, Qnil);
+      prepare_menu_bars ();
       redisplay ();
       if (EQ (c, make_number (040)))
        {
@@ -1710,6 +1718,7 @@ tracking_off (old_value)
         redisplay.  */
       if (!readable_events ())
        {
+         prepare_menu_bars ();
          redisplay_preserve_echo_area ();
          get_input_pending (&input_pending);
        }
@@ -1764,7 +1773,7 @@ kbd_buffer_store_event (event)
 
   if (event->kind == ascii_keystroke)
     {
-      register int c = XFASTINT (event->code) & 0377;
+      register int c = event->code & 0377;
 
       if (event->modifiers & ctrl_modifier)
        c = make_ctrl_char (c);
@@ -1783,8 +1792,8 @@ kbd_buffer_store_event (event)
             get returned to Emacs as an event, the next event read
             will set Vlast_event_frame again, so this is safe to do.  */
          {
-           Lisp_Object focus =
-             FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
+           Lisp_Object focus
+             FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
 
            if (NILP (focus))
              internal_last_event_frame = event->frame_or_window;
@@ -1816,13 +1825,23 @@ kbd_buffer_store_event (event)
   if (kbd_fetch_ptr - 1 != kbd_store_ptr)
     {
       kbd_store_ptr->kind = event->kind;
-      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;
+      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));
+       }
+      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;
+       }
       (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_store_ptr
                                                      - kbd_buffer]
        = event->frame_or_window);
@@ -1927,6 +1946,31 @@ kbd_buffer_get_event ()
          abort ();
 #endif
        }
+#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))
+           kill (getpid (), SIGHUP);
+
+         Fdelete_frame (event->frame_or_window, Qt);
+         kbd_fetch_ptr = event + 1;
+       }
+#endif
       /* Just discard these, by returning nil.
         (They shouldn't be found in the buffer,
         but on some machines it appears they do show up.)  */
@@ -2069,9 +2113,102 @@ swallow_events ()
 }
 \f
 /* Caches for modify_event_symbol.  */
+static Lisp_Object accent_key_syms;
 static Lisp_Object func_key_syms;
 static Lisp_Object mouse_syms;
 
+/* This is a list of keysym codes for special "accent" characters.
+   It parallels lispy_accent_keys.  */
+
+static int lispy_accent_codes[] =
+{
+#ifdef XK_dead_circumflex
+  XK_dead_circumflex,
+#else
+  0,
+#endif
+#ifdef XK_dead_grave
+  XK_dead_grave,
+#else
+  0,
+#endif
+#ifdef XK_dead_tilde
+  XK_dead_tilde,
+#else
+  0,
+#endif
+#ifdef XK_dead_diaeresis
+  XK_dead_diaeresis,
+#else
+  0,
+#endif
+#ifdef XK_dead_macron
+  XK_dead_macron,
+#else
+  0,
+#endif
+#ifdef XK_dead_degree
+  XK_dead_degree,
+#else
+  0,
+#endif
+#ifdef XK_dead_acute
+  XK_dead_acute,
+#else
+  0,
+#endif
+#ifdef XK_dead_cedilla
+  XK_dead_cedilla,
+#else
+  0,
+#endif
+#ifdef XK_dead_breve
+  XK_dead_breve,
+#else
+  0,
+#endif
+#ifdef XK_dead_ogonek
+  XK_dead_ogonek,
+#else
+  0,
+#endif
+#ifdef XK_dead_caron
+  XK_dead_caron,
+#else
+  0,
+#endif
+#ifdef XK_dead_doubleacute
+  XK_dead_doubleacute,
+#else
+  0,
+#endif
+#ifdef XK_dead_abovedot
+  XK_dead_abovedot,
+#else
+  0,
+#endif
+};
+
+/* This is a list of Lisp names for special "accent" characters.
+   It parallels lispy_accent_codes.  */
+
+static char *lispy_accent_keys[] =
+{
+  "dead-circumflex",
+  "dead-grave",
+  "dead-tilde",
+  "dead-diaeresis",
+  "dead-macron",
+  "dead-degree",
+  "dead-acute",
+  "dead-cedilla",
+  "dead-breve",
+  "dead-ogonek",
+  "dead-caron",
+  "dead-doubleacute",
+  "dead-abovedot",
+};
+
 /* You'll notice that this table is arranged to be conveniently
    indexed by X Windows keysym values.  */
 static char *lispy_function_keys[] =
@@ -2225,6 +2362,8 @@ static Lisp_Object
 make_lispy_event (event)
      struct input_event *event;
 {
+  int i;
+
 #ifdef SWITCH_ENUM_BUG
   switch ((int) event->kind)
 #else
@@ -2234,7 +2373,7 @@ make_lispy_event (event)
       /* A simple keystroke.  */
     case ascii_keystroke:
       {
-       int c = XFASTINT (event->code);
+       int c = event->code & 0377;
        /* Turn ASCII characters into control characters
           when proper.  */
        if (event->modifiers & ctrl_modifier)
@@ -2254,7 +2393,18 @@ make_lispy_event (event)
         tacked onto it.  */
     case non_ascii_keystroke:
       button_down_time = 0;
-      return modify_event_symbol (XFASTINT (event->code), event->modifiers,
+
+      for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++)
+       if (event->code == lispy_accent_codes[i])
+         return modify_event_symbol (i,
+                                     event->modifiers,
+                                     Qfunction_key,
+                                     lispy_accent_keys, &accent_key_syms,
+                                     (sizeof (lispy_accent_keys)
+                                      / sizeof (lispy_accent_keys[0])));
+
+      return modify_event_symbol (event->code - 0xff00,
+                                 event->modifiers,
                                  Qfunction_key,
                                  lispy_function_keys, &func_key_syms,
                                  (sizeof (lispy_function_keys)
@@ -2266,7 +2416,7 @@ make_lispy_event (event)
     case mouse_click:
     case scroll_bar_click:
       {
-       int button = XFASTINT (event->code);
+       int button = event->code;
        int is_double;
        Lisp_Object position;
        Lisp_Object *start_pos_ptr;
@@ -2515,6 +2665,11 @@ make_lispy_movement (frame, bar_window, part, x, y, time)
                  buffer_posn_from_coords (XWINDOW (window),
                                           XINT (x), XINT (y)));
        }
+      else if (frame != 0)
+       {
+         XSET (window, Lisp_Frame, frame);
+         posn = Qnil;
+       }
       else
        {
          window = Qnil;
@@ -3015,7 +3170,10 @@ read_avail_input (expected)
     nread = (*read_socket_hook) (0, buf, KBD_BUFFER_SIZE, expected, expected);
   else
     {
-      unsigned char cbuf[KBD_BUFFER_SIZE];
+      /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
+        the kbd_buffer can really hold.  That may prevent loss
+        of characters on some systems when input is stuffed at us.  */
+      unsigned char cbuf[KBD_BUFFER_SIZE - 1];
 
 #ifdef FIONREAD
       /* Find out how much input is available.  */
@@ -3032,7 +3190,7 @@ read_avail_input (expected)
       if (nread > sizeof cbuf)
        nread = sizeof cbuf;
 #else /* no FIONREAD */
-#ifdef USG
+#if defined(USG) || defined(DGUX)
       /* Read some input if available, but don't wait.  */
       nread = sizeof cbuf;
       fcntl (fileno (stdin), F_SETFL, O_NDELAY);
@@ -3053,6 +3211,8 @@ read_avail_input (expected)
          if (nread == 0)
            kill (SIGHUP, 0);
 #endif
+         /* This code is wrong, but at least it gets the right results.
+            Fix it for 19.23.  */
          /* Retry the read if it is interrupted.  */
          if (nread >= 0
              || ! (errno == EAGAIN || errno == EFAULT
@@ -3064,9 +3224,9 @@ read_avail_input (expected)
        }
 
 #ifndef FIONREAD
-#ifdef USG
+#if defined (USG) || defined (DGUX)
       fcntl (fileno (stdin), F_SETFL, 0);
-#endif /* USG */
+#endif /* USG or DGUX */
 #endif /* no FIONREAD */
       for (i = 0; i < nread; i++)
        {
@@ -3358,9 +3518,6 @@ menu_bar_item (key, item_string, def, result)
   return result;
 }
 \f
-static int echo_flag;
-static int echo_now;
-
 /* Read a character using menus based on maps in the array MAPS.
    NMAPS is the length of MAPS.  Return nil if there are no menus in the maps.
    Return t if we displayed a menu but the user rejected it.
@@ -3579,6 +3736,8 @@ read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
    When KEY is not defined in any of the keymaps, if it is an upper
    case letter and there are bindings for the corresponding lower-case
    letter, return the bindings for the lower-case letter.
+   We store 1 in *CASE_CONVERTED in this case.
+   Otherwise, we don't change *CASE_CONVERTED.
 
    If KEY has no bindings in any of the CURRENT maps, NEXT is left
    unmodified.
@@ -3586,10 +3745,11 @@ read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
    NEXT may == CURRENT.  */
 
 static int
-follow_key (key, nmaps, current, defs, next)
+follow_key (key, nmaps, current, defs, next, case_converted)
      Lisp_Object key;
      Lisp_Object *current, *defs, *next;
      int nmaps;
+     int *case_converted;
 {
   int i, first_binding;
 
@@ -3641,7 +3801,8 @@ follow_key (key, nmaps, current, defs, next)
       if (XINT (key) & shift_modifier)
        XSETINT (key, XINT (key) & ~shift_modifier);
       else
-       XSETINT (key, DOWNCASE (XINT (key)));
+       XSETINT (key, (DOWNCASE (XINT (key) & 0x3ffff)
+                      | (XINT (key) & ~0x3ffff)));
 
       first_binding = nmaps;
       for (i = nmaps - 1; i >= 0; i--)
@@ -3655,6 +3816,8 @@ follow_key (key, nmaps, current, defs, next)
          else
            defs[i] = Qnil;
        }
+      if (first_binding  != nmaps)
+       *case_converted = 1;
     }
 
   /* Given the set of bindings we've found, produce the next set of maps.  */
@@ -3703,7 +3866,7 @@ static int
 read_key_sequence (keybuf, bufsize, prompt)
      Lisp_Object *keybuf;
      int bufsize;
-     char *prompt;
+     Lisp_Object prompt;
 {
   int count = specpdl_ptr - specpdl;
 
@@ -3767,7 +3930,20 @@ read_key_sequence (keybuf, bufsize, prompt)
      we put it off for later.  While we're reading, we keep the event here.  */
   Lisp_Object delayed_switch_frame;
 
+  /* See the comment below... */
+#if defined (GOBBLE_FIRST_EVENT)
   Lisp_Object first_event;
+#endif
+
+  struct buffer *starting_buffer;
+
+  /* Nonzero if we found the binding for one of the chars
+     in this key sequence by downcasing it.  */
+  int case_converted = 0;
+
+  /* Nonzero if we seem to have got the beginning of a binding
+     in function_key_map.  */
+  int function_key_possible = 0;
 
   int junk;
 
@@ -3787,8 +3963,8 @@ read_key_sequence (keybuf, bufsize, prompt)
 
   if (INTERACTIVE)
     {
-      if (prompt)
-       echo_prompt (prompt);
+      if (!NILP (prompt))
+       echo_prompt (XSTRING (prompt)->data);
       else if (cursor_in_echo_area)
        /* This doesn't put in a dash if the echo buffer is empty, so
           you don't always see a dash hanging out in the minibuffer.  */
@@ -3801,20 +3977,26 @@ read_key_sequence (keybuf, bufsize, prompt)
     echo_start = echo_length ();
   keys_start = this_command_key_count;
 
-#if 0 /* This doesn't quite work, because some of the things
-        that read_char does cannot safely be bypassed.
-        It seems too risky to try to make this work right.  */ 
+#if defined (GOBBLE_FIRST_EVENT)
+  /* This doesn't quite work, because some of the things that read_char
+     does cannot safely be bypassed.  It seems too risky to try to make
+     this work right.  */ 
+
   /* Read the first char of the sequence specially, before setting
      up any keymaps, in case a filter runs and switches buffers on us.  */
-  first_event = read_char (!prompt, 0, submaps, last_nonmenu_event,
+  first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
                           &junk);
-#endif
+#endif /* GOBBLE_FIRST_EVENT */
 
   /* We jump here when the key sequence has been thoroughly changed, and
      we need to rescan it starting from the beginning.  When we jump here,
      keybuf[0..mock_input] holds the sequence we should reread.  */
  replay_sequence:
 
+  starting_buffer = current_buffer;
+  case_converted = 0;
+  function_key_possible = 0;
+
   /* Build our list of keymaps.
      If we recognize a function key and replace its escape sequence in
      keybuf with its symbol, or if the sequence starts with a mouse
@@ -3844,9 +4026,7 @@ read_key_sequence (keybuf, bufsize, prompt)
     if (! NILP (submaps[first_binding]))
       break;
 
-  /* We jump here when a function key substitution has forced us to
-     reprocess the current key sequence.  keybuf[0..mock_input] is the
-     sequence we want to reread.  */
+  /* Start from the beginning in keybuf.  */
   t = 0;
 
   /* These are no-ops the first time through, but if we restart, they
@@ -3866,7 +4046,13 @@ read_key_sequence (keybuf, bufsize, prompt)
         || (first_binding >= nmaps
             && keytran_start < t
             /* mock input is never part of a function key's sequence.  */
-            && mock_input <= keytran_start))
+            && mock_input <= keytran_start)
+        /* 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
+           and ESC o has a binding, don't return after ESC O,
+           so that we can translate ESC O plus the next character.  */
+        || (function_key_possible && case_converted))
     {
       Lisp_Object key;
       int used_mouse_menu = 0;
@@ -3918,7 +4104,7 @@ read_key_sequence (keybuf, bufsize, prompt)
        {
          struct buffer *buf = current_buffer;
 
-         key = read_char (!prompt, nmaps, submaps, last_nonmenu_event,
+         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.
@@ -3935,6 +4121,17 @@ read_key_sequence (keybuf, bufsize, prompt)
              goto done;
            }
          
+         /* 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)
+           {
+             keybuf[t++] = key;
+             mock_input = t;
+             Vquit_flag = Qnil;
+             goto replay_sequence;
+           }
+           
          Vquit_flag = Qnil;
        }
 
@@ -4070,7 +4267,8 @@ read_key_sequence (keybuf, bufsize, prompt)
                                   nmaps   - first_binding,
                                   submaps + first_binding,
                                   defs    + first_binding,
-                                  submaps + first_binding)
+                                  submaps + first_binding,
+                                  &case_converted)
                       + first_binding);
 
       /* If KEY wasn't bound, we'll try some fallbacks.  */
@@ -4156,21 +4354,22 @@ read_key_sequence (keybuf, bufsize, prompt)
                            }
                        }
 
-                     new_head =
-                       apply_modifiers (modifiers, XCONS (breakdown)->car);
-                     new_click =
-                       Fcons (new_head, Fcons (EVENT_START (key), Qnil));
+                     new_head
+                       apply_modifiers (modifiers, XCONS (breakdown)->car);
+                     new_click
+                       Fcons (new_head, Fcons (EVENT_START (key), Qnil));
 
                      /* Look for a binding for this new key.  follow_key
                         promises that it didn't munge submaps the
                         last time we called it, since key was unbound.  */
-                     first_binding =
-                       (follow_key (new_click,
-                                    nmaps   - local_first_binding,
-                                    submaps + local_first_binding,
-                                    defs    + local_first_binding,
-                                    submaps + local_first_binding)
-                        + local_first_binding);
+                     first_binding
+                       = (follow_key (new_click,
+                                      nmaps   - local_first_binding,
+                                      submaps + local_first_binding,
+                                      defs    + local_first_binding,
+                                      submaps + local_first_binding,
+                                      &case_converted)
+                          + local_first_binding);
 
                      /* If that click is bound, go for it.  */
                      if (first_binding < nmaps)
@@ -4196,12 +4395,14 @@ read_key_sequence (keybuf, bufsize, prompt)
         off the end of it.  We only want to scan real keyboard input
         for function key sequences, so if mock_input says that we're
         re-reading old events, don't examine it.  */
-      if (first_binding >= nmaps
+      if ((first_binding >= nmaps || case_converted)
          && t >= mock_input)
        {
          Lisp_Object fkey_next;
 
-         /* Scan from fkey_end until we find a bound suffix.  */
+         /* Continue scan from fkey_end until we find a bound suffix.
+            If we fail, increment fkey_start
+            and start fkey_end from there.  */
          while (fkey_end < t)
            {
              Lisp_Object key;
@@ -4224,6 +4425,29 @@ read_key_sequence (keybuf, bufsize, prompt)
              fkey_next
                = get_keyelt (access_keymap (fkey_next, key, 1, 0));
 
+             /* If the function key map gives a function, not an
+                array, then call the function with no args and use
+                its value instead.  */
+             if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
+                 && fkey_end == t)
+               {
+                 struct gcpro gcpro1, gcpro2, gcpro3;
+                 Lisp_Object tem;
+                 tem = fkey_next;
+
+                 GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
+                 fkey_next = call1 (fkey_next, prompt);
+                 UNGCPRO;
+                 /* If the function returned something invalid,
+                    barf--don't ignore it.
+                    (To ignore it safely, we would need to gcpro a bunch of 
+                    other variables.)  */
+                 if (! (VECTORP (fkey_next) || STRINGP (fkey_next)))
+                   error ("Function in function-key-map returns invalid key sequence");
+               }
+
+             function_key_possible = ! NILP (fkey_next);
+
              /* If keybuf[fkey_start..fkey_end] is bound in the
                 function key map and it's a suffix of the current
                 sequence (i.e. fkey_end == t), replace it with
@@ -4246,8 +4470,8 @@ read_key_sequence (keybuf, bufsize, prompt)
                      int i;
 
                      for (i = 0; i < len; i++)
-                       XFASTINT (keybuf[fkey_start + i]) =
-                         XSTRING (fkey_next)->data[i];
+                       XFASTINT (keybuf[fkey_start + i])
+                         XSTRING (fkey_next)->data[i];
                    }
                  
                  mock_input = t;
@@ -4265,6 +4489,7 @@ read_key_sequence (keybuf, bufsize, prompt)
                {
                  fkey_end = ++fkey_start;
                  fkey_map = Vfunction_key_map;
+                 function_key_possible = 0;
                }
            }
        }
@@ -4296,8 +4521,29 @@ read_key_sequence (keybuf, bufsize, prompt)
            keytran_next
              = get_keyelt (access_keymap (keytran_next, key, 1, 0));
 
+           /* If the key translation map gives a function, not an
+              array, then call the function with no args and use
+              its value instead.  */
+           if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
+               && keytran_end == t)
+             {
+               struct gcpro gcpro1, gcpro2, gcpro3;
+               Lisp_Object tem;
+               tem = keytran_next;
+
+               GCPRO3 (keytran_map, keytran_map, delayed_switch_frame);
+               keytran_next = call1 (keytran_next, prompt);
+               UNGCPRO;
+               /* If the function returned something invalid,
+                  barf--don't ignore it.
+                  (To ignore it safely, we would need to gcpro a bunch of 
+                  other variables.)  */
+               if (! (VECTORP (keytran_next) || STRINGP (keytran_next)))
+                 error ("Function in function-key-map returns invalid key sequence");
+             }
+
            /* If keybuf[keytran_start..keytran_end] is bound in the
-              function key map and it's a suffix of the current
+              key translation map and it's a suffix of the current
               sequence (i.e. keytran_end == t), replace it with
               the binding and restart with keytran_start at the end. */
            if ((VECTORP (keytran_next) || STRINGP (keytran_next))
@@ -4385,7 +4631,7 @@ and `quit-flag' is not set.\n\
 If the key sequence starts with a mouse click, then the sequence is read\n\
 using the keymaps of the buffer of the window clicked in, not the buffer\n\
 of the selected window as normal.\n\
-\n\
+""\n\
 `read-key-sequence' drops unbound button-down events, since you normally\n\
 only care about the click or drag events which follow them.  If a drag\n\
 or multi-click event is unbound, but the corresponding click event would\n\
@@ -4426,8 +4672,7 @@ 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])),
-                        NILP (prompt) ? 0 : XSTRING (prompt)->data);
+  i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), prompt);
 
   if (i == -1)
     {
@@ -4537,11 +4782,11 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
 
   /* Prompt with buf, and then read a string, completing from and
      restricting to the set of all defined commands.  Don't provide
-     any initial input.  The last Qnil says not to perform a 
-     peculiar hack on the initial input.  */
+     any initial input.  Save the command read on the extended-command
+     history list. */
   function = Fcompleting_read (build_string (buf),
                               Vobarray, Qcommandp,
-                              Qt, Qnil, Qnil);
+                              Qt, Qnil, Qextended_command_history);
 
   /* Set this_command_keys to the concatenation of saved_keys and
      function, followed by a RET.  */
@@ -4772,7 +5017,7 @@ stuff_buffered_input (stuffstring)
       if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
        kbd_fetch_ptr = kbd_buffer;
       if (kbd_fetch_ptr->kind == ascii_keystroke)
-       stuff_char (XINT (kbd_fetch_ptr->code));
+       stuff_char (kbd_fetch_ptr->code);
       kbd_fetch_ptr->kind = no_event;
       (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
                                                     - kbd_buffer]
@@ -4796,13 +5041,6 @@ set_waiting_for_input (time_to_clear)
      make it run again now, to avoid timing error. */
   if (!NILP (Vquit_flag))
     quit_throw_to_read_char ();
-
-  /* If alarm has gone off already, echo now.  */
-  if (echo_flag)
-    {
-      echo ();
-      echo_flag = 0;
-    }
 }
 
 clear_waiting_for_input ()
@@ -4930,6 +5168,11 @@ quit_throw_to_read_char ()
   if (poll_suppress_count == 0)
     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));
+#endif
 
   _longjmp (getcjmp, 1);
 }
@@ -5203,6 +5446,10 @@ syms_of_keyboard ()
   this_command_keys = Fmake_vector (make_number (40), Qnil);
   staticpro (&this_command_keys);
 
+  Qextended_command_history = intern ("extended-command-history");
+  Fset (Qextended_command_history, Qnil);
+  staticpro (&Qextended_command_history);
+
   kbd_buffer_frame_or_window
     = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
   staticpro (&kbd_buffer_frame_or_window);
@@ -5375,7 +5622,7 @@ 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\
 not count as a control character; rather, it counts as a character\n\
-with no modifiers; thus, setting extra_keyboard_modifiers to zero\n\
+with no modifiers; thus, setting `extra-keyboard-modifiers' to zero\n\
 cancels any modification.");
   extra_keyboard_modifiers = 0;
 
@@ -5402,6 +5649,9 @@ Buffer modification stores t in this variable.");
     "List of menu bar items to move to the end of the menu bar.\n\
 The elements of the list are event types that may have menu bar bindings.");
   Vmenu_bar_final_items = Qnil;
+
+  DEFVAR_BOOL ("track-mouse", &do_mouse_tracking,
+              "*Non-nil means generate motion events for mouse motion.");
 }
 
 keys_of_keyboard ()