comparison lisp/image-mode.el @ 91999:a58e06f6236c

Extend [hv]scroll support to per-window properties. (image-mode-current-vscroll, image-mode-current-hscroll): Remove. (image-mode-winprops-alist): New var to replace them. (image-mode-new-window-functions): New hook. (image-mode-winprops, image-mode-window-get, image-mode-window-put): New funs. (image-set-window-vscroll, image-set-window-hscroll): Use them. Remove the `window' argument, update callers. (image-mode-reapply-winprops): Rename image-reset-current-vhscroll. Use the new functions. (image-mode-reapply-winprops): New fun. (image-mode): Use it.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Thu, 21 Feb 2008 03:27:15 +0000
parents e788f311729d
children a7a0e6010c46
comparison
equal deleted inserted replaced
91998:eb8f54e30990 91999:a58e06f6236c
33 ;; the image data to the new file. 33 ;; the image data to the new file.
34 34
35 ;;; Code: 35 ;;; Code:
36 36
37 (require 'image) 37 (require 'image)
38 (eval-when-compile (require 'cl))
38 39
39 ;;;###autoload (push '("\\.jpe?g\\'" . image-mode) auto-mode-alist) 40 ;;;###autoload (push '("\\.jpe?g\\'" . image-mode) auto-mode-alist)
40 ;;;###autoload (push '("\\.png\\'" . image-mode) auto-mode-alist) 41 ;;;###autoload (push '("\\.png\\'" . image-mode) auto-mode-alist)
41 ;;;###autoload (push '("\\.gif\\'" . image-mode) auto-mode-alist) 42 ;;;###autoload (push '("\\.gif\\'" . image-mode) auto-mode-alist)
42 ;;;###autoload (push '("\\.tiff?\\'" . image-mode) auto-mode-alist) 43 ;;;###autoload (push '("\\.tiff?\\'" . image-mode) auto-mode-alist)
46 ;;;###autoload (push '("\\.x[bp]m\\'" . image-mode-maybe) auto-mode-alist) 47 ;;;###autoload (push '("\\.x[bp]m\\'" . image-mode-maybe) auto-mode-alist)
47 48
48 ;;;###autoload (push '("\\.svgz?\\'" . xml-mode) auto-mode-alist) 49 ;;;###autoload (push '("\\.svgz?\\'" . xml-mode) auto-mode-alist)
49 ;;;###autoload (push '("\\.svgz?\\'" . image-mode-maybe) auto-mode-alist) 50 ;;;###autoload (push '("\\.svgz?\\'" . image-mode-maybe) auto-mode-alist)
50 51
51 ;;; Image scrolling functions 52 ;;; Image mode window-info management.
52 53
53 (defvar image-mode-current-vscroll nil 54 (defvar image-mode-winprops-alist t)
54 "An alist with elements (WINDOW . VSCROLL).") 55 (make-variable-buffer-local 'image-mode-winprops-alist)
55 (make-variable-buffer-local 'image-mode-current-vscroll) 56
56 57 (defvar image-mode-new-window-functions nil
57 (defvar image-mode-current-hscroll nil 58 "Special hook run when image data is requested in a new window.
58 "An alist with elements (WINDOW . HSCROLL).") 59 It is called with one argument, the initial WINPROPS.")
59 (make-variable-buffer-local 'image-mode-current-hscroll) 60
60 61 (defun image-mode-winprops (&optional window)
61 (defun image-set-window-vscroll (window vscroll &optional pixels-p) 62 "Return winprops of WINDOW.
62 (setq image-mode-current-vscroll 63 A winprops object has the shape (WINDOW . ALIST)."
63 (cons (cons window vscroll) 64 (unless window (setq window (selected-window)))
64 (delq (assq window image-mode-current-vscroll) 65 (let ((winprops (assq window image-mode-winprops-alist)))
65 image-mode-current-vscroll))) 66 ;; For new windows, set defaults from the latest.
66 (set-window-vscroll window vscroll pixels-p)) 67 (unless winprops
67 68 (setq winprops (cons window
68 (defun image-set-window-hscroll (window ncol) 69 (copy-alist (cdar image-mode-winprops-alist))))
69 (setq image-mode-current-hscroll 70 (run-hook-with-args 'image-mode-new-window-functions winprops))
70 (cons (cons window ncol) 71 ;; Move window to front.
71 (delq (assq window image-mode-current-hscroll) 72 (setq image-mode-winprops-alist
72 image-mode-current-hscroll))) 73 (cons winprops (delq winprops image-mode-winprops-alist)))
73 (set-window-hscroll window ncol)) 74 winprops))
74 75
75 (defun image-reset-current-vhscroll () 76 (defun image-mode-window-get (prop &optional winprops)
77 (unless (consp winprops) (setq winprops (image-mode-winprops winprops)))
78 (cdr (assq prop (cdr winprops))))
79
80 (defsetf image-mode-window-get (prop &optional winprops) (val)
81 `(image-mode-window-put ,prop ,val ,winprops))
82
83 (defun image-mode-window-put (prop val &optional winprops)
84 (unless (consp winprops) (setq winprops (image-mode-winprops winprops)))
85 (setcdr winprops (cons (cons prop val)
86 (delq (assq prop (cdr winprops)) (cdr winprops)))))
87
88 (defun image-set-window-vscroll (vscroll)
89 (setf (image-mode-window-get 'vscroll) vscroll)
90 (set-window-vscroll (selected-window) vscroll))
91
92 (defun image-set-window-hscroll (ncol)
93 (setf (image-mode-window-put 'hscroll) ncol)
94 (set-window-hscroll (selected-window) ncol))
95
96 (defun image-mode-reapply-winprops ()
76 (walk-windows 97 (walk-windows
77 (lambda (win) 98 (lambda (win)
78 (with-current-buffer (window-buffer win) 99 (with-current-buffer (window-buffer win)
79 ;; When set-window-buffer, set hscroll and vscroll to what they were 100 ;; When set-window-buffer, set hscroll and vscroll to what they were
80 ;; last time the image was displayed in this window. If it's the first 101 ;; last time the image was displayed in this window.
81 ;; time it's displayed in this window, use the most recent setting. 102 (when (listp image-mode-winprops-alist)
82 (when image-mode-current-hscroll 103 (let* ((winprops (image-mode-winprops win))
83 (set-window-hscroll win (cdr (or (assoc win image-mode-current-hscroll) 104 (hscroll (image-mode-window-get 'hscroll winprops))
84 (car image-mode-current-hscroll))))) 105 (vscroll (image-mode-window-get 'vscroll winprops)))
85 (when image-mode-current-vscroll 106 (if hscroll (set-window-hscroll win hscroll))
86 (set-window-vscroll win (cdr (or (assoc win image-mode-current-vscroll) 107 (if vscroll (set-window-vscroll win vscroll))))))
87 (car image-mode-current-vscroll)))))))
88 'nomini 108 'nomini
89 (selected-frame))) 109 (selected-frame)))
110
111 (defun image-mode-setup-winprops ()
112 ;; Record current scroll settings.
113 (unless (listp image-mode-winprops-alist)
114 (setq image-mode-winprops-alist nil))
115 (add-hook 'window-configuration-change-hook
116 'image-mode-reapply-winprops nil t))
117
118 ;;; Image scrolling functions
90 119
91 (defun image-get-display-property () 120 (defun image-get-display-property ()
92 (get-char-property (point-min) 'display 121 (get-char-property (point-min) 'display
93 ;; There might be different images for different displays. 122 ;; There might be different images for different displays.
94 (if (eq (window-buffer) (current-buffer)) 123 (if (eq (window-buffer) (current-buffer))
98 "Scroll image in current window to the left by N character widths. 127 "Scroll image in current window to the left by N character widths.
99 Stop if the right edge of the image is reached." 128 Stop if the right edge of the image is reached."
100 (interactive "p") 129 (interactive "p")
101 (cond ((= n 0) nil) 130 (cond ((= n 0) nil)
102 ((< n 0) 131 ((< n 0)
103 (image-set-window-hscroll (selected-window) 132 (image-set-window-hscroll (max 0 (+ (window-hscroll) n))))
104 (max 0 (+ (window-hscroll) n))))
105 (t 133 (t
106 (let* ((image (image-get-display-property)) 134 (let* ((image (image-get-display-property))
107 (edges (window-inside-edges)) 135 (edges (window-inside-edges))
108 (win-width (- (nth 2 edges) (nth 0 edges))) 136 (win-width (- (nth 2 edges) (nth 0 edges)))
109 (img-width (ceiling (car (image-size image))))) 137 (img-width (ceiling (car (image-size image)))))
110 (image-set-window-hscroll (selected-window) 138 (image-set-window-hscroll (min (max 0 (- img-width win-width))
111 (min (max 0 (- img-width win-width))
112 (+ n (window-hscroll)))))))) 139 (+ n (window-hscroll))))))))
113 140
114 (defun image-backward-hscroll (&optional n) 141 (defun image-backward-hscroll (&optional n)
115 "Scroll image in current window to the right by N character widths. 142 "Scroll image in current window to the right by N character widths.
116 Stop if the left edge of the image is reached." 143 Stop if the left edge of the image is reached."
121 "Scroll image in current window upward by N lines. 148 "Scroll image in current window upward by N lines.
122 Stop if the bottom edge of the image is reached." 149 Stop if the bottom edge of the image is reached."
123 (interactive "p") 150 (interactive "p")
124 (cond ((= n 0) nil) 151 (cond ((= n 0) nil)
125 ((< n 0) 152 ((< n 0)
126 (image-set-window-vscroll (selected-window) 153 (image-set-window-vscroll (max 0 (+ (window-vscroll) n))))
127 (max 0 (+ (window-vscroll) n))))
128 (t 154 (t
129 (let* ((image (image-get-display-property)) 155 (let* ((image (image-get-display-property))
130 (edges (window-inside-edges)) 156 (edges (window-inside-edges))
131 (win-height (- (nth 3 edges) (nth 1 edges))) 157 (win-height (- (nth 3 edges) (nth 1 edges)))
132 (img-height (ceiling (cdr (image-size image))))) 158 (img-height (ceiling (cdr (image-size image)))))
133 (image-set-window-vscroll (selected-window) 159 (image-set-window-vscroll (min (max 0 (- img-height win-height))
134 (min (max 0 (- img-height win-height))
135 (+ n (window-vscroll)))))))) 160 (+ n (window-vscroll))))))))
136 161
137 (defun image-previous-line (&optional n) 162 (defun image-previous-line (&optional n)
138 "Scroll image in current window downward by N lines. 163 "Scroll image in current window downward by N lines.
139 Stop if the top edge of the image is reached." 164 Stop if the top edge of the image is reached."
188 stopping if the top or bottom edge of the image is reached." 213 stopping if the top or bottom edge of the image is reached."
189 (interactive "p") 214 (interactive "p")
190 (and arg 215 (and arg
191 (/= (setq arg (prefix-numeric-value arg)) 1) 216 (/= (setq arg (prefix-numeric-value arg)) 1)
192 (image-next-line (- arg 1))) 217 (image-next-line (- arg 1)))
193 (image-set-window-hscroll (selected-window) 0)) 218 (image-set-window-hscroll 0))
194 219
195 (defun image-eol (arg) 220 (defun image-eol (arg)
196 "Scroll horizontally to the right edge of the image in the current window. 221 "Scroll horizontally to the right edge of the image in the current window.
197 With argument ARG not nil or 1, move forward ARG - 1 lines first, 222 With argument ARG not nil or 1, move forward ARG - 1 lines first,
198 stopping if the top or bottom edge of the image is reached." 223 stopping if the top or bottom edge of the image is reached."
202 (image-next-line (- arg 1))) 227 (image-next-line (- arg 1)))
203 (let* ((image (image-get-display-property)) 228 (let* ((image (image-get-display-property))
204 (edges (window-inside-edges)) 229 (edges (window-inside-edges))
205 (win-width (- (nth 2 edges) (nth 0 edges))) 230 (win-width (- (nth 2 edges) (nth 0 edges)))
206 (img-width (ceiling (car (image-size image))))) 231 (img-width (ceiling (car (image-size image)))))
207 (image-set-window-hscroll (selected-window) 232 (image-set-window-hscroll (max 0 (- img-width win-width)))))
208 (max 0 (- img-width win-width)))))
209 233
210 (defun image-bob () 234 (defun image-bob ()
211 "Scroll to the top-left corner of the image in the current window." 235 "Scroll to the top-left corner of the image in the current window."
212 (interactive) 236 (interactive)
213 (image-set-window-hscroll (selected-window) 0) 237 (image-set-window-hscroll 0)
214 (image-set-window-vscroll (selected-window) 0)) 238 (image-set-window-vscroll 0))
215 239
216 (defun image-eob () 240 (defun image-eob ()
217 "Scroll to the bottom-right corner of the image in the current window." 241 "Scroll to the bottom-right corner of the image in the current window."
218 (interactive) 242 (interactive)
219 (let* ((image (image-get-display-property)) 243 (let* ((image (image-get-display-property))
220 (edges (window-inside-edges)) 244 (edges (window-inside-edges))
221 (win-width (- (nth 2 edges) (nth 0 edges))) 245 (win-width (- (nth 2 edges) (nth 0 edges)))
222 (img-width (ceiling (car (image-size image)))) 246 (img-width (ceiling (car (image-size image))))
223 (win-height (- (nth 3 edges) (nth 1 edges))) 247 (win-height (- (nth 3 edges) (nth 1 edges)))
224 (img-height (ceiling (cdr (image-size image))))) 248 (img-height (ceiling (cdr (image-size image)))))
225 (image-set-window-hscroll (selected-window) (max 0 (- img-width win-width))) 249 (image-set-window-hscroll (max 0 (- img-width win-width)))
226 (image-set-window-vscroll (selected-window) (max 0 (- img-height win-height))))) 250 (image-set-window-vscroll (max 0 (- img-height win-height)))))
227 251
228 ;;; Image Mode setup 252 ;;; Image Mode setup
229 253
230 (defvar image-type nil 254 (defvar image-type nil
231 "Current image type. 255 "Current image type.
268 ;; Use our own bookmarking function for images. 292 ;; Use our own bookmarking function for images.
269 (set (make-local-variable 'bookmark-make-cell-function) 293 (set (make-local-variable 'bookmark-make-cell-function)
270 'image-bookmark-make-cell) 294 'image-bookmark-make-cell)
271 295
272 ;; Keep track of [vh]scroll when switching buffers 296 ;; Keep track of [vh]scroll when switching buffers
273 (image-set-window-hscroll (selected-window) (window-hscroll)) 297 (image-mode-setup-winprops)
274 (image-set-window-vscroll (selected-window) (window-vscroll))
275 (add-hook 'window-configuration-change-hook
276 'image-reset-current-vhscroll nil t)
277 298
278 (add-hook 'change-major-mode-hook 'image-toggle-display-text nil t) 299 (add-hook 'change-major-mode-hook 'image-toggle-display-text nil t)
279 (if (and (display-images-p) 300 (if (and (display-images-p)
280 (not (image-get-display-property))) 301 (not (image-get-display-property)))
281 (image-toggle-display) 302 (image-toggle-display)