X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8c907a5633c31e6a297b0535804bbc929a672f18..24b97d4bf8cb03379c1b7e9ffe21a5ce3e657ba1:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index 4ce4bc6e5b..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. @@ -70,6 +70,10 @@ 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" @@ -93,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 @@ -198,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. */ @@ -215,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; @@ -247,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 @@ -452,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. */ @@ -511,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; @@ -632,6 +644,10 @@ 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. */ @@ -678,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; + + 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; + } - current_kboard->echo_after_prompt = len; + 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 (); } @@ -701,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; @@ -715,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)) { @@ -727,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 @@ -794,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. */ @@ -886,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); @@ -1203,8 +1253,8 @@ 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 return Fthrow (Qtop_level, Qnil); } @@ -1234,10 +1284,11 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, /* 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 () @@ -1313,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); @@ -1431,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; @@ -1559,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; @@ -1569,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: ; @@ -1956,10 +2012,10 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) args[1] = window; args[2] = object; args[3] = pos; - help = call_function (4, args); + help = safe_call (4, args); } else - help = eval_form (help); + help = safe_eval (help); if (!STRINGP (help)) return; @@ -1981,13 +2037,15 @@ show_help_echo (help, window, 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); } } @@ -2041,6 +2099,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) volatile Lisp_Object also_record; volatile int reread; struct gcpro gcpro1, gcpro2; + EMACS_TIME last_idle_start; also_record = Qnil; @@ -2092,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; } @@ -2171,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. */ @@ -2479,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); @@ -2524,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)) @@ -2549,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)) @@ -2742,6 +2812,9 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) 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; } @@ -2862,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. :-) */ @@ -2899,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++; } @@ -2954,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); } } @@ -3454,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)). */ @@ -3462,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)). */ @@ -3483,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; @@ -3583,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) @@ -3725,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. */ @@ -3925,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. */ @@ -4620,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; } } @@ -4673,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; @@ -4686,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 @@ -4719,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; @@ -4764,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; @@ -4786,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) @@ -4944,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)) { @@ -4968,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)); + } } { @@ -5002,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 @@ -5017,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)) { @@ -5048,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)); + } } { @@ -5073,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 @@ -5160,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) { @@ -5793,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; @@ -6134,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 @@ -6161,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; @@ -6212,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); @@ -6220,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; } @@ -6231,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. */ @@ -6475,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); @@ -6488,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); } @@ -6509,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. */ @@ -6546,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 @@ -6557,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)) @@ -6573,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))) { @@ -6583,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; } } @@ -6600,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 @@ -6625,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) @@ -6634,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. */ @@ -6661,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); @@ -6673,6 +6811,7 @@ parse_menu_item (item, notreal, inmenubar) XCAR (cachelist) = Qt; } } + tem = XCAR (cachelist); if (!EQ (tem, Qt)) { @@ -6682,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 @@ -6721,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); @@ -6765,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]; @@ -6779,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; @@ -6869,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); @@ -6877,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. */ @@ -6890,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; @@ -7112,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. */ @@ -7573,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--) { @@ -7609,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; } @@ -7620,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; } @@ -7672,6 +7788,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, int can_return_switch_frame; int fix_current_buffer; { + volatile Lisp_Object from_string; volatile int count = specpdl_ptr - specpdl; /* How many keys there are in the current key sequence. */ @@ -7763,6 +7880,9 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, 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. */ Lisp_Object prev_fkey_map; @@ -7777,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; @@ -7786,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))) @@ -7823,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, @@ -7993,8 +8117,8 @@ 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 @@ -8008,6 +8132,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (EQ (key, Qt)) { unbind_to (count, Qnil); + UNGCPRO; return -1; } @@ -8040,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; } @@ -8055,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; } @@ -8105,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; @@ -8141,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; } @@ -8168,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; @@ -8178,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; @@ -8193,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. */ @@ -8231,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)) @@ -8431,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)) @@ -8459,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 @@ -8532,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; @@ -8555,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)) @@ -8583,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 @@ -8647,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; @@ -8772,6 +8902,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, + UNGCPRO; return t; } @@ -8859,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) @@ -8914,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])), @@ -8923,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) @@ -9033,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", @@ -9155,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 @@ -9174,7 +9313,7 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ && message_p) restore_message (); - pop_message (); + unbind_to (count, Qnil); } } @@ -9208,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); @@ -9216,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; @@ -9249,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 @@ -9756,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); } @@ -9901,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 () @@ -10510,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, @@ -10616,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