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;