]> code.delx.au - gnu-emacs/blobdiff - src/keyboard.c
Remove obsolete USE_OLIT code.
[gnu-emacs] / src / keyboard.c
index 4866c9d636bda1d9333ebf2fce7efb33b4bc0753..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.  */
@@ -550,8 +550,10 @@ Lisp_Object Qhelp_echo;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 Lisp_Object Qmouse_wheel;
+#endif
+#ifdef WINDOWSNT
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
@@ -596,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 ();
 
@@ -644,7 +646,7 @@ int flow_control;
 
 /* If we support a window system, turn on the code to poll periodically
    to detect C-g.  It isn't actually used when doing interrupt input.  */
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined(HAVE_WINDOW_SYSTEM) && !defined(USE_ASYNC_EVENTS)
 #define POLL_FOR_INPUT
 #endif
 
@@ -748,8 +750,8 @@ echo_char (c)
        }
       else if (SYMBOLP (c))
        {
-         struct Lisp_String *name = XSTRING (SYMBOL_NAME (c));
-         int nbytes = STRING_BYTES (name);
+         Lisp_Object name = SYMBOL_NAME (c);
+         int nbytes = SBYTES (name);
          
          if (size - (ptr - buffer) < nbytes)
            {
@@ -759,8 +761,8 @@ echo_char (c)
              ptr = buffer + offset;
            }
 
-         ptr += copy_text (name->data, ptr, nbytes,
-                           name->size_byte >= 0, 1);
+         ptr += copy_text (SDATA (name), ptr, nbytes,
+                           STRING_MULTIBYTE (name), 1);
        }
 
       if ((NILP (echo_string) || SCHARS (echo_string) == 0)
@@ -1202,24 +1204,19 @@ cmd_error_internal (data, context)
   else
     {
       Fdiscard_input ();
+      message_log_maybe_newline ();
       bitch_at_user ();
       stream = Qt;
-
-      /* If we know from where the error was signaled, show it in
-        *Messages*.  */
-      if (!NILP (Vsignaling_function) && SYMBOLP (Vsignaling_function))
-       {
-         char *name = SDATA (SYMBOL_NAME (Vsignaling_function));
-         message_dolog (name, strlen (name), 0, 0);
-         message_dolog (": ", 2, 0, 0);
-         Vsignaling_function = Qnil;
-       }
     }
 
-  if (context != 0)
-    write_string_1 (context, -1, stream);
+  /* The immediate context is not interesting for Quits,
+     since they are asyncronous.  */
+  if (EQ (XCAR (data), Qquit))
+    Vsignaling_function = Qnil;
+  
+  print_error_message (data, stream, context, Vsignaling_function);
 
-  print_error_message (data, stream);
+  Vsignaling_function = Qnil;
 
   /* If the window system or terminal frame hasn't been initialized
      yet, or we're in -batch mode, this error should cause Emacs to exit.  */
@@ -1632,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))
@@ -1788,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;
     }
 }
 
@@ -2147,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.
@@ -2186,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;
 
@@ -2287,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));
@@ -2519,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.  */
@@ -2626,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
@@ -2695,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))
     {
@@ -2712,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.  */
@@ -2747,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);
@@ -2989,6 +3065,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
        }
     }
 
+ exit:
+  RESUME_POLLING;
   RETURN_UNGCPRO (c);
 }
 
@@ -3886,7 +3964,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
            {
              obj = make_lispy_event (event);
              
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS)
              /* If this was a menu selection, then set the flag to inhibit
                 writing to last_nonmenu_event.  Don't do this if the event
                 we're returning is (menu-bar), though; that indicates the
@@ -4265,7 +4343,7 @@ timer_check (do_it_now)
 static Lisp_Object accent_key_syms;
 static Lisp_Object func_key_syms;
 static Lisp_Object mouse_syms;
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 static Lisp_Object mouse_wheel_syms;
 #endif
 static Lisp_Object drag_n_drop_syms;
@@ -4340,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.
@@ -4360,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
@@ -4526,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[] =
   {
@@ -4560,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
 
@@ -4674,7 +4799,7 @@ static char *iso_lispy_function_keys[] =
 
 Lisp_Object Vlispy_mouse_stem;
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 /* mouse-wheel events are generated by the wheel on devices such as
    the MS Intellimouse.  The wheel sits in between the left and right
    mouse buttons, and is typically used to scroll or zoom the window
@@ -4814,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,
@@ -4823,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
@@ -5190,7 +5317,7 @@ make_lispy_event (event)
        }
       }
 
-#if USE_TOOLKIT_SCROLL_BARS
+#ifdef USE_TOOLKIT_SCROLL_BARS
 
       /* We don't have down and up events if using toolkit scroll bars,
         so make this always a click event.  Store in the `part' of
@@ -5226,11 +5353,12 @@ make_lispy_event (event)
 
        /* Always treat scroll bar events as clicks. */
        event->modifiers |= click_modifier;
+       event->modifiers &= ~up_modifier;
 
        /* 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);
@@ -5283,6 +5411,8 @@ make_lispy_event (event)
                               Qnil));
        }
       }
+#endif /* WINDOWSNT */
+#if defined(WINDOWSNT) || defined(MAC_OSX)
     case MOUSE_WHEEL_EVENT:
       {
        int part;
@@ -5354,7 +5484,7 @@ make_lispy_event (event)
                                             Qnil))));
        }
       }
-#endif /* WINDOWSNT */
+#endif /* WINDOWSNT || MAC_OSX */
 
     case DRAG_N_DROP_EVENT:
       {
@@ -5583,16 +5713,16 @@ parse_modifiers_uncached (symbol, modifier_end)
      Lisp_Object symbol;
      int *modifier_end;
 {
-  struct Lisp_String *name;
+  Lisp_Object name;
   int i;
   int modifiers;
 
   CHECK_SYMBOL (symbol);
 
   modifiers = 0;
-  name = XSTRING (SYMBOL_NAME (symbol));
+  name = SYMBOL_NAME (symbol);
 
-  for (i = 0; i+2 <= STRING_BYTES (name); )
+  for (i = 0; i+2 <= SBYTES (name); )
     {
       int this_mod_end = 0;
       int this_mod = 0;
@@ -5601,7 +5731,7 @@ parse_modifiers_uncached (symbol, modifier_end)
         Check that the word appears, but don't check what follows it.
         Set this_mod and this_mod_end to record what we find.  */
 
-      switch (name->data[i])
+      switch (SREF (name, i))
        {
 #define SINGLE_LETTER_MOD(BIT)                         \
          (this_mod_end = i + 1, this_mod = BIT)
@@ -5639,8 +5769,8 @@ parse_modifiers_uncached (symbol, modifier_end)
 
       /* Check there is a dash after the modifier, so that it
         really is a modifier.  */
-      if (this_mod_end >= STRING_BYTES (name)
-         || name->data[this_mod_end] != '-')
+      if (this_mod_end >= SBYTES (name)
+         || SREF (name, this_mod_end) != '-')
        break;
 
       /* This modifier is real; look for another.  */
@@ -5651,9 +5781,9 @@ parse_modifiers_uncached (symbol, modifier_end)
   /* Should we include the `click' modifier?  */
   if (! (modifiers & (down_modifier | drag_modifier
                      | double_modifier | triple_modifier))
-      && i + 7 == STRING_BYTES (name)
-      && strncmp (name->data + i, "mouse-", 6) == 0
-      && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9'))
+      && i + 7 == SBYTES (name)
+      && strncmp (SDATA (name) + i, "mouse-", 6) == 0
+      && ('0' <= SREF (name, i + 6) && SREF (name, i + 6) <= '9'))
     modifiers |= click_modifier;
 
   if (modifier_end)
@@ -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])
@@ -6080,17 +6214,17 @@ static int
 parse_solitary_modifier (symbol)
      Lisp_Object symbol;
 {
-  struct Lisp_String *name = XSTRING (SYMBOL_NAME (symbol));
+  Lisp_Object name = SYMBOL_NAME (symbol);
 
-  switch (name->data[0])
+  switch (SREF (name, 0))
     {
 #define SINGLE_LETTER_MOD(BIT)                         \
-      if (STRING_BYTES (name) == 1)                    \
+      if (SBYTES (name) == 1)                          \
        return BIT;
 
 #define MULTI_LETTER_MOD(BIT, NAME, LEN)               \
-      if (LEN == STRING_BYTES (name)                   \
-         && ! strncmp (name->data, NAME, LEN))         \
+      if (LEN == SBYTES (name)                         \
+         && ! strncmp (SDATA (name), NAME, LEN))       \
        return BIT;
 
     case 'A':
@@ -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;
        }
 
@@ -8586,7 +8723,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last,
                  /* Record that a fake prefix key has been generated
                     for KEY.  Don't modify the event; this would
                     prevent proper action when the event is pushed
-                    back tino unread-command-events.  */
+                    back into unread-command-events.  */
                  fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
 
                  /* If on a mode line string with a local keymap,
@@ -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;
@@ -9388,7 +9521,7 @@ a special event, so ignore the prefix argument and don't clear it.  */)
            }
        }
 
-      return Fexecute_kbd_macro (final, prefixarg);
+      return Fexecute_kbd_macro (final, prefixarg, Qnil);
     }
 
   if (CONSP (final) || SUBRP (final) || COMPILEDP (final))
@@ -9473,7 +9606,6 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
   /* Set this_command_keys to the concatenation of saved_keys and
      function, followed by a RET.  */
   {
-    struct Lisp_String *str;
     Lisp_Object *keys;
     int i;
 
@@ -9484,8 +9616,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_
     for (i = 0; i < XVECTOR (saved_keys)->size; i++)
       add_command_key (keys[i]);
 
-    str = XSTRING (function);
-    for (i = 0; i < str->size; i++)
+    for (i = 0; i < SCHARS (function); i++)
       add_command_key (Faref (function, make_number (i)));
 
     add_command_key (make_number ('\015'));
@@ -9539,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
@@ -9734,19 +9865,24 @@ appears in the echo area and in the value of `this-command-keys'.  */)
 }
 
 DEFUN ("clear-this-command-keys", Fclear_this_command_keys,
-       Sclear_this_command_keys, 0, 0, 0,
+       Sclear_this_command_keys, 0, 1, 0,
        doc: /* Clear out the vector that `this-command-keys' returns.
-Also clear the record of the last 100 events.  */)
-     ()
+Also clear the record of the last 100 events, unless optional arg
+KEEP-RECORD is non-nil.  */)
+     (keep_record)
+     Lisp_Object keep_record;
 {
   int i;
   
   this_command_key_count = 0;
 
-  for (i = 0; i < XVECTOR (recent_keys)->size; ++i)
-    XVECTOR (recent_keys)->contents[i] = Qnil;
-  total_keys = 0;
-  recent_keys_index = 0;
+  if (NILP (keep_record))
+    {
+      for (i = 0; i < XVECTOR (recent_keys)->size; ++i)
+       XVECTOR (recent_keys)->contents[i] = Qnil;
+      total_keys = 0;
+      recent_keys_index = 0;
+    }
   return Qnil;
 }
 
@@ -9783,10 +9919,16 @@ If FILE is nil, close any open dribble file.  */)
 
 DEFUN ("discard-input", Fdiscard_input, Sdiscard_input, 0, 0, 0,
        doc: /* Discard the contents of the terminal input buffer.
-Also cancel any kbd macro being defined.  */)
+Also end any kbd macro being defined.  */)
      ()
 {
-  current_kboard->defining_kbd_macro = Qnil;
+  if (!NILP (current_kboard->defining_kbd_macro))
+    {
+      /* Discard the last command from the macro.  */
+      Fcancel_kbd_macro_events ();
+      end_kbd_macro ();
+    }
+
   update_mode_lines++;
 
   Vunread_command_events = Qnil;
@@ -9940,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. */
 {
@@ -10439,9 +10581,11 @@ syms_of_keyboard ()
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   Qmouse_wheel = intern ("mouse-wheel");
   staticpro (&Qmouse_wheel);
+#endif
+#ifdef WINDOWSNT
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
 #endif
@@ -10589,10 +10733,9 @@ syms_of_keyboard ()
   func_key_syms = Qnil;
   staticpro (&func_key_syms);
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   mouse_wheel_syms = Qnil;
   staticpro (&mouse_wheel_syms);
-  
   drag_n_drop_syms = Qnil;
   staticpro (&drag_n_drop_syms);
 #endif
@@ -10808,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,