(g2-UU+5B73): Add `=decomposition@hanyo-denshi'.
[chise/xemacs-chise.git.1] / src / glyphs-msw.c
index 440e272..72902aa 100644 (file)
@@ -20,7 +20,7 @@ Boston, MA 02111-1307, USA.  */
 
 /* Synched up with: Not in FSF. */
 
-/* written by Andy Piper <andy@xemacs.org> plagerising bits from
+/* written by Andy Piper <andy@xemacs.org> plagiarising bits from
    glyphs-x.c */
 
 #include <config.h>
@@ -57,7 +57,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 (layout);
 #ifdef HAVE_JPEG
 DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
 #endif
@@ -80,6 +79,8 @@ DEFINE_DEVICE_IIFORMAT (msprinter, xbm);
 DEFINE_DEVICE_IIFORMAT (mswindows, xface);
 DEFINE_DEVICE_IIFORMAT (msprinter, xface);
 #endif
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout);
+DEFINE_DEVICE_IIFORMAT (mswindows, native_layout);
 DEFINE_DEVICE_IIFORMAT (mswindows, button);
 DEFINE_DEVICE_IIFORMAT (mswindows, edit_field);
 DEFINE_DEVICE_IIFORMAT (mswindows, subwindow);
@@ -132,9 +133,8 @@ get_device_compdc (struct device *d)
  */
 static void init_image_instance_geometry (Lisp_Image_Instance *ii)
 {
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  struct device *d = XDEVICE (device);
-  
+  struct device *d = DOMAIN_XDEVICE (ii->domain);
+
   if (/* #### Scaleable && */ DEVICE_MSPRINTER_P (d))
     {
       HDC printer_dc = DEVICE_MSPRINTER_HCDC (d);
@@ -154,7 +154,7 @@ static void init_image_instance_geometry (Lisp_Image_Instance *ii)
        IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_WIDTH (ii);
       IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) =
        IMAGE_INSTANCE_MSWINDOWS_BITMAP_REAL_HEIGHT (ii);
-    }      
+    }
 }
 
 #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3)))
@@ -349,8 +349,7 @@ init_image_instance_from_dibitmap (Lisp_Image_Instance *ii,
                                   int x_hot, int y_hot,
                                   int create_mask)
 {
-  Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
-  struct device *d = XDEVICE (device);
+  struct device *d = XDEVICE (IMAGE_INSTANCE_DEVICE (ii));
   void* bmp_buf=0;
   enum image_instance_type type;
   HBITMAP bitmap;
@@ -687,7 +686,7 @@ mswindows_create_resized_mask (Lisp_Image_Instance* ii,
 }
 
 #if 0 /* Currently unused */
-/* #### Warining: This function is not correct anymore with
+/* #### Warning: This function is not correct anymore with
    resizable printer bitmaps.  If you uncomment it, clean it. --kkm */
 int
 mswindows_resize_dibitmap_instance (Lisp_Image_Instance* ii,
@@ -1020,7 +1019,8 @@ bmp_validate (Lisp_Object instantiator)
 }
 
 static Lisp_Object
-bmp_normalize (Lisp_Object inst, Lisp_Object console_type)
+bmp_normalize (Lisp_Object inst, Lisp_Object console_type,
+              Lisp_Object dest_mask)
 {
   return simple_image_type_normalize (inst, console_type, Qbmp);
 }
@@ -1087,7 +1087,8 @@ mswindows_resource_validate (Lisp_Object instantiator)
 }
 
 static Lisp_Object
-mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type)
+mswindows_resource_normalize (Lisp_Object inst, Lisp_Object console_type,
+                             Lisp_Object dest_mask)
 {
   /* This function can call lisp */
   Lisp_Object file = Qnil;
@@ -1141,7 +1142,7 @@ typedef struct
 #define OIC_BANG            32515
 #define OIC_NOTE            32516
 #define OIC_WINLOGO         32517
-#if defined (__CYGWIN32__) && CYGWIN_VERSION_DLL_MAJOR < 21
+#if defined (CYGWIN) && CYGWIN_VERSION_DLL_MAJOR < 21
 #define LR_SHARED           0x8000
 #endif
 #endif
@@ -1290,7 +1291,7 @@ mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instanti
       TO_EXTERNAL_FORMAT (LISP_STRING, file,
                          C_STRING_ALLOCA, f,
                          Qfile_name);
-#ifdef __CYGWIN32__
+#ifdef CYGWIN
       CYGWIN_WIN32_PATH (f, fname);
 #else
       fname = f;
@@ -1316,12 +1317,32 @@ mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instanti
     signal_simple_error ("Invalid resource identifier", resource_id);
 
   /* load the image */
-  if (!(himage = LoadImage (hinst, resid, type, 0, 0,
-                           LR_CREATEDIBSECTION | LR_DEFAULTSIZE |
-                           LR_SHARED |
-                           (!NILP (file) ? LR_LOADFROMFILE : 0))))
+  if (xLoadImageA) /* not in NT 3.5 */
+    {
+      if (!(himage = xLoadImageA (hinst, resid, type, 0, 0,
+                                 LR_CREATEDIBSECTION | LR_DEFAULTSIZE |
+                                 LR_SHARED |
+                                 (!NILP (file) ? LR_LOADFROMFILE : 0))))
+       signal_simple_error ("Cannot load image", instantiator);
+    }
+  else
     {
-      signal_simple_error ("Cannot load image", instantiator);
+      /* Is this correct?  I don't really care. */
+      switch (type)
+       {
+       case IMAGE_BITMAP:
+         himage = LoadBitmap (hinst, resid);
+         break;
+       case IMAGE_CURSOR:
+         himage = LoadCursor (hinst, resid);
+         break;
+       case IMAGE_ICON:
+         himage = LoadIcon (hinst, resid);
+         break;
+       }
+
+      if (!himage)
+       signal_simple_error ("Cannot load image", instantiator);
     }
 
   if (hinst)
@@ -1439,7 +1460,7 @@ in this Software without prior written authorization from the X Consortium.
 
 /* shared data for the image read/parse logic */
 static short hexTable[256];            /* conversion value */
-static int initialized = FALSE;        /* easier to fill in at run time */
+static int hex_initialized = FALSE;    /* easier to fill in at run time */
 
 /*
  *     Table index for the hex values. Initialized once, first time.
@@ -1473,7 +1494,7 @@ initHexTable (void)
     hexTable['}'] = -1;        hexTable['\n'] = -1;
     hexTable['\t'] = -1;
 
-    initialized = TRUE;
+    hex_initialized = TRUE;
 }
 
 /*
@@ -1536,7 +1557,7 @@ int read_bitmap_data (FILE* fstream, unsigned int *width,
 #define Xmalloc(size) malloc(size)
 
     /* first time initialization */
-    if (initialized == FALSE) initHexTable();
+    if (hex_initialized == FALSE) initHexTable();
 
     /* error cleanup and return macro  */
 #define        RETURN(code) { if (data) free (data); return code; }
@@ -1699,9 +1720,9 @@ xbm_create_bitmap_from_data (HDC hdc, char *data,
 
       for (j=0; j<old_width; j++)
        {
-         int byte = offset[j];
+         int bite = offset[j];
          new_offset[j] = ~ (unsigned char)
-           ((flip_table[byte & 0xf] << 4) + flip_table[byte >> 4]);
+           ((flip_table[bite & 0xf] << 4) + flip_table[bite >> 4]);
        }
     }
 
@@ -1882,7 +1903,7 @@ init_image_instance_from_xbm_inline (Lisp_Image_Instance *ii,
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 }
 
@@ -1956,6 +1977,9 @@ mswindows_xbm_instantiate (Lisp_Object image_instance,
 #ifdef __cplusplus
 extern "C" {
 #endif
+#ifndef __STDC__ /* Needed to avoid prototype warnings */
+#define __STDC__
+#endif
 #include <compface.h>
 #ifdef __cplusplus
 }
@@ -2070,13 +2094,21 @@ extern int debug_widget_instances;
 #endif
 
 static void
+finalize_destroy_window (void *win)
+{
+  DestroyWindow ((HWND) win);
+}
+
+static void
 mswindows_finalize_image_instance (Lisp_Image_Instance *p)
 {
-  if (DEVICE_LIVE_P (XDEVICE (p->device)))
+  if (!p->data)
+    return;
+
+  if (DEVICE_LIVE_P (XDEVICE (IMAGE_INSTANCE_DEVICE (p))))
     {
-      if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET
-         ||
-         IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW)
+      if (image_instance_type_to_mask (IMAGE_INSTANCE_TYPE (p))
+         & (IMAGE_WIDGET_MASK | IMAGE_SUBWINDOW_MASK))
        {
 #ifdef DEBUG_WIDGETS
          debug_widget_instances--;
@@ -2084,8 +2116,14 @@ mswindows_finalize_image_instance (Lisp_Image_Instance *p)
 #endif
          if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
            {
-             DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
-             DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p));
+             /* DestroyWindow is not safe here, as it will send messages
+                to our window proc. */
+             register_post_gc_action
+               (finalize_destroy_window,
+                (void *) (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)));
+             register_post_gc_action
+               (finalize_destroy_window,
+                (void *) (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
              IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0;
            }
        }
@@ -2139,6 +2177,16 @@ mswindows_widget_hfont (Lisp_Image_Instance *p,
   return mswindows_get_hfont (XFONT_INSTANCE (font), under, strike);
 }
 
+static HDWP
+begin_defer_window_pos (struct frame *f)
+{
+#ifdef DEFER_WINDOW_POS
+  if (FRAME_MSWINDOWS_DATA (f)->hdwp == 0)
+    FRAME_MSWINDOWS_DATA (f)->hdwp = BeginDeferWindowPos (10);
+#endif
+  return FRAME_MSWINDOWS_DATA (f)->hdwp;
+}
+
 /* unmap the image if it is a widget. This is used by redisplay via
    redisplay_unmap_subwindows */
 static void
@@ -2146,11 +2194,34 @@ mswindows_unmap_subwindow (Lisp_Image_Instance *p)
 {
   if (IMAGE_INSTANCE_SUBWINDOW_ID (p))
     {
+#ifdef DEFER_WINDOW_POS
+      struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
+      HDWP hdwp = begin_defer_window_pos (f);
+      HDWP new_hdwp;
+      new_hdwp = DeferWindowPos (hdwp, IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
+                                NULL,
+                                0, 0, 0, 0,
+                                SWP_HIDEWINDOW | SWP_NOACTIVATE |
+                                SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
+                                /* Setting this flag causes the call to
+                                   DeferWindowPos to fail with
+                                   "Invalid parameter".  I don't understand
+                                   why we bother to try and set this
+                                   anyway. -- ben */
+                                /* | SWP_NOSENDCHANGING */
+                                );
+      if (!new_hdwp)
+       mswindows_output_last_error ("unmapping");
+      else
+       hdwp = new_hdwp;
+      FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
+#else
       SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
                    NULL,
                    0, 0, 0, 0,
-                   SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE
-                   | SWP_NOSENDCHANGING);
+                   SWP_HIDEWINDOW | SWP_NOACTIVATE |
+                   SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER );
+#endif
       if (GetFocus() == WIDGET_INSTANCE_MSWINDOWS_HANDLE (p))
        SetFocus (GetParent (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)));
     }
@@ -2162,6 +2233,11 @@ static void
 mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                         struct display_glyph_area* dga)
 {
+#ifdef DEFER_WINDOW_POS
+  struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p));
+  HDWP hdwp = begin_defer_window_pos (f);
+  HDWP new_hdwp;
+#endif
   /* move the window before mapping it ... */
   SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
                NULL,
@@ -2175,12 +2251,46 @@ mswindows_map_subwindow (Lisp_Image_Instance *p, int x, int y,
                SWP_NOZORDER | SWP_NOSIZE
                | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
   /* ... now map it - we are not allowed to move it at the same time. */
-  SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
-               NULL,
-               0, 0, 0, 0,
-               SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
-               | SWP_SHOWWINDOW | SWP_NOCOPYBITS
-               | SWP_NOSENDCHANGING);
+  if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p))
+    {
+#ifdef DEFER_WINDOW_POS
+      new_hdwp = DeferWindowPos
+       (hdwp,
+        IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
+        NULL, 0, 0, 0, 0,
+        SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
+        | SWP_SHOWWINDOW
+        /* | SWP_NOCOPYBITS */
+        /* Setting this flag causes the call to
+           DeferWindowPos to fail with
+           "Invalid parameter".  I don't understand
+           why we bother to try and set this
+           anyway. -- ben */
+        /* | SWP_NOSENDCHANGING */
+        | SWP_NOACTIVATE);
+      if (!new_hdwp)
+       mswindows_output_last_error ("mapping");
+      else
+       hdwp = new_hdwp;
+      FRAME_MSWINDOWS_DATA (f)->hdwp = hdwp;
+#else
+      SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p),
+                   NULL,
+                   0, 0, 0, 0,
+                   SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE
+                   | SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOACTIVATE);
+
+      /* Doing this once does not seem to be enough, for instance when
+        mapping the search dialog this gets called four times. If we
+        only set on the first time through then the subwindow never
+        gets focus as intended. However, doing this everytime doesn't
+        seem so bad, after all we only need to redo this after the
+        focus changes - and if that happens resetting the initial
+        focus doesn't seem so bad. */
+      if (IMAGE_INSTANCE_WANTS_INITIAL_FOCUS (p))
+       SetFocus (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p));
+#endif
+    }
 }
 
 /* resize the subwindow instance */
@@ -2188,16 +2298,17 @@ static void
 mswindows_resize_subwindow (Lisp_Image_Instance* ii, int w, int h)
 {
   /* Set the size of the control .... */
-  SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
-               NULL,
-               0, 0, w, h,
-               SWP_NOZORDER | SWP_NOMOVE
-               | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
+  if (!SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+                    NULL,
+                    0, 0, w, h,
+                    SWP_NOZORDER | SWP_NOMOVE
+                    | SWP_NOCOPYBITS | SWP_NOSENDCHANGING))
+    mswindows_output_last_error ("resizing");
 }
 
 /* Simply resize the window here. */
 static void
-mswindows_update_subwindow (Lisp_Image_Instance *p)
+mswindows_redisplay_subwindow (Lisp_Image_Instance *p)
 {
   mswindows_resize_subwindow (p,
                              IMAGE_INSTANCE_WIDTH (p),
@@ -2207,31 +2318,31 @@ mswindows_update_subwindow (Lisp_Image_Instance *p)
 /* when you click on a widget you may activate another widget this
    needs to be checked and all appropriate widgets updated */
 static void
-mswindows_update_widget (Lisp_Image_Instance *p)
+mswindows_redisplay_widget (Lisp_Image_Instance *p)
 {
   /* Possibly update the face font and colors. */
-  if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
-      ||
-      XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (p))->faces_changed
-      ||
-      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
+  if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (p))
+      && (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
+         || XFRAME (IMAGE_INSTANCE_FRAME (p))->faces_changed
+         || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)))
     {
       /* set the widget font from the widget face */
       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
                   WM_SETFONT,
                   (WPARAM) mswindows_widget_hfont
-                  (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)),
+                  (p, IMAGE_INSTANCE_FRAME (p)),
                   MAKELPARAM (TRUE, 0));
     }
   /* Possibly update the dimensions. */
   if (IMAGE_INSTANCE_SIZE_CHANGED (p))
     {
-      mswindows_resize_subwindow (p, 
+      mswindows_resize_subwindow (p,
                                  IMAGE_INSTANCE_WIDTH (p),
                                  IMAGE_INSTANCE_HEIGHT (p));
     }
   /* Possibly update the text in the widget. */
-  if (IMAGE_INSTANCE_TEXT_CHANGED (p))
+  if (IMAGE_INSTANCE_TEXT_CHANGED (p)
+      && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (p)))
     {
       Extbyte* lparam=0;
       TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (p),
@@ -2240,16 +2351,41 @@ mswindows_update_widget (Lisp_Image_Instance *p)
       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
                   WM_SETTEXT, 0, (LPARAM)lparam);
     }
+  /* Set active state. */
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
+    {
+      Lisp_Object item = IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (p);
+      LONG style = GetWindowLong 
+       (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
+        GWL_STYLE);
+
+      if (CONSP (item))
+       item = XCAR (item);
+
+      if (gui_item_active_p (item))
+       SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
+                      GWL_STYLE, style & ~WS_DISABLED);
+      else
+       SetWindowLong (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
+                      GWL_STYLE, style | WS_DISABLED);
+    }
+}
+
+/* Account for some of the limitations with widget images. */
+static int
+mswindows_widget_border_width (void)
+{
+  return DEFAULT_WIDGET_BORDER_WIDTH;
 }
 
-/* register widgets into our hastable so that we can cope with the
+/* register widgets into our hashtable so that we can cope with the
    callbacks. The hashtable is weak so deregistration is handled
    automatically */
 static int
 mswindows_register_gui_item (Lisp_Object image_instance,
                             Lisp_Object gui, Lisp_Object domain)
 {
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   struct frame* f = XFRAME (frame);
   int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f),
                             gui,
@@ -2278,7 +2414,7 @@ mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instant
 {
   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);
   HWND wnd;
 
   CHECK_MSWINDOWS_DEVICE (device);
@@ -2400,7 +2536,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   /* this function can call lisp */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
-  Lisp_Object frame = FW_FRAME (domain);
+  Lisp_Object frame = DOMAIN_FRAME (domain);
   Extbyte* nm=0;
   HWND wnd;
   int id = 0xffff;
@@ -2438,7 +2574,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
                        IMAGE_INSTANCE_WIDGET_WIDTH (ii),
                        IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
                        /* parent window */
-                       FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
+                       DOMAIN_MSWINDOWS_HANDLE (domain),
                        (HMENU)id,       /* No menu */
                        NULL, /* must be null for this class */
                        NULL)) == NULL)
@@ -2468,9 +2604,32 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
   SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
   /* set the widget font from the widget face */
-  SendMessage (wnd, WM_SETFONT,
-              (WPARAM) mswindows_widget_hfont (ii, domain),
-              MAKELPARAM (TRUE, 0));
+  if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+    SendMessage (wnd, WM_SETFONT,
+                (WPARAM) mswindows_widget_hfont (ii, domain),
+                MAKELPARAM (TRUE, 0));
+}
+
+/* Instantiate a native layout widget. */
+static void
+mswindows_native_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);
+
+  mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+                               pointer_bg, dest_mask, domain, "STATIC",
+                               /* Approximation to styles available with
+                                  an XEmacs layout. */
+                               (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+                                    Qetched_in) ||
+                                EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+                                    Qetched_out) ||
+                                GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
+                                ? SS_ETCHEDFRAME : SS_SUNKEN) | DS_CONTROL,
+                               0);
 }
 
 /* Instantiate a button widget. Unfortunately instantiated widgets are
@@ -2487,9 +2646,10 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   /* This function can call lisp */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   HWND wnd;
-  int flags = WS_TABSTOP;/* BS_NOTIFY #### is needed to get exotic feedback
-                           only. Since we seem to want nothing beyond BN_CLICK,
-                           the style is perhaps not necessary -- kkm */
+  int flags = WS_TABSTOP | BS_NOTIFY;
+  /* BS_NOTIFY #### is needed to get exotic feedback only. Since we
+     seem to want nothing beyond BN_CLICK, the style is perhaps not
+     necessary -- kkm */
   Lisp_Object style;
   Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
   Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
@@ -2548,7 +2708,7 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
 
 /* Update the state of a button. */
 static void
-mswindows_button_update (Lisp_Object image_instance)
+mswindows_button_redisplay (Lisp_Object image_instance)
 {
   /* This function can GC if IN_REDISPLAY is false. */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
@@ -2582,6 +2742,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in
 {
   HWND wnd;
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  Lisp_Object val;
   mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
                                pointer_bg, dest_mask, domain, PROGRESS_CLASS,
                                WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE);
@@ -2593,7 +2754,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in
                         (XCOLOR_INSTANCE
                          (FACE_BACKGROUND
                           (XIMAGE_INSTANCE_WIDGET_FACE (ii),
-                           XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+                           XIMAGE_INSTANCE_FRAME (ii))))));
 #endif
 #ifdef PBS_SETBARCOLOR
   SendMessage (wnd, PBS_SETBARCOLOR, 0,
@@ -2601,8 +2762,12 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in
                          (XCOLOR_INSTANCE
                           (FACE_FOREGROUND
                            (XIMAGE_INSTANCE_WIDGET_FACE (ii),
-                            XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+                            XIMAGE_INSTANCE_FRAME (ii))))));
 #endif
+  val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEMS (ii))->value;
+  CHECK_INT (val);
+  SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+              PBM_SETPOS, (WPARAM)XINT (val), 0);
 }
 
 /* instantiate a tree view widget */
@@ -2692,12 +2857,47 @@ mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instant
     }
 }
 
+/* Set the properties of a tree view. */
+static void
+mswindows_tree_view_redisplay (Lisp_Object image_instance)
+{
+  /* This function can GC if IN_REDISPLAY is false. */
+  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
+    {
+      HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+      Lisp_Object rest;
+      HTREEITEM parent;
+      /* Delete previous items. */
+      SendMessage (wnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
+      /* define a root */
+      parent = add_tree_item (image_instance, wnd, NULL,
+                             XCAR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)),
+                             TRUE, IMAGE_INSTANCE_DOMAIN (ii));
+
+      /* recursively add items to the tree view */
+      /* add items to the tab */
+      LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+       {
+         if (LISTP (XCAR (rest)))
+           add_tree_item_list (image_instance, wnd, parent, XCAR (rest),
+                               IMAGE_INSTANCE_DOMAIN (ii));
+         else
+           add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE,
+                          IMAGE_INSTANCE_DOMAIN (ii));
+       }
+    }
+}
+
 /* instantiate a tab control */
-static TC_ITEM* add_tab_item (Lisp_Object image_instance,
-                            HWND wnd, Lisp_Object item,
-                            Lisp_Object domain, int i)
+static int
+add_tab_item (Lisp_Object image_instance,
+             HWND wnd, Lisp_Object item,
+             Lisp_Object domain, int i)
 {
-  TC_ITEM tvitem, *ret;
+  TC_ITEM tvitem;
+  int ret = 0;
 
   tvitem.mask = TCIF_TEXT;
 
@@ -2720,8 +2920,8 @@ static TC_ITEM* add_tab_item (Lisp_Object image_instance,
 
   tvitem.cchTextMax = strlen (tvitem.pszText);
 
-  if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM,
-                                   i, (LPARAM)&tvitem)) < 0)
+  if ((ret = SendMessage (wnd, TCM_INSERTITEM,
+                         i, (LPARAM)&tvitem)) < 0)
     signal_simple_error ("error adding tab entry", item);
 
   return ret;
@@ -2757,7 +2957,8 @@ mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object insta
   /* add items to the tab */
   LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
     {
-      add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
+      int idx = add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
+      assert (idx == i);
       if (gui_item_selected_p (XCAR (rest)))
        selected = i;
       i++;
@@ -2765,32 +2966,78 @@ mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object insta
   SendMessage (wnd, TCM_SETCURSEL, selected, 0);
 }
 
-/* set the properties of a tab control */
+/* Set the properties of a tab control. */
 static void
-mswindows_tab_control_update (Lisp_Object image_instance)
+mswindows_tab_control_redisplay (Lisp_Object image_instance)
 {
   /* This function can GC if IN_REDISPLAY is false. */
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
-  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
+#ifdef DEBUG_WIDGET_OUTPUT
+  stderr_out ("tab control %p redisplayed\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
+#endif
+  if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
+      ||
+      IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
     {
       HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
-      int i = 0, selected = 0;
+      int i = 0, selected_idx = 0;
       Lisp_Object rest;
 
-      /* delete the pre-existing items */
-      SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
+      assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
 
-      /* add items to the tab */
-      LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+      /* If only the order has changed then simply select the first
+        one. This stops horrendous rebuilding of the tabs each time
+        you click on one. */
+      if (tab_control_order_only_changed (image_instance))
+       {
+         Lisp_Object 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))
+               {
+                 Lisp_Object old_selected = gui_item_list_find_selected
+                   (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
+
+                 /* 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. */
+                 IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
+                 IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
+
+                 SendMessage (wnd, TCM_SETCURSEL, i, 0);
+#ifdef DEBUG_WIDGET_OUTPUT
+                 stderr_out ("tab control %p selected item %d\n",
+                         IMAGE_INSTANCE_SUBWINDOW_ID (ii), i);
+#endif
+                 break;
+               }
+             i++;
+           }
+       }
+      else
        {
-         add_tab_item (image_instance, wnd, XCAR (rest),
-                       IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), i);
-         if (gui_item_selected_p (XCAR (rest)))
-           selected = i;
-         i++;
+         /* delete the pre-existing items */
+         SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
+
+         /* add items to the tab */
+         LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+           {
+             add_tab_item (image_instance, wnd, XCAR (rest),
+                           IMAGE_INSTANCE_FRAME (ii), i);
+             if (gui_item_selected_p (XCAR (rest)))
+               selected_idx = i;
+             i++;
+           }
+         SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0);
        }
-      SendMessage (wnd, TCM_SETCURSEL, selected, 0);
     }
 }
 
@@ -2825,8 +3072,7 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   HWND wnd;
   Lisp_Object rest;
-  Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
-                                Q_items, Qnil);
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
   int len, height;
 
   /* Maybe ought to generalise this more but it may be very windows
@@ -2840,9 +3086,9 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant
 
   /* We now have everything right apart from the height. */
   default_face_font_info (domain, 0, 0, &height, 0, 0);
-  GET_LIST_LENGTH (data, len);
+  GET_LIST_LENGTH (items, len);
 
-  height = (height + WIDGET_BORDER_HEIGHT * 2 ) * len;
+  height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len;
   IMAGE_INSTANCE_HEIGHT (ii) = height;
 
   /* Now create the widget. */
@@ -2856,12 +3102,14 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant
   image_instance_layout (image_instance,
                         IMAGE_UNSPECIFIED_GEOMETRY,
                         IMAGE_UNSPECIFIED_GEOMETRY,
+                        IMAGE_UNCHANGED_GEOMETRY,
+                        IMAGE_UNCHANGED_GEOMETRY,
                         domain);
 
   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
   /* add items to the combo box */
   SendMessage (wnd, CB_RESETCONTENT, 0, 0);
-  LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
+  LIST_LOOP (rest, items)
     {
       Extbyte* lparam;
       TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest),
@@ -2925,12 +3173,12 @@ mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
   return Qunbound;
 }
 
-/* set the properties of a progres guage */
+/* set the properties of a progress gauge */
 static void
-mswindows_progress_gauge_update (Lisp_Object image_instance)
+mswindows_progress_gauge_redisplay (Lisp_Object image_instance)
 {
   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  
+
   if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
       Lisp_Object val;
@@ -2938,10 +3186,10 @@ mswindows_progress_gauge_update (Lisp_Object image_instance)
       assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
 #endif
       val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
-#ifdef DEBUG_WIDGET_OUTPUT     
-      printf ("progress gauge displayed value on %p updated to %ld\n",
-             WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
-             XINT(val));
+#ifdef DEBUG_WIDGET_OUTPUT
+      stderr_out ("progress gauge displayed value on %p updated to %ld\n",
+                 WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+                 XINT(val));
 #endif
       CHECK_INT (val);
       SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
@@ -2991,13 +3239,14 @@ console_type_create_glyphs_mswindows (void)
   CONSOLE_HAS_METHOD (mswindows, finalize_image_instance);
   CONSOLE_HAS_METHOD (mswindows, unmap_subwindow);
   CONSOLE_HAS_METHOD (mswindows, map_subwindow);
-  CONSOLE_HAS_METHOD (mswindows, update_subwindow);
+  CONSOLE_HAS_METHOD (mswindows, redisplay_subwindow);
   CONSOLE_HAS_METHOD (mswindows, resize_subwindow);
-  CONSOLE_HAS_METHOD (mswindows, update_widget);
+  CONSOLE_HAS_METHOD (mswindows, redisplay_widget);
   CONSOLE_HAS_METHOD (mswindows, image_instance_equal);
   CONSOLE_HAS_METHOD (mswindows, image_instance_hash);
   CONSOLE_HAS_METHOD (mswindows, init_image_instance_from_eimage);
   CONSOLE_HAS_METHOD (mswindows, locate_pixmap_file);
+  CONSOLE_HAS_METHOD (mswindows, widget_border_width);
 
   /* image methods - printer */
   CONSOLE_INHERITS_METHOD (msprinter, mswindows, print_image_instance);
@@ -3013,7 +3262,6 @@ image_instantiator_format_create_glyphs_mswindows (void)
 {
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, nothing);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, string);
-  IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, layout);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, formatted_string);
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, inherit);
   /* image-instantiator types */
@@ -3046,48 +3294,45 @@ image_instantiator_format_create_glyphs_mswindows (void)
   IIFORMAT_VALID_CONSOLE2 (mswindows, msprinter, gif);
 #endif
 #ifdef HAVE_WIDGETS
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
+  /* layout widget */
+  IIFORMAT_VALID_CONSOLE (mswindows, layout);
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, native_layout);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, native_layout, instantiate);
   /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, button, update);
-
+  IIFORMAT_HAS_DEVMETHOD (mswindows, button, redisplay);
+  /* edit-field widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
   IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
-
+  /* subwindow */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
   IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
-
-  INITIALIZE_DEVICE_IIFORMAT (mswindows, widget);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property);
-
   /* label */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
   IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
-
   /* combo box */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, combo_box);
   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, property);
   IIFORMAT_HAS_DEVMETHOD (mswindows, combo_box, instantiate);
-
   /* scrollbar */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
   IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
-
   /* progress gauge */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, update);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, redisplay);
   IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, instantiate);
-
   /* tree view widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, tree_view);
-  /*  IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/
   IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, instantiate);
-
+  IIFORMAT_HAS_DEVMETHOD (mswindows, tree_view, redisplay);
   /* tab control widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
   IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, update);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, redisplay);
 #endif
   /* windows bitmap format */
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");