changeset 50357:e5a09c97e444

Include blockinput.h. (Vx_resource_name, Vx_resource_class, Qx_frame_parameter) (Qx_resource_name, Qface_set_after_frame_default): Define vars here. (Qauto_raise, Qauto_lower, ...): Define all frame parameter related vars here. (struct frame_parm_table, frame_parms): New table for describing frame parameters and their associated Q-variable. The order of the parameters corresponds to the sequence of the frame_parm_handlers table in redisplay_interface. (x_fullscreen_move, x_set_frame_parameters) (x_report_frame_params, x_set_fullscreen, x_set_line_spacing) (x_set_screen_gamma, x_set_font, x_set_fringe_width) (x_set_border_width, x_set_internal_border_width, x_set_visibility) (x_set_autoraise, x_set_autolower, x_set_unsplittable) (x_set_vertical_scroll_bars, x_set_scroll_bar_width, x_icon_type): Generic functions for processing of frame parameters. (validate_x_resource_name, xrdb_get_resource, Fx_get_resource) (display_x_get_resource, x_get_resource_string): Functions for generic access to X resources. (x_get_arg, x_frame_get_arg, x_frame_get_and_record_arg) (x_default_parameter, Fx_parse_geometry): Functions for generic access to frame parameters. (x_figure_window_size): Generic calculation of frame size. Fixed to add space needed for tool bar. Also setup size_hint_flags. (syms_of_frame): Intern and staticpro frame parameter variables. Defvar_lisp Vx_resource_class and Vx_resource_name here. Defsubr Sx_get_resource and Sx_parse_geometry.
author Kim F. Storm <storm@cua.dk>
date Mon, 31 Mar 2003 20:33:58 +0000
parents 933b5f877c91
children 35c02b1585b3
files src/frame.c
diffstat 1 files changed, 1560 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/frame.c	Mon Mar 31 20:33:14 2003 +0000
+++ b/src/frame.c	Mon Mar 31 20:33:58 2003 +0000
@@ -41,6 +41,7 @@
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
 #endif
+#include "blockinput.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
@@ -49,33 +50,65 @@
 #include "dosfns.h"
 #endif
 
-Lisp_Object Qframep;
-Lisp_Object Qframe_live_p;
-Lisp_Object Qheight;
-Lisp_Object Qicon;
-Lisp_Object Qminibuffer;
-Lisp_Object Qmodeline;
-Lisp_Object Qname;
+
+/* The name we're using in resource queries.  Most often "emacs".  */
+
+Lisp_Object Vx_resource_name;
+
+/* The application class we're using in resource queries.
+   Normally "Emacs".  */
+
+Lisp_Object Vx_resource_class;
+
+
+Lisp_Object Qframep, Qframe_live_p;
+Lisp_Object Qicon, Qmodeline;
 Lisp_Object Qonly;
-Lisp_Object Qunsplittable;
-Lisp_Object Qmenu_bar_lines;
-Lisp_Object Qtool_bar_lines;
-Lisp_Object Qwidth;
-Lisp_Object Qx;
-Lisp_Object Qw32;
-Lisp_Object Qpc;
-Lisp_Object Qmac;
+Lisp_Object Qx, Qw32, Qmac, Qpc;
 Lisp_Object Qvisible;
-Lisp_Object Qbuffer_predicate;
-Lisp_Object Qbuffer_list;
-Lisp_Object Qtitle;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
 Lisp_Object Qinhibit_default_face_x_resources;
-Lisp_Object Qleft_fringe;
-Lisp_Object Qright_fringe;
+
+Lisp_Object Qx_frame_parameter;
+Lisp_Object Qx_resource_name;
+
+/* Frame parameters (set or reported).  */
+
+Lisp_Object Qauto_raise, Qauto_lower;
+Lisp_Object Qborder_color, Qborder_width;
+Lisp_Object Qcursor_color, Qcursor_type;
+Lisp_Object Qgeometry;  /* Not used */
+Lisp_Object Qheight, Qwidth;
+Lisp_Object Qleft, Qright;
+Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
+Lisp_Object Qinternal_border_width;
+Lisp_Object Qmouse_color;
+Lisp_Object Qminibuffer;
+Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
+Lisp_Object Qvisibility;
+Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
+Lisp_Object Qscreen_gamma;
+Lisp_Object Qline_spacing;
+Lisp_Object Quser_position, Quser_size;
+Lisp_Object Qwait_for_wm;
+Lisp_Object Qwindow_id;
+#ifdef HAVE_X_WINDOWS
+Lisp_Object Qouter_window_id;
+#endif
+Lisp_Object Qparent_id;
+Lisp_Object Qtitle, Qname;
+Lisp_Object Qunsplittable;
+Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
+Lisp_Object Qleft_fringe, Qright_fringe;
+Lisp_Object Qbuffer_predicate, Qbuffer_list;
 Lisp_Object Qtty_color_mode;
 
+Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
+
+Lisp_Object Qface_set_after_frame_default;
+
+
 Lisp_Object Vterminal_frame;
 Lisp_Object Vdefault_frame_alist;
 Lisp_Object Vmouse_position_function;
@@ -2437,6 +2470,1431 @@
 }
 
 
+/***********************************************************************
+				Frame Parameters
+ ***********************************************************************/
+
+/* Connect the frame-parameter names for X frames
+   to the ways of passing the parameter values to the window system.
+
+   The name of a parameter, as a Lisp symbol,
+   has an `x-frame-parameter' property which is an integer in Lisp
+   that is an index in this table.  */
+
+struct frame_parm_table {
+  char *name;
+  Lisp_Object *variable;
+};
+
+static struct frame_parm_table frame_parms[] =
+{
+  {"auto-raise",		&Qauto_raise},
+  {"auto-lower",		&Qauto_lower},
+  {"background-color",		0},
+  {"border-color",		&Qborder_color},
+  {"border-width",		&Qborder_width},
+  {"cursor-color",		&Qcursor_color},
+  {"cursor-type",		&Qcursor_type},
+  {"font",			0},
+  {"foreground-color",		0},
+  {"icon-name",			&Qicon_name},
+  {"icon-type",			&Qicon_type},
+  {"internal-border-width",	&Qinternal_border_width},
+  {"menu-bar-lines",		&Qmenu_bar_lines},
+  {"mouse-color",		&Qmouse_color},
+  {"name",			&Qname},
+  {"scroll-bar-width",		&Qscroll_bar_width},
+  {"title",			&Qtitle},
+  {"unsplittable",		&Qunsplittable},
+  {"vertical-scroll-bars",	&Qvertical_scroll_bars},
+  {"visibility",		&Qvisibility},
+  {"tool-bar-lines",		&Qtool_bar_lines},
+  {"scroll-bar-foreground",	&Qscroll_bar_foreground},
+  {"scroll-bar-background",	&Qscroll_bar_background},
+  {"screen-gamma",		&Qscreen_gamma},
+  {"line-spacing",		&Qline_spacing},
+  {"left-fringe",		&Qleft_fringe},
+  {"right-fringe",		&Qright_fringe},
+  {"wait-for-wm",		&Qwait_for_wm},
+  {"fullscreen",                &Qfullscreen},
+};
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+extern Lisp_Object Qbox;
+extern Lisp_Object Qtop;
+
+/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
+   wanted positions of the WM window (not emacs window).
+   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+   window (FRAME_X_WINDOW).
+ */
+
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+     struct frame *f;
+     int *width;
+     int *height;
+     int *top_pos;
+     int *left_pos;
+{
+  int newwidth = f->width, newheight = f->height;
+
+  *top_pos = FRAME_X_OUTPUT (f)->top_pos;
+  *left_pos = FRAME_X_OUTPUT (f)->left_pos;
+
+  if (FRAME_X_OUTPUT (f)->want_fullscreen & FULLSCREEN_HEIGHT)
+    {
+      int ph;
+
+      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+        - FRAME_X_OUTPUT (f)->y_pixels_diff;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      *top_pos = 0;
+    }
+
+  if (FRAME_X_OUTPUT (f)->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      int pw;
+
+      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+        - FRAME_X_OUTPUT (f)->x_pixels_diff;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      *left_pos = 0;
+    }
+
+  *width = newwidth;
+  *height = newheight;
+}
+
+
+/* Really try to move where we want to be in case of fullscreen.  Some WMs
+   moves the window where we tell them.  Some (mwm, twm) moves the outer
+   window manager window there instead.
+   Try to compensate for those WM here. */
+
+static void
+x_fullscreen_move (f, new_top, new_left)
+     struct frame *f;
+     int new_top;
+     int new_left;
+{
+  if (new_top != FRAME_X_OUTPUT (f)->top_pos
+      || new_left != FRAME_X_OUTPUT (f)->left_pos)
+    {
+      int move_x = new_left;
+      int move_y = new_top;
+
+#ifdef HAVE_X_WINDOWS
+      move_x += FRAME_X_OUTPUT (f)->x_pixels_outer_diff;
+      move_y += FRAME_X_OUTPUT (f)->y_pixels_outer_diff;
+#endif
+
+      FRAME_X_OUTPUT (f)->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
+      x_set_offset (f, move_x, move_y, 1);
+    }
+}
+
+/* Change the parameters of frame F as specified by ALIST.
+   If a parameter is not specially recognized, do nothing special;
+   otherwise call the `x_set_...' function for that parameter.
+   Except for certain geometry properties, always call store_frame_param
+   to store the new value in the parameter alist.  */
+
+void
+x_set_frame_parameters (f, alist)
+     FRAME_PTR f;
+     Lisp_Object alist;
+{
+  Lisp_Object tail;
+
+  /* If both of these parameters are present, it's more efficient to
+     set them both at once.  So we wait until we've looked at the
+     entire list before we set them.  */
+  int width, height;
+
+  /* Same here.  */
+  Lisp_Object left, top;
+
+  /* Same with these.  */
+  Lisp_Object icon_left, icon_top;
+
+  /* Record in these vectors all the parms specified.  */
+  Lisp_Object *parms;
+  Lisp_Object *values;
+  int i, p;
+  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;
+
+  struct gcpro gcpro1, gcpro2;
+
+  i = 0;
+  for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+    i++;
+
+  parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+  values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+
+  /* Extract parm names and values into those vectors.  */
+
+  i = 0;
+  for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+    {
+      Lisp_Object elt;
+
+      elt = Fcar (tail);
+      parms[i] = Fcar (elt);
+      values[i] = Fcdr (elt);
+      i++;
+    }
+  /* TAIL and ALIST are not used again below here.  */
+  alist = tail = Qnil;
+
+  GCPRO2 (*parms, *values);
+  gcpro1.nvars = i;
+  gcpro2.nvars = i;
+
+  /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
+     because their values appear in VALUES and strings are not valid.  */
+  top = left = Qunbound;
+  icon_left = icon_top = Qunbound;
+
+  /* Provide default values for HEIGHT and WIDTH.  */
+  if (FRAME_NEW_WIDTH (f))
+    width = FRAME_NEW_WIDTH (f);
+  else
+    width = FRAME_WIDTH (f);
+
+  if (FRAME_NEW_HEIGHT (f))
+    height = FRAME_NEW_HEIGHT (f);
+  else
+    height = FRAME_HEIGHT (f);
+
+  /* Process foreground_color and background_color before anything else.
+     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 */
+  for (p = 0; p < i; p++)
+    {
+      Lisp_Object prop, val;
+
+      prop = parms[p];
+      val = values[p];
+      if (EQ (prop, Qforeground_color)
+	  || EQ (prop, Qbackground_color)
+	  || EQ (prop, Qfont)
+          || EQ (prop, Qfullscreen))
+	{
+	  register Lisp_Object param_index, old_value;
+
+	  old_value = get_frame_param (f, prop);
+ 	  fullscreen_is_being_set |= EQ (prop, Qfullscreen);
+
+	  if (NILP (Fequal (val, old_value)))
+	    {
+	      store_frame_param (f, prop, val);
+
+	      param_index = Fget (prop, Qx_frame_parameter);
+	      if (NATNUMP (param_index)
+		  && (XFASTINT (param_index)
+		      < sizeof (frame_parms)/sizeof (frame_parms[0]))
+		  && rif->frame_parm_handlers[XINT (param_index)])
+		(*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
+	    }
+	}
+    }
+
+  /* Now process them in reverse of specified order.  */
+  for (i--; i >= 0; i--)
+    {
+      Lisp_Object prop, val;
+
+      prop = parms[i];
+      val = values[i];
+
+      if (EQ (prop, Qwidth) && NUMBERP (val))
+	width = XFASTINT (val);
+      else if (EQ (prop, Qheight) && NUMBERP (val))
+	height = XFASTINT (val);
+      else if (EQ (prop, Qtop))
+	top = val;
+      else if (EQ (prop, Qleft))
+	left = val;
+      else if (EQ (prop, Qicon_top))
+	icon_top = val;
+      else if (EQ (prop, Qicon_left))
+	icon_left = val;
+      else if (EQ (prop, Qforeground_color)
+	       || EQ (prop, Qbackground_color)
+	       || EQ (prop, Qfont)
+               || EQ (prop, Qfullscreen))
+	/* Processed above.  */
+	continue;
+      else
+	{
+	  register Lisp_Object param_index, old_value;
+
+	  old_value = get_frame_param (f, prop);
+
+	  store_frame_param (f, prop, val);
+
+	  param_index = Fget (prop, Qx_frame_parameter);
+	  if (NATNUMP (param_index)
+	      && (XFASTINT (param_index)
+		  < sizeof (frame_parms)/sizeof (frame_parms[0]))
+	      && rif->frame_parm_handlers[XINT (param_index)])
+	    (*(rif->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
+	}
+    }
+
+  /* Don't die if just one of these was set.  */
+  if (EQ (left, Qunbound))
+    {
+      left_no_change = 1;
+      if (FRAME_X_OUTPUT (f)->left_pos < 0)
+	left = Fcons (Qplus, Fcons (make_number (FRAME_X_OUTPUT (f)->left_pos), Qnil));
+      else
+	XSETINT (left, FRAME_X_OUTPUT (f)->left_pos);
+    }
+  if (EQ (top, Qunbound))
+    {
+      top_no_change = 1;
+      if (FRAME_X_OUTPUT (f)->top_pos < 0)
+	top = Fcons (Qplus, Fcons (make_number (FRAME_X_OUTPUT (f)->top_pos), Qnil));
+      else
+	XSETINT (top, FRAME_X_OUTPUT (f)->top_pos);
+    }
+
+  /* If one of the icon positions was not set, preserve or default it.  */
+  if (EQ (icon_left, Qunbound) || ! INTEGERP (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))
+    {
+      icon_top_no_change = 1;
+      icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
+      if (NILP (icon_top))
+	XSETINT (icon_top, 0);
+    }
+
+#ifndef HAVE_CARBON
+  /* MAC_TODO: fullscreen */
+  if (FRAME_VISIBLE_P (f) && fullscreen_is_being_set)
+    {
+      /* If the frame is visible already and the fullscreen parameter is
+         being set, it is too late to set WM manager hints to specify
+         size and position.
+         Here we first get the width, height and position that applies to
+         fullscreen.  We then move the frame to the appropriate
+         position.  Resize of the frame is taken care of in the code after
+         this if-statement. */
+      int new_left, new_top;
+
+      x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
+      x_fullscreen_move (f, new_top, new_left);
+    }
+#endif
+
+  /* Don't set these parameters unless they've been explicitly
+     specified.  The window might be mapped or resized while we're in
+     this function, and we don't want to override that unless the lisp
+     code has asked for it.
+
+     Don't set these parameters unless they actually differ from the
+     window's current parameters; the window may not actually exist
+     yet.  */
+  {
+    Lisp_Object frame;
+
+    check_frame_size (f, &height, &width);
+
+    XSETFRAME (frame, f);
+
+    if (width != FRAME_WIDTH (f)
+	|| height != FRAME_HEIGHT (f)
+	|| FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
+      Fset_frame_size (frame, make_number (width), make_number (height));
+
+    if ((!NILP (left) || !NILP (top))
+	&& ! (left_no_change && top_no_change)
+	&& ! (NUMBERP (left) && XINT (left) == FRAME_X_OUTPUT (f)->left_pos
+	      && NUMBERP (top) && XINT (top) == FRAME_X_OUTPUT (f)->top_pos))
+      {
+	int leftpos = 0;
+	int toppos = 0;
+
+	/* Record the signs.  */
+	FRAME_X_OUTPUT (f)->size_hint_flags &= ~ (XNegative | YNegative);
+	if (EQ (left, Qminus))
+	  FRAME_X_OUTPUT (f)->size_hint_flags |= XNegative;
+	else if (INTEGERP (left))
+	  {
+	    leftpos = XINT (left);
+	    if (leftpos < 0)
+	      FRAME_X_OUTPUT (f)->size_hint_flags |= XNegative;
+	  }
+	else if (CONSP (left) && EQ (XCAR (left), Qminus)
+		 && CONSP (XCDR (left))
+		 && INTEGERP (XCAR (XCDR (left))))
+	  {
+	    leftpos = - XINT (XCAR (XCDR (left)));
+	    FRAME_X_OUTPUT (f)->size_hint_flags |= XNegative;
+	  }
+	else if (CONSP (left) && EQ (XCAR (left), Qplus)
+		 && CONSP (XCDR (left))
+		 && INTEGERP (XCAR (XCDR (left))))
+	  {
+	    leftpos = XINT (XCAR (XCDR (left)));
+	  }
+
+	if (EQ (top, Qminus))
+	  FRAME_X_OUTPUT (f)->size_hint_flags |= YNegative;
+	else if (INTEGERP (top))
+	  {
+	    toppos = XINT (top);
+	    if (toppos < 0)
+	      FRAME_X_OUTPUT (f)->size_hint_flags |= YNegative;
+	  }
+	else if (CONSP (top) && EQ (XCAR (top), Qminus)
+		 && CONSP (XCDR (top))
+		 && INTEGERP (XCAR (XCDR (top))))
+	  {
+	    toppos = - XINT (XCAR (XCDR (top)));
+	    FRAME_X_OUTPUT (f)->size_hint_flags |= YNegative;
+	  }
+	else if (CONSP (top) && EQ (XCAR (top), Qplus)
+		 && CONSP (XCDR (top))
+		 && INTEGERP (XCAR (XCDR (top))))
+	  {
+	    toppos = XINT (XCAR (XCDR (top)));
+	  }
+
+
+	/* Store the numeric value of the position.  */
+	FRAME_X_OUTPUT (f)->top_pos = toppos;
+	FRAME_X_OUTPUT (f)->left_pos = leftpos;
+
+	FRAME_X_OUTPUT (f)->win_gravity = NorthWestGravity;
+
+	/* Actually set that position, and convert to absolute.  */
+	x_set_offset (f, leftpos, toppos, -1);
+      }
+
+    if ((!NILP (icon_left) || !NILP (icon_top))
+	&& ! (icon_left_no_change && icon_top_no_change))
+      x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
+  }
+
+  UNGCPRO;
+}
+
+
+/* Insert a description of internally-recorded parameters of frame X
+   into the parameter alist *ALISTPTR that is to be given to the user.
+   Only parameters that are specific to the X window system
+   and whose values are not correctly recorded in the frame's
+   param_alist need to be considered here.  */
+
+void
+x_report_frame_params (f, alistptr)
+     struct frame *f;
+     Lisp_Object *alistptr;
+{
+  char buf[16];
+  Lisp_Object tem;
+
+  /* Represent negative positions (off the top or left screen edge)
+     in a way that Fmodify_frame_parameters will understand correctly.  */
+  XSETINT (tem, FRAME_X_OUTPUT (f)->left_pos);
+  if (FRAME_X_OUTPUT (f)->left_pos >= 0)
+    store_in_alist (alistptr, Qleft, tem);
+  else
+    store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
+
+  XSETINT (tem, FRAME_X_OUTPUT (f)->top_pos);
+  if (FRAME_X_OUTPUT (f)->top_pos >= 0)
+    store_in_alist (alistptr, Qtop, tem);
+  else
+    store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
+
+  store_in_alist (alistptr, Qborder_width,
+		  make_number (FRAME_X_OUTPUT (f)->border_width));
+  store_in_alist (alistptr, Qinternal_border_width,
+		  make_number (FRAME_X_OUTPUT (f)->internal_border_width));
+  store_in_alist (alistptr, Qleft_fringe,
+		  make_number (FRAME_X_OUTPUT (f)->left_fringe_width));
+  store_in_alist (alistptr, Qright_fringe,
+		  make_number (FRAME_X_OUTPUT (f)->right_fringe_width));
+  store_in_alist (alistptr, Qscroll_bar_width,
+		  (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+		   ? make_number (0)
+		   : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
+		   ? make_number (FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
+		   /* nil means "use default width"
+		      for non-toolkit scroll bar.
+		      ruler-mode.el depends on this.  */
+		   : Qnil));
+  sprintf (buf, "%ld", (long) FRAME_X_WINDOW (f));
+  store_in_alist (alistptr, Qwindow_id,
+		  build_string (buf));
+#ifdef HAVE_X_WINDOWS
+#ifdef USE_X_TOOLKIT
+  /* Tooltip frame may not have this widget.  */
+  if (FRAME_X_OUTPUT (f)->widget)
+#endif
+    sprintf (buf, "%ld", (long) FRAME_OUTER_WINDOW (f));
+  store_in_alist (alistptr, Qouter_window_id,
+		  build_string (buf));
+#endif
+  store_in_alist (alistptr, Qicon_name, f->icon_name);
+  FRAME_SAMPLE_VISIBILITY (f);
+  store_in_alist (alistptr, Qvisibility,
+		  (FRAME_VISIBLE_P (f) ? Qt
+		   : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
+  store_in_alist (alistptr, Qdisplay,
+		  XCAR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
+
+  if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_X_DISPLAY_INFO (f)->root_window)
+    tem = Qnil;
+  else
+    XSETFASTINT (tem, FRAME_X_OUTPUT (f)->parent_desc);
+  store_in_alist (alistptr, Qparent_id, tem);
+}
+
+
+/* Change the `fullscreen' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value. */
+
+void
+x_set_fullscreen (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+#ifndef HAVE_CARBON
+  if (NILP (new_value))
+    FRAME_X_OUTPUT (f)->want_fullscreen = FULLSCREEN_NONE;
+  else if (EQ (new_value, Qfullboth))
+    FRAME_X_OUTPUT (f)->want_fullscreen = FULLSCREEN_BOTH;
+  else if (EQ (new_value, Qfullwidth))
+    FRAME_X_OUTPUT (f)->want_fullscreen = FULLSCREEN_WIDTH;
+  else if (EQ (new_value, Qfullheight))
+    FRAME_X_OUTPUT (f)->want_fullscreen = FULLSCREEN_HEIGHT;
+#endif
+}
+
+
+/* Change the `line-spacing' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.  */
+
+void
+x_set_line_spacing (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->extra_line_spacing = 0;
+  else if (NATNUMP (new_value))
+    f->extra_line_spacing = XFASTINT (new_value);
+  else
+    Fsignal (Qerror, Fcons (build_string ("Invalid line-spacing"),
+			    Fcons (new_value, Qnil)));
+  if (FRAME_VISIBLE_P (f))
+    redraw_frame (f);
+}
+
+
+/* Change the `screen-gamma' frame parameter of frame F.  OLD_VALUE is
+   the previous value of that parameter, NEW_VALUE is the new value.  */
+
+void
+x_set_screen_gamma (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  if (NILP (new_value))
+    f->gamma = 0;
+  else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
+    /* The value 0.4545 is the normal viewing gamma.  */
+    f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
+  else
+    Fsignal (Qerror, Fcons (build_string ("Invalid screen-gamma"),
+			    Fcons (new_value, Qnil)));
+
+  clear_face_cache (0);
+}
+
+
+void
+x_set_font (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  Lisp_Object result;
+  Lisp_Object fontset_name;
+  Lisp_Object frame;
+  int old_fontset = FRAME_FONTSET(f);
+
+  CHECK_STRING (arg);
+
+  fontset_name = Fquery_fontset (arg, Qnil);
+
+  BLOCK_INPUT;
+  result = (STRINGP (fontset_name)
+            ? x_new_fontset (f, SDATA (fontset_name))
+            : x_new_font (f, SDATA (arg)));
+  UNBLOCK_INPUT;
+
+  if (EQ (result, Qnil))
+    error ("Font `%s' is not defined", SDATA (arg));
+  else if (EQ (result, Qt))
+    error ("The characters of the given font have varying widths");
+  else if (STRINGP (result))
+    {
+      if (STRINGP (fontset_name))
+	{
+	  /* Fontset names are built from ASCII font names, so the
+	     names may be equal despite there was a change.  */
+	  if (old_fontset == FRAME_FONTSET (f))
+	    return;
+	}
+      else if (!NILP (Fequal (result, oldval)))
+        return;
+
+      store_frame_param (f, Qfont, result);
+      recompute_basic_faces (f);
+    }
+  else
+    abort ();
+
+  do_pending_window_change (0);
+
+  /* Don't call `face-set-after-frame-default' when faces haven't been
+     initialized yet.  This is the case when called from
+     Fx_create_frame.  In that case, the X widget or window doesn't
+     exist either, and we can end up in x_report_frame_params with a
+     null widget which gives a segfault.  */
+  if (FRAME_FACE_CACHE (f))
+    {
+      XSETFRAME (frame, f);
+      call1 (Qface_set_after_frame_default, frame);
+    }
+}
+
+
+void
+x_set_fringe_width (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  compute_fringe_widths (f, 1);
+}
+
+void
+x_set_border_width (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  CHECK_NUMBER (arg);
+
+  if (XINT (arg) == FRAME_X_OUTPUT (f)->border_width)
+    return;
+
+#ifndef HAVE_CARBON
+  if (FRAME_X_WINDOW (f) != 0)
+    error ("Cannot change the border width of a window");
+#endif /* MAC_TODO */
+
+  FRAME_X_OUTPUT (f)->border_width = XINT (arg);
+}
+
+void
+x_set_internal_border_width (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  int old = FRAME_X_OUTPUT (f)->internal_border_width;
+
+  CHECK_NUMBER (arg);
+  FRAME_X_OUTPUT (f)->internal_border_width = XINT (arg);
+  if (FRAME_X_OUTPUT (f)->internal_border_width < 0)
+    FRAME_X_OUTPUT (f)->internal_border_width = 0;
+
+#ifdef USE_X_TOOLKIT
+  if (FRAME_X_OUTPUT (f)->edit_widget)
+    widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
+#endif
+
+  if (FRAME_X_OUTPUT (f)->internal_border_width == old)
+    return;
+
+  if (FRAME_X_WINDOW (f) != 0)
+    {
+      x_set_window_size (f, 0, f->width, f->height);
+      SET_FRAME_GARBAGED (f);
+      do_pending_window_change (0);
+    }
+  else
+    SET_FRAME_GARBAGED (f);
+}
+
+void
+x_set_visibility (f, value, oldval)
+     struct frame *f;
+     Lisp_Object value, oldval;
+{
+  Lisp_Object frame;
+  XSETFRAME (frame, f);
+
+  if (NILP (value))
+    Fmake_frame_invisible (frame, Qt);
+  else if (EQ (value, Qicon))
+    Ficonify_frame (frame);
+  else
+    Fmake_frame_visible (frame);
+}
+
+void
+x_set_autoraise (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  f->auto_raise = !EQ (Qnil, arg);
+}
+
+void
+x_set_autolower (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  f->auto_lower = !EQ (Qnil, arg);
+}
+
+void
+x_set_unsplittable (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  f->no_split = !NILP (arg);
+}
+
+void
+x_set_vertical_scroll_bars (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+      || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+      || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+      || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
+    {
+      FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
+	= (NILP (arg)
+	   ? vertical_scroll_bar_none
+	   : EQ (Qleft, arg)
+	   ? vertical_scroll_bar_left
+	   : EQ (Qright, arg)
+	   ? vertical_scroll_bar_right
+#ifdef HAVE_NTGUI
+	   /* MS-Windows has scroll bars on the right by default.  */
+	   : vertical_scroll_bar_right
+#else
+	   : vertical_scroll_bar_left
+#endif
+	   );
+
+      /* We set this parameter before creating the X window for the
+	 frame, so we can get the geometry right from the start.
+	 However, if the window hasn't been created yet, we shouldn't
+	 call x_set_window_size.  */
+      if (FRAME_X_WINDOW (f))
+	x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+      do_pending_window_change (0);
+    }
+}
+
+void
+x_set_scroll_bar_width (f, arg, oldval)
+     struct frame *f;
+     Lisp_Object arg, oldval;
+{
+  int wid = FONT_WIDTH (FRAME_FONT (f));
+
+  if (NILP (arg))
+    {
+      x_set_scroll_bar_default_width (f);
+
+      if (FRAME_X_WINDOW (f))
+        x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+      do_pending_window_change (0);
+    }
+  else if (INTEGERP (arg) && XINT (arg) > 0
+	   && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
+    {
+      if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
+	XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
+
+      FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
+      FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
+      if (FRAME_X_WINDOW (f))
+	x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+      do_pending_window_change (0);
+    }
+
+  change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
+  XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
+  XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
+}
+
+
+
+/* Return non-nil if frame F wants a bitmap icon.  */
+
+Lisp_Object
+x_icon_type (f)
+     FRAME_PTR f;
+{
+  Lisp_Object tem;
+
+  tem = assq_no_quit (Qicon_type, f->param_alist);
+  if (CONSP (tem))
+    return XCDR (tem);
+  else
+    return Qnil;
+}
+
+
+/* Subroutines of creating an X frame.  */
+
+/* Make sure that Vx_resource_name is set to a reasonable value.
+   Fix it up, or set it to `emacs' if it is too hopeless.  */
+
+void
+validate_x_resource_name ()
+{
+  int len = 0;
+  /* Number of valid characters in the resource name.  */
+  int good_count = 0;
+  /* Number of invalid characters in the resource name.  */
+  int bad_count = 0;
+  Lisp_Object new;
+  int i;
+
+  if (!STRINGP (Vx_resource_class))
+    Vx_resource_class = build_string (EMACS_CLASS);
+
+  if (STRINGP (Vx_resource_name))
+    {
+      unsigned char *p = SDATA (Vx_resource_name);
+      int i;
+
+      len = SBYTES (Vx_resource_name);
+
+      /* Only letters, digits, - and _ are valid in resource names.
+	 Count the valid characters and count the invalid ones.  */
+      for (i = 0; i < len; i++)
+	{
+	  int c = p[i];
+	  if (! ((c >= 'a' && c <= 'z')
+		 || (c >= 'A' && c <= 'Z')
+		 || (c >= '0' && c <= '9')
+		 || c == '-' || c == '_'))
+	    bad_count++;
+	  else
+	    good_count++;
+	}
+    }
+  else
+    /* Not a string => completely invalid.  */
+    bad_count = 5, good_count = 0;
+
+  /* If name is valid already, return.  */
+  if (bad_count == 0)
+    return;
+
+  /* If name is entirely invalid, or nearly so, use `emacs'.  */
+  if (good_count == 0
+      || (good_count == 1 && bad_count > 0))
+    {
+      Vx_resource_name = build_string ("emacs");
+      return;
+    }
+
+  /* Name is partly valid.  Copy it and replace the invalid characters
+     with underscores.  */
+
+  Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
+
+  for (i = 0; i < len; i++)
+    {
+      int c = SREF (new, i);
+      if (! ((c >= 'a' && c <= 'z')
+	     || (c >= 'A' && c <= 'Z')
+	     || (c >= '0' && c <= '9')
+	     || c == '-' || c == '_'))
+	SSET (new, i, '_');
+    }
+}
+
+
+extern char *x_get_string_resource P_ ((XrmDatabase, char *, char *));
+extern Display_Info *check_x_display_info P_ ((Lisp_Object));
+
+
+/* Get specified attribute from resource database RDB.  
+   See Fx_get_resource below for other parameters.  */
+
+static Lisp_Object
+xrdb_get_resource (rdb, attribute, class, component, subclass)
+     XrmDatabase rdb;
+     Lisp_Object attribute, class, component, subclass;
+{
+  register char *value;
+  char *name_key;
+  char *class_key;
+
+  CHECK_STRING (attribute);
+  CHECK_STRING (class);
+
+  if (!NILP (component))
+    CHECK_STRING (component);
+  if (!NILP (subclass))
+    CHECK_STRING (subclass);
+  if (NILP (component) != NILP (subclass))
+    error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
+
+  validate_x_resource_name ();
+
+  /* Allocate space for the components, the dots which separate them,
+     and the final '\0'.  Make them big enough for the worst case.  */
+  name_key = (char *) alloca (SBYTES (Vx_resource_name)
+			      + (STRINGP (component)
+				 ? SBYTES (component) : 0)
+			      + SBYTES (attribute)
+			      + 3);
+
+  class_key = (char *) alloca (SBYTES (Vx_resource_class)
+			       + SBYTES (class)
+			       + (STRINGP (subclass)
+				  ? SBYTES (subclass) : 0)
+			       + 3);
+
+  /* Start with emacs.FRAMENAME for the name (the specific one)
+     and with `Emacs' for the class key (the general one).  */
+  strcpy (name_key, SDATA (Vx_resource_name));
+  strcpy (class_key, SDATA (Vx_resource_class));
+
+  strcat (class_key, ".");
+  strcat (class_key, SDATA (class));
+
+  if (!NILP (component))
+    {
+      strcat (class_key, ".");
+      strcat (class_key, SDATA (subclass));
+
+      strcat (name_key, ".");
+      strcat (name_key, SDATA (component));
+    }
+
+  strcat (name_key, ".");
+  strcat (name_key, SDATA (attribute));
+
+  value = x_get_string_resource (rdb, name_key, class_key);
+
+  if (value != (char *) 0)
+    return build_string (value);
+  else
+    return Qnil;
+}
+
+
+DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
+       doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
+This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
+class, where INSTANCE is the name under which Emacs was invoked, or
+the name specified by the `-name' or `-rn' command-line arguments.
+
+The optional arguments COMPONENT and SUBCLASS add to the key and the
+class, respectively.  You must specify both of them or neither.
+If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
+and the class is `Emacs.CLASS.SUBCLASS'.  */)
+     (attribute, class, component, subclass)
+     Lisp_Object attribute, class, component, subclass;
+{
+#ifdef HAVE_X_WINDOWS
+  check_x ();
+#endif
+
+  return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
+			    attribute, class, component, subclass);
+}
+
+/* Get an X resource, like Fx_get_resource, but for display DPYINFO.  */
+
+Lisp_Object
+display_x_get_resource (dpyinfo, attribute, class, component, subclass)
+     struct x_display_info *dpyinfo;
+     Lisp_Object attribute, class, component, subclass;
+{
+  return xrdb_get_resource (dpyinfo->xrdb,
+			    attribute, class, component, subclass);
+}
+
+/* Used when C code wants a resource value.  */
+
+char *
+x_get_resource_string (attribute, class)
+     char *attribute, *class;
+{
+  char *name_key;
+  char *class_key;
+  struct frame *sf = SELECTED_FRAME ();
+
+  /* Allocate space for the components, the dots which separate them,
+     and the final '\0'.  */
+  name_key = (char *) alloca (SBYTES (Vinvocation_name)
+			      + strlen (attribute) + 2);
+  class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
+			       + strlen (class) + 2);
+
+  sprintf (name_key, "%s.%s", SDATA (Vinvocation_name), attribute);
+  sprintf (class_key, "%s.%s", EMACS_CLASS, class);
+
+  return x_get_string_resource (FRAME_X_DISPLAY_INFO (sf)->xrdb,
+				name_key, class_key);
+}
+
+
+/* Return the value of parameter PARAM.
+
+   First search ALIST, then Vdefault_frame_alist, then the X defaults
+   database, using ATTRIBUTE as the attribute name and CLASS as its class.
+
+   Convert the resource to the type specified by desired_type.
+
+   If no default is specified, return Qunbound.  If you call
+   x_get_arg, make sure you deal with Qunbound in a reasonable way,
+   and don't let it get stored in any Lisp-visible variables!  */
+
+Lisp_Object
+x_get_arg (dpyinfo, alist, param, attribute, class, type)
+     Display_Info *dpyinfo; 
+     Lisp_Object alist, param;
+     char *attribute;
+     char *class;
+     enum resource_types type;
+{
+  register Lisp_Object tem;
+
+  tem = Fassq (param, alist);
+  if (EQ (tem, Qnil))
+    tem = Fassq (param, Vdefault_frame_alist);
+  if (EQ (tem, Qnil))
+    {
+      if (attribute)
+	{
+	  tem = display_x_get_resource (dpyinfo,
+					build_string (attribute),
+					build_string (class),
+					Qnil, Qnil);
+
+	  if (NILP (tem))
+	    return Qunbound;
+
+	  switch (type)
+	    {
+	    case RES_TYPE_NUMBER:
+	      return make_number (atoi (SDATA (tem)));
+
+	    case RES_TYPE_FLOAT:
+	      return make_float (atof (SDATA (tem)));
+
+	    case RES_TYPE_BOOLEAN:
+	      tem = Fdowncase (tem);
+	      if (!strcmp (SDATA (tem), "on")
+		  || !strcmp (SDATA (tem), "true"))
+		return Qt;
+	      else
+		return Qnil;
+
+	    case RES_TYPE_STRING:
+	      return tem;
+
+	    case RES_TYPE_SYMBOL:
+	      /* As a special case, we map the values `true' and `on'
+		 to Qt, and `false' and `off' to Qnil.  */
+	      {
+		Lisp_Object lower;
+		lower = Fdowncase (tem);
+		if (!strcmp (SDATA (lower), "on")
+		    || !strcmp (SDATA (lower), "true"))
+		  return Qt;
+		else if (!strcmp (SDATA (lower), "off")
+		      || !strcmp (SDATA (lower), "false"))
+		  return Qnil;
+		else
+		  return Fintern (tem, Qnil);
+	      }
+
+	    default:
+	      abort ();
+	    }
+	}
+      else
+	return Qunbound;
+    }
+  return Fcdr (tem);
+}
+
+Lisp_Object
+x_frame_get_arg (f, alist, param, attribute, class, type)
+     struct frame *f;
+     Lisp_Object alist, param;
+     char *attribute;
+     char *class;
+     enum resource_types type;
+{
+  return x_get_arg (FRAME_X_DISPLAY_INFO (f),
+		    alist, param, attribute, class, type);
+}
+
+/* Like x_frame_get_arg, but also record the value in f->param_alist.  */
+
+Lisp_Object
+x_frame_get_and_record_arg (f, alist, param, attribute, class, type)
+     struct frame *f;
+     Lisp_Object alist, param;
+     char *attribute;
+     char *class;
+     enum resource_types type;
+{
+  Lisp_Object value;
+
+  value = x_get_arg (FRAME_X_DISPLAY_INFO (f), alist, param,
+		     attribute, class, type);
+  if (! NILP (value))
+    store_frame_param (f, param, value);
+
+  return value;
+}
+
+
+/* Record in frame F the specified or default value according to ALIST
+   of the parameter named PROP (a Lisp symbol).
+   If no value is specified for PROP, look for an X default for XPROP
+   on the frame named NAME.
+   If that is not found either, use the value DEFLT.  */
+
+Lisp_Object
+x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
+     struct frame *f;
+     Lisp_Object alist;
+     Lisp_Object prop;
+     Lisp_Object deflt;
+     char *xprop;
+     char *xclass;
+     enum resource_types type;
+{
+  Lisp_Object tem;
+
+  tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
+  if (EQ (tem, Qunbound))
+    tem = deflt;
+  x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
+  return tem;
+}
+
+
+
+
+DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
+       doc: /* Parse an X-style geometry string STRING.
+Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
+The properties returned may include `top', `left', `height', and `width'.
+The value of `left' or `top' may be an integer,
+or a list (+ N) meaning N pixels relative to top/left corner,
+or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
+     (string)
+     Lisp_Object string;
+{
+  int geometry, x, y;
+  unsigned int width, height;
+  Lisp_Object result;
+
+  CHECK_STRING (string);
+
+  geometry = XParseGeometry ((char *) SDATA (string),
+			     &x, &y, &width, &height);
+
+#if 0
+  if (!!(geometry & XValue) != !!(geometry & YValue))
+    error ("Must specify both x and y position, or neither");
+#endif
+
+  result = Qnil;
+  if (geometry & XValue)
+    {
+      Lisp_Object element;
+
+      if (x >= 0 && (geometry & XNegative))
+	element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
+      else if (x < 0 && ! (geometry & XNegative))
+	element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
+      else
+	element = Fcons (Qleft, make_number (x));
+      result = Fcons (element, result);
+    }
+
+  if (geometry & YValue)
+    {
+      Lisp_Object element;
+
+      if (y >= 0 && (geometry & YNegative))
+	element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
+      else if (y < 0 && ! (geometry & YNegative))
+	element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
+      else
+	element = Fcons (Qtop, make_number (y));
+      result = Fcons (element, result);
+    }
+
+  if (geometry & WidthValue)
+    result = Fcons (Fcons (Qwidth, make_number (width)), result);
+  if (geometry & HeightValue)
+    result = Fcons (Fcons (Qheight, make_number (height)), result);
+
+  return result;
+}
+
+/* Calculate the desired size and position of frame F.
+   Return the flags saying which aspects were specified.
+
+   Also set the win_gravity and size_hint_flags of F.
+
+   Adjust height for toolbar if TOOLBAR_P is 1.
+
+   This function does not make the coordinates positive.  */
+
+#define DEFAULT_ROWS 40
+#define DEFAULT_COLS 80
+
+int
+x_figure_window_size (f, parms, toolbar_p)
+     struct frame *f;
+     Lisp_Object parms;
+     int toolbar_p;
+{
+  register Lisp_Object tem0, tem1, tem2;
+  long window_prompting = 0;
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+  /* Default values if we fall through.
+     Actually, if that happens we should get
+     window manager prompting.  */
+  SET_FRAME_WIDTH (f, DEFAULT_COLS);
+  f->height = DEFAULT_ROWS;
+  /* Window managers expect that if program-specified
+     positions are not (0,0), they're intentional, not defaults.  */
+  FRAME_X_OUTPUT (f)->top_pos = 0;
+  FRAME_X_OUTPUT (f)->left_pos = 0;
+
+  /* Ensure that old new_width and new_height will not override the
+     values set here.  */
+  /* ++KFS: This was specific to W32, but seems ok for all platforms */
+  FRAME_NEW_WIDTH (f) = 0;
+  FRAME_NEW_HEIGHT (f) = 0;
+
+  tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+  tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+  tem2 = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+  if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+    {
+      if (!EQ (tem0, Qunbound))
+	{
+	  CHECK_NUMBER (tem0);
+	  f->height = XINT (tem0);
+	}
+      if (!EQ (tem1, Qunbound))
+	{
+	  CHECK_NUMBER (tem1);
+	  SET_FRAME_WIDTH (f, XINT (tem1));
+	}
+      if (!NILP (tem2) && !EQ (tem2, Qunbound))
+	window_prompting |= USSize;
+      else
+	window_prompting |= PSize;
+    }
+
+  FRAME_X_OUTPUT (f)->vertical_scroll_bar_extra
+    = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+       ? 0
+#ifndef HAVE_X_WINDOWS
+       /* +KFS: This was specific for W32 and MAC.. why?  */
+       : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
+       ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
+#endif
+       : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (FRAME_X_OUTPUT (f)->font)));
+
+  /* This used to be done _before_ calling x_figure_window_size, but
+     since the height is reset here, this was really a no-op.  I
+     assume that moving it here does what Gerd intended (although he
+     no longer can remember what that was...  ++KFS, 2003-03-25.  */
+
+  /* Add the tool-bar height to the initial frame height so that the
+     user gets a text display area of the size he specified with -g or
+     via .Xdefaults.  Later changes of the tool-bar height don't
+     change the frame size.  This is done so that users can create
+     tall Emacs frames without having to guess how tall the tool-bar
+     will get.  */
+  if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
+    {
+      int margin, relief, bar_height;
+
+      relief = (tool_bar_button_relief >= 0
+		? tool_bar_button_relief
+		: DEFAULT_TOOL_BAR_BUTTON_RELIEF);
+
+      if (INTEGERP (Vtool_bar_button_margin)
+	  && XINT (Vtool_bar_button_margin) > 0)
+	margin = XFASTINT (Vtool_bar_button_margin);
+      else if (CONSP (Vtool_bar_button_margin)
+	       && INTEGERP (XCDR (Vtool_bar_button_margin))
+	       && XINT (XCDR (Vtool_bar_button_margin)) > 0)
+	margin = XFASTINT (XCDR (Vtool_bar_button_margin));
+      else
+	margin = 0;
+
+      bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
+      f->height += (bar_height + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+    }
+
+  compute_fringe_widths (f, 0);
+
+  FRAME_X_OUTPUT (f)->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
+  FRAME_X_OUTPUT (f)->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
+
+  tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+  tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+  tem2 = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+  if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+    {
+      if (EQ (tem0, Qminus))
+	{
+	  FRAME_X_OUTPUT (f)->top_pos = 0;
+	  window_prompting |= YNegative;
+	}
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
+	       && CONSP (XCDR (tem0))
+	       && INTEGERP (XCAR (XCDR (tem0))))
+	{
+	  FRAME_X_OUTPUT (f)->top_pos = - XINT (XCAR (XCDR (tem0)));
+	  window_prompting |= YNegative;
+	}
+      else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
+	       && CONSP (XCDR (tem0))
+	       && INTEGERP (XCAR (XCDR (tem0))))
+	{
+	  FRAME_X_OUTPUT (f)->top_pos = XINT (XCAR (XCDR (tem0)));
+	}
+      else if (EQ (tem0, Qunbound))
+	FRAME_X_OUTPUT (f)->top_pos = 0;
+      else
+	{
+	  CHECK_NUMBER (tem0);
+	  FRAME_X_OUTPUT (f)->top_pos = XINT (tem0);
+	  if (FRAME_X_OUTPUT (f)->top_pos < 0)
+	    window_prompting |= YNegative;
+	}
+
+      if (EQ (tem1, Qminus))
+	{
+	  FRAME_X_OUTPUT (f)->left_pos = 0;
+	  window_prompting |= XNegative;
+	}
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
+	       && CONSP (XCDR (tem1))
+	       && INTEGERP (XCAR (XCDR (tem1))))
+	{
+	  FRAME_X_OUTPUT (f)->left_pos = - XINT (XCAR (XCDR (tem1)));
+	  window_prompting |= XNegative;
+	}
+      else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
+	       && CONSP (XCDR (tem1))
+	       && INTEGERP (XCAR (XCDR (tem1))))
+	{
+	  FRAME_X_OUTPUT (f)->left_pos = XINT (XCAR (XCDR (tem1)));
+	}
+      else if (EQ (tem1, Qunbound))
+	FRAME_X_OUTPUT (f)->left_pos = 0;
+      else
+	{
+	  CHECK_NUMBER (tem1);
+	  FRAME_X_OUTPUT (f)->left_pos = XINT (tem1);
+	  if (FRAME_X_OUTPUT (f)->left_pos < 0)
+	    window_prompting |= XNegative;
+	}
+
+      if (!NILP (tem2) && ! EQ (tem2, Qunbound))
+	window_prompting |= USPosition;
+      else
+	window_prompting |= PPosition;
+    }
+
+  if (FRAME_X_OUTPUT (f)->want_fullscreen != FULLSCREEN_NONE)
+    {
+      int left, top;
+      int width, height;
+
+      /* It takes both for some WM:s to place it where we want */
+      window_prompting = USPosition | PPosition;
+      x_fullscreen_adjust (f, &width, &height, &top, &left);
+      f->width = width;
+      f->height = height;
+      FRAME_X_OUTPUT (f)->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
+      FRAME_X_OUTPUT (f)->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
+      FRAME_X_OUTPUT (f)->left_pos = left;
+      FRAME_X_OUTPUT (f)->top_pos = top;
+    }
+
+  if (window_prompting & XNegative)
+    {
+      if (window_prompting & YNegative)
+	FRAME_X_OUTPUT (f)->win_gravity = SouthEastGravity;
+      else
+	FRAME_X_OUTPUT (f)->win_gravity = NorthEastGravity;
+    }
+  else
+    {
+      if (window_prompting & YNegative)
+	FRAME_X_OUTPUT (f)->win_gravity = SouthWestGravity;
+      else
+	FRAME_X_OUTPUT (f)->win_gravity = NorthWestGravity;
+    }
+
+  FRAME_X_OUTPUT (f)->size_hint_flags = window_prompting;
+
+  return window_prompting;
+}
+
+
+
+#endif /* HAVE_WINDOW_SYSTEM */
+
+
+
+/***********************************************************************
+				Initialization
+ ***********************************************************************/
+
 void
 syms_of_frame ()
 {
@@ -2452,18 +3910,32 @@
   staticpro (&Qminibuffer);
   Qmodeline = intern ("modeline");
   staticpro (&Qmodeline);
-  Qname = intern ("name");
-  staticpro (&Qname);
   Qonly = intern ("only");
   staticpro (&Qonly);
-  Qunsplittable = intern ("unsplittable");
-  staticpro (&Qunsplittable);
-  Qmenu_bar_lines = intern ("menu-bar-lines");
-  staticpro (&Qmenu_bar_lines);
-  Qtool_bar_lines = intern ("tool-bar-lines");
-  staticpro (&Qtool_bar_lines);
   Qwidth = intern ("width");
   staticpro (&Qwidth);
+  Qgeometry = intern ("geometry");
+  staticpro (&Qgeometry);
+  Qicon_left = intern ("icon-left");
+  staticpro (&Qicon_left);
+  Qicon_top = intern ("icon-top");
+  staticpro (&Qicon_top);
+  Qleft = intern ("left");
+  staticpro (&Qleft);
+  Qright = intern ("right");
+  staticpro (&Qright);
+  Quser_position = intern ("user-position");
+  staticpro (&Quser_position);
+  Quser_size = intern ("user-size");
+  staticpro (&Quser_size);
+  Qwindow_id = intern ("window-id");
+  staticpro (&Qwindow_id);
+#ifdef HAVE_X_WINDOWS
+  Qouter_window_id = intern ("outer-window-id");
+  staticpro (&Qouter_window_id);
+#endif
+  Qparent_id = intern ("parent-id");
+  staticpro (&Qparent_id);
   Qx = intern ("x");
   staticpro (&Qx);
   Qw32 = intern ("w32");
@@ -2478,19 +3950,67 @@
   staticpro (&Qbuffer_predicate);
   Qbuffer_list = intern ("buffer-list");
   staticpro (&Qbuffer_list);
-  Qtitle = intern ("title");
-  staticpro (&Qtitle);
   Qdisplay_type = intern ("display-type");
   staticpro (&Qdisplay_type);
   Qbackground_mode = intern ("background-mode");
   staticpro (&Qbackground_mode);
-  Qleft_fringe = intern ("left-fringe");
-  staticpro (&Qleft_fringe);
-  Qright_fringe = intern ("right-fringe");
-  staticpro (&Qright_fringe);
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
 
+  Qface_set_after_frame_default = intern ("face-set-after-frame-default");
+  staticpro (&Qface_set_after_frame_default);
+
+  Qfullwidth = intern ("fullwidth");
+  staticpro (&Qfullwidth);
+  Qfullheight = intern ("fullheight");
+  staticpro (&Qfullheight);
+  Qfullboth = intern ("fullboth");
+  staticpro (&Qfullboth);
+  Qx_resource_name = intern ("x-resource-name");
+  staticpro (&Qx_resource_name);
+
+  Qx_frame_parameter = intern ("x-frame-parameter");
+  staticpro (&Qx_frame_parameter);
+
+  {
+    int i;
+
+    for (i = 0; i < sizeof (frame_parms) / sizeof (frame_parms[0]); i++)
+      {
+	Lisp_Object v = intern (frame_parms[i].name);
+	if (frame_parms[i].variable)
+	  {
+	    *frame_parms[i].variable = v;
+	    staticpro (frame_parms[i].variable);
+	  }
+	Fput (v, Qx_frame_parameter, make_number (i));
+      }
+  }
+
+  DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
+    doc: /* The name Emacs uses to look up X resources.
+`x-get-resource' uses this as the first component of the instance name
+when requesting resource values.
+Emacs initially sets `x-resource-name' to the name under which Emacs
+was invoked, or to the value specified with the `-name' or `-rn'
+switches, if present.
+
+It may be useful to bind this variable locally around a call
+to `x-get-resource'.  See also the variable `x-resource-class'.  */);
+  Vx_resource_name = Qnil;
+
+  DEFVAR_LISP ("x-resource-class", &Vx_resource_class,
+    doc: /* The class Emacs uses to look up X resources.
+`x-get-resource' uses this as the first component of the instance class
+when requesting resource values.
+
+Emacs initially sets `x-resource-class' to "Emacs".
+
+Setting this variable permanently is not a reasonable thing to do,
+but binding this variable locally around a call to `x-get-resource'
+is a reasonable practice.  See also the variable `x-resource-name'.  */);
+  Vx_resource_class = build_string (EMACS_CLASS);
+
   DEFVAR_LISP ("default-frame-alist", &Vdefault_frame_alist,
 	       doc: /* Alist of default values for frame creation.
 These may be set in your init file, like this:
@@ -2600,4 +4120,10 @@
   defsubr (&Sset_frame_width);
   defsubr (&Sset_frame_size);
   defsubr (&Sset_frame_position);
+
+#ifdef HAVE_WINDOW_SYSTEM
+  defsubr (&Sx_get_resource);
+  defsubr (&Sx_parse_geometry);
+#endif
+
 }