/* Keyboard and mouse input; editor command loop.
Copyright (C) 1985, 1986, 1987, 1988, 1989, 1993. */
/* Allow config.h to undefine symbols found here. */
#include <signal.h>
#include <config.h>
#include <stdio.h>
#undef NULL
#include "termchar.h"
#include "termopts.h"
#include "lisp.h"
#include "termhooks.h"
#include "macros.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
#include "buffer.h"
#include "disptab.h"
#include "dispextern.h"
#include "keyboard.h"
#include "intervals.h"
#include "blockinput.h"
#include <setjmp.h>
#include <errno.h>
#ifndef VMS
#include <sys/ioctl.h>
#endif
#include "syssignal.h"
#include "systty.h"
#include "systime.h";
/* Make all keyboard buffers much bigger when using X windows. */
#define KBD_BUFFER_SIZE 4096
#else /* No X-windows, character input */
#define KBD_BUFFER_SIZE 256
#endif /* No X-windows */
/*-nil disable property on a command means
do not execute it; call disabled-command-hook's value instead. */
Lisp_Object Qdisabled, Qdisabled_command_hook;
#define NUM_RECENT_KEYS (100)
int recent_keys_index; /* Index for storing next element into recent_keys */
int total_keys; /* Total number of elements stored into recent_keys */
Lisp_Object recent_keys; /* A vector, holding the last 100 keystrokes */
/* Vector holding the key sequence that invoked the current command.
It is reused for each command, and it may be longer than the current
sequence; this_command_key_count indicates how many elements
actually mean something.
It's easier to staticpro a single Lisp_Object than an array. */
Lisp_Object this_command_keys;
int this_command_key_count;
extern int minbuf_level;
extern struct backtrace *backtrace_list;
/*. */
static int echoing;
/* Nonzero means C-G should cause immediate error-signal. */
int immediate_quit;
/* Character to recognize as the help char. */
Lisp_Object Vhelp_char;
/*;
/* Character that causes a quit. Normally C-g.
If we are running on an ordinary terminal, this must be an ordinary
ASCII char, since we want to make it our interrupt character.
If we are not running on an ordinary terminal, it still needs to be
an ordinary ASCII char. This character needs to be recognized in
the input interrupt handler. At this point, the keystroke is
represented as a struct input_event, while the desired quit
character is specified as a lispy event. The mapping from struct
input_events to lispy events cannot run in an interrupt handler,
and the reverse mapping is difficult for anything but ASCII
keystrokes.
FOR THESE ELABORATE AND UNSATISFYING REASONS, quit_char must be an
ASCII character. */
int quit_char;
extern Lisp_Object current_global_map;
extern int minibuf_level;
/* Current depth in recursive edits. */
int command_loop_level;
/* Total number of times command_loop has read a key sequence. */ unread_command_events;
/* If not -1, an event to be read as subsequent command input. */
int unread_command_char;
/* If not Qnil, this is a switch-frame event which we decided to put
off until the end of a key sequence. This should be read as the
next command input, after any unread_command_events.
read_key_sequence uses this to delay switch-frame events until the
end of the key sequence; Fread_char uses it to put off switch-frame
events until a non-ASCII event is acceptable as input. */
Lisp_Object unread_switch_frame;
/* A mask of extra modifier bits to put into every keyboard char. */_chars;
/* Total number of times read_char has returned, outside of macros. */
int num_nonmacro_input_chars;
/* Auto-save automatically when this many characters have been typed
since the last time. */
static int auto_save_interval;
/* Value of num_nonmacro_input_chars as of last auto save. */
int last_auto_save;
/* Last command executed by the editor command loop, not counting
commands that set the prefix argument. */
Lisp_Object last_command;
/* The command being executed by the command loop.
Commands may set this, and the value set will be copied into last_command
instead of the actual command. */
Lisp_Object this_command;
#ifdef MULTI_FRAME
/*. */
Lisp_Object internal_last_event_frame;
/* A user-visible version of the above, intended to allow users to
figure out where the last event came from, if the event doesn't
carry that information itself (i.e. if it was a character). */
Lisp_Object Vlast_event_frame;
#endif
/*;
/* read_key_sequence stores here the command definition of the
key sequence that it reads. */
Lisp_Object read_key_sequence_cmd;
/* Form to evaluate (if non-nil) when Emacs is started. */
Lisp_Object Vtop_level;
/* User-supplied string to translate input characters through. */
Lisp_Object Vkeyboard_translate_table;
/* Keymap mapping ASCII function key sequences onto their preferred forms. */
extern Lisp_Object Vfunction_key_map;
/* Keymap mapping ASCII function key sequences onto their preferred forms. */
Lisp_Object Vkey_translation_map;
/*;
/* Hooks to run before and after each command. */
Lisp_Object Qpre_command_hook, Qpost_command_hook;
Lisp_Object Vpre_command_hook, Vpost_command_hook;
/*;
/* Circular buffer for pre-read keyboard input. */
static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
/* Vector to GCPRO the frames and windows mentioned in kbd_buffer.
The interrupt-level event handlers will never enqueue an event on a
frame which is not in Vframe_list, and once an event is dequeued,
internal_last_event_frame or the event itself points to the frame.
So that's all fine.
But while the event is sitting in the queue, it's completely
unprotected. Suppose the user types one command which will run for
a while and then delete a frame, and then types another event at
the frame that will be deleted, before the command gets around to
it. Suppose there are no references to this frame elsewhere in
Emacs, and a GC occurs before the second event is dequeued. Now we
have an event referring to a freed frame, which will crash Emacs
when it is dequeued.
Similar things happen when an event on a scroll bar is enqueued; the
window may be deleted while the event is in the queue.
So, we use this vector to protect the frame_or_window field in the
event queue. That way, they'll be dequeued as dead frames or
windows, but still valid lisp objects.
If kbd_buffer[i].kind != no_event, then
(XVECTOR (kbd_buffer_frame_or_window)->contents[i]
== kbd_buffer[i].frame_or_window. */
static Lisp_Object kbd_buffer_frame_or_window;
/* Pointer to next available character in kbd_buffer.
If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the the
next available char is in kbd_buffer[0]. */
static struct input_event *kbd_fetch_ptr;
/* Pointer to next place to store character in kbd_buffer. This
may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the next
character should go in kbd_buffer[0]. */
;
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
/* Lisp_Object Qmouse_movement; - also an event header */
/* Properties of event headers. */
Lisp_Object Qevent_kind;
Lisp_Object Qevent_symbol_elements;
Lisp_Object Qmenu_enable;
/* An event header symbol HEAD may have a property named
Qevent_symbol_element_mask, which is of the form (BASE MODIFIERS);
BASE is the base, unmodified version of HEAD, and MODIFIERS is the
mask of modifiers applied to it. If present, this is used to help
speed up parse_modifiers. */
Lisp_Object Qevent_symbol_element_mask;
/* An unmodified event header BASE may have a property named
Qmodifier_cache, which is an alist mapping modifier masks onto
modified versions of BASE. If present, this helps speed up
apply_modifiers. */
Lisp_Object Qmodifier_cache;
/* Symbols to use for parts of windows. */
Lisp_Object Qmode_line;
Lisp_Object Qvertical_line;
Lisp_Object Qvertical_scroll_bar;
Lisp_Object Qmenu_bar;
extern Lisp_Object Qmenu_enable;
Lisp_Object recursive_edit_unwind (), command_loop ();
Lisp_Object Fthis_command_keys ();
Lisp_Object Qextended_command_history;
/* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
happens. */
EMACS_TIME *input_available_clear_time;
/* Nonzero means use SIGIO interrupts; zero means use CBREAK mode.
Default is 1 if INTERRUPT_INPUT is defined. */
int interrupt_input;
/* Nonzero while interrupts are temporarily deferred during redisplay. */
int interrupts_deferred;
/* nonzero means use ^S/^Q for flow control. */
int flow_control;
/* Allow m- file to inhibit use of FIONREAD. */
#ifdef BROKEN_FIONREAD
#undef FIONREAD
#endif
/* We are unable to use interrupts if FIONREAD is not available,
so flush SIGIO so we won't try. */
#ifndef FIONREAD
#ifdef SIGIO
#undef SIGIO
#endif
#endif
/* If we support X Windows, turn on the code to poll periodically
to detect C-g. It isn't actually used when doing interrupt input. */
#ifdef HAVE_X_WINDOWS
#define POLL_FOR_INPUT
#endif
/* 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 Lisp_Object read_char_menu_prompt ();
static Lisp_Object make_lispy_event ();;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
/* Install the string STR as the beginning of the string of echoing,
so that it serves as a prompt for the next character.
Also start echoing. */
echo_prompt (str)
char *str;
{
int len = strlen (str);
if (len > sizeof echobuf - 4)
len = sizeof echobuf - 4;
bcopy (str, echobuf, len);
echoptr = echobuf + len;
*echoptr = '\0';
echo ();
}
/* Add C to the echo string, if echoing is going on.
C can be a character, which is printed prettily ("M-C-x" and all that
jazz), or a symbol, whose name is printed. */
echo_char (c)
Lisp_Object c;
{
extern char *push_key_description ();++)
echo_char (XVECTOR (this_command_keys)->contents[i]);';
}
/* Functions for manipulating this_command_keys. */
static void
add_command_key (key)
Lisp_Object key;
{
int size = XVECTOR (this_command_keys)->size;
if (this_command_key_count >= size)
{
Lisp_Object new_keys = Fmake_vector (make_number (size * 2), Qnil);
bcopy (XVECTOR (this_command_keys)->contents,
XVECTOR (new_keys)->contents,
size * sizeof (Lisp_Object));
this_command_keys = new_keys;
}
XVECTOR (this_command_keys)->contents[this_command_key_count++] = key;
}
Lisp_Object
recursive_edit_1 ()
{
int count = specpdl_ptr - specpdl;
Lisp_Object val;
if (command_loop_level > 0)
{
specbind (Qstandard_output, Qt);
specbind (Qstandard_input, Qt);
}
val = command_loop ();
if (EQ (val, Qt))
Fsignal (Qquit, Qnil);
return unbind_to (count, Qnil);
}
/* When an auto-save happens, record the "time", and don't do again soon. */
record_auto_save ()
{
last_auto_save = num_nonmacro_input_chars;
}
DEFUN ("recursive-edit", Frecursive_edit, Srecursive_edit, 0, 0, "",
"Invoke the editor command loop recursively.\n\
To get out of the recursive edit, a command can do `(throw 'exit nil)';\n\
that tells this function to return.\n\
Alternately, `(throw 'exit t)' makes this function signal an error.\n\
This function is called by the editor initialization to begin editing.")
()
{
int count = specpdl_ptr - specpdl;
Lisp_Object val;
command_loop_level++;
update_mode_lines = 1;
record_unwind_protect (recursive_edit_unwind,
(command_loop_level
&& current_buffer != XBUFFER (XWINDOW (selected_window)->buffer))
? Fcurrent_buffer ()
: Qnil);
recursive_edit_1 ();
return unbind_to (count, Qnil);
}
Lisp_Object
recursive_edit_unwind (buffer)
Lisp_Object buffer;
{
if (!NILP (buffer))
Fset_buffer (buffer);
command_loop_level--;
update_mode_lines = 1;
return Qnil;
};
echo_area_glyphs = 0;
/* 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 (! FRAME_MESSAGE_BUF (selected_frame)
|| noninteractive)
stream = Qexternal_debugging_output;
else
{
Fdiscard_input ();
bitch_at_user ();
stream = Qt;
}
errname = Fcar (data);
if (EQ (errname, Qerror))
{
data = Fcdr (data);
if (!CONSP (data)) data = Qnil;
errmsg = Fcar (data);
file_error = Qnil;
}
else
{
errmsg = Fget (errname, Qerror_message);
file_error = Fmemq (Qfile_error,
Fget (errname, Qerror_conditions));
}
/* Print an error message including the data items.
This is done by printing it into a scratch buffer
and then making a copy of the text in the buffer. */
if (!CONSP (data)) data = Qnil;
tail = Fcdr (data);
GCPRO1 (tail);
/* For file-error, make error message by concatenating
all the data items. They are all strings. */
if (!NILP (file_error) && !NILP (tail))
errmsg = XCONS (tail)->car, tail = XCONS (tail)->cdr;
if (XTYPE (errmsg) == Lisp_String)
Fprinc (errmsg, stream);
else
write_string_1 ("peculiar error", -1, stream);
for (i = 0; CONSP (tail); tail = Fcdr (tail), i++)
{
write_string_1 (i ? ", " : ": ", 2, stream);
if (!NILP (file_error))
Fprinc (Fcar (tail), stream);
else
Fprin1 (Fcar (tail), stream);
}
UNGCPRO;
yet, or we're in -batch mode, this error should cause Emacs to exit. */
|| noninteractive)
{
Fterpri (stream);
Fkill_emacs (make_number (-1));
}
Vquit_flag = Qnil;
Vinhibit_quit = Qnil;
return make_number (0);
}
Lisp_Object command_loop_1 ();
Lisp_Object command_loop_2 ();
Lisp_Object top_level_1 ();
/* Entry to editor-command-loop.
This level has the catches for exiting/returning to editor command loop.
It returns nil to exit recursive edit, t to abort it. */
Lisp_Object
command_loop ()
{
if (command_loop_level > 0 || minibuf_level > 0)
{
return internal_catch (Qexit, command_loop_2, Qnil);
}
else
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
internal_catch (Qtop_level, command_loop_2, Qnil);
/* End of file in -batch run causes exit here. */
if (noninteractive)
Fkill_emacs (Qt);
}
}
/* Here we catch errors in execution of commands within the
editing loop, and reenter the editing loop.
When there is an error, cmd_error runs and returns a non-nil
value to us. A value of nil means that cmd_loop_1 itself
returned due to end of file (or end of kbd macro). */
Lisp_Object
command_loop_2 ()
{
register Lisp_Object val;
do
val = internal_condition_case (command_loop_1, Qerror, cmd_error);
while (!NILP (val));
return Qnil;
}
Lisp_Object
top_level_2 ()
{
return Feval (Vtop_level);
}
Lisp_Object
top_level_1 ()
{
/* On entry to the outer level, run the startup file */
if (!NILP (Vtop_level))
internal_condition_case (top_level_2, Qerror, cmd_error);
else if (!NILP (Vpurify_flag))
message ("Bare impure Emacs (standard Lisp code not loaded)");
else
message ("Bare Emacs (standard Lisp code not loaded)");
return Qnil;
}
DEFUN ("top-level", Ftop_level, Stop_level, 0, 0, "",
"Exit all recursive editing levels.")
()
{
Fthrow (Qtop_level, Qnil);
}
DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "",
"Exit from the innermost recursive edit or minibuffer.")
()
{
if (command_loop_level > 0 || minibuf_level > 0)
Fthrow (Qexit, Qnil);
error ("No recursive edit is in progress");
}
DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "",
"Abort the command that requested this recursive edit or minibuffer input.")
()
{
if (command_loop_level > 0 || minibuf_level > 0)
Fthrow (Qexit, Qt);
error ("No recursive edit is in progress");
}
/* This is the actual command reading loop,
sans error-handling encapsulation. */
Lisp_Object Fcommand_execute ();
static int read_key_sequence (); ();
/* Don't clear out last_command at the beginning of a macro. */
if (XTYPE (Vexecuting_macro) != Lisp_String)
last_command = Qt;
nonundocount = 0;
no_redisplay = 0;
this_command_key_count = 0;
/* Make sure this hook runs after commands that get errors and
throw to top level. */
if (!NILP (Vpost_command_hook))
call1 (Vrun_hooks, Qpost_command_hook);
while (1)
{
/* Install chars successfully executed in kbd macro. */
if (defining_kbd_macro && NILP (Vprefix_arg))
finalize_kbd_macro_chars ();
/* Make sure the current window's buffer is selected. */
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->buffer));
/* Display any malloc warning that just came out. Use while because
displaying one warning can cause another. */
while (pending_malloc_warning)
display_malloc_warning ();
no_direct = 0;
Vdeactivate_mark = Qnil;
/* If minibuffer on and echo area in use,
wait 2 sec and redraw minibuffer. */
if (minibuf_level && echo_area_glyphs)
{
/* 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);
unbind_to (count, Qnil);
echo_area_glyphs = 0;
no_direct = 1;
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
unread_command_events = Fcons (make_number (quit_char), Qnil);
}
}
#ifdef C_ALLOCA
alloca (0); /* Cause a garbage collection now */
/* Since we can free the most stuff here. */
#endif /* C_ALLOCA */
#if 0
/*_Frame
&& XFRAME (internal_last_event_frame) != selected_frame)
Fselect_frame (internal_last_event_frame, Qnil);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag)
&& !NILP (Ffboundp (Qrecompute_lucid_menubar)))
call0 (Qrecompute_lucid_menubar);
#if 0 /* This is done in xdisp.c now. */
#ifdef MULTI_FRAME
for (tem = Vframe_list; CONSP (tem); tem = XCONS (tem)->cdr)
{
struct frame *f = XFRAME (XCONS (tem)->car);
struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
/* If the user has switched buffers or windows, we need to
recompute to reflect the new bindings. But we'll
recompute when update_mode_lines is set too; that means
that people can use force-mode-line-update to request
that the menu bar be recomputed. The adverse effect on
the rest of the redisplay algorithm is about the same as
windows_or_buffers_changed anyway. */
if (windows_or_buffers_changed
|| update_mode_lines
|| (XFASTINT (w->last_modified) < MODIFF
&& (XFASTINT (w->last_modified)
<= XBUFFER (w->buffer)->save_modified)))
{
struct buffer *prev = current_buffer;
current_buffer = XBUFFER (w->buffer);
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
current_buffer = prev;
}
}
#endif /* MULTI_FRAME */
#endif /* 0 */
/*. */
no_redisplay = 0;
prev_buffer = current_buffer;
prev_modiff = MODIFF;
/* Execute the command. */
this_command = cmd;
if (!NILP (Vpre_command_hook))
call1 (Vrun_hooks, Q) && point < ZV)
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
lose = FETCH_CHAR (point);
SET_PT (point + 1);
if ((dp
? (VECTORP (DISP_CHAR_VECTOR (dp, lose))
&& XVECTOR (DISP_CHAR_VECTOR (dp, lose))->size == 1)
: (lose >= 0x20 && lose < 0x7f))
&& backward_char) && point > BEGV)
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
SET_PT (point - 1);
lose = FETCH_CHAR (point);
if ((dp
? (XTYPE (DISP_CHAR_VECTOR (dp, lose)) != Lisp_Vector
&& self)
!= point)
|| MODIFF <= current_buffer->save_modified
|| windows_or_buffers_changed
|| !EQ (current_buffer->selective_display, Qnil)
|| detect_input_pending ()
|| !NILP (Vexecuting_macro);
if (internal_self_insert (c, 0))
{
lose = 1;
nonundocount = 0;
}
if (!lose &&
(point == ZV || FETCH_CHAR (point) == '\n'))
{
struct Lisp_Vector *dp
= window_display_table (XWINDOW (selected_window));
int lose = c;
if (dp)
{
Lisp_Object obj = DISP_CHAR_VECTOR (dp, lose);
if (XTYPE (obj) == Lisp_Vector
&& XVECTOR (obj)->size == 1
&& (XTYPE (obj = XVECTOR (obj)->contents[0])
== Lisp_Int))))
call1 (Vrun_hooks, Q
}
/* Set the value of poll_suppress_count to COUNT
and start or stop polling accordingly. */
void
set_poll_suppress_count (count)
int count;
{
#ifdef POLL_FOR_INPUT
if (count == 0 && poll_suppress_count != 0)
{
poll_suppress_count = 1;
start_polling ();
}
else if (count != 0 && poll_suppress_count == 0)
{
stop_polling ();
}
poll_suppress_count = count;
#endif
}
/* Applying the control modifier to CHARACTER. */
int
make_ctrl_char (c)
int c;
{
/* Save the upper bits here. */
int upper = c & ~0177;
c &= 0177;
/* Everything in the columns containing the upper-case letters
denotes a control character. */
if (c >= 0100 && c < 0140)
{
int oc = c;
c &= ~0140;
/* Set the shift modifier for a control char
made from a shifted letter. But only for letters! */
if (oc >= 'A' && oc <= 'Z')
c |= shift_modifier;
}
/* The lower-case letters denote control characters too. */
else if (c >= 'a' && c <= 'z')
c &= ~0140;
/* Include the bits for control and shift
only if the basic ASCII code can't indicate them. */
else if (c >= ' ')
c |= ctrl_modifier;
/* Replace the high bits. */
c |= (upper & ~ctrl_modifier);
return c;
}
/* Input of single characters from keyboard */
Lisp_Object print_help ();
static Lisp_Object kbd_buffer_get_event ();
/* read a character from the keyboard; call the redisplay if needed */
/* commandflag 0 means do not do auto-saving, but do do redisplay.
-1 means do not do redisplay, but do do autosaving.
1 means do both. */
/* The arguments MAPS and NMAPS are for menu prompting.
MAPS is an array of keymaps; NMAPS is the length of MAPS.
PREV_EVENT is the previous input event, or nil if we are reading
the first event of a key sequence.
If USED_MOUSE_MENU is non-zero, then we set *USED_MOUSE_MENU to 1
if we used a mouse menu to read the input, or zero otherwise. If
USED_MOUSE_MENU is zero, *USED_MOUSE_MENU is left alone.
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)
int commandflag;
int nmaps;
Lisp_Object *maps;
Lisp_Object prev_event;
int *used_mouse_menu;
{
register Lisp_Object c;
int count;
jmp_buf save_jump;
if (CONSP (unread_command_events))
c = XCONS (unread_command_events)->car;
unread_command_events = XCONS (unread_command_events)->cdr;
if (this_command_key_count == 0)
goto reread_first;
else
goto reread;
}
if (unread_command_char != -1)
{
XSET (c, Lisp_Int, unread_command_char);
unread_command_char = -1;
if (this_command_key_count == 0)
goto reread_first;
else
goto reread;
}
if (!NILP (Vexecuting_macro))
{
/* We set this to Qmacro; since that's not a frame, nobody will
try to switch frames on us, and the selected window will
remain unchanged.
Since this event came from a macro, it would be misleading to
leave internal_last_event_frame set to wherever the last
real event came from. Normally, a switch-frame event selects
internal_last_event_frame after each command is read, but
events read from a macro should never cause a new frame to be
selected. */
Vlast_event_frame = internal_last_event_frame = Qmacro;
/* Exit the macro if we are at the end.
Also, some things replace the macro with t
to force an early exit. */
if (EQ (Vexecuting_macro, Qt)
|| executing_macro_index >= XFASTINT (Flength (Vexecuting_macro)))
{
XSET (c, Lisp_Int, -1);
return c;
}
c = Faref (Vexecuting_macro, make_number (executing_macro_index));
if (XTYPE (Vexecuting_macro) == Lisp_String
&& (XINT (c) & 0x80))
XFASTINT (c) = CHAR_META | (XINT (c) & ~0x80);
executing_macro_index++;
goto from_macro;
}
if (!NILP (unread_switch_frame))
{
c = unread_switch_frame;
unread_switch_frame = Qnil;
/* This event should make it into this_command_keys, and get echoed
again, so we go to reread_first, rather than reread. */
goto reread_first;
}
if (commandflag >= 0 && !input_pending && !detect_input_pending ())
prepare_menu_bars ();
/* Save outer setjmp data, in case called recursively. */
save_getcjmp (save_jump);
stop_polling ();
if (commandflag >= 0 && !input_pending && !detect_input_pending ())
redisplay ();
if (_setjmp (getcjmp))
{
XSET (c, Lisp_Int, quit_char);
XSET (internal_last_event_frame, Lisp_Frame, selected_frame);
Vlast_event_frame = internal_last_event_frame;
/* If we report the quit char as an event,
don't do so more than once. */
if (!NILP (Vinhibit_quit))
Vquit_flag = Qnil;
goto non_reread;
}
/* Message turns off echoing unless more keystrokes turn it on again. */
if (echo_area_glyphs && *echo_area_glyphs && echo_area_glyphs != echobuf)
cancel_echoing ();
else
/* If already echoing, continue. */
echo_dash ();
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
if (minibuf_level == 0 && !immediate_echo && this_command_key_count > 0
&& ! noninteractive
&& echo_keystrokes > 0
&& (echo_area_glyphs == 0 || *echo_area_glyphs == 0))
{
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. */
if (EVENT_HAS_PARAMETERS (prev_event))
echo ();
else
{
tem0 = sit_for (echo_keystrokes, 0, 1, 1);
if (EQ (tem0, Qt))
echo ();
}
}
/* Maybe auto save due to number of keystrokes or idle time. */
if (commandflag != 0
&& auto_save_interval > 0
&& num_nonmacro_input_chars - last_auto_save > max (auto_save_interval, 20)
&& !detect_input_pending ())
{
jmp_buf temp;
save_getcjmp (temp);
Fdo_auto_save (Qnil, Qnil);
restore_getcjmp (temp);
}
/* Try reading a character via menu prompting.
Try this before the sit-for, because the sit-for
would do the wrong thing if we are supposed to do
menu prompting. */
c = Qnil;
if (INTERACTIVE && !NILP (prev_event))
c = read_char_menu_prompt (nmaps, maps, prev_event, used_mouse_menu);
/* Slow down auto saves logarithmically in size of current buffer,
and garbage collect while we're at it. */
if (INTERACTIVE && NILP (c))
{
int delay_level, buffer_size;
if (! MINI_WINDOW_P (XWINDOW (selected_window)))
last_non_minibuf_size = Z - BEG;
buffer_size = (last_non_minibuf_size >> 8) + 1;
delay_level = 0;
while (buffer_size > 64)
delay_level++, buffer_size -= buffer_size >> 2;
if (delay_level < 4) delay_level = 4;
/* delay_level is 4 for files under around 50k, 7 at 100k,
9 at 200k, 11 at 300k, and 12 at 500k. It is 15 at 1 meg. */
/* Auto save if enough time goes by without input. */
if (commandflag != 0
&& num_nonmacro_input_chars > last_auto_save