/* The buffer that was current when the last command was started. */
Lisp_Object last_point_position_buffer;
+#ifdef MULTI_FRAME
+/* The frame in which the last input event occurred, or Qmacro if the
+ last event came from a macro. We use this to determine when to
+ generate switch-frame events. This may be cleared by functions
+ like Fselect_frame, to make sure that a switch-frame event is
+ generated by the next character. */
+Lisp_Object internal_last_event_frame;
+#endif
+
+/* 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;
+
/* The timestamp of the last input event we received from the X server.
X Windows wants this for selection ownership. */
unsigned long last_event_timestamp;
Lisp_Object Qforward_char;
Lisp_Object Qbackward_char;
Lisp_Object Qundefined;
+Lisp_Object Quniversal_argument, Qdigit_argument, Qnegative_argument;
/* read_key_sequence stores here the command definition of the
key sequence that it reads. */
Vstandard_output = Qt;
Vstandard_input = Qt;
Vexecuting_macro = Qnil;
- if (!current_perdisplay)
- abort ();
- current_perdisplay->Vprefix_arg = Qnil;
+ clear_prefix_arg ();
cancel_echoing ();
cmd_error_internal (data, 0);
error ("No recursive edit is in progress");
}
\f
+void
+clear_prefix_arg ()
+{
+ if (!current_perdisplay)
+ abort ();
+ current_perdisplay->prefix_factor = Qnil;
+ current_perdisplay->prefix_value = Qnil;
+ current_perdisplay->prefix_sign = 1;
+ current_perdisplay->prefix_partial = 0;
+ Vprefix_arg = Qnil;
+}
+
+static void
+finalize_prefix_arg ()
+{
+ if (!NILP (current_perdisplay->prefix_factor))
+ Vprefix_arg = Fcons (current_perdisplay->prefix_factor, Qnil);
+ else if (NILP (current_perdisplay->prefix_value))
+ Vprefix_arg = (current_perdisplay->prefix_sign > 0 ? Qnil : Qminus);
+ else if (current_perdisplay->prefix_sign > 0)
+ Vprefix_arg = current_perdisplay->prefix_value;
+ else
+ XSETINT (Vprefix_arg, -XINT (current_perdisplay->prefix_value));
+ current_perdisplay->prefix_partial = 0;
+}
+
+static void
+describe_prefix_arg ()
+{
+ if (INTEGERP (Vprefix_arg))
+ message ("Arg: %d", Vprefix_arg);
+ else if (CONSP (Vprefix_arg))
+ message ("Arg: [%d]", XCONS (Vprefix_arg)->car);
+ else if (EQ (Vprefix_arg, Qminus))
+ message ("Arg: -");
+}
+\f
/* This is the actual command reading loop,
sans error-handling encapsulation. */
last_point_position = PT;
XSETBUFFER (last_point_position_buffer, prev_buffer);
+ /* If we're building a prefix argument, override minus and digits. */
+ if (current_perdisplay->prefix_partial && i == 1 && NATNUMP (keybuf[0]))
+ {
+ if (XFASTINT (keybuf[0]) == '-'
+ && NILP (current_perdisplay->prefix_value))
+ cmd = Qnegative_argument;
+ else if (XFASTINT (keybuf[0]) >= '0' && XFASTINT (keybuf[0]) <= '9')
+ cmd = Qdigit_argument;
+ }
+
/* Execute the command. */
this_command = cmd;
bitch_at_user ();
defining_kbd_macro = 0;
update_mode_lines = 1;
- current_perdisplay->Vprefix_arg = Qnil;
-
+ clear_prefix_arg ();
}
else
{
- if (NILP (current_perdisplay->Vprefix_arg) && ! no_direct)
+ if (EQ (cmd, Quniversal_argument))
+ {
+ if (!current_perdisplay->prefix_partial)
+ {
+ /* First C-u */
+ XSETFASTINT (current_perdisplay->prefix_factor, 4);
+ current_perdisplay->prefix_value = Qnil;
+ current_perdisplay->prefix_sign = 1;
+ current_perdisplay->prefix_partial = 1;
+ }
+ else if (!NILP (current_perdisplay->prefix_factor))
+ {
+ /* Subsequent C-u */
+ XSETINT (current_perdisplay->prefix_factor,
+ XINT (current_perdisplay->prefix_factor) * 4);
+ }
+ else
+ {
+ /* Terminating C-u */
+ finalize_prefix_arg ();
+ describe_prefix_arg ();
+ }
+ goto directly_done;
+ }
+ else if (EQ (cmd, Qnegative_argument))
+ {
+ current_perdisplay->prefix_factor = Qnil;
+ current_perdisplay->prefix_sign *= -1;
+ current_perdisplay->prefix_partial = 1;
+ goto directly_done;
+ }
+ else if (EQ (cmd, Qdigit_argument) && INTEGERP (keybuf[0]))
+ {
+ current_perdisplay->prefix_factor = Qnil;
+ if (NILP (current_perdisplay->prefix_value))
+ XSETFASTINT (current_perdisplay->prefix_value, 0);
+ XSETINT (current_perdisplay->prefix_value,
+ (XINT (current_perdisplay->prefix_value) * 10
+ + (XINT (keybuf[0]) & 0177) - '0'));
+ current_perdisplay->prefix_partial = 1;
+ goto directly_done;
+ }
+ if (current_perdisplay->prefix_partial)
+ finalize_prefix_arg ();
+
+ if (NILP (Vprefix_arg) && ! no_direct)
{
/* Recognize some common commands in common situations and
do them directly. */
/* Here for a command that isn't executed directly */
nonundocount = 0;
- if (NILP (current_perdisplay->Vprefix_arg))
+ if (NILP (Vprefix_arg))
Fundo_boundary ();
Fcommand_execute (this_command, Qnil);
3) we want to leave this_command_key_count non-zero, so that
read_char will realize that it is re-reading a character, and
not echo it a second time. */
- if (NILP (current_perdisplay->Vprefix_arg))
+ if (NILP (Vprefix_arg))
{
last_command = this_command;
cancel_echoing ();
finalize:
/* Install chars successfully executed in kbd macro. */
- if (defining_kbd_macro && NILP (current_perdisplay->Vprefix_arg))
+ if (defining_kbd_macro && NILP (Vprefix_arg))
finalize_kbd_macro_chars ();
#ifdef MULTI_PERDISPLAY
internal_last_event_frame after each command is read, but
events read from a macro should never cause a new frame to be
selected. */
- if (!current_perdisplay)
- abort ();
- current_perdisplay->internal_last_event_frame = Qmacro;
- current_perdisplay->Vlast_event_frame = Qmacro;
+ Vlast_event_frame = internal_last_event_frame = Qmacro;
#endif
/* Exit the macro if we are at the end.
{
XSETINT (c, quit_char);
#ifdef MULTI_FRAME
- XSETFRAME (current_perdisplay->internal_last_event_frame,
- selected_frame);
- current_perdisplay->Vlast_event_frame
- = current_perdisplay->internal_last_event_frame;
+ XSETFRAME (internal_last_event_frame, selected_frame);
+ Vlast_event_frame = internal_last_event_frame;
#endif
/* If we report the quit char as an event,
don't do so more than once. */
{
c = XCONS (perd->kbd_queue)->car;
perd->kbd_queue = XCONS (perd->kbd_queue)->cdr;
+ input_pending = readable_events ();
+#ifdef MULTI_FRAME
+ if (EVENT_HAS_PARAMETERS (c)
+ && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qswitch_frame))
+ internal_last_event_frame = XCONS (XCONS (c)->cdr)->car;
+ Vlast_event_frame = internal_last_event_frame;
+#endif
}
else
{
if (FRAMEP (do_mouse_tracking) && mouse_moved)
return 1;
#endif
+ if (display_locked)
+ {
+ if (CONSP (current_perdisplay->kbd_queue))
+ return 1;
+ }
+ else
+ {
+ PERDISPLAY *perd;
+ for (perd = all_perdisplays; perd; perd = perd->next_perdisplay)
+ if (CONSP (perd->kbd_queue))
+ return 1;
+ }
return 0;
}
will set Vlast_event_frame again, so this is safe to do. */
{
Lisp_Object focus;
- PERDISPLAY *perd;
focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
if (NILP (focus))
focus = event->frame_or_window;
- perd = get_perdisplay (XFRAME (focus));
- perd->internal_last_event_frame = focus;
- perd->Vlast_event_frame = focus;
+ internal_last_event_frame = focus;
+ Vlast_event_frame = focus;
}
#endif
frame = XCONS (frame)->car;
else if (WINDOWP (frame))
frame = WINDOW_FRAME (XWINDOW (frame));
+ /* There are still some events that don't set this field.
+ For now, just ignore the problem. */
if (!FRAMEP (frame))
- abort ();
- *perdp = get_perdisplay (XFRAME (frame));
+ *perdp = all_perdisplays;
+ else
+ *perdp = get_perdisplay (XFRAME (frame));
}
obj = Qnil;
if (! NILP (focus))
frame = focus;
- if (! EQ (frame, (*perdp)->internal_last_event_frame)
+ if (! EQ (frame, internal_last_event_frame)
&& XFRAME (frame) != selected_frame)
obj = make_lispy_switch_frame (frame);
- (*perdp)->internal_last_event_frame = frame;
+ internal_last_event_frame = frame;
#endif /* MULTI_FRAME */
/* If we didn't decide to make a switch-frame event, go ahead
if (NILP (frame))
XSETFRAME (frame, f);
- if (! EQ (frame, (*perdp)->internal_last_event_frame)
+ if (! EQ (frame, internal_last_event_frame)
&& XFRAME (frame) != selected_frame)
obj = make_lispy_switch_frame (frame);
- (*perdp)->internal_last_event_frame = frame;
+ internal_last_event_frame = frame;
}
#endif
input_pending = readable_events ();
#ifdef MULTI_FRAME
- (*perdp)->Vlast_event_frame = (*perdp)->internal_last_event_frame;
+ Vlast_event_frame = internal_last_event_frame;
#endif
return (obj);
/* Record the initial state of the echo area and this_command_keys;
we will need to restore them if we replay a key sequence. */
if (INTERACTIVE)
- echo_start = echo_length ();
+ echo_start = (current_perdisplay ? echo_length () : 0);
keys_start = this_command_key_count;
#if defined (GOBBLE_FIRST_EVENT)
/* These are no-ops the first time through, but if we restart, they
revert the echo area and this_command_keys to their original state. */
this_command_key_count = keys_start;
- if (INTERACTIVE && t < mock_input)
+ if (INTERACTIVE && t < mock_input && current_perdisplay)
echo_truncate (echo_start);
/* If the best binding for the current key sequence is a keymap, or
struct backtrace backtrace;
extern int debug_on_next_call;
- prefixarg = current_perdisplay->Vprefix_arg;
- current_perdisplay->Vprefix_arg = Qnil;
- current_perdisplay->Vcurrent_prefix_arg = prefixarg;
+ prefixarg = Vprefix_arg;
+ clear_prefix_arg ();
+ Vcurrent_prefix_arg = prefixarg;
debug_on_next_call = 0;
if (SYMBOLP (cmd))
UNGCPRO;
function = Fintern (function, Qnil);
- current_perdisplay->Vprefix_arg = prefixarg;
+ Vprefix_arg = prefixarg;
this_command = function;
return Fcommand_execute (function, Qt);
abort ();
#endif
#ifdef MULTI_FRAME
- {
- Lisp_Object frame;
-
- if (!current_perdisplay)
- abort ();
- frame = current_perdisplay->internal_last_event_frame;
- if (FRAMEP (frame) && XFRAME (frame) != selected_frame)
- Fhandle_switch_frame (make_lispy_switch_frame (frame));
- }
+ if (FRAMEP (internal_last_event_frame)
+ && XFRAME (internal_last_event_frame) != selected_frame)
+ Fhandle_switch_frame (make_lispy_switch_frame (internal_last_event_frame));
#endif
_longjmp (getcjmp, 1);
init_perdisplay (perd)
PERDISPLAY *perd;
{
- perd->Vprefix_arg = Qnil;
- perd->Vcurrent_prefix_arg = Qnil;
-#ifdef MULTI_FRAME
- /* This means that command_loop_1 won't try to select anything the first
- time through. */
- perd->internal_last_event_frame = Qnil;
-#endif
+ perd->prefix_factor = Qnil;
+ perd->prefix_value = Qnil;
+ perd->prefix_sign = 1;
+ perd->prefix_partial = 0;
perd->kbd_queue = Qnil;
- perd->Vlast_event_frame = Qnil;
perd->immediate_echo = 0;
perd->echoptr = perd->echobuf;
perd->echo_after_prompt = -1;
#endif
input_pending = 0;
+#ifdef MULTI_FRAME
+ /* This means that command_loop_1 won't try to select anything the first
+ time through. */
+ internal_last_event_frame = Qnil;
+ Vlast_event_frame = internal_last_event_frame;
+#endif
+
#ifndef MULTI_PERDISPLAY
if (initialized)
wipe_perdisplay (&the_only_perdisplay);
Qundefined = intern ("undefined");
staticpro (&Qundefined);
+ Quniversal_argument = intern ("universal-argument");
+ staticpro (&Quniversal_argument);
+
+ Qdigit_argument = intern ("digit-argument");
+ staticpro (&Qdigit_argument);
+
+ Qnegative_argument = intern ("negative-argument");
+ staticpro (&Qnegative_argument);
+
Qpre_command_hook = intern ("pre-command-hook");
staticpro (&Qpre_command_hook);
"Number of complete keys read from the keyboard so far.");
num_input_keys = 0;
+ DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
+ "The frame in which the most recently read event occurred.\n\
+If the last event came from a keyboard macro, this is set to `macro'.");
+ Vlast_event_frame = Qnil;
+
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\
This function is called with no arguments after each command\n\
whenever `deferred-action-list' is non-nil.");
Vdeferred_action_function = Qnil;
-
- DEFVAR_DISPLAY ("prefix-arg", Vprefix_arg,
- "The value of the prefix argument for the next editing command.\n\
-It may be a number, or the symbol `-' for just a minus sign as arg,\n\
-or a list whose car is a number for just one or more C-U's\n\
-or nil if no argument has been specified.\n\
-\n\
-You cannot examine this variable to find the argument for this command\n\
-since it has been set to nil by the time you can look.\n\
-Instead, you should use the variable `current-prefix-arg', although\n\
-normally commands can get this prefix argument with (interactive \"P\").");
-
- DEFVAR_DISPLAY ("current-prefix-arg", Vcurrent_prefix_arg,
- "The value of the prefix argument for this editing command.\n\
-It may be a number, or the symbol `-' for just a minus sign as arg,\n\
-or a list whose car is a number for just one or more C-U's\n\
-or nil if no argument has been specified.\n\
-This is what `(interactive \"P\")' returns.");
-
- DEFVAR_DISPLAY ("last-event-frame", Vlast_event_frame,
- "The frame in which the most recently read event occurred.\n\
-If the last event came from a keyboard macro, this is set to `macro'.");
}
keys_of_keyboard ()