(charset_get_byte1): Fix bug about 94- and 96-set.
[chise/xemacs-chise.git] / src / glyphs-msw.c
index f95c1e8..7a9f8d3 100644 (file)
@@ -1,5 +1,5 @@
 /* mswindows-specific glyph objects.
-   Copyright (C) 1998 Andy Piper.
+   Copyright (C) 1998, 99 Andy Piper.
    
 This file is part of XEmacs.
 
@@ -47,15 +47,37 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #include <stdio.h>
 #include <ctype.h>
+#ifdef HAVE_XFACE
+#include <setjmp.h>
+#endif
 
 #define WIDGET_GLYPH_SLOT 0
 
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing);
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (string);
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string);
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit);
+#ifdef HAVE_JPEG
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
+#endif
+#ifdef HAVE_TIFF
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (tiff);
+#endif  
+#ifdef HAVE_PNG
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (png);
+#endif  
+#ifdef HAVE_GIF
+DECLARE_IMAGE_INSTANTIATOR_FORMAT (gif);
+#endif  
 #ifdef HAVE_XPM
 DEFINE_DEVICE_IIFORMAT (mswindows, xpm);
 #endif
 DEFINE_DEVICE_IIFORMAT (mswindows, xbm);
+#ifdef HAVE_XFACE
+DEFINE_DEVICE_IIFORMAT (mswindows, xface);
+#endif
 DEFINE_DEVICE_IIFORMAT (mswindows, button);
-DEFINE_DEVICE_IIFORMAT (mswindows, edit);
+DEFINE_DEVICE_IIFORMAT (mswindows, edit_field);
 #if 0
 DEFINE_DEVICE_IIFORMAT (mswindows, group);
 #endif
@@ -63,7 +85,10 @@ DEFINE_DEVICE_IIFORMAT (mswindows, subwindow);
 DEFINE_DEVICE_IIFORMAT (mswindows, widget);
 DEFINE_DEVICE_IIFORMAT (mswindows, label);
 DEFINE_DEVICE_IIFORMAT (mswindows, scrollbar);
-DEFINE_DEVICE_IIFORMAT (mswindows, combo);
+DEFINE_DEVICE_IIFORMAT (mswindows, combo_box);
+DEFINE_DEVICE_IIFORMAT (mswindows, progress_gauge);
+DEFINE_DEVICE_IIFORMAT (mswindows, tree_view);
+DEFINE_DEVICE_IIFORMAT (mswindows, tab_control);
 
 DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp);
 Lisp_Object Qbmp;
@@ -82,6 +107,7 @@ mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image,
                                          struct frame* f);
 
 COLORREF mswindows_string_to_color (CONST char *name);
+void check_valid_item_list_1 (Lisp_Object items);
 
 #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3)))
 
@@ -240,13 +266,13 @@ mswindows_locate_pixmap_file (Lisp_Object name)
        return Qnil;
     }
 
-  if (locate_file (Vmswindows_bitmap_file_path, name, "", &found, R_OK) < 0)
+  if (locate_file (Vmswindows_bitmap_file_path, name, Qnil, &found, R_OK) < 0)
     {
       Lisp_Object temp = list1 (Vdata_directory);
       struct gcpro gcpro1;
 
       GCPRO1 (temp);
-      locate_file (temp, name, "", &found, R_OK);
+      locate_file (temp, name, Qnil, &found, R_OK);
       UNGCPRO;
     }
     
@@ -275,7 +301,7 @@ init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii,
   struct device *d = XDEVICE (device);
   struct frame *f;
   void* bmp_buf=0;
-  int type;
+  int type = 0;
   HBITMAP bitmap;
   HDC hdc;
 
@@ -679,6 +705,7 @@ extract_xpm_color_names (Lisp_Object device,
        COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (XCDR (cons)));
 
       GET_C_STRING_OS_DATA_ALLOCA (XCAR (cons), colortbl[j].name);
+      colortbl[j].name = xstrdup (colortbl[j].name); /* mustn't lose this when we return */
       free_cons (XCONS (cons));
       cons = results;
       results = XCDR (results);
@@ -877,7 +904,13 @@ mswindows_xpm_instantiate (Lisp_Object image_instance,
     }
   
   if (color_symbols)
-    xfree(color_symbols);
+    {
+      while (nsymbols--)
+       {
+         xfree (color_symbols[nsymbols].name);
+       }
+      xfree(color_symbols);
+    }
   
   /* build a bitmap from the eimage */
   if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage,
@@ -1176,8 +1209,7 @@ mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instanti
 #ifdef __CYGWIN32__
       CYGWIN_WIN32_PATH (f, fname);
 #else
-      /* #### FIXME someone who knows ... */
-      fname = f
+      fname = f;
 #endif
       
       if (NILP (resource_id))
@@ -1562,7 +1594,7 @@ xbm_create_bitmap_from_data (HDC hdc, char *data,
                             int mask, COLORREF fg, COLORREF bg)
 {
   int old_width = (width + 7)/8;
-  int new_width = 2*((width + 15)/16);
+  int new_width = BPLINE (2*((width + 15)/16));
   unsigned char *offset;
   void *bmp_buf = 0;
   unsigned char *new_data, *new_offset;
@@ -1574,7 +1606,7 @@ xbm_create_bitmap_from_data (HDC hdc, char *data,
   if (!bmp_info)
     return NULL;
   
-  new_data = (unsigned char *) xmalloc (height * new_width);
+  new_data = (unsigned char *) xmalloc_and_zero (height * new_width);
       
   if (!new_data)
     {
@@ -1587,8 +1619,6 @@ xbm_create_bitmap_from_data (HDC hdc, char *data,
       offset = data + i*old_width;
       new_offset = new_data + i*new_width;
 
-      new_offset[new_width - 1] = 0; /* there may be an extra byte
-                                        that needs to be padded */
       for (j=0; j<old_width; j++)
        {
          int byte = offset[j];
@@ -1608,7 +1638,7 @@ xbm_create_bitmap_from_data (HDC hdc, char *data,
     }
 
   bmp_info->bmiHeader.biWidth=width;
-  bmp_info->bmiHeader.biHeight=-height;
+  bmp_info->bmiHeader.biHeight=-(LONG)height;
   bmp_info->bmiHeader.biPlanes=1;
   bmp_info->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
   bmp_info->bmiHeader.biBitCount=1; 
@@ -1833,6 +1863,93 @@ mswindows_xbm_instantiate (Lisp_Object image_instance,
                     XINT (XCAR (XCDR (data))), gcc_go_home);
 }
 
+#ifdef HAVE_XFACE
+/**********************************************************************
+ *                             X-Face                                 *
+ **********************************************************************/
+#if defined(EXTERN)
+/* This is about to get redefined! */
+#undef EXTERN
+#endif
+/* We have to define SYSV32 so that compface.h includes string.h
+   instead of strings.h. */
+#define SYSV32
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <compface.h>
+#ifdef __cplusplus
+}
+#endif
+/* JMP_BUF cannot be used here because if it doesn't get defined
+   to jmp_buf we end up with a conflicting type error with the
+   definition in compface.h */
+extern jmp_buf comp_env;
+#undef SYSV32
+
+static void
+mswindows_xface_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                            int dest_mask, Lisp_Object domain)
+{
+  Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
+  int i, stattis;
+  char *p, *bits, *bp;
+  CONST char * volatile emsg = 0;
+  CONST char * volatile dstring;
+
+  assert (!NILP (data));
+
+  GET_C_STRING_BINARY_DATA_ALLOCA (data, dstring);
+
+  if ((p = strchr (dstring, ':')))
+    {
+      dstring = p + 1;
+    }
+
+  /* Must use setjmp not SETJMP because we used jmp_buf above not JMP_BUF */
+  if (!(stattis = setjmp (comp_env)))
+    {
+      UnCompAll ((char *) dstring);
+      UnGenFace ();
+    }
+
+  switch (stattis)
+    {
+    case -2:
+      emsg = "uncompface: internal error";
+      break;
+    case -1:
+      emsg = "uncompface: insufficient or invalid data";
+      break;
+    case 1:
+      emsg = "uncompface: excess data ignored";
+      break;
+    }
+
+  if (emsg)
+    signal_simple_error_2 (emsg, data, Qimage);
+
+  bp = bits = (char *) alloca (PIXELS / 8);
+
+  /* the compface library exports char F[], which uses a single byte per
+     pixel to represent a 48x48 bitmap.  Yuck. */
+  for (i = 0, p = F; i < (PIXELS / 8); ++i)
+    {
+      int n, b;
+      /* reverse the bit order of each byte... */
+      for (b = n = 0; b < 8; ++b)
+       {
+         n |= ((*p++) << b);
+       }
+      *bp++ = (char) n;
+    }
+
+  xbm_instantiate_1 (image_instance, instantiator, pointer_fg,
+                    pointer_bg, dest_mask, 48, 48, bits);
+}
+#endif /* HAVE_XFACE */
+
 \f
 /************************************************************************/
 /*                      image instance methods                          */
@@ -1933,6 +2050,17 @@ mswindows_map_subwindow (struct Lisp_Image_Instance *p, int x, int y)
                | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
 }
 
+/* resize the subwindow instance */
+static void 
+mswindows_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h)
+{
+  SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), 
+               NULL, 
+               0, 0, w, h,
+               SWP_NOZORDER | SWP_NOMOVE
+               | SWP_NOCOPYBITS | SWP_NOSENDCHANGING);
+}
+
 /* when you click on a widget you may activate another widget this
    needs to be checked and all appropriate widgets updated */
 static void
@@ -1943,7 +2071,7 @@ mswindows_update_subwindow (struct Lisp_Image_Instance *p)
       /* buttons checked or otherwise */
       if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton))
        {
-         if (gui_item_selected_p (&IMAGE_INSTANCE_WIDGET_ITEM (p)))
+         if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p)))
            SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), 
                         BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 
          else
@@ -1957,19 +2085,26 @@ mswindows_update_subwindow (struct Lisp_Image_Instance *p)
    callbacks. The hashtable is weak so deregistration is handled
    automatically */
 static int
-mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
+mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain)
 {
   Lisp_Object frame = FW_FRAME (domain);
   struct frame* f = XFRAME (frame);
-  int id = gui_item_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
-                         &XIMAGE_INSTANCE_WIDGET_ITEM (instance),
-                         WIDGET_GLYPH_SLOT);
+  int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
+                            gui,
+                            WIDGET_GLYPH_SLOT);
   Fputhash (make_int (id),
-           XIMAGE_INSTANCE_WIDGET_CALLBACK (instance),
+           XGUI_ITEM (gui)->callback,
            FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
   return id;
 }
 
+static int
+mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
+{
+  return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_SINGLE_ITEM (instance),
+                                     domain);
+}
+
 static void
 mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                                 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -2066,7 +2201,6 @@ mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii,
 /************************************************************************/
 /*                            widgets                            */
 /************************************************************************/
-
 static void
 mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                              Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -2084,7 +2218,8 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   Extbyte* nm=0;
   HWND wnd;
   int id = 0xffff;
-  struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
+  Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+  struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
 
   if (!DEVICE_MSWINDOWS_P (d))
     signal_simple_error ("Not an mswindows device", device);
@@ -2099,7 +2234,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
       groupii = XIMAGE_INSTANCE (group);
     }
 #endif
-  if (!gui_item_active_p (pgui))
+  if (!gui_item_active_p (gui))
     flags |= WS_DISABLED;
 
   style = pgui->style;
@@ -2158,11 +2293,23 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
   HWND wnd;
   int flags = BS_NOTIFY;
   Lisp_Object style;
-  struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
-  
-  if (!gui_item_active_p (pgui))
+  Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+  struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
+  Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
+
+  if (!gui_item_active_p (gui))
     flags |= WS_DISABLED;
 
+  if (!NILP (glyph))
+    {
+      if (!IMAGE_INSTANCEP (glyph))
+       glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
+
+      if (IMAGE_INSTANCEP (glyph))
+       flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? 
+         BS_BITMAP : BS_ICON;
+    }
+
   style = pgui->style;
 
   if (EQ (style, Qradio))
@@ -2182,15 +2329,25 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat
 
   wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
   /* set the checked state */
-  if (gui_item_selected_p (pgui))
+  if (gui_item_selected_p (gui))
     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); 
   else
     SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
+  /* add the image if one was given */
+  if (!NILP (glyph) && IMAGE_INSTANCEP (glyph))
+    {
+      SendMessage (wnd, BM_SETIMAGE, 
+                  (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ? 
+                            IMAGE_BITMAP : IMAGE_ICON),
+                  (LPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
+                            XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
+                            XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
+    }
 }
 
 /* instantiate an edit control */
 static void
-mswindows_edit_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                            Lisp_Object pointer_fg, Lisp_Object pointer_bg,
                            int dest_mask, Lisp_Object domain)
 {
@@ -2201,6 +2358,238 @@ mswindows_edit_instantiate (Lisp_Object image_instance, Lisp_Object instantiator
                                WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
 }
 
+/* instantiate a progress gauge */
+static void
+mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                               Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                               int dest_mask, Lisp_Object domain)
+{
+  HWND wnd;
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+                               pointer_bg, dest_mask, domain, PROGRESS_CLASS, 
+                               WS_TABSTOP | WS_BORDER | PBS_SMOOTH,
+                               WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
+  wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+  /* set the colors */
+#ifdef PBS_SETBKCOLOR
+  SendMessage (wnd, PBS_SETBKCOLOR, 0, 
+              (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR 
+                        (XCOLOR_INSTANCE 
+                         (FACE_BACKGROUND 
+                          (XIMAGE_INSTANCE_WIDGET_FACE (ii),
+                           XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+#endif
+#ifdef PBS_SETBARCOLOR
+  SendMessage (wnd, PBS_SETBARCOLOR, 0, 
+              (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR 
+                         (XCOLOR_INSTANCE 
+                          (FACE_FOREGROUND 
+                           (XIMAGE_INSTANCE_WIDGET_FACE (ii),
+                            XIMAGE_INSTANCE_SUBWINDOW_FRAME (ii))))));
+#endif
+}
+
+/* instantiate a tree view widget */
+static HTREEITEM add_tree_item (Lisp_Object image_instance,
+                               HWND wnd, HTREEITEM parent, Lisp_Object entry,
+                               int children, Lisp_Object domain)
+{
+  TV_INSERTSTRUCT tvitem;
+  HTREEITEM ret;
+
+  tvitem.hParent = parent;
+  tvitem.hInsertAfter = TVI_LAST;
+  tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
+  tvitem.item.cChildren = children;
+      
+  if (VECTORP (entry))
+    {
+      /* we always maintain the real gui item at the head of the
+         list. We have to put them in the list in the first place
+         because the whole model assumes that the glyph instances have
+         references to all the associated data. If we didn't do this
+         GC would bite us badly. */
+      Lisp_Object gui = gui_parse_item_keywords_no_errors (entry);
+      if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)))
+       {
+         Lisp_Object rest = 
+           Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)));
+         Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest);
+       }
+      else
+       {
+         XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) = 
+           Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui);
+       }
+
+      tvitem.item.lParam = mswindows_register_gui_item (gui, domain);
+      tvitem.item.mask |= TVIF_PARAM;
+      GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name, 
+                                  tvitem.item.pszText);
+    }
+  else
+    GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.item.pszText);
+
+  tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
+
+  if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM, 
+                                    0, (LPARAM)&tvitem)) == 0)
+    signal_simple_error ("error adding tree view entry", entry);
+
+  return ret;
+}
+
+static void add_tree_item_list (Lisp_Object image_instance,
+                               HWND wnd, HTREEITEM parent, Lisp_Object list,
+                               Lisp_Object domain)
+{
+  Lisp_Object rest;
+
+  /* get the first item */
+  parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
+  /* recursively add items to the tree view */
+  LIST_LOOP (rest, XCDR (list))
+    {
+      if (LISTP (XCAR (rest)))
+       add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
+      else
+       add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
+    }
+}
+
+static void
+mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                           Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                           int dest_mask, Lisp_Object domain)
+{
+  Lisp_Object rest;
+  HWND wnd;
+  HTREEITEM parent;
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+                               pointer_bg, dest_mask, domain, WC_TREEVIEW, 
+                               WS_TABSTOP | WS_BORDER | PBS_SMOOTH
+                               | TVS_HASLINES | TVS_HASBUTTONS,
+                               WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
+
+  wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+  /* define a root */
+  parent = add_tree_item (image_instance,
+                         wnd, NULL, IMAGE_INSTANCE_WIDGET_TEXT (ii), TRUE,
+                         domain);
+  /* recursively add items to the tree view */
+  LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
+    {
+      if (LISTP (XCAR (rest)))
+       add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
+      else
+       add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
+    }
+}
+
+/* instantiate a tab control */
+static TC_ITEM* add_tab_item (Lisp_Object image_instance,
+                            HWND wnd, Lisp_Object entry,
+                            Lisp_Object domain, int index)
+{
+  TC_ITEM tvitem, *ret;
+
+  tvitem.mask = TCIF_TEXT;
+      
+  if (VECTORP (entry))
+    {
+      /* we always maintain the real gui item at the head of the
+         list. We have to put them in the list in the first place
+         because the whole model assumes that the glyph instances have
+         references to all the associated data. If we didn't do this
+         GC would bite us badly. */
+      Lisp_Object gui = gui_parse_item_keywords_no_errors (entry);
+      if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)))
+       {
+         Lisp_Object rest = 
+           Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)));
+         Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest);
+       }
+      else
+       {
+         XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) = 
+           Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui);
+       }
+
+      tvitem.lParam = mswindows_register_gui_item (gui, domain);
+      tvitem.mask |= TCIF_PARAM;
+      GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name, 
+                                  tvitem.pszText);
+    }
+  else
+    GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.pszText);
+
+  tvitem.cchTextMax = strlen (tvitem.pszText);
+
+  if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM, 
+                                   index, (LPARAM)&tvitem)) < 0)
+    signal_simple_error ("error adding tab entry", entry);
+
+  return ret;
+}
+
+static void
+mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+                          Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+                          int dest_mask, Lisp_Object domain)
+{
+  Lisp_Object rest;
+  HWND wnd;
+  int index = 0;
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+  mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+                               pointer_bg, dest_mask, domain, WC_TABCONTROL, 
+                               /* borders don't suit tabs so well */
+                               WS_TABSTOP,
+                               WS_EX_CONTROLPARENT);
+
+  wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+  /* add items to the tab */
+  LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
+    {
+      add_tab_item (image_instance, wnd, XCAR (rest), domain, index);
+      index++;
+    }
+}
+
+/* set the properties of a tab control */
+static Lisp_Object
+mswindows_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop,
+                                   Lisp_Object val)
+{
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  if (EQ (prop, Q_items))
+    {
+      HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+      int index = 0;
+      Lisp_Object rest;
+      check_valid_item_list_1 (val);
+
+      /* delete the pre-existing items */
+      SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
+  
+      /* add items to the tab */
+      LIST_LOOP (rest, val)
+       {
+         add_tab_item (image_instance, wnd, XCAR (rest), 
+                       IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), index);
+         index++;
+       }
+
+      return Qt;
+    }
+  return Qunbound;
+}
+
 /* instantiate a static control possible for putting other things in */
 static void
 mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
@@ -2240,7 +2629,7 @@ mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instant
 
 /* instantiate a combo control */
 static void
-mswindows_combo_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
                             Lisp_Object pointer_fg, Lisp_Object pointer_bg,
                             int dest_mask, Lisp_Object domain)
 {
@@ -2283,7 +2672,7 @@ mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
   /* get the text from a control */
-  if (EQ (prop, Qtext))
+  if (EQ (prop, Q_text))
     {
       Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
       Extbyte* buf =alloca (len+1);
@@ -2301,7 +2690,7 @@ mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
   /* check the state of a button */
-  if (EQ (prop, Qselected))
+  if (EQ (prop, Q_selected))
     {
       if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
        return Qt;
@@ -2313,12 +2702,12 @@ mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
 
 /* get properties of a combo box */
 static Lisp_Object
-mswindows_combo_property (Lisp_Object image_instance, Lisp_Object prop)
+mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
 {
   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
   HANDLE wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
   /* get the text from a control */
-  if (EQ (prop, Qtext))
+  if (EQ (prop, Q_text))
     {
       long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
       Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
@@ -2336,7 +2725,7 @@ mswindows_widget_set_property (Lisp_Object image_instance, Lisp_Object prop,
 {
   struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
 
-  if (EQ (prop, Qtext))
+  if (EQ (prop, Q_text))
     {
       Extbyte* lparam=0;
       CHECK_STRING (val);
@@ -2348,6 +2737,23 @@ mswindows_widget_set_property (Lisp_Object image_instance, Lisp_Object prop,
   return Qunbound;
 }
 
+/* set the properties of a progres guage */
+static Lisp_Object
+mswindows_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object prop,
+                                Lisp_Object val)
+{
+  struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+  if (EQ (prop, Q_percent))
+    {
+      CHECK_INT (val);
+      SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+                  PBM_SETPOS, (WPARAM)XINT (val), 0);
+      return Qt;
+    }
+  return Qunbound;
+}
+
 \f
 /************************************************************************/
 /*                            initialization                            */
@@ -2374,11 +2780,16 @@ console_type_create_glyphs_mswindows (void)
   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, resize_subwindow);
 }
 
 void
 image_instantiator_format_create_glyphs_mswindows (void)
 {
+  IIFORMAT_VALID_CONSOLE (mswindows, nothing);
+  IIFORMAT_VALID_CONSOLE (mswindows, string);
+  IIFORMAT_VALID_CONSOLE (mswindows, formatted_string);
+  IIFORMAT_VALID_CONSOLE (mswindows, inherit);
   /* image-instantiator types */
 #ifdef HAVE_XPM
   INITIALIZE_DEVICE_IIFORMAT (mswindows, xpm);
@@ -2386,13 +2797,29 @@ image_instantiator_format_create_glyphs_mswindows (void)
 #endif
   INITIALIZE_DEVICE_IIFORMAT (mswindows, xbm);
   IIFORMAT_HAS_DEVMETHOD (mswindows, xbm, instantiate);
-
+#ifdef HAVE_XFACE
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
+#endif
+#ifdef HAVE_JPEG
+  IIFORMAT_VALID_CONSOLE (mswindows, jpeg);
+#endif
+#ifdef HAVE_TIFF
+  IIFORMAT_VALID_CONSOLE (mswindows, tiff);
+#endif  
+#ifdef HAVE_PNG
+  IIFORMAT_VALID_CONSOLE (mswindows, png);
+#endif  
+#ifdef HAVE_GIF
+  IIFORMAT_VALID_CONSOLE (mswindows, gif);
+#endif  
+  /* button widget */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
   IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
 
-  INITIALIZE_DEVICE_IIFORMAT (mswindows, edit);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, edit, instantiate);
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, edit_field);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, edit_field, instantiate);
   
   INITIALIZE_DEVICE_IIFORMAT (mswindows, subwindow);
   IIFORMAT_HAS_DEVMETHOD (mswindows, subwindow, instantiate);
@@ -2404,18 +2831,36 @@ image_instantiator_format_create_glyphs_mswindows (void)
   INITIALIZE_DEVICE_IIFORMAT (mswindows, group);
   IIFORMAT_HAS_DEVMETHOD (mswindows, group, instantiate);
 #endif
+  /* label */
   INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
   IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
 
-  INITIALIZE_DEVICE_IIFORMAT (mswindows, combo);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, combo, property);
-  IIFORMAT_HAS_DEVMETHOD (mswindows, combo, 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);
 
-  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
+  /* progress gauge */
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, progress_gauge);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, progress_gauge, set_property);
+  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);
+
+  /* tab control widget */
+  INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate);
+  IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, set_property);
 
+  /* windows bitmap format */
+  INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
   IIFORMAT_HAS_METHOD (bmp, validate);
   IIFORMAT_HAS_METHOD (bmp, normalize);
   IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
@@ -2423,7 +2868,9 @@ image_instantiator_format_create_glyphs_mswindows (void)
 
   IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
   IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
+  IIFORMAT_VALID_CONSOLE (mswindows, bmp);
 
+  /* mswindows resources */
   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
                                        "mswindows-resource");
 
@@ -2436,24 +2883,17 @@ image_instantiator_format_create_glyphs_mswindows (void)
                          check_valid_resource_symbol);
   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_resource_id, check_valid_resource_id);
   IIFORMAT_VALID_KEYWORD (mswindows_resource, Q_file, check_valid_string);
+  IIFORMAT_VALID_CONSOLE (mswindows, mswindows_resource);
 }
 
 void
 vars_of_glyphs_mswindows (void)
 {
-  Fprovide (Qbmp);
-  Fprovide (Qmswindows_resource);
   DEFVAR_LISP ("mswindows-bitmap-file-path", &Vmswindows_bitmap_file_path /*
 A list of the directories in which mswindows bitmap files may be found.
 This is used by the `make-image-instance' function.
 */ );
   Vmswindows_bitmap_file_path = Qnil;
-
-  Fprovide (Qbutton);
-  Fprovide (Qedit);
-  Fprovide (Qcombo);
-  Fprovide (Qscrollbar);
-  Fprovide (Qlabel);
 }
 
 void