X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8dfd92c9a616f3c0184e764dac3985301ad7836c..24b97d4bf8cb03379c1b7e9ffe21a5ce3e657ba1:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 05e2e50e11..927e986b26 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,5 +1,5 @@ /* Keyboard and mouse input; editor command loop. - Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000 + Copyright (C) 1985,86,87,88,89,93,94,95,96,97,99, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ #include "lisp.h" #include "termhooks.h" #include "macros.h" +#include "keyboard.h" #include "frame.h" #include "window.h" #include "commands.h" @@ -34,7 +35,6 @@ Boston, MA 02111-1307, USA. */ #include "charset.h" #include "disptab.h" #include "dispextern.h" -#include "keyboard.h" #include "syntax.h" #include "intervals.h" #include "blockinput.h" @@ -70,10 +70,16 @@ Boston, MA 02111-1307, USA. */ #include "w32term.h" #endif /* HAVE_NTGUI */ +#ifdef macintosh +#include "macterm.h" +#endif + /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ #include "systime.h" +#ifndef USE_CRT_DLL extern int errno; +#endif /* Variables for blockinput.h: */ @@ -91,7 +97,7 @@ extern int input_fd; #ifdef HAVE_WINDOW_SYSTEM /* Make all keyboard buffers much bigger when using X windows. */ #ifdef macintosh -/* But not too big (local data > 32K error) if on macintosh */ +/* But not too big (local data > 32K error) if on macintosh. */ #define KBD_BUFFER_SIZE 512 #else #define KBD_BUFFER_SIZE 4096 @@ -196,7 +202,7 @@ int waiting_for_input; /* True while displaying for echoing. Delays C-g throwing. */ -static int echoing; +int echoing; /* Non-null means we can start echoing at the next input pause even though there is something in the echo area. */ @@ -213,7 +219,7 @@ static struct kboard *echo_kboard; /* The buffer used for echoing. Set in echo_now, reset in cancel_echoing. */ -static Lisp_Object echo_message_buffer; +Lisp_Object echo_message_buffer; /* Nonzero means disregard local maps for the menu bar. */ static int inhibit_local_menu_bar_menus; @@ -245,6 +251,10 @@ Lisp_Object Vmenu_bar_final_items; If the value is non-nil and not a number, we wait 2 seconds. */ Lisp_Object Vsuggest_key_bindings; +/* How long to display an echo-area message when the minibuffer is active. + If the value is not a number, such messages don't time out. */ +Lisp_Object Vminibuffer_message_timeout; + /* Character that causes a quit. Normally C-g. If we are running on an ordinary terminal, this must be an ordinary @@ -450,6 +460,10 @@ int input_pending; int meta_key; +/* Non-zero means force key bindings update in parse_menu_item. */ + +int update_menu_bindings; + extern char *pending_malloc_warning; /* Circular buffer for pre-read keyboard input. */ @@ -509,7 +523,7 @@ static struct input_event * volatile kbd_store_ptr; /* If this flag is non-nil, we check mouse_moved to see when the mouse moves, and motion events will appear in the input stream. Otherwise, mouse motion is ignored. */ -static Lisp_Object do_mouse_tracking; +Lisp_Object do_mouse_tracking; /* Symbols to head events. */ Lisp_Object Qmouse_movement; @@ -630,27 +644,42 @@ Lisp_Object Vdisable_point_adjustment; Lisp_Object Vglobal_disable_point_adjustment; +/* The time when Emacs started being idle. */ + +static EMACS_TIME timer_idleness_start_time; + /* Global variable declarations. */ /* Function for init_keyboard to call with no args (if nonzero). */ void (*keyboard_init_hook) (); -static int read_avail_input (); -static void get_input_pending (); -static int readable_events (); +static int read_avail_input P_ ((int)); +static void get_input_pending P_ ((int *, int)); +static int readable_events P_ ((int)); +static Lisp_Object read_char_x_menu_prompt P_ ((int, Lisp_Object *, + Lisp_Object, int *)); static Lisp_Object read_char_x_menu_prompt (); -static Lisp_Object read_char_minibuf_menu_prompt (); -static Lisp_Object make_lispy_event (); +static Lisp_Object read_char_minibuf_menu_prompt P_ ((int, int, + Lisp_Object *)); +static Lisp_Object make_lispy_event P_ ((struct input_event *)); #ifdef HAVE_MOUSE -static Lisp_Object make_lispy_movement (); +static Lisp_Object make_lispy_movement P_ ((struct frame *, Lisp_Object, + enum scroll_bar_part, + Lisp_Object, Lisp_Object, + unsigned long)); #endif -static Lisp_Object modify_event_symbol (); -static Lisp_Object make_lispy_switch_frame (); +static Lisp_Object modify_event_symbol P_ ((int, unsigned, Lisp_Object, + Lisp_Object, char **, + Lisp_Object *, unsigned)); +static Lisp_Object make_lispy_switch_frame P_ ((Lisp_Object)); +static int parse_solitary_modifier P_ ((Lisp_Object)); static int parse_solitary_modifier (); +static void save_getcjmp P_ ((jmp_buf)); static void save_getcjmp (); -static void restore_getcjmp (); +static void restore_getcjmp P_ ((jmp_buf)); static Lisp_Object apply_modifiers P_ ((int, Lisp_Object)); +static void clear_event P_ ((struct input_event *)); /* Nonzero means don't try to suspend even if the operating system seems to support it. */ @@ -665,17 +694,39 @@ static int cannot_suspend; void echo_prompt (str) - char *str; + Lisp_Object str; { - int len = strlen (str); + int nbytes = STRING_BYTES (XSTRING (str)); + int multibyte_p = STRING_MULTIBYTE (str); - if (len > ECHOBUFSIZE - 4) - len = ECHOBUFSIZE - 4; - bcopy (str, current_kboard->echobuf, len); - current_kboard->echoptr = current_kboard->echobuf + len; - *current_kboard->echoptr = '\0'; + if (nbytes > ECHOBUFSIZE - 4) + { + if (multibyte_p) + { + /* Have to find the last character that fit's into the + echo buffer. */ + unsigned char *p = XSTRING (str)->data; + unsigned char *pend = p + ECHOBUFSIZE - 4; + int char_len; - current_kboard->echo_after_prompt = len; + do + { + PARSE_MULTIBYTE_SEQ (p, pend - p, char_len); + p += char_len; + } + while (p < pend); + + nbytes = p - XSTRING (str)->data - char_len; + } + else + nbytes = ECHOBUFSIZE - 4; + } + + nbytes = copy_text (XSTRING (str)->data, current_kboard->echobuf, nbytes, + STRING_MULTIBYTE (str), 1); + current_kboard->echoptr = current_kboard->echobuf + nbytes; + *current_kboard->echoptr = '\0'; + current_kboard->echo_after_prompt = nbytes; echo_now (); } @@ -688,8 +739,6 @@ void echo_char (c) Lisp_Object c; { - extern char *push_key_description (); - if (current_kboard->immediate_echo) { char *ptr = current_kboard->echoptr; @@ -702,11 +751,13 @@ echo_char (c) if (INTEGERP (c)) { + int ch = XINT (c); + if (ptr - current_kboard->echobuf > ECHOBUFSIZE - KEY_DESCRIPTION_SIZE) return; - ptr = push_key_description (XINT (c), ptr); + ptr = push_key_description (ch, ptr, 1); } else if (SYMBOLP (c)) { @@ -714,8 +765,8 @@ echo_char (c) if ((ptr - current_kboard->echobuf) + STRING_BYTES (name) + 4 > ECHOBUFSIZE) return; - bcopy (name->data, ptr, STRING_BYTES (name)); - ptr += STRING_BYTES (name); + ptr += copy_text (name->data, ptr, STRING_BYTES (name), + name->size_byte >= 0, 1); } if (current_kboard->echoptr == current_kboard->echobuf @@ -781,7 +832,7 @@ echo_now () echoing = 1; message2_nolog (current_kboard->echobuf, strlen (current_kboard->echobuf), - ! NILP (current_buffer->enable_multibyte_characters)); + 1); echoing = 0; /* Record in what buffer we echoed, and from which kboard. */ @@ -873,13 +924,25 @@ recursive_edit_1 () } #ifdef HAVE_X_WINDOWS - /* The command loop has started a busy-cursor timer, so we have to + /* The command loop has started an hourglass timer, so we have to cancel it here, otherwise it will fire because the recursive edit can take some time. */ - if (display_busy_cursor_p) - cancel_busy_cursor (); + if (display_hourglass_p) + cancel_hourglass (); #endif + /* This function may have been called from a debugger called from + within redisplay, for instance by Edebugging a function called + from fontification-functions. We want to allow redisplay in + the debugging session. + + The recursive edit is left with a `(throw exit ...)'. The `exit' + tag is not caught anywhere in redisplay, i.e. when we leave the + recursive edit, the original redisplay leading to the recursive + edit will be unwound. The outcome should therefore be safe. */ + specbind (Qinhibit_redisplay, Qnil); + redisplaying_p = 0; + val = command_loop (); if (EQ (val, Qt)) Fsignal (Qquit, Qnil); @@ -1190,10 +1253,10 @@ DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "", () { #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - cancel_busy_cursor (); + if (display_hourglass_p) + cancel_hourglass (); #endif - Fthrow (Qtop_level, Qnil); + return Fthrow (Qtop_level, Qnil); } DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "", @@ -1204,6 +1267,7 @@ DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, Fthrow (Qexit, Qnil); error ("No recursive edit is in progress"); + return Qnil; } DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "", @@ -1214,15 +1278,17 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, Fthrow (Qexit, Qt); error ("No recursive edit is in progress"); + return Qnil; } /* This is the actual command reading loop, sans error-handling encapsulation. */ -Lisp_Object Fcommand_execute (); -static int read_key_sequence (); -void safe_run_hooks (); -static void adjust_point_for_property (); +EXFUN (Fcommand_execute, 4); +static int read_key_sequence P_ ((Lisp_Object *, int, Lisp_Object, + int, int, int)); +void safe_run_hooks P_ ((Lisp_Object)); +static void adjust_point_for_property P_ ((int)); Lisp_Object command_loop_1 () @@ -1234,7 +1300,7 @@ command_loop_1 () int i; int no_direct; int prev_modiff; - struct buffer *prev_buffer; + struct buffer *prev_buffer = NULL; #ifdef MULTI_KBOARD int was_locked = single_kboard; #endif @@ -1298,18 +1364,19 @@ command_loop_1 () Vdeactivate_mark = Qnil; /* If minibuffer on and echo area in use, - wait 2 sec and redraw minibuffer. */ + wait a short time and redraw minibuffer. */ if (minibuf_level && !NILP (echo_area_buffer[0]) - && EQ (minibuf_window, echo_area_window)) + && EQ (minibuf_window, echo_area_window) + && NUMBERP (Vminibuffer_message_timeout)) { /* Bind inhibit-quit to t so that C-g gets read in rather than quitting back to the minibuffer. */ int count = specpdl_ptr - specpdl; specbind (Qinhibit_quit, Qt); - Fsit_for (make_number (2), Qnil, Qnil); + Fsit_for (Vminibuffer_message_timeout, Qnil, Qnil); /* Clear the echo area. */ message2 (0, 0, 0); safe_run_hooks (Qecho_area_clear_hook); @@ -1416,6 +1483,10 @@ command_loop_1 () this variable differently. */ Vdisable_point_adjustment = Qnil; + /* Process filters and timers may have messed with deactivate-mark. + reset it before we execute the command. */ + Vdeactivate_mark = Qnil; + /* Execute the command. */ Vthis_command = cmd; @@ -1544,8 +1615,8 @@ command_loop_1 () /* Here for a command that isn't executed directly */ #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - start_busy_cursor (); + if (display_hourglass_p) + start_hourglass (); #endif nonundocount = 0; @@ -1554,8 +1625,8 @@ command_loop_1 () Fcommand_execute (Vthis_command, Qnil, Qnil, Qnil); #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - cancel_busy_cursor (); + if (display_hourglass_p) + cancel_hourglass (); #endif } directly_done: ; @@ -1907,9 +1978,18 @@ make_ctrl_char (c) arguments; the function should return a help string or nil for none. For all other types of HELP evaluate it to obtain a string. - OBJECT is the object where a `help-echo' property was found; POS - is the position within OBJECT where it was found. OBJECT is nil - if HELP isn't from a `help-echo' text property. + WINDOW is the window in which the help was generated, if any. + It is nil if not in a window. + + If OBJECT is a buffer, POS is the position in the buffer where the + `help-echo' text property was found. + + If OBJECT is an overlay, that overlay has a `help-echo' property, + and POS is the position in the overlay's buffer under the mouse. + + If OBJECT is a string (an overlay string or a string displayed with + the `display' property). POS is the position in that string under + the mouse. OK_TO_IVERWRITE_KEYSTROKE_ECHO non-zero means it's okay if the help echo overwrites a keystroke echo currently displayed in the echo @@ -1919,22 +1999,23 @@ make_ctrl_char (c) from X code running asynchronously. */ void -show_help_echo (help, object, pos, ok_to_overwrite_keystroke_echo) - Lisp_Object help, object, pos; +show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) + Lisp_Object help, window, object, pos; int ok_to_overwrite_keystroke_echo; { if (!NILP (help) && !STRINGP (help)) { if (FUNCTIONP (help)) { - Lisp_Object args[3]; + Lisp_Object args[4]; args[0] = help; - args[1] = object; - args[2] = pos; - help = call_function (3, args); + args[1] = window; + args[2] = object; + args[3] = pos; + help = safe_call (4, args); } else - help = eval_form (help); + help = safe_eval (help); if (!STRINGP (help)) return; @@ -1956,13 +2037,15 @@ show_help_echo (help, object, pos, ok_to_overwrite_keystroke_echo) { int count = specpdl_ptr - specpdl; specbind (Qmessage_truncate_lines, Qt); - message3_nolog (help, XSTRING (help)->size, + message3_nolog (help, STRING_BYTES (XSTRING (help)), STRING_MULTIBYTE (help)); unbind_to (count, Qnil); } else - message (0); + message (0); } + + help_echo_showing_p = STRINGP (help); } } @@ -2006,16 +2089,17 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) Lisp_Object prev_event; int *used_mouse_menu; { - Lisp_Object c; + volatile Lisp_Object c; int count; jmp_buf local_getcjmp; jmp_buf save_jump; - int key_already_recorded = 0; + volatile int key_already_recorded = 0; Lisp_Object tem, save; - Lisp_Object previous_echo_area_message; - Lisp_Object also_record; - int reread; + volatile Lisp_Object previous_echo_area_message; + volatile Lisp_Object also_record; + volatile int reread; struct gcpro gcpro1, gcpro2; + EMACS_TIME last_idle_start; also_record = Qnil; @@ -2067,6 +2151,12 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) && NILP (XCDR (c))) c = XCAR (c); + /* If the queued event is something that used the mouse, + set used_mouse_menu accordingly. */ + if (used_mouse_menu + && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar))) + *used_mouse_menu = 1; + reread = 1; goto reread_for_input_method; } @@ -2146,7 +2236,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Redisplay if no pending input. */ while (!input_pending) { - redisplay (); + if (help_echo_showing_p && !EQ (selected_window, minibuf_window)) + redisplay_preserve_echo_area (5); + else + redisplay (); if (!input_pending) /* Normal case: no input arrived during redisplay. */ @@ -2454,6 +2547,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Actually read a character, waiting if necessary. */ save_getcjmp (save_jump); restore_getcjmp (local_getcjmp); + timer_start_idle (); c = kbd_buffer_get_event (&kb, used_mouse_menu); restore_getcjmp (save_jump); @@ -2499,8 +2593,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) non_reread: + /* Record the last idle start time so that we can reset it + should the next event read be a help-echo. */ + last_idle_start = timer_idleness_start_time; timer_stop_idle (); - start_polling (); if (NILP (c)) @@ -2524,8 +2620,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) and loop around to read another event. */ save = Vquit_flag; Vquit_flag = Qnil; - tem = get_keyelt (access_keymap (get_keymap_1 (Vspecial_event_map, 0, 0), - c, 0, 0), 1); + tem = access_keymap (get_keymap (Vspecial_event_map, 0, 1), c, 0, 0, 1); Vquit_flag = save; if (!NILP (tem)) @@ -2710,12 +2805,16 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Display help if not echoing. */ if (CONSP (c) && EQ (XCAR (c), Qhelp_echo)) { - /* (help-echo FRAME HELP OBJECT POS). */ - Lisp_Object help, object, position; + /* (help-echo FRAME HELP WINDOW OBJECT POS). */ + Lisp_Object help, object, position, window; help = Fnth (make_number (2), c); - object = Fnth (make_number (3), c); - position = Fnth (make_number (4), c); - show_help_echo (help, object, position, 0); + window = Fnth (make_number (3), c); + object = Fnth (make_number (4), c); + position = Fnth (make_number (5), c); + show_help_echo (help, window, object, position, 0); + + /* We stopped being idle for this event; undo that. */ + timer_idleness_start_time = last_idle_start; goto retry; } @@ -2836,11 +2935,44 @@ static void record_char (c) Lisp_Object c; { - total_keys++; - XVECTOR (recent_keys)->contents[recent_keys_index] = c; - if (++recent_keys_index >= NUM_RECENT_KEYS) - recent_keys_index = 0; + /* Don't record `help-echo' in recent_keys unless it shows some help + message, and a different help than the previoiusly recorded + event. */ + if (CONSP (c) && EQ (XCAR (c), Qhelp_echo)) + { + Lisp_Object help; + help = Fnth (make_number (2), c); + if (STRINGP (help)) + { + int last_idx; + Lisp_Object last_c, last_help; + + last_idx = recent_keys_index - 1; + if (last_idx < 0) + last_idx = NUM_RECENT_KEYS - 1; + last_c = AREF (recent_keys, last_idx); + + if (!CONSP (last_c) + || !EQ (XCAR (last_c), Qhelp_echo) + || (last_help = Fnth (make_number (2), last_c), + !EQ (last_help, help))) + { + total_keys++; + ASET (recent_keys, recent_keys_index, c); + if (++recent_keys_index >= NUM_RECENT_KEYS) + recent_keys_index = 0; + } + } + } + else + { + total_keys++; + ASET (recent_keys, recent_keys_index, c); + if (++recent_keys_index >= NUM_RECENT_KEYS) + recent_keys_index = 0; + } + /* Write c to the dribble file. If c is a lispy event, write the event's symbol to the dribble file, in . Bleaugh. If you, dear reader, have a better idea, you've got the source. :-) */ @@ -2873,7 +3005,8 @@ record_char (c) fflush (dribble); } - store_kbd_macro_char (c); + if (!CONSP (c) || !EQ (Qhelp_echo, XCAR (c))) + store_kbd_macro_char (c); num_nonmacro_input_events++; } @@ -2928,7 +3061,7 @@ tracking_off (old_value) redisplay. */ if (!readable_events (1)) { - redisplay_preserve_echo_area (); + redisplay_preserve_echo_area (6); get_input_pending (&input_pending, 1); } } @@ -3162,36 +3295,45 @@ kbd_buffer_store_event (event) } -/* Generate HELP_EVENT input_events in BUFP. +/* Generate HELP_EVENT input_events in BUFP which has room for + SIZE events. If there's not enough room in BUFP, ignore this + event. HELP is the help form. FRAME is the frame on which the help is generated. OBJECT is the - Lisp object where the help was found (a buffer, a string, or nil if - neither from a string nor from a buffer. POS is the position - within OBJECT where the help was found. + Lisp object where the help was found (a buffer, a string, an + overlay, or nil if neither from a string nor from a buffer. POS is + the position within OBJECT where the help was found. Value is the number of input_events generated. */ int -gen_help_event (bufp, help, frame, object, pos) +gen_help_event (bufp, size, help, frame, window, object, pos) struct input_event *bufp; - Lisp_Object help, frame, object; + int size; + Lisp_Object help, frame, object, window; int pos; { - bufp->kind = HELP_EVENT; - bufp->frame_or_window = frame; - bufp->arg = object; - bufp->x = make_number (pos); - bufp->code = 0; - - ++bufp; - bufp->kind = HELP_EVENT; - bufp->frame_or_window = frame; - bufp->arg = help; - bufp->code = 1; + int nevents_stored = 0; - return 2; + if (size >= 2) + { + bufp->kind = HELP_EVENT; + bufp->frame_or_window = frame; + bufp->arg = object; + bufp->x = make_number (pos); + bufp->code = 0; + + ++bufp; + bufp->kind = HELP_EVENT; + bufp->frame_or_window = WINDOWP (window) ? window : frame; + bufp->arg = help; + bufp->code = 1; + nevents_stored = 2; + } + + return nevents_stored; } @@ -3240,7 +3382,49 @@ discard_mouse_events () } } } + + +/* Return non-zero if there are any real events waiting in the event + buffer, not counting `no_event's. + + If DISCARD is non-zero, discard no_event events at the front of + the input queue, possibly leaving the input queue empty if there + are no real input events. */ + +int +kbd_buffer_events_waiting (discard) + int discard; +{ + struct input_event *sp; + + for (sp = kbd_fetch_ptr; + sp != kbd_store_ptr && sp->kind == no_event; + ++sp) + { + if (sp == kbd_buffer + KBD_BUFFER_SIZE) + sp = kbd_buffer; + } + + if (discard) + kbd_fetch_ptr = sp; + + return sp != kbd_store_ptr && sp->kind != no_event; +} + +/* Clear input event EVENT. */ + +static INLINE void +clear_event (event) + struct input_event *event; +{ + int idx = 2 * (event - kbd_buffer); + ASET (kbd_buffer_gcpro, idx, Qnil); + ASET (kbd_buffer_gcpro, idx + 1, Qnil); + event->kind = no_event; +} + + /* Read one event from the event buffer, waiting if necessary. The value is a Lisp object representing the event. The value is nil for an event that should be ignored, @@ -3377,7 +3561,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu) abort (); #endif } -#if defined (HAVE_X11) || defined (HAVE_NTGUI) +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (macintosh) else if (event->kind == delete_window_event) { /* Make an event (delete-frame (FRAME)). */ @@ -3385,6 +3569,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu) obj = Fcons (Qdelete_frame, Fcons (obj, Qnil)); kbd_fetch_ptr = event + 1; } +#endif +#if defined (HAVE_X11) || defined (HAVE_NTGUI) else if (event->kind == iconify_event) { /* Make an event (iconify-frame (FRAME)). */ @@ -3406,7 +3592,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu) XSETBUFFER (obj, current_buffer); kbd_fetch_ptr = event + 1; } -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh) else if (event->kind == menu_bar_activate_event) { kbd_fetch_ptr = event + 1; @@ -3438,21 +3624,28 @@ kbd_buffer_get_event (kbp, used_mouse_menu) kbd_fetch_ptr = event + 1; else if (event->kind == HELP_EVENT) { - /* There are always two consecutive HELP_EVENTs in the - input queue. */ - Lisp_Object object, position, help, frame; - + /* There are always two HELP_EVENTs in the input queue. */ + Lisp_Object object, position, help, frame, window; + xassert (event->code == 0); frame = event->frame_or_window; object = event->arg; position = event->x; - xassert ((event + 1)->code == 1); - help = (event + 1)->arg; - - /* Event->frame_or_window is a frame, event->arg is the - help to display. */ - obj = list5 (Qhelp_echo, frame, help, object, position); - kbd_fetch_ptr = event + 2; + clear_event (event); + + kbd_fetch_ptr = event + 1; + event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE) + ? kbd_fetch_ptr + : kbd_buffer); + xassert (event->code == 1); + help = event->arg; + window = event->frame_or_window; + if (!WINDOWP (window)) + window = Qnil; + obj = Fcons (Qhelp_echo, + list5 (frame, help, window, object, position)); + clear_event (event); + kbd_fetch_ptr = event + 1; } else if (event->kind == FOCUS_IN_EVENT) { @@ -3499,8 +3692,6 @@ kbd_buffer_get_event (kbp, used_mouse_menu) if (NILP (obj)) { - int idx; - obj = make_lispy_event (event); #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) @@ -3517,11 +3708,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu) #endif /* Wipe out this event, to catch bugs. */ - event->kind = no_event; - idx = 2 * (event - kbd_buffer); - ASET (kbd_buffer_gcpro, idx, Qnil); - ASET (kbd_buffer_gcpro, idx + 1, Qnil); - + clear_event (event); kbd_fetch_ptr = event + 1; } } @@ -3645,11 +3832,9 @@ swallow_events (do_display) get_input_pending (&input_pending, 1); if (timers_run != old_timers_run && do_display) - redisplay_preserve_echo_area (); + redisplay_preserve_echo_area (7); } -static EMACS_TIME timer_idleness_start_time; - /* Record the start of when Emacs is idle, for the sake of running idle-time timers. */ @@ -3734,7 +3919,7 @@ timer_check (do_it_now) while (CONSP (timers) || CONSP (idle_timers)) { Lisp_Object *vector; - Lisp_Object timer, idle_timer; + Lisp_Object timer = Qnil, idle_timer = Qnil; EMACS_TIME timer_time, idle_timer_time; EMACS_TIME difference, timer_difference, idle_timer_difference; @@ -3845,17 +4030,18 @@ timer_check (do_it_now) if (NILP (vector[0])) { int was_locked = single_kboard; - int count = specpdl_ptr - specpdl; + int count = BINDING_STACK_SIZE (); + Lisp_Object old_deactivate_mark = Vdeactivate_mark; /* Mark the timer as triggered to prevent problems if the lisp code fails to reschedule it right. */ vector[0] = Qt; specbind (Qinhibit_quit, Qt); - + call1 (Qtimer_event_handler, chosen_timer); + Vdeactivate_mark = old_deactivate_mark; timers_run++; - unbind_to (count, Qnil); /* Resume allowing input from any kboard, if that was true before. */ @@ -4407,6 +4593,14 @@ make_lispy_event (event) return lispy_c; } + case multibyte_char_keystroke: + { + Lisp_Object lispy_c; + + XSETFASTINT (lispy_c, event->code); + return lispy_c; + } + /* A function key. The symbol may need to have modifier prefixes tacked onto it. */ case non_ascii_keystroke: @@ -4478,6 +4672,8 @@ make_lispy_event (event) Lisp_Object *start_pos_ptr; Lisp_Object start_pos; + position = Qnil; + /* Build the position as appropriate for this mouse click. */ if (event->kind == mouse_click) { @@ -4530,14 +4726,14 @@ make_lispy_event (event) for (i = 0; i < XVECTOR (items)->size; i += 4) { Lisp_Object pos, string; - string = XVECTOR (items)->contents[i + 1]; - pos = XVECTOR (items)->contents[i + 3]; + string = AREF (items, i + 1); + pos = AREF (items, i + 3); if (NILP (string)) break; if (column >= XINT (pos) && column < XINT (pos) + XSTRING (string)->size) { - item = XVECTOR (items)->contents[i]; + item = AREF (items, i); break; } } @@ -4583,7 +4779,7 @@ make_lispy_event (event) if (part == 1 || part == 3) { - /* Mode line or top line. Look for a string under + /* Mode line or header line. Look for a string under the mouse that may have a `local-map' property. */ Lisp_Object string; int charpos; @@ -4596,7 +4792,16 @@ make_lispy_event (event) else if (part == 2) posn = Qvertical_line; else - XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy)); + { + Lisp_Object object; + struct display_pos p; + buffer_posn_from_coords (w, &wx, &wy, &object, &p); + posn = make_number (CHARPOS (p.pos)); + if (STRINGP (object)) + string_info + = Fcons (object, + make_number (CHARPOS (p.string_pos))); + } } position @@ -4629,15 +4834,14 @@ make_lispy_event (event) } #endif /* not USE_TOOLKIT_SCROLL_BARS */ - if (button >= XVECTOR (button_down_location)->size) + if (button >= ASIZE (button_down_location)) { button_down_location = larger_vector (button_down_location, button + 1, Qnil); mouse_syms = larger_vector (mouse_syms, button + 1, Qnil); } - start_pos_ptr = &XVECTOR (button_down_location)->contents[button]; - + start_pos_ptr = &AREF (button_down_location, button); start_pos = *start_pos_ptr; *start_pos_ptr = Qnil; @@ -4674,12 +4878,11 @@ make_lispy_event (event) see if this was a click or a drag. */ else if (event->modifiers & up_modifier) { - /* If we did not see a down before this up, - ignore the up. Probably this happened because - the down event chose a menu item. - It would be an annoyance to treat the release - of the button that chose the menu item - as a separate event. */ + /* If we did not see a down before this up, ignore the up. + Probably this happened because the down event chose a + menu item. It would be an annoyance to treat the + release of the button that chose the menu item as a + separate event. */ if (!CONSP (start_pos)) return Qnil; @@ -4696,16 +4899,29 @@ make_lispy_event (event) Lisp_Object down; down = Fnth (make_number (2), start_pos); - if (EQ (event->x, XCAR (down)) - && EQ (event->y, XCDR (down))) - { - event->modifiers |= click_modifier; - } + if (EQ (event->x, XCAR (down)) && EQ (event->y, XCDR (down))) + /* Mouse hasn't moved. */ + event->modifiers |= click_modifier; else { - button_down_time = 0; - event->modifiers |= drag_modifier; + Lisp_Object window1, window2, posn1, posn2; + + /* Avoid generating a drag event if the mouse + hasn't actually moved off the buffer position. */ + window1 = Fnth (make_number (0), position); + posn1 = Fnth (make_number (1), position); + window2 = Fnth (make_number (0), start_pos); + posn2 = Fnth (make_number (1), start_pos); + + if (EQ (window1, window2) && EQ (posn1, posn2)) + event->modifiers |= click_modifier; + else + { + button_down_time = 0; + event->modifiers |= drag_modifier; + } } + /* Don't check is_double; treat this as multiple if the down-event was multiple. */ if (double_click_count > 1) @@ -4854,7 +5070,8 @@ make_lispy_event (event) return Qnil; pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), &column, &row, NULL, 1); - window = window_from_coordinates (f, column, row, &part, 0); + window = window_from_coordinates (f, XINT (event->x), + XINT (event->y), &part, 0); if (!WINDOWP (window)) { @@ -4878,9 +5095,13 @@ make_lispy_event (event) else if (part == 3) posn = Qheader_line; else - XSETINT (posn, - buffer_posn_from_coords (XWINDOW (window), - &column, &row)); + { + Lisp_Object object; + struct display_pos p; + buffer_posn_from_coords (XWINDOW (window), &column, &row, + &object, &p); + posn = make_number (CHARPOS (p.pos)); + } } { @@ -4912,7 +5133,6 @@ make_lispy_event (event) Lisp_Object window; Lisp_Object posn; Lisp_Object files; - int row, column; /* The frame_or_window field should be a cons of the frame in which the event occurred and a list of the filenames @@ -4927,9 +5147,9 @@ make_lispy_event (event) have been deleted. */ if (! FRAME_LIVE_P (f)) return Qnil; - pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), - &column, &row, NULL, 1); - window = window_from_coordinates (f, column, row, &part, 0); + + window = window_from_coordinates (f, XINT (event->x), + XINT (event->y), &part, 0); if (!WINDOWP (window)) { @@ -4958,7 +5178,12 @@ make_lispy_event (event) else if (part == 3) posn = Qheader_line; else - XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy)); + { + Lisp_Object object; + struct display_pos p; + buffer_posn_from_coords (w, &wx, &wy, &object, &p); + posn = make_number (CHARPOS (p.pos)); + } } { @@ -4983,7 +5208,7 @@ make_lispy_event (event) } #endif /* HAVE_MOUSE */ -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh) case MENU_BAR_EVENT: if (EQ (event->arg, event->frame_or_window)) /* This is the prefix key. We translate this to @@ -5070,7 +5295,12 @@ make_lispy_movement (frame, bar_window, part, x, y, time) else if (area == 3) posn = Qheader_line; else - XSETINT (posn, buffer_posn_from_coords (w, &wx, &wy)); + { + Lisp_Object object; + struct display_pos p; + buffer_posn_from_coords (w, &wx, &wy, &object, &p); + posn = make_number (CHARPOS (p.pos)); + } } else if (frame != 0) { @@ -5427,7 +5657,7 @@ reorder_modifiers (symbol) Alternatively, NAME_ALIST_OR_STEM is either an alist mapping codes into symbol names, or a string specifying a name stem used to - contruct a symbol name or the form `STEM-N', where N is the decimal + construct a symbol name or the form `STEM-N', where N is the decimal representation of SYMBOL_NUM. NAME_ALIST_OR_STEM is used if it is non-nil; otherwise NAME_TABLE is used. @@ -5604,7 +5834,10 @@ has the same base event type and all the specified modifiers.") else if (SYMBOLP (base)) return apply_modifiers (modifiers, base); else - error ("Invalid base event"); + { + error ("Invalid base event"); + return Qnil; + } } /* Try to recognize SYMBOL as a modifier name. @@ -5700,6 +5933,12 @@ lucid_event_type_list_p (object) if (! CONSP (object)) return 0; + if (EQ (XCAR (object), Qhelp_echo) + || EQ (XCAR (object), Qvertical_line) + || EQ (XCAR (object), Qmode_line) + || EQ (XCAR (object), Qheader_line)) + return 0; + for (tail = object; CONSP (tail); tail = XCDR (tail)) { Lisp_Object elt; @@ -6041,8 +6280,8 @@ map_prompt (map) return Qnil; } -static void menu_bar_item (); -static void menu_bar_one_keymap (); +static void menu_bar_item P_ ((Lisp_Object, Lisp_Object)); +static void menu_bar_one_keymap P_ ((Lisp_Object)); /* These variables hold the vector under construction within menu_bar_items and its subroutines, and the current index @@ -6068,7 +6307,7 @@ menu_bar_items (old) in the current keymaps, or nil where it is not a prefix. */ Lisp_Object *maps; - Lisp_Object def, tem, tail; + Lisp_Object def, tail; Lisp_Object result; @@ -6119,7 +6358,7 @@ menu_bar_items (old) { /* No, so use major and minor mode keymaps and keymap property. */ int extra_maps = 2; - Lisp_Object map = get_local_map (PT, current_buffer, keymap); + Lisp_Object map = get_local_map (PT, current_buffer, Qkeymap); if (!NILP (map)) extra_maps = 3; nmaps = current_minor_maps (NULL, &tmaps); @@ -6127,8 +6366,8 @@ menu_bar_items (old) * sizeof (maps[0])); bcopy (tmaps, maps, nmaps * sizeof (maps[0])); if (!NILP (map)) - maps[nmaps++] = get_local_map (PT, current_buffer, keymap); - maps[nmaps++] = get_local_map (PT, current_buffer, local_map); + maps[nmaps++] = map; + maps[nmaps++] = get_local_map (PT, current_buffer, Qlocal_map); } maps[nmaps++] = current_global_map; } @@ -6138,16 +6377,13 @@ menu_bar_items (old) result = Qnil; for (mapno = nmaps - 1; mapno >= 0; mapno--) - { - if (! NILP (maps[mapno])) - def = get_keyelt (access_keymap (maps[mapno], Qmenu_bar, 1, 0), 0); - else - def = Qnil; - - tem = Fkeymapp (def); - if (!NILP (tem)) - menu_bar_one_keymap (def); - } + if (!NILP (maps[mapno])) + { + def = get_keymap (access_keymap (maps[mapno], Qmenu_bar, 1, 0, 1), + 0, 1); + if (CONSP (def)) + menu_bar_one_keymap (def); + } /* Move to the end those items that should be at the end. */ @@ -6260,29 +6496,27 @@ menu_bar_item (key, item) &XVECTOR (menu_bar_items_vector)->contents[i], (menu_bar_items_index - i - 4) * sizeof (Lisp_Object)); menu_bar_items_index -= 4; - return; } - - /* If there's no definition for this key yet, - just ignore `undefined'. */ - return; } - GCPRO1 (key); /* Is this necessary? */ - i = parse_menu_item (item, 0, 1); - UNGCPRO; - if (!i) - return; - /* If this keymap has already contributed to this KEY, don't contribute to it a second time. */ tem = Fmemq (key, menu_bar_one_keymap_changed_items); - if (!NILP (tem)) + if (!NILP (tem) || NILP (item)) return; menu_bar_one_keymap_changed_items = Fcons (key, menu_bar_one_keymap_changed_items); + /* We add to menu_bar_one_keymap_changed_items before doing the + parse_menu_item, so that if it turns out it wasn't a menu item, + it still correctly hides any further menu item. */ + GCPRO1 (key); + i = parse_menu_item (item, 0, 1); + UNGCPRO; + if (!i) + return; + item = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; /* Find any existing item for this KEY. */ @@ -6384,11 +6618,11 @@ parse_menu_item (item, notreal, inmenubar) /* Initialize optional entries. */ for (i = ITEM_PROPERTY_DEF; i < ITEM_PROPERTY_ENABLE; i++) - XVECTOR (item_properties)->contents[i] = Qnil; - XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = Qt; + AREF (item_properties, i) = Qnil; + AREF (item_properties, ITEM_PROPERTY_ENABLE) = Qt; /* Save the item here to protect it from GC. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_ITEM] = item; + AREF (item_properties, ITEM_PROPERTY_ITEM) = item; item_string = XCAR (item); @@ -6397,13 +6631,12 @@ parse_menu_item (item, notreal, inmenubar) if (STRINGP (item_string)) { /* Old format menu item. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] = item_string; + AREF (item_properties, ITEM_PROPERTY_NAME) = item_string; /* Maybe help string. */ if (CONSP (item) && STRINGP (XCAR (item))) { - XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP] - = XCAR (item); + AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item); start = item; item = XCDR (item); } @@ -6418,27 +6651,25 @@ parse_menu_item (item, notreal, inmenubar) } /* This is the real definition--the function to run. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = item; + AREF (item_properties, ITEM_PROPERTY_DEF) = item; /* Get enable property, if any. */ if (SYMBOLP (item)) { tem = Fget (item, Qmenu_enable); if (!NILP (tem)) - XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = tem; + AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem; } } else if (EQ (item_string, Qmenu_item) && CONSP (item)) { /* New format menu item. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] - = XCAR (item); + AREF (item_properties, ITEM_PROPERTY_NAME) = XCAR (item); start = XCDR (item); if (CONSP (start)) { /* We have a real binding. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] - = XCAR (start); + AREF (item_properties, ITEM_PROPERTY_DEF) = XCAR (start); item = XCDR (start); /* Is there a cache list with key equivalences. */ @@ -6455,8 +6686,7 @@ parse_menu_item (item, notreal, inmenubar) item = XCDR (item); if (EQ (tem, QCenable)) - XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] - = XCAR (item); + AREF (item_properties, ITEM_PROPERTY_ENABLE) = XCAR (item); else if (EQ (tem, QCvisible) && !notreal) { /* If got a visible property and that evaluates to nil @@ -6466,8 +6696,7 @@ parse_menu_item (item, notreal, inmenubar) return 0; } else if (EQ (tem, QChelp)) - XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP] - = XCAR (item); + AREF (item_properties, ITEM_PROPERTY_HELP) = XCAR (item); else if (EQ (tem, QCfilter)) filter = item; else if (EQ (tem, QCkey_sequence)) @@ -6482,8 +6711,7 @@ parse_menu_item (item, notreal, inmenubar) { tem = XCAR (item); if (CONSP (tem) || (STRINGP (tem) && NILP (cachelist))) - XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ] - = tem; + AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem; } else if (EQ (tem, QCbutton) && CONSP (XCAR (item))) { @@ -6492,9 +6720,9 @@ parse_menu_item (item, notreal, inmenubar) type = XCAR (tem); if (EQ (type, QCtoggle) || EQ (type, QCradio)) { - XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED] + AREF (item_properties, ITEM_PROPERTY_SELECTED) = XCDR (tem); - XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE] + AREF (item_properties, ITEM_PROPERTY_TYPE) = type; } } @@ -6509,23 +6737,23 @@ parse_menu_item (item, notreal, inmenubar) /* If item string is not a string, evaluate it to get string. If we don't get a string, skip this item. */ - item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; + item_string = AREF (item_properties, ITEM_PROPERTY_NAME); if (!(STRINGP (item_string) || notreal)) { item_string = menu_item_eval_property (item_string); if (!STRINGP (item_string)) return 0; - XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME] = item_string; + AREF (item_properties, ITEM_PROPERTY_NAME) = item_string; } /* If got a filter apply it on definition. */ - def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; + def = AREF (item_properties, ITEM_PROPERTY_DEF); if (!NILP (filter)) { def = menu_item_eval_property (list2 (XCAR (filter), list2 (Qquote, def))); - XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = def; + AREF (item_properties, ITEM_PROPERTY_DEF) = def; } /* If we got no definition, this item is just unselectable text which @@ -6534,7 +6762,7 @@ parse_menu_item (item, notreal, inmenubar) return (inmenubar ? 0 : 1); /* Enable or disable selection of item. */ - tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; + tem = AREF (item_properties, ITEM_PROPERTY_ENABLE); if (!EQ (tem, Qt)) { if (notreal) @@ -6543,19 +6771,20 @@ parse_menu_item (item, notreal, inmenubar) tem = menu_item_eval_property (tem); if (inmenubar && NILP (tem)) return 0; /* Ignore disabled items in menu bar. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE] = tem; + AREF (item_properties, ITEM_PROPERTY_ENABLE) = tem; } /* See if this is a separate pane or a submenu. */ - def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; - tem = get_keymap_1 (def, 0, 1); + def = AREF (item_properties, ITEM_PROPERTY_DEF); + tem = get_keymap (def, 0, 1); /* For a subkeymap, just record its details and exit. */ - if (!NILP (tem)) + if (CONSP (tem)) { - XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP] = tem; - XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF] = tem; + AREF (item_properties, ITEM_PROPERTY_MAP) = tem; + AREF (item_properties, ITEM_PROPERTY_DEF) = tem; return 1; } + /* At the top level in the menu bar, do likewise for commands also. The menu bar does not display equivalent key bindings anyway. ITEM_PROPERTY_DEF is already set up properly. */ @@ -6570,7 +6799,7 @@ parse_menu_item (item, notreal, inmenubar) XCDR (start) = Fcons (Fcons (Qnil, Qnil), XCDR (start)); cachelist = XCAR (XCDR (start)); newcache = 1; - tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]; + tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ); if (!NILP (keyhint)) { XCAR (cachelist) = XCAR (keyhint); @@ -6582,6 +6811,7 @@ parse_menu_item (item, notreal, inmenubar) XCAR (cachelist) = Qt; } } + tem = XCAR (cachelist); if (!EQ (tem, Qt)) { @@ -6591,21 +6821,22 @@ parse_menu_item (item, notreal, inmenubar) if (!NILP (tem)) tem = Fkey_binding (tem, Qnil); - prefix = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]; + prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ); if (CONSP (prefix)) { def = XCAR (prefix); prefix = XCDR (prefix); } else - def = XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF]; + def = AREF (item_properties, ITEM_PROPERTY_DEF); - if (NILP (XCAR (cachelist))) /* Have no saved key. */ + if (!update_menu_bindings) + chkcache = 0; + else if (NILP (XCAR (cachelist))) /* Have no saved key. */ { if (newcache /* Always check first time. */ /* Should we check everything when precomputing key bindings? */ - /* || notreal */ /* If something had no key binding before, don't recheck it because that is too slow--except if we have a list of rebound commands in Vdefine_key_rebound_commands, do @@ -6630,7 +6861,8 @@ parse_menu_item (item, notreal, inmenubar) command name has equivalent keys. Otherwise look up the specified command itself. We don't try both, because that makes lmenu menus slow. */ - if (SYMBOLP (def) && SYMBOLP (XSYMBOL (def)->function) + if (SYMBOLP (def) + && SYMBOLP (XSYMBOL (def)->function) && ! NILP (Fget (def, Qmenu_alias))) def = XSYMBOL (def)->function; tem = Fwhere_is_internal (def, Qnil, Qt, Qnil); @@ -6674,7 +6906,7 @@ parse_menu_item (item, notreal, inmenubar) return 1; /* If we have an equivalent key binding, use that. */ - XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ] = tem; + AREF (item_properties, ITEM_PROPERTY_KEYEQ) = tem; /* Include this when menu help is implemented. tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]; @@ -6688,9 +6920,9 @@ parse_menu_item (item, notreal, inmenubar) */ /* Handle radio buttons or toggle boxes. */ - tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; + tem = AREF (item_properties, ITEM_PROPERTY_SELECTED); if (!NILP (tem)) - XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED] + AREF (item_properties, ITEM_PROPERTY_SELECTED) = menu_item_eval_property (tem); return 1; @@ -6778,7 +7010,7 @@ tool_bar_items (reuse, nitems) { /* No, so use major and minor mode keymaps and keymap property. */ int extra_maps = 2; - Lisp_Object map = get_local_map (PT, current_buffer, keymap); + Lisp_Object map = get_local_map (PT, current_buffer, Qkeymap); if (!NILP (map)) extra_maps = 3; nmaps = current_minor_maps (NULL, &tmaps); @@ -6786,8 +7018,8 @@ tool_bar_items (reuse, nitems) * sizeof (maps[0])); bcopy (tmaps, maps, nmaps * sizeof (maps[0])); if (!NILP (map)) - maps[nmaps++] = get_local_map (PT, current_buffer, keymap); - maps[nmaps++] = get_local_map (PT, current_buffer, local_map); + maps[nmaps++] = map; + maps[nmaps++] = get_local_map (PT, current_buffer, Qlocal_map); } /* Add global keymap at the end. */ @@ -6799,9 +7031,9 @@ tool_bar_items (reuse, nitems) if (!NILP (maps[i])) { Lisp_Object keymap; - - keymap = get_keyelt (access_keymap (maps[i], Qtool_bar, 1, 1), 0); - if (!NILP (Fkeymapp (keymap))) + + keymap = get_keymap (access_keymap (maps[i], Qtool_bar, 1, 0, 1), 0, 1); + if (CONSP (keymap)) { Lisp_Object tail; @@ -6918,9 +7150,9 @@ parse_tool_bar_item (key, item) extern Lisp_Object QCbutton, QCtoggle, QCradio; int i; - /* Defininition looks like `(tool-bar-item CAPTION BINDING - PROPS...)'. Rule out items that aren't lists, don't start with - `tool-bar-item' or whose rest following `tool-bar-item' is not a + /* Defininition looks like `(menu-item CAPTION BINDING PROPS...)'. + Rule out items that aren't lists, don't start with + `menu-item' or whose rest following `tool-bar-item' is not a list. */ if (!CONSP (item) || !EQ (XCAR (item), Qmenu_item) @@ -6964,6 +7196,10 @@ parse_tool_bar_item (key, item) PROP (TOOL_BAR_ITEM_BINDING) = XCAR (item); item = XCDR (item); + /* Ignore cached key binding, if any. */ + if (CONSP (item) && CONSP (XCAR (item))) + item = XCDR (item); + /* Process the rest of the properties. */ for (; CONSP (item) && CONSP (XCDR (item)); item = XCDR (XCDR (item))) { @@ -7017,7 +7253,7 @@ parse_tool_bar_item (key, item) PROP (TOOL_BAR_ITEM_BINDING)))); /* See if the binding is a keymap. Give up if it is. */ - if (!NILP (get_keymap_1 (PROP (TOOL_BAR_ITEM_BINDING), 0, 1))) + if (CONSP (get_keymap (PROP (TOOL_BAR_ITEM_BINDING), 0, 1))) return 0; /* Enable or disable selection of item. */ @@ -7223,6 +7459,8 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) Lisp_Object rest, vector; char *menu; + vector = Qnil; + if (! menu_prompting) return Qnil; @@ -7326,7 +7564,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) /* 1 if the char to type matches the string. */ int char_matches; Lisp_Object upcased_event, downcased_event; - Lisp_Object desc; + Lisp_Object desc = Qnil; Lisp_Object s = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; @@ -7335,7 +7573,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) char_matches = (XINT (upcased_event) == XSTRING (s)->data[0] || XINT (downcased_event) == XSTRING (s)->data[0]); if (! char_matches) - desc = Fsingle_key_description (event); + desc = Fsingle_key_description (event, Qnil); tem = XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ]; @@ -7429,7 +7667,7 @@ read_char_minibuf_menu_prompt (commandflag, nmaps, maps) orig_defn_macro = current_kboard->defining_kbd_macro; current_kboard->defining_kbd_macro = Qnil; do - obj = read_char (commandflag, 0, 0, Qnil, 0); + obj = read_char (commandflag, 0, 0, Qt, 0); while (BUFFERP (obj)); current_kboard->defining_kbd_macro = orig_defn_macro; @@ -7476,31 +7714,6 @@ follow_key (key, nmaps, current, defs, next) int i, first_binding; int did_meta = 0; - /* If KEY is a meta ASCII character, treat it like meta-prefix-char - followed by the corresponding non-meta character. - Put the results into DEFS, since we are going to alter that anyway. - Do not alter CURRENT or NEXT. */ - if (INTEGERP (key) && (XUINT (key) & CHAR_META)) - { - for (i = 0; i < nmaps; i++) - if (! NILP (current[i])) - { - Lisp_Object def; - def = get_keyelt (access_keymap (current[i], - meta_prefix_char, 1, 0), 0); - - /* Note that since we pass the resulting bindings through - get_keymap_1, non-prefix bindings for meta-prefix-char - disappear. */ - defs[i] = get_keymap_1 (def, 0, 1); - } - else - defs[i] = Qnil; - - did_meta = 1; - XSETINT (key, XFASTINT (key) & ~CHAR_META); - } - first_binding = nmaps; for (i = nmaps - 1; i >= 0; i--) { @@ -7512,7 +7725,7 @@ follow_key (key, nmaps, current, defs, next) else map = current[i]; - defs[i] = get_keyelt (access_keymap (map, key, 1, 0), 1); + defs[i] = access_keymap (map, key, 1, 0, 1); if (! NILP (defs[i])) first_binding = i; } @@ -7523,7 +7736,7 @@ follow_key (key, nmaps, current, defs, next) /* Given the set of bindings we've found, produce the next set of maps. */ if (first_binding < nmaps) for (i = 0; i < nmaps; i++) - next[i] = NILP (defs[i]) ? Qnil : get_keymap_1 (defs[i], 0, 1); + next[i] = NILP (defs[i]) ? Qnil : get_keymap (defs[i], 0, 1); return first_binding; } @@ -7575,44 +7788,45 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, int can_return_switch_frame; int fix_current_buffer; { - int count = specpdl_ptr - specpdl; + volatile Lisp_Object from_string; + volatile int count = specpdl_ptr - specpdl; /* How many keys there are in the current key sequence. */ - int t; + volatile int t; /* The length of the echo buffer when we started reading, and the length of this_command_keys when we started reading. */ - int echo_start; - int keys_start; + volatile int echo_start; + volatile int keys_start; /* The number of keymaps we're scanning right now, and the number of keymaps we have allocated space for. */ - int nmaps; - int nmaps_allocated = 0; + volatile int nmaps; + volatile int nmaps_allocated = 0; /* defs[0..nmaps-1] are the definitions of KEYBUF[0..t-1] in the current keymaps. */ - Lisp_Object *defs; + Lisp_Object *volatile defs = NULL; /* submaps[0..nmaps-1] are the prefix definitions of KEYBUF[0..t-1] in the current keymaps, or nil where it is not a prefix. */ - Lisp_Object *submaps; + Lisp_Object *volatile submaps = NULL; /* The local map to start out with at start of key sequence. */ - Lisp_Object orig_local_map; + volatile Lisp_Object orig_local_map; /* The map from the `keymap' property to start out with at start of key sequence. */ - Lisp_Object orig_keymap; + volatile Lisp_Object orig_keymap; /* 1 if we have already considered switching to the local-map property of the place where a mouse click occurred. */ - int localized_local_map = 0; + volatile int localized_local_map = 0; /* The index in defs[] of the first keymap that has a binding for this key sequence. In other words, the lowest i such that defs[i] is non-nil. */ - int first_binding; + volatile int first_binding; /* If t < mock_input, then KEYBUF[t] should be read as the next input key. @@ -7627,7 +7841,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, restart_sequence; the loop will read keys from keybuf up until mock_input, thus rebuilding the state; and then it will resume reading characters from the keyboard. */ - int mock_input = 0; + volatile int mock_input = 0; /* If the sequence is unbound in submaps[], then keybuf[fkey_start..fkey_end-1] is a prefix in Vfunction_key_map, @@ -7637,24 +7851,24 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, should hold off until t reaches them. We do this when we've just recognized a function key, to avoid searching for the function key's again in Vfunction_key_map. */ - int fkey_start = 0, fkey_end = 0; - Lisp_Object fkey_map; + volatile int fkey_start = 0, fkey_end = 0; + volatile Lisp_Object fkey_map; /* Likewise, for key_translation_map. */ - int keytran_start = 0, keytran_end = 0; - Lisp_Object keytran_map; + volatile int keytran_start = 0, keytran_end = 0; + volatile Lisp_Object keytran_map; /* If we receive a ``switch-frame'' event in the middle of a key sequence, we put it off for later. While we're reading, we keep the event here. */ - Lisp_Object delayed_switch_frame; + volatile Lisp_Object delayed_switch_frame; /* See the comment below... */ #if defined (GOBBLE_FIRST_EVENT) Lisp_Object first_event; #endif - Lisp_Object original_uppercase; - int original_uppercase_position = -1; + volatile Lisp_Object original_uppercase; + volatile int original_uppercase_position = -1; /* Gets around Microsoft compiler limitations. */ int dummyflag = 0; @@ -7663,8 +7877,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Nonzero if we seem to have got the beginning of a binding in function_key_map. */ - int function_key_possible = 0; - int key_translation_possible = 0; + volatile int function_key_possible = 0; + volatile int key_translation_possible = 0; + + /* List of events for which a fake prefix key has been generated. */ + volatile Lisp_Object fake_prefixed_keys = Qnil; /* Save the status of key translation before each step, so that we can restore this after downcasing. */ @@ -7680,6 +7897,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, int junk; #endif + struct gcpro gcpro1; + + GCPRO1 (fake_prefixed_keys); raw_keybuf_count = 0; last_nonmenu_event = Qnil; @@ -7689,17 +7909,17 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, keytran_map = Vkey_translation_map; /* If there is no function-key-map, turn off function key scanning. */ - if (NILP (Fkeymapp (Vfunction_key_map))) + if (!KEYMAPP (Vfunction_key_map)) fkey_start = fkey_end = bufsize + 1; /* If there is no key-translation-map, turn off scanning. */ - if (NILP (Fkeymapp (Vkey_translation_map))) + if (!KEYMAPP (Vkey_translation_map)) keytran_start = keytran_end = bufsize + 1; if (INTERACTIVE) { if (!NILP (prompt)) - echo_prompt (XSTRING (prompt)->data); + echo_prompt (prompt); else if (cursor_in_echo_area && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes)) && NILP (Fzerop (Vecho_keystrokes))) @@ -7726,8 +7946,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, &junk); #endif /* GOBBLE_FIRST_EVENT */ - orig_local_map = get_local_map (PT, current_buffer, local_map); - orig_keymap = get_local_map (PT, current_buffer, keymap); + orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); + orig_keymap = get_local_map (PT, current_buffer, Qkeymap); + from_string = Qnil; /* We jump here when the key sequence has been thoroughly changed, and we need to rescan it starting from the beginning. When we jump here, @@ -7775,7 +7996,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, * sizeof (defs[0])); nmaps_allocated = nmaps + extra_maps; } - bcopy (maps, submaps, nmaps * sizeof (submaps[0])); + bcopy (maps, (void *) submaps, nmaps * sizeof (submaps[0])); if (!NILP (orig_keymap)) submaps[nmaps++] = orig_keymap; submaps[nmaps++] = orig_local_map; @@ -7822,13 +8043,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, (say, a mouse click on the mode line which is being treated as [mode-line (mouse-...)], then we backtrack to this point of keybuf. */ - int last_real_key_start; + volatile int last_real_key_start; /* 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, keys_local_start, local_first_binding; + volatile int echo_local_start, keys_local_start, local_first_binding; if (t >= bufsize) error ("Key sequence too long"); @@ -7896,12 +8117,13 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, interrupted_kboard->kbd_queue); } mock_input = 0; - orig_local_map = get_local_map (PT, current_buffer, local_map); - orig_keymap = get_local_map (PT, current_buffer, keymap); + orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); + orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } #endif - key = read_char (NILP (prompt), nmaps, submaps, last_nonmenu_event, + key = read_char (NILP (prompt), nmaps, + (Lisp_Object *) submaps, last_nonmenu_event, &used_mouse_menu); } @@ -7910,6 +8132,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (EQ (key, Qt)) { unbind_to (count, Qnil); + UNGCPRO; return -1; } @@ -7942,8 +8165,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Fset_buffer (XWINDOW (selected_window)->buffer); } - orig_local_map = get_local_map (PT, current_buffer, local_map); - orig_keymap = get_local_map (PT, current_buffer, keymap); + orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); + orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } @@ -7957,8 +8180,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, keybuf[t++] = key; mock_input = t; Vquit_flag = Qnil; - orig_local_map = get_local_map (PT, current_buffer, local_map); - orig_keymap = get_local_map (PT, current_buffer, keymap); + orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); + orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } @@ -8007,10 +8230,12 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, window = POSN_WINDOW (EVENT_START (key)); posn = POSN_BUFFER_POSN (EVENT_START (key)); - if (CONSP (posn)) + if (CONSP (posn) + || (!NILP (fake_prefixed_keys) + && !NILP (Fmemq (key, fake_prefixed_keys)))) { - /* We're looking at the second event of a - sequence which we expanded before. Set + /* We're looking a second time at an event for which + we generated a fake prefix key. Set last_real_key_start appropriately. */ if (t > 0) last_real_key_start = t - 1; @@ -8043,12 +8268,10 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (! FRAME_LIVE_P (XFRAME (selected_frame))) Fkill_emacs (Qnil); - set_buffer_internal (XBUFFER (XWINDOW - (window)->buffer) -); + set_buffer_internal (XBUFFER (XWINDOW (window)->buffer)); orig_local_map = get_local_map (PT, current_buffer, - local_map); - orig_keymap = get_local_map (PT, current_buffer, keymap); + Qlocal_map); + orig_keymap = get_local_map (PT, current_buffer, Qkeymap); goto replay_sequence; } @@ -8070,7 +8293,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, && XINT (pos) >= BEG && XINT (pos) <= Z) { map_here = get_local_map (XINT (pos), - current_buffer, local_map); + current_buffer, Qlocal_map); if (!EQ (map_here, orig_local_map)) { orig_local_map = map_here; @@ -8080,7 +8303,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, goto replay_sequence; } map_here = get_local_map (XINT (pos), - current_buffer, keymap); + current_buffer, Qkeymap); if (!EQ (map_here, orig_keymap)) { orig_keymap = map_here; @@ -8095,18 +8318,22 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Expand mode-line and scroll-bar events into two events: use posn as a fake prefix key. */ - if (SYMBOLP (posn)) + if (SYMBOLP (posn) + && (NILP (fake_prefixed_keys) + || NILP (Fmemq (key, fake_prefixed_keys)))) { if (t + 1 >= bufsize) error ("Key sequence too long"); - keybuf[t] = posn; - keybuf[t+1] = key; - mock_input = t + 2; - /* Zap the position in key, so we know that we've - expanded it, and don't try to do so again. */ - POSN_BUFFER_POSN (EVENT_START (key)) - = Fcons (posn, Qnil); + keybuf[t] = posn; + keybuf[t + 1] = key; + mock_input = t + 2; + + /* Record that a fake prefix key has been generated + for KEY. Don't modify the event; this would + prevent proper action when the event is pushed + back tino unread-command-events. */ + fake_prefixed_keys = Fcons (key, fake_prefixed_keys); /* If on a mode line string with a local keymap, reconsider the key sequence with that keymap. */ @@ -8133,6 +8360,35 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, goto replay_key; } + else if (CONSP (POSN_STRING (EVENT_START (key))) + && NILP (from_string)) + { + /* For a click on a string, i.e. overlay string or a + string displayed via the `display' property, + consider `local-map' and `keymap' properties of + that string. */ + Lisp_Object string, pos, map, map2; + + string = POSN_STRING (EVENT_START (key)); + pos = XCDR (string); + string = XCAR (string); + if (XINT (pos) >= 0 + && XINT (pos) < XSTRING (string)->size) + { + map = Fget_text_property (pos, Qlocal_map, string); + if (!NILP (map)) + orig_local_map = map; + map2 = Fget_text_property (pos, Qkeymap, string); + if (!NILP (map2)) + orig_keymap = map2; + + if (!NILP (map) || !NILP (map2)) + { + from_string = string; + goto replay_sequence; + } + } + } } else if (CONSP (XCDR (key)) && CONSP (EVENT_START (key)) @@ -8333,22 +8589,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Lisp_Object key; key = keybuf[fkey_end++]; - /* Look up meta-characters by prefixing them - with meta_prefix_char. I hate this. */ - if (INTEGERP (key) && XUINT (key) & meta_modifier) - { - fkey_next - = get_keymap_1 - (get_keyelt - (access_keymap (fkey_map, meta_prefix_char, 1, 0), 0), - 0, 1); - XSETFASTINT (key, XFASTINT (key) & ~meta_modifier); - } - else - fkey_next = fkey_map; - fkey_next - = get_keyelt (access_keymap (fkey_next, key, 1, 0), 1); + = access_keymap (fkey_map, key, 1, 0, 1); /* Handle symbol with autoload definition. */ if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next)) @@ -8361,7 +8603,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, or an array. */ if (SYMBOLP (fkey_next) && ! NILP (Ffboundp (fkey_next)) && (!NILP (Farrayp (XSYMBOL (fkey_next)->function)) - || !NILP (Fkeymapp (XSYMBOL (fkey_next)->function)))) + || KEYMAPP (XSYMBOL (fkey_next)->function))) fkey_next = XSYMBOL (fkey_next)->function; #if 0 /* I didn't turn this on, because it might cause trouble @@ -8434,11 +8676,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, goto replay_sequence; } - fkey_map = get_keymap_1 (fkey_next, 0, 1); + fkey_map = get_keymap (fkey_next, 0, 1); /* If we no longer have a bound suffix, try a new positions for fkey_start. */ - if (NILP (fkey_map)) + if (!CONSP (fkey_map)) { fkey_end = ++fkey_start; fkey_map = Vfunction_key_map; @@ -8457,22 +8699,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, Lisp_Object key; key = keybuf[keytran_end++]; - /* Look up meta-characters by prefixing them - with meta_prefix_char. I hate this. */ - if (INTEGERP (key) && XUINT (key) & meta_modifier) - { - keytran_next - = get_keymap_1 - (get_keyelt - (access_keymap (keytran_map, meta_prefix_char, 1, 0), 0), - 0, 1); - XSETFASTINT (key, XFASTINT (key) & ~meta_modifier); - } - else - keytran_next = keytran_map; - keytran_next - = get_keyelt (access_keymap (keytran_next, key, 1, 0), 1); + = access_keymap (keytran_map, key, 1, 0, 1); /* Handle symbol with autoload definition. */ if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next)) @@ -8485,7 +8713,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, or an array. */ if (SYMBOLP (keytran_next) && ! NILP (Ffboundp (keytran_next)) && (!NILP (Farrayp (XSYMBOL (keytran_next)->function)) - || !NILP (Fkeymapp (XSYMBOL (keytran_next)->function)))) + || KEYMAPP (XSYMBOL (keytran_next)->function))) keytran_next = XSYMBOL (keytran_next)->function; /* If the key translation map gives a function, not an @@ -8549,11 +8777,11 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, goto replay_sequence; } - keytran_map = get_keymap_1 (keytran_next, 0, 1); + keytran_map = get_keymap (keytran_next, 0, 1); /* If we no longer have a bound suffix, try a new positions for keytran_start. */ - if (NILP (keytran_map)) + if (!CONSP (keytran_map)) { keytran_end = ++keytran_start; keytran_map = Vkey_translation_map; @@ -8674,6 +8902,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, + UNGCPRO; return t; } @@ -8761,17 +8990,21 @@ DEFUN ("read-key-sequence", Fread_key_sequence, Sread_key_sequence, 1, 5, 0, } #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - cancel_busy_cursor (); + if (display_hourglass_p) + cancel_hourglass (); #endif i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0); +#if 0 /* The following is fine for code reading a key sequence and + then proceeding with a lenghty compuation, but it's not good + for code reading keys in a loop, like an input method. */ #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - start_busy_cursor (); + if (display_hourglass_p) + start_hourglass (); +#endif #endif if (i == -1) @@ -8816,8 +9049,8 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, } #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - cancel_busy_cursor (); + if (display_hourglass_p) + cancel_hourglass (); #endif i = read_key_sequence (keybuf, (sizeof keybuf/sizeof (keybuf[0])), @@ -8825,8 +9058,8 @@ DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector, ! NILP (can_return_switch_frame), 0); #ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - start_busy_cursor (); + if (display_hourglass_p) + start_hourglass (); #endif if (i == -1) @@ -8935,6 +9168,8 @@ a special event, so ignore the prefix argument and don't clear it.") } return Qnil; } + + DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command, 1, 1, "P", @@ -9057,7 +9292,9 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ Lisp_Object binding; char *newmessage; int message_p = push_message (); + int count = BINDING_STACK_SIZE (); + record_unwind_protect (push_message_unwind, Qnil); binding = Fkey_description (bindings); newmessage @@ -9076,7 +9313,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ && message_p) restore_message (); - pop_message (); + unbind_to (count, Qnil); } } @@ -9110,7 +9347,7 @@ current_active_maps (maps_p) { /* No, so use major and minor mode keymaps and keymap property. */ int extra_maps = 2; - Lisp_Object map = get_local_map (PT, current_buffer, keymap); + Lisp_Object map = get_local_map (PT, current_buffer, Qkeymap); if (!NILP (map)) extra_maps = 3; nmaps = current_minor_maps (NULL, &tmaps); @@ -9118,8 +9355,8 @@ current_active_maps (maps_p) * sizeof (maps[0])); bcopy (tmaps, maps, nmaps * sizeof (maps[0])); if (!NILP (map)) - maps[nmaps++] = get_local_map (PT, current_buffer, keymap); - maps[nmaps++] = get_local_map (PT, current_buffer, local_map); + maps[nmaps++] = map; + maps[nmaps++] = get_local_map (PT, current_buffer, Qlocal_map); } maps[nmaps++] = current_global_map; @@ -9151,7 +9388,7 @@ detect_input_pending_run_timers (do_display) if (old_timers_run != timers_run && do_display) { - redisplay_preserve_echo_area (); + redisplay_preserve_echo_area (8); /* The following fixes a bug when using lazy-lock with lazy-lock-defer-on-the-fly set to t, i.e. when fontifying from an idle timer function. The symptom of the bug is that @@ -9658,7 +9895,7 @@ quit_throw_to_read_char () if (FRAMEP (internal_last_event_frame) && !EQ (internal_last_event_frame, selected_frame)) do_switch_frame (make_lispy_switch_frame (internal_last_event_frame), - Qnil, 0); + 0, 0); _longjmp (getcjmp, 1); } @@ -9803,19 +10040,35 @@ wipe_kboard (kb) } #ifdef MULTI_KBOARD + +/* Free KB and memory referenced from it. */ + void delete_kboard (kb) - KBOARD *kb; + KBOARD *kb; { KBOARD **kbp; + for (kbp = &all_kboards; *kbp != kb; kbp = &(*kbp)->next_kboard) if (*kbp == NULL) abort (); *kbp = kb->next_kboard; + + /* Prevent a dangling reference to KB. */ + if (kb == current_kboard + && FRAMEP (selected_frame) + && FRAME_LIVE_P (XFRAME (selected_frame))) + { + current_kboard = XFRAME (selected_frame)->kboard; + if (current_kboard == kb) + abort (); + } + wipe_kboard (kb); xfree (kb); } -#endif + +#endif /* MULTI_KBOARD */ void init_keyboard () @@ -9848,10 +10101,6 @@ init_keyboard () wipe_kboard (current_kboard); init_kboard (current_kboard); - if (initialized) - Ffillarray (kbd_buffer_gcpro, Qnil); - - kbd_buffer_gcpro = Fmake_vector (make_number (2 * KBD_BUFFER_SIZE), Qnil); if (!noninteractive && !read_socket_hook && NILP (Vwindow_system)) { signal (SIGINT, interrupt_signal); @@ -10067,6 +10316,8 @@ syms_of_keyboard () Fset (Qinput_method_exit_on_first_char, Qnil); Fset (Qinput_method_use_echo_area, Qnil); + last_point_position_buffer = Qnil; + { struct event_head *p; @@ -10414,7 +10665,7 @@ The elements of the list are event types that may have menu bar bindings."); "Per-terminal keymap that overrides all other local keymaps.\n\ If this variable is non-nil, it is used as a keymap instead of the\n\ buffer's local map, and the minor mode keymaps and text property keymaps.\n\ -This variable is intended to let commands such as `universal-argumemnt'\n\ +This variable is intended to let commands such as `universal-argument'\n\ set up a different keymap for reading the next command."); DEFVAR_LISP ("overriding-local-map", &Voverriding_local_map, @@ -10520,6 +10771,17 @@ The default value is nil, in which case, point adjustment are\n\ suppressed only after special commands that set\n\ `disable-point-adjustment' (which see) to non-nil."); Vglobal_disable_point_adjustment = Qnil; + + DEFVAR_BOOL ("update-menu-bindings", &update_menu_bindings, + "Non-nil means updating menu bindings is allowed.\n\ +A value of nil means menu bindings should not be updated.\n\ +Used during Emacs' startup."); + update_menu_bindings = 1; + + DEFVAR_LISP ("minibuffer-message-timeout", &Vminibuffer_message_timeout, + "*How long to display an echo-area message when the minibuffer is active.\n\ +If the value is not a number, such messages don't time out."); + Vminibuffer_message_timeout = make_number (2); } void