Subject: bug#79200: 31.0.50; Duplicated elements for '#<marker at' in buffer-undo-list

From: Gerd Möllmann <[email-masked]>
Date: Wed, 13 Aug 2025 05:29:24 +0200

Gerd Möllmann <[email-masked]> writes:

> Gerd Möllmann <[email-masked]> writes:
>
> Please find a port to feature/igc attached, for testing if you like.
> I'll run with these changes in my Emacs and see what happens.

Forfot to compact the undo list:

>From 8a61087d2b2bb1b82b933a0e2b8e0df4d402ef94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= <[email-masked]>
Date: Wed, 13 Aug 2025 05:22:42 +0200
Subject: [PATCH] Compact undo list

* src/marker.c (Fmarker_with_id): Add buffer parameter.
* src/alloc.c (compact_undo_list): Re-implement.
(garbage_collect): Pass buffer to compact_undo_list.
* lisp/simple.el (primitive-undo): Use marker-with-id with
buffer argument.
---
 lisp/simple.el |  2 +-
 src/alloc.c    | 35 ++++++++++++++++++++++++-----------
 src/marker.c   | 11 ++++++-----
 3 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/lisp/simple.el b/lisp/simple.el
index 42541a952fe..2547b5b5820 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3731,7 +3731,7 @@ primitive-undo
                (let* ((entry (cdr-safe (car list)))
                       (id (car entry))
                       (offset (cdr entry))
-                      (marker (marker-with-id id)))
+                      (marker (marker-with-id id (current-buffer))))
                  (pop list)
                  (when (and marker
                             (eq (marker-buffer marker) (current-buffer))
diff --git a/src/alloc.c b/src/alloc.c
index df47cd2fa9f..fb239fbc04e 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5839,25 +5839,38 @@ #define compact_font_caches() (void)(0)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
-/* Remove (MARKER . DATA) entries with unmarked MARKER
+/* Remove marker adjustment entries with unmarked MARKER
    from buffer undo LIST and return changed list.  */
 
 static Lisp_Object
-compact_undo_list (Lisp_Object list)
+compact_undo_list (Lisp_Object buffer)
 {
-#ifndef HAVE_MPS
+  struct buffer *b = XBUFFER (buffer);
+  Lisp_Object list = BVAR (b, undo_list);
   Lisp_Object tail, *prev = &list;
 
   for (tail = list; CONSP (tail); tail = XCDR (tail))
     {
-      if (CONSP (XCAR (tail))
-	  && MARKERP (XCAR (XCAR (tail)))
-	  && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
-	*prev = XCDR (tail);
-      else
-	prev = xcdr_addr (tail);
-    }
+      Lisp_Object entry = XCAR (tail);
+      if (CONSP (entry) && EQ (Qadjust_marker, XCAR (entry)))
+	{
+	  Lisp_Object id = XCAR (XCDR (entry));
+	  Lisp_Object marker = Fmarker_with_id (id, buffer);
+#ifdef HAVE_MPS
+	  if (NILP (marker))
+	    *prev = XCDR (tail);
+	  else
+	    prev = xcdr_addr (tail);
+#else
+	  if (MARKERP (marker)
+	      && !vectorlike_marked_p (&XMARKER (marker)->header))
+	    *prev = XCDR (tail);
+	  else
+	    prev = xcdr_addr (tail);
 #endif
+	}
+    }
+
   return list;
 }
 
@@ -6209,7 +6222,7 @@ garbage_collect (void)
     {
       struct buffer *nextb = XBUFFER (buffer);
       if (!EQ (BVAR (nextb, undo_list), Qt))
-	bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
+	bset_undo_list (nextb, compact_undo_list (buffer));
 #ifndef HAVE_MPS
       /* Now that we have stripped the elements that need not be
 	 in the undo_list any more, we can finally mark the list.  */
diff --git a/src/marker.c b/src/marker.c
index fd88743b0b3..15b26b18ad3 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -448,14 +448,15 @@ DEFUN ("marker-id", Fmarker_id, Smarker_id, 1, 1, 0,
   return make_fixnum (XMARKER (marker)->id);
 }
 
-DEFUN ("marker-with-id", Fmarker_with_id, Smarker_with_id, 1, 1, 0,
-       doc: /* Return the marker in the current buffer with id ID.
+DEFUN ("marker-with-id", Fmarker_with_id, Smarker_with_id, 2, 2, 0,
+       doc: /* Return the marker with id ID in BUFFER.
 Value is nil if no such marker exists.  */)
-  (Lisp_Object id)
+  (Lisp_Object id, Lisp_Object buffer)
 {
   CHECK_FIXNUM (id);
-
-  DO_MARKERS (current_buffer, m)
+  CHECK_BUFFER (buffer);
+  struct buffer *b = XBUFFER (buffer);
+  DO_MARKERS (b, m)
     {
       if (m->id == XFIXNUM (id))
 	return make_lisp_ptr (m, Lisp_Vectorlike);
-- 
2.50.1