Commit 98a07056 authored by Dmitry Antipov's avatar Dmitry Antipov

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.
parent 2b8c9064
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.
......
......@@ -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. */
......
......@@ -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);
}
/* 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. */
......
......@@ -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;
......
......@@ -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);
......
......@@ -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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment