aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/doc-view.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/doc-view.el')
-rw-r--r--lisp/doc-view.el203
1 files changed, 121 insertions, 82 deletions
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 9c153dc584f..aaa68bf6387 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -99,11 +99,11 @@
99 99
100;;; Todo: 100;;; Todo:
101 101
102;; - share more code with image-mode again.
102;; - better menu. 103;; - better menu.
103;; - don't use `find-file'.
104;; - Bind slicing to a drag event. 104;; - Bind slicing to a drag event.
105;; - doc-view-fit-doc-to-window and doc-view-fit-window-to-doc. 105;; - doc-view-fit-doc-to-window and doc-view-fit-window-to-doc.
106;; - zoom a the region around the cursor (like xdvi). 106;; - zoom the region around the cursor (like xdvi).
107;; - get rid of the silly arrow in the fringe. 107;; - get rid of the silly arrow in the fringe.
108;; - improve anti-aliasing (pdf-utils gets it better). 108;; - improve anti-aliasing (pdf-utils gets it better).
109 109
@@ -247,6 +247,14 @@ has finished."
247(defvar doc-view-previous-major-mode nil 247(defvar doc-view-previous-major-mode nil
248 "Only used internally.") 248 "Only used internally.")
249 249
250(defvar doc-view-buffer-file-name nil
251 "Only used internally.
252The file name used for conversion. Normally it's the same as
253`buffer-file-name', but for remote files, compressed files and
254files inside an archive it is a temporary copy of
255the (uncompressed, extracted) file residing in
256`doc-view-cache-directory'.")
257
250;;;; DocView Keymaps 258;;;; DocView Keymaps
251 259
252(defvar doc-view-mode-map 260(defvar doc-view-mode-map
@@ -349,12 +357,7 @@ has finished."
349 ;; Update the buffer 357 ;; Update the buffer
350 (doc-view-insert-image (nth (1- page) doc-view-current-files) 358 (doc-view-insert-image (nth (1- page) doc-view-current-files)
351 :pointer 'arrow) 359 :pointer 'arrow)
352 (overlay-put doc-view-current-overlay 'help-echo doc-view-current-info) 360 (overlay-put doc-view-current-overlay 'help-echo doc-view-current-info)))
353 (goto-char (point-min))
354 ;; This seems to be needed for set-window-hscroll (in
355 ;; image-forward-hscroll) to do something useful, I don't have time to
356 ;; debug this now. :-( --Stef
357 (forward-char)))
358 361
359(defun doc-view-next-page (&optional arg) 362(defun doc-view-next-page (&optional arg)
360 "Browse ARG pages forward." 363 "Browse ARG pages forward."
@@ -450,12 +453,12 @@ It's a subdirectory of `doc-view-cache-directory'."
450 (setq doc-view-current-cache-dir 453 (setq doc-view-current-cache-dir
451 (file-name-as-directory 454 (file-name-as-directory
452 (expand-file-name 455 (expand-file-name
453 (let ((doc buffer-file-name)) 456 (concat (file-name-nondirectory buffer-file-name)
454 (concat (file-name-nondirectory doc) 457 "-"
455 "-" 458 (let ((file doc-view-buffer-file-name))
456 (with-temp-buffer 459 (with-temp-buffer
457 (insert-file-contents-literally doc) 460 (insert-file-contents-literally file)
458 (md5 (current-buffer))))) 461 (md5 (current-buffer)))))
459 doc-view-cache-directory))))) 462 doc-view-cache-directory)))))
460 463
461(defun doc-view-remove-if (predicate list) 464(defun doc-view-remove-if (predicate list)
@@ -476,7 +479,7 @@ Image types are symbols like `dvi', `postscript' or `pdf'."
476 (and (doc-view-mode-p 'pdf) 479 (and (doc-view-mode-p 'pdf)
477 doc-view-dvipdfm-program 480 doc-view-dvipdfm-program
478 (executable-find doc-view-dvipdfm-program))) 481 (executable-find doc-view-dvipdfm-program)))
479 ((or (eq type 'postscript) (eq type 'ps) 482 ((or (eq type 'postscript) (eq type 'ps) (eq type 'eps)
480 (eq type 'pdf)) 483 (eq type 'pdf))
481 (and doc-view-ghostscript-program 484 (and doc-view-ghostscript-program
482 (executable-find doc-view-ghostscript-program))) 485 (executable-find doc-view-ghostscript-program)))
@@ -550,13 +553,16 @@ Should be invoked when the cached images aren't up-to-date."
550(defun doc-view-pdf/ps->png (pdf-ps png) 553(defun doc-view-pdf/ps->png (pdf-ps png)
551 "Convert PDF-PS to PNG asynchronously." 554 "Convert PDF-PS to PNG asynchronously."
552 (setq doc-view-current-converter-process 555 (setq doc-view-current-converter-process
553 (apply 'start-process 556 ;; Make sure the process is started in an existing directory,
554 (append (list "pdf/ps->png" doc-view-conversion-buffer 557 ;; (rather than some file-name-handler-managed dir, for example).
555 doc-view-ghostscript-program) 558 (let ((default-directory (file-name-directory pdf-ps)))
556 doc-view-ghostscript-options 559 (apply 'start-process
557 (list (format "-r%d" (round doc-view-resolution))) 560 (append (list "pdf/ps->png" doc-view-conversion-buffer
558 (list (concat "-sOutputFile=" png)) 561 doc-view-ghostscript-program)
559 (list pdf-ps))) 562 doc-view-ghostscript-options
563 (list (format "-r%d" (round doc-view-resolution)))
564 (list (concat "-sOutputFile=" png))
565 (list pdf-ps))))
560 mode-line-process (list (format ":%s" doc-view-current-converter-process))) 566 mode-line-process (list (format ":%s" doc-view-current-converter-process)))
561 (process-put doc-view-current-converter-process 567 (process-put doc-view-current-converter-process
562 'buffer (current-buffer)) 568 'buffer (current-buffer))
@@ -620,7 +626,7 @@ Should be invoked when the cached images aren't up-to-date."
620 (process-put doc-view-current-converter-process 'pdf-file pdf)) 626 (process-put doc-view-current-converter-process 'pdf-file pdf))
621 627
622(defun doc-view-convert-current-doc () 628(defun doc-view-convert-current-doc ()
623 "Convert `buffer-file-name' to a set of png files, one file per page. 629 "Convert `doc-view-buffer-file-name' to a set of png files, one file per page.
624Those files are saved in the directory given by the function 630Those files are saved in the directory given by the function
625`doc-view-current-cache-dir'." 631`doc-view-current-cache-dir'."
626 ;; Let stale files still display while we recompute the new ones, so only 632 ;; Let stale files still display while we recompute the new ones, so only
@@ -632,12 +638,12 @@ Those files are saved in the directory given by the function
632 (let ((png-file (expand-file-name "page-%d.png" 638 (let ((png-file (expand-file-name "page-%d.png"
633 (doc-view-current-cache-dir)))) 639 (doc-view-current-cache-dir))))
634 (make-directory (doc-view-current-cache-dir)) 640 (make-directory (doc-view-current-cache-dir))
635 (if (not (string= (file-name-extension buffer-file-name) "dvi")) 641 (if (not (string= (file-name-extension doc-view-buffer-file-name) "dvi"))
636 ;; Convert to PNG images. 642 ;; Convert to PNG images.
637 (doc-view-pdf/ps->png buffer-file-name png-file) 643 (doc-view-pdf/ps->png doc-view-buffer-file-name png-file)
638 ;; DVI files have to be converted to PDF before Ghostscript can process 644 ;; DVI files have to be converted to PDF before Ghostscript can process
639 ;; it. 645 ;; it.
640 (doc-view-dvi->pdf buffer-file-name 646 (doc-view-dvi->pdf doc-view-buffer-file-name
641 (expand-file-name "doc.pdf" 647 (expand-file-name "doc.pdf"
642 doc-view-current-cache-dir))))) 648 doc-view-current-cache-dir)))))
643 649
@@ -697,13 +703,23 @@ ARGS is a list of image descriptors."
697 (when doc-view-pending-cache-flush 703 (when doc-view-pending-cache-flush
698 (clear-image-cache) 704 (clear-image-cache)
699 (setq doc-view-pending-cache-flush nil)) 705 (setq doc-view-pending-cache-flush nil))
700 (let ((image (apply 'create-image file 'png nil args))) 706 (if (null file)
701 (setq doc-view-current-image image) 707 ;; We're trying to display a page that doesn't exist. Typically happens
702 (move-overlay doc-view-current-overlay (point-min) (point-max)) 708 ;; if the conversion process somehow failed. Better not signal an
703 (overlay-put doc-view-current-overlay 'display 709 ;; error here because it could prevent a subsequent reconversion from
704 (if doc-view-current-slice 710 ;; fixing the problem.
705 (list (cons 'slice doc-view-current-slice) image) 711 (progn
706 image)))) 712 (setq doc-view-current-image nil)
713 (move-overlay doc-view-current-overlay (point-min) (point-max))
714 (overlay-put doc-view-current-overlay 'display
715 "Cannot display this page! Probably a conversion failure!"))
716 (let ((image (apply 'create-image file 'png nil args)))
717 (setq doc-view-current-image image)
718 (move-overlay doc-view-current-overlay (point-min) (point-max))
719 (overlay-put doc-view-current-overlay 'display
720 (if doc-view-current-slice
721 (list (cons 'slice doc-view-current-slice) image)
722 image)))))
707 723
708(defun doc-view-sort (a b) 724(defun doc-view-sort (a b)
709 "Return non-nil if A should be sorted before B. 725 "Return non-nil if A should be sorted before B.
@@ -847,15 +863,15 @@ If BACKWARD is non-nil, jump to the previous match."
847 ;; We must convert to TXT first! 863 ;; We must convert to TXT first!
848 (if doc-view-current-converter-process 864 (if doc-view-current-converter-process
849 (message "DocView: please wait till conversion finished.") 865 (message "DocView: please wait till conversion finished.")
850 (let ((ext (file-name-extension buffer-file-name))) 866 (let ((ext (file-name-extension doc-view-buffer-file-name)))
851 (cond 867 (cond
852 ((string= ext "pdf") 868 ((string= ext "pdf")
853 ;; Doc is a PDF, so convert it to TXT 869 ;; Doc is a PDF, so convert it to TXT
854 (doc-view-pdf->txt buffer-file-name txt)) 870 (doc-view-pdf->txt doc-view-buffer-file-name txt))
855 ((string= ext "ps") 871 ((string= ext "ps")
856 ;; Doc is a PS, so convert it to PDF (which will be converted to 872 ;; Doc is a PS, so convert it to PDF (which will be converted to
857 ;; TXT thereafter). 873 ;; TXT thereafter).
858 (doc-view-ps->pdf buffer-file-name 874 (doc-view-ps->pdf doc-view-buffer-file-name
859 (expand-file-name "doc.pdf" 875 (expand-file-name "doc.pdf"
860 (doc-view-current-cache-dir)))) 876 (doc-view-current-cache-dir))))
861 ((string= ext "dvi") 877 ((string= ext "dvi")
@@ -900,7 +916,7 @@ If BACKWARD is non-nil, jump to the previous match."
900 916
901(defun doc-view-initiate-display () 917(defun doc-view-initiate-display ()
902 ;; Switch to image display if possible 918 ;; Switch to image display if possible
903 (if (doc-view-mode-p (intern (file-name-extension buffer-file-name))) 919 (if (doc-view-mode-p (intern (file-name-extension doc-view-buffer-file-name)))
904 (progn 920 (progn
905 (doc-view-buffer-message) 921 (doc-view-buffer-message)
906 (setq doc-view-current-page (or doc-view-current-page 1)) 922 (setq doc-view-current-page (or doc-view-current-page 1))
@@ -918,7 +934,7 @@ If BACKWARD is non-nil, jump to the previous match."
918 "%s" 934 "%s"
919 (substitute-command-keys 935 (substitute-command-keys
920 (concat "No image (png) support available or some conversion utility for " 936 (concat "No image (png) support available or some conversion utility for "
921 (file-name-extension buffer-file-name)" files is missing. " 937 (file-name-extension doc-view-buffer-file-name)" files is missing. "
922 "Type \\[doc-view-toggle-display] to switch to an editing mode."))))) 938 "Type \\[doc-view-toggle-display] to switch to an editing mode.")))))
923 939
924(defvar bookmark-make-cell-function) 940(defvar bookmark-make-cell-function)
@@ -929,49 +945,72 @@ If BACKWARD is non-nil, jump to the previous match."
929You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to 945You can use \\<doc-view-mode-map>\\[doc-view-toggle-display] to
930toggle between displaying the document or editing it as text." 946toggle between displaying the document or editing it as text."
931 (interactive) 947 (interactive)
932 (if jka-compr-really-do-compress 948
933 ;; This is a compressed file uncompressed by auto-compression-mode. 949 (let* ((prev-major-mode (if (eq major-mode 'doc-view-mode)
934 (when (y-or-n-p (concat "DocView: Cannot convert compressed file. " 950 doc-view-previous-major-mode
935 "Save it uncompressed first? ")) 951 major-mode)))
936 (let ((file (read-file-name 952 (kill-all-local-variables)
937 "File: " 953 (set (make-local-variable 'doc-view-previous-major-mode) prev-major-mode))
938 (file-name-directory buffer-file-name)))) 954
939 (write-region (point-min) (point-max) file) 955 ;; Handle compressed files, remote files, files inside archives
940 (kill-buffer nil) 956 (set (make-local-variable 'doc-view-buffer-file-name)
941 (find-file file) 957 (cond
942 (doc-view-mode))) 958 (jka-compr-really-do-compress
943 (let* ((prev-major-mode (if (eq major-mode 'doc-view-mode) 959 (expand-file-name
944 doc-view-previous-major-mode 960 (file-name-nondirectory
945 major-mode))) 961 (file-name-sans-extension buffer-file-name))
946 (kill-all-local-variables) 962 doc-view-cache-directory))
947 (set (make-local-variable 'doc-view-previous-major-mode) prev-major-mode)) 963 ;; Is the file readable by local processes?
948 (make-local-variable 'doc-view-current-files) 964 ;; We used to use `file-remote-p' but it's unclear what it's
949 (make-local-variable 'doc-view-current-image) 965 ;; supposed to return nil for things like local files accessed via
950 (make-local-variable 'doc-view-current-page) 966 ;; `su' or via file://...
951 (make-local-variable 'doc-view-current-converter-process) 967 ((let ((file-name-handler-alist nil))
952 (make-local-variable 'doc-view-current-timer) 968 (not (file-readable-p buffer-file-name)))
953 (make-local-variable 'doc-view-current-slice) 969 (expand-file-name
954 (make-local-variable 'doc-view-current-cache-dir) 970 (file-name-nondirectory buffer-file-name)
955 (make-local-variable 'doc-view-current-info) 971 doc-view-cache-directory))
956 (make-local-variable 'doc-view-current-search-matches) 972 (t buffer-file-name)))
957 (set (make-local-variable 'doc-view-current-overlay) 973 (when (not (string= doc-view-buffer-file-name buffer-file-name))
958 (make-overlay (point-min) (point-max) nil t)) 974 (write-region nil nil doc-view-buffer-file-name))
959 (add-hook 'change-major-mode-hook 975
960 (lambda () (delete-overlay doc-view-current-overlay)) 976 (make-local-variable 'doc-view-current-files)
961 nil t) 977 (make-local-variable 'doc-view-current-image)
962 (set (make-local-variable 'mode-line-position) 978 (make-local-variable 'doc-view-current-page)
963 '(" P" (:eval (number-to-string doc-view-current-page)) 979 (make-local-variable 'doc-view-current-converter-process)
964 "/" (:eval (number-to-string (length doc-view-current-files))))) 980 (make-local-variable 'doc-view-current-timer)
965 (set (make-local-variable 'cursor-type) nil) 981 (make-local-variable 'doc-view-current-slice)
966 (use-local-map doc-view-mode-map) 982 (make-local-variable 'doc-view-current-cache-dir)
967 (set (make-local-variable 'after-revert-hook) 'doc-view-reconvert-doc) 983 (make-local-variable 'doc-view-current-info)
968 (set (make-local-variable 'bookmark-make-cell-function) 984 (make-local-variable 'doc-view-current-search-matches)
969 'doc-view-bookmark-make-cell) 985 (set (make-local-variable 'doc-view-current-overlay)
970 (setq mode-name "DocView" 986 (make-overlay (point-min) (point-max) nil t))
971 buffer-read-only t 987 (add-hook 'change-major-mode-hook
972 major-mode 'doc-view-mode) 988 (lambda () (delete-overlay doc-view-current-overlay))
973 (doc-view-initiate-display) 989 nil t)
974 (run-mode-hooks 'doc-view-mode-hook))) 990
991 ;; Keep track of [vh]scroll when switching buffers
992 (make-local-variable 'image-mode-current-hscroll)
993 (make-local-variable 'image-mode-current-vscroll)
994 (image-set-window-hscroll (selected-window) (window-hscroll))
995 (image-set-window-vscroll (selected-window) (window-vscroll))
996 (add-hook 'window-configuration-change-hook
997 'image-reset-current-vhscroll nil t)
998
999 (set (make-local-variable 'mode-line-position)
1000 '(" P" (:eval (number-to-string doc-view-current-page))
1001 "/" (:eval (number-to-string (length doc-view-current-files)))))
1002 ;; Don't scroll unless the user specifically asked for it.
1003 (set (make-local-variable 'auto-hscroll-mode) nil)
1004 (set (make-local-variable 'cursor-type) nil)
1005 (use-local-map doc-view-mode-map)
1006 (set (make-local-variable 'after-revert-hook) 'doc-view-reconvert-doc)
1007 (set (make-local-variable 'bookmark-make-cell-function)
1008 'doc-view-bookmark-make-cell)
1009 (setq mode-name "DocView"
1010 buffer-read-only t
1011 major-mode 'doc-view-mode)
1012 (doc-view-initiate-display)
1013 (run-mode-hooks 'doc-view-mode-hook))
975 1014
976;;;###autoload 1015;;;###autoload
977(define-minor-mode doc-view-minor-mode 1016(define-minor-mode doc-view-minor-mode
@@ -1003,7 +1042,7 @@ See the command `doc-view-mode' for more information on this mode."
1003 1042
1004(defun doc-view-bookmark-make-cell (annotation &rest args) 1043(defun doc-view-bookmark-make-cell (annotation &rest args)
1005 (let ((the-record 1044 (let ((the-record
1006 `((filename . ,(buffer-file-name)) 1045 `((filename . ,buffer-file-name)
1007 (page . ,doc-view-current-page) 1046 (page . ,doc-view-current-page)
1008 (handler . doc-view-bookmark-jump)))) 1047 (handler . doc-view-bookmark-jump))))
1009 1048