diff --git a/src/keyboard.c b/src/keyboard.c index e1d738dd6ef..b6ba3c57ff8 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2281,7 +2281,7 @@ read_char_help_form_unwind (void) Lisp_Object window_config = XCAR (help_form_saved_window_configs); help_form_saved_window_configs = XCDR (help_form_saved_window_configs); if (!NILP (window_config)) - Fset_window_configuration (window_config, Qnil, Qnil); + Fset_window_configuration (window_config, Qnil, Qnil, Qnil); } #define STOP_POLLING \ diff --git a/src/window.c b/src/window.c index 3a54f7ce7b1..c33b987c24f 100644 --- a/src/window.c +++ b/src/window.c @@ -7037,6 +7037,7 @@ DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line, union vectorlike_header header; Lisp_Object window, buffer, start, pointm, old_pointm; + Lisp_Object start_pos, pointm_pos; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; @@ -7079,7 +7080,7 @@ DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_config } DEFUN ("set-window-configuration", Fset_window_configuration, - Sset_window_configuration, 1, 3, 0, + Sset_window_configuration, 1, 4, 0, doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION. CONFIGURATION must be a value previously returned by `current-window-configuration' (which see). @@ -7090,16 +7091,35 @@ DEFUN ("set-window-configuration", Fset_window_configuration, 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 KEEP-WINDOWS 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 +'post-set-window-configuration-functions' with two arguments - the frame +whose layout is has restored and, provided KEEP-WINDOWS is non-nil, 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 + where `window' denotes the window whose +buffer was found dead, `buffer' denotes the dead buffer, and `start' and +`point' denote the positions of `window-start' and `window-point' of +that window at the time CONFIGURATION was made. Note that these +positions are no markers and may be no more accurate if the buffer has +been modified afterwards. If KEEP-WINDOWS is nil, the second argument +is nil. + If CONFIGURATION was made from a frame that is now deleted, only frame-independent values can be restored. In this case, the return value is nil. Otherwise the value is t. */) (Lisp_Object configuration, Lisp_Object dont_set_frame, - Lisp_Object dont_set_miniwindow) + Lisp_Object dont_set_miniwindow, Lisp_Object keep_windows) { register struct save_window_data *data; struct Lisp_Vector *saved_windows; Lisp_Object new_current_buffer; Lisp_Object frame; + Lisp_Object kept_windows = Qnil; Lisp_Object old_frame = selected_frame; struct frame *f; ptrdiff_t old_point = -1; @@ -7340,6 +7360,10 @@ DEFUN ("set-window-configuration", Fset_window_configuration, BUF_PT (XBUFFER (w->contents)), BUF_PT_BYTE (XBUFFER (w->contents))); w->start_at_line_beg = true; + if (!NILP (keep_windows)) + kept_windows = Fcons (list4 (window, p->buffer, + p->start_pos, p->pointm_pos), + kept_windows); } else if (!NILP (w->start)) /* Leaf window has no live buffer, get one. */ @@ -7360,6 +7384,10 @@ DEFUN ("set-window-configuration", Fset_window_configuration, dead_windows = Fcons (window, dead_windows); /* Make sure window is no more dedicated. */ wset_dedicated (w, Qnil); + if (!NILP (keep_windows)) + kept_windows = Fcons (list4 (window, p->buffer, + p->start_pos, p->pointm_pos), + kept_windows); } } @@ -7411,12 +7439,13 @@ DEFUN ("set-window-configuration", Fset_window_configuration, unblock_input (); /* Scan dead buffer windows. */ - 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); - } + if (NILP (keep_windows)) + 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. */ @@ -7463,6 +7492,11 @@ DEFUN ("set-window-configuration", Fset_window_configuration, minibuf_selected_window = data->minibuf_selected_window; SAFE_FREE (); + + if (!NILP (Vrun_hooks) && !NILP (Vpost_set_window_configuration_functions)) + run_hook_with_args_2 (Qpost_set_window_configuration_functions, frame, + kept_windows); + return FRAME_LIVE_P (f) ? Qt : Qnil; } @@ -7472,12 +7506,12 @@ restore_window_configuration (Lisp_Object configuration) if (CONSP (configuration)) Fset_window_configuration (XCAR (configuration), Fcar_safe (XCDR (configuration)), - Fcar_safe (Fcdr_safe (XCDR (configuration)))); + Fcar_safe (Fcdr_safe (XCDR (configuration))), + Qnil); else - Fset_window_configuration (configuration, Qnil, Qnil); + Fset_window_configuration (configuration, Qnil, Qnil, Qnil); } - /* If WINDOW is an internal window, recursively delete all child windows reachable via the next and contents slots of WINDOW. Otherwise setup WINDOW to not show any buffer. */ @@ -7685,16 +7719,24 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) is the selected window, then get the value of point from the buffer; pointm is garbage in the selected window. */ if (EQ (window, selected_window)) - p->pointm = build_marker (XBUFFER (w->contents), - BUF_PT (XBUFFER (w->contents)), - BUF_PT_BYTE (XBUFFER (w->contents))); + { + p->pointm = build_marker (XBUFFER (w->contents), + BUF_PT (XBUFFER (w->contents)), + BUF_PT_BYTE (XBUFFER (w->contents))); + p->pointm_pos = make_fixnum (BUF_PT (XBUFFER (w->contents))); + } else - p->pointm = Fcopy_marker (w->pointm, Qnil); + { + p->pointm = Fcopy_marker (w->pointm, Qnil); + p->pointm_pos = make_fixnum (marker_position (w->pointm)); + } + p->old_pointm = Fcopy_marker (w->old_pointm, Qnil); XMARKER (p->pointm)->insertion_type = window_point_insertion_type; XMARKER (p->old_pointm)->insertion_type = window_point_insertion_type; p->start = Fcopy_marker (w->start, Qnil); + p->start_pos = make_fixnum (marker_position (w->start)); p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil; } else @@ -8460,6 +8502,8 @@ 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 (Qpost_set_window_configuration_functions, + "post-set-window-configuration-functions"); DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, doc: /* Non-nil means call as function to display a help buffer. @@ -8617,6 +8661,21 @@ syms_of_window (void) call is performed with the frame temporarily selected. */); Vwindow_configuration_change_hook = Qnil; + DEFVAR_LISP ("post-set-window-configuration-functions", + Vpost_set_window_configuration_functions, + doc: /* Functions called after restoring a window configuration. +The value should be a list of functions that take two arguments. + +This function is called by `set-window-configuration' after it has +restored the layout of a frame. 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' 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. */); + Vpost_set_window_configuration_functions = Qnil; + DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, doc: /* Non-nil means `recenter' redraws entire frame. If this option is non-nil, then the `recenter' command with a nil