Index: lisp/doc-view.el =================================================================== RCS file: /sources/emacs/emacs/lisp/doc-view.el,v retrieving revision 1.18 diff -u -r1.18 doc-view.el --- lisp/doc-view.el 1 Nov 2007 03:53:32 -0000 1.18 +++ lisp/doc-view.el 5 Nov 2007 11:41:33 -0000 @@ -101,11 +101,11 @@ ;; Todo: ;; - better menu. -;; - don't use `find-file'. ;; - Bind slicing to a drag event. ;; - zoom (the whole document and/or just the region around the cursor). ;; - get rid of the silly arrow in the fringe. ;; - improve anti-aliasing (pdf-utils gets it better). +;; - Make it work with auto-compression-mode. (require 'dired) (require 'image-mode) @@ -197,11 +197,9 @@ (defvar doc-view-current-cache-dir nil "Only used internally.") -(defvar doc-view-current-search-matches nil - "Only used internally.") - (defvar doc-view-current-image nil "Only used internally.") + (defvar doc-view-current-overlay) (defvar doc-view-pending-cache-flush nil) @@ -211,6 +209,10 @@ (defvar doc-view-previous-major-mode nil "Only used internally.") +(defvar doc-view-last-isearch-function nil + "Only used internally. +Used to distinguish between forward and backward isearch.") + ;;;; DocView Keymaps (defvar doc-view-mode-map @@ -237,10 +239,9 @@ (define-key map (kbd "s m") 'doc-view-set-slice-using-mouse) (define-key map (kbd "s r") 'doc-view-reset-slice) ;; Searching - (define-key map (kbd "C-s") 'doc-view-search) - (define-key map (kbd "") 'doc-view-search) - (define-key map (kbd "C-S-n") 'doc-view-search-next-match) - (define-key map (kbd "C-S-p") 'doc-view-search-previous-match) + (define-key map (kbd "C-s") 'isearch-forward) + (define-key map (kbd "") 'isearch-forward) + (define-key map (kbd "C-r") 'isearch-backward) ;; Scrolling (define-key map [remap forward-char] 'image-forward-hscroll) (define-key map [remap backward-char] 'image-backward-hscroll) @@ -294,17 +295,7 @@ ;; Tell user if converting isn't finished yet (if doc-view-current-converter-process " (still converting...)\n" - "\n") - ;; Display context infos if this page matches the last search - (when (and doc-view-current-search-matches - (assq doc-view-current-page - doc-view-current-search-matches)) - (concat (propertize "Search matches:\n" 'face 'bold) - (let ((contexts "")) - (dolist (m (cdr (assq doc-view-current-page - doc-view-current-search-matches))) - (setq contexts (concat contexts " - \"" m "\"\n"))) - contexts))))) + "\n"))) ;; Update the buffer (doc-view-insert-image (nth (1- page) doc-view-current-files) :pointer 'arrow) @@ -500,9 +491,9 @@ (setq doc-view-current-converter-process nil mode-line-process nil) ;; If the user looks at the DocView buffer where the conversion was - ;; performed, search anew. This time it will be queried for a regexp. + ;; performed, search anew. (when (eq current-buffer proc-buffer) - (doc-view-search))))) + (funcall doc-view-last-isearch-function))))) (defun doc-view-pdf->txt (pdf txt) "Convert PDF to TXT asynchronously." @@ -693,68 +684,21 @@ ;;;; Searching -(defun doc-view-search-internal (regexp file) - "Return a list of FILE's pages that contain text matching REGEXP. -The value is an alist of the form (PAGE CONTEXTS) where PAGE is -the pagenumber and CONTEXTS are all lines of text containing a match." - (with-temp-buffer - (insert-file-contents file) - (let ((page 1) - (lastpage 1) - matches) - (while (re-search-forward (concat "\\(?:\\([ ]\\)\\|\\(" - regexp "\\)\\)") nil t) - (when (match-string 1) (incf page)) - (when (match-string 2) - (if (/= page lastpage) - (push (cons page - (list (buffer-substring - (line-beginning-position) - (line-end-position)))) - matches) - (setq matches (cons - (append - (or - ;; This page already is a match. - (car matches) - ;; This is the first match on page. - (list page)) - (list (buffer-substring - (line-beginning-position) - (line-end-position)))) - (cdr matches)))) - (setq lastpage page))) - (nreverse matches)))) - -(defun doc-view-search-no-of-matches (list) - "Extract the number of matches from the search result LIST." - (let ((no 0)) - (dolist (p list) - (setq no (+ no (1- (length p))))) - no)) - -(defun doc-view-search () - "Query for a regexp and search the current document. -If the current document hasn't been transformed to plain text -till now do that first. You should try searching anew when the -conversion finished." - (interactive) - ;; New search, so forget the old results. - (setq doc-view-current-search-matches nil) +(defun doc-view-isearch-function () + "Return the function to use for the search." + (message "fooooo") + (if isearch-forward 'doc-view-search-forward 'doc-view-search-backward)) + +(defun doc-view-isearch-text-file () + "Return the text file used for searching or nil if it doesn't exist. +If the text file doesn't exist start the conversion." (let ((txt (expand-file-name "doc.txt" (doc-view-current-cache-dir)))) (if (file-readable-p txt) - (progn - (setq doc-view-current-search-matches - (doc-view-search-internal - (read-from-minibuffer "Regexp: ") - txt)) - (message "DocView: search yielded %d matches." - (doc-view-search-no-of-matches - doc-view-current-search-matches))) - ;; We must convert to TXT first! + txt + ;; We must convert to TXT first. (if doc-view-current-converter-process - (message "DocView: please wait till conversion finished.") + nil (let ((ext (file-name-extension buffer-file-name))) (cond ((string= ext "pdf") @@ -772,35 +716,42 @@ (doc-view-pdf->txt (expand-file-name "doc.pdf" (doc-view-current-cache-dir)) txt)) - (t (error "DocView doesn't know what to do")))))))) - -(defun doc-view-search-next-match (arg) - "Go to the ARGth next matching page." - (interactive "p") - (let* ((next-pages (doc-view-remove-if - (lambda (i) (<= (car i) doc-view-current-page)) - doc-view-current-search-matches)) - (page (car (nth (1- arg) next-pages)))) - (if page - (doc-view-goto-page page) - (when (and - doc-view-current-search-matches - (y-or-n-p "No more matches after current page. Wrap to first match? ")) - (doc-view-goto-page (caar doc-view-current-search-matches)))))) + (t (error "DocView doesn't know what to do"))) + nil))))) -(defun doc-view-search-previous-match (arg) - "Go to the ARGth previous matching page." - (interactive "p") - (let* ((prev-pages (doc-view-remove-if - (lambda (i) (>= (car i) doc-view-current-page)) - doc-view-current-search-matches)) - (page (car (nth (1- arg) (nreverse prev-pages))))) - (if page - (doc-view-goto-page page) - (when (and - doc-view-current-search-matches - (y-or-n-p "No more matches before current page. Wrap to last match? ")) - (doc-view-goto-page (caar (last doc-view-current-search-matches))))))) +(defun doc-view-search-forward (regexp &rest args) + (interactive "sRegexp: ") + (message "Regexp = %s" regexp) + (setq doc-view-last-isearch-function 'doc-view-search-forward) + (let* ((txt (doc-view-isearch-text-file)) + (page doc-view-current-page) + (cur-page page) + (pages (length doc-view-current-files)) + (cur-buf (current-buffer))) + (if (not txt) + (message "DocView: Please wait till the conversian has finished.") + (set-buffer (find-file-noselect txt t)) + (goto-char (point-min)) + ;; Go to the beginning of the current page. + (unless (= cur-page 0) + (search-forward " " nil t (- cur-page 1))) + ;; Now do a regexp search forward and goto that page. + (let ((search-again t)) + (while search-again + (re-search-forward (concat "\\(?:\\([ ]\\)\\|\\(" + regexp "\\)\\)") nil t) + (when (match-string 1) (incf page)) + (when (and (match-string 2) + (/= cur-page page)) + (message "match-str = %s" (buffer-substring (line-beginning-position) + (line-end-position))) + (setq search-again nil)) + (when (> page pages) + (setq search-again nil + page nil))) + (set-buffer cur-buf) + (when page + (doc-view-goto-page page)))))) ;;;; User interface commands and the mode @@ -848,9 +799,11 @@ (make-local-variable 'doc-view-current-slice) (make-local-variable 'doc-view-current-cache-dir) (make-local-variable 'doc-view-current-info) - (make-local-variable 'doc-view-current-search-matches) + (make-local-variable 'doc-view-last-isearch-function) (set (make-local-variable 'doc-view-current-overlay) (make-overlay (point-min) (point-max) nil t)) + (set (make-local-variable 'isearch-search-fun-function) + 'doc-view-isearch-function) (add-hook 'change-major-mode-hook (lambda () (delete-overlay doc-view-current-overlay)) nil t)