(IU+25133): Add intermediate glyph nodes.
[chise/xemacs-chise.git.1] / src / glyphs-x.c
index 0651929..105bbff 100644 (file)
@@ -4,7 +4,7 @@
    Copyright (C) 1995 Tinker Systems
    Copyright (C) 1995, 1996 Ben Wing
    Copyright (C) 1995 Sun Microsystems
    Copyright (C) 1995 Tinker Systems
    Copyright (C) 1995, 1996 Ben Wing
    Copyright (C) 1995 Sun Microsystems
-   Copyright (C) 1999, 2000 Andy Piper
+   Copyright (C) 1999, 2000, 2002 Andy Piper
 
 This file is part of XEmacs.
 
 
 This file is part of XEmacs.
 
@@ -17,7 +17,6 @@ XEmacs is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
-
 You should have received a copy of the GNU General Public License
 along with XEmacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 You should have received a copy of the GNU General Public License
 along with XEmacs; see the file COPYING.  If not, write to
 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
@@ -25,6 +24,8 @@ Boston, MA 02111-1307, USA.  */
 
 /* Synched up with: Not in FSF. */
 
 
 /* Synched up with: Not in FSF. */
 
+/* 7-8-00 This file is more or less Mule-ized in my Mule workspace. */
+
 /* Original author: Jamie Zawinski for 19.8
    font-truename stuff added by Jamie Zawinski for 19.10
    subwindow support added by Chuck Thompson
 /* Original author: Jamie Zawinski for 19.8
    font-truename stuff added by Jamie Zawinski for 19.10
    subwindow support added by Chuck Thompson
@@ -98,7 +99,6 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
-DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
 #ifdef HAVE_JPEG
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
 #endif
 #ifdef HAVE_JPEG
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
 #endif
@@ -128,7 +128,9 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (font);
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
 
 #ifdef HAVE_WIDGETS
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect);
 
 #ifdef HAVE_WIDGETS
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
 DEFINE_DEVICE_IIFORMAT (x, widget);
 DEFINE_DEVICE_IIFORMAT (x, widget);
+DEFINE_DEVICE_IIFORMAT (x, native_layout);
 DEFINE_DEVICE_IIFORMAT (x, button);
 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
 DEFINE_DEVICE_IIFORMAT (x, edit_field);
 DEFINE_DEVICE_IIFORMAT (x, button);
 DEFINE_DEVICE_IIFORMAT (x, progress_gauge);
 DEFINE_DEVICE_IIFORMAT (x, edit_field);
@@ -154,6 +156,10 @@ static void
 update_tab_widget_face (widget_value* wv,
                        Lisp_Image_Instance* ii, Lisp_Object domain);
 #endif
 update_tab_widget_face (widget_value* wv,
                        Lisp_Image_Instance* ii, Lisp_Object domain);
 #endif
+void
+emacs_Xt_handle_widget_losing_focus (struct frame* f, Widget losing_widget);
+void
+enqueue_focus_event (Widget wants_it, Lisp_Object frame, int in_p);
 
 #include "bitmaps.h"
 
 
 #include "bitmaps.h"
 
@@ -227,7 +233,8 @@ convert_EImage_to_XImage (Lisp_Object device, int width, int height,
   if (vis->class == PseudoColor)
     {
       unsigned long pixarray[256];
   if (vis->class == PseudoColor)
     {
       unsigned long pixarray[256];
-      int pixcount, n;
+      int pixcount;
+      unsigned int n;
       /* use our quantize table to allocate the colors */
       pixcount = 32;
       *pixtbl = xnew_array (unsigned long, pixcount);
       /* use our quantize table to allocate the colors */
       pixcount = 32;
       *pixtbl = xnew_array (unsigned long, pixcount);
@@ -264,7 +271,7 @@ convert_EImage_to_XImage (Lisp_Object device, int width, int height,
              gr = *ip++;
              bl = *ip++;
              conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
              gr = *ip++;
              bl = *ip++;
              conv.val = pixarray[QUANT_GET_COLOR(qtable,rd,gr,bl)];
-#if WORDS_BIGENDIAN
+#ifdef WORDS_BIGENDIAN
              if (outimg->byte_order == MSBFirst)
                for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
              else
              if (outimg->byte_order == MSBFirst)
                for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
              else
@@ -339,7 +346,7 @@ convert_EImage_to_XImage (Lisp_Object device, int width, int height,
                bl = *ip++ >> (8 - bbits);
 
              conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
                bl = *ip++ >> (8 - bbits);
 
              conv.val = (rd << rshift) | (gr << gshift) | (bl << bshift);
-#if WORDS_BIGENDIAN
+#ifdef WORDS_BIGENDIAN
              if (outimg->byte_order == MSBFirst)
                for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
              else
              if (outimg->byte_order == MSBFirst)
                for (q = 4-byte_cnt; q < 4; q++) *dp++ = conv.cp[q];
              else
@@ -394,11 +401,14 @@ x_finalize_image_instance (Lisp_Image_Instance *p)
   if (!p->data)
     return;
 
   if (!p->data)
     return;
 
-  if (DEVICE_LIVE_P (XDEVICE (p->device)))
+  if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
     {
     {
-      Display *dpy = DEVICE_X_DISPLAY (XDEVICE (p->device));
-
-      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
+      Display *dpy = DEVICE_X_DISPLAY
+       (XDEVICE (IMAGE_INSTANCE_DEVICE (p)));
+      if (0)
+       ;
+#ifdef HAVE_WIDGETS
+      else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET)
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
            {
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
            {
@@ -408,10 +418,15 @@ x_finalize_image_instance (Lisp_Image_Instance *p)
 #endif
              lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
              lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
 #endif
              lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p));
              lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
+
+             /* We can release the callbacks again. */
+             ungcpro_popup_callbacks (IMAGE_INSTANCE_X_WIDGET_LWID (p));
+
              IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
              IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
            }
        }
              IMAGE_INSTANCE_X_WIDGET_ID (p) = 0;
              IMAGE_INSTANCE_X_CLIPWIDGET (p) = 0;
            }
        }
+#endif
       else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
       else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
        {
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
@@ -420,7 +435,7 @@ x_finalize_image_instance (Lisp_Image_Instance *p)
        }
       else
        {
        }
       else
        {
-         int i;
+         unsigned int i;
          if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
            disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
 
          if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p))
            disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p));
 
@@ -691,7 +706,7 @@ write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
   /* Get the data while doing the conversion */
   while (1)
     {
   /* Get the data while doing the conversion */
   while (1)
     {
-      ssize_t size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
+      Lstream_data_count size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
       if (!size_in_bytes)
        break;
       /* It does seem the flushes are necessary... */
       if (!size_in_bytes)
        break;
       /* It does seem the flushes are necessary... */
@@ -786,7 +801,7 @@ generate_cursor_fg_bg (Lisp_Object device, Lisp_Object *foreground,
   else
     {
       xbg->pixel = 0;
   else
     {
       xbg->pixel = 0;
-      xbg->red = xbg->green = xbg->blue = ~0;
+      xbg->red = xbg->green = xbg->blue = USHRT_MAX;
     }
 }
 
     }
 }
 
@@ -990,12 +1005,13 @@ int read_bitmap_data_from_file (const char *filename, unsigned int *width,
 static Pixmap
 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
                        /* Note that data is in ext-format! */
 static Pixmap
 pixmap_from_xbm_inline (Lisp_Object device, int width, int height,
                        /* Note that data is in ext-format! */
-                       const Extbyte *bits)
+                       const char *bits)
 {
 {
-  return XCreatePixmapFromBitmapData (DEVICE_X_DISPLAY (XDEVICE(device)),
-                                     XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
-                                     (char *) bits, width, height,
-                                     1, 0, 1);
+  return XCreatePixmapFromBitmapData
+    (DEVICE_X_DISPLAY (XDEVICE (device)),
+     XtWindow (DEVICE_XT_APP_SHELL (XDEVICE (device))),
+     (char *) bits, width, height,
+     1, 0, 1);
 }
 
 /* Given inline data for a mono pixmap, initialize the given
 }
 
 /* Given inline data for a mono pixmap, initialize the given
@@ -1134,7 +1150,7 @@ init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
       break;
 
     default:
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 }
 
     }
 }
 
@@ -1154,13 +1170,11 @@ xbm_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
     {
       const char *ext_data;
 
     {
       const char *ext_data;
 
-      TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (mask_data))),
-                         C_STRING_ALLOCA, ext_data,
-                         Qbinary);
+      LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (mask_data))), ext_data, Qbinary);
       mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
                                     XINT (XCAR (mask_data)),
                                     XINT (XCAR (XCDR (mask_data))),
       mask = pixmap_from_xbm_inline (IMAGE_INSTANCE_DEVICE (ii),
                                     XINT (XCAR (mask_data)),
                                     XINT (XCAR (XCDR (mask_data))),
-                                    (const unsigned char *) ext_data);
+                                    ext_data);
     }
 
   init_image_instance_from_xbm_inline (ii, width, height, bits,
     }
 
   init_image_instance_from_xbm_inline (ii, width, height, bits,
@@ -1180,9 +1194,7 @@ x_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 
   assert (!NILP (data));
 
 
   assert (!NILP (data));
 
-  TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (XCDR (XCDR (data))),
-                     C_STRING_ALLOCA, ext_data,
-                     Qbinary);
+  LISP_STRING_TO_EXTERNAL (XCAR (XCDR (XCDR (data))), ext_data, Qbinary);
 
   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
                     pointer_bg, dest_mask, XINT (XCAR (data)),
 
   xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
                     pointer_bg, dest_mask, XINT (XCAR (data)),
@@ -1265,7 +1277,7 @@ extract_xpm_color_names (XpmAttributes *xpmattrs, Lisp_Object device,
       /* Duplicate the pixel value so that we still have a lock on it if
         the pixel we were passed is later freed. */
       if (! XAllocColor (dpy, cmap, &color))
       /* Duplicate the pixel value so that we still have a lock on it if
         the pixel we were passed is later freed. */
       if (! XAllocColor (dpy, cmap, &color))
-       abort ();  /* it must be allocable since we're just duplicating it */
+       ABORT ();  /* it must be allocable since we're just duplicating it */
 
       symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
       symbols [i].pixel = color.pixel;
 
       symbols [i].name = (char *) XSTRING_DATA (XCAR (cons));
       symbols [i].pixel = color.pixel;
@@ -1620,7 +1632,7 @@ x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
       break;
 
     default:
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 
   xpm_free (&xpmattrs);        /* after we've read pixels and hotspot */
     }
 
   xpm_free (&xpmattrs);        /* after we've read pixels and hotspot */
@@ -1661,15 +1673,14 @@ x_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 {
   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
   int i, stattis;
 {
   Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
   int i, stattis;
-  char *p, *bits, *bp;
+  char *bits, *bp;
+  const char *p;
   const char * volatile emsg = 0;
   const char * volatile dstring;
 
   assert (!NILP (data));
 
   const char * volatile emsg = 0;
   const char * volatile dstring;
 
   assert (!NILP (data));
 
-  TO_EXTERNAL_FORMAT (LISP_STRING, data,
-                     C_STRING_ALLOCA, dstring,
-                     Qbinary);
+  LISP_STRING_TO_EXTERNAL (data, dstring, Qbinary);
 
   if ((p = strchr (dstring, ':')))
     {
 
   if ((p = strchr (dstring, ':')))
     {
@@ -1733,7 +1744,8 @@ autodetect_validate (Lisp_Object instantiator)
 
 static Lisp_Object
 autodetect_normalize (Lisp_Object instantiator,
 
 static Lisp_Object
 autodetect_normalize (Lisp_Object instantiator,
-                     Lisp_Object console_type)
+                     Lisp_Object console_type,
+                     Lisp_Object dest_mask)
 {
   Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
   Lisp_Object filename = Qnil;
 {
   Lisp_Object file = find_keyword_in_vector (instantiator, Q_data);
   Lisp_Object filename = Qnil;
@@ -1841,9 +1853,7 @@ autodetect_instantiate (Lisp_Object image_instance,
   if (dest_mask & IMAGE_POINTER_MASK)
     {
       const char *name_ext;
   if (dest_mask & IMAGE_POINTER_MASK)
     {
       const char *name_ext;
-      TO_EXTERNAL_FORMAT (LISP_STRING, data,
-                         C_STRING_ALLOCA, name_ext,
-                         Qfile_name);
+      LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
       if (XmuCursorNameToIndex (name_ext) != -1)
         {
           result = alist_to_tagged_vector (Qcursor_font, alist);
       if (XmuCursorNameToIndex (name_ext) != -1)
         {
           result = alist_to_tagged_vector (Qcursor_font, alist);
@@ -2043,9 +2053,7 @@ cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   if (!(dest_mask & IMAGE_POINTER_MASK))
     incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
 
   if (!(dest_mask & IMAGE_POINTER_MASK))
     incompatible_image_types (instantiator, dest_mask, IMAGE_POINTER_MASK);
 
-  TO_EXTERNAL_FORMAT (LISP_STRING, data,
-                     C_STRING_ALLOCA, name_ext,
-                     Qfile_name);
+  LISP_STRING_TO_EXTERNAL (data, name_ext, Qfile_name);
   if ((i = XmuCursorNameToIndex (name_ext)) == -1)
     signal_simple_error ("Unrecognized cursor-font name", data);
 
   if ((i = XmuCursorNameToIndex (name_ext)) == -1)
     signal_simple_error ("Unrecognized cursor-font name", data);
 
@@ -2127,6 +2135,12 @@ x_unmap_subwindow (Lisp_Image_Instance *p)
     }
   else                         /* must be a widget */
     {
     }
   else                         /* must be a widget */
     {
+      /* Since we are being unmapped we want the enclosing frame to
+        get focus. The losing with simple scrolling but is the safest
+        thing to do. */
+      emacs_Xt_handle_widget_losing_focus 
+       ( XFRAME (IMAGE_INSTANCE_FRAME (p)),
+         IMAGE_INSTANCE_X_WIDGET_ID (p));
       XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
     }
 }
       XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
     }
 }
@@ -2137,6 +2151,7 @@ static void
 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                 struct display_glyph_area* dga)
 {
 x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                 struct display_glyph_area* dga)
 {
+  assert (dga->width > 0 && dga->height > 0);
   if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
     {
       Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
   if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
     {
       Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p);
@@ -2145,8 +2160,9 @@ x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                         x, y, dga->width, dga->height);
       XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
                   subwindow, -dga->xoffset, -dga->yoffset);
                         x, y, dga->width, dga->height);
       XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
                   subwindow, -dga->xoffset, -dga->yoffset);
-      XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
-                 IMAGE_INSTANCE_X_CLIPWINDOW (p));
+      if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
+       XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p),
+                   IMAGE_INSTANCE_X_CLIPWINDOW (p));
     }
   else                         /* must be a widget */
     {
     }
   else                         /* must be a widget */
     {
@@ -2156,14 +2172,23 @@ x_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                         dga->width, dga->height, 0);
       XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
                    -dga->xoffset, -dga->yoffset);
                         dga->width, dga->height, 0);
       XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p),
                    -dga->xoffset, -dga->yoffset);
-      XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
+      if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
+       XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p));
+      /* See comments in glyphs-msw.c about keyboard focus. */
+      if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p)) {
+       /* #### FIXME to pop-up the find dialog we map the text-field
+          seven times! This doesn't show on a fast linux box but does
+          under X on windows. */
+       enqueue_focus_event (IMAGE_INSTANCE_X_WIDGET_ID (p),
+                            IMAGE_INSTANCE_FRAME (p), 1);
+      }
     }
 }
 
 /* when you click on a widget you may activate another widget this
    needs to be checked and all appropriate widgets updated */
 static void
     }
 }
 
 /* when you click on a widget you may activate another widget this
    needs to be checked and all appropriate widgets updated */
 static void
-x_update_subwindow (Lisp_Image_Instance *p)
+x_redisplay_subwindow (Lisp_Image_Instance *p)
 {
   /* Update the subwindow size if necessary. */
   if (IMAGE_INSTANCE_SIZE_CHANGED (p))
 {
   /* Update the subwindow size if necessary. */
   if (IMAGE_INSTANCE_SIZE_CHANGED (p))
@@ -2178,7 +2203,7 @@ x_update_subwindow (Lisp_Image_Instance *p)
 /* Update all attributes that have changed. Lwlib actually does most
    of this for us. */
 static void
 /* Update all attributes that have changed. Lwlib actually does most
    of this for us. */
 static void
-x_update_widget (Lisp_Image_Instance *p)
+x_redisplay_widget (Lisp_Image_Instance *p)
 {
   /* This function can GC if IN_REDISPLAY is false. */
 #ifdef HAVE_WIDGETS
 {
   /* This function can GC if IN_REDISPLAY is false. */
 #ifdef HAVE_WIDGETS
@@ -2189,35 +2214,42 @@ x_update_widget (Lisp_Image_Instance *p)
      need to update most other things after the items have changed.*/
   if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
     {
      need to update most other things after the items have changed.*/
   if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
     {
-      /* Pick up the items we recorded earlier. We do this here so
-         that the callbacks get set up with the new items. */
-      IMAGE_INSTANCE_WIDGET_ITEMS (p) =
-       IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p);
-      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p) = Qnil;
+      Lisp_Object image_instance;
 
 
+      XSETIMAGE_INSTANCE (image_instance, p);
       wv = gui_items_to_widget_values
       wv = gui_items_to_widget_values
-       (IMAGE_INSTANCE_WIDGET_ITEMS (p));
+       (image_instance, IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p),
+        /* #### this is not right; we need to keep track of which widgets
+           want accelerators and which don't */ 0);
       wv->change = STRUCTURAL_CHANGE;
       wv->change = STRUCTURAL_CHANGE;
-      /* now modify the widget */
-      lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
-                            wv, True);
-      free_widget_value_tree (wv);
     }
     }
-
-  /* Now do non structural updates. */
-  wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (p));
-
-  if (!wv)
-    return;
+  else
+    {
+      /* Assume the lotus position, breath deeply and chant to
+        yourself lwlibsux, lwlibsux ... lw_get_all_values returns a
+        reference to the real values rather than a copy thus any
+        changes we make to the values we get back will look like they
+        have already been applied. If we rebuild the widget tree then
+        we may lose properties. */
+      wv = copy_widget_value_tree (lw_get_all_values 
+                                  (IMAGE_INSTANCE_X_WIDGET_LWID (p)),
+                                  NO_CHANGE);
+    }
 
   /* Possibly update the colors and font */
 
   /* Possibly update the colors and font */
-  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) 
+  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       ||
       ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (p))->faces_changed
+      /* #### This is not sufficient because it will not cope with widgets
+        that are not currently visible. Once redisplay has done the
+        visible ones it will clear this flag so that when new ones
+        become visible they will not be updated. */
+      XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
+      ||
+      XFRAME (IMAGE_INSTANCE_FRAME (p))->frame_changed
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
     {
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
     {
-      update_widget_face (wv, p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p));
+      update_widget_face (wv, p, IMAGE_INSTANCE_FRAME (p));
     }
 
   /* Possibly update the text. */
     }
 
   /* Possibly update the text. */
@@ -2225,16 +2257,16 @@ x_update_widget (Lisp_Image_Instance *p)
     {
       char* str;
       Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
     {
       char* str;
       Lisp_Object val = IMAGE_INSTANCE_WIDGET_TEXT (p);
-      TO_EXTERNAL_FORMAT (LISP_STRING, val,
-                         C_STRING_ALLOCA, str,
-                         Qnative);
+      LISP_STRING_TO_EXTERNAL (val, str, Qnative);
       wv->value = str;
     }
 
   /* Possibly update the size. */
   if (IMAGE_INSTANCE_SIZE_CHANGED (p)
       ||
       wv->value = str;
     }
 
   /* Possibly update the size. */
   if (IMAGE_INSTANCE_SIZE_CHANGED (p)
       ||
-      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)
+      ||
+      IMAGE_INSTANCE_TEXT_CHANGED (p))
     {
       assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
              IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
     {
       assert (IMAGE_INSTANCE_X_WIDGET_ID (p) &&
              IMAGE_INSTANCE_X_CLIPWIDGET (p)) ;
@@ -2253,9 +2285,20 @@ x_update_widget (Lisp_Image_Instance *p)
                               (Dimension)IMAGE_INSTANCE_HEIGHT (p));
     }
 
                               (Dimension)IMAGE_INSTANCE_HEIGHT (p));
     }
 
+  /* Adjust offsets within the frame. */
+  if (XFRAME (IMAGE_INSTANCE_FRAME (p))->size_changed)
+    {
+      Arg al[2];
+      XtSetArg (al [0], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (p));
+      XtSetArg (al [1], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (p));
+      XtGetValues (FRAME_X_TEXT_WIDGET 
+                  (XFRAME (IMAGE_INSTANCE_FRAME (p))), al, 2);
+    }
+
   /* now modify the widget */
   lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
   /* now modify the widget */
   lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
-                        wv, False);
+                        wv, True);
+  free_widget_value_tree (wv);
 #endif
 }
 
 #endif
 }
 
@@ -2268,15 +2311,15 @@ x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   /* This function can GC */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
   /* This function can GC */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   Display *dpy;
   Screen *xs;
   Window pw, win;
   XSetWindowAttributes xswa;
   Mask valueMask = 0;
   struct frame* f = XFRAME (frame);
   Display *dpy;
   Screen *xs;
   Window pw, win;
   XSetWindowAttributes xswa;
   Mask valueMask = 0;
-  unsigned int w = IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii),
-    h = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii);
+  unsigned int w = IMAGE_INSTANCE_WIDTH (ii),
+    h = IMAGE_INSTANCE_HEIGHT (ii);
 
   if (!DEVICE_X_P (XDEVICE (device)))
     signal_simple_error ("Not an X device", device);
 
   if (!DEVICE_X_P (XDEVICE (device)))
     signal_simple_error ("Not an X device", device);
@@ -2313,6 +2356,14 @@ x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
 }
 
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)win;
 }
 
+/* Account for some of the limitations with widget images. */
+static int
+x_widget_border_width (void)
+{
+  return DEFAULT_WIDGET_BORDER_WIDTH * 2;
+}
+
+
 #if 0
 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
 #if 0
 /* #### Should this function exist? If there's any doubt I'm not implementing it --andyp */
 DEFUN ("change-subwindow-property", Fchange_subwindow_property, 3, 3, 0, /*
@@ -2385,6 +2436,11 @@ update_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
                      (IMAGE_INSTANCE_WIDGET_TEXT (ii),
                       IMAGE_INSTANCE_WIDGET_FACE (ii),
                       domain))));
                      (IMAGE_INSTANCE_WIDGET_TEXT (ii),
                       IMAGE_INSTANCE_WIDGET_FACE (ii),
                       domain))));
+  wv->change = VISIBLE_CHANGE;
+  /* #### Megahack - but its just getting too complicated to do this
+     in the right place. */
+  if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qtab_control))
+    update_tab_widget_face (wv, ii, domain);
 }
 
 static void
 }
 
 static void
@@ -2401,9 +2457,12 @@ update_tab_widget_face (widget_value* wv, Lisp_Image_Instance *ii,
         domain);
       XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
       lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
         domain);
       XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
       lw_add_widget_value_arg (val, XtNtabForeground, fcolor.pixel);
+      wv->change = VISIBLE_CHANGE;
+      val->change = VISIBLE_CHANGE;
 
       for (cur = val->next; cur; cur = cur->next)
        {
 
       for (cur = val->next; cur; cur = cur->next)
        {
+         cur->change = VISIBLE_CHANGE;
          if (cur->value)
            {
              lw_copy_widget_value_args (val, cur);
          if (cur->value)
            {
              lw_copy_widget_value_args (val, cur);
@@ -2421,7 +2480,7 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
   struct device* d = XDEVICE (device);
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), pixel;
   struct device* d = XDEVICE (device);
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   char* nm=0;
   Widget wid;
   struct frame* f = XFRAME (frame);
   char* nm=0;
   Widget wid;
@@ -2440,9 +2499,7 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
 
   if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
   IMAGE_INSTANCE_TYPE (ii) = IMAGE_WIDGET;
 
   if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
-    TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
-                       C_STRING_ALLOCA, nm,
-                       Qnative);
+    LISP_STRING_TO_EXTERNAL (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm, Qnative);
 
   ii->data = xnew_and_zero (struct x_subwindow_data);
 
 
   ii->data = xnew_and_zero (struct x_subwindow_data);
 
@@ -2469,6 +2526,10 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 
   free_widget_value_tree (clip_wv);
 
 
   free_widget_value_tree (clip_wv);
 
+  /* create a sensible name. */
+  if (wv->name == 0 || strcmp(wv->name, "") == 0)
+    wv->name = xstrdup (type);
+
   /* copy any args we were given */
   ac = 0;
   lw_add_value_args_to_args (wv, al, &ac);
   /* copy any args we were given */
   ac = 0;
   lw_add_value_args_to_args (wv, al, &ac);
@@ -2479,12 +2540,12 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
      anymore...*/
   pixel = FACE_FOREGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
      anymore...*/
   pixel = FACE_FOREGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
-     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+     IMAGE_INSTANCE_FRAME (ii));
   fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   pixel = FACE_BACKGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
   fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   pixel = FACE_BACKGROUND
     (IMAGE_INSTANCE_WIDGET_FACE (ii),
-     IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+     IMAGE_INSTANCE_FRAME (ii));
   bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
   bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel));
 
   lw_add_widget_value_arg (wv, XtNbackground, bcolor.pixel);
@@ -2503,16 +2564,6 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
   IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
 
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid;
   IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id;
-#if 0
-  /* Resize the widget here so that the values do not get copied by
-     lwlib. */
-  ac = 0;
-  XtSetArg (al [ac], XtNwidth,
-           (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++;
-  XtSetArg (al [ac], XtNheight,
-           (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++;
-  XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac);
-#endif
   /* because the EmacsManager is the widgets parent we have to
      offset the redisplay of the widget by the amount the text
      widget is inside the manager. */
   /* because the EmacsManager is the widgets parent we have to
      offset the redisplay of the widget by the amount the text
      widget is inside the manager. */
@@ -2524,6 +2575,9 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   XtSetMappedWhenManaged (wid, TRUE);
 
   free_widget_value_tree (wv);
   XtSetMappedWhenManaged (wid, TRUE);
 
   free_widget_value_tree (wv);
+  /* A kludgy but simple way to make sure the callback for a widget
+     doesn't get deleted. */
+  gcpro_popup_callbacks (id);
 }
 
 /* get properties of a control */
 }
 
 /* get properties of a control */
@@ -2540,6 +2594,16 @@ x_widget_property (Lisp_Object image_instance, Lisp_Object prop)
   return Qunbound;
 }
 
   return Qunbound;
 }
 
+/* Instantiate a layout control for putting other widgets in. */
+static void
+x_native_layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                            int dest_mask, Lisp_Object domain)
+{
+  x_widget_instantiate (image_instance, instantiator, pointer_fg,
+                       pointer_bg, dest_mask, domain, "layout", 0);
+}
+
 /* Instantiate a button widget. Unfortunately instantiated widgets are
    particular to a frame since they need to have a parent. It's not
    like images where you just select the image into the context you
 /* Instantiate a button widget. Unfortunately instantiated widgets are
    particular to a frame since they need to have a parent. It's not
    like images where you just select the image into the context you
@@ -2554,9 +2618,7 @@ x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
   Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
-  widget_value* wv = xmalloc_widget_value ();
-
-  button_item_to_widget_value (gui, wv, 1, 1);
+  widget_value* wv = gui_items_to_widget_values (image_instance, gui, 1);
 
   if (!NILP (glyph))
     {
 
   if (!NILP (glyph))
     {
@@ -2583,6 +2645,30 @@ x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
     }
 }
 
     }
 }
 
+/* Update a button's clicked state.
+
+   #### This is overkill, but it works. Right now this causes all
+   button instances to flash for some reason buried deep in lwlib. In
+   theory this should be the Right Thing to do since lwlib should only
+   merge in changed values - and if nothing has changed then nothing
+   should get done. This may be because of the args stuff,
+   i.e. although the arg contents may be the same the args look
+   different and so are re-applied to the widget. */
+static void
+x_button_redisplay (Lisp_Object image_instance)
+{
+  /* This function can GC if IN_REDISPLAY is false. */
+  Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
+  widget_value* wv =
+    gui_items_to_widget_values (image_instance,
+                               IMAGE_INSTANCE_WIDGET_ITEMS (p), 1);
+
+  /* now modify the widget */
+  lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p),
+                        wv, True);
+  free_widget_value_tree (wv);
+}
+
 /* get properties of a button */
 static Lisp_Object
 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
 /* get properties of a button */
 static Lisp_Object
 x_button_property (Lisp_Object image_instance, Lisp_Object prop)
@@ -2609,26 +2695,26 @@ x_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
-  widget_value* wv = xmalloc_widget_value ();
-
-  button_item_to_widget_value (gui, wv, 1, 1);
+  widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "progress", wv);
 }
 
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "progress", wv);
 }
 
-/* set the properties of a progres guage */
+/* set the properties of a progress gauge */
 static void
 static void
-x_progress_gauge_update (Lisp_Object image_instance)
+x_progress_gauge_redisplay (Lisp_Object image_instance)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
 
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
 
-  if (IMAGE_INSTANCE_WIDGET_PERCENT_CHANGED (ii))
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
       Arg al [1];
     {
       Arg al [1];
-      /* #### I'm not convinced we should store this in the plist. */
-      Lisp_Object val = Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii),
-                                   Q_percent, Qnil);
+      Lisp_Object val;
+#ifdef ERROR_CHECK_GLYPHS
+      assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+#endif
+      val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
       XtSetArg (al[0], XtNvalue, XINT (val));
       XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
     }
       XtSetArg (al[0], XtNvalue, XINT (val));
       XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
     }
@@ -2642,9 +2728,7 @@ x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
-  widget_value* wv = xmalloc_widget_value ();
-
-  button_item_to_widget_value (gui, wv, 1, 1);
+  widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "text-field", wv);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "text-field", wv);
@@ -2664,7 +2748,8 @@ x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
   widget_instantiate (image_instance, instantiator, pointer_fg,
                      pointer_bg, dest_mask, domain);
 
   widget_instantiate (image_instance, instantiator, pointer_fg,
                      pointer_bg, dest_mask, domain);
 
-  wv = gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
+  wv = gui_items_to_widget_values (image_instance,
+                                  IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "combo-box", wv);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "combo-box", wv);
@@ -2678,38 +2763,101 @@ x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   widget_value * wv =
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   widget_value * wv =
-    gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
-
+    gui_items_to_widget_values (image_instance,
+                               IMAGE_INSTANCE_WIDGET_ITEMS (ii), 0);
   update_tab_widget_face (wv, ii,
   update_tab_widget_face (wv, ii,
-                         IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
-
+                         IMAGE_INSTANCE_FRAME (ii));
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "tab-control", wv);
 }
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "tab-control", wv);
 }
 
-/* set the properties of a tab control */
+/* Set the properties of a tab control */
 static void
 static void
-x_tab_control_update (Lisp_Object image_instance) 
+x_tab_control_redisplay (Lisp_Object image_instance)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
 
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
 
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
+      ||
+      IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
+    {
+      /* If only the order has changed then simply select the first
+        one of the pending set. This stops horrendous rebuilding -
+        and hence flicker - of the tabs each time you click on
+        one. */
+      if (tab_control_order_only_changed (image_instance))
+       {
+         Lisp_Object rest, selected =
+           gui_item_list_find_selected
+           (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
+            XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
+            XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+
+         LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+           {
+             if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
+               {
+                 /* There may be an encapsulated way of doing this,
+                    but I couldn't find it. */
+                 Lisp_Object old_selected =gui_item_list_find_selected
+                   (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
+                 Arg al [2];
+                 char* name;
+                 unsigned int num_children, i;
+                 Widget* children;
+
+                 LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
+                                          name, Qnative);
+                 /* The name may contain a `.' which confuses
+                    XtNameToWidget, so we do it ourselves. */
+                 children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
+                                                 &num_children);
+                 for (i = 0; i < num_children; i++)
+                   {
+                     if (!strcmp (XtName (children [i]), name))
+                       {
+                         XtSetArg (al [0], XtNtopWidget, children [i]);
+                         XtSetArg (al [1], XtNhighlightWidget,
+                                   children [i]);
+                         XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2);
+                         break;
+                       }
+                   }
+                 /* Pick up the new selected item. */
+                 XGUI_ITEM (old_selected)->selected =
+                   XGUI_ITEM (XCAR (rest))->selected;
+                 XGUI_ITEM (XCAR (rest))->selected =
+                   XGUI_ITEM (selected)->selected;
+                 /* We're not actually changing the items anymore. */
+                 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
+                 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
+                 break;
+               }
+           }
+       }
+    }
   /* Possibly update the face. */
   /* Possibly update the face. */
-  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) 
+  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii)
       ||
       ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))->faces_changed
+      XFRAME (IMAGE_INSTANCE_FRAME (ii))->faces_changed
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
       ||
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
-      widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
+      /* See previous comments on the brokeness of lwlib.
 
 
-      /* #### I don't know why this can occur. */
-      if (!wv)
-       return;
+        #### There's actually not much point in doing this here
+        since, colors will have been set appropriately by
+        x_redisplay_widget. */
+      widget_value* wv =copy_widget_value_tree
+       (lw_get_all_values
+        (IMAGE_INSTANCE_X_WIDGET_LWID (ii)),
+        NO_CHANGE);
 
       update_tab_widget_face (wv, ii,
 
       update_tab_widget_face (wv, ii,
-                             IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+                             IMAGE_INSTANCE_FRAME (ii));
 
       lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
 
       lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True);
+      free_widget_value_tree (wv);
     }
 }
 
     }
 }
 
@@ -2721,9 +2869,7 @@ x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
-  widget_value* wv = xmalloc_widget_value ();
-
-  button_item_to_widget_value (gui, wv, 1, 1);
+  widget_value* wv = gui_items_to_widget_values (image_instance, gui, 0);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "button", wv);
 
   x_widget_instantiate (image_instance, instantiator, pointer_fg,
                        pointer_bg, dest_mask, domain, "button", wv);
@@ -2757,8 +2903,9 @@ console_type_create_glyphs_x (void)
   CONSOLE_HAS_METHOD (x, locate_pixmap_file);
   CONSOLE_HAS_METHOD (x, unmap_subwindow);
   CONSOLE_HAS_METHOD (x, map_subwindow);
   CONSOLE_HAS_METHOD (x, locate_pixmap_file);
   CONSOLE_HAS_METHOD (x, unmap_subwindow);
   CONSOLE_HAS_METHOD (x, map_subwindow);
-  CONSOLE_HAS_METHOD (x, update_widget);
-  CONSOLE_HAS_METHOD (x, update_subwindow);
+  CONSOLE_HAS_METHOD (x, redisplay_widget);
+  CONSOLE_HAS_METHOD (x, redisplay_subwindow);
+  CONSOLE_HAS_METHOD (x, widget_border_width);
 }
 
 void
 }
 
 void
@@ -2766,7 +2913,9 @@ image_instantiator_format_create_glyphs_x (void)
 {
   IIFORMAT_VALID_CONSOLE (x, nothing);
   IIFORMAT_VALID_CONSOLE (x, string);
 {
   IIFORMAT_VALID_CONSOLE (x, nothing);
   IIFORMAT_VALID_CONSOLE (x, string);
+#ifdef HAVE_WIDGETS
   IIFORMAT_VALID_CONSOLE (x, layout);
   IIFORMAT_VALID_CONSOLE (x, layout);
+#endif
   IIFORMAT_VALID_CONSOLE (x, formatted_string);
   IIFORMAT_VALID_CONSOLE (x, inherit);
 #ifdef HAVE_XPM
   IIFORMAT_VALID_CONSOLE (x, formatted_string);
   IIFORMAT_VALID_CONSOLE (x, inherit);
 #ifdef HAVE_XPM
@@ -2791,16 +2940,20 @@ image_instantiator_format_create_glyphs_x (void)
   INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
   IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
 #ifdef HAVE_WIDGETS
   INITIALIZE_DEVICE_IIFORMAT (x, subwindow);
   IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate);
 #ifdef HAVE_WIDGETS
+  /* layout widget */
+  INITIALIZE_DEVICE_IIFORMAT (x, native_layout);
+  IIFORMAT_HAS_DEVMETHOD (x, native_layout, instantiate);
   /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (x, button);
   IIFORMAT_HAS_DEVMETHOD (x, button, property);
   IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
   /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (x, button);
   IIFORMAT_HAS_DEVMETHOD (x, button, property);
   IIFORMAT_HAS_DEVMETHOD (x, button, instantiate);
-
+  IIFORMAT_HAS_DEVMETHOD (x, button, redisplay);
+  /* general widget methods. */
   INITIALIZE_DEVICE_IIFORMAT (x, widget);
   IIFORMAT_HAS_DEVMETHOD (x, widget, property);
   /* progress gauge */
   INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
   INITIALIZE_DEVICE_IIFORMAT (x, widget);
   IIFORMAT_HAS_DEVMETHOD (x, widget, property);
   /* progress gauge */
   INITIALIZE_DEVICE_IIFORMAT (x, progress_gauge);
-  IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, update);
+  IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, redisplay);
   IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
   /* text field */
   INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
   IIFORMAT_HAS_DEVMETHOD (x, progress_gauge, instantiate);
   /* text field */
   INITIALIZE_DEVICE_IIFORMAT (x, edit_field);
@@ -2809,12 +2962,12 @@ image_instantiator_format_create_glyphs_x (void)
   /* combo box */
   INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
   IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
   /* combo box */
   INITIALIZE_DEVICE_IIFORMAT (x, combo_box);
   IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate);
-  IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, update, tab_control);
+  IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, redisplay, tab_control);
 #endif
   /* tab control widget */
   INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
   IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
 #endif
   /* tab control widget */
   INITIALIZE_DEVICE_IIFORMAT (x, tab_control);
   IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate);
-  IIFORMAT_HAS_DEVMETHOD (x, tab_control, update);
+  IIFORMAT_HAS_DEVMETHOD (x, tab_control, redisplay);
   /* label */
   INITIALIZE_DEVICE_IIFORMAT (x, label);
   IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
   /* label */
   INITIALIZE_DEVICE_IIFORMAT (x, label);
   IIFORMAT_HAS_DEVMETHOD (x, label, instantiate);
@@ -2852,6 +3005,17 @@ image_instantiator_format_create_glyphs_x (void)
   IIFORMAT_HAS_METHOD (autodetect, validate);
   IIFORMAT_HAS_METHOD (autodetect, normalize);
   IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
   IIFORMAT_HAS_METHOD (autodetect, validate);
   IIFORMAT_HAS_METHOD (autodetect, normalize);
   IIFORMAT_HAS_METHOD (autodetect, possible_dest_types);
+  /* #### autodetect is flawed IMO: 
+  1. It makes the assumption that you can detect whether the user
+  wanted a cursor or a string based on the data, since the data is a
+  string you have to prioritise cursors. Instead we will force users
+  to pick the appropriate image type, this is what we do under
+  MS-Windows anyway.
+  2. It doesn't fit with the new domain model - you cannot tell which
+  domain it needs to be instantiated in until you've actually
+  instantiated it, which mucks up caching.
+  3. It only copes with cursors and strings which seems bogus. */
+  IIFORMAT_HAS_SHARED_METHOD (autodetect, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (autodetect, instantiate);
   IIFORMAT_VALID_CONSOLE (x, autodetect);
 
   IIFORMAT_HAS_METHOD (autodetect, instantiate);
   IIFORMAT_VALID_CONSOLE (x, autodetect);
 
@@ -2879,7 +3043,7 @@ complex_vars_of_glyphs_x (void)
      vector3 (Qxbm, Q_data,                                    \
              list3 (make_int (name##_width),                   \
                     make_int (name##_height),                  \
      vector3 (Qxbm, Q_data,                                    \
              list3 (make_int (name##_width),                   \
                     make_int (name##_height),                  \
-                    make_ext_string (name##_bits,              \
+                    make_ext_string ((Extbyte *) name##_bits,  \
                                      sizeof (name##_bits),     \
                                      Qbinary))),               \
      Qglobal, Qx, Qnil)
                                      sizeof (name##_bits),     \
                                      Qbinary))),               \
      Qglobal, Qx, Qnil)