delete_temp_file fix
[bpt/emacs.git] / lisp / image-file.el
CommitLineData
112d54c1 1;;; image-file.el --- support for visiting image files
5859e61a 2;;
ba318903 3;; Copyright (C) 2000-2014 Free Software Foundation, Inc.
5859e61a
MB
4;;
5;; Author: Miles Bader <miles@gnu.org>
6;; Keywords: multimedia
7
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
5859e61a 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
5859e61a
MB
14
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.
19
20;; You should have received a copy of the GNU General Public License
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
5859e61a
MB
22
23;;; Commentary:
24
25;; Defines a file-name-handler hook that transforms visited (or
112d54c1 26;; inserted) image files so that they are displayed by Emacs as
5859e61a
MB
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.
31
32;;; Code:
33
34(require 'image)
35
75e5b373 36
1c7e37a9 37;;;###autoload
75e5b373 38(defcustom image-file-name-extensions
1e8780b1 39 (purecopy '("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm" "xpm" "pbm" "pgm" "ppm" "pnm" "svg"))
9201cc28 40 "A list of image-file filename extensions.
75e5b373
MB
41Filenames having one of these extensions are considered image files,
42in addition to those matching `image-file-name-regexps'.
43
44See `auto-image-file-mode'; if `auto-image-file-mode' is enabled,
45setting this variable directly does not take effect unless
228b0b9a
DL
46`auto-image-file-mode' is re-enabled; this happens automatically when
47the variable is set using \\[customize]."
75e5b373
MB
48 :type '(repeat string)
49 :set (lambda (sym val)
50 (set-default sym val)
51 (when auto-image-file-mode
52 ;; Re-initialize the image-file handler
53 (auto-image-file-mode t)))
5859e61a 54 :initialize 'custom-initialize-default
5859e61a
MB
55 :group 'image)
56
1c7e37a9 57;;;###autoload
75e5b373 58(defcustom image-file-name-regexps nil
9201cc28 59 "List of regexps matching image-file filenames.
75e5b373
MB
60Filenames matching one of these regexps are considered image files,
61in addition to those with an extension in `image-file-name-extensions'.
5859e61a 62
db623cef
DL
63See function `auto-image-file-mode'; if `auto-image-file-mode' is
64enabled, setting this variable directly does not take effect unless
228b0b9a
DL
65`auto-image-file-mode' is re-enabled; this happens automatically when
66the variable is set using \\[customize]."
5859e61a
MB
67 :type '(repeat regexp)
68 :set (lambda (sym val)
69 (set-default sym val)
75e5b373 70 (when auto-image-file-mode
5859e61a 71 ;; Re-initialize the image-file handler
75e5b373 72 (auto-image-file-mode t)))
5859e61a
MB
73 :initialize 'custom-initialize-default
74 :group 'image)
75
75e5b373
MB
76
77;;;###autoload
78(defun image-file-name-regexp ()
34a19346 79 "Return a regular expression matching image-file filenames."
75e5b373
MB
80 (let ((exts-regexp
81 (and image-file-name-extensions
82 (concat "\\."
b170205b
MB
83 (regexp-opt (nconc (mapcar #'upcase
84 image-file-name-extensions)
85 image-file-name-extensions)
86 t)
75e5b373
MB
87 "\\'"))))
88 (if image-file-name-regexps
89 (mapconcat 'identity
90 (if exts-regexp
a23ccdf2
DL
91 (cons exts-regexp image-file-name-regexps)
92 image-file-name-regexps)
75e5b373
MB
93 "\\|")
94 exts-regexp)))
95
96
5859e61a
MB
97;;;###autoload
98(defun insert-image-file (file &optional visit beg end replace)
99 "Insert the image file FILE into the current buffer.
100Optional arguments VISIT, BEG, END, and REPLACE are interpreted as for
101the command `insert-file-contents'."
102 (let ((rval
103 (image-file-call-underlying #'insert-file-contents-literally
104 'insert-file-contents
105 file visit beg end replace)))
75e5b373
MB
106 ;; Turn the image data into a real image, but only if the whole file
107 ;; was inserted
108 (when (and (or (null beg) (zerop beg)) (null end))
5859e61a
MB
109 (let* ((ibeg (point))
110 (iend (+ (point) (cadr rval)))
33155ffb 111 (visitingp (and visit (= ibeg (point-min)) (= iend (point-max))))
5859e61a 112 (data
75e5b373
MB
113 (string-make-unibyte
114 (buffer-substring-no-properties ibeg iend)))
5859e61a
MB
115 (image
116 (create-image data nil t))
117 (props
118 `(display ,image
eab48795
KS
119 yank-handler
120 (image-file-yank-handler nil t)
5859e61a 121 intangible ,image
a02b5bb4 122 rear-nonsticky (display intangible)
5859e61a 123 ;; This a cheap attempt to make the whole buffer
a02b5bb4
MB
124 ;; read-only when we're visiting the file (as
125 ;; opposed to just inserting it).
33155ffb 126 ,@(and visitingp
5859e61a 127 '(read-only t front-sticky (read-only))))))
33155ffb
MB
128 (add-text-properties ibeg iend props)
129 (when visitingp
130 ;; Inhibit the cursor when the buffer contains only an image,
131 ;; because cursors look very strange on top of images.
65e70fc4
MB
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))))
5859e61a
MB
136 rval))
137
6ed554f2
KS
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."
eab48795
KS
143 (let ((len (length string))
144 (image (get-text-property 0 'display string)))
145 (remove-text-properties 0 len yank-excluded-properties string)
6ed554f2 146 (if (consp image)
eab48795
KS
147 (add-text-properties 0
148 (or (next-single-property-change 0 'image-counter string)
149 (length string))
150 `(display
151 ,(cons (car image) (cdr image))
152 yank-handler
153 ,(cons 'image-file-yank-handler '(nil t)))
154 string))
6ed554f2
KS
155 (insert string)))
156
15a420bd 157(put 'image-file-handler 'safe-magic t)
5859e61a 158(defun image-file-handler (operation &rest args)
34a19346 159 "Filename handler for inserting image files.
5859e61a
MB
160OPERATION is the operation to perform, on ARGS.
161See `file-name-handler-alist' for details."
75e5b373
MB
162 (if (and (eq operation 'insert-file-contents)
163 auto-image-file-mode)
5859e61a
MB
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)))
167
168(defun image-file-call-underlying (function operation &rest args)
169 "Call FUNCTION with `image-file-handler' and OPERATION inhibited.
170Optional 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)))
177
5859e61a 178
33c7a00c
MB
179;;;###autoload
180(define-minor-mode auto-image-file-mode
06e21633
CY
181 "Toggle visiting of image files as images (Auto Image File mode).
182With a prefix argument ARG, enable Auto Image File mode if ARG is
183positive, and disable it otherwise. If called from Lisp, enable
184the mode if ARG is omitted or nil.
33c7a00c 185
06e21633 186An image file is one whose name has an extension in
33c7a00c
MB
187`image-file-name-extensions', or matches a regexp in
188`image-file-name-regexps'."
33c7a00c
MB
189 :global t
190 :group 'image
191 ;; Remove existing handler
192 (let ((existing-entry
193 (rassq 'image-file-handler file-name-handler-alist)))
194 (when existing-entry
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)))
201
202
5859e61a
MB
203(provide 'image-file)
204
205;;; image-file.el ends here