]> code.delx.au - gnu-emacs/commitdiff
Per-buffer window counters.
authorDmitry Antipov <dmantipov@yandex.ru>
Mon, 10 Dec 2012 17:34:47 +0000 (21:34 +0400)
committerDmitry Antipov <dmantipov@yandex.ru>
Mon, 10 Dec 2012 17:34:47 +0000 (21:34 +0400)
* buffer.h (struct buffer): New member window_count.
(buffer_window_count): New function.
* buffer.c (Fget_buffer_create, Fmake_indirect_buffer):
Initialize window_count.
(Fkill_buffer): Verify window_count for the buffer being killed.
(modify_overlay): Do not force redisplay if buffer is not shown
in any window.
(init_buffer_once): Initialize window_count for buffer_defaults
and buffer_local_symbols.
* window.h (buffer_shared): Remove declaration.
(wset_buffer): Convert from inline ...
* window.c (wset_buffer): ... to an ordinary function.
(adjust_window_count): New function.
(make_parent_window): Use it.
* xdisp.c (buffer_shared): Remove.
(redisplay_internal, redisplay_window): Adjust users.
(buffer_shared_and_changed): Use per-buffer window counter.

src/ChangeLog
src/buffer.c
src/buffer.h
src/window.c
src/window.h
src/xdisp.c

index 584ee17cc1bc5510406b73e8a7f684e1f07b1cf6..ecaa60697ea4790a30549e8375ca0ac8f64b22e2 100644 (file)
@@ -1,3 +1,24 @@
+2012-12-10  Dmitry Antipov  <dmantipov@yandex.ru>
+
+       Per-buffer window counters.
+       * buffer.h (struct buffer): New member window_count.
+       (buffer_window_count): New function.
+       * buffer.c (Fget_buffer_create, Fmake_indirect_buffer):
+       Initialize window_count.
+       (Fkill_buffer): Verify window_count for the buffer being killed.
+       (modify_overlay): Do not force redisplay if buffer is not shown
+       in any window.
+       (init_buffer_once): Initialize window_count for buffer_defaults
+       and buffer_local_symbols.
+       * window.h (buffer_shared): Remove declaration.
+       (wset_buffer): Convert from inline ...
+       * window.c (wset_buffer): ... to an ordinary function.
+       (adjust_window_count): New function.
+       (make_parent_window): Use it.
+       * xdisp.c (buffer_shared): Remove.
+       (redisplay_internal, redisplay_window): Adjust users.
+       (buffer_shared_and_changed): Use per-buffer window counter.
+
 2012-12-10  Eli Zaretskii  <eliz@gnu.org>
 
        Support for filesystem notifications on MS-Windows.
index 6e2191dc22fa7e28c614c23235bdc6cb96ddc32b..1194431841a055c8e1eb8b6ccf9f9ca57160fb2c 100644 (file)
@@ -547,6 +547,8 @@ even if it is dead.  The return value is never nil.  */)
   b->base_buffer = NULL;
   /* No one shares the text with us now.  */
   b->indirections = 0;
+  /* No one shows us now.  */
+  b->window_count = 0;
 
   BUF_GAP_SIZE (b) = 20;
   block_input ();
@@ -794,6 +796,8 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
   b->indirections = -1;
   /* Notify base buffer that we share the text now.  */
   b->base_buffer->indirections++;
+  /* Always -1 for an indirect buffer.  */
+  b->window_count = -1;
 
   b->pt = b->base_buffer->pt;
   b->begv = b->base_buffer->begv;
@@ -1929,10 +1933,16 @@ cleaning up all windows currently displaying the buffer to be killed. */)
       eassert (b->indirections == -1);
       b->base_buffer->indirections--;
       eassert (b->base_buffer->indirections >= 0);
+      /* Make sure that we wasn't confused.  */
+      eassert (b->window_count == -1);
     }
   else
-    /* No one shares our buffer text, can free it.  */
-    free_buffer_text (b);
+    {
+      /* Make sure that no one shows us.  */
+      eassert (b->window_count == 0);
+      /* No one shares our buffer text, can free it.  */
+      free_buffer_text (b);
+    }
 
   if (b->newline_cache)
     {
@@ -3880,17 +3890,17 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end)
 
   BUF_COMPUTE_UNCHANGED (buf, start, end);
 
-  /* If this is a buffer not in the selected window,
-     we must do other windows.  */
-  if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
-    windows_or_buffers_changed = 1;
-  /* If multiple windows show this buffer, we must do other windows.  */
-  else if (buffer_shared > 1)
-    windows_or_buffers_changed = 1;
-  /* If we modify an overlay at the end of the buffer, we cannot
-     be sure that window end is still valid.  */
-  else if (end >= ZV && start <= ZV)
-    windows_or_buffers_changed = 1;
+  /* If BUF is visible, consider updating the display if ...  */
+  if (buffer_window_count (buf) > 0)
+    {
+      /* ... it's visible in other window than selected,  */
+      if (buf != XBUFFER (XWINDOW (selected_window)->buffer))
+       windows_or_buffers_changed = 1;
+      /* ... or if we modify an overlay at the end of the buffer
+        and so we cannot be sure that window end is still valid.  */
+      else if (end >= ZV && start <= ZV)
+       windows_or_buffers_changed = 1;
+    }
 
   ++BUF_OVERLAY_MODIFF (buf);
 }
@@ -5125,6 +5135,9 @@ init_buffer_once (void)
   /* No one will share the text with these buffers, but let's play it safe.  */
   buffer_defaults.indirections = 0;
   buffer_local_symbols.indirections = 0;
+  /* Likewise no one will display them.  */
+  buffer_defaults.window_count = 0;
+  buffer_local_symbols.window_count = 0;
   set_buffer_intervals (&buffer_defaults, NULL);
   set_buffer_intervals (&buffer_local_symbols, NULL);
   /* This is not strictly necessary, but let's make them initialized.  */
index 1129840bd47fd67796b5fe7dccda91e6da30179e..d838d3767efaeb543221d1e2188db1d836649006 100644 (file)
@@ -770,11 +770,15 @@ struct buffer
      In an ordinary buffer, it is 0.  */
   struct buffer *base_buffer;
 
-  /* In an indirect buffer, this is -1. In an ordinary buffer,
+  /* In an indirect buffer, this is -1.  In an ordinary buffer,
      it's the number of indirect buffers that share our text;
      zero means that we're the only owner of this text.  */
   int indirections;
 
+  /* Number of windows showing this buffer.  Always -1 for
+     an indirect buffer since it counts as its base buffer.  */
+  int window_count;
+
   /* A non-zero value in slot IDX means that per-buffer variable
      with index IDX has a local value in this buffer.  The index IDX
      for a buffer-local variable is stored in that variable's slot
@@ -1173,7 +1177,18 @@ BUF_FETCH_MULTIBYTE_CHAR (struct buffer *buf, ptrdiff_t pos)
        + pos + BUF_BEG_ADDR (buf) - BEG_BYTE);
   return STRING_CHAR (p);
 }
-\f
+
+/* Return number of windows showing B.  */
+
+BUFFER_INLINE int
+buffer_window_count (struct buffer *b)
+{
+  if (b->base_buffer)
+    b = b->base_buffer;
+  eassert (b->window_count >= 0);
+  return b->window_count;
+}
+
 /* Overlays */
 
 /* Return the marker that stands for where OV starts in the buffer.  */
index d7c2e8b236ecc25a8f6c3da554e84d1640e91770..9d593b6d36e16d816d9574a8319ec589d8f5b2a0 100644 (file)
@@ -270,6 +270,35 @@ decode_valid_window (register Lisp_Object window)
   return w;
 }
 
+/* Called when W's buffer slot is changed.  ARG -1 means that W is about to
+   cease its buffer, and 1 means that W is about to set up the new one.  */
+
+static void
+adjust_window_count (struct window *w, int arg)
+{
+  eassert (eabs (arg) == 1);
+  if (BUFFERP (w->buffer))
+    {
+      struct buffer *b = XBUFFER (w->buffer);
+      
+      if (b->base_buffer)
+       b = b->base_buffer;
+      b->window_count += arg;
+      eassert (b->window_count >= 0);
+    }
+}
+
+/* Set W's buffer slot to VAL and recompute number
+   of windows showing VAL if it is a buffer.  */
+
+void
+wset_buffer (struct window *w, Lisp_Object val)
+{
+  adjust_window_count (w, -1);
+  w->buffer = val;
+  adjust_window_count (w, 1);
+}
+
 /* Build a frequently used 4-integer (X Y W H) list.  */
 
 static Lisp_Object
@@ -3391,6 +3420,8 @@ make_parent_window (Lisp_Object window, int horflag)
   memcpy ((char *) p + sizeof (struct vectorlike_header),
          (char *) o + sizeof (struct vectorlike_header),
          word_size * VECSIZE (struct window));
+  /* P's buffer slot may change from nil to a buffer.  */
+  adjust_window_count (p, 1);
   XSETWINDOW (parent, p);
 
   p->sequence_number = ++sequence_number;
index 2a12226c0aaeedb5353ec736c6da45f0201cae91..f4f42a25af4ee282909eafb8e405ac575fde16fe 100644 (file)
@@ -351,11 +351,6 @@ struct window
 /* Most code should use these functions to set Lisp fields in struct
    window.  */
 WINDOW_INLINE void
-wset_buffer (struct window *w, Lisp_Object val)
-{
-  w->buffer = val;
-}
-WINDOW_INLINE void
 wset_frame (struct window *w, Lisp_Object val)
 {
   w->frame = val;
@@ -947,11 +942,6 @@ extern int windows_or_buffers_changed;
 
 extern int cursor_type_changed;
 
-/* Number of windows displaying the selected buffer.  Normally this is
-   1, but it can be more.  */
-
-extern int buffer_shared;
-
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 
@@ -997,6 +987,8 @@ extern int window_body_cols (struct window *w);
 extern void temp_output_buffer_show (Lisp_Object);
 extern void replace_buffer_in_windows (Lisp_Object);
 extern void replace_buffer_in_windows_safely (Lisp_Object);
+/* This looks like a setter, but it is a bit special.  */
+extern void wset_buffer (struct window *, Lisp_Object);
 extern void init_window_once (void);
 extern void init_window (void);
 extern void syms_of_window (void);
index 9464e87b36240f2bcdc848c233cf131aba1ea908..cf0424ede179a192e6adfc67bffc557c0791317b 100644 (file)
@@ -515,11 +515,6 @@ Lisp_Object Qmenu_bar_update_hook;
 
 static int overlay_arrow_seen;
 
-/* Number of windows showing the buffer of the selected
-   window (or another buffer with the same base buffer).  */
-
-int buffer_shared;
-
 /* Vector containing glyphs for an ellipsis `...'.  */
 
 static Lisp_Object default_invis_vector[3];
@@ -10894,9 +10889,8 @@ echo_area_display (int update_frame_p)
 static int
 buffer_shared_and_changed (void)
 {
-  /* The variable buffer_shared is set in redisplay_window and
-     indicates that we redisplay a buffer in different windows. */
-  return (buffer_shared > 1 && UNCHANGED_MODIFIED < MODIFF);
+  return (buffer_window_count (current_buffer) > 1
+         && UNCHANGED_MODIFIED < MODIFF);
 }
 
 /* Nonzero if W doesn't reflect the actual state of current buffer due
@@ -13470,10 +13464,6 @@ redisplay_internal (void)
       FOR_EACH_FRAME (tail, frame)
        XFRAME (frame)->updated_p = 0;
 
-      /* Recompute # windows showing selected buffer.  This will be
-        incremented each time such a window is displayed.  */
-      buffer_shared = 0;
-
       FOR_EACH_FRAME (tail, frame)
        {
          struct frame *f = XFRAME (frame);
@@ -15568,21 +15558,6 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   if (mode_line_update_needed (w))
     update_mode_line = 1;
 
-  /* Count number of windows showing the selected buffer.  An indirect
-     buffer counts as its base buffer.  */
-  if (!just_this_one_p)
-    {
-      struct buffer *current_base, *window_base;
-      current_base = current_buffer;
-      window_base = XBUFFER (XWINDOW (selected_window)->buffer);
-      if (current_base->base_buffer)
-       current_base = current_base->base_buffer;
-      if (window_base->base_buffer)
-       window_base = window_base->base_buffer;
-      if (current_base == window_base)
-       buffer_shared++;
-    }
-
   /* Point refers normally to the selected window.  For any other
      window, set up appropriate value.  */
   if (!EQ (window, selected_window))