(read_char): After Fgarbage_collect, call redisplay.

(read_key_sequence): When inserting `menu-bar' prefix,
modify the position field to prevent doing so twice.
Do all these forms of event expansion after replayed events also.
Set last_real_key_start before each key.
Use last_real_key_start in criterion for being the first event.

(syms_of_keyboard): Doc fix.
(Vhelp_char): Renamed from help_char.
(Vprefix_help_command): New Lisp variable.
(read_key_sequence): Use that, for help char after prefix key.

(kbd_buffer_get_event): Clear f before calling mouse_position_hook.
This commit is contained in:
Richard M. Stallman 1993-07-04 02:21:02 +00:00
parent 58bf604216
commit 7e85b93579

View file

@ -122,11 +122,14 @@ static int echoing;
int immediate_quit;
/* Character to recognize as the help char. */
Lisp_Object help_char;
Lisp_Object Vhelp_char;
/* Form to execute when help char is typed. */
Lisp_Object Vhelp_form;
/* Command to run when the help character follows a prefix key. */
Lisp_Object Vprefix_help_command;
/* Character that causes a quit. Normally C-g.
If we are running on an ordinary terminal, this must be an ordinary
@ -505,7 +508,7 @@ echo_char (c)
ptr += name->size;
}
if (echoptr == echobuf && EQ (c, help_char))
if (echoptr == echobuf && EQ (c, Vhelp_char))
{
strcpy (ptr, " (Type ? for further options)");
ptr += strlen (ptr);
@ -1480,7 +1483,10 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
consing going on to make it worthwhile. */
if (!detect_input_pending ()
&& consing_since_gc > gc_cons_threshold / 2)
Fgarbage_collect ();
{
Fgarbage_collect ();
redisplay ();
}
}
}
}
@ -1587,7 +1593,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
num_input_chars++;
/* Process the help character specially if enabled */
if (EQ (c, help_char) && !NILP (Vhelp_form))
if (EQ (c, Vhelp_char) && !NILP (Vhelp_form))
{
Lisp_Object tem0;
count = specpdl_ptr - specpdl;
@ -1914,7 +1920,7 @@ kbd_buffer_get_event ()
}
else if (do_mouse_tracking && mouse_moved)
{
FRAME_PTR f;
FRAME_PTR f = 0;
Lisp_Object bar_window;
enum scroll_bar_part part;
Lisp_Object x, y;
@ -3802,6 +3808,9 @@ read_key_sequence (keybuf, bufsize, prompt)
this_command_key_count = keys_local_start;
first_binding = local_first_binding;
/* By default, assume each event is "real". */
last_real_key_start = t;
/* Does mock_input indicate that we are re-reading a key sequence? */
if (t < mock_input)
{
@ -3815,8 +3824,6 @@ read_key_sequence (keybuf, bufsize, prompt)
{
struct buffer *buf = current_buffer;
last_real_key_start = t;
key = read_char (!prompt, nmaps, submaps, last_nonmenu_event,
&used_mouse_menu);
@ -3830,125 +3837,131 @@ read_key_sequence (keybuf, bufsize, prompt)
}
Vquit_flag = Qnil;
}
/* Clicks in non-text areas get prefixed by the symbol
in their CHAR-ADDRESS field. For example, a click on
the mode line is prefixed by the symbol `mode-line'.
/* Clicks in non-text areas get prefixed by the symbol
in their CHAR-ADDRESS field. For example, a click on
the mode line is prefixed by the symbol `mode-line'.
Furthermore, key sequences beginning with mouse clicks
are read using the keymaps of the buffer clicked on, not
the current buffer. So we may have to switch the buffer
here.
Furthermore, key sequences beginning with mouse clicks
are read using the keymaps of the buffer clicked on, not
the current buffer. So we may have to switch the buffer
here.
If the event was obtained from the unread_command_events
queue, then don't expand it; we did that the first time
we read it. */
if (EVENT_HAS_PARAMETERS (key))
When we turn one event into two events, we must make sure
that neither of the two looks like the original--so that,
if we replay the events, they won't be expanded again.
If not for this, such reexpansion could happen either here
or when user programs play with this-command-keys. */
if (EVENT_HAS_PARAMETERS (key))
{
Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
Lisp_Object window = POSN_WINDOW (EVENT_START (key));
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
if (EQ (kind, Qmouse_click))
if (XTYPE (posn) == Lisp_Cons)
{
Lisp_Object window = POSN_WINDOW (EVENT_START (key));
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Key sequences beginning with mouse clicks are
read using the keymaps in the buffer clicked on,
not the current buffer. If we're at the
beginning of a key sequence, switch buffers. */
if (t == 0
&& XTYPE (window) == Lisp_Window
&& XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer
&& XBUFFER (XWINDOW (window)->buffer) != current_buffer)
{
keybuf[t] = key;
mock_input = t + 1;
/* Arrange to go back to the original buffer once we're
done reading the key sequence. Note that we can't
use save_excursion_{save,restore} here, because they
save point as well as the current buffer; we don't
want to save point, because redisplay may change it,
to accommodate a Fset_window_start or something. We
don't want to do this at the top of the function,
because we may get input from a subprocess which
wants to change the selected window and stuff (say,
emacsclient). */
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
goto replay_sequence;
}
else if (XTYPE (posn) == Lisp_Symbol)
{
if (t + 1 >= bufsize)
error ("key sequence too long");
keybuf[t] = posn;
keybuf[t+1] = key;
mock_input = t + 2;
/* 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);
/* If we switched buffers while reading the first event,
replay in case we switched keymaps too. */
if (buf != current_buffer && t == 0)
goto replay_sequence;
goto replay_key;
}
else if (XTYPE (posn) == Lisp_Cons)
{
/* We're looking at the second event of a
sequence which we expanded before. Set
last_real_key_start appropriately. */
if (last_real_key_start == t && t > 0)
last_real_key_start = t - 1;
}
}
else if (EQ (kind, Qswitch_frame))
{
/* If we're at the beginning of a key sequence, go
ahead and return this event. If we're in the
midst of a key sequence, delay it until the end. */
/* We're looking at the second event of a
sequence which we expanded before. Set
last_real_key_start appropriately. */
if (t > 0)
{
delayed_switch_frame = key;
goto replay_key;
}
last_real_key_start = t - 1;
}
else
{
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix char `menu-bar'. */
if (EQ (posn, Qmenu_bar))
{
if (t + 1 >= bufsize)
error ("key sequence too long");
/* Run the Lucid hook. */
call1 (Vrun_hooks, Qactivate_menubar_hook);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
call0 (Qrecompute_lucid_menubar);
keybuf[t] = posn;
keybuf[t+1] = key;
mock_input = t + 2;
goto replay_sequence;
}
/* Key sequences beginning with mouse clicks are
read using the keymaps in the buffer clicked on,
not the current buffer. If we're at the
beginning of a key sequence, switch buffers. */
if (last_real_key_start == 0
&& XTYPE (window) == Lisp_Window
&& XTYPE (XWINDOW (window)->buffer) == Lisp_Buffer
&& XBUFFER (XWINDOW (window)->buffer) != current_buffer)
{
keybuf[t] = key;
mock_input = t + 1;
/* Arrange to go back to the original buffer once we're
done reading the key sequence. Note that we can't
use save_excursion_{save,restore} here, because they
save point as well as the current buffer; we don't
want to save point, because redisplay may change it,
to accommodate a Fset_window_start or something. We
don't want to do this at the top of the function,
because we may get input from a subprocess which
wants to change the selected window and stuff (say,
emacsclient). */
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
goto replay_sequence;
}
else if (XTYPE (posn) == Lisp_Symbol)
{
/* Expand mode-line and scroll-bar events into two events:
use posn as a fake prefix key. */
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);
goto replay_key;
}
}
/* If we switched buffers while reading the first event,
replay in case we switched keymaps too. */
if (buf != current_buffer && t == 0)
else if (EQ (kind, Qswitch_frame))
{
keybuf[t++] = key;
mock_input = t;
goto replay_sequence;
/* If we're at the beginning of a key sequence, go
ahead and return this event. If we're in the
midst of a key sequence, delay it until the end. */
if (t > 0)
{
delayed_switch_frame = key;
goto replay_key;
}
}
else
{
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
/* Handle menu-bar events:
insert the dummy prefix event `menu-bar'. */
if (EQ (posn, Qmenu_bar))
{
if (t + 1 >= bufsize)
error ("key sequence too long");
/* Run the Lucid hook. */
call1 (Vrun_hooks, Qactivate_menubar_hook);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
call0 (Qrecompute_lucid_menubar);
keybuf[t] = posn;
keybuf[t+1] = key;
/* 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);
mock_input = t + 2;
goto replay_sequence;
}
else if (XTYPE (posn) == Lisp_Cons)
{
/* We're looking at the second event of a
sequence which we expanded before. Set
last_real_key_start appropriately. */
if (last_real_key_start == t && t > 0)
last_real_key_start = t - 1;
}
}
}
@ -3966,6 +3979,14 @@ read_key_sequence (keybuf, bufsize, prompt)
{
Lisp_Object head = EVENT_HEAD (key);
if (EQ (head, Vhelp_char))
{
read_key_sequence_cmd = Vprefix_help_command;
keybuf[t++] = key;
last_nonmenu_event = key;
goto done;
}
if (XTYPE (head) == Lisp_Symbol)
{
Lisp_Object breakdown = parse_modifiers (head);
@ -5081,18 +5102,24 @@ If the last event came from a keyboard macro, this is set to `macro'.");
Vlast_event_frame = Qnil;
#endif
DEFVAR_LISP ("help-char", &help_char,
DEFVAR_LISP ("help-char", &Vhelp_char,
"Character to recognize as meaning Help.\n\
When it is read, do `(eval help-form)', and display result if it's a string.\n\
If the value of `help-form' is nil, this char can be read normally.");
XSET (help_char, Lisp_Int, Ctl ('H'));
XSET (Vhelp_char, Lisp_Int, Ctl ('H'));
DEFVAR_LISP ("help-form", &Vhelp_form,
"Form to execute when character help-char is read.\n\
"Form to execute when character `help-char' is read.\n\
If the form returns a string, that string is displayed.\n\
If `help-form' is nil, the help char is not recognized.");
Vhelp_form = Qnil;
DEFVAR_LISP ("prefix-help-command", &Vprefix_help_command,
"Command to run when `help-char' character follows a prefix key.\n\
This command is used only when there is no actual binding\n\
for that character after that prefix key.");
Vprefix_help_command = Qnil;
DEFVAR_LISP ("top-level", &Vtop_level,
"Form to evaluate when Emacs starts up.\n\
Useful to set before you dump a modified Emacs.");
@ -5144,7 +5171,7 @@ Buffer modification stores t in this variable.");
Vpre_command_hook = Qnil;
DEFVAR_LISP ("post-command-hook", &Vpost_command_hook,
"Normal hook run before each command is executed.");
"Normal hook run after each command is executed.");
Vpost_command_hook = Qnil;
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", &Vlucid_menu_bar_dirty_flag,