summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorAndreas Politz <politza@hochschule-trier.de>2014-11-14 10:06:26 +0100
committerAndreas Politz <politza@hochschule-trier.de>2014-11-14 10:06:26 +0100
commitcf7553e95d4eb7a04b1b418e4dc06c7654eb786b (patch)
tree5360c3b73a7eda32a1226d68b3bfd2425f39c60c /lisp
parent80ee4236f1d06a9b96a3ce7594f37e10c5227275 (diff)
*** empty log message ***
Diffstat (limited to 'lisp')
-rw-r--r--lisp/pdf-annot.el2
-rw-r--r--lisp/pdf-info.el5
-rw-r--r--lisp/pdf-isearch.el468
-rw-r--r--lisp/pdf-util.el1187
-rw-r--r--lisp/pdf-view.el75
5 files changed, 720 insertions, 1017 deletions
diff --git a/lisp/pdf-annot.el b/lisp/pdf-annot.el
index 80f5f70..262f90d 100644
--- a/lisp/pdf-annot.el
+++ b/lisp/pdf-annot.el
@@ -1318,7 +1318,7 @@ i.e. a non mouse-movement event is read."
buffer
'(nil (inhibit-same-window . t))))
(when (pdf-util-page-displayed-p)
- (pdf-util-scroll-to-edges
+ (pdf-util-display-edges
(pdf-util-scale-edges
(pdf-annot-get a 'edges)
(pdf-util-image-size t)))
diff --git a/lisp/pdf-info.el b/lisp/pdf-info.el
index 99a175c..c9d247d 100644
--- a/lisp/pdf-info.el
+++ b/lisp/pdf-info.el
@@ -1052,7 +1052,10 @@ the caller."
(cons
(pdf-util-hexcolor fg)
(cons (pdf-util-hexcolor bg)
- (apply 'append edges)))))
+ (mapcar
+ (lambda (e)
+ (mapconcat 'number-to-string e " "))
+ edges)))))
selections))))
diff --git a/lisp/pdf-isearch.el b/lisp/pdf-isearch.el
index 03ab154..57f4b30 100644
--- a/lisp/pdf-isearch.el
+++ b/lisp/pdf-isearch.el
@@ -32,91 +32,68 @@
;;; Code:
-;;
-;; *Customizable variables
-;;
+
+
+;; * ================================================================== *
+;; * Customizations
+;; * ================================================================== *
(defgroup pdf-isearch nil
"Isearch in pdf buffers."
:group 'pdf-tools)
-(defcustom pdf-isearch-convert-commands
- '("-fuzz" "30%%" "-region" "%g"
- "-fill" "%b" "-draw" "color 0,-1 replace")
- "The commands for the external convert program.
-
-This should be a list of strings, possibly containing special
-escape characters. Every found match produces one such command
-in the pipeline of the program. The format is used with the
-function `format-spec' and the following specs are available:
-
-%g -- Expands to the geometry of the match, i.e. WxH+X+Y.
-%f -- Expands to the foreground color.
-%b -- Expands to the background color.
-%x -- Expands to the left edge of the match.
-%X -- Expands to the right edge of the match.
-%y -- Expands to the top edge of the match.
-%Y -- Expands to the bottom edge of the match.
-%w -- Expands to the width of the match.
-%h -- Expands to the height of the match
-%W -- Expands to the width of the file image.
-%H -- Expands to the height of the file image.
-%s -- Expands to the matched text (FIXME: Not implemented).
-
-Keep in mind, that every element of this list is treated as one
-argument for the convert program. Also note, that the notion of
-image-size may be different between Emacs and the image on disk.
-All format spec coordinates are with respect to the actual
-image (the one convert operates on).
-
-See url `http://www.imagemagick.org/script/convert.php'."
- :group 'pdf-isearch
- :type '(repeat string)
- :link '(url-link "http://www.imagemagick.org/script/convert.php"))
-
(defface pdf-isearch-match
'((((background dark)) (:inherit isearch))
(((background light)) (:inherit isearch)))
"Face used to determine the colors of the current match."
- ;; :group 'pdf-isearch
+ :group 'pdf-isearch
:group 'pdf-tools-faces)
(defface pdf-isearch-lazy
'((((background dark)) (:inherit lazy-highlight))
(((background light)) (:inherit lazy-highlight)))
"Face used to determine the colors of non-current matches."
- ;; :group 'pdf-isearch
+ :group 'pdf-isearch
:group 'pdf-tools-faces)
(defface pdf-isearch-batch
'((((background dark)) (:inherit match))
(((background light)) (:inherit match)))
"Face used to determine the colors in `pdf-isearch-batch-mode'."
- ;; :group 'pdf-isearch
+ :group 'pdf-isearch
:group 'pdf-tools-faces)
-;;
+(defcustom pdf-isearch-cache-images nil
+ "Whether already displayed images should be cached.
+
+FIXME: Explain."
+ :group 'pdf-isearch
+ :type 'boolean)
+
+
+
+
+;; * ================================================================== *
;; * Internal Variables
-;;
+;; * ================================================================== *
-(defvar-local pdf-isearch-page nil
+(defvar-local pdf-isearch-current-page nil
"The page that is currently searched.")
(defvar-local pdf-isearch-current-match nil
"A list (LEFT TOP RIGHT BOT) of the current match or nil.")
-(defvar-local pdf-isearch-matches nil
+(defvar-local pdf-isearch-current-matches nil
"A list of matches of the last search.")
-(defvar-local pdf-isearch-search-parameter nil
- "A list of search parameter (search-string, regex-p and case-fold).")
+(defvar-local pdf-isearch-current-parameter nil
+ "A list of search parameter \(search-string regex-p case-fold\).")
-(defvar-local pdf-isearch-convert-process nil
- "Process used to convert images.")
-;;
+
+;; * ================================================================== *
;; * Modes
-;;
+;; * ================================================================== *
(defvar pdf-isearch-minor-mode-map
(let ((kmap (make-sparse-keymap)))
@@ -161,19 +138,15 @@ from stopping at and highlighting every single match, but rather
display them batch-wise. Here a batch means a number of matches
currently visible in the selected window.
-Performance is also greatly influenced by the kind of image the
-convert program produces. This may be determined by the variable
-`pdf-util-fast-image-format'.
-
-The kind of highlighting is determined by the variable
-`pdf-isearch-convert-commands' and the three faces pdf-isearch-match
-\(for the current match\), pdf-isearch-lazy \(for all other matches\)
-and pdf-isearch-batch \(when in batch mode\), which see.
+The kind of highlighting is determined by three faces
+`pdf-isearch-match' \(for the current match\), `pdf-isearch-lazy'
+\(for all other matches\) and `pdf-isearch-batch' \(when in batch
+mode\), which see.
Colors may also be influenced by the minor-mode
-`pdf-misc-dark-mode'. If this is enabled, each face's dark
-colors, are used (see variable `frame-background-mode' etc.),
-rather than the light ones.
+`pdf-misc-dark-mode'. If this is minor mode enabled, each face's
+dark colors, are used (see e.g. `frame-background-mode'), instead
+of the light ones.
\\{pdf-isearch-minor-mode-map}
While in `isearch-mode' the following keys are available.
@@ -196,14 +169,16 @@ While in `isearch-mode' the following keys are available.
;; This maybe edit or t, but edit would suppress our cmds
;; in isearch-other-meta-char.
(not (not search-exit-option)))
+ ;; FIXME: Die Variable imagemagick-render-type entweder an anderer
+ ;; Stelle global setzen oder nur irgendwo auf den
+ ;; Performancegewinn hinweisen.
(when (and (boundp 'imagemagick-render-type)
(= 0 imagemagick-render-type))
;; This enormously speeds up rendering.
(setq imagemagick-render-type 1))
(add-hook 'isearch-mode-hook 'pdf-isearch-mode-initialize nil t)
(add-hook 'isearch-mode-end-hook 'pdf-isearch-mode-cleanup nil t)
- (add-hook 'isearch-update-post-hook 'pdf-isearch-update nil t)
- (advice-add 'isearch-done :around 'pdf-isearch-done-advice))
+ (add-hook 'isearch-update-post-hook 'pdf-isearch-update nil t))
(t
(kill-local-variable 'search-exit-option)
(kill-local-variable 'isearch-allow-scroll)
@@ -213,41 +188,18 @@ While in `isearch-mode' the following keys are available.
(kill-local-variable 'isearch-lazy-highlight)
(remove-hook 'isearch-update-post-hook 'pdf-isearch-update t)
(remove-hook 'isearch-mode-hook 'pdf-isearch-mode-initialize t)
- (remove-hook 'isearch-mode-end-hook 'pdf-isearch-mode-cleanup t)
- (advice-remove 'isearch-done 'pdf-isearch-done-advice))))
-
-(defvar pdf-isearch-suspended-p nil
- "Non-nil in `isearch-mode-end-hook', if isearch is suspended.")
+ (remove-hook 'isearch-mode-end-hook 'pdf-isearch-mode-cleanup t))))
-(defun pdf-isearch-done-advice (fn &optional nopush edit)
- "Make a supsended isearch distinguishable from a quit.
-Binds `pdf-isearch-suspended-p' to the EDIT argument around
-`isearch-done'."
- (let ((pdf-isearch-suspended-p edit))
- (funcall fn nopush edit)))
-
-(define-minor-mode pdf-isearch-active-mode
- "" nil nil nil
- (cond
- (pdf-isearch-active-mode
- ;; The PDF buffer is usually in binary mode, but we probably want
- ;; to search for multibyte characters.
- ;; (unless enable-multibyte-characters
- ;; (set-buffer-multibyte t))
- )
- (t
- ;; (unless pdf-isearch-suspended-p
- ;; (set-buffer-multibyte nil))
- )))
+(define-minor-mode pdf-isearch-active-mode "" nil nil nil)
(define-minor-mode pdf-isearch-batch-mode
- "Incrementally search PDF documents in batches.
+ "Isearch PDF documents batch-wise.
If this mode is enabled, isearching does not stop at every match,
-but rather moves to next one not currently visible. This
+but rather moves to the next one not currently visible. This
behaviour is much faster than ordinary isearch, since far less
-images have to be created."
+different images have to be displayed."
nil nil nil
:group 'pdf-isearch
(when isearch-mode
@@ -255,11 +207,17 @@ images have to be created."
(pdf-isearch-message
(if pdf-isearch-batch-mode "batch mode" "isearch mode"))))
-;;
-;; * Isearch Interface
-;;
-(defvar pdf-isearch-filter-matches-function nil)
+
+;; * ================================================================== *
+;; * Isearch interface
+;; * ================================================================== *
+
+(defvar pdf-isearch-filter-matches-function nil
+ "A function for filtering isearch matches.
+
+The function receives one argument: a list of edges. It should
+return a subset of this list. The edges are in PDF points.")
(defun pdf-isearch-search-function (string &rest _)
"Search for STRING in the current PDF buffer.
@@ -267,32 +225,32 @@ images have to be created."
This is a Isearch interface function."
(when (> (length string) 0)
(let ((same-search-p (pdf-isearch-same-search-p))
- (oldpage pdf-isearch-page)
+ (oldpage pdf-isearch-current-page)
(matches (pdf-isearch-search-page string))
next-match)
;; matches is a list of edges ((x0 y1 x1 y2) ...), sorted top to
- ;; bottom ,left to right,
+ ;; bottom ,left to right, in points
(unless isearch-forward
(setq matches (reverse matches)))
(when pdf-isearch-filter-matches-function
(setq matches (funcall pdf-isearch-filter-matches-function matches)))
;; Where to go next ?
- (setq pdf-isearch-page (pdf-view-current-page)
- pdf-isearch-matches matches
+ (setq pdf-isearch-current-page (pdf-view-current-page)
+ pdf-isearch-current-matches matches
next-match
(pdf-isearch-next-match
- oldpage pdf-isearch-page
+ oldpage pdf-isearch-current-page
pdf-isearch-current-match matches
same-search-p
isearch-forward)
- pdf-isearch-search-parameter
+ pdf-isearch-current-parameter
(list string nil isearch-case-fold-search))
(cond
(next-match
(setq pdf-isearch-current-match next-match)
(pdf-isearch-hl-matches next-match matches)
(pdf-isearch-focus-match next-match)
- ;; Is this necessary ? Does this mess up isearch ?
+ ;; Don't get off track.
(when (or (and (bobp) (not isearch-forward))
(and (eobp) isearch-forward))
(goto-char (1+ (/ (buffer-size) 2))))
@@ -302,36 +260,34 @@ This is a Isearch interface function."
(re-search-backward ".")))
(t
(let ((next-page (pdf-isearch-find-next-matching-page
- string pdf-isearch-page isearch-forward t)))
- (when nil ;; next-page
- (let ((pdf-render-inhibit-display t))
- (pdf-view-goto-page next-page))
+ string pdf-isearch-current-page isearch-forward t)))
+ (when next-page
+ (pdf-view-goto-page next-page)
(pdf-isearch-search-function string))))))))
(defun pdf-isearch-push-state-function ()
"Push the current search state.
This is a Isearch interface function."
- (let ((hscroll (* (window-hscroll) (frame-char-width)))
+ (let ((hscroll (window-hscroll))
(vscroll (window-vscroll nil t))
- (parms pdf-isearch-search-parameter)
- (matches pdf-isearch-matches)
+ (parms pdf-isearch-current-parameter)
+ (matches pdf-isearch-current-matches)
(match pdf-isearch-current-match)
- (page pdf-isearch-page))
+ (page pdf-isearch-current-page))
(lambda (_state)
- (setq pdf-isearch-search-parameter parms
- pdf-isearch-matches matches
+ (setq pdf-isearch-current-parameter parms
+ pdf-isearch-current-matches matches
pdf-isearch-current-match match
- pdf-isearch-page page)
+ pdf-isearch-current-page page)
- (let ((pdf-render-inhibit-display t))
- (pdf-view-goto-page pdf-isearch-page))
+ (pdf-view-goto-page pdf-isearch-current-page)
(when pdf-isearch-current-match
(pdf-isearch-hl-matches
pdf-isearch-current-match
- pdf-isearch-matches))
- (pdf-util-set-window-pixel-hscroll hscroll)
- (pdf-util-set-window-pixel-vscroll vscroll))))
+ pdf-isearch-current-matches))
+ (set-window-hscroll nil hscroll)
+ (set-window-vscroll nil vscroll t))))
(defun pdf-isearch-wrap-function ()
"Go to first or last page.
@@ -339,10 +295,9 @@ This is a Isearch interface function."
This is a Isearch interface function."
(let ((page (if isearch-forward
1
- (pdf-info-number-of-pages))))
+ (pdf-cache-number-of-pages))))
(unless (= page (pdf-view-current-page))
- (let ((pdf-render-inhibit-display t))
- (pdf-view-goto-page page))
+ (pdf-view-goto-page page)
(let ((next-screen-context-lines 0))
(if (= page 1)
(image-scroll-down)
@@ -354,18 +309,17 @@ This is a Isearch interface function."
This is a Isearch interface function."
(pdf-isearch-active-mode -1)
- (pdf-view-redisplay)
- (pdf-util-cache-clear "pdf-isearch"))
+ (pdf-view-redisplay))
(defun pdf-isearch-mode-initialize ()
"Initialize isearching.
This is a Isearch interface function."
(pdf-isearch-active-mode 1)
- (setq pdf-isearch-page (pdf-view-current-page)
+ (setq pdf-isearch-current-page (pdf-view-current-page)
pdf-isearch-current-match nil
- pdf-isearch-matches nil
- pdf-isearch-search-parameter nil)
+ pdf-isearch-current-matches nil
+ pdf-isearch-current-parameter nil)
(goto-char (1+ (/ (buffer-size) 2))))
(defun pdf-isearch-same-search-p (&optional ignore-search-string-p)
@@ -374,11 +328,11 @@ This is a Isearch interface function."
Parameter inspected are `isearch-string' (unless
IGNORE-SEARCH-STRING-P is t) and `isearch-case-fold-search'. If
there was no previous search, this function returns t."
- (or (null pdf-isearch-search-parameter)
+ (or (null pdf-isearch-current-parameter)
(if ignore-search-string-p
- (equal (cdr pdf-isearch-search-parameter)
+ (equal (cdr pdf-isearch-current-parameter)
(list isearch-regexp isearch-case-fold-search))
- (equal pdf-isearch-search-parameter
+ (equal pdf-isearch-current-parameter
(list isearch-string isearch-regexp
isearch-case-fold-search)))))
@@ -402,14 +356,14 @@ there was no previous search, this function returns t."
(defun pdf-isearch-redisplay ()
"Redisplay the current highlighting."
(pdf-isearch-hl-matches pdf-isearch-current-match
- pdf-isearch-matches))
+ pdf-isearch-current-matches))
(defun pdf-isearch-update ()
"Update search and redisplay, if necessary."
(unless (pdf-isearch-same-search-p t)
- (setq pdf-isearch-search-parameter
+ (setq pdf-isearch-current-parameter
(list isearch-string nil isearch-case-fold-search)
- pdf-isearch-matches
+ pdf-isearch-current-matches
(pdf-isearch-search-page isearch-string))
(pdf-isearch-redisplay)))
@@ -424,20 +378,23 @@ there was no previous search, this function returns t."
(sit-for 1))
(message "%s" fmt))))
-;;
+
+
+;; * ================================================================== *
;; * Interface to epdfinfo
-;;
+;; * ================================================================== *
(defun pdf-isearch-search-page (string &optional page)
"Search STRING on PAGE in the current window.
-Returns a list of edges (LEFT TOP RIGHT BOTTOM) in image
+Returns a list of edges (LEFT TOP RIGHT BOTTOM) in PDF
coordinates, sorted top to bottom, then left to right."
(unless page (setq page (pdf-view-current-page)))
(let ((case-fold-search isearch-case-fold-search))
- (mapcar 'car (cdar (pdf-info-search
- string nil page)))))
+ (pdf-util-scale-relative-to-pixel
+ (mapcar 'car (cdar (pdf-info-search
+ string nil page))))))
(defun pdf-isearch-find-next-matching-page (string page &optional
forward-p interactive-p)
@@ -454,7 +411,7 @@ is no such page."
(1+ page))
(cons (1- page)
(1- page))))
- (final-page (and forward-p (pdf-info-number-of-pages)))
+ (final-page (and forward-p (pdf-cache-number-of-pages)))
matched-page
reporter)
@@ -467,7 +424,6 @@ is no such page."
(setq matched-page (if forward-p
(caar matches)
(caar (last matches)))))
- ;; (logger "%s %s %s" pages matched-page pdf-isearch-search-parameter)
(setq incr (* incr 2))
(cond (forward-p
(setcar pages (1+ (cdr pages)))
@@ -493,9 +449,11 @@ is no such page."
(- page (car pages)))))))
matched-page))
-;;
+
+
+;; * ================================================================== *
;; * Isearch Behavior
-;;
+;; * ================================================================== *
(defun pdf-isearch-next-match-isearch (last-page this-page last-match
matches same-search-p
@@ -512,7 +470,7 @@ match."
(if forward
(cons iedges-left iedges-top)
(cons iedges-right iedges-bot)))))
- (pdf-isearch-nearest-match pos matches forward)))
+ (pdf-isearch-closest-match pos matches forward)))
((not (eq last-page this-page))
;; First match from top-left or bottom-right of the new
;; page.
@@ -523,21 +481,13 @@ match."
(cadr (member last-match matches))))
(matches
;; Next match of new search closest to the last one.
- (pdf-isearch-nearest-match
+ (pdf-isearch-closest-match
last-match matches forward))))
-(defun pdf-isearch-focus-match-isearch (match &optional eager-p)
+(defun pdf-isearch-focus-match-isearch (match)
"Make the image area in MATCH visible in the selected window."
- (unless (image-get-display-property)
- (error "No image found in buffer"))
- (let ((hscroll (pdf-util-required-hscroll match eager-p))
- (vscroll (pdf-util-required-vscroll match eager-p)))
- (when hscroll
- (pdf-util-set-window-pixel-hscroll hscroll))
- (when vscroll
- (pdf-util-set-window-pixel-vscroll vscroll)))
- nil)
+ (pdf-util-display-edges match))
(defun pdf-isearch-next-match-batch (last-page this-page last-match
matches same-search-p
@@ -562,11 +512,46 @@ match."
(defun pdf-isearch-focus-match-batch (match)
"Make the image area in MATCH eagerly visible in the selected window."
- (pdf-isearch-focus-match-isearch match t))
+ (pdf-util-display-edges match t))
+
+(defun pdf-isearch-closest-match (match-or-pos list-of-matches
+ &optional forward-p)
+ "Find the nearest element to MATCH-OR-POS in LIST-OF-MATCHES.
+
+The direction in which to look is determined by FORWARD-P.
+
+MATCH-OR-POS is either a list of edges or a cons (X . Y).
+LIST-OF-MATCHES is assumed to be ordered with respect to
+FORWARD-P."
+
+ (let ((match (if (not (consp (cdr match-or-pos)))
+ (list (car match-or-pos) (cdr match-or-pos)
+ (car match-or-pos) (cdr match-or-pos))
+ match-or-pos))
+ found edges)
+ (pdf-util-with-edges (match)
+ (while (and (not found)
+ list-of-matches)
+ (setq edges (car list-of-matches)
+ list-of-matches (cdr list-of-matches))
+ (pdf-util-with-edges (edges)
+ (when (or (and forward-p
+ (or (>= edges-top match-bot)
+ (and (>= edges-top match-top)
+ (>= edges-right match-right))))
+ (and (null forward-p)
+ (or (<= edges-bot match-top)
+ (and (<= edges-top match-top)
+ (<= edges-left match-left)))))
+ (setq found edges)))))
+ found))
+
+
+
+;; * ================================================================== *
+;; * Display
+;; * ================================================================== *
-;;
-;; * Highlighting matches
-;;
(defun pdf-isearch-current-colors ()
"Return the current color set.
@@ -591,9 +576,9 @@ MATCH-BG LAZY-FG LAZY-BG\)."
(cdr lazy)))))))
(defun pdf-isearch-hl-matches (current matches)
- "Highlighting edges CURRENT and MATCHES using the convert program."
+ "Highlighting edges CURRENT and MATCHES."
(let* ((hash (sxhash (cons current matches)))
- (width (car (image-size (pdf-view-current-image) t)))
+ (width (car (pdf-view-image-size)))
(page (pdf-view-current-page))
(data ;; (pdf-cache-lookup-image page width nil hash)
))
@@ -602,7 +587,6 @@ MATCH-BG LAZY-FG LAZY-BG\)."
data (pdf-view-image-type) t))
(let* ((window (selected-window))
(buffer (current-buffer))
- (pdf-info-cancelable nil)
(pdf-info-asynchronous
(lambda (status file)
(when (and (null status)
@@ -616,7 +600,6 @@ MATCH-BG LAZY-FG LAZY-BG\)."
(eq page (pdf-view-current-page))
(file-readable-p file))
(let ((data (pdf-util-munch-file file)))
- (setq pdf-isearch-query-cookie nil)
(pdf-cache-put-image page width data hash)
(pdf-view-display-image
(create-image data (pdf-view-image-type) t)))))))))
@@ -624,107 +607,74 @@ MATCH-BG LAZY-FG LAZY-BG\)."
(pdf-isearch-current-colors)
(pdf-info-renderpage-selection
page width nil
- `(,fg1 ,bg1 ,current)
- `(,fg2 ,bg2 ,@(remq current matches))))))))
+ `(,fg1 ,bg1 ,(pdf-util-scale-pixel-to-relative current))
+ `(,fg2 ,bg2 ,@(pdf-util-scale-pixel-to-relative
+ (remq current matches)))))))))
-;;
-;; * Utility functions and macros
-;;
-(defun pdf-isearch-nearest-match (match-or-pos list-of-matches
- &optional forward-p)
- "Find the nearest element to MATCH-OR-POS in LIST-OF-MATCHES.
-
-The direction in which to look is determined by FORWARD-P.
-
-MATCH-OR-POS is either a list of edges or a cons (X . Y).
-LIST-OF-MATCHES is assumed to be ordered with respect to
-FORWARD-P."
-
- (let ((match (if (not (consp (cdr match-or-pos)))
- (list (car match-or-pos) (cdr match-or-pos)
- (car match-or-pos) (cdr match-or-pos))
- match-or-pos))
- found edges)
- (pdf-util-with-edges (match)
- (while (and (not found)
- list-of-matches)
- (setq edges (car list-of-matches)
- list-of-matches (cdr list-of-matches))
- (pdf-util-with-edges (edges)
- (when (or (and forward-p
- (or (>= edges-top match-bot)
- (and (>= edges-top match-top)
- (>= edges-right match-right))))
- (and (null forward-p)
- (or (<= edges-bot match-top)
- (and (<= edges-top match-top)
- (<= edges-left match-left)))))
- (setq found edges)))))
- found))
+;; The following isearch-search function is debugable.
+;;
+(defun isearch-search ()
+ ;; Do the search with the current search string.
+ (if isearch-message-function
+ (funcall isearch-message-function nil t)
+ (isearch-message nil t))
+ (if (and (eq isearch-case-fold-search t) search-upper-case)
+ (setq isearch-case-fold-search
+ (isearch-no-upper-case-p isearch-string isearch-regexp)))
+ (condition-case lossage
+ (let ((inhibit-point-motion-hooks
+ ;; FIXME: equality comparisons on functions is asking for trouble.
+ (and (eq isearch-filter-predicate 'isearch-filter-visible)
+ search-invisible))
+ (inhibit-quit nil)
+ (case-fold-search isearch-case-fold-search)
+ (retry t))
+ (setq isearch-error nil)
+ (while retry
+ (setq isearch-success
+ (isearch-search-string isearch-string nil t))
+ ;; Clear RETRY unless the search predicate says
+ ;; to skip this search hit.
+ (if (or (not isearch-success)
+ (bobp) (eobp)
+ (= (match-beginning 0) (match-end 0))
+ (funcall isearch-filter-predicate
+ (match-beginning 0) (match-end 0)))
+ (setq retry nil)))
+ (setq isearch-just-started nil)
+ (if isearch-success
+ (setq isearch-other-end
+ (if isearch-forward (match-beginning 0) (match-end 0)))))
+
+ (quit (isearch-unread ?\C-g)
+ (setq isearch-success nil))
+
+ (invalid-regexp
+ (setq isearch-error (car (cdr lossage)))
+ (if (string-match
+ "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
+ isearch-error)
+ (setq isearch-error "incomplete input")))
+
+ (search-failed
+ (setq isearch-success nil)
+ (setq isearch-error (nth 2 lossage)))
+
+ ;; (error
+ ;; ;; stack overflow in regexp search.
+ ;; (setq isearch-error (format "%s" lossage)))
+ )
-;; Redefinition: This isearch-search function is debugable.
-;; (defun isearch-search ()
-;; ;; Do the search with the current search string.
-;; (if isearch-message-function
-;; (funcall isearch-message-function nil t)
-;; (isearch-message nil t))
-;; (if (and (eq isearch-case-fold-search t) search-upper-case)
-;; (setq isearch-case-fold-search
-;; (isearch-no-upper-case-p isearch-string isearch-regexp)))
-;; (condition-case lossage
-;; (let ((inhibit-point-motion-hooks
-;; ;; FIXME: equality comparisons on functions is asking for trouble.
-;; (and (eq isearch-filter-predicate 'isearch-filter-visible)
-;; search-invisible))
-;; (inhibit-quit nil)
-;; (case-fold-search isearch-case-fold-search)
-;; (retry t))
-;; (setq isearch-error nil)
-;; (while retry
-;; (setq isearch-success
-;; (isearch-search-string isearch-string nil t))
-;; ;; Clear RETRY unless the search predicate says
-;; ;; to skip this search hit.
-;; (if (or (not isearch-success)
-;; (bobp) (eobp)
-;; (= (match-beginning 0) (match-end 0))
-;; (funcall isearch-filter-predicate
-;; (match-beginning 0) (match-end 0)))
-;; (setq retry nil)))
-;; (setq isearch-just-started nil)
-;; (if isearch-success
-;; (setq isearch-other-end
-;; (if isearch-forward (match-beginning 0) (match-end 0)))))
-
-;; (quit (isearch-unread ?\C-g)
-;; (setq isearch-success nil))
-
-;; (invalid-regexp
-;; (setq isearch-error (car (cdr lossage)))
-;; (if (string-match
-;; "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
-;; isearch-error)
-;; (setq isearch-error "incomplete input")))
-
-;; (search-failed
-;; (setq isearch-success nil)
-;; (setq isearch-error (nth 2 lossage)))
-
-;; ;; (error
-;; ;; ;; stack overflow in regexp search.
-;; ;; (setq isearch-error (format "%s" lossage)))
-;; )
-
-;; (if isearch-success
-;; nil
-;; ;; Ding if failed this time after succeeding last time.
-;; (and (isearch--state-success (car isearch-cmds))
-;; (ding))
-;; (if (functionp (isearch--state-pop-fun (car isearch-cmds)))
-;; (funcall (isearch--state-pop-fun (car isearch-cmds))
-;; (car isearch-cmds)))
-;; (goto-char (isearch--state-point (car isearch-cmds)))))
+ (if isearch-success
+ nil
+ ;; Ding if failed this time after succeeding last time.
+ (and (isearch--state-success (car isearch-cmds))
+ (ding))
+ (if (functionp (isearch--state-pop-fun (car isearch-cmds)))
+ (funcall (isearch--state-pop-fun (car isearch-cmds))
+ (car isearch-cmds)))
+ (goto-char (isearch--state-point (car isearch-cmds)))))
(provide 'pdf-isearch)
diff --git a/lisp/pdf-util.el b/lisp/pdf-util.el
index 14f1c87..39d1fdb 100644
--- a/lisp/pdf-util.el
+++ b/lisp/pdf-util.el
@@ -28,233 +28,181 @@
(require 'faces)
-(defun pdf-util-munch-file (filename &optional multibyte-p)
- "Read contents from FILENAME and delete it.
-
-Return the file's content as a unibyte string, unless MULTIBYTE-P
-is non-nil."
- (unwind-protect
- (with-temp-buffer
- (set-buffer-multibyte multibyte-p)
- (insert-file-contents-literally filename)
- (buffer-substring-no-properties
- (point-min)
- (point-max)))
- (when (and filename
- (file-exists-p filename))
- (delete-file filename))))
-
-(defun pdf-util-hexcolor (color)
- "Return COLOR in hex-format
-
-Singal an error, if color is invalid."
- (let ((values (color-values (string-trim color))))
- (unless values
- (signal 'wrong-type-argument (list 'color-defined-p color)))
- (apply 'format "#%02x%02x%02x"
- (mapcar (lambda (c) (lsh c -8))
- values))))
-
+
+;; * ================================================================== *
+;; * Transforming coordinates
+;; * ================================================================== *
-(defun pdf-util-image-size (&optional sliced-p)
- (image-size (pdf-view-current-image) t))
+(defun pdf-util-scale (list-of-edges-or-pos scale &optional rounding-fn)
+ "Scale LIST-OF-EDGES-OR-POS by SCALE.
-(defun pdf-util-scale (list-of-edges scale &optional rounding-fn)
- "Scale LIST-OF-EDGES by SCALE.
+SCALE is a cons (SX . SY), by which edges/positions are scaled.
+If ROUNDING-FN is non-nil, it should be a function of one
+argument, a real value, returning a rounded
+value (e.g. `ceiling').
-SCALE is a cons (SX . SY), by which edges are scaled. If
-ROUNDING-FN is non-nil, it should be a function of one argument,
-a real value, returning a rounded value (e.g. `ceiling').
+The elements in LIST-OF-EDGES-OR-POS should be either a list
+\(LEFT TOP RIGHT BOT\) or a position \(X . Y\).
-LIST-OF-EDGES may also be a single element.
+LIST-OF-EDGES-OR-POS may also be a single such element.
-Return scaled list of edges if LIST-OF-EDGES was indeed a list,
+Return scaled list of edges if LIST-OF-EDGES-OR-POS was indeed a list,
else return the scaled singleton."
- (let ((have-list-p (listp (car list-of-edges))))
+ (let ((have-list-p (listp (car list-of-edges-or-pos))))
(unless have-list-p
- (setq list-of-edges (list list-of-edges)))
+ (setq list-of-edges-or-pos (list list-of-edges-or-pos)))
(let* ((sx (car scale))
(sy (cdr scale))
- (result (mapcar (lambda (edges)
- (let ((e (list (* (nth 0 edges) sx)
- (* (nth 1 edges) sy)
- (* (nth 2 edges) sx)
- (* (nth 3 edges) sy))))
- (if rounding-fn
- (mapcar rounding-fn e)
- e)))
- list-of-edges)))
+ (result
+ (mapcar
+ (lambda (edges)
+ (cond
+ ((consp (cdr edges))
+ (let ((e (list (* (nth 0 edges) sx)
+ (* (nth 1 edges) sy)
+ (* (nth 2 edges) sx)
+ (* (nth 3 edges) sy))))
+ (if rounding-fn
+ (mapcar rounding-fn e)
+ e)))
+ (rounding-fn
+ (cons (funcall rounding-fn (* (car edges) sx))
+ (funcall rounding-fn (* (cdr edges) sy))))
+ (t
+ (cons (* (car edges) sx)
+ (* (cdr edges) sy)))))
+ list-of-edges-or-pos)))
(if have-list-p
result
(car result)))))
-(defun pdf-util-scale-to-pixel (list-of-point-edges
- &optional rounding-fn window)
- "Scale LIST-OF-EDGES to match SIZE.
-
-See also `pdf-util-scale'."
- )
-
-(defun pdf-util-scale-to-points (list-of-pixel-edges
- &optional rounding-fn window)
- "Scale LIST-OF-EDGES to match SIZE.
-
-See also `pdf-util-scale'."
- )
-
-
-;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-;;
-;; O L D C O D E
-;;
-;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-
-
-
+(defun pdf-util-scale-to (list-of-edges from to &optional rounding-fn)
+ "Scale LIST-OF-EDGES in FROM basis to TO.
+FROM and TO should both be a cons \(WIDTH . HEIGTH\). See also
+`pdf-util-scale'."
-(require 'cl-lib)
-(require 'doc-view)
-(require 'format-spec)
-(require 'gnus-range)
-
-;; Compatibility aliases for recent renaming in bzr doc-view.el .
-(when (fboundp 'doc-view--current-cache-dir)
- (defalias 'doc-view-current-cache-dir 'doc-view--current-cache-dir)
- (defvaralias 'doc-view-current-cache-dir 'doc-view--current-cache-dir)
- (defvaralias 'doc-view-current-converter-processes 'doc-view--current-converter-processes)
- (defvaralias 'doc-view-buffer-file-name 'doc-view--buffer-file-name))
-
-(eval-when-compile
- (declare-function doc-view-current-cache-dir "pdf-util.el" nil t)
- (defvar doc-view-buffer-file-name)
- (defvar doc-view-current-converter-processes)
- (defvar doc-view-buffer-file-name))
-
-;;
-;; Variables
-;;
+ (pdf-util-scale list-of-edges
+ (cons (/ (float (car to))
+ (float (car from)))
+ (/ (float (cdr to))
+ (float (cdr from))))
+ rounding-fn))
-(defvar-local pdf-util-png-image-size-alist nil
- "Alist of cached png image sizes.")
+(defun pdf-util-scale-pixel-to-points (list-of-pixel-edges
+ &optional window)
+ "Scale LIST-OF-PIXEL-EDGES to point values.
-(defvar pdf-util-after-change-page-hook nil
- "A hook ran after turning the page.")
-
-(defvar pdf-util-after-reconvert-hook nil
- "A hook ran after the document was reconverted.")
-
-;;
-;; Doc View Buffers
-;;
+The result depends on the currently displayed page in WINDOW.
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-pixel-edges
+ (pdf-view-image-size window)
+ (pdf-cache-pagesize)))
-(defun pdf-util-docview-buffer-p (&optional buffer)
- (and (or (null buffer)
- (buffer-live-p buffer))
- (save-current-buffer
- (and buffer (set-buffer buffer))
- (derived-mode-p 'doc-view-mode))))
+(defun pdf-util-scale-points-to-pixel (list-of-points-edges
+ &optional window)
+ "Scale LIST-OF-POINTS-EDGES to point values.
-(defun pdf-util-assert-docview-buffer ()
- (unless (pdf-util-docview-buffer-p)
- (error "Buffer is not in DocView mode")))
+The result depends on the currently displayed page in WINDOW.
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-points-edges
+ (pdf-cache-pagesize)
+ (pdf-view-image-size window)
+ 'round))
+
+(defun pdf-util-scale-relative-to-points (list-of-relative-edges
+ &optional window)
+ "Scale LIST-OF-RELATIVE-EDGES to point values.
+
+The result depends on the currently displayed page in WINDOW.
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-relative-edges
+ '(1.0 . 1.0)
+ (pdf-cache-pagesize)))
-(defun pdf-util-pdf-buffer-p (&optional buffer)
- (and (or (null buffer)
- (buffer-live-p buffer))
- (save-current-buffer
- (and buffer (set-buffer buffer))
- (derived-mode-p 'pdf-view-mode))))
+(defun pdf-util-scale-points-to-relative (list-of-points-edges
+ &optional window)
+ "Scale LIST-OF-POINTS-EDGES to relative values.
-(defun pdf-util-assert-pdf-buffer (&optional buffer)
- (unless (pdf-util-pdf-buffer-p buffer)
- (error "Buffer is not in DocView PDF mode")))
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-points-edges
+ (pdf-cache-pagesize)
+ '(1.0 . 1.0)))
-(defun pdf-util-docview-window-p (&optional window)
- (save-selected-window
- (and window (select-window window))
- (pdf-util-docview-buffer-p)))
+(defun pdf-util-scale-pixel-to-relative (list-of-pixel-edges
+ &optional window)
+ "Scale LIST-OF-PIXEL-EDGES to relative values.
-(defun pdf-util-assert-docview-window (&optional window)
- (unless (pdf-util-docview-window-p window)
- (error "Window's buffer is not in DocView mode")))
+The result depends on the currently displayed page in WINDOW.
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-pixel-edges
+ (pdf-view-image-size window)
+ '(1.0 . 1.0)))
-(defun pdf-util-pdf-window-p (&optional window)
- (save-selected-window
- (and window (select-window window))
- (pdf-util-pdf-buffer-p)))
-
-(defun pdf-util-assert-pdf-window (&optional window)
- (unless (pdf-util-pdf-window-p window)
- (error "Window's buffer is not in DocView PDF mode")))
-
-(defun pdf-util-doc-view-windows (&optional buffer)
- (unless buffer (setq buffer (current-buffer)))
- (with-current-buffer buffer
- (pdf-util-assert-docview-buffer))
- (let (windows)
- (walk-windows
- (lambda (win)
- (with-selected-window win
- (when (eq (current-buffer) buffer)
- (push win windows))))
- 'no-mini t)
- windows))
-
-(defadvice doc-view-goto-page (around pdf-util activate)
- "Run `pdf-util-after-change-page-hook'."
- (let ((pdf-util-current-page (doc-view-current-page)))
- ad-do-it
- ;; Delete the annoying tooltip ,,Page x of y''.
- (let ((ov (doc-view-current-overlay)))
- (when (and ov (stringp (overlay-get ov 'help-echo)))
- (overlay-put ov 'help-echo nil)))
- (unless (eq pdf-util-current-page
- (doc-view-current-page))
- (run-hooks 'pdf-util-after-change-page-hook))))
-
-(defadvice doc-view-reconvert-doc (after pdf-links activate)
- (run-hooks 'pdf-util-after-reconvert-hook))
-;;
+(defun pdf-util-scale-relative-to-pixel (list-of-relative-edges
+ &optional window)
+ "Scale LIST-OF-EDGES to match SIZE.
-;;
-;;
+The result depends on the currently displayed page in WINDOW.
+See also `pdf-util-scale'."
+ (pdf-util-assert-pdf-window window)
+ (pdf-util-scale-to
+ list-of-relative-edges
+ '(1.0 . 1.0)
+ (pdf-view-image-size window)
+ 'round))
+
+(defun pdf-util-translate-edges (list-of-edges-or-pos
+ offset &optional negative-offset-p)
+ (let ((have-list-p (listp (car list-of-edges-or-pos))))
+ (unless have-list-p
+ (setq list-of-edges-or-pos (list list-of-edges-or-pos)))
+ (let* ((ox (if negative-offset-p
+ (- (car offset))
+ (car offset)))
+ (oy (if negative-offset-p
+ (- (cdr offset))
+ (cdr offset)))
+ (result
+ (mapcar
+ (lambda (edges)
+ (cond
+ ((consp (cdr edges))
+ (list (+ (nth 0 edges) ox)
+ (+ (nth 1 edges) oy)
+ (+ (nth 2 edges) ox)
+ (+ (nth 3 edges) oy)))
+ (t
+ (cons (+ (car edges) ox)
+ (+ (cdr edges) oy)))))
+ list-of-edges-or-pos)))
+ (if have-list-p
+ result
+ (car result)))))
-(defun pdf-util-assert-derived-mode (&rest modes)
- (unless (apply 'derived-mode-p modes)
- (error "Buffer is not derived from %s"
- (concat (mapconcat 'symbol-name (butlast modes) ", ")
- (if (cdr modes) " or ")
- (symbol-name (car (last modes)))))))
-
-(defun pdf-util-page-displayed-p ()
- (consp (ignore-errors
- (doc-view-current-image))))
-
-(defun pdf-util-page-displayable-p (&optional page)
- (unless page (setq page (doc-view-current-page)))
- (file-readable-p
- (expand-file-name
- (format "page-%d.png" page)
- (doc-view-current-cache-dir))))
-
+
+;; * ================================================================== *
+;; * Scrolling
+;; * ================================================================== *
-(defun pdf-util-current-image-file (&optional page)
- (expand-file-name (format "page-%d.png"
- (or page (doc-view-current-page)))
- (doc-view-current-cache-dir)))
-;;
-;; Handling Edges
-;;
(defmacro pdf-util-with-edges (list-of-edges &rest body)
(declare (indent 1) (debug (sexp &rest form)))
(unless (cl-every 'symbolp list-of-edges)
- (signal 'wrong-type-argument (list 'symbolp list-of-edges)))
+ (signal 'wrong-type-argument (list 'list-of-symbols list-of-edges)))
(let ((list-of-syms
(mapcar (lambda (edge)
(cons edge (mapcar
@@ -262,200 +210,31 @@ See also `pdf-util-scale'."
(intern (format "%s-%s" edge kind)))
'(left top right bot width height))))
list-of-edges)))
- (let ((lisp (macroexpand-all
- `(cl-symbol-macrolet
- ,(apply 'nconc
- (mapcar
- (lambda (edge-syms)
- (let ((edge (nth 0 edge-syms))
- (syms (cdr edge-syms)))
- `((,(pop syms) (nth 0 ,edge))
- (,(pop syms) (nth 1 ,edge))
- (,(pop syms) (nth 2 ,edge))
- (,(pop syms) (nth 3 ,edge))
- (,(pop syms) (- (nth 2 ,edge)
- (nth 0 ,edge)))
- (,(pop syms) (- (nth 3 ,edge)
- (nth 1 ,edge))))))
- list-of-syms))
- ,@body))))
- ;; get rid of silly nested (progn (progn ...
- (while (eq 'progn (car-safe (nth 1 lisp)))
- (setq lisp (nth 1 lisp)))
- lisp)))
-
-(defun pdf-util-scale-edges (list-of-edges scale)
- "Scale LIST-OF-EDGES in both directions by SCALE.
-
-SCALE is a cons (SX . SY), by which edges are scaled and defaults
-to the scale of the image in the current window."
-
- (let ((have-list-p (listp (car list-of-edges))))
- (unless have-list-p
- (setq list-of-edges (list list-of-edges)))
- (let* ((sx (car scale))
- (sy (cdr scale))
- (round-p (or (> sx 1) (> sy 1)))
- (result (mapcar (lambda (edges)
- (let ((e (list (* (nth 0 edges) sx)
- (* (nth 1 edges) sy)
- (* (nth 2 edges) sx)
- (* (nth 3 edges) sy))))
- (if round-p
- (mapcar 'floor e)
- e)))
- list-of-edges)))
- (if have-list-p
- result
- (car result)))))
-
-(defun pdf-util-translate-edges (list-of-edges offset &optional inverse-p)
- (let ((have-list-p (listp (car list-of-edges))))
- (if (equal offset '(0 . 0))
- list-of-edges
- (unless have-list-p
- (setq list-of-edges (list list-of-edges)))
- (let* ((ox (if inverse-p
- (- (car offset))
- (car offset)))
- (oy (if inverse-p
- (- (cdr offset))
- (cdr offset)))
- (result (mapcar (lambda (edges)
- (mapcar 'round
- (list (+ (nth 0 edges) ox)
- (+ (nth 1 edges) oy)
- (+ (nth 2 edges) ox)
- (+ (nth 3 edges) oy))))
- list-of-edges)))
- (if have-list-p
- result
- (car result))))))
-
-(defun pdf-util-transform-edges (list-of-edges scale offset)
- (pdf-util-translate-edges
- (pdf-util-scale-edges list-of-edges scale)
- offset))
-
-(defun pdf-util-enlarge-edges (list-of-edges dx dy)
- (let ((have-list-p (listp (car list-of-edges))))
- (unless have-list-p
- (setq list-of-edges (list list-of-edges)))
- (let ((result (mapcar (lambda (edges)
- (list (- (nth 0 edges) dx)
- (- (nth 1 edges) dy)
- (+ (nth 2 edges) dx)
- (+ (nth 3 edges) dy)))
- list-of-edges)))
- (if have-list-p
- result
- (car result)))))
-
-(defun pdf-utils-edges-inside-p (edges pos &optional epsilon)
- (pdf-utils-edges-contained-p
- edges
- (list (car pos) (cdr pos) (car pos) (cdr pos))
- epsilon))
-
-(defun pdf-utils-edges-contained-p (edges contained &optional epsilon)
- (unless epsilon (setq epsilon 0))
- (pdf-util-with-edges (edges contained)
- (and (<= (- edges-left epsilon)
- contained-left)
- (>= (+ edges-right epsilon)
- contained-right)
- (<= (- edges-top epsilon)
- contained-top)
- (>= (+ edges-bot epsilon)
- contained-bot))))
-
-(defun pdf-utils-edges-disjoint-p (edges1 edges2 &optional epsilon)
- (unless epsilon (setq epsilon 0))
- (pdf-util-with-edges (edges1 edges2)
- (or (<= (- edges2-right epsilon)
- edges1-left)
- (<= (- edges2-bot epsilon)
- edges1-top)
- (>= (+ edges2-left epsilon)
- edges1-right)
- (>= (+ edges2-top epsilon)
- edges1-bot))))
-
-(defun pdf-utils-edges-intersection (e1 e2)
- (pdf-util-with-edges (edges1 e1 e2)
- (let ((left (max e1-left e2-left))
- (top (max e1-top e2-top))
- (right (min e1-right e2-right))
- (bot (min e1-bot e2-bot)))
- (when (and (<= left right)
- (<= top bot))
- (list left top right bot)))))
-
-(defun pdf-utils-edges-intersection-area (e1 e2)
- (let ((inters (pdf-utils-edges-intersection e1 e2)))
- (if (null inters)
- 0
- (pdf-util-with-edges (inters)
- (* inters-width inters-height)))))
-
-
-;;
-;; Handling Images In Windows
-;;
-
-(defcustom pdf-util-fast-image-format nil
- "An image format appropriate for fast displaying.
-
-This should be the string of a file extension of a supported (by
-Emacs and convert) image format. If nil, the value is determined
-automatically.
-
-Different formats have different properties, with respect to
-Emacs loading time, convert creation time and the file-size. In
-general, uncompressed formats are faster, but may need a fair
-amount of (temporary) disk space."
- :group 'pdf-tools)
-
-(defun pdf-util-fast-image-format ()
- "Return an image format appropriate for fast displaying.
-
-This function returns a file extension as a string, without the
-dot."
- (or pdf-util-fast-image-format
- (setq pdf-util-fast-image-format
- (if (fboundp 'imagemagick-types)
- (cond
- ((memq 'BMP2 (imagemagick-types))
- "bmp2")
- ((memq 'JPEG (imagemagick-types))
- "jpeg")
- (t
- "png"))
- "png"))))
-
-(defun pdf-util-image-offset ()
- (let* ((slice (pdf-view-current-slice)))
- (if slice
- (cons (nth 0 slice) (nth 1 slice))
- (cons 0 0))))
-
-(defun pdf-util-set-window-pixel-vscroll (vscroll)
- (setq vscroll (max (round vscroll) 0))
- (set-window-vscroll (selected-window) vscroll t)
- (setf (image-mode-window-get 'vscroll) (window-vscroll))
- nil)
-
-(defun pdf-util-set-window-pixel-hscroll (hscroll)
- (setq hscroll (max 0 (round (/ hscroll (float (frame-char-width))))))
- (setf (image-mode-window-get 'hscroll) hscroll)
- (set-window-hscroll nil hscroll)
- nil)
-
-(defun pdf-util-image-edges-in-window (&optional window)
- "Return the visible edges of some image in WINDOW."
+ (macroexpand-all
+ `(cl-symbol-macrolet
+ ,(apply 'nconc
+ (mapcar
+ (lambda (edge-syms)
+ (let ((edge (nth 0 edge-syms))
+ (syms (cdr edge-syms)))
+ `((,(pop syms) (nth 0 ,edge))
+ (,(pop syms) (nth 1 ,edge))
+ (,(pop syms) (nth 2 ,edge))
+ (,(pop syms) (nth 3 ,edge))
+ (,(pop syms) (- (nth 2 ,edge)
+ (nth 0 ,edge)))
+ (,(pop syms) (- (nth 3 ,edge)
+ (nth 1 ,edge))))))
+ list-of-syms))
+ ,@body))))
+
+(defun pdf-util-image-displayed-edges (&optional window)
+ "Return the visible region of the image in WINDOW.
+
+Returns a list of pixel edges."
(let* ((edges (window-inside-pixel-edges window))
- (isize (pdf-util-image-size))
- (offset (pdf-util-image-offset))
+ (isize (pdf-view-image-size window))
+ (offset (pdf-view-image-offset window))
(hscroll (* (window-hscroll window)
(frame-char-width (window-frame window))))
(vscroll (window-vscroll window t))
@@ -467,17 +246,16 @@ dot."
(+ y0 (- (nth 3 edges) (nth 1 edges))))))
(list x0 y0 x1 y1)))
-
(defun pdf-util-required-hscroll (edges &optional eager-p context-pixel)
- (unless context-pixel (setq context-pixel 0;; (frame-char-width)
- ))
+ (unless context-pixel
+ (setq context-pixel 0))
(let* ((win (window-inside-pixel-edges))
- (image-width (car (pdf-util-image-size t)))
+ (image-width (car (pdf-view-image-size t)))
(image-left (* (frame-char-width)
(window-hscroll)))
(edges (pdf-util-translate-edges
edges
- (pdf-util-image-offset) t)))
+ (pdf-view-image-offset) t)))
(pdf-util-with-edges (win edges)
(let* ((edges-left (- edges-left context-pixel))
(edges-right (+ edges-right context-pixel)))
@@ -495,11 +273,11 @@ dot."
(defun pdf-util-required-vscroll (edges &optional eager-p context-pixel)
(let* ((win (window-inside-pixel-edges))
- (image-height (cdr (pdf-util-image-size t)))
+ (image-height (cdr (pdf-view-image-size t)))
(image-top (window-vscroll nil t))
(edges (pdf-util-translate-edges
edges
- (pdf-util-image-offset) t)))
+ (pdf-view-image-offset) t)))
(pdf-util-with-edges (win edges)
(let* ((context-pixel (or context-pixel
(* next-screen-context-lines
@@ -519,109 +297,221 @@ dot."
edges-top
(- edges-bot win-height)))))))))
-(defun pdf-util-scroll-to-edges (edges &optional eager-p)
- (pdf-util-assert-pdf-window)
+(defun pdf-util-set-window-pixel-vscroll (vscroll)
+ (setq vscroll (max (round vscroll) 0))
+ (set-window-vscroll (selected-window) vscroll t)
+ (setf (image-mode-window-get 'vscroll) (window-vscroll))
+ nil)
+
+(defun pdf-util-set-window-pixel-hscroll (hscroll)
+ (setq hscroll (max 0 (round (/ hscroll (float (frame-char-width))))))
+ (setf (image-mode-window-get 'hscroll) hscroll)
+ (set-window-hscroll nil hscroll)
+ nil)
+
+(defun pdf-util-display-edges (edges &optional eager-p)
(let ((vscroll (pdf-util-required-vscroll edges eager-p))
(hscroll (pdf-util-required-hscroll edges eager-p)))
(when vscroll
(pdf-util-set-window-pixel-vscroll vscroll))
(when hscroll
(pdf-util-set-window-pixel-hscroll hscroll))))
-
-(defmacro pdf-util-save-window-scroll (&rest body)
- (declare (indent 0) (debug t))
- (let ((hscroll (make-symbol "hscroll"))
- (vscroll (make-symbol "vscroll")))
- `(let ((,hscroll (window-hscroll))
- (,vscroll (window-vscroll)))
- (unwind-protect
- (progn ,@body)
- (image-set-window-hscroll ,hscroll)
- (image-set-window-vscroll ,vscroll)))))
-(defun pdf-util-read-image-position (prompt)
- (pdf-util-assert-pdf-window)
- (save-selected-window
- (let ((ev (read-event
- (propertize prompt 'face 'minibuffer-prompt)))
- (buffer (current-buffer)))
- (unless (mouse-event-p ev)
- (error "Not a mouse event"))
- (let ((posn (event-start ev)))
- (unless (and (eq (window-buffer
- (posn-window posn))
- buffer)
- (eq 'image (car-safe (posn-object posn))))
- (error "Invalid image position"))
- (posn-object-x-y posn)))))
-(defun pdf-util-image-map-mouse-event-proxy (event)
- "Remove the POS-OR-AREA symbol from EVENT and restuff it."
- (interactive "e")
- (setcar (cdr (cadr event)) 1)
- (setq unread-command-events (list event)))
-(defun pdf-util-image-map-divert-mouse-clicks (id &optional buttons)
- (dolist (kind '("" "down-" "drag-"))
- (dolist (b (or buttons '(2 3 4 5 6)))
- (local-set-key
- (vector id (intern (format "%smouse-%d" kind b)))
- 'pdf-util-image-map-mouse-event-proxy))))
-
+
+;; * ================================================================== *
+;; * Various
+;; * ================================================================== *
+
+(defun pdf-util-pdf-buffer-p (&optional buffer)
+ (and (or (null buffer)
+ (buffer-live-p buffer))
+ (save-current-buffer
+ (and buffer (set-buffer buffer))
+ (derived-mode-p 'pdf-view-mode))))
+
+(defun pdf-util-assert-pdf-buffer (&optional buffer)
+ (unless (pdf-util-pdf-buffer-p buffer)
+ (error "Buffer is not in PDFView mode")))
+
+(defun pdf-util-pdf-window-p (&optional window)
+ (unless window (setq window (selected-window)))
+ (and (window-live-p window)
+ (with-selected-window window
+ (pdf-util-pdf-buffer-p))))
+(defun pdf-util-assert-pdf-window (&optional window)
+ (unless (pdf-util-pdf-window-p window)
+ (error "Window's buffer is not in PdfView mode")))
+
+(defun pdf-util-munch-file (filename &optional multibyte-p)
+ "Read contents from FILENAME and delete it.
+
+Return the file's content as a unibyte string, unless MULTIBYTE-P
+is non-nil."
+ (unwind-protect
+ (with-temp-buffer
+ (set-buffer-multibyte multibyte-p)
+ (insert-file-contents-literally filename)
+ (buffer-substring-no-properties
+ (point-min)
+ (point-max)))
+ (when (and filename
+ (file-exists-p filename))
+ (delete-file filename))))
+
+(defun pdf-util-hexcolor (color)
+ "Return COLOR in hex-format.
+
+Singal an error, if color is invalid."
+ (let ((values (color-values (string-trim color))))
+ (unless values
+ (signal 'wrong-type-argument (list 'color-defined-p color)))
+ (apply 'format "#%02x%02x%02x"
+ (mapcar (lambda (c) (lsh c -8))
+ values))))
+
+(defun pdf-util-tooltip-in-window (text x y &optional window)
+ (let* ((we (window-inside-absolute-pixel-edges window))
+ (dx (round (+ x (nth 0 we))))
+ (dy (round (+ y (nth 1 we))))
+ (tooltip-frame-parameters
+ `((left . ,dx)
+ (top . ,dy)
+ ,@tooltip-frame-parameters)))
+ (tooltip-show text)))
+
+(defun pdf-util-tooltip-arrow (image-top &optional timeout)
+ (pdf-util-assert-pdf-window)
+ (when (floatp image-top)
+ (setq image-top
+ (round (* image-top (cdr (pdf-view-image-size))))))
+ (let* (x-gtk-use-system-tooltips ;allow for display property in tooltip
+ (dx (+ (or (car (window-margins)) 0)
+ (car (window-fringes))))
+ (dy image-top)
+ (pos (list dx dy dx (+ dy (* 2 (frame-char-height)))))
+ (vscroll
+ (pdf-util-required-vscroll pos))
+ (tooltip-frame-parameters
+ `((border-width . 0)
+ (internal-border-width . 0)
+ ,@tooltip-frame-parameters))
+ (tooltip-hide-delay (or timeout 3)))
+ (when vscroll
+ (pdf-util-set-window-pixel-vscroll vscroll))
+ (setq dy (max 0 (- dy
+ (cdr (pdf-view-image-offset))
+ (window-vscroll nil t))))
+ (when (overlay-get (doc-view-current-overlay) 'before-string)
+ (let* ((e (window-inside-pixel-edges))
+ (xw (pdf-util-with-edges (e) e-width)))
+ (cl-incf dx (/ (- xw (car (pdf-view-image-size))) 2))))
+ (pdf-util-tooltip-in-window
+ (propertize
+ " " 'display (propertize
+ "\u2192" ;;right arrow
+ 'display '(height 2)
+ 'face '(:foreground
+ "orange red"
+ :background "white")))
+ dx dy)))
+
+(defvar pdf-util--face-colors-cache (make-hash-table))
-;;
-;; Converting Images
-;;
+(defun pdf-util-face-colors (face &optional dark-p)
+ "Return both colors of FACE as a cons.
+
+Look also in inherited faces. If DARK-P is non-nil, return dark
+colors, otherwise light."
+ (let* ((bg (if dark-p 'dark 'light))
+ (spec (list (get face 'face-defface-spec)
+ (get face 'theme-face)
+ (get face 'customized-face)))
+ (cached (gethash face pdf-util--face-colors-cache)))
+ (cl-destructuring-bind (&optional cspec color-alist)
+ cached
+ (or (and color-alist
+ (equal cspec spec)
+ (cdr (assq bg color-alist)))
+ (let* ((this-bg (frame-parameter nil 'background-mode))
+ (frame-background-mode bg)
+ (f (and (not (eq bg this-bg))
+ (x-create-frame-with-faces '((visibility . nil))))))
+ (with-selected-frame (or f (selected-frame))
+ (unwind-protect
+ (let ((colors
+ (cons (face-attribute face :foreground nil 'default)
+ (face-attribute face :background nil 'default))))
+ (puthash face `(,(mapcar 'copy-sequence spec)
+ ((,bg . ,colors) ,@color-alist))
+ pdf-util--face-colors-cache)
+ colors)
+ (when (and f (frame-live-p f))
+ (delete-frame f)))))))))
+
+(defun pdf-util-window-attach (awindow &optional window)
+ "Attach AWINDOW to WINDOW.
+
+This has the following effect. Whenever WINDOW, defaulting to
+the selected window, stops displaying the buffer it currently
+displays (e.g., by switching buffers or because it was deleted)
+AWINDOW is deleted also."
+ (unless window (setq window (selected-window)))
+ (let ((buffer (window-buffer window))
+ (hook (make-symbol "window-attach-hook")))
+ (fset hook
+ (lambda ()
+ (when (or (not (window-live-p window))
+ (not (eq buffer (window-buffer window))))
+ (remove-hook 'window-configuration-change-hook
+ hook)
+ ;; Deleting windows inside wcch may cause errors in
+ ;; windows.el .
+ (run-with-timer
+ 0 nil (lambda (win)
+ (when (and (window-live-p win)
+ (not (eq win (selected-window))))
+ (delete-window win)))
+ awindow))))
+ (add-hook 'window-configuration-change-hook hook)))
+
+(defun display-buffer-split-below-and-attach (buf alist)
+ "Display buffer action using `pdf-util-window-attach'."
+ (let ((window (selected-window))
+ (height (cdr (assq 'window-height alist)))
+ newwin)
+ (when height
+ (when (floatp height)
+ (setq height (round (* height (frame-height)))))
+ (setq height (- (max height window-min-height))))
+ (setq newwin (window--display-buffer
+ buf
+ (split-window-below height)
+ 'window alist display-buffer-mark-dedicated))
+ (pdf-util-window-attach newwin window)
+ newwin))
+
+
+;; * ================================================================== *
+;; * Imagemagick's convert
+;; * ================================================================== *
+
+(defcustom pdf-util-convert-program (executable-find "convert")
+ "Absolute path to the convert program."
+ :group 'pdf-tools
+ :type 'executable)
(defun pdf-util-assert-convert-program ()
(unless (and pdf-util-convert-program
(file-executable-p pdf-util-convert-program))
(error "The pdf-util-convert-program is unset or non-executable")))
-(defvar-local pdf-util-png-image-size-resolution nil
- "Saved resolution of the current conversion.
-
-Used to determine whether cached image-file sizes are still
-valid.")
-
-(defun pdf-util-png-image-size (&optional page)
- "Return the image size of the image file of the current PAGE.
-
-This returns a cons \(WIDTH . HEIGHT\) or nil, if not
-available (e.g. because it does not exist or is currently written
-to)."
-
- (unless page (setq page (ignore-errors
- (doc-view-current-page))))
- (when page
- (unless (eq doc-view-resolution
- pdf-util-png-image-size-resolution)
- (setq pdf-util-png-image-size-resolution doc-view-resolution
- pdf-util-png-image-size-alist nil))
- (let ((entry
- (cl-assoc page pdf-util-png-image-size-alist
- :test 'gnus-member-of-range)))
- (if entry
- (nth 2 entry)
- (let ((page-size (pdf-info-pagesize page)))
- (setq entry (car (cl-member page-size
- pdf-util-png-image-size-alist
- :key 'cadr :test 'equal)))
- (unless entry
- (let ((size (pdf-util-image-file-size
- (pdf-util-current-image-file page))))
- (when size
- (setq entry
- (list nil page-size size))
- (push entry pdf-util-png-image-size-alist))))
- (when entry
- (setcar entry (gnus-range-add
- (car entry) (list page)))
- (nth 2 entry)))))))
-
-
(defun pdf-util-image-file-size (image-file)
+ "Determine the size of the image in IMAGE-FILE.
+
+Returns a cons \(WIDTH . HEIGHT\)."
(pdf-util-assert-convert-program)
(with-temp-buffer
(when (save-excursion
@@ -709,7 +599,6 @@ See url `http://www.imagemagick.org/script/convert.php'."
out-file))
(defun pdf-util-convert-asynch (in-file out-file &rest spec-and-callback)
- ;; Influence compression level with -quality 0-100.
(pdf-util-assert-convert-program)
(let ((callback (car (last spec-and-callback)))
spec)
@@ -773,272 +662,106 @@ See url `http://www.imagemagick.org/script/convert.php'."
(dolist (fmt cmds)
(push (format-spec fmt alist) result))))))))
(nreverse result)))
-
-;;
-;; Caching Converted Images
+
+
+
+;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;;
+;; O L D C O D E
+;;
+;; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
-(defvar pdf-util-cache-directories nil)
-
-(defun pdf-util-cache-make-filename (dir &optional extension &rest keys)
- (when (symbolp dir)
- (setq dir (symbol-name dir)))
- (let ((root (pdf-util-cache--get-root-dir)))
- (unless root
- (error "The DocView cache directory is n/a"))
- (let ((file (format "%s.%s" (sha1 (format "%S" keys))
- (or extension "png")))
- (dir (file-name-as-directory
- (expand-file-name
- dir
- root))))
- (unless (file-exists-p dir)
- (make-directory dir)
- (push dir pdf-util-cache-directories))
- (setq file (expand-file-name file dir))
- (when (file-exists-p file)
- (set-file-times file))
- file)))
-
-(defun pdf-util-cache-files (dir)
- (when (symbolp dir)
- (setq dir (symbol-name dir)))
- (let ((root (pdf-util-cache--get-root-dir)))
- (when root
- (let ((dir (file-name-as-directory
- (expand-file-name
- dir
- root))))
- (when (file-exists-p dir)
- (directory-files
- dir t directory-files-no-dot-files-regexp))))))
-
-(defun pdf-util-cache-clear (dir)
- (when (symbolp dir)
- (setq dir (symbol-name dir)))
- (let ((root (pdf-util-cache--get-root-dir)))
- (when root
- (let ((dir (file-name-as-directory
- (expand-file-name
- dir
- root))))
- (when (file-exists-p dir)
- (mapc 'clear-image-cache
- (directory-files
- dir t directory-files-no-dot-files-regexp t))
- (delete-directory dir t))))))
-
-(defun pdf-util-cache-clear-all ()
- (interactive)
- (let ((dir (pdf-util-cache--get-root-dir)))
- (when (and dir
- (file-exists-p dir))
- (with-temp-buffer
- ;; Switch to multibyte buffer, because delete-directory has a
- ;; filename encoding bug when deleting recursively from
- ;; unibyte buffer.
- (delete-directory dir t)))))
-
-(defun pdf-util-cache--get-root-dir ()
- (when (and (pdf-util-docview-buffer-p)
- (doc-view-current-cache-dir)
- (file-exists-p (doc-view-current-cache-dir)))
- (let ((dir (file-name-as-directory
- (expand-file-name
- ".pdf-util-cache"
- (doc-view-current-cache-dir)))))
- (unless (file-exists-p dir)
- (make-directory dir))
- (add-hook 'kill-buffer-hook 'pdf-util-cache-clear-all nil t)
- dir)))
-
-(defun pdf-util-cache-clean-globally ()
- "Remove all not recently used cached images."
- (let ((dvcd (expand-file-name doc-view-cache-directory)))
- (setq pdf-util-cache-directories
- (cl-remove-if-not
- (lambda (d)
- (and (file-readable-p d)
- (string-prefix-p dvcd d)))
- pdf-util-cache-directories)))
- (let ((now (current-time)))
- (dolist (dir pdf-util-cache-directories)
- (when (file-readable-p dir)
- (dolist (file (directory-files
- dir t directory-files-no-dot-files-regexp t))
- (let ((mtime (nth 5 (file-attributes file))))
- (when (and (time-less-p
- (time-add mtime (seconds-to-time (* 5 60)))
- now)
- (not (pdf-util-image-in-use-p file)))
- (if (file-directory-p file)
- (let ((pdf-util-cache-directories
- (list file)))
- (pdf-util-cache-clean-globally))
- (clear-image-cache file)
- (delete-file file)))))
- (when (and (file-readable-p dir)
- (null (directory-files
- dir t directory-files-no-dot-files-regexp t)))
- (delete-directory dir))))))
-
-;;(run-with-timer 0 (* 5 60) 'pdf-util-cache-clean-globally)
-
-(defun pdf-util-image-in-use-p (file)
- "Return t if image FILE is displayed in some window."
- (cl-labels
- ((check-buffer (buffer &optional window)
- ;; Deleting a used image-file with imagemagick may crash Emacs,
- ;; be thorough.
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-min))
- (catch 'found
- (while (not (eobp))
- (let ((display (get-char-property
- (point) 'display window))
- image-file)
- (when (and (consp display)
- (eq 'image (car display))
- (setq image-file (plist-get (cdr display) :file))
- image-file
- (file-equal-p image-file file))
- (throw 'found t)))
- (goto-char (next-single-char-property-change
- (point) 'display nil (point-max)))))))))
- (or (get-window-with-predicate
- (lambda (win)
- (check-buffer (window-buffer win) win))
- 'no-mini t)
- (let ((tip (get-buffer " *tip*")))
- (and (buffer-live-p tip)
- (check-buffer tip))))))
+
+
+
+
+(require 'cl-lib)
+(require 'format-spec)
;;
-;; Various Functions
+;; Handling Edges
;;
-(defun pdf-util-tooltip-in-window (text x y &optional window)
- (let* ((we (window-inside-absolute-pixel-edges window))
- (dx (round (+ x (nth 0 we))))
- (dy (round (+ y (nth 1 we))))
- (tooltip-frame-parameters
- `((left . ,dx)
- (top . ,dy)
- ,@tooltip-frame-parameters)))
- (tooltip-show text)))
-(defun pdf-util-tooltip-arrow (image-top &optional timeout)
+
+
+
+
+(defun pdf-utils-edges-inside-p (edges pos &optional epsilon)
+ (pdf-utils-edges-contained-p
+ edges
+ (list (car pos) (cdr pos) (car pos) (cdr pos))
+ epsilon))
+
+(defun pdf-utils-edges-contained-p (edges contained &optional epsilon)
+ (unless epsilon (setq epsilon 0))
+ (pdf-util-with-edges (edges contained)
+ (and (<= (- edges-left epsilon)
+ contained-left)
+ (>= (+ edges-right epsilon)
+ contained-right)
+ (<= (- edges-top epsilon)
+ contained-top)
+ (>= (+ edges-bot epsilon)
+ contained-bot))))
+
+(defun pdf-utils-edges-intersection (e1 e2)
+ (pdf-util-with-edges (edges1 e1 e2)
+ (let ((left (max e1-left e2-left))
+ (top (max e1-top e2-top))
+ (right (min e1-right e2-right))
+ (bot (min e1-bot e2-bot)))
+ (when (and (<= left right)
+ (<= top bot))
+ (list left top right bot)))))
+
+(defun pdf-utils-edges-intersection-area (e1 e2)
+ (let ((inters (pdf-utils-edges-intersection e1 e2)))
+ (if (null inters)
+ 0
+ (pdf-util-with-edges (inters)
+ (* inters-width inters-height)))))
+
+
+
+(defun pdf-util-read-image-position (prompt)
(pdf-util-assert-pdf-window)
- (unless (pdf-util-page-displayed-p)
- (error "No page displayed in this window"))
- (when (floatp image-top)
- (setq image-top
- (round (* image-top (cdr (pdf-util-image-size))))))
- (let* (x-gtk-use-system-tooltips ;allow for display property in tooltip
- (dx (+ (or (car (window-margins)) 0)
- (car (window-fringes))))
- (dy image-top)
- (pos (list dx dy dx (+ dy (* 2 (frame-char-height)))))
- (vscroll
- (pdf-util-required-vscroll pos))
- (tooltip-frame-parameters
- `((border-width . 0)
- (internal-border-width . 0)
- ,@tooltip-frame-parameters))
- (tooltip-hide-delay (or timeout 3)))
- (when vscroll
- (pdf-util-set-window-pixel-vscroll vscroll))
- (setq dy (max 0 (- dy
- (cdr (pdf-util-image-offset))
- (window-vscroll nil t))))
- (when (overlay-get (doc-view-current-overlay) 'before-string)
- (let* ((e (window-inside-pixel-edges))
- (xw (pdf-util-with-edges (e) e-width)))
- (cl-incf dx (/ (- xw (car (pdf-util-image-size))) 2))))
- (pdf-util-tooltip-in-window
- (propertize
- " " 'display (propertize
- "\u2192" ;;right arrow
- 'display '(height 2)
- 'face '(:foreground
- "orange red"
- :background "white")))
- dx dy)))
+ (save-selected-window
+ (let ((ev (read-event
+ (propertize prompt 'face 'minibuffer-prompt)))
+ (buffer (current-buffer)))
+ (unless (mouse-event-p ev)
+ (error "Not a mouse event"))
+ (let ((posn (event-start ev)))
+ (unless (and (eq (window-buffer
+ (posn-window posn))
+ buffer)
+ (eq 'image (car-safe (posn-object posn))))
+ (error "Invalid image position"))
+ (posn-object-x-y posn)))))
-(defvar pdf-util-face-colors--cache (make-hash-table))
-
-(defun pdf-util-face-colors (face &optional dark-p)
- "Return both colors of FACE as a cons.
+(defun pdf-util-image-map-mouse-event-proxy (event)
+ "Remove the POS-OR-AREA symbol from EVENT and restuff it."
+ (interactive "e")
+ (setcar (cdr (cadr event)) 1)
+ (setq unread-command-events (list event)))
-Look also in inherited faces. If DARK-P is non-nil, return dark
-colors, otherwise light."
- (let* ((bg (if dark-p 'dark 'light))
- (spec (list (get face 'face-defface-spec)
- (get face 'theme-face)
- (get face 'customized-face)))
- (cached (gethash face pdf-util-face-colors--cache)))
- (cl-destructuring-bind (&optional cspec color-alist)
- cached
- (or (and color-alist
- (equal cspec spec)
- (cdr (assq bg color-alist)))
- (let* ((this-bg (frame-parameter nil 'background-mode))
- (frame-background-mode bg)
- (f (and (not (eq bg this-bg))
- (x-create-frame-with-faces '((visibility . nil))))))
- (with-selected-frame (or f (selected-frame))
- (unwind-protect
- (let ((colors
- (cons (face-attribute face :foreground nil 'default)
- (face-attribute face :background nil 'default))))
- (puthash face `(,(mapcar 'copy-sequence spec)
- ((,bg . ,colors) ,@color-alist))
- pdf-util-face-colors--cache)
- colors)
- (when (and f (frame-live-p f))
- (delete-frame f)))))))))
+(defun pdf-util-image-map-divert-mouse-clicks (id &optional buttons)
+ (dolist (kind '("" "down-" "drag-"))
+ (dolist (b (or buttons '(2 3 4 5 6)))
+ (local-set-key
+ (vector id (intern (format "%smouse-%d" kind b)))
+ 'pdf-util-image-map-mouse-event-proxy))))
+
+
-(defun pdf-util-window-attach (awindow &optional window)
- "Attach AWINDOW to WINDOW.
-This has the following effect. Whenever WINDOW, defaulting to
-the selected window, stops displaying the buffer it currently
-displays (e.g., by switching buffers or because it was deleted)
-AWINDOW is deleted."
- (unless window (setq window (selected-window)))
- (let ((buffer (window-buffer window))
- (hook (make-symbol "window-attach-hook")))
- (fset hook
- (lambda ()
- (when (or (not (window-live-p window))
- (not (eq buffer (window-buffer window))))
- (remove-hook 'window-configuration-change-hook
- hook)
- ;; Deleting windows inside wcch leads to errors in
- ;; windows.el .
- (run-with-timer
- 0 nil (lambda (win)
- (when (and (window-live-p win)
- (not (eq win (selected-window))))
- (delete-window win)))
- awindow))))
- (add-hook 'window-configuration-change-hook hook)))
+
+;;
+;; Various Functions
+;;
-(defun display-buffer-split-below-and-attach (buf alist)
- (let ((window (selected-window))
- (height (cdr (assq 'window-height alist)))
- newwin)
- (when height
- (when (floatp height)
- (setq height (round (* height (frame-height)))))
- (setq height (- (max height window-min-height))))
- (setq newwin (window--display-buffer
- buf
- (split-window-below height)
- 'window alist display-buffer-mark-dedicated))
- (pdf-util-window-attach newwin window)
- newwin))
(provide 'pdf-util)
diff --git a/lisp/pdf-view.el b/lisp/pdf-view.el
index 84097ed..fa55216 100644
--- a/lisp/pdf-view.el
+++ b/lisp/pdf-view.el
@@ -446,18 +446,18 @@ at the top edge of the page moves to the previous page."
;; * Slicing
;; * ================================================================== *
-(defun pdf-view-set-slice (x y width height)
+(defun pdf-view-set-slice (x y width height &optional window)
"Set the slice of the pages that should be displayed.
X, Y, WIDTH and HEIGHT should be relative coordinates, i.e. in
\[0;1\]. To reset the slice use `pdf-view-reset-slice'."
- (unless (equal (pdf-view-current-slice)
+ (unless (equal (pdf-view-current-slice window)
(list x y width height))
- (setf (pdf-view-current-slice)
+ (setf (pdf-view-current-slice window)
(mapcar (lambda (v)
(max 0 (min 1 v)))
(list x y width height)))
- (pdf-view-redisplay)))
+ (pdf-view-redisplay window)))
(defun pdf-view-set-slice-using-mouse ()
"Set the slice of the images that should be displayed.
@@ -483,8 +483,8 @@ dragging it to its bottom-right corner. See also
(cons (/ 1.0 (float (car size)))
(/ 1.0 (float (cdr size))))))))
-(defun pdf-view-set-slice-from-bounding-box ()
- "Set the slice from the document's bounding-box.
+(defun pdf-view-set-slice-from-bounding-box (&optional window)
+ "Set the slice from the page's bounding-box.
The result is that the margins are almost completely cropped,
much more accurate than could be done manually using
@@ -492,7 +492,7 @@ much more accurate than could be done manually using
See also `pdf-view-bounding-box-margin'."
(interactive)
- (let* ((bb (pdf-cache-boundingbox (pdf-view-current-page)))
+ (let* ((bb (pdf-cache-boundingbox (pdf-view-current-page window)))
(margin (max 0 (or pdf-view-bounding-box-margin 0)))
(slice (list (- (nth 0 bb)
(/ margin 2.0))
@@ -502,17 +502,19 @@ See also `pdf-view-bounding-box-margin'."
margin)
(+ (- (nth 3 bb) (nth 1 bb))
margin))))
- (apply 'pdf-view-set-slice slice)))
+ (apply 'pdf-view-set-slice
+ (append slice (and window (list window))))))
-(defun pdf-view-reset-slice ()
+(defun pdf-view-reset-slice (&optional window)
"Reset the current slice.
After calling this function the whole page will be visible
again."
(interactive)
- (when (pdf-view-current-slice)
- (setf (pdf-view-current-slice) nil)
- (pdf-view-redisplay)))
+ (when (pdf-view-current-slice window)
+ (setf (pdf-view-current-slice window) nil)
+ (pdf-view-redisplay window))
+ nil)
@@ -551,8 +553,32 @@ or png."
:width (car size)
:map hotspots)))
-(defun pdf-view-image-size (&optional window)
- (image-size (pdf-view-current-image window) t))
+(defun pdf-view-image-size (&optional displayed-p window)
+ "Return the size in pixel of the current image.
+
+If DISPLAYED-P is non-nil, returned the size of the displayed
+image. These may be different, if slicing is in use."
+ (if displayed-p
+ (with-selected-window (or window (selected-window))
+ (image-display-size
+ (image-get-display-property) t))
+ (image-size (pdf-view-current-image window) t)))
+
+(defalias 'pdf-util-image-size 'pdf-view-image-size)
+
+(defun pdf-view-image-offset (&optional window)
+ "Return the offset of the current image.
+
+It is equal to \(LEFT . TOP\) of the current slice in pixel."
+
+ (let* ((slice (pdf-view-current-slice window)))
+ (cond
+ (slice
+ (pdf-util-scale-relative-to-pixel
+ (cons (nth 0 slice) (nth 1 slice))
+ window))
+ (t
+ (cons 0 0)))))
(defun pdf-view-display-page (page &optional window inhibit-hotspots-p)
"Display page PAGE in WINDOW."
@@ -748,8 +774,6 @@ supercede hotspots in lower ones."
(pdf-view-current-page))))))))))
(defun pdf-view--prefetch-pages (window image-width)
- (unless pdf-view--prefetch-pages
- (pdf-util-debug "Prefetching done."))
(when (and pdf-view--prefetch-pages
(eq window (selected-window)))
(let ((page (pop pdf-view--prefetch-pages)))
@@ -761,18 +785,21 @@ supercede hotspots in lower ones."
image-width
(* 2 image-width))))
(setq page (pop pdf-view--prefetch-pages)))
- (when page
+ (if (null page)
+ (pdf-tools-debug "Prefetching done.")
(let ((pdf-info-asynchronous
(lambda (status data)
(when (and (null status)
(eq window
(selected-window)))
- (pdf-cache-put-image page image-width data)
- (image-size (pdf-view-create-image page))
- (pdf-util-debug "Prefetched Page %s." page)
- ;; Avoid max-lisp-eval-depth
- (run-with-timer
- 0 nil 'pdf-view--prefetch-pages window image-width)))))
+ (with-current-buffer (window-buffer)
+ (pdf-cache-put-image
+ page image-width (pdf-util-munch-file data))
+ (image-size (pdf-view-create-image page))
+ (pdf-tools-debug "Prefetched Page %s." page)
+ ;; Avoid max-lisp-eval-depth
+ (run-with-timer
+ 0 nil 'pdf-view--prefetch-pages window image-width))))))
(pdf-info-renderpage page image-width))))))
(defun pdf-view--prefetch-start (buffer)
@@ -784,7 +811,7 @@ supercede hotspots in lower ones."
(let ((pages (funcall pdf-view-prefetch-pages-function)))
(setq pdf-view--prefetch-pages
(butlast pages (max 0 (- (length pages)
- pdf-cache-image-cache-limit))))
+ pdf-cache-image-limit))))
(pdf-view--prefetch-pages
(selected-window)
(car (pdf-view-desired-image-size))))))