]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
(kbd_buffer_store_event): Fix interrupt_signal decl
[gnu-emacs] / src / keyboard.c
index c680473c79d648080fb7407805050409a8f8326f..37529018962461c25dce47eb55b3fedc229a6e84 100644 (file)
@@ -1,5 +1,5 @@
 /* Keyboard and mouse input; editor command loop.
-   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 2001
+   Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 01, 02
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -505,7 +505,7 @@ static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
    queue.  That way, they'll be dequeued as dead frames or windows,
    but still valid Lisp objects.
 
-   If kbd_buffer[i].kind != no_event, then
+   If kbd_buffer[i].kind != NO_EVENT, then
 
    AREF (kbd_buffer_gcpro, 2 * i) == kbd_buffer[i].frame_or_window.
    AREF (kbd_buffer_gcpro, 2 * i + 1) == kbd_buffer[i].arg.  */
@@ -664,6 +664,11 @@ Lisp_Object Vglobal_disable_point_adjustment;
 
 static EMACS_TIME timer_idleness_start_time;
 
+/* After Emacs stops being idle, this saves the last value
+   of timer_idleness_start_time from when it was idle.  */
+
+static EMACS_TIME timer_last_idleness_start_time;
+
 \f
 /* Global variable declarations.  */
 
@@ -672,7 +677,9 @@ void (*keyboard_init_hook) ();
 
 static int read_avail_input P_ ((int));
 static void get_input_pending P_ ((int *, int));
+static void get_filtered_input_pending P_ ((int *, int, int));
 static int readable_events P_ ((int));
+static int readable_filtered_events P_ ((int, int));
 static Lisp_Object read_char_x_menu_prompt P_ ((int, Lisp_Object *,
                                                Lisp_Object, int *));
 static Lisp_Object read_char_x_menu_prompt ();
@@ -3253,31 +3260,37 @@ some_mouse_moved ()
 /* Return true iff there are any events in the queue that read-char
    would return.  If this returns false, a read-char would block.  */
 static int
-readable_events (do_timers_now)
+readable_filtered_events (do_timers_now, filter_events)
      int do_timers_now;
+     int filter_events;
 {
   if (do_timers_now)
     timer_check (do_timers_now);
 
   /* If the buffer contains only FOCUS_IN_EVENT events,
-     report it as empty.  */
+     and FILTER_EVENTS is nonzero, report it as empty.  */
   if (kbd_fetch_ptr != kbd_store_ptr)
     {
-      struct input_event *event;
-
-      event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
-              ? kbd_fetch_ptr
-              : kbd_buffer);
+      int have_live_event = 1;
 
-      while (event->kind == FOCUS_IN_EVENT)
-       {
-         event++;
-         if (event == kbd_buffer + KBD_BUFFER_SIZE)
-           event = kbd_buffer;
-         if (event == kbd_store_ptr)
-           return 0;
-       }
-      return 1;
+      if (filter_events)
+        {
+          struct input_event *event;
+
+          event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
+                   ? kbd_fetch_ptr
+                   : kbd_buffer);
+
+          while (have_live_event && event->kind == FOCUS_IN_EVENT)
+            {
+              event++;
+              if (event == kbd_buffer + KBD_BUFFER_SIZE)
+                event = kbd_buffer;
+              if (event == kbd_store_ptr)
+                have_live_event = 0;
+            }
+        }
+      if (have_live_event) return 1;
     }
 
 #ifdef HAVE_MOUSE
@@ -3299,6 +3312,15 @@ readable_events (do_timers_now)
   return 0;
 }
 
+/* Return true iff there are any events in the queue that read-char
+   would return.  If this returns false, a read-char would block.  */
+static int
+readable_events (do_timers_now)
+     int do_timers_now;
+{
+  return readable_filtered_events (do_timers_now, 0);
+}
+
 /* Set this for debugging, to have a way to get out */
 int stop_character;
 
@@ -3330,10 +3352,10 @@ void
 kbd_buffer_store_event (event)
      register struct input_event *event;
 {
-  if (event->kind == no_event)
+  if (event->kind == NO_EVENT)
     abort ();
 
-  if (event->kind == ascii_keystroke)
+  if (event->kind == ASCII_KEYSTROKE_EVENT)
     {
       register int c = event->code & 0377;
 
@@ -3346,7 +3368,7 @@ kbd_buffer_store_event (event)
 
       if (c == quit_char)
        {
-         static SIGTYPE interrupt_signal (int);
+         static SIGTYPE interrupt_signal P_ ((int));
 #ifdef MULTI_KBOARD
          KBOARD *kb;
          struct input_event *sp;
@@ -3366,7 +3388,7 @@ kbd_buffer_store_event (event)
 
                  if (event_to_kboard (sp) == kb)
                    {
-                     sp->kind = no_event;
+                     sp->kind = NO_EVENT;
                      sp->frame_or_window = Qnil;
                      sp->arg = Qnil;
                    }
@@ -3400,11 +3422,11 @@ kbd_buffer_store_event (event)
          return;
        }
     }
-  /* Don't insert two buffer_switch_event's in a row.
+  /* Don't insert two BUFFER_SWITCH_EVENT's in a row.
      Just ignore the second one.  */
-  else if (event->kind == buffer_switch_event
+  else if (event->kind == BUFFER_SWITCH_EVENT
           && kbd_fetch_ptr != kbd_store_ptr
-          && kbd_store_ptr->kind == buffer_switch_event)
+          && kbd_store_ptr->kind == BUFFER_SWITCH_EVENT)
     return;
 
   if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE)
@@ -3418,12 +3440,12 @@ kbd_buffer_store_event (event)
     {
       int idx;
       
-#if 0 /* The selection_request_event case looks bogus, and it's error
+#if 0 /* The SELECTION_REQUEST_EVENT case looks bogus, and it's error
         prone to assign individual members for other events, in case
         the input_event structure is changed.  --2000-07-13, gerd.  */
       struct input_event *sp = kbd_store_ptr;
       sp->kind = event->kind;
-      if (event->kind == selection_request_event)
+      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
@@ -3507,7 +3529,7 @@ kbd_buffer_store_help_event (frame, help)
 
 \f
 /* Discard any mouse events in the event buffer by setting them to
-   no_event.  */
+   NO_EVENT.  */
 void
 discard_mouse_events ()
 {
@@ -3517,22 +3539,22 @@ discard_mouse_events ()
       if (sp == kbd_buffer + KBD_BUFFER_SIZE)
        sp = kbd_buffer;
 
-      if (sp->kind == mouse_click
+      if (sp->kind == MOUSE_CLICK_EVENT
 #ifdef WINDOWSNT
-         || sp->kind == w32_scroll_bar_click
+         || sp->kind == W32_SCROLL_BAR_CLICK_EVENT
 #endif
-         || sp->kind == scroll_bar_click)
+         || sp->kind == SCROLL_BAR_CLICK_EVENT)
        {
-         sp->kind = no_event;
+         sp->kind = NO_EVENT;
        }
     }
 }
 
 
 /* Return non-zero if there are any real events waiting in the event
-   buffer, not counting `no_event's.
+   buffer, not counting `NO_EVENT's.
 
-   If DISCARD is non-zero, discard no_event events at the front of
+   If DISCARD is non-zero, discard NO_EVENT events at the front of
    the input queue, possibly leaving the input queue empty if there
    are no real input events.  */
 
@@ -3543,7 +3565,7 @@ kbd_buffer_events_waiting (discard)
   struct input_event *sp;
   
   for (sp = kbd_fetch_ptr;
-       sp != kbd_store_ptr && sp->kind == no_event;
+       sp != kbd_store_ptr && sp->kind == NO_EVENT;
        ++sp)
     {
       if (sp == kbd_buffer + KBD_BUFFER_SIZE)
@@ -3553,7 +3575,7 @@ kbd_buffer_events_waiting (discard)
   if (discard)
     kbd_fetch_ptr = sp;
 
-  return sp != kbd_store_ptr && sp->kind != no_event;
+  return sp != kbd_store_ptr && sp->kind != NO_EVENT;
 }
 
 \f
@@ -3566,7 +3588,7 @@ clear_event (event)
   int idx = 2 * (event - kbd_buffer);
   ASET (kbd_buffer_gcpro, idx, Qnil);
   ASET (kbd_buffer_gcpro, idx + 1, Qnil);
-  event->kind = no_event;
+  event->kind = NO_EVENT;
 }
 
 
@@ -3671,7 +3693,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.
         We return nil for them.  */
-      if (event->kind == selection_request_event)
+      if (event->kind == SELECTION_REQUEST_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3690,7 +3712,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
 #endif
        }
 
-      else if (event->kind == selection_clear_event)
+      else if (event->kind == SELECTION_CLEAR_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3707,7 +3729,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
 #endif
        }
 #if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
-      else if (event->kind == delete_window_event)
+      else if (event->kind == DELETE_WINDOW_EVENT)
        {
          /* Make an event (delete-frame (FRAME)).  */
          obj = Fcons (event->frame_or_window, Qnil);
@@ -3716,14 +3738,14 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
        }
 #endif
 #if defined (HAVE_X11) || defined (HAVE_NTGUI)
-      else if (event->kind == iconify_event)
+      else if (event->kind == ICONIFY_EVENT)
        {
          /* Make an event (iconify-frame (FRAME)).  */
          obj = Fcons (event->frame_or_window, Qnil);
          obj = Fcons (Qiconify_frame, Fcons (obj, Qnil));
          kbd_fetch_ptr = event + 1;
        }
-      else if (event->kind == deiconify_event)
+      else if (event->kind == DEICONIFY_EVENT)
        {
          /* Make an event (make-frame-visible (FRAME)).  */
          obj = Fcons (event->frame_or_window, Qnil);
@@ -3731,14 +3753,14 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
          kbd_fetch_ptr = event + 1;
        }
 #endif
-      else if (event->kind == buffer_switch_event)
+      else if (event->kind == BUFFER_SWITCH_EVENT)
        {
          /* The value doesn't matter here; only the type is tested.  */
          XSETBUFFER (obj, current_buffer);
          kbd_fetch_ptr = event + 1;
        }
 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
-      else if (event->kind == menu_bar_activate_event)
+      else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
        {
          kbd_fetch_ptr = event + 1;
          input_pending = readable_events (0);
@@ -3747,7 +3769,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
        }
 #endif
 #ifdef WINDOWSNT
-      else if (event->kind == language_change_event)
+      else if (event->kind == LANGUAGE_CHANGE_EVENT)
        {
          /* Make an event (language-change (FRAME CHARSET LCID)).  */
          obj = Fcons (event->modifiers, Qnil);
@@ -3757,7 +3779,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
          kbd_fetch_ptr = event + 1;
        }
 #endif
-      else if (event->kind == save_session_event)
+      else if (event->kind == SAVE_SESSION_EVENT)
         {
           obj = Fcons (Qsave_session, Qnil);
          kbd_fetch_ptr = event + 1;
@@ -3768,9 +3790,9 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
         (They shouldn't otherwise be found in the buffer,
         but on some machines it appears they do show up
         even without MULTI_KBOARD.)  */
-      /* On Windows NT/9X, no_event is used to delete extraneous
+      /* On Windows NT/9X, NO_EVENT is used to delete extraneous
          mouse events during a popup-menu call.  */
-      else if (event->kind == no_event)
+      else if (event->kind == NO_EVENT)
        kbd_fetch_ptr = event + 1;
       else if (event->kind == HELP_EVENT)
        {
@@ -3938,7 +3960,7 @@ swallow_events (do_display)
 
       /* These two kinds of events get special handling
         and don't actually appear to the command loop.  */
-      if (event->kind == selection_request_event)
+      if (event->kind == SELECTION_REQUEST_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3957,7 +3979,7 @@ swallow_events (do_display)
 #endif
        }
 
-      else if (event->kind == selection_clear_event)
+      else if (event->kind == SELECTION_CLEAR_EVENT)
        {
 #ifdef HAVE_X11
          struct input_event copy;
@@ -3999,6 +4021,8 @@ timer_start_idle ()
 
   EMACS_GET_TIME (timer_idleness_start_time);
 
+  timer_last_idleness_start_time = timer_idleness_start_time;
+
   /* Mark all idle-time timers as once again candidates for running.  */
   for (timers = Vtimer_idle_list; CONSP (timers); timers = XCDR (timers))
     {
@@ -4724,7 +4748,7 @@ make_lispy_event (event)
   switch (SWITCH_ENUM_CAST (event->kind))
     {
       /* A simple keystroke.  */
-    case ascii_keystroke:
+    case ASCII_KEYSTROKE_EVENT:
       {
        Lisp_Object lispy_c;
        int c = event->code & 0377;
@@ -4748,7 +4772,7 @@ make_lispy_event (event)
        return lispy_c;
       }
 
-    case multibyte_char_keystroke:
+    case MULTIBYTE_CHAR_KEYSTROKE_EVENT:
       {
        Lisp_Object lispy_c;
 
@@ -4758,7 +4782,7 @@ make_lispy_event (event)
 
       /* A function key.  The symbol may need to have modifier prefixes
         tacked onto it.  */
-    case non_ascii_keystroke:
+    case NON_ASCII_KEYSTROKE_EVENT:
       button_down_time = 0;
 
       for (i = 0; i < sizeof (lispy_accent_codes) / sizeof (int); i++)
@@ -4820,9 +4844,9 @@ make_lispy_event (event)
 #ifdef HAVE_MOUSE
       /* A mouse click.  Figure out where it is, decide whether it's
          a press, click or drag, and build the appropriate structure.  */
-    case mouse_click:
+    case MOUSE_CLICK_EVENT:
 #ifndef USE_TOOLKIT_SCROLL_BARS
-    case scroll_bar_click:
+    case SCROLL_BAR_CLICK_EVENT:
 #endif
       {
        int button = event->code;
@@ -4835,7 +4859,7 @@ make_lispy_event (event)
        position = Qnil;
 
        /* Build the position as appropriate for this mouse click.  */
-       if (event->kind == mouse_click)
+       if (event->kind == MOUSE_CLICK_EVENT)
          {
            int part;
            struct frame *f = XFRAME (event->frame_or_window);
@@ -5165,7 +5189,7 @@ make_lispy_event (event)
         index of type `enum scroll_bar_part' which we can use as an
         index in scroll_bar_parts to get the appropriate symbol.  */
         
-    case scroll_bar_click:
+    case SCROLL_BAR_CLICK_EVENT:
       {
        Lisp_Object position, head, window, portion_whole, part;
 
@@ -5196,7 +5220,7 @@ make_lispy_event (event)
 #endif /* USE_TOOLKIT_SCROLL_BARS */
 
 #ifdef WINDOWSNT
-    case w32_scroll_bar_click:
+    case W32_SCROLL_BAR_CLICK_EVENT:
       {
        int button = event->code;
        int is_double;
@@ -5239,7 +5263,7 @@ make_lispy_event (event)
                               Qnil));
        }
       }
-    case mouse_wheel:
+    case MOUSE_WHEEL_EVENT:
       {
        int part;
        FRAME_PTR f = XFRAME (event->frame_or_window);
@@ -5312,7 +5336,7 @@ make_lispy_event (event)
       }
 #endif /* WINDOWSNT */
 
-    case drag_n_drop:
+    case DRAG_N_DROP_EVENT:
       {
        int part;
        FRAME_PTR f;
@@ -5418,7 +5442,7 @@ make_lispy_event (event)
       /* A user signal.  */
       return *lispy_user_signals[event->code];
       
-    case save_session_event:
+    case SAVE_SESSION_EVENT:
       return Qsave_session;
       
       /* The 'kind' field of the event is something we don't recognize.  */
@@ -6144,15 +6168,18 @@ lucid_event_type_list_p (object)
    but works even if FIONREAD does not exist.
    (In fact, this may actually read some input.)
 
-   If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe.  */
+   If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe.
+   If FILTER_EVENTS is nonzero, ignore internal events (FOCUS_IN_EVENT). */
 
 static void
-get_input_pending (addr, do_timers_now)
+get_filtered_input_pending (addr, do_timers_now, filter_events)
      int *addr;
      int do_timers_now;
+     int filter_events;
 {
   /* First of all, have we already counted some input?  */
-  *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
+  *addr = (!NILP (Vquit_flag)
+           || readable_filtered_events (do_timers_now, filter_events));
 
   /* If input is being read as it arrives, and we have none, there is none.  */
   if (*addr > 0 || (interrupt_input && ! interrupts_deferred))
@@ -6160,7 +6187,23 @@ get_input_pending (addr, do_timers_now)
 
   /* Try to read some input and see how much we get.  */
   gobble_input (0);
-  *addr = !NILP (Vquit_flag) || readable_events (do_timers_now);
+  *addr = (!NILP (Vquit_flag)
+           || readable_filtered_events (do_timers_now, filter_events));
+}
+
+/* Store into *addr a value nonzero if terminal input chars are available.
+   Serves the purpose of ioctl (0, FIONREAD, addr)
+   but works even if FIONREAD does not exist.
+   (In fact, this may actually read some input.)
+
+   If DO_TIMERS_NOW is nonzero, actually run timer events that are ripe.  */
+
+static void
+get_input_pending (addr, do_timers_now)
+     int *addr;
+     int do_timers_now;
+{
+  get_filtered_input_pending (addr, do_timers_now, 0);
 }
 
 /* Interface to read_avail_input, blocking SIGIO or SIGALRM if necessary.  */
@@ -6194,7 +6237,7 @@ gobble_input (expected)
 #endif
 }
 
-/* Put a buffer_switch_event in the buffer
+/* Put a BUFFER_SWITCH_EVENT in the buffer
    so that read_key_sequence will notice the new current buffer.  */
 
 void
@@ -6203,7 +6246,7 @@ record_asynch_buffer_change ()
   struct input_event event;
   Lisp_Object tem;
 
-  event.kind = buffer_switch_event;
+  event.kind = BUFFER_SWITCH_EVENT;
   event.frame_or_window = Qnil;
   event.arg = Qnil;
 
@@ -6358,7 +6401,7 @@ read_avail_input (expected)
 #endif /* no FIONREAD */
       for (i = 0; i < nread; i++)
        {
-         buf[i].kind = ascii_keystroke;
+         buf[i].kind = ASCII_KEYSTROKE_EVENT;
          buf[i].modifiers = 0;
          if (meta_key == 1 && (cbuf[i] & 0x80))
            buf[i].modifiers = meta_modifier;
@@ -6377,7 +6420,7 @@ read_avail_input (expected)
       kbd_buffer_store_event (&buf[i]);
       /* Don't look at input that follows a C-g too closely.
         This reduces lossage due to autorepeat on C-g.  */
-      if (buf[i].kind == ascii_keystroke
+      if (buf[i].kind == ASCII_KEYSTROKE_EVENT
          && buf[i].code == quit_char)
        break;
     }
@@ -8051,11 +8094,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
 
   struct buffer *starting_buffer;
 
-  /* Nonzero if we seem to have got the beginning of a binding
-     in function_key_map.  */
-  volatile int function_key_possible = 0;
-  volatile int key_translation_possible = 0;
-
   /* List of events for which a fake prefix key has been generated.  */
   volatile Lisp_Object fake_prefixed_keys = Qnil;
 
@@ -8122,8 +8160,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
  replay_sequence:
 
   starting_buffer = current_buffer;
-  function_key_possible = 0;
-  key_translation_possible = 0;
   first_unbound = bufsize + 1;
 
   /* Build our list of keymaps.
@@ -8193,10 +8229,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      we may be looking at a function key's escape sequence, keep on
      reading.  */
   while ((first_binding < nmaps && ! NILP (submaps[first_binding]))
-        || (first_binding >= nmaps
-            && fkey_start < t)
-        || (first_binding >= nmaps
-            && keytran_start < t && key_translation_possible)
+        || (first_binding >= nmaps && fkey_start < t)
+        || (first_binding >= nmaps && keytran_start < t)
         /* 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
@@ -8341,6 +8375,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
             keymap may have changed, so replay the sequence.  */
          if (BUFFERP (key))
            {
+             EMACS_TIME initial_idleness_start_time
+               = timer_last_idleness_start_time;
+
+             /* Resume idle state, using the same start-time as before.  */
+             timer_start_idle ();
+             timer_idleness_start_time = initial_idleness_start_time;
+
              mock_input = t;
              /* Reset the current buffer from the selected window
                 in case something changed the former and not the latter.
@@ -8626,7 +8667,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                       + first_binding);
 
       /* If KEY wasn't bound, we'll try some fallbacks.  */
-      if (first_binding >= nmaps)
+      if (first_binding < nmaps)
+       /* This is needed for the following scenario:
+          event 0: a down-event that gets dropped by calling replay_key.
+          event 1: some normal prefix like C-h.
+          After event 0, first_unbound is 0, after event 1 fkey_start
+          and keytran_start are both 1, so when we see that C-h is bound,
+          we need to update first_unbound.  */
+       first_unbound = max (t + 1, first_unbound);
+      else
        {
          Lisp_Object head;
          
@@ -8706,6 +8755,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                             generate mouse events, so it's okay to zero
                             mock_input in that case too.
 
+                            FIXME: The above paragraph seems just plain
+                            wrong, if you consider things like
+                            xterm-mouse-mode.  -stef
+
                             Isn't this just the most wonderful code ever?  */
                          if (t == last_real_key_start)
                            {
@@ -8758,25 +8811,30 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       /* Record what part of this_command_keys is the current key sequence.  */
       this_single_command_key_start = this_command_key_count - t;
 
-      /* If the sequence is unbound, see if we can hang a function key
-        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
-         && t >= mock_input)
+      if (first_binding < nmaps && NILP (submaps[first_binding]))
+       /* There is a binding and it's not a prefix.
+          There is thus no function-key in this sequence.
+          Moving fkey.start is important in this case to allow keytran.start
+          to go over the sequence before we return (since we keep the
+          invariant that keytran.end <= fkey.start).  */
+       {
+         if (fkey_start < t)
+           (fkey_start = fkey_end = t, fkey_map = Vfunction_key_map);
+       }
+      else
+       /* If the sequence is unbound, see if we can hang a function key
+          off the end of it.  */
        {
          Lisp_Object fkey_next;
 
          /* Continue scan from fkey_end until we find a bound suffix.
-            If we fail, increment fkey_start
-            and start fkey_end from there.  */
+            If we fail, increment fkey_start and start over from there.  */
          while (fkey_end < t)
            {
              Lisp_Object key;
 
              key = keybuf[fkey_end++];
-             fkey_next
-               = access_keymap (fkey_map, key, 1, 0, 1);
+             fkey_next = access_keymap (fkey_map, key, 1, 0, 1);
 
              /* Handle symbol with autoload definition.  */
              if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
@@ -8804,7 +8862,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                 array, then call the function with no args and use
                 its value instead.  */
              if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
-                 && fkey_end == t)
+                 /* If there's a binding (i.e. first_binding >= nmaps)
+                    we don't want to apply this function-key-mapping.  */
+                 && fkey_end == t && first_binding >= nmaps)
                {
                  struct gcpro gcpro1, gcpro2, gcpro3;
                  Lisp_Object tem;
@@ -8821,14 +8881,14 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                    error ("Function in key-translation-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
                 the binding and restart with fkey_start at the end. */
              if ((VECTORP (fkey_next) || STRINGP (fkey_next))
-                 && fkey_end == t)
+                 /* If there's a binding (i.e. first_binding >= nmaps)
+                    we don't want to apply this function-key-mapping.  */
+                 && fkey_end == t && first_binding >= nmaps)
                {
                  int len = XFASTINT (Flength (fkey_next));
 
@@ -8870,20 +8930,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                {
                  fkey_end = ++fkey_start;
                  fkey_map = Vfunction_key_map;
-                 function_key_possible = 0;
                }
            }
        }
-      else if (NILP (submaps[first_binding]))
-       /* There is a global binding and it's not a prefix.
-          There is thus no function-key in this sequence.
-          We can probably show that there can't be any afterwards either
-          but I can't seem to find a clear reason why not, so I'll
-          be conservative.
-          Moving fkey.start is important in this case to allow keytran.start
-          to go over the sequence before we return (since we keep the
-          invariant that keytran.end <= fkey.start).  */
-       (fkey_start = max (fkey_start, t), fkey_end = max (fkey_end, t));
 
       /* Look for this sequence in key-translation-map.  */
       {
@@ -8932,8 +8981,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                  error ("Function in key-translation-map returns invalid key sequence");
              }
 
-           key_translation_possible = ! NILP (keytran_next);
-
            /* If keybuf[keytran_start..keytran_end] is bound in the
               key translation map and it's a suffix of the current
               sequence (i.e. keytran_end == t), replace it with
@@ -8979,7 +9026,6 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
              {
                keytran_end = ++keytran_start;
                keytran_map = Vkey_translation_map;
-               key_translation_possible = 0;
              }
          }
       }
@@ -8988,8 +9034,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and cannot be part of a function key or translation,
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
-      if (first_binding == nmaps && ! function_key_possible
-         && ! key_translation_possible
+      if (first_binding >= nmaps
+         && fkey_start >= t && keytran_start >= t
          && INTEGERP (key)
          && ((((XINT (key) & 0x3ffff)
                < XCHAR_TABLE (current_buffer->downcase_table)->size)
@@ -9019,8 +9065,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and cannot be part of a function key or translation,
         and is a shifted function key,
         use the corresponding unshifted function key instead.  */
-      if (first_binding == nmaps && ! function_key_possible
-         && ! key_translation_possible
+      if (first_binding >= nmaps
+         && fkey_start >= t && keytran_start >= t
          && SYMBOLP (key))
        {
          Lisp_Object breakdown;
@@ -9567,7 +9613,7 @@ if there is a doubt, the value is t.  */)
   if (!NILP (Vunread_command_events) || unread_command_char != -1)
     return (Qt);
 
-  get_input_pending (&input_pending, 1);
+  get_filtered_input_pending (&input_pending, 1, 1);
   return input_pending > 0 ? Qt : Qnil;
 }
 
@@ -9822,10 +9868,10 @@ 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)
+      if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT)
        stuff_char (kbd_fetch_ptr->code);
       
-      kbd_fetch_ptr->kind = no_event;
+      kbd_fetch_ptr->kind = NO_EVENT;
       idx = 2 * (kbd_fetch_ptr - kbd_buffer);
       ASET (kbd_buffer_gcpro, idx, Qnil);
       ASET (kbd_buffer_gcpro, idx + 1, Qnil);