X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9d56e0da1fe2128b9c7ffdf05f5f7b9ad2ece9fc..ee6bb6939fe507dc98986bfc23794da6110f61ef:/src/keyboard.c diff --git a/src/keyboard.c b/src/keyboard.c index a1b8ad34b0..364fa89353 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -242,6 +242,9 @@ static int inhibit_local_menu_bar_menus; /* Nonzero means C-g should cause immediate error-signal. */ int immediate_quit; +/* The user's hook function for outputting an error message. */ +Lisp_Object Vcommand_error_function; + /* The user's ERASE setting. */ Lisp_Object Vtty_erase_char; @@ -1003,7 +1006,7 @@ recursive_edit_1 () /* Handle throw from read_minibuf when using minibuffer while it's active but we're in another window. */ if (STRINGP (val)) - Fsignal (Qerror, Fcons (val, Qnil)); + xsignal1 (Qerror, val); return unbind_to (count, Qnil); } @@ -1230,52 +1233,47 @@ cmd_error_internal (data, context) Lisp_Object data; char *context; { - Lisp_Object stream; - int kill_emacs_p = 0; struct frame *sf = SELECTED_FRAME (); + /* The immediate context is not interesting for Quits, + since they are asyncronous. */ + if (EQ (XCAR (data), Qquit)) + Vsignaling_function = Qnil; + Vquit_flag = Qnil; Vinhibit_quit = Qt; - clear_message (1, 0); + /* Use user's specified output function if any. */ + if (!NILP (Vcommand_error_function)) + call3 (Vcommand_error_function, data, + build_string (context ? context : ""), + Vsignaling_function); /* If the window system or terminal frame hasn't been initialized - yet, or we're not interactive, it's best to dump this message out - to stderr and exit. */ - if (!sf->glyphs_initialized_p - /* This is the case of the frame dumped with Emacs, when we're - running under a window system. */ - || (!NILP (Vwindow_system) - && !inhibit_window_system - && FRAME_TERMCAP_P (sf)) - || noninteractive) - { - stream = Qexternal_debugging_output; - kill_emacs_p = 1; + yet, or we're not interactive, write the message to stderr and exit. */ + else if (!sf->glyphs_initialized_p + /* This is the case of the frame dumped with Emacs, when we're + running under a window system. */ + || (!NILP (Vwindow_system) + && !inhibit_window_system + && FRAME_TERMCAP_P (sf)) + || noninteractive) + { + print_error_message (data, Qexternal_debugging_output, + context, Vsignaling_function); + Fterpri (Qexternal_debugging_output); + Fkill_emacs (make_number (-1)); } else { + clear_message (1, 0); Fdiscard_input (); message_log_maybe_newline (); bitch_at_user (); - stream = Qt; - } - - /* The immediate context is not interesting for Quits, - since they are asyncronous. */ - if (EQ (XCAR (data), Qquit)) - Vsignaling_function = Qnil; - print_error_message (data, stream, context, Vsignaling_function); + print_error_message (data, Qt, context, Vsignaling_function); + } Vsignaling_function = Qnil; - - /* If the window system or terminal frame hasn't been initialized - yet, or we're in -batch mode, this error should cause Emacs to exit. */ - if (kill_emacs_p) - { - Fterpri (stream); - Fkill_emacs (make_number (-1)); - } } Lisp_Object command_loop_1 (); @@ -1389,6 +1387,72 @@ DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, return Qnil; } +#ifdef HAVE_MOUSE + +/* Restore mouse tracking enablement. See Ftrack_mouse for the only use + of this function. */ + +static Lisp_Object +tracking_off (old_value) + Lisp_Object old_value; +{ + do_mouse_tracking = old_value; + if (NILP (old_value)) + { + /* Redisplay may have been preempted because there was input + available, and it assumes it will be called again after the + input has been processed. If the only input available was + the sort that we have just disabled, then we need to call + redisplay. */ + if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW)) + { + redisplay_preserve_echo_area (6); + get_input_pending (&input_pending, + READABLE_EVENTS_DO_TIMERS_NOW); + } + } + return Qnil; +} + +DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0, + doc: /* Evaluate BODY with mouse movement events enabled. +Within a `track-mouse' form, mouse motion generates input events that +you can read with `read-event'. +Normally, mouse motion is ignored. +usage: (track-mouse BODY ...) */) + (args) + Lisp_Object args; +{ + int count = SPECPDL_INDEX (); + Lisp_Object val; + + record_unwind_protect (tracking_off, do_mouse_tracking); + + do_mouse_tracking = Qt; + + val = Fprogn (args); + return unbind_to (count, val); +} + +/* If mouse has moved on some frame, return one of those frames. + Return 0 otherwise. */ + +static FRAME_PTR +some_mouse_moved () +{ + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + if (XFRAME (frame)->mouse_moved) + return XFRAME (frame); + } + + return 0; +} + +#endif /* HAVE_MOUSE */ + /* This is the actual command reading loop, sans error-handling encapsulation. */ @@ -1418,7 +1482,7 @@ command_loop_1 () Lisp_Object keybuf[30]; int i; int no_direct; - int prev_modiff; + int prev_modiff = 0; struct buffer *prev_buffer = NULL; #ifdef MULTI_KBOARD int was_locked = single_kboard; @@ -1482,15 +1546,18 @@ command_loop_1 () if (minibuf_level && !NILP (echo_area_buffer[0]) - && EQ (minibuf_window, echo_area_window) - && NUMBERP (Vminibuffer_message_timeout)) + && EQ (minibuf_window, echo_area_window)) { /* Bind inhibit-quit to t so that C-g gets read in rather than quitting back to the minibuffer. */ int count = SPECPDL_INDEX (); specbind (Qinhibit_quit, Qt); - Fsit_for (Vminibuffer_message_timeout, Qnil, Qnil); + if (NUMBERP (Vminibuffer_message_timeout)) + sit_for (Vminibuffer_message_timeout, 0, 2); + else + sit_for (Qt, 0, 2); + /* Clear the echo area. */ message2 (0, 0, 0); safe_run_hooks (Qecho_area_clear_hook); @@ -1609,7 +1676,7 @@ command_loop_1 () if (SYMBOLP (cmd)) { Lisp_Object cmd1; - if (cmd1 = Fcommand_remapping (cmd), !NILP (cmd1)) + if (cmd1 = Fcommand_remapping (cmd, Qnil), !NILP (cmd1)) cmd = cmd1; } @@ -2033,6 +2100,8 @@ static Lisp_Object safe_run_hooks_1 (hook) Lisp_Object hook; { + if (NILP (Vrun_hooks)) + return Qnil; return call1 (Vrun_hooks, Vinhibit_quit); } @@ -2306,7 +2375,17 @@ show_help_echo (help, window, object, pos, ok_to_overwrite_keystroke_echo) #ifdef HAVE_MOUSE if (!noninteractive && STRINGP (help)) - help = call1 (Qmouse_fixup_help_message, help); + { + /* The mouse-fixup-help-message Lisp function can call + mouse_position_hook, which resets the mouse_moved flags. + This causes trouble if we are trying to read a mouse motion + event (i.e., if we are inside a `track-mouse' form), so we + restore the mouse_moved flag. */ + FRAME_PTR f = NILP (do_mouse_tracking) ? NULL : some_mouse_moved (); + help = call1 (Qmouse_fixup_help_message, help); + if (f) + f->mouse_moved = 1; + } #endif if (STRINGP (help) || NILP (help)) @@ -2386,18 +2465,23 @@ do { if (polling_stopped_here) start_polling (); \ if we used a mouse menu to read the input, or zero otherwise. If USED_MOUSE_MENU is null, we don't dereference it. + If END_TIME is non-null, it is a pointer to an EMACS_TIME + specifying the maximum time to wait until. If no input arrives by + that time, stop waiting and return nil. + Value is t if we showed a menu and the user rejected it. */ Lisp_Object -read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) +read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, end_time) int commandflag; int nmaps; Lisp_Object *maps; Lisp_Object prev_event; int *used_mouse_menu; + EMACS_TIME *end_time; { volatile Lisp_Object c; - int count; + int count, jmpcount; jmp_buf local_getcjmp; jmp_buf save_jump; volatile int key_already_recorded = 0; @@ -2453,6 +2537,18 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) c = XCAR (Vunread_command_events); Vunread_command_events = XCDR (Vunread_command_events); + reread = 1; + + /* Undo what sit-for did when it unread additional keys + inside universal-argument. */ + + if (CONSP (c) + && EQ (XCAR (c), Qt)) + { + reread = 0; + c = XCDR (c); + } + /* Undo what read_char_x_menu_prompt did when it unread additional keys returned by Fx_popup_menu. */ if (CONSP (c) @@ -2466,7 +2562,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) && (EQ (c, Qtool_bar) || EQ (c, Qmenu_bar))) *used_mouse_menu = 1; - reread = 1; goto reread_for_input_method; } @@ -2623,11 +2718,13 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) around any call to sit_for or kbd_buffer_get_event; it *must not* be in effect when we call redisplay. */ + jmpcount = SPECPDL_INDEX (); if (_setjmp (local_getcjmp)) { /* We must have saved the outer value of getcjmp here, so restore it now. */ restore_getcjmp (save_jump); + unbind_to (jmpcount, Qnil); XSETINT (c, quit_char); internal_last_event_frame = selected_frame; Vlast_event_frame = internal_last_event_frame; @@ -2668,12 +2765,18 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) goto non_reread; } - timer_start_idle (); + /* Start idle timers if no time limit is supplied. We don't do it + if a time limit is supplied to avoid an infinite recursion in the + situation where an idle timer calls `sit-for'. */ + + if (!end_time) + timer_start_idle (); /* If in middle of key sequence and minibuffer not active, start echoing if enough time elapses. */ if (minibuf_level == 0 + && !end_time && !current_kboard->immediate_echo && this_command_key_count > 0 && ! noninteractive @@ -2689,8 +2792,6 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) /* Or not echoing before and echoing allowed. */ || (!echo_kboard && ok_to_echo_at_next_pause))) { - Lisp_Object tem0; - /* After a mouse event, start echoing right away. This is because we are probably about to display a menu, and we don't want to delay before doing so. */ @@ -2698,13 +2799,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) echo_now (); else { - int sec, usec; - double duration = extract_float (Vecho_keystrokes); - sec = (int) duration; - usec = (duration - sec) * 1000000; + Lisp_Object tem0; + save_getcjmp (save_jump); restore_getcjmp (local_getcjmp); - tem0 = sit_for (sec, usec, 1, 1, 0); + tem0 = sit_for (Vecho_keystrokes, 1, 1); restore_getcjmp (save_jump); if (EQ (tem0, Qt) && ! CONSP (Vunread_command_events)) @@ -2741,7 +2840,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) c = read_char_x_menu_prompt (nmaps, maps, prev_event, used_mouse_menu); /* Now that we have read an event, Emacs is not idle. */ - timer_stop_idle (); + if (!end_time) + timer_stop_idle (); goto exit; } @@ -2771,11 +2871,11 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) && XINT (Vauto_save_timeout) > 0) { Lisp_Object tem0; + int timeout = delay_level * XFASTINT (Vauto_save_timeout) / 4; save_getcjmp (save_jump); restore_getcjmp (local_getcjmp); - tem0 = sit_for (delay_level * XFASTINT (Vauto_save_timeout) / 4, - 0, 1, 1, 0); + tem0 = sit_for (make_number (timeout), 1, 1); restore_getcjmp (save_jump); if (EQ (tem0, Qt) @@ -2860,11 +2960,20 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) { KBOARD *kb; + if (end_time) + { + EMACS_TIME now; + EMACS_GET_TIME (now); + if (EMACS_TIME_GE (now, *end_time)) + goto exit; + } + /* 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); + if (!end_time) + timer_start_idle (); + c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time); restore_getcjmp (save_jump); #ifdef MULTI_KBOARD @@ -2915,7 +3024,8 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) non_reread: - timer_stop_idle (); + if (!end_time) + timer_stop_idle (); RESUME_POLLING; if (NILP (c)) @@ -2949,7 +3059,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) last_input_char = c; Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt); - if (CONSP (c) && EQ (XCAR (c), Qselect_window)) + if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time) /* We stopped being idle for this event; undo that. This prevents automatic window selection (under mouse_autoselect_window from acting as a real input event, for @@ -3155,12 +3265,14 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) show_help_echo (help, window, object, position, 0); /* We stopped being idle for this event; undo that. */ - timer_resume_idle (); + if (!end_time) + timer_resume_idle (); goto retry; } - if (! reread || this_command_key_count == 0 - || this_command_key_count_reset) + if ((! reread || this_command_key_count == 0 + || this_command_key_count_reset) + && !end_time) { /* Don't echo mouse motion events. */ @@ -3201,7 +3313,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) cancel_echoing (); do - c = read_char (0, 0, 0, Qnil, 0); + c = read_char (0, 0, 0, Qnil, 0, NULL); while (BUFFERP (c)); /* Remove the help from the frame */ unbind_to (count, Qnil); @@ -3211,7 +3323,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu) { cancel_echoing (); do - c = read_char (0, 0, 0, Qnil, 0); + c = read_char (0, 0, 0, Qnil, 0, NULL); while (BUFFERP (c)); } } @@ -3439,72 +3551,6 @@ restore_getcjmp (temp) bcopy (temp, getcjmp, sizeof getcjmp); } -#ifdef HAVE_MOUSE - -/* Restore mouse tracking enablement. See Ftrack_mouse for the only use - of this function. */ - -static Lisp_Object -tracking_off (old_value) - Lisp_Object old_value; -{ - do_mouse_tracking = old_value; - if (NILP (old_value)) - { - /* Redisplay may have been preempted because there was input - available, and it assumes it will be called again after the - input has been processed. If the only input available was - the sort that we have just disabled, then we need to call - redisplay. */ - if (!readable_events (READABLE_EVENTS_DO_TIMERS_NOW)) - { - redisplay_preserve_echo_area (6); - get_input_pending (&input_pending, - READABLE_EVENTS_DO_TIMERS_NOW); - } - } - return Qnil; -} - -DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0, - doc: /* Evaluate BODY with mouse movement events enabled. -Within a `track-mouse' form, mouse motion generates input events that -you can read with `read-event'. -Normally, mouse motion is ignored. -usage: (track-mouse BODY ...) */) - (args) - Lisp_Object args; -{ - int count = SPECPDL_INDEX (); - Lisp_Object val; - - record_unwind_protect (tracking_off, do_mouse_tracking); - - do_mouse_tracking = Qt; - - val = Fprogn (args); - return unbind_to (count, val); -} - -/* If mouse has moved on some frame, return one of those frames. - Return 0 otherwise. */ - -static FRAME_PTR -some_mouse_moved () -{ - Lisp_Object tail, frame; - - FOR_EACH_FRAME (tail, frame) - { - if (XFRAME (frame)->mouse_moved) - return XFRAME (frame); - } - - return 0; -} - -#endif /* HAVE_MOUSE */ - /* Low level keyboard/mouse input. kbd_buffer_store_event places events in kbd_buffer, and kbd_buffer_get_event retrieves them. */ @@ -3890,9 +3936,10 @@ clear_event (event) We always read and discard one event. */ static Lisp_Object -kbd_buffer_get_event (kbp, used_mouse_menu) +kbd_buffer_get_event (kbp, used_mouse_menu, end_time) KBOARD **kbp; int *used_mouse_menu; + EMACS_TIME *end_time; { register int c; Lisp_Object obj; @@ -3936,13 +3983,26 @@ kbd_buffer_get_event (kbp, used_mouse_menu) if (!NILP (do_mouse_tracking) && some_mouse_moved ()) break; #endif - { + if (end_time) + { + EMACS_TIME duration; + EMACS_GET_TIME (duration); + if (EMACS_TIME_GE (duration, *end_time)) + return Qnil; /* finished waiting */ + else + { + EMACS_SUB_TIME (duration, *end_time, duration); + wait_reading_process_output (EMACS_SECS (duration), + EMACS_USECS (duration), + -1, 1, Qnil, NULL, 0); + } + } + else wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0); - if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr) - /* Pass 1 for EXPECT since we just waited to have input. */ - read_avail_input (1); - } + if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr) + /* Pass 1 for EXPECT since we just waited to have input. */ + read_avail_input (1); #endif /* not VMS */ } @@ -4504,6 +4564,32 @@ timer_check (do_it_now) UNGCPRO; return nexttime; } + +DEFUN ("current-idle-time", Fcurrent_idle_time, Scurrent_idle_time, 0, 0, 0, + doc: /* Return the current length of Emacs idleness. +The value is returned as a list of three integers. The first has the +most significant 16 bits of the seconds, while the second has the +least significant 16 bits. The third integer gives the microsecond +count. + +The microsecond count is zero on systems that do not provide +resolution finer than a second. */) + () +{ + if (! EMACS_TIME_NEG_P (timer_idleness_start_time)) + { + EMACS_TIME now, idleness_now; + + EMACS_GET_TIME (now); + EMACS_SUB_TIME (idleness_now, now, timer_idleness_start_time); + + return list3 (make_number ((EMACS_SECS (idleness_now) >> 16) & 0xffff), + make_number ((EMACS_SECS (idleness_now) >> 0) & 0xffff), + make_number (EMACS_USECS (idleness_now))); + } + + return Qnil; +} /* Caches for modify_event_symbol. */ static Lisp_Object accent_key_syms; @@ -5881,8 +5967,7 @@ make_lispy_event (event) spec[1] = event->y; return Fcons (Qmac_apple_event, Fcons (Fvector (2, spec), - Fcons (mac_make_lispy_event_code (event->code), - Qnil))); + Fcons (event->arg, Qnil))); } #endif @@ -7445,7 +7530,7 @@ parse_menu_item (item, notreal, inmenubar) Lisp_Object prefix; if (!NILP (tem)) - tem = Fkey_binding (tem, Qnil, Qnil); + tem = Fkey_binding (tem, Qnil, Qnil, Qnil); prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ); if (CONSP (prefix)) @@ -7581,7 +7666,7 @@ Lisp_Object QCimage; /* Function prototypes. */ static void init_tool_bar_items P_ ((Lisp_Object)); -static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object)); +static void process_tool_bar_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, void*)); static int parse_tool_bar_item P_ ((Lisp_Object, Lisp_Object)); static void append_tool_bar_item P_ ((void)); @@ -7659,17 +7744,7 @@ tool_bar_items (reuse, nitems) keymap = get_keymap (access_keymap (maps[i], Qtool_bar, 1, 0, 1), 0, 1); if (CONSP (keymap)) - { - Lisp_Object tail; - - /* KEYMAP is a list `(keymap (KEY . BINDING) ...)'. */ - for (tail = keymap; CONSP (tail); tail = XCDR (tail)) - { - Lisp_Object keydef = XCAR (tail); - if (CONSP (keydef)) - process_tool_bar_item (XCAR (keydef), XCDR (keydef)); - } - } + map_keymap (keymap, process_tool_bar_item, Qnil, NULL, 1); } Vinhibit_quit = oquit; @@ -7681,8 +7756,9 @@ tool_bar_items (reuse, nitems) /* Process the definition of KEY which is DEF. */ static void -process_tool_bar_item (key, def) - Lisp_Object key, def; +process_tool_bar_item (key, def, data, args) + Lisp_Object key, def, data; + void *args; { int i; extern Lisp_Object Qundefined; @@ -8297,7 +8373,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, Qt, 0); + obj = read_char (commandflag, 0, 0, Qt, 0, NULL); while (BUFFERP (obj)); current_kboard->defining_kbd_macro = orig_defn_macro; @@ -8368,7 +8444,15 @@ follow_key (key, nmaps, current, defs, next) such as Vfunction_key_map and Vkey_translation_map. */ typedef struct keyremap { - Lisp_Object map, parent; + /* This is the map originally specified for this use. */ + Lisp_Object parent; + /* This is a submap reached by looking up, in PARENT, + the events from START to END. */ + Lisp_Object map; + /* Positions [START, END) in the key sequence buffer + are the key that we have scanned so far. + Those events are the ones that we will replace + if PAREHT maps them into a key sequence. */ int start, end; } keyremap; @@ -8397,7 +8481,7 @@ access_keymap_keyremap (map, key, prompt, do_funcall) /* Handle a symbol whose function definition is a keymap or an array. */ if (SYMBOLP (next) && !NILP (Ffboundp (next)) - && (!NILP (Farrayp (XSYMBOL (next)->function)) + && (ARRAYP (XSYMBOL (next)->function) || KEYMAPP (XSYMBOL (next)->function))) next = XSYMBOL (next)->function; @@ -8441,7 +8525,11 @@ keyremap_step (keybuf, bufsize, fkey, input, doit, diff, prompt) Lisp_Object next, key; key = keybuf[fkey->end++]; - next = access_keymap_keyremap (fkey->map, key, prompt, doit); + + if (KEYMAPP (fkey->parent)) + next = access_keymap_keyremap (fkey->map, key, prompt, doit); + else + next = Qnil; /* If keybuf[fkey->start..fkey->end] is bound in the map and we're in a position to do the key remapping, replace it with @@ -8639,9 +8727,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, delayed_switch_frame = Qnil; fkey.map = fkey.parent = Vfunction_key_map; keytran.map = keytran.parent = Vkey_translation_map; - /* If there is no translation-map, turn off scanning. */ - fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1; - keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1; + fkey.start = fkey.end = 0; + keytran.start = keytran.end = 0; if (INTERACTIVE) { @@ -8670,7 +8757,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Read the first char of the sequence specially, before setting up any keymaps, in case a filter runs and switches buffers on us. */ first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event, - &junk); + &junk, NULL); #endif /* GOBBLE_FIRST_EVENT */ orig_local_map = get_local_map (PT, current_buffer, Qlocal_map); @@ -8692,17 +8779,25 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, the initial keymaps from the current buffer. */ nmaps = 0; - if (!NILP (current_kboard->Voverriding_terminal_local_map) - || !NILP (Voverriding_local_map)) + if (!NILP (current_kboard->Voverriding_terminal_local_map)) { - if (3 > nmaps_allocated) + if (2 > nmaps_allocated) { - submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0])); - defs = (Lisp_Object *) alloca (3 * sizeof (defs[0])); - nmaps_allocated = 3; + submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0])); + defs = (Lisp_Object *) alloca (2 * sizeof (defs[0])); + nmaps_allocated = 2; } if (!NILP (current_kboard->Voverriding_terminal_local_map)) submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map; + } + else if (!NILP (Voverriding_local_map)) + { + if (2 > nmaps_allocated) + { + submaps = (Lisp_Object *) alloca (2 * sizeof (submaps[0])); + defs = (Lisp_Object *) alloca (2 * sizeof (defs[0])); + nmaps_allocated = 2; + } if (!NILP (Voverriding_local_map)) submaps[nmaps++] = Voverriding_local_map; } @@ -8873,7 +8968,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, #endif key = read_char (NILP (prompt), nmaps, (Lisp_Object *) submaps, last_nonmenu_event, - &used_mouse_menu); + &used_mouse_menu, NULL); } /* read_char returns t when it shows a menu and the user rejects it. @@ -9052,16 +9147,19 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, if (!EQ (map_here, orig_local_map)) { orig_local_map = map_here; - keybuf[t] = key; - mock_input = t + 1; - - goto replay_sequence; + ++localized_local_map; } + map_here = get_local_map (XINT (pos), current_buffer, Qkeymap); if (!EQ (map_here, orig_keymap)) { orig_keymap = map_here; + ++localized_local_map; + } + + if (localized_local_map > 1) + { keybuf[t] = key; mock_input = t + 1; @@ -9469,8 +9567,8 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, keybuf[t - 1] = new_key; mock_input = max (t, mock_input); - fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1; - keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1; + fkey.start = fkey.end = 0; + keytran.start = keytran.end = 0; goto replay_sequence; } @@ -9488,6 +9586,7 @@ read_key_sequence (keybuf, bufsize, prompt, dont_downcase_last, /* Don't downcase the last character if the caller says don't. Don't downcase it if the result is undefined, either. */ if ((dont_downcase_last || first_binding >= nmaps) + && t > 0 && t - 1 == original_uppercase_position) keybuf[t - 1] = original_uppercase; @@ -9777,7 +9876,13 @@ a special event, so ignore the prefix argument and don't clear it. */) DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_command, 1, 1, "P", - doc: /* Read function name, then read its arguments and call it. */) + doc: /* Read function name, then read its arguments and call it. + +To pass a numeric argument to the command you are invoking with, specify +the numeric argument to this command. + +Noninteractively, the argument PREFIXARG is the prefix argument to +give to the command you invoke, if it asks for an argument. */) (prefixarg) Lisp_Object prefixarg; { @@ -9883,19 +9988,18 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ Qmouse_movement))) { /* But first wait, and skip the message if there is input. */ - int delay_time; - if (!NILP (echo_area_buffer[0])) - /* This command displayed something in the echo area; - so wait a few seconds, then display our suggestion message. */ - delay_time = (NUMBERP (Vsuggest_key_bindings) - ? XINT (Vsuggest_key_bindings) : 2); + Lisp_Object waited; + + /* If this command displayed something in the echo area; + wait a few seconds, then display our suggestion message. */ + if (NILP (echo_area_buffer[0])) + waited = sit_for (make_number (0), 0, 2); + else if (NUMBERP (Vsuggest_key_bindings)) + waited = sit_for (Vsuggest_key_bindings, 0, 2); else - /* This command left the echo area empty, - so display our message immediately. */ - delay_time = 0; + waited = sit_for (make_number (2), 0, 2); - if (!NILP (Fsit_for (make_number (delay_time), Qnil, Qnil)) - && ! CONSP (Vunread_command_events)) + if (!NILP (waited) && ! CONSP (Vunread_command_events)) { Lisp_Object binding; char *newmessage; @@ -9915,10 +10019,12 @@ DEFUN ("execute-extended-command", Fexecute_extended_command, Sexecute_extended_ message2_nolog (newmessage, strlen (newmessage), STRING_MULTIBYTE (binding)); - if (!NILP (Fsit_for ((NUMBERP (Vsuggest_key_bindings) - ? Vsuggest_key_bindings : make_number (2)), - Qnil, Qnil)) - && message_p) + if (NUMBERP (Vsuggest_key_bindings)) + waited = sit_for (Vsuggest_key_bindings, 0, 2); + else + waited = sit_for (make_number (2), 0, 2); + + if (!NILP (waited) && message_p) restore_message (); unbind_to (count, Qnil); @@ -10007,7 +10113,9 @@ Actually, the value is nil only if we can be sure that no input is available; if there is a doubt, the value is t. */) () { - if (!NILP (Vunread_command_events) || unread_command_char != -1) + if (!NILP (Vunread_command_events) || unread_command_char != -1 + || !NILP (Vunread_post_input_method_events) + || !NILP (Vunread_input_method_events)) return (Qt); get_input_pending (&input_pending, @@ -11079,6 +11187,7 @@ syms_of_keyboard () menu_bar_items_vector = Qnil; staticpro (&menu_bar_items_vector); + defsubr (&Scurrent_idle_time); defsubr (&Sevent_convert_list); defsubr (&Sread_key_sequence); defsubr (&Sread_key_sequence_vector); @@ -11128,7 +11237,10 @@ so that you can determine whether the command was run by mouse or not. */); DEFVAR_LISP ("unread-command-events", &Vunread_command_events, doc: /* List of events to be read as the command input. -These events are processed first, before actual keyboard input. */); +These events are processed first, before actual keyboard input. +Events read from this list are not normally added to `this-command-keys', +as they will already have been added once as they were read for the first time. +An element of the form (t . EVENT) forces EVENT to be added to that list. */); Vunread_command_events = Qnil; DEFVAR_INT ("unread-command-char", &unread_command_char, @@ -11136,14 +11248,16 @@ These events are processed first, before actual keyboard input. */); DEFVAR_LISP ("unread-post-input-method-events", &Vunread_post_input_method_events, doc: /* List of events to be processed as input by input methods. -These events are processed after `unread-command-events', but -before actual keyboard input. */); +These events are processed before `unread-command-events' +and actual keyboard input without given to `input-method-function'. */); Vunread_post_input_method_events = Qnil; DEFVAR_LISP ("unread-input-method-events", &Vunread_input_method_events, doc: /* List of events to be processed as input by input methods. These events are processed after `unread-command-events', but -before actual keyboard input. */); +before actual keyboard input. +If there's an active input method, the events are given to +`input-method-function'. */); Vunread_input_method_events = Qnil; DEFVAR_LISP ("meta-prefix-char", &meta_prefix_char, @@ -11489,6 +11603,15 @@ The value of that variable is passed to `quit-flag' and later causes a peculiar kind of quitting. */); Vthrow_on_input = Qnil; + DEFVAR_LISP ("command-error-function", &Vcommand_error_function, + doc: /* If non-nil, function to output error messages. +The arguments are the error data, a list of the form + (SIGNALED-CONDITIONS . SIGNAL-DATA) +such as just as `condition-case' would bind its variable to, +the context (a string which normally goes at the start of the message), +and the Lisp function within which the error was signaled. */); + Vcommand_error_function = Qnil; + DEFVAR_LISP ("enable-disabled-menus-and-buttons", &Venable_disabled_menus_and_buttons, doc: /* If non-nil, don't ignore events produced by disabled menu items and tool-bar.