diff options
author | Martin Rudalics <rudalics@gmx.at> | 2024-03-15 10:35:27 +0100 |
---|---|---|
committer | Martin Rudalics <rudalics@gmx.at> | 2024-03-15 10:35:27 +0100 |
commit | 5bba1b95b8088048808b306bf8b00eb9b342ce92 (patch) | |
tree | 0320ea25b5ea77cd7224134a69dd73dcf8996753 /src | |
parent | 1c4233b9a391ba5d5746acf6b6fd4b352b8c3a58 (diff) | |
download | emacs-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.c | 26 | ||||
-rw-r--r-- | src/buffer.h | 3 | ||||
-rw-r--r-- | src/window.c | 155 |
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. |