@code{minibuffer-selected-window}. In this case, the function returns
@code{nil}. Otherwise, it returns @code{t}.
-If the buffer of a window of @var{configuration} has been killed since
-@var{configuration} was made, that window is, as a rule, removed from
-the restored configuration. However, if that window is the last window
-remaining in the restored configuration, another live buffer is shown in
-it. Also, if the variable @var{window-kept-windows-functions} is
-non-@code{nil}, any window whose buffer is now dead is not deleted.
-Rather, this function will show another live buffer in that window and
-include an entry for that window when calling any function in
-@var{window-kept-windows-functions} (@pxref{Window Hooks}).
+This function consults the variable
+@code{window-restore-killed-buffer-windows} (see below) when it tries to
+restore a window whose buffer was killed after @var{configuration} was
+recorded.
Here is a way of using this function to get the same effect as
@code{save-window-excursion}:
frame before putting @var{state} into it. If @var{window} is @code{nil},
it puts the window state into a new window.
-If the buffer of any window recorded in @var{state} has been killed
-since @var{state} was made, that window is, as a rule, not restored.
-However, if that window is the only window in @var{state}, another live
-buffer will be shown in it. Also, if the variable
-@var{window-kept-windows-functions} is non-@code{nil}, any window whose
-buffer is now dead is restored. This function will show another live
-buffer in it and include an entry for that window when calling a
-function in @var{window-kept-windows-functions} (@pxref{Window Hooks}).
+This function consults the variable
+@code{window-restore-killed-buffer-windows} (see below) when it tries to
+restore a window whose buffer was killed after @var{state} was recorded.
If the optional argument @var{ignore} is non-@code{nil}, it means to ignore
minimum window sizes and fixed-size restrictions. If @var{ignore}
and/or two columns.
@end defun
+By default, @code{set-window-configuration} and @code{window-state-put}
+may delete a window from the restored configuration when they find out
+that its buffer was killed since the corresponding configuration or
+state has been recorded. The variable described next can be used to
+fine-tune that behavior.
+
+@cindex restoring windows whose buffers have been killed
+@defvar window-restore-killed-buffer-windows
+This variable specifies how @code{set-window-configuration} and
+@code{window-state-put} shall handle a window whose buffer has been
+killed since the corresponding configuration or state was made. Any
+such window may be live - in which case it shows some other buffer - or
+dead at the time one of these functions is called. Usually,
+@code{set-window-configuration} leaves the window alone if it is live
+while @code{window-state-put} deletes it.
+
+The following values can be used to override the default behavior for
+dead windows in the case of @code{set-window-configuration} and for dead
+and live windows in the case of @code{window-state-put}.
+
+@table @asis
+@item @code{t}
+This value means to unconditionally restore the window and show some
+other buffer in it.
+
+@item @code{delete}
+This means to unconditionally try to delete the window.
+
+@item @code{dedicated}
+This means to try to delete the window if and only if it is dedicated to
+its buffer.
+
+@item @code{nil}
+This is the default and means that @code{set-window-configuration} will
+try to delete the window if and only if it is dedicated to its buffer
+and @code{window-state-put} will unconditionally try to delete it.
+
+@item a function
+This means to restore the window, show some other buffer in it and add
+an entry for that window to a list that will be later passed as argument
+to that function.
+@end table
+
+If a window cannot be deleted (typically, because it is the last window
+on its frame), @code{set-window-configuration} and
+@code{window-state-put} will show another buffer in it.
+
+If the value of this variable is a function, that function should take
+three arguments. The first argument specifies the frame whose windows
+have been restored. The third argument is either the constant
+@code{configuration} if the windows are restored by
+@code{set-window-configuration} or the constant @code{state} if the
+windows are restored by @code{window-state-put}.
+
+The second argument specifies a list of entries for @emph{any} window
+whose previous buffer has been encountered dead at the time
+@code{set-window-configuration} or @code{window-state-put} tried to
+restore it in that window (minibuffer windows are excluded). This means
+that the function specified by this variable may also delete windows
+encountered live by @code{set-window-configuration}.
+
+Each entry is a list of six values - the window whose buffer was found
+dead, the dead buffer or its name, the positions of start and point of
+the buffer in that window, the dedicated status of the window as
+previously reported by @code{window-dedicated-p} and a flag that is
+@code{t} if the window has been encountered live by
+@code{set-window-configuration} and @code{nil} otherwise.
+@end defvar
+
The functions @code{window-state-get} and @code{window-state-put} also
allow exchanging the contents of two live windows. The following
function does precisely that:
buffer are (re)fontified because a window was scrolled or its size
changed. @xref{Other Font Lock Variables}.
-@cindex window kept windows functions
-@defvar window-kept-windows-functions
- This variable holds a list of functions that Emacs will call after
-restoring a window configuration via @code{set-window-configuration} or
-state via @code{window-state-put} (@pxref{Window Configurations}). When
-the value of this variable is non-@code{nil}, these functions will not
-delete any window whose buffer has been killed since the corresponding
-configuration or state was saved, but show some live buffer in it.
-
-The value should be a list of functions that take two arguments. The
-first argument specifies the frame whose windows have been restored.
-The second argument specifies a list of entries for each window whose
-buffer has been found dead at the time @code{set-window-configuration}
-or @code{window-state-put} tried to restore it. Each entry is a list of
-four values - the window whose buffer was found dead, the dead buffer,
-and the last known positions of start and point of the buffer in that
-window. Any function run by this hook should check that the window is
-live since another function run by this hook may have deleted it in the
-meantime.
-@end defvar
-
@cindex window change functions
The remainder of this section covers six hooks that are called
during redisplay provided a significant, non-scrolling change of a
It specifies whether the window of the displayed buffer should be
selected or deselected at the end of executing the current command.
++++
+*** New variable 'window-restore-killed-buffer-windows'.
+It specifies how 'set-window-configuration' and 'window-state-put'
+should proceed with windows whose buffer was killed after the
+corresponding configuration or state was made.
+
** Tab Bars and Tab Lines
---
(when state
(let* ((old-buffer-or-name (car state))
(buffer (get-buffer old-buffer-or-name))
- (state (cdr state)))
+ (state (cdr state))
+ (dedicated (cdr (assq 'dedicated state))))
(if (buffer-live-p buffer)
(with-current-buffer buffer
(set-window-buffer window buffer)
window delta t ignore nil nil nil pixelwise))
(window-resize window delta t ignore pixelwise))))
;; Set dedicated status.
- (set-window-dedicated-p window (cdr (assq 'dedicated state)))
+ (set-window-dedicated-p window dedicated)
;; Install positions (maybe we should do this after all
;; windows have been created and sized).
(ignore-errors
(set-marker (make-marker) m2
buffer))))))
prev-buffers))))
- ;; We don't want to raise an error in case the buffer does
- ;; not exist anymore, so we switch to a previous one and
- ;; save the window with the intention of deleting it later
- ;; if possible.
- (switch-to-prev-buffer window)
- (if window-kept-windows-functions
+ (unless (window-minibuffer-p window)
+ ;; Preferably show a buffer previously shown in this
+ ;; window.
+ (switch-to-prev-buffer window)
+ (cond
+ ((functionp window-restore-killed-buffer-windows)
(let* ((start (cdr (assq 'start state)))
;; Handle both - marker positions from writable
;; states and markers from non-writable states.
(point-pos (if (markerp point)
(marker-last-position point)
point)))
- (push (list window old-buffer-or-name start-pos point-pos)
- window-state-put-kept-windows))
- (push window window-state-put-stale-windows))))))))
+ (push (list window old-buffer-or-name
+ start-pos point-pos dedicated nil)
+ window-state-put-kept-windows)))
+ ((or (and dedicated
+ (eq window-restore-killed-buffer-windows 'dedicated))
+ (memq window-restore-killed-buffer-windows '(nil delete)))
+ ;; Try to delete the window.
+ (push window window-state-put-stale-windows)))
+ (set-window-dedicated-p window nil))))))))
(defun window-state-put (state &optional window ignore)
"Put window state STATE into WINDOW.
windows can get as small as `window-safe-min-height' and
`window-safe-min-width'.
-If the abnormal hook `window-kept-windows-functions' is non-nil,
-do not delete any windows saved by STATE whose buffers were
-deleted since STATE was saved. Rather, show some live buffer in
-them and call the functions in `window-kept-windows-functions'
-with a list of two arguments: the frame where STATE was put and a
-list of entries for each such window. Each entry contains four
-elements - the window, its old buffer and the last positions of
-`window-start' and `window-point' for the buffer in that window.
-Always check the window for liveness because another function run
-by this hook may have deleted it."
+If this function tries to restore a non-minibuffer window whose buffer
+was killed since STATE was made, it will consult the variable
+`window-restore-killed-buffer-windows' on how to proceed."
(setq window-state-put-stale-windows nil)
(setq window-state-put-kept-windows nil)
(when (and (window-valid-p window)
(eq (window-deletable-p window) t))
(delete-window window))))
- (when window-kept-windows-functions
- (run-hook-with-args
- 'window-kept-windows-functions
- frame window-state-put-kept-windows)
+ (when (functionp window-restore-killed-buffer-windows)
+ (funcall window-restore-killed-buffer-windows
+ frame window-state-put-kept-windows 'state)
(setq window-state-put-kept-windows nil))
(window--check frame))))
b->name_ = val;
}
static void
+bset_last_name (struct buffer *b, Lisp_Object val)
+{
+ b->last_name_ = val;
+}
+static void
bset_overwrite_mode (struct buffer *b, Lisp_Object val)
{
b->overwrite_mode_ = val;
name = Fcopy_sequence (buffer_or_name);
set_string_intervals (name, NULL);
bset_name (b, name);
+ bset_last_name (b, name);
b->inhibit_buffer_hooks = !NILP (inhibit_buffer_hooks);
bset_undo_list (b, SREF (name, 0) != ' ' ? Qnil : Qt);
name = Fcopy_sequence (name);
set_string_intervals (name, NULL);
bset_name (b, name);
+ bset_last_name (b, name);
/* An indirect buffer shares undo list of its base (Bug#18180). */
bset_undo_list (b, BVAR (b->base_buffer, undo_list));
return BVAR (decode_buffer (buffer), name);
}
+DEFUN ("buffer-last-name", Fbuffer_last_name, Sbuffer_last_name, 0, 1, 0,
+ doc: /* Return last name of BUFFER, as a string.
+BUFFER defaults to the current buffer.
+
+This is the name BUFFER had before the last time it was renamed or
+immediately before it was killed. */)
+ (Lisp_Object buffer)
+{
+ return BVAR (decode_buffer (buffer), last_name);
+}
+
DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0,
doc: /* Return name of file BUFFER is visiting, or nil if none.
No argument or nil as argument means use the current buffer. */)
(register Lisp_Object newname, Lisp_Object unique)
{
register Lisp_Object tem, buf;
+ Lisp_Object oldname = BVAR (current_buffer, name);
Lisp_Object requestedname = newname;
CHECK_STRING (newname);
if (NILP (unique) && XBUFFER (tem) == current_buffer)
return BVAR (current_buffer, name);
if (!NILP (unique))
- newname = Fgenerate_new_buffer_name (newname,
- BVAR (current_buffer, name));
+ newname = Fgenerate_new_buffer_name (newname, oldname);
else
error ("Buffer name `%s' is in use", SDATA (newname));
}
+ bset_last_name (current_buffer, oldname);
bset_name (current_buffer, newname);
/* Catch redisplay's attention. Unless we do this, the mode lines for
This gets rid of them for certain. */
reset_buffer_local_variables (b, 1);
+ bset_last_name (b, BVAR (b, name));
bset_name (b, Qnil);
block_input ();
/* These used to be stuck at 0 by default, but now that the all-zero value
means Qnil, we have to initialize them explicitly. */
bset_name (&buffer_local_flags, make_fixnum (0));
+ bset_last_name (&buffer_local_flags, make_fixnum (0));
bset_mark (&buffer_local_flags, make_fixnum (0));
bset_local_var_alist (&buffer_local_flags, make_fixnum (0));
bset_keymap (&buffer_local_flags, make_fixnum (0));
defsubr (&Smake_indirect_buffer);
defsubr (&Sgenerate_new_buffer_name);
defsubr (&Sbuffer_name);
+ defsubr (&Sbuffer_last_name);
defsubr (&Sbuffer_file_name);
defsubr (&Sbuffer_base_buffer);
defsubr (&Sbuffer_local_value);
/* The name of this buffer. */
Lisp_Object name_;
+ /* The last name of this buffer before it was renamed or killed. */
+ Lisp_Object last_name_;
+
/* The name of the file visited in this buffer, or nil. */
Lisp_Object filename_;
the mini-window of the frame doesn't get set to the corresponding element
of CONFIGURATION.
-Normally, this function will try to delete any dead window in
-CONFIGURATION whose buffer has been deleted since CONFIGURATION was
-made. However, if the abnormal hook `window-kept-windows-functions' is
-non-nil, it will preserve such a window in the restored layout and show
-another buffer in it.
-
-After restoring the frame layout, this function runs the abnormal hook
-`window-kept-windows-functions' with two arguments - the frame whose
-layout it has restored and a list of entries for each window whose
-buffer has been found dead when it tried to restore CONFIGURATION: Each
-entry is a list of four elements <window, buffer, start, point> where
-`window' denotes the window whose buffer was found dead, `buffer'
-denotes the dead buffer, and `start' and `point' denote the last known
-positions of `window-start' and `window-point' of the buffer in that
-window. Any function run by this hook should check such a window for
-liveness because another function run by this hook may have deleted it
-in the meantime."
+This function consults the variable `window-restore-killed-buffer-windows'
+when restoring a window whose buffer was killed after CONFIGURATION was
+recorded.
If CONFIGURATION was made from a frame that is now deleted,
only frame-independent values can be restored. In this case,
BUF_PT (XBUFFER (w->contents)),
BUF_PT_BYTE (XBUFFER (w->contents)));
w->start_at_line_beg = true;
- if (!NILP (Vwindow_kept_windows_functions))
- kept_windows = Fcons (list4 (window, p->buffer,
+ if (FUNCTIONP (window_restore_killed_buffer_windows)
+ && !MINI_WINDOW_P (w))
+ kept_windows = Fcons (listn (6, window, p->buffer,
Fmarker_last_position (p->start),
- Fmarker_last_position (p->pointm)),
+ Fmarker_last_position (p->pointm),
+ p->dedicated, Qt),
kept_windows);
}
else if (!NILP (w->start))
set_marker_restricted_both (w->pointm, w->contents, 0, 0);
set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
w->start_at_line_beg = true;
- if (!NILP (w->dedicated))
- /* Record this window as dead. */
- dead_windows = Fcons (window, dead_windows);
- /* Make sure window is no more dedicated. */
- wset_dedicated (w, Qnil);
- if (!NILP (Vwindow_kept_windows_functions))
- kept_windows = Fcons (list4 (window, p->buffer,
- Fmarker_last_position (p->start),
- Fmarker_last_position (p->pointm)),
- kept_windows);
+ if (!MINI_WINDOW_P (w))
+ {
+ if (FUNCTIONP (window_restore_killed_buffer_windows))
+ kept_windows
+ = Fcons (listn (6, window, p->buffer,
+ Fmarker_last_position (p->start),
+ Fmarker_last_position (p->pointm),
+ p->dedicated, Qnil),
+ kept_windows);
+ else if (EQ (window_restore_killed_buffer_windows, Qdelete)
+ || (!NILP (p->dedicated)
+ && (NILP (window_restore_killed_buffer_windows)
+ || EQ (window_restore_killed_buffer_windows,
+ Qdedicated))))
+ /* Try to delete this window later. */
+ dead_windows = Fcons (window, dead_windows);
+ /* Make sure window is no more dedicated. */
+ wset_dedicated (w, Qnil);
+ }
}
}
unblock_input ();
/* Scan dead buffer windows. */
- if (!NILP (Vwindow_kept_windows_functions))
- for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
- {
- window = XCAR (dead_windows);
- if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
- delete_deletable_window (window);
- }
+ for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
+ {
+ window = XCAR (dead_windows);
+ if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
+ delete_deletable_window (window);
+ }
/* Record the selected window's buffer here. The window should
already be the selected one from the call above. */
SAFE_FREE ();
- if (!NILP (Vrun_hooks) && !NILP (Vwindow_kept_windows_functions))
- run_hook_with_args_2 (Qwindow_kept_windows_functions, frame,
- kept_windows);
+ if (!NILP (Vrun_hooks) && FUNCTIONP (window_restore_killed_buffer_windows))
+ safe_calln (window_restore_killed_buffer_windows,
+ frame, kept_windows, Qconfiguration);
return FRAME_LIVE_P (f) ? Qt : Qnil;
}
DEFSYM (Qheader_line_format, "header-line-format");
DEFSYM (Qtab_line_format, "tab-line-format");
DEFSYM (Qno_other_window, "no-other-window");
- DEFSYM (Qwindow_kept_windows_functions,
- "window-kept-windows-functions");
+ DEFSYM (Qconfiguration, "configuration");
+ DEFSYM (Qdelete, "delete");
+ DEFSYM (Qdedicated, "dedicated");
DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
doc: /* Non-nil means call as function to display a help buffer.
call is performed with the frame temporarily selected. */);
Vwindow_configuration_change_hook = Qnil;
- DEFVAR_LISP ("window-kept-windows-functions",
- Vwindow_kept_windows_functions,
- doc: /* Functions run after restoring a window configuration or state.
-These functions are called by `set-window-configuration' and
-`window-state-put'. When the value of this variable is non-nil, these
-functions restore any window whose buffer has been deleted since the
-corresponding configuration or state was saved. Rather than deleting
-such a window, `set-window-configuration' and `window-state-put' show
-some live buffer in it.
-
-The value should be a list of functions that take two arguments. The
-first argument specifies the frame whose configuration has been
-restored. The second argument, if non-nil, specifies a list of entries
-for each window whose buffer has been found dead at the time
-'set-window-configuration' or `window-state-put' tried to restore it in
-that window. Each entry is a list of four values - the window whose
-buffer was found dead, the dead buffer, and the positions of start and
-point of the buffer in that window. Note that the window may be already
-dead since another function on this list may have deleted it in the
-meantime. */);
- Vwindow_kept_windows_functions = Qnil;
+ DEFVAR_LISP ("window-restore-killed-buffer-windows",
+ window_restore_killed_buffer_windows,
+ doc: /* Control restoring windows whose buffer was killed.
+This variable specifies how the functions `set-window-configuration' and
+`window-state-put' shall handle a window whose buffer has been killed
+since the corresponding configuration or state was made. Any such
+window may be live - in which case it shows some other buffer - or dead
+at the time one of these functions is called.
+
+As a rule, `set-window-configuration' leaves the window alone if it is
+live while `window-state-put' deletes it. The following values can be
+used to override the default behavior for dead windows in the case of
+`set-window-configuration' and for dead and live windows in the case of
+`window-state-put'.
+
+- t means to restore the window and show some other buffer in it.
+
+- `delete' means to try to delete the window.
+
+- `dedicated' means to try to delete the window if and only if it is
+ dedicated to its buffer.
+
+- nil, the default, means that `set-window-configuration' will try to
+ delete the window if and only if it is dedicated to its buffer while
+ `window-state-put' will unconditionally try to delete it.
+
+- a function means to restore the window, show some other buffer in it
+ and add an entry for that window to a list that will be later passed
+ as argument to that function.
+
+If a window cannot be deleted (typically, because it is the last window
+on its frame), show another buffer in it.
+
+If the value is a function, it should take three arguments. The first
+argument specifies the frame whose windows have been restored. The
+third argument is the constant `configuration' if the windows are
+restored by `set-window-configuration' and the constant `state' if the
+windows are restored by `window-state-put'.
+
+The second argument specifies a list of entries for @emph{any} window
+whose previous buffer has been encountered dead at the time
+`set-window-configuration' or `window-state-put' tried to restore it in
+that window (minibuffer windows are excluded). This means that the
+function specified by this variable may also delete windows encountered
+live by `set-window-configuration'.
+
+Each entry is a list of six values - the window whose buffer was found
+dead, the dead buffer or its name, the positions of start and point of
+the buffer in that window, the dedicated status of the window as
+reported by `window-dedicated-p' and a boolean - t if the window was
+live when `set-window-configuration' tried to restore it and nil
+otherwise. */);
+ window_restore_killed_buffer_windows = Qnil;
DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
doc: /* Non-nil means `recenter' redraws entire frame.