summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics <rudalics@gmx.at>2024-03-15 10:35:27 +0100
committerMartin Rudalics <rudalics@gmx.at>2024-03-15 10:35:27 +0100
commit5bba1b95b8088048808b306bf8b00eb9b342ce92 (patch)
tree0320ea25b5ea77cd7224134a69dd73dcf8996753 /src
parent1c4233b9a391ba5d5746acf6b6fd4b352b8c3a58 (diff)
downloademacs-5bba1b95b8088048808b306bf8b00eb9b342ce92.tar.gz
Further adjustments for restoring killed buffer windows (Bug#68235)
* etc/NEWS: Announce 'window-restore-killed-buffer-windows'. * src/buffer.h (struct buffer) : New field last_name_. * src/buffer.c (Fbuffer_last_name): New function to return last name of buffer before it was killed or renamed. (bset_last_name, Fget_buffer_create, Fmake_indirect_buffer) (Frename_buffer, Fkill_buffer, init_buffer_once): Set buffer's last_name_ field accordingly. * src/window.c (window_restore_killed_buffer_windows): New variable replacing Vwindow_kept_windows_functions. (Fset_window_configuration): Use window_restore_killed_buffer_windows instead of Vwindow_kept_windows_functions. * lisp/window.el (window--state-put-2, window-state-put): Use 'window-restore-killed-buffer-windows' instead of 'window-kept-windows-functions'. * doc/lispref/windows.texi (Window Configurations): Describe 'window-restore-killed-buffer-windows' which replaces 'window-kept-windows-functions'.
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c26
-rw-r--r--src/buffer.h3
-rw-r--r--src/window.c155
3 files changed, 119 insertions, 65 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 43a9249528c..07d19dfc078 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -327,6 +327,11 @@ bset_name (struct buffer *b, Lisp_Object val)
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;
@@ -647,6 +652,7 @@ even if it is dead. The return value is never nil. */)
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);
@@ -866,6 +872,7 @@ Interactively, CLONE and INHIBIT-BUFFER-HOOKS are nil. */)
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));
@@ -1282,6 +1289,17 @@ Return nil if BUFFER has been killed. */)
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. */)
@@ -1652,6 +1670,7 @@ This does not change the name of the visited file (if any). */)
(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);
@@ -1669,12 +1688,12 @@ This does not change the name of the visited file (if any). */)
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
@@ -2095,6 +2114,7 @@ cleaning up all windows currently displaying the buffer to be killed. */)
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 ();
@@ -4666,6 +4686,7 @@ init_buffer_once (void)
/* 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));
@@ -6026,6 +6047,7 @@ There is no reason to change that value except for debugging purposes. */);
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);
diff --git a/src/buffer.h b/src/buffer.h
index 87ba2802b39..bbe1aeff668 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -309,6 +309,9 @@ struct buffer
/* 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_;
diff --git a/src/window.c b/src/window.c
index ea761fad8bc..928c4ae02a8 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7109,23 +7109,9 @@ current at the start of the function. If DONT-SET-MINIWINDOW is non-nil,
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,
@@ -7378,10 +7364,12 @@ the return value is nil. Otherwise the value is t. */)
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))
@@ -7398,16 +7386,25 @@ the return value is nil. Otherwise the value is t. */)
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);
+ }
}
}
@@ -7459,13 +7456,12 @@ the return value is nil. Otherwise the value is t. */)
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. */
@@ -7513,9 +7509,9 @@ the return value is nil. Otherwise the value is t. */)
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;
}
@@ -8514,8 +8510,9 @@ syms_of_window (void)
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.
@@ -8673,27 +8670,59 @@ its buffer or its total or body size since the last redisplay. Each
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.