- (run-at-time "1 secs" doc-view-conversion-refresh-interval
- 'doc-view-display
- buffer-file-name))))
-
-(defun doc-view-pdf->txt-sentinel (proc event)
- (if (not (string-match "finished" event))
- (message "DocView: converter process changed status to %s." event)
- (let ((current-buffer (current-buffer))
- (proc-buffer (process-get proc 'buffer)))
- (with-current-buffer proc-buffer
- (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.
- (when (eq current-buffer proc-buffer)
- (doc-view-search nil))))))
-
-(defun doc-view-pdf->txt (pdf txt)
- "Convert PDF to TXT asynchronously."
- (setq doc-view-current-converter-process
- (start-process "pdf->txt" doc-view-conversion-buffer
- doc-view-pdftotext-program "-raw"
- pdf txt)
- mode-line-process (list (format ":%s" doc-view-current-converter-process)))
- (set-process-sentinel doc-view-current-converter-process
- 'doc-view-pdf->txt-sentinel)
- (process-put doc-view-current-converter-process 'buffer (current-buffer)))
-
-(defun doc-view-ps->pdf-sentinel (proc event)
- (if (not (string-match "finished" event))
- (message "DocView: converter process changed status to %s." event)
- (with-current-buffer (process-get proc 'buffer)
- (setq doc-view-current-converter-process nil
- mode-line-process nil)
- ;; Now we can transform to plain text.
- (doc-view-pdf->txt (process-get proc 'pdf-file)
- (expand-file-name "doc.txt"
- (doc-view-current-cache-dir))))))
-
-(defun doc-view-ps->pdf (ps pdf)
- "Convert PS to PDF asynchronously."
- (setq doc-view-current-converter-process
- (start-process "ps->pdf" doc-view-conversion-buffer
- doc-view-ps2pdf-program
- ;; Avoid security problems when rendering files from
- ;; untrusted sources.
- "-dSAFER"
- ;; in-file and out-file
- ps pdf)
- mode-line-process (list (format ":%s" doc-view-current-converter-process)))
- (set-process-sentinel doc-view-current-converter-process
- 'doc-view-ps->pdf-sentinel)
- (process-put doc-view-current-converter-process 'buffer (current-buffer))
- (process-put doc-view-current-converter-process 'pdf-file pdf))
+ (run-at-time "1 secs" doc-view-conversion-refresh-interval
+ 'doc-view-display
+ (current-buffer)))))
+
+(defun doc-view-pdf->png-1 (pdf png page callback)
+ "Convert a PAGE of a PDF file to PNG asynchronously.
+Call CALLBACK with no arguments when done."
+ (doc-view-start-process
+ "pdf->png-1" doc-view-ghostscript-program
+ (append doc-view-ghostscript-options
+ (list (format "-r%d" (round doc-view-resolution))
+ ;; Sadly, `gs' only supports the page-range
+ ;; for PDF files.
+ (format "-dFirstPage=%d" page)
+ (format "-dLastPage=%d" page)
+ (concat "-sOutputFile=" png)
+ pdf))
+ callback))
+
+(declare-function clear-image-cache "image.c" (&optional filter))
+
+(defun doc-view-pdf->png (pdf png pages)
+ "Convert a PDF file to PNG asynchronously.
+Start by converting PAGES, and then the rest."
+ (if (null pages)
+ (doc-view-pdf/ps->png pdf png)
+ ;; We could render several `pages' with a single process if they're
+ ;; (almost) consecutive, but since in 99% of the cases, there'll be only
+ ;; a single page anyway, and of the remaining 1%, few cases will have
+ ;; consecutive pages, it's not worth the trouble.
+ (lexical-let ((pdf pdf) (png png) (rest (cdr pages)))
+ (doc-view-pdf->png-1
+ pdf (format png (car pages)) (car pages)
+ (lambda ()
+ (if rest
+ (doc-view-pdf->png pdf png rest)
+ ;; Yippie, the important pages are done, update the display.
+ (clear-image-cache)
+ ;; Convert the rest of the pages.
+ (doc-view-pdf/ps->png pdf png)))))))
+
+(defun doc-view-pdf->txt (pdf txt callback)
+ "Convert PDF to TXT asynchronously and call CALLBACK when finished."
+ (or doc-view-pdftotext-program
+ (error "You need the `pdftotext' program to convert a PDF to text"))
+ (doc-view-start-process "pdf->txt" doc-view-pdftotext-program
+ (list "-raw" pdf txt)
+ callback))
+
+(defun doc-view-doc->txt (txt callback)
+ "Convert the current document to text and call CALLBACK when done."
+ (make-directory (doc-view-current-cache-dir) t)
+ (case doc-view-doc-type
+ (pdf
+ ;; Doc is a PDF, so convert it to TXT
+ (doc-view-pdf->txt doc-view-buffer-file-name txt callback))
+ (ps
+ ;; Doc is a PS, so convert it to PDF (which will be converted to
+ ;; TXT thereafter).
+ (lexical-let ((pdf (expand-file-name "doc.pdf"
+ (doc-view-current-cache-dir)))
+ (txt txt)
+ (callback callback))
+ (doc-view-ps->pdf doc-view-buffer-file-name pdf
+ (lambda () (doc-view-pdf->txt pdf txt callback)))))
+ (dvi
+ ;; Doc is a DVI. This means that a doc.pdf already exists in its
+ ;; cache subdirectory.
+ (doc-view-pdf->txt (expand-file-name "doc.pdf"
+ (doc-view-current-cache-dir))
+ txt callback))
+ (t (error "DocView doesn't know what to do"))))
+
+(defun doc-view-ps->pdf (ps pdf callback)
+ "Convert PS to PDF asynchronously and call CALLBACK when finished."
+ (or doc-view-ps2pdf-program
+ (error "You need the `ps2pdf' program to convert PS to PDF"))
+ (doc-view-start-process "ps->pdf" doc-view-ps2pdf-program
+ (list
+ ;; Avoid security problems when rendering files from
+ ;; untrusted sources.
+ "-dSAFER"
+ ;; in-file and out-file
+ ps pdf)
+ callback))
+
+(defun doc-view-active-pages ()
+ (let ((pages ()))
+ (dolist (win (get-buffer-window-list (current-buffer) nil 'visible))
+ (let ((page (image-mode-window-get 'page win)))
+ (unless (memq page pages) (push page pages))))
+ pages))