changeset 10985:d917a965cb47

(unlock_display): current_perdisplay now is never null. (cmd_error, command_loop_1, read_char): Likewise. (kbd_buffer_get_event, read_key_sequence): Likewise. (read_char): Handle synchronous quit_char on a different display. (read_char): Rewrite queue-searching code. (read_key_sequence): Save selected_frame. (init_keyboard): Initialize current_perdisplay.
author Karl Heuer <kwzh@gnu.org>
date Mon, 13 Mar 1995 03:09:40 +0000
parents 0409e4548077
children 7e797580a46d
files src/keyboard.c
diffstat 1 files changed, 126 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/src/keyboard.c	Sun Mar 12 21:30:35 1995 +0000
+++ b/src/keyboard.c	Mon Mar 13 03:09:40 1995 +0000
@@ -525,7 +525,7 @@
   echo ();
 }
 
-/* Add C to the echo string, if echoing is going on.  
+/* 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.  */
 
@@ -537,7 +537,7 @@
   if (current_perdisplay->immediate_echo)
     {
       char *ptr = current_perdisplay->echoptr;
-      
+
       if (ptr != current_perdisplay->echobuf)
 	*ptr++ = ' ';
 
@@ -762,7 +762,6 @@
       current_perdisplay->kbd_queue_has_data = 1;
     }
   Vunread_command_events = Qnil;
-  current_perdisplay = 0;
   display_locked = 0;
 }
 #endif
@@ -776,11 +775,8 @@
   Vstandard_output = Qt;
   Vstandard_input = Qt;
   Vexecuting_macro = Qnil;
-  if (current_perdisplay)
-    {
-      clear_prefix_arg ();
-      cancel_echoing ();
-    }
+  clear_prefix_arg ();
+  cancel_echoing ();
 
   /* Avoid unquittable loop if data contains a circular list.  */
   old_level = Vprint_level;
@@ -795,8 +791,7 @@
 
   Vinhibit_quit = Qnil;
 #ifdef MULTI_PERDISPLAY
-  if (current_perdisplay)
-    unlock_display ();
+  unlock_display ();
 #endif
 
   return make_number (0);
@@ -905,7 +900,7 @@
       {
 	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);
@@ -1001,8 +996,7 @@
 
   Vdeactivate_mark = Qnil;
   waiting_for_input = 0;
-  if (current_perdisplay)
-    cancel_echoing ();
+  cancel_echoing ();
 
   nonundocount = 0;
   no_redisplay = 0;
@@ -1606,7 +1600,7 @@
 	  XSETINT (c, -1);
 	  return c;
 	}
-      
+
       c = Faref (Vexecuting_macro, make_number (executing_macro_index));
       if (STRINGP (Vexecuting_macro)
 	  && (XINT (c) & 0x80))
@@ -1653,19 +1647,36 @@
       if (!NILP (Vinhibit_quit))
 	Vquit_flag = Qnil;
 
+#ifdef MULTI_PERDISPLAY
+      {
+	PERDISPLAY *perd = get_perdisplay (selected_frame);
+	if (perd != current_perdisplay)
+	  {
+	    Lisp_Object *tailp = &perd->kbd_queue;
+	    /* We shouldn't get here if we were locked onto one display!  */
+	    if (display_locked)
+	      abort ();
+	    while (CONSP (*tailp))
+	      tailp = &XCONS (*tailp)->cdr;
+	    if (!NILP (*tailp))
+	      abort ();
+	    *tailp = Fcons (c, Qnil);
+	    perd->kbd_queue_has_data = 1;
+	    current_perdisplay = perd;
+	    longjmp (wrong_display_jmpbuf, 1);
+	  }
+      }
+#endif
       goto non_reread;
     }
 
-  if (current_perdisplay)
-    {
-      /* Message turns off echoing unless more keystrokes turn it on again. */
-      if (echo_area_glyphs && *echo_area_glyphs
-	  && echo_area_glyphs != current_perdisplay->echobuf)
-	cancel_echoing ();
-      else
-	/* If already echoing, continue.  */
-	echo_dash ();
-    }
+  /* Message turns off echoing unless more keystrokes turn it on again. */
+  if (echo_area_glyphs && *echo_area_glyphs
+      && echo_area_glyphs != current_perdisplay->echobuf)
+    cancel_echoing ();
+  else
+    /* If already echoing, continue.  */
+    echo_dash ();
 
   /* Try reading a character via menu prompting in the minibuf.
      Try this before the sit-for, because the sit-for
@@ -1690,9 +1701,7 @@
 
   /* If in middle of key sequence and minibuffer not active,
      start echoing if enough time elapses.  */
-  if (current_perdisplay
-      && minibuf_level == 0
-      && !current_perdisplay->immediate_echo
+  if (minibuf_level == 0 && !current_perdisplay->immediate_echo
       && this_command_key_count > 0
       && ! noninteractive
       && echo_keystrokes > 0
@@ -1786,33 +1795,20 @@
 
   if (NILP (c))
     {
-      PERDISPLAY *perd;
-      /* Check for something on one of the side queues.  Give priority to
-	 the current display, but if we're not locked, then check the other
-	 displays as well.  */
-      if (current_perdisplay && current_perdisplay->kbd_queue_has_data)
-	perd = current_perdisplay;
-      else if (!display_locked)
+      /* Primary consideration goes to current_perdisplay's side queue.
+	 If that's empty, then we check the other side queues and throw
+	 if we find something there.  Finally, we read from the main queue,
+	 and if that gives us something we can't use yet, we put it on the
+	 appropriate side queue and try again.  */
+      if (current_perdisplay->kbd_queue_has_data)
 	{
-	  for (perd = all_perdisplays; perd; perd = perd->next_perdisplay)
-	    if (perd->kbd_queue_has_data)
-	      break;
-	}
-      else
-	perd = 0;
-
-      /* If we found something on a side queue, use that.
-	 Otherwise, read from the main queue, and if that gives us
-	 something we can't use yet, put it on the side queue and
-	 try again.  */
-      if (perd)
-	{
-	  if (!CONSP (perd->kbd_queue))
+	  if (!CONSP (current_perdisplay->kbd_queue))
 	    abort ();
-	  c = XCONS (perd->kbd_queue)->car;
-	  perd->kbd_queue = XCONS (perd->kbd_queue)->cdr;
-	  if (NILP (perd->kbd_queue))
-	    perd->kbd_queue_has_data = 0;
+	  c = XCONS (current_perdisplay->kbd_queue)->car;
+	  current_perdisplay->kbd_queue
+	    = XCONS (current_perdisplay->kbd_queue)->cdr;
+	  if (NILP (current_perdisplay->kbd_queue))
+	    current_perdisplay->kbd_queue_has_data = 0;
 	  input_pending = readable_events ();
 #ifdef MULTI_FRAME
 	  if (EVENT_HAS_PARAMETERS (c)
@@ -1823,6 +1819,19 @@
 	}
       else
 	{
+	  PERDISPLAY *perd;
+#ifdef MULTI_PERDISPLAY
+	  if (!display_locked)
+	    {
+	      for (perd = all_perdisplays; perd; perd = perd->next_perdisplay)
+		if (perd->kbd_queue_has_data)
+		  {
+		    current_perdisplay = perd;
+		    longjmp (wrong_display_jmpbuf, 1);
+		  }
+	    }
+#endif
+
 	wrong_display:
 	  /* Actually read a character, waiting if necessary.  */
 	  while (c = kbd_buffer_get_event (&perd), NILP (c))
@@ -1834,7 +1843,8 @@
 		  redisplay ();
 		}
 	    }
-	  if (display_locked && perd != current_perdisplay)
+#ifdef MULTI_PERDISPLAY
+	  if (perd != current_perdisplay)
 	    {
 	      Lisp_Object *tailp = &perd->kbd_queue;
 	      while (CONSP (*tailp))
@@ -1843,21 +1853,13 @@
 		abort ();
 	      *tailp = Fcons (c, Qnil);
 	      perd->kbd_queue_has_data = 1;
-	      goto wrong_display;
+	      if (display_locked)
+		goto wrong_display;
+	      current_perdisplay = perd;
+	      longjmp (wrong_display_jmpbuf, 1);
 	    }
+#endif
 	}
-#ifdef MULTI_PERDISPLAY
-      if (perd != current_perdisplay)
-	{
-	  /* We shouldn't get here if we were locked onto one display!  */
-	  if (display_locked)
-	    abort ();
-	  perd->kbd_queue = Fcons (c, perd->kbd_queue);
-	  perd->kbd_queue_has_data = 1;
-	  current_perdisplay = perd;
-	  longjmp (wrong_display_jmpbuf, 1);
-	}
-#endif
     }
   /* Terminate Emacs in batch mode if at eof.  */
   if (noninteractive && INTEGERP (c) && XINT (c) < 0)
@@ -2111,7 +2113,7 @@
     prepare_menu_bars ();
 
   XSETFRAME (do_mouse_tracking, selected_frame);
-  
+
   val = Fprogn (args);
   return unbind_to (count, val);
 }
@@ -2455,9 +2457,6 @@
       Lisp_Object x, y;
       unsigned long time;
 
-      if (!current_perdisplay)
-	abort ();
-
       *perdp = current_perdisplay;
       /* Note that this uses F to determine which display to look at.
 	 If there is no valid info, it does not store anything
@@ -2486,7 +2485,7 @@
 	}
 #endif
 
-      /* If we didn't decide to make a switch-frame event, go ahead and 
+      /* If we didn't decide to make a switch-frame event, go ahead and
 	 return a mouse-motion event.  */
       if (!NILP (x) && NILP (obj))
 	obj = make_lispy_movement (f, bar_window, part, x, y, time);
@@ -2752,7 +2751,7 @@
     0, 0, 0, 0, 0, 0, 0, "delete"
     };
 
-static char *lispy_mouse_names[] = 
+static char *lispy_mouse_names[] =
 {
   "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5"
 };
@@ -2873,7 +2872,7 @@
       break;
 
 #if defined (MULTI_FRAME) || defined (HAVE_MOUSE)
-      /* A mouse click.  Figure out where it is, decide whether it's 
+      /* A mouse click.  Figure out where it is, decide whether it's
          a press, click or drag, and build the appropriate structure.  */
     case mouse_click:
     case scroll_bar_click:
@@ -3241,7 +3240,7 @@
   int modifiers;
 
   CHECK_SYMBOL (symbol, 1);
-  
+
   modifiers = 0;
   name = XSYMBOL (symbol)->name;
 
@@ -3357,7 +3356,7 @@
 
   {
     Lisp_Object new_name;
-    
+
     new_name = make_uninit_string (mod_len + base_len);
     bcopy (new_mods, XSTRING (new_name)->data,	       mod_len);
     bcopy (base,     XSTRING (new_name)->data + mod_len, base_len);
@@ -3470,7 +3469,7 @@
     new_symbol = XCONS (entry)->cdr;
   else
     {
-      /* We have to create the symbol ourselves.  */  
+      /* We have to create the symbol ourselves.  */
       new_symbol = apply_modifiers_uncached (modifiers,
 					     XSYMBOL (base)->name->data,
 					     XSYMBOL (base)->name->size);
@@ -3487,7 +3486,7 @@
 	    Fcons (base, lispy_modifier_list (modifiers)));
     }
 
-  /* Make sure this symbol is of the same kind as BASE.  
+  /* Make sure this symbol is of the same kind as BASE.
 
      You'd think we could just set this once and for all when we
      intern the symbol above, but reorder_modifiers may call us when
@@ -3547,12 +3546,12 @@
    before.  The object stored there may be a vector or an alist.
 
    SYMBOL_NUM is the number of the base name we want from NAME_TABLE.
-   
+
    MODIFIERS is a set of modifier bits (as given in struct input_events)
    whose prefixes should be applied to the symbol name.
 
    SYMBOL_KIND is the value to be placed in the event_kind property of
-   the returned symbol. 
+   the returned symbol.
 
    The symbols we create are supposed to have an
    `event-symbol-elements' property, which lists the modifiers present
@@ -3620,7 +3619,7 @@
       else
 	XVECTOR (*symbol_table)->contents[symbol_num] = value;
 
-      /* Fill in the cache entries for this symbol; this also 	
+      /* Fill in the cache entries for this symbol; this also
 	 builds the Qevent_symbol_elements property, which the user
 	 cares about.  */
       apply_modifiers (modifiers & click_modifier, value);
@@ -4093,7 +4092,7 @@
 void
 reinvoke_input_signal ()
 {
-#ifdef SIGIO  
+#ifdef SIGIO
   kill (0, SIGIO);
 #endif
 }
@@ -4164,7 +4163,7 @@
      We do this instead of specbind because (1) errors will clear it anyway
      and (2) this avoids risk of specpdl overflow.  */
   oquit = Vinhibit_quit;
-  Vinhibit_quit = Qt; 
+  Vinhibit_quit = Qt;
 
   if (!NILP (old))
     menu_bar_items_vector = old;
@@ -4179,7 +4178,7 @@
      keybuf with its symbol, or if the sequence starts with a mouse
      click and we need to switch buffers, we jump back here to rebuild
      the initial keymaps from the current buffer.  */
-  { 
+  {
     Lisp_Object *tmaps;
 
     /* Should overriding-local-map apply, here?  */
@@ -4433,7 +4432,7 @@
    USED_MOUSE_MENU is zero, *USED_MOUSE_MENU is left alone.
 
    The prompting is done based on the prompt-string of the map
-   and the strings associated with various map elements.  
+   and the strings associated with various map elements.
 
    This can be done with X menus or with menus put in the minibuf.
    These are done in different ways, depending on how the input will be read.
@@ -4654,7 +4653,7 @@
       /* Prompt with that and read response.  */
       message1 (menu);
 
-      /* Make believe its not a keyboard macro in case the help char 
+      /* Make believe its not a keyboard macro in case the help char
 	 is pressed.  Help characters are not recorded because menu prompting
 	 is not used on replay.
 	 */
@@ -4750,7 +4749,7 @@
   return first_binding;
 }
 
-/* Read a sequence of keys that ends with a non prefix character, 
+/* Read a sequence of keys that ends with a non prefix character,
    storing it in KEYBUF, a buffer of size BUFSIZE.
    Prompt with PROMPT.
    Return the length of the key sequence stored.
@@ -4909,13 +4908,13 @@
   /* 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 = (current_perdisplay ? echo_length () : 0);
+    echo_start = echo_length ();
   keys_start = this_command_key_count;
 
 #if defined (GOBBLE_FIRST_EVENT)
   /* This doesn't quite work, because some of the things that read_char
      does cannot safely be bypassed.  It seems too risky to try to make
-     this work right.  */ 
+     this work right.  */
 
   /* Read the first char of the sequence specially, before setting
      up any keymaps, in case a filter runs and switches buffers on us.  */
@@ -4939,7 +4938,7 @@
      keybuf with its symbol, or if the sequence starts with a mouse
      click and we need to switch buffers, we jump back here to rebuild
      the initial keymaps from the current buffer.  */
-  { 
+  {
     Lisp_Object *maps;
 
     if (!NILP (Voverriding_local_map))
@@ -4983,7 +4982,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 && current_perdisplay)
+  if (INTERACTIVE && t < mock_input)
     echo_truncate (echo_start);
 
   /* If the best binding for the current key sequence is a keymap, or
@@ -5026,7 +5025,7 @@
 	echo_local_start = echo_length ();
       keys_local_start = this_command_key_count;
       local_first_binding = first_binding;
-      
+
     replay_key:
       /* These are no-ops, unless we throw away a keystroke below and
 	 jumped back up to replay_key; in that case, these restore the
@@ -5057,11 +5056,26 @@
 	  {
 #ifdef MULTI_PERDISPLAY
 	    PERDISPLAY *interrupted_perdisplay = current_perdisplay;
+	    struct frame *interrupted_frame = selected_frame;
 	    if (setjmp (wrong_display_jmpbuf))
 	      {
 		while (t > 0)
 		  interrupted_perdisplay->kbd_queue
 		    = Fcons (keybuf[--t], interrupted_perdisplay->kbd_queue);
+		/* Ensure that the side queue begins with a switch-frame, so
+		   we'll be in the right context when we replay it later.  */
+		if (!(CONSP (interrupted_perdisplay->kbd_queue)
+		      && (key = XCONS (interrupted_perdisplay->kbd_queue)->car,
+			  EVENT_HAS_PARAMETERS (key))
+		      && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)),
+			     Qswitch_frame)))
+		  {
+		    Lisp_Object frame;
+		    XSETFRAME (frame, interrupted_frame);
+		    interrupted_perdisplay->kbd_queue
+		      = Fcons (make_lispy_switch_frame (frame),
+			       interrupted_perdisplay->kbd_queue);
+		  }
 		mock_input = 0;
 		orig_local_map = get_local_map (PT, current_buffer);
 		goto replay_sequence;
@@ -5087,7 +5101,7 @@
 	      dummyflag = 1;
 	      break;
 	    }
-	  
+
 	  /* If the current buffer has been changed from under us, the
 	     keymap may have changed, so replay the sequence.  */
 	  if (BUFFERP (key))
@@ -5112,7 +5126,7 @@
 	  Vquit_flag = Qnil;
 	}
 
-      /* Clicks in non-text areas get prefixed by the symbol 
+      /* 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'.
 
@@ -5464,7 +5478,7 @@
 		  UNGCPRO;
 		  /* If the function returned something invalid,
 		     barf--don't ignore it.
-		     (To ignore it safely, we would need to gcpro a bunch of 
+		     (To ignore it safely, we would need to gcpro a bunch of
 		     other variables.)  */
 		  if (! (VECTORP (fkey_next) || STRINGP (fkey_next)))
 		    error ("Function in function-key-map returns invalid key sequence");
@@ -5497,7 +5511,7 @@
 			XSETFASTINT (keybuf[fkey_start + i],
 				     XSTRING (fkey_next)->data[i]);
 		    }
-		  
+
 		  mock_input = t;
 		  fkey_start = fkey_end = t;
 		  fkey_map = Vfunction_key_map;
@@ -5508,10 +5522,10 @@
 
 		  goto replay_sequence;
 		}
-	      
+
 	      fkey_map = get_keymap_1 (fkey_next, 0, 1);
 
-	      /* If we no longer have a bound suffix, try a new positions for 
+	      /* If we no longer have a bound suffix, try a new positions for
 		 fkey_start.  */
 	      if (NILP (fkey_map))
 		{
@@ -5564,7 +5578,7 @@
 		UNGCPRO;
 		/* If the function returned something invalid,
 		   barf--don't ignore it.
-		   (To ignore it safely, we would need to gcpro a bunch of 
+		   (To ignore it safely, we would need to gcpro a bunch of
 		   other variables.)  */
 		if (! (VECTORP (keytran_next) || STRINGP (keytran_next)))
 		  error ("Function in key-translation-map returns invalid key sequence");
@@ -5612,7 +5626,7 @@
 
 	    keytran_map = get_keymap_1 (keytran_next, 0, 1);
 
-	    /* If we no longer have a bound suffix, try a new positions for 
+	    /* If we no longer have a bound suffix, try a new positions for
 	       keytran_start.  */
 	    if (NILP (keytran_map))
 	      {
@@ -6093,7 +6107,7 @@
   /* Run suspend-resume-hook.  */
   if (!NILP (Vrun_hooks))
     call1 (Vrun_hooks, intern ("suspend-resume-hook"));
-  
+
   UNGCPRO;
   return Qnil;
 }
@@ -6453,11 +6467,17 @@
   Vlast_event_frame = internal_last_event_frame;
 #endif
 
-#ifndef MULTI_PERDISPLAY
+  if (!initialized)
+    {
+#ifdef MULTI_PERDISPLAY
+      current_perdisplay = (PERDISPLAY *)xmalloc (sizeof (PERDISPLAY));
+      all_perdisplays = current_perdisplay;
+#endif
+      current_perdisplay->next_perdisplay = 0;
+    }
   if (initialized)
-    wipe_perdisplay (&the_only_perdisplay);
-  init_perdisplay (&the_only_perdisplay);
-#endif
+    wipe_perdisplay (current_perdisplay);
+  init_perdisplay (current_perdisplay);
 
   if (initialized)
     Ffillarray (kbd_buffer_frame_or_window, Qnil);
@@ -6505,7 +6525,7 @@
 #endif
 }
 
-/* This type's only use is in syms_of_keyboard, to initialize the 
+/* This type's only use is in syms_of_keyboard, to initialize the
    event header symbols and put properties on them.  */
 struct event_head {
   Lisp_Object *var;
@@ -6749,7 +6769,7 @@
 Polling is needed only when using X windows and SIGIO does not work.\n\
 Polling is automatically disabled in all other cases.");
   polling_period = 2;
-  
+
   DEFVAR_LISP ("double-click-time", &Vdouble_click_time,
     "*Maximum time between mouse clicks to make a double-click.\n\
 Measured in milliseconds.  nil means disable double-click recognition;\n\