Subject: Re: bug#75646: 31.0.50; Deleting editable-field widget leaves some overlays behind

From: Mauro Aranda <[email-masked]>
Date: Sat, 25 Jan 2025 07:10:07 -0300

Eli Zaretskii <[email-masked]> writes:

 >> Date: Sat, 18 Jan 2025 08:31:39 -0300
 >> From: Mauro Aranda <[email-masked]>
 >>
 >> I attach a patch with a fix and a test.
 >
 > Thanks, but this doesn't apply on the master branch (it looks like you
 > have local changes in wid-edit-tests.el?).  Could you please resubmit
 > a patch relative to the current master branch?

Oops, sorry.  Sending the patch again.
From e8ee7873b67e879a0a9fca4c1edc1dcc806a9549 Mon Sep 17 00:00:00 2001
From: Mauro Aranda <[email-masked]>
Date: Sat, 18 Jan 2025 08:25:40 -0300
Subject: [PATCH] Delete all overlays that belong to an editable-field

* lisp/wid-edit.el (widget-specify-field): Store the end overlay
that we sometimes create for an editable-field widget.
(widget-field-value-delete): Make sure we delete all overlays
that belong to the widget.  (Bug#75646)

* test/lisp/wid-edit-tests.el (widget-test-delete-field-overlays): New
test.
---
 lisp/wid-edit.el            | 10 +++++++++-
 test/lisp/wid-edit-tests.el | 16 ++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index ca4e1e184cb..7260f60196a 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -416,6 +416,9 @@ widget-specify-field
       ;; character (so we don't do this for the character widget),
       ;; or if the size of the editable field isn't specified.
       (let ((overlay (make-overlay (1- to) to nil t nil)))
+        ;; Save it so that we can easily delete it in
+        ;; `widget-field-value-delete'.  (Bug#75646)
+        (widget-put widget :field-end-overlay overlay)
 	(overlay-put overlay 'field 'boundary)
         ;; We need the real field for tabbing.
 	(overlay-put overlay 'real-field widget)
@@ -2223,11 +2226,16 @@ widget-field-value-create
     (set-marker-insertion-type (car overlay) t)))
 
 (defun widget-field-value-delete (widget)
-  "Remove the widget from the list of active editing fields."
+  "Remove the field WIDGET from the list of active editing fields.
+
+Delete its overlays as well."
   (setq widget-field-list (delq widget widget-field-list))
   (setq widget-field-new (delq widget widget-field-new))
   ;; These are nil if the :format string doesn't contain `%v'.
   (let ((overlay (widget-get widget :field-overlay)))
+    (when (overlayp overlay)
+      (delete-overlay overlay)))
+  (let ((overlay (widget-get widget :field-end-overlay)))
     (when (overlayp overlay)
       (delete-overlay overlay))))
 
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
index 6f3c87a809f..c18e6d14c4c 100644
--- a/test/lisp/wid-edit-tests.el
+++ b/test/lisp/wid-edit-tests.el
@@ -414,4 +414,20 @@ widget-test-restricted-sexp-empty-val
       (delete-char 1)
       (should (string= (widget-value w) "")))))
 
+(ert-deftest widget-test-delete-field-overlays ()
+  "Test that we delete all the field's overlays when deleting it."
+  (with-temp-buffer
+    (let ((field (widget-create 'editable-field
+                                :format "%t: %v "
+                                :tag "Delete me"))
+          field-overlay field-end-overlay)
+      (widget-insert "\n")
+      (widget-setup)
+      (widget-backward 1)
+      (setq field-overlay (widget-get field :field-overlay))
+      (setq field-end-overlay (car (overlays-at (point))))
+      (widget-delete field)
+      (should-not (overlay-buffer field-overlay))
+      (should-not (overlay-buffer field-end-overlay)))))
+
 ;;; wid-edit-tests.el ends here
-- 
2.34.1