summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c458
1 files changed, 364 insertions, 94 deletions
diff --git a/src/window.c b/src/window.c
index 558554a7b54..ff58eb12ee0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -652,15 +652,16 @@ Return nil for an internal window or a deleted window. */)
DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0,
doc: /* Return the old buffer displayed by WINDOW.
-WINDOW must be a live window and defaults to the selected one.
+WINDOW can be any window and defaults to the selected one.
The return value is the buffer shown in WINDOW at the last time window
-change functions were run. It is nil if WINDOW was created after
-that. It is t if WINDOW has been restored from a window configuration
-after that. */)
+change functions were run or WINDOW is a former live window that was
+deleted. It is nil if WINDOW was created after that. It is t if WINDOW
+has been restored from a window configuration after that. It is always
+nil if WINDOW is an internal window. */)
(Lisp_Object window)
{
- struct window *w = decode_live_window (window);
+ struct window *w = decode_any_window (window);
return (NILP (w->old_buffer)
/* A new window. */
@@ -668,8 +669,8 @@ after that. */)
: (w->change_stamp != WINDOW_XFRAME (w)->change_stamp)
/* A window restored from a configuration. */
? Qt
- /* A window that was live the last time seen by window
- change functions. */
+ /* A window that was live the last time seen by window change
+ functions or was deleted. */
: w->old_buffer);
}
@@ -2394,8 +2395,41 @@ Return VALUE. */)
{
register struct window *w = decode_any_window (window);
Lisp_Object old_alist_elt;
+ struct frame* f;
old_alist_elt = Fassq (parameter, w->window_parameters);
+
+ /* If this window parameter has been used in a face remapping filter
+ expression anywhere at any time and we changed its value, force a
+ from-scratch redisplay to make sure that everything that depends on
+ a face filtered on the window parameter value is up-to-date.
+
+ We compare with Qt here instead of using !NILP so that users can
+ set this property to a non-nil, non-t value to inhibit this
+ mechanism for a specific window parameter.
+
+ FIXME: instead of taking a sledgehammer to redisplay, we could be
+ more precise in tracking which display bits depend on which
+ remapped faces. In particular, 1) if a window parameter named in a
+ face filter affects only faces used in drawing fringes, we don't
+ need to redraw TTY frames, but if the filter is ever used in a
+ non-fringe context (e.g. the 'face' text property), we need to
+ redraw TTY frames too. 2) In the fringe case, we should limit the
+ redraw damage to the fringes of the affected window and not the
+ whole frame containing the window. Today, we seldom change window
+ parameters named in face filters. We should implement the
+ optimizations above when this assumption no longer holds. */
+ if (SYMBOLP (parameter)
+ && WINDOW_LIVE_P (window)
+ && EQ (Fget (parameter, QCfiltered), Qt)
+ && FRAME_WINDOW_P ((f = WINDOW_XFRAME (w)))
+ && !EQ (CDR_SAFE (old_alist_elt), value)
+ && window_auto_redraw_on_parameter_change)
+ {
+ f->face_change = 1;
+ fset_redisplay (f);
+ }
+
if (NILP (old_alist_elt))
wset_window_parameters
(w, Fcons (Fcons (parameter, value), w->window_parameters));
@@ -3277,6 +3311,113 @@ window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
}
+/** Remove all occurrences of element whose car is BUFFER from ALIST.
+ Return changed ALIST. */
+static Lisp_Object
+window_discard_buffer_from_alist (Lisp_Object buffer, Lisp_Object alist)
+{
+ Lisp_Object tail, *prev = &alist;
+
+ for (tail = alist; CONSP (tail); tail = XCDR (tail))
+ {
+ Lisp_Object tem = XCAR (tail);
+
+ tem = XCAR (tem);
+
+ if (EQ (tem, buffer))
+ *prev = XCDR (tail);
+ else
+ prev = xcdr_addr (tail);
+ }
+
+ return alist;
+}
+
+/** Remove all occurrences of BUFFER from LIST. Return changed
+ LIST. */
+static Lisp_Object
+window_discard_buffer_from_list (Lisp_Object buffer, Lisp_Object list)
+{
+ Lisp_Object tail, *prev = &list;
+
+ for (tail = list; CONSP (tail); tail = XCDR (tail))
+ if (EQ (XCAR (tail), buffer))
+ *prev = XCDR (tail);
+ else
+ prev = xcdr_addr (tail);
+
+ return list;
+}
+
+/** Remove BUFFER from the lists of previous and next buffers of object
+ WINDOW. ALL true means remove any `quit-restore' and
+ `quit-restore-prev' parameter of WINDOW referencing BUFFER too. */
+static void
+window_discard_buffer_from_window (Lisp_Object buffer, Lisp_Object window, bool all)
+{
+ struct window *w = XWINDOW (window);
+
+ wset_prev_buffers
+ (w, window_discard_buffer_from_alist (buffer, w->prev_buffers));
+ wset_next_buffers
+ (w, window_discard_buffer_from_list (buffer, w->next_buffers));
+
+ if (all)
+ {
+ Lisp_Object quit_restore = window_parameter (w, Qquit_restore);
+ Lisp_Object quit_restore_prev = window_parameter (w, Qquit_restore_prev);
+ Lisp_Object quad;
+
+ if (EQ (buffer, Fnth (make_fixnum (3), quit_restore_prev))
+ || (CONSP (quad = Fcar (Fcdr (quit_restore_prev)))
+ && EQ (Fcar (quad), buffer)))
+ Fset_window_parameter (window, Qquit_restore_prev, Qnil);
+
+ if (EQ (buffer, Fnth (make_fixnum (3), quit_restore))
+ || (CONSP (quad = Fcar (Fcdr (quit_restore)))
+ && EQ (Fcar (quad), buffer)))
+ {
+ Fset_window_parameter (window, Qquit_restore,
+ window_parameter (w, Qquit_restore_prev));
+ Fset_window_parameter (window, Qquit_restore_prev, Qnil);
+ }
+ }
+}
+
+/** Remove BUFFER from the lists of previous and next buffers and the
+ `quit-restore' and `quit-restore-prev' parameters of any dead
+ WINDOW. */
+void
+window_discard_buffer_from_dead_windows (Lisp_Object buffer)
+{
+ struct Lisp_Hash_Table *h = XHASH_TABLE (window_dead_windows_table);
+
+ DOHASH (h, k, v)
+ window_discard_buffer_from_window (buffer, v, true);
+}
+
+DEFUN ("window-discard-buffer-from-window", Fwindow_discard_buffer,
+ Swindow_discard_buffer, 2, 3, 0,
+ doc: /* Discard BUFFER from WINDOW.
+Discard specified live BUFFER from the lists of previous and next
+buffers of specified live WINDOW.
+
+Optional argument ALL non-nil means discard any `quit-restore' and
+`quit-restore-prev' parameters of WINDOW referencing BUFFER too. */)
+ (Lisp_Object buffer, Lisp_Object window, Lisp_Object all)
+{
+ if (!BUFFER_LIVE_P (XBUFFER (buffer)))
+ error ("Not a live buffer");
+
+ if (!WINDOW_LIVE_P (window))
+ error ("Not a live window");
+
+ window_discard_buffer_from_window (buffer, window, !NILP (all));
+
+ return Qnil;
+}
+
+
DEFUN ("delete-other-windows-internal", Fdelete_other_windows_internal,
Sdelete_other_windows_internal, 0, 2, "",
doc: /* Make WINDOW fill its frame.
@@ -3540,9 +3681,17 @@ replace_buffer_in_windows (Lisp_Object buffer)
call1 (Qreplace_buffer_in_windows, buffer);
}
-/* If BUFFER is shown in a window, safely replace it with some other
- buffer in all windows of all frames, even those on other keyboards. */
+/** If BUFFER is shown in any window, safely replace it with some other
+ buffer in all windows of all frames, even those on other keyboards.
+ Do not delete any window.
+ This function is called by Fkill_buffer when it detects that
+ replacing BUFFER in some window showing BUFFER has failed. It
+ assumes that ‘replace-buffer-in-windows’ has removed any entry
+ referencing BUFFER from any window's lists of previous and next
+ buffers and that window's ‘quit-restore’ and 'quit-restore-prev'
+ parameters.
+*/
void
replace_buffer_in_windows_safely (Lisp_Object buffer)
{
@@ -4143,6 +4292,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
w->window_end_vpos = 0;
w->last_cursor_vpos = 0;
+ /* Discard BUFFER from WINDOW's previous and next buffers. */
+ window_discard_buffer_from_window (buffer, window, false);
+
if (!(keep_margins_p && samebuf))
{ /* If we're not actually changing the buffer, don't reset hscroll
and vscroll. Resetting hscroll and vscroll here is problematic
@@ -4373,41 +4525,6 @@ allocate_window (void)
PVEC_WINDOW);
}
-/* Make new window, have it replace WINDOW in window-tree, and make
- WINDOW its only vertical child (HORFLAG means make WINDOW its only
- horizontal child). */
-static void
-make_parent_window (Lisp_Object window, bool horflag)
-{
- Lisp_Object parent;
- register struct window *o, *p;
-
- o = XWINDOW (window);
- p = allocate_window ();
- memcpy ((char *) p + sizeof (union vectorlike_header),
- (char *) o + sizeof (union 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;
-
- replace_window (window, parent, true);
-
- wset_next (o, Qnil);
- wset_prev (o, Qnil);
- wset_parent (o, parent);
- /* ...but now P becomes an internal window. */
- wset_start (p, Qnil);
- wset_pointm (p, Qnil);
- wset_old_pointm (p, Qnil);
- wset_buffer (p, Qnil);
- wset_combination (p, horflag, window);
- wset_combination_limit (p, Qnil);
- wset_window_parameters (p, Qnil);
-}
-
/* Make new window from scratch. */
Lisp_Object
make_window (void)
@@ -4429,10 +4546,6 @@ make_window (void)
wset_vertical_scroll_bar_type (w, Qt);
wset_horizontal_scroll_bar_type (w, Qt);
wset_cursor_type (w, Qt);
- /* These Lisp fields are marked specially so they're not set to nil by
- allocate_window. */
- wset_prev_buffers (w, Qnil);
- wset_next_buffers (w, Qnil);
/* Initialize non-Lisp data. Note that allocate_window zeroes out all
non-Lisp data, so do it only for slots which should not be zero. */
@@ -4955,7 +5068,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
}
-DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
+DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 5, 0,
doc: /* Split window OLD.
Second argument PIXEL-SIZE specifies the number of pixels of the
new window. It must be a positive integer.
@@ -4970,32 +5083,33 @@ SIDE t (or `right') specifies that the new window shall be located on
the right side of WINDOW. SIDE `left' means the new window shall be
located on the left of WINDOW. In both cases PIXEL-SIZE specifies the
width of the new window including space reserved for fringes and the
-scrollbar or a divider column.
+scroll bar or a divider column.
Fourth argument NORMAL-SIZE specifies the normal size of the new window
-according to the SIDE argument.
+according to the SIDE argument. Optional fifth argument REFER is as for
+'split-window'.
The new pixel and normal sizes of all involved windows must have been
set correctly. See the code of `split-window' for how this is done. */)
- (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
-{
- /* OLD (*o) is the window we have to split. (*p) is either OLD's
- parent window or an internal window we have to install as OLD's new
- parent. REFERENCE (*r) must denote a live window, or is set to OLD
- provided OLD is a leaf window, or to the frame's selected window.
- NEW (*n) is the new window created with some parameters taken from
- REFERENCE (*r). */
- Lisp_Object new, frame, reference;
- struct window *o, *p, *n, *r, *c;
- struct frame *f;
+ (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side,
+ Lisp_Object normal_size, Lisp_Object refer)
+{
+ /* OLD (*o) is the window to split. REFER (*r) is a reference window,
+ either an arbitrary live window or a former live, now deleted
+ window on the same frame as OLD. NEW (*n) is the new window
+ created anew or resurrected from REFER (*r), if specified. *p
+ refers either to OLD's parent window that will become NEW's parent
+ window too or to a new internal window that becomes OLD's and NEW's
+ new parent. */
+ struct window *o = decode_valid_window (old);
+ Lisp_Object frame = WINDOW_FRAME (o);
+ struct frame *f = XFRAME (frame);
+ struct window *p, *n, *r, *c;
bool horflag
/* HORFLAG is true when we split side-by-side, false otherwise. */
= EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
-
- CHECK_WINDOW (old);
- o = XWINDOW (old);
- frame = WINDOW_FRAME (o);
- f = XFRAME (frame);
+ Lisp_Object new, parent = Qnil;
+ bool dead = false;
CHECK_FIXNUM (pixel_size);
EMACS_INT total_size
@@ -5013,14 +5127,74 @@ set correctly. See the code of `split-window' for how this is done. */)
? WINDOW_VERTICAL_COMBINATION_P (XWINDOW (o->parent))
: WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (o->parent))));
- /* We need a live reference window to initialize some parameters. */
- if (WINDOW_LIVE_P (old))
- /* OLD is live, use it as reference window. */
- reference = old;
+ /* Set up reference window. */
+ if (NILP (refer))
+ {
+ if (WINDOW_LIVE_P (old))
+ /* OLD is live, use it as reference window. */
+ refer = old;
+ else
+ /* Use the frame's selected window as reference window. */
+ refer = FRAME_SELECTED_WINDOW (f);
+
+ r = XWINDOW (refer);
+ }
+ else if (CONSP (refer))
+ {
+ /* If REFER is a cons, then its car must be a deleted, former live
+ window and its cdr must be a deleted former parent window. Set
+ PARENT to the cdr of REFER and REFER to its car. WINDOW and
+ REFER end up as the sole children of PARENT which replaces
+ WINDOW in the window tree. As a special case, if REFER's cdr
+ is t, reuse REFER's car's old parent as new parent provided it
+ is a deleted fromer parent window. */
+ parent = Fcdr (refer);
+ refer = Fcar (refer);
+ r = decode_any_window (refer);
+
+ if (!NILP (r->contents) || !BUFFERP (r->old_buffer))
+ error ("REFER's car must specify a deleted, former live window");
+ else if (!BUFFER_LIVE_P (XBUFFER (r->old_buffer)))
+ error ("The buffer formerly shown by REFER's car has been killed");
+ else if (!EQ (r->frame, frame))
+ error ("REFER's car must specify a window on same frame as WINDOW");
+
+ if (EQ (parent, Qt))
+ /* If REFER's cdr is t, use the old parent of REFER's car as new
+ parent. */
+ parent = r->parent;
+
+ p = decode_any_window (parent);
+
+ if (!NILP (p->contents) || BUFFERP (p->old_buffer))
+ error ("REFER's cdr must specify a deleted, former parent window");
+ else if (!EQ (p->frame, frame))
+ error ("REFER's cdr must specify window on same frame as WINDOW");
+
+ dead = true;
+ }
else
- /* Use the frame's selected window as reference window. */
- reference = FRAME_SELECTED_WINDOW (f);
- r = XWINDOW (reference);
+ {
+ r = decode_any_window (refer);
+
+ if (NILP (r->contents))
+ /* Presumably a deleted, former live window. Check whether its
+ contents can be used. */
+ {
+ if (!BUFFERP (r->old_buffer))
+ error ("REFER must specify a former live window (must have shown a buffer)");
+ else if (!BUFFER_LIVE_P (XBUFFER (r->old_buffer)))
+ error ("The buffer formerly shown by REFER has been killed");
+ else if (!EQ (r->frame, frame))
+ error ("REFER must specify a window on same frame as WINDOW");
+
+ dead = true;
+ }
+ else if (!NILP (parent))
+ error ("If REFER is a cons, its car must not specify a live window");
+ else if (!WINDOW_LIVE_P (refer))
+ error ("REFER is not a live window (does not show a buffer)");
+ }
/* The following bugs are caught by `split-window'. */
if (MINI_WINDOW_P (o))
@@ -5031,16 +5205,18 @@ set correctly. See the code of `split-window' for how this is done. */)
/* `window-combination-resize' non-nil means try to resize OLD's siblings
proportionally. */
{
- p = XWINDOW (o->parent);
+ struct window *op = XWINDOW (o->parent);
+
/* Temporarily pretend we split the parent window. */
wset_new_pixel
- (p, make_fixnum ((horflag ? p->pixel_width : p->pixel_height)
+ (op, make_fixnum ((horflag ? op->pixel_width : op->pixel_height)
- XFIXNUM (pixel_size)));
- if (!window_resize_check (p, horflag))
+ if (!window_resize_check (op, horflag))
error ("Window sizes don't fit");
else
/* Undo the temporary pretension. */
- wset_new_pixel (p, make_fixnum (horflag ? p->pixel_width : p->pixel_height));
+ wset_new_pixel
+ (op, make_fixnum (horflag ? op->pixel_width : op->pixel_height));
}
else
{
@@ -5060,8 +5236,24 @@ set correctly. See the code of `split-window' for how this is done. */)
Lisp_Object new_normal
= horflag ? o->normal_cols : o->normal_lines;
- make_parent_window (old, horflag);
- p = XWINDOW (o->parent);
+ if (NILP (parent))
+ /* This is the crux of the old make_parent_window. */
+ {
+ p = allocate_window ();
+ XSETWINDOW (parent, p);
+ p->sequence_number = ++sequence_number;
+ wset_frame (p, frame);
+ }
+ else
+ /* Pacify GCC. */
+ p = XWINDOW (parent);
+
+ replace_window (old, parent, true);
+ wset_next (o, Qnil);
+ wset_prev (o, Qnil);
+ wset_parent (o, parent);
+ wset_combination (p, horflag, old);
+
if (EQ (Vwindow_combination_limit, Qt))
/* Store t in the new parent's combination_limit slot to avoid
that its children get merged into another window. */
@@ -5077,7 +5269,12 @@ set correctly. See the code of `split-window' for how this is done. */)
p = XWINDOW (o->parent);
fset_redisplay (f);
- new = make_window ();
+
+ if (dead)
+ new = refer;
+ else
+ new = make_window ();
+
n = XWINDOW (new);
wset_frame (n, frame);
wset_parent (n, o->parent);
@@ -5104,16 +5301,19 @@ set correctly. See the code of `split-window' for how this is done. */)
n->window_end_valid = false;
n->last_cursor_vpos = 0;
- /* Get special geometry settings from reference window. */
- n->left_margin_cols = r->left_margin_cols;
- n->right_margin_cols = r->right_margin_cols;
- n->left_fringe_width = r->left_fringe_width;
- n->right_fringe_width = r->right_fringe_width;
- n->fringes_outside_margins = r->fringes_outside_margins;
- n->scroll_bar_width = r->scroll_bar_width;
- n->scroll_bar_height = r->scroll_bar_height;
- wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
- wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
+ if (!dead)
+ {
+ /* Get special geometry settings from reference window. */
+ n->left_margin_cols = r->left_margin_cols;
+ n->right_margin_cols = r->right_margin_cols;
+ n->left_fringe_width = r->left_fringe_width;
+ n->right_fringe_width = r->right_fringe_width;
+ n->fringes_outside_margins = r->fringes_outside_margins;
+ n->scroll_bar_width = r->scroll_bar_width;
+ n->scroll_bar_height = r->scroll_bar_height;
+ wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
+ wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
+ }
/* Directly assign orthogonal coordinates and sizes. */
if (horflag)
@@ -5142,6 +5342,7 @@ set correctly. See the code of `split-window' for how this is done. */)
sum = sum + XFIXNUM (c->new_total);
c = NILP (c->next) ? 0 : XWINDOW (c->next);
}
+
wset_new_total (n, make_fixnum ((horflag
? p->total_cols
: p->total_lines)
@@ -5149,10 +5350,30 @@ set correctly. See the code of `split-window' for how this is done. */)
wset_new_normal (n, normal_size);
block_input ();
+
+ if (dead)
+ {
+ /* Get dead window back its old buffer and markers. */
+ wset_buffer (n, n->old_buffer);
+ set_marker_restricted
+ (n->start, make_fixnum (XMARKER (n->start)->charpos), n->contents);
+ set_marker_restricted
+ (n->pointm, make_fixnum (XMARKER (n->pointm)->charpos), n->contents);
+ set_marker_restricted
+ (n->old_pointm, make_fixnum (XMARKER (n->old_pointm)->charpos),
+ n->contents);
+
+ Vwindow_list = Qnil;
+ /* Remove window from the table of dead windows. */
+ Fremhash (make_fixnum (n->sequence_number),
+ window_dead_windows_table);
+ }
+
window_resize_apply (p, horflag);
adjust_frame_glyphs (f);
- /* Set buffer of NEW to buffer of reference window. */
+
set_window_buffer (new, r->contents, true, true);
+
FRAME_WINDOW_CHANGE (f) = true;
unblock_input ();
@@ -5250,11 +5471,18 @@ Signal an error when WINDOW is the only window on its frame. */)
}
else
{
+ /* Store WINDOW's buffer in old_buffer. */
+ wset_old_buffer (w, w->contents);
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
unchain_marker (XMARKER (w->old_pointm));
unchain_marker (XMARKER (w->start));
wset_buffer (w, Qnil);
+ /* Add WINDOW to table of dead windows so when killing a buffer
+ WINDOW mentions, all references to that buffer can be removed
+ and the buffer be collected. */
+ Fputhash (make_fixnum (w->sequence_number),
+ window, window_dead_windows_table);
}
if (NILP (s->prev) && NILP (s->next))
@@ -6714,7 +6942,7 @@ and redisplay normally--don't erase and redraw the frame. */)
https://lists.gnu.org/r/emacs-devel/2014-06/msg00053.html,
https://lists.gnu.org/r/emacs-devel/2014-06/msg00094.html. */
if (buf != current_buffer)
- error ("`recenter'ing a window that does not display current-buffer.");
+ error ("`recenter'ing a window that does not display current-buffer");
/* If redisplay is suppressed due to an error, try again. */
buf->display_error_modiff = 0;
@@ -7359,12 +7587,21 @@ the return value is nil. Otherwise the value is t. */)
}
}
+ /* Remove window from the table of dead windows. */
+ Fremhash (make_fixnum (w->sequence_number),
+ window_dead_windows_table);
+
if ((NILP (dont_set_miniwindow) || !MINI_WINDOW_P (w))
&& BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
/* If saved buffer is alive, install it, unless it's a
minibuffer we explicitly prohibit. */
{
- wset_buffer (w, p->buffer);
+ if (!EQ (w->contents, p->buffer))
+ {
+ wset_buffer (w, p->buffer);
+ window_discard_buffer_from_window (w->contents, window, false);
+ }
+
w->start_at_line_beg = !NILP (p->start_at_line_beg);
set_marker_restricted (w->start, p->start, w->contents);
set_marker_restricted (w->pointm, p->pointm, w->contents);
@@ -7409,6 +7646,7 @@ the return value is nil. Otherwise the value is t. */)
recreate *scratch* in the course (part of Juanma's bs-show
scenario from March 2011). */
wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
+ window_discard_buffer_from_window (w->contents, window, false);
/* This will set the markers to beginning of visible
range. */
set_marker_restricted_both (w->start, w->contents, 0, 0);
@@ -7579,6 +7817,8 @@ delete_all_child_windows (Lisp_Object window)
}
else if (BUFFERP (w->contents))
{
+ /* Store WINDOW's buffer in old_buffer. */
+ wset_old_buffer (w, w->contents);
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
unchain_marker (XMARKER (w->old_pointm));
@@ -7588,6 +7828,11 @@ delete_all_child_windows (Lisp_Object window)
possible resurrection in Fset_window_configuration. */
wset_combination_limit (w, w->contents);
wset_buffer (w, Qnil);
+ /* Add WINDOW to table of dead windows so when killing a buffer
+ WINDOW mentions, all references to that buffer can be removed
+ and the buffer be collected. */
+ Fputhash (make_fixnum (w->sequence_number),
+ window, window_dead_windows_table);
}
Vwindow_list = Qnil;
@@ -8597,6 +8842,8 @@ syms_of_window (void)
DEFSYM (Qconfiguration, "configuration");
DEFSYM (Qdelete, "delete");
DEFSYM (Qdedicated, "dedicated");
+ DEFSYM (Qquit_restore, "quit-restore");
+ DEFSYM (Qquit_restore_prev, "quit-restore-prev");
DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
doc: /* Non-nil means call as function to display a help buffer.
@@ -8920,6 +9167,28 @@ Note that this optimization can cause the portion of the buffer
displayed after a scrolling operation to be somewhat inaccurate. */);
fast_but_imprecise_scrolling = false;
+ DEFVAR_LISP ("window-dead-windows-table", window_dead_windows_table,
+ doc: /* Hash table of dead windows.
+Each entry in this table maps a window number to a window object.
+Entries are added by `delete-window-internal' and are removed by the
+garbage collector. */);
+ window_dead_windows_table
+ = CALLN (Fmake_hash_table, QCweakness, Qvalue);
+
+ DEFVAR_BOOL ("window-auto-redraw-on-parameter-change",
+ window_auto_redraw_on_parameter_change,
+ doc: /* When non-nil, redraw based on face filters.
+When this variable is non-nil, force a potentially expensive redraw when
+a window parameter named in a `:window' expression for ':filtered'
+changes. This redraw is necessary for correctness; this variable is an
+escape hatch to recover performance in the case that our assumption that
+these parameter changes are rare does not hold.
+
+You can also inhibit the automatic redraw for a specific window
+parameter by setting the `:filtered` symbol property of the parameter
+name to `'ignore'. */);
+ window_auto_redraw_on_parameter_change = true;
+
defsubr (&Sselected_window);
defsubr (&Sold_selected_window);
defsubr (&Sminibuffer_window);
@@ -9035,6 +9304,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
defsubr (&Swindow_parameters);
defsubr (&Swindow_parameter);
defsubr (&Sset_window_parameter);
+ defsubr (&Swindow_discard_buffer);
defsubr (&Swindow_cursor_type);
defsubr (&Sset_window_cursor_type);
}