]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix unclean "can't happen" error handling in read_minibuf_unwind
authorAlan Mackenzie <acm@muc.de>
Thu, 22 Apr 2021 12:07:21 +0000 (12:07 +0000)
committerAlan Mackenzie <acm@muc.de>
Thu, 22 Apr 2021 12:07:21 +0000 (12:07 +0000)
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.

doc/lispref/windows.texi
etc/NEWS
src/keyboard.c
src/minibuf.c
src/window.c

index c32d711f12a1b5894f59dd29bef3a3b540ff4ea8..82d2ce4757be615cbb3de236cadc33d36ae1de6f 100644 (file)
@@ -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
index 559ffd6d8f657b9612bfc0951d7946cbd0d804ca..e7258f19b46a2ee7e8da504b3adda68a4b6708f7 100644 (file)
--- 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.
index 266ebaa5fdf0ba65c43a4bae1f2907ed47f2975e..5db45ce8e575531b9f17d789ea4c4feffb9c4ef0 100644 (file)
@@ -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                                   \
index 1a637c86adef1ec2b474770f6df9f781e7cdd4bc..c4482d7f1ee1ead2c1c80307b1b9d6f4e5024aaa 100644 (file)
@@ -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);
index a22fab244412a1317b4317cfcaa398a3a21afd7a..5134c3df63dfb7d25ffc1d078ee15483159cd78f 100644 (file)
@@ -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);
 }