changeset 83449:ff74a86c2b16

Overhaul and simplify single_kboard API. Allow calls to `recursive-edit' in process filters. Small fixes. * lisp/server.el (server-process-filter): Protect `display-splash-screen' call in a condition-case. Explain why. * src/callint.c (Fcall_interactively): Update call to `temporarily_switch_to_single_kboard'. * src/fns.c (Fy_or_n_p): Ditto. * src/frame.c (Fdelete_frame): Remove unused variable `count'. * src/keyboard.c (wrong_kboard_jmpbuf): Remove global variable. * src/keyboard.c (read_char): Add wrong_kboard_jmpbuf parameter to allow for recursive calls. Update longjmp invocations. Remember the original current_kboard, and longjmp to `wrong_kboard_jmpbuf' when a filter, timer or sentinel changes it. Comment out unnecessary calls to `record_single_kboard_state' and `any_kboard_state'. Update recursive calls. * src/keyboard.c (read_key_sequence): Add `wrong_kboard_jmpbuf' local variable. Update setjmp and read_char calls. Abort if interrupted_kboard died in read_char. * src/keyboard.c (any_kboard_state, single_kboard_state) (record_single_kboard_state): Comment out obsolete functions. (push_frame_kboard): Remove function. (pop_kboard): Switch out of single_kboard mode if the kboard has been deleted. (temporarily_switch_to_single_kboard): Change first parameter to a frame pointer. Throw an error when caller wants to change kboards while in single_kboard mode. (restore_kboard_configuration): Abort if pop_kboard changed the kboard in single_kboard mode. (Frecursive_edit): Switch to single_kboard mode only in nested command loops. (cmd_error, command_loop, command_loop_1, timer_check): Comment out unnecessary call to `any_kboard_state' and `record_single_kboard_state'. * src/keyboard.c (delete_kboard): Exit single_kboard mode if we have just deleted that kboard. * src/keyboard.c (interrupt_signal): Use `Fkill_emacs' to exit Emacs, not `fatal_error_signal'. * src/keyboard.h (read_char, single_kboard_state) (record_single_kboard_state): Remove. (temporarily_switch_to_single_kboard): Update. * src/lread.c: Include setjmp.h. Update declaration of `read_char'. (read_filtered_event): Call `read_char' with a local `wrong_kboard_jmpbuf'. * src/minibuf.c (read_minibuf): Update call to `temporarily_switch_to_single_kboard'. * src/termchar.h (tty_display_info): Rename `previous_terminal_frame' member to `previous_frame'. * src/xdisp.c (redisplay_internal): Update references to `previous_terminal_frame'. (display_mode_line, Fformat_mode_line): Replace calls to `push_frame_kboard' with `push_kboard'. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-489
author Karoly Lorentey <lorentey@elte.hu>
date Tue, 03 Jan 2006 01:50:46 +0000
parents d2af586aefe4
children c69d44922688
files README.multi-tty lisp/server.el src/callint.c src/fns.c src/frame.c src/keyboard.c src/keyboard.h src/lread.c src/minibuf.c src/termchar.h src/xdisp.c
diffstat 11 files changed, 170 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Tue Jan 03 01:22:02 2006 +0000
+++ b/README.multi-tty	Tue Jan 03 01:50:46 2006 +0000
@@ -401,12 +401,6 @@
 THINGS TO DO
 ------------
 
-** Let-binding `overriding-terminal-local-map' on a brand new frame
-   does not seem to work correctly.  (See `fancy-splash-screens'.)
-   The keymap seems to be set up right, but events go to another
-   terminal.  Or is it `unread-command-events' that gets Emacs
-   confused?  Investigate.
-
 ** `delete-frame' events are handled by `special-event-map'
    immediately when read by `read_char'.  This is fine but it prevents
    higher-level keymaps from binding that event to get notified of the
@@ -466,6 +460,10 @@
    Emacs with GTK support.  If you want to play around with GTK
    multidisplay (and don't mind core dumps), you can edit src/config.h
    and define HAVE_GTK_MULTIDISPLAY there by hand.
+   
+   Update: Han reports that GTK+ version 2.8.9 almost gets display
+   disconnects right.  GTK will probably be fully fixed by the time
+   multi-tty gets into the trunk.
 
 ** Audit `face-valid-attribute-values' usage in customize and
    elsewhere.  Its return value depends on the current window system.
@@ -477,10 +475,6 @@
 
 ** frames-on-display-list should also accept frames.
 
-** I smell something funny around pop_kboard's "deleted kboard" case.
-   Determine what are the circumstances of this case, and fix any
-   bug that comes to light.
-
 ** Consider the `tty-type' frame parameter and the `display-tty-type'
    function.  They serve the exact same purpose.  I think it may be
    a good idea to eliminate one of them, preferably `tty-type'.
@@ -514,10 +508,6 @@
    instead of delete-frame-functions),
    after-delete-terminal-functions, after-create-terminal-functions.
 
-** Fix set-input-mode for multi-tty.  It's a truly horrible interface;
-   what if we'd blow it up into several separate functions (with a
-   compatibility definition)?
-
 ** BULK RENAME: The `display-' prefix of new Lisp-level functions
    conflicts with stuff like `display-time-mode'.  Use `device-'
    or `terminal-' instead.  I think I prefer `terminal-'.
@@ -583,6 +573,8 @@
    by changing the modelines or some other frame-local display element
    on the locked out displays.
 
+   Update: In fact struct kboard does have an echo_string slot.
+
 ** The session management module is prone to crashes when the X
    connection is closed and then later I try to connect to a new X
    session:
@@ -670,6 +662,9 @@
    terminals in xterm and konsole.  The screen does flicker a bit,
    but it's so quick it isn't noticable.
 
+   (Update: This is probably some problem with padding or whatnot on
+   the secondary terminals.)
+
 ** Move baud_rate to struct display.
 
 ** Implement support for starting an interactive Emacs session without
@@ -1414,6 +1409,32 @@
    against `delete-frame-functions' throwing an error and preventing a
    frame delete. (patch-475)
 
+-- Fix set-input-mode for multi-tty.  It's a truly horrible interface;
+   what if we'd blow it up into several separate functions (with a
+   compatibility definition)?
+
+   (Done.  See `set-input-interrupt-mode', `set-output-flow-control',
+   `set-input-meta-mode' and `set-quit-char'.) (patch-457)
+
+-- Let-binding `overriding-terminal-local-map' on a brand new frame
+   does not seem to work correctly.  (See `fancy-splash-screens'.)
+   The keymap seems to be set up right, but events go to another
+   terminal.  Or is it `unread-command-events' that gets Emacs
+   confused?  Investigate.
+
+   (Emacs was confused because a process filter entered
+   `recursive-edit' while Emacs was reading input.  I added support
+   for this in the input system.) (patch-489)
+
+-- I smell something funny around pop_kboard's "deleted kboard" case.
+   Determine what are the circumstances of this case, and fix any
+   bug that comes to light.
+
+   (It happens simply because single_kboard's terminal is sometimes
+   deleted while executing a command on it, for example the one that
+   kills the terminal.  There was no bug here, but I rewrote the whole
+   single_kboard mess anyway.) (patch-489)
+
 
 ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
 
--- a/lisp/server.el	Tue Jan 03 01:22:02 2006 +0000
+++ b/lisp/server.el	Tue Jan 03 01:50:46 2006 +0000
@@ -755,9 +755,17 @@
 		(with-selected-frame frame
 		  (switch-to-buffer (or (car buffers)
 					(get-buffer-create "*scratch*")))
-		  (display-startup-echo-area-message))
+		  (display-startup-echo-area-message)
 		  (unless inhibit-splash-screen
-		    (display-splash-screen)))
+		    (condition-case err
+			;; This looks scary because `fancy-splash-screens'
+			;; will call `recursive-edit' from a process filter.
+			;; However, that should be safe to do now.
+			(display-splash-screen)
+		      ;; `recursive-edit' will throw an error if Emacs is
+		      ;; already doing a recursive edit elsewhere.  Catch it
+		      ;; here so that we can finish normally.
+		      (error nil)))))
 
 	      ;; Delete the client if necessary.
 	      (cond
--- a/src/callint.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/callint.c	Tue Jan 03 01:50:46 2006 +0000
@@ -875,12 +875,11 @@
   real_this_command= save_real_this_command;
   current_kboard->Vlast_command = save_last_command;
 
-  temporarily_switch_to_single_kboard (NULL);
-
   {
     Lisp_Object val;
     specbind (Qcommand_debug_status, Qnil);
 
+    temporarily_switch_to_single_kboard (NULL);
     val = Ffuncall (count + 1, args);
     UNGCPRO;
     return unbind_to (speccount, val);
--- a/src/fns.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/fns.c	Tue Jan 03 01:50:46 2006 +0000
@@ -3308,7 +3308,7 @@
 	  Fraise_frame (mini_frame);
 	}
 
-      temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ()));
+      temporarily_switch_to_single_kboard (SELECTED_FRAME ());
       obj = read_filtered_event (1, 0, 0, 0);
 
       cursor_in_echo_area = 0;
--- a/src/frame.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/frame.c	Tue Jan 03 01:50:46 2006 +0000
@@ -1406,7 +1406,6 @@
   if (!NILP (Vrun_hooks)
       && NILP (Fframe_parameter (frame, intern ("tooltip"))))
     {
-      int count = SPECPDL_INDEX ();
       Lisp_Object args[2];
       struct gcpro gcpro1, gcpro2;
 
--- a/src/keyboard.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/keyboard.c	Tue Jan 03 01:50:46 2006 +0000
@@ -670,7 +670,6 @@
 static void restore_getcjmp P_ ((jmp_buf));
 static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
 static void clear_event P_ ((struct input_event *));
-static void any_kboard_state P_ ((void));
 static Lisp_Object restore_kboard_configuration P_ ((Lisp_Object));
 static SIGTYPE interrupt_signal P_ ((int signalnum));
 static void handle_interrupt P_ ((void));
@@ -1034,7 +1033,8 @@
      like it is done in the splash screen display, we have to
      make sure that we restore single_kboard as command_loop_1
      would have done if it were left normally.  */
-  temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ()));
+  if (command_loop_level > 0)
+    temporarily_switch_to_single_kboard (SELECTED_FRAME ());
   record_unwind_protect (recursive_edit_unwind, buffer);
 
   recursive_edit_1 ();
@@ -1054,6 +1054,8 @@
 }
 
 
+#if 0  /* These two functions are now replaced with
+          temporarily_switch_to_single_kboard. */
 static void
 any_kboard_state ()
 {
@@ -1084,6 +1086,7 @@
   single_kboard = 1;
 #endif
 }
+#endif
 
 /* If we're in single_kboard state for kboard KBOARD,
    get out of it.  */
@@ -1127,13 +1130,6 @@
 }
 
 void
-push_frame_kboard (f)
-     FRAME_PTR f;
-{
-  push_kboard (f->terminal->kboard);
-}
-
-void
 pop_kboard ()
 {
 #ifdef MULTI_KBOARD
@@ -1153,37 +1149,55 @@
     {
       /* The terminal we remembered has been deleted.  */
       current_kboard = FRAME_KBOARD (SELECTED_FRAME ());
+      single_kboard = 0;
     }
   kboard_stack = p->next;
   xfree (p);
 #endif
 }
 
-/* Switch to single_kboard mode.  If K is non-nil, set it as the
-  current keyboard.  Use record_unwind_protect to return to the
-  previous state later.  */
+/* Switch to single_kboard mode, making current_kboard the only KBOARD
+  from which further input is accepted.  If F is non-nil, set its
+  KBOARD as the current keyboard.
+
+  This function uses record_unwind_protect to return to the previous
+  state later.
+
+  If Emacs is already in single_kboard mode, and F's keyboard is
+  locked, then this function will throw an errow.  */
 
 void
-temporarily_switch_to_single_kboard (k)
-     struct kboard *k;
+temporarily_switch_to_single_kboard (f)
+     struct frame *f;
 {
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
   if (was_locked)
     {
-      if (k != NULL)
-        push_kboard (k);
+      if (f != NULL && FRAME_KBOARD (f) != current_kboard)
+        /* We can not switch keyboards while in single_kboard mode.
+           This can legally happen when Lisp code calls
+           `recursive-edit' (or `read-minibuffer' or `y-or-n-p') after
+           it switched to a locked frame.  This kind of situation is
+           likely to happen when server.el connects to a new
+           terminal.  */
+        error ("Terminal %d is locked, cannot read from it",
+               FRAME_TERMINAL (f)->id);
       else
+        /* This call is unnecessary, but helps
+           `restore_kboard_configuration' discover if somebody changed
+           `current_kboard' behind our back.  */
         push_kboard (current_kboard);
     }
-  else if (k != NULL)
-    current_kboard = k;
-  single_kboard_state ();
+  else if (f != NULL)
+    current_kboard = FRAME_KBOARD (f);
+  single_kboard = 1;
   record_unwind_protect (restore_kboard_configuration,
                          (was_locked ? Qt : Qnil));
 #endif
 }
 
+#if 0 /* This function is not needed anymore.  */
 void
 record_single_kboard_state ()
 {
@@ -1192,17 +1206,22 @@
   record_unwind_protect (restore_kboard_configuration,
                          (single_kboard ? Qt : Qnil));
 }
+#endif
 
 static Lisp_Object
 restore_kboard_configuration (was_locked)
      Lisp_Object was_locked;
 {
   if (NILP (was_locked))
-    any_kboard_state ();
+    single_kboard = 0;
   else
     {
-      single_kboard_state ();
+      struct kboard *prev = current_kboard;
+      single_kboard = 1;
       pop_kboard ();
+      /* The pop should not change the kboard.  */
+      if (single_kboard && current_kboard != prev)
+        abort ();
     }
   return Qnil;
 }
@@ -1253,10 +1272,12 @@
   Vquit_flag = Qnil;
 
   Vinhibit_quit = Qnil;
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
 #ifdef MULTI_KBOARD
   if (command_loop_level == 0 && minibuf_level == 0)
     any_kboard_state ();
 #endif
+#endif
 
   return make_number (0);
 }
@@ -1340,10 +1361,12 @@
     while (1)
       {
 	internal_catch (Qtop_level, top_level_1, Qnil);
+#if 0 /* This shouldn't be necessary anymore.  --lorentey  */
         /* Reset single_kboard in case top-level set it while
            evaluating an -f option, or we are stuck there for some
            other reason. */
         any_kboard_state ();
+#endif
 	internal_catch (Qtop_level, command_loop_2, Qnil);
 	executing_kbd_macro = Qnil;
 
@@ -1460,9 +1483,11 @@
   int no_direct;
   int prev_modiff = 0;
   struct buffer *prev_buffer = NULL;
+#if 0 /* This shouldn't be necessary anymore.  --lorentey  */
 #ifdef MULTI_KBOARD
   int was_locked = single_kboard;
 #endif
+#endif  
   int already_adjusted = 0;
 
   current_kboard->Vprefix_arg = Qnil;
@@ -1919,10 +1944,11 @@
       if (!NILP (current_kboard->defining_kbd_macro)
 	  && NILP (current_kboard->Vprefix_arg))
 	finalize_kbd_macro_chars ();
-
+#if 0 /* This shouldn't be necessary anymore.  --lorentey  */
 #ifdef MULTI_KBOARD
       if (!was_locked)
-	any_kboard_state ();
+        any_kboard_state ();
+#endif
 #endif
     }
 }
@@ -2405,10 +2431,6 @@
 static Lisp_Object kbd_buffer_get_event ();
 static void record_char ();
 
-#ifdef MULTI_KBOARD
-static jmp_buf wrong_kboard_jmpbuf;
-#endif
-
 #define STOP_POLLING					\
 do { if (! polling_stopped_here) stop_polling ();	\
        polling_stopped_here = 1; } while (0)
@@ -2435,15 +2457,19 @@
    if we used a mouse menu to read the input, or zero otherwise.  If
    USED_MOUSE_MENU is null, we don't dereference it.
 
+   WRONG_KBOARD_JMPBUF should be a stack context to longjmp to in case
+   we find input on another keyboard.
+   
    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)
+read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, wrong_kboard_jmpbuf)
      int commandflag;
      int nmaps;
      Lisp_Object *maps;
      Lisp_Object prev_event;
      int *used_mouse_menu;
+     jmp_buf *wrong_kboard_jmpbuf;
 {
   volatile Lisp_Object c;
   int count;
@@ -2456,6 +2482,7 @@
   volatile int reread;
   struct gcpro gcpro1, gcpro2;
   int polling_stopped_here = 0;
+  struct kboard *orig_kboard = current_kboard;
 
   also_record = Qnil;
 
@@ -2711,7 +2738,9 @@
 	    /* This is going to exit from read_char
 	       so we had better get rid of this frame's stuff.  */
 	    UNGCPRO;
-	    longjmp (wrong_kboard_jmpbuf, 1);
+            if (wrong_kboard_jmpbuf == NULL)
+              abort ();
+	    longjmp (*wrong_kboard_jmpbuf, 1);
 	  }
       }
 #endif
@@ -2845,6 +2874,20 @@
 	}
     }
 
+  /* Notify the caller if a timer or sentinel or filter in the sit_for
+     calls above have changed the current kboard.  This could happen
+     if they start a recursive edit, like the fancy splash screen in
+     server.el's filter.  If this longjmp wasn't here,
+     read_key_sequence would interpret the next key sequence using the
+     wrong translation tables and function keymaps.  */
+  if (NILP (c) && current_kboard != orig_kboard)
+    {
+      UNGCPRO;
+      if (wrong_kboard_jmpbuf == NULL)
+        abort ();
+      longjmp (*wrong_kboard_jmpbuf, 1);
+    }
+
   /* If this has become non-nil here, it has been set by a timer
      or sentinel or filter.  */
   if (CONSP (Vunread_command_events))
@@ -2893,7 +2936,9 @@
 	    /* This is going to exit from read_char
 	       so we had better get rid of this frame's stuff.  */
 	    UNGCPRO;
-	    longjmp (wrong_kboard_jmpbuf, 1);
+            if (wrong_kboard_jmpbuf == NULL)
+              abort ();
+	    longjmp (*wrong_kboard_jmpbuf, 1);
 	  }
     }
 #endif
@@ -2940,7 +2985,9 @@
 	  /* This is going to exit from read_char
 	     so we had better get rid of this frame's stuff.  */
 	  UNGCPRO;
-	  longjmp (wrong_kboard_jmpbuf, 1);
+          if (wrong_kboard_jmpbuf == NULL)
+            abort ();
+	  longjmp (*wrong_kboard_jmpbuf, 1);
 	}
 #endif
     }
@@ -2994,8 +3041,12 @@
 
   if (!NILP (tem))
     {
+#if 0 /* This shouldn't be necessary anymore. --lorentey  */
       int was_locked = single_kboard;
-
+      int count = SPECPDL_INDEX ();
+      record_single_kboard_state ();
+#endif
+      
       last_input_char = c;
       Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
 
@@ -3006,9 +3057,12 @@
 	   example banishing the mouse under mouse-avoidance-mode.  */
 	timer_resume_idle ();
 
+#if 0 /* This shouldn't be necessary anymore. --lorentey  */
       /* Resume allowing input from any kboard, if that was true before.  */
       if (!was_locked)
 	any_kboard_state ();
+      unbind_to (count, Qnil);
+#endif
 
       goto retry;
     }
@@ -3251,7 +3305,7 @@
 
       cancel_echoing ();
       do
-	c = read_char (0, 0, 0, Qnil, 0);
+	c = read_char (0, 0, 0, Qnil, 0, &wrong_kboard_jmpbuf);
       while (BUFFERP (c));
       /* Remove the help from the frame */
       unbind_to (count, Qnil);
@@ -3261,7 +3315,7 @@
 	{
 	  cancel_echoing ();
 	  do
-	    c = read_char (0, 0, 0, Qnil, 0);
+	    c = read_char (0, 0, 0, Qnil, 0, &wrong_kboard_jmpbuf);
 	  while (BUFFERP (c));
 	}
     }
@@ -4522,10 +4576,11 @@
 	      int count = SPECPDL_INDEX ();
 	      Lisp_Object old_deactivate_mark = Vdeactivate_mark;
 
+#if 0 /* This shouldn't be necessary anymore.  --lorentey  */
 	      /* On unbind_to, resume allowing input from any kboard, if that
                  was true before.  */
               record_single_kboard_state ();
-
+#endif
 	      /* Mark the timer as triggered to prevent problems if the lisp
 		 code fails to reschedule it right.  */
 	      vector[0] = Qt;
@@ -8739,6 +8794,8 @@
   int junk;
 #endif
 
+  jmp_buf *volatile wrong_kboard_jmpbuf = alloca (sizeof (jmp_buf));
+
   struct gcpro gcpro1;
 
   GCPRO1 (fake_prefixed_keys);
@@ -8775,7 +8832,7 @@
   /* Read the first char of the sequence specially, before setting
      up any keymaps, in case a filter runs and switches buffers on us.  */
   first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
-			   &junk);
+			   &junk, NULL);
 #endif /* GOBBLE_FIRST_EVENT */
 
   orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
@@ -8951,8 +9008,17 @@
 #ifdef MULTI_KBOARD
 	    KBOARD *interrupted_kboard = current_kboard;
 	    struct frame *interrupted_frame = SELECTED_FRAME ();
-	    if (setjmp (wrong_kboard_jmpbuf))
+	    if (setjmp (*wrong_kboard_jmpbuf))
 	      {
+                int found = 0;
+                struct kboard *k;
+
+                for (k = all_kboards; k; k = k->next_kboard)
+                  if (k == interrupted_kboard)
+                    found = 1;
+                if (!found)
+                  abort ();
+
 		if (!NILP (delayed_switch_frame))
 		  {
 		    interrupted_kboard->kbd_queue
@@ -8986,7 +9052,7 @@
 #endif
 	    key = read_char (NILP (prompt), nmaps,
 			     (Lisp_Object *) submaps, last_nonmenu_event,
-			     &used_mouse_menu);
+			     &used_mouse_menu, wrong_kboard_jmpbuf);
 	  }
 
 	  /* read_char returns t when it shows a menu and the user rejects it.
@@ -10466,7 +10532,7 @@
     {
       /* If there are no frames there, let's pretend that we are a
          well-behaving UN*X program and quit. */
-      fatal_error_signal (SIGTERM);
+      Fkill_emacs (Qnil);
     }
   else
     {
@@ -11034,7 +11100,8 @@
       && FRAMEP (selected_frame)
       && FRAME_LIVE_P (XFRAME (selected_frame)))
     {
-      current_kboard = XFRAME (selected_frame)->terminal->kboard;
+      current_kboard = FRAME_KBOARD (XFRAME (selected_frame));
+      single_kboard = 0;
       if (current_kboard == kb)
 	abort ();
     }
--- a/src/keyboard.h	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/keyboard.h	Tue Jan 03 01:50:46 2006 +0000
@@ -305,7 +305,6 @@
 
 extern Lisp_Object parse_modifiers P_ ((Lisp_Object));
 extern Lisp_Object reorder_modifiers P_ ((Lisp_Object));
-extern Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, int *));
 
 /* Parent keymap of terminal-local function-key-map instances.  */
 extern Lisp_Object Vfunction_key_map;
@@ -318,13 +317,11 @@
 extern void echo_now P_ ((void));
 extern void init_kboard P_ ((KBOARD *));
 extern void delete_kboard P_ ((KBOARD *));
-extern void single_kboard_state P_ ((void));
 extern void not_single_kboard_state P_ ((KBOARD *));
 extern void push_kboard P_ ((struct kboard *));
 extern void push_frame_kboard P_ ((struct frame *));
 extern void pop_kboard P_ ((void));
-extern void temporarily_switch_to_single_kboard P_ ((struct kboard *));
-extern void record_single_kboard_state P_ ((void));
+extern void temporarily_switch_to_single_kboard P_ ((struct frame *));
 extern void record_asynch_buffer_change P_ ((void));
 extern SIGTYPE input_poll_signal P_ ((int));
 extern void start_polling P_ ((void));
--- a/src/lread.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/lread.c	Tue Jan 03 01:50:46 2006 +0000
@@ -27,6 +27,7 @@
 #include <sys/stat.h>
 #include <sys/file.h>
 #include <errno.h>
+#include <setjmp.h>
 #include "lisp.h"
 #include "intervals.h"
 #include "buffer.h"
@@ -434,7 +435,7 @@
 
 /* Get a character from the tty.  */
 
-extern Lisp_Object read_char ();
+extern Lisp_Object read_char P_ ((int, int, Lisp_Object *, Lisp_Object, int *, jmp_buf *));
 
 /* Read input events until we get one that's acceptable for our purposes.
 
@@ -459,7 +460,8 @@
 		     input_method)
      int no_switch_frame, ascii_required, error_nonascii, input_method;
 {
-  register Lisp_Object val, delayed_switch_frame;
+  volatile register Lisp_Object val, delayed_switch_frame;
+  jmp_buf *volatile wrong_kboard_jmpbuf = alloca (sizeof (jmp_buf));
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (display_hourglass_p)
@@ -470,10 +472,12 @@
 
   /* Read until we get an acceptable event.  */
  retry:
+  setjmp (*wrong_kboard_jmpbuf);
+
   val = read_char (0, 0, 0,
 		   (input_method ? Qnil : Qt),
-		   0);
-
+		   0, wrong_kboard_jmpbuf);
+ 
   if (BUFFERP (val))
     goto retry;
 
--- a/src/minibuf.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/minibuf.c	Tue Jan 03 01:50:46 2006 +0000
@@ -552,7 +552,7 @@
   if (minibuffer_auto_raise)
     Fraise_frame (mini_frame);
 
-  temporarily_switch_to_single_kboard (XFRAME (mini_frame)->terminal->kboard);
+  temporarily_switch_to_single_kboard (XFRAME (mini_frame));
 
   /* We have to do this after saving the window configuration
      since that is what restores the current buffer.  */
--- a/src/termchar.h	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/termchar.h	Tue Jan 03 01:50:46 2006 +0000
@@ -68,8 +68,8 @@
 
   Lisp_Object top_frame;        /* The topmost frame on this tty. */
   
-  /* The previous terminal frame we displayed on this tty.  */
-  struct frame *previous_terminal_frame;
+  /* The previous frame we displayed on this tty.  */
+  struct frame *previous_frame;
 
   /* Strings, numbers and flags taken from the termcap entry.  */
 
--- a/src/xdisp.c	Tue Jan 03 01:22:02 2006 +0000
+++ b/src/xdisp.c	Tue Jan 03 01:50:46 2006 +0000
@@ -10549,14 +10549,14 @@
     ++windows_or_buffers_changed;
 
   if (FRAME_TERMCAP_P (sf)
-      && FRAME_TTY (sf)->previous_terminal_frame != sf)
+      && FRAME_TTY (sf)->previous_frame != sf)
     {
       /* Since frames on a single ASCII terminal share the same
 	 display area, displaying a different frame means redisplay
 	 the whole thing.  */
       windows_or_buffers_changed++;
       SET_FRAME_GARBAGED (sf);
-      FRAME_TTY (sf)->previous_terminal_frame = sf;
+      FRAME_TTY (sf)->previous_frame = sf;
     }
 
   /* Set the visible flags for all frames.  Do this before checking
@@ -16194,7 +16194,7 @@
   /* Temporarily make frame's keyboard the current kboard so that
      kboard-local variables in the mode_line_format will get the right
      values.  */
-  push_frame_kboard (it.f);
+  push_kboard (FRAME_KBOARD (it.f));
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
   pop_kboard ();
 
@@ -16908,7 +16908,7 @@
 	= (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
     }
 
-  push_frame_kboard (it.f);
+  push_kboard (FRAME_KBOARD (it.f));
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
   pop_kboard ();