Index: src/buffer.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/buffer.c,v
retrieving revision 1.36.2.37
diff -u -r1.36.2.37 buffer.c
--- src/buffer.c 2000/08/06 09:27:05 1.36.2.37
+++ src/buffer.c 2000/08/18 17:05:45
@@ -1384,8 +1384,6 @@
   XCDR (lynk) = f->buffer_alist;
   f->buffer_alist = lynk;
 
-  MARK_FRAME_CHANGED (f);
-
   return Qnil;
 }
 
Index: src/frame.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/frame.c,v
retrieving revision 1.37.2.36
diff -u -r1.37.2.36 frame.c
--- src/frame.c 2000/08/06 09:27:13 1.37.2.36
+++ src/frame.c 2000/08/18 17:05:56
@@ -1560,9 +1560,9 @@
   /* Unfortunately deleting the frame will also delete the parent of
      all of the subwindow instances current on the frame. I think this
      can lead to bad things when trying to finalize the
-     instances. Thus we loop over the instance cache calling the
+     instances. Thus we loop over all instance caches calling the
      finalize method for each instance. */
-  free_frame_subwindow_instance_cache (f);
+  free_frame_subwindow_instances (f);
 
   /* This must be done before the window and window_mirror structures
      are freed.  The scrollbar information is attached to them. */
Index: src/glyphs-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v
retrieving revision 1.21.2.63
diff -u -r1.21.2.63 glyphs-msw.c
--- src/glyphs-msw.c 2000/08/06 09:27:14 1.21.2.63
+++ src/glyphs-msw.c 2000/08/18 17:06:05
@@ -2841,11 +2841,13 @@
 }
 
 /* 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;
 
@@ -2868,8 +2870,8 @@
 
   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;
@@ -2905,7 +2907,8 @@
   /* 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++;
@@ -2930,24 +2933,30 @@
 	 you click on one. */
       if (tab_control_order_only_changed (image_instance))
 	{
+	  Lisp_Object selected = gui_item_list_find_selected 
+	    (XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+
 	  LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
 	    {
-	      if (gui_item_equal_sans_selected
-		  (XCAR (rest),
-		   XCAR (XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))), 0))
-	      {
-		XGUI_ITEM (XCAR (rest))->selected = 
-		  XGUI_ITEM 
-		  (XCAR (XCDR 
-			 (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))))->selected;
-		SendMessage (wnd, TCM_SETCURSEL, i, 0);
-		break;
-	      }
+	      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);
+		  break;
+		}
 	      i++;
 	    }
-	  /* We're not actually changing the items. */
-	  IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
-	  IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
 	}
       else 
 	{
Index: src/glyphs-widget.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/glyphs-widget.c,v
retrieving revision 1.1.2.49
diff -u -r1.1.2.49 glyphs-widget.c
--- src/glyphs-widget.c 2000/08/06 09:27:15 1.1.2.49
+++ src/glyphs-widget.c 2000/08/18 17:06:09
@@ -783,7 +783,7 @@
 		    Lisp_Object instantiator)
 {
   Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
-  /* Record new items for update. *_tab_control_update will do the
+  /* Record new items for update. *_tab_control_redisplay will do the
      rest. */
   if (!NILP (items))
     {
Index: src/glyphs-x.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.c,v
retrieving revision 1.49.2.76
diff -u -r1.49.2.76 glyphs-x.c
--- src/glyphs-x.c 2000/08/06 09:27:15 1.49.2.76
+++ src/glyphs-x.c 2000/08/18 17:06:17
@@ -2207,10 +2208,8 @@
 
   /* Now do non structural updates. */
   wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (p));
+  assert (wv);
 
-  if (!wv)
-    return;
-
   /* Possibly update the colors and font */
   if (IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       ||
@@ -2719,37 +2718,54 @@
 
   if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
-      Lisp_Object rest;
       /* If only the order has changed then simply select the first
 	 one of the pending set. This stops horrendous rebuilding -
 	 and hence flicker - of the tabs each time you click on
 	 one. */
       if (tab_control_order_only_changed (image_instance))
 	{
-	  widget_value* wv = lw_get_all_values
-	    (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
-	  widget_value* cur = wv->contents;
+	  Lisp_Object rest;
+	  Lisp_Object selected = gui_item_list_find_selected 
+	    (XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
 	  LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
 	    {
-	      if (internal_equal 
-		  (XCAR (rest),
-		   XCAR (XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))), 0))
+	      if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
 		{
 		  /* There may be an encapsulated way of doing this,
 		     but I couldn't find it. */
+		  Lisp_Object old_selected =gui_item_list_find_selected
+		    (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
 		  Arg al [1];
-		  Widget child = XtNameToWidget 
-		    (IMAGE_INSTANCE_X_WIDGET_ID (ii),
-		     cur->name);
-		  XtSetArg (al [0], XtNtopWidget, child);
-		  XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
+		  char* name;
+		  unsigned int num_children, i;
+		  Widget* children;
+
+		  LISP_STRING_TO_EXTERNAL (XGUI_ITEM (XCAR (rest))->name,
+					   name, Qnative);
+		  /* The name may contain a `.' which confuses
+		     XtNameToWidget, so we do it ourselves. */
+		  children = XtCompositeChildren (IMAGE_INSTANCE_X_WIDGET_ID (ii),
+						  &num_children);
+		  for (i = 0; i < num_children; i++)
+		    {
+		      if (!strcmp (XtName (children [i]), name))
+			{
+			  XtSetArg (al [0], XtNtopWidget, children [i]);
+			  XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 1);
+			  break;
+			}
+		    }
+		  /* Pick up the new selected item. */
+		  XGUI_ITEM (old_selected)->selected = 
+		    XGUI_ITEM (XCAR (rest))->selected;
+		  XGUI_ITEM (XCAR (rest))->selected = 
+		    XGUI_ITEM (selected)->selected;
+		  /* We're not actually changing the items anymore. */
+		  IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
+		  IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
 		  break;
 		}
-	      cur = cur->next;
 	    }
-	  /* We're not actually changing the items anymore. */
-	  IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
-	  IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
 	}
     }
   /* Possibly update the face. */
@@ -2760,10 +2776,7 @@
       IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
     {
       widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii));
-
-      /* #### I don't know why this can occur. */
-      if (!wv)
-	return;
+      assert (wv);
 
       update_tab_widget_face (wv, ii,
 			      IMAGE_INSTANCE_FRAME (ii));
Index: src/glyphs-x.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-x.h,v
retrieving revision 1.4.2.12
diff -u -r1.4.2.12 glyphs-x.h
--- src/glyphs-x.h 2000/05/03 14:47:08 1.4.2.12
+++ src/glyphs-x.h 2000/08/18 17:06:17
@@ -32,6 +32,7 @@
 
 #include "xintrinsic.h"
 #include "../lwlib/lwlib.h"
+#include "../lwlib/lwlib-utils.h"
 
 /****************************************************************************
  *                         Image-Instance Object                            *
Index: src/glyphs.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v
retrieving revision 1.23.2.79
diff -u -r1.23.2.79 glyphs.c
--- src/glyphs.c 2000/08/06 09:27:16 1.23.2.79
+++ src/glyphs.c 2000/08/18 17:06:31
@@ -2066,7 +2066,7 @@
   assert (!internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0)
 	  || (internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0)
 	   && internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, -10)));
-
+  
   /* If the instantiator is identical then do nothing. We must use
      equal here because the specifier code copies the instantiator. */
   if (!internal_equal (IMAGE_INSTANCE_INSTANTIATOR (ii), instantiator, 0))
@@ -4290,19 +4290,44 @@
    deleted in and moreover, frame finalization deletes the window
    system windows before deleting XEmacs windows, and hence
    subwindows.  */
-void
-free_frame_subwindow_instance_cache (struct frame* f)
+int
+unmap_subwindow_instance_cache_mapper (Lisp_Object key, Lisp_Object value, 
+				       void* finalize)
 {
-  Lisp_Object rest;
-
-  LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
+  /* value can be nil; we cache failures as well as successes */
+  if (!NILP (value))
     {
-      Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
-      /* Make sure that the subwindow is unmapped so that window
-	 deletion will not try and do it again. */
-      unmap_subwindow (XCAR (rest));
-      finalize_image_instance (ii, 0);
+      struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value));
+      unmap_subwindow (value);
+      /* In case GC doesn't catch up fast enough, remove from the frame
+	 cache also. Otherwise code that checks the sanity of the instance
+	 will fail. */
+      XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
+	= delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
+      if (finalize)
+	finalize_image_instance (XIMAGE_INSTANCE (value), 0);
     }
+  return 0;
+}
+
+static void
+finalize_all_subwindow_instances (struct window *w)
+{
+  if (!NILP (w->next))   finalize_all_subwindow_instances (XWINDOW (w->next));
+  if (!NILP (w->vchild)) finalize_all_subwindow_instances (XWINDOW (w->vchild));
+  if (!NILP (w->hchild)) finalize_all_subwindow_instances (XWINDOW (w->hchild));
+
+  elisp_maphash (unmap_subwindow_instance_cache_mapper,
+		 w->subwindow_instance_cache, (void*)1);
+}
+
+void
+free_frame_subwindow_instances (struct frame* f)
+{
+  /* Make sure all instances are finalized. We have to do this via the
+     instance cache since some instances may be extant but not
+     displayed (and hence not in the frame cache). */
+  finalize_all_subwindow_instances (XWINDOW (f->root_window));
 }
 
 /* Unmap and remove all instances from the frame cache. */
Index: src/glyphs.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v
retrieving revision 1.18.2.56
diff -u -r1.18.2.56 glyphs.h
--- src/glyphs.h 2000/08/06 09:27:17 1.18.2.56
+++ src/glyphs.h 2000/08/18 17:06:34
@@ -1124,8 +1124,10 @@
 void redisplay_subwindow (Lisp_Object subwindow);
 Lisp_Object image_instance_parent_glyph (struct Lisp_Image_Instance*);
 int image_instance_changed (Lisp_Object image);
-void free_frame_subwindow_instance_cache (struct frame* f);
+void free_frame_subwindow_instances (struct frame* f);
 void reset_frame_subwindow_instance_cache (struct frame* f);
+int unmap_subwindow_instance_cache_mapper (Lisp_Object key,
+					   Lisp_Object value, void* finalize);
 
 struct expose_ignore
 {
Index: src/gui.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.c,v
retrieving revision 1.10.2.32
diff -u -r1.10.2.32 gui.c
--- src/gui.c 2000/08/06 09:27:18 1.10.2.32
+++ src/gui.c 2000/08/18 17:06:37
@@ -358,6 +358,19 @@
 	  || !NILP (Feval (XGUI_ITEM (gui_item)->selected)));
 }
 
+Lisp_Object
+gui_item_list_find_selected (Lisp_Object gui_item_list)
+{
+  /* This function can GC. */
+  Lisp_Object rest;
+  LIST_LOOP (rest, gui_item_list)
+    {
+      if (gui_item_selected_p (XCAR (rest)))
+	return XCAR (rest);
+    }
+  return XCAR (gui_item_list);
+}
+
 /*
  * Decide whether a GUI item is included by evaluating its :included
  * form if given, and testing its :config form against supplied CONFLIST
Index: src/gui.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.h,v
retrieving revision 1.6.2.19
diff -u -r1.6.2.19 gui.h
--- src/gui.h 2000/08/06 09:27:18 1.6.2.19
+++ src/gui.h 2000/08/18 17:06:37
@@ -72,6 +72,7 @@
 void gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item);
 int  gui_item_active_p (Lisp_Object);
 int  gui_item_selected_p (Lisp_Object);
+Lisp_Object gui_item_list_find_selected (Lisp_Object gui_item_list);
 int  gui_item_included_p (Lisp_Object, Lisp_Object into);
 Lisp_Object gui_item_accelerator (Lisp_Object gui_item);
 Lisp_Object gui_name_accelerator (Lisp_Object name);
Index: src/window.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/window.c,v
retrieving revision 1.41.2.57
diff -u -r1.41.2.57 window.c
--- src/window.c 2000/08/06 09:27:24 1.41.2.57
+++ src/window.c 2000/08/18 17:07:21
@@ -283,7 +283,7 @@
   p->line_start_cache = Dynarr_new (line_start_cache);
   p->subwindow_instance_cache = make_lisp_hash_table (30,
 						      HASH_TABLE_KEY_VALUE_WEAK,
-						      HASH_TABLE_EQUAL);
+						      HASH_TABLE_EQ);
   p->line_cache_last_updated = Qzero;
   INIT_DISP_VARIABLE (last_point_x, 0);
   INIT_DISP_VARIABLE (last_point_y, 0);
@@ -1874,29 +1874,11 @@
   ERROR_CHECK_SUBWINDOW_CACHE (p);
 }
 
-static int
-window_unmap_subwindows_cache_mapper (Lisp_Object key, Lisp_Object value,
-				      void *flag_closure)
-{
-  /* value can be nil; we cache failures as well as successes */
-  if (!NILP (value))
-    {
-      struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value));
-      unmap_subwindow (value);
-      /* In case GC doesn't catch up fast enough, remove from the frame
-	 cache also. Otherwise code that checks the sanity of the instance
-	 will fail. */
-      XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))
-	= delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)));
-    }
-  return 0;
-}
-
 static void
 window_unmap_subwindows (struct window* w)
 {
   assert (!NILP (w->subwindow_instance_cache));
-  elisp_maphash (window_unmap_subwindows_cache_mapper,
+  elisp_maphash (unmap_subwindow_instance_cache_mapper,
 		 w->subwindow_instance_cache, 0);
 }
 
@@ -3523,7 +3505,7 @@
   p->subwindow_instance_cache = 
     make_lisp_hash_table (30,
 			  HASH_TABLE_KEY_VALUE_WEAK,
-			  HASH_TABLE_EQUAL);
+			  HASH_TABLE_EQ);
 
   /* Put new into window structure in place of window */
   replace_window (window, new);
@@ -5366,23 +5348,28 @@
 	  w->hscroll = p->hscroll;
 	  w->modeline_hscroll = p->modeline_hscroll;
 	  w->line_cache_last_updated = Qzero;
-	  /* The subwindow instance cache isn't preserved across
-	     window configurations, and in fact doing so would be
-	     wrong. We just reset to zero and then redisplay will fill
-	     it up as needed. 
+	  /* When we restore a window's configuration, the identity of
+	     the window hasn't actually changed - so there is no
+	     reason why we shouldn't preserve the instance cache for
+	     it - unless it was origincally deleted. This will often
+	     buy us something as we will not have to re-instantiate
+	     all the instances. This is because this is an instance
+	     cache - not a display cache. Preserving the display cache
+	     would definitely be wrong.
 
-	     #### This is a bit of a pain for tabs, since for some
+	     We specifically want to do this for tabs, since for some
 	     reason finding a file will cause the configuration to be
-	     set. We should investigate preserving the cache across
-	     config changes. */
-	  w->subwindow_instance_cache =
-	    make_lisp_hash_table (30,
-				  HASH_TABLE_KEY_VALUE_WEAK,
-				  HASH_TABLE_EQUAL);
+	     set. */
+	  if (NILP (w->subwindow_instance_cache))
+	    w->subwindow_instance_cache =
+	      make_lisp_hash_table (30,
+				    HASH_TABLE_KEY_VALUE_WEAK,
+				    HASH_TABLE_EQ);
 	  SET_LAST_MODIFIED (w, 1);
 	  SET_LAST_FACECHANGE (w);
 	  w->config_mark = 0;
 
+	  /* #### Consider making the instance cache a winslot. */
 #define WINDOW_SLOT(slot, compare) w->slot = p->slot
 #include "winslots.h"
 
