From 98a07056558be8c13945a3a99b4801996af685a4 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Mon, 10 Dec 2012 21:34:47 +0400 Subject: [PATCH] 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. --- src/ChangeLog | 21 +++++++++++++++++++++ src/buffer.c | 39 ++++++++++++++++++++++++++------------- src/buffer.h | 19 +++++++++++++++++-- src/window.c | 31 +++++++++++++++++++++++++++++++ src/window.h | 12 ++---------- src/xdisp.c | 29 ++--------------------------- 6 files changed, 99 insertions(+), 52 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 584ee17cc1b..ecaa60697ea 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2012-12-10 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. + 2012-12-10 Eli Zaretskii Support for filesystem notifications on MS-Windows. diff --git a/src/buffer.c b/src/buffer.c index 6e2191dc22f..1194431841a 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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. */ diff --git a/src/buffer.h b/src/buffer.h index 1129840bd47..d838d3767ef 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -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. */ diff --git a/src/window.c b/src/window.c index d7c2e8b236e..9d593b6d36e 100644 --- a/src/window.c +++ b/src/window.c @@ -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; diff --git a/src/window.h b/src/window.h index 2a12226c0aa..f4f42a25af4 100644 --- a/src/window.h +++ b/src/window.h @@ -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); diff --git a/src/xdisp.c b/src/xdisp.c index 9464e87b362..cf0424ede17 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -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)) -- 2.39.5