diff options
| author | Richard M. Stallman | 1996-06-06 20:25:48 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-06-06 20:25:48 +0000 |
| commit | 7d58ed9927a9ab6e4220f02975e46e0f39ba05aa (patch) | |
| tree | 9675d670294bb3b546034325c0a71be6a7024e6e /src | |
| parent | 1f4cd937080fb5e936e1d7be7c0b023b45bebcb7 (diff) | |
| download | emacs-7d58ed9927a9ab6e4220f02975e46e0f39ba05aa.tar.gz emacs-7d58ed9927a9ab6e4220f02975e46e0f39ba05aa.zip | |
(Fkeymap_parent, Fset_keymap_parent): New functions.
(fix_submap_inheritance): New function.
(access_keymap): Use fix_submap_inheritance.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keymap.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/keymap.c b/src/keymap.c index 5fd28583573..bb141e84e6c 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -258,8 +258,131 @@ get_keymap (object) | |||
| 258 | { | 258 | { |
| 259 | return get_keymap_1 (object, 1, 0); | 259 | return get_keymap_1 (object, 1, 0); |
| 260 | } | 260 | } |
| 261 | |||
| 262 | /* Return the parent map of the keymap MAP, or nil if it has none. | ||
| 263 | We assume that MAP is a valid keymap. */ | ||
| 264 | |||
| 265 | DEFUN ("keymap-parent", Fkeymap_parent, Skeymap_parent, 1, 1, 0, | ||
| 266 | "Return the parent keymap of KEYMAP.") | ||
| 267 | (keymap) | ||
| 268 | Lisp_Object keymap; | ||
| 269 | { | ||
| 270 | Lisp_Object list; | ||
| 271 | |||
| 272 | keymap = get_keymap_1 (keymap, 1, 1); | ||
| 273 | |||
| 274 | /* Skip past the initial element `keymap'. */ | ||
| 275 | list = XCONS (keymap)->cdr; | ||
| 276 | for (; CONSP (list); list = XCONS (list)->cdr) | ||
| 277 | { | ||
| 278 | /* See if there is another `keymap'. */ | ||
| 279 | if (EQ (Qkeymap, XCONS (list)->car)) | ||
| 280 | return list; | ||
| 281 | } | ||
| 282 | |||
| 283 | return Qnil; | ||
| 284 | } | ||
| 285 | |||
| 286 | /* Set the parent keymap of MAP to PARENT. */ | ||
| 287 | |||
| 288 | DEFUN ("set-keymap-parent", Fset_keymap_parent, Sset_keymap_parent, 2, 2, 0, | ||
| 289 | "Modify KEYMAP to set its parent map to PARENT.\n\ | ||
| 290 | PARENT should be nil or another keymap.") | ||
| 291 | (keymap, parent) | ||
| 292 | Lisp_Object keymap, parent; | ||
| 293 | { | ||
| 294 | Lisp_Object list, prev; | ||
| 295 | int i; | ||
| 261 | 296 | ||
| 297 | keymap = get_keymap_1 (keymap, 1, 1); | ||
| 298 | if (!NILP (parent)) | ||
| 299 | parent = get_keymap_1 (parent, 1, 1); | ||
| 262 | 300 | ||
| 301 | /* Skip past the initial element `keymap'. */ | ||
| 302 | prev = keymap; | ||
| 303 | while (1) | ||
| 304 | { | ||
| 305 | list = XCONS (prev)->cdr; | ||
| 306 | /* If there is a parent keymap here, replace it. | ||
| 307 | If we came to the end, add the parent in PREV. */ | ||
| 308 | if (! CONSP (list) || EQ (Qkeymap, XCONS (list)->car)) | ||
| 309 | { | ||
| 310 | XCONS (prev)->cdr = parent; | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | prev = list; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* Scan through for submaps, and set their parents too. */ | ||
| 317 | |||
| 318 | for (list = XCONS (keymap)->cdr; CONSP (list); list = XCONS (list)->cdr) | ||
| 319 | { | ||
| 320 | /* Stop the scan when we come to the parent. */ | ||
| 321 | if (EQ (XCONS (list)->car, Qkeymap)) | ||
| 322 | break; | ||
| 323 | |||
| 324 | /* If this element holds a prefix map, deal with it. */ | ||
| 325 | if (CONSP (XCONS (list)->car) | ||
| 326 | && CONSP (XCONS (XCONS (list)->car)->cdr)) | ||
| 327 | fix_submap_inheritance (keymap, XCONS (XCONS (list)->car)->car, | ||
| 328 | XCONS (XCONS (list)->car)->cdr); | ||
| 329 | |||
| 330 | if (VECTORP (XCONS (list)->car)) | ||
| 331 | for (i = 0; i < XVECTOR (XCONS (list)->car)->size; i++) | ||
| 332 | if (CONSP (XVECTOR (XCONS (list)->car)->contents[i])) | ||
| 333 | fix_submap_inheritance (keymap, make_number (i), | ||
| 334 | XVECTOR (XCONS (list)->car)->contents[i]); | ||
| 335 | } | ||
| 336 | |||
| 337 | return parent; | ||
| 338 | } | ||
| 339 | |||
| 340 | /* EVENT is defined in MAP as a prefix, and SUBMAP is its definition. | ||
| 341 | if EVENT is also a prefix in MAP's parent, | ||
| 342 | make sure that SUBMAP inherits that definition as its own parent. */ | ||
| 343 | |||
| 344 | fix_submap_inheritance (map, event, submap) | ||
| 345 | Lisp_Object map, event, submap; | ||
| 346 | { | ||
| 347 | Lisp_Object map_parent, parent_entry; | ||
| 348 | |||
| 349 | /* SUBMAP is a cons that we found as a key binding. | ||
| 350 | Discard the other things found in a menu key binding. */ | ||
| 351 | |||
| 352 | if (CONSP (submap) | ||
| 353 | && STRINGP (XCONS (submap)->car)) | ||
| 354 | { | ||
| 355 | submap = XCONS (submap)->cdr; | ||
| 356 | /* Also remove a menu help string, if any, | ||
| 357 | following the menu item name. */ | ||
| 358 | if (CONSP (submap) && STRINGP (XCONS (submap)->car)) | ||
| 359 | submap = XCONS (submap)->cdr; | ||
| 360 | /* Also remove the sublist that caches key equivalences, if any. */ | ||
| 361 | if (CONSP (submap) | ||
| 362 | && CONSP (XCONS (submap)->car)) | ||
| 363 | { | ||
| 364 | Lisp_Object carcar; | ||
| 365 | carcar = XCONS (XCONS (submap)->car)->car; | ||
| 366 | if (NILP (carcar) || VECTORP (carcar)) | ||
| 367 | submap = XCONS (submap)->cdr; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | /* If it isn't a keymap now, there's no work to do. */ | ||
| 372 | if (! CONSP (submap) | ||
| 373 | || ! EQ (XCONS (submap)->car, Qkeymap)) | ||
| 374 | return; | ||
| 375 | |||
| 376 | map_parent = Fkeymap_parent (map); | ||
| 377 | if (! NILP (map_parent)) | ||
| 378 | parent_entry = access_keymap (map_parent, event, 0, 0); | ||
| 379 | else | ||
| 380 | parent_entry = Qnil; | ||
| 381 | |||
| 382 | if (! EQ (parent_entry, submap)) | ||
| 383 | Fset_keymap_parent (submap, parent_entry); | ||
| 384 | } | ||
| 385 | |||
| 263 | /* Look up IDX in MAP. IDX may be any sort of event. | 386 | /* Look up IDX in MAP. IDX may be any sort of event. |
| 264 | Note that this does only one level of lookup; IDX must be a single | 387 | Note that this does only one level of lookup; IDX must be a single |
| 265 | event, not a sequence. | 388 | event, not a sequence. |
| @@ -320,6 +443,8 @@ access_keymap (map, idx, t_ok, noinherit) | |||
| 320 | val = XCONS (binding)->cdr; | 443 | val = XCONS (binding)->cdr; |
| 321 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) | 444 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) |
| 322 | return Qnil; | 445 | return Qnil; |
| 446 | if (CONSP (val)) | ||
| 447 | fix_submap_inheritance (map, idx, val); | ||
| 323 | return val; | 448 | return val; |
| 324 | } | 449 | } |
| 325 | if (t_ok && EQ (XCONS (binding)->car, Qt)) | 450 | if (t_ok && EQ (XCONS (binding)->car, Qt)) |
| @@ -332,6 +457,8 @@ access_keymap (map, idx, t_ok, noinherit) | |||
| 332 | val = XVECTOR (binding)->contents[XFASTINT (idx)]; | 457 | val = XVECTOR (binding)->contents[XFASTINT (idx)]; |
| 333 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) | 458 | if (noprefix && CONSP (val) && EQ (XCONS (val)->car, Qkeymap)) |
| 334 | return Qnil; | 459 | return Qnil; |
| 460 | if (CONSP (val)) | ||
| 461 | fix_submap_inheritance (map, idx, val); | ||
| 335 | return val; | 462 | return val; |
| 336 | } | 463 | } |
| 337 | } | 464 | } |
| @@ -759,6 +886,20 @@ define_as_prefix (keymap, c) | |||
| 759 | make it a prefix in this map, and make its definition | 886 | make it a prefix in this map, and make its definition |
| 760 | inherit the other prefix definition. */ | 887 | inherit the other prefix definition. */ |
| 761 | inherit = access_keymap (keymap, c, 0, 0); | 888 | inherit = access_keymap (keymap, c, 0, 0); |
| 889 | #if 0 | ||
| 890 | /* This code is needed to do the right thing in the following case: | ||
| 891 | keymap A inherits from B, | ||
| 892 | you define KEY as a prefix in A, | ||
| 893 | then later you define KEY as a prefix in B. | ||
| 894 | We want the old prefix definition in A to inherit from that in B. | ||
| 895 | It is hard to do that retroactively, so this code | ||
| 896 | creates the prefix in B right away. | ||
| 897 | |||
| 898 | But it turns out that this code causes problems immediately | ||
| 899 | when the prefix in A is defined: it causes B to define KEY | ||
| 900 | as a prefix with no subcommands. | ||
| 901 | |||
| 902 | So I took out this code. */ | ||
| 762 | if (NILP (inherit)) | 903 | if (NILP (inherit)) |
| 763 | { | 904 | { |
| 764 | /* If there's an inherited keymap | 905 | /* If there's an inherited keymap |
| @@ -773,6 +914,7 @@ define_as_prefix (keymap, c) | |||
| 773 | if (!NILP (tail)) | 914 | if (!NILP (tail)) |
| 774 | inherit = define_as_prefix (tail, c); | 915 | inherit = define_as_prefix (tail, c); |
| 775 | } | 916 | } |
| 917 | #endif | ||
| 776 | 918 | ||
| 777 | cmd = nconc2 (cmd, inherit); | 919 | cmd = nconc2 (cmd, inherit); |
| 778 | store_in_keymap (keymap, c, cmd); | 920 | store_in_keymap (keymap, c, cmd); |
| @@ -2648,6 +2790,8 @@ and applies even for keys that have ordinary bindings."); | |||
| 2648 | staticpro (&Qnon_ascii); | 2790 | staticpro (&Qnon_ascii); |
| 2649 | 2791 | ||
| 2650 | defsubr (&Skeymapp); | 2792 | defsubr (&Skeymapp); |
| 2793 | defsubr (&Skeymap_parent); | ||
| 2794 | defsubr (&Sset_keymap_parent); | ||
| 2651 | defsubr (&Smake_keymap); | 2795 | defsubr (&Smake_keymap); |
| 2652 | defsubr (&Smake_sparse_keymap); | 2796 | defsubr (&Smake_sparse_keymap); |
| 2653 | defsubr (&Scopy_keymap); | 2797 | defsubr (&Scopy_keymap); |