;;; earl's emacs search commands
;;; $Id: eaksearch.el,v 1.2 1999/12/31 03:03:27 earl Exp $

; Copyright (c) 2000 by Earl A. Killian.  All Rights Reserved.
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License version 2 as
; published by the Free Software Foundation.
;
; This program is distributed in the hope that it will be useful, 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.
;
; You should have received a copy of the GNU General Public License
; along with this program; see the file COPYING.  If not, write to the
; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
; MA 02111-1307, USA.

(defvar search-history nil
  "For minibuffer previous/next commands during search string read.")

(defun string-search (count c backward)
  (let ((prompt)
	(p (point))
	(initial-string "")
	(case-fold t)
	(word-search nil)
	(regexp-search nil)
	(from-beginning nil)
	(from-end nil))
    (while (not (null c))
      (cond ((= c ?)
	     (setq c nil))
	    ((= c ?)
	     (setq from-beginning (not from-beginning))
	     (setq from-end nil)
	     (setq c (read-char)))
	    ((= c ?)
	     (setq case-fold (not case-fold))
	     (setq c (read-char)))
	    ((= c ?)
	     (setq from-end (not from-end))
	     (setq from-beginning nil)
	     (setq c (read-char)))
	    ((= c ?)
	     (setq regexp-search (not regexp-search))
	     (setq c (read-char)))
	    ((= c ?)
	     (setq word-search (not word-search))
	     (setq c (read-char)))
	    (t (setq unread-command-events (list (character-to-event c)))
	       (setq c nil))))
    (setq prompt (if backward "Reverse Search" "Search"))
    (if word-search
	(setq prompt (concat "Word " prompt)))
    (if regexp-search
	(setq prompt (concat "Regexp " prompt)))
    (if (not case-fold)
	(setq prompt (concat "Case-sensitive " prompt)))
    (if from-beginning
	(setq prompt (concat prompt " from beginning")))
    (if from-end
	(setq prompt (concat prompt " from end")))
    (setq prompt (concat prompt ": " initial-string))
    (setq search-last-string
	  (read-string prompt initial-string 'search-history))
    (if (not regexp-search)
	(setq search-last-string (regexp-quote search-last-string)))
    (if word-search
	(progn (setq search-last-string
		     (concat "\\b" search-last-string "\\b"))))
    (unwind-protect
	(let ((case-fold-search case-fold))
	  (if from-beginning (goto-char (point-min)))
	  (if from-end (goto-char (point-max)))
	  (if backward
	      (re-search-backward search-last-string nil nil count)
	    (re-search-forward search-last-string nil nil count))
	  (setq p (point)))
      (goto-char p))))

(defun forward-search-char (count)
  (interactive "_p")
  (let ((c (read-char)))
    (cond ((= c ?)
	   (re-search-forward search-last-string nil nil count))
	  ((or (= c ?) (= c ?) (= c ?) (= c ?) (= c ?) (= c ?))
	   (string-search count c nil))
	  ((= c ?)
	   (setq search-last-string (regexp-quote (char-to-string (read-char))))
	   (re-search-forward search-last-string nil nil count))
	  (t
	   (setq search-last-string (regexp-quote (char-to-string c)))
	   (re-search-forward search-last-string nil nil count)))))

(defun backward-search-char (count)
  (interactive "_p")
  (let ((c (read-char)))
    (cond ((= c ?)
	   (re-search-backward search-last-string nil nil count))
	  ((or (= c ?) (= c ?) (= c ?) (= c ?) (= c ?) (= c ?))
	   (string-search count c t))
	  ((= c ?)
	   (setq search-last-string (regexp-quote (char-to-string (read-char))))
	   (re-search-backward search-last-string nil nil count))
	  (t
	   (setq search-last-string (regexp-quote (char-to-string c)))
	   (re-search-backward search-last-string nil nil count)))))

(provide 'eaksearch)
