changeset 10861:655e3daa560c

(cmd_error): Use clear_prefix_arg. (internal_last_event_frame, Vlast_event_frame): Normal vars again. All uses changed. (Quniversal_argument, Qdigit_argument, Qnegative_argument): Declare. (clear_prefix_arg, finalize_prefix_arg, describe_prefix_arg): New fns. (command_loop_1): Handle digits and minus specially, when they're part of a prefix arg. Handle universal-argument and digit-argument and negative-argument bindings here, rather than doing I/O in the Lisp code. (read_char): When reading switch-frame events from the side queue, set internal_last_event_frame. (readable_events): Return non-zero if a side queue has data. (kbd_buffer_get_event): Don't abort if event has no associated frame. (read_key_sequence): Improve behavior when there's no current display. (init_perdisplay): Initialize the new members.
author Karl Heuer <kwzh@gnu.org>
date Wed, 01 Mar 1995 04:27:37 +0000
parents 9f9a34e401d5
children b905092475a7
files src/keyboard.c
diffstat 1 files changed, 181 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/src/keyboard.c	Wed Mar 01 03:45:45 1995 +0000
+++ b/src/keyboard.c	Wed Mar 01 04:27:37 1995 +0000
@@ -259,6 +259,20 @@
 /* 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;
@@ -267,6 +281,7 @@
 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.  */
@@ -753,9 +768,7 @@
   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);
 
@@ -943,6 +956,43 @@
   error ("No recursive edit is in progress");
 }
 
+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: -");
+}
+
 /* This is the actual command reading loop,
    sans error-handling encapsulation.  */
 
@@ -1096,6 +1146,16 @@
       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;
@@ -1110,12 +1170,56 @@
 	  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.  */
@@ -1238,7 +1342,7 @@
 	  /* 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);
 
@@ -1262,7 +1366,7 @@
 	 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 ();
@@ -1283,7 +1387,7 @@
     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
@@ -1546,10 +1650,7 @@
 	 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.
@@ -1600,10 +1701,8 @@
     {
       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.  */
@@ -1766,6 +1865,13 @@
 	{
 	  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
 	{
@@ -2081,6 +2187,18 @@
   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;
 }
 
@@ -2118,14 +2236,12 @@
 	     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
 
@@ -2261,9 +2377,12 @@
 	  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;
@@ -2357,10 +2476,10 @@
 	  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
@@ -2412,10 +2531,10 @@
 	  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
 
@@ -2433,7 +2552,7 @@
   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);
@@ -4801,7 +4920,7 @@
   /* 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)
@@ -4875,7 +4994,7 @@
   /* 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
@@ -5687,9 +5806,9 @@
   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))
@@ -5805,7 +5924,7 @@
   UNGCPRO;
 
   function = Fintern (function, Qnil);
-  current_perdisplay->Vprefix_arg = prefixarg;
+  Vprefix_arg = prefixarg;
   this_command = function;
 
   return Fcommand_execute (function, Qt);
@@ -6183,15 +6302,9 @@
     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);
@@ -6289,15 +6402,11 @@
 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;
@@ -6335,6 +6444,13 @@
 #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);
@@ -6424,6 +6540,15 @@
   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);
 
@@ -6641,6 +6766,11 @@
     "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\
@@ -6781,28 +6911,6 @@
 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 ()