Update FSF's address.
[bpt/emacs.git] / lisp / isearch.el
index d3231ba..6fb5360 100644 (file)
@@ -1,58 +1,36 @@
-;; Incremental search minor mode.
-;; Copyright (C) 1992 Free Software Foundation, Inc.
+;;; isearch.el --- incremental search minor mode.
 
-;; LCD Archive Entry:
-;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu
-;; |A minor mode replacement for isearch.el.
-;; |$Date: 1992/10/20 21:21:47 $|$Revision: 1.12 $|~/modes/isearch-mode.el
+;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
 
-;; This file is not yet part of GNU Emacs, but it is based almost
-;; entirely on isearch.el which is part of GNU Emacs.
+;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
+;; Maintainer: FSF
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY.  No author or distributor
-;; accepts responsibility to anyone for the consequences of using it
-;; or for whether it serves any particular purpose or works at all,
-;; unless he says so in writing.  Refer to the GNU Emacs General Public
-;; License for full details.
-
-;; Everyone is granted permission to copy, modify and redistribute
-;; GNU Emacs, but only under the conditions described in the
-;; GNU Emacs General Public License.   A copy of this license is
-;; supposed to have been given to you along with GNU Emacs so you
-;; can know your rights and responsibilities.  It should be in a
-;; file named COPYING.  Among other things, the copyright notice
-;; and this notice must be preserved on all copies.
-
-;;;====================================================================
-;; Instructions
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
 
-;; Searching with isearch-mode.el should work just like isearch.el,
-;; except it is done in a temporary minor mode that terminates when
-;; you finish searching.
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
-;; To use isearch-mode instead of the standard isearch.el, add the
-;; following to your .emacs file.  The standard key bindings to
-;; isearch-forward, etc, will then use isearch-mode instead of
-;; isearch.
+;;; Commentary:
 
-;; (fset 'isearch 'isearch-mode)
-;; (autoload 'isearch-mode "isearch-mode")
+;; Instructions
 
 ;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
 ;; isearch-mode behaves modally and does not return until the search
 ;; is completed.  It uses a recursive-edit to behave this way.  Note:
 ;; gnus does it wrong: (call-interactively 'isearch-forward).
 
-;; If any package you use invokes isearching non-interactively to get
-;; the modal behavior described above, you must use the redefinitions
-;; of isearch-forward, etc. found in this file instead of those in
-;; loaddefs.el.  The simplest way to ensure this is to just load
-;; isearch-mode explicitly in your .emacs instead of using the above
-;; fset and autoload.
-
-;; (load "isearch-mode")
-
 ;; The key bindings active within isearch-mode are defined below in
 ;; `isearch-mode-map' which is given bindings close to the default
 ;; characters of the original isearch.el.  With `isearch-mode',
 ;; the last possible moment.
 
 ;; TODO
-;; - Integrate the emacs 19 generalized commmand history.
+;; - Integrate the emacs 19 generalized command history.
 ;; - Think about incorporating query-replace.
 ;; - Hooks and options for failed search.
 
-;;;====================================================================
-;;; Change History
-
-;;; $Header: /gd/gnu/emacs/19.0/lisp/RCS/isearch-mode.el,v 1.12 1992/10/20 21:21:47 rms Exp rms $
-;;; $Log: isearch-mode.el,v $
-; Revision 1.12  1992/10/20  21:21:47  rms
-; (isearch-mode-map): Make the top-level keymap dense.
-; Explicitly bind control characters at that level.
-;
-; Revision 1.11  1992/10/11  05:25:11  rms
-; (isearch-ring-advance-edit): Delete spurious `)'.
-;
-; Revision 1.10  1992/09/21  08:28:43  rms
-; entered into RCS
-;
-;;; Revision 1.4  92/09/14  16:26:02  liberte
-;;; Added prefix args to isearch-forward, etc. to switch between
-;;;    string and regular expression searching.
-;;; Added some support for lemacs.
-;;; Added general isearch-highlight option - but only for lemacs so far.
-;;; Added support for frame switching in emacs 19.
-;;; Added word search option to isearch-edit-string.
-;;; Renamed isearch-quit to isearch-abort.
-;;; Numerous changes to comments and doc strings.
-;;; 
-;;; Revision 1.3  92/06/29  13:10:08  liberte
-;;; Moved modal isearch-mode handling into isearch-mode.
-;;; Got rid of buffer-local isearch variables.
-;;; isearch-edit-string used by ring adjustments, completion, and
-;;; nonincremental searching.  C-s and C-r are additional exit commands.
-;;; Renamed all regex to regexp.
-;;; Got rid of found-start and found-point globals.
-;;; Generalized handling of upper-case chars.
-;;; Revision 1.2  92/05/27  11:33:57  liberte
-;;; Emacs version 19 has a search ring, which is supported here.
-;;; Other fixes found in the version 19 isearch are included here.
-;;;
-;;; Also see variables search-caps-disable-folding,
-;;; search-nonincremental-instead, search-whitespace-regexp, and
-;;; commands isearch-toggle-regexp, isearch-edit-string.
-;;;
-;;; semi-modal isearching is supported.
-
-;;; Changes for 1.1
-;;; 3/18/92 Fixed invalid-regexp.
-;;; 3/18/92 Fixed yanking in regexps.
-
+;;; Change Log:
+
+;; Changes before those recorded in ChangeLog:
+
+;; Revision 1.4  92/09/14  16:26:02  liberte
+;; Added prefix args to isearch-forward, etc. to switch between
+;;    string and regular expression searching.
+;; Added some support for lemacs.
+;; Added general isearch-highlight option - but only for lemacs so far.
+;; Added support for frame switching in emacs 19.
+;; Added word search option to isearch-edit-string.
+;; Renamed isearch-quit to isearch-abort.
+;; Numerous changes to comments and doc strings.
+;; 
+;; Revision 1.3  92/06/29  13:10:08  liberte
+;; Moved modal isearch-mode handling into isearch-mode.
+;; Got rid of buffer-local isearch variables.
+;; isearch-edit-string used by ring adjustments, completion, and
+;; nonincremental searching.  C-s and C-r are additional exit commands.
+;; Renamed all regex to regexp.
+;; Got rid of found-start and found-point globals.
+;; Generalized handling of upper-case chars.
+
+;; Revision 1.2  92/05/27  11:33:57  liberte
+;; Emacs version 19 has a search ring, which is supported here.
+;; Other fixes found in the version 19 isearch are included here.
+;;
+;; Also see variables search-caps-disable-folding,
+;; search-nonincremental-instead, search-whitespace-regexp, and
+;; commands isearch-toggle-regexp, isearch-edit-string.
+;;
+;; semi-modal isearching is supported.
+
+;; Changes for 1.1
+;; 3/18/92 Fixed invalid-regexp.
+;; 3/18/92 Fixed yanking in regexps.
+
+;;; Code:
 
 \f
-;;;=========================================================================
-;;; Emacs features
-
-;; isearch-mode takes advantage of the features provided by several
-;; different versions of emacs.  Rather than testing the version of
-;; emacs, several constants are defined, one for each of the features.
-;; Each of the tests below must work on any version of emacs.
-;; (Perhaps provide and featurep could be used for this purpose.)
-
-(defconst isearch-frames-exist (fboundp 'select-frame)) ;; emacs 19
-(defconst isearch-pre-command-hook-exists (boundp 'pre-command-hook)) ;; lemacs
-(defconst isearch-event-data-type nil)  ;; lemacs
+;;; Some additional options and constants.
 
 (defconst search-exit-option t
   "*Non-nil means random control characters terminate incremental search.")
@@ -162,10 +119,7 @@ and the value is minus the number of lines.")
 This is the style where a one-line window is created to show the line
 that the search has reached.")
 
-;;;========================================================================
-;;; Some additional options and constants.
-
-(defvar search-upper-case t
+(defvar search-upper-case 'not-yanks
   "*If non-nil, upper case chars disable case fold searching.
 That is, upper and lower case chars must match exactly.
 This applies no matter where the chars come from, but does not
@@ -181,13 +135,8 @@ string, and RET terminates editing and does a nonincremental search.")
   "*If non-nil, regular expression to match a sequence of whitespace chars.
 You might want to use something like \"[ \\t\\r\\n]+\" instead.")
 
-;; I removed the * from the doc string because highlighting is not 
-;; currently a clean thing to do.  Once highlighting is made clean, 
-;; this feature can be re-enabled and advertised.
 (defvar search-highlight nil
-  "Whether isearch and query-replace should highlight the text which 
-currently matches the search-string.")
-
+  "*Non-nil means incremental search highlights the current match.")
 
 (defvar isearch-mode-hook nil
   "Function(s) to call after starting up an incremental search.")
@@ -195,7 +144,6 @@ currently matches the search-string.")
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.")
 
-;;;==================================================================
 ;;; Search ring.
 
 (defvar search-ring nil
@@ -219,7 +167,6 @@ nil if none yet.")
   "*Non-nil if advancing or retreating in the search ring should cause search.
 Default value, nil, means edit the string instead.")
 
-;;;====================================================
 ;;; Define isearch-mode keymap.
 
 (defvar isearch-mode-map nil
@@ -228,6 +175,11 @@ Default value, nil, means edit the string instead.")
 (or isearch-mode-map
     (let* ((i 0)
           (map (make-keymap)))
+      (or (vectorp (nth 1 map))
+         (error "The initialization of isearch-mode-map must be updated"))
+      ;; Give this map a vector 256 long, for dense binding
+      ;; of a larger range of ordinary characters.
+      (setcar (cdr map) (make-vector 256 nil))
 
       ;; Make function keys, etc, exit the search.
       (define-key map [t] 'isearch-other-control-char)
@@ -239,23 +191,35 @@ Default value, nil, means edit the string instead.")
        (define-key map (make-string 1 i) 'isearch-other-control-char)
        (setq i (1+ i)))
 
-      ;; Printing chars extend the selection by default.
+      ;; Printing chars extend the search string by default.
       (setq i ?\ )
-      (while (< i 128)
-       (define-key map (make-string 1 i) 'isearch-printing-char)
+      (while (< i (length (nth 1 map)))
+       (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)
     
       (define-key map "\C-q" 'isearch-quote-char)
 
-      ;;  (define-key map "\r" 'isearch-return-char)
-      ;; For version 19, RET (C-m) terminates search and LFD (C-j) matches eol.
-      ;; We could make this conditional.
       (define-key map "\r" 'isearch-exit)
       (define-key map "\C-j" 'isearch-printing-char)
       (define-key map "\t" 'isearch-printing-char)
@@ -270,43 +234,30 @@ Default value, nil, means edit the string instead.")
       (define-key map "?" 'isearch-*-char)
       (define-key map "|" 'isearch-|-char)
 
-      ;; You can reenable global keys by binding them locally to nil.
-      ;; For the help char this doesnt work quite as expected because
-      ;; isearch-mode is not a major mode.  Also the echo area is not
-      ;; restored after the help command while isearch-mode is
-      ;; still active.  Furthermore, we should not assume that the
-      ;; help-command is on C-h.  But here is how it would be done:
-      ;; (define-key map "\C-h" nil)
-
-      ;; Instead bind C-h to special help command for isearch-mode.
-      (define-key map "\C-h" 'isearch-mode-help)
-
-      ;; 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.
-      (define-key map (char-to-string meta-prefix-char) (make-sparse-keymap))
-      (define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
-;;;      (setq i 0)
-;;;      (while (< i 128)
-;;;    (define-key map (char-to-string (+ 128 i));; Needs to be generalized.
-;;;      'isearch-other-meta-char)
-;;;    (setq i (1+ i)))
+;;; 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)
 
-      ;; For emacs 19, switching frames should terminate isearch-mode
-      (if isearch-frames-exist
-         (define-key map [switch-frame] 'isearch-switch-frame-handler))
-      
+      ;; 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)
+
       (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)
 
@@ -325,7 +276,6 @@ Default value, nil, means edit the string instead.")
       (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.
@@ -340,11 +290,16 @@ Default value, nil, means edit the string instead.")
 
 (defvar isearch-success t)             ; Searching is currently successful.
 (defvar isearch-invalid-regexp nil)    ; Regexp not well formed.
+(defvar isearch-within-brackets nil)   ; Regexp has unclosed [.
 (defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
 (defvar isearch-wrapped nil)   ; Searching restarted from the top (bottom).
 (defvar isearch-barrier 0)
+(defvar isearch-just-started nil)
 
-(defvar isearch-case-fold-search nil) ; case-fold-search while searching.
+; case-fold-search while searching.
+;   either nil, t, or 'yes.  'yes means the same as t except that mixed
+;   case in the search string is ignored.
+(defvar isearch-case-fold-search nil)
 
 (defvar isearch-adjusted nil)
 (defvar isearch-slow-terminal-mode nil)
@@ -353,7 +308,6 @@ Default value, nil, means edit the string instead.")
 (defvar isearch-opoint 0)
 ;;; The window configuration active at the beginning of the search.
 (defvar isearch-window-configuration nil)
-(defvar isearch-old-local-map nil)
 
 ;; Flag to indicate a yank occurred, so don't move the cursor.
 (defvar isearch-yank-flag nil)
@@ -373,7 +327,6 @@ Default value, nil, means edit the string instead.")
 (defvar isearch-new-forward nil)
 
 
-;;;==============================================================
 ;; Minor-mode-alist changes - kind of redundant with the
 ;; echo area, but if isearching in multiple windows, it can be useful.
 
@@ -389,13 +342,12 @@ Default value, nil, means edit the string instead.")
 (define-key global-map "\C-r" 'isearch-backward)
 (define-key esc-map "\C-r" 'isearch-backward-regexp)
 
-;;;===============================================================
 ;;; Entry points to isearch-mode.
 ;;; These four functions should replace those in loaddefs.el
-;;; An alternative is to fset isearch-forward etc to isearch-mode,
+;;; An alternative is to defalias isearch-forward etc to isearch-mode,
 ;;; and look at this-command to set the options accordingly.
 
-(defun isearch-forward (&optional regexp-p)
+(defun isearch-forward (&optional regexp-p no-recursive-edit)
   "\
 Do incremental search forward.
 With a prefix argument, do an incremental regular expression search instead.
@@ -413,7 +365,6 @@ Type \\[isearch-yank-word] to yank word from buffer onto end of search\
 Type \\[isearch-yank-line] to yank rest of line onto end of search string\
  and search for it.
 Type \\[isearch-quote-char] to quote control character to search for it.
-Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp.
 \\[isearch-abort] while searching or when search has failed cancels input\
  back to what has
  been found successfully.
@@ -430,38 +381,39 @@ 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
  and are then executed normally (depending on `search-exit-option').
+Likewise for function keys and mouse button events.
 
 If this function is called non-interactively, it does not return to
 the calling function until the search is done."
 
-  (interactive "P")
-  (isearch-mode t (not (null regexp-p)) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
 
-(defun isearch-forward-regexp (&optional regexp-p)
+(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
   "\
 Do incremental search forward for regular expression.
 With a prefix argument, do a regular string search instead.
 Like ordinary incremental search except that your input
 is treated as a regexp.  See \\[isearch-forward] for more info."
-  (interactive)
-  (isearch-mode t (null regexp-p) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
 
-(defun isearch-backward (&optional regexp-p)
+(defun isearch-backward (&optional regexp-p no-recursive-edit)
   "\
 Do incremental search backward.
 With a prefix argument, do a regular expression search instead.
 See \\[isearch-forward] for more information."
-  (interactive)
-  (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
 
-(defun isearch-backward-regexp (&optional regexp-p)
+(defun isearch-backward-regexp (&optional not-regexp no-recursive-edit)
   "\
 Do incremental search backward for regular expression.
 With a prefix argument, do a regular string search instead.
 Like ordinary incremental search except that your input
 is treated as a regexp.  See \\[isearch-forward] for more info."
-  (interactive)
-  (isearch-mode nil (null regexp-p) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
 
 
 (defun isearch-mode-help ()
@@ -470,7 +422,6 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   (isearch-update))
 
 \f
-;;;==================================================================
 ;; isearch-mode only sets up incremental search for the minor mode.
 ;; All the work is done by the isearch-mode commands.
 
@@ -481,7 +432,9 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
                             
 
 (defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
-  "Start isearch minor mode.  Called by isearch-forward, etc."
+  "Start isearch minor mode.  Called by `isearch-forward', etc.
+
+\\{isearch-mode-map}"
 
   ;; Initialize global vars.
   (setq isearch-forward forward
@@ -498,46 +451,46 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
        isearch-adjusted nil
        isearch-yank-flag nil
        isearch-invalid-regexp nil
-       ;; Use (baud-rate) for now, for sake of other versions.
-       isearch-slow-terminal-mode (and (<= (baud-rate) search-slow-speed)
+       isearch-within-brackets nil
+       isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
                                        (> (window-height)
                                           (* 4 search-slow-window-lines)))
        isearch-other-end nil
        isearch-small-window nil
+       isearch-just-started t
 
        isearch-opoint (point)
-       isearch-window-configuration (current-window-configuration)
-       isearch-old-local-map (current-local-map)
        search-ring-yank-pointer nil
        regexp-search-ring-yank-pointer nil)
-  (if isearch-pre-command-hook-exists
-      (add-hook 'pre-command-hook 'isearch-pre-command-hook))
+  (looking-at "")
+  (setq isearch-window-configuration
+       (if isearch-slow-terminal-mode (current-window-configuration) nil))
+
   (setq        isearch-mode " Isearch")  ;; forward? regexp?
-  (set-buffer-modified-p (buffer-modified-p)) ; update modeline
+  (force-mode-line-update)
 
   (isearch-push-state)
 
-  (use-local-map isearch-mode-map)
+  (setq overriding-terminal-local-map isearch-mode-map)
   (isearch-update)
   (run-hooks 'isearch-mode-hook)
 
+  (setq mouse-leave-buffer-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 
   ;; a recursive-edit and exiting it when done isearching.
-  (if recursive-edit (recursive-edit))
-  )
+  (if recursive-edit
+      (let ((isearch-recursive-edit t))
+       (recursive-edit)))
+  isearch-success)
 
 
-;;;====================================================
 ;; Some high level utilities.  Others below.
 
 (defun isearch-update ()
   ;; Called after each command to update the display.  
-  (if (if isearch-event-data-type
-         (null unread-command-event)
-       (if isearch-frames-exist
-           (null unread-command-char)
-         (< unread-command-char 0)))
+  (if (null unread-command-events)
       (progn
        (if (not (input-pending-p))
            (isearch-message))
@@ -563,62 +516,71 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
        (if isearch-other-end
            (if (< isearch-other-end (point)) ; isearch-forward?
                (isearch-highlight isearch-other-end (point))
-             (isearch-highlight (point) isearch-other-end)))
+             (isearch-highlight (point) isearch-other-end))
+         (isearch-dehighlight nil))
        ))
   (setq ;; quit-flag nil  not for isearch-mode
    isearch-adjusted nil
    isearch-yank-flag nil)
   )
 
-
-(defun isearch-done (&optional nopush)
+(defun isearch-done (&optional nopush edit)
+  (setq mouse-leave-buffer-hook nil)
   ;; Called by all commands that terminate isearch-mode.
   ;; If NOPUSH is non-nil, we don't push the string on the search ring.
-  (use-local-map isearch-old-local-map)
+  (setq overriding-terminal-local-map nil)
   ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
   (isearch-dehighlight t)
   (let ((found-start (window-start (selected-window)))
        (found-point (point)))
-    (set-window-configuration isearch-window-configuration)
+    (if isearch-window-configuration
+       (set-window-configuration isearch-window-configuration))
 
-    ;; If there was movement, mark the starting position.
-    ;; Maybe should test difference between and set mark iff > threshold.
-    (if (/= (point) isearch-opoint)
-       (push-mark isearch-opoint)
-      ;; (message "") why is this needed?
-      )
     (if isearch-small-window
        (goto-char found-point)
       ;; Exiting the save-window-excursion clobbers window-start; restore it.
-      (set-window-start (selected-window) found-start t)))
+      (set-window-start (selected-window) found-start t))
+
+    ;; If there was movement, mark the starting position.
+    ;; Maybe should test difference between and set mark iff > threshold.
+    (if (/= (point) isearch-opoint)
+       (or (and transient-mark-mode mark-active)
+           (progn
+             (push-mark isearch-opoint t)
+             (or executing-kbd-macro (> (minibuffer-depth) 0)
+                 (message "Mark saved where search started"))))))
 
   (setq isearch-mode nil)
-  (set-buffer-modified-p (buffer-modified-p))  ;; update modeline
+  (force-mode-line-update)
 
   (if (and (> (length isearch-string) 0) (not nopush))
       ;; Update the ring data.
-      (if isearch-regexp 
-         (if (or (null regexp-search-ring)
-                 (not (string= isearch-string (car regexp-search-ring))))
-             (progn
-               (setq regexp-search-ring
-                     (cons isearch-string regexp-search-ring))
-               (if (> (length regexp-search-ring) regexp-search-ring-max)
-                   (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
-                           nil))))
-       (if (or (null search-ring)
-               (not (string= isearch-string (car search-ring))))
-           (progn
-             (setq search-ring (cons isearch-string search-ring))
-             (if (> (length search-ring) search-ring-max)
-                 (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
+      (isearch-update-ring isearch-string isearch-regexp))
 
   (run-hooks 'isearch-mode-end-hook)
-  (if isearch-recursive-edit (exit-recursive-edit)))
+  (and (not edit) isearch-recursive-edit (exit-recursive-edit)))
+
+(defun isearch-update-ring (string &optional regexp)
+  "Add STRING to the beginning of the search ring.
+REGEXP says which ring to use."
+  (if regexp 
+      (if (or (null regexp-search-ring)
+             (not (string= string (car regexp-search-ring))))
+         (progn
+           (setq regexp-search-ring
+                 (cons string regexp-search-ring))
+           (if (> (length regexp-search-ring) regexp-search-ring-max)
+               (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
+                       nil))))
+    (if (or (null search-ring)
+           (not (string= string (car search-ring))))
+       (progn
+         (setq search-ring (cons string search-ring))
+         (if (> (length search-ring) search-ring-max)
+             (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
 
-;;;=======================================================
 ;;; Switching buffers should first terminate isearch-mode.
-;;; This is done quite differently for each varient of emacs.
+;;; This is done quite differently for each variant of emacs.
 ;;; For lemacs, see Exiting in lemacs below
 
 ;; For Emacs 19, the frame switch event is handled.
@@ -626,12 +588,9 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   (interactive) ;; Is this necessary?
   ;; First terminate isearch-mode.
   (isearch-done)
-  (select-frame (car (cdr (isearch-last-command-char)))))
-
-;;;========================================================
+  (handle-switch-frame (car (cdr (isearch-last-command-char)))))
 
 \f
-;;;====================================================
 ;; Commands active while inside of the isearch minor mode.
 
 (defun isearch-exit ()
@@ -654,21 +613,21 @@ The following additional command keys are active while editing.
 \\[exit-minibuffer] to resume incremental searching with the edited string.
 \\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
 \\[isearch-forward-exit-minibuffer] to resume isearching forward.
-\\[isearch-backward-exit-minibuffer] to resume isearching backward.
+\\[isearch-reverse-exit-minibuffer] to resume isearching backward.
 \\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring.
-\\[isearch-ring-retreat-edit] to replace the search string with the previou item in the search ring.
+\\[isearch-ring-retreat-edit] to replace the search string with the previous item in the search ring.
 \\[isearch-complete-edit] to complete the search string using the search ring.
-
+\\<isearch-mode-map>
 If first char entered is \\[isearch-yank-word], then do word search instead."
 
   ;; This code is very hairy for several reasons, explained in the code.
   ;; Mainly, isearch-mode must be terminated while editing and then restarted.
   ;; If there were a way to catch any change of buffer from the minibuffer,
   ;; this could be simplified greatly.
-  ;; Editing doesnt back up the search point.  Should it?
+  ;; Editing doesn't back up the search point.  Should it?
   (interactive)
   (condition-case err
-      (let (isearch-nonincremental     ; should search nonincrementally?
+      (let ((isearch-nonincremental isearch-nonincremental)
 
            ;; Locally bind all isearch global variables to protect them
            ;; from recursive isearching.
@@ -688,7 +647,13 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
            (isearch-adjusted isearch-adjusted)
            (isearch-yank-flag isearch-yank-flag)
            (isearch-invalid-regexp isearch-invalid-regexp)
-           (isearch-other-end isearch-other-end)
+           (isearch-within-brackets isearch-within-brackets)
+;;; Don't bind this.  We want isearch-search, below, to set it.
+;;; And the old value won't matter after that.
+;;;        (isearch-other-end isearch-other-end)
+;;; Perhaps some of these other variables should be bound for a
+;;; shorter period, ending before the next isearch-search.
+;;; But there doesn't seem to be a real bug, so let's not risk it now.
            (isearch-opoint isearch-opoint)
            (isearch-slow-terminal-mode isearch-slow-terminal-mode)
            (isearch-small-window isearch-small-window)
@@ -701,7 +666,7 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
        ;; This is so that the user can do anything without failure, 
        ;; like switch buffers and start another isearch, and return.
        (condition-case err
-           (isearch-done t)
+           (isearch-done t t)
          (exit nil))                   ; was recursive editing
 
        (isearch-message) ;; for read-char
@@ -709,11 +674,11 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
            (let* (;; Why does following read-char echo?  
                   ;;(echo-keystrokes 0) ;; not needed with above message
                   (e (let ((cursor-in-echo-area t))
-                       (if isearch-event-data-type
-                           (allocate-event) (read-char))))
+                       (read-event)))
                   ;; Binding minibuffer-history-symbol to nil is a work-around
                   ;; for some incompatibility with gmhist.
-                  (minibuffer-history-symbol))
+                  (minibuffer-history-symbol)
+                  (message-log-max nil))
              ;; If the first character the user types when we prompt them
              ;; for a string is the yank-word character, then go into
              ;; word-search mode.  Otherwise unread that character and
@@ -722,29 +687,26 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
              ;; no check is made here.
              (message (isearch-message-prefix nil nil t))
              (if (eq 'isearch-yank-word
-                     (lookup-key
-                      isearch-mode-map
-                      (char-to-string
-                       (if isearch-event-data-type
-                           (or (event-to-character (next-command-event e)) 0)
-                         e))))
+                     (lookup-key isearch-mode-map (vector e)))
                  (setq isearch-word t  ;; so message-prefix is right
                        isearch-new-word t)
                (isearch-unread e))
              (setq cursor-in-echo-area nil)
              (setq isearch-new-string
                    (let (junk-ring)
-                     (read-from-minibuffer (isearch-message-prefix)
-                                           isearch-string
-                                           minibuffer-local-isearch-map nil
-                                           'junk-ring))
-                   isearch-new-message (mapconcat 'text-char-description
-                                                  isearch-new-string "")))
+                     (read-from-minibuffer
+                      (isearch-message-prefix nil nil isearch-nonincremental)
+                      isearch-string
+                      minibuffer-local-isearch-map nil
+                      'junk-ring))
+                   isearch-new-message
+                   (mapconcat 'isearch-text-char-description
+                              isearch-new-string "")))
          ;; Always resume isearching by restarting it.
          (isearch-mode isearch-forward 
                        isearch-regexp 
                        isearch-op-fun 
-                       isearch-recursive-edit
+                       nil
                        isearch-word)
 
          ;; Copy new local values to isearch globals
@@ -755,8 +717,10 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
 
        ;; Empty isearch-string means use default.
        (if (= 0 (length isearch-string))
-           (setq isearch-string (car (if isearch-regexp regexp-search-ring
-                                       search-ring)))
+           (setq isearch-string (or (car (if isearch-regexp
+                                             regexp-search-ring
+                                           search-ring))
+                                    ""))
          ;; This used to set the last search string,
          ;; but I think it is not right to do that here.
          ;; Only the string actually used should be saved.
@@ -790,25 +754,33 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
   (setq isearch-new-forward nil)
   (exit-minibuffer))
 
+(defun isearch-cancel ()
+  "Terminate the search and go back to the starting point."
+  (interactive)
+  (goto-char isearch-opoint)
+  (isearch-done t)
+  (signal 'quit nil))  ; and pass on quit signal
 
 (defun isearch-abort ()
-  "Abort incremental search mode if searching is successful, signalling quit.
+  "Abort incremental search mode if searching is successful, signaling quit.
 Otherwise, revert to previous successful search and continue searching.
-Use `isearch-exit' to quit without signalling."
+Use `isearch-exit' to quit without signaling."
   (interactive)
-;;  (ding)  signal instead below, if quiting
+;;  (ding)  signal instead below, if quitting
   (discard-input)
   (if isearch-success
       ;; If search is successful, move back to starting point
       ;; and really do quit.
       (progn (goto-char isearch-opoint)
+            (setq isearch-success nil)
             (isearch-done t)   ; exit isearch
             (signal 'quit nil))  ; and pass on quit signal
-    ;; If search is failing, rub out until it is once more successful.
-    (while (not isearch-success) (isearch-pop-state))
+    ;; If search is failing, or has an incomplete regexp,
+    ;; rub out until it is once more successful.
+    (while (or (not isearch-success) isearch-invalid-regexp)
+      (isearch-pop-state))
     (isearch-update)))
 
-
 (defun isearch-repeat (direction)
   ;; Utility for isearch-repeat-forward and -backward.
   (if (eq isearch-forward (eq direction 'forward))
@@ -833,14 +805,22 @@ Use `isearch-exit' to quit without signalling."
     (setq isearch-forward (not isearch-forward)))
 
   (setq isearch-barrier (point)) ; For subsequent \| if regexp.
-  (setq isearch-success t)
-  (or (equal isearch-string "")
-      (progn
+
+  (if (equal isearch-string "")
+      (setq isearch-success t)
+    (if (and isearch-success (equal (match-end 0) (match-beginning 0))
+            (not isearch-just-started))
        ;; If repeating a search that found
        ;; an empty string, ensure we advance.
-       (if (equal (match-end 0) (match-beginning 0))
-           (forward-char (if isearch-forward 1 -1)))
-       (isearch-search)))
+       (if (if isearch-forward (eobp) (bobp))
+           ;; If there's nowhere to advance to, fail (and wrap next time).
+           (progn
+             (setq isearch-success nil)
+             (ding))
+         (forward-char (if isearch-forward 1 -1))
+         (isearch-search))
+      (isearch-search)))
+
   (isearch-push-state)
   (isearch-update))
 
@@ -862,6 +842,20 @@ Use `isearch-exit' to quit without signalling."
   (if isearch-regexp (setq isearch-word nil))
   (isearch-update))
 
+(defun isearch-toggle-case-fold ()
+  "Toggle case folding in searching on or off."
+  (interactive)
+  (setq isearch-case-fold-search
+       (if isearch-case-fold-search nil 'yes))
+  (let ((message-log-max nil))
+    (message "%s%s [case %ssensitive]"
+            (isearch-message-prefix nil nil isearch-nonincremental)
+            isearch-message
+            (if isearch-case-fold-search "in" "")))
+  (setq isearch-adjusted t)
+  (sit-for 1)
+  (isearch-update))
+
 (defun isearch-delete-char ()
   "Discard last input item and move point back.  
 If no previous match was done, just beep."
@@ -874,18 +868,23 @@ If no previous match was done, just beep."
 
 (defun isearch-yank (chunk)
   ;; Helper for isearch-yank-word and isearch-yank-line
-  (let ((string (save-excursion
-                 (and (not isearch-forward) isearch-other-end
-                      (goto-char isearch-other-end))
-                 (buffer-substring
-                  (point)
-                  (save-excursion
-                    (cond
-                     ((eq chunk 'word)
-                      (forward-word 1))
-                     ((eq chunk 'line)
-                      (end-of-line)))
-                    (point))))))
+  ;; CHUNK should be word, line or kill.
+  (let ((string (cond
+                 ((eq chunk 'kill)
+                  (current-kill 0))
+                 (t
+                 (save-excursion
+                   (and (not isearch-forward) isearch-other-end
+                        (goto-char isearch-other-end))
+                   (buffer-substring
+                    (point)
+                    (save-excursion
+                      (cond
+                       ((eq chunk 'word)
+                        (forward-word 1))
+                       ((eq chunk 'line)
+                        (end-of-line)))
+                      (point))))))))
     ;; Downcase the string if not supposed to case-fold yanked strings.
     (if (and isearch-case-fold-search
             (eq 'not-yanks search-upper-case))
@@ -900,6 +899,10 @@ If no previous match was done, just beep."
          isearch-yank-flag t))
   (isearch-search-and-update))
 
+(defun isearch-yank-kill ()
+  "Pull string from kill ring into search string."
+  (interactive)
+  (isearch-yank 'kill))
 
 (defun isearch-yank-word ()
   "Pull next word from buffer into search string."
@@ -927,14 +930,16 @@ If no previous match was done, just beep."
     ;; long as the match does not extend past search origin.
     (if (and (not isearch-forward) (not isearch-adjusted)
             (condition-case ()
-                (looking-at (if isearch-regexp isearch-string
-                              (regexp-quote isearch-string)))
+                (let ((case-fold-search isearch-case-fold-search))
+                  (looking-at (if isearch-regexp isearch-string
+                                (regexp-quote isearch-string))))
               (error nil))
               (or isearch-yank-flag
                   (<= (match-end 0) 
                       (min isearch-opoint isearch-barrier))))
        (setq isearch-success t 
              isearch-invalid-regexp nil
+             isearch-within-brackets nil
              isearch-other-end (match-end 0))
       ;; Not regexp, not reverse, or no match at point.
       (if (and isearch-other-end (not isearch-adjusted))
@@ -986,40 +991,83 @@ If no previous match was done, just beep."
   (isearch-process-search-char (isearch-last-command-char)))
 
 
-(defun isearch-other-control-char ()
-  "Any other control char => unread it and exit the search normally.
-But only if `search-exit-option' is non-nil, the default.
-If it is the symbol `edit', the search string is edited in the minibuffer
-and the control char is unread so that it applies to editing the string."
-  (interactive)
-  (cond ((eq search-exit-option 'edit)
-        (isearch-unread (isearch-last-command-char))
-        (isearch-edit-string))
-       (search-exit-option;; any other non-nil value
-        (isearch-unread (isearch-last-command-char))
-        (isearch-done))
-       (t;; search-exit-option is nil
-        (isearch-process-search-char (isearch-last-command-char)))))
-
+(defalias 'isearch-other-control-char 'isearch-other-meta-char)
 
 (defun isearch-other-meta-char ()
-  "Any other meta char => exit the search normally and reread the character.
+  "Exit the search normally and reread this key sequence.
 But only if `search-exit-option' is non-nil, the default.
 If it is the symbol `edit', the search string is edited in the minibuffer
 and the meta character is unread so that it applies to editing the string."
   (interactive)
-  (cond ((eq search-exit-option 'edit)
-        (let ((key (this-command-keys)))
-          (isearch-unread (+ 128 (aref key (1- (length key))))))
-        (isearch-edit-string))
-       (search-exit-option
-        (let ((key (this-command-keys)))
-          (isearch-unread (+ 128 (aref key (1- (length key))))))
-        (isearch-done))
-       (t;; otherwise nil
-        (isearch-process-search-string (this-command-keys)
-                                       (this-command-keys)))))
-
+  (let* ((key (this-command-keys))
+        (main-event (aref key 0))
+        (keylist (listify-key-sequence key)))
+    (cond ((and (= (length key) 1)
+               (let ((lookup (lookup-key function-key-map key)))
+                 (not (or (null lookup) (integerp lookup)))))
+          ;; Handle a function key that translates into something else.
+          ;; If the key has a global definition too,
+          ;; exit and unread the key itself, so its global definition runs.
+          ;; Otherwise, unread the translation,
+          ;; so that the translated key takes effect within isearch.
+          (cancel-kbd-macro-events)
+          (if (lookup-key global-map key)
+              (progn 
+                (isearch-done)
+                (apply 'isearch-unread keylist))
+            (apply 'isearch-unread
+                   (listify-key-sequence (lookup-key function-key-map key)))))
+         (
+          ;; Handle an undefined shifted control character
+          ;; by downshifting it if that makes it defined.
+          ;; (As read-key-sequence would normally do,
+          ;; if we didn't have a default definition.)
+          (let ((mods (event-modifiers main-event)))
+            (and (integerp main-event)
+                 (memq 'shift mods)
+                 (memq 'control mods)
+                 (lookup-key isearch-mode-map
+                             (let ((copy (copy-sequence key)))
+                               (aset copy 0
+                                     (- main-event (- ?\C-\S-a ?\C-a)))
+                               copy)
+                             nil)))
+          (setcar keylist (- main-event (- ?\C-\S-a ?\C-a)))
+          (cancel-kbd-macro-events)
+          (apply 'isearch-unread keylist))
+         ((eq search-exit-option 'edit)
+          (apply 'isearch-unread keylist)
+          (isearch-edit-string))
+         (search-exit-option
+          (let (window)
+            (cancel-kbd-macro-events)
+            (apply 'isearch-unread keylist)
+            ;; Properly handle scroll-bar and mode-line clicks
+            ;; for which a dummy prefix event was generated as (aref key 0).
+            (and (> (length key) 1)
+                 (symbolp (aref key 0))
+                 (listp (aref key 1))
+                 (not (numberp (posn-point (event-start (aref key 1)))))
+                 ;; Convert the event back into its raw form,
+                 ;; with the dummy prefix implicit in the mouse event,
+                 ;; so it will get split up once again.
+                 (progn (setq unread-command-events
+                              (cdr unread-command-events))
+                        (setq main-event (car unread-command-events))
+                        (setcar (cdr (event-start main-event))
+                                (car (nth 1 (event-start main-event))))))
+            ;; If we got a mouse click, maybe it was read with the buffer
+            ;; it was clicked on.  If so, that buffer, not the current one,
+            ;; is in isearch mode.  So end the search in that buffer.
+            (if (and (listp main-event)
+                     (setq window (posn-window (event-start main-event)))
+                     (windowp window))
+                (save-excursion
+                  (set-buffer (window-buffer window))
+                  (isearch-done))
+              (isearch-done))))
+         (t;; otherwise nil
+          (isearch-process-search-string key key)))))
 
 (defun isearch-quote-char ()
   "Quote special characters for incremental search."
@@ -1033,20 +1081,20 @@ Obsolete."
   (isearch-process-search-char ?\n))
 
 (defun isearch-printing-char ()
-  "Any other printing character => add it to the search string and search."
+  "Add this ordinary printing character to the search string and search."
   (interactive)
   (isearch-process-search-char (isearch-last-command-char)))
 
 (defun isearch-whitespace-chars ()
   "Match all whitespace chars, if in regexp mode.
-If not in regexp mode, activate word search."
+If you want to search for just a space, type C-q SPC."
   (interactive)
   (if isearch-regexp 
-      (if search-whitespace-regexp
+      (if (and search-whitespace-regexp (not isearch-within-brackets))
          (isearch-process-search-string search-whitespace-regexp " ")
        (isearch-printing-char))
     (progn
-      ;; This way of doing word search doesnt correctly extend current search.
+      ;; This way of doing word search doesn't correctly extend current search.
       ;;      (setq isearch-word t)
       ;;      (setq isearch-adjusted t)
       ;;      (goto-char isearch-barrier)
@@ -1064,7 +1112,6 @@ If not in regexp mode, activate word search."
   (isearch-search-and-update))
 
 \f
-;;===========================================================
 ;; Search Ring
 
 (defun isearch-ring-adjust1 (advance)
@@ -1079,9 +1126,9 @@ If not in regexp mode, activate word search."
        ()
       (set yank-pointer-name
           (setq yank-pointer
-                (% (+ (or yank-pointer 0)
-                      (if advance (1- length) 1))
-                   length)))
+                (mod (+ (or yank-pointer 0)
+                        (if advance -1 1))
+                     length)))
       (setq isearch-string (nth yank-pointer ring)
            isearch-message (mapconcat 'isearch-text-char-description
                                       isearch-string "")))))
@@ -1123,11 +1170,8 @@ If not in regexp mode, activate word search."
        ()
       (set yank-pointer-name
           (setq yank-pointer
-                (% (+ (or yank-pointer 0)
-                      ;; Add LENGTH here to ensure a positive result.
-                      length
-                      (% (- n) length))
-                   length)))
+                (mod (- (or yank-pointer 0) n)
+                     length)))
 
       (erase-buffer)
       (insert (nth yank-pointer ring))
@@ -1166,7 +1210,7 @@ If not in regexp mode, activate word search."
       ;; isearch-string stays the same
       t)
      ((or completion ; not nil, must be a string
-         (= 0 (length isearch-string))) ; shouldnt have to say this
+         (= 0 (length isearch-string))) ; shouldn't have to say this
       (if (equal completion isearch-string)  ;; no extension?
          (if completion-auto-help
              (with-output-to-temp-buffer "*Isearch completions*"
@@ -1199,7 +1243,6 @@ If there is no completion possible, say so and continue searching."
        (insert isearch-string))))
 
 \f
-;;;==============================================================
 ;; The search status stack (and isearch window-local variables, not used).
 ;; Need a structure for this.
 
@@ -1213,7 +1256,9 @@ If there is no completion possible, say so and continue searching."
          isearch-word (nth 6 cmd)
          isearch-invalid-regexp (nth 7 cmd)
          isearch-wrapped (nth 8 cmd)
-         isearch-barrier (nth 9 cmd))
+         isearch-barrier (nth 9 cmd)
+         isearch-within-brackets (nth 10 cmd)
+         isearch-case-fold-search (nth 11 cmd))
     (goto-char (car (cdr (cdr cmd))))))
 
 (defun isearch-pop-state ()
@@ -1226,11 +1271,11 @@ If there is no completion possible, say so and continue searching."
        (cons (list isearch-string isearch-message (point)
                    isearch-success isearch-forward isearch-other-end 
                    isearch-word
-                   isearch-invalid-regexp isearch-wrapped isearch-barrier)
+                   isearch-invalid-regexp isearch-wrapped isearch-barrier
+                   isearch-within-brackets isearch-case-fold-search)
              isearch-cmds)))
 
 \f
-;;;==================================================================
 ;; Message string
 
 (defun isearch-message (&optional c-q-hack ellipsis)
@@ -1241,7 +1286,10 @@ If there is no completion possible, say so and continue searching."
            isearch-message
            (isearch-message-suffix c-q-hack ellipsis)
            )))
-    (if c-q-hack m (message "%s" m))))
+    (if c-q-hack
+       m
+      (let ((message-log-max nil))
+       (message "%s" m)))))
 
 (defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
   ;; If about to search, and previous search regexp was invalid,
@@ -1250,11 +1298,17 @@ If there is no completion possible, say so and continue searching."
   (and isearch-invalid-regexp ellipsis
        (condition-case ()
           (progn (re-search-forward isearch-string (point) t)
-                 (setq isearch-invalid-regexp nil))
+                 (setq isearch-invalid-regexp nil
+                       isearch-within-brackets nil))
         (error nil)))
   ;; If currently failing, display no ellipsis.
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
+                  (if (and isearch-wrapped
+                           (if isearch-forward
+                               (> (point) isearch-opoint)
+                             (< (point) isearch-opoint)))
+                      "over")
                   (if isearch-wrapped "wrapped ")
                   (if isearch-word "word " "")
                   (if isearch-regexp "regexp " "")
@@ -1272,18 +1326,19 @@ If there is no completion possible, say so and continue searching."
            "")))
 
 \f
-;;;========================================================
 ;;; Searching
 
 (defun isearch-search ()
   ;; Do the search with the current search string.
   (isearch-message nil t)
-  (if search-upper-case
-      (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string)))
+  (if (and (eq isearch-case-fold-search t) search-upper-case)
+      (setq isearch-case-fold-search
+           (isearch-no-upper-case-p isearch-string isearch-regexp)))
   (condition-case lossage
       (let ((inhibit-quit nil)
            (case-fold-search isearch-case-fold-search))
        (if isearch-regexp (setq isearch-invalid-regexp nil))
+       (setq isearch-within-brackets nil)
        (setq isearch-success
              (funcall
               (cond (isearch-word
@@ -1295,6 +1350,7 @@ If there is no completion possible, say so and continue searching."
                     (t
                      (if isearch-forward 'search-forward 'search-backward)))
               isearch-string nil t))
+       (setq isearch-just-started nil)
        (if isearch-success
            (setq isearch-other-end
                  (if isearch-forward (match-beginning 0) (match-end 0)))))
@@ -1304,10 +1360,15 @@ If there is no completion possible, say so and continue searching."
 
     (invalid-regexp 
      (setq isearch-invalid-regexp (car (cdr lossage)))
+     (setq isearch-within-brackets (string-match "\\`Unmatched \\["
+                                                isearch-invalid-regexp))
      (if (string-match
          "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
          isearch-invalid-regexp)
-        (setq isearch-invalid-regexp "incomplete input"))))
+        (setq isearch-invalid-regexp "incomplete input")))
+    (error
+     ;; stack overflow in regexp search.
+     (setq isearch-invalid-regexp (car (cdr lossage)))))
 
   (if isearch-success
       nil
@@ -1318,199 +1379,60 @@ If there is no completion possible, say so and continue searching."
 
 
 \f
-;;;========================================================
 ;;; Highlighting
 
-(defun isearch-highlight (begin end))
-(defun isearch-dehighlight (totally))
-
-;; lemacs uses faces
-'(progn
-(defvar isearch-extent nil)
+(defvar isearch-overlay nil)
 
-(or (find-face 'isearch)       ;; this face is initialized by x-faces.el
-    (make-face 'isearch))      ;; since isearch is preloaded
-
-(defun isearch-lemacs-highlight (begin end)
-  (if (null isearch-highlight)
+(defun isearch-highlight (beg end)
+  (if (or (null search-highlight) (null window-system))
       nil
-    (if (and (extentp isearch-extent)
-            (eq (extent-buffer isearch-extent) (current-buffer)))
-       (set-extent-endpoints isearch-extent begin end)
-      (if (and (extentp isearch-extent)
-              (bufferp (extent-buffer isearch-extent))
-              (buffer-name (extent-buffer isearch-extent)))
-         (delete-extent isearch-extent))
-      (setq isearch-extent (make-extent begin end (current-buffer))))
-    (set-extent-face isearch-extent 'isearch)))
-
-(defun isearch-lemacs-dehighlight (totally)
-  (if (and isearch-highlight isearch-extent)
-      (if totally
-         (let ((inhibit-quit t))
-           (if (and (extentp isearch-extent)
-                    (bufferp (extent-buffer isearch-extent))
-                    (buffer-name (extent-buffer isearch-extent)))
-               (delete-extent isearch-extent))
-           (setq isearch-extent nil))
-       (if (and (extentp isearch-extent)
-                (bufferp (extent-buffer isearch-extent))
-                (buffer-name (extent-buffer isearch-extent)))
-           (set-extent-face isearch-extent 'default)
-         (isearch-dehighlight t)))))
-
-(fset 'isearch-highlight (symbol-function 'isearch-lemacs-highlight))
-(fset 'isearch-dehighlight (symbol-function 'isearch-lemacs-dehighlight))
-)
-
-;;;===========================================================
-;;; General utilities
+    (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))))
 
-;; (fset 'isearch-member-equal (symbol-function 'member)) ; for emacs 19
+(defun isearch-dehighlight (totally)
+  (if isearch-overlay
+      (delete-overlay isearch-overlay)))
 
-(defun isearch-member-equal (item list)
-  "Return non-nil if ITEM is `equal' to some item in LIST.
-Actually return the list whose car is that item."
-  (while (and list (not (equal item (car list))))
-    (setq list (cdr list)))
-  list)
+;;; General utilities
 
 
-(defun isearch-no-upper-case-p (string)
-  "Return t if there are no upper case chars in string.
-But upper case chars preceeded by \\ (but not \\\\) do not count since they
-have special meaning in a regexp."
+(defun isearch-no-upper-case-p (string regexp-flag)
+  "Return t if there are no upper case chars in STRING.
+If REGEXP-FLAG is non-nil, disregard letters preceded by `\\' (but not `\\\\')
+since they have special meaning in a regexp."
   (let ((case-fold-search nil))
-    (not (string-match "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]" string))))
+    (not (string-match (if regexp-flag "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]"
+                        "[A-Z]")
+                      string))))
 
 
-;;;=================================================
-;;; Special functions for lemacs events.
+;; Portability functions to support various Emacs versions.
 
 ;; To quiet the byte-compiler.
 (defvar unread-command-event)
+(defvar unread-command-events)
 (defvar last-command-event)
 
 (defun isearch-char-to-string (c)
-  (if (integerp c)
-      (make-string 1 c)
-   (make-string 1 (event-to-character c))))
+  (make-string 1 c))
 
 (defun isearch-text-char-description (c)
-  (isearch-char-to-string c))
+  (if (and (integerp c) (or (< c ?\ ) (= c ?\^?)))
+      (text-char-description c)
+    (isearch-char-to-string c)))
 
-(defun isearch-unread (char-or-event)
-  ;; General function to unread a character or event.
-  (if isearch-event-data-type
-      (setq unread-command-event char-or-event)
-    (setq unread-command-char char-or-event)))
+;; 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)
+  (setq unread-command-events
+       (append char-or-events unread-command-events)))
 
 (defun isearch-last-command-char ()
   ;; General function to return the last command character.
-  (if isearch-event-data-type
-      last-command-event
-    last-command-char))
-
+  last-command-char)
 
-
-\f
-;;;========================================================
-;;; Exiting in lemacs
-
-;; This is a large amount of code to support automatic termination of
-;; isearch-mode when a command (however it is invoked) is not an
-;; isearch command, or the buffer is switched out from under
-;; isearch-mode.   Only later versions of lemacs have the pre-command-hook.
-
-;;(if isearch-pre-command-hook-exists
-;;(progn
-
-;;;; This list must be modified whenever the available commands are modified.
-;;(mapcar (function (lambda (command)
-;;                 (put command 'isearch-command t)))
-;;     '(isearch-printing-char
-;;       isearch-return-char
-;;       isearch-repeat-forward
-;;       isearch-repeat-backward
-;;       isearch-delete-char
-;;       isearch-abort 
-;;       isearch-quote-char
-;;       isearch-exit  
-;;       isearch-printing-char
-;;       isearch-printing-char
-;;       isearch-yank-word     
-;;       isearch-yank-line     
-;;       isearch-*-char        
-;;       isearch-*-char        
-;;       isearch-|-char        
-;;       isearch-toggle-regexp
-;;       isearch-edit-string
-;;       isearch-mode-help     
-;;       isearch-ring-advance
-;;       isearch-ring-retreat
-;;       isearch-ring-advance-edit
-;;       isearch-ring-retreat-edit
-;;       isearch-whitespace-chars
-;;       isearch-complete      
-;;       isearch-complete-edit
-;;       isearch-edit-string
-;;       isearch-toggle-regexp
-;;       ;; The following may not be needed since isearch-mode is off already.
-;;       isearch-forward-exit-minibuffer
-;;       isearch-reverse-exit-minibuffer
-;;       isearch-nonincremental-exit-minibuffer))
-
-;;(defun isearch-pre-command-hook ()
-;;  ;;
-;;  ;; For use as the value of `pre-command-hook' when isearch-mode is active.
-;;  ;; If the command about to be executed is not one of the isearch commands,
-;;  ;; then isearch-mode is turned off before that command is executed.
-;;  ;;
-;;  ;; If the command about to be executed is self-insert-command, or is a
-;;  ;; keyboard macro of a single key sequence which is bound to self-insert-
-;;  ;; command, then we add those chars to the search ring instead of inserting
-;;  ;; them in the buffer.  In this way, the set of self-searching characters
-;;  ;; need not be exhaustively enumerated, but is derived from other maps.
-;;  ;;
-;;  (isearch-maybe-frob-keyboard-macros)
-;;  (if (and (symbolp this-command)
-;;        (get this-command 'isearch-command))
-;;      nil
-;;    (isearch-done)))
-
-;;(defun isearch-maybe-frob-keyboard-macros ()
-;;  ;;
-;;  ;; If the command about to be executed is `self-insert-command' then change
-;;  ;; the command to `isearch-printing-char' instead, meaning add the last-
-;;  ;; typed character to the search string.
-;;  ;;
-;;  ;; If `this-command' is a string or a vector (that is, a keyboard macro)
-;;  ;; and it contains only one command, which is bound to self-insert-command,
-;;  ;; then do the same thing as for self-inserting commands: arrange for that
-;;  ;; character to be added to the search string.  If we didn't do this, then
-;;  ;; typing a compose sequence (a la x-compose.el) would terminate the search
-;;  ;; and insert the character, instead of searching for that character.
-;;  ;;
-;;  (cond ((eq this-command 'self-insert-command)
-;;      (setq this-command 'isearch-printing-char))
-;;     ((and (stringp this-command)
-;;           (eq (key-binding this-command) 'self-insert-command))
-;;      (setq last-command-char (aref this-command 0)
-;;            last-command-event (character-to-event last-command-char)
-;;            this-command 'isearch-printing-char))
-;;     ((and (vectorp this-command)
-;;           (eq (key-binding this-command) 'self-insert-command))
-;;      (let* ((desc (aref this-command 0))
-;;             (code (cond ((integerp desc) desc)
-;;                         ((symbolp desc) (get desc character-set-property))
-;;                         ((consp desc)
-;;                          (and (null (cdr desc))
-;;                               (get (car desc) character-set-property)))
-;;                         (t nil))))
-;;        (if code
-;;            (setq last-command-char code
-;;                  last-command-event (character-to-event last-command-char)
-;;                  this-command 'isearch-printing-char))))
-;;     ))
-
-;;))
+;;; isearch.el ends here