From: Stefan Monnier Date: Fri, 5 Feb 2010 01:53:40 +0000 (-0500) Subject: Fix up various corner case problems. X-Git-Tag: emacs-pretest-23.1.93~109 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=bdd428996e3c2cc58ffcde8b0cb2215e2e2b247c;p=emacs.git Fix up various corner case problems. * doc-view.el (doc-view-last-page-number): New function. (doc-view-mode, doc-view-last-page, doc-view-goto-page): Use it. (doc-view-goto-page): Avoid inf-loops when the conversion fails. (doc-view-kill-proc): Avoid inf-loop in freak cases. (doc-view-reconvert-doc): Use the new recursive delete-directory. (doc-view-convert-current-doc): Don't create the resolution.el file here any more. (doc-view-pdf/ps->png): Do it here instead. (doc-view-already-converted-p): Check that resolution.el is present. (doc-view-pdf->png): Don't rely on doc-view-pdf/ps->png for the few windows that are not yet showing images. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0e831a4be72..0d1538c0136 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,18 @@ +2010-02-05 Stefan Monnier + + Fix up various corner case problems. + * doc-view.el (doc-view-last-page-number): New function. + (doc-view-mode, doc-view-last-page, doc-view-goto-page): Use it. + (doc-view-goto-page): Avoid inf-loops when the conversion fails. + (doc-view-kill-proc): Avoid inf-loop in freak cases. + (doc-view-reconvert-doc): Use the new recursive delete-directory. + (doc-view-convert-current-doc): Don't create the resolution.el file + here any more. + (doc-view-pdf/ps->png): Do it here instead. + (doc-view-already-converted-p): Check that resolution.el is present. + (doc-view-pdf->png): Don't rely on doc-view-pdf/ps->png for the few + windows that are not yet showing images. + 2010-02-04 Alan Mackenzie Change strategy for marking < and > as template delimiters: mark diff --git a/lisp/doc-view.el b/lisp/doc-view.el index d8a2e909732..5b84fc3e0d1 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -383,10 +383,13 @@ Can be `dvi', `pdf', or `ps'.") (defmacro doc-view-current-image () `(image-mode-window-get 'image)) (defmacro doc-view-current-slice () `(image-mode-window-get 'slice)) +(defun doc-view-last-page-number () + (length doc-view-current-files)) + (defun doc-view-goto-page (page) "View the page given by PAGE." (interactive "nPage: ") - (let ((len (length doc-view-current-files)) + (let ((len (doc-view-last-page-number)) (hscroll (window-hscroll))) (if (< page 1) (setq page 1) @@ -426,12 +429,15 @@ Can be `dvi', `pdf', or `ps'.") ;; The PNG file hasn't been generated yet. (doc-view-pdf->png-1 doc-view-buffer-file-name file page (lexical-let ((page page) - (win (selected-window))) + (win (selected-window)) + (file file)) (lambda () (and (eq (current-buffer) (window-buffer win)) ;; If we changed page in the mean ;; time, don't mess things up. (eq (doc-view-current-page win) page) + ;; Make sure we don't infloop. + (file-readable-p file) (with-selected-window win (doc-view-goto-page page)))))))) (overlay-put (doc-view-current-overlay) @@ -455,7 +461,7 @@ Can be `dvi', `pdf', or `ps'.") (defun doc-view-last-page () "View the last page." (interactive) - (doc-view-goto-page (length doc-view-current-files))) + (doc-view-goto-page (doc-view-last-page-number))) (defun doc-view-scroll-up-or-next-page (&optional arg) "Scroll page up ARG lines if possible, else goto next page. @@ -528,7 +534,7 @@ at the top edge of the page moves to the previous page." (defun doc-view-kill-proc () "Kill the current converter process(es)." (interactive) - (while doc-view-current-converter-processes + (while (consp doc-view-current-converter-processes) (ignore-errors ;; Maybe it's dead already? (kill-process (pop doc-view-current-converter-processes)))) (when doc-view-current-timer @@ -638,7 +644,7 @@ Should be invoked when the cached images aren't up-to-date." (doc-view-kill-proc) ;; Clear the old cached files (when (file-exists-p (doc-view-current-cache-dir)) - (dired-delete-file (doc-view-current-cache-dir) 'always)) + (delete-directory (doc-view-current-cache-dir) 'recursive)) (doc-view-initiate-display)) (defun doc-view-sentinel (proc event) @@ -694,11 +700,18 @@ Should be invoked when the cached images aren't up-to-date." (list (format "-r%d" (round doc-view-resolution)) (concat "-sOutputFile=" png) pdf-ps)) - (lambda () - (when doc-view-current-timer - (cancel-timer doc-view-current-timer) - (setq doc-view-current-timer nil)) - (doc-view-display (current-buffer) 'force))) + (lexical-let ((resolution doc-view-resolution)) + (lambda () + ;; Only create the resolution file when it's all done, so it also + ;; serves as a witness that the conversion is complete. + (write-region (prin1-to-string resolution) nil + (expand-file-name "resolution.el" + (doc-view-current-cache-dir)) + nil 'silently) + (when doc-view-current-timer + (cancel-timer doc-view-current-timer) + (setq doc-view-current-timer nil)) + (doc-view-display (current-buffer) 'force)))) ;; Update the displayed pages as soon as they're done generating. (when doc-view-conversion-refresh-interval (setq doc-view-current-timer @@ -740,6 +753,13 @@ Start by converting PAGES, and then the rest." (doc-view-pdf->png pdf png rest) ;; Yippie, the important pages are done, update the display. (clear-image-cache) + ;; For the windows that have a message (like "Welcome to + ;; DocView") display property, clearing the image cache is + ;; not sufficient. + (dolist (win (get-buffer-window-list (current-buffer) nil 'visible)) + (with-selected-window win + (when (stringp (get-char-property (point-min) 'display)) + (doc-view-goto-page (doc-view-current-page))))) ;; Convert the rest of the pages. (doc-view-pdf/ps->png pdf png))))))) @@ -806,18 +826,8 @@ 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 @@ -827,10 +837,10 @@ Those files are saved in the directory given by the function (png-file png-file)) (doc-view-dvi->pdf doc-view-buffer-file-name pdf (lambda () (doc-view-pdf/ps->png pdf png-file))))) - (pdf - (let ((pages (doc-view-active-pages))) - ;; Convert PDF to PNG images starting with the active pages. - (doc-view-pdf->png doc-view-buffer-file-name png-file pages))) + (pdf + (let ((pages (doc-view-active-pages))) + ;; Convert PDF to PNG images starting with the active pages. + (doc-view-pdf->png doc-view-buffer-file-name png-file pages))) (t ;; Convert to PNG images. (doc-view-pdf/ps->png doc-view-buffer-file-name png-file))))) @@ -1129,7 +1139,13 @@ If BACKWARD is non-nil, jump to the previous match." (defun doc-view-already-converted-p () "Return non-nil if the current doc was already converted." (and (file-exists-p (doc-view-current-cache-dir)) - (> (length (directory-files (doc-view-current-cache-dir) nil "\\.png$")) 0))) + ;; Check that the resolution info is there, otherwise it means + ;; the conversion is incomplete. + (file-readable-p (expand-file-name "resolution.el" + (doc-view-current-cache-dir))) + (> (length (directory-files (doc-view-current-cache-dir) + nil "\\.png\\'")) + 0))) (defun doc-view-initiate-display () ;; Switch to image display if possible @@ -1141,14 +1157,14 @@ If BACKWARD is non-nil, jump to the previous match." (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) + (let* ((res-file (expand-file-name "resolution.el" + (doc-view-current-cache-dir))) + (res + (with-temp-buffer + (when (file-readable-p res-file) + (insert-file-contents res-file) + (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)) @@ -1282,7 +1298,7 @@ toggle between displaying the document or editing it as text. (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))))) + "/" (:eval (number-to-string (doc-view-last-page-number))))) ;; Don't scroll unless the user specifically asked for it. (set (make-local-variable 'auto-hscroll-mode) nil) (set (make-local-variable 'mwheel-scroll-up-function)