diff src/window.c @ 5495:1f0b15040456

Merge.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 01 May 2011 18:44:03 +0100
parents 4dee0387b9de
children 56144c8593a8
line wrap: on
line diff
--- a/src/window.c	Sat Feb 20 06:03:00 2010 -0600
+++ b/src/window.c	Sun May 01 18:44:03 2011 +0100
@@ -1,15 +1,15 @@
 /* Window creation, deletion and examination for XEmacs.
    Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc.
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
-   Copyright (C) 1995, 1996, 2002 Ben Wing.
+   Copyright (C) 1995, 1996, 2002, 2010 Ben Wing.
    Copyright (C) 1996 Chuck Thompson.
 
 This file is part of XEmacs.
 
-XEmacs is free software; you can redistribute it and/or modify it
+XEmacs is free software: you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
 
 XEmacs is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -17,9 +17,7 @@
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with XEmacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with XEmacs.  If not, see <http://www.gnu.org/licenses/>. */
 
 /* Synched up with: FSF 19.30. */
 /* Beginning to diverge significantly. */
@@ -47,7 +45,7 @@
 #include "frame-impl.h"
 #include "glyphs.h"
 #include "gutter.h"
-#include "objects.h"
+#include "fontcolor.h"
 #include "redisplay.h"
 #include "window-impl.h"
 
@@ -55,7 +53,7 @@
 Lisp_Object Qdisplay_buffer;
 
 #ifdef MEMORY_USAGE_STATS
-Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay;
+Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qredisplay_structs;
 #ifdef HAVE_SCROLLBARS
 Lisp_Object Qscrollbar_instances;
 #endif
@@ -182,11 +180,9 @@
 };
 
 #ifdef NEW_GC
-DEFINE_LRECORD_IMPLEMENTATION ("face-cachel", face_cachel,
-			       1, /*dumpable-flag*/
-                               0, 0, 0, 0, 0,
-			       face_cachel_description_1,
-			       Lisp_Face_Cachel);
+DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel", face_cachel,
+				      0, face_cachel_description_1,
+				      Lisp_Face_Cachel);
 #endif /* NEW_GC */
 
 static const struct sized_memory_description face_cachel_description = {
@@ -204,11 +200,9 @@
 };
 
 #ifdef NEW_GC
-DEFINE_LRECORD_IMPLEMENTATION ("face-cachel-dynarr", face_cachel_dynarr,
-			       1, /*dumpable-flag*/
-                               0, 0, 0, 0, 0,
-			       face_cachel_dynarr_description_1,
-			       face_cachel_dynarr);
+DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel-dynarr", face_cachel_dynarr,
+				      0, face_cachel_dynarr_description_1,
+				      face_cachel_dynarr);
 #else /* not NEW_GC */
 static const struct sized_memory_description face_cachel_dynarr_description = {
   sizeof (face_cachel_dynarr),
@@ -222,11 +216,9 @@
 };
 
 #ifdef NEW_GC
-DEFINE_LRECORD_IMPLEMENTATION ("glyph-cachel", glyph_cachel,
-			       1, /*dumpable-flag*/
-                               0, 0, 0, 0, 0,
-			       glyph_cachel_description_1,
-			       Lisp_Glyph_Cachel);
+DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel", glyph_cachel,
+				      0, glyph_cachel_description_1,
+				      Lisp_Glyph_Cachel);
 #endif /* NEW_GC */
 
 static const struct sized_memory_description glyph_cachel_description = {
@@ -244,11 +236,10 @@
 };
 
 #ifdef NEW_GC
-DEFINE_LRECORD_IMPLEMENTATION ("glyph-cachel-dynarr", glyph_cachel_dynarr,
-			       1, /*dumpable-flag*/
-                               0, 0, 0, 0, 0,
-			       glyph_cachel_dynarr_description_1,
-			       glyph_cachel_dynarr);
+DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel-dynarr",
+				      glyph_cachel_dynarr, 0,
+				      glyph_cachel_dynarr_description_1,
+				      glyph_cachel_dynarr);
 #else /* not NEW_GC */
 static const struct sized_memory_description glyph_cachel_dynarr_description = {
   sizeof (glyph_cachel_dynarr),
@@ -316,7 +307,7 @@
   Lisp_Object buf;
 
   if (print_readably)
-    printing_unreadable_lcrecord (obj, 0);
+    printing_unreadable_lisp_object (obj, 0);
 
   write_ascstring (printcharfun, "#<window");
   buf = XWINDOW_BUFFER (obj);
@@ -328,13 +319,13 @@
       Lisp_Object name = XBUFFER (buf)->name;
       write_fmt_string_lisp (printcharfun, " on %S", 1, name);
     }
-  write_fmt_string (printcharfun, " 0x%x>", XWINDOW (obj)->header.uid);
+  write_fmt_string (printcharfun, " 0x%x>", LISP_OBJECT_UID (obj));
 }
 
 static void
-finalize_window (void *header, int UNUSED (for_disksave))
-{
-  struct window *w = (struct window *) header;
+finalize_window (Lisp_Object obj)
+{
+  struct window *w = XWINDOW (obj);
 
   if (w->line_start_cache)
     {
@@ -372,13 +363,12 @@
 static Lisp_Object
 make_saved_buffer_point_cache (void)
 {
-  return make_lisp_hash_table (20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQ);
+  return make_lisp_hash_table (20, HASH_TABLE_KEY_WEAK, Qeq);
 }
 
-DEFINE_LRECORD_IMPLEMENTATION ("window", window,
-			       0, /*dumpable-flag*/
-                               mark_window, print_window, finalize_window,
-			       0, 0, window_description, struct window);
+DEFINE_NODUMP_LISP_OBJECT ("window", window,
+			   mark_window, print_window, finalize_window,
+			   0, 0, window_description, struct window);
 
 #define INIT_DISP_VARIABLE(field, initialization)	\
   p->field[CURRENT_DISP] = initialization;		\
@@ -397,8 +387,8 @@
 Lisp_Object
 allocate_window (void)
 {
-  struct window *p = ALLOC_LCRECORD_TYPE (struct window, &lrecord_window);
-  Lisp_Object val = wrap_window (p);
+  Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window);
+  struct window *p = XWINDOW (obj);
 
 #define WINDOW_SLOT(slot) p->slot = Qnil;
 #include "winslots.h"
@@ -432,7 +422,7 @@
   p->windows_changed = 1;
   p->shadow_thickness_changed = 1;
 
-  return val;
+  return obj;
 }
 #undef INIT_DISP_VARIABLE
 
@@ -531,19 +521,18 @@
     return Qnil;
 }
 
-DEFINE_LRECORD_IMPLEMENTATION ("window-mirror", window_mirror,
-			       0, /*dumpable-flag*/
-                               mark_window_mirror, internal_object_printer,
-			       0, 0, 0, window_mirror_description,
-			       struct window_mirror);
+DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("window-mirror", window_mirror,
+				    mark_window_mirror,
+				    window_mirror_description,
+				    struct window_mirror);
 
 /* Create a new window mirror structure and associated redisplay
    structs. */
 static struct window_mirror *
 new_window_mirror (struct frame *f)
 {
-  struct window_mirror *t =
-    ALLOC_LCRECORD_TYPE (struct window_mirror, &lrecord_window_mirror);
+  Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window_mirror);
+  struct window_mirror *t = XWINDOW_MIRROR (obj);
 
   t->frame = f;
   t->current_display_lines = Dynarr_new (display_line);
@@ -636,7 +625,7 @@
 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir,
 			    struct window *w)
 {
-  for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next)
+  for (; !NILP (win) && rmir; win = XWINDOW (win)->next, rmir = rmir->next)
     {
       if (w == XWINDOW (win))
 	return rmir;
@@ -687,7 +676,7 @@
 #endif
       free_display_structs (mir);
       mir = mir->next;
-      /* not worth calling free_managed_lcrecord() -- window mirrors
+      /* not worth calling free_normal_lisp_object() -- window mirrors
 	 are not created that frequently and it's dangerous.  we don't
 	 know for sure that there aren't other pointers around -- e.g.
 	 in a scrollbar instance. */
@@ -702,8 +691,7 @@
   Lisp_Object retval =
     real_window_internal (mir->frame->root_window,
 			  XWINDOW_MIRROR (mir->frame->root_mirror), mir);
-  if (NILP (retval) && !no_abort)
-    ABORT ();
+  assert (!NILP (retval) || no_abort);
 
   return retval;
 }
@@ -720,6 +708,18 @@
 				      XWINDOW_MIRROR (f->root_mirror), w);
 }
 
+/* Given a real window, return its mirror structure, if it exists.
+   Don't do any updating. */
+static struct window_mirror *
+find_window_mirror_maybe (struct window *w)
+{
+  struct frame *f = XFRAME (w->frame);
+  if (!WINDOW_MIRRORP (f->root_mirror))
+    return 0;
+  return find_window_mirror_internal (f->root_window,
+				      XWINDOW_MIRROR (f->root_mirror), w);
+}
+
 /*****************************************************************************
  find_window_by_pixel_pos
 
@@ -762,11 +762,8 @@
 {
   struct window_mirror *t;
 
-  if (XFRAME (w->frame)->mirror_dirty)
-    update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
-  if (!t)
-    ABORT ();
+  assert (t);
 
   if (which == CURRENT_DISP)
     return t->current_display_lines;
@@ -786,11 +783,8 @@
 {
   struct window_mirror *t;
 
-  if (XFRAME (w->frame)->mirror_dirty)
-    update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
-  if (!t)
-    ABORT ();
+  assert (t);
 
   return t->buffer;
 }
@@ -800,11 +794,8 @@
 {
   struct window_mirror *t;
 
-  if (XFRAME (w->frame)->mirror_dirty)
-    update_frame_window_mirror (XFRAME (w->frame));
   t = find_window_mirror (w);
-  if (!t)
-    ABORT ();
+  assert (t);
 
   t->buffer = b;
 }
@@ -1179,7 +1170,7 @@
   margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
 		   XINT (w->right_margin_width));
 
-  default_face_height_and_width (window, 0, &font_width);
+  default_face_width_and_height (window, &font_width, 0);
 
   /* The left margin takes precedence over the right margin so we
      subtract its width from the space available for the right
@@ -1662,7 +1653,7 @@
   hlimit = WINDOW_TEXT_HEIGHT (w);
   eobuf  = BUF_ZV (XBUFFER (w->buffer));
 
-  default_face_height_and_width (window, &defheight, NULL);
+  default_face_width_and_height (window, NULL, &defheight);
 
   /* guess lines needed in line start cache + a few extra */
   needed = (hlimit + defheight-1) / defheight + 3;
@@ -1817,10 +1808,8 @@
   struct window *w = decode_window (window);
   struct frame *f = XFRAME (w->frame);
 
-  int left =
-    w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
-  int top =
-    w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
+  int left = w->pixel_left - FRAME_PANED_LEFT_EDGE (f);
+  int top = w->pixel_top - FRAME_PANED_TOP_EDGE (f);
 
   return list4 (make_int (left),
 		make_int (top),
@@ -2024,8 +2013,7 @@
   Lisp_Object buf = w->buffer;
   struct buffer *b = XBUFFER (buf);
 
-  if (b != XMARKER (w->pointm[CURRENT_DISP])->buffer)
-    ABORT ();
+  assert (b == XMARKER (w->pointm[CURRENT_DISP])->buffer);
 
   /* FSF disables this check, so I'll do it too.  I hope it won't
      break things.  --ben */
@@ -2151,7 +2139,7 @@
   /* Free the extra data structures attached to windows immediately so
      they don't sit around consuming excess space.  They will be
      reinitialized by the window-configuration code as necessary. */
-  finalize_window ((void *) w, 0);
+  finalize_window (wrap_window (w));
 
   /* Nobody should be accessing anything in this object any more,
      and making them Qnil allows for better GC'ing in case a pointer
@@ -3138,7 +3126,7 @@
   w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices);
 
   /* At this point we damn well better have found something. */
-  if (NILP (w)) ABORT ();
+  assert (!NILP (w));
 #endif
 
   return w;
@@ -3482,8 +3470,8 @@
 
 /* Return non-zero if both frame sizes are less than or equal to
    minimal allowed values. ROWS and COLS are in characters */
-int
-frame_size_valid_p (struct frame *frame, int rows, int cols)
+static int
+frame_size_valid_p (struct frame *frame, int cols, int rows)
 {
   return (rows >= frame_min_height (frame)
 	  && cols >= MIN_SAFE_WINDOW_WIDTH);
@@ -3495,21 +3483,30 @@
 frame_pixsize_valid_p (struct frame *frame, int width, int height)
 {
   int rows, cols;
-  pixel_to_real_char_size (frame, width, height, &cols, &rows);
-  return frame_size_valid_p (frame, rows, cols);
+  pixel_to_char_size (frame, width, height, &cols, &rows);
+  return frame_size_valid_p (frame, cols, rows);
 }
 
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 void
-check_frame_size (struct frame *frame, int *rows, int *cols)
+check_frame_size (struct frame *frame, int *cols, int *rows)
 {
   int min_height = frame_min_height (frame);
-
-  if (*rows < min_height)
-    *rows = min_height;
-  if (*cols  < MIN_SAFE_WINDOW_WIDTH)
-    *cols = MIN_SAFE_WINDOW_WIDTH;
+  int min_pixwidth, min_pixheight;
+  int min_geomwidth, min_geomheight;
+
+  /* There is no char_to_frame_unit_size().  This can be done with
+     frame_conversion_internal(), but that's currently static, and we can
+     do it fine with two steps, as follows. */
+  char_to_pixel_size (frame, MIN_SAFE_WINDOW_WIDTH, min_height,
+		      &min_pixwidth, &min_pixheight);
+  pixel_to_frame_unit_size (frame, min_pixwidth, min_pixheight,
+			   &min_geomwidth, &min_geomheight);
+  if (*rows < min_geomheight)
+    *rows = min_geomheight;
+  if (*cols  < min_geomwidth)
+    *cols = min_geomwidth;
 }
 
 /* Normally the window is deleted if it gets too small.
@@ -3528,7 +3525,7 @@
   int line_size;
   int defheight, defwidth;
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
   line_size = (set_height ? defheight : defwidth);
 
   check_min_window_sizes ();
@@ -3758,6 +3755,11 @@
 
       Fset_buffer (buffer);
     }
+  if (NILP (XBUFFER (buffer)->display_count))
+    XBUFFER (buffer)->display_count = make_int (1);
+  else
+    XBUFFER (buffer)->display_count = make_int (1 + XINT (XBUFFER (buffer)->display_count));
+  XBUFFER (buffer)->display_time = Fcurrent_time();
   return Qnil;
 }
 
@@ -3870,12 +3872,11 @@
 static void
 make_dummy_parent (Lisp_Object window)
 {
-  Lisp_Object new_;
   struct window *o = XWINDOW (window);
-  struct window *p = ALLOC_LCRECORD_TYPE (struct window, &lrecord_window);
-
-  new_ = wrap_window (p);
-  COPY_LCRECORD (p, o);
+  Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window);
+  struct window *p = XWINDOW (obj);
+
+  copy_lisp_object (obj, window);
 
   /* Don't copy the pointers to the line start cache or the face
      instances. */
@@ -3895,13 +3896,13 @@
     make_image_instance_cache_hash_table ();
 
   /* Put new into window structure in place of window */
-  replace_window (window, new_);
+  replace_window (window, obj);
 
   o->next = Qnil;
   o->prev = Qnil;
   o->vchild = Qnil;
   o->hchild = Qnil;
-  o->parent = new_;
+  o->parent = obj;
 
   p->start[CURRENT_DISP] = Qnil;
   p->start[DESIRED_DISP] = Qnil;
@@ -4132,7 +4133,7 @@
 		   window_top_window_gutter_height (w) +
 		   window_bottom_window_gutter_height (w)));
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   if (defheight)
     char_height = avail_height / defheight;
@@ -4156,7 +4157,7 @@
   Lisp_Object window = wrap_window (w);
 
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   avail_height = char_height * defheight;
   pixel_height = (avail_height +
@@ -4236,7 +4237,7 @@
 	    }
 	}
 
-      default_face_height_and_width (window, &defheight, &defwidth);
+      default_face_width_and_height (window, &defwidth, &defheight);
       /* #### This probably needs to know about the clipping area once a
          final definition is decided on. */
       if (defheight)
@@ -4279,7 +4280,7 @@
 		 (include_margins_p ? 0 : window_left_margin_width (w)) -
 		 (include_margins_p ? 0 : window_right_margin_width (w)));
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   if (defwidth) 
     char_width = (avail_width / defwidth);
@@ -4302,7 +4303,7 @@
   Lisp_Object window = wrap_window (w);
 
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   avail_width = char_width * defwidth;
   pixel_width = (avail_width +
@@ -4385,7 +4386,7 @@
   if (EQ (window, FRAME_ROOT_WINDOW (f)))
     invalid_operation ("Won't change only window", Qunbound);
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   while (1)
     {
@@ -4614,7 +4615,7 @@
   if (INTP (Vwindow_pixel_scroll_increment))
     fheight = XINT (Vwindow_pixel_scroll_increment);
   else if (!NILP (Vwindow_pixel_scroll_increment))
-    default_face_height_and_width (window, &fheight, &fwidth);
+    default_face_width_and_height (window, &fwidth, &fheight);
 
   if (Dynarr_length (dla) >= 1)
     modeline = Dynarr_begin (dla)->modeline;
@@ -5164,103 +5165,106 @@
 
 #ifdef MEMORY_USAGE_STATS
 
-struct window_stats
-{
-  int face;
-  int glyph;
+struct window_mirror_stats
+{
+  struct usage_stats u;
+  /* Ancillary non-lisp */
+  Bytecount redisplay_structs;
 #ifdef HAVE_SCROLLBARS
-  int scrollbar;
+  /* Ancillary Lisp */
+  Bytecount scrollbar;
 #endif
-  int line_start;
-  int other_redisplay;
-  int other;
+};
+
+struct window_stats
+{
+  struct usage_stats u;
+  /* Ancillary non-Lisp */
+  Bytecount line_start;
+  /* The next two: ancillary non-Lisp under old-GC, ancillary Lisp under
+     NEW_GC */
+  Bytecount face;
+  Bytecount glyph;
+  /* The next two are copied out of the window mirror, which is an ancillary
+     Lisp structure; the first is non-Lisp, the second Lisp, but from our
+     perspective, they are both counted as Lisp */
+  Bytecount redisplay_structs;
+#ifdef HAVE_SCROLLBARS
+  Bytecount scrollbar;
+#endif
+  /* Remaining memory associated with window mirror (ancillary Lisp) */
+  Bytecount window_mirror;
 };
 
 static void
 compute_window_mirror_usage (struct window_mirror *mir,
-			     struct window_stats *stats,
-			     struct overhead_stats *ovstats)
-{
-  if (!mir)
-    return;
-  stats->other += LISPOBJ_STORAGE_SIZE (mir, sizeof (*mir), ovstats);
+			     struct window_mirror_stats *stats)
+{
+  stats->redisplay_structs =
+    compute_display_line_dynarr_usage (mir->current_display_lines, &stats->u)
+    +
+    compute_display_line_dynarr_usage (mir->desired_display_lines, &stats->u);
 #ifdef HAVE_SCROLLBARS
-  {
-    struct device *d = XDEVICE (FRAME_DEVICE (mir->frame));
-
-    stats->scrollbar +=
-      compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance,
-					ovstats);
-    stats->scrollbar +=
-      compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance,
-					ovstats);
-  }
+  stats->scrollbar =
+    compute_all_scrollbar_instance_usage (mir->scrollbar_vertical_instance) +
+    compute_all_scrollbar_instance_usage (mir->scrollbar_horizontal_instance);
 #endif /* HAVE_SCROLLBARS */
-  stats->other_redisplay +=
-    compute_display_line_dynarr_usage (mir->current_display_lines, ovstats);
-  stats->other_redisplay +=
-    compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats);
+}
+
+
+static void
+window_mirror_memory_usage (Lisp_Object window_mirror,
+			    struct generic_usage_stats *gustats)
+{
+  struct window_mirror_stats *stats = (struct window_mirror_stats *) gustats;
+
+  compute_window_mirror_usage (XWINDOW_MIRROR (window_mirror), stats);
 }
 
 static void
 compute_window_usage (struct window *w, struct window_stats *stats,
-		      struct overhead_stats *ovstats)
-{
-  xzero (*stats);
-  stats->other += LISPOBJ_STORAGE_SIZE (w, sizeof (*w), ovstats);
-  stats->face += compute_face_cachel_usage (w->face_cachels, ovstats);
-  stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats);
-  stats->line_start +=
-    compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats);
-  compute_window_mirror_usage (find_window_mirror (w), stats, ovstats);
+		      struct usage_stats *ustats)
+{
+  stats->line_start =
+    compute_line_start_cache_dynarr_usage (w->line_start_cache, ustats);
+  stats->face = compute_face_cachel_usage (w->face_cachels,
+					   ustats);
+  stats->glyph = compute_glyph_cachel_usage (w->glyph_cachels,
+					     ustats);
+  {
+    struct window_mirror *wm;
+
+    wm = find_window_mirror_maybe (w);
+    if (wm)
+      {
+	struct generic_usage_stats gustats;
+	struct window_mirror_stats *wmstats;
+	Bytecount total;
+	total = lisp_object_memory_usage_full (wrap_window_mirror (wm),
+					       NULL, NULL, NULL, &gustats);
+	wmstats = (struct window_mirror_stats *) &gustats;
+	stats->redisplay_structs = wmstats->redisplay_structs;
+	total -= stats->redisplay_structs;
+#ifdef HAVE_SCROLLBARS
+	stats->scrollbar = wmstats->scrollbar;
+	total -= stats->scrollbar;
+#endif
+	stats->window_mirror = total;
+      }
+  }
 }
 
-DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /*
-Return stats about the memory usage of window WINDOW.
-The values returned are in the form of an alist of usage types and byte
-counts.  The byte counts attempt to encompass all the memory used
-by the window (separate from the memory logically associated with a
-buffer or frame), including internal structures and any malloc()
-overhead associated with them.  In practice, the byte counts are
-underestimated because certain memory usage is very hard to determine
-\(e.g. the amount of memory used inside the Xt library or inside the
-X server) and because there is other stuff that might logically
-be associated with a window, buffer, or frame (e.g. window configurations,
-glyphs) but should not obviously be included in the usage counts.
-
-Multiple slices of the total memory usage may be returned, separated
-by a nil.  Each slice represents a particular view of the memory, a
-particular way of partitioning it into groups.  Within a slice, there
-is no overlap between the groups of memory, and each slice collectively
-represents all the memory concerned.
-*/
-       (window))
-{
-  struct window_stats stats;
-  struct overhead_stats ovstats;
-  Lisp_Object val = Qnil;
-
-  CHECK_WINDOW (window); /* dead windows should be allowed, no? */
-  xzero (ovstats);
-  compute_window_usage (XWINDOW (window), &stats, &ovstats);
-
-  val = acons (Qface_cache,          make_int (stats.face),              val);
-  val = acons (Qglyph_cache,         make_int (stats.glyph),             val);
-#ifdef HAVE_SCROLLBARS
-  val = acons (Qscrollbar_instances, make_int (stats.scrollbar),         val);
-#endif
-  val = acons (Qline_start_cache,    make_int (stats.line_start),        val);
-  val = acons (Qother_redisplay,     make_int (stats.other_redisplay),   val);
-  val = acons (Qother,               make_int (stats.other),             val);
-  val = Fcons (Qnil, val);
-  val = acons (Qactually_requested,  make_int (ovstats.was_requested),   val);
-  val = acons (Qmalloc_overhead,     make_int (ovstats.malloc_overhead), val);
-  val = acons (Qdynarr_overhead,     make_int (ovstats.dynarr_overhead), val);
-
-  return Fnreverse (val);
+static void
+window_memory_usage (Lisp_Object window, struct generic_usage_stats *gustats)
+{
+  struct window_stats *stats = (struct window_stats *) gustats;
+
+  compute_window_usage (XWINDOW (window), stats, &stats->u);
 }
 
 #endif /* MEMORY_USAGE_STATS */
+
+
 
 /* Mark all subwindows of a window as deleted.  The argument
    W is actually the subwindow tree of the window in question. */
@@ -5414,7 +5418,7 @@
     if (!NILP (buffer) && BUFFERP (buffer))
       stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
   }
-  stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
+  stderr_out (" 0x%x>", LISP_OBJECT_UID (window));
 
   while (!NILP (child))
     {
@@ -5438,15 +5442,24 @@
 /************************************************************************/
 
 void
+window_objects_create (void)
+{
+#ifdef MEMORY_USAGE_STATS
+  OBJECT_HAS_METHOD (window, memory_usage);
+  OBJECT_HAS_METHOD (window_mirror, memory_usage);
+#endif
+}
+
+void
 syms_of_window (void)
 {
-  INIT_LRECORD_IMPLEMENTATION (window);
-  INIT_LRECORD_IMPLEMENTATION (window_mirror);
+  INIT_LISP_OBJECT (window);
+  INIT_LISP_OBJECT (window_mirror);
 #ifdef NEW_GC
-  INIT_LRECORD_IMPLEMENTATION (face_cachel);
-  INIT_LRECORD_IMPLEMENTATION (face_cachel_dynarr);
-  INIT_LRECORD_IMPLEMENTATION (glyph_cachel);
-  INIT_LRECORD_IMPLEMENTATION (glyph_cachel_dynarr);
+  INIT_LISP_OBJECT (face_cachel);
+  INIT_LISP_OBJECT (face_cachel_dynarr);
+  INIT_LISP_OBJECT (glyph_cachel);
+  INIT_LISP_OBJECT (glyph_cachel_dynarr);
 #endif /* NEW_GC */
 
   DEFSYMBOL (Qwindowp);
@@ -5460,8 +5473,7 @@
 #ifdef HAVE_SCROLLBARS
   DEFSYMBOL (Qscrollbar_instances);
 #endif
-  DEFSYMBOL (Qother_redisplay);
-  /* Qother in general.c */
+  DEFSYMBOL (Qredisplay_structs);
 #endif
 
   DEFSYMBOL (Qtruncate_partial_width_windows);
@@ -5539,9 +5551,6 @@
   DEFSUBR (Fscroll_other_window);
   DEFSUBR (Fcenter_to_window_line);
   DEFSUBR (Fmove_to_window_line);
-#ifdef MEMORY_USAGE_STATS
-  DEFSUBR (Fwindow_memory_usage);
-#endif
   DEFSUBR (Fcurrent_pixel_column);
   DEFSUBR (Fcurrent_pixel_row);
 }
@@ -5557,6 +5566,34 @@
 void
 vars_of_window (void)
 {
+#ifdef MEMORY_USAGE_STATS
+  Lisp_Object l;
+
+  l = listu (Qline_start_cache,
+#ifdef NEW_GC
+	     Qt,
+#endif
+	     Qface_cache, Qglyph_cache,
+#ifndef NEW_GC
+	     Qt,
+#endif
+	     Qredisplay_structs,
+#ifdef HAVE_SCROLLBARS
+	     Qscrollbar_instances,
+#endif
+	     intern ("window-mirror"),
+	     Qunbound);
+
+  OBJECT_HAS_PROPERTY (window, memusage_stats_list, l);
+
+  l = listu (Qredisplay_structs,
+#ifdef HAVE_SCROLLBARS
+	     Qt, Qscrollbar_instances,
+#endif
+	     Qunbound);
+  OBJECT_HAS_PROPERTY (window_mirror, memusage_stats_list, l);
+#endif /* MEMORY_USAGE_STATS */
+
   DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /*
 *Non-nil means to scroll if point lands on a line which is clipped.
 */ );