1 ;;; image-file.el --- support for visiting image files
3 ;; Copyright (C) 2000-2015 Free Software Foundation, Inc.
5 ;; Author: Miles Bader <miles@gnu.org>
6 ;; Keywords: multimedia
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
25 ;; Defines a file-name-handler hook that transforms visited (or
26 ;; inserted) image files so that they are displayed by Emacs as
27 ;; images. This is done by putting a `display' text-property on the
28 ;; image data, with the image-data still present underneath; if the
29 ;; resulting buffer file is saved to another name it will correctly save
30 ;; the image data to the new file.
38 (defcustom image-file-name-extensions
39 (purecopy '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm" "svg"))
40 "A list of image-file filename extensions.
41 Filenames having one of these extensions are considered image files,
42 in addition to those matching `image-file-name-regexps'.
44 See `auto-image-file-mode'; if `auto-image-file-mode' is enabled,
45 setting this variable directly does not take effect unless
46 `auto-image-file-mode' is re-enabled; this happens automatically when
47 the variable is set using \\[customize]."
48 :type
'(repeat string
)
49 :set
(lambda (sym val
)
51 (when auto-image-file-mode
52 ;; Re-initialize the image-file handler
53 (auto-image-file-mode t
)))
54 :initialize
'custom-initialize-default
58 (defcustom image-file-name-regexps nil
59 "List of regexps matching image-file filenames.
60 Filenames matching one of these regexps are considered image files,
61 in addition to those with an extension in `image-file-name-extensions'.
63 See function `auto-image-file-mode'; if `auto-image-file-mode' is
64 enabled, setting this variable directly does not take effect unless
65 `auto-image-file-mode' is re-enabled; this happens automatically when
66 the variable is set using \\[customize]."
67 :type
'(repeat regexp
)
68 :set
(lambda (sym val
)
70 (when auto-image-file-mode
71 ;; Re-initialize the image-file handler
72 (auto-image-file-mode t
)))
73 :initialize
'custom-initialize-default
78 (defun image-file-name-regexp ()
79 "Return a regular expression matching image-file filenames."
81 (and image-file-name-extensions
83 (regexp-opt (nconc (mapcar #'upcase
84 image-file-name-extensions
)
85 image-file-name-extensions
)
88 (if image-file-name-regexps
91 (cons exts-regexp image-file-name-regexps
)
92 image-file-name-regexps
)
98 (defun insert-image-file (file &optional visit beg end replace
)
99 "Insert the image file FILE into the current buffer.
100 Optional arguments VISIT, BEG, END, and REPLACE are interpreted as for
101 the command `insert-file-contents'."
103 (image-file-call-underlying #'insert-file-contents-literally
104 'insert-file-contents
105 file visit beg end replace
)))
106 ;; Turn the image data into a real image, but only if the whole file
108 (when (and (or (null beg
) (zerop beg
)) (null end
))
109 (let* ((ibeg (point))
110 (iend (+ (point) (cadr rval
)))
111 (visitingp (and visit
(= ibeg
(point-min)) (= iend
(point-max))))
114 (buffer-substring-no-properties ibeg iend
)))
116 (create-image data nil t
))
120 (image-file-yank-handler nil t
)
122 rear-nonsticky
(display intangible
)
123 ;; This a cheap attempt to make the whole buffer
124 ;; read-only when we're visiting the file (as
125 ;; opposed to just inserting it).
127 '(read-only t front-sticky
(read-only))))))
128 (add-text-properties ibeg iend props
)
130 ;; Inhibit the cursor when the buffer contains only an image,
131 ;; because cursors look very strange on top of images.
132 (setq cursor-type nil
)
133 ;; This just makes the arrow displayed in the right fringe
134 ;; area look correct when the image is wider than the window.
135 (setq truncate-lines t
))))
138 ;; We use a yank-handler to make yanked images unique, so that
139 ;; yanking two copies of the same image next to each other are
140 ;; recognized as two different images.
141 (defun image-file-yank-handler (string)
142 "Yank handler for inserting an image into a buffer."
143 (let ((len (length string
))
144 (image (get-text-property 0 'display string
)))
145 (remove-text-properties 0 len yank-excluded-properties string
)
147 (add-text-properties 0
148 (or (next-single-property-change 0 'image-counter string
)
151 ,(cons (car image
) (cdr image
))
153 ,(cons 'image-file-yank-handler
'(nil t
)))
157 (put 'image-file-handler
'safe-magic t
)
158 (defun image-file-handler (operation &rest args
)
159 "Filename handler for inserting image files.
160 OPERATION is the operation to perform, on ARGS.
161 See `file-name-handler-alist' for details."
162 (if (and (eq operation
'insert-file-contents
)
163 auto-image-file-mode
)
164 (apply #'insert-image-file args
)
165 ;; We don't handle OPERATION, use another handler or the default
166 (apply #'image-file-call-underlying operation operation args
)))
168 (defun image-file-call-underlying (function operation
&rest args
)
169 "Call FUNCTION with `image-file-handler' and OPERATION inhibited.
170 Optional argument ARGS are the arguments to call FUNCTION with."
171 (let ((inhibit-file-name-handlers
172 (cons 'image-file-handler
173 (and (eq inhibit-file-name-operation operation
)
174 inhibit-file-name-handlers
)))
175 (inhibit-file-name-operation operation
))
176 (apply function args
)))
180 (define-minor-mode auto-image-file-mode
181 "Toggle visiting of image files as images (Auto Image File mode).
182 With a prefix argument ARG, enable Auto Image File mode if ARG is
183 positive, and disable it otherwise. If called from Lisp, enable
184 the mode if ARG is omitted or nil.
186 An image file is one whose name has an extension in
187 `image-file-name-extensions', or matches a regexp in
188 `image-file-name-regexps'."
191 ;; Remove existing handler
192 (let ((existing-entry
193 (rassq 'image-file-handler file-name-handler-alist
)))
195 (setq file-name-handler-alist
196 (delq existing-entry file-name-handler-alist
))))
197 ;; Add new handler, if enabled
198 (when auto-image-file-mode
199 (push (cons (image-file-name-regexp) 'image-file-handler
)
200 file-name-handler-alist
)))
203 (provide 'image-file
)
205 ;;; image-file.el ends here