emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 780b1db: Various detailed fixes to minibuf.c, etc., to fix bug #4


From: Alan Mackenzie
Subject: master 780b1db: Various detailed fixes to minibuf.c, etc., to fix bug #48337
Date: Fri, 14 May 2021 11:55:11 -0400 (EDT)

branch: master
commit 780b1db126fcfdbb50da5c1acf24b3c6e614dd9f
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Various detailed fixes to minibuf.c, etc., to fix bug #48337
    
    Also fix some unsafe coding.
    
    * lisp/window.el (push-window-buffer-onto-prev): New function, extracted 
from
    (record-window-buffer): Refactor by extracting the above, and removing the 
now
    redundant parameter DO-MINIBUF.
    
    * src/minibuf.c (zip_minibuffer_stacks, read_minibuf): Replace calls to
    get_minibuffer (0) by nth_minibuffer (0).  Replace calls to
    Qrecord_window_buffer by calls to Qpush_window_buffer_onto_prev.
    (Factive_minibuffer_window, read_minibuf_unwind): Call abort_emacs should an
    "impossible" null value be returned by nth_minibuffer.
    (read_minibuf): Move the get_minibuffer_call to just after the 
incrementation
    of minibuf_level as a precaution against a missing buffer in
    Vminibuffer_list.
    (nth_minibuffer): Replace XCAR by Fcar, to allow (car nil) to work.
    (init_minibuf_once): Create the inactive buffer  *Minibuf-0*.
    (syms_of_minibuf): New DEFSYM, Qpush_window_buffer_onto_prev.
    
    * src/window.c (restore_window_configuration): Replace some XCARs and XCDRs
    by Fcar_safe and Fcdr_safe.
---
 lisp/window.el | 62 +++++++++++++++++++++++++++++-----------------------------
 src/minibuf.c  | 35 +++++++++++++++++++++------------
 src/window.c   |  4 ++--
 3 files changed, 55 insertions(+), 46 deletions(-)

diff --git a/lisp/window.el b/lisp/window.el
index db62d33..8928308 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4361,45 +4361,45 @@ This may be a useful alternative binding for 
\\[delete-other-windows]
 
 ;; The following function is called by `set-window-buffer' _before_ it
 ;; replaces the buffer of the argument window with the new buffer.
-(defun record-window-buffer (&optional window do-minibuf)
-  "Record WINDOW's buffer.
+(defun push-window-buffer-onto-prev (&optional window)
+  "Push entry for WINDOW's buffer onto WINDOW's prev-buffers list.
 WINDOW must be a live window and defaults to the selected one.
 
-If WINDOW is a minibuffer, it will only be recorded if DO-MINIBUF
-is non-nil."
+Any duplicate entries for the buffer in the list are removed."
   (let* ((window (window-normalize-window window t))
-        (buffer (window-buffer window))
-        (entry (assq buffer (window-prev-buffers window))))
+         (buffer (window-buffer window))
+         (w-list (window-prev-buffers window))
+         (entry (assq buffer w-list)))
+    (when entry
+      (setq w-list (assq-delete-all buffer w-list)))
+    (let ((start (window-start window))
+          (point (window-point window)))
+      (setq entry
+            (cons buffer
+                  (with-current-buffer buffer
+                    (if entry
+                        ;; We have an entry, update marker positions.
+                        (list (set-marker (nth 1 entry) start)
+                              (set-marker (nth 2 entry) point))
+                      (list (copy-marker start)
+                            (copy-marker
+                             ;; Preserve window-point-insertion-type
+                             ;; (Bug#12855)
+                             point window-point-insertion-type))))))
+      (set-window-prev-buffers window (cons entry w-list)))))
+
+(defun record-window-buffer (&optional window)
+  "Record WINDOW's buffer.
+WINDOW must be a live window and defaults to the selected one."
+  (let* ((window (window-normalize-window window t))
+         (buffer (window-buffer window)))
     ;; Reset WINDOW's next buffers.  If needed, they are resurrected by
     ;; `switch-to-prev-buffer' and `switch-to-next-buffer'.
     (set-window-next-buffers window nil)
 
     ;; Don't record insignificant buffers.
-    (when (or (not (eq (aref (buffer-name buffer) 0) ?\s))
-              (and do-minibuf (minibufferp buffer)))
-      (when entry
-        ;; Remove all entries for BUFFER from WINDOW's previous buffers.
-        (set-window-prev-buffers
-         window (assq-delete-all buffer (window-prev-buffers window))))
-      ;; Add an entry for buffer to WINDOW's previous buffers.
-      (with-current-buffer buffer
-       (let ((start (window-start window))
-             (point (window-point window)))
-         (setq entry
-               (cons buffer
-                     (if entry
-                         ;; We have an entry, update marker positions.
-                         (list (set-marker (nth 1 entry) start)
-                               (set-marker (nth 2 entry) point))
-                       ;; Make new markers.
-                       (list (copy-marker start)
-                             (copy-marker
-                              ;; Preserve window-point-insertion-type
-                              ;; (Bug#12855).
-                              point window-point-insertion-type)))))
-         (set-window-prev-buffers
-          window (cons entry (window-prev-buffers window)))))
-
+    (when (not (eq (aref (buffer-name buffer) 0) ?\s))
+      (push-window-buffer-onto-prev window)
       (run-hooks 'buffer-list-update-hook))))
 
 (defun unrecord-window-buffer (&optional window buffer)
diff --git a/src/minibuf.c b/src/minibuf.c
index 52d1275..428998a 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -157,16 +157,15 @@ zip_minibuffer_stacks (Lisp_Object dest_window, 
Lisp_Object source_window)
       Fset_window_start (dest_window, Fwindow_start (source_window), Qnil);
       Fset_window_point (dest_window, Fwindow_point (source_window));
       dw->prev_buffers = sw->prev_buffers;
-      set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+      set_window_buffer (source_window, nth_minibuffer (0), 0, 0);
       sw->prev_buffers = Qnil;
       return;
     }
 
   if (live_minibuffer_p (dw->contents))
-    call2 (Qrecord_window_buffer, dest_window, Qt);
+    call1 (Qpush_window_buffer_onto_prev, dest_window);
   if (live_minibuffer_p (sw->contents))
-    call2 (Qrecord_window_buffer, source_window, Qt);
-
+    call1 (Qpush_window_buffer_onto_prev, source_window);
   acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater);
 
   if (!NILP (acc))
@@ -179,7 +178,7 @@ zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object 
source_window)
     }
   dw->prev_buffers = acc;
   sw->prev_buffers = Qnil;
-  set_window_buffer (source_window, get_minibuffer (0), 0, 0);
+  set_window_buffer (source_window, nth_minibuffer (0), 0, 0);
 }
 
 /* If `minibuffer_follows_selected_frame' is t, or we're about to
@@ -228,6 +227,8 @@ DEFUN ("active-minibuffer-window", 
Factive_minibuffer_window,
     return Qnil;
 
   innermost_MB = nth_minibuffer (minibuf_level);
+  if (NILP (innermost_MB))
+    emacs_abort ();
   FOR_EACH_FRAME (frames, frame)
     {
       f = XFRAME (frame);
@@ -653,6 +654,10 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
     }
 
   minibuf_level++;         /* Before calling choose_minibuf_frame.  */
+  /* Ensure now that the latest minibuffer has been created, in case
+     anything happens which depends on MINNIBUF_LEVEL and
+     Vminibuffer_list being consistent with eachother.  */
+  minibuffer = get_minibuffer (minibuf_level);
 
   /* Choose the minibuffer window and frame, and take action on them.  */
 
@@ -680,7 +685,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
     }
   MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame;
   if (live_minibuffer_p (XWINDOW (minibuf_window)->contents))
-    call2 (Qrecord_window_buffer, minibuf_window, Qt);
+    call1 (Qpush_window_buffer_onto_prev, minibuf_window);
 
   record_unwind_protect_void (minibuffer_unwind);
   record_unwind_protect (restore_window_configuration,
@@ -766,7 +771,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
 
   /* Switch to the minibuffer.  */
 
-  minibuffer = get_minibuffer (minibuf_level);
   set_minibuffer_mode (minibuffer, minibuf_level);
   Fset_buffer (minibuffer);
 
@@ -807,7 +811,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, 
Lisp_Object prompt,
   /* Empty out the minibuffers of all frames, except those frames
      where there is an active minibuffer.
      Set them to point to ` *Minibuf-0*', which is always empty.  */
-  empty_minibuf = get_minibuffer (0);
+  empty_minibuf = nth_minibuffer (0);
   set_minibuffer_mode (empty_minibuf, 0);
 
   /* Display this minibuffer in the proper window.  */
@@ -969,9 +973,7 @@ static Lisp_Object
 nth_minibuffer (EMACS_INT depth)
 {
   Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list);
-  if (NILP (tail))
-    return Qnil;
-  return XCAR (tail);
+  return Fcar (tail);
 }
 
 /* Set the major mode of the minibuffer BUF, depending on DEPTH, the
@@ -1076,9 +1078,13 @@ read_minibuf_unwind (void)
   Lisp_Object future_mini_window;
   Lisp_Object saved_selected_frame = selected_frame;
   Lisp_Object window, frames;
+  Lisp_Object expired_MB = nth_minibuffer (minibuf_level);
   struct window *w;
   struct frame *f;
 
+  if (NILP (expired_MB))
+    emacs_abort ();
+
   /* Locate the expired minibuffer.  */
   FOR_EACH_FRAME (frames, exp_MB_frame)
     {
@@ -1088,7 +1094,7 @@ read_minibuf_unwind (void)
        {
          w = XWINDOW (window);
          if (EQ (w->frame, exp_MB_frame)
-             && EQ (w->contents, nth_minibuffer (minibuf_level)))
+             && EQ (w->contents, expired_MB))
            goto found;
        }
     }
@@ -1104,7 +1110,7 @@ read_minibuf_unwind (void)
      minibuffer when we reset the relevant variables.  Don't depend on
      `minibuf_window' here.  This could by now be the mini-window of any
      frame.  */
-  Fset_buffer (nth_minibuffer (minibuf_level));
+  Fset_buffer (expired_MB);
   minibuf_level--;
 
   /* Restore prompt, etc, from outer minibuffer level.  */
@@ -2272,6 +2278,8 @@ init_minibuf_once (void)
   staticpro (&Vminibuffer_list);
   staticpro (&Vcommand_loop_level_list);
   pdumper_do_now_and_after_load (init_minibuf_once_for_pdumper);
+  /* Ensure our inactive minibuffer exists.  */
+  get_minibuffer (0);
 }
 
 static void
@@ -2337,6 +2345,7 @@ syms_of_minibuf (void)
   DEFSYM (Qminibuffer_completing_file_name, "minibuffer-completing-file-name");
   DEFSYM (Qselect_frame_set_input_focus, "select-frame-set-input-focus");
   DEFSYM (Qadd_to_history, "add-to-history");
+  DEFSYM (Qpush_window_buffer_onto_prev, "push-window-buffer-onto-prev");
 
   DEFVAR_LISP ("read-expression-history", Vread_expression_history,
               doc: /* A history list for arguments that are Lisp expressions 
to evaluate.
diff --git a/src/window.c b/src/window.c
index 0a14eca..9961c54 100644
--- a/src/window.c
+++ b/src/window.c
@@ -7264,8 +7264,8 @@ restore_window_configuration (Lisp_Object configuration)
 {
   if (CONSP (configuration))
     Fset_window_configuration (XCAR (configuration),
-                              XCAR (XCDR (configuration)),
-                              XCAR (XCDR (XCDR (configuration))));
+                              Fcar_safe (XCDR (configuration)),
+                              Fcar_safe (Fcdr_safe (XCDR (configuration))));
   else
     Fset_window_configuration (configuration, Qnil, Qnil);
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]