Some fixes to follow coding conventions in files maintained by FSF.
[bpt/emacs.git] / lisp / isearch.el
index 2682e9f..672f559 100644 (file)
@@ -1,6 +1,7 @@
-;;; isearch.el --- incremental search minor mode.
+;;; isearch.el --- incremental search minor mode
 
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 2001
+;;   Free Software Foundation, Inc.
 
 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
 ;; Maintainer: FSF
@@ -222,124 +223,124 @@ Default value, nil, means edit the string instead."
 
 ;;; Define isearch-mode keymap.
 
-(defvar isearch-mode-map nil
-  "Keymap for isearch-mode.")
-
-(or isearch-mode-map
-    (let* ((i 0)
-          (map (make-keymap)))
-      (or (vectorp (nth 1 map))
-         (char-table-p (nth 1 map))
-         (error "The initialization of isearch-mode-map must be updated"))
-      ;; Make all multibyte characters search for themselves.
-      (let ((l (generic-character-list))
-           (table (nth 1 map)))
-       (while l
-         (set-char-table-default table (car l) 'isearch-printing-char)
-         (setq l (cdr l))))
-      ;; Make function keys, etc, exit the search.
-      (define-key map [t] 'isearch-other-control-char)
-      ;; Control chars, by default, end isearch mode transparently.
-      ;; We need these explicit definitions because, in a dense keymap, 
-      ;; the binding for t does not affect characters.
-      ;; We use a dense keymap to save space.
-      (while (< i ?\ )
-       (define-key map (make-string 1 i) 'isearch-other-control-char)
-       (setq i (1+ i)))
-
-      ;; Single-byte printing chars extend the search string by default.
-      (setq i ?\ )
-      (while (< i 256)
-       (define-key map (vector i) 'isearch-printing-char)
-       (setq i (1+ i)))
-
-      ;; To handle local bindings with meta char prefix keys, define
-      ;; another full keymap.  This must be done for any other prefix
-      ;; keys as well, one full keymap per char of the prefix key.  It
-      ;; would be simpler to disable the global keymap, and/or have a
-      ;; default local key binding for any key not otherwise bound.
-      (let ((meta-map (make-sparse-keymap)))
-       (define-key map (char-to-string meta-prefix-char) meta-map)
-       (define-key map [escape] meta-map))
-      (define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
-
-      ;; Several non-printing chars change the searching behavior.
-      (define-key map "\C-s" 'isearch-repeat-forward)
-      (define-key map "\C-r" 'isearch-repeat-backward)
-      (define-key map "\177" 'isearch-delete-char)
-      (define-key map "\C-g" 'isearch-abort)
-      ;; This assumes \e is the meta-prefix-char.
-      (or (= ?\e meta-prefix-char)
-         (error "Inconsistency in isearch.el"))
-      (define-key map "\e\e\e" 'isearch-cancel)
-      (define-key map  [escape escape escape] 'isearch-cancel)
+(defvar isearch-mode-map
+  (let* ((i 0)
+        (map (make-keymap)))
+    (or (vectorp (nth 1 map))
+       (char-table-p (nth 1 map))
+       (error "The initialization of isearch-mode-map must be updated"))
+    ;; Make all multibyte characters search for themselves.
+    (let ((l (generic-character-list))
+         (table (nth 1 map)))
+      (while l
+       (set-char-table-default table (car l) 'isearch-printing-char)
+       (setq l (cdr l))))
+    ;; Make function keys, etc, exit the search.
+    (define-key map [t] 'isearch-other-control-char)
+    ;; Control chars, by default, end isearch mode transparently.
+    ;; We need these explicit definitions because, in a dense keymap, 
+    ;; the binding for t does not affect characters.
+    ;; We use a dense keymap to save space.
+    (while (< i ?\ )
+      (define-key map (make-string 1 i) 'isearch-other-control-char)
+      (setq i (1+ i)))
+
+    ;; Single-byte printing chars extend the search string by default.
+    (setq i ?\ )
+    (while (< i 256)
+      (define-key map (vector i) 'isearch-printing-char)
+      (setq i (1+ i)))
+
+    ;; To handle local bindings with meta char prefix keys, define
+    ;; another full keymap.  This must be done for any other prefix
+    ;; keys as well, one full keymap per char of the prefix key.  It
+    ;; would be simpler to disable the global keymap, and/or have a
+    ;; default local key binding for any key not otherwise bound.
+    (let ((meta-map (make-sparse-keymap)))
+      (define-key map (char-to-string meta-prefix-char) meta-map)
+      (define-key map [escape] meta-map))
+    (define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
+
+    ;; Several non-printing chars change the searching behavior.
+    (define-key map "\C-s" 'isearch-repeat-forward)
+    (define-key map "\C-r" 'isearch-repeat-backward)
+    ;; Define M-C-s and M-C-r like C-s and C-r so that the same key
+    ;; combinations can be used to repeat regexp isearches that can
+    ;; be used to start these searches.
+    (define-key map "\M-\C-s" 'isearch-repeat-forward)
+    (define-key map "\M-\C-r" 'isearch-repeat-backward)
+    (define-key map "\177" 'isearch-delete-char)
+    (define-key map "\C-g" 'isearch-abort)
+
+    ;; This assumes \e is the meta-prefix-char.
+    (or (= ?\e meta-prefix-char)
+       (error "Inconsistency in isearch.el"))
+    (define-key map "\e\e\e" 'isearch-cancel)
+    (define-key map  [escape escape escape] 'isearch-cancel)
     
-      (define-key map "\C-q" 'isearch-quote-char)
+    (define-key map "\C-q" 'isearch-quote-char)
 
-      (define-key map "\r" 'isearch-exit)
-      (define-key map "\C-j" 'isearch-printing-char)
-      (define-key map "\t" 'isearch-printing-char)
-      (define-key map " " 'isearch-whitespace-chars)
-      (define-key map [?\S-\ ] 'isearch-whitespace-chars)
+    (define-key map "\r" 'isearch-exit)
+    (define-key map "\C-j" 'isearch-printing-char)
+    (define-key map "\t" 'isearch-printing-char)
+    (define-key map " " 'isearch-whitespace-chars)
+    (define-key map [?\S-\ ] 'isearch-whitespace-chars)
     
-      (define-key map "\C-w" 'isearch-yank-word)
-      (define-key map "\C-y" 'isearch-yank-line)
+    (define-key map "\C-w" 'isearch-yank-word)
+    (define-key map "\C-y" 'isearch-yank-line)
 
-      ;; Define keys for regexp chars * ? |.
-      ;; Nothing special for + because it matches at least once.
-      (define-key map "*" 'isearch-*-char)
-      (define-key map "?" 'isearch-*-char)
-      (define-key map "|" 'isearch-|-char)
+    ;; Define keys for regexp chars * ? |.
+    ;; Nothing special for + because it matches at least once.
+    (define-key map "*" 'isearch-*-char)
+    (define-key map "?" 'isearch-*-char)
+    (define-key map "|" 'isearch-|-char)
 
 ;;; Turned off because I find I expect to get the global definition--rms.
 ;;;      ;; Instead bind C-h to special help command for isearch-mode.
 ;;;      (define-key map "\C-h" 'isearch-mode-help)
 
-      (define-key map "\M-n" 'isearch-ring-advance)
-      (define-key map "\M-p" 'isearch-ring-retreat)
-      (define-key map "\M-y" 'isearch-yank-kill)
-
-      (define-key map "\M-\t" 'isearch-complete)
-
-      ;; Pass frame events transparently so they won't exit the search.
-      ;; In particular, if we have more than one display open, then a
-      ;; switch-frame might be generated by someone typing at another keyboard.
-      (define-key map [switch-frame] nil)
-      (define-key map [delete-frame] nil)
-      (define-key map [iconify-frame] nil)
-      (define-key map [make-frame-visible] nil)
-      ;; For searching multilingual text.
-      (define-key map "\C-\\" 'isearch-toggle-input-method)
-      (define-key map "\C-^" 'isearch-toggle-specified-input-method)
-
-      ;; People expect to be able to paste with the mouse.
-      (define-key map [mouse-2] #'isearch-mouse-yank)
-      (define-key map [down-mouse-2] nil)
-
-      (setq isearch-mode-map map)
-      ))
-
-;; Some bindings you may want to put in your isearch-mode-hook.
-;; Suggest some alternates...
-;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-case-fold)
-;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
-;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
-
-
-(defvar minibuffer-local-isearch-map nil
+    (define-key map "\M-n" 'isearch-ring-advance)
+    (define-key map "\M-p" 'isearch-ring-retreat)
+    (define-key map "\M-y" 'isearch-yank-kill)
+
+    (define-key map "\M-\t" 'isearch-complete)
+
+    ;; Pass frame events transparently so they won't exit the search.
+    ;; In particular, if we have more than one display open, then a
+    ;; switch-frame might be generated by someone typing at another keyboard.
+    (define-key map [switch-frame] nil)
+    (define-key map [delete-frame] nil)
+    (define-key map [iconify-frame] nil)
+    (define-key map [make-frame-visible] nil)
+    ;; For searching multilingual text.
+    (define-key map "\C-\\" 'isearch-toggle-input-method)
+    (define-key map "\C-^" 'isearch-toggle-specified-input-method)
+
+    ;; People expect to be able to paste with the mouse.
+    (define-key map [mouse-2] #'isearch-mouse-yank)
+    (define-key map [down-mouse-2] nil)
+
+    ;; Some bindings you may want to put in your isearch-mode-hook.
+    ;; Suggest some alternates...
+    (define-key map "\M-c" 'isearch-toggle-case-fold)
+    (define-key map "\M-r" 'isearch-toggle-regexp)
+    (define-key map "\M-e" 'isearch-edit-string)
+
+    map)
+  "Keymap for `isearch-mode'.")
+
+(defvar minibuffer-local-isearch-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map minibuffer-local-map)
+    (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
+    (define-key map "\M-n" 'isearch-ring-advance-edit)
+    (define-key map "\M-p" 'isearch-ring-retreat-edit)
+    (define-key map "\M-\t" 'isearch-complete-edit)
+    (define-key map "\C-s" 'isearch-forward-exit-minibuffer)
+    (define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
+    map)
   "Keymap for editing isearch strings in the minibuffer.")
 
-(or minibuffer-local-isearch-map
-    (let ((map (copy-keymap minibuffer-local-map)))
-      (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
-      (define-key map "\M-n" 'isearch-ring-advance-edit)
-      (define-key map "\M-p" 'isearch-ring-retreat-edit)
-      (define-key map "\M-\t" 'isearch-complete-edit)
-      (define-key map "\C-s" 'isearch-forward-exit-minibuffer)
-      (define-key map "\C-r" 'isearch-reverse-exit-minibuffer)
-      (setq minibuffer-local-isearch-map map)
-      ))
-
 ;; Internal variables declared globally for byte-compiler.
 ;; These are all set with setq while isearching
 ;; and bound locally while editing the search string.
@@ -365,6 +366,9 @@ Default value, nil, means edit the string instead."
 ;   case in the search string is ignored.
 (defvar isearch-case-fold-search nil)
 
+;; Used to save default value while isearch is active
+(defvar isearch-original-minibuffer-message-timeout nil)
+
 (defvar isearch-adjusted nil)
 (defvar isearch-slow-terminal-mode nil)
 ;;; If t, using a small window.
@@ -443,12 +447,25 @@ Type \\[isearch-quote-char] to quote control character to search for it.
 \\[isearch-abort] when search is successful aborts and moves point to\
  starting point.
 
+Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity.
+Type \\[isearch-toggle-regexp] to toggle regular-expression mode.
+Type \\[isearch-edit-string] to edit the search string in the minibuffer.
+
 Also supported is a search ring of the previous 16 search strings.
 Type \\[isearch-ring-advance] to search for the next item in the search ring.
 Type \\[isearch-ring-retreat] to search for the previous item in the search\
  ring.
 Type \\[isearch-complete] to complete the search string using the search ring.
 
+If an input method is turned on in the current buffer, that input
+method is also active while you are typing a characters to search.  To
+toggle the input method, type \\[isearch-toggle-input-method].  It
+also toggles the input method in the current buffer.
+
+To use a different input method for searching, type
+\\[isearch-toggle-specified-input-method], and specify an input method
+you want to use.
+
 The above keys, bound in `isearch-mode-map', are often controlled by 
  options; do M-x apropos on search-.* to find them.
 Other control and meta characters terminate the search
@@ -536,11 +553,16 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
        isearch-opened-overlays nil
        isearch-input-method-function input-method-function
        isearch-input-method-local-p (local-variable-p 'input-method-function)
-       regexp-search-ring-yank-pointer nil)
+       regexp-search-ring-yank-pointer nil
+
+       ;; Save the original value of `minibuffer-message-timeout', and
+       ;; set it to nil so that isearch's messages don't get timed out.
+       isearch-original-minibuffer-message-timeout minibuffer-message-timeout
+       minibuffer-message-timeout nil)
 
   ;; We must bypass input method while reading key.  When a user type
   ;; printable character, appropriate input method is turned on in
-  ;; minibuffer to read multibyte charactes.
+  ;; minibuffer to read multibyte characters.
   (or isearch-input-method-local-p
       (make-local-variable 'input-method-function))
   (setq input-method-function nil)
@@ -567,6 +589,7 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   (run-hooks 'isearch-mode-hook)
 
   (add-hook 'mouse-leave-buffer-hook 'isearch-done)
+  (add-hook 'kbd-macro-termination-hook 'isearch-done)
 
   ;; isearch-mode can be made modal (in the sense of not returning to 
   ;; the calling function until searching is completed) by entering 
@@ -583,46 +606,60 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   ;; Called after each command to update the display.  
   (if (null unread-command-events)
       (progn
-       (if (not (input-pending-p))
-           (isearch-message))
-       (if (and isearch-slow-terminal-mode
-                (not (or isearch-small-window 
-                         (pos-visible-in-window-p))))
-           (let ((found-point (point)))
-             (setq isearch-small-window t)
-             (move-to-window-line 0)
-             (let ((window-min-height 1))
-               (split-window nil (if (< search-slow-window-lines 0)
-                                     (1+ (- search-slow-window-lines))
-                                   (- (window-height)
-                                      (1+ search-slow-window-lines)))))
-             (if (< search-slow-window-lines 0)
-                 (progn (vertical-motion (- 1 search-slow-window-lines))
-                        (set-window-start (next-window) (point))
-                        (set-window-hscroll (next-window)
-                                            (window-hscroll))
-                        (set-window-hscroll (selected-window) 0))
-               (other-window 1))
-             (goto-char found-point)))
-       (if isearch-other-end
-           (if (< isearch-other-end (point)) ; isearch-forward?
-               (isearch-highlight isearch-other-end (point))
-             (isearch-highlight (point) isearch-other-end))
-         (isearch-dehighlight nil))
-       ))
+        (if (not (input-pending-p))
+            (isearch-message))
+        (if (and isearch-slow-terminal-mode
+                 (not (or isearch-small-window 
+                          (pos-visible-in-window-p))))
+            (let ((found-point (point)))
+              (setq isearch-small-window t)
+              (move-to-window-line 0)
+              (let ((window-min-height 1))
+                (split-window nil (if (< search-slow-window-lines 0)
+                                      (1+ (- search-slow-window-lines))
+                                    (- (window-height)
+                                       (1+ search-slow-window-lines)))))
+              (if (< search-slow-window-lines 0)
+                  (progn (vertical-motion (- 1 search-slow-window-lines))
+                         (set-window-start (next-window) (point))
+                         (set-window-hscroll (next-window)
+                                             (window-hscroll))
+                         (set-window-hscroll (selected-window) 0))
+                (other-window 1))
+              (goto-char found-point)))
+        (if isearch-other-end
+            (if (< isearch-other-end (point)) ; isearch-forward?
+                (isearch-highlight isearch-other-end (point))
+              (isearch-highlight (point) isearch-other-end))
+          (isearch-dehighlight nil))
+        ))
   (setq ;; quit-flag nil  not for isearch-mode
    isearch-adjusted nil
    isearch-yank-flag nil)
-  (isearch-lazy-highlight-new-loop))
+  (isearch-lazy-highlight-new-loop)
+  ;; We must prevent the point moving to the end of composition when a
+  ;; part of the composition has just been searched.
+  (setq disable-point-adjustment t))
 
 (defun isearch-done (&optional nopush edit)
+  (let ((command `(isearch-resume ,isearch-string ,isearch-regexp
+                                 ,isearch-word ,isearch-forward
+                                 ,isearch-message
+                                 ,isearch-case-fold-search)))
+    (unless (equal (car command-history) command)
+      (setq command-history (cons command command-history))))
+
   (remove-hook 'mouse-leave-buffer-hook 'isearch-done)
+  (remove-hook 'kbd-macro-termination-hook 'isearch-done)
+  (setq isearch-lazy-highlight-start nil)
+
   ;; Called by all commands that terminate isearch-mode.
   ;; If NOPUSH is non-nil, we don't push the string on the search ring.
   (setq overriding-terminal-local-map nil)
   ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
+  (setq minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
   (isearch-dehighlight t)
-  (isearch-lazy-highlight-cleanup)
+  (isearch-lazy-highlight-cleanup isearch-lazy-highlight-cleanup)
   (let ((found-start (window-start (selected-window)))
        (found-point (point)))
     (if isearch-window-configuration
@@ -767,6 +804,12 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
              (isearch-recursive-edit isearch-recursive-edit)
              ;; Save current configuration so we can restore it here.
              (isearch-window-configuration (current-window-configuration))
+
+             ;; Temporarily restore `minibuffer-message-timeout'.
+             (minibuffer-message-timeout
+              isearch-original-minibuffer-message-timeout)
+             (isearch-original-minibuffer-message-timeout
+              isearch-original-minibuffer-message-timeout)
              )
 
          ;; Actually terminate isearching until editing is done.
@@ -909,7 +952,7 @@ Use `isearch-exit' to quit without signaling."
                           isearch-string ""))
        ;; If already have what to search for, repeat it.
        (or isearch-success
-           (progn 
+           (progn
              (goto-char (if isearch-forward (point-min) (point-max)))
              (setq isearch-wrapped t))))
     ;; C-s in reverse or C-r in forward, change direction.
@@ -1021,7 +1064,8 @@ Otherwise invoke `mouse-yank-at-click'."
    (save-excursion
      (and (not isearch-forward) isearch-other-end
          (goto-char isearch-other-end))
-     (buffer-substring (point) (progn (forward-word 1) (point))))))
+     (buffer-substring-no-properties
+      (point) (progn (forward-word 1) (point))))))
 
 (defun isearch-yank-line ()
   "Pull rest of line from buffer into search string."
@@ -1030,7 +1074,7 @@ Otherwise invoke `mouse-yank-at-click'."
    (save-excursion
      (and (not isearch-forward) isearch-other-end
          (goto-char isearch-other-end))
-     (buffer-substring (point) (line-end-position)))))
+     (buffer-substring-no-properties (point) (line-end-position)))))
 
 
 (defun isearch-search-and-update ()
@@ -1141,11 +1185,25 @@ and the meta character is unread so that it applies to editing the string."
           ;; so that the translated key takes effect within isearch.
           (cancel-kbd-macro-events)
           (if (lookup-key global-map key)
-              (progn 
+              (progn
                 (isearch-done)
                 (apply 'isearch-unread keylist))
-            (apply 'isearch-unread
-                   (listify-key-sequence (lookup-key function-key-map key)))))
+            (setq keylist
+                  (listify-key-sequence (lookup-key function-key-map key)))
+            (while keylist
+              (setq key (car keylist))
+              ;; If KEY is a printing char, we handle it here
+              ;; directly to avoid the input method and keyboard
+              ;; coding system translating it.
+              (if (and (integerp key)
+                       (>= key ?\ ) (/= key 127) (< key 256))
+                  (progn
+                    (isearch-process-search-char key)
+                    (setq keylist (cdr keylist)))
+                ;; As the remaining keys in KEYLIST can't be handled
+                ;; here, we must reread them.
+                (apply 'isearch-unread keylist)
+                (setq keylist nil)))))
          (
           ;; Handle an undefined shifted control character
           ;; by downshifting it if that makes it defined.
@@ -1230,7 +1288,9 @@ Obsolete."
     (if (and enable-multibyte-characters
             (>= char ?\200)
             (<= char ?\377))
-       (isearch-process-search-char (unibyte-char-to-multibyte char))
+       (if (keyboard-coding-system)
+           (isearch-process-search-multibyte-characters char)
+         (isearch-process-search-char (unibyte-char-to-multibyte char)))
       (if current-input-method
          (isearch-process-search-multibyte-characters char)
        (isearch-process-search-char char)))))
@@ -1418,8 +1478,7 @@ If there is no completion possible, say so and continue searching."
 
 (defun isearch-pop-state ()
   (setq isearch-cmds (cdr isearch-cmds))
-  (isearch-top-state)
-  )
+  (isearch-top-state))
 
 (defun isearch-push-state ()
   (setq isearch-cmds 
@@ -1473,8 +1532,7 @@ If there is no completion possible, say so and continue searching."
                       (concat " [" current-input-method-title "]: ")
                     ": ")
                   )))
-    (aset m 0 (upcase (aref m 0)))
-    m))
+    (concat (upcase (substring m 0 1)) (substring m 1))))
 
 
 (defun isearch-message-suffix (&optional c-q-hack ellipsis)
@@ -1538,7 +1596,7 @@ If there is no completion possible, say so and continue searching."
         (setq isearch-invalid-regexp "incomplete input")))
     (error
      ;; stack overflow in regexp search.
-     (setq isearch-invalid-regexp (car (cdr lossage)))))
+     (setq isearch-invalid-regexp (format "%s" lossage))))
 
   (if isearch-success
       nil
@@ -1559,7 +1617,7 @@ If there is no completion possible, say so and continue searching."
     ;; properties, and then set them to nil. This way the text hidden
     ;; by this overlay becomes visible.
 
-    ;; Do we realy need to set the `intangible' property to t? Can we
+    ;; Do we really need to set the `intangible' property to t? Can we
     ;; have the point inside an overlay with an `intangible' property?
     ;; In 19.34 this does not exist so I cannot test it.
     (overlay-put ov 'isearch-invisible (overlay-get ov 'invisible))
@@ -1594,9 +1652,7 @@ If there is no completion possible, say so and continue searching."
 ;;; opened overlays, except the ones that contain the latest match.
 (defun isearch-clean-overlays ()
   (when isearch-opened-overlays
-    ;; Use a cycle instead of a mapcar here?
-    (mapcar 
-     (function isearch-open-necessary-overlays) isearch-opened-overlays)
+    (mapc 'isearch-open-necessary-overlays isearch-opened-overlays)
     (setq isearch-opened-overlays nil)))
 
 ;;; Verify if the current match is outside of each element of
@@ -1618,7 +1674,7 @@ If there is no completion possible, say so and continue searching."
       ;; this function, not by us tweaking the overlay properties.
       (setq fct-temp (overlay-get ov 'isearch-open-invisible-temporary))
       (if inside-overlay
-       (setq isearch-opened-overlays (cons ov isearch-opened-overlays))
+         (setq isearch-opened-overlays (cons ov isearch-opened-overlays))
        (if fct-temp
            (funcall fct-temp ov t)
          (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible))
@@ -1687,9 +1743,7 @@ If there is no completion possible, say so and continue searching."
                 (progn
                   (setq isearch-opened-overlays
                         (append isearch-opened-overlays crt-overlays))
-                  ;; maybe use a cycle instead of mapcar?
-                  (mapcar (function isearch-open-overlay-temporary)
-                          crt-overlays)
+                  (mapc 'isearch-open-overlay-temporary crt-overlays)
                   nil)
               t))))))
 
@@ -1699,17 +1753,22 @@ If there is no completion possible, say so and continue searching."
 (defvar isearch-overlay nil)
 
 (defun isearch-highlight (beg end)
-  (if (or (null search-highlight) (null window-system))
-      nil
-    (or isearch-overlay (setq isearch-overlay (make-overlay beg end)))
-    (move-overlay isearch-overlay beg end (current-buffer))
-    (overlay-put isearch-overlay 'face
-                (if (internal-find-face 'isearch nil)
-                    'isearch 'region))))
+  (unless (null search-highlight)
+    (cond (isearch-overlay
+          ;; Overlay already exists, just move it.
+          (move-overlay isearch-overlay beg end (current-buffer)))
+
+         (t
+          ;; Overlay doesn't exist, create it.
+          (setq isearch-overlay (make-overlay beg end))
+          (overlay-put isearch-overlay 'face isearch)
+           (overlay-put isearch-overlay 'priority 1) ;higher than lazy overlays
+           ))))
 
 (defun isearch-dehighlight (totally)
-  (if isearch-overlay
-      (delete-overlay isearch-overlay)))
+  (when isearch-overlay
+    (delete-overlay isearch-overlay)))
+
 
 ;;; General utilities
 
@@ -1731,14 +1790,15 @@ since they have special meaning in a regexp."
 ;; Portability functions to support various Emacs versions.
 
 (defun isearch-text-char-description (c)
-  (if (and (integerp c) (or (< c ?\ ) (= c ?\^?)))
-      (text-char-description c)
-    (char-to-string c)))
+  (cond
+   ((< c ?\ ) (format "^%c" (+ c 64)))
+   ((= c ?\^?) "^?")
+   (t (char-to-string c))))
 
 ;; General function to unread characters or events.
 ;; Also insert them in a keyboard macro being defined.
 (defun isearch-unread (&rest char-or-events)
-  (mapcar 'store-kbd-macro-event char-or-events)
+  (mapc 'store-kbd-macro-event char-or-events)
   (setq unread-command-events
        (append char-or-events unread-command-events)))
 
@@ -1748,23 +1808,19 @@ since they have special meaning in a regexp."
 
 ;;; When active, *every* match for the current search string is
 ;;; highlighted: the current one using the normal isearch match color
-;;; and all the others using the unobtrusive `secondary-selection'
-;;; color.  The extra highlighting makes it easier to anticipate where
-;;; the cursor will land each time you press C-s or C-r to repeat a
-;;; pending search.  Highlighting of these additional matches happens
-;;; in a deferred fashion using "idle timers," so the cycles needed do
-;;; not rob isearch of its usual snappy response.
+;;; and all the others using `isearch-lazy-highlight-face'.  The extra
+;;; highlighting makes it easier to anticipate where the cursor will
+;;; land each time you press C-s or C-r to repeat a pending search.
+;;; Highlighting of these additional matches happens in a deferred
+;;; fashion using "idle timers," so the cycles needed do not rob
+;;; isearch of its usual snappy response.
 
 ;;; IMPLEMENTATION NOTE: This depends on some isearch internals.
 ;;; Specifically:
 ;;;  - `isearch-update' is expected to be called (at least) every time
-;;;    the search string changes;
+;;;    the search string or window-start changes;
 ;;;  - `isearch-string' is expected to contain the current search
 ;;;    string as entered by the user;
-;;;  - `isearch-overlay' is expected to contain the overlay used for
-;;;    primary isearch match-highlighting;
-;;;  - `isearch-opoint' is expected to contain the location where the
-;;;    current search began;
 ;;;  - the type of the current search is expected to be given by
 ;;;    `isearch-word' and `isearch-regexp';
 ;;;  - the direction of the current search is expected to be given by
@@ -1777,6 +1833,7 @@ since they have special meaning in a regexp."
 (defgroup isearch-lazy-highlight nil
   "Lazy highlighting feature for incremental search."
   :prefix "isearch-lazy-highlight-"
+  :version "21.1"
   :group 'isearch)
 
 (defcustom isearch-lazy-highlight t
@@ -1799,22 +1856,59 @@ If this is nil, extra highlighting can be \"manually\" removed with
   :type 'number
   :group 'isearch-lazy-highlight)
 
-(defcustom isearch-lazy-highlight-interval 0.0625
+(defcustom isearch-lazy-highlight-interval 0 ; 0.0625
   "*Seconds between lazily highlighting successive matches."
   :type 'number
   :group 'isearch-lazy-highlight)
 
-(defcustom isearch-lazy-highlight-face 'secondary-selection
-  "*Face to use for lazily highlighting all matches."
-  :type 'face
+(defcustom isearch-lazy-highlight-max-at-a-time 20
+  "*Maximum matches to highlight at a time (for `isearch-lazy-highlight').
+Larger values may reduce isearch's responsiveness to user input;
+smaller values make matches highlight slowly.
+A value of nil means highlight all matches."
+  :type '(choice (const :tag "All" nil)
+                (integer :tag "Some"))
   :group 'isearch-lazy-highlight)
 
+(defgroup isearch-faces nil
+  "Lazy highlighting feature for incremental search."
+  :version "21.1"
+  :group 'isearch)
+
+(defface isearch
+  '((((type tty pc) (class color))
+     (:background "magenta4" :foreground "cyan1"))
+    (((class color) (background light))
+     (:background "magenta4" :foreground "lightskyblue1"))
+    (((class color) (background dark))
+     (:background "palevioletred2" :foreground "brown4"))
+    (t (:inverse-video t)))
+  "Face for highlighting Isearch matches."
+  :group 'isearch-faces)
+(defvar isearch 'isearch)
+
+(defface isearch-lazy-highlight-face
+  '((((type tty pc) (class color))
+     (:background "turquoise3"))
+    (((class color) (background light))
+     (:background "paleturquoise"))
+    (((class color) (background dark))
+     (:background "paleturquoise4"))
+    (t (:underline t)))
+  "Face for lazy highlighting of Isearch matches other than the current one."
+  :group 'isearch-faces)
+(defvar isearch-lazy-highlight-face 'isearch-lazy-highlight-face)
+
 (defvar isearch-lazy-highlight-overlays nil)
 (defvar isearch-lazy-highlight-wrapped nil)
 (defvar isearch-lazy-highlight-start nil)
 (defvar isearch-lazy-highlight-end nil)
 (defvar isearch-lazy-highlight-timer nil)
 (defvar isearch-lazy-highlight-last-string nil)
+(defvar isearch-lazy-highlight-window nil)
+(defvar isearch-lazy-highlight-window-start nil)
+(defvar isearch-lazy-highlight-case-fold-search nil)
+(defvar isearch-lazy-highlight-regexp nil)
 
 (defun isearch-lazy-highlight-cleanup (&optional force)
   "Stop lazy highlighting and remove extra highlighting from current buffer.
@@ -1823,95 +1917,128 @@ is nil.  This function is called when exiting an incremental search if
 `isearch-lazy-highlight-cleanup' is non-nil."
   (interactive '(t))
   (if (or force isearch-lazy-highlight-cleanup)
-      (isearch-lazy-highlight-remove-overlays))
-  (if isearch-lazy-highlight-timer
-      (progn
-        (cancel-timer isearch-lazy-highlight-timer)
-        (setq isearch-lazy-highlight-timer nil))))
-
-(defun isearch-lazy-highlight-remove-overlays ()
-  "Remove lazy highlight overlays from the current buffer."
-  (while isearch-lazy-highlight-overlays
-    (delete-overlay (car isearch-lazy-highlight-overlays))
-    (setq isearch-lazy-highlight-overlays
-          (cdr isearch-lazy-highlight-overlays))))
+      (while isearch-lazy-highlight-overlays
+        (delete-overlay (car isearch-lazy-highlight-overlays))
+        (setq isearch-lazy-highlight-overlays
+              (cdr isearch-lazy-highlight-overlays))))
+  (when isearch-lazy-highlight-timer
+    (cancel-timer isearch-lazy-highlight-timer)
+    (setq isearch-lazy-highlight-timer nil)))
 
 (defun isearch-lazy-highlight-new-loop ()
-  "Cleanup any previous isearch-lazy-highlight loop and begin a new one.
+  "Cleanup any previous `isearch-lazy-highlight' loop and begin a new one.
 This happens when `isearch-update' is invoked (which can cause the
-search string to change)."
-  (if (and isearch-lazy-highlight
-           (not (equal isearch-string isearch-lazy-highlight-last-string)))
-      ;; the search string did indeed change
-      (progn
-        (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays
-        (if (and isearch-overlay
-                 (not (overlay-get isearch-overlay 'priority)))
-            ;; make sure the isearch-overlay takes priority
-            (overlay-put isearch-overlay 'priority 1))
-        (setq isearch-lazy-highlight-start isearch-opoint
-              isearch-lazy-highlight-end isearch-opoint
-              isearch-lazy-highlight-last-string isearch-string
-              isearch-lazy-highlight-wrapped nil)
-        (setq isearch-lazy-highlight-timer
-              (run-with-idle-timer isearch-lazy-highlight-initial-delay nil
-                                   'isearch-lazy-highlight-update)))))
+search string to change or the window to scroll)."
+  (when (and isearch-lazy-highlight
+             (sit-for 0)         ;make sure (window-start) is credible
+             (or (not (equal isearch-string
+                             isearch-lazy-highlight-last-string))
+                 (not (eq (selected-window)
+                          isearch-lazy-highlight-window))
+                (not (eq isearch-lazy-highlight-case-fold-search
+                         isearch-case-fold-search))
+                (not (eq isearch-lazy-highlight-regexp
+                         isearch-regexp))
+                 (not (= (window-start)
+                         isearch-lazy-highlight-window-start))))
+    ;; something important did indeed change
+    (isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays
+    (when (not isearch-invalid-regexp)
+      (setq isearch-lazy-highlight-window       (selected-window)
+            isearch-lazy-highlight-window-start (window-start)
+            isearch-lazy-highlight-start        (point)
+            isearch-lazy-highlight-end          (point)
+            isearch-lazy-highlight-last-string  isearch-string
+           isearch-lazy-highlight-case-fold-search isearch-case-fold-search
+           isearch-lazy-highlight-regexp       isearch-regexp
+            isearch-lazy-highlight-wrapped      nil)
+      (setq isearch-lazy-highlight-timer
+            (run-with-idle-timer isearch-lazy-highlight-initial-delay nil
+                                 'isearch-lazy-highlight-update)))))
 
 (defun isearch-lazy-highlight-search ()
   "Search ahead for the next or previous match, for lazy highlighting.
 Attempt to do the search exactly the way the pending isearch would."
-  (let ((case-fold-search isearch-case-fold-search))
-    (funcall (cond (isearch-word (if isearch-forward
-                                     'word-search-forward
-                                   'word-search-backward))
-                   (isearch-regexp (if isearch-forward
-                                       're-search-forward
-                                     're-search-backward))
-                   (t (if isearch-forward
-                          'search-forward
-                        'search-backward)))
+  (let ((case-fold-search isearch-case-fold-search)
+        (choices (cond (isearch-word
+                        '(word-search-forward . word-search-backward))
+                       (isearch-regexp
+                        '(re-search-forward . re-search-backward))
+                       (t
+                        '(search-forward . search-backward)))))
+    (funcall (if isearch-forward
+                 (car choices)
+               (cdr choices))
              isearch-string
              (if isearch-forward
                  (if isearch-lazy-highlight-wrapped
                      isearch-lazy-highlight-start
-                   nil)
+                   (window-end))
                (if isearch-lazy-highlight-wrapped
                    isearch-lazy-highlight-end
-                 nil))
+                 (window-start)))
              t)))
 
 (defun isearch-lazy-highlight-update ()
-  "Find and highlight the next match in the lazy highlighting loop."
-  (when (not isearch-invalid-regexp)
+  "Update highlighting of other matches for current search."
+  (let ((max isearch-lazy-highlight-max-at-a-time)
+        (looping t)
+        nomore)
     (save-excursion
       (save-match-data
         (goto-char (if isearch-forward
                        isearch-lazy-highlight-end
                      isearch-lazy-highlight-start))
-        (let ((found (isearch-lazy-highlight-search))) ;do search
-          (if found
-              ;; found the next match
-              (let ((ov (make-overlay (match-beginning 0)
-                                      (match-end 0))))
-                (overlay-put ov 'face isearch-lazy-highlight-face)
-                (overlay-put ov 'priority 0)
-                (setq isearch-lazy-highlight-overlays
-                      (cons ov isearch-lazy-highlight-overlays))
-                (setq isearch-lazy-highlight-timer
-                      (run-at-time isearch-lazy-highlight-interval nil
-                                   'isearch-lazy-highlight-update))
+        (while looping
+          (let ((found (isearch-lazy-highlight-search)))
+            (when max
+              (setq max (1- max))
+              (if (<= max 0)
+                  (setq looping nil)))
+            (if found
+                (let ((mb (match-beginning 0))
+                      (me (match-end 0)))
+                  (if (= mb me)      ;zero-length match
+                      (forward-char 1)
+
+                    ;; non-zero-length match
+                    (let ((ov (make-overlay mb me)))
+                      (overlay-put ov 'face isearch-lazy-highlight-face)
+                      (overlay-put ov 'priority 0) ;lower than main overlay
+                      (overlay-put ov 'window (selected-window))
+                      (push ov isearch-lazy-highlight-overlays)))
+                  (if isearch-forward
+                      (setq isearch-lazy-highlight-end (point))
+                    (setq isearch-lazy-highlight-start (point))))
+
+              ;; not found
+              (if isearch-lazy-highlight-wrapped
+                  (setq looping nil
+                        nomore  t)
+                (setq isearch-lazy-highlight-wrapped t)
                 (if isearch-forward
-                    (setq isearch-lazy-highlight-end (point))
-                  (setq isearch-lazy-highlight-start (point))))
-            ;; found no next match
-            (when (not isearch-lazy-highlight-wrapped)
-              ;; let's try wrapping around the end of the buffer
-              (setq isearch-lazy-highlight-wrapped t)
-              (setq isearch-lazy-highlight-timer
-                    (run-at-time isearch-lazy-highlight-interval nil
-                                 'isearch-lazy-highlight-update))
-              (if isearch-forward
-                  (setq isearch-lazy-highlight-end (point-min))
-                (setq isearch-lazy-highlight-start (point-max))))))))))
-
+                    (progn
+                      (setq isearch-lazy-highlight-end (window-start))
+                      (goto-char (window-start)))
+                  (setq isearch-lazy-highlight-start (window-end))
+                  (goto-char (window-end)))))))
+        (unless nomore
+          (setq isearch-lazy-highlight-timer
+                (run-at-time isearch-lazy-highlight-interval nil
+                             'isearch-lazy-highlight-update)))))))
+
+(defun isearch-resume (search regexp word forward message case-fold)
+  "Resume an incremental search.
+SEARCH is the string or regexp searched for.
+REGEXP non-nil means the resumed search was a regexp search.
+WORD non-nil means resume a word search.
+FORWARD non-nil means resume a forward search.
+MESSAGE is the echo-area message recorded for the search resumed.
+CASE-FOLD non-nil means the search was case-insensitive."
+  (isearch-mode forward regexp nil nil word)
+  (setq isearch-string search
+       isearch-message message
+       isearch-case-fold-search case-fold)
+  (isearch-search))
+       
 ;;; isearch.el ends here