changeset 1142:7fc9de9d8cef

*** empty log message ***
author Richard M. Stallman <rms@gnu.org>
date Mon, 14 Sep 1992 22:31:47 +0000
parents d4f6d7467916
children 0b4552590bb8
files lisp/isearch.el
diffstat 1 files changed, 875 insertions(+), 486 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/isearch.el	Mon Sep 14 22:11:23 1992 +0000
+++ b/lisp/isearch.el	Mon Sep 14 22:31:47 1992 +0000
@@ -1,11 +1,13 @@
-;; isearch-mode.el --- incremental search minor mode.
-
+;; Incremental search minor mode.
 ;; Copyright (C) 1992 Free Software Foundation, Inc.
 
-;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
-;; Version: 1.2
+;; LCD Archive Entry:
+;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu
+;; |A minor mode replacement for isearch.el.
+;; |$Date: 92/09/14 16:26:02 $|$Revision: 1.4 $|~/modes/isearch-mode.el
 
-;; This file is part of GNU Emacs.
+;; This file is not yet part of GNU Emacs, but it is based almost
+;; entirely on isearch.el which is part of GNU Emacs.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY.  No author or distributor
@@ -22,8 +24,6 @@
 ;; file named COPYING.  Among other things, the copyright notice
 ;; and this notice must be preserved on all copies.
 
-;;; Commentary:
-
 ;;;====================================================================
 ;; Instructions
 
@@ -39,48 +39,105 @@
 ;; (fset 'isearch 'isearch-mode)
 ;; (autoload 'isearch-mode "isearch-mode")
 
+;; 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' and `isearch-mode-meta-map' which are given
-;; bindings close to the default characters of isearch.el for
-;; version 19.  With `isearch-mode', however, you can bind
-;; multi-character keys and it should be easier to add new commands.
+;; `isearch-mode-map' which is given bindings close to the default
+;; characters of the original isearch.el.  With `isearch-mode',
+;; however, you can bind multi-character keys and it should be easier
+;; to add new commands.  One bug though: keys with meta-prefix cannot
+;; be longer than two chars.  Also see minibuffer-local-isearch-map
+;; for bindings active during `isearch-edit-string'.
 
-;; Note to epoch and emacs version 19 users: isearch-mode should
-;; work even if you switch windows with the mouse.  However, if
-;; you isearch in a buffer that is also displayed in another window,
-;; when you switch to that other window you will still be in
-;; isearch mode but not necessarily in the right state for it to work.
-;; So ... don't do it unless you are in an experimental mood.
-;; You can also experiment with the window-local-variable routines
-;; contained in this package but not yet used.
-;; Also, I am not sure what happens when you return to an isearching
-;; buffer; ideally, the echo area should redisplay the searching status.
-;; A select-window-hook might be useful.
+;; Note to emacs version 19 users: isearch-mode should work even if
+;; you switch windows with the mouse, in which case isearch-mode is
+;; terminated automatically before the switch.  This is true of lemacs
+;; too, with a few more cleanups I've neglected in this release. 
+;; No one has supplied patches for epoch yet.
 
-;;; Change Log:
+;; The search ring and completion commands automatically put you in
+;; the minibuffer to edit the string.  This gives you a chance to
+;; modify the search string before executing the search.  There are
+;; three commands to terminate the editing: C-s and C-r exit the
+;; minibuffer and search forward and reverse respectively, while C-m
+;; exits and does a nonincremental search.
+
+;; Exiting immediately from isearch uses isearch-edit-string instead
+;; of nonincremental-search, if search-nonincremental-instead is non-nil.
+;; The name of this option should probably be changed if we decide to
+;; keep the behavior.  No point in forcing nonincremental search until
+;; the last possible moment.
+
+;; TODO
+;; - Integrate the emacs 19 generalized commmand history.
+;; - Think about incorporating query-replace.
+;; - Hooks and options for failed search.
 
 ;;;====================================================================
+;;; Change History
 
+;;; $Header: /import/kaplan/kaplan/liberte/Isearch/RCS/isearch-mode.el,v 1.4 92/09/14 16:26:02 liberte Exp Locker: liberte $
+;;; $Log:	isearch-mode.el,v $
+;;; 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
-;;; Several new commands and features have been added.  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 searching is supported, using a recursive edit. If
-;;; isearching is started non-interactively by calling one of the
-;;; isearch commands (e.g. isearch-forward), it does not return
-;;; until the search is completed.  You should still be able switch
-;;; buffers, so be careful not to get things confused.
-;;; 
+;;; 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:
+
+
+;;;=========================================================================
+;;; 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 nil) ;; emacs 19
+(defconst isearch-pre-command-hook-exists (boundp 'pre-command-hook)) ;; lemacs
+(defconst isearch-events-exist nil)  ;; lemacs
+
 
 ;;;=========================================================================
 ;;; The following, defined in loaddefs.el, are still used with isearch-mode.
@@ -111,180 +168,202 @@
 
 (defvar search-caps-disable-folding t
   "*If non-nil, upper case chars disable case fold searching.
-This does not yet apply to yanked strings, however.")
+That is, upper and lower case chars must match exactly.
+This applies no matter where the chars come from, but does not
+apply to chars prefixed with \\, for regexps.
+If this value is 'not-yanks, yanked text is always downcased.")
 
 (defvar search-nonincremental-instead t
   "*If non-nil, do a nonincremental search instead if exiting immediately.
-The default value of t reflects the default behavior of old  
-isearch.")
+Actually, `isearch-edit-string' is called to let you enter the search
+string, and RET terminates editing and does a nonincremental search.")
 
 (defconst search-whitespace-regexp "\\s-+"
   "*If non-nil, regular expression to match a sequence of whitespace chars.
 You might want to use something like \"[ \\t\\r\\n]+\" instead.")
 
+(defvar search-highlight nil
+  "*Whether isearch and query-replace should highlight the text which 
+currently matches the search-string.")
+
+
+(defvar isearch-mode-hook nil
+  "Function(s) to call after starting up an incremental search.")
+
+(defvar isearch-mode-end-hook nil
+  "Function(s) to call after terminating an incremental search.")
+
 ;;;==================================================================
 ;;; Search ring.
-;;; "regex" == "regexp".  One should become the standard term.
 
 (defvar search-ring nil
   "List of search string sequences.")
-(defvar regex-search-ring nil   ;; Is `regex' the new spelling?
+(defvar regexp-search-ring nil
   "List of regular expression search string sequences.")
 
 (defconst search-ring-max 16
   "*Maximum length of search ring before oldest elements are thrown away.")
-(defconst regex-search-ring-max 16
-  "*Maximum length of regex search ring before oldest elements are thrown away.")
+(defconst regexp-search-ring-max 16
+  "*Maximum length of regexp search ring before oldest elements are thrown away.")
 
 (defvar search-ring-yank-pointer nil
   "The tail of the search ring whose car is the last thing searched for.")
-(defvar regex-search-ring-yank-pointer nil
+(defvar regexp-search-ring-yank-pointer nil
   "The tail of the regular expression search ring whose car is the last
 thing searched for.")
 
+(defvar search-ring-update nil
+  "*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
   "Keymap for isearch-mode.")
 
-(defvar isearch-mode-meta-map nil
-  "Keymap for isearch-mode for keys with meta char prefix.")
+(or isearch-mode-map
+    (let* ((i 0)
+	   (map (make-keymap))
+	   (len (length map)))
+
+      ;; Control chars, by default, end isearch mode transparently.
+      (while (< i ?\ )
+	(define-key map (make-string 1 i) 'isearch-other-control-char)
+	(setq i (1+ i)))
+
+      ;; Printing chars extend the selection by default.
+      ;; This assumes that all remaining chars are printable.
+      (while (< i len)
+	(define-key map (make-string 1 i) 'isearch-printing-char)
+	(setq i (1+ i)))
+
+      ;; 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)
+    
+      (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)
+      (define-key map " " 'isearch-whitespace-chars)
+    
+      (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)
+
+      ;; 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-keymap))
+      (setq i 0)
+      (while (< i len)
+	(define-key map (char-to-string (+ 128 i)) ;; Needs to be generalized.
+	  'isearch-other-meta-char)
+	(setq i (1+ i)))
+
+      (define-key map "\M-n" 'isearch-ring-advance)
+      (define-key map "\M-p" 'isearch-ring-retreat)
+      (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))
+      
+      (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-regexp)
+;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
 
 
-;; To handle meta char prefix keys, define another full keymap.
-;; The same must be done for any other prefix keys.
-;; It would be simpler to disable to global keymap, and/or
-;; have a default local key binding for any key not otherwise bound.
-(if isearch-mode-meta-map
-    nil
-  (setq isearch-mode-meta-map 	
-	(list 'keymap (make-vector 128 'isearch-other-meta-char)))
-  (define-key isearch-mode-meta-map "n" 'isearch-ring-advance)
-  (define-key isearch-mode-meta-map "p" 'isearch-ring-retreat)
-  (define-key isearch-mode-meta-map " " 'isearch-whitespace-chars)  
-;for regexps
-
-;;  (define-key isearch-mode-meta-map "?" nil) ; my help key is M-?
-  )
-
-(if isearch-mode-map
-    nil
-  (let ((i 0)
-
-	;; Printing chars extend the selection by default.
-	(array (make-vector 128 'isearch-printing-char)))
-
-    ;; Non-printing chars by default suspend isearch mode transparently
-    (while (< i ?\ )
-      (aset array i 'isearch-other-control-char)
-      (setq i (1+ i)))
-
-    (setq i ?A)
-    (while (<= i ?Z)
-      (aset array i 'isearch-upper-case-char)
-      (setq i (1+ i)))
-
-    (setq isearch-mode-map (list 'keymap array))
-
-    ;; You can reenable global keys by unbinding them locally.  
+(defvar minibuffer-local-isearch-map nil
+  "Keymap for editing isearch strings in the minibuffer.")
 
-    ;; For the help char this doesnt work quite as expected because
-    ;; isearch-mode is not a major mode, and the echo area is not
-    ;; restored after the help command.
-    ;; Also, we should not assume that the help-command is on C-h.
-    ;; If it is not, and the prefix is not the meta-char, we would
-    ;; have to create another map for its prefix.
-;    (define-key isearch-mode-map "\C-h" nil)
-
-    ;; Several non-printing chars change the searching behavior.
-    (define-key isearch-mode-map "\C-s" 'isearch-repeat-forward)
-    (define-key isearch-mode-map "\C-r" 'isearch-repeat-backward)
-    (define-key isearch-mode-map "\177" 'isearch-delete-char)
-    (define-key isearch-mode-map "\C-g" 'isearch-quit)
-    
-
-    (define-key isearch-mode-map "\C-q" 'isearch-quote-char)
-
-    ;;  (define-key isearch-mode-map "\r" 'isearch-return-char)
-    ;; For version 19, CR (C-m) terminates search and LFD (C-j) matches eol.
-    (define-key isearch-mode-map "\r" 'isearch-exit)
-    (define-key isearch-mode-map "\C-j" 'isearch-printing-char)
-    
-
-    (define-key isearch-mode-map "\C-w" 'isearch-yank-word)
-    (define-key isearch-mode-map "\C-y" 'isearch-yank-line)
-
-    (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp)
-    (define-key isearch-mode-map "\C-^" 'isearch-edit-string)
-
-    ;; define keys for regexp chars * ? |
-    (define-key isearch-mode-map "*" 'isearch-*-char)
-    (define-key isearch-mode-map "?" 'isearch-*-char)
-    (define-key isearch-mode-map "|" 'isearch-|-char)
-
-    ;; Assumes meta-prefix-char is \e.
-    ;; isearch-mode-meta-map must be a keymap before this.
-    (define-key isearch-mode-map "\e" isearch-mode-meta-map)
-    ))
+(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 made buffer-local during searching.
+;; These are all set with setq while isearching
+;; and bound locally while editing the search string.
+
+(defvar isearch-forward nil)	; Searching in the forward direction.
+(defvar isearch-regexp nil)	; Searching for a regexp.
+(defvar isearch-word nil)	; Searching for words.
 
-(defvar isearch-cmds nil
-  "Stack of search status sets.")
-(defvar isearch-string ""
-  "The current search string.")
-(defvar isearch-message ""
-  "The text-char-description version of isearch-string")
-(defvar isearch-success t)
-(defvar isearch-forward nil)
-(defvar isearch-other-end nil	
-  "Start of last match if forward, end if backward.")
-(defvar isearch-invalid-regexp nil)
-(defvar isearch-wrapped nil)
+(defvar isearch-cmds nil)   ; Stack of search status sets.
+(defvar isearch-string "")  ; The current search string.
+(defvar isearch-message "") ; text-char-description version of isearch-string
+
+(defvar isearch-success t)		; Searching is currently successful.
+(defvar isearch-invalid-regexp nil)	; Regexp not well formed.
+(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-regexp nil)
-(defvar isearch-case-fold-search nil
-  "Value of case-fold-search while actually searching.")
+(defvar isearch-case-fold-search nil) ; case-fold-search while searching.
 
 (defvar isearch-adjusted nil)
 (defvar isearch-slow-terminal-mode nil)
-(defvar isearch-small-window nil
-  "If t, using a small window.")
-(defvar isearch-found-point nil
-  "to restore point from a small window.")
+;;; If t, using a small window.
+(defvar isearch-small-window nil)
+(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)
 
-(defvar isearch-found-start nil
-  "This is the window-start value found by the search.")
-(defvar isearch-opoint 0)
-(defvar isearch-window-configuration nil
-  "The window configuration active at the beginning of the search.")
-(defvar isearch-old-local-map [])
-
-(defvar isearch-yank-flag nil
-  "Flag to indicate a yank occurred, so don't move the cursor.")
+;; Flag to indicate a yank occurred, so don't move the cursor.
+(defvar isearch-yank-flag nil)
 
-(defvar isearch-op-fun nil
-  "A function to be called after each input character is processed.
-(It is not called after characters that exit the search.)
-It is only set from an optional argument to `isearch-mode'.")
-
-;; This is a global variable to avoid byte-compile warnings.
-(defvar isearch-last-command-char -1
-  "Last command char.")
+;;; A function to be called after each input character is processed.
+;;; (It is not called after characters that exit the search.)
+;;; It is only set from an optional argument to `isearch-mode'.
+(defvar isearch-op-fun nil)
 
-(defvar isearch-mode-hook nil
-  "List of functions to call after starting up an incremental search.
-See `isearch-modal' for an example.
-Set with `(setq isearch-mode-hook (cons 'myhook isearch-mode-hook))
-where myhook can be a function name or lambda expression.")
+;;;  Is isearch-mode in a recursive edit for modal searching.
+(defvar isearch-recursive-edit nil)
 
-(defvar isearch-mode-end-hook nil
-  "List of functions to call after terminating an incremental search.
-See `isearch-mode-hook' for more details.")
+;;; Should isearch be terminated after doing one search?
+(defvar isearch-nonincremental nil)
+
+;; New value of isearch-forward after isearch-edit-string.
+(defvar isearch-new-forward nil)
+
 
 ;;;==============================================================
 ;; Minor-mode-alist changes - kind of redundant with the
@@ -294,117 +373,107 @@
     (nconc minor-mode-alist
 	   (list '(isearch-mode isearch-mode))))
 
-(defvar isearch-mode nil)
+(defvar isearch-mode nil) ;; Name of the minor mode, if non-nil.
 (make-variable-buffer-local 'isearch-mode)
 
 ;;;===============================================================
 ;;; Entry points to isearch-mode.
-;;; These four functions should be moved to loaddefs.el
+;;; These four functions should replace those in loaddefs.el
+;;; An alternative is to fset isearch-forward etc to isearch-mode,
+;;; and look at this-command to set the options accordingly.
 
-(defun isearch-forward ()
+(defun isearch-forward (&optional regexp-p)
   "\
 Do incremental search forward.
-As you type characters, they add to the search string and are found.
-
+With a prefix argument, do an incremental regular expression search instead.
 \\<isearch-mode-map>
-Type \\[isearch-delete-char] to cancel characters from end of search  
-string.
+As you type characters, they add to the search string and are found.
+The following non-printing keys are bound in `isearch-mode-map'.  
+
+Type \\[isearch-delete-char] to cancel characters from end of search string.
 Type \\[isearch-exit] to exit, leaving point at location found.
-Type \\[isearch-repeat-forward] to search again forward,  
-\\[isearch-repeat-backward] to search again backward.
-Type \\[isearch-toggle-regexp] to toggle regular expression with normal searching.
-Type \\[isearch-yank-word] to yank word from buffer onto end of  
-search string and search for it.
-Type \\[isearch-yank-line] to yank rest of line onto end of search string, etc.
+Type LFD (C-j) to match end of line.
+Type \\[isearch-repeat-forward] to search again forward,\
+ \\[isearch-repeat-backward] to search again backward.
+Type \\[isearch-yank-word] to yank word from buffer onto end of search\
+ string and search for it.
+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 C-j to match end of line.
+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.
+\\[isearch-abort] when search is successful aborts and moves point to\
+ starting point.
 
 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.
-
-Other control and meta characters terminate the search
- and are then executed normally.
-
-\\[isearch-quit] while searching or when search has failed
- cancels input back to what has been found successfully.
-\\[isearch-quit] when search is successful aborts and moves point to starting point.
+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.
 
-All of these keys are bound in `isearch-mode-map' and
-`isearch-mode-meta-map'.  If `isearch-forward' is called
-non-interactively, it does not return to the calling function until
-the search is done."
-  (interactive)
-  (if (interactive-p)
-      (isearch-mode t)
-    (isearch-modal t)))
+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').
 
-(defun isearch-forward-regexp ()
+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))))
+
+(defun isearch-forward-regexp (&optional regexp-p)
   "\
 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)
-  (if (interactive-p)
-      (isearch-mode t t)
-    (isearch-modal t t)))
+  (isearch-mode t (null regexp-p) nil (not (interactive-p))))
 
-(defun isearch-backward ()
+(defun isearch-backward (&optional regexp-p)
   "\
 Do incremental search backward.
+With a prefix argument, do a regular expression search instead.
 See \\[isearch-forward] for more information."
   (interactive)
-  (if (interactive-p)
-      (isearch-mode nil)
-    (isearch-modal nil)))
+  (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p))))
 
-(defun isearch-backward-regexp ()
+(defun isearch-backward-regexp (&optional regexp-p)
   "\
 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)
-  (if (interactive-p)
-      (isearch-mode nil t)
-    (isearch-modal nil t)))
+  (isearch-mode nil (null regexp-p) nil (not (interactive-p))))
 
 
-(defun isearch-modal (forward &optional regexp op-fun)
-  ;; As an example of using the hooks, 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.
-  ;; This is used if the above functions are called non-interactively.
-  (let ((isearch-mode-hook 
-	 (cons (function (lambda () (recursive-edit)))
-	       isearch-mode-hook))
-	(isearch-mode-end-hook
-	 (cons (function (lambda () (exit-recursive-edit)))
-	       isearch-mode-end-hook)))
-    (isearch-mode forward regexp op-fun)))
+(defun isearch-mode-help ()
+  (interactive)
+  (describe-function 'isearch-forward)
+  (isearch-update))
 
 
 ;;;==================================================================
 ;; isearch-mode only sets up incremental search for the minor mode.
 ;; All the work is done by the isearch-mode commands.
 
-(defun isearch-mode (forward &optional regexp op-fun)
+;; Not used yet:
+;;(defconst isearch-commands '(isearch-forward isearch-backward
+;;			     isearch-forward-regexp isearch-backward-regexp)
+;;  "List of commands for which isearch-mode does not recursive-edit.")
+			     
+
+(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
   "Start isearch minor mode.  Called by isearch-forward, etc."
-  ;; Make buffer-local variables for isearching.
-  ;; We really need window-local variables.
-  (mapcar 
-   'make-local-variable
-   '(isearch-forward 
-     isearch-regexp isearch-string isearch-message
-     isearch-case-fold-search
-     isearch-cmds isearch-success isearch-wrapped
-     isearch-barrier isearch-adjusted isearch-invalid-regexp
-     isearch-slow-terminal-mode isearch-other-end isearch-small-window
-     isearch-found-point isearch-found-start isearch-opoint 
-     isearch-window-configuration isearch-old-local-map))
 
   ;; Initialize global vars.
   (setq isearch-forward forward
 	isearch-regexp regexp
+	isearch-word word-p
 	isearch-op-fun op-fun
 	isearch-case-fold-search case-fold-search
 	isearch-string ""
@@ -416,20 +485,17 @@
 	isearch-adjusted nil
 	isearch-yank-flag nil
 	isearch-invalid-regexp nil
-	isearch-slow-terminal-mode (and (<= (baud-rate) search-slow-speed)
+	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-found-point nil
 
-	isearch-found-start nil
 	isearch-opoint (point)
 	isearch-window-configuration (current-window-configuration)
-	isearch-old-local-map (current-local-map)
-
-;;	inhibit-quit t
-	)
+	isearch-old-local-map (current-local-map))
+  (if isearch-pre-command-hook-exists
+      (add-hook 'pre-command-hook 'isearch-pre-command-hook))
   (setq	isearch-mode " Isearch")  ;; forward? regexp?
   (set-buffer-modified-p (buffer-modified-p)) ; update modeline
 
@@ -438,6 +504,11 @@
   (use-local-map isearch-mode-map)
   (isearch-update)
   (run-hooks 'isearch-mode-hook)
+
+  ;; 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))
   )
 
 
@@ -446,16 +517,19 @@
 
 (defun isearch-update ()
   ;; Called after each command to update the display.  
-  (or unread-command-char
+  (if (if isearch-events-exist
+	  (null unread-command-event)
+	(if isearch-frames-exist
+	    (null unread-command-char)
+	  (< unread-command-char 0)))
       (progn
 	(if (not (input-pending-p))
 	    (isearch-message))
 	(if (and isearch-slow-terminal-mode
 		 (not (or isearch-small-window 
 			  (pos-visible-in-window-p))))
-	    (progn
+	    (let ((found-point (point)))
 	      (setq isearch-small-window t)
-	      (setq isearch-found-point (point))
 	      (move-to-window-line 0)
 	      (let ((window-min-height 1))
 		(split-window nil (if (< search-slow-window-lines 0)
@@ -469,7 +543,12 @@
 					     (window-hscroll))
 			 (set-window-hscroll (selected-window) 0))
 		(other-window 1))
-	      (goto-char isearch-found-point)))))
+	      (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)))
+	))
   (setq ;; quit-flag nil  not for isearch-mode
    isearch-adjusted nil
    isearch-yank-flag nil)
@@ -479,55 +558,65 @@
 (defun isearch-done ()
   ;; Called by all commands that terminate isearch-mode.
   (use-local-map isearch-old-local-map)
-  (setq isearch-found-start (window-start (selected-window)))
-  (setq isearch-found-point (point))
-  (set-window-configuration isearch-window-configuration)
+  ;; (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 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)))
+
+  (setq isearch-mode nil)
+  (set-buffer-modified-p (buffer-modified-p))  ;; update modeline
 
   (if (> (length isearch-string) 0)
       ;; Update the ring data.
       (if isearch-regexp 
-	  (if (not (setq regex-search-ring-yank-pointer
-			 (memq isearch-string regex-search-ring)))
+	  (if (not (setq regexp-search-ring-yank-pointer
+			 ;; really need equal test instead of eq.
+			 (isearch-member-equal 
+			  isearch-string regexp-search-ring)))
 	      (progn
-		(setq regex-search-ring (cons isearch-string regex-search-ring)
-		      regex-search-ring-yank-pointer regex-search-ring)
-		(if (> (length regex-search-ring) regex-search-ring-max)
-		    (setcdr (nthcdr (1- search-ring-max) regex-search-ring)
+		(setq regexp-search-ring
+		      (cons isearch-string regexp-search-ring)
+		      regexp-search-ring-yank-pointer regexp-search-ring)
+		(if (> (length regexp-search-ring) regexp-search-ring-max)
+		    (setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
 			    nil))))
 	(if (not (setq search-ring-yank-pointer
-		       (memq isearch-string search-ring)))
+		       ;; really need equal test instead of eq.
+		       (isearch-member-equal isearch-string search-ring)))
 	    (progn
 	      (setq search-ring (cons isearch-string search-ring)
 		    search-ring-yank-pointer search-ring)
 	      (if (> (length search-ring) search-ring-max)
 		  (setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
 
-  ;; 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 ""))
-  (if isearch-small-window
-      (goto-char isearch-found-point)
-    ;; Exiting the save-window-excursion clobbers window-start; restore it.
-    (set-window-start (selected-window) isearch-found-start t))
+  (run-hooks 'isearch-mode-end-hook)
+  (if isearch-recursive-edit (exit-recursive-edit)))
+
+;;;=======================================================
+;;; Switching buffers should first terminate isearch-mode.
+;;; This is done quite differently for each varient of emacs.
+;;; For lemacs, see Exiting in lemacs below
 
-  ;; Kill buffer-local variables for isearching
-  (mapcar 
-   'kill-local-variable
-   '(isearch-forward 
-     isearch-regexp isearch-string isearch-message
-     isearch-case-fold-search
-     isearch-cmds isearch-success isearch-wrapped
-     isearch-barrier isearch-adjusted isearch-invalid-regexp
-     isearch-slow-terminal-mode isearch-other-end isearch-small-window
-     isearch-found-point isearch-found-start isearch-opoint 
-     isearch-window-configuration isearch-old-local-map))
+;; For Emacs 19, the frame switch event is handled.
+(defun isearch-switch-frame-handler ()
+  (interactive) ;; Is this necessary?
+  ;; First terminate isearch-mode.
+  (isearch-done)
+  (select-frame (car (cdr (isearch-last-command-char)))))
 
-  (setq isearch-mode nil)
-  (set-buffer-modified-p (buffer-modified-p))
-  (run-hooks 'isearch-mode-end-hook)
-  )
+;;;========================================================
 
 
 ;;;====================================================
@@ -537,40 +626,168 @@
   "Exit search normally.
 However, if this is the first command after starting incremental
 search and `search-nonincremental-instead' is non-nil, do a
-nonincremental search instead."
-
+nonincremental search instead via `isearch-edit-string'."
   (interactive)
   (if (and search-nonincremental-instead 
 	   (= 0 (length isearch-string)))
-      (nonincremental-search isearch-forward isearch-regexp))
+      (let ((isearch-nonincremental t))
+	(isearch-edit-string)))
   (isearch-done))
 
 
 (defun isearch-edit-string ()
-  "Edit the search string in the minibuffer and return to incremental search."
-  ;; This doesnt back up the search point.
+  "Edit the search string in the minibuffer.
+The following additional command keys are active while editing.
+\\<minibuffer-local-isearch-map>
+\\[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-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-complete-edit] to complete the search string using the search ring.
+
+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?
   (interactive)
-  (setq isearch-string (read-string (isearch-message-prefix) isearch-string)
-	isearch-message (mapconcat 'text-char-description
-				   isearch-string ""))
-  (isearch-push-state)
-  (isearch-search)
-  (isearch-update))
+  (condition-case err
+      (let ((minibuffer-local-map minibuffer-local-isearch-map)
+	    isearch-nonincremental	; should search nonincrementally?
+
+	    ;; Locally bind all isearch global variables to protect them
+	    ;; from recursive isearching.
+	    ;; isearch-string -message and -forward are not bound
+	    ;; so they may be changed.  Instead, save the values.
+	    (isearch-new-string isearch-string)
+	    (isearch-new-message isearch-message)
+	    (isearch-new-forward isearch-forward)
+	    (isearch-new-word isearch-word)
+
+	    (isearch-regexp isearch-regexp)
+	    (isearch-op-fun isearch-op-fun)
+	    (isearch-cmds isearch-cmds)
+	    (isearch-success isearch-success)
+	    (isearch-wrapped isearch-wrapped)
+	    (isearch-barrier isearch-barrier)
+	    (isearch-adjusted isearch-adjusted)
+	    (isearch-yank-flag isearch-yank-flag)
+	    (isearch-invalid-regexp isearch-invalid-regexp)
+	    (isearch-other-end isearch-other-end)
+	    (isearch-opoint isearch-opoint)
+	    (isearch-slow-terminal-mode isearch-slow-terminal-mode)
+	    (isearch-small-window isearch-small-window)
+	    (isearch-recursive-edit isearch-recursive-edit)
+	    ;; Save current configuration so we can restore it here.
+	    (isearch-window-configuration (current-window-configuration))
+	    )
+
+	;; Actually terminate isearching until editing is done.
+	;; 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)
+	  (exit nil))			; was recursive editing
+
+	(isearch-message) ;; for read-char
+	(unwind-protect
+	    (let* (;; Why does following read-char echo?  
+		   ;;(echo-keystrokes 0) ;; not needed with above message
+		   (cursor-in-echo-area t)
+		   (e (if isearch-events-exist (allocate-event) (read-char)))
+		   ;; Binding minibuffer-history-symbol to nil is a work-around
+		   ;; for some incompatibility with gmhist.
+		   (minibuffer-history-symbol))
+	      ;; 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
+	      ;; read a key the normal way.
+	      ;; Word search does not apply (yet) to regexp searches,
+	      ;; 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-events-exist
+			    (or (event-to-character (next-command-event e)) 0)
+			  e))))
+		  (setq isearch-word t  ;; so message-prefix is right
+			isearch-new-word t)
+		(isearch-unread e))
+	      (setq isearch-new-string (read-string (isearch-message-prefix)
+						    isearch-string)
+		    isearch-new-message (mapconcat 'text-char-description
+						   isearch-new-string "")))
+	  ;; Always resume isearching by restarting it.
+	  (isearch-mode isearch-forward 
+			isearch-regexp 
+			isearch-op-fun 
+			isearch-recursive-edit
+			isearch-word)
+
+	  ;; Copy new local values to isearch globals
+	  (setq isearch-string isearch-new-string
+		isearch-message isearch-new-message
+		isearch-forward isearch-new-forward
+		isearch-word isearch-new-word))
+
+	;; Empty isearch-string means use default.
+	(if (= 0 (length isearch-string))
+	    (setq isearch-string (if isearch-regexp search-last-regexp
+				   search-last-string))
+	  ;; Set last search string now so it is set even if we fail.
+	  (if search-last-regexp
+	      (setq search-last-regexp isearch-string)
+	    (setq search-last-string isearch-string)))
+
+	;; Reinvoke the pending search.
+	(isearch-push-state)
+	(isearch-search)
+	(isearch-update)
+	(if isearch-nonincremental 
+	    (progn
+	      ;; (sit-for 1) ;; needed if isearch-done does: (message "")
+	      (isearch-done))))
+
+    (quit  ; handle abort-recursive-edit
+     (isearch-abort)  ;; outside of let to restore outside global values
+     )))
+
+(defun isearch-nonincremental-exit-minibuffer ()
+  (interactive)
+  (setq isearch-nonincremental t)
+  (exit-minibuffer))
+
+(defun isearch-forward-exit-minibuffer ()
+  (interactive)
+  (setq isearch-new-forward t)
+  (exit-minibuffer))
+
+(defun isearch-reverse-exit-minibuffer ()
+  (interactive)
+  (setq isearch-new-forward nil)
+  (exit-minibuffer))
 
 
-(defun isearch-quit ()
-  "Quit incremental search mode if searching is successful.
-Otherwise, revert to previous successful search and continue searching."
+(defun isearch-abort ()
+  "Abort incremental search mode if searching is successful, signalling quit.
+Otherwise, revert to previous successful search and continue searching.
+Use `isearch-exit' to quit without signalling."
   (interactive)
-  (ding)
+;;  (ding)  signal instead below, if quiting
   (discard-input)
   (if isearch-success
       ;; If search is successful, move back to starting point
       ;; and really do quit.
       (progn (goto-char isearch-opoint)
-	     (isearch-done))  ; exit and quit
-    ;; If search is failing, rub out until it is once more
-    ;;  successful.
+	     (isearch-done)   ; exit isearch
+	     (signal 'quit '(isearch)))  ; and pass on quit signal
+    ;; If search is failing, rub out until it is once more successful.
     (while (not isearch-success) (isearch-pop-state))
     (isearch-update)))
 
@@ -582,18 +799,16 @@
       (if (equal isearch-string "")
 	  ;; If search string is empty, use last one.
 	  (setq isearch-string
-;;		(if isearch-regexp
-;;		    search-last-regexp search-last-string)
 		(or (if isearch-regexp
-			(if regex-search-ring-yank-pointer
-			    (car regex-search-ring-yank-pointer)
-			  (car regex-search-ring))
+			(if regexp-search-ring-yank-pointer
+			    (car regexp-search-ring-yank-pointer)
+			  (car regexp-search-ring))
 		      (if search-ring-yank-pointer
 			  (car search-ring-yank-pointer)
 			(car search-ring)))
 		    "")
 		isearch-message
-		(mapconcat 'text-char-description
+		(mapconcat 'isearch-text-char-description
 			   isearch-string ""))
 	;; If already have what to search for, repeat it.
 	(or isearch-success
@@ -631,6 +846,7 @@
   ;; The status stack is left unchanged.
   (interactive)
   (setq isearch-regexp (not isearch-regexp))
+  (if isearch-regexp (setq isearch-word nil))
   (isearch-update))
 
 (defun isearch-delete-char ()
@@ -645,24 +861,28 @@
 
 (defun isearch-yank (chunk)
   ;; Helper for isearch-yank-word and isearch-yank-line
-  (let ((word (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))))))
-    (if isearch-regexp (setq word (regexp-quote word)))
-    (setq isearch-string (concat isearch-string word)
+  (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))))))
+    ;; Downcase the string if not supposed to case-fold yanked strings.
+    (if (and isearch-case-fold-search
+	     (eq 'not-yanks search-caps-disable-folding))
+	(setq string (downcase string)))
+    (if isearch-regexp (setq string (regexp-quote string)))
+    (setq isearch-string (concat isearch-string string)
 	  isearch-message
 	  (concat isearch-message
-		  (mapconcat 'text-char-description
-			     word ""))
+		  (mapconcat 'isearch-text-char-description
+			     string ""))
 	  ;; Don't move cursor in reverse search.
 	  isearch-yank-flag t))
   (isearch-search-and-update))
@@ -717,10 +937,10 @@
 
 
 ;; *, ?, and | chars can make a regexp more liberal.
-;; They can make a regexp match sooner
-;; or make it succeed instead of failing.
+;; They can make a regexp match sooner or make it succeed instead of failing.
 ;; So go back to place last successful search started
 ;; or to the last ^S/^R (barrier), whichever is nearer.
+;; + needs no special handling because the string must match at least once.
 
 (defun isearch-*-char ()
   "Handle * and ? specially in regexps."
@@ -740,10 +960,9 @@
 	   (if isearch-forward
 	       (max cs isearch-barrier)
 	     (min cs isearch-barrier))))))
-  (isearch-process-search-char last-command-char))
+  (isearch-process-search-char (isearch-last-command-char)))
   
 
-
 (defun isearch-|-char ()
   "If in regexp search, jump to the barrier."
   (interactive)
@@ -751,20 +970,25 @@
       (progn
 	(setq isearch-adjusted t)
 	(goto-char isearch-barrier)))
-  (isearch-process-search-char last-command-char))
-
+  (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."
+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 is applied to the editing."
   (interactive)
-  (if search-exit-option
-      (progn
-	(setq unread-command-char last-command-char)
-	(isearch-done))
-    ;; otherwise
-    (isearch-search-and-update)))
+  (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)))
+   ))
 
 
 (defun isearch-other-meta-char ()
@@ -774,13 +998,24 @@
   ;; but here we use unwind-protect and command-execute since it is
   ;; a multi-char key we would want to unread.
   (interactive)
-  (if search-exit-option
-      (unwind-protect
-	  (isearch-done)  ;; this exits recursive edit
-	;; Reexecute the key.
-	(command-execute (this-command-keys)))
-    ;; otherwise
-    (isearch-search-and-update)))
+  (cond
+   (search-exit-option
+    (unwind-protect
+	;; Exit recursive edit and restore the outside keymap.
+	(isearch-done)
+      ;; Reexecute the key with the outside keymap.
+      ;; Note: this doesnt work unless the entered key is the same 
+      ;; as some outside key since command-execute only takes whole keys.
+      ;; So three character keys typically will not work!
+      ;; Also, executing the command here may not work if isearch was
+      ;; invoked non-interactively, since other input may be expected.
+      ;; We also can't do isearch-edit-string as in -other-control-char.
+      ;; because we need to set unread-command-key, if that existed.
+      ;; So a new unread-command-key would solve all these problems.
+      (command-execute (this-command-keys))))
+   (t  ;; otherwise nil
+    (isearch-process-search-string (this-command-keys) (this-command-keys))
+    )))
 
 
 (defun isearch-quote-char ()
@@ -788,42 +1023,37 @@
   (interactive)
   (isearch-process-search-char (read-quoted-char (isearch-message t))))
 
-
 (defun isearch-return-char ()
   "Convert return into newline for incremental search.
 Obsolete."
   (interactive)
   (isearch-process-search-char ?\n))
 
-
 (defun isearch-printing-char ()
   "Any other printing character => add it to the search string and search."
   (interactive)
-  (isearch-process-search-char last-command-char))
-
-
-(defun isearch-upper-case-char ()
-  "Any upper case char => turn off case fold search for remainder of search."
-  ;; This feature only applies to interactively entered chars,
-  ;; but not yanked chars, repeat default searches, or search ring searches.
-  ;; Support for these should be easy to add.
-  (interactive)
-  (if search-caps-disable-folding
-      (setq isearch-case-fold-search nil))
-  (isearch-printing-char))
+  (isearch-process-search-char (isearch-last-command-char)))
 
 (defun isearch-whitespace-chars ()
-  "Match all whitespace chars, if in regexp mode."
+  "Match all whitespace chars, if in regexp mode.
+If not in regexp mode, activate word search."
   (interactive)
-  (if (and isearch-regexp search-whitespace-regexp)
-      (isearch-process-search-string search-whitespace-regexp " ")
-    (isearch-other-meta-char)))
+  (if isearch-regexp 
+      (if search-whitespace-regexp
+	  (isearch-process-search-string search-whitespace-regexp " ")
+	(isearch-printing-char))
+    (progn
+      ;; This way of doing word search doesnt correctly extend current search.
+      ;;      (setq isearch-word t)
+      ;;      (setq isearch-adjusted t)
+      ;;      (goto-char isearch-barrier)
+      (isearch-printing-char))))
 
 (defun isearch-process-search-char (char)
   ;; Append the char to the search string, update the message and re-search.
-  (isearch-process-search-string (char-to-string char) 
-
-				 (text-char-description char)))
+  (isearch-process-search-string 
+   (isearch-char-to-string char) 
+   (isearch-text-char-description char)))
 
 (defun isearch-process-search-string (string message)
   (setq isearch-string (concat isearch-string string)
@@ -834,14 +1064,12 @@
 ;;===========================================================
 ;; Search Ring
 
-(defun isearch-ring-adjust (advance)
-  ;; helper for isearch-ring-advance and isearch-ring-retreat
-  (if (cdr isearch-cmds)
-      (isearch-pop-state))
-  (let* ((ring (if isearch-regexp regex-search-ring search-ring))
+(defun isearch-ring-adjust1 (advance)
+  ;; Helper for isearch-ring-adjust
+  (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
 	 (length (length ring))
 	 (yank-pointer-name (if isearch-regexp
-				'regex-search-ring-yank-pointer
+				'regexp-search-ring-yank-pointer
 			      'search-ring-yank-pointer))
 	 (yank-pointer (eval yank-pointer-name)))
     (if (zerop length)
@@ -852,14 +1080,25 @@
 			       (if advance (1- length) 1))
 			    length) ring)))
       (setq isearch-string (car yank-pointer)
-	    isearch-message (mapconcat 'text-char-description
-				       isearch-string ""))))
+	    isearch-message (mapconcat 'isearch-text-char-description
+				       isearch-string "")))))
+
+(defun isearch-ring-adjust (advance)
+  ;; Helper for isearch-ring-advance and isearch-ring-retreat
+  (if (cdr isearch-cmds)  ;; is there more than one thing on stack?
+      (isearch-pop-state))
+  (isearch-ring-adjust1 advance)
   (isearch-push-state)
-  (isearch-search)
-  (isearch-update))
+  (if search-ring-update
+      (progn
+	(isearch-search)
+	(isearch-update))
+    (isearch-edit-string)
+    ))
 
 (defun isearch-ring-advance ()
   "Advance to the next search string in the ring."
+  ;; This could be more general to handle a prefix arg, but who would use it.
   (interactive)
   (isearch-ring-adjust 'advance))
 
@@ -868,75 +1107,85 @@
   (interactive)
   (isearch-ring-adjust nil))
 
-
-;;;=============================================================
-;; Window-local variables
-;; (not used yet - and maybe never)
-
-(defvar window-local-variable-alist nil
-  "An alist of windows associated with window local variables and values.
-The cdr of each item is another alist of variables and values.")
-
-(defvar last-local-window nil)
-(defvar last-window-local-vars nil)
+(defun isearch-ring-adjust-edit (advance)
+  "Use the next or previous search string in the ring while in minibuffer."
+  (isearch-ring-adjust1 advance)
+  (erase-buffer)
+  (insert isearch-string))
 
-(defun kill-window-local-variables ()
-  "Remove the old variable list, if any."
-  (setq window-local-variable-alist
-	(delq window-local-variable-alist
-	      (assq (selected-window)
-		    window-local-variable-alist))))
+(defun isearch-ring-advance-edit ()
+  (interactive)
+  (isearch-ring-adjust-edit 'advance))
 
-;; Assume that window-local variables are not buffer-local
-;; so we can delay storing until absolutely necessary.
-
-(defun store-window-local-variables (&rest vars-and-vals)
-  "Store the window local variables for selected window."
-  (setq last-local-window (selected-window))
-  (setq last-window-local-vars vars-and-vals))
+(defun isearch-ring-retreat-edit ()
+  "Retreat to the previous search string in the ring while in the minibuffer."
+  (interactive)
+  (isearch-ring-adjust-edit nil))
 
 
-(defun fetch-window-local-variables ()
- "Fetch the window local variables for selected window.
-Does nothing if the last store was for the same window."
-  (if (not (eq (selected-window) last-local-window))
+(defun isearch-complete1 ()
+  ;; Helper for isearch-complete and isearch-complete-edit
+  ;; Return t if completion OK, nil if no completion exists.
+  (let* ((ring (if isearch-regexp regexp-search-ring search-ring))
+         (alist (mapcar (function (lambda (string) (list string))) ring))
+         (completion-ignore-case case-fold-search)
+         (completion (try-completion isearch-string alist)))
+    (cond
+     ((eq completion t)
+      ;; isearch-string stays the same
+      t)
+     ((or completion ; not nil, must be a string
+	  (= 0 (length isearch-string))) ; shouldnt have to say this
+      (if (equal completion isearch-string)  ;; no extension?
+	  (if completion-auto-help
+	      (with-output-to-temp-buffer "*Isearch completions*"
+		(display-completion-list 
+		 (all-completions isearch-string alist))))
+	(setq isearch-string completion))
+      t)
+     (t
+      (message "No completion") ; waits a second if in minibuffer
+      nil))))
+
+(defun isearch-complete ()
+  "Complete the search string from the strings on the search ring.
+The completed string is then editable in the minibuffer.
+If there is no completion possible, say so and continue searching."
+  (interactive)
+  (if (isearch-complete1)
+      (isearch-edit-string)
+    ;; else
+    (sit-for 1)
+    (isearch-update)))
+
+(defun isearch-complete-edit ()
+  "Same as `isearch-complete' except in the minibuffer."
+  (interactive)
+  (setq isearch-string (buffer-string))
+  (if (isearch-complete1)
       (progn
-	;; First store the previous values.
-	(setq window-local-variable-alist
-	      (cons (cons last-local-window
-			  last-window-local-vars)
-		    (delq window-local-variable-alist
-			  (assq last-local-window
-				window-local-variable-alist))))
-	;; Now fetch the values for the selected-window.
-	(setq last-local-window (selected-window))
-	(setq last-window-local-vars 
-		(cdr (assq last-local-window window-local-variable-alist)))
-	(let ((vars-and-vals last-window-local-vars))
-	  (while vars-and-vals
-	    (set (car vars-and-vals) (car (cdr vars-and-vals)))
-	    (setq vars-and-vals (cdr (cdr vars-and-vals))))))))
-		    
+	(erase-buffer)
+	(insert isearch-string))))
 
 
 ;;;==============================================================
 ;; The search status stack (and isearch window-local variables, not used).
+;; Need a structure for this.
 
 (defun isearch-top-state ()
-;;  (fetch-window-local-variables)
   (let ((cmd (car isearch-cmds)))
     (setq isearch-string (car cmd)
 	  isearch-message (car (cdr cmd))
 	  isearch-success (nth 3 cmd)
 	  isearch-forward (nth 4 cmd)
 	  isearch-other-end (nth 5 cmd)
-	  isearch-invalid-regexp (nth 6 cmd)
-	  isearch-wrapped (nth 7 cmd)
-	  isearch-barrier (nth 8 cmd))
+	  isearch-word (nth 6 cmd)
+	  isearch-invalid-regexp (nth 7 cmd)
+	  isearch-wrapped (nth 8 cmd)
+	  isearch-barrier (nth 9 cmd))
     (goto-char (car (cdr (cdr cmd))))))
 
 (defun isearch-pop-state ()
-;;  (fetch-window-local-variables)
   (setq isearch-cmds (cdr isearch-cmds))
   (isearch-top-state)
   )
@@ -945,23 +1194,10 @@
   (setq isearch-cmds 
 	(cons (list isearch-string isearch-message (point)
 		    isearch-success isearch-forward isearch-other-end 
+		    isearch-word
 		    isearch-invalid-regexp isearch-wrapped isearch-barrier)
 	      isearch-cmds)))
 
-(defun isearch-store-variables ()
-  (store-window-local-variables 
-   'isearch-cmds isearch-cmds
-   'isearch-regexp isearch-regexp
-   'isearch-adjusted isearch-adjusted
-   'isearch-slow-terminal-mode isearch-slow-terminal-mode
-   'isearch-small-window isearch-small-window
-   'isearch-found-point isearch-found-point
-   'isearch-found-start isearch-found-start
-   'isearch-opoint isearch-opoint
-   'isearch-window-configuration isearch-window-configuration
-   'isearch-old-local-map isearch-old-local-map
-   ))
-
 
 ;;;==================================================================
 ;; Message string
@@ -970,13 +1206,13 @@
   ;; Generate and print the message string.
   (let ((cursor-in-echo-area ellipsis)
 	(m (concat
-	    (isearch-message-prefix c-q-hack ellipsis)
+	    (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
 	    isearch-message
 	    (isearch-message-suffix c-q-hack ellipsis)
 	    )))
     (if c-q-hack m (message "%s" m))))
 
-(defun isearch-message-prefix (&optional c-q-hack ellipsis)
+(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
   ;; If about to search, and previous search regexp was invalid,
   ;; check that it still is.  If it is valid now,
   ;; let the message we display while searching say that it is valid.
@@ -989,8 +1225,9 @@
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
 		   (if isearch-wrapped "wrapped ")
+		   (if isearch-word "word " "")
 		   (if isearch-regexp "regexp " "")
-		   "I-search"
+		   (if nonincremental "search" "I-search")
 		   (if isearch-forward ": " " backward: ")
 		   )))
     (aset m 0 (upcase (aref m 0)))
@@ -1010,21 +1247,28 @@
 (defun isearch-search ()
   ;; Do the search with the current search string.
   (isearch-message nil t)
+  (if search-caps-disable-folding
+      (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string)))
   (condition-case lossage
       (let ((inhibit-quit nil)
 	    (case-fold-search isearch-case-fold-search))
 	(if isearch-regexp (setq isearch-invalid-regexp nil))
 	(setq isearch-success
 	      (funcall
-	       (if isearch-regexp
-		   (if isearch-forward 're-search-forward 're-search-backward)
-		 (if isearch-forward 'search-forward 'search-backward))
+	       (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)))
 	       isearch-string nil t))
 	(if isearch-success
 	    (setq isearch-other-end
 		  (if isearch-forward (match-beginning 0) (match-end 0)))))
 
-    (quit (setq unread-command-char ?\C-g)
+    (quit (isearch-unread ?\C-g)
 	  (setq isearch-success nil))
 
     (invalid-regexp 
@@ -1041,56 +1285,201 @@
 	 (ding))
     (goto-char (nth 2 (car isearch-cmds)))))
 
-;;;=================================================
-;; This is called from incremental-search
-;; if the first input character is the exit character.
+
+
+;;;========================================================
+;;; Highlighting
+
+(defun isearch-highlight (begin end))
+(defun isearch-dehighlight (totally))
+
+;; lemacs uses faces
+'(progn
+(defvar isearch-extent nil)
+
+(or (find-face 'isearch)	;; this face is initialized by x-faces.el
+    (make-face 'isearch))	;; since isearch is preloaded
 
-;; We store the search string in `isearch-string'
-;; which has been bound already by `isearch-search'
-;; so that, when we exit, it is copied into `search-last-string'.
+(defun isearch-lemacs-highlight (begin end)
+  (if (null isearch-highlight)
+      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))
+)
 
-(defun nonincremental-search (forward regexp)
-  ;; This may be broken.  Anyway, it could be replaced by the
-  ;; isearch-edit-string command instead.
-  (setq isearch-forward forward
-	isearch-regexp regexp)
-  (let (char function
-	inhibit-quit
-	(cursor-in-echo-area t))
-    ;; Prompt assuming not word search,
-    (setq isearch-message 
+;;;===========================================================
+;;; General utilities
+
+;; (fset 'isearch-member-equal (symbol-function 'member)) ; for emacs 19
+
+(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)
+
+
+(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."
+  (let ((case-fold-search nil))
+    (not (string-match "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]" string))))
+
+
+;;;=================================================
+;;; Special functions for lemacs events.
 
-	  (if isearch-regexp 
+;; To quiet the byte-compiler.
+(defvar unread-command-event)
+(defvar last-command-event)
+
+(defun isearch-char-to-string (c)
+  (if (integerp c)
+      (make-string 1 c)
+   (make-string 1 (event-to-character c))))
+
+(defun isearch-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-events-exist
+      (setq unread-command-event char-or-event)
+    (setq unread-command-char char-or-event)))
+
+(defun isearch-last-command-char ()
+  ;; General function to return the last command character.
+  (if isearch-events-exist
+      last-command-event
+    last-command-char))
+
+
 
-	      (if isearch-forward "Regexp search: "
-		"Regexp search backward: ")
-	    (if isearch-forward "Search: " "Search backward: ")))
-    (message "%s" isearch-message)
-    ;; Read 1 char and switch to word search if it is ^W.
-    (setq char (read-char))
-    (if (eq char search-yank-word-char)
-	(setq isearch-message (if isearch-forward "Word search: " 
+
+;;;========================================================
+;;; 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))
 
-				"Word search backward: "))
-      ;; Otherwise let that 1 char be part of the search string.
-      (setq unread-command-char char))
-    (setq function
-	  (if (eq char search-yank-word-char)
-	      (if isearch-forward 'word-search-forward 'word-search-backward)
-	    (if isearch-regexp
-		(if isearch-forward 're-search-forward 're-search-backward)
-	      (if isearch-forward 'search-forward 'search-backward))))
-    ;; Read the search string with corrected prompt.
-    (setq isearch-string (read-string isearch-message isearch-string))
-    ;; Empty means use default.
-    (if (= 0 (length isearch-string))
-	(setq isearch-string search-last-string)
-      ;; Set last search string now so it is set even if we fail.
-      (setq search-last-string isearch-string))
-    ;; Since we used the minibuffer, we should be available for redo.
-    (setq command-history 
+;;(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)))
 
-	  (cons (list function isearch-string) command-history))
-    ;; Go ahead and search.
-    (let ((case-fold-search isearch-case-fold-search))
-      (funcall function isearch-string))))
+;;(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))))
+;;	))
+
+;;))