Index: lisp/gui.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/gui.el,v
retrieving revision 1.5.2.3
diff -u -r1.5.2.3 gui.el
--- lisp/gui.el 1999/10/20 07:14:33 1.5.2.3
+++ lisp/gui.el 2001/01/17 21:09:40
@@ -94,14 +94,25 @@
       (set-face-foreground 'gui-button-face '(((x color) . "black")
 					      ((mswindows color) . "black")))))
 
+
+(defun gui-button-action (instance action user-data)
+  (let ((domain (image-instance-domain instance)))
+    (with-current-buffer (if (windowp domain)
+			     (window-buffer domain) nil)
+      (funcall action user-data))))
+
 (defun make-gui-button (string &optional action user-data)
   "Make a GUI button whose label is STRING and whose action is ACTION.
 If the button is inserted in a buffer and then clicked on, and ACTION
-is non-nil, ACTION will be called with one argument, USER-DATA."
+is non-nil, ACTION will be called with one argument, USER-DATA.
+When ACTION is called, the buffer containing the button is made current."
   (vector 'button
 	  :descriptor string
 	  :face 'gui-button-face
-	  :callback `(funcall (quote ,action) (quote ,user-data))))
+	  :callback-ex `(lambda (image-instance event)
+			  (gui-button-action image-instance
+					     (quote ,action)
+					     (quote ,user-data)))))
 
 (defun insert-gui-button (button &optional pos buffer)
   "Insert GUI button BUTTON at POS in BUFFER."
Index: lisp/package-get.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/package-get.el,v
retrieving revision 1.13.2.32
diff -u -r1.13.2.32 package-get.el
--- lisp/package-get.el 2001/01/17 07:05:18 1.13.2.32
+++ lisp/package-get.el 2001/01/17 21:09:47
@@ -1048,7 +1048,8 @@
 	    (if (eval (intern (concat (symbol-name (car pkg)) "-package")))
 		(package-get (car pkg) nil))
 	    t)
-	  package-get-base))
+	  package-get-base)
+  (package-net-update-installed-db))
 
 (defun package-get-ever-installed-p (pkg &optional notused)
   (string-match "-package$" (symbol-name pkg))
Index: lisp/package-net.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/Attic/package-net.el,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 package-net.el
--- lisp/package-net.el 2001/01/12 16:33:09 1.1.2.5
+++ lisp/package-net.el 2001/01/17 21:09:47
@@ -185,28 +185,31 @@
   "Write out the installed package index in a net install suitable format.
 If DESTDIR is non-nil then use that as the destination directory. 
 DESTDIR defaults to the value of `package-net-setup-directory'."
-  ;; Need the local version
-  (package-get-require-base)
 
-  (setq destdir (file-name-as-directory 
-		 (or destdir (package-net-setup-directory))))
-  (let ((buf (get-buffer-create "*installed.db*")))
-    (unwind-protect
-        (save-excursion
-          (set-buffer buf)
-          (erase-buffer buf)
-          (goto-char (point-min))
-          (let ((entries package-get-base) entry plist)
-	    (while entries
-	      (setq entry (car entries))
-	      (setq plist (car (cdr entry)))
-	      (insert (format "%s %s %s\n" (symbol-name (car entry))
-			      (plist-get plist 'filename)
-			      (plist-get plist 'size)))
-	      (setq entries (cdr entries))))
-	  (make-directory-path destdir)
-	  (write-region (point-min) (point-max) (concat destdir "installed.db")))
-      (kill-buffer buf))))
+  (when (or (eq system-type 'cygwin32)
+	    (eq system-type 'window-nt))
+    (setq destdir (file-name-as-directory 
+		   (or destdir (package-net-setup-directory))))
+    (let ((buf (get-buffer-create "*installed.db*")))
+      (unwind-protect
+	  (save-excursion
+	    (set-buffer buf)
+	    (erase-buffer buf)
+	    (goto-char (point-min))
+	    ;; we use packages-package-list here as we actually want to
+	    ;; update relative to the installed reality
+	    (let ((entries packages-package-list) entry version)
+	      (while entries
+		(setq entry (car entries))
+		(setq version (plist-get (cdr entry) :version))
+		;; Unfortunately we can't read the size from this
+		(insert (format "%s %s-%3.2f-pkg.tar.gz 0\n" (symbol-name (car entry))
+				(symbol-name (car entry))
+				version))
+		(setq entries (cdr entries))))
+	    (make-directory-path destdir)
+	    (write-region (point-min) (point-max) (concat destdir "installed.db")))
+	(kill-buffer buf)))))
 
 (defun package-net-convert-download-sites-to-mirrors (&optional destdir)
   "Write out the download site list in a net install suitable format.
Index: lisp/package-ui.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/package-ui.el,v
retrieving revision 1.1.2.12
diff -u -r1.1.2.12 package-ui.el
--- lisp/package-ui.el 2000/07/21 10:15:20 1.1.2.12
+++ lisp/package-ui.el 2001/01/17 21:09:49
@@ -424,6 +424,8 @@
       (if pui-deleted-packages
 	  (pui-list-packages)
 	(error "No packages have been selected!")))
+    ;; sync with windows type systems
+    (package-net-update-installed-db)
     ))
 
 (defun pui-add-required-packages ()
Index: lisp/packages.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/packages.el,v
retrieving revision 1.29.2.18
diff -u -r1.29.2.18 packages.el
--- lisp/packages.el 2000/12/13 08:12:00 1.29.2.18
+++ lisp/packages.el 2001/01/17 21:09:51
@@ -55,7 +55,7 @@
 ;;; Package versioning
 
 (defvar packages-package-list nil
-  "Database of loaded packages and version numbers")
+  "Database of installed packages and version numbers")
 
 (defvar packages-hierarchy-depth 1
   "Depth of package hierarchies.")
Index: lisp/wid-edit.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/lisp/wid-edit.el,v
retrieving revision 1.11.2.15
diff -u -r1.11.2.15 wid-edit.el
--- lisp/wid-edit.el 2000/11/23 06:27:38 1.11.2.15
+++ lisp/wid-edit.el 2001/01/17 21:10:12
@@ -480,14 +480,22 @@
       (let* ((glyph-widget (extent-property extent 'glyph-widget))
 	     (up-glyph (widget-get glyph-widget :glyph-up))
 	     (inactive-glyph (widget-get glyph-widget :glyph-inactive))
+	     (instantiator (widget-get glyph-widget :glyph-instantiator))
 	     (new-glyph (if activate-p up-glyph inactive-glyph)))
+	(cond
+	 ;; Assume that an instantiator means a native widget.
+	 (instantiator
+	  (setq instantiator
+		(set-instantiator-property instantiator :active activate-p))
+	  (widget-put glyph-widget :glyph-instantiator instantiator)
+	  (set-glyph-image up-glyph instantiator))
 	 ;; Check that the new glyph exists, and differs from the
 	 ;; default one.
-	(and up-glyph inactive-glyph (not (eq up-glyph inactive-glyph))
-	     ;; Check if the glyph is already installed.
-	     (not (eq (extent-end-glyph extent) new-glyph))
-	     ;; Change it.
-	     (set-extent-end-glyph extent new-glyph)))))
+	 ((and up-glyph inactive-glyph (not (eq up-glyph inactive-glyph))
+	       ;; Check if the glyph is already installed.
+	       (not (eq (extent-end-glyph extent) new-glyph)))
+	  ;; Change it.
+	  (set-extent-end-glyph extent new-glyph))))))
   nil)
 
 (defun widget-specify-inactive (widget from to)
@@ -785,10 +793,12 @@
       (insert tag))
     glyph))
 
-(defun widget-glyph-insert-glyph (widget glyph &optional down inactive)
+(defun widget-glyph-insert-glyph (widget glyph &optional down inactive
+					 instantiator)
   "In WIDGET, insert GLYPH.
 If optional arguments DOWN and INACTIVE are given, they should be
-glyphs used when the widget is pushed and inactive, respectively."
+glyphs used when the widget is pushed and inactive, respectively.
+INSTANTIATOR is the vector used to create the glyph."
   (insert "*")
   (let ((extent (make-extent (point) (1- (point))))
 	(help-echo (and widget (widget-get widget :help-echo)))
@@ -810,6 +820,7 @@
   (when widget
     (widget-put widget :glyph-up glyph)
     (when down (widget-put widget :glyph-down down))
+    (when instantiator (widget-put widget :glyph-instantiator instantiator))
     (when inactive (widget-put widget :glyph-inactive inactive))))
 
 
@@ -1924,7 +1935,7 @@
 	 (tag-glyph (widget-get widget :tag-glyph))
 	 (text (concat widget-push-button-prefix
 		       tag widget-push-button-suffix))
-	 gui)
+	 gui inst)
     (cond (tag-glyph
 	   (widget-glyph-insert widget text tag-glyph))
 	  ;; We must check for console-on-window-system-p here,
@@ -1933,9 +1944,9 @@
 	  ((and widget-push-button-gui
 		(console-on-window-system-p))
 	   (let* ((gui-button-shadow-thickness 1))
-	     (setq gui (make-glyph 
-			(make-gui-button tag 'widget-gui-action widget))))
-	   (widget-glyph-insert-glyph widget gui))
+	     (setq inst (make-gui-button tag 'widget-gui-action widget))
+	     (setq gui (make-glyph inst)))
+	   (widget-glyph-insert-glyph widget gui nil nil inst))
 	  (t
 	   (insert text)))))
 
Index: netinstall/ini.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/netinstall/Attic/ini.h,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 ini.h
--- netinstall/ini.h 2000/12/12 18:01:19 1.1.2.2
+++ netinstall/ini.h 2001/01/17 21:11:18
@@ -61,14 +61,14 @@
   } info[NTRUST+1];	/* +1 for TRUST_UNKNOWN */
 } Package;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern Package *package;
 extern Package *xemacs_package;
 
 extern int npackages;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 Package *new_package (char *name);
 void	ini_init (char *string);
Index: src/fns.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/fns.c,v
retrieving revision 1.30.2.47
diff -u -r1.30.2.47 fns.c
--- src/fns.c 2000/11/06 05:43:26 1.30.2.47
+++ src/fns.c 2001/01/17 21:11:35
@@ -56,6 +56,7 @@
 Lisp_Object Qidentity;
 
 static int internal_old_equal (Lisp_Object, Lisp_Object, int);
+Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth);
 
 static Lisp_Object
 mark_bit_vector (Lisp_Object obj)
@@ -863,6 +864,15 @@
 */
        (arg, vecp))
 {
+  return safe_copy_tree (arg, vecp, 0);
+}
+
+Lisp_Object
+safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth)
+{
+  if (depth > 200)
+    signal_simple_error ("Stack overflow in copy-tree", arg);
+    
   if (CONSP (arg))
     {
       Lisp_Object rest;
@@ -872,9 +882,9 @@
 	  Lisp_Object elt = XCAR (rest);
 	  QUIT;
 	  if (CONSP (elt) || VECTORP (elt))
-	    XCAR (rest) = Fcopy_tree (elt, vecp);
+	    XCAR (rest) = safe_copy_tree (elt, vecp, depth + 1);
 	  if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
-	    XCDR (rest) = Fcopy_tree (XCDR (rest), vecp);
+	    XCDR (rest) = safe_copy_tree (XCDR (rest), vecp, depth +1);
 	  rest = XCDR (rest);
 	}
     }
@@ -888,7 +898,7 @@
 	  Lisp_Object elt = XVECTOR_DATA (arg) [j];
 	  QUIT;
 	  if (CONSP (elt) || VECTORP (elt))
-	    XVECTOR_DATA (arg) [j] = Fcopy_tree (elt, vecp);
+	    XVECTOR_DATA (arg) [j] = safe_copy_tree (elt, vecp, depth + 1);
 	}
     }
   return arg;
Index: src/glyphs-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v
retrieving revision 1.21.2.68
diff -u -r1.21.2.68 glyphs-msw.c
--- src/glyphs-msw.c 2000/11/07 23:24:27 1.21.2.68
+++ src/glyphs-msw.c 2001/01/17 21:11:48
@@ -2326,6 +2326,24 @@
       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);
+    }
 }
 
 /* register widgets into our hashtable so that we can cope with the
@@ -2935,7 +2953,7 @@
       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;
 
       assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
@@ -2988,10 +3006,10 @@
 	      add_tab_item (image_instance, wnd, XCAR (rest),
 			    IMAGE_INSTANCE_FRAME (ii), i);
 	      if (gui_item_selected_p (XCAR (rest)))
-		selected = i;
+		selected_idx = i;
 	      i++;
 	    }
-	  SendMessage (wnd, TCM_SETCURSEL, selected, 0);
+	  SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0);
 	}
     }
 }
Index: src/glyphs-widget.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/glyphs-widget.c,v
retrieving revision 1.1.2.54
diff -u -r1.1.2.54 glyphs-widget.c
--- src/glyphs-widget.c 2000/09/26 15:37:19 1.1.2.54
+++ src/glyphs-widget.c 2001/01/17 21:11:54
@@ -294,16 +294,89 @@
 {
   Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
   struct image_instantiator_methods* meths;
+  struct gcpro gcpro1;
 
   Lisp_Object text = find_keyword_in_vector (instantiator, Q_text);
+  Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
+  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+  Lisp_Object descriptor_item = Qnil;
+
+  GCPRO1 (descriptor_item);
+
   /* Pick up any generic properties that we might need to keep hold
-     of. */
+     of. 
+     #### This is potentially bogus because it is changing the items
+     in place rather than in the pending items. */
   if (!NILP (text))
     {
       IMAGE_INSTANCE_WIDGET_TEXT (ii) = text;
       IMAGE_INSTANCE_TEXT_CHANGED (ii) = 1;
     }
 
+  /* Retrieve the gui item information. This is easy if we have been
+     provided with a vector, more difficult if we have just been given
+     keywords.
+
+     #### This is inconsistent with instantiation in that you have to
+     have the :descriptor keyword for updates in order to recognise 
+     changes. */
+  if (VECTORP (desc))
+    {
+      descriptor_item = gui_parse_item_keywords_no_errors (desc);
+    }
+  else
+    {
+      /* Since we are updating the instantiator could be incomplete
+	 and hence the gui item descriptor not well formed. We
+	 therefore try updating and discard the results if nothing
+	 changed. */
+      descriptor_item = copy_gui_item (IMAGE_INSTANCE_WIDGET_ITEM (ii));
+      if (!update_gui_item_keywords (descriptor_item, instantiator))
+	descriptor_item = Qnil;
+    }
+
+  /* Record new items for update. *_redisplay will do the
+     rest. */
+  if (!EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qlayout)
+      && 
+      !EQ (IMAGE_INSTANCE_WIDGET_TYPE (ii), Qnative_layout))
+    {
+      if (!NILP (items))
+	{
+	  if (NILP (descriptor_item))
+	    descriptor_item = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+	  
+	  check_valid_item_list (items);
+#ifdef DEBUG_WIDGET_OUTPUT
+	  stderr_out ("items for widget %p updated\n", 
+		      IMAGE_INSTANCE_SUBWINDOW_ID (ii));
+#endif
+	  /* Don't set the actual items since we might decide not to use
+	     the new ones (because nothing has really changed). If we did
+	     set them and didn't use them then we would get into whole
+	     heaps of trouble when the old items get GC'd. */
+	  descriptor_item = Fcons (descriptor_item, parse_gui_item_tree_children (items));
+	}
+      /* If the descriptor was updated but not the items we need to fill
+	 in the `new' items. */
+      else if (!NILP (descriptor_item) 
+	       && 
+	       CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+	{
+	  descriptor_item = Fcons 
+	    (descriptor_item,
+	     copy_gui_item_tree (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))));
+	}
+    }
+
+  if (!NILP (descriptor_item))
+    {
+      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = descriptor_item;
+      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
+    }
+
+  UNGCPRO;
+      
   /* Now try device specific methods first ... */
   meths = decode_device_ii_format (image_instance_device (image_instance),
 				   IMAGE_INSTANCE_WIDGET_TYPE (ii),
@@ -570,19 +643,24 @@
   if (!NILP (face))
     SET_IMAGE_INSTANCE_WIDGET_FACE (ii, Fget_face (face));
 
-  /* retrieve the gui item information. This is easy if we have been
+  /* Retrieve the gui item information. This is easy if we have been
      provided with a vector, more difficult if we have just been given
-     keywords */
-  if (STRINGP (desc) || NILP (desc))
+     keywords. Note that standard gui descriptor shortcuts will not work
+     because of keyword parsing.
+
+     #### This is bogus in that descriptor and items share the same slot, 
+     we should rationalize. */
+  if (VECTORP (desc))
     {
-      /* big cheat - we rely on the fact that a gui item looks like an instantiator */
       IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
-	gui_parse_item_keywords_no_errors (instantiator);
-      IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
+	gui_parse_item_keywords_no_errors (desc);
     }
   else
-    IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
-      gui_parse_item_keywords_no_errors (desc);
+    {
+      /* big cheat - we rely on the fact that a gui item looks like an instantiator */
+      IMAGE_INSTANCE_WIDGET_ITEMS (ii) =
+	widget_gui_parse_item_keywords (instantiator);
+    }
 
   /* Pick up the orientation before we do our first layout. */
   if (EQ (orient, Qleft) || EQ (orient, Qright) || EQ (orient, Qvertical))
@@ -776,32 +854,6 @@
     }
 }
 
-/* Update the contents of a tab control. */
-static void
-tab_control_update (Lisp_Object image_instance,
-		    Lisp_Object instantiator)
-{
-  Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
-  /* Record new items for update. *_tab_control_redisplay will do the
-     rest. */
-  if (!NILP (items))
-    {
-      Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
-      check_valid_item_list (items);
-#ifdef DEBUG_WIDGET_OUTPUT
-      stderr_out ("tab control %p updated\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
-#endif
-      /* Don't set the actual items since we might decide not to use
-         the new ones (because nothing has really changed). If we did
-         set them and didn't use them then we would get into whole
-         heaps of trouble when the old items get GC'd. */
-      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
-	Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
-	       parse_gui_item_tree_children (items));
-      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
-    }
-}
-
 /* Determine whether only the order has changed for a tab. */
 int tab_control_order_only_changed (Lisp_Object image_instance)
 {
@@ -840,32 +892,6 @@
   return found;
 }
 
-/* Set the properties of a progress gauge */
-static void
-progress_gauge_update (Lisp_Object image_instance,
-		       Lisp_Object instantiator)
-{
-  Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object value = find_keyword_in_vector (instantiator, Q_value);
-
-  if (!NILP (value))
-    {
-      CHECK_INT (value);
-#ifdef DEBUG_WIDGET_OUTPUT
-      stderr_out ("progress gauge value set to %ld\n", XINT (value));
-#endif
-      IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) =
-	copy_gui_item_tree (IMAGE_INSTANCE_WIDGET_ITEMS (ii));
-#ifdef ERROR_CHECK_GLYPHS
-      assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
-#endif
-      if (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
-	XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value = value;
-
-      IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 1;
-    }
-}
-
 
 /*****************************************************************************
  *                              widget layout                               *
@@ -1480,7 +1506,6 @@
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, post_instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (progress_gauge, governing_domain, subwindow);
-  IIFORMAT_HAS_METHOD (progress_gauge, update);
   VALID_WIDGET_KEYWORDS (progress_gauge);
   VALID_GUI_KEYWORDS (progress_gauge);
 
@@ -1495,7 +1520,6 @@
   IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, post_instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (tree_view, governing_domain, subwindow);
-  IIFORMAT_HAS_SHARED_METHOD (tree_view, update, tab_control);
   IIFORMAT_HAS_METHOD (tree_view, query_geometry);
   VALID_WIDGET_KEYWORDS (tree_view);
   VALID_GUI_KEYWORDS (tree_view);
@@ -1511,7 +1535,6 @@
   IIFORMAT_HAS_SHARED_METHOD (tab_control, post_instantiate, widget);
   IIFORMAT_HAS_SHARED_METHOD (tab_control, governing_domain, subwindow);
   IIFORMAT_HAS_METHOD (tab_control, query_geometry);
-  IIFORMAT_HAS_METHOD (tab_control, update);
   VALID_WIDGET_KEYWORDS (tab_control);
   VALID_GUI_KEYWORDS (tab_control);
   IIFORMAT_VALID_KEYWORD (tab_control, Q_orientation,
Index: src/glyphs-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v
retrieving revision 1.49.2.88
diff -u -r1.49.2.88 glyphs-x.c
--- src/glyphs-x.c 2001/01/05 13:49:47 1.49.2.88
+++ src/glyphs-x.c 2001/01/17 21:12:08
@@ -2228,7 +2228,13 @@
   /* Possibly update the colors and font */
   if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       ||
+      /* #### 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))
     {
Index: src/glyphs.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v
retrieving revision 1.23.2.92
diff -u -r1.23.2.92 glyphs.c
--- src/glyphs.c 2001/01/16 16:11:36 1.23.2.92
+++ src/glyphs.c 2001/01/17 21:12:25
@@ -1004,7 +1004,7 @@
 	  print_internal
 	    (IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
 	}
-
+      /* fallthrough */
 
     case IMAGE_SUBWINDOW:
       sprintf (buf, " %dx%d", IMAGE_INSTANCE_WIDTH (ii),
Index: src/gui.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.c,v
retrieving revision 1.10.2.34
diff -u -r1.10.2.34 gui.c
--- src/gui.c 2000/10/03 06:29:37 1.10.2.34
+++ src/gui.c 2001/01/17 21:12:27
@@ -37,6 +37,7 @@
 Lisp_Object Vmenu_no_selection_hook;
 
 static Lisp_Object parse_gui_item_tree_list (Lisp_Object list);
+Lisp_Object find_keyword_in_vector (Lisp_Object vector, Lisp_Object keyword);
 
 #ifdef HAVE_POPUPS
 
@@ -111,39 +112,63 @@
  * structure. If KEY is not a keyword, or is an unknown keyword, then
  * error is signaled.
  */
-void
+int
 gui_item_add_keyval_pair (Lisp_Object gui_item,
 			  Lisp_Object key, Lisp_Object val,
 			  Error_behavior errb)
 {
   Lisp_Gui_Item *pgui_item = XGUI_ITEM (gui_item);
+  int retval = 0;
 
   if (!KEYWORDP (key))
     syntax_error_2 ("Non-keyword in gui item", key, pgui_item->name);
 
-  if	  (EQ (key, Q_suffix))	 pgui_item->suffix   = val;
-  else if (EQ (key, Q_active))	 pgui_item->active   = val;
-  else if (EQ (key, Q_included)) pgui_item->included = val;
-  else if (EQ (key, Q_config))	 pgui_item->config   = val;
-  else if (EQ (key, Q_filter))	 pgui_item->filter   = val;
-  else if (EQ (key, Q_style))	 pgui_item->style    = val;
-  else if (EQ (key, Q_selected)) pgui_item->selected = val;
-  else if (EQ (key, Q_keys))	 pgui_item->keys     = val;
-  else if (EQ (key, Q_callback)) pgui_item->callback = val;
-  else if (EQ (key, Q_callback_ex)) pgui_item->callback_ex = val;
-  else if (EQ (key, Q_value))	 pgui_item->value     = val;
+  if (EQ (key, Q_descriptor))
+    {
+      if (!EQ (pgui_item->name, val))
+	{
+	  retval = 1;
+	  pgui_item->name   = val;
+	}
+    }
+#define FROB(slot) \
+  else if (EQ (key, Q_##slot))			\
+  {						\
+    if (!EQ (pgui_item->slot, val))			\
+      {						\
+	retval = 1;				\
+	pgui_item->slot   = val;			\
+      }						\
+  }
+  FROB (suffix)
+  FROB (active)
+  FROB (included)
+  FROB (config)
+  FROB (filter)
+  FROB (style)
+  FROB (selected)
+  FROB (keys)
+  FROB (callback)
+  FROB (callback_ex)
+  FROB (value)
+#undef FROB
   else if (EQ (key, Q_key_sequence)) ;   /* ignored for FSF compatibility */
   else if (EQ (key, Q_label)) ;   /* ignored for 21.0 implement in 21.2  */
   else if (EQ (key, Q_accelerator))
     {
-      if (SYMBOLP (val) || CHARP (val))
-	pgui_item->accelerator = val;
-      else if (ERRB_EQ (errb, ERROR_ME))
-	syntax_error ("Bad keyboard accelerator", val);
+      if (!EQ (pgui_item->accelerator, val))
+	{
+	  retval = 1;
+	  if (SYMBOLP (val) || CHARP (val))
+	    pgui_item->accelerator = val;
+	  else if (ERRB_EQ (errb, ERROR_ME))
+	    syntax_error ("Bad keyboard accelerator", val);
+	}
     }
   else if (ERRB_EQ (errb, ERROR_ME))
     syntax_error_2 ("Unknown keyword in gui item", key,
 			   pgui_item->name);
+  return retval;
 }
 
 void
@@ -248,6 +273,69 @@
   return gui_item;
 }
 
+/* This will only work with descriptors in the new format. */
+Lisp_Object
+widget_gui_parse_item_keywords (Lisp_Object item)
+{
+  int i, length;
+  Lisp_Object *contents;
+  Lisp_Object gui_item = allocate_gui_item ();
+  Lisp_Object desc = find_keyword_in_vector (item, Q_descriptor);
+
+  CHECK_VECTOR (item);
+  length = XVECTOR_LENGTH (item);
+  contents = XVECTOR_DATA (item);
+
+  if (!NILP (desc) && !STRINGP (desc) && !VECTORP (desc))
+    syntax_error ("Invalid GUI item descriptor", item);
+
+  if (length & 1)
+    {
+      if (!SYMBOLP (contents [0]))
+	syntax_error ("Invalid GUI item descriptor", item);
+      contents++;			/* Ignore the leading symbol. */
+      length--;
+    }
+
+  for (i = 0; i < length;)
+    {
+      Lisp_Object key = contents [i++];
+      Lisp_Object val = contents [i++];
+      gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME_NOT);
+    }
+
+  return gui_item;
+}
+
+/* Update a gui item from a partial descriptor. */
+int
+update_gui_item_keywords (Lisp_Object gui_item, Lisp_Object item)
+{
+  int i, length, retval = 0;
+  Lisp_Object *contents;
+
+  CHECK_VECTOR (item);
+  length = XVECTOR_LENGTH (item);
+  contents = XVECTOR_DATA (item);
+
+ if (length & 1)
+    {
+      if (!SYMBOLP (contents [0]))
+	syntax_error ("Invalid GUI item descriptor", item);
+      contents++;			/* Ignore the leading symbol. */
+      length--;
+    }
+
+  for (i = 0; i < length;)
+    {
+      Lisp_Object key = contents [i++];
+      Lisp_Object val = contents [i++];
+      if (gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME_NOT))
+	retval = 1;
+    }
+  return retval;
+}
+
 Lisp_Object
 gui_parse_item_keywords (Lisp_Object item)
 {
@@ -618,7 +706,7 @@
   write_c_string (buf, printcharfun);
 }
 
-static Lisp_Object
+Lisp_Object
 copy_gui_item (Lisp_Object gui_item)
 {
   Lisp_Object  ret = allocate_gui_item ();
Index: man/internals/internals.texi
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/man/internals/internals.texi,v
retrieving revision 1.17.2.42
diff -u -r1.17.2.42 internals.texi
--- man/internals/internals.texi 2001/01/12 13:59:07 1.17.2.42
+++ man/internals/internals.texi 2001/01/17 21:11:15
@@ -8734,8 +8734,8 @@
 Glyphs are lazily instantiated by calling one of the glyph
 functions. This usually occurs within redisplay when
 @code{Fglyph_height} is called. Instantiation causes an image-instance
-to be created and cached. This cache is on a device basis for all glyphs
-except glyph-widgets, and on a window basis for glyph widgets.  The
+to be created and cached. This cache is on a per-device basis for all glyphs
+except widget-glyphs, and on a per-window basis for widgets-glyphs.  The
 caching is done by @code{image_instantiate} and is necessary because it
 is generally possible to display an image-instance in multiple
 domains. For instance if we create a Pixmap, we can actually display
@@ -8752,16 +8752,109 @@
 Any action on a glyph first consults the cache before actually
 instantiating a widget.
 
+@section Glyph Instantiation
+
+Glyph instantiation is a hairy topic and requires some explanation. The
+guts of glyph instantiation is contained within
+@code{image_instantiate}. A glyph contains an image which is a
+specifier. When a glyph function - for instance @code{Fglyph_height} -
+asks for a property of the glyph that can only be determined from its
+instantiated state, then the glyph image is instantiated and an image
+instance created. The instantiation process is governed by the specifier
+code and goes through a series of steps:
+
+@itemize @bullet
+@item
+Validation. Instantiation of image instances happens dynamically - often
+within the guts of redisplay. Thus it is often not feasible to catch
+instantiator errors at instantiation time. Instead the instantiator is
+validated at the time it is added to the image specifier. This function
+is defined by @code{image_validate} and at a simple level validates
+keyword value pairs.
+@item
+Duplication. The specifier code by default takes a copy of the
+instantiator. This is reasonable for most specifiers but in the case of
+widget-glyphs can be problematic, since some of the properties in the
+instantiator - for instance callbacks - could cause infinite recursion
+in the copying process. Thus the image code defines a function -
+@code{image_copy_instantiator} - which will selectively copy values.
+This is controlled by the way that a keyword is defined either using
+@code{IIFORMAT_VALID_KEYWORD} or
+@code{IIFORMAT_VALID_NONCOPY_KEYWORD}. Note that the image caching and
+redisplay code relies on instantiator copying to ensure that current and
+new instantiators are actually different rather than referring to the
+same thing.
+@item
+Normalization. Once the instantiator has been copied it must be
+converted into a form that is viable at instantiation time. This can
+involve no changes at all, but typically involves things like converting
+file names to the actual data. This function is defined by
+@code{image_going_to_add} and @code{normalize_image_instantiator}.
+@item
+Instantiation. When an image instance is actually required for display
+it is instantiated using @code{image_instantiate}. This involves calling
+instantiate methods that are specific to the type of image being
+instantiated.
+@end itemize
+
+The final instantiation phase also involves a number of steps. In order
+to understand these we need to describe a number of concepts.
+
+An image is instantiated in a @dfn{domain}, where a domain can be any
+one of a device, frame, window or image-instance. The domain gives the
+image-instance context and identity and properties that affect the
+appearance of the image-instance may be different for the same glyph
+instantiated in different domains. An example is the face used to
+display the image-instance.
+
+Although an image is instantiated in a particular domain the
+instantiation domain is not necessarily the domain in which the
+image-instance is cached. For example a pixmap can be instantiated in a
+window be actually be cached on a per-device basis. The domain in which
+the image-instance is actually cached is called the
+@dfn{governing-domain}. A governing-domain is currently either a device
+or a window. Widget-glyphs and text-glyphs have a window as a
+governing-domain, all other image-instances have a device as the
+governing-domain. The governing domain for an image-instance is
+determined using the governing_domain image-instance method.
+
+@section Widget-Glyphs
+
 @section Widget-Glyphs in the MS-Windows Environment
 
 To Do
 
 @section Widget-Glyphs in the X Environment
 
 Widget-glyphs under X make heavy use of lwlib (@pxref{Lucid Widget
 Library}) for manipulating the native toolkit objects. This is primarily
 so that different toolkits can be supported for widget-glyphs, just as
 they are supported for features such as menubars etc.

+Lwlib is extremely poorly documented and quite hairy so here is my
+understanding of what goes on.
+
+Lwlib maintains a set of widget_instances which mirror the hierarchical
+state of Xt widgets. I think this is so that widgets can be updated and
+manipulated generically by the lwlib library. For instance
+update_one_widget_instance can cope with multiple types of widget and
+multiple types of toolkit. Each element in the widget hierarchy is updated
+from its corresponding widget_instance by walking the widget_instance
+tree recursively.
+
+This has desirable properties such as lw_modify_all_widgets which is
+called from @file{glyphs-x.c} and updates all the properties of a widget
+without having to know what the widget is or what toolkit it is from.
+Unfortunately this also has hairy properties such as making the lwlib
+code quite complex. And of course lwlib has to know at some level what
+the widget is and how to set its properties.
 
 @node Specifiers, Menus, Glyphs, Top
 @chapter Specifiers
