aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReiner Steib2007-10-17 21:34:19 +0000
committerReiner Steib2007-10-17 21:34:19 +0000
commit640602f766d7431ae40ac5ffa274db405b1c4d7d (patch)
tree69fe77c0ddc934d842a20916bf7c5e5b404bd2eb
parent57581fccfe5e3a879853efe9fb685d45b9c5b63b (diff)
downloademacs-640602f766d7431ae40ac5ffa274db405b1c4d7d.tar.gz
emacs-640602f766d7431ae40ac5ffa274db405b1c4d7d.zip
* bindings.el (completion-ignored-extensions): Remove pdf and dvi
extensions since they can be viewed with doc-view. * files.el (auto-mode-alist): Make doc-view-mode the default mode for pdf, ps and dvi files. * doc-view.el: Make doc-view-mode the standard mode for viewing pdf, [e]ps and dvi files and add binding C-c C-c to toggle between text and image display. Add binding C-c C-e to switch to an editing mode. (doc-view-ghostscript-options, doc-view-ps->pdf): Add "-dSAFER" to avoid security problems when rendering files untrusted sources.
-rw-r--r--lisp/ChangeLog15
-rw-r--r--lisp/bindings.el2
-rw-r--r--lisp/doc-view.el369
-rw-r--r--lisp/files.el2
4 files changed, 231 insertions, 157 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 77740d1f910..d6b0dd86cac 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,18 @@
12007-10-17 Tassilo Horn <tassilo@member.fsf.org>
2
3 * bindings.el (completion-ignored-extensions): Remove pdf and dvi
4 extensions since they can be viewed with doc-view.
5
6 * files.el (auto-mode-alist): Make doc-view-mode the default mode
7 for pdf, ps and dvi files.
8
9 * doc-view.el: Make doc-view-mode the standard mode for viewing
10 pdf, [e]ps and dvi files and add binding C-c C-c to toggle between
11 text and image display. Add binding C-c C-e to switch to an
12 editing mode.
13 (doc-view-ghostscript-options, doc-view-ps->pdf): Add "-dSAFER" to
14 avoid security problems when rendering files untrusted sources.
15
12007-10-17 Aaron Hawley <aaronh@garden.org> 162007-10-17 Aaron Hawley <aaronh@garden.org>
2 17
3 * tutorial.el (tutorial--save-tutorial): Display message when tutorial 18 * tutorial.el (tutorial--save-tutorial): Display message when tutorial
diff --git a/lisp/bindings.el b/lisp/bindings.el
index bab319fa029..5080eb8c3b0 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -536,7 +536,7 @@ is okay. See `mode-line-format'.")
536 '(".elc" ".lof" 536 '(".elc" ".lof"
537 ".glo" ".idx" ".lot" 537 ".glo" ".idx" ".lot"
538 ;; TeX-related 538 ;; TeX-related
539 ".dvi" ".fmt" ".tfm" ".pdf" 539 ".fmt" ".tfm"
540 ;; Java compiled 540 ;; Java compiled
541 ".class" 541 ".class"
542 ;; CLISP 542 ;; CLISP
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 40c91ffe016..64ee1bbd8ea 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -5,7 +5,7 @@
5;; Author: Tassilo Horn <tassilo@member.fsf.org> 5;; Author: Tassilo Horn <tassilo@member.fsf.org>
6;; Maintainer: Tassilo Horn <tassilo@member.fsf.org> 6;; Maintainer: Tassilo Horn <tassilo@member.fsf.org>
7;; Keywords: files, pdf, ps, dvi 7;; Keywords: files, pdf, ps, dvi
8;; Version: <2007-10-02 Tue 18:21> 8;; Version: <2007-10-17 Wed 22:15>
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
11 11
@@ -28,8 +28,7 @@
28 28
29;; doc-view.el requires GNU Emacs 22.1 or newer. You also need Ghostscript, 29;; doc-view.el requires GNU Emacs 22.1 or newer. You also need Ghostscript,
30;; `dvipdfm' which comes with teTeX and `pdftotext', which comes with xpdf 30;; `dvipdfm' which comes with teTeX and `pdftotext', which comes with xpdf
31;; (http://www.foolabs.com/xpdf/) or poppler 31;; (http://www.foolabs.com/xpdf/) or poppler (http://poppler.freedesktop.org/).
32;; (http://poppler.freedesktop.org/).
33 32
34;;; Commentary: 33;;; Commentary:
35 34
@@ -38,16 +37,19 @@
38;; inside an Emacs buffer. This buffer uses `doc-view-mode' which provides 37;; inside an Emacs buffer. This buffer uses `doc-view-mode' which provides
39;; convenient key bindings for browsing the document. 38;; convenient key bindings for browsing the document.
40;; 39;;
41;; To use it simply do 40;; To use it simply open a document file with
42;; 41;;
43;; M-x doc-view RET 42;; C-x C-f ~/path/to/document RET
44;; 43;;
45;; and you'll be queried for a document to open. 44;; and the document will be converted and displayed, if your emacs supports png
45;; images. With `C-c C-c' you can toggle between the rendered images
46;; representation and the source text representation of the document. With
47;; `C-c C-e' you can switch to an appropriate editing mode for the document.
46;; 48;;
47;; Since conversion may take some time all the PNG images are cached in a 49;; Since conversion may take some time all the PNG images are cached in a
48;; subdirectory of `doc-view-cache-directory' and reused when you want to view 50;; subdirectory of `doc-view-cache-directory' and reused when you want to view
49;; that file again. This reusing can be omitted if you provide a prefx 51;; that file again. To reconvert a document hit `g' (`doc-view-reconvert-doc')
50;; argument to `doc-view'. To delete all cached files use 52;; when displaying the document. To delete all cached files use
51;; `doc-view-clear-cache'. To open the cache with dired, so that you can tidy 53;; `doc-view-clear-cache'. To open the cache with dired, so that you can tidy
52;; it out use `doc-view-dired-cache'. 54;; it out use `doc-view-dired-cache'.
53;; 55;;
@@ -68,8 +70,6 @@
68;; bottom-right corner of the desired slice. To reset the slice use 70;; bottom-right corner of the desired slice. To reset the slice use
69;; `doc-view-reset-slice' (bound to `s r'). 71;; `doc-view-reset-slice' (bound to `s r').
70;; 72;;
71;; Dired users should have a look at `doc-view-dired'.
72;;
73;; You can also search within the document. The command `doc-view-search' 73;; You can also search within the document. The command `doc-view-search'
74;; (bound to `C-s') queries for a search regexp and initializes a list of all 74;; (bound to `C-s') queries for a search regexp and initializes a list of all
75;; matching pages and messages how many match-pages were found. After that you 75;; matching pages and messages how many match-pages were found. After that you
@@ -81,17 +81,16 @@
81;; conversion. When that finishes and you're still viewing the document 81;; conversion. When that finishes and you're still viewing the document
82;; (i.e. you didn't switch to another buffer) you're queried for the regexp 82;; (i.e. you didn't switch to another buffer) you're queried for the regexp
83;; then. 83;; then.
84;;
85;; Dired users can simply hit `v' on a document file. If it's a PS, PDF or DVI
86;; it will be opened using `doc-view-mode'.
87;;
84 88
85;;; Configuration: 89;;; Configuration:
86 90
87;; Basically doc-view should be quite usable with its standard settings, so 91;; If the images are too small or too big you should set the "-rXXX" option in
88;; putting 92;; `doc-view-ghostscript-options' to another value. (The bigger your screen,
89;; 93;; the higher the value.)
90;; (require 'doc-view)
91;;
92;; into your `user-init-file' should be enough. If the images are too small or
93;; too big you should set the "-rXXX" option in `doc-view-ghostscript-options'
94;; to another value. (The bigger your screen, the higher the value.)
95;; 94;;
96;; This and all other options can be set with the customization interface. 95;; This and all other options can be set with the customization interface.
97;; Simply do 96;; Simply do
@@ -123,7 +122,7 @@
123(defcustom doc-view-ghostscript-options 122(defcustom doc-view-ghostscript-options
124 '("-dNOPAUSE" "-sDEVICE=png16m" "-dTextAlphaBits=4" 123 '("-dNOPAUSE" "-sDEVICE=png16m" "-dTextAlphaBits=4"
125 "-dBATCH" "-dGraphicsAlphaBits=4" "-dQUIET" 124 "-dBATCH" "-dGraphicsAlphaBits=4" "-dQUIET"
126 "-r100") 125 "-dSAFER" "-r100")
127 "A list of options to give to ghostscript." 126 "A list of options to give to ghostscript."
128 :type '(sexp) 127 :type '(sexp)
129 :group 'doc-view) 128 :group 'doc-view)
@@ -202,7 +201,10 @@ has finished."
202(defvar doc-view-current-info nil 201(defvar doc-view-current-info nil
203 "Only used internally.") 202 "Only used internally.")
204 203
205;;;; DocView Keymap 204(defvar doc-view-current-display nil
205 "Only used internally.")
206
207;;;; DocView Keymaps
206 208
207(defvar doc-view-mode-map 209(defvar doc-view-mode-map
208 (let ((map (make-sparse-keymap))) 210 (let ((map (make-sparse-keymap)))
@@ -236,9 +238,26 @@ has finished."
236 (define-key map (kbd "M-v") 'scroll-down) 238 (define-key map (kbd "M-v") 'scroll-down)
237 ;; Show the tooltip 239 ;; Show the tooltip
238 (define-key map (kbd "C-t") 'doc-view-show-tooltip) 240 (define-key map (kbd "C-t") 'doc-view-show-tooltip)
241 ;; Toggle between text and image display or editing
242 (define-key map (kbd "C-c C-c") 'doc-view-toggle-display)
243 (define-key map (kbd "C-c C-e") 'doc-view-edit-doc)
244 ;; Reconvert the current document
245 (define-key map (kbd "g") 'doc-view-reconvert-doc)
239 (suppress-keymap map) 246 (suppress-keymap map)
240 map) 247 map)
241 "Keymap used by `doc-view-mode'.") 248 "Keymap used by `doc-view-mode' when displaying a doc as a set of images.")
249
250(defvar doc-view-mode-text-map
251 (let ((map (make-sparse-keymap)))
252 ;; Toggle between text and image display or editing
253 (define-key map (kbd "C-c C-c") 'doc-view-toggle-display)
254 (define-key map (kbd "C-c C-e") 'doc-view-edit-doc)
255 ;; Killing/burying the buffer (and the process)
256 (define-key map (kbd "q") 'bury-buffer)
257 (define-key map (kbd "k") 'doc-view-kill-proc-and-buffer)
258 (define-key map (kbd "C-x k") 'doc-view-kill-proc-and-buffer)
259 map)
260 "Keymap used by `doc-view-mode' when displaying a document as text.")
242 261
243;;;; Navigation Commands 262;;;; Navigation Commands
244 263
@@ -272,16 +291,16 @@ has finished."
272 (setq contexts (concat contexts " - \"" m "\"\n"))) 291 (setq contexts (concat contexts " - \"" m "\"\n")))
273 contexts))))) 292 contexts)))))
274 ;; Update the buffer 293 ;; Update the buffer
275 (setq inhibit-read-only t) 294 (let ((inhibit-read-only t))
276 (erase-buffer) 295 (erase-buffer)
277 (let ((beg (point))) 296 (let ((beg (point)))
278 (doc-view-insert-image (nth (1- page) doc-view-current-files) 297 (doc-view-insert-image (nth (1- page) doc-view-current-files)
279 :pointer 'arrow) 298 :pointer 'arrow)
280 (put-text-property beg (point) 'help-echo doc-view-current-info)) 299 (put-text-property beg (point) 'help-echo doc-view-current-info))
281 (insert "\n" doc-view-current-info) 300 (insert "\n" doc-view-current-info)
282 (goto-char (point-min)) 301 (goto-char (point-min))
283 (forward-char) 302 (forward-char))
284 (setq inhibit-read-only nil))) 303 (set-buffer-modified-p nil)))
285 304
286(defun doc-view-next-page (&optional arg) 305(defun doc-view-next-page (&optional arg)
287 "Browse ARG pages forward." 306 "Browse ARG pages forward."
@@ -318,42 +337,62 @@ has finished."
318 (error (doc-view-previous-page) 337 (error (doc-view-previous-page)
319 (goto-char (point-max))))) 338 (goto-char (point-max)))))
320 339
340(defun doc-view-kill-proc ()
341 "Kill the current converter process."
342 (interactive)
343 (when doc-view-current-converter-process
344 (kill-process doc-view-current-converter-process))
345 (when doc-view-current-timer
346 (cancel-timer doc-view-current-timer)
347 (setq doc-view-current-timer nil))
348 (setq mode-line-process nil))
349
321(defun doc-view-kill-proc-and-buffer () 350(defun doc-view-kill-proc-and-buffer ()
322 "Kill the current converter process and buffer." 351 "Kill the current converter process and buffer."
323 (interactive) 352 (interactive)
353 (doc-view-kill-proc)
324 (when (eq major-mode 'doc-view-mode) 354 (when (eq major-mode 'doc-view-mode)
325 (when doc-view-current-converter-process
326 (kill-process doc-view-current-converter-process))
327 (when doc-view-current-timer
328 (cancel-timer doc-view-current-timer)
329 (setq doc-view-current-timer nil))
330 (kill-buffer (current-buffer)))) 355 (kill-buffer (current-buffer))))
331 356
332;;;; Conversion Functions 357;;;; Conversion Functions
333 358
334(defun doc-view-file-name-to-directory-name (file) 359(defun doc-view-reconvert-doc (&rest args)
335 "Return the directory where the png files of FILE should be saved. 360 "Reconvert the current document.
336 361Should be invoked when the cached images aren't up-to-date."
337It'a a subdirectory of `doc-view-cache-directory'." 362 (interactive)
363 (let ((inhibit-read-only t)
364 (doc doc-view-current-doc))
365 (doc-view-kill-proc)
366 ;; Clear the old cached files
367 (when (file-exists-p (doc-view-current-cache-dir))
368 (dired-delete-file (doc-view-current-cache-dir) 'always))
369 (doc-view-kill-proc-and-buffer)
370 (find-file doc)))
371
372(defun doc-view-current-cache-dir ()
373 "Return the directory where the png files of the current doc should be saved.
374It's a subdirectory of `doc-view-cache-directory'."
338 (if doc-view-current-cache-dir 375 (if doc-view-current-cache-dir
339 doc-view-current-cache-dir 376 doc-view-current-cache-dir
340 (file-name-as-directory 377 (setq doc-view-current-cache-dir
341 (concat (file-name-as-directory doc-view-cache-directory) 378 (file-name-as-directory
342 (with-temp-buffer 379 (concat (file-name-as-directory doc-view-cache-directory)
343 (insert-file-contents-literally file) 380 (let ((doc doc-view-current-doc))
344 (md5 (current-buffer))))))) 381 (with-temp-buffer
382 (insert-file-contents-literally doc)
383 (md5 (current-buffer)))))))))
345 384
346(defun doc-view-dvi->pdf-sentinel (proc event) 385(defun doc-view-dvi->pdf-sentinel (proc event)
347 "If DVI->PDF conversion was successful, convert the PDF to PNG now." 386 "If DVI->PDF conversion was successful, convert the PDF to PNG now."
348 (if (not (string-match "finished" event)) 387 (if (not (string-match "finished" event))
349 (message "DocView: dvi->pdf process changed status to %s." event) 388 (message "DocView: dvi->pdf process changed status to %s." event)
350 (set-buffer (process-get proc 'buffer)) 389 (set-buffer (process-get proc 'buffer))
351 (setq doc-view-current-converter-process nil) 390 (setq doc-view-current-converter-process nil
391 mode-line-process nil)
352 (message "DocView: finished conversion from DVI to PDF!") 392 (message "DocView: finished conversion from DVI to PDF!")
353 ;; Now go on converting this PDF to a set of PNG files. 393 ;; Now go on converting this PDF to a set of PNG files.
354 (let* ((pdf (process-get proc 'pdf-file)) 394 (let* ((pdf (process-get proc 'pdf-file))
355 (png (concat (doc-view-file-name-to-directory-name 395 (png (concat (doc-view-current-cache-dir)
356 doc-view-current-doc)
357 "page-%d.png"))) 396 "page-%d.png")))
358 (doc-view-pdf/ps->png pdf png)))) 397 (doc-view-pdf/ps->png pdf png))))
359 398
@@ -361,9 +400,10 @@ It'a a subdirectory of `doc-view-cache-directory'."
361 "Convert DVI to PDF asynchrounously." 400 "Convert DVI to PDF asynchrounously."
362 (message "DocView: converting DVI to PDF now!") 401 (message "DocView: converting DVI to PDF now!")
363 (setq doc-view-current-converter-process 402 (setq doc-view-current-converter-process
364 (start-process "doc-view-dvi->pdf" doc-view-conversion-buffer 403 (start-process "dvi->pdf" doc-view-conversion-buffer
365 doc-view-dvipdfm-program 404 doc-view-dvipdfm-program
366 "-o" pdf dvi)) 405 "-o" pdf dvi)
406 mode-line-process (list (format ":%s" doc-view-current-converter-process)))
367 (set-process-sentinel doc-view-current-converter-process 407 (set-process-sentinel doc-view-current-converter-process
368 'doc-view-dvi->pdf-sentinel) 408 'doc-view-dvi->pdf-sentinel)
369 (process-put doc-view-current-converter-process 'buffer (current-buffer)) 409 (process-put doc-view-current-converter-process 'buffer (current-buffer))
@@ -374,7 +414,8 @@ It'a a subdirectory of `doc-view-cache-directory'."
374 (if (not (string-match "finished" event)) 414 (if (not (string-match "finished" event))
375 (message "DocView: converter process changed status to %s." event) 415 (message "DocView: converter process changed status to %s." event)
376 (set-buffer (process-get proc 'buffer)) 416 (set-buffer (process-get proc 'buffer))
377 (setq doc-view-current-converter-process nil) 417 (setq doc-view-current-converter-process nil
418 mode-line-process nil)
378 (when doc-view-current-timer 419 (when doc-view-current-timer
379 (cancel-timer doc-view-current-timer) 420 (cancel-timer doc-view-current-timer)
380 (setq doc-view-current-timer nil)) 421 (setq doc-view-current-timer nil))
@@ -387,11 +428,12 @@ It'a a subdirectory of `doc-view-cache-directory'."
387 (message "DocView: converting PDF or PS to PNG now!") 428 (message "DocView: converting PDF or PS to PNG now!")
388 (setq doc-view-current-converter-process 429 (setq doc-view-current-converter-process
389 (apply 'start-process 430 (apply 'start-process
390 (append (list "doc-view-pdf/ps->png" doc-view-conversion-buffer 431 (append (list "pdf/ps->png" doc-view-conversion-buffer
391 doc-view-ghostscript-program) 432 doc-view-ghostscript-program)
392 doc-view-ghostscript-options 433 doc-view-ghostscript-options
393 (list (concat "-sOutputFile=" png)) 434 (list (concat "-sOutputFile=" png))
394 (list pdf-ps)))) 435 (list pdf-ps)))
436 mode-line-process (list (format ":%s" doc-view-current-converter-process)))
395 (process-put doc-view-current-converter-process 437 (process-put doc-view-current-converter-process
396 'buffer (current-buffer)) 438 'buffer (current-buffer))
397 (set-process-sentinel doc-view-current-converter-process 439 (set-process-sentinel doc-view-current-converter-process
@@ -399,7 +441,7 @@ It'a a subdirectory of `doc-view-cache-directory'."
399 (when doc-view-conversion-refresh-interval 441 (when doc-view-conversion-refresh-interval
400 (setq doc-view-current-timer 442 (setq doc-view-current-timer
401 (run-at-time "1 secs" doc-view-conversion-refresh-interval 443 (run-at-time "1 secs" doc-view-conversion-refresh-interval
402 'doc-view-display 444 'doc-view-display-maybe
403 doc-view-current-doc)))) 445 doc-view-current-doc))))
404 446
405(defun doc-view-pdf->txt-sentinel (proc event) 447(defun doc-view-pdf->txt-sentinel (proc event)
@@ -408,7 +450,8 @@ It'a a subdirectory of `doc-view-cache-directory'."
408 (let ((current-buffer (current-buffer)) 450 (let ((current-buffer (current-buffer))
409 (proc-buffer (process-get proc 'buffer))) 451 (proc-buffer (process-get proc 'buffer)))
410 (set-buffer proc-buffer) 452 (set-buffer proc-buffer)
411 (setq doc-view-current-converter-process nil) 453 (setq doc-view-current-converter-process nil
454 mode-line-process nil)
412 (message "DocView: finished conversion from PDF to TXT!") 455 (message "DocView: finished conversion from PDF to TXT!")
413 ;; If the user looks at the DocView buffer where the conversion was 456 ;; If the user looks at the DocView buffer where the conversion was
414 ;; performed, search anew. This time it will be queried for a regexp. 457 ;; performed, search anew. This time it will be queried for a regexp.
@@ -419,9 +462,10 @@ It'a a subdirectory of `doc-view-cache-directory'."
419 "Convert PDF to TXT asynchrounously." 462 "Convert PDF to TXT asynchrounously."
420 (message "DocView: converting PDF to TXT now!") 463 (message "DocView: converting PDF to TXT now!")
421 (setq doc-view-current-converter-process 464 (setq doc-view-current-converter-process
422 (start-process "doc-view-pdf->txt" doc-view-conversion-buffer 465 (start-process "pdf->txt" doc-view-conversion-buffer
423 doc-view-pdftotext-program "-raw" 466 doc-view-pdftotext-program "-raw"
424 pdf txt)) 467 pdf txt)
468 mode-line-process (list (format ":%s" doc-view-current-converter-process)))
425 (set-process-sentinel doc-view-current-converter-process 469 (set-process-sentinel doc-view-current-converter-process
426 'doc-view-pdf->txt-sentinel) 470 'doc-view-pdf->txt-sentinel)
427 (process-put doc-view-current-converter-process 'buffer (current-buffer))) 471 (process-put doc-view-current-converter-process 'buffer (current-buffer)))
@@ -430,65 +474,44 @@ It'a a subdirectory of `doc-view-cache-directory'."
430 (if (not (string-match "finished" event)) 474 (if (not (string-match "finished" event))
431 (message "DocView: converter process changed status to %s." event) 475 (message "DocView: converter process changed status to %s." event)
432 (set-buffer (process-get proc 'buffer)) 476 (set-buffer (process-get proc 'buffer))
433 (setq doc-view-current-converter-process nil) 477 (setq doc-view-current-converter-process nil
478 mode-line-process nil)
434 (message "DocView: finished conversion from PS to PDF!") 479 (message "DocView: finished conversion from PS to PDF!")
435 ;; Now we can transform to plain text. 480 ;; Now we can transform to plain text.
436 (doc-view-pdf->txt (process-get proc 'pdf-file) 481 (doc-view-pdf->txt (process-get proc 'pdf-file)
437 (concat (doc-view-file-name-to-directory-name 482 (concat (doc-view-current-cache-dir)
438 doc-view-current-doc)
439 "doc.txt")))) 483 "doc.txt"))))
440 484
441(defun doc-view-ps->pdf (ps pdf) 485(defun doc-view-ps->pdf (ps pdf)
442 "Convert PS to PDF asynchronously." 486 "Convert PS to PDF asynchronously."
443 (message "DocView: converting PS to PDF now!") 487 (message "DocView: converting PS to PDF now!")
444 (setq doc-view-current-converter-process 488 (setq doc-view-current-converter-process
445 (start-process "doc-view-ps->pdf" doc-view-conversion-buffer 489 (start-process "ps->pdf" doc-view-conversion-buffer
446 doc-view-ps2pdf-program 490 doc-view-ps2pdf-program
447 ps pdf)) 491 ps pdf "-dSAFER")
492 mode-line-process (list (format ":%s" doc-view-current-converter-process)))
448 (set-process-sentinel doc-view-current-converter-process 493 (set-process-sentinel doc-view-current-converter-process
449 'doc-view-ps->pdf-sentinel) 494 'doc-view-ps->pdf-sentinel)
450 (process-put doc-view-current-converter-process 'buffer (current-buffer)) 495 (process-put doc-view-current-converter-process 'buffer (current-buffer))
451 (process-put doc-view-current-converter-process 'pdf-file pdf)) 496 (process-put doc-view-current-converter-process 'pdf-file pdf))
452 497
453(defun doc-view-convert-doc (doc) 498(defun doc-view-convert-current-doc ()
454 "Convert DOC to a set of png files, one file per page. 499 "Convert `doc-view-current-doc' to a set of png files, one file per page.
455 500Those files are saved in the directory given by the function
456Those files are saved in the directory given by 501`doc-view-current-cache-dir'."
457`doc-view-file-name-to-directory-name'."
458 (clear-image-cache) 502 (clear-image-cache)
459 (let* ((dir (doc-view-file-name-to-directory-name doc)) 503 (let ((png-file (concat (doc-view-current-cache-dir)
460 (png-file (concat (file-name-as-directory dir) "page-%d.png"))) 504 "page-%d.png")))
461 (when (file-exists-p dir) 505 (make-directory doc-view-current-cache-dir t)
462 (dired-delete-file dir 'always)) 506 (if (not (string= (file-name-extension doc-view-current-doc) "dvi"))
463 (make-directory dir t)
464 (if (not (string= (file-name-extension doc) "dvi"))
465 ;; Convert to PNG images. 507 ;; Convert to PNG images.
466 (doc-view-pdf/ps->png doc png-file) 508 (doc-view-pdf/ps->png doc-view-current-doc png-file)
467 ;; DVI files have to be converted to PDF before Ghostscript can process 509 ;; DVI files have to be converted to PDF before Ghostscript can process
468 ;; it. 510 ;; it.
469 (doc-view-dvi->pdf doc 511 (doc-view-dvi->pdf doc-view-current-doc
470 (concat (file-name-as-directory dir) 512 (concat (file-name-as-directory doc-view-current-cache-dir)
471 "doc.pdf"))))) 513 "doc.pdf")))))
472 514
473;;;; DocView Mode
474
475(define-derived-mode doc-view-mode nil "DocView"
476 "Major mode in DocView buffers.
477
478\\{doc-view-mode-map}"
479 :group 'doc-view
480 (setq buffer-read-only t)
481 (make-local-variable 'doc-view-current-files)
482 (make-local-variable 'doc-view-current-doc)
483 (make-local-variable 'doc-view-current-image)
484 (make-local-variable 'doc-view-current-page)
485 (make-local-variable 'doc-view-current-converter-process)
486 (make-local-variable 'doc-view-current-timer)
487 (make-local-variable 'doc-view-current-slice)
488 (make-local-variable 'doc-view-current-cache-dir)
489 (make-local-variable 'doc-view-current-info)
490 (make-local-variable 'doc-view-current-search-matches))
491
492;;;; Slicing 515;;;; Slicing
493 516
494(defun doc-view-set-slice (x y width height) 517(defun doc-view-set-slice (x y width height)
@@ -556,19 +579,22 @@ Predicate for sorting `doc-view-current-files'."
556 nil 579 nil
557 (string< a b)))) 580 (string< a b))))
558 581
582(defun doc-view-display-maybe (doc)
583 "Call `doc-view-display' iff we're in the image display."
584 (when (eq doc-view-current-display 'image)
585 (doc-view-display doc)))
586
559(defun doc-view-display (doc) 587(defun doc-view-display (doc)
560 "Start viewing the document DOC." 588 "Start viewing the document DOC."
561 (let ((dir (doc-view-file-name-to-directory-name doc))) 589 (set-buffer (get-file-buffer doc))
562 (set-buffer (format "*DocView: %s*" doc)) 590 (setq doc-view-current-files
563 (setq doc-view-current-files 591 (sort (directory-files (doc-view-current-cache-dir) t
564 (sort (directory-files dir t "page-[0-9]+\\.png" t) 592 "page-[0-9]+\\.png" t)
565 'doc-view-sort)) 593 'doc-view-sort))
566 (when (> (length doc-view-current-files) 0) 594 (when (> (length doc-view-current-files) 0)
567 (doc-view-goto-page doc-view-current-page)))) 595 (doc-view-goto-page doc-view-current-page)))
568 596
569(defun doc-view-buffer-message () 597(defun doc-view-buffer-message ()
570 (setq inhibit-read-only t)
571 (erase-buffer)
572 (insert (propertize "Welcome to DocView!" 'face 'bold) 598 (insert (propertize "Welcome to DocView!" 'face 'bold)
573 "\n" 599 "\n"
574 " 600 "
@@ -581,12 +607,58 @@ For now these keys are useful:
581 607
582`q' : Bury this buffer. Conversion will go on in background. 608`q' : Bury this buffer. Conversion will go on in background.
583`k' : Kill the conversion process and this buffer.\n") 609`k' : Kill the conversion process and this buffer.\n")
584 (setq inhibit-read-only nil)) 610 (set-buffer-modified-p nil))
585 611
586(defun doc-view-show-tooltip () 612(defun doc-view-show-tooltip ()
587 (interactive) 613 (interactive)
588 (tooltip-show doc-view-current-info)) 614 (tooltip-show doc-view-current-info))
589 615
616;;;;; Toggle between text and image display
617
618(defun doc-view-toggle-display ()
619 "Start or stop displaying a document file as a set of images.
620This command toggles between showing the text of the document
621file and showing the document as a set of images."
622 (interactive)
623 (if (get-text-property (point-min) 'display)
624 ;; Switch to text display
625 (let ((inhibit-read-only t))
626 (erase-buffer)
627 (insert-file-contents doc-view-current-doc)
628 (use-local-map doc-view-mode-text-map)
629 (setq mode-name "DocView[text]"
630 doc-view-current-display 'text)
631 (if (called-interactively-p)
632 (message "Repeat this command to go back to displaying the file as images")))
633 ;; Switch to image display
634 (let ((inhibit-read-only t))
635 (erase-buffer)
636 (doc-view-buffer-message)
637 (setq doc-view-current-page (or doc-view-current-page 1))
638 (if (file-exists-p (doc-view-current-cache-dir))
639 (progn
640 (message "DocView: using cached files!")
641 (doc-view-display doc-view-current-doc))
642 (doc-view-convert-current-doc))
643 (use-local-map doc-view-mode-map)
644 (setq mode-name (format "DocView")
645 doc-view-current-display 'image)
646 (if (called-interactively-p)
647 (message "Repeat this command to go back to displaying the file as text"))))
648 (set-buffer-modified-p nil))
649
650;;;;; Leave doc-view-mode and open the file for edit
651
652(defun doc-view-edit-doc ()
653 "Leave `doc-view-mode' and open the current doc with an appropriate editing mode."
654 (interactive)
655 (let ((filename doc-view-current-doc)
656 (auto-mode-alist (append '(("\\.[eE]?[pP][sS]\\'" . ps-mode)
657 ("\\.\\(pdf\\|PDF\\|dvi\\|DVI\\)$" . fundamental-mode))
658 auto-mode-alist)))
659 (kill-buffer (current-buffer))
660 (find-file filename)))
661
590;;;; Searching 662;;;; Searching
591 663
592(defun doc-view-search-internal (regexp file) 664(defun doc-view-search-internal (regexp file)
@@ -637,8 +709,7 @@ conversion finished."
637 (interactive) 709 (interactive)
638 ;; New search, so forget the old results. 710 ;; New search, so forget the old results.
639 (setq doc-view-current-search-matches nil) 711 (setq doc-view-current-search-matches nil)
640 (let ((txt (concat (doc-view-file-name-to-directory-name 712 (let ((txt (concat (doc-view-current-cache-dir)
641 doc-view-current-doc)
642 "doc.txt"))) 713 "doc.txt")))
643 (if (file-readable-p txt) 714 (if (file-readable-p txt)
644 (progn 715 (progn
@@ -661,14 +732,12 @@ conversion finished."
661 ;; Doc is a PS, so convert it to PDF (which will be converted to 732 ;; Doc is a PS, so convert it to PDF (which will be converted to
662 ;; TXT thereafter). 733 ;; TXT thereafter).
663 (doc-view-ps->pdf doc-view-current-doc 734 (doc-view-ps->pdf doc-view-current-doc
664 (concat (doc-view-file-name-to-directory-name 735 (concat (doc-view-current-cache-dir)
665 doc-view-current-doc)
666 "doc.pdf"))) 736 "doc.pdf")))
667 ((string= ext "dvi") 737 ((string= ext "dvi")
668 ;; Doc is a DVI. This means that a doc.pdf already exists in its 738 ;; Doc is a DVI. This means that a doc.pdf already exists in its
669 ;; cache subdirectory. 739 ;; cache subdirectory.
670 (doc-view-pdf->txt (concat (doc-view-file-name-to-directory-name 740 (doc-view-pdf->txt (concat (doc-view-current-cache-dir)
671 doc-view-current-doc)
672 "doc.pdf") 741 "doc.pdf")
673 txt)) 742 txt))
674 (t (error "DocView doesn't know what to do")))))))) 743 (t (error "DocView doesn't know what to do"))))))))
@@ -699,52 +768,42 @@ conversion finished."
699 (y-or-n-p "No more matches before current page. Wrap to last match? ")) 768 (y-or-n-p "No more matches before current page. Wrap to last match? "))
700 (doc-view-goto-page (caar (last doc-view-current-search-matches))))))) 769 (doc-view-goto-page (caar (last doc-view-current-search-matches)))))))
701 770
702;;;; User Interface Commands 771;;;; User interface commands and the mode
703 772
704;;;###autoload 773(put 'doc-view-mode 'mode-class 'special)
705(defun doc-view (no-cache &optional file)
706 "Convert FILE to png and start viewing it.
707If no FILE is given, query for on.
708If this FILE is still in the cache, don't convert and use the
709existing page files. With prefix arg NO-CACHE, don't use the
710cached files and convert anew."
711 (interactive "P")
712 (if (not (and (image-type-available-p 'png)
713 (display-images-p)))
714 (message "DocView: your emacs or display doesn't support png images.")
715 (let* ((doc (or file
716 (expand-file-name
717 (let ((completion-ignored-extensions
718 ;; Don't hide files doc-view can display
719 (remove-if (lambda (str)
720 (string-match "\\.\\(ps\\|pdf\\|dvi\\)$"
721 str))
722 completion-ignored-extensions)))
723 (read-file-name "File: " nil nil t)))))
724 (buffer (get-buffer-create (format "*DocView: %s*" doc)))
725 (dir (doc-view-file-name-to-directory-name doc)))
726 (switch-to-buffer buffer)
727 (doc-view-buffer-message)
728 (doc-view-mode)
729 (setq doc-view-current-doc doc)
730 (setq doc-view-current-page 1)
731 (if (not (and (file-exists-p dir)
732 (not no-cache)))
733 (progn
734 (setq doc-view-current-cache-dir nil)
735 (doc-view-convert-doc doc-view-current-doc))
736 (message "DocView: using cached files!")
737 (doc-view-display doc-view-current-doc)))))
738 774
739(defun doc-view-dired (no-cache) 775;;;###autoload
740 "View the current dired file with doc-view. 776(define-derived-mode doc-view-mode nil "DocView"
741NO-CACHE is the same as in `doc-view'. 777 "Major mode in DocView buffers.
742 778You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to
743You might want to bind this command to a dired key, e.g. 779toggle between display as a set of images and display as text."
744 780 :group 'doc-view
745 (define-key dired-mode-map (kbd \"C-c d\") 'doc-view-dired)" 781 (make-local-variable 'doc-view-current-files)
746 (interactive "P") 782 (make-local-variable 'doc-view-current-doc)
747 (doc-view no-cache (dired-get-file-for-visit))) 783 (make-local-variable 'doc-view-current-image)
784 (make-local-variable 'doc-view-current-page)
785 (make-local-variable 'doc-view-current-converter-process)
786 (make-local-variable 'doc-view-current-timer)
787 (make-local-variable 'doc-view-current-slice)
788 (make-local-variable 'doc-view-current-cache-dir)
789 (make-local-variable 'doc-view-current-info)
790 (make-local-variable 'doc-view-current-search-matches)
791 (setq doc-view-current-doc (buffer-file-name))
792 (insert-file-contents doc-view-current-doc)
793 (use-local-map doc-view-mode-text-map)
794 (setq mode-name "DocView[text]"
795 doc-view-current-display 'text
796 buffer-read-only t
797 revert-buffer-function 'doc-view-reconvert-doc)
798 ;; Switch to image display if possible
799 (if (and (display-images-p)
800 (image-type-available-p 'png)
801 (not (get-text-property (point-min) 'display)))
802 (doc-view-toggle-display))
803 (message
804 "%s"
805 (substitute-command-keys
806 "Type \\[doc-view-toggle-display] to toggle between image and text display.")))
748 807
749(defun doc-view-clear-cache () 808(defun doc-view-clear-cache ()
750 "Delete the whole cache (`doc-view-cache-directory')." 809 "Delete the whole cache (`doc-view-cache-directory')."
diff --git a/lisp/files.el b/lisp/files.el
index be28dec4c40..3b0b670e21f 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -2059,7 +2059,7 @@ ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
2059 ("\\.\\(as\\|mi\\|sm\\)2\\'" . snmpv2-mode) 2059 ("\\.\\(as\\|mi\\|sm\\)2\\'" . snmpv2-mode)
2060 ("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode) 2060 ("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode)
2061 ("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MSDOG 2061 ("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MSDOG
2062 ("\\.[eE]?[pP][sS]\\'" . ps-mode) 2062 ("\\(?:DVI\\|EPS\\|P\\(?:DF\\|S\\)\\|dvi\\|eps\\|p\\(?:df\\|s\\)\\)" . doc-view-mode)
2063 ("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode) 2063 ("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
2064 ("BROWSE\\'" . ebrowse-tree-mode) 2064 ("BROWSE\\'" . ebrowse-tree-mode)
2065 ("\\.ebrowse\\'" . ebrowse-tree-mode) 2065 ("\\.ebrowse\\'" . ebrowse-tree-mode)