update.
[chise/xemacs-chise.git.1] / src / keymap.c
index 430acdc..3752f0f 100644 (file)
@@ -37,17 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "insdel.h"
 #include "keymap.h"
 #include "window.h"
-
-#ifdef WINDOWSNT
-/* Hmm, under unix we want X modifiers, under NT we want X modifiers if
-   we are running X and Windows modifiers otherwise.
-   gak. This is a kludge until we support multiple native GUIs!
-*/
-#undef MOD_ALT
-#undef MOD_CONTROL
-#undef MOD_SHIFT
-#endif
-
 #include "events-mod.h"
 
 \f
@@ -99,25 +88,25 @@ Boston, MA 02111-1307, USA.  */
 
    If the key `C-a' was bound to some command, the hierarchy would look like
 
-      keymap-1: associates the integer MOD_CONTROL with keymap-2
+      keymap-1: associates the integer XEMACS_MOD_CONTROL with keymap-2
       keymap-2: associates "a" with the command
 
    Similarly, if the key `C-H-a' was bound to some command, the hierarchy
    would look like
 
-      keymap-1: associates the integer (MOD_CONTROL | MOD_HYPER)
+      keymap-1: associates the integer (XEMACS_MOD_CONTROL | XEMACS_MOD_HYPER)
                 with keymap-2
       keymap-2: associates "a" with the command
 
    Note that a special exception is made for the meta modifier, in order
    to deal with ESC/meta lossage.  Any key combination containing the
    meta modifier is first indexed off of the main map into the meta
-   submap (with hash key MOD_META) and then indexed off of the
+   submap (with hash key XEMACS_MOD_META) and then indexed off of the
    meta submap with the meta modifier removed from the key combination.
    For example, when associating a command with C-M-H-a, we'd have
 
-      keymap-1: associates the integer MOD_META with keymap-2
-      keymap-2: associates the integer (MOD_CONTROL | MOD_HYPER)
+      keymap-1: associates the integer XEMACS_MOD_META with keymap-2
+      keymap-2: associates the integer (XEMACS_MOD_CONTROL | XEMACS_MOD_HYPER)
                 with keymap-3
       keymap-3: associates "a" with the command
 
@@ -131,7 +120,7 @@ Boston, MA 02111-1307, USA.  */
    Note that this new model of keymaps takes much of the magic away from
    the Escape key: the value of the variable `esc-map' is no longer indexed
    in the `global-map' under the ESC key.  It's indexed under the integer
-   MOD_META.  This is not user-visible, however; none of the "bucky"
+   XEMACS_MOD_META.  This is not user-visible, however; none of the "bucky"
    maps are.
 
    There is a hack in Flookup_key() that makes (lookup-key global-map "\^[")
@@ -141,7 +130,7 @@ Boston, MA 02111-1307, USA.  */
    Since keymaps are opaque, the only way to extract information from them
    is with the functions lookup-key, key-binding, local-key-binding, and
    global-key-binding, which work just as before, and the new function
-   map-keymap, which is roughly analagous to maphash.
+   map-keymap, which is roughly analogous to maphash.
 
    Note that map-keymap perpetuates the illusion that the "bucky" submaps
    don't exist: if you map over a keymap with bucky submaps, it will also
@@ -156,33 +145,25 @@ Boston, MA 02111-1307, USA.  */
 
  */
 
-typedef struct Lisp_Keymap
+struct Lisp_Keymap
 {
   struct lcrecord_header header;
-  Lisp_Object parents;         /* Keymaps to be searched after this one
-                                *  An ordered list */
+  Lisp_Object parents;         /* Keymaps to be searched after this one.
+                                  An ordered list */
   Lisp_Object prompt;           /* Qnil or a string to print in the minibuffer
-                                 *  when reading from this keymap */
-
+                                   when reading from this keymap */
   Lisp_Object table;           /* The contents of this keymap */
   Lisp_Object inverse_table;   /* The inverse mapping of the above */
-
   Lisp_Object default_binding;  /* Use this if no other binding is found
-                                 *  (this overrides parent maps and the
-                                 *   normal global-map lookup). */
-
-
+                                   (this overrides parent maps and the
+                                   normal global-map lookup). */
   Lisp_Object sub_maps_cache;  /* Cache of directly inferior keymaps;
                                   This holds an alist, of the key and the
                                   maps, or the modifier bit and the map.
                                   If this is the symbol t, then the cache
-                                  needs to be recomputed.
-                                */
-  int fullness;                        /* How many entries there are in this table.
-                                  This should be the same as the fullness
-                                  of the `table', but hash.c is broken. */
+                                  needs to be recomputed. */
   Lisp_Object name;             /* Just for debugging convenience */
-} Lisp_Keymap;
+};
 
 #define MAKE_MODIFIER_HASH_KEY(modifier) make_int (modifier)
 #define MODIFIER_HASH_KEY_BITS(x) (INTP (x) ? XINT (x) : 0)
@@ -191,7 +172,7 @@ typedef struct Lisp_Keymap
 
 /* Actually allocate storage for these variables */
 
-static Lisp_Object Vcurrent_global_map; /* Always a keymap */
+Lisp_Object Vcurrent_global_map; /* Always a keymap */
 
 static Lisp_Object Vmouse_grabbed_buffer;
 
@@ -208,7 +189,7 @@ static Lisp_Object Vvertical_divider_map;
    so that things which care (such as the menubar code) can recompute
    privately-cached data when the user has changed keybindings.
  */
-int keymap_tick;
+Fixnum keymap_tick;
 
 /* Prefixing a key with this character is the same as sending a meta bit. */
 Lisp_Object Vmeta_prefix_char;
@@ -230,6 +211,7 @@ static void describe_map (Lisp_Object keymap, Lisp_Object elt_prefix,
                          Lisp_Object shadow,
                          int mice_only_p,
                          Lisp_Object buffer);
+static Lisp_Object keymap_submaps (Lisp_Object keymap);
 
 Lisp_Object Qcontrol, Qctrl, Qmeta, Qsuper, Qhyper, Qalt, Qshift;
 Lisp_Object Qbutton0, Qbutton1, Qbutton2, Qbutton3;
@@ -239,9 +221,13 @@ Lisp_Object Qbutton4up, Qbutton5up, Qbutton6up, Qbutton7up;
 
 Lisp_Object Qmenu_selection;
 /* Emacs compatibility */
-Lisp_Object Qdown_mouse_1, Qdown_mouse_2, Qdown_mouse_3, Qdown_mouse_4,
-  Qdown_mouse_5;
-Lisp_Object Qmouse_1, Qmouse_2, Qmouse_3, Qmouse_4, Qmouse_5;
+Lisp_Object Qdown_mouse_1, Qmouse_1;
+Lisp_Object Qdown_mouse_2, Qmouse_2;
+Lisp_Object Qdown_mouse_3, Qmouse_3;
+Lisp_Object Qdown_mouse_4, Qmouse_4;
+Lisp_Object Qdown_mouse_5, Qmouse_5;
+Lisp_Object Qdown_mouse_6, Qmouse_6;
+Lisp_Object Qdown_mouse_7, Qmouse_7;
 
 /* Kludge kludge kludge */
 Lisp_Object QLFD, QTAB, QRET, QESC, QDEL, QSPC, QBS;
@@ -252,15 +238,15 @@ Lisp_Object QLFD, QTAB, QRET, QESC, QDEL, QSPC, QBS;
 /************************************************************************/
 
 static Lisp_Object
-mark_keymap (Lisp_Object obj, void (*markobj) (Lisp_Object))
+mark_keymap (Lisp_Object obj)
 {
   Lisp_Keymap *keymap = XKEYMAP (obj);
-  markobj (keymap->parents);
-  markobj (keymap->prompt);
-  markobj (keymap->inverse_table);
-  markobj (keymap->sub_maps_cache);
-  markobj (keymap->default_binding);
-  markobj (keymap->name);
+  mark_object (keymap->parents);
+  mark_object (keymap->prompt);
+  mark_object (keymap->inverse_table);
+  mark_object (keymap->sub_maps_cache);
+  mark_object (keymap->default_binding);
+  mark_object (keymap->name);
   return keymap->table;
 }
 
@@ -270,24 +256,27 @@ print_keymap (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
   /* This function can GC */
   Lisp_Keymap *keymap = XKEYMAP (obj);
   char buf[200];
-  int size = XINT (Fkeymap_fullness (obj));
   if (print_readably)
     error ("printing unreadable object #<keymap 0x%x>", keymap->header.uid);
   write_c_string ("#<keymap ", printcharfun);
   if (!NILP (keymap->name))
-    print_internal (keymap->name, printcharfun, 1);
-  /* #### Yuck!  This is no way to form plural!  --hniksic */
-  sprintf (buf, "%s%d entr%s 0x%x>",
-           ((NILP (keymap->name)) ? "" : " "),
-           size,
-           ((size == 1) ? "y" : "ies"),
-           keymap->header.uid);
+    {
+      print_internal (keymap->name, printcharfun, 1);
+      write_c_string (" ", printcharfun);
+    }
+  sprintf (buf, "size %ld 0x%x>",
+          (long) XINT (Fkeymap_fullness (obj)), keymap->header.uid);
   write_c_string (buf, printcharfun);
 }
 
 static const struct lrecord_description keymap_description[] = {
-  { XD_LISP_OBJECT, offsetof(Lisp_Keymap, parents), 6 },
-  { XD_LISP_OBJECT, offsetof(Lisp_Keymap, name), 1 },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, parents) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, prompt) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, table) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, inverse_table) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, default_binding) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, sub_maps_cache) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Keymap, name) },
   { XD_END }
 };
 
@@ -319,19 +308,19 @@ traverse_keymaps (Lisp_Object start_keymap, Lisp_Object start_parents,
   start_keymap = get_keymap (start_keymap, 1, 1);
   keymap = start_keymap;
   /* Hack special-case parents at top-level */
-  tail = ((!NILP (tail)) ? tail : XKEYMAP (keymap)->parents);
+  tail = !NILP (tail) ? tail : XKEYMAP (keymap)->parents;
 
   for (;;)
     {
       Lisp_Object result;
 
       QUIT;
-      result = ((mapper) (keymap, mapper_arg));
+      result = mapper (keymap, mapper_arg);
       if (!NILP (result))
        {
          while (CONSP (malloc_bites))
            {
-             struct Lisp_Cons *victim = XCONS (malloc_bites);
+             Lisp_Cons *victim = XCONS (malloc_bites);
              malloc_bites = victim->cdr;
              free_cons (victim);
            }
@@ -348,7 +337,7 @@ traverse_keymaps (Lisp_Object start_keymap, Lisp_Object start_parents,
          stack_depth--;
          if (CONSP (malloc_bites))
            {
-             struct Lisp_Cons *victim = XCONS (malloc_bites);
+             Lisp_Cons *victim = XCONS (malloc_bites);
              tail = victim->car;
              malloc_bites = victim->cdr;
              free_cons (victim);
@@ -410,40 +399,40 @@ traverse_keymaps (Lisp_Object start_keymap, Lisp_Object start_parents,
 /*                     Some low-level functions                         */
 /************************************************************************/
 
-static unsigned int
+static int
 bucky_sym_to_bucky_bit (Lisp_Object sym)
 {
-  if (EQ (sym, Qcontrol)) return MOD_CONTROL;
-  if (EQ (sym, Qmeta))    return MOD_META;
-  if (EQ (sym, Qsuper))   return MOD_SUPER;
-  if (EQ (sym, Qhyper))   return MOD_HYPER;
-  if (EQ (sym, Qalt))     return MOD_ALT;
-  if (EQ (sym, Qsymbol))  return MOD_ALT; /* #### - reverse compat */
-  if (EQ (sym, Qshift))   return MOD_SHIFT;
+  if (EQ (sym, Qcontrol)) return XEMACS_MOD_CONTROL;
+  if (EQ (sym, Qmeta))    return XEMACS_MOD_META;
+  if (EQ (sym, Qsuper))   return XEMACS_MOD_SUPER;
+  if (EQ (sym, Qhyper))   return XEMACS_MOD_HYPER;
+  if (EQ (sym, Qalt))     return XEMACS_MOD_ALT;
+  if (EQ (sym, Qsymbol))  return XEMACS_MOD_ALT; /* #### - reverse compat */
+  if (EQ (sym, Qshift))   return XEMACS_MOD_SHIFT;
 
   return 0;
 }
 
 static Lisp_Object
-control_meta_superify (Lisp_Object frob, unsigned int modifiers)
+control_meta_superify (Lisp_Object frob, int modifiers)
 {
   if (modifiers == 0)
     return frob;
   frob = Fcons (frob, Qnil);
-  if (modifiers & MOD_SHIFT)   frob = Fcons (Qshift,   frob);
-  if (modifiers & MOD_ALT)     frob = Fcons (Qalt,     frob);
-  if (modifiers & MOD_HYPER)   frob = Fcons (Qhyper,   frob);
-  if (modifiers & MOD_SUPER)   frob = Fcons (Qsuper,   frob);
-  if (modifiers & MOD_CONTROL) frob = Fcons (Qcontrol, frob);
-  if (modifiers & MOD_META)    frob = Fcons (Qmeta,    frob);
+  if (modifiers & XEMACS_MOD_SHIFT)   frob = Fcons (Qshift,   frob);
+  if (modifiers & XEMACS_MOD_ALT)     frob = Fcons (Qalt,     frob);
+  if (modifiers & XEMACS_MOD_HYPER)   frob = Fcons (Qhyper,   frob);
+  if (modifiers & XEMACS_MOD_SUPER)   frob = Fcons (Qsuper,   frob);
+  if (modifiers & XEMACS_MOD_CONTROL) frob = Fcons (Qcontrol, frob);
+  if (modifiers & XEMACS_MOD_META)    frob = Fcons (Qmeta,    frob);
   return frob;
 }
 
 static Lisp_Object
-make_key_description (CONST struct key_data *key, int prettify)
+make_key_description (const struct key_data *key, int prettify)
 {
   Lisp_Object keysym = key->keysym;
-  unsigned int modifiers = key->modifiers;
+  int modifiers = key->modifiers;
 
   if (prettify && CHARP (keysym))
     {
@@ -468,19 +457,22 @@ make_key_description (CONST struct key_data *key, int prettify)
 
 static Lisp_Object
 raw_lookup_key (Lisp_Object keymap,
-                CONST struct key_data *raw_keys, int raw_keys_count,
+                const struct key_data *raw_keys, int raw_keys_count,
                 int keys_so_far, int accept_default);
 
 /* Relies on caller to gc-protect args */
 static Lisp_Object
 keymap_lookup_directly (Lisp_Object keymap,
-                        Lisp_Object keysym, unsigned int modifiers)
+                        Lisp_Object keysym, int modifiers)
 {
   Lisp_Keymap *k;
 
-  if ((modifiers & ~(MOD_CONTROL | MOD_META | MOD_SUPER | MOD_HYPER
-                     | MOD_ALT | MOD_SHIFT)) != 0)
-    abort ();
+  modifiers &= ~(XEMACS_MOD_BUTTON1 | XEMACS_MOD_BUTTON2 | XEMACS_MOD_BUTTON3
+                | XEMACS_MOD_BUTTON4 | XEMACS_MOD_BUTTON5);
+  if ((modifiers & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_META | XEMACS_MOD_SUPER
+                    | XEMACS_MOD_HYPER | XEMACS_MOD_ALT | XEMACS_MOD_SHIFT))
+      != 0)
+    ABORT ();
 
   k = XKEYMAP (keymap);
 
@@ -492,14 +484,14 @@ keymap_lookup_directly (Lisp_Object keymap,
       keysym = i_fart_on_gcc;
     }
 
-  if (modifiers & MOD_META)     /* Utterly hateful ESC lossage */
+  if (modifiers & XEMACS_MOD_META)     /* Utterly hateful ESC lossage */
     {
-      Lisp_Object submap = Fgethash (MAKE_MODIFIER_HASH_KEY (MOD_META),
+      Lisp_Object submap = Fgethash (MAKE_MODIFIER_HASH_KEY (XEMACS_MOD_META),
                                      k->table, Qnil);
       if (NILP (submap))
         return Qnil;
       k = XKEYMAP (submap);
-      modifiers &= ~MOD_META;
+      modifiers &= ~XEMACS_MOD_META;
     }
 
   if (modifiers != 0)
@@ -555,7 +547,7 @@ keymap_delete_inverse_internal (Lisp_Object inverse_table,
   Lisp_Object *prev;
 
   if (UNBOUNDP (keys))
-    abort ();
+    ABORT ();
 
   for (prev = &new_keys, tail = new_keys;
        ;
@@ -583,38 +575,57 @@ keymap_delete_inverse_internal (Lisp_Object inverse_table,
    */
 }
 
+/* Prevent luser from shooting herself in the foot using something like
+   (define-key ctl-x-4-map "p" global-map) */
+static void
+check_keymap_definition_loop (Lisp_Object def, Lisp_Keymap *to_keymap)
+{
+  def = get_keymap (def, 0, 0);
+
+  if (KEYMAPP (def))
+    {
+      Lisp_Object maps;
+
+      if (XKEYMAP (def) == to_keymap)
+       signal_simple_error ("Cyclic keymap definition", def);
+
+      for (maps = keymap_submaps (def);
+          CONSP (maps);
+          maps = XCDR (maps))
+       check_keymap_definition_loop (XCDR (XCAR (maps)), to_keymap);
+    }
+}
 
 static void
 keymap_store_internal (Lisp_Object keysym, Lisp_Keymap *keymap,
-                      Lisp_Object value)
+                      Lisp_Object def)
 {
-  Lisp_Object prev_value = Fgethash (keysym, keymap->table, Qnil);
+  Lisp_Object prev_def = Fgethash (keysym, keymap->table, Qnil);
 
-  if (EQ (prev_value, value))
+  if (EQ (prev_def, def))
       return;
-  if (!NILP (prev_value))
+
+  check_keymap_definition_loop (def, keymap);
+
+  if (!NILP (prev_def))
     keymap_delete_inverse_internal (keymap->inverse_table,
-                                    keysym, prev_value);
-  if (NILP (value))
+                                    keysym, prev_def);
+  if (NILP (def))
     {
-      keymap->fullness--;
-      if (keymap->fullness < 0) abort ();
       Fremhash (keysym, keymap->table);
     }
   else
     {
-      if (NILP (prev_value))
-       keymap->fullness++;
-      Fputhash (keysym, value, keymap->table);
+      Fputhash (keysym, def, keymap->table);
       keymap_store_inverse_internal (keymap->inverse_table,
-                                     keysym, value);
+                                     keysym, def);
     }
   keymap_tick++;
 }
 
 
 static Lisp_Object
-create_bucky_submap (Lisp_Keymap *k, unsigned int modifiers,
+create_bucky_submap (Lisp_Keymap *k, int modifiers,
                      Lisp_Object parent_for_debugging_info)
 {
   Lisp_Object submap = Fmake_sparse_keymap (Qnil);
@@ -630,35 +641,31 @@ create_bucky_submap (Lisp_Keymap *k, unsigned int modifiers,
 
 /* Relies on caller to gc-protect keymap, keysym, value */
 static void
-keymap_store (Lisp_Object keymap, CONST struct key_data *key,
+keymap_store (Lisp_Object keymap, const struct key_data *key,
               Lisp_Object value)
 {
   Lisp_Object keysym = key->keysym;
-  unsigned int modifiers = key->modifiers;
-  Lisp_Keymap *k;
+  int modifiers = key->modifiers;
+  Lisp_Keymap *k = XKEYMAP (keymap);
 
-  if ((modifiers & ~(MOD_CONTROL | MOD_META | MOD_SUPER | MOD_HYPER
-                     | MOD_ALT | MOD_SHIFT)) != 0)
-    abort ();
-
-  k = XKEYMAP (keymap);
+  modifiers &= ~(XEMACS_MOD_BUTTON1 | XEMACS_MOD_BUTTON2 | XEMACS_MOD_BUTTON3
+                | XEMACS_MOD_BUTTON4 | XEMACS_MOD_BUTTON5);
+  assert ((modifiers & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_META
+                        | XEMACS_MOD_SUPER | XEMACS_MOD_HYPER
+                        | XEMACS_MOD_ALT | XEMACS_MOD_SHIFT)) == 0);
 
   /* If the keysym is a one-character symbol, use the char code instead. */
   if (SYMBOLP (keysym) && string_char_length (XSYMBOL (keysym)->name) == 1)
-    {
-      Lisp_Object run_the_gcc_developers_over_with_a_steamroller =
-       make_char (string_char (XSYMBOL (keysym)->name, 0));
-      keysym = run_the_gcc_developers_over_with_a_steamroller;
-    }
+    keysym = make_char (string_char (XSYMBOL (keysym)->name, 0));
 
-  if (modifiers & MOD_META)     /* Utterly hateful ESC lossage */
+  if (modifiers & XEMACS_MOD_META)     /* Utterly hateful ESC lossage */
     {
-      Lisp_Object submap = Fgethash (MAKE_MODIFIER_HASH_KEY (MOD_META),
+      Lisp_Object submap = Fgethash (MAKE_MODIFIER_HASH_KEY (XEMACS_MOD_META),
                                     k->table, Qnil);
       if (NILP (submap))
-       submap = create_bucky_submap (k, MOD_META, keymap);
+       submap = create_bucky_submap (k, XEMACS_MOD_META, keymap);
       k = XKEYMAP (submap);
-      modifiers &= ~MOD_META;
+      modifiers &= ~XEMACS_MOD_META;
     }
 
   if (modifiers != 0)
@@ -759,7 +766,6 @@ make_keymap (size_t size)
   keymap->inverse_table   = Qnil;
   keymap->default_binding = Qnil;
   keymap->sub_maps_cache  = Qnil; /* No possible submaps */
-  keymap->fullness        = 0;
   keymap->name            = Qnil;
 
   if (size != 0) /* hack for copy-keymap */
@@ -793,9 +799,9 @@ it is not used except when printing the keymap.
 DEFUN ("make-sparse-keymap", Fmake_sparse_keymap, 0, 1, 0, /*
 Construct and return a new keymap object.
 All entries in it are nil, meaning "command undefined".  The only
-difference between this function and make-keymap is that this function
+difference between this function and `make-keymap' is that this function
 returns a "smaller" keymap (one that is expected to contain fewer
-entries).  As keymaps dynamically resize, the distinction is not great.
+entries).  As keymaps dynamically resize, this distinction is not great.
 
 Optional argument NAME specifies a name to assign to the keymap,
 as in `set-keymap-name'.  This name is only a debugging convenience;
@@ -966,7 +972,7 @@ parents nor the current global map are searched for key bindings.
 }
 
 DEFUN ("keymapp", Fkeymapp, 1, 1, 0, /*
-Return t if ARG is a keymap object.
+Return t if OBJECT is a keymap object.
 The keymap may be autoloaded first if necessary.
 */
        (object))
@@ -1009,10 +1015,8 @@ get_keymap (Lisp_Object object, int errorp, int autoload)
                && EQ (XCAR (tem), Qautoload)
                && EQ (Fcar (Fcdr (Fcdr (Fcdr (Fcdr (tem))))), Qkeymap))
        {
-         struct gcpro gcpro1, gcpro2;
-         GCPRO2 (tem, object);
+         /* do_autoload GCPROs both arguments */
          do_autoload (tem, object);
-         UNGCPRO;
        }
       else if (errorp)
        object = wrong_type_argument (Qkeymapp, object);
@@ -1051,7 +1055,7 @@ get_keyelt (Lisp_Object object, int accept_default)
       struct key_data indirection;
       if (CHARP (idx))
        {
-         struct Lisp_Event event;
+         Lisp_Event event;
          event.event_type = empty_event;
          character_to_event (XCHAR (idx), &event,
                              XCONSOLE (Vselected_console), 0, 0);
@@ -1062,7 +1066,7 @@ get_keyelt (Lisp_Object object, int accept_default)
          if (!INTP (XCDR (idx)))
            return Qnil;
          indirection.keysym = XCAR (idx);
-         indirection.modifiers = XINT (XCDR (idx));
+         indirection.modifiers = (unsigned char) XINT (XCDR (idx));
        }
       else if (SYMBOLP (idx))
        {
@@ -1093,7 +1097,7 @@ get_keyelt (Lisp_Object object, int accept_default)
 }
 
 static Lisp_Object
-keymap_lookup_1 (Lisp_Object keymap, CONST struct key_data *key,
+keymap_lookup_1 (Lisp_Object keymap, const struct key_data *key,
                  int accept_default)
 {
   /* This function can GC */
@@ -1137,7 +1141,6 @@ copy_keymap_internal (Lisp_Keymap *keymap)
   copy_keymap_inverse_closure.inverse_table = keymap->inverse_table;
 
   new_keymap->parents        = Fcopy_sequence (keymap->parents);
-  new_keymap->fullness       = keymap->fullness;
   new_keymap->sub_maps_cache = Qnil; /* No submaps */
   new_keymap->table          = Fcopy_hash_table (keymap->table);
   new_keymap->inverse_table  = Fcopy_hash_table (keymap->inverse_table);
@@ -1215,16 +1218,17 @@ keymap_fullness (Lisp_Object keymap)
   struct gcpro gcpro1, gcpro2;
 
   keymap = get_keymap (keymap, 1, 1);
-  fullness = XKEYMAP (keymap)->fullness;
-  sub_maps = keymap_submaps (keymap);
+  fullness = XINT (Fhash_table_count (XKEYMAP (keymap)->table));
   GCPRO2 (keymap, sub_maps);
-  for (; !NILP (sub_maps); sub_maps = XCDR (sub_maps))
+  for (sub_maps = keymap_submaps (keymap);
+       !NILP (sub_maps);
+       sub_maps = XCDR (sub_maps))
     {
       if (MODIFIER_HASH_KEY_BITS (XCAR (XCAR (sub_maps))) != 0)
        {
-         Lisp_Object sub_map = XCDR (XCAR (sub_maps));
-         fullness--; /* don't count bucky maps */
-         fullness += keymap_fullness (sub_map);
+         Lisp_Object bucky_map = XCDR (XCAR (sub_maps));
+         fullness--; /* don't count bucky maps themselves. */
+         fullness += keymap_fullness (bucky_map);
        }
     }
   UNGCPRO;
@@ -1251,7 +1255,7 @@ Return the number of bindings in the keymap.
 static void
 define_key_check_and_coerce_keysym (Lisp_Object spec,
                                    Lisp_Object *keysym,
-                                   unsigned int modifiers)
+                                   int modifiers)
 {
   /* Now, check and massage the trailing keysym specifier. */
   if (SYMBOLP (*keysym))
@@ -1274,21 +1278,19 @@ define_key_check_and_coerce_keysym (Lisp_Object spec,
           problems ... */
        signal_simple_error ("keysym char must be printable", *keysym);
       /* #### This bites!  I want to be able to write (control shift a) */
-      if (modifiers & MOD_SHIFT)
+      if (modifiers & XEMACS_MOD_SHIFT)
        signal_simple_error
          ("The `shift' modifier may not be applied to ASCII keysyms",
           spec);
     }
   else
     {
-      signal_simple_error ("Unknown keysym specifier",
-                          *keysym);
+      signal_simple_error ("Unknown keysym specifier", *keysym);
     }
 
   if (SYMBOLP (*keysym))
     {
-      char *name = (char *)
-       string_data (XSYMBOL (*keysym)->name);
+      char *name = (char *) string_data (XSYMBOL (*keysym)->name);
 
       /* FSFmacs uses symbols with the printed representation of keysyms in
         their names, like 'M-x, and we use the syntax '(meta x).  So, to avoid
@@ -1351,6 +1353,8 @@ define_key_check_and_coerce_keysym (Lisp_Object spec,
        *keysym = QKescape;
       else if (EQ (*keysym, QDEL))
        *keysym = QKdelete;
+      else if (EQ (*keysym, QSPC))
+       *keysym = QKspace;
       else if (EQ (*keysym, QBS))
        *keysym = QKbackspace;
       /* Emacs compatibility */
@@ -1364,6 +1368,10 @@ define_key_check_and_coerce_keysym (Lisp_Object spec,
        *keysym = Qbutton4;
       else if (EQ(*keysym, Qdown_mouse_5))
        *keysym = Qbutton5;
+      else if (EQ(*keysym, Qdown_mouse_6))
+       *keysym = Qbutton6;
+      else if (EQ(*keysym, Qdown_mouse_7))
+       *keysym = Qbutton7;
       else if (EQ(*keysym, Qmouse_1))
        *keysym = Qbutton1up;
       else if (EQ(*keysym, Qmouse_2))
@@ -1374,6 +1382,10 @@ define_key_check_and_coerce_keysym (Lisp_Object spec,
        *keysym = Qbutton4up;
       else if (EQ(*keysym, Qmouse_5))
        *keysym = Qbutton5up;
+      else if (EQ(*keysym, Qmouse_6))
+       *keysym = Qbutton6up;
+      else if (EQ(*keysym, Qmouse_7))
+       *keysym = Qbutton7up;
     }
 }
 
@@ -1390,7 +1402,7 @@ define_key_parser (Lisp_Object spec, struct key_data *returned_value)
 {
   if (CHAR_OR_CHAR_INTP (spec))
     {
-      struct Lisp_Event event;
+      Lisp_Event event;
       event.event_type = empty_event;
       character_to_event (XCHAR_OR_CHAR_INT (spec), &event,
                          XCONSOLE (Vselected_console), 0, 0);
@@ -1451,14 +1463,14 @@ define_key_parser (Lisp_Object spec, struct key_data *returned_value)
     }
   else if (CONSP (spec))
     {
-      unsigned int modifiers = 0;
+      int modifiers = 0;
       Lisp_Object keysym = Qnil;
       Lisp_Object rest = spec;
 
       /* First, parse out the leading modifier symbols. */
       while (CONSP (rest))
        {
-         unsigned int modifier;
+         int modifier;
 
          keysym = XCAR (rest);
          modifier = bucky_sym_to_bucky_bit (keysym);
@@ -1538,10 +1550,9 @@ key_desc_list_to_event (Lisp_Object list, Lisp_Object event,
 
 
 int
-event_matches_key_specifier_p (struct Lisp_Event *event,
-                              Lisp_Object key_specifier)
+event_matches_key_specifier_p (Lisp_Event *event, Lisp_Object key_specifier)
 {
-  Lisp_Object event2;
+  Lisp_Object event2 = Qnil;
   int retval;
   struct gcpro gcpro1;
 
@@ -1590,9 +1601,9 @@ event_matches_key_specifier_p (struct Lisp_Event *event,
 }
 
 static int
-meta_prefix_char_p (CONST struct key_data *key)
+meta_prefix_char_p (const struct key_data *key)
 {
-  struct Lisp_Event event;
+  Lisp_Event event;
 
   event.event_type = key_press_event;
   event.channel = Vselected_console;
@@ -1629,14 +1640,14 @@ define_key_alternate_name (struct key_data *key,
                            struct key_data *returned_value)
 {
   Lisp_Object keysym = key->keysym;
-  unsigned int modifiers = key->modifiers;
-  unsigned int modifiers_sans_control = (modifiers & (~MOD_CONTROL));
-  unsigned int modifiers_sans_meta = (modifiers & (~MOD_META));
+  int modifiers = key->modifiers;
+  int modifiers_sans_control = (modifiers & (~XEMACS_MOD_CONTROL));
+  int modifiers_sans_meta = (modifiers & (~XEMACS_MOD_META));
   returned_value->keysym = Qnil; /* By default, no "alternate" key */
   returned_value->modifiers = 0;
-  if (modifiers_sans_meta == MOD_CONTROL)
+  if (modifiers_sans_meta == XEMACS_MOD_CONTROL)
     {
-      if EQ (keysym, QKspace)
+      if (EQ (keysym, QKspace))
         MACROLET (make_char ('@'), modifiers);
       else if (!CHARP (keysym))
         return;
@@ -1661,15 +1672,15 @@ define_key_alternate_name (struct key_data *key,
   else if (modifiers_sans_meta != 0)
     return;
   else if (EQ (keysym, QKbackspace)) /* backspace => c-h */
-    MACROLET (make_char ('h'), (modifiers | MOD_CONTROL));
+    MACROLET (make_char ('h'), (modifiers | XEMACS_MOD_CONTROL));
   else if (EQ (keysym, QKtab))       /* tab => c-i */
-    MACROLET (make_char ('i'), (modifiers | MOD_CONTROL));
+    MACROLET (make_char ('i'), (modifiers | XEMACS_MOD_CONTROL));
   else if (EQ (keysym, QKlinefeed))  /* linefeed => c-j */
-    MACROLET (make_char ('j'), (modifiers | MOD_CONTROL));
+    MACROLET (make_char ('j'), (modifiers | XEMACS_MOD_CONTROL));
   else if (EQ (keysym, QKreturn))    /* return => c-m */
-    MACROLET (make_char ('m'), (modifiers | MOD_CONTROL));
+    MACROLET (make_char ('m'), (modifiers | XEMACS_MOD_CONTROL));
   else if (EQ (keysym, QKescape))    /* escape => c-[ */
-    MACROLET (make_char ('['), (modifiers | MOD_CONTROL));
+    MACROLET (make_char ('['), (modifiers | XEMACS_MOD_CONTROL));
   else
     return;
 #undef MACROLET
@@ -1706,7 +1717,10 @@ ensure_meta_prefix_char_keymapp (Lisp_Object keys, int indx,
        XVECTOR_DATA (new_keys) [i] = XVECTOR_DATA (keys) [i];
     }
   else
-    abort ();
+    {
+      new_keys = Qnil;
+      ABORT ();
+    }
 
   if (EQ (keys, new_keys))
     error_with_frob (mpc_binding,
@@ -1898,20 +1912,17 @@ these features.
                 (defvar my-escape-map (lookup-key my-map "\e"))
                 if the luser really wants the map in a variable.
                 */
-             Lisp_Object mmap;
+             Lisp_Object meta_map;
               struct gcpro ngcpro1;
 
               NGCPRO1 (c);
-              mmap = Fgethash (MAKE_MODIFIER_HASH_KEY (MOD_META),
-                               XKEYMAP (keymap)->table, Qnil);
-             if (!NILP (mmap)
-                 && keymap_fullness (mmap) != 0)
-               {
-                  Lisp_Object desc
-                    = Fsingle_key_description (Vmeta_prefix_char);
-                 signal_simple_error_2
-                   ("Map contains meta-bindings, can't bind", desc, keymap);
-               }
+              meta_map = Fgethash (MAKE_MODIFIER_HASH_KEY (XEMACS_MOD_META),
+                                  XKEYMAP (keymap)->table, Qnil);
+             if (!NILP (meta_map)
+                 && keymap_fullness (meta_map) != 0)
+               signal_simple_error_2
+                 ("Map contains meta-bindings, can't bind",
+                  Fsingle_key_description (Vmeta_prefix_char), keymap);
               NUNGCPRO;
            }
          else
@@ -1932,14 +1943,14 @@ these features.
 
       if (metized)
        {
-         raw_key1.modifiers  |= MOD_META;
-         raw_key2.modifiers |= MOD_META;
+         raw_key1.modifiers |= XEMACS_MOD_META;
+         raw_key2.modifiers |= XEMACS_MOD_META;
          metized = 0;
        }
 
       /* This crap is to make sure that someone doesn't bind something like
         "C-x M-a" while "C-x ESC" has a non-keymap binding. */
-      if (raw_key1.modifiers & MOD_META)
+      if (raw_key1.modifiers & XEMACS_MOD_META)
        ensure_meta_prefix_char_keymapp (keys, idx, keymap);
 
       if (++idx == len)
@@ -1989,7 +2000,7 @@ these features.
 struct raw_lookup_key_mapper_closure
 {
   int remaining;
-  CONST struct key_data *raw_keys;
+  const struct key_data *raw_keys;
   int raw_keys_count;
   int keys_so_far;
   int accept_default;
@@ -2000,7 +2011,7 @@ static Lisp_Object raw_lookup_key_mapper (Lisp_Object k, void *);
 /* Caller should gc-protect args (keymaps may autoload) */
 static Lisp_Object
 raw_lookup_key (Lisp_Object keymap,
-                CONST struct key_data *raw_keys, int raw_keys_count,
+                const struct key_data *raw_keys, int raw_keys_count,
                 int keys_so_far, int accept_default)
 {
   /* This function can GC */
@@ -2023,7 +2034,7 @@ raw_lookup_key_mapper (Lisp_Object k, void *arg)
   int accept_default = c->accept_default;
   int remaining = c->remaining;
   int keys_so_far = c->keys_so_far;
-  CONST struct key_data *raw_keys = c->raw_keys;
+  const struct key_data *raw_keys = c->raw_keys;
   Lisp_Object cmd;
 
   if (! meta_prefix_char_p (&(raw_keys[0])))
@@ -2062,7 +2073,7 @@ raw_lookup_key_mapper (Lisp_Object k, void *arg)
          if (NILP (cmd))
            {
              /* Do kludgy return of the meta-map */
-             cmd = Fgethash (MAKE_MODIFIER_HASH_KEY (MOD_META),
+             cmd = Fgethash (MAKE_MODIFIER_HASH_KEY (XEMACS_MOD_META),
                              XKEYMAP (k)->table, Qnil);
            }
        }
@@ -2074,11 +2085,12 @@ raw_lookup_key_mapper (Lisp_Object k, void *arg)
          if (!NILP (cmd))
            cmd = raw_lookup_key (cmd, raw_keys + 1, remaining,
                                  keys_so_far + 1, accept_default);
-         else if ((raw_keys[1].modifiers & MOD_META) == 0)
+         else if ((raw_keys[1].modifiers & XEMACS_MOD_META) == 0)
            {
              struct key_data metified;
              metified.keysym = raw_keys[1].keysym;
-             metified.modifiers = raw_keys[1].modifiers | MOD_META;
+             metified.modifiers = raw_keys[1].modifiers |
+               (unsigned char) XEMACS_MOD_META;
 
              /* Search for meta-next-char sequence directly */
              cmd = keymap_lookup_1 (k, &metified, accept_default);
@@ -2114,7 +2126,7 @@ lookup_keys (Lisp_Object keymap, int nkeys, Lisp_Object *keys,
   if (nkeys == 0)
     return Qnil;
 
-  if (nkeys < (countof (kkk)))
+  if (nkeys < countof (kkk))
     raw_keys = kkk;
   else
     raw_keys = alloca_array (struct key_data, nkeys);
@@ -2144,7 +2156,7 @@ lookup_events (Lisp_Object event_head, int nmaps, Lisp_Object keymaps[],
 
   nkeys = event_chain_count (event_head);
 
-  if (nkeys < (countof (kkk)))
+  if (nkeys < countof (kkk))
     raw_keys = kkk;
   else
     raw_keys = alloca_array (struct key_data, nkeys);
@@ -2179,8 +2191,8 @@ Nil is returned if KEYS is unbound.  See documentation of `define-key'
 for valid key definitions and key-sequence specifications.
 A number is returned if KEYS is "too long"; that is, the leading
 characters fail to be a valid sequence of prefix characters in KEYMAP.
-The number is how many characters at the front of KEYS
-it takes to reach a non-prefix command.
+The number is how many key strokes at the front of KEYS it takes to
+reach a non-prefix command.
 */
        (keymap, keys, accept_default))
 {
@@ -2370,8 +2382,7 @@ get_relevant_keymaps (Lisp_Object keys,
                  get_relevant_extent_keymaps
                    (Fevent_modeline_position (terminal),
                     XBUFFER (buffer)->generated_modeline_string,
-                    /* #### third arg should maybe be a glyph. */
-                    Qnil, &closure);
+                    Fevent_glyph_extent (terminal), &closure);
 
                  if (!UNBOUNDP (map) && !NILP (map))
                    relevant_map_push (get_keymap (map, 1, 1), &closure);
@@ -2534,7 +2545,7 @@ the documentation for `lookup-key' for more information.
 For key-presses, the order of keymaps searched is:
   - the `keymap' property of any extent(s) at point;
   - any applicable minor-mode maps;
-  - the current-local-map of the current-buffer;
+  - the current local map of the current-buffer;
   - the current global map.
 
 For mouse-clicks, the order of keymaps searched is:
@@ -2544,9 +2555,9 @@ For mouse-clicks, the order of keymaps searched is:
     (this includes modeline extents);
   - the modeline-map of the buffer corresponding to the modeline under
     the mouse (if the click happened over a modeline);
-  - the value of toolbar-map in the current-buffer (if the click
+  - the value of `toolbar-map' in the current-buffer (if the click
     happened over a toolbar);
-  - the current-local-map of the buffer under the mouse (does not
+  - the current local map of the buffer under the mouse (does not
     apply to toolbar clicks);
   - any applicable minor-mode maps;
   - the current global map.
@@ -2739,9 +2750,9 @@ Return the current global keymap.
 
 struct map_keymap_unsorted_closure
 {
-  void (*fn) (CONST struct key_data *, Lisp_Object binding, void *arg);
+  void (*fn) (const struct key_data *, Lisp_Object binding, void *arg);
   void *arg;
-  unsigned int modifiers;
+  int modifiers;
 };
 
 /* used by map_keymap() */
@@ -2752,8 +2763,8 @@ map_keymap_unsorted_mapper (Lisp_Object keysym, Lisp_Object value,
   /* This function can GC */
   struct map_keymap_unsorted_closure *closure =
     (struct map_keymap_unsorted_closure *) map_keymap_unsorted_closure;
-  unsigned int modifiers = closure->modifiers;
-  unsigned int mod_bit;
+  int modifiers = closure->modifiers;
+  int mod_bit;
   mod_bit = MODIFIER_HASH_KEY_BITS (keysym);
   if (mod_bit != 0)
     {
@@ -2803,7 +2814,7 @@ map_keymap_sort_predicate (Lisp_Object obj1, Lisp_Object obj2,
 {
   /* obj1 and obj2 are conses with keysyms in their cars.  Cdrs are ignored.
    */
-  unsigned int bit1, bit2;
+  int bit1, bit2;
   int sym1_p = 0;
   int sym2_p = 0;
   obj1 = XCAR (obj1);
@@ -2877,8 +2888,8 @@ map_keymap_sort_predicate (Lisp_Object obj1, Lisp_Object obj2,
 /* used by map_keymap() */
 static void
 map_keymap_sorted (Lisp_Object keymap_table,
-                   unsigned int modifiers,
-                   void (*function) (CONST struct key_data *key,
+                   int modifiers,
+                   void (*function) (const struct key_data *key,
                                      Lisp_Object binding,
                                      void *map_keymap_sorted_closure),
                    void *map_keymap_sorted_closure)
@@ -2902,7 +2913,7 @@ map_keymap_sorted (Lisp_Object keymap_table,
     {
       Lisp_Object keysym = XCAR (XCAR (contents));
       Lisp_Object binding = XCDR (XCAR (contents));
-      unsigned int sub_bits = MODIFIER_HASH_KEY_BITS (keysym);
+      int sub_bits = MODIFIER_HASH_KEY_BITS (keysym);
       if (sub_bits != 0)
        map_keymap_sorted (XKEYMAP (get_keymap (binding,
                                                1, 1))->table,
@@ -2923,7 +2934,7 @@ map_keymap_sorted (Lisp_Object keymap_table,
 
 /* used by Fmap_keymap() */
 static void
-map_keymap_mapper (CONST struct key_data *key,
+map_keymap_mapper (const struct key_data *key,
                    Lisp_Object binding,
                    void *function)
 {
@@ -2936,7 +2947,7 @@ map_keymap_mapper (CONST struct key_data *key,
 
 static void
 map_keymap (Lisp_Object keymap_table, int sort_first,
-            void (*function) (CONST struct key_data *key,
+            void (*function) (const struct key_data *key,
                               Lisp_Object binding,
                               void *fn_arg),
             void *fn_arg)
@@ -2977,7 +2988,8 @@ faster.
      (function, keymap, sort_first))
 {
   /* This function can GC */
-  struct gcpro gcpro1, gcpro2;
+  struct gcpro gcpro1, gcpro2, gcpro3;
+  Lisp_Object table = Qnil;
 
  /* tolerate obviously transposed args */
   if (!NILP (Fkeymapp (function)))
@@ -2986,9 +2998,17 @@ faster.
       function = keymap;
       keymap = tmp;
     }
-  GCPRO2 (function, keymap);
+
+  GCPRO3 (function, keymap, table);
   keymap = get_keymap (keymap, 1, 1);
-  map_keymap (XKEYMAP (keymap)->table, !NILP (sort_first),
+
+  /* elisp_maphash does not allow mapping functions to modify the hash
+     table being mapped over.  Since map-keymap explicitly allows a
+     mapping function to modify KEYMAP, we map over a copy of the hash
+     table instead.  */
+  table = Fcopy_hash_table (XKEYMAP (keymap)->table);
+
+  map_keymap (table, !NILP (sort_first),
              map_keymap_mapper, LISP_TO_VOID (function));
   UNGCPRO;
   return Qnil;
@@ -3008,11 +3028,11 @@ struct accessible_keymaps_closure
 
 static void
 accessible_keymaps_mapper_1 (Lisp_Object keysym, Lisp_Object contents,
-                             unsigned int modifiers,
+                             int modifiers,
                              struct accessible_keymaps_closure *closure)
 {
   /* This function can GC */
-  unsigned int subbits = MODIFIER_HASH_KEY_BITS (keysym);
+  int subbits = MODIFIER_HASH_KEY_BITS (keysym);
 
   if (subbits != 0)
     {
@@ -3040,10 +3060,10 @@ accessible_keymaps_mapper_1 (Lisp_Object keysym, Lisp_Object contents,
       key.modifiers = modifiers;
 
       if (NILP (cmd))
-       abort ();
+       ABORT ();
       cmd = get_keymap (cmd, 0, 1);
       if (!KEYMAPP (cmd))
-       abort ();
+       ABORT ();
 
       vec = make_vector (XVECTOR_LENGTH (thisseq) + 1, Qnil);
       len = XVECTOR_LENGTH (thisseq);
@@ -3092,23 +3112,28 @@ then the value includes only maps for prefixes that start with PREFIX.
   c.tail = Qnil;
   GCPRO4 (accessible_keymaps, c.tail, prefix, keymap);
 
- retry:
   keymap = get_keymap (keymap, 1, 1);
+
+ retry:
   if (NILP (prefix))
-    prefix = make_vector (0, Qnil);
-  else if (!VECTORP (prefix) || STRINGP (prefix))
     {
-      prefix = wrong_type_argument (Qarrayp, prefix);
-      goto retry;
+      prefix = make_vector (0, Qnil);
     }
-  else
+  else if (VECTORP (prefix) || STRINGP (prefix))
     {
       int len = XINT (Flength (prefix));
-      Lisp_Object def = Flookup_key (keymap, prefix, Qnil);
+      Lisp_Object def;
       Lisp_Object p;
       int iii;
       struct gcpro ngcpro1;
 
+      if (len == 0)
+       {
+         prefix = Qnil;
+         goto retry;
+       }
+
+      def = Flookup_key (keymap, prefix, Qnil);
       def = get_keymap (def, 0, 1);
       if (!KEYMAPP (def))
        goto RETURN;
@@ -3125,12 +3150,16 @@ then the value includes only maps for prefixes that start with PREFIX.
       NUNGCPRO;
       prefix = p;
     }
+  else
+    {
+      prefix = wrong_type_argument (Qarrayp, prefix);
+      goto retry;
+    }
 
   accessible_keymaps = list1 (Fcons (prefix, keymap));
 
-  /* For each map in the list maps,
-     look at any other maps it points to
-     and stick them at the end if they are not already in the list */
+  /* For each map in the list maps, look at any other maps it points
+     to and stick them at the end if they are not already in the list */
 
   for (c.tail = accessible_keymaps;
        !NILP (c.tail);
@@ -3175,9 +3204,9 @@ spaces are put between sequence elements, etc...
       for (i = 0; i < size; i++)
        {
          Lisp_Object s2 = Fsingle_key_description
-           (((STRINGP (keys))
-             ? make_char (string_char (XSTRING (keys), i))
-             : XVECTOR_DATA (keys)[i]));
+           (STRINGP (keys)
+            ? make_char (string_char (XSTRING (keys), i))
+            : XVECTOR_DATA (keys)[i]);
 
          if (i == 0)
            string = s2;
@@ -3208,7 +3237,7 @@ of a key read from the user rather than a character from a buffer.
       char buf [255];
       if (!EVENTP (key))
        {
-         struct Lisp_Event event;
+         Lisp_Event event;
          event.event_type = empty_event;
          CHECK_CHAR_COERCE_INT (key);
          character_to_event (XCHAR (key), &event,
@@ -3457,7 +3486,7 @@ static void
 format_raw_keys (struct key_data *keys, int count, char *buf)
 {
   int i;
-  struct Lisp_Event event;
+  Lisp_Event event;
   event.event_type = key_press_event;
   event.channel = Vselected_console;
   for (i = 0; i < count; i++)
@@ -3481,7 +3510,7 @@ format_raw_keys (struct key_data *keys, int count, char *buf)
    keys_so_far and modifiers_so_far describe which map we're looking in;
    If we're in the "meta" submap of the map that "C-x 4" is bound to,
    then keys_so_far will be {(control x), \4}, and modifiers_so_far
-   will be MOD_META.  That is, keys_so_far is the chain of keys that we
+   will be XEMACS_MOD_META.  That is, keys_so_far is the chain of keys that we
    have followed, and modifiers_so_far_so_far is the bits (partial keys)
    beyond that.
 
@@ -3499,7 +3528,7 @@ struct where_is_closure
     int shadow_count;
     int firstonly;
     int keys_count;
-    unsigned int modifiers_so_far;
+    int modifiers_so_far;
     char *target_buffer;
     struct key_data *keys_so_far;
     int keys_so_far_total_size;
@@ -3514,9 +3543,9 @@ where_is_recursive_mapper (Lisp_Object map, void *arg)
   /* This function can GC */
   struct where_is_closure *c = (struct where_is_closure *) arg;
   Lisp_Object definition = c->definition;
-  CONST int firstonly = c->firstonly;
-  CONST unsigned int keys_count = c->keys_count;
-  CONST unsigned int modifiers_so_far = c->modifiers_so_far;
+  const int firstonly = c->firstonly;
+  const int keys_count = c->keys_count;
+  const int modifiers_so_far = c->modifiers_so_far;
   char *target_buffer = c->target_buffer;
   Lisp_Object keys = Fgethash (definition,
                                XKEYMAP (map)->inverse_table,
@@ -3534,7 +3563,7 @@ where_is_recursive_mapper (Lisp_Object map, void *arg)
 
       for (;;) /* loop over all keys that match */
        {
-         Lisp_Object k = ((CONSP (keys)) ? XCAR (keys) : keys);
+         Lisp_Object k = CONSP (keys) ? XCAR (keys) : keys;
          int i;
 
          so_far [keys_count].keysym = k;
@@ -3560,7 +3589,7 @@ where_is_recursive_mapper (Lisp_Object map, void *arg)
          /* OK, the key is for real */
          if (target_buffer)
            {
-             if (!firstonly) abort ();
+             if (!firstonly) ABORT ();
              format_raw_keys (so_far, keys_count + 1, target_buffer);
              return make_int (1);
            }
@@ -3589,9 +3618,9 @@ where_is_recursive_mapper (Lisp_Object map, void *arg)
     {
       Lisp_Object key    = XCAR (XCAR (submaps));
       Lisp_Object submap = XCDR (XCAR (submaps));
-      unsigned int lower_modifiers;
+      int lower_modifiers;
       int lower_keys_count = keys_count;
-      unsigned int bucky;
+      int bucky;
 
       submap = get_keymap (submap, 0, 0);
 
@@ -3632,8 +3661,10 @@ where_is_recursive_mapper (Lisp_Object map, void *arg)
          if (! c->keys_so_far_malloced)
            {
              struct key_data *new = xnew_array (struct key_data, size);
-             memcpy ((void *)new, (CONST void *)c->keys_so_far,
+             memcpy ((void *)new, (const void *)c->keys_so_far,
                      c->keys_so_far_total_size * sizeof (struct key_data));
+             xfree (c->keys_so_far);
+             c->keys_so_far = new;
            }
          else
            XREALLOC_ARRAY (c->keys_so_far, struct key_data, size);
@@ -3885,7 +3916,7 @@ struct describe_map_closure
 
 struct describe_map_shadow_closure
   {
-    CONST struct key_data *raw_key;
+    const struct key_data *raw_key;
     Lisp_Object self;
   };
 
@@ -3914,7 +3945,7 @@ keymap_lookup_inherited_mapper (Lisp_Object km, void *arg)
 
 
 static void
-describe_map_mapper (CONST struct key_data *key,
+describe_map_mapper (const struct key_data *key,
                      Lisp_Object binding,
                     void *describe_map_closure)
 {
@@ -3922,7 +3953,7 @@ describe_map_mapper (CONST struct key_data *key,
   struct describe_map_closure *closure =
     (struct describe_map_closure *) describe_map_closure;
   Lisp_Object keysym = key->keysym;
-  unsigned int modifiers = key->modifiers;
+  int modifiers = key->modifiers;
 
   /* Don't mention suppressed commands.  */
   if (SYMBOLP (binding)
@@ -3996,7 +4027,7 @@ describe_map_sort_predicate (Lisp_Object obj1, Lisp_Object obj2,
      ( ( <keysym> . <modifiers> ) . <binding> )
      keysym and modifiers are used, binding is ignored.
    */
-  unsigned int bit1, bit2;
+  int bit1, bit2;
   obj1 = XCAR (obj1);
   obj2 = XCAR (obj2);
   bit1 = XINT (XCDR (obj1));
@@ -4116,17 +4147,23 @@ describe_map (Lisp_Object keymap, Lisp_Object elt_prefix,
        {
           Lisp_Object elt = XCAR (XCAR (list));
          Lisp_Object keysym = XCAR (elt);
-         unsigned int modifiers = XINT (XCDR (elt));
+         int modifiers = XINT (XCDR (elt));
 
          if (!NILP (elt_prefix))
            buffer_insert_lisp_string (buf, elt_prefix);
 
-         if (modifiers & MOD_META)    buffer_insert_c_string (buf, "M-");
-         if (modifiers & MOD_CONTROL) buffer_insert_c_string (buf, "C-");
-         if (modifiers & MOD_SUPER)   buffer_insert_c_string (buf, "S-");
-         if (modifiers & MOD_HYPER)   buffer_insert_c_string (buf, "H-");
-         if (modifiers & MOD_ALT)     buffer_insert_c_string (buf, "Alt-");
-         if (modifiers & MOD_SHIFT)   buffer_insert_c_string (buf, "Sh-");
+         if (modifiers & XEMACS_MOD_META)
+           buffer_insert_c_string (buf, "M-");
+         if (modifiers & XEMACS_MOD_CONTROL)
+           buffer_insert_c_string (buf, "C-");
+         if (modifiers & XEMACS_MOD_SUPER)
+           buffer_insert_c_string (buf, "S-");
+         if (modifiers & XEMACS_MOD_HYPER)
+           buffer_insert_c_string (buf, "H-");
+         if (modifiers & XEMACS_MOD_ALT)
+           buffer_insert_c_string (buf, "Alt-");
+         if (modifiers & XEMACS_MOD_SHIFT)
+           buffer_insert_c_string (buf, "Sh-");
          if (SYMBOLP (keysym))
            {
              Lisp_Object code = Fget (keysym, Vcharacter_set_property, Qnil);
@@ -4193,6 +4230,8 @@ describe_map (Lisp_Object keymap, Lisp_Object elt_prefix,
 void
 syms_of_keymap (void)
 {
+  INIT_LRECORD_IMPLEMENTATION (keymap);
+
   defsymbol (&Qminor_mode_map_alist, "minor-mode-map-alist");
 
   defsymbol (&Qkeymapp, "keymapp");
@@ -4263,17 +4302,22 @@ syms_of_keymap (void)
   defsymbol (&Qmouse_3, "mouse-3");
   defsymbol (&Qmouse_4, "mouse-4");
   defsymbol (&Qmouse_5, "mouse-5");
+  defsymbol (&Qmouse_6, "mouse-6");
+  defsymbol (&Qmouse_7, "mouse-7");
   defsymbol (&Qdown_mouse_1, "down-mouse-1");
   defsymbol (&Qdown_mouse_2, "down-mouse-2");
   defsymbol (&Qdown_mouse_3, "down-mouse-3");
   defsymbol (&Qdown_mouse_4, "down-mouse-4");
   defsymbol (&Qdown_mouse_5, "down-mouse-5");
+  defsymbol (&Qdown_mouse_6, "down-mouse-6");
+  defsymbol (&Qdown_mouse_7, "down-mouse-7");
   defsymbol (&Qmenu_selection, "menu-selection");
   defsymbol (&QLFD, "LFD");
   defsymbol (&QTAB, "TAB");
   defsymbol (&QRET, "RET");
   defsymbol (&QESC, "ESC");
   defsymbol (&QDEL, "DEL");
+  defsymbol (&QSPC, "SPC");
   defsymbol (&QBS, "BS");
 }
 
@@ -4310,8 +4354,28 @@ You should *bind* this, not set it.
 
   DEFVAR_LISP ("key-translation-map", &Vkey_translation_map /*
 Keymap of key translations that can override keymaps.
-This keymap works like `function-key-map', but comes after that,
+
+This keymap works like `function-key-map', but is searched before it,
 and applies even for keys that have ordinary bindings.
+
+The `read-key-sequence' function replaces any subsequence bound by
+`key-translation-map' with its binding.  More precisely, when the active
+keymaps have no binding for the current key sequence but
+`key-translation-map' binds a suffix of the sequence to a vector or string,
+`read-key-sequence' replaces the matching suffix with its binding, and
+continues with the new sequence.  See `key-binding' for details.
+
+The events that come from bindings in `key-translation-map' are not
+themselves looked up in `key-translation-map'.
+
+#### FIXME: stolen from `function-key-map'; need better example.
+#### I guess you could implement a Dvorak keyboard with this?
+For example, suppose `key-translation-map' binds `ESC O P' to [f1].
+Typing `ESC O P' to `read-key-sequence' would return
+\[#<keypress-event f1>].  Typing `C-x ESC O P' would return
+\[#<keypress-event control-X> #<keypress-event f1>].  If [f1]
+were a prefix key, typing `ESC O P x' would return
+\[#<keypress-event f1> #<keypress-event x>].
 */ );
   Vkey_translation_map = Qnil;
 
@@ -4327,7 +4391,7 @@ Incremented for each change to any keymap.
 
   staticpro (&Vcurrent_global_map);
 
-  Vsingle_space_string = make_string_nocopy ((CONST Bufbyte *) " ", 1);
+  Vsingle_space_string = make_string ((const Bufbyte *) " ", 1);
   staticpro (&Vsingle_space_string);
 }
 
@@ -4343,7 +4407,7 @@ complex_vars_of_keymap (void)
   meta_disgustitute = Fmake_keymap (Qnil);
   Ffset (ESC_prefix, meta_disgustitute);
   /* no need to protect meta_disgustitute, though */
-  keymap_store_internal (MAKE_MODIFIER_HASH_KEY (MOD_META),
+  keymap_store_internal (MAKE_MODIFIER_HASH_KEY (XEMACS_MOD_META),
                          XKEYMAP (Vcurrent_global_map),
                          meta_disgustitute);
   XKEYMAP (Vcurrent_global_map)->sub_maps_cache = Qt;