diff options
| author | Stefan Monnier | 2009-09-10 16:19:52 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2009-09-10 16:19:52 +0000 |
| commit | a88a5372fd9b93a3f8e3a3264de867f0ee0590cd (patch) | |
| tree | 8c62d5d4b38e1227ea0f54bc193d3328f6be8a89 /src | |
| parent | a126db16fa29e84987cf4e37434eeaebc43d72bb (diff) | |
| download | emacs-a88a5372fd9b93a3f8e3a3264de867f0ee0590cd.tar.gz emacs-a88a5372fd9b93a3f8e3a3264de867f0ee0590cd.zip | |
* keymap.c (where_is_internal_data): Make noindirect a boolean.
(where_is_internal): Strip it down to only traverse the keymaps.
Move the cache handling from Fwhere_is_internal to here.
(Fwhere_is_internal): Move the handling of remapping and the choice of
the best binding from where_is_internal to here.
Unify the cached/noncached paths, so remapping is also handled
correctly when the cache is used, and so the cache can be used to
speed up remap-handling when applicable.
Give preference to non-remapped bindings.
* doc.c (Fsubstitute_command_keys): Let Fwhere_is_internal's prefer
non-remapped bindings.
* keyboard.c (parse_menu_item): Let Fwhere_is_internal handle
command remapping.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/doc.c | 5 | ||||
| -rw-r--r-- | src/keyboard.c | 6 | ||||
| -rw-r--r-- | src/keymap.c | 334 |
4 files changed, 176 insertions, 183 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 09967b68d3f..c530325ed69 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,19 @@ | |||
| 1 | 2009-09-10 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2009-09-10 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * keymap.c (where_is_internal_data): Make noindirect a boolean. | ||
| 4 | (where_is_internal): Strip it down to only traverse the keymaps. | ||
| 5 | Move the cache handling from Fwhere_is_internal to here. | ||
| 6 | (Fwhere_is_internal): Move the handling of remapping and the choice of | ||
| 7 | the best binding from where_is_internal to here. | ||
| 8 | Unify the cached/noncached paths, so remapping is also handled | ||
| 9 | correctly when the cache is used, and so the cache can be used to | ||
| 10 | speed up remap-handling when applicable. | ||
| 11 | Give preference to non-remapped bindings. | ||
| 12 | * doc.c (Fsubstitute_command_keys): Let Fwhere_is_internal's prefer | ||
| 13 | non-remapped bindings. | ||
| 14 | * keyboard.c (parse_menu_item): Let Fwhere_is_internal handle | ||
| 15 | command remapping. | ||
| 16 | |||
| 3 | * xdisp.c (display_mode_element): Move list length limit from 50 to | 17 | * xdisp.c (display_mode_element): Move list length limit from 50 to |
| 4 | 5000 (see thread starting with <xbaik5174uqu.fsf@cam.ac.uk>). | 18 | 5000 (see thread starting with <xbaik5174uqu.fsf@cam.ac.uk>). |
| 5 | 19 | ||
| @@ -802,10 +802,7 @@ a new string, without any text properties, is returned. */) | |||
| 802 | name = Fintern (make_string (start, length_byte), Qnil); | 802 | name = Fintern (make_string (start, length_byte), Qnil); |
| 803 | 803 | ||
| 804 | do_remap: | 804 | do_remap: |
| 805 | /* Ignore remappings unless there are no ordinary bindings. */ | 805 | tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil); |
| 806 | tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qt); | ||
| 807 | if (NILP (tem)) | ||
| 808 | tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil); | ||
| 809 | 806 | ||
| 810 | if (VECTORP (tem) && XVECTOR (tem)->size > 1 | 807 | if (VECTORP (tem) && XVECTOR (tem)->size > 1 |
| 811 | && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1)) | 808 | && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1)) |
diff --git a/src/keyboard.c b/src/keyboard.c index dfb625675a4..04af3585897 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -8158,11 +8158,7 @@ parse_menu_item (item, notreal, inmenubar) | |||
| 8158 | && SYMBOLP (XSYMBOL (def)->function) | 8158 | && SYMBOLP (XSYMBOL (def)->function) |
| 8159 | && ! NILP (Fget (def, Qmenu_alias))) | 8159 | && ! NILP (Fget (def, Qmenu_alias))) |
| 8160 | def = XSYMBOL (def)->function; | 8160 | def = XSYMBOL (def)->function; |
| 8161 | tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt); | 8161 | tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qnil); |
| 8162 | |||
| 8163 | /* Don't display remap bindings.*/ | ||
| 8164 | if (VECTORP (tem) && ASIZE (tem) > 0 && EQ (AREF (tem, 0), Qremap)) | ||
| 8165 | tem = Qnil; | ||
| 8166 | 8162 | ||
| 8167 | XSETCAR (cachelist, tem); | 8163 | XSETCAR (cachelist, tem); |
| 8168 | if (NILP (tem)) | 8164 | if (NILP (tem)) |
diff --git a/src/keymap.c b/src/keymap.c index dcf8e19900c..111352c7f8a 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -2640,7 +2640,6 @@ preferred_sequence_p (seq) | |||
| 2640 | 2640 | ||
| 2641 | /* where-is - finding a command in a set of keymaps. */ | 2641 | /* where-is - finding a command in a set of keymaps. */ |
| 2642 | 2642 | ||
| 2643 | static Lisp_Object where_is_internal (); | ||
| 2644 | static void where_is_internal_1 P_ ((Lisp_Object key, Lisp_Object binding, | 2643 | static void where_is_internal_1 P_ ((Lisp_Object key, Lisp_Object binding, |
| 2645 | Lisp_Object args, void *data)); | 2644 | Lisp_Object args, void *data)); |
| 2646 | 2645 | ||
| @@ -2672,23 +2671,49 @@ shadow_lookup (shadow, key, flag) | |||
| 2672 | static Lisp_Object Vmouse_events; | 2671 | static Lisp_Object Vmouse_events; |
| 2673 | 2672 | ||
| 2674 | struct where_is_internal_data { | 2673 | struct where_is_internal_data { |
| 2675 | Lisp_Object definition, noindirect, this, last; | 2674 | Lisp_Object definition, this, last; |
| 2676 | int last_is_meta; | 2675 | int last_is_meta, noindirect; |
| 2677 | Lisp_Object sequences; | 2676 | Lisp_Object sequences; |
| 2678 | }; | 2677 | }; |
| 2679 | 2678 | ||
| 2680 | /* This function can GC if Flookup_key autoloads any keymaps. */ | 2679 | /* This function can't GC, AFAIK. */ |
| 2680 | /* Return the list of bindings found. This list is ordered "longest | ||
| 2681 | to shortest". It may include bindings that are actually shadowed | ||
| 2682 | by others, as well as duplicate bindings and remapping bindings. | ||
| 2683 | The list returned is potentially shared with where_is_cache, so | ||
| 2684 | be careful not to modify it via side-effects. */ | ||
| 2681 | 2685 | ||
| 2682 | static Lisp_Object | 2686 | static Lisp_Object |
| 2683 | where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | 2687 | where_is_internal (Lisp_Object definition, Lisp_Object keymaps, |
| 2684 | Lisp_Object definition, keymaps; | 2688 | int noindirect, int nomenus) |
| 2685 | Lisp_Object firstonly, noindirect, no_remap; | ||
| 2686 | { | 2689 | { |
| 2687 | Lisp_Object maps = Qnil; | 2690 | Lisp_Object maps = Qnil; |
| 2688 | Lisp_Object found, sequences; | 2691 | Lisp_Object found; |
| 2689 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | 2692 | struct where_is_internal_data data; |
| 2690 | /* 1 means ignore all menu bindings entirely. */ | 2693 | |
| 2691 | int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); | 2694 | /* Only important use of caching is for the menubar |
| 2695 | (i.e. where-is-internal called with (def nil t nil nil)). */ | ||
| 2696 | if (nomenus && !noindirect) | ||
| 2697 | { | ||
| 2698 | /* Check heuristic-consistency of the cache. */ | ||
| 2699 | if (NILP (Fequal (keymaps, where_is_cache_keymaps))) | ||
| 2700 | where_is_cache = Qnil; | ||
| 2701 | |||
| 2702 | if (NILP (where_is_cache)) | ||
| 2703 | { | ||
| 2704 | /* We need to create the cache. */ | ||
| 2705 | Lisp_Object args[2]; | ||
| 2706 | where_is_cache = Fmake_hash_table (0, args); | ||
| 2707 | where_is_cache_keymaps = Qt; | ||
| 2708 | } | ||
| 2709 | else | ||
| 2710 | /* We can reuse the cache. */ | ||
| 2711 | return Fgethash (definition, where_is_cache, Qnil); | ||
| 2712 | } | ||
| 2713 | else | ||
| 2714 | /* Kill the cache so that where_is_internal_1 doesn't think | ||
| 2715 | we're filling it up. */ | ||
| 2716 | where_is_cache = Qnil; | ||
| 2692 | 2717 | ||
| 2693 | found = keymaps; | 2718 | found = keymaps; |
| 2694 | while (CONSP (found)) | 2719 | while (CONSP (found)) |
| @@ -2699,22 +2724,11 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2699 | found = XCDR (found); | 2724 | found = XCDR (found); |
| 2700 | } | 2725 | } |
| 2701 | 2726 | ||
| 2702 | GCPRO5 (definition, keymaps, maps, found, sequences); | 2727 | data.sequences = Qnil; |
| 2703 | found = Qnil; | ||
| 2704 | sequences = Qnil; | ||
| 2705 | |||
| 2706 | /* If this command is remapped, then it has no key bindings | ||
| 2707 | of its own. */ | ||
| 2708 | if (NILP (no_remap) | ||
| 2709 | && SYMBOLP (definition) | ||
| 2710 | && !NILP (Fcommand_remapping (definition, Qnil, keymaps))) | ||
| 2711 | RETURN_UNGCPRO (Qnil); | ||
| 2712 | |||
| 2713 | for (; CONSP (maps); maps = XCDR (maps)) | 2728 | for (; CONSP (maps); maps = XCDR (maps)) |
| 2714 | { | 2729 | { |
| 2715 | /* Key sequence to reach map, and the map that it reaches */ | 2730 | /* Key sequence to reach map, and the map that it reaches */ |
| 2716 | register Lisp_Object this, map, tem; | 2731 | register Lisp_Object this, map, tem; |
| 2717 | struct where_is_internal_data data; | ||
| 2718 | 2732 | ||
| 2719 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into | 2733 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into |
| 2720 | [M-CHAR] sequences, check if last character of the sequence | 2734 | [M-CHAR] sequences, check if last character of the sequence |
| @@ -2744,105 +2758,24 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2744 | data.this = this; | 2758 | data.this = this; |
| 2745 | data.last = last; | 2759 | data.last = last; |
| 2746 | data.last_is_meta = last_is_meta; | 2760 | data.last_is_meta = last_is_meta; |
| 2747 | data.sequences = Qnil; | ||
| 2748 | 2761 | ||
| 2749 | if (CONSP (map)) | 2762 | if (CONSP (map)) |
| 2750 | map_keymap (map, where_is_internal_1, Qnil, &data, 0); | 2763 | map_keymap (map, where_is_internal_1, Qnil, &data, 0); |
| 2751 | |||
| 2752 | sequences = data.sequences; | ||
| 2753 | |||
| 2754 | while (CONSP (sequences)) | ||
| 2755 | { | ||
| 2756 | Lisp_Object sequence, remapped, function; | ||
| 2757 | |||
| 2758 | sequence = XCAR (sequences); | ||
| 2759 | sequences = XCDR (sequences); | ||
| 2760 | |||
| 2761 | /* Verify that this key binding is not shadowed by another | ||
| 2762 | binding for the same key, before we say it exists. | ||
| 2763 | |||
| 2764 | Mechanism: look for local definition of this key and if | ||
| 2765 | it is defined and does not match what we found then | ||
| 2766 | ignore this key. | ||
| 2767 | |||
| 2768 | Either nil or number as value from Flookup_key | ||
| 2769 | means undefined. */ | ||
| 2770 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2771 | continue; | ||
| 2772 | |||
| 2773 | /* If the current sequence is a command remapping with | ||
| 2774 | format [remap COMMAND], find the key sequences | ||
| 2775 | which run COMMAND, and use those sequences instead. */ | ||
| 2776 | if (NILP (no_remap) | ||
| 2777 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 | ||
| 2778 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2779 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2780 | remapped = where_is_internal (function, keymaps, firstonly, | ||
| 2781 | noindirect, Qt); | ||
| 2782 | else | ||
| 2783 | remapped = Fcons (sequence, Qnil); | ||
| 2784 | |||
| 2785 | for (; CONSP (remapped); | ||
| 2786 | sequence = XCAR (remapped), remapped = XCDR (remapped)) | ||
| 2787 | { | ||
| 2788 | /* Don't annoy user with strings from a menu such as the | ||
| 2789 | entries from the "Edit => Paste from Kill Menu". | ||
| 2790 | Change them all to "(any string)", so that there | ||
| 2791 | seems to be only one menu item to report. */ | ||
| 2792 | if (! NILP (sequence)) | ||
| 2793 | { | ||
| 2794 | Lisp_Object tem; | ||
| 2795 | tem = Faref (sequence, make_number (ASIZE (sequence) - 1)); | ||
| 2796 | if (STRINGP (tem)) | ||
| 2797 | Faset (sequence, make_number (ASIZE (sequence) - 1), | ||
| 2798 | build_string ("(any string)")); | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | /* It is a true unshadowed match. Record it, unless it's already | ||
| 2802 | been seen (as could happen when inheriting keymaps). */ | ||
| 2803 | if (NILP (Fmember (sequence, found))) | ||
| 2804 | found = Fcons (sequence, found); | ||
| 2805 | |||
| 2806 | /* If firstonly is Qnon_ascii, then we can return the first | ||
| 2807 | binding we find. If firstonly is not Qnon_ascii but not | ||
| 2808 | nil, then we should return the first ascii-only binding | ||
| 2809 | we find. */ | ||
| 2810 | if (EQ (firstonly, Qnon_ascii)) | ||
| 2811 | RETURN_UNGCPRO (sequence); | ||
| 2812 | else if (!NILP (firstonly) | ||
| 2813 | && 2 == preferred_sequence_p (sequence)) | ||
| 2814 | RETURN_UNGCPRO (sequence); | ||
| 2815 | |||
| 2816 | } | ||
| 2817 | } | ||
| 2818 | } | 2764 | } |
| 2819 | 2765 | ||
| 2820 | UNGCPRO; | 2766 | if (nomenus && !noindirect) |
| 2821 | 2767 | /* Remember for which keymaps this cache was built. | |
| 2822 | found = Fnreverse (found); | 2768 | We do it here (late) because we want to keep where_is_cache_keymaps |
| 2769 | set to t while the cache isn't fully filled. */ | ||
| 2770 | where_is_cache_keymaps = keymaps; | ||
| 2823 | 2771 | ||
| 2824 | /* firstonly may have been t, but we may have gone all the way through | 2772 | return data.sequences; |
| 2825 | the keymaps without finding an all-ASCII key sequence. So just | ||
| 2826 | return the best we could find. */ | ||
| 2827 | if (NILP (firstonly)) | ||
| 2828 | return found; | ||
| 2829 | else if (where_is_preferred_modifier == 0) | ||
| 2830 | return Fcar (found); | ||
| 2831 | else | ||
| 2832 | { /* Maybe we did not find a preferred_modifier binding, but we did find | ||
| 2833 | some ASCII binding. */ | ||
| 2834 | Lisp_Object bindings = found; | ||
| 2835 | while (CONSP (bindings)) | ||
| 2836 | if (preferred_sequence_p (XCAR (bindings))) | ||
| 2837 | return XCAR (bindings); | ||
| 2838 | else | ||
| 2839 | bindings = XCDR (bindings); | ||
| 2840 | return Fcar (found); | ||
| 2841 | } | ||
| 2842 | } | 2773 | } |
| 2843 | 2774 | ||
| 2844 | static Lisp_Object Vwhere_is_preferred_modifier; | 2775 | static Lisp_Object Vwhere_is_preferred_modifier; |
| 2845 | 2776 | ||
| 2777 | /* This function can GC if Flookup_key autoloads any keymaps. */ | ||
| 2778 | |||
| 2846 | DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0, | 2779 | DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0, |
| 2847 | doc: /* Return list of keys that invoke DEFINITION. | 2780 | doc: /* Return list of keys that invoke DEFINITION. |
| 2848 | If KEYMAP is a keymap, search only KEYMAP and the global keymap. | 2781 | If KEYMAP is a keymap, search only KEYMAP and the global keymap. |
| @@ -2868,10 +2801,23 @@ remapped command in the returned list. */) | |||
| 2868 | Lisp_Object definition, keymap; | 2801 | Lisp_Object definition, keymap; |
| 2869 | Lisp_Object firstonly, noindirect, no_remap; | 2802 | Lisp_Object firstonly, noindirect, no_remap; |
| 2870 | { | 2803 | { |
| 2871 | Lisp_Object sequences, keymaps; | 2804 | /* The keymaps in which to search. */ |
| 2805 | Lisp_Object keymaps; | ||
| 2806 | /* Potentially relevant bindings in "shortest to longest" order. */ | ||
| 2807 | Lisp_Object sequences = Qnil, | ||
| 2808 | /* Actually relevant bindings. */ | ||
| 2809 | Lisp_Object found = Qnil; | ||
| 2872 | /* 1 means ignore all menu bindings entirely. */ | 2810 | /* 1 means ignore all menu bindings entirely. */ |
| 2873 | int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); | 2811 | int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii); |
| 2874 | Lisp_Object result; | 2812 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; |
| 2813 | /* List of sequences found via remapping. Keep them in a separate | ||
| 2814 | variable, so as to push them later, since we prefer | ||
| 2815 | non-remapped binding. */ | ||
| 2816 | Lisp_Object remapped_sequences = Qnil; | ||
| 2817 | /* Whether or not we're handling remapped sequences. This is needed | ||
| 2818 | because remapping is not done recursively by Fcommand_remapping: you | ||
| 2819 | can't remap and remapped command. */ | ||
| 2820 | int remapped = 0; | ||
| 2875 | 2821 | ||
| 2876 | /* Refresh the C version of the modifier preference. */ | 2822 | /* Refresh the C version of the modifier preference. */ |
| 2877 | where_is_preferred_modifier | 2823 | where_is_preferred_modifier |
| @@ -2885,74 +2831,114 @@ remapped command in the returned list. */) | |||
| 2885 | else | 2831 | else |
| 2886 | keymaps = Fcurrent_active_maps (Qnil, Qnil); | 2832 | keymaps = Fcurrent_active_maps (Qnil, Qnil); |
| 2887 | 2833 | ||
| 2888 | /* Only use caching for the menubar (i.e. called with (def nil t nil). | 2834 | GCPRO5 (definition, keymaps, found, sequences, remapped_sequences); |
| 2889 | We don't really need to check `keymap'. */ | ||
| 2890 | if (nomenus && NILP (noindirect) && NILP (keymap)) | ||
| 2891 | { | ||
| 2892 | Lisp_Object *defns; | ||
| 2893 | int i, n; | ||
| 2894 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; | ||
| 2895 | 2835 | ||
| 2896 | /* Check heuristic-consistency of the cache. */ | 2836 | /* If this command is remapped, then it has no key bindings of its own. |
| 2897 | if (NILP (Fequal (keymaps, where_is_cache_keymaps))) | 2837 | FIXME: Actually, this is not quite right: if A is remapped to |
| 2898 | where_is_cache = Qnil; | 2838 | `definition', then bindings to A will actually bind the key to |
| 2839 | `definition' despite the remapping from `definition' to something else. | ||
| 2840 | Another corner case is if `definition' is remapped to itself. */ | ||
| 2841 | if (NILP (no_remap) | ||
| 2842 | && SYMBOLP (definition) | ||
| 2843 | && !NILP (Fcommand_remapping (definition, Qnil, keymaps))) | ||
| 2844 | RETURN_UNGCPRO (Qnil); | ||
| 2899 | 2845 | ||
| 2900 | if (NILP (where_is_cache)) | 2846 | sequences = Freverse (where_is_internal (definition, keymaps, |
| 2847 | !NILP (noindirect), nomenus)); | ||
| 2848 | |||
| 2849 | while (CONSP (sequences)) | ||
| 2850 | { | ||
| 2851 | Lisp_Object sequence, function; | ||
| 2852 | |||
| 2853 | sequence = XCAR (sequences); | ||
| 2854 | sequences = XCDR (sequences); | ||
| 2855 | |||
| 2856 | if (NILP (sequences) && !remapped) | ||
| 2901 | { | 2857 | { |
| 2902 | /* We need to create the cache. */ | 2858 | sequences = remapped_sequences; |
| 2903 | Lisp_Object args[2]; | 2859 | remapped = 1; |
| 2904 | where_is_cache = Fmake_hash_table (0, args); | 2860 | } |
| 2905 | where_is_cache_keymaps = Qt; | ||
| 2906 | 2861 | ||
| 2907 | /* Fill in the cache. */ | 2862 | /* Verify that this key binding is not shadowed by another |
| 2908 | GCPRO5 (definition, keymaps, firstonly, noindirect, no_remap); | 2863 | binding for the same key, before we say it exists. |
| 2909 | where_is_internal (definition, keymaps, firstonly, noindirect, no_remap); | 2864 | |
| 2910 | UNGCPRO; | 2865 | Mechanism: look for local definition of this key and if |
| 2866 | it is defined and does not match what we found then | ||
| 2867 | ignore this key. | ||
| 2868 | |||
| 2869 | Either nil or number as value from Flookup_key | ||
| 2870 | means undefined. */ | ||
| 2871 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2872 | continue; | ||
| 2911 | 2873 | ||
| 2912 | where_is_cache_keymaps = keymaps; | 2874 | /* If the current sequence is a command remapping with |
| 2875 | format [remap COMMAND], find the key sequences | ||
| 2876 | which run COMMAND, and use those sequences instead. */ | ||
| 2877 | if (NILP (no_remap) && !remapped | ||
| 2878 | && VECTORP (sequence) && ASIZE (sequence) == 2 | ||
| 2879 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2880 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2881 | { | ||
| 2882 | Lisp_Object seqs = where_is_internal (function, keymaps, | ||
| 2883 | !NILP (noindirect), nomenus); | ||
| 2884 | Lisp_Object args[2]; | ||
| 2885 | args[0] = Freverse (seqs); | ||
| 2886 | args[1] = remapped_sequences; | ||
| 2887 | remapped_sequences = Fnconc (2, args); | ||
| 2888 | continue; | ||
| 2913 | } | 2889 | } |
| 2914 | 2890 | ||
| 2915 | /* We want to process definitions from the last to the first. | 2891 | /* Don't annoy user with strings from a menu such as the |
| 2916 | Instead of consing, copy definitions to a vector and step | 2892 | entries from the "Edit => Paste from Kill Menu". |
| 2917 | over that vector. */ | 2893 | Change them all to "(any string)", so that there |
| 2918 | sequences = Fgethash (definition, where_is_cache, Qnil); | 2894 | seems to be only one menu item to report. */ |
| 2919 | n = XINT (Flength (sequences)); | 2895 | if (! NILP (sequence)) |
| 2920 | defns = (Lisp_Object *) alloca (n * sizeof *defns); | 2896 | { |
| 2921 | for (i = 0; CONSP (sequences); sequences = XCDR (sequences)) | 2897 | Lisp_Object tem; |
| 2922 | defns[i++] = XCAR (sequences); | 2898 | tem = Faref (sequence, make_number (ASIZE (sequence) - 1)); |
| 2923 | 2899 | if (STRINGP (tem)) | |
| 2924 | /* Verify that the key bindings are not shadowed. Note that | 2900 | Faset (sequence, make_number (ASIZE (sequence) - 1), |
| 2925 | the following can GC. */ | 2901 | build_string ("(any string)")); |
| 2926 | GCPRO2 (definition, keymaps); | 2902 | } |
| 2927 | result = Qnil; | 2903 | |
| 2928 | { | 2904 | /* It is a true unshadowed match. Record it, unless it's already |
| 2929 | int best_pref = -1; | 2905 | been seen (as could happen when inheriting keymaps). */ |
| 2930 | int j = -1; | 2906 | if (NILP (Fmember (sequence, found))) |
| 2931 | for (i = n - 1; i >= 0; --i) | 2907 | found = Fcons (sequence, found); |
| 2932 | { | 2908 | |
| 2933 | int pref = preferred_sequence_p (defns[i]); | 2909 | /* If firstonly is Qnon_ascii, then we can return the first |
| 2934 | if (pref > best_pref | 2910 | binding we find. If firstonly is not Qnon_ascii but not |
| 2935 | && EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) | 2911 | nil, then we should return the first ascii-only binding |
| 2936 | { | 2912 | we find. */ |
| 2937 | j = i; | 2913 | if (EQ (firstonly, Qnon_ascii)) |
| 2938 | best_pref = pref; | 2914 | RETURN_UNGCPRO (sequence); |
| 2939 | if (best_pref == 2) | 2915 | else if (!NILP (firstonly) |
| 2940 | break; | 2916 | && 2 == preferred_sequence_p (sequence)) |
| 2941 | } | 2917 | RETURN_UNGCPRO (sequence); |
| 2942 | } | ||
| 2943 | result = j >= 0 ? defns[j] : Qnil; | ||
| 2944 | } | ||
| 2945 | UNGCPRO; | ||
| 2946 | } | 2918 | } |
| 2919 | |||
| 2920 | UNGCPRO; | ||
| 2921 | |||
| 2922 | found = Fnreverse (found); | ||
| 2923 | |||
| 2924 | /* firstonly may have been t, but we may have gone all the way through | ||
| 2925 | the keymaps without finding an all-ASCII key sequence. So just | ||
| 2926 | return the best we could find. */ | ||
| 2927 | if (NILP (firstonly)) | ||
| 2928 | return found; | ||
| 2929 | else if (where_is_preferred_modifier == 0) | ||
| 2930 | return Fcar (found); | ||
| 2947 | else | 2931 | else |
| 2948 | { | 2932 | { /* Maybe we did not find a preferred_modifier binding, but we did find |
| 2949 | /* Kill the cache so that where_is_internal_1 doesn't think | 2933 | some ASCII binding. */ |
| 2950 | we're filling it up. */ | 2934 | Lisp_Object bindings = found; |
| 2951 | where_is_cache = Qnil; | 2935 | while (CONSP (bindings)) |
| 2952 | result = where_is_internal (definition, keymaps, firstonly, noindirect, no_remap); | 2936 | if (preferred_sequence_p (XCAR (bindings))) |
| 2937 | return XCAR (bindings); | ||
| 2938 | else | ||
| 2939 | bindings = XCDR (bindings); | ||
| 2940 | return Fcar (found); | ||
| 2953 | } | 2941 | } |
| 2954 | |||
| 2955 | return result; | ||
| 2956 | } | 2942 | } |
| 2957 | 2943 | ||
| 2958 | /* This function can GC because get_keyelt can. */ | 2944 | /* This function can GC because get_keyelt can. */ |
| @@ -2964,14 +2950,14 @@ where_is_internal_1 (key, binding, args, data) | |||
| 2964 | { | 2950 | { |
| 2965 | struct where_is_internal_data *d = data; /* Cast! */ | 2951 | struct where_is_internal_data *d = data; /* Cast! */ |
| 2966 | Lisp_Object definition = d->definition; | 2952 | Lisp_Object definition = d->definition; |
| 2967 | Lisp_Object noindirect = d->noindirect; | 2953 | int noindirect = d->noindirect; |
| 2968 | Lisp_Object this = d->this; | 2954 | Lisp_Object this = d->this; |
| 2969 | Lisp_Object last = d->last; | 2955 | Lisp_Object last = d->last; |
| 2970 | int last_is_meta = d->last_is_meta; | 2956 | int last_is_meta = d->last_is_meta; |
| 2971 | Lisp_Object sequence; | 2957 | Lisp_Object sequence; |
| 2972 | 2958 | ||
| 2973 | /* Search through indirections unless that's not wanted. */ | 2959 | /* Search through indirections unless that's not wanted. */ |
| 2974 | if (NILP (noindirect)) | 2960 | if (noindirect) |
| 2975 | binding = get_keyelt (binding, 0); | 2961 | binding = get_keyelt (binding, 0); |
| 2976 | 2962 | ||
| 2977 | /* End this iteration if this element does not match | 2963 | /* End this iteration if this element does not match |