# HG changeset patch # User Richard M. Stallman # Date 740125560 0 # Node ID 7193a99a87c1ab6f79a780a1bf67e130a76cd903 # Parent 5ada670e1fd88df61d6c01cff8669679f704a55f Make prefix keys work with keymap inheritance by creating an inheritance structure for each subkeymap that we create in the inheriting keymap. (access_keymap): New arg NOINHERIT. All calls changed. (define_as_prefix): New function. (Fdefine_key): Use them. diff -r 5ada670e1fd8 -r 7193a99a87c1 src/keymap.c --- a/src/keymap.c Tue Jun 15 05:27:54 1993 +0000 +++ b/src/keymap.c Tue Jun 15 06:26:00 1993 +0000 @@ -81,6 +81,7 @@ extern Lisp_Object meta_prefix_char; void describe_map_tree (); +static Lisp_Object define_as_prefix (); static Lisp_Object describe_buffer_bindings (); static void describe_command (); static void describe_map (); @@ -255,14 +256,20 @@ bindings; any key left unmentioned by other tables and bindings is given the binding of Qt. - If T_OK is zero, bindings for Qt are not treated specially. */ + If T_OK is zero, bindings for Qt are not treated specially. + + If NOINHERIT, don't accept a subkeymap found in an inherited keymap. */ Lisp_Object -access_keymap (map, idx, t_ok) +access_keymap (map, idx, t_ok, noinherit) Lisp_Object map; Lisp_Object idx; int t_ok; + int noinherit; { + int noprefix = 0; + Lisp_Object val; + /* If idx is a list (some sort of mouse click, perhaps?), the index we want to use is the car of the list, which ought to be a symbol. */ @@ -287,9 +294,21 @@ switch (XTYPE (binding)) { + case Lisp_Symbol: + /* If NOINHERIT, stop finding prefix definitions + after we pass a second occurrence of the `keymap' symbol. */ + if (noinherit && EQ (binding, Qkeymap) && ! EQ (tail, map)) + noprefix = 1; + break; + case Lisp_Cons: if (EQ (XCONS (binding)->car, idx)) - return XCONS (binding)->cdr; + { + val = XCONS (binding)->cdr; + if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) + return Qnil; + return val; + } if (t_ok && EQ (XCONS (binding)->car, Qt)) t_binding = XCONS (binding)->cdr; break; @@ -298,7 +317,12 @@ if (XTYPE (idx) == Lisp_Int && XINT (idx) >= 0 && XINT (idx) < XVECTOR (binding)->size) - return XVECTOR (binding)->contents[XINT (idx)]; + { + val = XVECTOR (binding)->contents[XINT (idx)]; + if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) + return Qnil; + return val; + } break; } @@ -330,7 +354,7 @@ map = get_keymap_1 (Fcar_safe (object), 0, 0); tem = Fkeymapp (map); if (!NILP (tem)) - object = access_keymap (map, Fcdr (object), 0); + object = access_keymap (map, Fcdr (object), 0, 0); /* If the keymap contents looks like (STRING . DEFN), use DEFN. @@ -552,13 +576,11 @@ if (idx == length) RETURN_UNGCPRO (store_in_keymap (keymap, c, def)); - cmd = get_keyelt (access_keymap (keymap, c, 0)); + cmd = get_keyelt (access_keymap (keymap, c, 0, 1)); + /* If this key is undefined, make it a prefix. */ if (NILP (cmd)) - { - cmd = Fmake_sparse_keymap (Qnil); - store_in_keymap (keymap, c, cmd); - } + cmd = define_as_prefix (keymap, c); keymap = get_keymap_1 (cmd, 0, 1); if (NILP (keymap)) @@ -640,7 +662,7 @@ idx++; } - cmd = get_keyelt (access_keymap (keymap, c, t_ok)); + cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0)); if (idx == length) return cmd; @@ -652,6 +674,42 @@ } } +/* Make KEYMAP define event C as a keymap (i.e., as a prefix). + Assume that currently it does not define C at all. + Return the keymap. */ + +static Lisp_Object +define_as_prefix (keymap, c) + Lisp_Object keymap, c; +{ + Lisp_Object inherit, cmd; + + cmd = Fmake_sparse_keymap (Qnil); + /* If this key is defined as a prefix in an inherited keymap, + make it a prefix in this map, and make its definition + inherit the other prefix definition. */ + inherit = access_keymap (keymap, c, 0, 0); + if (NILP (inherit)) + { + /* If there's an inherited keymap + and it doesn't define this key, + make it define this key. */ + Lisp_Object tail; + + for (tail = Fcdr (keymap); CONSP (tail); tail = XCONS (tail)->cdr) + if (EQ (XCONS (tail)->car, Qkeymap)) + break; + + if (!NILP (tail)) + inherit = define_as_prefix (tail, c); + } + + cmd = nconc2 (cmd, inherit); + store_in_keymap (keymap, c, cmd); + + return cmd; +} + /* Append a key to the end of a key sequence. We always make a vector. */ Lisp_Object