]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Remove obsolete USE_OLIT code.
[gnu-emacs] / src / keyboard.c
index 76101090d4c122af5b12f70cddd38143f6843c1a..fd726a5a254e656d18908a35cb20e30b5d437a0b 100644 (file)
@@ -412,7 +412,7 @@ Lisp_Object Vecho_keystrokes;
 /* Form to evaluate (if non-nil) when Emacs is started.  */
 Lisp_Object Vtop_level;
 
-/* User-supplied string to translate input characters through.  */
+/* User-supplied table to translate input characters.  */
 Lisp_Object Vkeyboard_translate_table;
 
 /* Keymap mapping ASCII function key sequences onto their preferred forms.  */
@@ -598,7 +598,7 @@ Lisp_Object Fthis_command_keys ();
 Lisp_Object Qextended_command_history;
 EMACS_TIME timer_check ();
 
-extern Lisp_Object Vhistory_length;
+extern Lisp_Object Vhistory_length, Vtranslation_table_for_input;
 
 extern char *x_get_keysym_name ();
 
@@ -1629,10 +1629,13 @@ command_loop_1 ()
                  goto directly_done;
                }
              else if (EQ (Vthis_command, Qself_insert_command)
-                      /* Try this optimization only on ascii keystrokes.  */
-                      && INTEGERP (last_command_char))
+                      /* Try this optimization only on char keystrokes.  */
+                      && NATNUMP (last_command_char)
+                      && CHAR_VALID_P (XFASTINT (last_command_char), 0))
                {
-                 unsigned int c = XINT (last_command_char);
+                 unsigned int c =
+                   translate_char (Vtranslation_table_for_input,
+                                   XFASTINT (last_command_char), 0, 0, 0);
                  int value;
                  if (NILP (Vexecuting_macro)
                      && !EQ (minibuf_window, selected_window))
@@ -1785,47 +1788,114 @@ extern Lisp_Object Qcomposition, Qdisplay;
 
 /* Adjust point to a boundary of a region that has such a property
    that should be treated intangible.  For the moment, we check
-   `composition' and `display' property.  LAST_PT is the last position
-   of point.  */
+   `composition', `display' and `invisible' properties.
+   LAST_PT is the last position of point.  */
+
+extern Lisp_Object Qafter_string, Qbefore_string;
+extern Lisp_Object get_pos_property P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 
 static void
 adjust_point_for_property (last_pt)
      int last_pt;
 {
-  int start, end;
-  Lisp_Object val;
-  int check_composition = 1, check_display = 1;
+  int beg, end;
+  Lisp_Object val, overlay, tmp;
+  int check_composition = 1, check_display = 1, check_invisible = 1;
 
-  while (check_composition || check_display)
+  while (check_composition || check_display || check_invisible)
     {
       if (check_composition
          && PT > BEGV && PT < ZV
-         && get_property_and_range (PT, Qcomposition, &val, &start, &end, Qnil)
-         && COMPOSITION_VALID_P (start, end, val)
-         && start < PT && end > PT
-         && (last_pt <= start || last_pt >= end))
+         && get_property_and_range (PT, Qcomposition, &val, &beg, &end, Qnil)
+         && COMPOSITION_VALID_P (beg, end, val)
+         && beg < PT /* && end > PT   <- It's always the case.  */
+         && (last_pt <= beg || last_pt >= end))
        {
-         if (PT < last_pt)
-           SET_PT (start);
-         else
-           SET_PT (end);
-         check_display = 1;
+         xassert (end > PT);
+         SET_PT (PT < last_pt ? beg : end);
+         check_display = check_invisible = 1;
        }
       check_composition = 0;
       if (check_display
          && PT > BEGV && PT < ZV
-         && get_property_and_range (PT, Qdisplay, &val, &start, &end, Qnil)
+         && !NILP (val = get_char_property_and_overlay
+                             (make_number (PT), Qdisplay, Qnil, &overlay))
          && display_prop_intangible_p (val)
-         && start < PT && end > PT
-         && (last_pt <= start || last_pt >= end))
+         && (!OVERLAYP (overlay)
+             ? get_property_and_range (PT, Qdisplay, &val, &beg, &end, Qnil)
+             : (beg = OVERLAY_POSITION (OVERLAY_START (overlay)),
+                end = OVERLAY_POSITION (OVERLAY_END (overlay))))
+         && beg < PT) /* && end > PT   <- It's always the case.  */
        {
-         if (PT < last_pt)
-           SET_PT (start);
-         else
-           SET_PT (end);
-         check_composition = 1;
+         xassert (end > PT);
+         SET_PT (PT < last_pt ? beg : end);
+         check_composition = check_invisible = 1;
        }
       check_display = 0;
+      if (check_invisible && PT > BEGV && PT < ZV)
+       {
+         int inv, ellipsis = 0;
+         beg = end = PT;
+
+         /* Find boundaries `beg' and `end' of the invisible area, if any.  */
+         while (end < ZV
+                && !NILP (val = get_char_property_and_overlay
+                          (make_number (end), Qinvisible, Qnil, &overlay))
+                && (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
+           {
+             ellipsis = ellipsis || inv > 1
+               || (OVERLAYP (overlay)
+                   && (!NILP (Foverlay_get (overlay, Qafter_string))
+                       || !NILP (Foverlay_get (overlay, Qbefore_string))));
+             tmp = Fnext_single_char_property_change
+               (make_number (end), Qinvisible, Qnil, Qnil);
+             end = NATNUMP (tmp) ? XFASTINT (tmp) : ZV;
+           }
+         while (beg > BEGV
+                && !NILP (val = get_char_property_and_overlay
+                          (make_number (beg - 1), Qinvisible, Qnil, &overlay))
+                && (inv = TEXT_PROP_MEANS_INVISIBLE (val)))
+           {
+             ellipsis = ellipsis || inv > 1
+               || (OVERLAYP (overlay)
+                   && (!NILP (Foverlay_get (overlay, Qafter_string))
+                       || !NILP (Foverlay_get (overlay, Qbefore_string))));
+             tmp = Fprevious_single_char_property_change
+               (make_number (beg), Qinvisible, Qnil, Qnil);
+             beg = NATNUMP (tmp) ? XFASTINT (tmp) : BEGV;
+           }
+         
+         /* Move away from the inside area.  */
+         if (beg < PT && end > PT)
+           {
+             SET_PT (PT < last_pt ? beg : end);
+             check_composition = check_display = 1;
+           }
+         xassert (PT == beg || PT == end);
+         /* Pretend the area doesn't exist.  */
+         if (!ellipsis && beg < end)
+           {
+             if (last_pt == beg && PT == end && end < ZV)
+               (check_composition = check_display = 1, SET_PT (end + 1));
+             else if (last_pt == end && PT == beg && beg > BEGV)
+               (check_composition = check_display = 1, SET_PT (beg - 1));
+             else if (PT == ((PT < last_pt) ? beg : end))
+               /* We've already moved as far as we can.  Trying to go
+                  to the other end would mean moving backwards and thus
+                  could lead to an infinite loop.  */
+               ;
+             else if (val = get_pos_property (make_number (PT),
+                                              Qinvisible, Qnil),
+                      TEXT_PROP_MEANS_INVISIBLE (val)
+                      && (val = get_pos_property
+                          (make_number (PT == beg ? end : beg),
+                           Qinvisible, Qnil),
+                          !TEXT_PROP_MEANS_INVISIBLE (val)))
+               (check_composition = check_display = 1,
+                SET_PT (PT == beg ? end : beg));
+           }
+       }
+      check_invisible = 0;
     }
 }
 
@@ -2144,6 +2214,14 @@ static void record_char ();
 static jmp_buf wrong_kboard_jmpbuf;
 #endif
 
+#define STOP_POLLING                                   \
+do { if (! polling_stopped_here) stop_polling ();      \
+       polling_stopped_here = 1; } while (0)
+
+#define RESUME_POLLING                                 \
+do { if (polling_stopped_here) start_polling ();       \
+       polling_stopped_here = 0; } while (0)
+
 /* 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.
@@ -2183,6 +2261,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
   volatile int reread;
   struct gcpro gcpro1, gcpro2;
   EMACS_TIME last_idle_start;
+  int polling_stopped_here = 0;
 
   also_record = Qnil;
 
@@ -2284,7 +2363,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
          || executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
        {
          XSETINT (c, -1);
-         RETURN_UNGCPRO (c);
+         goto exit;
        }
 
       c = Faref (Vexecuting_macro, make_number (executing_macro_index));
@@ -2516,7 +2595,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
       /* Now that we have read an event, Emacs is not idle.  */
       timer_stop_idle ();
 
-      RETURN_UNGCPRO (c);
+      goto exit;
     }
 
   /* Maybe autosave and/or garbage collect due to idleness.  */
@@ -2623,7 +2702,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
 
  wrong_kboard:
 
-  stop_polling ();
+  STOP_POLLING;
 
   /* Finally, we read from the main queue,
      and if that gives us something we can't use yet, we put it on the
@@ -2692,7 +2771,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
      should the next event read be a help-echo.  */
   last_idle_start = timer_idleness_start_time;
   timer_stop_idle ();
-  start_polling ();
+  RESUME_POLLING;
 
   if (NILP (c))
     {
@@ -2709,7 +2788,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
      so don't show them to the user.
      Also, don't record a key if we already did.  */
   if (BUFFERP (c) || key_already_recorded)
-    RETURN_UNGCPRO (c);
+    goto exit;
 
   /* Process special events within read_char
      and loop around to read another event.  */
@@ -2744,14 +2823,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
     {
       /* If kbd_buffer_get_event gave us an EOF, return that.  */
       if (XINT (c) == -1)
-       RETURN_UNGCPRO (c);
+       goto exit;
 
       if ((STRINGP (Vkeyboard_translate_table)
           && SCHARS (Vkeyboard_translate_table) > (unsigned) XFASTINT (c))
          || (VECTORP (Vkeyboard_translate_table)
              && XVECTOR (Vkeyboard_translate_table)->size > (unsigned) XFASTINT (c))
          || (CHAR_TABLE_P (Vkeyboard_translate_table)
-             && CHAR_TABLE_ORDINARY_SLOTS > (unsigned) XFASTINT (c)))
+             && CHAR_VALID_P (XINT (c), 0)))
        {
          Lisp_Object d;
          d = Faref (Vkeyboard_translate_table, c);
@@ -2986,6 +3065,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        }
     }
 
+ exit:
+  RESUME_POLLING;
   RETURN_UNGCPRO (c);
 }
 
@@ -4337,6 +4418,41 @@ static int lispy_accent_codes[] =
 #else
   0,
 #endif
+#ifdef XK_dead_abovering
+  XK_dead_abovering,
+#else
+  0,
+#endif
+#ifdef XK_dead_iota
+  XK_dead_iota,
+#else
+  0,
+#endif
+#ifdef XK_dead_belowdot
+  XK_dead_belowdot,
+#else
+  0,
+#endif
+#ifdef XK_dead_voiced_sound
+  XK_dead_voiced_sound,
+#else
+  0,
+#endif
+#ifdef XK_dead_semivoiced_sound
+  XK_dead_semivoiced_sound,
+#else
+  0,
+#endif
+#ifdef XK_dead_hook
+  XK_dead_hook,
+#else
+  0,
+#endif
+#ifdef XK_dead_horn
+  XK_dead_horn,
+#else
+  0,
+#endif
 };
 
 /* This is a list of Lisp names for special "accent" characters.
@@ -4357,6 +4473,13 @@ static char *lispy_accent_keys[] =
   "dead-caron",
   "dead-doubleacute",
   "dead-abovedot",
+  "dead-abovering",
+  "dead-iota",
+  "dead-belowdot",
+  "dead-voiced-sound",
+  "dead-semivoiced-sound",
+  "dead-hook",
+  "dead-horn",
 };
 
 #ifdef HAVE_NTGUI
@@ -4523,6 +4646,10 @@ char *lispy_function_keys[] =
 
 #else /* not HAVE_NTGUI */
 
+/* This should be dealt with in XTread_socket now, and that doesn't
+   depend on the client system having the Kana syms defined.  See also
+   the XK_kana_A case below.  */
+#if 0
 #ifdef XK_kana_A
 static char *lispy_kana_keys[] =
   {
@@ -4557,6 +4684,7 @@ static char *lispy_kana_keys[] =
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,   /* 0x4f0 .. 0x4ff */
   };
 #endif /* XK_kana_A */
+#endif /* 0 */
 
 #define FUNCTION_KEY_OFFSET 0xff00
 
@@ -4811,6 +4939,7 @@ make_lispy_event (event)
                                      (sizeof (lispy_accent_keys)
                                       / sizeof (lispy_accent_keys[0])));
 
+#if 0
 #ifdef XK_kana_A
       if (event->code >= 0x400 && event->code < 0x500)
        return modify_event_symbol (event->code - 0x400,
@@ -4820,6 +4949,7 @@ make_lispy_event (event)
                                    (sizeof (lispy_kana_keys)
                                     / sizeof (lispy_kana_keys[0])));
 #endif /* XK_kana_A */
+#endif /* 0 */
 
 #ifdef ISO_FUNCTION_KEY_OFFSET
       if (event->code < FUNCTION_KEY_OFFSET
@@ -5228,7 +5358,7 @@ make_lispy_event (event)
        /* Get the symbol we should use for the mouse click.  */
        head = modify_event_symbol (event->code,
                                    event->modifiers,
-                                   Qmouse_click, 
+                                   Qmouse_click,
                                    Vlispy_mouse_stem,
                                    NULL, &mouse_syms,
                                    XVECTOR (mouse_syms)->size);
@@ -5963,8 +6093,12 @@ modify_event_symbol (symbol_num, modifiers, symbol_kind, name_alist_or_stem,
        {
          int len = SBYTES (name_alist_or_stem);
          char *buf = (char *) alloca (len + 50);
-         sprintf (buf, "%s-%d", SDATA (name_alist_or_stem),
-                  XINT (symbol_int) + 1);
+         if (sizeof (int) == sizeof (EMACS_INT))
+           sprintf (buf, "%s-%d", SDATA (name_alist_or_stem),
+                    XINT (symbol_int) + 1);
+         else if (sizeof (long) == sizeof (EMACS_INT))
+           sprintf (buf, "%s-%ld", SDATA (name_alist_or_stem),
+                    XINT (symbol_int) + 1);
          value = intern (buf);
        }
       else if (name_table != 0 && name_table[symbol_num])
@@ -7584,7 +7718,7 @@ read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu)
      int *used_mouse_menu;
 {
   int mapno;
-  register Lisp_Object name;
+  register Lisp_Object name = Qnil;
 
   if (used_mouse_menu)
     *used_mouse_menu = 0;
@@ -7686,6 +7820,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps)
   int mapno;
   register Lisp_Object name;
   int nlength;
+  /* FIXME: Use the minibuffer's frame width.  */
   int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4;
   int idx = -1;
   int nobindings = 1;
@@ -7977,6 +8112,15 @@ follow_key (key, nmaps, current, defs, next)
   return first_binding;
 }
 
+/* Structure used to keep track of partial application of key remapping
+   such as Vfunction_key_map and Vkey_translation_map.  */
+typedef struct keyremap
+{
+  Lisp_Object map;
+  int start, end;
+} keyremap;
+
+
 /* Read a sequence of keys that ends with a non prefix character,
    storing it in KEYBUF, a buffer of size BUFSIZE.
    Prompt with PROMPT.
@@ -8064,7 +8208,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
      defs[i] is non-nil.  */
   volatile int first_binding;
   /* Index of the first key that has no binding.
-     It is useless to try fkey_start larger than that.  */
+     It is useless to try fkey.start larger than that.  */
   volatile int first_unbound;
 
   /* If t < mock_input, then KEYBUF[t] should be read as the next
@@ -8083,19 +8227,17 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   volatile int mock_input = 0;
 
   /* If the sequence is unbound in submaps[], then
-     keybuf[fkey_start..fkey_end-1] is a prefix in Vfunction_key_map,
-     and fkey_map is its binding.
+     keybuf[fkey.start..fkey.end-1] is a prefix in Vfunction_key_map,
+     and fkey.map is its binding.
 
      These might be > t, indicating that all function key scanning
      should hold off until t reaches them.  We do this when we've just
      recognized a function key, to avoid searching for the function
      key's again in Vfunction_key_map.  */
-  volatile int fkey_start = 0, fkey_end = 0;
-  volatile Lisp_Object fkey_map;
+  volatile keyremap fkey;
 
   /* Likewise, for key_translation_map.  */
-  volatile int keytran_start = 0, keytran_end = 0;
-  volatile Lisp_Object keytran_map;
+  volatile keyremap keytran;
 
   /* If we receive a ``switch-frame'' event in the middle of a key sequence,
      we put it off for later.  While we're reading, we keep the event here.  */
@@ -8129,16 +8271,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   last_nonmenu_event = Qnil;
 
   delayed_switch_frame = Qnil;
-  fkey_map = Vfunction_key_map;
-  keytran_map = Vkey_translation_map;
-
-  /* If there is no function-key-map, turn off function key scanning.  */
-  if (!KEYMAPP (Vfunction_key_map))
-    fkey_start = fkey_end = bufsize + 1;
-
-  /* If there is no key-translation-map, turn off scanning.  */
-  if (!KEYMAPP (Vkey_translation_map))
-    keytran_start = keytran_end = bufsize + 1;
+  fkey.map = Vfunction_key_map;
+  keytran.map = Vkey_translation_map;
+  /* If there is no translation-map, turn off scanning.  */
+  fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
+  keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
 
   if (INTERACTIVE)
     {
@@ -8248,15 +8385,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
   /* If the best binding for the current key sequence is a keymap, or
      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)
+  while (first_binding < nmaps
+        /* Keep reading as long as there's a prefix binding.  */
+        ? !NILP (submaps[first_binding])
         /* 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.  */
-        )
+        : (fkey.start < t || keytran.start < t))
     {
       Lisp_Object key;
       int used_mouse_menu = 0;
@@ -8275,9 +8412,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
       volatile int echo_local_start, keys_local_start, local_first_binding;
 
       /* key-translation-map is applied *after* function-key-map.  */
-      eassert (keytran_end <= fkey_start);
+      eassert (keytran.end <= fkey.start);
 
-      if (first_unbound < fkey_start && first_unbound < keytran_start)
+      if (first_unbound < fkey.start && first_unbound < keytran.start)
        { /* The prefix upto first_unbound has no binding and has
             no translation left to do either, so we know it's unbound.
             If we don't stop now, we risk staying here indefinitely
@@ -8287,10 +8424,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
          for (i = first_unbound + 1; i < t; i++)
            keybuf[i - first_unbound - 1] = keybuf[i];
          mock_input = t - first_unbound - 1;
-         fkey_end = fkey_start -= first_unbound + 1;
-         fkey_map = Vfunction_key_map;
-         keytran_end = keytran_start -= first_unbound + 1;
-         keytran_map = Vkey_translation_map;
+         fkey.end = fkey.start -= first_unbound + 1;
+         fkey.map = Vfunction_key_map;
+         keytran.end = keytran.start -= first_unbound + 1;
+         keytran.map = Vkey_translation_map;
          goto replay_sequence;
        }
 
@@ -8693,15 +8830,15 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
        /* 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,
+          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;
          
-         /* Remember the position to put an upper bound on fkey_start.  */
+         /* Remember the position to put an upper bound on fkey.start.  */
          first_unbound = min (t, first_unbound);
 
          head = EVENT_HEAD (key);
@@ -8840,214 +8977,210 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
           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);
+         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;
+         Lisp_Object next;
 
-         /* Continue scan from fkey_end until we find a bound suffix.
-            If we fail, increment fkey_start and start over from there.  */
-         while (fkey_end < t)
+         /* Continue scan from fkey.end until we find a bound suffix.
+            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);
+             key = keybuf[fkey.end++];
+             next = access_keymap (fkey.map, key, 1, 0, 1);
 
              /* Handle symbol with autoload definition.  */
-             if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
-                 && CONSP (XSYMBOL (fkey_next)->function)
-                 && EQ (XCAR (XSYMBOL (fkey_next)->function), Qautoload))
-               do_autoload (XSYMBOL (fkey_next)->function,
-                            fkey_next);
+             if (SYMBOLP (next) && ! NILP (Ffboundp (next))
+                 && CONSP (XSYMBOL (next)->function)
+                 && EQ (XCAR (XSYMBOL (next)->function), Qautoload))
+               do_autoload (XSYMBOL (next)->function, next);
 
              /* Handle a symbol whose function definition is a keymap
                 or an array.  */
-             if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next))
-                 && (!NILP (Farrayp (XSYMBOL (fkey_next)->function))
-                     || KEYMAPP (XSYMBOL (fkey_next)->function)))
-               fkey_next = XSYMBOL (fkey_next)->function;
+             if (SYMBOLP (next) && ! NILP (Ffboundp (next))
+                 && (!NILP (Farrayp (XSYMBOL (next)->function))
+                     || KEYMAPP (XSYMBOL (next)->function)))
+               next = XSYMBOL (next)->function;
 
 #if 0 /* I didn't turn this on, because it might cause trouble
         for the mapping of return into C-m and tab into C-i.  */
              /* Optionally don't map function keys into other things.
                 This enables the user to redefine kp- keys easily.  */
              if (SYMBOLP (key) && !NILP (Vinhibit_function_key_mapping))
-               fkey_next = Qnil;
+               next = Qnil;
 #endif
 
              /* 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))
+             if (SYMBOLP (next) && ! NILP (Ffboundp (next))
                  /* 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)
+                 && fkey.end == t && first_binding >= nmaps)
                {
                  struct gcpro gcpro1, gcpro2, gcpro3;
                  Lisp_Object tem;
-                 tem = fkey_next;
+                 tem = next;
 
-                 GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
-                 fkey_next = call1 (fkey_next, prompt);
+                 GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+                 next = call1 (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)))
+                 if (! (VECTORP (next) || STRINGP (next)))
                    error ("Function in key-translation-map returns invalid key sequence");
                }
 
-             /* If keybuf[fkey_start..fkey_end] is bound in the
+             /* 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))
+                sequence (i.e. fkey.end == t), replace it with
+                the binding and restart with fkey.start at the end. */
+             if ((VECTORP (next) || STRINGP (next))
                  /* 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)
+                 && fkey.end == t && first_binding >= nmaps)
                {
-                 int len = XFASTINT (Flength (fkey_next));
+                 int len = XFASTINT (Flength (next));
 
-                 t = fkey_start + len;
+                 t = fkey.start + len;
                  if (t >= bufsize)
                    error ("Key sequence too long");
 
-                 if (VECTORP (fkey_next))
-                   bcopy (XVECTOR (fkey_next)->contents,
-                          keybuf + fkey_start,
-                          (t - fkey_start) * sizeof (keybuf[0]));
-                 else if (STRINGP (fkey_next))
+                 if (VECTORP (next))
+                   bcopy (XVECTOR (next)->contents,
+                          keybuf + fkey.start,
+                          (t - fkey.start) * sizeof (keybuf[0]));
+                 else if (STRINGP (next))
                    {
                      int i;
 
                      for (i = 0; i < len; i++)
-                       XSETFASTINT (keybuf[fkey_start + i],
-                                    SREF (fkey_next, i));
+                       XSETFASTINT (keybuf[fkey.start + i], SREF (next, i));
                    }
 
                  mock_input = t;
-                 fkey_start = fkey_end = t;
-                 fkey_map = Vfunction_key_map;
+                 fkey.start = fkey.end = t;
+                 fkey.map = Vfunction_key_map;
 
                  /* Do pass the results through key-translation-map.
                     But don't retranslate what key-translation-map
                     has already translated.  */
-                 keytran_end = keytran_start;
-                 keytran_map = Vkey_translation_map;
+                 keytran.end = keytran.start;
+                 keytran.map = Vkey_translation_map;
 
                  goto replay_sequence;
                }
 
-             fkey_map = get_keymap (fkey_next, 0, 1);
+             fkey.map = get_keymap (next, 0, 1);
 
              /* If we no longer have a bound suffix, try a new positions for
-                fkey_start.  */
-             if (!CONSP (fkey_map))
+                fkey.start.  */
+             if (!CONSP (fkey.map))
                {
-                 fkey_end = ++fkey_start;
-                 fkey_map = Vfunction_key_map;
+                 fkey.end = ++fkey.start;
+                 fkey.map = Vfunction_key_map;
                }
            }
        }
 
       /* Look for this sequence in key-translation-map.  */
       {
-       Lisp_Object keytran_next;
+       Lisp_Object next;
 
-       /* Scan from keytran_end until we find a bound suffix.  */
-       while (keytran_end < fkey_start)
+       /* Scan from keytran.end until we find a bound suffix.  */
+       while (keytran.end < fkey.start)
          {
            Lisp_Object key;
 
-           key = keybuf[keytran_end++];
-           keytran_next
-             = access_keymap (keytran_map, key, 1, 0, 1);
+           key = keybuf[keytran.end++];
+           next = access_keymap (keytran.map, key, 1, 0, 1);
 
            /* Handle symbol with autoload definition.  */
-           if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
-               && CONSP (XSYMBOL (keytran_next)->function)
-               && EQ (XCAR (XSYMBOL (keytran_next)->function), Qautoload))
-             do_autoload (XSYMBOL (keytran_next)->function,
-                          keytran_next);
+           if (SYMBOLP (next) && ! NILP (Ffboundp (next))
+               && CONSP (XSYMBOL (next)->function)
+               && EQ (XCAR (XSYMBOL (next)->function), Qautoload))
+             do_autoload (XSYMBOL (next)->function, next);
 
            /* Handle a symbol whose function definition is a keymap
               or an array.  */
-           if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next))
-               && (!NILP (Farrayp (XSYMBOL (keytran_next)->function))
-                   || KEYMAPP (XSYMBOL (keytran_next)->function)))
-             keytran_next = XSYMBOL (keytran_next)->function;
+           if (SYMBOLP (next) && ! NILP (Ffboundp (next))
+               && (!NILP (Farrayp (XSYMBOL (next)->function))
+                   || KEYMAPP (XSYMBOL (next)->function)))
+             next = XSYMBOL (next)->function;
            
            /* If the key translation map gives a function, not an
               array, then call the function with one arg and use
               its value instead.  */
-           if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next)))
+           if (SYMBOLP (next) && ! NILP (Ffboundp (next)))
              {
                struct gcpro gcpro1, gcpro2, gcpro3;
                Lisp_Object tem;
-               tem = keytran_next;
+               tem = next;
 
-               GCPRO3 (fkey_map, keytran_map, delayed_switch_frame);
-               keytran_next = call1 (keytran_next, prompt);
+               GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
+               next = call1 (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)))
+               if (! (VECTORP (next) || STRINGP (next)))
                  error ("Function in key-translation-map returns invalid key sequence");
              }
 
-           /* If keybuf[keytran_start..keytran_end] is bound in the
+           /* 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
-              the binding and restart with keytran_start at the end. */
-           if ((VECTORP (keytran_next) || STRINGP (keytran_next)))
+              sequence (i.e. keytran.end == t), replace it with
+              the binding and restart with keytran.start at the end. */
+           if ((VECTORP (next) || STRINGP (next)))
              {
-               int len = XFASTINT (Flength (keytran_next));
-               int i, diff = len - (keytran_end - keytran_start);
+               int len = XFASTINT (Flength (next));
+               int i, diff = len - (keytran.end - keytran.start);
 
                mock_input = max (t, mock_input);
                if (mock_input + diff >= bufsize)
                  error ("Key sequence too long");
 
-               /* Shift the keys that are after keytran_end.  */
+               /* Shift the keys that are after keytran.end.  */
                if (diff < 0)
-                 for (i = keytran_end; i < mock_input; i++)
+                 for (i = keytran.end; i < mock_input; i++)
                    keybuf[i + diff] = keybuf[i];
                else if (diff > 0)
-                 for (i = mock_input - 1; i >= keytran_end; i--)
+                 for (i = mock_input - 1; i >= keytran.end; i--)
                    keybuf[i + diff] = keybuf[i];
-               /* Replace the keys between keytran_start and keytran_end
-                  with those from keytran_next.  */
+               /* Replace the keys between keytran.start and keytran.end
+                  with those from next.  */
                for (i = 0; i < len; i++)
-                 keybuf[keytran_start + i]
-                   = Faref (keytran_next, make_number (i));
+                 keybuf[keytran.start + i]
+                   = Faref (next, make_number (i));
 
                mock_input += diff;
-               keytran_start = keytran_end += diff;
-               keytran_map = Vkey_translation_map;
+               keytran.start = keytran.end += diff;
+               keytran.map = Vkey_translation_map;
 
                /* Adjust the function-key-map counters.  */
-               fkey_start += diff;
-               fkey_end += diff;
+               fkey.start += diff;
+               fkey.end += diff;
 
                goto replay_sequence;
              }
 
-           keytran_map = get_keymap (keytran_next, 0, 1);
+           keytran.map = get_keymap (next, 0, 1);
 
            /* If we no longer have a bound suffix, try a new positions for
-              keytran_start.  */
-           if (!CONSP (keytran_map))
+              keytran.start.  */
+           if (!CONSP (keytran.map))
              {
-               keytran_end = ++keytran_start;
-               keytran_map = Vkey_translation_map;
+               keytran.end = ++keytran.start;
+               keytran.map = Vkey_translation_map;
              }
          }
       }
@@ -9057,7 +9190,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is an upper case letter
         use the corresponding lower-case letter instead.  */
       if (first_binding >= nmaps
-         && fkey_start >= t && keytran_start >= t
+         && fkey.start >= t && keytran.start >= t
          && INTEGERP (key)
          && ((((XINT (key) & 0x3ffff)
                < XCHAR_TABLE (current_buffer->downcase_table)->size)
@@ -9088,7 +9221,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
         and is a shifted function key,
         use the corresponding unshifted function key instead.  */
       if (first_binding >= nmaps
-         && fkey_start >= t && keytran_start >= t
+         && fkey.start >= t && keytran.start >= t
          && SYMBOLP (key))
        {
          Lisp_Object breakdown;
@@ -9537,7 +9670,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
          int message_p = push_message ();
          int count = SPECPDL_INDEX ();
 
-         record_unwind_protect (push_message_unwind, Qnil);
+         record_unwind_protect (pop_message_unwind, Qnil);
          binding = Fkey_description (bindings);
 
          newmessage
@@ -9949,7 +10082,7 @@ clear_waiting_for_input ()
    eval to throw, when it gets a chance.  If quit-flag is already
    non-nil, it stops the job right away.  */
 
-SIGTYPE
+static SIGTYPE
 interrupt_signal (signalnum)   /* If we don't have an argument, */
      int signalnum;            /* some compilers complain in signal calls. */
 {
@@ -10818,7 +10951,10 @@ Each character is looked up in this string and the contents used instead.
 The value may be a string, a vector, or a char-table.
 If it is a string or vector of length N,
 character codes N and up are untranslated.
-In a vector or a char-table, an element which is nil means "no translation".  */);
+In a vector or a char-table, an element which is nil means "no translation".
+
+This is applied to the characters supplied to input methods, not their
+output.  See also `translation-table-for-input'.  */);
   Vkeyboard_translate_table = Qnil;
 
   DEFVAR_BOOL ("cannot-suspend", &cannot_suspend,