Preserve tty top-frames under various window-changing operations.
[bpt/emacs.git] / src / frame.c
index 8505398..fc52b07 100644 (file)
@@ -331,7 +331,7 @@ make_frame (int mini_p)
       mini_window = make_window ();
       XWINDOW (root_window)->next = mini_window;
       XWINDOW (mini_window)->prev = root_window;
-      XWINDOW (mini_window)->mini_p = Qt;
+      XWINDOW (mini_window)->mini = 1;
       XWINDOW (mini_window)->frame = frame;
       f->minibuffer_window = mini_window;
     }
@@ -480,7 +480,7 @@ make_minibuffer_frame (void)
      as nil. */
 
   mini_window = f->minibuffer_window = f->root_window;
-  XWINDOW (mini_window)->mini_p = Qt;
+  XWINDOW (mini_window)->mini = 1;
   XWINDOW (mini_window)->next = Qnil;
   XWINDOW (mini_window)->prev = Qnil;
   XWINDOW (mini_window)->frame = frame;
@@ -630,8 +630,8 @@ DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
        doc: /* Create an additional terminal frame, possibly on another terminal.
 This function takes one argument, an alist specifying frame parameters.
 
-You can create multiple frames on a single text-only terminal, but
-only one of them (the selected terminal frame) is actually displayed.
+You can create multiple frames on a single text terminal, but only one
+of them (the selected terminal frame) is actually displayed.
 
 In practice, generally you don't need to specify any parameters,
 except when you want to create a new frame on another terminal.
@@ -865,8 +865,8 @@ something to select a different frame, or until the next time
 this function is called.  If you are using a window system, the
 previously selected frame may be restored as the selected frame
 when returning to the command loop, because it still may have
-the window system's input focus.  On a text-only terminal, the
-next redisplay will display FRAME.
+the window system's input focus.  On a text terminal, the next
+redisplay will display FRAME.
 
 This function returns FRAME, or nil if FRAME has been deleted.  */)
   (Lisp_Object frame, Lisp_Object norecord)
@@ -1118,41 +1118,32 @@ Otherwise, include all frames.  */)
 static int
 other_visible_frames (FRAME_PTR f)
 {
-  /* We know the selected frame is visible,
-     so if F is some other frame, it can't be the sole visible one.  */
-  if (f == SELECTED_FRAME ())
-    {
-      Lisp_Object frames;
-      int count = 0;
+  Lisp_Object frames;
 
-      for (frames = Vframe_list;
-          CONSP (frames);
-          frames = XCDR (frames))
-       {
-         Lisp_Object this;
+  for (frames = Vframe_list; CONSP (frames); frames = XCDR (frames))
+    {
+      Lisp_Object this = XCAR (frames);
+      if (f == XFRAME (this))
+       continue;
 
-         this = XCAR (frames);
-         /* Verify that the frame's window still exists
-            and we can still talk to it.  And note any recent change
-            in visibility.  */
+      /* Verify that we can still talk to the frame's X window,
+        and note any recent change in visibility.  */
 #ifdef HAVE_WINDOW_SYSTEM
-         if (FRAME_WINDOW_P (XFRAME (this)))
-           {
-             x_sync (XFRAME (this));
-             FRAME_SAMPLE_VISIBILITY (XFRAME (this));
-           }
+      if (FRAME_WINDOW_P (XFRAME (this)))
+       {
+         x_sync (XFRAME (this));
+         FRAME_SAMPLE_VISIBILITY (XFRAME (this));
+       }
 #endif
 
-         if (FRAME_VISIBLE_P (XFRAME (this))
-             || FRAME_ICONIFIED_P (XFRAME (this))
-             /* Allow deleting the terminal frame when at least
-                one X frame exists!  */
-             || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
-           count++;
-       }
-      return count > 1;
+      if (FRAME_VISIBLE_P (XFRAME (this))
+         || FRAME_ICONIFIED_P (XFRAME (this))
+         /* Allow deleting the terminal frame when at least one X
+            frame exists.  */
+         || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
+       return 1;
     }
-  return 1;
+  return 0;
 }
 
 /* Delete FRAME.  When FORCE equals Qnoelisp, delete FRAME
@@ -1161,10 +1152,6 @@ other_visible_frames (FRAME_PTR f)
   described for Fdelete_frame.  */
 Lisp_Object
 delete_frame (Lisp_Object frame, Lisp_Object force)
-     /* If we use `register' here, gcc-4.0.2 on amd64 using
-       -DUSE_LISP_UNION_TYPE complains further down that we're getting the
-       address of `force'.  Go figure.  */
-
 {
   struct frame *f;
   struct frame *sf = SELECTED_FRAME ();
@@ -1267,7 +1254,17 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
          FOR_EACH_FRAME (tail, frame1)
            {
              if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
-               break;
+               {
+                 /* Do not change a text terminal's top-frame.  */
+                 struct frame *f1 = XFRAME (frame1);
+                 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
+                   {
+                     Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
+                     if (!EQ (top_frame, frame))
+                       frame1 = top_frame;
+                   }
+                 break;
+               }
            }
        }
 #ifdef NS_IMPL_COCOA
@@ -1612,8 +1609,8 @@ before calling this function on it, like this.
   (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
 {
   CHECK_LIVE_FRAME (frame);
-  CHECK_NUMBER (x);
-  CHECK_NUMBER (y);
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1653,8 +1650,8 @@ before calling this function on it, like this.
   (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
 {
   CHECK_LIVE_FRAME (frame);
-  CHECK_NUMBER (x);
-  CHECK_NUMBER (y);
+  CHECK_TYPE_RANGED_INTEGER (int, x);
+  CHECK_TYPE_RANGED_INTEGER (int, y);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
@@ -1743,8 +1740,8 @@ usually not displayed at all, even in a window system's \"taskbar\".
 Normally you may not make FRAME invisible if all other frames are invisible,
 but if the second optional argument FORCE is non-nil, you may do so.
 
-This function has no effect on text-only terminal frames.  Such frames
-are always considered visible, whether or not they are currently being
+This function has no effect on text terminal frames.  Such frames are
+always considered visible, whether or not they are currently being
 displayed in the terminal.  */)
   (Lisp_Object frame, Lisp_Object force)
 {
@@ -1756,12 +1753,6 @@ displayed in the terminal.  */)
   if (NILP (force) && !other_visible_frames (XFRAME (frame)))
     error ("Attempt to make invisible the sole visible or iconified frame");
 
-#if 0 /* This isn't logically necessary, and it can do GC.  */
-  /* Don't let the frame remain selected.  */
-  if (EQ (frame, selected_frame))
-    do_switch_frame (next_frame (frame, Qt), 0, 0, Qnil)
-#endif
-
   /* Don't allow minibuf_window to remain on a deleted frame.  */
   if (EQ (XFRAME (frame)->minibuffer_window, minibuf_window))
     {
@@ -1829,7 +1820,7 @@ Return nil if FRAME was made invisible, via `make-frame-invisible'.
 On graphical displays, invisible frames are not updated and are
 usually not displayed at all, even in a window system's \"taskbar\".
 
-If FRAME is a text-only terminal frame, this always returns t.
+If FRAME is a text terminal frame, this always returns t.
 Such frames are always considered visible, whether or not they are
 currently being displayed on the terminal.  */)
   (Lisp_Object frame)
@@ -1885,7 +1876,7 @@ doesn't support multiple overlapping frames, this function selects FRAME.  */)
   f = XFRAME (frame);
 
   if (FRAME_TERMCAP_P (f))
-    /* On a text-only terminal select FRAME.  */
+    /* On a text terminal select FRAME.  */
     Fselect_frame (frame, Qnil);
   else
     /* Do like the documentation says. */
@@ -2046,7 +2037,7 @@ store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
 }
 
 static int
-frame_name_fnn_p (char *str, EMACS_INT len)
+frame_name_fnn_p (char *str, ptrdiff_t len)
 {
   if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
     {
@@ -2330,7 +2321,7 @@ If FRAME is nil, describe the currently selected frame.  */)
              if (STRINGP (value) && !FRAME_WINDOW_P (f))
                {
                  const char *color_name;
-                 EMACS_INT csz;
+                 ptrdiff_t csz;
 
                  if (EQ (parameter, Qbackground_color))
                    {
@@ -2406,12 +2397,13 @@ use is not recommended.  Explicitly check for a frame-parameter instead.  */)
 #endif
 
     {
-      int length = XINT (Flength (alist));
-      int i;
-      Lisp_Object *parms
-       = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
-      Lisp_Object *values
-       = (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
+      EMACS_INT length = XFASTINT (Flength (alist));
+      ptrdiff_t i;
+      Lisp_Object *parms;
+      Lisp_Object *values;
+      USE_SAFE_ALLOCA;
+      SAFE_ALLOCA_LISP (parms, 2 * length);
+      values = parms + length;
 
       /* Extract parm names and values into those vectors.  */
 
@@ -2437,6 +2429,8 @@ use is not recommended.  Explicitly check for a frame-parameter instead.  */)
              || EQ (prop, Qbackground_color))
            update_face_from_frame_parameter (f, prop, val);
        }
+
+      SAFE_FREE ();
     }
   return Qnil;
 }
@@ -2503,7 +2497,7 @@ not the menu bar).
 In a graphical version with no toolkit, it includes both the tool bar
 and menu bar.
 
-For a text-only terminal, it includes the menu bar.  In this case, the
+For a text terminal, it includes the menu bar.  In this case, the
 result is really in characters rather than pixels (i.e., is identical
 to `frame-height'). */)
   (Lisp_Object frame)
@@ -2575,7 +2569,7 @@ but that the idea of the actual height of the frame should not be changed.  */)
 {
   register struct frame *f;
 
-  CHECK_NUMBER (lines);
+  CHECK_TYPE_RANGED_INTEGER (int, lines);
   if (NILP (frame))
     frame = selected_frame;
   CHECK_LIVE_FRAME (frame);
@@ -2602,7 +2596,7 @@ but that the idea of the actual width of the frame should not be changed.  */)
   (Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
 {
   register struct frame *f;
-  CHECK_NUMBER (cols);
+  CHECK_TYPE_RANGED_INTEGER (int, cols);
   if (NILP (frame))
     frame = selected_frame;
   CHECK_LIVE_FRAME (frame);
@@ -2629,8 +2623,8 @@ DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
   register struct frame *f;
 
   CHECK_LIVE_FRAME (frame);
-  CHECK_NUMBER (cols);
-  CHECK_NUMBER (rows);
+  CHECK_TYPE_RANGED_INTEGER (int, cols);
+  CHECK_TYPE_RANGED_INTEGER (int, rows);
   f = XFRAME (frame);
 
   /* I think this should be done with a hook.  */
@@ -2661,8 +2655,8 @@ the rightmost or bottommost possible position (that stays within the screen).  *
   register struct frame *f;
 
   CHECK_LIVE_FRAME (frame);
-  CHECK_NUMBER (xoffset);
-  CHECK_NUMBER (yoffset);
+  CHECK_TYPE_RANGED_INTEGER (int, xoffset);
+  CHECK_TYPE_RANGED_INTEGER (int, yoffset);
   f = XFRAME (frame);
 
   /* I think this should be done with a hook.  */
@@ -2881,12 +2875,12 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
       prop = parms[i];
       val = values[i];
 
-      if (EQ (prop, Qwidth) && NATNUMP (val))
+      if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
         {
           size_changed = 1;
           width = XFASTINT (val);
         }
-      else if (EQ (prop, Qheight) && NATNUMP (val))
+      else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
         {
           size_changed = 1;
           height = XFASTINT (val);
@@ -2922,7 +2916,7 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
     }
 
   /* Don't die if just one of these was set.  */
-  if (EQ (left, Qunbound))
+  if (! TYPE_RANGED_INTEGERP (int, left))
     {
       left_no_change = 1;
       if (f->left_pos < 0)
@@ -2930,7 +2924,7 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
       else
        XSETINT (left, f->left_pos);
     }
-  if (EQ (top, Qunbound))
+  if (! TYPE_RANGED_INTEGERP (int, top))
     {
       top_no_change = 1;
       if (f->top_pos < 0)
@@ -2940,14 +2934,14 @@ x_set_frame_parameters (FRAME_PTR f, Lisp_Object alist)
     }
 
   /* If one of the icon positions was not set, preserve or default it.  */
-  if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
+  if (! TYPE_RANGED_INTEGERP (int, icon_left))
     {
       icon_left_no_change = 1;
       icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
       if (NILP (icon_left))
        XSETINT (icon_left, 0);
     }
-  if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
+  if (! TYPE_RANGED_INTEGERP (int, icon_top))
     {
       icon_top_no_change = 1;
       icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
@@ -3162,7 +3156,7 @@ x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
 {
   if (NILP (new_value))
     f->extra_line_spacing = 0;
-  else if (NATNUMP (new_value))
+  else if (RANGED_INTEGERP (0, new_value, INT_MAX))
     f->extra_line_spacing = XFASTINT (new_value);
   else
     signal_error ("Invalid line-spacing", new_value);
@@ -3371,7 +3365,7 @@ x_set_fringe_width (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu
 void
 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
-  CHECK_NUMBER (arg);
+  CHECK_TYPE_RANGED_INTEGER (int, arg);
 
   if (XINT (arg) == f->border_width)
     return;
@@ -3387,7 +3381,7 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
 {
   int old = FRAME_INTERNAL_BORDER_WIDTH (f);
 
-  CHECK_NUMBER (arg);
+  CHECK_TYPE_RANGED_INTEGER (int, arg);
   FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
   if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
     FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
@@ -4124,7 +4118,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p)
        f->top_pos = 0;
       else
        {
-         CHECK_NUMBER (tem0);
+         CHECK_TYPE_RANGED_INTEGER (int, tem0);
          f->top_pos = XINT (tem0);
          if (f->top_pos < 0)
            window_prompting |= YNegative;
@@ -4152,7 +4146,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, int toolbar_p)
        f->left_pos = 0;
       else
        {
-         CHECK_NUMBER (tem1);
+         CHECK_TYPE_RANGED_INTEGER (int, tem1);
          f->left_pos = XINT (tem1);
          if (f->left_pos < 0)
            window_prompting |= XNegative;