(delete_frame): Work around compiler bug.
[bpt/emacs.git] / src / frame.c
index 611dd1e..1a11021 100644 (file)
@@ -1,6 +1,6 @@
 /* Generic frame functions.
    Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+     2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -193,7 +193,6 @@ set_menu_bar_lines (f, value, oldval)
     }
 }
 \f
-Lisp_Object Vemacs_iconified;
 Lisp_Object Vframe_list;
 
 extern Lisp_Object Vminibuffer_list;
@@ -595,20 +594,12 @@ make_terminal_frame (struct terminal *terminal)
     f->output_method = output_msdos_raw;
   else
     f->output_method = output_termcap;
-#else
-  {
-    f->output_method = output_termcap;
-    create_tty_output (f);
-
-    FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
-    FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
-  }
-
-#ifdef CANNOT_DUMP
-  FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
-  FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
-#endif
-#endif /* MSDOS */
+#else /* not MSDOS */
+  f->output_method = output_termcap;
+  create_tty_output (f);
+  FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
+  FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
+#endif /* not MSDOS */
 
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
@@ -684,7 +675,7 @@ affects all frames on the same terminal device.  */)
     abort ();
 #else /* not MSDOS */
 
-#if 0                           /* This should work now! */
+#ifdef WINDOWSNT                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
@@ -1322,19 +1313,15 @@ delete_frame_handler (Lisp_Object arg)
 
 extern Lisp_Object Qrun_hook_with_args;
 
-DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
-       doc: /* Delete FRAME, permanently eliminating it from use.
-If omitted, FRAME defaults to the selected frame.
-A frame may not be deleted if its minibuffer is used by other frames.
-Normally, you may not delete a frame if all other frames are invisible,
-but if the second optional argument FORCE is non-nil, you may do so.
-
-This function runs `delete-frame-functions' before actually deleting the
-frame, unless the frame is a tooltip.
-The functions are run with one arg, the frame to be deleted.
-But FORCE inhibits this too.  */)
-/* FORCE is non-nil when handling a disconnected terminal.  */
-     (frame, force)
+/* 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
+  described for Fdelete_frame.  */
+Lisp_Object
+delete_frame (frame, 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.  */
      Lisp_Object frame, force;
 {
   struct frame *f;
@@ -1360,12 +1347,10 @@ But FORCE inhibits this too.  */)
   if (NILP (force) && !other_visible_frames (f))
     error ("Attempt to delete the sole visible or iconified frame");
 
-#if 0
-  /* This is a nice idea, but x_connection_closed needs to be able
+  /* x_connection_closed must have set FORCE to `noelisp' in order
      to delete the last frame, if it is gone.  */
-  if (NILP (XCDR (Vframe_list)))
+  if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
     error ("Attempt to delete the only frame");
-#endif
 
   /* Does this frame have a minibuffer, and is it the surrogate
      minibuffer for any other frame?  */
@@ -1385,19 +1370,20 @@ But FORCE inhibits this too.  */)
                     WINDOW_FRAME (XWINDOW
                                   (FRAME_MINIBUF_WINDOW (XFRAME (this))))))
            {
-             /* If we MUST delete this frame, delete the other first.  */
-             if (!NILP (force))
-               Fdelete_frame (this, force);
+             /* If we MUST delete this frame, delete the other first.
+                But do this only if FORCE equals `noelisp'.  */
+             if (EQ (force, Qnoelisp))
+               delete_frame (this, Qnoelisp);
              else
                error ("Attempt to delete a surrogate minibuffer frame");
            }
        }
     }
 
-  /* Run `delete-frame-functions'
-     unless FORCE is `noelisp' or frame is a tooltip.
-     FORCE is set to `noelisp' when handling a disconnect from the terminal,
-     so we don't dare call Lisp code.  */
+  /* Run `delete-frame-functions' unless FORCE is `noelisp' or
+     frame is a tooltip.  FORCE is set to `noelisp' when handling
+     a disconnect from the terminal, so we don't dare call Lisp
+     code.  */
   if (NILP (Vrun_hooks) || !NILP (Fframe_parameter (frame, intern ("tooltip"))))
     ;
   if (EQ (force, Qnoelisp))
@@ -1480,6 +1466,13 @@ But FORCE inhibits this too.  */)
   Vframe_list = Fdelq (frame, Vframe_list);
   FRAME_SET_VISIBLE (f, 0);
 
+  /* Allow the vector of menu bar contents to be freed in the next
+     garbage collection.  The frame object itself may not be garbage
+     collected until much later, because recent_keys and other data
+     structures can still refer to it.  */
+  f->menu_bar_vector = Qnil;
+
+  free_font_driver_list (f);
   xfree (f->namebuf);
   xfree (f->decode_mode_spec_buffer);
   xfree (FRAME_INSERT_COST (f));
@@ -1634,6 +1627,24 @@ But FORCE inhibits this too.  */)
 
   return Qnil;
 }
+
+DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
+       doc: /* Delete FRAME, permanently eliminating it from use.
+FRAME defaults to the selected frame.
+
+A frame may not be deleted if its minibuffer is used by other frames.
+Normally, you may not delete a frame if all other frames are invisible,
+but if the second optional argument FORCE is non-nil, you may do so.
+
+This function runs `delete-frame-functions' before actually
+deleting the frame, unless the frame is a tooltip.
+The functions are run with one argument, the frame to be deleted.  */)
+     (frame, force)
+     Lisp_Object frame, force;
+{
+  return delete_frame (frame, !NILP (force) ? Qt : Qnil);
+}
+
 \f
 /* Return mouse position in character cell units.  */
 
@@ -2278,7 +2289,6 @@ store_frame_param (f, prop, val)
        swap_in_global_binding (prop);
     }
 
-#ifndef WINDOWSNT
   /* The tty color needed to be set before the frame's parameter
      alist was updated with the new value.  This is not true any more,
      but we still do this test early on.  */
@@ -2286,7 +2296,6 @@ store_frame_param (f, prop, val)
       && f == FRAME_TTY (f)->previous_frame)
     /* Force redisplay of this tty.  */
     FRAME_TTY (f)->previous_frame = NULL;
-#endif
 
   /* Update the frame parameter alist.  */
   old_alist_elt = Fassq (prop, f->param_alist);
@@ -2919,6 +2928,9 @@ x_set_frame_parameters (f, alist)
   int left_no_change = 0, top_no_change = 0;
   int icon_left_no_change = 0, icon_top_no_change = 0;
   int fullscreen_is_being_set = 0;
+  int height_for_full_width = 0;
+  int width_for_full_height = 0;
+  enum fullscreen_type fullscreen_wanted = FULLSCREEN_NONE;
 
   struct gcpro gcpro1, gcpro2;
 
@@ -2961,7 +2973,7 @@ x_set_frame_parameters (f, alist)
      They are independent of other properties, but other properties (e.g.,
      cursor_color) are dependent upon them.  */
   /* Process default font as well, since fringe widths depends on it.  */
-  /* Also, process fullscreen, width and height depend upon that */
+  /* Also, process fullscreen, width and height depend upon that */
   for (p = 0; p < i; p++)
     {
       Lisp_Object prop, val;
@@ -2975,6 +2987,19 @@ x_set_frame_parameters (f, alist)
        {
          register Lisp_Object param_index, old_value;
 
+         if (EQ (prop, Qfullscreen))
+           {
+             /* The parameter handler can reset f->want_fullscreen to
+                FULLSCREEN_NONE.  But we need the requested value later
+                to decide whether a height or width parameter shall be
+                applied.  Therefore, we remember the requested value in
+                fullscreen_wanted for the following two cases.  */ 
+             if (EQ (val, Qfullheight))
+               fullscreen_wanted = FULLSCREEN_HEIGHT;
+             else if (EQ (val, Qfullwidth))
+               fullscreen_wanted = FULLSCREEN_WIDTH;
+           }
+
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
          if (NILP (Fequal (val, old_value)))
@@ -3000,9 +3025,9 @@ x_set_frame_parameters (f, alist)
       val = values[i];
 
       if (EQ (prop, Qwidth) && NATNUMP (val))
-       width = XFASTINT (val);
+       width_for_full_height = width = XFASTINT (val);
       else if (EQ (prop, Qheight) && NATNUMP (val))
-       height = XFASTINT (val);
+       height_for_full_width = height = XFASTINT (val);
       else if (EQ (prop, Qtop))
        top = val;
       else if (EQ (prop, Qleft))
@@ -3082,6 +3107,15 @@ x_set_frame_parameters (f, alist)
       x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
       if (new_top != f->top_pos || new_left != f->left_pos)
         x_set_offset (f, new_left, new_top, 1);
+
+      /* When both height and fullwidth were requested, make sure the
+        requested value for height gets applied.  */
+      if (height_for_full_width && fullscreen_wanted == FULLSCREEN_WIDTH)
+       height = height_for_full_width;
+      /* When both width and fullheight were requested, make sure the
+        requested value for width gets applied.  */
+      if (width_for_full_height && fullscreen_wanted == FULLSCREEN_HEIGHT)
+       width = width_for_full_height;
     }
 
   /* Don't set these parameters unless they've been explicitly
@@ -3341,8 +3375,9 @@ x_set_font (f, arg, oldval)
      fail to use ARG as the new parameter value.  */
   store_frame_param (f, Qfont, oldval);
 
-  /* ARG is a fontset name, a font name, or a font object.
-     In the last case, this function never fail.  */
+  /* ARG is a fontset name, a font name, a cons of fontset name and a
+     font object, or a font object.  In the last case, this function
+     never fail.  */
   if (STRINGP (arg))
     {
       fontset = fs_query_fontset (arg, 0);
@@ -3360,25 +3395,55 @@ x_set_font (f, arg, oldval)
          font_object = font_open_by_name (f, SDATA (ascii_font));
          if (NILP (font_object))
            error ("Font `%s' is not defined", SDATA (arg));
-         arg = fontset_name (fontset);
+         arg = AREF (font_object, FONT_NAME_INDEX);
        }
       else
        error ("The default fontset can't be used for a frame font");
     }
+  else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
+    {
+      /* This is the case that the ASCII font of F's fontset XCAR
+        (arg) is changed to the font XCDR (arg) by
+        `set-fontset-font'.  */
+      fontset = fs_query_fontset (XCAR (arg), 0);
+      if (fontset < 0)
+       error ("Unknown fontset: %s", SDATA (XCAR (arg)));
+      font_object = XCDR (arg);
+      arg = AREF (font_object, FONT_NAME_INDEX);
+    }
   else if (FONT_OBJECT_P (arg))
     {
       font_object = arg;
-      /* This is store the XLFD font name in the frame parameter for
+      /* This is to store the XLFD font name in the frame parameter for
         backward compatiblity.  We should store the font-object
         itself in the future.  */
       arg = AREF (font_object, FONT_NAME_INDEX);
+      fontset = FRAME_FONTSET (f);
     }
   else
     signal_error ("Invalid font", arg);
 
   if (! NILP (Fequal (font_object, oldval)))
     return;
+
+  
+  Lisp_Object lval = Fassq (Qfullscreen, f->param_alist);
+  if (CONSP (lval)) lval = CDR (lval);
+
   x_new_font (f, font_object, fontset);
+  /* If the fullscreen property is non-nil, adjust lines and columns so we
+     keep the same pixel height and width.  */
+  if (! NILP (lval))
+    {
+      int height = FRAME_LINES (f), width = FRAME_COLS (f);
+      if (EQ (lval, Qfullboth) || EQ (lval, Qfullwidth))
+        width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
+      if (EQ (lval, Qfullboth) || EQ (lval, Qfullheight))
+        height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, FRAME_PIXEL_HEIGHT (f));
+      
+      change_frame_size (f, height, width, 0, 0, 1);
+    }
+
   store_frame_param (f, Qfont, arg);
   /* Recalculate toolbar height.  */
   f->n_tool_bar_rows = 0;
@@ -3916,7 +3981,6 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
     {
       /* If we find this parm in ALIST, clear it out
         so that it won't be "left over" at the end.  */
-#ifndef WINDOWSNT /* w32fns.c has not yet been changed to cope with this.  */
       Lisp_Object tail;
       XSETCAR (tem, Qnil);
       /* In case the parameter appears more than once in the alist,
@@ -3925,7 +3989,6 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
        if (CONSP (XCAR (tail))
            && EQ (XCAR (XCAR (tail)), param))
          XSETCAR (XCAR (tail), Qnil);
-#endif
     }
   else
     tem = Fassq (param, Vdefault_frame_alist);
@@ -4523,10 +4586,6 @@ Setting this variable does not affect existing frames, only new ones.  */);
   DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
                doc: /* The initial frame-object, which represents Emacs's stdout.  */);
 
-  DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
-              doc: /* Non-nil if all of Emacs is iconified and frame updates are not needed.  */);
-  Vemacs_iconified = Qnil;
-
   DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
               doc: /* If non-nil, function to transform normal value of `mouse-position'.
 `mouse-position' calls this function, passing its usual return value as