+ if (!pw)
+ pw = glyph_width (glyph, image_instance) + 2 * widget_instance_border_width (ii);
+ if (!ph)
+ ph = glyph_height (glyph, image_instance) + 2 * widget_instance_border_width (ii);
+ IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii) = 0;
+ IMAGE_INSTANCE_SUBWINDOW_H_RESIZEP (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 ");
+ debug_print (instantiator);
+ stderr_out ("%d widgets instantiated\n", debug_widget_instances);
+#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 + 3 * widget_instance_border_width (ii);
+
+ 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 + 3 * widget_instance_border_width (ii);
+}
+
+/* Get the geometry of an edit field. */
+static void
+edit_field_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 + 4 * widget_instance_border_width (ii);
+ if (IMAGE_INSTANCE_SUBWINDOW_V_RESIZEP (ii))
+ *height = h + 4 * widget_instance_border_width (ii);
+}
+
+/* tree-view geometry - get the height right */
+static void
+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. */
+ query_string_geometry (IMAGE_INSTANCE_WIDGET_TEXT (ii),
+ IMAGE_INSTANCE_WIDGET_FACE (ii),
+ width, 0, 0, domain);
+ }
+ if (*height)
+ {
+ int len, h;
+ /* #### widget face would be better here. */
+ default_face_font_info (domain, 0, 0, &h, 0, 0);
+ GET_LIST_LENGTH (items, len);
+ *height = len * h;
+ }
+}
+
+/* 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,
+ int* width, int* height,
+ enum image_instance_geometry disp, Lisp_Object domain)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object items = XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
+ Lisp_Object rest;
+ int tw = 0, th = 0;
+
+ LIST_LOOP (rest, items)
+ {
+ int h, w;
+
+ query_string_geometry (XGUI_ITEM (XCAR (rest))->name,
+ IMAGE_INSTANCE_WIDGET_FACE (ii),
+ &w, &h, 0, domain);
+ tw += 5 * widget_instance_border_width (ii); /* some bias */
+ tw += w;
+ th = max (th, h + 2 * widget_instance_border_width (ii));
+ }
+
+ /* Fixup returned values depending on orientation. */
+ if (IMAGE_INSTANCE_SUBWINDOW_ORIENT (ii))
+ {
+ if (height) *height = tw;
+ if (width) *width = th;
+ }
+ else
+ {
+ if (height) *height = th;
+ if (width) *width = tw;
+ }
+}
+
+/* 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;
+ }