From: Alan Mackenzie Date: Thu, 22 Apr 2021 12:07:21 +0000 (+0000) Subject: Fix unclean "can't happen" error handling in read_minibuf_unwind X-Git-Tag: emacs-28.0.90~2780 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=846989498b66f94739e78ca274c8d1176c137591;p=emacs.git Fix unclean "can't happen" error handling in read_minibuf_unwind Also fix a bug where, with minibuffer-follows-selected-frame neither nil nor t, a minibuffer could appear in two frames at the same time. * src/window.c (Fset_window_configuration): Add a new &optional parameter DONT-SET-MINIWINDOW, which inhibits the minibuffer from being restored from the supplied window configuration. (restore_window_configuration): Enhance to match the above. * src/minibuf.c (read_minibuf): Enhance the argument list to the restore_window_configuration calls to match the above. In the main case, restoring the minibuffer is inhibited. (read_minibuf_unwind): Should the frame with the expired minibuffer not be found ("can't happen"), unwind the stacked data nevertheless, rather than just exiting. * src/keyboard.c (read_char_help_form_unwind): Amend a call of Fset_window_configuration. * doc/lispref/windows.texi (Window Configurations): Document the new form of set-window-configuration. * etc/NEWS (Lisp Changes in Emacs 28.1): Amend the entry for set-window-configuration. --- diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index c32d711f12a..82d2ce4757b 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -5877,7 +5877,7 @@ which window parameters (if any) are saved by this function. @xref{Window Parameters}. @end defun -@defun set-window-configuration configuration &optional dont-set-frame +@defun set-window-configuration configuration &optional dont-set-frame dont-set-miniwindow This function restores the configuration of windows and buffers as specified by @var{configuration}, for the frame that @var{configuration} was created for, regardless of whether that frame @@ -5885,8 +5885,12 @@ is selected or not. The argument @var{configuration} must be a value that was previously returned by @code{current-window-configuration} for that frame. Normally the function also selects the frame which is recorded in the configuration, but if @var{dont-set-frame} is -non-@code{nil}, it leaves selected the frame which was current at the -start of the function. +non-@code{nil}, it leaves selected the frame which was already +selected at the start of the function. + +Normally the function restores the saved minibuffer (if any), but if +@var{dont-set-miniwindow} is non-@code{nil}, the minibuffer current +at the start of the function (if any) remains in the mini-window. If the frame from which @var{configuration} was saved is dead, all this function does is to restore the value of the variable diff --git a/etc/NEWS b/etc/NEWS index 559ffd6d8f6..e7258f19b46 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2674,9 +2674,11 @@ one to another in the init file. The same user option also controls whether the function 'read-answer' accepts short answers. +++ -** 'set-window-configuration' now takes an optional 'dont-set-frame' -parameter which, when non-nil, instructs the function not to select -the frame recorded in the configuration. +** 'set-window-configuration' now takes two optional parameters, +'dont-set-frame' and 'dont-set-miniwindow'. The first of these, when +non-nil, instructs the function not to select the frame recorded in +the configuration. The second prevents the current minibuffer being +replaced by the one stored in the configuration. +++ ** 'define-globalized-minor-mode' now takes a ':predicate' parameter. diff --git a/src/keyboard.c b/src/keyboard.c index 266ebaa5fdf..5db45ce8e57 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -2121,7 +2121,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); + Fset_window_configuration (window_config, Qnil, Qnil); } #define STOP_POLLING \ diff --git a/src/minibuf.c b/src/minibuf.c index 1a637c86ade..c4482d7f1ee 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -660,17 +660,14 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, record_unwind_protect_void (minibuffer_unwind); record_unwind_protect (restore_window_configuration, - Fcons (Qt, Fcurrent_window_configuration (Qnil))); + list3 (Fcurrent_window_configuration (Qnil), Qt, Qt)); /* If the minibuffer window is on a different frame, save that frame's configuration too. */ if (!EQ (mini_frame, selected_frame)) record_unwind_protect (restore_window_configuration, - Fcons (/* Arrange for the frame later to be - switched back to the calling - frame. */ - Qnil, - Fcurrent_window_configuration (mini_frame))); + list3 (Fcurrent_window_configuration (mini_frame), + Qnil, Qt)); /* If the minibuffer is on an iconified or invisible frame, make it visible now. */ @@ -1069,13 +1066,13 @@ read_minibuf_unwind (void) goto found; } } - return; /* expired minibuffer not found. Maybe we should output an - error, here. */ + exp_MB_frame = Qnil; /* "Can't happen." */ found: - if (!EQ (exp_MB_frame, saved_selected_frame)) + if (!EQ (exp_MB_frame, saved_selected_frame) + && !NILP (exp_MB_frame)) do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets - minibuff_window */ + minibuf_window */ /* To keep things predictable, in case it matters, let's be in the minibuffer when we reset the relevant variables. Don't depend on @@ -1185,7 +1182,8 @@ read_minibuf_unwind (void) } /* Restore the selected frame. */ - if (!EQ (exp_MB_frame, saved_selected_frame)) + if (!EQ (exp_MB_frame, saved_selected_frame) + && !NILP (exp_MB_frame)) do_switch_frame (saved_selected_frame, 0, 0, Qt); } @@ -1200,6 +1198,7 @@ minibuffer_unwind (void) Lisp_Object window; Lisp_Object entry; + if (NILP (exp_MB_frame)) return; /* "Can't happen." */ f = XFRAME (exp_MB_frame); window = f->minibuffer_window; w = XWINDOW (window); diff --git a/src/window.c b/src/window.c index a22fab24441..5134c3df63d 100644 --- a/src/window.c +++ b/src/window.c @@ -6881,19 +6881,22 @@ DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_config } DEFUN ("set-window-configuration", Fset_window_configuration, - Sset_window_configuration, 1, 2, 0, + Sset_window_configuration, 1, 3, 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). Normally, this function selects the frame of the CONFIGURATION, but if DONT-SET-FRAME is non-nil, it leaves selected the frame which was -current at the start of the function. +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. 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 configuration, Lisp_Object dont_set_frame, + Lisp_Object dont_set_miniwindow) { register struct save_window_data *data; struct Lisp_Vector *saved_windows; @@ -7104,8 +7107,10 @@ the return value is nil. Otherwise the value is t. */) } } - if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) - /* If saved buffer is alive, install it. */ + if ((NILP (dont_set_miniwindow) || !MINI_WINDOW_P (w)) + && BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) + /* If saved buffer is alive, install it, unless it's a + minibuffer we explicitly prohibit. */ { wset_buffer (w, p->buffer); w->start_at_line_beg = !NILP (p->start_at_line_beg); @@ -7258,9 +7263,11 @@ void restore_window_configuration (Lisp_Object configuration) { if (CONSP (configuration)) - Fset_window_configuration (XCDR (configuration), XCAR (configuration)); + Fset_window_configuration (XCAR (configuration), + XCAR (XCDR (configuration)), + XCAR (XCDR (XCDR (configuration)))); else - Fset_window_configuration (configuration, Qnil); + Fset_window_configuration (configuration, Qnil, Qnil); }