(Vtruncate_partial_width_windows): Improve docstring.
[bpt/emacs.git] / lisp / doc-view.el
index 8817db7..3ea4fce 100644 (file)
@@ -62,7 +62,7 @@
 ;; slice you can use `doc-view-set-slice' (bound to `s s') which will query you
 ;; for the coordinates of the slice's top-left corner and its width and height.
 ;; A much more convenient way to do the same is offered by the command
-;; `doc-view-set-slice-using-mouse' (bound to `s m').  After invokation you
+;; `doc-view-set-slice-using-mouse' (bound to `s m').  After invocation you
 ;; only have to press mouse-1 at the top-left corner and drag it to the
 ;; bottom-right corner of the desired slice.  To reset the slice use
 ;; `doc-view-reset-slice' (bound to `s r').
@@ -74,7 +74,7 @@
 ;; `C-r' you can do the same, but backwards.  To search for a new regexp give a
 ;; prefix arg to one of the search functions, e.g. by typing `C-u C-s'.  The
 ;; searching works by using a plain text representation of the document.  If
-;; that doesn't already exist the first invokation of `doc-view-search' (or
+;; that doesn't already exist the first invocation of `doc-view-search' (or
 ;; `doc-view-search-backward') starts the conversion.  When that finishes and
 ;; you're still viewing the document (i.e. you didn't switch to another buffer)
 ;; you're queried for the regexp then.
@@ -289,6 +289,7 @@ Can be `dvi', `pdf', or `ps'.")
     (define-key map (kbd "M-<")       'doc-view-first-page)
     (define-key map (kbd "M->")       'doc-view-last-page)
     (define-key map [remap goto-line] 'doc-view-goto-page)
+    (define-key map (kbd "RET")       'image-next-line)
     ;; Zoom in/out.
     (define-key map "+"               'doc-view-enlarge)
     (define-key map "-"               'doc-view-shrink)
@@ -346,7 +347,8 @@ Can be `dvi', `pdf', or `ps'.")
 (defun doc-view-goto-page (page)
   "View the page given by PAGE."
   (interactive "nPage: ")
-  (let ((len (length doc-view-current-files)))
+  (let ((len (length doc-view-current-files))
+       (hscroll (window-hscroll)))
     (if (< page 1)
        (setq page 1)
       (when (and (> page len)
@@ -379,6 +381,7 @@ Can be `dvi', `pdf', or `ps'.")
     (let ((file (expand-file-name (format "page-%d.png" page)
                                   (doc-view-current-cache-dir))))
       (doc-view-insert-image file :pointer 'arrow)
+      (set-window-hscroll (selected-window) hscroll)
       (when (and (not (file-exists-p file))
                  doc-view-current-converter-processes)
         ;; The PNG file hasn't been generated yet.
@@ -418,22 +421,26 @@ Can be `dvi', `pdf', or `ps'.")
 (defun doc-view-scroll-up-or-next-page ()
   "Scroll page up if possible, else goto next page."
   (interactive)
-  (when (= (window-vscroll) (image-scroll-up nil))
-    (let ((cur-page (doc-view-current-page)))
+  (let ((hscroll (window-hscroll))
+       (cur-page (doc-view-current-page)))
+    (when (= (window-vscroll) (image-scroll-up nil))
       (doc-view-next-page)
       (when (/= cur-page (doc-view-current-page))
        (image-bob)
-       (image-bol 1)))))
+       (image-bol 1))
+      (set-window-hscroll (selected-window) hscroll))))
 
 (defun doc-view-scroll-down-or-previous-page ()
   "Scroll page down if possible, else goto previous page."
   (interactive)
-  (when (= (window-vscroll) (image-scroll-down nil))
-    (let ((cur-page (doc-view-current-page)))
+  (let ((hscroll (window-hscroll))
+       (cur-page (doc-view-current-page)))
+    (when (= (window-vscroll) (image-scroll-down nil))
       (doc-view-previous-page)
       (when (/= cur-page (doc-view-current-page))
        (image-eob)
-       (image-bol 1)))))
+       (image-bol 1))
+      (set-window-hscroll (selected-window) hscroll))))
 
 ;;;; Utility Functions
 
@@ -557,7 +564,10 @@ Should be invoked when the cached images aren't up-to-date."
   "Generic sentinel for doc-view conversion processes."
   (if (not (string-match "finished" event))
       (message "DocView: process %s changed status to %s."
-               (process-name proc) event)
+               (process-name proc)
+              (if (string-match "\\(.+\\)\n?\\'" event)
+                  (match-string 1 event)
+                event))
     (when (buffer-live-p (process-get proc 'buffer))
       (with-current-buffer (process-get proc 'buffer)
         (setq doc-view-current-converter-processes
@@ -715,8 +725,18 @@ Those files are saved in the directory given by the function
   ;; resets during the redisplay).
   (setq doc-view-pending-cache-flush t)
   (let ((png-file (expand-file-name "page-%d.png"
+                                    (doc-view-current-cache-dir)))
+       (res-file (expand-file-name "resolution.el"
                                     (doc-view-current-cache-dir))))
     (make-directory (doc-view-current-cache-dir) t)
+    ;; Save the used resolution so that it can be restored when
+    ;; reading the cached files.
+    (let ((res doc-view-resolution))
+      (with-temp-buffer
+       (princ res (current-buffer))
+        ;; Don't use write-file, so as to avoid prompts for `require-newline',
+        ;; or for pre-existing buffers with the same name, ...
+       (write-region nil nil res-file nil 'silently)))
     (case doc-view-doc-type
       (dvi
        ;; DVI files have to be converted to PDF before Ghostscript can process
@@ -1039,6 +1059,16 @@ If BACKWARD is non-nil, jump to the previous match."
        (if (doc-view-already-converted-p)
            (progn
              (message "DocView: using cached files!")
+             ;; Load the saved resolution
+             (let ((res-file (expand-file-name "resolution.el"
+                                               (doc-view-current-cache-dir)))
+                   (res doc-view-resolution))
+               (with-temp-buffer
+                 (when (file-exists-p res-file)
+                   (insert-file-contents res-file)
+                   (setq res (read (current-buffer)))))
+               (when (numberp res)
+                 (set (make-local-variable 'doc-view-resolution) res)))
              (doc-view-display (current-buffer) 'force))
          (doc-view-convert-current-doc))
        (message
@@ -1048,15 +1078,14 @@ If BACKWARD is non-nil, jump to the previous match."
                  "editing or viewing the document."))))
     (message
      "%s"
-     (substitute-command-keys
-      (concat "No PNG support available or some conversion utility for "
-             (file-name-extension doc-view-buffer-file-name)" files is missing.  "
-             "Type \\[doc-view-toggle-display] to switch to "
-             (if (eq doc-view-doc-type 'ps)
-                 "ps-mode"
-               "fundamental-mode")
-             ", \\[doc-view-open-text] to show the doc as text in a separate buffer "
-             " or \\[doc-view-kill-proc-and-buffer] to kill this buffer.")))))
+     (concat "No PNG support is available, or some conversion utility for "
+            (file-name-extension doc-view-buffer-file-name)
+            " files is missing."))
+    (if (and (executable-find doc-view-pdftotext-program)
+            (y-or-n-p
+             "Unable to render file.  View extracted text instead? "))
+       (doc-view-open-text)
+      (doc-view-toggle-display))))
 
 (defvar bookmark-make-record-function)
 
@@ -1091,20 +1120,20 @@ toggle between displaying the document or editing it as text.
 \\{doc-view-mode-map}"
   (interactive)
 
-  (if (or (not (file-exists-p buffer-file-name))
-         (= (point-min) (point-max)))
-      ;; The doc is empty or doesn't exist at all, so fallback to an
-      ;; editing mode.
-      (if (string-match "[eE]?[pP][sS]" (file-name-extension buffer-file-name))
-         (ps-mode)
-       (fundamental-mode)) ;;Should we activate d-v-minor-mode here?
+  (if (= (point-min) (point-max))
+      ;; The doc is empty or doesn't exist at all, so fallback to
+      ;; another mode.  We used to also check file-exists-p, but this
+      ;; returns nil for tar members.
+      (let ((auto-mode-alist (remq (rassq 'doc-view-mode auto-mode-alist)
+                                  auto-mode-alist)))
+       (normal-mode))
 
     (let* ((prev-major-mode (if (eq major-mode 'doc-view-mode)
                                doc-view-previous-major-mode
                              major-mode)))
       (kill-all-local-variables)
       (set (make-local-variable 'doc-view-previous-major-mode) prev-major-mode))
-    
+
     ;; Figure out the document type.
     (let ((name-types
           (when buffer-file-name
@@ -1128,7 +1157,7 @@ toggle between displaying the document or editing it as text.
                             name-types content-types))
                    name-types content-types
                    (error "Cannot determine the document type")))))
-    
+
     (doc-view-make-safe-dir doc-view-cache-directory)
     ;; Handle compressed files, remote files, files inside archives
     (set (make-local-variable 'doc-view-buffer-file-name)
@@ -1150,7 +1179,7 @@ toggle between displaying the document or editing it as text.
          (t buffer-file-name)))
     (when (not (string= doc-view-buffer-file-name buffer-file-name))
       (write-region nil nil doc-view-buffer-file-name))
-    
+
     (add-hook 'change-major-mode-hook
              (lambda ()
                (doc-view-kill-proc)
@@ -1158,14 +1187,14 @@ toggle between displaying the document or editing it as text.
              nil t)
     (add-hook 'clone-indirect-buffer-hook 'doc-view-clone-buffer-hook nil t)
     (add-hook 'kill-buffer-hook 'doc-view-kill-proc nil t)
-    
+
     (remove-overlays (point-min) (point-max) 'doc-view t) ;Just in case.
     ;; Keep track of display info ([vh]scroll, page number, overlay,
     ;; ...)  for each window in which this document is shown.
     (add-hook 'image-mode-new-window-functions
              'doc-view-new-window-function nil t)
     (image-mode-setup-winprops)
-    
+
     (set (make-local-variable 'mode-line-position)
         '(" P" (:eval (number-to-string (doc-view-current-page)))
           "/" (:eval (number-to-string (length doc-view-current-files)))))