diff options
| author | Miles Bader | 2007-07-15 02:05:20 +0000 |
|---|---|---|
| committer | Miles Bader | 2007-07-15 02:05:20 +0000 |
| commit | 7eb1e4534e88a32fe5e549e630fdabf3e062be2b (patch) | |
| tree | 34fc72789f1cfbfeb067cf507f8871c322df300a /src/keymap.c | |
| parent | 76d11d2cf9623e9f4c38e8239c4444ffc1fae485 (diff) | |
| parent | 6f8a87c027ebd6f9cfdac5c0df97d651227bec62 (diff) | |
| download | emacs-7eb1e4534e88a32fe5e549e630fdabf3e062be2b.tar.gz emacs-7eb1e4534e88a32fe5e549e630fdabf3e062be2b.zip | |
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 803-813)
- Update from CVS
- Merge from emacs--rel--22
* emacs--rel--22 (patch 51-58)
- Update from CVS
- Merge from gnus--rel--5.10
* gnus--rel--5.10 (patch 233-236)
- Merge from emacs--devo--0
- Update from CVS
Revision: emacs@sv.gnu.org/emacs--multi-tty--0--patch-25
Diffstat (limited to 'src/keymap.c')
| -rw-r--r-- | src/keymap.c | 502 |
1 files changed, 241 insertions, 261 deletions
diff --git a/src/keymap.c b/src/keymap.c index 904e3c89d55..869fd7a24a6 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -422,7 +422,7 @@ Return PARENT. PARENT should be nil or another keymap. */) | |||
| 422 | 422 | ||
| 423 | if (CHAR_TABLE_P (XCAR (list))) | 423 | if (CHAR_TABLE_P (XCAR (list))) |
| 424 | { | 424 | { |
| 425 | Lisp_Object indices[3]; | 425 | int indices[3]; |
| 426 | 426 | ||
| 427 | map_char_table (fix_submap_inheritance, Qnil, | 427 | map_char_table (fix_submap_inheritance, Qnil, |
| 428 | XCAR (list), XCAR (list), | 428 | XCAR (list), XCAR (list), |
| @@ -721,7 +721,7 @@ map_keymap (map, fun, args, data, autoload) | |||
| 721 | } | 721 | } |
| 722 | else if (CHAR_TABLE_P (binding)) | 722 | else if (CHAR_TABLE_P (binding)) |
| 723 | { | 723 | { |
| 724 | Lisp_Object indices[3]; | 724 | int indices[3]; |
| 725 | map_char_table (map_keymap_char_table_item, Qnil, binding, binding, | 725 | map_char_table (map_keymap_char_table_item, Qnil, binding, binding, |
| 726 | Fcons (make_save_value (fun, 0), | 726 | Fcons (make_save_value (fun, 0), |
| 727 | Fcons (make_save_value (data, 0), | 727 | Fcons (make_save_value (data, 0), |
| @@ -1072,7 +1072,7 @@ is not copied. */) | |||
| 1072 | Lisp_Object elt = XCAR (keymap); | 1072 | Lisp_Object elt = XCAR (keymap); |
| 1073 | if (CHAR_TABLE_P (elt)) | 1073 | if (CHAR_TABLE_P (elt)) |
| 1074 | { | 1074 | { |
| 1075 | Lisp_Object indices[3]; | 1075 | int indices[3]; |
| 1076 | elt = Fcopy_sequence (elt); | 1076 | elt = Fcopy_sequence (elt); |
| 1077 | map_char_table (copy_keymap_1, Qnil, elt, elt, elt, 0, indices); | 1077 | map_char_table (copy_keymap_1, Qnil, elt, elt, elt, 0, indices); |
| 1078 | } | 1078 | } |
| @@ -1149,7 +1149,7 @@ binding KEY to DEF is added at the front of KEYMAP. */) | |||
| 1149 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) | 1149 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) |
| 1150 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); | 1150 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); |
| 1151 | 1151 | ||
| 1152 | meta_bit = (VECTORP (key) || STRINGP (key) && STRING_MULTIBYTE (key) | 1152 | meta_bit = (VECTORP (key) || (STRINGP (key) && STRING_MULTIBYTE (key)) |
| 1153 | ? meta_modifier : 0x80); | 1153 | ? meta_modifier : 0x80); |
| 1154 | 1154 | ||
| 1155 | if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0))) | 1155 | if (VECTORP (def) && ASIZE (def) > 0 && CONSP (AREF (def, 0))) |
| @@ -1534,14 +1534,47 @@ current_minor_maps (modeptr, mapptr) | |||
| 1534 | } | 1534 | } |
| 1535 | 1535 | ||
| 1536 | DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps, | 1536 | DEFUN ("current-active-maps", Fcurrent_active_maps, Scurrent_active_maps, |
| 1537 | 0, 1, 0, | 1537 | 0, 2, 0, |
| 1538 | doc: /* Return a list of the currently active keymaps. | 1538 | doc: /* Return a list of the currently active keymaps. |
| 1539 | OLP if non-nil indicates that we should obey `overriding-local-map' and | 1539 | OLP if non-nil indicates that we should obey `overriding-local-map' and |
| 1540 | `overriding-terminal-local-map'. */) | 1540 | `overriding-terminal-local-map'. POSITION can specify a click position |
| 1541 | (olp) | 1541 | like in the respective argument of `key-binding'. */) |
| 1542 | Lisp_Object olp; | 1542 | (olp, position) |
| 1543 | Lisp_Object olp, position; | ||
| 1543 | { | 1544 | { |
| 1544 | Lisp_Object keymaps = Fcons (current_global_map, Qnil); | 1545 | int count = SPECPDL_INDEX (); |
| 1546 | |||
| 1547 | Lisp_Object keymaps; | ||
| 1548 | |||
| 1549 | /* If a mouse click position is given, our variables are based on | ||
| 1550 | the buffer clicked on, not the current buffer. So we may have to | ||
| 1551 | switch the buffer here. */ | ||
| 1552 | |||
| 1553 | if (CONSP (position)) | ||
| 1554 | { | ||
| 1555 | Lisp_Object window; | ||
| 1556 | |||
| 1557 | window = POSN_WINDOW (position); | ||
| 1558 | |||
| 1559 | if (WINDOWP (window) | ||
| 1560 | && BUFFERP (XWINDOW (window)->buffer) | ||
| 1561 | && XBUFFER (XWINDOW (window)->buffer) != current_buffer) | ||
| 1562 | { | ||
| 1563 | /* Arrange to go back to the original buffer once we're done | ||
| 1564 | processing the key sequence. We don't use | ||
| 1565 | save_excursion_{save,restore} here, in analogy to | ||
| 1566 | `read-key-sequence' to avoid saving point. Maybe this | ||
| 1567 | would not be a problem here, but it is easier to keep | ||
| 1568 | things the same. | ||
| 1569 | */ | ||
| 1570 | |||
| 1571 | record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); | ||
| 1572 | |||
| 1573 | set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); | ||
| 1574 | } | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | keymaps = Fcons (current_global_map, Qnil); | ||
| 1545 | 1578 | ||
| 1546 | if (!NILP (olp)) | 1579 | if (!NILP (olp)) |
| 1547 | { | 1580 | { |
| @@ -1555,15 +1588,76 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and | |||
| 1555 | } | 1588 | } |
| 1556 | if (NILP (XCDR (keymaps))) | 1589 | if (NILP (XCDR (keymaps))) |
| 1557 | { | 1590 | { |
| 1558 | Lisp_Object local; | ||
| 1559 | Lisp_Object *maps; | 1591 | Lisp_Object *maps; |
| 1560 | int nmaps, i; | 1592 | int nmaps, i; |
| 1561 | 1593 | ||
| 1562 | /* This usually returns the buffer's local map, | 1594 | Lisp_Object keymap, local_map; |
| 1563 | but that can be overridden by a `local-map' property. */ | 1595 | EMACS_INT pt; |
| 1564 | local = get_local_map (PT, current_buffer, Qlocal_map); | 1596 | |
| 1565 | if (!NILP (local)) | 1597 | pt = INTEGERP (position) ? XINT (position) |
| 1566 | keymaps = Fcons (local, keymaps); | 1598 | : MARKERP (position) ? marker_position (position) |
| 1599 | : PT; | ||
| 1600 | |||
| 1601 | /* Get the buffer local maps, possibly overriden by text or | ||
| 1602 | overlay properties */ | ||
| 1603 | |||
| 1604 | local_map = get_local_map (pt, current_buffer, Qlocal_map); | ||
| 1605 | keymap = get_local_map (pt, current_buffer, Qkeymap); | ||
| 1606 | |||
| 1607 | if (CONSP (position)) | ||
| 1608 | { | ||
| 1609 | Lisp_Object string; | ||
| 1610 | |||
| 1611 | /* For a mouse click, get the local text-property keymap | ||
| 1612 | of the place clicked on, rather than point. */ | ||
| 1613 | |||
| 1614 | if (POSN_INBUFFER_P (position)) | ||
| 1615 | { | ||
| 1616 | Lisp_Object pos; | ||
| 1617 | |||
| 1618 | pos = POSN_BUFFER_POSN (position); | ||
| 1619 | if (INTEGERP (pos) | ||
| 1620 | && XINT (pos) >= BEG && XINT (pos) <= Z) | ||
| 1621 | { | ||
| 1622 | local_map = get_local_map (XINT (pos), | ||
| 1623 | current_buffer, Qlocal_map); | ||
| 1624 | |||
| 1625 | keymap = get_local_map (XINT (pos), | ||
| 1626 | current_buffer, Qkeymap); | ||
| 1627 | } | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | /* If on a mode line string with a local keymap, | ||
| 1631 | or for a click on a string, i.e. overlay string or a | ||
| 1632 | string displayed via the `display' property, | ||
| 1633 | consider `local-map' and `keymap' properties of | ||
| 1634 | that string. */ | ||
| 1635 | |||
| 1636 | if (string = POSN_STRING (position), | ||
| 1637 | (CONSP (string) && STRINGP (XCAR (string)))) | ||
| 1638 | { | ||
| 1639 | Lisp_Object pos, map; | ||
| 1640 | |||
| 1641 | pos = XCDR (string); | ||
| 1642 | string = XCAR (string); | ||
| 1643 | if (INTEGERP (pos) | ||
| 1644 | && XINT (pos) >= 0 | ||
| 1645 | && XINT (pos) < SCHARS (string)) | ||
| 1646 | { | ||
| 1647 | map = Fget_text_property (pos, Qlocal_map, string); | ||
| 1648 | if (!NILP (map)) | ||
| 1649 | local_map = map; | ||
| 1650 | |||
| 1651 | map = Fget_text_property (pos, Qkeymap, string); | ||
| 1652 | if (!NILP (map)) | ||
| 1653 | keymap = map; | ||
| 1654 | } | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | } | ||
| 1658 | |||
| 1659 | if (!NILP (local_map)) | ||
| 1660 | keymaps = Fcons (local_map, keymaps); | ||
| 1567 | 1661 | ||
| 1568 | /* Now put all the minor mode keymaps on the list. */ | 1662 | /* Now put all the minor mode keymaps on the list. */ |
| 1569 | nmaps = current_minor_maps (0, &maps); | 1663 | nmaps = current_minor_maps (0, &maps); |
| @@ -1572,12 +1666,12 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and | |||
| 1572 | if (!NILP (maps[i])) | 1666 | if (!NILP (maps[i])) |
| 1573 | keymaps = Fcons (maps[i], keymaps); | 1667 | keymaps = Fcons (maps[i], keymaps); |
| 1574 | 1668 | ||
| 1575 | /* This returns nil unless there is a `keymap' property. */ | 1669 | if (!NILP (keymap)) |
| 1576 | local = get_local_map (PT, current_buffer, Qkeymap); | 1670 | keymaps = Fcons (keymap, keymaps); |
| 1577 | if (!NILP (local)) | ||
| 1578 | keymaps = Fcons (local, keymaps); | ||
| 1579 | } | 1671 | } |
| 1580 | 1672 | ||
| 1673 | unbind_to (count, Qnil); | ||
| 1674 | |||
| 1581 | return keymaps; | 1675 | return keymaps; |
| 1582 | } | 1676 | } |
| 1583 | 1677 | ||
| @@ -1945,12 +2039,23 @@ DEFUN ("current-minor-mode-maps", Fcurrent_minor_mode_maps, Scurrent_minor_mode_ | |||
| 1945 | 2039 | ||
| 1946 | /* Help functions for describing and documenting keymaps. */ | 2040 | /* Help functions for describing and documenting keymaps. */ |
| 1947 | 2041 | ||
| 2042 | struct accessible_keymaps_data { | ||
| 2043 | Lisp_Object maps, tail, thisseq; | ||
| 2044 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2045 | int is_metized; | ||
| 2046 | }; | ||
| 1948 | 2047 | ||
| 1949 | static void | 2048 | static void |
| 1950 | accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized) | 2049 | accessible_keymaps_1 (key, cmd, args, data) |
| 1951 | Lisp_Object maps, tail, thisseq, key, cmd; | 2050 | Lisp_Object key, cmd, args; |
| 1952 | int is_metized; /* If 1, `key' is assumed to be INTEGERP. */ | 2051 | /* Use void* to be compatible with map_keymap_function_t. */ |
| 2052 | void *data; | ||
| 1953 | { | 2053 | { |
| 2054 | struct accessible_keymaps_data *d = data; /* Cast! */ | ||
| 2055 | Lisp_Object maps = d->maps; | ||
| 2056 | Lisp_Object tail = d->tail; | ||
| 2057 | Lisp_Object thisseq = d->thisseq; | ||
| 2058 | int is_metized = d->is_metized && INTEGERP (key); | ||
| 1954 | Lisp_Object tem; | 2059 | Lisp_Object tem; |
| 1955 | 2060 | ||
| 1956 | cmd = get_keymap (get_keyelt (cmd, 0), 0, 0); | 2061 | cmd = get_keymap (get_keyelt (cmd, 0), 0, 0); |
| @@ -2004,17 +2109,6 @@ accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized) | |||
| 2004 | } | 2109 | } |
| 2005 | } | 2110 | } |
| 2006 | 2111 | ||
| 2007 | static void | ||
| 2008 | accessible_keymaps_char_table (args, index, cmd) | ||
| 2009 | Lisp_Object args, index, cmd; | ||
| 2010 | { | ||
| 2011 | accessible_keymaps_1 (index, cmd, | ||
| 2012 | XCAR (XCAR (args)), | ||
| 2013 | XCAR (XCDR (args)), | ||
| 2014 | XCDR (XCDR (args)), | ||
| 2015 | XINT (XCDR (XCAR (args)))); | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | /* This function cannot GC. */ | 2112 | /* This function cannot GC. */ |
| 2019 | 2113 | ||
| 2020 | DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, | 2114 | DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps, |
| @@ -2029,14 +2123,11 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2029 | Lisp_Object keymap, prefix; | 2123 | Lisp_Object keymap, prefix; |
| 2030 | { | 2124 | { |
| 2031 | Lisp_Object maps, tail; | 2125 | Lisp_Object maps, tail; |
| 2032 | int prefixlen = 0; | 2126 | int prefixlen = XINT (Flength (prefix)); |
| 2033 | 2127 | ||
| 2034 | /* no need for gcpro because we don't autoload any keymaps. */ | 2128 | /* no need for gcpro because we don't autoload any keymaps. */ |
| 2035 | 2129 | ||
| 2036 | if (!NILP (prefix)) | 2130 | if (!NILP (prefix)) |
| 2037 | prefixlen = XINT (Flength (prefix)); | ||
| 2038 | |||
| 2039 | if (!NILP (prefix)) | ||
| 2040 | { | 2131 | { |
| 2041 | /* If a prefix was specified, start with the keymap (if any) for | 2132 | /* If a prefix was specified, start with the keymap (if any) for |
| 2042 | that prefix, so we don't waste time considering other prefixes. */ | 2133 | that prefix, so we don't waste time considering other prefixes. */ |
| @@ -2046,7 +2137,9 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2046 | if the prefix is not defined in this particular map. | 2137 | if the prefix is not defined in this particular map. |
| 2047 | It might even give us a list that isn't a keymap. */ | 2138 | It might even give us a list that isn't a keymap. */ |
| 2048 | tem = get_keymap (tem, 0, 0); | 2139 | tem = get_keymap (tem, 0, 0); |
| 2049 | if (CONSP (tem)) | 2140 | /* If the keymap is autoloaded `tem' is not a cons-cell, but we still |
| 2141 | want to return it. */ | ||
| 2142 | if (!NILP (tem)) | ||
| 2050 | { | 2143 | { |
| 2051 | /* Convert PREFIX to a vector now, so that later on | 2144 | /* Convert PREFIX to a vector now, so that later on |
| 2052 | we don't have to deal with the possibility of a string. */ | 2145 | we don't have to deal with the possibility of a string. */ |
| @@ -2086,57 +2179,26 @@ then the value includes only maps for prefixes that start with PREFIX. */) | |||
| 2086 | 2179 | ||
| 2087 | for (tail = maps; CONSP (tail); tail = XCDR (tail)) | 2180 | for (tail = maps; CONSP (tail); tail = XCDR (tail)) |
| 2088 | { | 2181 | { |
| 2089 | register Lisp_Object thisseq, thismap; | 2182 | struct accessible_keymaps_data data; |
| 2183 | register Lisp_Object thismap = Fcdr (XCAR (tail)); | ||
| 2090 | Lisp_Object last; | 2184 | Lisp_Object last; |
| 2091 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2092 | int is_metized; | ||
| 2093 | 2185 | ||
| 2094 | thisseq = Fcar (Fcar (tail)); | 2186 | data.thisseq = Fcar (XCAR (tail)); |
| 2095 | thismap = Fcdr (Fcar (tail)); | 2187 | data.maps = maps; |
| 2096 | last = make_number (XINT (Flength (thisseq)) - 1); | 2188 | data.tail = tail; |
| 2097 | is_metized = (XINT (last) >= 0 | 2189 | last = make_number (XINT (Flength (data.thisseq)) - 1); |
| 2190 | /* Does the current sequence end in the meta-prefix-char? */ | ||
| 2191 | data.is_metized = (XINT (last) >= 0 | ||
| 2098 | /* Don't metize the last char of PREFIX. */ | 2192 | /* Don't metize the last char of PREFIX. */ |
| 2099 | && XINT (last) >= prefixlen | 2193 | && XINT (last) >= prefixlen |
| 2100 | && EQ (Faref (thisseq, last), meta_prefix_char)); | 2194 | && EQ (Faref (data.thisseq, last), meta_prefix_char)); |
| 2101 | |||
| 2102 | for (; CONSP (thismap); thismap = XCDR (thismap)) | ||
| 2103 | { | ||
| 2104 | Lisp_Object elt; | ||
| 2105 | |||
| 2106 | elt = XCAR (thismap); | ||
| 2107 | |||
| 2108 | QUIT; | ||
| 2109 | |||
| 2110 | if (CHAR_TABLE_P (elt)) | ||
| 2111 | { | ||
| 2112 | Lisp_Object indices[3]; | ||
| 2113 | |||
| 2114 | map_char_table (accessible_keymaps_char_table, Qnil, elt, | ||
| 2115 | elt, Fcons (Fcons (maps, make_number (is_metized)), | ||
| 2116 | Fcons (tail, thisseq)), | ||
| 2117 | 0, indices); | ||
| 2118 | } | ||
| 2119 | else if (VECTORP (elt)) | ||
| 2120 | { | ||
| 2121 | register int i; | ||
| 2122 | |||
| 2123 | /* Vector keymap. Scan all the elements. */ | ||
| 2124 | for (i = 0; i < ASIZE (elt); i++) | ||
| 2125 | accessible_keymaps_1 (make_number (i), AREF (elt, i), | ||
| 2126 | maps, tail, thisseq, is_metized); | ||
| 2127 | 2195 | ||
| 2128 | } | 2196 | /* Since we can't run lisp code, we can't scan autoloaded maps. */ |
| 2129 | else if (CONSP (elt)) | 2197 | if (CONSP (thismap)) |
| 2130 | accessible_keymaps_1 (XCAR (elt), XCDR (elt), | 2198 | map_keymap (thismap, accessible_keymaps_1, Qnil, &data, 0); |
| 2131 | maps, tail, thisseq, | ||
| 2132 | is_metized && INTEGERP (XCAR (elt))); | ||
| 2133 | |||
| 2134 | } | ||
| 2135 | } | 2199 | } |
| 2136 | |||
| 2137 | return maps; | 2200 | return maps; |
| 2138 | } | 2201 | } |
| 2139 | |||
| 2140 | Lisp_Object Qsingle_key_description, Qkey_description; | 2202 | Lisp_Object Qsingle_key_description, Qkey_description; |
| 2141 | 2203 | ||
| 2142 | /* This function cannot GC. */ | 2204 | /* This function cannot GC. */ |
| @@ -2407,7 +2469,7 @@ around function keys and event symbols. */) | |||
| 2407 | { | 2469 | { |
| 2408 | char buf[256]; | 2470 | char buf[256]; |
| 2409 | 2471 | ||
| 2410 | sprintf (buf, "Invalid char code %d", XINT (key)); | 2472 | sprintf (buf, "Invalid char code %ld", XINT (key)); |
| 2411 | return build_string (buf); | 2473 | return build_string (buf); |
| 2412 | } | 2474 | } |
| 2413 | else if (charset | 2475 | else if (charset |
| @@ -2550,8 +2612,8 @@ ascii_sequence_p (seq) | |||
| 2550 | /* where-is - finding a command in a set of keymaps. */ | 2612 | /* where-is - finding a command in a set of keymaps. */ |
| 2551 | 2613 | ||
| 2552 | static Lisp_Object where_is_internal (); | 2614 | static Lisp_Object where_is_internal (); |
| 2553 | static Lisp_Object where_is_internal_1 (); | 2615 | static void where_is_internal_1 P_ ((Lisp_Object key, Lisp_Object binding, |
| 2554 | static void where_is_internal_2 (); | 2616 | Lisp_Object args, void *data)); |
| 2555 | 2617 | ||
| 2556 | /* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map. | 2618 | /* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map. |
| 2557 | Returns the first non-nil binding found in any of those maps. */ | 2619 | Returns the first non-nil binding found in any of those maps. */ |
| @@ -2580,6 +2642,12 @@ shadow_lookup (shadow, key, flag) | |||
| 2580 | 2642 | ||
| 2581 | static Lisp_Object Vmouse_events; | 2643 | static Lisp_Object Vmouse_events; |
| 2582 | 2644 | ||
| 2645 | struct where_is_internal_data { | ||
| 2646 | Lisp_Object definition, noindirect, this, last; | ||
| 2647 | int last_is_meta; | ||
| 2648 | Lisp_Object sequences; | ||
| 2649 | }; | ||
| 2650 | |||
| 2583 | /* This function can GC if Flookup_key autoloads any keymaps. */ | 2651 | /* This function can GC if Flookup_key autoloads any keymaps. */ |
| 2584 | 2652 | ||
| 2585 | static Lisp_Object | 2653 | static Lisp_Object |
| @@ -2617,6 +2685,7 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2617 | { | 2685 | { |
| 2618 | /* Key sequence to reach map, and the map that it reaches */ | 2686 | /* Key sequence to reach map, and the map that it reaches */ |
| 2619 | register Lisp_Object this, map, tem; | 2687 | register Lisp_Object this, map, tem; |
| 2688 | struct where_is_internal_data data; | ||
| 2620 | 2689 | ||
| 2621 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into | 2690 | /* In order to fold [META-PREFIX-CHAR CHAR] sequences into |
| 2622 | [M-CHAR] sequences, check if last character of the sequence | 2691 | [M-CHAR] sequences, check if last character of the sequence |
| @@ -2641,148 +2710,94 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2641 | 2710 | ||
| 2642 | QUIT; | 2711 | QUIT; |
| 2643 | 2712 | ||
| 2644 | while (CONSP (map)) | 2713 | data.definition = definition; |
| 2645 | { | 2714 | data.noindirect = noindirect; |
| 2646 | /* Because the code we want to run on each binding is rather | 2715 | data.this = this; |
| 2647 | large, we don't want to have two separate loop bodies for | 2716 | data.last = last; |
| 2648 | sparse keymap bindings and tables; we want to iterate one | 2717 | data.last_is_meta = last_is_meta; |
| 2649 | loop body over both keymap and vector bindings. | 2718 | data.sequences = Qnil; |
| 2650 | 2719 | ||
| 2651 | For this reason, if Fcar (map) is a vector, we don't | 2720 | if (CONSP (map)) |
| 2652 | advance map to the next element until i indicates that we | 2721 | map_keymap (map, where_is_internal_1, Qnil, &data, 0); |
| 2653 | have finished off the vector. */ | ||
| 2654 | Lisp_Object elt, key, binding; | ||
| 2655 | elt = XCAR (map); | ||
| 2656 | map = XCDR (map); | ||
| 2657 | 2722 | ||
| 2658 | sequences = Qnil; | 2723 | sequences = data.sequences; |
| 2659 | 2724 | ||
| 2660 | QUIT; | 2725 | while (CONSP (sequences)) |
| 2661 | 2726 | { | |
| 2662 | /* Set key and binding to the current key and binding, and | 2727 | Lisp_Object sequence, remapped, function; |
| 2663 | advance map and i to the next binding. */ | 2728 | |
| 2664 | if (VECTORP (elt)) | 2729 | sequence = XCAR (sequences); |
| 2730 | sequences = XCDR (sequences); | ||
| 2731 | |||
| 2732 | /* If the current sequence is a command remapping with | ||
| 2733 | format [remap COMMAND], find the key sequences | ||
| 2734 | which run COMMAND, and use those sequences instead. */ | ||
| 2735 | remapped = Qnil; | ||
| 2736 | if (NILP (no_remap) | ||
| 2737 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 | ||
| 2738 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2739 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2665 | { | 2740 | { |
| 2666 | Lisp_Object sequence; | 2741 | Lisp_Object remapped1; |
| 2667 | int i; | 2742 | |
| 2668 | /* In a vector, look at each element. */ | 2743 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); |
| 2669 | for (i = 0; i < XVECTOR (elt)->size; i++) | 2744 | if (CONSP (remapped1)) |
| 2670 | { | 2745 | { |
| 2671 | binding = AREF (elt, i); | 2746 | /* Verify that this key binding actually maps to the |
| 2672 | XSETFASTINT (key, i); | 2747 | remapped command (see below). */ |
| 2673 | sequence = where_is_internal_1 (binding, key, definition, | 2748 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) |
| 2674 | noindirect, this, | 2749 | continue; |
| 2675 | last, nomenus, last_is_meta); | 2750 | sequence = XCAR (remapped1); |
| 2676 | if (!NILP (sequence)) | 2751 | remapped = XCDR (remapped1); |
| 2677 | sequences = Fcons (sequence, sequences); | 2752 | goto record_sequence; |
| 2678 | } | 2753 | } |
| 2679 | } | 2754 | } |
| 2680 | else if (CHAR_TABLE_P (elt)) | ||
| 2681 | { | ||
| 2682 | Lisp_Object indices[3]; | ||
| 2683 | Lisp_Object args; | ||
| 2684 | |||
| 2685 | args = Fcons (Fcons (Fcons (definition, noindirect), | ||
| 2686 | Qnil), /* Result accumulator. */ | ||
| 2687 | Fcons (Fcons (this, last), | ||
| 2688 | Fcons (make_number (nomenus), | ||
| 2689 | make_number (last_is_meta)))); | ||
| 2690 | map_char_table (where_is_internal_2, Qnil, elt, elt, args, | ||
| 2691 | 0, indices); | ||
| 2692 | sequences = XCDR (XCAR (args)); | ||
| 2693 | } | ||
| 2694 | else if (CONSP (elt)) | ||
| 2695 | { | ||
| 2696 | Lisp_Object sequence; | ||
| 2697 | 2755 | ||
| 2698 | key = XCAR (elt); | 2756 | /* Verify that this key binding is not shadowed by another |
| 2699 | binding = XCDR (elt); | 2757 | binding for the same key, before we say it exists. |
| 2700 | 2758 | ||
| 2701 | sequence = where_is_internal_1 (binding, key, definition, | 2759 | Mechanism: look for local definition of this key and if |
| 2702 | noindirect, this, | 2760 | it is defined and does not match what we found then |
| 2703 | last, nomenus, last_is_meta); | 2761 | ignore this key. |
| 2704 | if (!NILP (sequence)) | ||
| 2705 | sequences = Fcons (sequence, sequences); | ||
| 2706 | } | ||
| 2707 | 2762 | ||
| 2763 | Either nil or number as value from Flookup_key | ||
| 2764 | means undefined. */ | ||
| 2765 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2766 | continue; | ||
| 2708 | 2767 | ||
| 2709 | while (!NILP (sequences)) | 2768 | record_sequence: |
| 2769 | /* Don't annoy user with strings from a menu such as | ||
| 2770 | Select Paste. Change them all to "(any string)", | ||
| 2771 | so that there seems to be only one menu item | ||
| 2772 | to report. */ | ||
| 2773 | if (! NILP (sequence)) | ||
| 2710 | { | 2774 | { |
| 2711 | Lisp_Object sequence, remapped, function; | 2775 | Lisp_Object tem; |
| 2712 | 2776 | tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1)); | |
| 2713 | sequence = XCAR (sequences); | 2777 | if (STRINGP (tem)) |
| 2714 | sequences = XCDR (sequences); | 2778 | Faset (sequence, make_number (XVECTOR (sequence)->size - 1), |
| 2715 | 2779 | build_string ("(any string)")); | |
| 2716 | /* If the current sequence is a command remapping with | 2780 | } |
| 2717 | format [remap COMMAND], find the key sequences | ||
| 2718 | which run COMMAND, and use those sequences instead. */ | ||
| 2719 | remapped = Qnil; | ||
| 2720 | if (NILP (no_remap) | ||
| 2721 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 | ||
| 2722 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2723 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2724 | { | ||
| 2725 | Lisp_Object remapped1; | ||
| 2726 | |||
| 2727 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); | ||
| 2728 | if (CONSP (remapped1)) | ||
| 2729 | { | ||
| 2730 | /* Verify that this key binding actually maps to the | ||
| 2731 | remapped command (see below). */ | ||
| 2732 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) | ||
| 2733 | continue; | ||
| 2734 | sequence = XCAR (remapped1); | ||
| 2735 | remapped = XCDR (remapped1); | ||
| 2736 | goto record_sequence; | ||
| 2737 | } | ||
| 2738 | } | ||
| 2739 | |||
| 2740 | /* Verify that this key binding is not shadowed by another | ||
| 2741 | binding for the same key, before we say it exists. | ||
| 2742 | |||
| 2743 | Mechanism: look for local definition of this key and if | ||
| 2744 | it is defined and does not match what we found then | ||
| 2745 | ignore this key. | ||
| 2746 | |||
| 2747 | Either nil or number as value from Flookup_key | ||
| 2748 | means undefined. */ | ||
| 2749 | if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition)) | ||
| 2750 | continue; | ||
| 2751 | |||
| 2752 | record_sequence: | ||
| 2753 | /* Don't annoy user with strings from a menu such as | ||
| 2754 | Select Paste. Change them all to "(any string)", | ||
| 2755 | so that there seems to be only one menu item | ||
| 2756 | to report. */ | ||
| 2757 | if (! NILP (sequence)) | ||
| 2758 | { | ||
| 2759 | Lisp_Object tem; | ||
| 2760 | tem = Faref (sequence, make_number (XVECTOR (sequence)->size - 1)); | ||
| 2761 | if (STRINGP (tem)) | ||
| 2762 | Faset (sequence, make_number (XVECTOR (sequence)->size - 1), | ||
| 2763 | build_string ("(any string)")); | ||
| 2764 | } | ||
| 2765 | 2781 | ||
| 2766 | /* It is a true unshadowed match. Record it, unless it's already | 2782 | /* It is a true unshadowed match. Record it, unless it's already |
| 2767 | been seen (as could happen when inheriting keymaps). */ | 2783 | been seen (as could happen when inheriting keymaps). */ |
| 2768 | if (NILP (Fmember (sequence, found))) | 2784 | if (NILP (Fmember (sequence, found))) |
| 2769 | found = Fcons (sequence, found); | 2785 | found = Fcons (sequence, found); |
| 2770 | 2786 | ||
| 2771 | /* If firstonly is Qnon_ascii, then we can return the first | 2787 | /* If firstonly is Qnon_ascii, then we can return the first |
| 2772 | binding we find. If firstonly is not Qnon_ascii but not | 2788 | binding we find. If firstonly is not Qnon_ascii but not |
| 2773 | nil, then we should return the first ascii-only binding | 2789 | nil, then we should return the first ascii-only binding |
| 2774 | we find. */ | 2790 | we find. */ |
| 2775 | if (EQ (firstonly, Qnon_ascii)) | 2791 | if (EQ (firstonly, Qnon_ascii)) |
| 2776 | RETURN_UNGCPRO (sequence); | 2792 | RETURN_UNGCPRO (sequence); |
| 2777 | else if (!NILP (firstonly) && ascii_sequence_p (sequence)) | 2793 | else if (!NILP (firstonly) && ascii_sequence_p (sequence)) |
| 2778 | RETURN_UNGCPRO (sequence); | 2794 | RETURN_UNGCPRO (sequence); |
| 2779 | 2795 | ||
| 2780 | if (CONSP (remapped)) | 2796 | if (CONSP (remapped)) |
| 2781 | { | 2797 | { |
| 2782 | sequence = XCAR (remapped); | 2798 | sequence = XCAR (remapped); |
| 2783 | remapped = XCDR (remapped); | 2799 | remapped = XCDR (remapped); |
| 2784 | goto record_sequence; | 2800 | goto record_sequence; |
| 2785 | } | ||
| 2786 | } | 2801 | } |
| 2787 | } | 2802 | } |
| 2788 | } | 2803 | } |
| @@ -2835,7 +2850,7 @@ remapped command in the returned list. */) | |||
| 2835 | else if (!NILP (keymap)) | 2850 | else if (!NILP (keymap)) |
| 2836 | keymaps = Fcons (keymap, Fcons (current_global_map, Qnil)); | 2851 | keymaps = Fcons (keymap, Fcons (current_global_map, Qnil)); |
| 2837 | else | 2852 | else |
| 2838 | keymaps = Fcurrent_active_maps (Qnil); | 2853 | keymaps = Fcurrent_active_maps (Qnil, Qnil); |
| 2839 | 2854 | ||
| 2840 | /* Only use caching for the menubar (i.e. called with (def nil t nil). | 2855 | /* Only use caching for the menubar (i.e. called with (def nil t nil). |
| 2841 | We don't really need to check `keymap'. */ | 2856 | We don't really need to check `keymap'. */ |
| @@ -2901,53 +2916,19 @@ remapped command in the returned list. */) | |||
| 2901 | return result; | 2916 | return result; |
| 2902 | } | 2917 | } |
| 2903 | 2918 | ||
| 2904 | /* This is the function that Fwhere_is_internal calls using map_char_table. | ||
| 2905 | ARGS has the form | ||
| 2906 | (((DEFINITION . NOINDIRECT) . (KEYMAP . RESULT)) | ||
| 2907 | . | ||
| 2908 | ((THIS . LAST) . (NOMENUS . LAST_IS_META))) | ||
| 2909 | Since map_char_table doesn't really use the return value from this function, | ||
| 2910 | we the result append to RESULT, the slot in ARGS. | ||
| 2911 | |||
| 2912 | This function can GC because it calls where_is_internal_1 which can | ||
| 2913 | GC. */ | ||
| 2914 | |||
| 2915 | static void | ||
| 2916 | where_is_internal_2 (args, key, binding) | ||
| 2917 | Lisp_Object args, key, binding; | ||
| 2918 | { | ||
| 2919 | Lisp_Object definition, noindirect, this, last; | ||
| 2920 | Lisp_Object result, sequence; | ||
| 2921 | int nomenus, last_is_meta; | ||
| 2922 | struct gcpro gcpro1, gcpro2, gcpro3; | ||
| 2923 | |||
| 2924 | GCPRO3 (args, key, binding); | ||
| 2925 | result = XCDR (XCAR (args)); | ||
| 2926 | definition = XCAR (XCAR (XCAR (args))); | ||
| 2927 | noindirect = XCDR (XCAR (XCAR (args))); | ||
| 2928 | this = XCAR (XCAR (XCDR (args))); | ||
| 2929 | last = XCDR (XCAR (XCDR (args))); | ||
| 2930 | nomenus = XFASTINT (XCAR (XCDR (XCDR (args)))); | ||
| 2931 | last_is_meta = XFASTINT (XCDR (XCDR (XCDR (args)))); | ||
| 2932 | |||
| 2933 | sequence = where_is_internal_1 (binding, key, definition, noindirect, | ||
| 2934 | this, last, nomenus, last_is_meta); | ||
| 2935 | |||
| 2936 | if (!NILP (sequence)) | ||
| 2937 | XSETCDR (XCAR (args), Fcons (sequence, result)); | ||
| 2938 | |||
| 2939 | UNGCPRO; | ||
| 2940 | } | ||
| 2941 | |||
| 2942 | |||
| 2943 | /* This function can GC because get_keyelt can. */ | 2919 | /* This function can GC because get_keyelt can. */ |
| 2944 | 2920 | ||
| 2945 | static Lisp_Object | 2921 | static void |
| 2946 | where_is_internal_1 (binding, key, definition, noindirect, this, last, | 2922 | where_is_internal_1 (key, binding, args, data) |
| 2947 | nomenus, last_is_meta) | 2923 | Lisp_Object key, binding, args; |
| 2948 | Lisp_Object binding, key, definition, noindirect, this, last; | 2924 | void *data; |
| 2949 | int nomenus, last_is_meta; | ||
| 2950 | { | 2925 | { |
| 2926 | struct where_is_internal_data *d = data; /* Cast! */ | ||
| 2927 | Lisp_Object definition = d->definition; | ||
| 2928 | Lisp_Object noindirect = d->noindirect; | ||
| 2929 | Lisp_Object this = d->this; | ||
| 2930 | Lisp_Object last = d->last; | ||
| 2931 | int last_is_meta = d->last_is_meta; | ||
| 2951 | Lisp_Object sequence; | 2932 | Lisp_Object sequence; |
| 2952 | 2933 | ||
| 2953 | /* Search through indirections unless that's not wanted. */ | 2934 | /* Search through indirections unless that's not wanted. */ |
| @@ -2961,7 +2942,7 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, | |||
| 2961 | || EQ (binding, definition) | 2942 | || EQ (binding, definition) |
| 2962 | || (CONSP (definition) && !NILP (Fequal (binding, definition))))) | 2943 | || (CONSP (definition) && !NILP (Fequal (binding, definition))))) |
| 2963 | /* Doesn't match. */ | 2944 | /* Doesn't match. */ |
| 2964 | return Qnil; | 2945 | return; |
| 2965 | 2946 | ||
| 2966 | /* We have found a match. Construct the key sequence where we found it. */ | 2947 | /* We have found a match. Construct the key sequence where we found it. */ |
| 2967 | if (INTEGERP (key) && last_is_meta) | 2948 | if (INTEGERP (key) && last_is_meta) |
| @@ -2976,10 +2957,9 @@ where_is_internal_1 (binding, key, definition, noindirect, this, last, | |||
| 2976 | { | 2957 | { |
| 2977 | Lisp_Object sequences = Fgethash (binding, where_is_cache, Qnil); | 2958 | Lisp_Object sequences = Fgethash (binding, where_is_cache, Qnil); |
| 2978 | Fputhash (binding, Fcons (sequence, sequences), where_is_cache); | 2959 | Fputhash (binding, Fcons (sequence, sequences), where_is_cache); |
| 2979 | return Qnil; | ||
| 2980 | } | 2960 | } |
| 2981 | else | 2961 | else |
| 2982 | return sequence; | 2962 | d->sequences = Fcons (sequence, d->sequences); |
| 2983 | } | 2963 | } |
| 2984 | 2964 | ||
| 2985 | /* describe-bindings - summarizing all the bindings in a set of keymaps. */ | 2965 | /* describe-bindings - summarizing all the bindings in a set of keymaps. */ |