* xterm.c (handle_one_xevent): Use event.xunmap and not event.xmap when
[bpt/emacs.git] / src / frame.c
index a1f151a..5ee421b 100644 (file)
@@ -692,22 +692,14 @@ affects all frames on the same terminal device.  */)
                        ? FRAME_TTY (XFRAME (selected_frame))->name
                        : NULL));
       if (!NILP (tty))
-        {
-          name = alloca (SBYTES (tty) + 1);
-          memcpy (name, SSDATA (tty), SBYTES (tty));
-          name[SBYTES (tty)] = 0;
-        }
+       name = xlispstrdupa (tty);
 
       tty_type = get_future_frame_param
         (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                             ? FRAME_TTY (XFRAME (selected_frame))->type
                             : NULL));
       if (!NILP (tty_type))
-        {
-          type = alloca (SBYTES (tty_type) + 1);
-          memcpy (type, SSDATA (tty_type), SBYTES (tty_type));
-          type[SBYTES (tty_type)] = 0;
-        }
+       type = xlispstrdupa (tty_type);
 
       t = init_tty (name, type, 0); /* Errors are not fatal.  */
     }
@@ -1118,6 +1110,51 @@ other_visible_frames (struct frame *f)
   return 0;
 }
 
+/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
+   window.  Preferably use the selected frame's minibuffer window
+   instead.  If the selected frame doesn't have one, get some other
+   frame's minibuffer window.  SELECT non-zero means select the new
+   minibuffer window.  */
+static void
+check_minibuf_window (Lisp_Object frame, int select)
+{
+  struct frame *f = decode_live_frame (frame);
+
+  if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
+    {
+      Lisp_Object frames, this, window = make_number (0);
+
+      if (!EQ (frame, selected_frame)
+         && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
+       window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
+      else
+       FOR_EACH_FRAME (frames, this)
+         {
+           if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
+             {
+               window = FRAME_MINIBUF_WINDOW (XFRAME (this));
+               break;
+             }
+         }
+
+      if (!WINDOWP (window))
+       emacs_abort ();
+      else
+       {
+         /* Use set_window_buffer instead of Fset_window_buffer (see
+            discussion of bug#11984, bug#12025, bug#12026).  */
+         set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
+         minibuf_window = window;
+
+         /* SELECT non-zero usually means that FRAME's minibuffer
+            window was selected; select the new one.  */
+         if (select)
+           Fselect_window (minibuf_window, Qnil);
+       }
+    }
+}
+
+
 /* Delete FRAME.  When FORCE equals Qnoelisp, delete FRAME
   unconditionally.  x_connection_closed and delete_terminal use
   this.  Any other value of FORCE implements the semantics
@@ -1205,10 +1242,18 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
   /* Don't let the frame remain selected.  */
   if (f == sf)
     {
-      Lisp_Object tail, frame1;
-
-      /* Look for another visible frame on the same terminal.  */
-      frame1 = next_frame (frame, Qvisible);
+      Lisp_Object tail;
+      Lisp_Object frame1 = Qnil;
+
+      /* Look for another visible frame on the same terminal.
+        Do not call next_frame here because it may loop forever.
+        See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025.  */
+      FOR_EACH_FRAME (tail, frame1)
+       if (!EQ (frame, frame1)
+           && (FRAME_TERMINAL (XFRAME (frame))
+               == FRAME_TERMINAL (XFRAME (frame1)))
+           && FRAME_VISIBLE_P (XFRAME (frame1)))
+         break;
 
       /* If there is none, find *some* other frame.  */
       if (NILP (frame1) || EQ (frame1, frame))
@@ -1244,19 +1289,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
     }
 
   /* Don't allow minibuf_window to remain on a deleted frame.  */
-  if (EQ (f->minibuffer_window, minibuf_window))
-    {
-      /* Use set_window_buffer instead of Fset_window_buffer (see
-        discussion of bug#11984, bug#12025, bug#12026).  */
-      set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->contents, 0, 0);
-      minibuf_window = sf->minibuffer_window;
-
-      /* If the dying minibuffer window was selected,
-        select the new one.  */
-      if (minibuffer_selected)
-       Fselect_window (minibuf_window, Qnil);
-    }
+  check_minibuf_window (frame, minibuffer_selected);
 
   /* Don't let echo_area_window to remain on a deleted frame.  */
   if (EQ (f->minibuffer_window, echo_area_window))
@@ -1683,16 +1716,8 @@ displayed in the terminal.  */)
   if (NILP (force) && !other_visible_frames (f))
     error ("Attempt to make invisible the sole visible or iconified frame");
 
-  /* Don't allow minibuf_window to remain on a deleted frame.  */
-  if (EQ (f->minibuffer_window, minibuf_window))
-    {
-      struct frame *sf = XFRAME (selected_frame);
-      /* Use set_window_buffer instead of Fset_window_buffer (see
-        discussion of bug#11984, bug#12025, bug#12026).  */
-      set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->contents, 0, 0);
-      minibuf_window = sf->minibuffer_window;
-    }
+  /* Don't allow minibuf_window to remain on an invisible frame.  */
+  check_minibuf_window (frame, EQ (minibuf_window, selected_window));
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1715,15 +1740,7 @@ If omitted, FRAME defaults to the currently selected frame.  */)
   struct frame *f = decode_live_frame (frame);
 
   /* Don't allow minibuf_window to remain on an iconified frame.  */
-  if (EQ (f->minibuffer_window, minibuf_window))
-    {
-      struct frame *sf = XFRAME (selected_frame);
-      /* Use set_window_buffer instead of Fset_window_buffer (see
-        discussion of bug#11984, bug#12025, bug#12026).  */
-      set_window_buffer (sf->minibuffer_window,
-                        XWINDOW (minibuf_window)->contents, 0, 0);
-      minibuf_window = sf->minibuffer_window;
-    }
+  check_minibuf_window (frame, EQ (minibuf_window, selected_window));
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM