diff options
| author | Stefan Monnier | 2007-07-10 15:20:15 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2007-07-10 15:20:15 +0000 |
| commit | fab84e3cfb291680f863074023e29b8daea0ed82 (patch) | |
| tree | 76189887a98a21a27c0afd4a36bc69b0012e3fb8 /src | |
| parent | a1be1ce88b203a86b4f52b9f6e8360557098009a (diff) | |
| download | emacs-fab84e3cfb291680f863074023e29b8daea0ed82.tar.gz emacs-fab84e3cfb291680f863074023e29b8daea0ed82.zip | |
(struct accessible_keymaps_data, struct where_is_internal_data): New structs.
(accessible_keymaps_1, where_is_internal_1): Use them to change
interface to adhere to the one used by map_keymap.
(Faccessible_keymaps, where_is_internal): Use map_keymap.
(accessible_keymaps_char_table, where_is_internal_2): Remove.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 7 | ||||
| -rw-r--r-- | src/keymap.c | 370 |
2 files changed, 135 insertions, 242 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 5c8a1db1dc5..8c4cbe1c214 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,12 @@ | |||
| 1 | 2007-07-10 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2007-07-10 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * keymap.c (struct accessible_keymaps_data) | ||
| 4 | (struct where_is_internal_data): New structures. | ||
| 5 | (accessible_keymaps_1, where_is_internal_1): Use them to change | ||
| 6 | interface to adhere to the one used by map_keymap. | ||
| 7 | (Faccessible_keymaps, where_is_internal): Use map_keymap. | ||
| 8 | (accessible_keymaps_char_table, where_is_internal_2): Remove. | ||
| 9 | |||
| 3 | * keymap.h (map_keymap_function_t): More informative prototype. | 10 | * keymap.h (map_keymap_function_t): More informative prototype. |
| 4 | 11 | ||
| 5 | 2007-07-10 Guanpeng Xu <herberteuler@hotmail.com> | 12 | 2007-07-10 Guanpeng Xu <herberteuler@hotmail.com> |
diff --git a/src/keymap.c b/src/keymap.c index f9071f9c633..e008fceed99 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -1156,7 +1156,7 @@ binding KEY to DEF is added at the front of KEYMAP. */) | |||
| 1156 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) | 1156 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) |
| 1157 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); | 1157 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); |
| 1158 | 1158 | ||
| 1159 | meta_bit = (VECTORP (key) || STRINGP (key) && STRING_MULTIBYTE (key) | 1159 | meta_bit = (VECTORP (key) || (STRINGP (key) && STRING_MULTIBYTE (key)) |
| 1160 | ? meta_modifier : 0x80); | 1160 | ? meta_modifier : 0x80); |
| 1161 | 1161 | ||
| 1162 | if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0))) | 1162 | if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0))) |
| @@ -2046,12 +2046,23 @@ DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_ | |||
| 2046 | 2046 | ||
| 2047 | /* Help functions for describing and documenting keymaps. */ | 2047 | /* Help functions for describing and documenting keymaps. */ |
| 2048 | 2048 | ||
| 2049 | struct accessible_keymaps_data { | ||
| 2050 | Lisp_Object maps, tail, thisseq; | ||
| 2051 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2052 | int is_metized; | ||
| 2053 | }; | ||
| 2049 | 2054 | ||
| 2050 | static void | 2055 | static void |
| 2051 | accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized) | 2056 | accessible_keymaps_1 (key, cmd, args, data) |
| 2052 | Lisp_Object maps, tail, thisseq, key, cmd; | 2057 | Lisp_Object key, cmd, args; |
| 2053 | int is_metized; /* If 1, `key' is assumed to be INTEGERP. */ | 2058 | /* Use void* to be compatible with map_keymap_function_t. */ |
| 2059 | void *data; | ||
| 2054 | { | 2060 | { |
| 2061 | struct accessible_keymaps_data *d = data; /* Cast! */ | ||
| 2062 | Lisp_Object maps = d->maps; | ||
| 2063 | Lisp_Object tail = d->tail; | ||
| 2064 | Lisp_Object thisseq = d->thisseq; | ||
| 2065 | int is_metized = d->is_metized && INTEGERP (key); | ||
| 2055 | Lisp_Object tem; | 2066 | Lisp_Object tem; |
| 2056 | 2067 | ||
| 2057 | cmd = get_keymap (get_keyelt (cmd, 0), 0, 0); | 2068 | cmd = get_keymap (get_keyelt (cmd, 0), 0, 0); |
| @@ -2105,17 +2116,6 @@ accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized) | |||
| 2105 | } | 2116 | } |
| 2106 | } | 2117 | } |
| 2107 | 2118 | ||
| 2108 | static void | ||
| 2109 | accessible_keymaps_char_table (args, index, cmd) | ||
| 2110 | Lisp_Object args, index, cmd; | ||
| 2111 | { | ||
| 2112 | accessible_keymaps_1 (index, cmd, | ||
| 2113 | XCAR (XCAR (args)), | ||
| 2114 | XCAR (XCDR (args)), | ||
| 2115 | XCDR (XCDR (args)), | ||
| 2116 | XINT (XCDR (XCAR (args)))); | ||
| 2117 | } | ||
| 2118 | |||
| 2119 | /* This function cannot GC. */ | 2119 | /* This function cannot GC. */ |
| 2120 | 2120 | ||
| 2121 | DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, | 2121 | DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, |
| @@ -2130,14 +2130,11 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2130 | Lisp_Object keymap, prefix; | 2130 | Lisp_Object keymap, prefix; |
| 2131 | { | 2131 | { |
| 2132 | Lisp_Object maps, tail; | 2132 | Lisp_Object maps, tail; |
| 2133 | int prefixlen = 0; | 2133 | int prefixlen = XINT (Flength (prefix)); |
| 2134 | 2134 | ||
| 2135 | /* no need for gcpro because we don't autoload any keymaps. */ | 2135 | /* no need for gcpro because we don't autoload any keymaps. */ |
| 2136 | 2136 | ||
| 2137 | if (!NILP (prefix)) | 2137 | if (!NILP (prefix)) |
| 2138 | prefixlen = XINT (Flength (prefix)); | ||
| 2139 | |||
| 2140 | if (!NILP (prefix)) | ||
| 2141 | { | 2138 | { |
| 2142 | /* If a prefix was specified, start with the keymap (if any) for | 2139 | /* If a prefix was specified, start with the keymap (if any) for |
| 2143 | that prefix, so we don't waste time considering other prefixes. */ | 2140 | that prefix, so we don't waste time considering other prefixes. */ |
| @@ -2147,7 +2144,9 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2147 | if the prefix is not defined in this particular map. | 2144 | if the prefix is not defined in this particular map. |
| 2148 | It might even give us a list that isn't a keymap. */ | 2145 | It might even give us a list that isn't a keymap. */ |
| 2149 | tem = get_keymap (tem, 0, 0); | 2146 | tem = get_keymap (tem, 0, 0); |
| 2150 | if (CONSP (tem)) | 2147 | /* If the keymap is autoloaded `tem' is not a cons-cell, but we still |
| 2148 | want to return it. */ | ||
| 2149 | if (!NILP (tem)) | ||
| 2151 | { | 2150 | { |
| 2152 | /* Convert PREFIX to a vector now, so that later on | 2151 | /* Convert PREFIX to a vector now, so that later on |
| 2153 | we don't have to deal with the possibility of a string. */ | 2152 | we don't have to deal with the possibility of a string. */ |
| @@ -2187,57 +2186,26 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2187 | 2186 | ||
| 2188 | for (tail = maps; CONSP (tail); tail = XCDR (tail)) | 2187 | for (tail = maps; CONSP (tail); tail = XCDR (tail)) |
| 2189 | { | 2188 | { |
| 2190 | register Lisp_Object thisseq, thismap; | 2189 | struct accessible_keymaps_data data; |
| 2190 | register Lisp_Object thismap = Fcdr (XCAR (tail)); | ||
| 2191 | Lisp_Object last; | 2191 | Lisp_Object last; |
| 2192 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2193 | int is_metized; | ||
| 2194 | 2192 | ||
| 2195 | thisseq = Fcar (Fcar (tail)); | 2193 | data.thisseq = Fcar (XCAR (tail)); |
| 2196 | thismap = Fcdr (Fcar (tail)); | 2194 | data.maps = maps; |
| 2197 | last = make_number (XINT (Flength (thisseq)) - 1); | 2195 | data.tail = tail; |
| 2198 | is_metized = (XINT (last) >= 0 | 2196 | last = make_number (XINT (Flength (data.thisseq)) - 1); |
| 2197 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2198 | data.is_metized = (XINT (last) >= 0 | ||
| 2199 | /* Don't metize the last char of PREFIX. */ | 2199 | /* Don't metize the last char of PREFIX. */ |
| 2200 | && XINT (last) >= prefixlen | 2200 | && XINT (last) >= prefixlen |
| 2201 | && EQ (Faref (thisseq, last), meta_prefix_char)); | 2201 | && EQ (Faref (data.thisseq, last), meta_prefix_char)); |
| 2202 | |||
| 2203 | for (; CONSP (thismap); thismap = XCDR (thismap)) | ||
| 2204 | { | ||
| 2205 | Lisp_Object elt; | ||
| 2206 | |||
| 2207 | elt = XCAR (thismap); | ||
| 2208 | |||
| 2209 | QUIT; | ||
| 2210 | |||
| 2211 | if (CHAR_TABLE_P (elt)) | ||
| 2212 | { | ||
| 2213 | Lisp_Object indices[3]; | ||
| 2214 | |||
| 2215 | map_char_table (accessible_keymaps_char_table, Qnil, elt, | ||
| 2216 | elt, Fcons (Fcons (maps, make_number (is_metized)), | ||
| 2217 | Fcons (tail, thisseq)), | ||
| 2218 | 0, indices); | ||
| 2219 | } | ||
| 2220 | else if (VECTORP (elt)) | ||
| 2221 | { | ||
| 2222 | register int i; | ||
| 2223 | 2202 | ||
| 2224 | /* Vector keymap. Scan all the elements. */ | 2203 | /* Since we can't run lisp code, we can't scan autoloaded maps. */ |
| 2225 | for (i = 0; i < ASIZE (elt); i++) | 2204 | if (CONSP (thismap)) |
| 2226 | accessible_keymaps_1 (make_number (i), AREF (elt, i), | 2205 | map_keymap (thismap, accessible_keymaps_1, Qnil, &data, 0); |
| 2227 | maps, tail, thisseq, is_metized); | ||
| 2228 | |||
| 2229 | } | ||
| 2230 | else if (CONSP (elt)) | ||
| 2231 | accessible_keymaps_1 (XCAR (elt), XCDR (elt), | ||
| 2232 | maps, tail, thisseq, | ||
| 2233 | is_metized && INTEGERP (XCAR (elt))); | ||
| 2234 | |||
| 2235 | } | ||
| 2236 | } | 2206 | } |
| 2237 | |||
| 2238 | return maps; | 2207 | return maps; |
| 2239 | } | 2208 | } |
| 2240 | |||
| 2241 | Lisp_Object Qsingle_key_description, Qkey_description; | 2209 | Lisp_Object Qsingle_key_description, Qkey_description; |
| 2242 | 2210 | ||
| 2243 | /* This function cannot GC. */ | 2211 | /* This function cannot GC. */ |
| @@ -2508,7 +2476,7 @@ around function keys and event symbols. */) | |||
| 2508 | { | 2476 | { |
| 2509 | char buf[256]; | 2477 | char buf[256]; |
| 2510 | 2478 | ||
| 2511 | sprintf (buf, "Invalid char code %d", XINT (key)); | 2479 | sprintf (buf, "Invalid char code %ld", XINT (key)); |
| 2512 | return build_string (buf); | 2480 | return build_string (buf); |
| 2513 | } | 2481 | } |
| 2514 | else if (charset | 2482 | else if (charset |
| @@ -2651,8 +2619,8 @@ ascii_sequence_p (seq) | |||
| 2651 | /* where-is - finding a command in a set of keymaps. */ | 2619 | /* where-is - finding a command in a set of keymaps. */ |
| 2652 | 2620 | ||
| 2653 | static Lisp_Object where_is_internal (); | 2621 | static Lisp_Object where_is_internal (); |
| 2654 | static Lisp_Object where_is_internal_1 (); | 2622 | static void where_is_internal_1 P_ ((Lisp_Object key, Lisp_Object binding, |
| 2655 | static void where_is_internal_2 (); | 2623 | Lisp_Object args, void *data)); |
| 2656 | 2624 | ||
| 2657 | /* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map. | 2625 | /* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map. |
| 2658 | Returns the first non-nil binding found in any of those maps. */ | 2626 | Returns the first non-nil binding found in any of those maps. */ |
| @@ -2681,6 +2649,12 @@ shadow_lookup (shadow, key, flag) | |||
| 2681 | 2649 | ||
| 2682 | static Lisp_Object Vmouse_events; | 2650 | static Lisp_Object Vmouse_events; |
| 2683 | 2651 | ||
| 2652 | struct where_is_internal_data { | ||
| 2653 | Lisp_Object definition, noindirect, this, last; | ||
| 2654 | int last_is_meta; | ||
| 2655 | Lisp_Object sequences; | ||
| 2656 | }; | ||
| 2657 | |||
| 2684 | /* This function can GC if Flookup_key autoloads any keymaps. */ | 2658 | /* This function can GC if Flookup_key autoloads any keymaps. */ |
| 2685 | 2659 | ||
| 2686 | static Lisp_Object | 2660 | static Lisp_Object |
| @@ -2718,6 +2692,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2718 | { | 2692 | { |
| 2719 | /* Key sequence to reach map, and the map that it reaches */ | 2693 | /* Key sequence to reach map, and the map that it reaches */ |
| 2720 | register Lisp_Object this, map, tem; | 2694 | register Lisp_Object this, map, tem; |
| 2695 | struct where_is_internal_data data; | ||
| 2721 | 2696 | ||
| 2722 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into | 2697 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into |
| 2723 | [M-CHAR] sequences, check if last character of the sequence | 2698 | [M-CHAR] sequences, check if last character of the sequence |
| @@ -2742,148 +2717,94 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2742 | 2717 | ||
| 2743 | QUIT; | 2718 | QUIT; |
| 2744 | 2719 | ||
| 2745 | while (CONSP (map)) | 2720 | data.definition = definition; |
| 2746 | { | 2721 | data.noindirect = noindirect; |
| 2747 | /* Because the code we want to run on each binding is rather | 2722 | data.this = this; |
| 2748 | large, we don't want to have two separate loop bodies for | 2723 | data.last = last; |
| 2749 | sparse keymap bindings and tables; we want to iterate one | 2724 | data.last_is_meta = last_is_meta; |
| 2750 | loop body over both keymap and vector bindings. | 2725 | data.sequences = Qnil; |
| 2751 | |||
| 2752 | For this reason, if Fcar (map) is a vector, we don't | ||
| 2753 | advance map to the next element until i indicates that we | ||
| 2754 | have finished off the vector. */ | ||
| 2755 | Lisp_Object elt, key, binding; | ||
| 2756 | elt = XCAR (map); | ||
| 2757 | map = XCDR (map); | ||
| 2758 | 2726 | ||
| 2759 | sequences = Qnil; | 2727 | if (CONSP (map)) |
| 2728 | map_keymap (map, where_is_internal_1, Qnil, &data, 0); | ||
| 2760 | 2729 | ||
| 2761 | QUIT; | 2730 | sequences = data.sequences; |
| 2762 | 2731 | ||
| 2763 | /* Set key and binding to the current key and binding, and | 2732 | while (CONSP (sequences)) |
| 2764 | advance map and i to the next binding. */ | 2733 | { |
| 2765 | if (VECTORP (elt)) | 2734 | Lisp_Object sequence, remapped, function; |
| 2735 | |||
| 2736 | sequence = XCAR (sequences); | ||
| 2737 | sequences = XCDR (sequences); | ||
| 2738 | |||
| 2739 | /* If the current sequence is a command remapping with | ||
| 2740 | format [remap COMMAND], find the key sequences | ||
| 2741 | which run COMMAND, and use those sequences instead. */ | ||
| 2742 | remapped = Qnil; | ||
| 2743 | if (NILP (no_remap) | ||
| 2744 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 | ||
| 2745 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2746 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2766 | { | 2747 | { |
| 2767 | Lisp_Object sequence; | 2748 | Lisp_Object remapped1; |
| 2768 | int i; | 2749 | |
| 2769 | /* In a vector, look at each element. */ | 2750 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); |
| 2770 | for (i = 0; i < XVECTOR (elt)->size; i++) | 2751 | if (CONSP (remapped1)) |
| 2771 | { | 2752 | { |
| 2772 | binding = AREF (elt, i); | 2753 | /* Verify that this key binding actually maps to the |
| 2773 | XSETFASTINT (key, i); | 2754 | remapped command (see below). */ |
| 2774 | sequence = where_is_internal_1 (binding, key, definition, | 2755 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) |
| 2775 | noindirect, this, | 2756 | continue; |
| 2776 | last, nomenus, last_is_meta); | 2757 | sequence = XCAR (remapped1); |
| 2777 | if (!NILP (sequence)) | 2758 | remapped = XCDR (remapped1); |
| 2778 | sequences = Fcons (sequence, sequences); | 2759 | goto record_sequence; |
| 2779 | } | 2760 | } |
| 2780 | } | 2761 | } |
| 2781 | else if (CHAR_TABLE_P (elt)) | ||
| 2782 | { | ||
| 2783 | Lisp_Object indices[3]; | ||
| 2784 | Lisp_Object args; | ||
| 2785 | |||
| 2786 | args = Fcons (Fcons (Fcons (definition, noindirect), | ||
| 2787 | Qnil), /* Result accumulator. */ | ||
| 2788 | Fcons (Fcons (this, last), | ||
| 2789 | Fcons (make_number (nomenus), | ||
| 2790 | make_number (last_is_meta)))); | ||
| 2791 | map_char_table (where_is_internal_2, Qnil, elt, elt, args, | ||
| 2792 | 0, indices); | ||
| 2793 | sequences = XCDR (XCAR (args)); | ||
| 2794 | } | ||
| 2795 | else if (CONSP (elt)) | ||
| 2796 | { | ||
| 2797 | Lisp_Object sequence; | ||
| 2798 | 2762 | ||
| 2799 | key = XCAR (elt); | 2763 | /* Verify that this key binding is not shadowed by another |
| 2800 | binding = XCDR (elt); | 2764 | binding for the same key, before we say it exists. |
| 2801 | 2765 | ||
| 2802 | sequence = where_is_internal_1 (binding, key, definition, | 2766 | Mechanism: look for local definition of this key and if |
| 2803 | noindirect, this, | 2767 | it is defined and does not match what we found then |
| 2804 | last, nomenus, last_is_meta); | 2768 | ignore this key. |
| 2805 | if (!NILP (sequence)) | ||
| 2806 | sequences = Fcons (sequence, sequences); | ||
| 2807 | } | ||
| 2808 | 2769 | ||
| 2770 | Either nil or number as value from Flookup_key | ||
| 2771 | means undefined. */ | ||
| 2772 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2773 | continue; | ||
| 2809 | 2774 | ||
| 2810 | while (!NILP (sequences)) | 2775 | record_sequence: |
| 2776 | /* Don't annoy user with strings from a menu such as | ||
| 2777 | Select Paste. Change them all to "(any string)", | ||
| 2778 | so that there seems to be only one menu item | ||
| 2779 | to report. */ | ||
| 2780 | if (! NILP (sequence)) | ||
| 2811 | { | 2781 | { |
| 2812 | Lisp_Object sequence, remapped, function; | 2782 | Lisp_Object tem; |
| 2813 | 2783 | tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1)); | |
| 2814 | sequence = XCAR (sequences); | 2784 | if (STRINGP (tem)) |
| 2815 | sequences = XCDR (sequences); | 2785 | Faset (sequence, make_number (XVECTOR (sequence)->size - 1), |
| 2816 | 2786 | build_string ("(any string)")); | |
| 2817 | /* If the current sequence is a command remapping with | 2787 | } |
| 2818 | format [remap COMMAND], find the key sequences | ||
| 2819 | which run COMMAND, and use those sequences instead. */ | ||
| 2820 | remapped = Qnil; | ||
| 2821 | if (NILP (no_remap) | ||
| 2822 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 | ||
| 2823 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2824 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2825 | { | ||
| 2826 | Lisp_Object remapped1; | ||
| 2827 | |||
| 2828 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); | ||
| 2829 | if (CONSP (remapped1)) | ||
| 2830 | { | ||
| 2831 | /* Verify that this key binding actually maps to the | ||
| 2832 | remapped command (see below). */ | ||
| 2833 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) | ||
| 2834 | continue; | ||
| 2835 | sequence = XCAR (remapped1); | ||
| 2836 | remapped = XCDR (remapped1); | ||
| 2837 | goto record_sequence; | ||
| 2838 | } | ||
| 2839 | } | ||
| 2840 | |||
| 2841 | /* Verify that this key binding is not shadowed by another | ||
| 2842 | binding for the same key, before we say it exists. | ||
| 2843 | |||
| 2844 | Mechanism: look for local definition of this key and if | ||
| 2845 | it is defined and does not match what we found then | ||
| 2846 | ignore this key. | ||
| 2847 | |||
| 2848 | Either nil or number as value from Flookup_key | ||
| 2849 | means undefined. */ | ||
| 2850 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2851 | continue; | ||
| 2852 | |||
| 2853 | record_sequence: | ||
| 2854 | /* Don't annoy user with strings from a menu such as | ||
| 2855 | Select Paste. Change them all to "(any string)", | ||
| 2856 | so that there seems to be only one menu item | ||
| 2857 | to report. */ | ||
| 2858 | if (! NILP (sequence)) | ||
| 2859 | { | ||
| 2860 | Lisp_Object tem; | ||
| 2861 | tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1)); | ||
| 2862 | if (STRINGP (tem)) | ||
| 2863 | Faset (sequence, make_number (XVECTOR (sequence)->size - 1), | ||
| 2864 | build_string ("(any string)")); | ||
| 2865 | } | ||
| 2866 | 2788 | ||
| 2867 | /* It is a true unshadowed match. Record it, unless it's already | 2789 | /* It is a true unshadowed match. Record it, unless it's already |
| 2868 | been seen (as could happen when inheriting keymaps). */ | 2790 | been seen (as could happen when inheriting keymaps). */ |
| 2869 | if (NILP (Fmember (sequence, found))) | 2791 | if (NILP (Fmember (sequence, found))) |
| 2870 | found = Fcons (sequence, found); | 2792 | found = Fcons (sequence, found); |
| 2871 | 2793 | ||
| 2872 | /* If firstonly is Qnon_ascii, then we can return the first | 2794 | /* If firstonly is Qnon_ascii, then we can return the first |
| 2873 | binding we find. If firstonly is not Qnon_ascii but not | 2795 | binding we find. If firstonly is not Qnon_ascii but not |
| 2874 | nil, then we should return the first ascii-only binding | 2796 | nil, then we should return the first ascii-only binding |
| 2875 | we find. */ | 2797 | we find. */ |
| 2876 | if (EQ (firstonly, Qnon_ascii)) | 2798 | if (EQ (firstonly, Qnon_ascii)) |
| 2877 | RETURN_UNGCPRO (sequence); | 2799 | RETURN_UNGCPRO (sequence); |
| 2878 | else if (!NILP (firstonly) && ascii_sequence_p (sequence)) | 2800 | else if (!NILP (firstonly) && ascii_sequence_p (sequence)) |
| 2879 | RETURN_UNGCPRO (sequence); | 2801 | RETURN_UNGCPRO (sequence); |
| 2880 | 2802 | ||
| 2881 | if (CONSP (remapped)) | 2803 | if (CONSP (remapped)) |
| 2882 | { | 2804 | { |
| 2883 | sequence = XCAR (remapped); | 2805 | sequence = XCAR (remapped); |
| 2884 | remapped = XCDR (remapped); | 2806 | remapped = XCDR (remapped); |
| 2885 | goto record_sequence; | 2807 | goto record_sequence; |
| 2886 | } | ||
| 2887 | } | 2808 | } |
| 2888 | } | 2809 | } |
| 2889 | } | 2810 | } |
| @@ -3002,53 +2923,19 @@ remapped command in the returned list. */) | |||
| 3002 | return result; | 2923 | return result; |
| 3003 | } | 2924 | } |
| 3004 | 2925 | ||
| 3005 | /* This is the function that Fwhere_is_internal calls using map_char_table. | ||
| 3006 | ARGS has the form | ||
| 3007 | (((DEFINITION . NOINDIRECT) . (KEYMAP . RESULT)) | ||
| 3008 | . | ||
| 3009 | ((THIS . LAST) . (NOMENUS . LAST_IS_META))) | ||
| 3010 | Since map_char_table doesn't really use the return value from this function, | ||
| 3011 | we the result append to RESULT, the slot in ARGS. | ||
| 3012 | |||
| 3013 | This function can GC because it calls where_is_internal_1 which can | ||
| 3014 | GC. */ | ||
| 3015 | |||
| 3016 | static void | ||
| 3017 | where_is_internal_2 (args, key, binding) | ||
| 3018 | Lisp_Object args, key, binding; | ||
| 3019 | { | ||
| 3020 | Lisp_Object definition, noindirect, this, last; | ||
| 3021 | Lisp_Object result, sequence; | ||
| 3022 | int nomenus, last_is_meta; | ||
| 3023 | struct gcpro gcpro1, gcpro2, gcpro3; | ||
| 3024 | |||
| 3025 | GCPRO3 (args, key, binding); | ||
| 3026 | result = XCDR (XCAR (args)); | ||
| 3027 | definition = XCAR (XCAR (XCAR (args))); | ||
| 3028 | noindirect = XCDR (XCAR (XCAR (args))); | ||
| 3029 | this = XCAR (XCAR (XCDR (args))); | ||
| 3030 | last = XCDR (XCAR (XCDR (args))); | ||
| 3031 | nomenus = XFASTINT (XCAR (XCDR (XCDR (args)))); | ||
| 3032 | last_is_meta = XFASTINT (XCDR (XCDR (XCDR (args)))); | ||
| 3033 | |||
| 3034 | sequence = where_is_internal_1 (binding, key, definition, noindirect, | ||
| 3035 | this, last, nomenus, last_is_meta); | ||
| 3036 | |||
| 3037 | if (!NILP (sequence)) | ||
| 3038 | XSETCDR (XCAR (args), Fcons (sequence, result)); | ||
| 3039 | |||
| 3040 | UNGCPRO; | ||
| 3041 | } | ||
| 3042 | |||
| 3043 | |||
| 3044 | /* This function can GC because get_keyelt can. */ | 2926 | /* This function can GC because get_keyelt can. */ |
| 3045 | 2927 | ||
| 3046 | static Lisp_Object | 2928 | static void |
| 3047 | where_is_internal_1 (binding, key, definition, noindirect, this, last, | 2929 | where_is_internal_1 (key, binding, args, data) |
| 3048 | nomenus, last_is_meta) | 2930 | Lisp_Object key, binding, args; |
| 3049 | Lisp_Object binding, key, definition, noindirect, this, last; | 2931 | void *data; |
| 3050 | int nomenus, last_is_meta; | ||
| 3051 | { | 2932 | { |
| 2933 | struct where_is_internal_data *d = data; /* Cast! */ | ||
| 2934 | Lisp_Object definition = d->definition; | ||
| 2935 | Lisp_Object noindirect = d->noindirect; | ||
| 2936 | Lisp_Object this = d->this; | ||
| 2937 | Lisp_Object last = d->last; | ||
| 2938 | int last_is_meta = d->last_is_meta; | ||
| 3052 | Lisp_Object sequence; | 2939 | Lisp_Object sequence; |
| 3053 | 2940 | ||
| 3054 | /* Search through indirections unless that's not wanted. */ | 2941 | /* Search through indirections unless that's not wanted. */ |
| @@ -3062,7 +2949,7 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, | |||
| 3062 | || EQ (binding, definition) | 2949 | || EQ (binding, definition) |
| 3063 | || (CONSP (definition) && !NILP (Fequal (binding, definition))))) | 2950 | || (CONSP (definition) && !NILP (Fequal (binding, definition))))) |
| 3064 | /* Doesn't match. */ | 2951 | /* Doesn't match. */ |
| 3065 | return Qnil; | 2952 | return; |
| 3066 | 2953 | ||
| 3067 | /* We have found a match. Construct the key sequence where we found it. */ | 2954 | /* We have found a match. Construct the key sequence where we found it. */ |
| 3068 | if (INTEGERP (key) && last_is_meta) | 2955 | if (INTEGERP (key) && last_is_meta) |
| @@ -3077,10 +2964,9 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, | |||
| 3077 | { | 2964 | { |
| 3078 | Lisp_Object sequences = Fgethash (binding, where_is_cache, Qnil); | 2965 | Lisp_Object sequences = Fgethash (binding, where_is_cache, Qnil); |
| 3079 | Fputhash (binding, Fcons (sequence, sequences), where_is_cache); | 2966 | Fputhash (binding, Fcons (sequence, sequences), where_is_cache); |
| 3080 | return Qnil; | ||
| 3081 | } | 2967 | } |
| 3082 | else | 2968 | else |
| 3083 | return sequence; | 2969 | d->sequences = Fcons (sequence, d->sequences); |
| 3084 | } | 2970 | } |
| 3085 | 2971 | ||
| 3086 | /* describe-bindings - summarizing all the bindings in a set of keymaps. */ | 2972 | /* describe-bindings - summarizing all the bindings in a set of keymaps. */ |