Merge from emacs-24; up to 2012-12-29T12:57:49Z!fgallina@gnu.org
[bpt/emacs.git] / lisp / mh-e / mh-compat.el
CommitLineData
da6062e6 1;;; mh-compat.el --- make MH-E compatible with various versions of Emacs
dda00b2c 2
ab422c4d 3;; Copyright (C) 2006-2013 Free Software Foundation, Inc.
dda00b2c
BW
4
5;; Author: Bill Wohler <wohler@newt.com>
6;; Maintainer: Bill Wohler <wohler@newt.com>
7;; Keywords: mail
8;; See: mh-e.el
9
10;; This file is part of GNU Emacs.
11
5e809f55 12;; GNU Emacs is free software: you can redistribute it and/or modify
dda00b2c 13;; it under the terms of the GNU General Public License as published by
5e809f55
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
dda00b2c
BW
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
5e809f55 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
dda00b2c
BW
24
25;;; Commentary:
26
27;;; Change Log:
28
29;;; Code:
30
31;; This is a good place to gather code that is used for compatibility
32;; between different versions of Emacs. Please document which versions
33;; of Emacs that the defsubst, defalias, or defmacro applies. That
34;; way, it's easy to occasionally go through this file and see which
35;; macros we can retire.
36
06e7028b 37;; Please use mh-gnus.el when providing compatibility with different
d5dc8c56 38;; versions of Gnus.
dda00b2c 39
d5dc8c56 40;; Items are listed alphabetically (except for mh-require which is
30545916 41;; needed sooner it would normally appear).
d5dc8c56
BW
42
43(require 'mh-acros)
44
45(mh-do-in-gnu-emacs
46 (defalias 'mh-require 'require))
47
48(mh-do-in-xemacs
49 (defun mh-require (feature &optional filename noerror)
50 "If feature FEATURE is not loaded, load it from FILENAME.
51If FEATURE is not a member of the list `features', then the feature
52is not loaded; so load the file FILENAME.
53If FILENAME is omitted, the printname of FEATURE is used as the file name.
54If the optional third argument NOERROR is non-nil,
55then return nil if the file is not found instead of signaling an error.
56
57Simulate NOERROR argument in XEmacs which lacks it."
58 (if (not (featurep feature))
59 (if filename
60 (load filename noerror t)
61 (load (format "%s" feature) noerror t)))))
dda00b2c 62
c90c4cf1 63(defun-mh mh-assoc-string assoc-string (key list case-fold)
06e7028b 64 "Like `assoc' but specifically for strings.
dda00b2c 65Case is ignored if CASE-FOLD is non-nil.
d5dc8c56
BW
66This function is used by Emacs versions that lack `assoc-string',
67introduced in Emacs 22."
06e7028b
BW
68 (if case-fold
69 (assoc-ignore-case key list)
70 (assoc key list)))
71
d5dc8c56
BW
72;; For XEmacs.
73(defalias 'mh-cancel-timer
74 (if (fboundp 'cancel-timer)
75 'cancel-timer
76 'delete-itimer))
77
fb9958d7
BW
78;; Emacs 24 renamed flet to cl-flet.
79(defalias 'mh-cl-flet
80 (if (fboundp 'cl-flet)
81 'cl-flet
82 'flet))
83
1a98ebdf 84(defun mh-display-color-cells (&optional display)
d5dc8c56 85 "Return the number of color cells supported by DISPLAY.
1a98ebdf
BW
86This function is used by XEmacs to return 2 when `device-color-cells'
87or `display-color-cells' returns nil. This happens when compiling or
a425dc3d
BW
88running on a tty and causes errors since `display-color-cells' is
89expected to return an integer."
1a98ebdf
BW
90 (cond ((fboundp 'display-color-cells) ; GNU Emacs, XEmacs 21.5b28
91 (or (display-color-cells display) 2))
92 ((fboundp 'device-color-cells) ; XEmacs 21.4
93 (or (device-color-cells display) 2))
94 (t 2)))
dda00b2c
BW
95
96(defmacro mh-display-completion-list (completions &optional common-substring)
97 "Display the list of COMPLETIONS.
06e7028b
BW
98See documentation for `display-completion-list' for a description of the
99arguments COMPLETIONS and perhaps COMMON-SUBSTRING.
d5dc8c56
BW
100This macro is used by Emacs versions that lack a COMMON-SUBSTRING
101argument, introduced in Emacs 22."
dda00b2c
BW
102 (if (< emacs-major-version 22)
103 `(display-completion-list ,completions)
104 `(display-completion-list ,completions ,common-substring)))
105
06e7028b
BW
106(defmacro mh-face-foreground (face &optional frame inherit)
107 "Return the foreground color name of FACE, or nil if unspecified.
108See documentation for `face-foreground' for a description of the
109arguments FACE, FRAME, and perhaps INHERIT.
d5dc8c56
BW
110This macro is used by Emacs versions that lack an INHERIT argument,
111introduced in Emacs 22."
06e7028b
BW
112 (if (< emacs-major-version 22)
113 `(face-foreground ,face ,frame)
114 `(face-foreground ,face ,frame ,inherit)))
115
116(defmacro mh-face-background (face &optional frame inherit)
117 "Return the background color name of face, or nil if unspecified.
118See documentation for `back-foreground' for a description of the
119arguments FACE, FRAME, and INHERIT.
d5dc8c56
BW
120This macro is used by Emacs versions that lack an INHERIT argument,
121introduced in Emacs 22."
06e7028b
BW
122 (if (< emacs-major-version 22)
123 `(face-background ,face ,frame)
124 `(face-background ,face ,frame ,inherit)))
125
c90c4cf1 126(defun-mh mh-font-lock-add-keywords font-lock-add-keywords
30545916 127 (mode keywords &optional how)
21acd4c9 128 "XEmacs does not have `font-lock-add-keywords'.
30545916
BW
129This function returns nil on that system.")
130
c90c4cf1 131(defun-mh mh-image-load-path-for-library
08f99a54 132 image-load-path-for-library (library image &optional path no-error)
d79c9e9d 133 "Return a suitable search path for images used by LIBRARY.
c80658b7 134
1792673d 135It searches for IMAGE in `image-load-path' (excluding
e8b5a7ce
BW
136\"`data-directory'/images\") and `load-path', followed by a path
137suitable for LIBRARY, which includes \"../../etc/images\" and
138\"../etc/images\" relative to the library file itself, and then
139in \"`data-directory'/images\".
c80658b7 140
44e3f440
BW
141Then this function returns a list of directories which contains
142first the directory in which IMAGE was found, followed by the
143value of `load-path'. If PATH is given, it is used instead of
144`load-path'.
08f99a54 145
44e3f440
BW
146If NO-ERROR is non-nil and a suitable path can't be found, don't
147signal an error. Instead, return a list of directories as before,
148except that nil appears in place of the image directory.
c80658b7
BW
149
150Here is an example that uses a common idiom to provide
151compatibility with versions of Emacs that lack the variable
152`image-load-path':
153
f875b154
BW
154 ;; Shush compiler.
155 (defvar image-load-path)
c80658b7 156
44e3f440 157 (let* ((load-path (image-load-path-for-library \"mh-e\" \"mh-logo.xpm\"))
f875b154
BW
158 (image-load-path (cons (car load-path)
159 (when (boundp 'image-load-path)
160 image-load-path))))
44e3f440 161 (mh-tool-bar-folder-buttons-init))"
c80658b7
BW
162 (unless library (error "No library specified"))
163 (unless image (error "No image specified"))
e8b5a7ce
BW
164 (let (image-directory image-directory-load-path)
165 ;; Check for images in image-load-path or load-path.
166 (let ((img image)
167 (dir (or
168 ;; Images in image-load-path.
169 (mh-image-search-load-path image)
170 ;; Images in load-path.
171 (locate-library image)))
172 parent)
173 ;; Since the image might be in a nested directory (for
174 ;; example, mail/attach.pbm), adjust `image-directory'
175 ;; accordingly.
176 (when dir
177 (setq dir (file-name-directory dir))
178 (while (setq parent (file-name-directory img))
179 (setq img (directory-file-name parent)
180 dir (expand-file-name "../" dir))))
181 (setq image-directory-load-path dir))
182
44e97401 183 ;; If `image-directory-load-path' isn't Emacs's image directory,
e8b5a7ce
BW
184 ;; it's probably a user preference, so use it. Then use a
185 ;; relative setting if possible; otherwise, use
186 ;; `image-directory-load-path'.
c80658b7 187 (cond
e8b5a7ce
BW
188 ;; User-modified image-load-path?
189 ((and image-directory-load-path
190 (not (equal image-directory-load-path
191 (file-name-as-directory
192 (expand-file-name "images" data-directory)))))
193 (setq image-directory image-directory-load-path))
c80658b7
BW
194 ;; Try relative setting.
195 ((let (library-name d1ei d2ei)
196 ;; First, find library in the load-path.
197 (setq library-name (locate-library library))
198 (if (not library-name)
199 (error "Cannot find library %s in load-path" library))
200 ;; And then set image-directory relative to that.
201 (setq
202 ;; Go down 2 levels.
e8b5a7ce
BW
203 d2ei (file-name-as-directory
204 (expand-file-name
205 (concat (file-name-directory library-name) "../../etc/images")))
c80658b7 206 ;; Go down 1 level.
e8b5a7ce
BW
207 d1ei (file-name-as-directory
208 (expand-file-name
209 (concat (file-name-directory library-name) "../etc/images"))))
c80658b7
BW
210 (setq image-directory
211 ;; Set it to nil if image is not found.
212 (cond ((file-exists-p (expand-file-name image d2ei)) d2ei)
213 ((file-exists-p (expand-file-name image d1ei)) d1ei)))))
44e97401 214 ;; Use Emacs's image directory.
e8b5a7ce
BW
215 (image-directory-load-path
216 (setq image-directory image-directory-load-path))
08f99a54 217 (no-error
08f99a54 218 (message "Could not find image %s for library %s" image library))
c80658b7
BW
219 (t
220 (error "Could not find image %s for library %s" image library)))
221
44e3f440
BW
222 ;; Return an augmented `path' or `load-path'.
223 (nconc (list image-directory)
224 (delete image-directory (copy-sequence (or path load-path))))))
c80658b7 225
c90c4cf1 226(defun-mh mh-image-search-load-path
fc0f755f
PG
227 image-search-load-path (file &optional path)
228 "Emacs 21 and XEmacs don't have `image-search-load-path'.
229This function returns nil on those systems."
230 nil)
231
d5dc8c56
BW
232;; For XEmacs.
233(defalias 'mh-line-beginning-position
234 (if (fboundp 'line-beginning-position)
235 'line-beginning-position
236 'point-at-bol))
237
238;; For XEmacs.
239(defalias 'mh-line-end-position
240 (if (fboundp 'line-end-position)
241 'line-end-position
242 'point-at-eol))
243
244(mh-require 'mailabbrev nil t)
c90c4cf1 245(defun-mh mh-mail-abbrev-make-syntax-table
d5dc8c56
BW
246 mail-abbrev-make-syntax-table ()
247 "Emacs 21 and XEmacs don't have `mail-abbrev-make-syntax-table'.
fc0f755f 248This function returns nil on those systems."
d5dc8c56
BW
249 nil)
250
fb9958d7
BW
251(defmacro mh-define-obsolete-variable-alias
252 (obsolete-name current-name &optional when docstring)
253 "Make OBSOLETE-NAME a variable alias for CURRENT-NAME and mark it obsolete.
254See documentation for `define-obsolete-variable-alias' for a description
255of the arguments OBSOLETE-NAME, CURRENT-NAME, and perhaps WHEN
256and DOCSTRING. This macro is used by XEmacs that lacks WHEN and
257DOCSTRING arguments."
258 (if (featurep 'xemacs)
259 `(define-obsolete-variable-alias ,obsolete-name ,current-name)
260 `(define-obsolete-variable-alias ,obsolete-name ,current-name ,when ,docstring)))
261
262(defmacro mh-make-obsolete-variable (obsolete-name current-name &optional when access-type)
263 "Make the byte-compiler warn that OBSOLETE-NAME is obsolete.
264See documentation for `make-obsolete-variable' for a description
265of the arguments OBSOLETE-NAME, CURRENT-NAME, and perhaps WHEN
266and ACCESS-TYPE. This macro is used by XEmacs that lacks WHEN and
267ACCESS-TYPE arguments."
268 (if (featurep 'xemacs)
269 `(make-obsolete-variable ,obsolete-name ,current-name)
270 `(make-obsolete-variable ,obsolete-name ,current-name ,when ,access-type)))
271
272(defmacro mh-make-obsolete-variable (obsolete-name current-name &optional when access-type)
273 "Make the byte-compiler warn that OBSOLETE-NAME is obsolete.
274See documentation for `make-obsolete-variable' for a description
275of the arguments OBSOLETE-NAME, CURRENT-NAME, and perhaps WHEN
276and ACCESS-TYPE. This macro is used by XEmacs that lacks WHEN and
277ACCESS-TYPE arguments and by Emacs versions that lack ACCESS-TYPE,
278introduced in Emacs 24."
279 (if (featurep 'xemacs)
280 `(make-obsolete-variable ,obsolete-name ,current-name)
281 (if (< emacs-major-version 24)
282 `(make-obsolete-variable ,obsolete-name ,current-name ,when)
283 `(make-obsolete-variable ,obsolete-name ,current-name ,when ,access-type))))
284
c90c4cf1 285(defun-mh mh-match-string-no-properties
d5dc8c56
BW
286 match-string-no-properties (num &optional string)
287 "Return string of text matched by last search, without text properties.
288This function is used by XEmacs that lacks `match-string-no-properties'.
289The function `buffer-substring-no-properties' is used instead.
290The argument STRING is ignored."
291 (buffer-substring-no-properties
292 (match-beginning num) (match-end num)))
293
c90c4cf1 294(defun-mh mh-replace-regexp-in-string replace-regexp-in-string
613cd8c5 295 (regexp rep string &optional fixedcase literal subexp start)
d5dc8c56
BW
296 "Replace REGEXP with REP everywhere in STRING and return result.
297This function is used by XEmacs that lacks `replace-regexp-in-string'.
298The function `replace-in-string' is used instead.
4a732ae9
BW
299The arguments FIXEDCASE, SUBEXP, and START, used by
300`replace-in-string' are ignored."
301 (replace-in-string string regexp rep literal))
d5dc8c56 302
9c1c3a42
BW
303(defun-mh mh-test-completion
304 test-completion (string collection &optional predicate)
7895927f
BW
305 "Return non-nil if STRING is a valid completion.
306XEmacs does not have `test-completion'. This function returns nil
307on that system." nil)
9c1c3a42 308
06e7028b
BW
309;; Copy of constant from url-util.el in Emacs 22; needed by Emacs 21.
310(if (not (boundp 'url-unreserved-chars))
e6e91eda 311 (defconst mh-url-unreserved-chars
06e7028b
BW
312 '(
313 ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
314 ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
315 ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
316 ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\))
317 "A list of characters that are _NOT_ reserved in the URL spec.
318This is taken from RFC 2396."))
319
c90c4cf1 320(defun-mh mh-url-hexify-string url-hexify-string (str)
06e7028b
BW
321 "Escape characters in a string.
322This is a copy of `url-hexify-string' from url-util.el in Emacs
32322; needed by Emacs 21."
324 (mapconcat
325 (lambda (char)
326 ;; Fixme: use a char table instead.
327 (if (not (memq char mh-url-unreserved-chars))
328 (if (> char 255)
329 (error "Hexifying multibyte character %s" str)
330 (format "%%%02X" char))
331 (char-to-string char)))
332 str ""))
333
c90c4cf1 334(defun-mh mh-view-mode-enter
d5dc8c56
BW
335 view-mode-enter (&optional return-to exit-action)
336 "Enter View mode.
337This function is used by XEmacs that lacks `view-mode-enter'.
338The function `view-mode' is used instead.
339The arguments RETURN-TO and EXIT-ACTION are ignored."
340 ;; Shush compiler.
341 (if return-to nil)
342 (if exit-action nil)
343 (view-mode 1))
344
93d4ce1e
BW
345(defun-mh mh-window-full-height-p
346 window-full-height-p (&optional WINDOW)
347 "Return non-nil if WINDOW is not the result of a vertical split.
348This function is defined in XEmacs as it lacks
349`window-full-height-p'. The values of the functions
350`window-height' and `frame-height' are compared instead. The
351argument WINDOW is ignored."
352 (= (1+ (window-height))
353 (frame-height)))
354
06e7028b
BW
355(defmacro mh-write-file-functions ()
356 "Return `write-file-functions' if it exists.
357Otherwise return `local-write-file-hooks'.
358This macro exists purely for compatibility. The former symbol is used
359in Emacs 22 onward while the latter is used in previous versions and
360XEmacs."
361 (if (boundp 'write-file-functions)
362 ''write-file-functions ;Emacs 22 on
363 ''local-write-file-hooks)) ;XEmacs
364
dda00b2c
BW
365(provide 'mh-compat)
366
367;; Local Variables:
368;; no-byte-compile: t
369;; indent-tabs-mode: nil
370;; sentence-end-double-space: nil
371;; End:
372
373;;; mh-compat.el ends here