diff src/glyphs-widget.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children d7a9135ec789
line wrap: on
line diff
--- a/src/glyphs-widget.c	Mon Aug 13 11:33:40 2007 +0200
+++ b/src/glyphs-widget.c	Mon Aug 13 11:35:02 2007 +0200
@@ -55,10 +55,11 @@
 Lisp_Object Qtab_control;
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout);
 Lisp_Object Qlayout;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (native_layout);
+Lisp_Object Qnative_layout;
 
-Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
-Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border;
 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
+Lisp_Object Qmake_glyph;
 
 #ifdef DEBUG_WIDGETS
 int debug_widget_instances;
@@ -82,16 +83,14 @@
 }
 
 static void
-check_valid_glyph_or_instantiator (Lisp_Object data)
+check_valid_instantiator (Lisp_Object data)
 {
   Lisp_Object glyph = data;
   if (SYMBOLP (data))
     glyph = XSYMBOL (data)->value;
 
-  if (IMAGE_INSTANCEP (glyph))
-    CHECK_IMAGE_INSTANCE (glyph);
-  else if (!CONSP (glyph) && !VECTORP (glyph))
-    CHECK_BUFFER_GLYPH (glyph);
+  if (!CONSP (glyph) && !VECTORP (glyph))
+    invalid_argument ("instantiator item must be a vector", data);
 }
 
 static void
@@ -100,7 +99,7 @@
   if (!EQ (data, Qhorizontal)
       &&
       !EQ (data, Qvertical))
-    signal_simple_error ("unknown orientation for layout", data);
+    invalid_argument ("unknown orientation for layout", data);
 }
 
 static void
@@ -113,14 +112,14 @@
       !EQ (data, Qleft)
       &&
       !EQ (data, Qright))
-    signal_simple_error ("unknown orientation for tab control", data);
+    invalid_argument ("unknown orientation for tab control", data);
 }
 
 static void
 check_valid_justification (Lisp_Object data)
 {
   if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter))
-    signal_simple_error ("unknown justification for layout", data);
+    invalid_argument ("unknown justification for layout", data);
 }
 
 static void
@@ -129,7 +128,7 @@
   if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out)
       && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out)
       && !GLYPHP (data) && !VECTORP (data))
-    signal_simple_error ("unknown border style for layout", data);
+    invalid_argument ("unknown border style for layout", data);
 }
 
 static void
@@ -144,11 +143,18 @@
 	&& !COMPILED_FUNCTIONP (data)
 	&& !CONSP (data))
     {
-	signal_simple_error (":callback must be a function or expression", data);
+	invalid_argument (":callback must be a function or expression", data);
     }
 }
 
 static void
+check_valid_int_or_function (Lisp_Object data)
+{
+  if (!INTP (data) && !CONSP (data))
+    invalid_argument ("must be an integer or expresssion", data);
+}
+
+static void
 check_valid_symbol (Lisp_Object data)
 {
     CHECK_SYMBOL (data);
@@ -158,11 +164,11 @@
 check_valid_string_or_vector (Lisp_Object data)
 {
     if (!STRINGP (data) && !VECTORP (data))
-	signal_simple_error (":descriptor must be a string or a vector", data);
+	invalid_argument (":descriptor must be a string or a vector", data);
 }
 
 void
-check_valid_item_list_1 (Lisp_Object items)
+check_valid_item_list (Lisp_Object items)
 {
   Lisp_Object rest;
 
@@ -174,32 +180,21 @@
       else if (VECTORP (XCAR (rest)))
 	gui_parse_item_keywords (XCAR (rest));
       else if (LISTP (XCAR (rest)))
-	check_valid_item_list_1 (XCAR (rest));
+	check_valid_item_list (XCAR (rest));
       else
-	signal_simple_error ("Items must be vectors, lists or strings", items);
+	invalid_argument ("Items must be vectors, lists or strings", items);
     }
 }
 
 static void
-check_valid_item_list (Lisp_Object data)
-{
-  Lisp_Object items;
-
-  Fcheck_valid_plist (data);
-  items = Fplist_get (data, Q_items, Qnil);
-
-  check_valid_item_list_1 (items);
-}
-
-static void
-check_valid_glyph_or_instantiator_list (Lisp_Object data)
+check_valid_instantiator_list (Lisp_Object data)
 {
   Lisp_Object rest;
 
   CHECK_LIST (data);
   EXTERNAL_LIST_LOOP (rest, data)
     {
-      check_valid_glyph_or_instantiator (XCAR (rest));
+      check_valid_instantiator (XCAR (rest));
     }
 }
 
@@ -209,26 +204,26 @@
   /* This function calls lisp. */
   Lisp_Object glyph = sym;
   struct gcpro gcpro1;
-	  
+
   GCPRO1 (glyph);
   /* if we have a symbol get at the actual data */
   if (SYMBOLP (glyph))
     glyph = XSYMBOL (glyph)->value;
-	  
+
   if (CONSP (glyph))
     glyph = Feval (glyph);
 
   /* Be really helpful to the user. */
   if (VECTORP (glyph))
     {
-      glyph = call1 (intern ("make-glyph"), glyph);
+      glyph = call1 (Qmake_glyph, glyph);
     }
 
   /* substitute the new glyph */
   RETURN_UNGCPRO (glyph);
 }
 
-static void 
+static void
 substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val)
 {
   int i;
@@ -254,24 +249,24 @@
    type (Qedit_field for example). It is debatable whether we should
    wire things in this generalised way rather than treating widgets
    specially in image_instance_property. */
-static Lisp_Object 
+static Lisp_Object
 widget_property (Lisp_Object image_instance, Lisp_Object prop)
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
   struct image_instantiator_methods* meths;
-
+#if 0				/* The usefulness of this is dubious. */
   /* first see if its a general property ... */
   if (!NILP (Fplist_member (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop)))
     return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
-
+#endif
   /* .. then try device specific methods ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
-				   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance),
+				   IMAGE_INSTANCE_WIDGET_TYPE (ii),
 				   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, property))
     return IIFORMAT_METH (meths, property, (image_instance, prop));
   /* ... then format specific methods ... */
-  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
 				   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, property))
     return IIFORMAT_METH (meths, property, (image_instance, prop));
@@ -279,86 +274,135 @@
   return Qunbound;
 }
 
-static Lisp_Object 
-widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object val)
+/* Update the displayed properties of a widget.
+
+   #### This has been adapted from the original set_property functions
+   and thus reuses the state management of that. A better solution is
+   to simply re-parse the instantiator when items need updating. This
+   make comparing differences much simpler and obviates the need for a
+   lot of the state variables.
+
+   #### property is still a valid function since we have to be able to
+   extract information from the actual widget.
+
+   #### update_widget should probably be re-written to use the
+   instantiator. We probably want to keep a record of the differences
+   also to make this easy. We would also need a pending_instantiator
+   so that changes could be delayed. */
+static void
+widget_update (Lisp_Object image_instance, Lisp_Object instantiator)
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
   struct image_instantiator_methods* meths;
-  Lisp_Object ret;
 
-  /* PIck up any generic properties that we might need to keep hold
+  Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
+  /* Pick up any generic properties that we might need to keep hold
      of. */
-  if (EQ (prop, Q_text))
+  if (!NILP (text))
     {
-      IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
+      IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
+      IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
     }
 
   /* Now try device specific methods first ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance),
+				   IMAGE_INSTANCE_WIDGET_TYPE (ii),
+				   ERROR_ME_NOT);
+  MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
+  /* ... then format specific methods ... */
+  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
+				   ERROR_ME_NOT);
+  MAYBE_IIFORMAT_METH (meths, update, (image_instance, instantiator));
+#if 0 /* The usefulness of this is dubious. */
+  /* we didn't do any device specific properties, so shove the property in our plist. */
+  IMAGE_INSTANCE_WIDGET_PROPS (ii)
+    = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
+#endif
+}
+
+/* Like the rest of redisplay, we want widget updates to occur
+   asynchronously. Thus toolkit specific methods for setting
+   properties must be called by redisplay instead of by *_update. Thus
+   *_update records the change and this function actually implements
+   it. We want to be slightly clever about this however by supplying
+   format specific functions for the updates instead of lumping them
+   all into this function. Note that there is no need for format
+   generic functions. This is not the same as widget_update! */
+void
+redisplay_widget (Lisp_Object widget)
+{
+  Lisp_Image_Instance* ii = XIMAGE_INSTANCE (widget);
+  struct image_instantiator_methods* meths;
+
+  if (!WIDGET_IMAGE_INSTANCEP (widget)
+      || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      || EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
+    return;
+
+  /* Device-format specific methods - e.g. x_tab_control_redisplay () */
+  meths = decode_device_ii_format (image_instance_device (widget), 
 				   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
 				   ERROR_ME_NOT);
-  if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
-      &&
-      !UNBOUNDP (ret = 
-		 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
+  MAYBE_IIFORMAT_METH (meths, redisplay, (widget));
+
+  /* Device generic methods - e.g. x_redisplay_widget (). We must
+     update the widget's size as it may have been changed by the the
+     layout routines. We also do this here so that explicit resizing
+     from lisp does not result in synchronous updates. Do this last so
+     that format-specific methods have an opportunity to prevent
+     wholesale changes - e.g. rebuilding tabs. */
+  MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), redisplay_widget, (ii));
+
+  /* Pick up the items we recorded earlier. */
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
-      return ret;
+      IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
+	IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
+      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
     }
-  /* ... then format specific methods ... */
-  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
-				   ERROR_ME_NOT);
-  if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
-      &&
-      !UNBOUNDP (ret = 
-		 IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
-    {
-      return ret;
-    }
-  /* we didn't do any device specific properties, so shove the property in our plist */
-  IMAGE_INSTANCE_WIDGET_PROPS (ii)
-    = Fplist_put (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, val);
-  return val;
 }
 
 /* Query for a widgets desired geometry. If no type specific method is
    provided then use the widget text to calculate sizes. */
-static void 
-widget_query_geometry (Lisp_Object image_instance, 
-		       unsigned int* width, unsigned int* height,
+static void
+widget_query_geometry (Lisp_Object image_instance,
+		       int* width, int* height,
 		       enum image_instance_geometry disp, Lisp_Object domain)
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
   struct image_instantiator_methods* meths;
+  Lisp_Object dynamic_width = Qnil;
+  Lisp_Object dynamic_height = Qnil;
 
   /* First just set up what we already have. */
   if (width)	*width = IMAGE_INSTANCE_WIDTH (ii);
   if (height)	*height = IMAGE_INSTANCE_HEIGHT (ii);
-  
+
   if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
       ||
       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
     {
       /* .. then try device specific methods ... */
-      meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
-				       IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+      meths = decode_device_ii_format (image_instance_device (image_instance),
+				       IMAGE_INSTANCE_WIDGET_TYPE (ii),
 				       ERROR_ME_NOT);
       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
-	IIFORMAT_METH (meths, query_geometry, (image_instance, 
+	IIFORMAT_METH (meths, query_geometry, (image_instance,
 					       width, height, disp,
 					       domain));
       else
 	{
 	  /* ... then format specific methods ... */
-	  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+	  meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
 					   ERROR_ME_NOT);
 	  if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
-	    IIFORMAT_METH (meths, query_geometry, (image_instance, 
+	    IIFORMAT_METH (meths, query_geometry, (image_instance,
 						   width, height, disp,
 						   domain));
-	  else 
+	  else
 	    {
-	      unsigned int w, h;
-	      
+	      int w, h;
+
 	      /* Then if we are allowed to resize the widget, make the
 		 size the same as the text dimensions. */
 	      query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
@@ -371,32 +415,49 @@
 		*height = h +  2 * WIDGET_BORDER_HEIGHT;
 	    }
 	}
+      /* Finish off with dynamic sizing. */
+      if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
+	{
+	  dynamic_width = Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
+	  if (INTP (dynamic_width))
+	    *width = XINT (dynamic_width);
+	}
+      if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
+	{
+	  dynamic_height = Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
+	  if (INTP (dynamic_height))
+	    *height = XINT (dynamic_height);
+	}
     }
 }
 
-static void 
-widget_layout (Lisp_Object image_instance, 
-	       unsigned int width, unsigned int height, Lisp_Object domain)
+static int
+widget_layout (Lisp_Object image_instance,
+	       int width, int height, int xoffset, int yoffset,
+	       Lisp_Object domain)
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
   struct image_instantiator_methods* meths;
 
   /* .. then try device specific methods ... */
-  meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii), 
-				   IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+  meths = decode_device_ii_format (image_instance_device (image_instance),
+				   IMAGE_INSTANCE_WIDGET_TYPE (ii),
 				   ERROR_ME_NOT);
   if (meths && HAS_IIFORMAT_METH_P (meths, layout))
-    IIFORMAT_METH (meths, layout, (image_instance, 
-				   width, height, domain));
+    return IIFORMAT_METH (meths, layout, (image_instance,
+					  width, height, xoffset, yoffset,
+					  domain));
   else
     {
       /* ... then format specific methods ... */
-      meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+      meths = decode_device_ii_format (Qnil, IMAGE_INSTANCE_WIDGET_TYPE (ii),
 				       ERROR_ME_NOT);
       if (meths && HAS_IIFORMAT_METH_P (meths, layout))
-	IIFORMAT_METH (meths, layout, (image_instance, 
-				       width, height, domain));
+	return IIFORMAT_METH (meths, layout, (image_instance,
+					      width, height, xoffset, yoffset,
+					      domain));
     }
+  return 1;
 }
 
 static void
@@ -405,38 +466,41 @@
   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
 
   if (NILP (desc))
-    signal_simple_error ("Must supply :descriptor", instantiator);
+    syntax_error ("Must supply :descriptor", instantiator);
 
   if (VECTORP (desc))
     gui_parse_item_keywords (desc);
 
   if (!NILP (find_keyword_in_vector (instantiator, Q_width))
       && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
-    signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
+    syntax_error ("Must supply only one of :width and :pixel-width", instantiator);
 
   if (!NILP (find_keyword_in_vector (instantiator, Q_height))
 	     && !NILP (find_keyword_in_vector (instantiator, Q_pixel_height)))
-    signal_simple_error ("Must supply only one of :height and :pixel-height", instantiator);
+    syntax_error ("Must supply only one of :height and :pixel-height", instantiator);
 }
 
 static void
 combo_box_validate (Lisp_Object instantiator)
 {
   widget_validate (instantiator);
-  if (NILP (find_keyword_in_vector (instantiator, Q_properties)))
-    signal_simple_error ("Must supply item list", instantiator);
+  if (NILP (find_keyword_in_vector (instantiator, Q_items)))
+    syntax_error ("Must supply item list", instantiator);
 }
 
 /* we need to convert things like glyphs to images, eval expressions
    etc.*/
 static Lisp_Object
-widget_normalize (Lisp_Object inst, Lisp_Object console_type)
+widget_normalize (Lisp_Object inst, Lisp_Object console_type,
+		  Lisp_Object dest_mask)
 {
   /* This function can call lisp */
   Lisp_Object glyph = find_keyword_in_vector (inst, Q_image);
 
   /* we need to eval glyph if its an expression, we do this for the
-     same reasons we normalize file to data. */
+     same reasons we normalize file to data.
+
+     #### should just normalize the data. */
   if (!NILP (glyph))
     {
       substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph));
@@ -453,9 +517,13 @@
   IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
   SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Qnil);
   IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item ();
+  IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Qnil;
+  IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
+  IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = Qnil;
+  IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = Qnil;
   IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 1;
   IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 1;
-  IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 0;
+  IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_HORIZONTAL;
   IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) = 0;
 }
 
@@ -470,6 +538,9 @@
 		    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
 		    int dest_mask, Lisp_Object domain)
 {
+  /* #### practically all of this should be moved to widget_update()
+     so that users can dynamically change all possible widget
+     properties. */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
   Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
@@ -478,78 +549,34 @@
   Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height);
   Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
-  Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties);
   Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
   Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
+  Lisp_Object mwidth = find_keyword_in_vector (instantiator, Q_margin_width);
+  Lisp_Object ifocus = find_keyword_in_vector (instantiator, Q_initial_focus);
   int pw=0, ph=0, tw=0, th=0;
-  
+
   /* this just does pixel type sizing */
   subwindow_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
 			 dest_mask, domain);
 
-  if (!(dest_mask & (IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK)))
-    incompatible_image_types (instantiator, dest_mask, 
-			      IMAGE_WIDGET_MASK | IMAGE_LAYOUT_MASK);
+  if (!(dest_mask & IMAGE_WIDGET_MASK))
+    incompatible_image_types (instantiator, dest_mask, IMAGE_WIDGET_MASK);
 
   initialize_widget_image_instance (ii, XVECTOR_DATA (instantiator)[0]);
 
   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
-  IMAGE_INSTANCE_WIDGET_PROPS (ii) = props;
 
   /* retrieve the fg and bg colors */
   if (!NILP (face))
     SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
-  
-  /* Do layout specific initialisation. This feels a bit tacky, but
-     the alternative is a myriad of different little functions. */
-  if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
-    {
-      Lisp_Object rest, children = Qnil;
-      Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
 
-      if (NILP (orient))
-	{
-	  IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
-	}
-      IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT;
-      
-      if (EQ (border, Qt))
-	{
-	  IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
-	}
-      else if (GLYPHP (border))
-	{
-	  /* We are going to be sneaky here and add the border text as
-	     just another child, the layout and output routines don't know
-	     this and will just display at the offsets we prescribe. */
-	  children = Fcons (glyph_image_instance (border, domain, ERROR_ME, 1),
-			    children);
-	  IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
-	}
-      else
-	{
-	  IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
-	}
-
-      /* Pick up the sub-widgets. */
-      LIST_LOOP (rest, items)
-	{
-	  /* make sure the image is instantiated */
-	  Lisp_Object gii = glyph_image_instance (XCAR (rest), domain, ERROR_ME, 1);
-	  children = Fcons (gii, children);
-	  /* Make sure elements in the layout are in the order the
-             user expected. */
-	  children = Fnreverse (children);
-	}
-      IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children;
-    }
   /* retrieve the gui item information. This is easy if we have been
      provided with a vector, more difficult if we have just been given
      keywords */
-  else if (STRINGP (desc) || NILP (desc))
+  if (STRINGP (desc) || NILP (desc))
     {
       /* big cheat - we rely on the fact that a gui item looks like an instantiator */
-      IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
+      IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
 	gui_parse_item_keywords_no_errors (instantiator);
       IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
     }
@@ -559,22 +586,15 @@
 
   /* Pick up the orientation before we do our first layout. */
   if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
-    IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = 1;
+    IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
 
   /* parse more gui items out of the properties */
-  if (!NILP (props)
-      && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout))
+  if (!NILP (items) && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
     {
-      if (NILP (items))
-	{
-	  items = Fplist_get (props, Q_items, Qnil);
-	}
-      if (!NILP (items))
-	{
-	  IMAGE_INSTANCE_WIDGET_ITEMS (ii) = 
-	    Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), 
-		   parse_gui_item_tree_children (items));
-	}
+      IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
+	Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
+	       parse_gui_item_tree_children (items));
     }
 
   /* Normalize size information. We now only assign sizes if the user
@@ -583,8 +603,13 @@
      geometry gets called. */
   if (!NILP (pixwidth))		/* pixwidth takes precendent */
     {
-      pw = XINT (pixwidth);
-      IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
+      if (!INTP (pixwidth))
+	IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii) = pixwidth;
+      else
+	{
+	  pw = XINT (pixwidth);
+	  IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
+	}
     }
   else if (!NILP (width))
     {
@@ -594,8 +619,13 @@
 
   if (!NILP (pixheight))
     {
-      ph = XINT (pixheight);
-      IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
+      if (!INTP (pixheight))
+	IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii) = pixheight;
+      else
+	{
+	  ph = XINT (pixheight);
+	  IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
+	}
     }
   else if (!NILP (height) && XINT (height) > 1)
     {
@@ -622,24 +652,32 @@
   if (!NILP (glyph))
     {
       if (!pw)
-	pw = glyph_width (glyph, domain) + 2 * WIDGET_BORDER_WIDTH;
+	pw = glyph_width (glyph, image_instance) + 2 * WIDGET_BORDER_WIDTH;
       if (!ph)
-	ph = glyph_height (glyph, domain) + 2 * WIDGET_BORDER_HEIGHT;
+	ph = glyph_height (glyph, image_instance) + 2 * WIDGET_BORDER_HEIGHT;
       IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii) = 0;
     }
 
-  /* When we create the widgets the window system expects a valid
-     size, so If we still don' t have sizes, call layout to pick them
-     up. If query_geometry or layout relies on the widget being in
-     existence then we are in catch 22. */
-  image_instance_layout (image_instance, 
-			 pw ? pw : IMAGE_UNSPECIFIED_GEOMETRY,
-			 ph ? ph : IMAGE_UNSPECIFIED_GEOMETRY,
-			 domain);
-  /* Layout has already been done so we don't need to re-layout. */
-  IMAGE_INSTANCE_DIRTYP (ii) = 0;
+  /* Pick up the margin width. */
+  if (!NILP (mwidth))
+    IMAGE_INSTANCE_MARGIN_WIDTH (ii) = XINT (mwidth);
+
+  IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (ii) = !NILP (ifocus);
 
+  /* Layout for the layout widget is premature at this point since the
+     children will not have been instantiated. We can't instantiate
+     them until the device instantiation method for the layout has
+     been executed. We do however want to record any specified
+     dimensions. */
+  if (pw)	IMAGE_INSTANCE_WIDTH (ii) = pw;
+  if (ph)	IMAGE_INSTANCE_HEIGHT (ii) = ph;
+}
+
+static void
+widget_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+			 Lisp_Object domain)
+{
 #ifdef DEBUG_WIDGETS
   debug_widget_instances++;
   stderr_out ("instantiated ");
@@ -648,16 +686,43 @@
 #endif
 }
 
+/* Get the geometry of a button control. We need to adjust the size
+   depending on the type of button. */
+static void
+button_query_geometry (Lisp_Object image_instance,
+		       int* width, int* height,
+		       enum image_instance_geometry disp, Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  int w, h;
+  query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
+			 IMAGE_INSTANCE_WIDGET_FACE (ii),
+			 &w, &h, 0, domain);
+  /* Adjust the size for borders. */
+  if (IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
+    {
+      *width = w + 2 * WIDGET_BORDER_WIDTH;
+
+      if (EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qradio)
+	  ||
+	  EQ (XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (ii))->style, Qtoggle))
+	/* This is an approximation to the size of the actual button bit. */
+	*width += 12;
+    }
+  if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
+    *height = h +  2 * WIDGET_BORDER_HEIGHT;
+}
+
 /* tree-view geometry - get the height right */
 static void
-tree_view_query_geometry (Lisp_Object image_instance, 
-			  unsigned int* width, unsigned int* height,
+tree_view_query_geometry (Lisp_Object image_instance,
+			  int* width, int* height,
 			  enum image_instance_geometry disp, Lisp_Object domain)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
 
-  
+
   if (*width)
     {
       /* #### what should this be. reconsider when X has tree views. */
@@ -677,23 +742,23 @@
 /* Get the geometry of a tab control. This is based on the number of
    items and text therin in the tab control. */
 static void
-tab_control_query_geometry (Lisp_Object image_instance, 
-			    unsigned int* width, unsigned int* height,
+tab_control_query_geometry (Lisp_Object image_instance,
+			    int* width, int* height,
 			    enum image_instance_geometry disp, Lisp_Object domain)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object items = IMAGE_INSTANCE_WIDGET_ITEMS (ii);
+  Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
   Lisp_Object rest;
-  unsigned int tw = 0, th = 0;
+  int tw = 0, th = 0;
 
   LIST_LOOP (rest, items)
     {
-      unsigned int h, w;
+      int h, w;
 
       query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
 			     IMAGE_INSTANCE_WIDGET_FACE (ii),
 			     &w, &h, 0, domain);
-      tw += 2 * WIDGET_BORDER_WIDTH; /* some bias */
+      tw += 5 * WIDGET_BORDER_WIDTH; /* some bias */
       tw += w;
       th = max (th, h + 2 * WIDGET_BORDER_HEIGHT);
     }
@@ -711,41 +776,263 @@
     }
 }
 
+/* Update the contents of a tab control. */
+static void
+tab_control_update (Lisp_Object image_instance,
+		    Lisp_Object instantiator)
+{
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+  /* Record new items for update. *_tab_control_redisplay will do the
+     rest. */
+  if (!NILP (items))
+    {
+      Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+      check_valid_item_list (items);
+#ifdef DEBUG_WIDGET_OUTPUT
+      stderr_out ("tab control %p updated\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
+#endif
+      /* Don't set the actual items since we might decide not to use
+         the new ones (because nothing has really changed). If we did
+         set them and didn't use them then we would get into whole
+         heaps of trouble when the old items get GC'd. */
+      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
+	Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
+	       parse_gui_item_tree_children (items));
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+    }
+}
+
+/* Determine whether only the order has changed for a tab. */
+int tab_control_order_only_changed (Lisp_Object image_instance)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  int found = 0, len, pending_len;
+  Lisp_Object rest;
+
+  /* Degenerate case. */
+  if (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+    return 1;
+
+  /* See whether we just need a change in order. */
+  GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_ITEMS (ii), len);
+  GET_LIST_LENGTH (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii),
+		   pending_len);
+  if (len == pending_len)
+    {
+      LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+	{
+	  Lisp_Object pending_rest;
+	  found = 0;
+	  LIST_LOOP (pending_rest,
+		     XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+	    {
+	      if (gui_item_equal_sans_selected (XCAR (rest),
+						XCAR (pending_rest), 0))
+		{
+		  found = 1;
+		  break;
+		}
+	    }
+	  if (!found)
+	    break;
+	}
+    }
+  return found;
+}
+
+/* Set the properties of a progress gauge */
+static void
+progress_gauge_update (Lisp_Object image_instance,
+		       Lisp_Object instantiator)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object value = find_keyword_in_vector (instantiator, Q_value);
+
+  if (!NILP (value))
+    {
+      CHECK_INT (value);
+#ifdef DEBUG_WIDGET_OUTPUT
+      stderr_out ("progress gauge value set to %ld\n", XINT (value));
+#endif
+      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
+	copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
+#ifdef ERROR_CHECK_GLYPHS
+      assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+#endif
+      if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+	XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = value;
+
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+    }
+}
+
 
 /*****************************************************************************
  *                              widget layout                               *
  *****************************************************************************/
-static int
-layout_possible_dest_types (void)
-{
-  return IMAGE_LAYOUT_MASK;
-}
-
-/* we need to convert things like glyphs to images, eval expressions
-   etc.*/
+/* We need to cascade normalization.*/
 static Lisp_Object
-layout_normalize (Lisp_Object inst, Lisp_Object console_type)
+layout_normalize (Lisp_Object inst, Lisp_Object console_type,
+		  Lisp_Object dest_mask)
 {
   /* This function can call lisp */
-  Lisp_Object items = find_keyword_in_vector (inst, Q_items);
-  Lisp_Object border = find_keyword_in_vector (inst, Q_border);
-  /* we need to eval glyph if its an expression, we do this for the
-     same reasons we normalize file to data. */
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object alist = Qnil, new_items = Qnil, border;
+  /* This function can call lisp */
+  Lisp_Object items;
+
+  GCPRO2 (alist, new_items);
+  alist = tagged_vector_to_alist (inst);
+  items = assq_no_quit (Q_items, alist);
+
+  /* We need to normalize sub-objects. */
   if (!NILP (items))
     {
       Lisp_Object rest;
-      LIST_LOOP (rest, items)
+      LIST_LOOP (rest, XCDR (items))
 	{
-	  /* substitute the new glyph */
-	  Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest)));
+	  /* Substitute the new instantiator */
+	  new_items = Fcons (normalize_image_instantiator (XCAR (rest),
+							   console_type, dest_mask),
+			     new_items);
+	}
+      new_items = Fnreverse (new_items);
+      Fsetcdr (items, new_items);
+    }
+  /* Normalize the border spec. */
+  border = assq_no_quit (Q_border, alist);
+  if (!NILP (border) && VECTORP (XCDR (border)))
+    {
+      Fsetcdr (border, normalize_image_instantiator (XCDR (border),
+						     console_type, dest_mask));
+    }
+
+  {
+    Lisp_Object result = alist_to_tagged_vector (XVECTOR_DATA (inst)[0],
+						 alist);
+    free_alist (alist);
+    RETURN_UNGCPRO (result);
+  }
+}
+
+/* Update the instances in the layout. */
+static void
+layout_update (Lisp_Object image_instance, Lisp_Object instantiator)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+  Lisp_Object border_inst = find_keyword_in_vector (instantiator, Q_border);
+  Lisp_Object border = Qnil;
+  Lisp_Object children = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
+  int structure_changed = 0;
+  struct gcpro gcpro1;
+
+  /* We want to avoid consing if we can. This is quite awkward because
+     we have to deal with the border as well as the items. */
+
+  GCPRO1 (border);
+
+  if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      border = XCAR (children);
+      children = XCDR (children);
+    }
+
+#ifdef DEBUG_WIDGET_OUTPUT
+  stderr_out ("layout updated\n");
+#endif
+  /* Update the border. */
+  if (!NILP (border_inst))
+    {
+      if (VECTORP (border_inst))
+	{
+	  /* We are going to be sneaky here and add the border text as
+	     just another child, the layout and output routines don't know
+	     this and will just display at the offsets we prescribe. */
+	  if (!NILP (border))
+	    call3 (Qset_glyph_image, border, border_inst,
+		   IMAGE_INSTANCE_DOMAIN (ii));
+	  else
+	    {
+	      border = Fcons (call1 (Qmake_glyph, border_inst), Qnil);
+	      structure_changed = 1;
+	    }
+	  IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
+	}
+      else
+	{
+	  if (!NILP (border))
+	    {
+	      border = Qnil;
+	      structure_changed = 1;
+	    }
+	  if (EQ (border_inst, Qt))
+	      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
+	  else
+	    IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border_inst;
 	}
     }
-  /* normalize the border spec. */
-  if (VECTORP (border) || CONSP (border))
+
+  /* Pick up the sub-widgets. */
+  if (!NILP (items))
     {
-      substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border));
+      int len1, len2;
+      GET_LIST_LENGTH (items, len1);
+      GET_LIST_LENGTH (children, len2);
+      /* The structure hasn't changed so just update the images. */
+      if (!structure_changed && len1 == len2)
+	{
+	  /* Pick up the sub-widgets. */
+	  for (; !NILP (children); children = XCDR (children), items = XCDR (items))
+	    {
+	      call3 (Qset_glyph_image, XCAR (children), XCAR (items),
+		     IMAGE_INSTANCE_DOMAIN (ii));
+	    }
+	}
+      /* The structure has changed so start over. */
+      else
+	{
+	  /* Instantiate any new glyphs. */
+	  for (; !NILP (items); items = XCDR (items))
+	    {
+	      border = Fcons (call1 (Qmake_glyph, XCAR (items)), border);
+	    }
+	  IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = Fnreverse (border);
+	}
     }
-  return inst;
+  UNGCPRO;
+}
+
+static void
+layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+		    Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+		    int dest_mask, Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
+
+#ifdef DEBUG_WIDGET_OUTPUT
+  stderr_out ("layout instantiated\n");
+#endif
+  /* Do widget type instantiation first. */
+  widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg,
+		      dest_mask, domain);
+
+  if (NILP (orient))
+    {
+      IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) = LAYOUT_VERTICAL;
+    }
+
+  /* Get child glyphs and finish instantiation. We can't do image
+     instance children yet as we might not have a containing
+     window. */
+  layout_update (image_instance, instantiator);
+}
+
+static void
+layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+			 Lisp_Object domain)
+{
 }
 
 /* Layout widget. Sizing commentary: we have a number of problems that
@@ -758,30 +1045,30 @@
    course these attributes can change dynamically and so the size
    should changed dynamically also. Only in a few limited cases should
    the size be fixed and remain fixed. Of course this actually means
-   that we don't really want to specifiy the size *at all* for most
+   that we don't really want to specify the size *at all* for most
    widgets - we want it to be discovered dynamically. Thus we can
    envisage the following scenarios:
-   
+
    1. A button is sized to accommodate its text, the text changes and the
-   button should change size also.  
+   button should change size also.
 
    2. A button is given an explicit size. Its size should never change.
 
    3. Layout is put inside an area. The size of the area changes, the
-   layout should change with it. 
+   layout should change with it.
 
    4. A button grows to accommodate additional text. The whitespace
    around it should be modified to cope with the new layout
-   requirements. 
+   requirements.
 
    5. A button grows. The area surrounding it should grow also if
-   possible. 
+   possible.
 
    What metrics are important?
    1. Actual width and height.
-   
+
    2. Whether the width and height are what the widget actually wants, or
-   whether it can grow or shrink. 
+   whether it can grow or shrink.
 
    Text glyphs are particularly troublesome since their metrics depend
    on the context in which they are being viewed. For instance they
@@ -797,106 +1084,141 @@
 /* Query the geometry of a layout widget. We assume that we can only
    get here if the size is not already fixed. */
 static void
-layout_query_geometry (Lisp_Object image_instance, unsigned int* width,
-		       unsigned int* height, enum image_instance_geometry disp,
+layout_query_geometry (Lisp_Object image_instance, int* width,
+		       int* height, enum image_instance_geometry disp,
 		       Lisp_Object domain)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii), rest;
   int maxph = 0, maxpw = 0, nitems = 0, ph_adjust = 0;
+  int gheight, gwidth;
+
+  /* If we are not initialized then we won't have any children. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+      return;
+
+  /* First just set up what we already have. */
+  if (width)	*width = IMAGE_INSTANCE_WIDTH (ii);
+  if (height)	*height = IMAGE_INSTANCE_HEIGHT (ii);
+
+  /* If we are not allowed to dynamically size then return. */
+  if (!IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii)
+      &&
+      !IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
+    return;
+
+  /* Pick up the border text if we have one. */
+  if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      glyph_query_geometry (XCAR (items), &gwidth, &gheight, disp,
+			    image_instance);
+      ph_adjust = gheight / 2;
+      items = XCDR (items);
+    }
 
   /* Flip through the items to work out how much stuff we have to display */
   LIST_LOOP (rest, items)
     {
       Lisp_Object glyph = XCAR (rest);
-      unsigned int gheight, gwidth;
-      
-      image_instance_query_geometry (glyph, &gwidth, &gheight, disp, domain);
+      glyph_query_geometry (glyph, &gwidth, &gheight, disp, image_instance);
 
-      /* Pick up the border text if we have one. */
-      if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
-	  && NILP (XCDR (rest)))
+      nitems ++;
+      if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	  == LAYOUT_HORIZONTAL)
 	{
-	  ph_adjust = gheight / 2;
+	  maxph = max (maxph, gheight);
+	  maxpw += gwidth;
 	}
       else
 	{
-
-	  nitems ++;
-	  if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-	      == LAYOUT_HORIZONTAL)
-	    {
-	      maxph = max (maxph, gheight);
-	      maxpw += gwidth;
-	    }
-	  else
-	    {
-	      maxpw = max (maxpw, gwidth);
-	      maxph += gheight;
-	    }
+	  maxpw = max (maxpw, gwidth);
+	  maxph += gheight;
 	}
     }
 
-  /* work out spacing between items and bounds of the layout.  No user
-      provided width so we just do default spacing. */
-  if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-      == LAYOUT_HORIZONTAL)
-    *width = maxpw + (nitems + 1) * WIDGET_BORDER_WIDTH * 2;
-  else 
-    *width = maxpw + 2 * WIDGET_BORDER_WIDTH * 2;
+  /* Work out minimum space we need to fit all the items. This could
+     have been fixed by the user. */
+  if (!NILP (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii)))
+    {
+      Lisp_Object dynamic_width =
+	Feval (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (ii));
+      if (INTP (dynamic_width))
+	*width = XINT (dynamic_width);
+    }
+  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	   == LAYOUT_HORIZONTAL)
+    *width = maxpw + ((nitems + 1) * WIDGET_BORDER_WIDTH +
+		      IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2;
+  else
+    *width = maxpw + 2 * (WIDGET_BORDER_WIDTH * 2 +
+			  IMAGE_INSTANCE_MARGIN_WIDTH (ii));
 
   /* Work out vertical spacings. */
-  if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-      == LAYOUT_VERTICAL)
-    *height = maxph + (nitems + 1) * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
-  else 
-    *height = maxph + 2 * WIDGET_BORDER_HEIGHT * 2 + ph_adjust;
+  if (!NILP (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii)))
+    {
+      Lisp_Object dynamic_height =
+	Feval (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (ii));
+      if (INTP (dynamic_height))
+	*height = XINT (dynamic_height);
+    }
+  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	   == LAYOUT_VERTICAL)
+    *height = maxph + ((nitems + 1) * WIDGET_BORDER_HEIGHT +
+		       IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
+  else
+    *height = maxph + (2 * WIDGET_BORDER_HEIGHT +
+		       IMAGE_INSTANCE_MARGIN_WIDTH (ii)) * 2 + ph_adjust;
 }
 
-
-static void
-layout_layout (Lisp_Object image_instance, 
-	       unsigned int width, unsigned int height, Lisp_Object domain)
+int
+layout_layout (Lisp_Object image_instance,
+	       int width, int height, int xoffset, int yoffset,
+	       Lisp_Object domain)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object rest;
   Lisp_Object items = IMAGE_INSTANCE_LAYOUT_CHILDREN (ii);
   int x, y, maxph = 0, maxpw = 0, nitems = 0,
     horiz_spacing, vert_spacing, ph_adjust = 0;
-  unsigned int gheight, gwidth;
+  int gheight, gwidth;
+
+  /* If we are not initialized then we won't have any children. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+      return 0;
 
-  /* flip through the items to work out how much stuff we have to display */
+  /* Pick up the border text if we have one. */
+  if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      Lisp_Object border = XCAR (items);
+      items = XCDR (items);
+      glyph_query_geometry (border, &gwidth, &gheight,
+			    IMAGE_DESIRED_GEOMETRY, image_instance);
+      ph_adjust = gheight / 2;
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
+
+      /* #### Really, what should this be? */
+      glyph_do_layout (border, gwidth, gheight, 10, 0,
+		       image_instance);
+    }
+
+  /* Flip through the items to work out how much stuff we have to display. */
   LIST_LOOP (rest, items)
     {
       Lisp_Object glyph = XCAR (rest);
-      
-      image_instance_query_geometry (glyph, &gwidth, &gheight, 
-				     IMAGE_DESIRED_GEOMETRY, domain);
 
-      /* Pick up the border text if we have one. */
-      if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
-	  && NILP (XCDR (rest)))
+      glyph_query_geometry (glyph, &gwidth, &gheight,
+			    IMAGE_DESIRED_GEOMETRY, image_instance);
+      nitems ++;
+      if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	  == LAYOUT_HORIZONTAL)
 	{
-	  XIMAGE_INSTANCE_XOFFSET (glyph) = 10; /* Really, what should this be? */
-	  XIMAGE_INSTANCE_YOFFSET (glyph) = 0;
-	  ph_adjust = gheight / 2;
-	  IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
+	  maxph = max (maxph, gheight);
+	  maxpw += gwidth;
 	}
       else
 	{
-
-	  nitems ++;
-	  if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-	      == LAYOUT_HORIZONTAL)
-	    {
-	      maxph = max (maxph, gheight);
-	      maxpw += gwidth;
-	    }
-	  else
-	    {
-	      maxpw = max (maxpw, gwidth);
-	      maxph += gheight;
-	    }
+	  maxpw = max (maxpw, gwidth);
+	  maxph += gheight;
 	}
     }
 
@@ -906,24 +1228,30 @@
        just provide default spacing and will let the output routines
        clip.. */
     horiz_spacing = WIDGET_BORDER_WIDTH * 2;
-  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
+  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
 	   == LAYOUT_HORIZONTAL)
     /* We have a larger area to display in so distribute the space
        evenly. */
-    horiz_spacing = (width - maxpw) / (nitems + 1);
+    horiz_spacing = (width - (maxpw +
+			      IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
+      / (nitems + 1);
   else
-    horiz_spacing = (width - maxpw) / 2;
+    horiz_spacing = (width - maxpw) / 2
+      - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
   if (height < maxph)
     vert_spacing = WIDGET_BORDER_HEIGHT * 2;
-  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
+  else if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
 	   == LAYOUT_VERTICAL)
-    vert_spacing = (height - (maxph + ph_adjust)) / (nitems + 1);
+    vert_spacing = (height - (maxph + ph_adjust +
+			      IMAGE_INSTANCE_MARGIN_WIDTH (ii) * 2))
+      / (nitems + 1);
   else
-    vert_spacing = (height - (maxph + ph_adjust)) / 2;
+    vert_spacing = (height - (maxph + ph_adjust)) / 2
+      - IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
-  y = vert_spacing + ph_adjust;
-  x = horiz_spacing;
+  y = vert_spacing + ph_adjust + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
+  x = horiz_spacing + IMAGE_INSTANCE_MARGIN_WIDTH (ii);
 
   /* Now flip through putting items where we want them, paying
      attention to justification. Make sure we don't mess with the
@@ -932,52 +1260,102 @@
     {
       Lisp_Object glyph = XCAR (rest);
 
-      image_instance_query_geometry (glyph, &gwidth, &gheight, 
-				     IMAGE_DESIRED_GEOMETRY, domain);
+      glyph_query_geometry (glyph, &gwidth, &gheight,
+			    IMAGE_DESIRED_GEOMETRY, image_instance);
+
+      if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	  == LAYOUT_HORIZONTAL)
+	{
+	  if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
+	      == LAYOUT_JUSTIFY_RIGHT)
+	    y = height - (gheight + vert_spacing);
+	  if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
+	      == LAYOUT_JUSTIFY_CENTER)
+	    y = (height - gheight) / 2;
+	}
+      else
+	{
+	  if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
+	      == LAYOUT_JUSTIFY_RIGHT)
+	    x = width - (gwidth + horiz_spacing);
+	  if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii)
+	      == LAYOUT_JUSTIFY_CENTER)
+	    x = (width - gwidth) / 2;
+	}
+
+      /* Now layout subwidgets if they require it. */
+      glyph_do_layout (glyph, gwidth, gheight, x, y, image_instance);
+
+      if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii)
+	  == LAYOUT_HORIZONTAL)
+	{
+	  x += (gwidth + horiz_spacing);
+	}
+      else
+	{
+	  y += (gheight + vert_spacing);
+	}
+
+    }
+  return 1;
+}
+
+/* Get the glyphs that comprise a layout. These are created internally
+   and so are otherwise inaccessible to lisp. We need some way of getting
+   properties from the widgets that comprise a layout and this is the
+   simplest way of doing it.
 
-      if (!INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
-	  || !NILP (XCDR (rest)))
-      {
-	if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-	    == LAYOUT_HORIZONTAL)
-	  {
-	    if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
-		== LAYOUT_JUSTIFY_RIGHT)
-	      y = height - (gheight + vert_spacing);
-	    if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
-		== LAYOUT_JUSTIFY_CENTER)
-	      y = (height - gheight) / 2;
-	  }
-	else 
-	  {
-	    if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
-		== LAYOUT_JUSTIFY_RIGHT)
-	      x = width - (gwidth + horiz_spacing);
-	    if (IMAGE_INSTANCE_SUBWINDOW_JUSTIFY (ii) 
-		== LAYOUT_JUSTIFY_CENTER)
-	      x = (width - gwidth) / 2;
-	  }
-	
-	XIMAGE_INSTANCE_XOFFSET (glyph) = x;
-	XIMAGE_INSTANCE_YOFFSET (glyph) = y;
-	
-	if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii) 
-	    == LAYOUT_HORIZONTAL)
-	  {
-	    x += (gwidth + horiz_spacing);
-	  }
-	else
-	  {
-	    y += (gheight + vert_spacing);
-	  }
-      }
-      
-      /* Now layout subwidgets if they require it. */
-      image_instance_layout (glyph, gwidth, gheight, domain);
+   #### Eventually we should allow some more intelligent access to
+   sub-widgets. */
+static Lisp_Object
+layout_property (Lisp_Object image_instance, Lisp_Object prop)
+{
+  /* This function can GC. */
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  if (EQ (prop, Q_items))
+    {
+      if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)) &&
+	  CONSP (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)))
+	return Fcopy_sequence (XCDR
+			       (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii)));
+      else
+	return Fcopy_sequence (IMAGE_INSTANCE_LAYOUT_CHILDREN (ii));
     }
+  return Qunbound;
+}
 
-  IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = width;
-  IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = height;
+/* Layout subwindows if they are real subwindows. */
+static int
+native_layout_layout (Lisp_Object image_instance,
+		      int width, int height, int xoffset, int yoffset,
+		      Lisp_Object domain)
+{
+  Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object rest;
+
+  /* The first time this gets called, the layout will be only
+     partially instantiated. The children get done in
+     post_instantiate. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+    return 0;
+
+  /* Defining this overrides the default layout_layout so we first have to call that to get
+     suitable instances and values set up. */
+  layout_layout (image_instance, width, height, xoffset, yoffset, domain);
+
+  LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (ii))
+    {
+      struct display_glyph_area dga;
+      dga.xoffset = 0;
+      dga.yoffset = 0;
+      dga.width = IMAGE_INSTANCE_WIDTH (ii);
+      dga.height = IMAGE_INSTANCE_HEIGHT (ii);
+
+      map_subwindow (XCAR (rest),
+		     IMAGE_INSTANCE_XOFFSET (ii),
+		     IMAGE_INSTANCE_YOFFSET (ii), &dga);
+    }
+  return 1;
 }
 
 
@@ -988,46 +1366,38 @@
 void
 syms_of_glyphs_widget (void)
 {
-  defkeyword (&Q_descriptor, ":descriptor");
-  defkeyword (&Q_height, ":height");
-  defkeyword (&Q_width, ":width");
-  defkeyword (&Q_properties, ":properties");
-  defkeyword (&Q_items, ":items");
-  defkeyword (&Q_image, ":image");
-  defkeyword (&Q_percent, ":percent");
-  defkeyword (&Q_text, ":text");
-  defkeyword (&Q_orientation, ":orientation");
-  defkeyword (&Q_justify, ":justify");
-  defkeyword (&Q_border, ":border");
-
-  defsymbol (&Qetched_in, "etched-in");
-  defsymbol (&Qetched_out, "etched-out");
-  defsymbol (&Qbevel_in, "bevel-in");
-  defsymbol (&Qbevel_out, "bevel-out");
+  DEFSYMBOL (Qetched_in);
+  DEFSYMBOL (Qetched_out);
+  DEFSYMBOL (Qbevel_in);
+  DEFSYMBOL (Qbevel_out);
+  DEFSYMBOL (Qmake_glyph);
 }
 
-#define VALID_GUI_KEYWORDS(type) do {							\
-  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything);		\
-  IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything);			\
-  IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string);				\
-  IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol);				\
-  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything);		\
-  IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything);			\
-  IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol);				\
-  IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything);			\
-  IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string);			\
-  IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string);			\
-  IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything);				\
-  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback);		\
-  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor, check_valid_string_or_vector);	\
+#define VALID_GUI_KEYWORDS(type) do {					      \
+  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_active, check_valid_anything);      \
+  IIFORMAT_VALID_KEYWORD (type, Q_suffix, check_valid_anything);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_keys, check_valid_string);		      \
+  IIFORMAT_VALID_KEYWORD (type, Q_style, check_valid_symbol);		      \
+  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_selected, check_valid_anything);    \
+  IIFORMAT_VALID_KEYWORD (type, Q_filter, check_valid_anything);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_config, check_valid_symbol);		      \
+  IIFORMAT_VALID_KEYWORD (type, Q_included, check_valid_anything);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_initial_focus, check_valid_anything);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_key_sequence, check_valid_string);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_accelerator, check_valid_string);	      \
+  IIFORMAT_VALID_KEYWORD (type, Q_label, check_valid_anything);		      \
+  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback, check_valid_callback);    \
+  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_callback_ex, check_valid_callback); \
+  IIFORMAT_VALID_NONCOPY_KEYWORD (type, Q_descriptor,			      \
+				  check_valid_string_or_vector);	      \
 } while (0)
 
-#define VALID_WIDGET_KEYWORDS(type) do {				\
-  IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int);		\
-  IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int);		\
-  IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int);	\
-  IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int);	\
-  IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face);		\
+#define VALID_WIDGET_KEYWORDS(type) do {				      \
+  IIFORMAT_VALID_KEYWORD (type, Q_width, check_valid_int);		      \
+  IIFORMAT_VALID_KEYWORD (type, Q_height, check_valid_int);		      \
+  IIFORMAT_VALID_KEYWORD (type, Q_pixel_width, check_valid_int_or_function);  \
+  IIFORMAT_VALID_KEYWORD (type, Q_pixel_height, check_valid_int_or_function); \
+  IIFORMAT_VALID_KEYWORD (type, Q_face, check_valid_face);		      \
 } while (0)
 
 
@@ -1035,7 +1405,7 @@
 { /* we only do this for properties */
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM (widget, "widget");
   IIFORMAT_HAS_METHOD (widget, property);
-  IIFORMAT_HAS_METHOD (widget, set_property);
+  IIFORMAT_HAS_METHOD (widget, update);
   IIFORMAT_HAS_METHOD (widget, query_geometry);
   IIFORMAT_HAS_METHOD (widget, layout);
 }
@@ -1046,9 +1416,12 @@
   IIFORMAT_HAS_SHARED_METHOD (button, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, post_instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget);
+  IIFORMAT_HAS_SHARED_METHOD (button, governing_domain, subwindow);
+  IIFORMAT_HAS_METHOD (button, query_geometry);
   IIFORMAT_VALID_KEYWORD (button,
-			  Q_image, check_valid_glyph_or_instantiator);
+			  Q_image, check_valid_instantiator);
   VALID_WIDGET_KEYWORDS (button);
   VALID_GUI_KEYWORDS (button);
 }
@@ -1059,6 +1432,8 @@
   IIFORMAT_HAS_SHARED_METHOD (edit_field, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (edit_field, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (edit_field, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit_field, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (edit_field, governing_domain, subwindow);
   VALID_WIDGET_KEYWORDS (edit_field);
   VALID_GUI_KEYWORDS (edit_field);
 }
@@ -1068,13 +1443,16 @@
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box");
   IIFORMAT_HAS_METHOD (combo_box, validate);
   IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (combo_box, governing_domain, subwindow);
+
   VALID_GUI_KEYWORDS (combo_box);
 
   IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int);
   IIFORMAT_VALID_KEYWORD (combo_box, Q_height, check_valid_int);
-  IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (combo_box, Q_pixel_width,
+			  check_valid_int_or_function);
   IIFORMAT_VALID_KEYWORD (combo_box, Q_face, check_valid_face);
-  IIFORMAT_VALID_KEYWORD (combo_box, Q_properties, check_valid_item_list);
+  IIFORMAT_VALID_KEYWORD (combo_box, Q_items, check_valid_item_list);
 }
 
 static void image_instantiator_scrollbar (void)
@@ -1083,10 +1461,14 @@
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (scrollbar, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (scrollbar, governing_domain, subwindow);
   VALID_GUI_KEYWORDS (scrollbar);
 
-  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width, check_valid_int);
-  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height, check_valid_int);
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_width,
+			  check_valid_int_or_function);
+  IIFORMAT_VALID_KEYWORD (scrollbar, Q_pixel_height,
+			  check_valid_int_or_function);
   IIFORMAT_VALID_KEYWORD (scrollbar, Q_face, check_valid_face);
 }
 
@@ -1096,8 +1478,13 @@
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
+  IIFORMAT_HAS_METHOD (progress_gauge, update);
   VALID_WIDGET_KEYWORDS (progress_gauge);
   VALID_GUI_KEYWORDS (progress_gauge);
+
+  IIFORMAT_VALID_KEYWORD (progress_gauge, Q_value, check_valid_int);
 }
 
 static void image_instantiator_tree_view (void)
@@ -1106,10 +1493,13 @@
   IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
+  IIFORMAT_HAS_SHARED_METHOD (tree_view, update, tab_control);
   IIFORMAT_HAS_METHOD (tree_view, query_geometry);
   VALID_WIDGET_KEYWORDS (tree_view);
   VALID_GUI_KEYWORDS (tree_view);
-  IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list);
+  IIFORMAT_VALID_KEYWORD (tree_view, Q_items, check_valid_item_list);
 }
 
 static void image_instantiator_tab_control (void)
@@ -1118,11 +1508,15 @@
   IIFORMAT_HAS_SHARED_METHOD (tab_control, validate, combo_box);
   IIFORMAT_HAS_SHARED_METHOD (tab_control, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (tab_control, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (tab_control, query_geometry);
+  IIFORMAT_HAS_METHOD (tab_control, update);
   VALID_WIDGET_KEYWORDS (tab_control);
   VALID_GUI_KEYWORDS (tab_control);
-  IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
-  IIFORMAT_VALID_KEYWORD (tab_control, Q_properties, check_valid_item_list);
+  IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation,
+			  check_valid_tab_orientation);
+  IIFORMAT_VALID_KEYWORD (tab_control, Q_items, check_valid_item_list);
 }
 
 static void image_instantiator_labels (void)
@@ -1130,25 +1524,53 @@
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
   IIFORMAT_HAS_SHARED_METHOD (label, possible_dest_types, widget);
   IIFORMAT_HAS_SHARED_METHOD (label, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (label, post_instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (label, governing_domain, subwindow);
   VALID_WIDGET_KEYWORDS (label);
   IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string);
 }
 
+#define VALID_LAYOUT_KEYWORDS(layout)					   \
+  VALID_WIDGET_KEYWORDS (layout);					   \
+  IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); \
+  IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);   \
+  IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);	   \
+  IIFORMAT_VALID_KEYWORD (layout, Q_margin_width, check_valid_int);	   \
+  IIFORMAT_VALID_KEYWORD (layout, Q_items,				   \
+			  check_valid_instantiator_list)
+
 static void image_instantiator_layout (void)
 {
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout");
-  IIFORMAT_HAS_METHOD (layout, possible_dest_types);
-  IIFORMAT_HAS_SHARED_METHOD (layout, instantiate, widget);
+  IIFORMAT_HAS_SHARED_METHOD (layout, possible_dest_types, widget);
+  IIFORMAT_HAS_METHOD (layout, instantiate);
+  IIFORMAT_HAS_METHOD (layout, post_instantiate);
+  IIFORMAT_HAS_SHARED_METHOD (layout, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (layout, normalize);
   IIFORMAT_HAS_METHOD (layout, query_geometry);
   IIFORMAT_HAS_METHOD (layout, layout);
-  IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int);
-  IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int);
-  IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation);
-  IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification);
-  IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border);
-  IIFORMAT_VALID_KEYWORD (layout, Q_items,
-			  check_valid_glyph_or_instantiator_list);
+  IIFORMAT_HAS_METHOD (layout, update);
+  IIFORMAT_HAS_METHOD (layout, property);
+
+  VALID_GUI_KEYWORDS (layout);
+  VALID_LAYOUT_KEYWORDS (layout);
+}
+
+static void image_instantiator_native_layout (void)
+{
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (native_layout, "native-layout");
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, possible_dest_types, widget);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, instantiate, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, post_instantiate, layout);
+  IIFORMAT_HAS_METHOD (native_layout, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, governing_domain, subwindow);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, normalize, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, query_geometry, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, layout, layout);
+  IIFORMAT_HAS_SHARED_METHOD (native_layout, property, layout);
+
+  VALID_GUI_KEYWORDS (native_layout);
+  VALID_LAYOUT_KEYWORDS (native_layout);
 }
 
 void
@@ -1164,6 +1586,7 @@
   image_instantiator_tab_control();
   image_instantiator_labels();
   image_instantiator_layout();
+  image_instantiator_native_layout();
 }
 
 void