Mercurial > emacs
changeset 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 | ef16e7c0d402 |
children | b825fe93c826 |
files | src/keyboard.c |
diffstat | 1 files changed, 409 insertions(+), 220 deletions(-) [+] |
line wrap: on
line diff
--- a/src/keyboard.c Sat Oct 03 08:36:49 1992 +0000 +++ b/src/keyboard.c Sat Oct 03 15:37:35 1992 +0000 @@ -295,6 +295,19 @@ Lisp_Object Qevent_kind; Lisp_Object Qevent_symbol_elements; +/* An event header symbol HEAD may have a property named + Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS); + BASE is the base, unmodified version of HEAD, and MODIFIERS is the + mask of modifiers applied to it. If present, this is used to help + speed up parse_modifiers. */ +Lisp_Object Qevent_symbol_element_mask; + +/* An unmodified event header BASE may have a property named + Qmodifier_cache, which is an alist mapping modifier masks onto + modified versions of BASE. If present, this helps speed up + apply_modifiers. */ +Lisp_Object Qmodifier_cache; + /* Symbols to use for non-text mouse positions. */ Lisp_Object Qmode_line; Lisp_Object Qvertical_line; @@ -369,8 +382,9 @@ int len = strlen (str); if (len > sizeof echobuf - 4) len = sizeof echobuf - 4; - bcopy (str, echobuf, len + 1); + bcopy (str, echobuf, len); echoptr = echobuf + len; + *echoptr = '\0'; echo (); } @@ -487,7 +501,7 @@ int len; { echobuf[len] = '\0'; - echoptr = echobuf + strlen (echobuf); + echoptr = echobuf + len; } @@ -1703,7 +1717,7 @@ { /* A simple keystroke. */ case ascii_keystroke: - return event->code; + return XFASTINT (event->code); break; /* A function key. The symbol may need to have modifier prefixes @@ -1720,12 +1734,13 @@ a press, click or drag, and build the appropriate structure. */ case mouse_click: { + int button = XFASTINT (event->code); int part; Lisp_Object window; Lisp_Object posn; struct mouse_position *loc; - if (event->code < 0 || event->code >= NUM_MOUSE_BUTTONS) + if (button < 0 || button >= NUM_MOUSE_BUTTONS) abort (); /* Where did this mouse click occur? */ @@ -1753,7 +1768,7 @@ /* If this is a button press, squirrel away the location, so we can decide later whether it was a click or a drag. */ - loc = button_down_location + event->code; + loc = button_down_location + button; if (event->modifiers & down_modifier) { loc->window = window; @@ -1783,7 +1798,7 @@ Lisp_Object head, start, end; /* Build the components of the event. */ - head = modify_event_symbol (XFASTINT (event->code) - 1, + head = modify_event_symbol (button - 1, event->modifiers, Qmouse_click, lispy_mouse_names, &mouse_syms, @@ -1883,34 +1898,266 @@ } - -/* Place the written representation of MODIFIERS in BUF, '\0'-terminated, - and return its length. */ - + +/* Manipulating modifiers. */ + +/* Parse the name of SYMBOL, and return the set of modifiers it contains. + + If MODIFIER_END is non-zero, set *MODIFIER_END to the position in + SYMBOL's name of the end of the modifiers; the string from this + position is the unmodified symbol name. + + This doesn't use any caches. */ static int -format_modifiers (modifiers, buf) +parse_modifiers_uncached (symbol, modifier_end) + Lisp_Object symbol; + int *modifier_end; +{ + struct Lisp_String *name; + int i; + int modifiers; + + CHECK_SYMBOL (symbol, 1); + + modifiers = 0; + name = XSYMBOL (symbol)->name; + + + for (i = 0; i+2 <= name->size; ) + switch (name->data[i]) + { +#define SINGLE_LETTER_MOD(bit) \ + if (name->data[i+1] != '-') \ + goto no_more_modifiers; \ + modifiers |= bit; \ + i += 2; + + case 'A': + SINGLE_LETTER_MOD (alt_modifier); + break; + + case 'C': + SINGLE_LETTER_MOD (ctrl_modifier); + break; + + case 'H': + SINGLE_LETTER_MOD (hyper_modifier); + break; + + case 'M': + SINGLE_LETTER_MOD (meta_modifier); + break; + + case 'S': + SINGLE_LETTER_MOD (shift_modifier); + break; + + case 's': + if (i + 6 > name->size + || strncmp (name->data + i, "super-", 6)) + goto no_more_modifiers; + modifiers |= super_modifier; + i += 6; + break; + + case 'd': + if (i + 5 > name->size) + goto no_more_modifiers; + if (! strncmp (name->data + i, "drag-", 5)) + { + modifiers |= drag_modifier; + i += 5; + } + else if (! strncmp (name->data + i, "down-", 5)) + { + modifiers |= down_modifier; + i += 5; + } + else + goto no_more_modifiers; + break; + + default: + goto no_more_modifiers; + +#undef SINGLE_LETTER_MOD + } + no_more_modifiers: + + /* Should we include the `click' modifier? */ + if (! (modifiers & (down_modifier | drag_modifier)) + && i + 7 == name->size + && strncmp (name->data + i, "mouse-", 6) + && '0' <= name->data[i + 6] + && name->data[i + 6] <= '9') + modifiers |= click_modifier; + + if (modifier_end) + *modifier_end = i; + + return modifiers; +} + + +/* Return a symbol whose name is the modifier prefixes for MODIFIERS + prepended to the string BASE[0..BASE_LEN-1]. + This doesn't use any caches. */ +static Lisp_Object +apply_modifiers_uncached (modifiers, base, base_len) int modifiers; - char *buf; + char *base; + int base_len; { - char *p = buf; - - /* Only the event queue may use the `up' modifier; it should always - be turned into a click or drag event before presented to lisp code. */ - if (modifiers & up_modifier) - abort (); - - if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; } - if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } - if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } - if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } - if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } - if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } - if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } - if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } - /* The click modifier is denoted by the absence of other modifiers. */ - *p = '\0'; - - return p - buf; + /* Since BASE could contain nulls, we can't use intern here; we have + to use Fintern, which expects a genuine Lisp_String, and keeps a + reference to it. */ + char *new_mods = + (char *) alloca (sizeof ("A-C-H-M-S-super-down-drag-")); + int mod_len; + + { + char *p = new_mods; + + /* Only the event queue may use the `up' modifier; it should always + be turned into a click or drag event before presented to lisp code. */ + if (modifiers & up_modifier) + abort (); + + if (modifiers & alt_modifier) { *p++ = 'A'; *p++ = '-'; } + if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } + if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } + if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } + if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } + if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } + if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } + if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } + /* The click modifier is denoted by the absence of other modifiers. */ + + *p = '\0'; + + mod_len = p - new_mods; + } + + { + Lisp_Object new_name = make_uninit_string (mod_len + base_len); + + bcopy (new_mods, XSTRING (new_name)->data, mod_len); + bcopy (base, XSTRING (new_name)->data + mod_len, base_len); + + return Fintern (new_name, Qnil); + } +} + + +static char *modifier_names[] = +{ + "up", "alt", "control", "hyper", "meta", "shift", "super", "down", "drag", + "click" +}; + +static Lisp_Object modifier_symbols; + +/* Return the list of modifier symbols corresponding to the mask MODIFIERS. */ +static Lisp_Object +lispy_modifier_list (modifiers) + int modifiers; +{ + Lisp_Object modifier_list; + int i; + + modifier_list = Qnil; + for (i = 0; (1<<i) <= modifiers; i++) + if (modifiers & (1<<i)) + modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], + modifier_list); + + return modifier_list; +} + + +/* Parse the modifiers on SYMBOL, and return a list like (UNMODIFIED MASK), + where UNMODIFIED is the unmodified form of SYMBOL, + MASK is the set of modifiers present in SYMBOL's name. + This is similar to parse_modifiers_uncached, but uses the cache in + SYMBOL's Qevent_symbol_element_mask property, and maintains the + Qevent_symbol_elements property. */ +static Lisp_Object +parse_modifiers (symbol) + Lisp_Object symbol; +{ + Lisp_Object elements = Fget (symbol, Qevent_symbol_element_mask); + + if (CONSP (elements)) + return elements; + else + { + int end; + int modifiers = parse_modifiers_uncached (symbol, &end); + Lisp_Object unmodified + = Fintern (make_string (XSYMBOL (symbol)->name->data + end, + XSYMBOL (symbol)->name->size - end), + Qnil); + Lisp_Object mask; + + XFASTINT (mask) = modifiers; + elements = Fcons (unmodified, Fcons (mask, Qnil)); + + /* Cache the parsing results on SYMBOL. */ + Fput (symbol, Qevent_symbol_element_mask, + elements); + Fput (symbol, Qevent_symbol_elements, + Fcons (unmodified, lispy_modifier_list (modifiers))); + + /* Since we know that SYMBOL is modifiers applied to unmodified, + it would be nice to put that in unmodified's cache. + But we can't, since we're not sure that parse_modifiers is + canonical. */ + + return elements; + } +} + +/* Apply the modifiers MODIFIERS to the symbol BASE. + BASE must be unmodified. + + This is like apply_modifiers_uncached, but uses BASE's + Qmodifier_cache property, if present. It also builds + Qevent_symbol_elements properties, since it has that info anyway. */ +static Lisp_Object +apply_modifiers (modifiers, base) + int modifiers; + Lisp_Object base; +{ + Lisp_Object cache, index, entry; + + /* The click modifier never figures into cache indices. */ + XFASTINT (index) = (modifiers & ~click_modifier); + cache = Fget (base, Qmodifier_cache); + entry = Fassq (index, cache); + + if (CONSP (entry)) + return XCONS (entry)->cdr; + + /* We have to create the symbol ourselves. */ + { + Lisp_Object new_symbol + = apply_modifiers_uncached (modifiers, + XSYMBOL (base)->name->data, + XSYMBOL (base)->name->size); + + /* Add the new symbol to the base's cache. */ + Fput (base, Qmodifier_cache, + Fcons (Fcons (index, new_symbol), cache)); + + /* We have the parsing info now for free, so add it to the caches. */ + XFASTINT (index) = modifiers; + Fput (new_symbol, Qevent_symbol_element_mask, + Fcons (base, Fcons (index, Qnil))); + Fput (new_symbol, Qevent_symbol_elements, + Fcons (base, lispy_modifier_list (modifiers))); + + return new_symbol; + } } @@ -1926,109 +2173,12 @@ reorder_modifiers (symbol) Lisp_Object symbol; { - struct Lisp_String *name; - int i; - int modifiers; - int not_canonical; - - CHECK_SYMBOL (symbol, 1); - - modifiers = 0; - name = XSYMBOL (symbol)->name; - - /* Special case for things with only one modifier, which is - (hopefully) the vast majority of cases. */ - if (! (name->size >= 4 && name->data[1] == '-' && name->data[3] == '-')) - return symbol; - - for (i = 0; i+1 < name->data[i]; ) - switch (name->data[i]) - { - case 'A': - if (name->data[i] != '-') goto no_more_modifiers; - not_canonical |= (modifiers & ~(alt_modifier - 1)); - modifiers |= alt_modifier; - i += 2; - break; - - case 'C': - if (name->data[i] != '-') goto no_more_modifiers; - not_canonical |= (modifiers & ~(ctrl_modifier - 1)); - modifiers |= ctrl_modifier; - i += 2; - break; - - case 'H': - if (name->data[i] != '-') goto no_more_modifiers; - not_canonical |= (modifiers & ~(hyper_modifier - 1)); - modifiers |= hyper_modifier; - i += 2; - break; - - case 'M': - if (name->data[i] != '-') goto no_more_modifiers; - not_canonical |= (modifiers & ~(meta_modifier - 1)); - modifiers |= meta_modifier; - i += 2; - break; - - case 'S': - if (name->data[i] != '-') goto no_more_modifiers; - not_canonical |= (modifiers & ~(shift_modifier - 1)); - modifiers |= shift_modifier; - i += 2; - break; - - case 's': - if (i + 6 > name->size - || strncmp (name->data + i, "super-", 6)) - goto no_more_modifiers; - not_canonical |= (modifiers & ~(super_modifier - 1)); - modifiers |= super_modifier; - i += 6; - break; - - case 'd': - if (i + 5 > name->size) - goto no_more_modifiers; - if (! strncmp (name->data + i, "drag-", 5)) - { - not_canonical |= (modifiers & ~(drag_modifier - 1)); - modifiers |= drag_modifier; - i += 5; - } - else if (! strncmp (name->data + i, "down-", 5)) - { - not_canonical |= (modifiers & ~(down_modifier - 1)); - modifiers |= down_modifier; - i += 5; - } - else - goto no_more_modifiers; - break; - - default: - goto no_more_modifiers; - } - no_more_modifiers: - - if (!not_canonical) - return symbol; - - /* The modifiers were out of order, so find a new symbol with the - mods in order. Since the symbol name could contain nulls, we can't - use intern here; we have to use Fintern, which expects a genuine - Lisp_String, and keeps a reference to it. */ - { - char *new_mods = (char *) alloca (sizeof ("A-C-H-M-S-super-U-down-drag-")); - int len = format_modifiers (modifiers, new_mods); - Lisp_Object new_name = make_uninit_string (len + name->size - i); - - bcopy (new_mods, XSTRING (new_name)->data, len); - bcopy (name->data + i, XSTRING (new_name)->data + len, name->size - i); - - return Fintern (new_name, Qnil); - } + /* It's hopefully okay to write the code this way, since everything + will soon be in caches, and no consing will be done at all. */ + Lisp_Object parsed = parse_modifiers (symbol); + + return apply_modifiers (XCONS (XCONS (parsed)->cdr)->car, + XCONS (parsed)->car); } @@ -2058,14 +2208,6 @@ `event-symbol-elements' propery, which lists the modifiers present in the symbol's name. */ -static char *modifier_names[] = -{ - "up", "alt", "ctrl", "hyper", "meta", "shift", "super", "down", "drag", - "click" -}; - -static Lisp_Object modifier_symbols; - static Lisp_Object modify_event_symbol (symbol_num, modifiers, symbol_kind, name_table, symbol_table, table_size) @@ -2077,89 +2219,42 @@ int table_size; { Lisp_Object *slot; - Lisp_Object unmodified; - Lisp_Object temp; /* Is this a request for a valid symbol? */ if (symbol_num < 0 || symbol_num >= table_size) abort (); - /* If *symbol_table doesn't seem to be initialized property, fix that. - + /* If *symbol_table doesn't seem to be initialized properly, fix that. *symbol_table should be a lisp vector TABLE_SIZE elements long, - where the Nth element is an alist for modified versions of - name_table[N]; the alist maps modifier masks onto the modified - symbols. The click modifier is always omitted from the mask; it - is indicated implicitly on a mouse event by the absence of the - down_ and drag_ modifiers. */ + where the Nth element is the symbol for NAME_TABLE[N]. */ if (XTYPE (*symbol_table) != Lisp_Vector || XVECTOR (*symbol_table)->size != table_size) { - XFASTINT (temp) = table_size; - *symbol_table = Fmake_vector (temp, Qnil); + Lisp_Object size; + + XFASTINT (size) = table_size; + *symbol_table = Fmake_vector (size, Qnil); } slot = & XVECTOR (*symbol_table)->contents[symbol_num]; - /* Have we already modified this symbol? */ - XFASTINT (temp) = modifiers & ~(click_modifier); - temp = Fassq (temp, *slot); - if (CONSP (temp)) - return (XCONS (temp)->cdr); - - /* We don't have an entry for the symbol; we have to build it. */ - - /* Create a modified version of the symbol, and add it to the alist. */ - { - Lisp_Object modified; - char *modified_name - = (char *) alloca (sizeof ("A-C-H-M-S-super-U-down-drag") - + strlen (name_table [symbol_num])); - - strcpy (modified_name + format_modifiers (modifiers, modified_name), - name_table [symbol_num]); - - modified = intern (modified_name); - XFASTINT (temp) = modifiers & ~click_modifier; - *slot = Fcons (Fcons (temp, modified), *slot); - Fput (modified, Qevent_kind, symbol_kind); - + /* Have we already used this symbol before? */ + if (NILP (*slot)) { - Lisp_Object modifier_list; - int i; - - modifier_list = Qnil; - for (i = 0; (1<<i) <= modifiers; i++) - if (modifiers & (1<<i)) - modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], - modifier_list); - - /* Put an unmodified version of the symbol at the head of the - list of symbol elements. */ - { - /* We recurse to get the unmodified symbol; this allows us to - write out the code to build event headers only once. - - Note that we put ourselves in the symbol_table before we - recurse, so when an unmodified symbol calls this code - to put itself on its Qevent_symbol_elements property, we do - terminate. */ - Lisp_Object unmodified = - modify_event_symbol (symbol_num, - ((modifiers & (down_modifier | drag_modifier)) - ? click_modifier - : 0), - symbol_kind, - name_table, symbol_table, table_size); - - Fput (modified, Qevent_symbol_elements, - Fcons (unmodified, modifier_list)); - } + /* No; let's create it. */ + *slot = intern (name_table[symbol_num]); + + /* Fill in the cache entries for this symbol; this also + builds the Qevent_symbol_elements property, which the user + cares about. */ + apply_modifiers (0, *slot); + Fput (*slot, Qevent_kind, symbol_kind); } - return modified; - } + /* Apply modifiers to that symbol. */ + return apply_modifiers (modifiers, *slot); } + DEFUN ("mouse-click-p", Fmouse_click_p, Smouse_click_p, 1, 1, 0, "Return non-nil iff OBJECT is a representation of a mouse event.\n\ @@ -2667,8 +2762,9 @@ } /* Given the set of bindings we've found, produce the next set of maps. */ - for (i = 0; i < nmaps; i++) - next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0); + if (first_binding < nmaps) + for (i = 0; i < nmaps; i++) + next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0); return first_binding; } @@ -2768,6 +2864,11 @@ t = 0; this_command_key_count = keys_start; + /* This is a no-op the first time through, but if we restart, it + reverts the echo area to its original state. */ + if (INTERACTIVE) + echo_truncate (echo_start); + { Lisp_Object *maps; @@ -2794,9 +2895,26 @@ Lisp_Object key; int used_mouse_menu = 0; + /* These variables are analogous to echo_start and keys_start; + while those allow us to restart the entire key sequence, + echo_local_start and keys_local_start allow us to throw away + just one key. */ + int echo_local_start = echo_length (); + int keys_local_start = this_command_key_count; + int local_first_binding = first_binding; + if (t >= bufsize) error ("key sequence too long"); + retry_key: + /* These are no-ops, unless we throw away a keystroke below and + jumped back up to retry_key; in that case, these restore these + variables to their original state, allowing us to restart the + loop. */ + echo_truncate (echo_local_start); + this_command_key_count = keys_local_start; + first_binding = local_first_binding; + /* Are we re-reading a key sequence, as indicated by mock_input? */ if (t < mock_input) { @@ -2821,6 +2939,26 @@ Vquit_flag = Qnil; + /* Clicks in non-text areas get prefixed by the symbol + in their CHAR-ADDRESS field. For example, a click on + the mode line is prefixed by the symbol `mode-line'. */ + if (EVENT_HAS_PARAMETERS (key) + && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qmouse_click)) + { + Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key)); + + if (XTYPE (posn) == Lisp_Symbol) + { + if (t + 1 >= bufsize) + error ("key sequence too long"); + keybuf[t] = posn; + keybuf[t+1] = key; + mock_input = t + 2; + + goto retry_key; + } + } + #ifdef MULTI_FRAME /* What buffer was this event typed/moused at? */ if (used_mouse_menu) @@ -2859,21 +2997,72 @@ keybuf[0] = key; mock_input = 1; - /* Truncate the key sequence in the echo area. */ - if (INTERACTIVE) - echo_truncate (echo_start); - goto restart; } #endif } - + first_binding = (follow_key (key, nmaps - first_binding, submaps + first_binding, defs + first_binding, submaps + first_binding) + first_binding); + + /* If this key wasn't bound, we'll try some fallbacks. */ + if (first_binding >= nmaps) + { + Lisp_Object head = EVENT_HEAD (key); + + if (XTYPE (head) == Lisp_Symbol) + { + Lisp_Object breakdown = parse_modifiers (head); + Lisp_Object modifiers = + XINT (XCONS (XCONS (breakdown)->cdr)->car); + + /* We drop unbound `down-' events altogether. */ + if (modifiers & down_modifier) + { + /* Adding prefixes for non-textual mouse clicks creates + two characters of mock input, and this can't be the + first, so it's okay to clear mock_input in that case. + Only function key expansion could create more than + two keys, but that should never generate mouse events, + so it's okay to nuke mock_input in that case too. + Isn't this just the most wonderful code ever? */ + mock_input = 0; + goto retry_key; + } + + /* We turn unbound `drag-' events into `click-' + events, if the click would be bound. */ + else if (modifiers & drag_modifier) + { + Lisp_Object new_head = + apply_modifiers (modifiers & ~drag_modifier, + XCONS (breakdown)->car); + Lisp_Object new_click = + Fcons (new_head, Fcons (EVENT_START (key), Qnil)); + + /* Look for a binding for this new key. follow_key + promises that it didn't munge submaps the + last time we called it, since key was unbound. */ + first_binding = + (follow_key (new_click, + nmaps - local_first_binding, + submaps + local_first_binding, + defs + local_first_binding, + submaps + local_first_binding) + + local_first_binding); + + /* If that click is bound, go for it. */ + if (first_binding < nmaps) + key = new_click; + /* Otherwise, we'll leave key set to the drag event. */ + } + } + } + keybuf[t++] = key; /* Normally, last_nonmenu_event gets the previous key we read. But when a mouse popup menu is being used, @@ -2926,10 +3115,6 @@ mock_input = t; fkey_start = fkey_end = t; - /* Truncate the key sequence in the echo area. */ - if (INTERACTIVE) - echo_truncate (echo_start); - goto restart; } @@ -3125,7 +3310,7 @@ UNGCPRO; - function = Fintern (function, Vobarray); + function = Fintern (function, Qnil); Vprefix_arg = prefixarg; this_command = function; @@ -3621,6 +3806,10 @@ staticpro (&Qevent_kind); Qevent_symbol_elements = intern ("event-symbol-elements"); staticpro (&Qevent_symbol_elements); + Qevent_symbol_element_mask = intern ("event-symbol-element-mask"); + staticpro (&Qevent_symbol_element_mask); + Qmodifier_cache = intern ("modifier-cache"); + staticpro (&Qmodifier_cache); { struct event_head *p;