diff options
| author | Reiner Steib | 2007-10-17 21:34:19 +0000 |
|---|---|---|
| committer | Reiner Steib | 2007-10-17 21:34:19 +0000 |
| commit | 640602f766d7431ae40ac5ffa274db405b1c4d7d (patch) | |
| tree | 69fe77c0ddc934d842a20916bf7c5e5b404bd2eb | |
| parent | 57581fccfe5e3a879853efe9fb685d45b9c5b63b (diff) | |
| download | emacs-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/ChangeLog | 15 | ||||
| -rw-r--r-- | lisp/bindings.el | 2 | ||||
| -rw-r--r-- | lisp/doc-view.el | 369 | ||||
| -rw-r--r-- | lisp/files.el | 2 |
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 @@ | |||
| 1 | 2007-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 | |||
| 1 | 2007-10-17 Aaron Hawley <aaronh@garden.org> | 16 | 2007-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 | 361 | Should be invoked when the cached images aren't up-to-date." | |
| 337 | It'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. | ||
| 374 | It'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 | 500 | Those files are saved in the directory given by the function | |
| 456 | Those 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. | ||
| 620 | This command toggles between showing the text of the document | ||
| 621 | file 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. | ||
| 707 | If no FILE is given, query for on. | ||
| 708 | If this FILE is still in the cache, don't convert and use the | ||
| 709 | existing page files. With prefix arg NO-CACHE, don't use the | ||
| 710 | cached 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" |
| 741 | NO-CACHE is the same as in `doc-view'. | 777 | "Major mode in DocView buffers. |
| 742 | 778 | You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to | |
| 743 | You might want to bind this command to a dired key, e.g. | 779 | toggle 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) |