import -ko -b 1.1.3 XEmacs XEmacs-21_2 r21-2-35
[chise/xemacs-chise.git.1] / src / glyphs-widget.c
index b5881ca..bc3e829 100644 (file)
@@ -55,9 +55,12 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control);
 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 Q_image, Q_text, Q_orientation, Q_justify, Q_border;
+Lisp_Object Q_margin_width;
 Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out;
 
 #ifdef DEBUG_WIDGETS
@@ -149,6 +152,13 @@ check_valid_callback (Lisp_Object data)
 }
 
 static void
+check_valid_int_or_function (Lisp_Object data)
+{
+  if (!INTP (data) && !CONSP (data))
+    signal_simple_error ("must be an integer or expresssion", data);
+}
+
+static void
 check_valid_symbol (Lisp_Object data)
 {
     CHECK_SYMBOL (data);
@@ -265,7 +275,7 @@ widget_property (Lisp_Object image_instance, Lisp_Object prop)
     return Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), prop, Qnil);
 
   /* .. then try device specific methods ... */
-  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);
   if (meths && HAS_IIFORMAT_METH_P (meths, property))
@@ -291,10 +301,11 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v
   if (EQ (prop, Q_text))
     {
       IMAGE_INSTANCE_WIDGET_TEXT (ii) = val;
+      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);
   if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
@@ -320,15 +331,57 @@ widget_set_property (Lisp_Object image_instance, Lisp_Object prop, Lisp_Object v
   return val;
 }
 
+/* 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
+   *_set_property. Thus *_set_property 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. */
+void
+update_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 generic methods. 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. */
+  MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), update_widget, (ii));
+
+  /* Device-format specific methods */
+  meths = decode_device_ii_format (image_instance_device (widget), 
+                                  IMAGE_INSTANCE_WIDGET_TYPE (ii), 
+                                  ERROR_ME_NOT);
+  MAYBE_IIFORMAT_METH (meths, update, (widget));
+
+  /* Pick up the items we recorded earlier. */
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
+    {
+      IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
+       IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii);
+      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
+    }
+}
+
 /* 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,
+                      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);
@@ -339,7 +392,7 @@ widget_query_geometry (Lisp_Object image_instance,
       IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (ii))
     {
       /* .. then try device specific methods ... */
-      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);
       if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
@@ -357,7 +410,7 @@ widget_query_geometry (Lisp_Object image_instance,
                                                   domain));
          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. */
@@ -371,32 +424,46 @@ widget_query_geometry (Lisp_Object image_instance,
                *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 
+static int 
 widget_layout (Lisp_Object image_instance, 
-              unsigned int width, unsigned int height, Lisp_Object domain)
+              int width, int height, 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), 
+  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, domain));
   else
     {
       /* ... 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, layout))
-       IIFORMAT_METH (meths, layout, (image_instance, 
-                                      width, height, domain));
+       return IIFORMAT_METH (meths, layout, (image_instance, 
+                                             width, height, domain));
     }
+  return 1;
 }
 
 static void
@@ -453,9 +520,13 @@ initialize_widget_image_instance (Lisp_Image_Instance *ii, Lisp_Object type)
   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;
 }
 
@@ -481,15 +552,15 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   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);
   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]);
 
@@ -500,53 +571,10 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   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) = 
@@ -556,14 +584,16 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   else
     IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
       gui_parse_item_keywords_no_errors (desc);
-
+      
   /* 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))
+      && 
+      !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      && !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
     {
       if (NILP (items))
        {
@@ -583,8 +613,13 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
      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 +629,13 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 
   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)
     {
@@ -629,17 +669,23 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
       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);
+
+  /* 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,10 +694,37 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 #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,
+                         int* width, int* height,
                          enum image_instance_geometry disp, Lisp_Object domain)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
@@ -678,22 +751,22 @@ tree_view_query_geometry (Lisp_Object image_instance,
    items and text therin in the tab control. */
 static void
 tab_control_query_geometry (Lisp_Object image_instance, 
-                           unsigned int* width, unsigned int* height,
+                           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;
 
   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,16 +784,68 @@ tab_control_query_geometry (Lisp_Object image_instance,
     }
 }
 
+/* Get the geometry of a tab control. This is based on the number of
+   items and text therin in the tab control. */
+static Lisp_Object
+tab_control_set_property (Lisp_Object image_instance, 
+                         Lisp_Object prop,
+                         Lisp_Object val)
+{
+  /* Record new items for update. *_tab_control_update will do the
+     rest. */
+  if (EQ (prop, Q_items))
+    {
+      Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+
+      check_valid_item_list_1 (val);
+      
+      /* 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 (val));
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+
+      return Qt;
+    }
+  return Qunbound;
+}
+
+/* set the properties of a progres guage */
+static Lisp_Object
+progress_gauge_set_property (Lisp_Object image_instance,
+                            Lisp_Object prop,
+                            Lisp_Object val)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  if (EQ (prop, Q_value))
+    {
+      CHECK_INT (val);
+#ifdef DEBUG_WIDGET_OUTPUT
+      printf ("progress gauge value set to %ld\n", XINT (val));
+#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 = val;
+
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+
+      return Qt;
+    }
+  return Qunbound;
+}
+
 \f
 /*****************************************************************************
  *                              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.*/
 static Lisp_Object
@@ -748,6 +873,79 @@ layout_normalize (Lisp_Object inst, Lisp_Object console_type)
   return inst;
 }
 
+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);
+  Lisp_Object border = find_keyword_in_vector (instantiator, Q_border);
+
+  /* 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;
+    }
+      
+  if (EQ (border, Qt))
+    {
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = Qetched_in;
+    }
+  else
+    {
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border;
+    }
+  /* We don't do the children yet as we might not have a containing
+     window. */
+}
+
+static void
+layout_post_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                        Lisp_Object domain)
+{
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+  Lisp_Object rest, children = Qnil;
+
+  if (GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      /* 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. */
+      Lisp_Object gii = glyph_image_instance 
+       (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+        image_instance, ERROR_ME, 1);
+
+      if (!IMAGE_INSTANCEP (gii))
+       return;
+      /* make sure we are designated as the parent. */
+      XIMAGE_INSTANCE_PARENT (gii) = image_instance;
+      children = Fcons (gii, children);
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (0);
+    }
+
+  /* Pick up the sub-widgets. */
+  LIST_LOOP (rest, items)
+    {
+      /* make sure the image is instantiated */
+      Lisp_Object gii = glyph_image_instance (XCAR (rest), 
+                                             image_instance, ERROR_ME, 1);
+      if (!IMAGE_INSTANCEP (gii))
+       return;
+      /* make sure we are designated as the parent. */
+      XIMAGE_INSTANCE_PARENT (gii) = image_instance;
+      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;
+}
+
 /* Layout widget. Sizing commentary: we have a number of problems that
    we would like to address. Some consider some of these more
    important than others. It used to be that size information was
@@ -797,106 +995,140 @@ layout_normalize (Lisp_Object inst, Lisp_Object console_type)
 /* 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)))
+    {
+      image_instance_query_geometry (XCAR (items), &gwidth, &gheight, disp, domain);
+      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);
 
-      /* 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;
+  /* 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;
+    *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
+int
 layout_layout (Lisp_Object image_instance, 
-              unsigned int width, unsigned int height, Lisp_Object domain)
+              int width, int height, 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;
 
-  /* flip through the items to work out how much stuff we have to display */
+  /* If we are not initialized then we won't have any children. */
+  if (!IMAGE_INSTANCE_INITIALIZED (ii))
+      return 0;
+
+  /* Pick up the border text if we have one. */
+  if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (ii)))
+    {
+      Lisp_Object border = XCAR (items);
+      items = XCDR (items);
+      image_instance_query_geometry (border, &gwidth, &gheight,
+                                    IMAGE_DESIRED_GEOMETRY, domain);
+      /* #### Really, what should this be? */
+      XIMAGE_INSTANCE_XOFFSET (border) = 10;
+      XIMAGE_INSTANCE_YOFFSET (border) = 0;
+      ph_adjust = gheight / 2;
+      IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust);
+
+      image_instance_layout (border, gwidth, gheight, domain);
+    }
+
+  /* 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)))
+      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;
        }
     }
 
@@ -910,20 +1142,26 @@ layout_layout (Lisp_Object image_instance,
           == 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) 
           == 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
@@ -935,49 +1173,77 @@ layout_layout (Lisp_Object image_instance,
       image_instance_query_geometry (glyph, &gwidth, &gheight, 
                                     IMAGE_DESIRED_GEOMETRY, domain);
 
-      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;
-         }
+      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;
+      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);
-         }
-      }
+      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);
     }
+  return 1;
+}
 
-  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,
+                     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, 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;
 }
 
 \f
@@ -994,11 +1260,11 @@ syms_of_glyphs_widget (void)
   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");
+  defkeyword (&Q_margin_width, ":margin-width");
 
   defsymbol (&Qetched_in, "etched-in");
   defsymbol (&Qetched_out, "etched-out");
@@ -1019,14 +1285,15 @@ syms_of_glyphs_widget (void)
   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_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)
 
@@ -1046,7 +1313,10 @@ static void image_instantiator_buttons (void)
   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);
   VALID_WIDGET_KEYWORDS (button);
@@ -1059,6 +1329,8 @@ static void image_instantiator_edit_fields (void)
   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,11 +1340,13 @@ static void image_instantiator_combo_box (void)
   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);
 }
@@ -1083,10 +1357,12 @@ static void image_instantiator_scrollbar (void)
   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,6 +1372,9 @@ static void image_instantiator_progress_guage (void)
   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, set_property);
   VALID_WIDGET_KEYWORDS (progress_gauge);
   VALID_GUI_KEYWORDS (progress_gauge);
 }
@@ -1106,6 +1385,8 @@ static void image_instantiator_tree_view (void)
   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_METHOD (tree_view, query_geometry);
   VALID_WIDGET_KEYWORDS (tree_view);
   VALID_GUI_KEYWORDS (tree_view);
@@ -1118,7 +1399,10 @@ static void image_instantiator_tab_control (void)
   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, set_property);
   VALID_WIDGET_KEYWORDS (tab_control);
   VALID_GUI_KEYWORDS (tab_control);
   IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation, check_valid_tab_orientation);
@@ -1130,25 +1414,50 @@ static void image_instantiator_labels (void)
   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_glyph_or_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);
+
+  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);
+
+  VALID_GUI_KEYWORDS (native_layout);
+  VALID_LAYOUT_KEYWORDS (native_layout);
 }
 
 void
@@ -1164,6 +1473,7 @@ image_instantiator_format_create_glyphs_widget (void)
   image_instantiator_tab_control();
   image_instantiator_labels();
   image_instantiator_layout();
+  image_instantiator_native_layout();
 }
 
 void