aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2024-03-15 10:35:27 +0100
committerMartin Rudalics2024-03-15 10:35:27 +0100
commit5bba1b95b8088048808b306bf8b00eb9b342ce92 (patch)
tree0320ea25b5ea77cd7224134a69dd73dcf8996753 /src
parent1c4233b9a391ba5d5746acf6b6fd4b352b8c3a58 (diff)
downloademacs-5bba1b95b8088048808b306bf8b00eb9b342ce92.tar.gz
emacs-5bba1b95b8088048808b306bf8b00eb9b342ce92.zip
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)
327 b->name_ = val; 327 b->name_ = val;
328} 328}
329static void 329static void
330bset_last_name (struct buffer *b, Lisp_Object val)
331{
332 b->last_name_ = val;
333}
334static void
330bset_overwrite_mode (struct buffer *b, Lisp_Object val) 335bset_overwrite_mode (struct buffer *b, Lisp_Object val)
331{ 336{
332 b->overwrite_mode_ = val; 337 b->overwrite_mode_ = val;
@@ -647,6 +652,7 @@ even if it is dead. The return value is never nil. */)
647 name = Fcopy_sequence (buffer_or_name); 652 name = Fcopy_sequence (buffer_or_name);
648 set_string_intervals (name, NULL); 653 set_string_intervals (name, NULL);
649 bset_name (b, name); 654 bset_name (b, name);
655 bset_last_name (b, name);
650 656
651 b->inhibit_buffer_hooks = !NILP (inhibit_buffer_hooks); 657 b->inhibit_buffer_hooks = !NILP (inhibit_buffer_hooks);
652 bset_undo_list (b, SREF (name, 0) != ' ' ? Qnil : Qt); 658 bset_undo_list (b, SREF (name, 0) != ' ' ? Qnil : Qt);
@@ -866,6 +872,7 @@ Interactively, CLONE and INHIBIT-BUFFER-HOOKS are nil. */)
866 name = Fcopy_sequence (name); 872 name = Fcopy_sequence (name);
867 set_string_intervals (name, NULL); 873 set_string_intervals (name, NULL);
868 bset_name (b, name); 874 bset_name (b, name);
875 bset_last_name (b, name);
869 876
870 /* An indirect buffer shares undo list of its base (Bug#18180). */ 877 /* An indirect buffer shares undo list of its base (Bug#18180). */
871 bset_undo_list (b, BVAR (b->base_buffer, undo_list)); 878 bset_undo_list (b, BVAR (b->base_buffer, undo_list));
@@ -1282,6 +1289,17 @@ Return nil if BUFFER has been killed. */)
1282 return BVAR (decode_buffer (buffer), name); 1289 return BVAR (decode_buffer (buffer), name);
1283} 1290}
1284 1291
1292DEFUN ("buffer-last-name", Fbuffer_last_name, Sbuffer_last_name, 0, 1, 0,
1293 doc: /* Return last name of BUFFER, as a string.
1294BUFFER defaults to the current buffer.
1295
1296This is the name BUFFER had before the last time it was renamed or
1297immediately before it was killed. */)
1298 (Lisp_Object buffer)
1299{
1300 return BVAR (decode_buffer (buffer), last_name);
1301}
1302
1285DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0, 1303DEFUN ("buffer-file-name", Fbuffer_file_name, Sbuffer_file_name, 0, 1, 0,
1286 doc: /* Return name of file BUFFER is visiting, or nil if none. 1304 doc: /* Return name of file BUFFER is visiting, or nil if none.
1287No argument or nil as argument means use the current buffer. */) 1305No 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). */)
1652 (register Lisp_Object newname, Lisp_Object unique) 1670 (register Lisp_Object newname, Lisp_Object unique)
1653{ 1671{
1654 register Lisp_Object tem, buf; 1672 register Lisp_Object tem, buf;
1673 Lisp_Object oldname = BVAR (current_buffer, name);
1655 Lisp_Object requestedname = newname; 1674 Lisp_Object requestedname = newname;
1656 1675
1657 CHECK_STRING (newname); 1676 CHECK_STRING (newname);
@@ -1669,12 +1688,12 @@ This does not change the name of the visited file (if any). */)
1669 if (NILP (unique) && XBUFFER (tem) == current_buffer) 1688 if (NILP (unique) && XBUFFER (tem) == current_buffer)
1670 return BVAR (current_buffer, name); 1689 return BVAR (current_buffer, name);
1671 if (!NILP (unique)) 1690 if (!NILP (unique))
1672 newname = Fgenerate_new_buffer_name (newname, 1691 newname = Fgenerate_new_buffer_name (newname, oldname);
1673 BVAR (current_buffer, name));
1674 else 1692 else
1675 error ("Buffer name `%s' is in use", SDATA (newname)); 1693 error ("Buffer name `%s' is in use", SDATA (newname));
1676 } 1694 }
1677 1695
1696 bset_last_name (current_buffer, oldname);
1678 bset_name (current_buffer, newname); 1697 bset_name (current_buffer, newname);
1679 1698
1680 /* Catch redisplay's attention. Unless we do this, the mode lines for 1699 /* 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. */)
2095 This gets rid of them for certain. */ 2114 This gets rid of them for certain. */
2096 reset_buffer_local_variables (b, 1); 2115 reset_buffer_local_variables (b, 1);
2097 2116
2117 bset_last_name (b, BVAR (b, name));
2098 bset_name (b, Qnil); 2118 bset_name (b, Qnil);
2099 2119
2100 block_input (); 2120 block_input ();
@@ -4666,6 +4686,7 @@ init_buffer_once (void)
4666 /* These used to be stuck at 0 by default, but now that the all-zero value 4686 /* These used to be stuck at 0 by default, but now that the all-zero value
4667 means Qnil, we have to initialize them explicitly. */ 4687 means Qnil, we have to initialize them explicitly. */
4668 bset_name (&buffer_local_flags, make_fixnum (0)); 4688 bset_name (&buffer_local_flags, make_fixnum (0));
4689 bset_last_name (&buffer_local_flags, make_fixnum (0));
4669 bset_mark (&buffer_local_flags, make_fixnum (0)); 4690 bset_mark (&buffer_local_flags, make_fixnum (0));
4670 bset_local_var_alist (&buffer_local_flags, make_fixnum (0)); 4691 bset_local_var_alist (&buffer_local_flags, make_fixnum (0));
4671 bset_keymap (&buffer_local_flags, make_fixnum (0)); 4692 bset_keymap (&buffer_local_flags, make_fixnum (0));
@@ -6026,6 +6047,7 @@ There is no reason to change that value except for debugging purposes. */);
6026 defsubr (&Smake_indirect_buffer); 6047 defsubr (&Smake_indirect_buffer);
6027 defsubr (&Sgenerate_new_buffer_name); 6048 defsubr (&Sgenerate_new_buffer_name);
6028 defsubr (&Sbuffer_name); 6049 defsubr (&Sbuffer_name);
6050 defsubr (&Sbuffer_last_name);
6029 defsubr (&Sbuffer_file_name); 6051 defsubr (&Sbuffer_file_name);
6030 defsubr (&Sbuffer_base_buffer); 6052 defsubr (&Sbuffer_base_buffer);
6031 defsubr (&Sbuffer_local_value); 6053 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
309 /* The name of this buffer. */ 309 /* The name of this buffer. */
310 Lisp_Object name_; 310 Lisp_Object name_;
311 311
312 /* The last name of this buffer before it was renamed or killed. */
313 Lisp_Object last_name_;
314
312 /* The name of the file visited in this buffer, or nil. */ 315 /* The name of the file visited in this buffer, or nil. */
313 Lisp_Object filename_; 316 Lisp_Object filename_;
314 317
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,
7109the mini-window of the frame doesn't get set to the corresponding element 7109the mini-window of the frame doesn't get set to the corresponding element
7110of CONFIGURATION. 7110of CONFIGURATION.
7111 7111
7112Normally, this function will try to delete any dead window in 7112This function consults the variable `window-restore-killed-buffer-windows'
7113CONFIGURATION whose buffer has been deleted since CONFIGURATION was 7113when restoring a window whose buffer was killed after CONFIGURATION was
7114made. However, if the abnormal hook `window-kept-windows-functions' is 7114recorded.
7115non-nil, it will preserve such a window in the restored layout and show
7116another buffer in it.
7117
7118After restoring the frame layout, this function runs the abnormal hook
7119`window-kept-windows-functions' with two arguments - the frame whose
7120layout it has restored and a list of entries for each window whose
7121buffer has been found dead when it tried to restore CONFIGURATION: Each
7122entry is a list of four elements <window, buffer, start, point> where
7123`window' denotes the window whose buffer was found dead, `buffer'
7124denotes the dead buffer, and `start' and `point' denote the last known
7125positions of `window-start' and `window-point' of the buffer in that
7126window. Any function run by this hook should check such a window for
7127liveness because another function run by this hook may have deleted it
7128in the meantime."
7129 7115
7130If CONFIGURATION was made from a frame that is now deleted, 7116If CONFIGURATION was made from a frame that is now deleted,
7131only frame-independent values can be restored. In this case, 7117only frame-independent values can be restored. In this case,
@@ -7378,10 +7364,12 @@ the return value is nil. Otherwise the value is t. */)
7378 BUF_PT (XBUFFER (w->contents)), 7364 BUF_PT (XBUFFER (w->contents)),
7379 BUF_PT_BYTE (XBUFFER (w->contents))); 7365 BUF_PT_BYTE (XBUFFER (w->contents)));
7380 w->start_at_line_beg = true; 7366 w->start_at_line_beg = true;
7381 if (!NILP (Vwindow_kept_windows_functions)) 7367 if (FUNCTIONP (window_restore_killed_buffer_windows)
7382 kept_windows = Fcons (list4 (window, p->buffer, 7368 && !MINI_WINDOW_P (w))
7369 kept_windows = Fcons (listn (6, window, p->buffer,
7383 Fmarker_last_position (p->start), 7370 Fmarker_last_position (p->start),
7384 Fmarker_last_position (p->pointm)), 7371 Fmarker_last_position (p->pointm),
7372 p->dedicated, Qt),
7385 kept_windows); 7373 kept_windows);
7386 } 7374 }
7387 else if (!NILP (w->start)) 7375 else if (!NILP (w->start))
@@ -7398,16 +7386,25 @@ the return value is nil. Otherwise the value is t. */)
7398 set_marker_restricted_both (w->pointm, w->contents, 0, 0); 7386 set_marker_restricted_both (w->pointm, w->contents, 0, 0);
7399 set_marker_restricted_both (w->old_pointm, w->contents, 0, 0); 7387 set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
7400 w->start_at_line_beg = true; 7388 w->start_at_line_beg = true;
7401 if (!NILP (w->dedicated)) 7389 if (!MINI_WINDOW_P (w))
7402 /* Record this window as dead. */ 7390 {
7403 dead_windows = Fcons (window, dead_windows); 7391 if (FUNCTIONP (window_restore_killed_buffer_windows))
7404 /* Make sure window is no more dedicated. */ 7392 kept_windows
7405 wset_dedicated (w, Qnil); 7393 = Fcons (listn (6, window, p->buffer,
7406 if (!NILP (Vwindow_kept_windows_functions)) 7394 Fmarker_last_position (p->start),
7407 kept_windows = Fcons (list4 (window, p->buffer, 7395 Fmarker_last_position (p->pointm),
7408 Fmarker_last_position (p->start), 7396 p->dedicated, Qnil),
7409 Fmarker_last_position (p->pointm)), 7397 kept_windows);
7410 kept_windows); 7398 else if (EQ (window_restore_killed_buffer_windows, Qdelete)
7399 || (!NILP (p->dedicated)
7400 && (NILP (window_restore_killed_buffer_windows)
7401 || EQ (window_restore_killed_buffer_windows,
7402 Qdedicated))))
7403 /* Try to delete this window later. */
7404 dead_windows = Fcons (window, dead_windows);
7405 /* Make sure window is no more dedicated. */
7406 wset_dedicated (w, Qnil);
7407 }
7411 } 7408 }
7412 } 7409 }
7413 7410
@@ -7459,13 +7456,12 @@ the return value is nil. Otherwise the value is t. */)
7459 unblock_input (); 7456 unblock_input ();
7460 7457
7461 /* Scan dead buffer windows. */ 7458 /* Scan dead buffer windows. */
7462 if (!NILP (Vwindow_kept_windows_functions)) 7459 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
7463 for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows)) 7460 {
7464 { 7461 window = XCAR (dead_windows);
7465 window = XCAR (dead_windows); 7462 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f)))
7466 if (WINDOW_LIVE_P (window) && !EQ (window, FRAME_ROOT_WINDOW (f))) 7463 delete_deletable_window (window);
7467 delete_deletable_window (window); 7464 }
7468 }
7469 7465
7470 /* Record the selected window's buffer here. The window should 7466 /* Record the selected window's buffer here. The window should
7471 already be the selected one from the call above. */ 7467 already be the selected one from the call above. */
@@ -7513,9 +7509,9 @@ the return value is nil. Otherwise the value is t. */)
7513 7509
7514 SAFE_FREE (); 7510 SAFE_FREE ();
7515 7511
7516 if (!NILP (Vrun_hooks) && !NILP (Vwindow_kept_windows_functions)) 7512 if (!NILP (Vrun_hooks) && FUNCTIONP (window_restore_killed_buffer_windows))
7517 run_hook_with_args_2 (Qwindow_kept_windows_functions, frame, 7513 safe_calln (window_restore_killed_buffer_windows,
7518 kept_windows); 7514 frame, kept_windows, Qconfiguration);
7519 7515
7520 return FRAME_LIVE_P (f) ? Qt : Qnil; 7516 return FRAME_LIVE_P (f) ? Qt : Qnil;
7521} 7517}
@@ -8514,8 +8510,9 @@ syms_of_window (void)
8514 DEFSYM (Qheader_line_format, "header-line-format"); 8510 DEFSYM (Qheader_line_format, "header-line-format");
8515 DEFSYM (Qtab_line_format, "tab-line-format"); 8511 DEFSYM (Qtab_line_format, "tab-line-format");
8516 DEFSYM (Qno_other_window, "no-other-window"); 8512 DEFSYM (Qno_other_window, "no-other-window");
8517 DEFSYM (Qwindow_kept_windows_functions, 8513 DEFSYM (Qconfiguration, "configuration");
8518 "window-kept-windows-functions"); 8514 DEFSYM (Qdelete, "delete");
8515 DEFSYM (Qdedicated, "dedicated");
8519 8516
8520 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, 8517 DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
8521 doc: /* Non-nil means call as function to display a help buffer. 8518 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
8673call is performed with the frame temporarily selected. */); 8670call is performed with the frame temporarily selected. */);
8674 Vwindow_configuration_change_hook = Qnil; 8671 Vwindow_configuration_change_hook = Qnil;
8675 8672
8676 DEFVAR_LISP ("window-kept-windows-functions", 8673 DEFVAR_LISP ("window-restore-killed-buffer-windows",
8677 Vwindow_kept_windows_functions, 8674 window_restore_killed_buffer_windows,
8678 doc: /* Functions run after restoring a window configuration or state. 8675 doc: /* Control restoring windows whose buffer was killed.
8679These functions are called by `set-window-configuration' and 8676This variable specifies how the functions `set-window-configuration' and
8680`window-state-put'. When the value of this variable is non-nil, these 8677`window-state-put' shall handle a window whose buffer has been killed
8681functions restore any window whose buffer has been deleted since the 8678since the corresponding configuration or state was made. Any such
8682corresponding configuration or state was saved. Rather than deleting 8679window may be live - in which case it shows some other buffer - or dead
8683such a window, `set-window-configuration' and `window-state-put' show 8680at the time one of these functions is called.
8684some live buffer in it. 8681
8685 8682As a rule, `set-window-configuration' leaves the window alone if it is
8686The value should be a list of functions that take two arguments. The 8683live while `window-state-put' deletes it. The following values can be
8687first argument specifies the frame whose configuration has been 8684used to override the default behavior for dead windows in the case of
8688restored. The second argument, if non-nil, specifies a list of entries 8685`set-window-configuration' and for dead and live windows in the case of
8689for each window whose buffer has been found dead at the time 8686`window-state-put'.
8690'set-window-configuration' or `window-state-put' tried to restore it in 8687
8691that window. Each entry is a list of four values - the window whose 8688- t means to restore the window and show some other buffer in it.
8692buffer was found dead, the dead buffer, and the positions of start and 8689
8693point of the buffer in that window. Note that the window may be already 8690- `delete' means to try to delete the window.
8694dead since another function on this list may have deleted it in the 8691
8695meantime. */); 8692- `dedicated' means to try to delete the window if and only if it is
8696 Vwindow_kept_windows_functions = Qnil; 8693 dedicated to its buffer.
8694
8695- nil, the default, means that `set-window-configuration' will try to
8696 delete the window if and only if it is dedicated to its buffer while
8697 `window-state-put' will unconditionally try to delete it.
8698
8699- a function means to restore the window, show some other buffer in it
8700 and add an entry for that window to a list that will be later passed
8701 as argument to that function.
8702
8703If a window cannot be deleted (typically, because it is the last window
8704on its frame), show another buffer in it.
8705
8706If the value is a function, it should take three arguments. The first
8707argument specifies the frame whose windows have been restored. The
8708third argument is the constant `configuration' if the windows are
8709restored by `set-window-configuration' and the constant `state' if the
8710windows are restored by `window-state-put'.
8711
8712The second argument specifies a list of entries for @emph{any} window
8713whose previous buffer has been encountered dead at the time
8714`set-window-configuration' or `window-state-put' tried to restore it in
8715that window (minibuffer windows are excluded). This means that the
8716function specified by this variable may also delete windows encountered
8717live by `set-window-configuration'.
8718
8719Each entry is a list of six values - the window whose buffer was found
8720dead, the dead buffer or its name, the positions of start and point of
8721the buffer in that window, the dedicated status of the window as
8722reported by `window-dedicated-p' and a boolean - t if the window was
8723live when `set-window-configuration' tried to restore it and nil
8724otherwise. */);
8725 window_restore_killed_buffer_windows = Qnil;
8697 8726
8698 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, 8727 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
8699 doc: /* Non-nil means `recenter' redraws entire frame. 8728 doc: /* Non-nil means `recenter' redraws entire frame.