Mercurial > emacs
comparison src/keyboard.c @ 1328:c4eb3aa71303
* keyboard.c (read_key_sequence): Treat mouse clicks on non-text
areas as if they were prefixed with the symbol denoting the
area clicked on - `mode-line', etcetera.
When we throw away an unbound `down-' event, reset mock_input as
well.
* keyboard.c (Qevent_symbol_element_mask, Qmodifier_cache): Two
new symbols, used to implement caches on event heads. These take
the place of some of the caching that modify_event_symbol used to do.
(parse_modifiers_uncached, apply_modifiers_uncached,
lispy_modifier_list, parse_modifiers, apply_modifiers): New
functions, which replace format_modifiers and reorder_modifiers;
they can be useful elsewhere too.
(reorder_modifiers, modify_event_symbol): Re-implement these in
terms of parse_modifiers and apply_modifiers. modify_event_symbol
now uses a much simpler cache, and takes advantage of the caches
maintained by parse_ and apply_modifiers.
(follow_key): Don't modify NEXT if KEY has no bindings.
(read_key_sequence): Drop unbound `down-' events, and turn unbound
`drag-' events into clicks if that would make them bound. This
benefits from the rewriting of the modifier key handling code.
(syms_of_keyboard): Initialize and intern
Qevent_symbol_element_mask and Qmodifier_cache.
* keyboard.c (echo_prompt): Terminate the echo buffer properly
even when the string is too long to display in the minibuffer.
(echo_truncate): Just return echoptr - echobuf, rather than
calling strlen on echobuf.
* keyboard.c (modifier_names): The modifier is named "control",
not "ctrl".
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Sat, 03 Oct 1992 15:37:35 +0000 |
parents | 5f327f1dddd3 |
children | 5845050f9d5c |
comparison
equal
deleted
inserted
replaced
1327:ef16e7c0d402 | 1328:c4eb3aa71303 |
---|---|
293 | 293 |
294 /* Properties of event headers. */ | 294 /* Properties of event headers. */ |
295 Lisp_Object Qevent_kind; | 295 Lisp_Object Qevent_kind; |
296 Lisp_Object Qevent_symbol_elements; | 296 Lisp_Object Qevent_symbol_elements; |
297 | 297 |
298 /* An event header symbol HEAD may have a property named | |
299 Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS); | |
300 BASE is the base, unmodified version of HEAD, and MODIFIERS is the | |
301 mask of modifiers applied to it. If present, this is used to help | |
302 speed up parse_modifiers. */ | |
303 Lisp_Object Qevent_symbol_element_mask; | |
304 | |
305 /* An unmodified event header BASE may have a property named | |
306 Qmodifier_cache, which is an alist mapping modifier masks onto | |
307 modified versions of BASE. If present, this helps speed up | |
308 apply_modifiers. */ | |
309 Lisp_Object Qmodifier_cache; | |
310 | |
298 /* Symbols to use for non-text mouse positions. */ | 311 /* Symbols to use for non-text mouse positions. */ |
299 Lisp_Object Qmode_line; | 312 Lisp_Object Qmode_line; |
300 Lisp_Object Qvertical_line; | 313 Lisp_Object Qvertical_line; |
301 | 314 |
302 | 315 |
367 char *str; | 380 char *str; |
368 { | 381 { |
369 int len = strlen (str); | 382 int len = strlen (str); |
370 if (len > sizeof echobuf - 4) | 383 if (len > sizeof echobuf - 4) |
371 len = sizeof echobuf - 4; | 384 len = sizeof echobuf - 4; |
372 bcopy (str, echobuf, len + 1); | 385 bcopy (str, echobuf, len); |
373 echoptr = echobuf + len; | 386 echoptr = echobuf + len; |
387 *echoptr = '\0'; | |
374 | 388 |
375 echo (); | 389 echo (); |
376 } | 390 } |
377 | 391 |
378 /* Add C to the echo string, if echoing is going on. | 392 /* Add C to the echo string, if echoing is going on. |
485 static void | 499 static void |
486 echo_truncate (len) | 500 echo_truncate (len) |
487 int len; | 501 int len; |
488 { | 502 { |
489 echobuf[len] = '\0'; | 503 echobuf[len] = '\0'; |
490 echoptr = echobuf + strlen (echobuf); | 504 echoptr = echobuf + len; |
491 } | 505 } |
492 | 506 |
493 | 507 |
494 /* Functions for manipulating this_command_keys. */ | 508 /* Functions for manipulating this_command_keys. */ |
495 static void | 509 static void |
1701 switch (event->kind) | 1715 switch (event->kind) |
1702 #endif | 1716 #endif |
1703 { | 1717 { |
1704 /* A simple keystroke. */ | 1718 /* A simple keystroke. */ |
1705 case ascii_keystroke: | 1719 case ascii_keystroke: |
1706 return event->code; | 1720 return XFASTINT (event->code); |
1707 break; | 1721 break; |
1708 | 1722 |
1709 /* A function key. The symbol may need to have modifier prefixes | 1723 /* A function key. The symbol may need to have modifier prefixes |
1710 tacked onto it. */ | 1724 tacked onto it. */ |
1711 case non_ascii_keystroke: | 1725 case non_ascii_keystroke: |
1718 | 1732 |
1719 /* A mouse click. Figure out where it is, decide whether it's | 1733 /* A mouse click. Figure out where it is, decide whether it's |
1720 a press, click or drag, and build the appropriate structure. */ | 1734 a press, click or drag, and build the appropriate structure. */ |
1721 case mouse_click: | 1735 case mouse_click: |
1722 { | 1736 { |
1737 int button = XFASTINT (event->code); | |
1723 int part; | 1738 int part; |
1724 Lisp_Object window; | 1739 Lisp_Object window; |
1725 Lisp_Object posn; | 1740 Lisp_Object posn; |
1726 struct mouse_position *loc; | 1741 struct mouse_position *loc; |
1727 | 1742 |
1728 if (event->code < 0 || event->code >= NUM_MOUSE_BUTTONS) | 1743 if (button < 0 || button >= NUM_MOUSE_BUTTONS) |
1729 abort (); | 1744 abort (); |
1730 | 1745 |
1731 /* Where did this mouse click occur? */ | 1746 /* Where did this mouse click occur? */ |
1732 window = window_from_coordinates (event->frame, | 1747 window = window_from_coordinates (event->frame, |
1733 XINT (event->x), XINT (event->y), | 1748 XINT (event->x), XINT (event->y), |
1751 XINT (event->y))); | 1766 XINT (event->y))); |
1752 } | 1767 } |
1753 | 1768 |
1754 /* If this is a button press, squirrel away the location, so we | 1769 /* If this is a button press, squirrel away the location, so we |
1755 can decide later whether it was a click or a drag. */ | 1770 can decide later whether it was a click or a drag. */ |
1756 loc = button_down_location + event->code; | 1771 loc = button_down_location + button; |
1757 if (event->modifiers & down_modifier) | 1772 if (event->modifiers & down_modifier) |
1758 { | 1773 { |
1759 loc->window = window; | 1774 loc->window = window; |
1760 loc->buffer_pos = posn; | 1775 loc->buffer_pos = posn; |
1761 loc->x = event->x; | 1776 loc->x = event->x; |
1781 /* Build the event. */ | 1796 /* Build the event. */ |
1782 { | 1797 { |
1783 Lisp_Object head, start, end; | 1798 Lisp_Object head, start, end; |
1784 | 1799 |
1785 /* Build the components of the event. */ | 1800 /* Build the components of the event. */ |
1786 head = modify_event_symbol (XFASTINT (event->code) - 1, | 1801 head = modify_event_symbol (button - 1, |
1787 event->modifiers, | 1802 event->modifiers, |
1788 Qmouse_click, | 1803 Qmouse_click, |
1789 lispy_mouse_names, &mouse_syms, | 1804 lispy_mouse_names, &mouse_syms, |
1790 (sizeof (lispy_mouse_names) | 1805 (sizeof (lispy_mouse_names) |
1791 / sizeof (lispy_mouse_names[0]))); | 1806 / sizeof (lispy_mouse_names[0]))); |
1881 Qnil)))), | 1896 Qnil)))), |
1882 Qnil)); | 1897 Qnil)); |
1883 } | 1898 } |
1884 | 1899 |
1885 | 1900 |
1886 | 1901 |
1887 /* Place the written representation of MODIFIERS in BUF, '\0'-terminated, | 1902 /* Manipulating modifiers. */ |
1888 and return its length. */ | 1903 |
1889 | 1904 /* Parse the name of SYMBOL, and return the set of modifiers it contains. |
1905 | |
1906 If MODIFIER_END is non-zero, set *MODIFIER_END to the position in | |
1907 SYMBOL's name of the end of the modifiers; the string from this | |
1908 position is the unmodified symbol name. | |
1909 | |
1910 This doesn't use any caches. */ | |
1890 static int | 1911 static int |
1891 format_modifiers (modifiers, buf) | 1912 parse_modifiers_uncached (symbol, modifier_end) |
1892 int modifiers; | |
1893 char *buf; | |
1894 { | |
1895 char *p = buf; | |
1896 | |
1897 /* Only the event queue may use the `up' modifier; it should always | |
1898 be turned into a click or drag event before presented to lisp code. */ | |
1899 if (modifiers & up_modifier) | |
1900 abort (); | |
1901 | |
1902 if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; } | |
1903 if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } | |
1904 if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } | |
1905 if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } | |
1906 if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } | |
1907 if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } | |
1908 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } | |
1909 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } | |
1910 /* The click modifier is denoted by the absence of other modifiers. */ | |
1911 *p = '\0'; | |
1912 | |
1913 return p - buf; | |
1914 } | |
1915 | |
1916 | |
1917 /* Given a symbol whose name begins with modifiers ("C-", "M-", etc), | |
1918 return a symbol with the modifiers placed in the canonical order. | |
1919 Canonical order is alphabetical, except for down and drag, which | |
1920 always come last. The 'click' modifier is never written out. | |
1921 | |
1922 Fdefine_key calls this to make sure that (for example) C-M-foo | |
1923 and M-C-foo end up being equivalent in the keymap. */ | |
1924 | |
1925 Lisp_Object | |
1926 reorder_modifiers (symbol) | |
1927 Lisp_Object symbol; | 1913 Lisp_Object symbol; |
1914 int *modifier_end; | |
1928 { | 1915 { |
1929 struct Lisp_String *name; | 1916 struct Lisp_String *name; |
1930 int i; | 1917 int i; |
1931 int modifiers; | 1918 int modifiers; |
1932 int not_canonical; | |
1933 | 1919 |
1934 CHECK_SYMBOL (symbol, 1); | 1920 CHECK_SYMBOL (symbol, 1); |
1935 | 1921 |
1936 modifiers = 0; | 1922 modifiers = 0; |
1937 name = XSYMBOL (symbol)->name; | 1923 name = XSYMBOL (symbol)->name; |
1938 | 1924 |
1939 /* Special case for things with only one modifier, which is | 1925 |
1940 (hopefully) the vast majority of cases. */ | 1926 for (i = 0; i+2 <= name->size; ) |
1941 if (! (name->size >= 4 && name->data[1] == '-' && name->data[3] == '-')) | |
1942 return symbol; | |
1943 | |
1944 for (i = 0; i+1 < name->data[i]; ) | |
1945 switch (name->data[i]) | 1927 switch (name->data[i]) |
1946 { | 1928 { |
1929 #define SINGLE_LETTER_MOD(bit) \ | |
1930 if (name->data[i+1] != '-') \ | |
1931 goto no_more_modifiers; \ | |
1932 modifiers |= bit; \ | |
1933 i += 2; | |
1934 | |
1947 case 'A': | 1935 case 'A': |
1948 if (name->data[i] != '-') goto no_more_modifiers; | 1936 SINGLE_LETTER_MOD (alt_modifier); |
1949 not_canonical |= (modifiers & ~(alt_modifier - 1)); | |
1950 modifiers |= alt_modifier; | |
1951 i += 2; | |
1952 break; | 1937 break; |
1953 | 1938 |
1954 case 'C': | 1939 case 'C': |
1955 if (name->data[i] != '-') goto no_more_modifiers; | 1940 SINGLE_LETTER_MOD (ctrl_modifier); |
1956 not_canonical |= (modifiers & ~(ctrl_modifier - 1)); | |
1957 modifiers |= ctrl_modifier; | |
1958 i += 2; | |
1959 break; | 1941 break; |
1960 | 1942 |
1961 case 'H': | 1943 case 'H': |
1962 if (name->data[i] != '-') goto no_more_modifiers; | 1944 SINGLE_LETTER_MOD (hyper_modifier); |
1963 not_canonical |= (modifiers & ~(hyper_modifier - 1)); | |
1964 modifiers |= hyper_modifier; | |
1965 i += 2; | |
1966 break; | 1945 break; |
1967 | 1946 |
1968 case 'M': | 1947 case 'M': |
1969 if (name->data[i] != '-') goto no_more_modifiers; | 1948 SINGLE_LETTER_MOD (meta_modifier); |
1970 not_canonical |= (modifiers & ~(meta_modifier - 1)); | |
1971 modifiers |= meta_modifier; | |
1972 i += 2; | |
1973 break; | 1949 break; |
1974 | 1950 |
1975 case 'S': | 1951 case 'S': |
1976 if (name->data[i] != '-') goto no_more_modifiers; | 1952 SINGLE_LETTER_MOD (shift_modifier); |
1977 not_canonical |= (modifiers & ~(shift_modifier - 1)); | |
1978 modifiers |= shift_modifier; | |
1979 i += 2; | |
1980 break; | 1953 break; |
1981 | 1954 |
1982 case 's': | 1955 case 's': |
1983 if (i + 6 > name->size | 1956 if (i + 6 > name->size |
1984 || strncmp (name->data + i, "super-", 6)) | 1957 || strncmp (name->data + i, "super-", 6)) |
1985 goto no_more_modifiers; | 1958 goto no_more_modifiers; |
1986 not_canonical |= (modifiers & ~(super_modifier - 1)); | |
1987 modifiers |= super_modifier; | 1959 modifiers |= super_modifier; |
1988 i += 6; | 1960 i += 6; |
1989 break; | 1961 break; |
1990 | 1962 |
1991 case 'd': | 1963 case 'd': |
1992 if (i + 5 > name->size) | 1964 if (i + 5 > name->size) |
1993 goto no_more_modifiers; | 1965 goto no_more_modifiers; |
1994 if (! strncmp (name->data + i, "drag-", 5)) | 1966 if (! strncmp (name->data + i, "drag-", 5)) |
1995 { | 1967 { |
1996 not_canonical |= (modifiers & ~(drag_modifier - 1)); | |
1997 modifiers |= drag_modifier; | 1968 modifiers |= drag_modifier; |
1998 i += 5; | 1969 i += 5; |
1999 } | 1970 } |
2000 else if (! strncmp (name->data + i, "down-", 5)) | 1971 else if (! strncmp (name->data + i, "down-", 5)) |
2001 { | 1972 { |
2002 not_canonical |= (modifiers & ~(down_modifier - 1)); | |
2003 modifiers |= down_modifier; | 1973 modifiers |= down_modifier; |
2004 i += 5; | 1974 i += 5; |
2005 } | 1975 } |
2006 else | 1976 else |
2007 goto no_more_modifiers; | 1977 goto no_more_modifiers; |
2008 break; | 1978 break; |
2009 | 1979 |
2010 default: | 1980 default: |
2011 goto no_more_modifiers; | 1981 goto no_more_modifiers; |
1982 | |
1983 #undef SINGLE_LETTER_MOD | |
2012 } | 1984 } |
2013 no_more_modifiers: | 1985 no_more_modifiers: |
2014 | 1986 |
2015 if (!not_canonical) | 1987 /* Should we include the `click' modifier? */ |
2016 return symbol; | 1988 if (! (modifiers & (down_modifier | drag_modifier)) |
2017 | 1989 && i + 7 == name->size |
2018 /* The modifiers were out of order, so find a new symbol with the | 1990 && strncmp (name->data + i, "mouse-", 6) |
2019 mods in order. Since the symbol name could contain nulls, we can't | 1991 && '0' <= name->data[i + 6] |
2020 use intern here; we have to use Fintern, which expects a genuine | 1992 && name->data[i + 6] <= '9') |
2021 Lisp_String, and keeps a reference to it. */ | 1993 modifiers |= click_modifier; |
1994 | |
1995 if (modifier_end) | |
1996 *modifier_end = i; | |
1997 | |
1998 return modifiers; | |
1999 } | |
2000 | |
2001 | |
2002 /* Return a symbol whose name is the modifier prefixes for MODIFIERS | |
2003 prepended to the string BASE[0..BASE_LEN-1]. | |
2004 This doesn't use any caches. */ | |
2005 static Lisp_Object | |
2006 apply_modifiers_uncached (modifiers, base, base_len) | |
2007 int modifiers; | |
2008 char *base; | |
2009 int base_len; | |
2010 { | |
2011 /* Since BASE could contain nulls, we can't use intern here; we have | |
2012 to use Fintern, which expects a genuine Lisp_String, and keeps a | |
2013 reference to it. */ | |
2014 char *new_mods = | |
2015 (char *) alloca (sizeof ("A-C-H-M-S-super-down-drag-")); | |
2016 int mod_len; | |
2017 | |
2022 { | 2018 { |
2023 char *new_mods = (char *) alloca (sizeof ("A-C-H-M-S-super-U-down-drag-")); | 2019 char *p = new_mods; |
2024 int len = format_modifiers (modifiers, new_mods); | 2020 |
2025 Lisp_Object new_name = make_uninit_string (len + name->size - i); | 2021 /* Only the event queue may use the `up' modifier; it should always |
2026 | 2022 be turned into a click or drag event before presented to lisp code. */ |
2027 bcopy (new_mods, XSTRING (new_name)->data, len); | 2023 if (modifiers & up_modifier) |
2028 bcopy (name->data + i, XSTRING (new_name)->data + len, name->size - i); | 2024 abort (); |
2025 | |
2026 if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; } | |
2027 if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } | |
2028 if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } | |
2029 if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } | |
2030 if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } | |
2031 if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } | |
2032 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } | |
2033 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } | |
2034 /* The click modifier is denoted by the absence of other modifiers. */ | |
2035 | |
2036 *p = '\0'; | |
2037 | |
2038 mod_len = p - new_mods; | |
2039 } | |
2040 | |
2041 { | |
2042 Lisp_Object new_name = make_uninit_string (mod_len + base_len); | |
2043 | |
2044 bcopy (new_mods, XSTRING (new_name)->data, mod_len); | |
2045 bcopy (base, XSTRING (new_name)->data + mod_len, base_len); | |
2029 | 2046 |
2030 return Fintern (new_name, Qnil); | 2047 return Fintern (new_name, Qnil); |
2031 } | 2048 } |
2049 } | |
2050 | |
2051 | |
2052 static char *modifier_names[] = | |
2053 { | |
2054 "up", "alt", "control", "hyper", "meta", "shift", "super", "down", "drag", | |
2055 "click" | |
2056 }; | |
2057 | |
2058 static Lisp_Object modifier_symbols; | |
2059 | |
2060 /* Return the list of modifier symbols corresponding to the mask MODIFIERS. */ | |
2061 static Lisp_Object | |
2062 lispy_modifier_list (modifiers) | |
2063 int modifiers; | |
2064 { | |
2065 Lisp_Object modifier_list; | |
2066 int i; | |
2067 | |
2068 modifier_list = Qnil; | |
2069 for (i = 0; (1<<i) <= modifiers; i++) | |
2070 if (modifiers & (1<<i)) | |
2071 modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], | |
2072 modifier_list); | |
2073 | |
2074 return modifier_list; | |
2075 } | |
2076 | |
2077 | |
2078 /* Parse the modifiers on SYMBOL, and return a list like (UNMODIFIED MASK), | |
2079 where UNMODIFIED is the unmodified form of SYMBOL, | |
2080 MASK is the set of modifiers present in SYMBOL's name. | |
2081 This is similar to parse_modifiers_uncached, but uses the cache in | |
2082 SYMBOL's Qevent_symbol_element_mask property, and maintains the | |
2083 Qevent_symbol_elements property. */ | |
2084 static Lisp_Object | |
2085 parse_modifiers (symbol) | |
2086 Lisp_Object symbol; | |
2087 { | |
2088 Lisp_Object elements = Fget (symbol, Qevent_symbol_element_mask); | |
2089 | |
2090 if (CONSP (elements)) | |
2091 return elements; | |
2092 else | |
2093 { | |
2094 int end; | |
2095 int modifiers = parse_modifiers_uncached (symbol, &end); | |
2096 Lisp_Object unmodified | |
2097 = Fintern (make_string (XSYMBOL (symbol)->name->data + end, | |
2098 XSYMBOL (symbol)->name->size - end), | |
2099 Qnil); | |
2100 Lisp_Object mask; | |
2101 | |
2102 XFASTINT (mask) = modifiers; | |
2103 elements = Fcons (unmodified, Fcons (mask, Qnil)); | |
2104 | |
2105 /* Cache the parsing results on SYMBOL. */ | |
2106 Fput (symbol, Qevent_symbol_element_mask, | |
2107 elements); | |
2108 Fput (symbol, Qevent_symbol_elements, | |
2109 Fcons (unmodified, lispy_modifier_list (modifiers))); | |
2110 | |
2111 /* Since we know that SYMBOL is modifiers applied to unmodified, | |
2112 it would be nice to put that in unmodified's cache. | |
2113 But we can't, since we're not sure that parse_modifiers is | |
2114 canonical. */ | |
2115 | |
2116 return elements; | |
2117 } | |
2118 } | |
2119 | |
2120 /* Apply the modifiers MODIFIERS to the symbol BASE. | |
2121 BASE must be unmodified. | |
2122 | |
2123 This is like apply_modifiers_uncached, but uses BASE's | |
2124 Qmodifier_cache property, if present. It also builds | |
2125 Qevent_symbol_elements properties, since it has that info anyway. */ | |
2126 static Lisp_Object | |
2127 apply_modifiers (modifiers, base) | |
2128 int modifiers; | |
2129 Lisp_Object base; | |
2130 { | |
2131 Lisp_Object cache, index, entry; | |
2132 | |
2133 /* The click modifier never figures into cache indices. */ | |
2134 XFASTINT (index) = (modifiers & ~click_modifier); | |
2135 cache = Fget (base, Qmodifier_cache); | |
2136 entry = Fassq (index, cache); | |
2137 | |
2138 if (CONSP (entry)) | |
2139 return XCONS (entry)->cdr; | |
2140 | |
2141 /* We have to create the symbol ourselves. */ | |
2142 { | |
2143 Lisp_Object new_symbol | |
2144 = apply_modifiers_uncached (modifiers, | |
2145 XSYMBOL (base)->name->data, | |
2146 XSYMBOL (base)->name->size); | |
2147 | |
2148 /* Add the new symbol to the base's cache. */ | |
2149 Fput (base, Qmodifier_cache, | |
2150 Fcons (Fcons (index, new_symbol), cache)); | |
2151 | |
2152 /* We have the parsing info now for free, so add it to the caches. */ | |
2153 XFASTINT (index) = modifiers; | |
2154 Fput (new_symbol, Qevent_symbol_element_mask, | |
2155 Fcons (base, Fcons (index, Qnil))); | |
2156 Fput (new_symbol, Qevent_symbol_elements, | |
2157 Fcons (base, lispy_modifier_list (modifiers))); | |
2158 | |
2159 return new_symbol; | |
2160 } | |
2161 } | |
2162 | |
2163 | |
2164 /* Given a symbol whose name begins with modifiers ("C-", "M-", etc), | |
2165 return a symbol with the modifiers placed in the canonical order. | |
2166 Canonical order is alphabetical, except for down and drag, which | |
2167 always come last. The 'click' modifier is never written out. | |
2168 | |
2169 Fdefine_key calls this to make sure that (for example) C-M-foo | |
2170 and M-C-foo end up being equivalent in the keymap. */ | |
2171 | |
2172 Lisp_Object | |
2173 reorder_modifiers (symbol) | |
2174 Lisp_Object symbol; | |
2175 { | |
2176 /* It's hopefully okay to write the code this way, since everything | |
2177 will soon be in caches, and no consing will be done at all. */ | |
2178 Lisp_Object parsed = parse_modifiers (symbol); | |
2179 | |
2180 return apply_modifiers (XCONS (XCONS (parsed)->cdr)->car, | |
2181 XCONS (parsed)->car); | |
2032 } | 2182 } |
2033 | 2183 |
2034 | 2184 |
2035 /* For handling events, we often want to produce a symbol whose name | 2185 /* For handling events, we often want to produce a symbol whose name |
2036 is a series of modifier key prefixes ("M-", "C-", etcetera) attached | 2186 is a series of modifier key prefixes ("M-", "C-", etcetera) attached |
2055 the returned symbol. | 2205 the returned symbol. |
2056 | 2206 |
2057 The symbols we create are supposed to have an | 2207 The symbols we create are supposed to have an |
2058 `event-symbol-elements' propery, which lists the modifiers present | 2208 `event-symbol-elements' propery, which lists the modifiers present |
2059 in the symbol's name. */ | 2209 in the symbol's name. */ |
2060 | |
2061 static char *modifier_names[] = | |
2062 { | |
2063 "up", "alt", "ctrl", "hyper", "meta", "shift", "super", "down", "drag", | |
2064 "click" | |
2065 }; | |
2066 | |
2067 static Lisp_Object modifier_symbols; | |
2068 | 2210 |
2069 static Lisp_Object | 2211 static Lisp_Object |
2070 modify_event_symbol (symbol_num, modifiers, symbol_kind, name_table, | 2212 modify_event_symbol (symbol_num, modifiers, symbol_kind, name_table, |
2071 symbol_table, table_size) | 2213 symbol_table, table_size) |
2072 int symbol_num; | 2214 int symbol_num; |
2075 char **name_table; | 2217 char **name_table; |
2076 Lisp_Object *symbol_table; | 2218 Lisp_Object *symbol_table; |
2077 int table_size; | 2219 int table_size; |
2078 { | 2220 { |
2079 Lisp_Object *slot; | 2221 Lisp_Object *slot; |
2080 Lisp_Object unmodified; | |
2081 Lisp_Object temp; | |
2082 | 2222 |
2083 /* Is this a request for a valid symbol? */ | 2223 /* Is this a request for a valid symbol? */ |
2084 if (symbol_num < 0 || symbol_num >= table_size) | 2224 if (symbol_num < 0 || symbol_num >= table_size) |
2085 abort (); | 2225 abort (); |
2086 | 2226 |
2087 /* If *symbol_table doesn't seem to be initialized property, fix that. | 2227 /* If *symbol_table doesn't seem to be initialized properly, fix that. |
2088 | |
2089 *symbol_table should be a lisp vector TABLE_SIZE elements long, | 2228 *symbol_table should be a lisp vector TABLE_SIZE elements long, |
2090 where the Nth element is an alist for modified versions of | 2229 where the Nth element is the symbol for NAME_TABLE[N]. */ |
2091 name_table[N]; the alist maps modifier masks onto the modified | |
2092 symbols. The click modifier is always omitted from the mask; it | |
2093 is indicated implicitly on a mouse event by the absence of the | |
2094 down_ and drag_ modifiers. */ | |
2095 if (XTYPE (*symbol_table) != Lisp_Vector | 2230 if (XTYPE (*symbol_table) != Lisp_Vector |
2096 || XVECTOR (*symbol_table)->size != table_size) | 2231 || XVECTOR (*symbol_table)->size != table_size) |
2097 { | 2232 { |
2098 XFASTINT (temp) = table_size; | 2233 Lisp_Object size; |
2099 *symbol_table = Fmake_vector (temp, Qnil); | 2234 |
2235 XFASTINT (size) = table_size; | |
2236 *symbol_table = Fmake_vector (size, Qnil); | |
2100 } | 2237 } |
2101 | 2238 |
2102 slot = & XVECTOR (*symbol_table)->contents[symbol_num]; | 2239 slot = & XVECTOR (*symbol_table)->contents[symbol_num]; |
2103 | 2240 |
2104 /* Have we already modified this symbol? */ | 2241 /* Have we already used this symbol before? */ |
2105 XFASTINT (temp) = modifiers & ~(click_modifier); | 2242 if (NILP (*slot)) |
2106 temp = Fassq (temp, *slot); | 2243 { |
2107 if (CONSP (temp)) | 2244 /* No; let's create it. */ |
2108 return (XCONS (temp)->cdr); | 2245 *slot = intern (name_table[symbol_num]); |
2109 | 2246 |
2110 /* We don't have an entry for the symbol; we have to build it. */ | 2247 /* Fill in the cache entries for this symbol; this also |
2111 | 2248 builds the Qevent_symbol_elements property, which the user |
2112 /* Create a modified version of the symbol, and add it to the alist. */ | 2249 cares about. */ |
2113 { | 2250 apply_modifiers (0, *slot); |
2114 Lisp_Object modified; | 2251 Fput (*slot, Qevent_kind, symbol_kind); |
2115 char *modified_name | 2252 } |
2116 = (char *) alloca (sizeof ("A-C-H-M-S-super-U-down-drag") | 2253 |
2117 + strlen (name_table [symbol_num])); | 2254 /* Apply modifiers to that symbol. */ |
2118 | 2255 return apply_modifiers (modifiers, *slot); |
2119 strcpy (modified_name + format_modifiers (modifiers, modified_name), | 2256 } |
2120 name_table [symbol_num]); | 2257 |
2121 | |
2122 modified = intern (modified_name); | |
2123 XFASTINT (temp) = modifiers & ~click_modifier; | |
2124 *slot = Fcons (Fcons (temp, modified), *slot); | |
2125 Fput (modified, Qevent_kind, symbol_kind); | |
2126 | |
2127 { | |
2128 Lisp_Object modifier_list; | |
2129 int i; | |
2130 | |
2131 modifier_list = Qnil; | |
2132 for (i = 0; (1<<i) <= modifiers; i++) | |
2133 if (modifiers & (1<<i)) | |
2134 modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], | |
2135 modifier_list); | |
2136 | |
2137 /* Put an unmodified version of the symbol at the head of the | |
2138 list of symbol elements. */ | |
2139 { | |
2140 /* We recurse to get the unmodified symbol; this allows us to | |
2141 write out the code to build event headers only once. | |
2142 | |
2143 Note that we put ourselves in the symbol_table before we | |
2144 recurse, so when an unmodified symbol calls this code | |
2145 to put itself on its Qevent_symbol_elements property, we do | |
2146 terminate. */ | |
2147 Lisp_Object unmodified = | |
2148 modify_event_symbol (symbol_num, | |
2149 ((modifiers & (down_modifier | drag_modifier)) | |
2150 ? click_modifier | |
2151 : 0), | |
2152 symbol_kind, | |
2153 name_table, symbol_table, table_size); | |
2154 | |
2155 Fput (modified, Qevent_symbol_elements, | |
2156 Fcons (unmodified, modifier_list)); | |
2157 } | |
2158 } | |
2159 | |
2160 return modified; | |
2161 } | |
2162 } | |
2163 | 2258 |
2164 DEFUN ("mouse-click-p", Fmouse_click_p, Smouse_click_p, 1, 1, 0, | 2259 DEFUN ("mouse-click-p", Fmouse_click_p, Smouse_click_p, 1, 1, 0, |
2165 "Return non-nil iff OBJECT is a representation of a mouse event.\n\ | 2260 "Return non-nil iff OBJECT is a representation of a mouse event.\n\ |
2166 A mouse event is a list of five elements whose car is a symbol of the\n\ | 2261 A mouse event is a list of five elements whose car is a symbol of the\n\ |
2167 form <MODIFIERS>mouse-<DIGIT>. I hope this is a temporary hack.") | 2262 form <MODIFIERS>mouse-<DIGIT>. I hope this is a temporary hack.") |
2665 defs[i] = Qnil; | 2760 defs[i] = Qnil; |
2666 } | 2761 } |
2667 } | 2762 } |
2668 | 2763 |
2669 /* Given the set of bindings we've found, produce the next set of maps. */ | 2764 /* Given the set of bindings we've found, produce the next set of maps. */ |
2670 for (i = 0; i < nmaps; i++) | 2765 if (first_binding < nmaps) |
2671 next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0); | 2766 for (i = 0; i < nmaps; i++) |
2767 next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0); | |
2672 | 2768 |
2673 return first_binding; | 2769 return first_binding; |
2674 } | 2770 } |
2675 | 2771 |
2676 /* Read a sequence of keys that ends with a non prefix character | 2772 /* Read a sequence of keys that ends with a non prefix character |
2765 fkey_start = fkey_end = bufsize + 1; | 2861 fkey_start = fkey_end = bufsize + 1; |
2766 | 2862 |
2767 restart: | 2863 restart: |
2768 t = 0; | 2864 t = 0; |
2769 this_command_key_count = keys_start; | 2865 this_command_key_count = keys_start; |
2866 | |
2867 /* This is a no-op the first time through, but if we restart, it | |
2868 reverts the echo area to its original state. */ | |
2869 if (INTERACTIVE) | |
2870 echo_truncate (echo_start); | |
2770 | 2871 |
2771 { | 2872 { |
2772 Lisp_Object *maps; | 2873 Lisp_Object *maps; |
2773 | 2874 |
2774 nmaps = current_minor_maps (0, &maps) + 2; | 2875 nmaps = current_minor_maps (0, &maps) + 2; |
2792 || (first_binding >= nmaps && fkey_start < t)) | 2893 || (first_binding >= nmaps && fkey_start < t)) |
2793 { | 2894 { |
2794 Lisp_Object key; | 2895 Lisp_Object key; |
2795 int used_mouse_menu = 0; | 2896 int used_mouse_menu = 0; |
2796 | 2897 |
2898 /* These variables are analogous to echo_start and keys_start; | |
2899 while those allow us to restart the entire key sequence, | |
2900 echo_local_start and keys_local_start allow us to throw away | |
2901 just one key. */ | |
2902 int echo_local_start = echo_length (); | |
2903 int keys_local_start = this_command_key_count; | |
2904 int local_first_binding = first_binding; | |
2905 | |
2797 if (t >= bufsize) | 2906 if (t >= bufsize) |
2798 error ("key sequence too long"); | 2907 error ("key sequence too long"); |
2908 | |
2909 retry_key: | |
2910 /* These are no-ops, unless we throw away a keystroke below and | |
2911 jumped back up to retry_key; in that case, these restore these | |
2912 variables to their original state, allowing us to restart the | |
2913 loop. */ | |
2914 echo_truncate (echo_local_start); | |
2915 this_command_key_count = keys_local_start; | |
2916 first_binding = local_first_binding; | |
2799 | 2917 |
2800 /* Are we re-reading a key sequence, as indicated by mock_input? */ | 2918 /* Are we re-reading a key sequence, as indicated by mock_input? */ |
2801 if (t < mock_input) | 2919 if (t < mock_input) |
2802 { | 2920 { |
2803 key = keybuf[t]; | 2921 key = keybuf[t]; |
2818 zero, so that's what we'll do. */ | 2936 zero, so that's what we'll do. */ |
2819 if (XTYPE (key) == Lisp_Int && XINT (key) < 0) | 2937 if (XTYPE (key) == Lisp_Int && XINT (key) < 0) |
2820 return 0; | 2938 return 0; |
2821 | 2939 |
2822 Vquit_flag = Qnil; | 2940 Vquit_flag = Qnil; |
2941 | |
2942 /* Clicks in non-text areas get prefixed by the symbol | |
2943 in their CHAR-ADDRESS field. For example, a click on | |
2944 the mode line is prefixed by the symbol `mode-line'. */ | |
2945 if (EVENT_HAS_PARAMETERS (key) | |
2946 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qmouse_click)) | |
2947 { | |
2948 Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); | |
2949 | |
2950 if (XTYPE (posn) == Lisp_Symbol) | |
2951 { | |
2952 if (t + 1 >= bufsize) | |
2953 error ("key sequence too long"); | |
2954 keybuf[t] = posn; | |
2955 keybuf[t+1] = key; | |
2956 mock_input = t + 2; | |
2957 | |
2958 goto retry_key; | |
2959 } | |
2960 } | |
2823 | 2961 |
2824 #ifdef MULTI_FRAME | 2962 #ifdef MULTI_FRAME |
2825 /* What buffer was this event typed/moused at? */ | 2963 /* What buffer was this event typed/moused at? */ |
2826 if (used_mouse_menu) | 2964 if (used_mouse_menu) |
2827 /* Never change last_event_buffer for using a menu. */ | 2965 /* Never change last_event_buffer for using a menu. */ |
2857 | 2995 |
2858 /* Arrange to read key as the next event. */ | 2996 /* Arrange to read key as the next event. */ |
2859 keybuf[0] = key; | 2997 keybuf[0] = key; |
2860 mock_input = 1; | 2998 mock_input = 1; |
2861 | 2999 |
2862 /* Truncate the key sequence in the echo area. */ | |
2863 if (INTERACTIVE) | |
2864 echo_truncate (echo_start); | |
2865 | |
2866 goto restart; | 3000 goto restart; |
2867 } | 3001 } |
2868 #endif | 3002 #endif |
2869 } | 3003 } |
2870 | 3004 |
2871 first_binding = (follow_key (key, | 3005 first_binding = (follow_key (key, |
2872 nmaps - first_binding, | 3006 nmaps - first_binding, |
2873 submaps + first_binding, | 3007 submaps + first_binding, |
2874 defs + first_binding, | 3008 defs + first_binding, |
2875 submaps + first_binding) | 3009 submaps + first_binding) |
2876 + first_binding); | 3010 + first_binding); |
3011 | |
3012 /* If this key wasn't bound, we'll try some fallbacks. */ | |
3013 if (first_binding >= nmaps) | |
3014 { | |
3015 Lisp_Object head = EVENT_HEAD (key); | |
3016 | |
3017 if (XTYPE (head) == Lisp_Symbol) | |
3018 { | |
3019 Lisp_Object breakdown = parse_modifiers (head); | |
3020 Lisp_Object modifiers = | |
3021 XINT (XCONS (XCONS (breakdown)->cdr)->car); | |
3022 | |
3023 /* We drop unbound `down-' events altogether. */ | |
3024 if (modifiers & down_modifier) | |
3025 { | |
3026 /* Adding prefixes for non-textual mouse clicks creates | |
3027 two characters of mock input, and this can't be the | |
3028 first, so it's okay to clear mock_input in that case. | |
3029 Only function key expansion could create more than | |
3030 two keys, but that should never generate mouse events, | |
3031 so it's okay to nuke mock_input in that case too. | |
3032 Isn't this just the most wonderful code ever? */ | |
3033 mock_input = 0; | |
3034 goto retry_key; | |
3035 } | |
3036 | |
3037 /* We turn unbound `drag-' events into `click-' | |
3038 events, if the click would be bound. */ | |
3039 else if (modifiers & drag_modifier) | |
3040 { | |
3041 Lisp_Object new_head = | |
3042 apply_modifiers (modifiers & ~drag_modifier, | |
3043 XCONS (breakdown)->car); | |
3044 Lisp_Object new_click = | |
3045 Fcons (new_head, Fcons (EVENT_START (key), Qnil)); | |
3046 | |
3047 /* Look for a binding for this new key. follow_key | |
3048 promises that it didn't munge submaps the | |
3049 last time we called it, since key was unbound. */ | |
3050 first_binding = | |
3051 (follow_key (new_click, | |
3052 nmaps - local_first_binding, | |
3053 submaps + local_first_binding, | |
3054 defs + local_first_binding, | |
3055 submaps + local_first_binding) | |
3056 + local_first_binding); | |
3057 | |
3058 /* If that click is bound, go for it. */ | |
3059 if (first_binding < nmaps) | |
3060 key = new_click; | |
3061 /* Otherwise, we'll leave key set to the drag event. */ | |
3062 } | |
3063 } | |
3064 } | |
3065 | |
2877 keybuf[t++] = key; | 3066 keybuf[t++] = key; |
2878 /* Normally, last_nonmenu_event gets the previous key we read. | 3067 /* Normally, last_nonmenu_event gets the previous key we read. |
2879 But when a mouse popup menu is being used, | 3068 But when a mouse popup menu is being used, |
2880 we don't update last_nonmenu_event; it continues to hold the mouse | 3069 we don't update last_nonmenu_event; it continues to hold the mouse |
2881 event that preceded the first level of menu. */ | 3070 event that preceded the first level of menu. */ |
2923 keybuf + fkey_start, | 3112 keybuf + fkey_start, |
2924 (t - fkey_start) * sizeof (keybuf[0])); | 3113 (t - fkey_start) * sizeof (keybuf[0])); |
2925 | 3114 |
2926 mock_input = t; | 3115 mock_input = t; |
2927 fkey_start = fkey_end = t; | 3116 fkey_start = fkey_end = t; |
2928 | |
2929 /* Truncate the key sequence in the echo area. */ | |
2930 if (INTERACTIVE) | |
2931 echo_truncate (echo_start); | |
2932 | 3117 |
2933 goto restart; | 3118 goto restart; |
2934 } | 3119 } |
2935 | 3120 |
2936 fkey_map = get_keymap_1 (fkey_next, 0); | 3121 fkey_map = get_keymap_1 (fkey_next, 0); |
3123 add_command_key (tem); | 3308 add_command_key (tem); |
3124 } | 3309 } |
3125 | 3310 |
3126 UNGCPRO; | 3311 UNGCPRO; |
3127 | 3312 |
3128 function = Fintern (function, Vobarray); | 3313 function = Fintern (function, Qnil); |
3129 Vprefix_arg = prefixarg; | 3314 Vprefix_arg = prefixarg; |
3130 this_command = function; | 3315 this_command = function; |
3131 | 3316 |
3132 return Fcommand_execute (function, Qt); | 3317 return Fcommand_execute (function, Qt); |
3133 } | 3318 } |
3619 | 3804 |
3620 Qevent_kind = intern ("event-type"); | 3805 Qevent_kind = intern ("event-type"); |
3621 staticpro (&Qevent_kind); | 3806 staticpro (&Qevent_kind); |
3622 Qevent_symbol_elements = intern ("event-symbol-elements"); | 3807 Qevent_symbol_elements = intern ("event-symbol-elements"); |
3623 staticpro (&Qevent_symbol_elements); | 3808 staticpro (&Qevent_symbol_elements); |
3809 Qevent_symbol_element_mask = intern ("event-symbol-element-mask"); | |
3810 staticpro (&Qevent_symbol_element_mask); | |
3811 Qmodifier_cache = intern ("modifier-cache"); | |
3812 staticpro (&Qmodifier_cache); | |
3624 | 3813 |
3625 { | 3814 { |
3626 struct event_head *p; | 3815 struct event_head *p; |
3627 | 3816 |
3628 for (p = head_table; | 3817 for (p = head_table; |