diff options
| author | Richard M. Stallman | 1993-06-15 06:26:00 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-06-15 06:26:00 +0000 |
| commit | c07aec9773d9b595200422b1225cc5ffe591e4e0 (patch) | |
| tree | eff186a4b6f390301acb0c002c2d44d7bbf27bf5 /src | |
| parent | 0df8950e08c052ee296aa21891931e08cb0ec759 (diff) | |
| download | emacs-c07aec9773d9b595200422b1225cc5ffe591e4e0.tar.gz emacs-c07aec9773d9b595200422b1225cc5ffe591e4e0.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keymap.c | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/src/keymap.c b/src/keymap.c index 79c2836b905..e08a285ae6c 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -81,6 +81,7 @@ Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii; | |||
| 81 | extern Lisp_Object meta_prefix_char; | 81 | extern Lisp_Object meta_prefix_char; |
| 82 | 82 | ||
| 83 | void describe_map_tree (); | 83 | void describe_map_tree (); |
| 84 | static Lisp_Object define_as_prefix (); | ||
| 84 | static Lisp_Object describe_buffer_bindings (); | 85 | static Lisp_Object describe_buffer_bindings (); |
| 85 | static void describe_command (); | 86 | static void describe_command (); |
| 86 | static void describe_map (); | 87 | static void describe_map (); |
| @@ -255,14 +256,20 @@ get_keymap (object) | |||
| 255 | bindings; any key left unmentioned by other tables and bindings is | 256 | bindings; any key left unmentioned by other tables and bindings is |
| 256 | given the binding of Qt. | 257 | given the binding of Qt. |
| 257 | 258 | ||
| 258 | If T_OK is zero, bindings for Qt are not treated specially. */ | 259 | If T_OK is zero, bindings for Qt are not treated specially. |
| 260 | |||
| 261 | If NOINHERIT, don't accept a subkeymap found in an inherited keymap. */ | ||
| 259 | 262 | ||
| 260 | Lisp_Object | 263 | Lisp_Object |
| 261 | access_keymap (map, idx, t_ok) | 264 | access_keymap (map, idx, t_ok, noinherit) |
| 262 | Lisp_Object map; | 265 | Lisp_Object map; |
| 263 | Lisp_Object idx; | 266 | Lisp_Object idx; |
| 264 | int t_ok; | 267 | int t_ok; |
| 268 | int noinherit; | ||
| 265 | { | 269 | { |
| 270 | int noprefix = 0; | ||
| 271 | Lisp_Object val; | ||
| 272 | |||
| 266 | /* If idx is a list (some sort of mouse click, perhaps?), | 273 | /* If idx is a list (some sort of mouse click, perhaps?), |
| 267 | the index we want to use is the car of the list, which | 274 | the index we want to use is the car of the list, which |
| 268 | ought to be a symbol. */ | 275 | ought to be a symbol. */ |
| @@ -287,9 +294,21 @@ access_keymap (map, idx, t_ok) | |||
| 287 | 294 | ||
| 288 | switch (XTYPE (binding)) | 295 | switch (XTYPE (binding)) |
| 289 | { | 296 | { |
| 297 | case Lisp_Symbol: | ||
| 298 | /* If NOINHERIT, stop finding prefix definitions | ||
| 299 | after we pass a second occurrence of the `keymap' symbol. */ | ||
| 300 | if (noinherit && EQ (binding, Qkeymap) && ! EQ (tail, map)) | ||
| 301 | noprefix = 1; | ||
| 302 | break; | ||
| 303 | |||
| 290 | case Lisp_Cons: | 304 | case Lisp_Cons: |
| 291 | if (EQ (XCONS (binding)->car, idx)) | 305 | if (EQ (XCONS (binding)->car, idx)) |
| 292 | return XCONS (binding)->cdr; | 306 | { |
| 307 | val = XCONS (binding)->cdr; | ||
| 308 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) | ||
| 309 | return Qnil; | ||
| 310 | return val; | ||
| 311 | } | ||
| 293 | if (t_ok && EQ (XCONS (binding)->car, Qt)) | 312 | if (t_ok && EQ (XCONS (binding)->car, Qt)) |
| 294 | t_binding = XCONS (binding)->cdr; | 313 | t_binding = XCONS (binding)->cdr; |
| 295 | break; | 314 | break; |
| @@ -298,7 +317,12 @@ access_keymap (map, idx, t_ok) | |||
| 298 | if (XTYPE (idx) == Lisp_Int | 317 | if (XTYPE (idx) == Lisp_Int |
| 299 | && XINT (idx) >= 0 | 318 | && XINT (idx) >= 0 |
| 300 | && XINT (idx) < XVECTOR (binding)->size) | 319 | && XINT (idx) < XVECTOR (binding)->size) |
| 301 | return XVECTOR (binding)->contents[XINT (idx)]; | 320 | { |
| 321 | val = XVECTOR (binding)->contents[XINT (idx)]; | ||
| 322 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) | ||
| 323 | return Qnil; | ||
| 324 | return val; | ||
| 325 | } | ||
| 302 | break; | 326 | break; |
| 303 | } | 327 | } |
| 304 | 328 | ||
| @@ -330,7 +354,7 @@ get_keyelt (object) | |||
| 330 | map = get_keymap_1 (Fcar_safe (object), 0, 0); | 354 | map = get_keymap_1 (Fcar_safe (object), 0, 0); |
| 331 | tem = Fkeymapp (map); | 355 | tem = Fkeymapp (map); |
| 332 | if (!NILP (tem)) | 356 | if (!NILP (tem)) |
| 333 | object = access_keymap (map, Fcdr (object), 0); | 357 | object = access_keymap (map, Fcdr (object), 0, 0); |
| 334 | 358 | ||
| 335 | /* If the keymap contents looks like (STRING . DEFN), | 359 | /* If the keymap contents looks like (STRING . DEFN), |
| 336 | use DEFN. | 360 | use DEFN. |
| @@ -552,13 +576,11 @@ the front of KEYMAP.") | |||
| 552 | if (idx == length) | 576 | if (idx == length) |
| 553 | RETURN_UNGCPRO (store_in_keymap (keymap, c, def)); | 577 | RETURN_UNGCPRO (store_in_keymap (keymap, c, def)); |
| 554 | 578 | ||
| 555 | cmd = get_keyelt (access_keymap (keymap, c, 0)); | 579 | cmd = get_keyelt (access_keymap (keymap, c, 0, 1)); |
| 556 | 580 | ||
| 581 | /* If this key is undefined, make it a prefix. */ | ||
| 557 | if (NILP (cmd)) | 582 | if (NILP (cmd)) |
| 558 | { | 583 | cmd = define_as_prefix (keymap, c); |
| 559 | cmd = Fmake_sparse_keymap (Qnil); | ||
| 560 | store_in_keymap (keymap, c, cmd); | ||
| 561 | } | ||
| 562 | 584 | ||
| 563 | keymap = get_keymap_1 (cmd, 0, 1); | 585 | keymap = get_keymap_1 (cmd, 0, 1); |
| 564 | if (NILP (keymap)) | 586 | if (NILP (keymap)) |
| @@ -640,7 +662,7 @@ recognize the default bindings, just as `read-key-sequence' does.") | |||
| 640 | idx++; | 662 | idx++; |
| 641 | } | 663 | } |
| 642 | 664 | ||
| 643 | cmd = get_keyelt (access_keymap (keymap, c, t_ok)); | 665 | cmd = get_keyelt (access_keymap (keymap, c, t_ok, 0)); |
| 644 | if (idx == length) | 666 | if (idx == length) |
| 645 | return cmd; | 667 | return cmd; |
| 646 | 668 | ||
| @@ -652,6 +674,42 @@ recognize the default bindings, just as `read-key-sequence' does.") | |||
| 652 | } | 674 | } |
| 653 | } | 675 | } |
| 654 | 676 | ||
| 677 | /* Make KEYMAP define event C as a keymap (i.e., as a prefix). | ||
| 678 | Assume that currently it does not define C at all. | ||
| 679 | Return the keymap. */ | ||
| 680 | |||
| 681 | static Lisp_Object | ||
| 682 | define_as_prefix (keymap, c) | ||
| 683 | Lisp_Object keymap, c; | ||
| 684 | { | ||
| 685 | Lisp_Object inherit, cmd; | ||
| 686 | |||
| 687 | cmd = Fmake_sparse_keymap (Qnil); | ||
| 688 | /* If this key is defined as a prefix in an inherited keymap, | ||
| 689 | make it a prefix in this map, and make its definition | ||
| 690 | inherit the other prefix definition. */ | ||
| 691 | inherit = access_keymap (keymap, c, 0, 0); | ||
| 692 | if (NILP (inherit)) | ||
| 693 | { | ||
| 694 | /* If there's an inherited keymap | ||
| 695 | and it doesn't define this key, | ||
| 696 | make it define this key. */ | ||
| 697 | Lisp_Object tail; | ||
| 698 | |||
| 699 | for (tail = Fcdr (keymap); CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 700 | if (EQ (XCONS (tail)->car, Qkeymap)) | ||
| 701 | break; | ||
| 702 | |||
| 703 | if (!NILP (tail)) | ||
| 704 | inherit = define_as_prefix (tail, c); | ||
| 705 | } | ||
| 706 | |||
| 707 | cmd = nconc2 (cmd, inherit); | ||
| 708 | store_in_keymap (keymap, c, cmd); | ||
| 709 | |||
| 710 | return cmd; | ||
| 711 | } | ||
| 712 | |||
| 655 | /* Append a key to the end of a key sequence. We always make a vector. */ | 713 | /* Append a key to the end of a key sequence. We always make a vector. */ |
| 656 | 714 | ||
| 657 | Lisp_Object | 715 | Lisp_Object |