branch: elpa/pdf-tools
commit 2603233d2b3814c75c762783327f1fd633f82549
Author: Vedang Manerikar <[email protected]>
Commit: Vedang Manerikar <[email protected]>
feat: integrate pdf-view-roll-minor-mode with existing features
Update all pdf-tools features to work correctly when
pdf-view-roll-minor-mode is active:
- pdf-isearch: Search across all displayed pages simultaneously
- pdf-links: Link selection works with multiple visible pages
- pdf-annot: Annotations work on correct page, add pdf-annot-edit
command for avy-style annotation editing
- pdf-sync: SyncTeX jumps work with continuous scroll mode
- pdf-view: Display and navigation functions updated for multi-page
- pdf-util: Coordinate transformation updates for visible pages
- pdf-cache: Simplify prefetch (remove timer indirection)
- pdf-occur: Minor compatibility updates
The mode is experimental. Some features may not interact perfectly
with roll mode. Enable with M-x pdf-view-roll-minor-mode.
API changes:
- pdf-view-active-region now includes page information
- isearch results include page data for multi-page display
Co-authored-by: Daniel Nicolai <[email protected]>
Co-authored-by: Rahguzar <[email protected]>
Co-authored-by: Ihor Radchenko <[email protected]>
Co-authored-by: NightMachinery <[email protected]>
---
lisp/pdf-annot.el | 83 ++++++++++++++++--
lisp/pdf-cache.el | 5 +-
lisp/pdf-isearch.el | 165 ++++++++++++++++++++---------------
lisp/pdf-links.el | 96 ++++++++++-----------
lisp/pdf-occur.el | 6 +-
lisp/pdf-sync.el | 19 +++--
lisp/pdf-util.el | 137 ++++++++++++++++-------------
lisp/pdf-view.el | 241 ++++++++++++++++++++++++++++++++--------------------
8 files changed, 461 insertions(+), 291 deletions(-)
diff --git a/lisp/pdf-annot.el b/lisp/pdf-annot.el
index 0abad53d41a..4c87e24c8ad 100644
--- a/lisp/pdf-annot.el
+++ b/lisp/pdf-annot.el
@@ -1012,7 +1012,8 @@ other annotations."
`("white" "steel blue" 0.35 ,@edges))
:map (pdf-view-apply-hotspot-functions
window page size)
- :width (car size))))
+ :width (car size))
+ (when pdf-view-roll-minor-mode page)))
(pdf-util-scroll-to-edges
(pdf-util-scale-relative-to-pixel (car edges)))))))
@@ -1099,8 +1100,8 @@ Return the new annotation."
(pdf-annot-activate-annotation a))
a))
-(defun pdf-annot-add-text-annotation (pos &optional icon property-alist)
- "Add a new text annotation at POS in the selected window.
+(defun pdf-annot-add-text-annotation (pos &optional icon property-alist page)
+ "Add a new text annotation at POS on PAGE in the selected window.
POS should be a image position object or a cons \(X . Y\), both
being image coordinates.
@@ -1128,6 +1129,9 @@ Return the new annotation."
(list posn)))
(pdf-util-assert-pdf-window)
(when (posnp pos)
+ (setq page (or page
+ (when pdf-view-roll-minor-mode
+ (1+ (/ (posn-point pos) 4)))))
(setq pos (posn-object-x-y pos)))
(let ((isize (pdf-view-image-size))
(x (car pos))
@@ -1152,7 +1156,8 @@ Return the new annotation."
property-alist
(cdr (assq 'text pdf-annot-default-annotation-properties))
(cdr (assq t pdf-annot-default-annotation-properties))
- `((color . ,(car pdf-annot-color-history))))))))
+ `((color . ,(car pdf-annot-color-history))))
+ page))))
(defun pdf-annot-mouse-add-text-annotation (ev)
"Add a text annotation using the mouse.
@@ -1168,11 +1173,12 @@ EV describes the captured mouse event."
"Click where a new text annotation should be added ..."))
(event-start ev))))
-(defun pdf-annot-add-markup-annotation (list-of-edges type &optional color
+(defun pdf-annot-add-markup-annotation (region type &optional color
property-alist)
"Add a new markup annotation in the selected window.
-LIST-OF-EDGES determines the marked up area and should be a list
+REGION determines the marked up area and should be a cons cell
+\(PAGE . LIST-OF-EDGES\) where LIST-OF-EDGES should be list
of \(LEFT TOP RIGHT BOT\), each value a relative coordinate.
TYPE should be one of `squiggly', `underline', `strike-out' or
@@ -1195,7 +1201,7 @@ Return the new annotation."
(pdf-util-assert-pdf-window)
(pdf-annot-add-annotation
type
- list-of-edges
+ (cdr region)
(pdf-annot-merge-alists
(and color `((color . ,color)))
property-alist
@@ -1204,7 +1210,7 @@ Return the new annotation."
(when pdf-annot-color-history
`((color . ,(car pdf-annot-color-history))))
'((color . "#ffff00")))
- (pdf-view-current-page)))
+ (car region)))
(defun pdf-annot-add-squiggly-markup-annotation (list-of-edges
&optional color
property-alist)
@@ -1554,6 +1560,66 @@ At any given point of time, only one annotation can be
in edit mode."
(error "No annotation at this position"))
(pdf-annot-edit-contents a)))
+(defun pdf-annot-edit (annot)
+ "Activate ANNOT, for editing.
+
+Interactively, annot is read via `pdf-annot-read-annot'.
+This function displays characters around the annots in the current
+page and starts reading characters (ignoring case). After a
+sufficient number of characters have been read, the corresponding
+annot's annot is invoked. Additionally, SPC may be used to
+scroll the current page."
+ (interactive
+ (list (or (pdf-annot-read-annot "Activate annot (SPC scrolls): ")
+ (error "No annot selected"))))
+ (pdf-annot-activate-annotation annot))
+
+;; TODO 'merge' this function with `pdf-links-read-link-action' into a single
+;; universal 'read-action' function (in `pdf-util'?)
+(defun pdf-annot-read-annot (prompt)
+ "Using PROMPT, interactively read an annot-action.
+
+See `pdf-annot-edit' for the interface."
+ (pdf-util-assert-pdf-window)
+ (let* ((annots (pdf-annot-getannots (pdf-view-current-page) nil nil))
+ (keys (pdf-links-read-link-action--create-keys
+ (length annots)))
+ (key-strings (mapcar (apply-partially 'apply 'string)
+ keys))
+ (alist (cl-mapcar 'cons keys annots))
+ (size (pdf-view-image-size))
+ (colors (pdf-util-face-colors
+ 'pdf-links-read-link pdf-view-dark-minor-mode))
+ (args (list
+ :foreground (car colors)
+ :background (cdr colors)
+ :formats
+ `((?c . ,(lambda (_edges) (pop key-strings)))
+ (?P . ,(number-to-string
+ (max 1 (* (cdr size)
+ pdf-links-convert-pointsize-scale)))))
+ :commands pdf-links-read-link-convert-commands
+ :apply (pdf-util-scale-relative-to-pixel
+ (mapcar (lambda (l) (cdr (assq 'edges l)))
+ annots)))))
+ ;; (print (plist-get args :apply))
+ (unless annots
+ (error "No annots on this page"))
+ (unwind-protect
+ (let ((image-data
+ (pdf-cache-get-image
+ (pdf-view-current-page)
+ (car size) (car size) 'pdf-annot-read-annot)))
+ (unless image-data
+ (setq image-data (apply 'pdf-util-convert-page args ))
+ (pdf-cache-put-image
+ (pdf-view-current-page)
+ (car size) image-data 'pdf-annot-read-annot))
+ (pdf-view-display-image
+ (create-image image-data (pdf-view-image-type) t)
+ (when pdf-view-roll-minor-mode (pdf-view-current-page)))
+ (pdf-links-read-link-action--read-chars prompt alist))
+ (pdf-view-redisplay))))
;; * ================================================================== *
@@ -1596,6 +1662,7 @@ Currently supported properties are page, type, label,
date and contents."
(defvar pdf-annot-list-mode-map
(let ((km (make-sparse-keymap)))
+ (define-key km (kbd "e") 'pdf-annot-edit)
(define-key km (kbd "C-c C-f") #'pdf-annot-list-follow-minor-mode)
(define-key km (kbd "SPC") #'pdf-annot-list-display-annotation-from-id)
km))
diff --git a/lisp/pdf-cache.el b/lisp/pdf-cache.el
index a4f0d60801e..57c824fcaed 100644
--- a/lisp/pdf-cache.el
+++ b/lisp/pdf-cache.el
@@ -456,10 +456,7 @@ WINDOW and IMAGE-WIDTH decide the page and scale of the
final image."
(image-size (pdf-view-create-page page))
(pdf-util-debug
(message "Prefetched page %s." page))
- ;; Avoid max-lisp-eval-depth
- (run-with-timer
- 0.001 nil
- #'pdf-cache--prefetch-pages window image-width)))))))
+ (pdf-cache--prefetch-pages window image-width)))))))
(condition-case err
(pdf-info-renderpage page image-width)
(error
diff --git a/lisp/pdf-isearch.el b/lisp/pdf-isearch.el
index f5468eb56a6..9ffc2e41df3 100644
--- a/lisp/pdf-isearch.el
+++ b/lisp/pdf-isearch.el
@@ -33,7 +33,7 @@
(require 'let-alist)
;;; Code:
-
+(defvar pdf-isearch--hl-matches-tick 0)
;; * ================================================================== *
@@ -249,42 +249,55 @@ This is a Isearch interface function."
(when (> (length string) 0)
(let ((same-search-p (pdf-isearch-same-search-p))
(oldpage pdf-isearch-current-page)
- (matches (pdf-isearch-search-page string))
+ (pages (or (image-mode-window-get 'displayed-pages (selected-window))
+ (list (pdf-view-current-page))))
+ matches
next-match)
- ;; matches is a list of list of edges ((x0 y1 x1 y2) ...),
- ;; sorted top to bottom ,left to right. Coordinates are in image
- ;; space.
- (unless isearch-forward
- (setq matches (reverse matches)))
- (when pdf-isearch-filter-matches-function
- (setq matches (funcall pdf-isearch-filter-matches-function matches)))
+ (dolist (page pages)
+ (let ((page-matches (pdf-isearch-search-page string page)))
+ ;; matches is a list of list of edges ((x0 y1 x1 y2) ...),
+ ;; sorted top to bottom ,left to right. Coordinates are in image
+ ;; space.
+ (unless isearch-forward
+ (setq page-matches (reverse page-matches)))
+ (when pdf-isearch-filter-matches-function
+ (setq page-matches (funcall pdf-isearch-filter-matches-function
page-matches)))
+ (push page-matches matches)))
;; Where to go next ?
(setq pdf-isearch-current-page (pdf-view-current-page)
pdf-isearch-current-matches matches
next-match
(pdf-isearch-next-match
oldpage pdf-isearch-current-page
- pdf-isearch-current-match matches
+ pdf-isearch-current-match (car matches)
same-search-p
isearch-forward)
pdf-isearch-current-parameter
(list string isearch-regexp
isearch-case-fold-search isearch-word))
+ (cl-callf nreverse matches)
(cond
(next-match
(setq pdf-isearch-current-match next-match)
- (pdf-isearch-hl-matches next-match matches)
+ (pdf-isearch-hl-matches next-match matches nil pages)
(pdf-isearch-focus-match next-match)
;; Don't get off track.
(when (or (and (bobp) (not isearch-forward))
(and (eobp) isearch-forward))
- (goto-char (1+ (/ (buffer-size) 2))))
+ (unless pdf-view-roll-minor-mode
+ (goto-char (1+ (/ (buffer-size) 2)))))
;; Signal success to isearch.
+ ;; Moving the point is for `pdf-roll'. It ensures that
+ ;; `re-search-forward' takes us back to the starting point. Otherwise
+ ;; every call to `isearch-repeat' will increment/decrement the point
+ ;; and that causes recentering.
(if isearch-forward
- (re-search-forward ".")
+ (progn (unless (bobp) (forward-char -1))
+ (re-search-forward "."))
+ (unless (eobp) (forward-char 1))
(re-search-backward ".")))
((and (not pdf-isearch-narrow-to-page)
- (not (pdf-isearch-empty-match-p matches)))
+ (not (pdf-isearch-empty-match-p pdf-isearch-current-matches)))
(let ((next-page (pdf-isearch-find-next-matching-page
string pdf-isearch-current-page t)))
(when next-page
@@ -306,12 +319,14 @@ This is a Isearch interface function."
pdf-isearch-current-matches matches
pdf-isearch-current-match match
pdf-isearch-current-page page)
-
(pdf-view-goto-page pdf-isearch-current-page)
- (when pdf-isearch-current-match
- (pdf-isearch-hl-matches
- pdf-isearch-current-match
- pdf-isearch-current-matches))
+ (if pdf-isearch-current-match
+ (pdf-isearch-hl-matches
+ pdf-isearch-current-match
+ pdf-isearch-current-matches
+ nil (image-mode-window-get 'displayed-pages (selected-window)))
+ (when pdf-view-roll-minor-mode
+ (pdf-view-redisplay)))
(image-set-window-hscroll hscroll)
(image-set-window-vscroll vscroll))))
@@ -347,7 +362,8 @@ This is a Isearch interface function."
pdf-isearch-current-match nil
pdf-isearch-current-matches nil
pdf-isearch-current-parameter nil)
- (goto-char (1+ (/ (buffer-size) 2))))
+ (unless pdf-view-roll-minor-mode
+ (goto-char (1+ (/ (buffer-size) 2)))))
(defun pdf-isearch-same-search-p (&optional ignore-search-string-p)
"Return non-nil, if search parameter have not changed.
@@ -385,8 +401,12 @@ 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-current-matches))
+ (pdf-isearch-hl-matches
+ pdf-isearch-current-match
+ pdf-isearch-current-matches
+ nil
+ (or (image-mode-window-get 'displayed-pages (selected-window))
+ (list (pdf-view-current-page)))))
(defun pdf-isearch-update ()
"Update search and redisplay, if necessary."
@@ -412,13 +432,14 @@ there was no previous search, this function returns t."
(message "%s" msg))))
(defun pdf-isearch-empty-match-p (matches)
- (and matches
+ (let ((all-matches (apply #'append matches)))
+ (and all-matches
(cl-every
(lambda (match)
(cl-every (lambda (edges)
(cl-every 'zerop edges))
match))
- matches)))
+ all-matches))))
(defun pdf-isearch-occur ()
"Run `occur' using the last search string or regexp."
@@ -564,10 +585,10 @@ is no such page."
(= incr 8)) ;;Don't bother right away.
(setq reporter
(apply
- 'make-progress-reporter "Searching"
- (if isearch-forward
- (list (car pages) (pdf-cache-number-of-pages) nil 0)
- (list 1 (cdr pages) nil 0)))))
+ 'make-progress-reporter "Searching"
+ (if isearch-forward
+ (list (car pages) (pdf-cache-number-of-pages) nil 0)
+ (list 1 (cdr pages) nil 0)))))
(when reporter
(progress-reporter-update
reporter (if isearch-forward
@@ -674,18 +695,18 @@ it is assumed to be ordered with respect to FORWARD-P."
(let ((matched (apply 'pdf-util-edges-union match)))
(pdf-util-with-edges (matched)
(cl-loop for next in matches do
- (let ((edges (apply 'pdf-util-edges-union next)))
- (pdf-util-with-edges (edges)
- (when (if forward-p
- (or (>= edges-top matched-bot)
- (and (or (>= edges-top matched-top)
- (>= edges-bot matched-bot))
- (>= edges-right matched-right)))
- (or (<= edges-bot matched-top)
- (and (or (<= edges-bot matched-bot)
- (<= edges-top matched-top))
- (<= edges-left matched-left))))
- (cl-return next))))))))
+ (let ((edges (apply 'pdf-util-edges-union next)))
+ (pdf-util-with-edges (edges)
+ (when (if forward-p
+ (or (>= edges-top matched-bot)
+ (and (or (>= edges-top matched-top)
+ (>= edges-bot matched-bot))
+ (>= edges-right matched-right)))
+ (or (<= edges-bot matched-top)
+ (and (or (<= edges-bot matched-bot)
+ (<= edges-top matched-top))
+ (<= edges-left matched-left))))
+ (cl-return next))))))))
@@ -716,41 +737,45 @@ MATCH-BG LAZY-FG LAZY-BG\)."
(car lazy)
(cdr lazy)))))))
-(defvar pdf-isearch--hl-matches-tick 0)
-
-(defun pdf-isearch-hl-matches (current matches &optional occur-hack-p)
+(defun pdf-isearch-hl-matches (current matches &optional occur-hack-p pages)
"Highlighting edges CURRENT and MATCHES."
(cl-check-type current pdf-isearch-match)
- (cl-check-type matches (list-of pdf-isearch-match))
+ (cl-check-type matches (list-of (list-of pdf-isearch-match)))
(cl-destructuring-bind (fg1 bg1 fg2 bg2)
(pdf-isearch-current-colors)
- (let* ((width (car (pdf-view-image-size)))
- (page (pdf-view-current-page))
- (window (selected-window))
+ (let* ((window (selected-window))
+ (pages (or pages
+ (image-mode-window-get 'displayed-pages
(selected-window))
+ (list (pdf-view-current-page))))
(buffer (current-buffer))
- (tick (cl-incf pdf-isearch--hl-matches-tick))
- (pdf-info-asynchronous
- (lambda (status data)
- (when (and (null status)
- (eq tick pdf-isearch--hl-matches-tick)
- (buffer-live-p buffer)
- (window-live-p window)
- (eq (window-buffer window)
- buffer))
- (with-selected-window window
- (when (and (derived-mode-p 'pdf-view-mode)
- (or isearch-mode
- occur-hack-p)
- (eq page (pdf-view-current-page)))
- (pdf-view-display-image
- (pdf-view-create-image data :width width))))))))
- (pdf-info-renderpage-text-regions
- page width t nil nil
- `(,fg1 ,bg1 ,@(pdf-util-scale-pixel-to-relative
- current))
- `(,fg2 ,bg2 ,@(pdf-util-scale-pixel-to-relative
- (apply 'append
- (remove current matches))))))))
+ (tick (cl-incf pdf-isearch--hl-matches-tick)))
+ (dolist (page pages)
+ (let* ((width (car (pdf-view-image-size nil window page)))
+ (pdf-info-asynchronous
+ (lambda (status data)
+ (when (and (null status)
+ (eq tick pdf-isearch--hl-matches-tick)
+ (buffer-live-p buffer)
+ (window-live-p window)
+ (eq (window-buffer window)
+ buffer))
+ (with-selected-window window
+ (when (and (derived-mode-p 'pdf-view-mode)
+ (or isearch-mode occur-hack-p
+ (memq last-command
'(isearch-repeat-forward isearch-repeat-backward)))
+ (or (eq page (pdf-view-current-page))
+ (memq page (image-mode-window-get
'displayed-pages window))))
+ (pdf-view-display-image
+ (pdf-view-create-image data :width width)
+ page window)))))))
+ (pdf-info-renderpage-text-regions
+ page width t nil nil
+ `(,fg1 ,bg1 ,@(pdf-util-scale-pixel-to-relative
+ (when (eq page (pdf-view-current-page window))
+ current)))
+ `(,fg2 ,bg2 ,@(pdf-util-scale-pixel-to-relative
+ (apply 'append
+ (remove current (pop matches)))))))))))
;; * ================================================================== *
diff --git a/lisp/pdf-links.el b/lisp/pdf-links.el
index d54981e0019..3542085471c 100644
--- a/lisp/pdf-links.el
+++ b/lisp/pdf-links.el
@@ -29,6 +29,10 @@
(require 'let-alist)
(require 'org)
+
+
+(declare-function pdf-roll-page-overlay "pdf-roll")
+(declare-function pdf-roll-displayed-pages "pdf-roll")
;;; Code:
@@ -103,7 +107,7 @@ do something with it."
;;;###autoload
(define-minor-mode pdf-links-minor-mode
- "Handle links in PDF documents.\\<pdf-links-minor-mode-map>
+ "Handle links in PDF documents.
If this mode is enabled, most links in the document may be
activated by clicking on them or by pressing \\[pdf-links-action-perform] and
selecting
@@ -151,7 +155,7 @@ links via \\[pdf-links-isearch-link].
(nreverse hotspots)))
(defun pdf-links-action-to-string (link)
- "Return a string representation of ACTION."
+ "Return a string representation of action for LINK."
(let-alist link
(concat
(cl-case .type
@@ -208,17 +212,10 @@ scroll the current page."
(with-selected-window window
(when (derived-mode-p 'pdf-view-mode)
(when (> .page 0)
- (pdf-view-goto-page .page))
+ (pdf-view-goto-page .page window))
(when .top
- ;; Showing the tooltip delays displaying the page for
- ;; some reason (sit-for/redisplay don't help), do it
- ;; later.
- (run-with-idle-timer 0.001 nil
- (lambda ()
- (when (window-live-p window)
- (with-selected-window window
- (when (derived-mode-p 'pdf-view-mode)
- (pdf-util-tooltip-arrow .top)))))))))))
+ (when (derived-mode-p 'pdf-view-mode)
+ (pdf-util-tooltip-arrow .top)))))))
(uri
(funcall pdf-links-browse-uri-function .uri))
(t
@@ -231,44 +228,47 @@ scroll the current page."
See `pdf-links-action-perform' for the interface."
(pdf-util-assert-pdf-window)
- (let* ((links (pdf-cache-pagelinks
- (pdf-view-current-page)))
+ (let* ((win (selected-window))
+ (pages (if pdf-view-roll-minor-mode
+ (reverse (image-mode-window-get 'displayed-pages win))
+ (list (pdf-view-current-page))))
+ (links (mapcar #'pdf-cache-pagelinks pages))
(keys (pdf-links-read-link-action--create-keys
- (length links)))
- (key-strings (mapcar (apply-partially 'apply 'string)
- keys))
- (alist (cl-mapcar 'cons keys links))
- (size (pdf-view-image-size))
+ (apply #'+ (mapcar #'length links))))
+ (alist (cl-mapcar 'cons keys (apply #'append links)))
(colors (pdf-util-face-colors
- 'pdf-links-read-link pdf-view-dark-minor-mode))
- (args (list
- :foreground (car colors)
- :background (cdr colors)
- :formats
- `((?c . ,(lambda (_edges) (pop key-strings)))
- (?P . ,(number-to-string
- (max 1 (* (cdr size)
- pdf-links-convert-pointsize-scale)))))
- :commands pdf-links-read-link-convert-commands
- :apply (pdf-util-scale-relative-to-pixel
- (mapcar (lambda (l) (cdr (assq 'edges l)))
- links)))))
- (unless links
- (error "No links on this page"))
- (unwind-protect
- (let ((image-data
- (pdf-cache-get-image
- (pdf-view-current-page)
- (car size) (car size) 'pdf-links-read-link-action)))
- (unless image-data
- (setq image-data (apply 'pdf-util-convert-page args ))
- (pdf-cache-put-image
- (pdf-view-current-page)
- (car size) image-data 'pdf-links-read-link-action))
- (pdf-view-display-image
- (create-image image-data (pdf-view-image-type) t))
- (pdf-links-read-link-action--read-chars prompt alist))
- (pdf-view-redisplay))))
+ 'pdf-links-read-link pdf-view-dark-minor-mode)))
+ (if (not links)
+ (error "No links on displayed pages")
+ (unwind-protect
+ (progn
+ (dolist (page pages)
+ (let* ((image (or (overlay-get (pdf-roll-page-overlay page win)
'display)
+ (pdf-view-current-image)))
+ (image (or (assoc 'image image) image))
+ (height (cdr (image-size image t)))
+ (orig-image (create-image (plist-get (cdr image) :data)
+ (pdf-view-image-type) t)))
+ (pdf-view-display-image
+ (create-image (pdf-util-convert-image
+ orig-image
+ :foreground (car colors)
+ :background (cdr colors)
+ :formats
+ `((?c . ,(lambda (_edges) (apply #'string (pop
keys))))
+ (?P . ,(number-to-string
+ (max 1 (* height
+
pdf-links-convert-pointsize-scale)))))
+ :commands pdf-links-read-link-convert-commands
+ :apply (pdf-util-scale
+ (mapcar (lambda (l) (cdr (assq 'edges
l)))
+ (pop links))
+ (image-size orig-image t)))
+ (pdf-view-image-type) t
+ :height height)
+ page win)))
+ (pdf-links-read-link-action--read-chars prompt alist))
+ (pdf-view-redisplay)))))
(defun pdf-links-read-link-action--read-chars (prompt alist)
(catch 'done
diff --git a/lisp/pdf-occur.el b/lisp/pdf-occur.el
index 47bf2d29d03..ea5fa1740ee 100644
--- a/lisp/pdf-occur.el
+++ b/lisp/pdf-occur.el
@@ -629,9 +629,9 @@ matches linked with PAGE."
(setq pdf-occur-number-of-matches 0)
(setq pdf-occur-search-pages-left
(apply #'+ (mapcar (lambda (elt)
- (1+ (- (cdr (nth 1 elt))
- (car (nth 1 elt)))))
- batches)))))
+ (1+ (- (cdr (nth 1 elt))
+ (car (nth 1 elt)))))
+ batches)))))
diff --git a/lisp/pdf-sync.el b/lisp/pdf-sync.el
index 68de3b90598..18fd6e00e22 100644
--- a/lisp/pdf-sync.el
+++ b/lisp/pdf-sync.el
@@ -277,15 +277,18 @@ Has no effect if `pdf-sync-backward-use-heuristic' is
nil."
(xy (posn-object-x-y posn)))
(unless image
(error "Outside of image area"))
- (pdf-sync-backward-search (car xy) (cdr xy))))
+ (pdf-sync-backward-search
+ (car xy) (cdr xy)
+ (and (bound-and-true-p pdf-view-roll-minor-mode)
+ (/ (+ (posn-point posn) 3) 4)))))
-(defun pdf-sync-backward-search (x y)
- "Go to the source corresponding to image coordinates X, Y.
+(defun pdf-sync-backward-search (x y &optional page)
+ "Go to the source corresponding to image coordinates X, Y on PAGE.
Try to find the exact position, if
`pdf-sync-backward-use-heuristic' is non-nil."
(cl-destructuring-bind (source finder)
- (pdf-sync-backward-correlate x y)
+ (pdf-sync-backward-correlate x y page)
(pop-to-buffer (or (find-buffer-visiting source)
(find-file-noselect source))
pdf-sync-backward-display-action)
@@ -293,8 +296,8 @@ Try to find the exact position, if
(funcall finder)
(run-hooks 'pdf-sync-backward-hook)))
-(defun pdf-sync-backward-correlate (x y)
- "Find the source corresponding to image coordinates X, Y.
+(defun pdf-sync-backward-correlate (x y &optional page)
+ "Find the source corresponding to image coordinates X, Y on PAGE.
Returns a list \(SOURCE FINDER\), where SOURCE is the name of the
TeX file and FINDER a function of zero arguments which, when
@@ -303,7 +306,7 @@ point to the correct position."
(pdf-util-assert-pdf-window)
(let ((size (pdf-view-image-size))
- (page (pdf-view-current-page)))
+ (page (or page (pdf-view-current-page))))
(setq x (/ x (float (car size)))
y (/ y (float (cdr size))))
(let-alist (pdf-info-synctex-backward-search page x y)
@@ -656,7 +659,7 @@ Needs to have `pdf-sync-backward-debug-minor-mode' enabled."
buffer pdf-sync-forward-display-action)
(pdf-util-assert-pdf-window)
(when page
- (pdf-view-goto-page page)
+ (pdf-view-goto-page page (selected-window))
(when y1
(let ((top (* y1 (cdr (pdf-view-image-size)))))
(pdf-util-tooltip-arrow (round top))))))
diff --git a/lisp/pdf-util.el b/lisp/pdf-util.el
index 5c0e50d6450..8886de3c7a9 100644
--- a/lisp/pdf-util.el
+++ b/lisp/pdf-util.el
@@ -28,6 +28,7 @@
(require 'pdf-macs)
(require 'cl-lib)
(require 'format-spec)
+(require 'image-mode)
(require 'faces)
;; These functions are only used after a PdfView window was asserted,
@@ -40,6 +41,7 @@
(declare-function image-set-window-vscroll "image-mode")
(declare-function image-set-window-hscroll "image-mode")
+(defvar pdf-view-roll-minor-mode)
;; * ================================================================== *
@@ -161,7 +163,7 @@ See also `pdf-util-scale'."
The result depends on the currently displayed page in WINDOW.
See also `pdf-util-scale'."
- (pdf-util-assert-pdf-window window)
+ (when displayed-p (pdf-util-assert-pdf-window window))
(pdf-util-scale-to
list-of-pixel-edges
(pdf-view-image-size displayed-p window)
@@ -314,15 +316,19 @@ depending on the input."
"Return the visible region of the image in WINDOW.
Returns a list of pixel edges."
- (pdf-util-assert-pdf-window)
+ (when displayed-p (pdf-util-assert-pdf-window window))
(let* ((edges (window-inside-pixel-edges window))
(isize (pdf-view-image-size displayed-p window))
(offset (if displayed-p
`(0 . 0)
(pdf-view-image-offset window)))
- (hscroll (* (window-hscroll window)
+ (hscroll (* (if displayed-p
+ (window-hscroll window)
+ (or (image-mode-window-get 'hscroll window) 0))
(frame-char-width (window-frame window))))
- (vscroll (window-vscroll window t))
+ (vscroll (if displayed-p
+ (window-vscroll window t)
+ (or (image-mode-window-get 'vscroll window) 0)))
(x0 (+ hscroll (car offset)))
(y0 (+ vscroll (cdr offset)))
(x1 (min (car isize)
@@ -386,40 +392,46 @@ needed.
Note: For versions of emacs before 27 this will return lines instead of
pixels. This is because of a change that occurred to `image-mode' in 27."
(pdf-util-assert-pdf-window)
- (let* ((win (window-inside-pixel-edges))
- (image-height (cdr (pdf-view-image-size t)))
- (image-top (window-vscroll nil t))
- (edges (pdf-util-translate
- edges
- (pdf-view-image-offset) t)))
- (pdf-util-with-edges (win edges)
- (let* ((context-pixel (or context-pixel
- (* next-screen-context-lines
- (frame-char-height))))
- ;;Be careful not to modify edges.
- (edges-top (- edges-top context-pixel))
- (edges-bot (+ edges-bot context-pixel))
- (vscroll
- (cond ((< edges-top image-top)
- (max 0 (if eager-p
- (- edges-bot win-height)
- edges-top)))
- ((> (min image-height
- edges-bot)
- (+ image-top win-height))
- (min (- image-height win-height)
- (if eager-p
- edges-top
- (- edges-bot win-height)))))))
-
-
- (when vscroll
- (round
- ;; `image-set-window-vscroll' changed in version 27 to using
- ;; pixels, not lines.
- (if (version< emacs-version "27")
- (/ vscroll (float (frame-char-height)))
- vscroll)))))))
+ (if pdf-view-roll-minor-mode
+ (max 0 (- (nth 1 edges)
+ (or context-pixel
+ (* next-screen-context-lines (frame-char-height)))))
+ (let* ((win (window-inside-pixel-edges))
+ (image-height (cdr (pdf-view-image-size
+ (unless pdf-view-roll-minor-mode
+ t))))
+ (image-top (window-vscroll nil t))
+ (edges (pdf-util-translate
+ edges
+ (pdf-view-image-offset) t)))
+ (pdf-util-with-edges (win edges)
+ (let* ((context-pixel (or context-pixel
+ (* next-screen-context-lines
+ (frame-char-height))))
+ ;;Be careful not to modify edges.
+ (edges-top (- edges-top context-pixel))
+ (edges-bot (+ edges-bot context-pixel))
+ (vscroll
+ (cond ((< edges-top image-top)
+ (max 0 (if eager-p
+ (- edges-bot win-height)
+ edges-top)))
+ ((> (min image-height
+ edges-bot)
+ (+ image-top win-height))
+ (min (- image-height win-height)
+ (if eager-p
+ edges-top
+ (- edges-bot win-height)))))))
+
+
+ (when vscroll
+ (round
+ ;; `image-set-window-vscroll' changed in version 27 to using
+ ;; pixels, not lines.
+ (if (version< emacs-version "27")
+ (/ vscroll (float (frame-char-height)))
+ vscroll))))))))
(defun pdf-util-scroll-to-edges (edges &optional eager-p)
"Scroll window such that image EDGES are visible.
@@ -639,10 +651,9 @@ string."
(cdr (pdf-view-image-offset))
(window-vscroll nil t)
(frame-char-height))))
- (when (overlay-get (pdf-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 t))) 2))))
+ (let* ((e (window-inside-pixel-edges))
+ (xw (pdf-util-with-edges (e) e-width)))
+ (cl-incf dx (/ (- xw (car (pdf-view-image-size t))) 2)))
(pdf-util-tooltip-in-window
(propertize
" " 'display (propertize
@@ -787,8 +798,8 @@ respective sequence."
(cl-macrolet ((make-matrix (rows columns)
`(apply #'vector
- (cl-loop for i from 1 to ,rows
- collect (make-vector ,columns nil))))
+ (cl-loop for i from 1 to ,rows
+ collect (make-vector ,columns nil))))
(mset (matrix row column newelt)
`(aset (aref ,matrix ,row) ,column ,newelt))
(mref (matrix row column)
@@ -803,21 +814,21 @@ respective sequence."
(if (equal a b) 1 -1)))))
(cl-loop for i from 0 to len1 do
- (mset d i 0 (- i)))
+ (mset d i 0 (- i)))
(cl-loop for j from 0 to len2 do
- (mset d 0 j (if suffix-p 0 (- j))))
+ (mset d 0 j (if suffix-p 0 (- j))))
(cl-loop for i from 1 to len1 do
- (cl-loop for j from 1 to len2 do
- (let ((max (max
- (1- (mref d (1- i) j))
- (+ (mref d i (1- j))
- (if (and prefix-p (= i len1)) 0 -1))
- (+ (mref d (1- i) (1- j))
- (funcall similarity-fn
- (elt seq1 (1- i))
- (elt seq2 (1- j)))))))
- (mset d i j max))))
+ (cl-loop for j from 1 to len2 do
+ (let ((max (max
+ (1- (mref d (1- i) j))
+ (+ (mref d i (1- j))
+ (if (and prefix-p (= i len1)) 0 -1))
+ (+ (mref d (1- i) (1- j))
+ (funcall similarity-fn
+ (elt seq1 (1- i))
+ (elt seq2 (1- j)))))))
+ (mset d i j max))))
(let ((i len1)
(j len2)
@@ -1042,8 +1053,8 @@ Returns the convert process."
(set-process-sentinel proc callback))
proc)))
-(defun pdf-util-convert-page (&rest specs)
- "Convert image of current page according to SPECS.
+(defun pdf-util-convert-image (image &rest specs)
+ "Convert IMAGE page according to SPECS.
Return the converted PNG image as a string. See also
`pdf-util-convert'."
@@ -1053,7 +1064,7 @@ Return the converted PNG image as a string. See also
(out-file (make-temp-file "pdf-util-convert" nil ".png")))
(unwind-protect
(let ((image-data
- (plist-get (cdr (pdf-view-current-image)) :data)))
+ (plist-get (cdr image) :data)))
(with-temp-file in-file
(set-buffer-multibyte nil)
(set-buffer-file-coding-system 'binary)
@@ -1066,6 +1077,14 @@ Return the converted PNG image as a string. See also
(when (file-exists-p out-file)
(delete-file out-file)))))
+(defun pdf-util-convert-page (&rest specs)
+ "Convert image of current page according to SPECS.
+
+Return the converted PNG image as a string. See also
+`pdf-util-convert'."
+
+ (pdf-util-assert-pdf-window)
+ (apply #'pdf-util-convert-image (pdf-view-current-image) specs))
(defun pdf-util-convert--create-commands (spec)
(let ((fg "red")
diff --git a/lisp/pdf-view.el b/lisp/pdf-view.el
index 620e5269d77..d1ff32f9b60 100644
--- a/lisp/pdf-view.el
+++ b/lisp/pdf-view.el
@@ -36,6 +36,18 @@
(declare-function cua-copy-region "cua-base")
(declare-function pdf-tools-pdf-buffer-p "pdf-tools")
+
+(declare-function pdf-roll-scroll-forward "pdf-roll")
+(declare-function pdf-roll-scroll-backward "pdf-roll")
+(declare-function pdf-roll-next-page "pdf-roll")
+(declare-function pdf-roll-redisplay "pdf-roll")
+(declare-function pdf-roll-pre-redisplay "pdf-roll")
+(declare-function pdf-roll-page-overlay "pdf-roll")
+(declare-function pdf-roll-page-at-current-pos "pdf-roll")
+(declare-function pdf-roll-display-image "pdf-roll")
+
+(defvar pdf-view-roll-minor-mode nil)
+
;; * ================================================================== *
;; * Customizations
@@ -252,7 +264,7 @@ Must be one of `glyph', `word', or `line'."
;; * ================================================================== *
(defvar-local pdf-view-active-region nil
- "The active region as a list of edges.
+ "The active region as a cons cell of page and list of edges.
Edge values are relative coordinates.")
@@ -551,7 +563,8 @@ PNG images in Emacs buffers."
This may be different from variable `buffer-file-name' when
operating on a local copy of a remote file."
(or pdf-view--buffer-file-name
- (buffer-file-name)))
+ (buffer-file-name)
+ (buffer-file-name (buffer-base-buffer))))
(defun pdf-view--write-contents-function ()
"Function for `write-contents-functions' to save the buffer."
@@ -734,7 +747,10 @@ windows."
(setf (pdf-view-current-page window) page)
(run-hooks 'pdf-view-change-page-hook))
(when (window-live-p window)
- (pdf-view-redisplay window))
+ (image-set-window-vscroll 0)
+ (if pdf-view-roll-minor-mode
+ (pdf-roll-pre-redisplay window)
+ (pdf-view-redisplay window)))
(when changing-p
(pdf-view-deactivate-region)
(force-mode-line-update)
@@ -860,7 +876,7 @@ to previous page only on typing DEL (ARG is nil)."
(image-set-window-hscroll hscroll)))
(image-scroll-down arg)))
-(defun pdf-view-next-line-or-next-page (&optional arg)
+(defun pdf-view--next-line-or-next-page (&optional arg)
"Scroll upward by ARG lines if possible, else go to the next page.
When `pdf-view-continuous' is non-nil, scrolling a line upward
@@ -878,7 +894,13 @@ at the bottom edge of the page moves to the next page."
(image-set-window-hscroll hscroll)))
(image-next-line arg)))
-(defun pdf-view-previous-line-or-previous-page (&optional arg)
+(defun pdf-view-next-line-or-next-page (&optional arg)
+ (interactive "p")
+ (if pdf-view-roll-minor-mode
+ (dotimes (_ (or arg 1)) (pdf-roll-scroll-forward))
+ (pdf-view--next-line-or-next-page arg)))
+
+(defun pdf-view--previous-line-or-previous-page (&optional arg)
"Scroll downward by ARG lines if possible, else go to the previous page.
When `pdf-view-continuous' is non-nil, scrolling a line downward
@@ -896,6 +918,12 @@ at the top edge of the page moves to the previous page."
(image-set-window-hscroll hscroll)))
(image-previous-line arg)))
+(defun pdf-view-previous-line-or-previous-page (&optional arg)
+ (interactive "p")
+ (if pdf-view-roll-minor-mode
+ (dotimes (_ (or arg 1)) (pdf-roll-scroll-backward))
+ (pdf-view--previous-line-or-previous-page arg)))
+
(defun pdf-view-goto-label (label)
"Go to the page corresponding to LABEL.
@@ -1119,17 +1147,23 @@ See also `pdf-view-use-imagemagick'."
:map hotspots
:pointer 'arrow)))
-(defun pdf-view-image-size (&optional displayed-p window)
- ;; TODO: add WINDOW to docstring.
- "Return the size in pixel of the current image.
+(defun pdf-view-image-size (&optional displayed-p window page)
+ "Return the size in pixel of the current image in WINDOW.
If DISPLAYED-P is non-nil, return the size of the displayed
-image. These values may be different, if slicing is used."
- (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)))
+image. These values may be different, if slicing is used.
+
+If PAGE is non-nil return its size instead of current page."
+ (let ((display-prop (if pdf-view-roll-minor-mode
+ (progn (setq window (if (windowp window) window
(selected-window)))
+ (setq page (or page (pdf-view-current-page
window)))
+ (unless (memq page (image-mode-window-get
'displayed-pages window))
+ (pdf-view-display-page page window))
+ (overlay-get (pdf-roll-page-overlay page
window) 'display))
+ (image-get-display-property))))
+ (if displayed-p
+ (image-display-size display-prop t)
+ (image-size display-prop t))))
(defun pdf-view-image-offset (&optional window)
;; TODO: add WINDOW to docstring.
@@ -1149,47 +1183,49 @@ It is equal to \(LEFT . TOP\) of the current slice in
pixel."
"Display page PAGE in WINDOW."
(setf (pdf-view-window-needs-redisplay window) nil)
(pdf-view-display-image
- (pdf-view-create-page page window)
- window))
+ (pdf-view-create-page page window) page window))
-(defun pdf-view-display-image (image &optional window inhibit-slice-p)
+(defun pdf-view-display-image (image page &optional window inhibit-slice-p)
;; TODO: write documentation!
- (let ((ol (pdf-view-current-overlay window)))
- (when (window-live-p (overlay-get ol 'window))
- (let* ((size (image-size image t))
- (slice (if (not inhibit-slice-p)
- (pdf-view-current-slice window)))
- (displayed-width (floor
- (if slice
- (* (nth 2 slice)
- (car (image-size image)))
- (car (image-size image))))))
- (setf (pdf-view-current-image window) image)
- (move-overlay ol (point-min) (point-max))
- ;; In case the window is wider than the image, center the image
- ;; horizontally.
- (overlay-put ol 'before-string
- (when (> (window-width window)
- displayed-width)
- (propertize " " 'display
- `(space :align-to
- ,(/ (- (window-width window)
- displayed-width) 2)))))
- (overlay-put ol 'display
- (if slice
- (list (cons 'slice
- (pdf-util-scale slice size 'round))
- image)
- image))
- (let* ((win (overlay-get ol 'window))
- (hscroll (image-mode-window-get 'hscroll win))
- (vscroll (image-mode-window-get 'vscroll win)))
- ;; Reset scroll settings, in case they were changed.
- (if hscroll (set-window-hscroll win hscroll))
- (if vscroll (set-window-vscroll
- win vscroll
pdf-view-have-image-mode-pixel-vscroll)))))))
-
-(defun pdf-view-redisplay (&optional window)
+ (if pdf-view-roll-minor-mode
+ (pdf-roll-display-image
+ image page (or window (selected-window)) inhibit-slice-p)
+ (let ((ol (pdf-view-current-overlay window)))
+ (when (window-live-p (overlay-get ol 'window))
+ (let* ((size (image-size image t))
+ (slice (if (not inhibit-slice-p)
+ (pdf-view-current-slice window)))
+ (displayed-width (floor
+ (if slice
+ (* (nth 2 slice)
+ (car (image-size image)))
+ (car (image-size image))))))
+ (setf (pdf-view-current-image window) image)
+ (move-overlay ol (point-min) (point-max))
+ ;; In case the window is wider than the image, center the image
+ ;; horizontally.
+ (overlay-put ol 'before-string
+ (when (> (window-width window)
+ displayed-width)
+ (propertize " " 'display
+ `(space :align-to
+ ,(/ (- (window-width window)
+ displayed-width) 2)))))
+ (overlay-put ol 'display
+ (if slice
+ (list (cons 'slice
+ (pdf-util-scale slice size 'round))
+ image)
+ image))
+ (let* ((win (overlay-get ol 'window))
+ (hscroll (image-mode-window-get 'hscroll win))
+ (vscroll (image-mode-window-get 'vscroll win)))
+ ;; Reset scroll settings, in case they were changed.
+ (if hscroll (set-window-hscroll win hscroll))
+ (if vscroll (set-window-vscroll
+ win vscroll
pdf-view-have-image-mode-pixel-vscroll))))))))
+
+(defun pdf-view--redisplay (&optional window)
"Redisplay page in WINDOW.
If WINDOW is t, redisplay pages in all windows."
@@ -1210,12 +1246,18 @@ If WINDOW is t, redisplay pages in all windows."
(setf (pdf-view-window-needs-redisplay window) t)))))
(force-mode-line-update)))
+(defun pdf-view-redisplay (&optional window)
+ (if pdf-view-roll-minor-mode
+ (pdf-roll-redisplay window)
+ (pdf-view--redisplay window)))
+
(defun pdf-view-redisplay-pages (&rest pages)
"Redisplay PAGES in all windows."
(pdf-util-assert-pdf-buffer)
(dolist (window (get-buffer-window-list nil nil t))
- (when (memq (pdf-view-current-page window)
- pages)
+ (when (cl-some (lambda (page) (memq page pages))
+ (or (image-mode-window-get 'displayed-pages window)
+ (list (pdf-view-current-page window))))
(pdf-view-redisplay window))))
(defun pdf-view-maybe-redisplay-resized-windows ()
@@ -1261,7 +1303,7 @@ If WINDOW is t, redisplay pages in all windows."
;; `window' property is only effective if its value is a window).
(cl-assert (eq t (car winprops)))
(delete-overlay ol))
- (image-mode-window-put 'overlay ol winprops)
+ (image-mode-window-put 'overlay ol)
;; Clean up some overlays.
(dolist (ov (overlays-in (point-min) (point-max)))
(when (and (windowp (overlay-get ov 'window))
@@ -1406,7 +1448,7 @@ current theme's colors."
(pdf-util-assert-pdf-buffer)
(pdf-cache-clear-images)
(when get-theme
- (pdf-view-set-theme-background))
+ (pdf-view-set-theme-background))
(pdf-view-redisplay t))
(define-minor-mode pdf-view-themed-minor-mode
@@ -1487,7 +1529,7 @@ supersede hotspots in lower ones."
(setq deactivate-mark nil))
(defun pdf-view-active-region (&optional deactivate-p)
- "Return the active region, a list of edges.
+ "Return the active region, as a cons cell of page number and list of edges.
Deactivate the region if DEACTIVATE-P is non-nil."
(pdf-view-assert-active-region)
@@ -1537,9 +1579,14 @@ Stores the region in `pdf-view-active-region'."
(setq begin-inside-image-p nil)
(posn-x-y pos)))
(abs-begin (posn-x-y pos))
+ (page (if pdf-view-roll-minor-mode
+ (/ (+ 3 (posn-point pos)) 4)
+ (pdf-view-current-page)))
+ (margin (frame-char-height))
(selection-style (or selection-style pdf-view-selection-style))
pdf-view-continuous
region)
+ (setq pdf-view-active-region (list page))
(when (pdf-util-track-mouse-dragging (event 0.05)
(let* ((pos (event-start event))
(end (posn-object-x-y pos))
@@ -1579,23 +1626,33 @@ Stores the region in `pdf-view-active-region'."
(+ (car begin) (car dxy))))
(max 0 (min (cdr size)
(+ (cdr begin) (cdr
dxy)))))))))
- (let ((iregion (if rectangle-p
- (list (min (car begin) (car end))
- (min (cdr begin) (cdr end))
- (max (car begin) (car end))
- (max (cdr begin) (cdr end)))
- (list (car begin) (cdr begin)
- (car end) (cdr end)))))
+ (let* ((iregion (if rectangle-p
+ (list (min (car begin) (car end))
+ (min (cdr begin) (cdr end))
+ (max (car begin) (car end))
+ (max (cdr begin) (cdr end)))
+ (list (car begin) (cdr begin)
+ (car end) (cdr end))))
+ (y (cdr (posn-x-y pos)))
+ (dy (- y (cdr abs-begin))))
(setq region
(pdf-util-scale-pixel-to-relative iregion))
(pdf-view-display-region
- (cons region pdf-view-active-region)
+ (cons page (cons region (cdr pdf-view-active-region)))
rectangle-p
selection-style)
- (pdf-util-scroll-to-edges iregion)))))
- (setq pdf-view-active-region
- (append pdf-view-active-region
- (list region)))
+ (if pdf-view-roll-minor-mode
+ (cond
+ ((and (> dy 0) (< (- (window-text-height window t) y)
margin))
+ (pdf-roll-scroll-forward
+ (min margin
+ (or (nth 3 (pos-visible-in-window-p (posn-point
pos) window t)) 0))))
+ ((and (< dy 0) (< (- y (window-header-line-height
window)) margin))
+ (pdf-roll-scroll-backward
+ (min margin
+ (or (nth 2 (pos-visible-in-window-p (posn-point
pos) window t)) 0)))))
+ (pdf-util-scroll-to-edges iregion))))))
+ (cl-callf append (cdr pdf-view-active-region) (list region))
(pdf-view--push-mark))))
(defun pdf-view-mouse-extend-region (event)
@@ -1622,18 +1679,19 @@ This is more useful for commands like
(let ((colors (pdf-util-face-colors
(if rectangle-p 'pdf-view-rectangle 'pdf-view-region)
(bound-and-true-p pdf-view-dark-minor-mode)))
- (page (pdf-view-current-page))
+ (page (car region))
(width (car (pdf-view-image-size))))
(pdf-view-display-image
(pdf-view-create-image
(if rectangle-p
(pdf-info-renderpage-highlight
page width nil
- `(,(car colors) ,(cdr colors) 0.35 ,@region))
+ `(,(car colors) ,(cdr colors) 0.35 ,@(cdr region)))
(pdf-info-renderpage-text-regions
page width nil selection-style nil
- `(,(car colors) ,(cdr colors) ,@region)))
- :width width))))
+ `(,(car colors) ,(cdr colors) ,@(cdr region))))
+ :width width)
+ (when pdf-view-roll-minor-mode page))))
(defun pdf-view-kill-ring-save ()
"Copy the region to the `kill-ring'."
@@ -1648,7 +1706,7 @@ This is more useful for commands like
(interactive)
(pdf-view-deactivate-region)
(setq pdf-view-active-region
- (list (list 0 0 1 1)))
+ (cons (pdf-view-current-page) (list (list 0 0 1 1))))
(pdf-view--push-mark)
(pdf-view-display-region))
@@ -1658,10 +1716,10 @@ This is more useful for commands like
(mapcar
(lambda (edges)
(pdf-info-gettext
- (pdf-view-current-page)
+ (car pdf-view-active-region)
edges
pdf-view-selection-style))
- pdf-view-active-region))
+ (cdr pdf-view-active-region)))
(defun pdf-view-extract-region-image (regions &optional page size
output-buffer no-display-p)
@@ -1683,11 +1741,11 @@ the `convert' program is used."
(interactive
(list (if (pdf-view-active-region-p)
(pdf-view-active-region t)
- '((0 0 1 1)))))
+ '(,(pdf-view-current-page) (0 0 1 1)))))
(unless page
- (setq page (pdf-view-current-page)))
+ (setq page (car regions)))
(unless size
- (setq size (pdf-view-image-size)))
+ (setq size (pdf-view-image-size nil nil page)))
(unless output-buffer
(setq output-buffer (get-buffer-create "*PDF image*")))
(let* ((images (mapcar (lambda (edges)
@@ -1699,7 +1757,7 @@ the `convert' program is used."
:crop-to edges)
nil file nil 'no-message)
file))
- regions))
+ (cdr regions)))
result)
(unwind-protect
(progn
@@ -1758,23 +1816,25 @@ the selection styles."
The optional, boolean args exclude certain attributes."
(or pdf-view--bookmark-to-restore
- (let ((displayed-p (eq (current-buffer)
- (window-buffer))))
+ (let ((win (car (cl-find-if #'window-live-p image-mode-winprops-alist
+ :key #'car-safe))))
(cons (buffer-name)
- (append (bookmark-make-record-default nil t 1)
+ (append (bookmark-make-record-default
+ nil t (if pdf-view-roll-minor-mode (point) 1))
`(,(unless no-page
- (cons 'page (pdf-view-current-page)))
+ (cons 'page (pdf-view-current-page win)))
,(unless no-slice
- (cons 'slice (and displayed-p
- (pdf-view-current-slice))))
+ (cons 'slice (and win (pdf-view-current-slice
win))))
,(unless no-size
(cons 'size pdf-view-display-size))
,(unless no-origin
(cons 'origin
- (and displayed-p
- (let ((edges
(pdf-util-image-displayed-edges nil t)))
+ (and win
+ (let* ((edges
(pdf-util-image-displayed-edges
+ win (eq (window-buffer
win) (current-buffer)))))
(pdf-util-scale-pixel-to-relative
- (cons (car edges) (cadr edges)) nil
t)))))
+ (cons (car edges) (cadr edges)) nil
+ (eq (current-buffer) (window-buffer))
win)))))
(handler . pdf-view-bookmark-jump-handler)))))))
;;;###autoload
@@ -1813,7 +1873,6 @@ See also `pdf-view-bookmark-make-record'."
(when-let ((origin (bookmark-prop-get
pdf-view--bookmark-to-restore 'origin))
(size (pdf-view-image-size t win)))
-
(image-set-window-hscroll
(round (/ (* (car origin) (car size))
(frame-char-width))))