Subject: bug#8721: isearch does not handle list values for `invisible' property

From: Dmitry Kurochkin <[email-masked]>
Date: Tue, 24 May 2011 03:46:56 +0400

Package: emacs
Version: 24.0.50
Tags: patch

Isearch allows searching in hidden text by showing invisible overlays.
But it does not work with overlays which have a list value for
`invisible' property.

Attached patch fixes the issue by using `invalid-p' function instead of
custom checks.

The second patch fixes another related issue.

Regards,
  Dmitry
isearch.el (isearch-range-invisible): use `invisible-p' instead of custom checks

Isearch allows searching in hidden text by showing invisible overlays.
The `isearch-range-invisible' function needs to check if a character
is visible and which overlays make it invisible.  Before the change,
this was done using direct checks of properties and
`buffer-invisibility-spec' variable.  Besides making code more
complex, the checks were not complete: it did not handle case when
`invisible' property is a list.  The patch replaces the custom checks
with `invisible-p' function.

=== modified file 'lisp/isearch.el'
--- lisp/isearch.el	2011-05-03 03:34:26 +0000
+++ lisp/isearch.el	2011-05-23 23:20:05 +0000
@@ -2417,66 +2417,57 @@ update the match data, and return point.
 	    (overlay-put ov 'intangible (overlay-get ov 'isearch-intangible))
 	    (overlay-put ov 'isearch-invisible nil)
 	    (overlay-put ov 'isearch-intangible nil)))))))

 (defun isearch-range-invisible (beg end)
   "Return t if all the text from BEG to END is invisible."
   (when (/= beg end)
     ;; Check that invisibility runs up to END.
     (save-excursion
       (goto-char beg)
       (let (;; can-be-opened keeps track if we can open some overlays.
 	    (can-be-opened (eq search-invisible 'open))
 	    ;; the list of overlays that could be opened
 	    (crt-overlays nil))
 	(when (and can-be-opened isearch-hide-immediately)
 	  (isearch-close-unnecessary-overlays beg end))
 	;; If the following character is currently invisible,
 	;; skip all characters with that same `invisible' property value.
 	;; Do that over and over.
-	(while (and (< (point) end)
-		    (let ((prop
-			   (get-char-property (point) 'invisible)))
-		      (if (eq buffer-invisibility-spec t)
-			  prop
-			(or (memq prop buffer-invisibility-spec)
-			    (assq prop buffer-invisibility-spec)))))
+	(while (and (< (point) end) (invisible-p (point)))
 	  (if (get-text-property (point) 'invisible)
 	      (progn
 		(goto-char (next-single-property-change (point) 'invisible
 							nil end))
 		;; if text is hidden by an `invisible' text property
 		;; we cannot open it at all.
 		(setq can-be-opened nil))
 	    (when can-be-opened
 	      (let ((overlays (overlays-at (point)))
 		    ov-list
 		    o
 		    invis-prop)
 		(while overlays
 		  (setq o (car overlays)
 			invis-prop (overlay-get o 'invisible))
-		  (if (if (eq buffer-invisibility-spec t)
-			  invis-prop
-			(or (memq invis-prop buffer-invisibility-spec)
-			    (assq invis-prop buffer-invisibility-spec)))
+		  (if (invisible-p invis-prop)
 		      (if (overlay-get o 'isearch-open-invisible)
 			  (setq ov-list (cons o ov-list))
 			;; We found one overlay that cannot be
 			;; opened, that means the whole chunk
 			;; cannot be opened.
 			(setq can-be-opened nil)))
 		  (setq overlays (cdr overlays)))
 		(if can-be-opened
 		    ;; It makes sense to append to the open
 		    ;; overlays list only if we know that this is
 		    ;; t.
 		    (setq crt-overlays (append ov-list crt-overlays)))))
 	    (goto-char (next-overlay-change (point)))))
 	;; See if invisibility reaches up thru END.
 	(if (>= (point) end)
 	    (if (and can-be-opened (consp crt-overlays))
 		(progn
 		  (setq isearch-opened-overlays
 			(append isearch-opened-overlays crt-overlays))
 		  (mapc 'isearch-open-overlay-temporary crt-overlays)

isearch.el (isearch-range-invisible): improve `invisible' text property check

Isearch does not search in text hidden with `invisible' text property.
Before the change, `isearch-range-invisible' function checked if
`invisible' text property is set.  But it did not check if the text
property really makes the text invisible.  This results in isearch not
searching a visible text in some cases.  The patch uses `invisible-p'
function to check if the `invisible' text property really makes the
text invisible.

=== modified file 'lisp/isearch.el'
--- lisp/isearch.el	2011-05-23 23:20:05 +0000
+++ lisp/isearch.el	2011-05-23 23:44:16 +0000
@@ -2418,41 +2418,41 @@ update the match data, and return point.
 	    (overlay-put ov 'isearch-invisible nil)
 	    (overlay-put ov 'isearch-intangible nil)))))))

 (defun isearch-range-invisible (beg end)
   "Return t if all the text from BEG to END is invisible."
   (when (/= beg end)
     ;; Check that invisibility runs up to END.
     (save-excursion
       (goto-char beg)
       (let (;; can-be-opened keeps track if we can open some overlays.
 	    (can-be-opened (eq search-invisible 'open))
 	    ;; the list of overlays that could be opened
 	    (crt-overlays nil))
 	(when (and can-be-opened isearch-hide-immediately)
 	  (isearch-close-unnecessary-overlays beg end))
 	;; If the following character is currently invisible,
 	;; skip all characters with that same `invisible' property value.
 	;; Do that over and over.
 	(while (and (< (point) end) (invisible-p (point)))
-	  (if (get-text-property (point) 'invisible)
+	  (if (invisible-p (get-text-property (point) 'invisible))
 	      (progn
 		(goto-char (next-single-property-change (point) 'invisible
 							nil end))
 		;; if text is hidden by an `invisible' text property
 		;; we cannot open it at all.
 		(setq can-be-opened nil))
 	    (when can-be-opened
 	      (let ((overlays (overlays-at (point)))
 		    ov-list
 		    o
 		    invis-prop)
 		(while overlays
 		  (setq o (car overlays)
 			invis-prop (overlay-get o 'invisible))
 		  (if (invisible-p invis-prop)
 		      (if (overlay-get o 'isearch-open-invisible)
 			  (setq ov-list (cons o ov-list))
 			;; We found one overlay that cannot be
 			;; opened, that means the whole chunk
 			;; cannot be opened.