Move constant `emacs-minor-version', Emacs 19 emulating definitions
[elisp/apel.git] / emu.el
1 ;;; emu.el --- Emulation module for each Emacs variants
2
3 ;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;; Keywords: emulation, compatibility, NEmacs, MULE, Emacs/mule, XEmacs
7
8 ;; This file is part of emu.
9
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
14
15 ;; This program is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (require 'poe)
28
29 (defvar running-emacs-18 (<= emacs-major-version 18))
30 (defvar running-xemacs (string-match "XEmacs" emacs-version))
31
32 (defvar running-mule-merged-emacs (and (not (boundp 'MULE))
33                                        (not running-xemacs) (featurep 'mule)))
34 (defvar running-xemacs-with-mule (and running-xemacs (featurep 'mule)))
35
36 (defvar running-emacs-19 (and (not running-xemacs) (= emacs-major-version 19)))
37 (defvar running-emacs-19_29-or-later
38   (or (and running-emacs-19 (>= emacs-minor-version 29))
39       (and (not running-xemacs)(>= emacs-major-version 20))))
40
41 (defvar running-xemacs-19 (and running-xemacs
42                                (= emacs-major-version 19)))
43 (defvar running-xemacs-20-or-later (and running-xemacs
44                                         (>= emacs-major-version 20)))
45 (defvar running-xemacs-19_14-or-later
46   (or (and running-xemacs-19 (>= emacs-minor-version 14))
47       running-xemacs-20-or-later))
48
49 (cond (running-xemacs
50        ;; for XEmacs
51        (defvar mouse-button-1 'button1)
52        (defvar mouse-button-2 'button2)
53        (defvar mouse-button-3 'button3)
54        )
55       ((>= emacs-major-version 19)
56        ;; for tm-7.106
57        (defalias 'tl:make-overlay 'make-overlay)
58        (defalias 'tl:overlay-put 'overlay-put)
59        (defalias 'tl:overlay-buffer 'overlay-buffer)
60        
61        (make-obsolete 'tl:make-overlay 'make-overlay)
62        (make-obsolete 'tl:overlay-put 'overlay-put)
63        (make-obsolete 'tl:overlay-buffer 'overlay-buffer)
64        
65        ;; mouse
66        (defvar mouse-button-1 [mouse-1])
67        (defvar mouse-button-2 [mouse-2])
68        (defvar mouse-button-3 [down-mouse-3])
69        )
70       (t
71        ;; mouse
72        (defvar mouse-button-1 nil)
73        (defvar mouse-button-2 nil)
74        (defvar mouse-button-3 nil)
75        ))
76
77 (cond (running-xemacs
78        (if (featurep 'mule)
79            ;; for XEmacs with MULE
80            (require 'emu-x20)
81          ;; for XEmacs without MULE
82          (require 'emu-latin1)
83          ))
84       (running-mule-merged-emacs
85        ;; for Emacs 20.1 and 20.2
86        (require 'emu-e20)
87        )
88       ((boundp 'MULE)
89        ;; for MULE 1.* and 2.*
90        (require 'emu-mule)
91        )
92       ((boundp 'NEMACS)
93        ;; for NEmacs and NEpoch
94        (require 'emu-nemacs)
95        )
96       (t
97        ;; for Emacs 19
98        (require 'emu-latin1)
99        ))
100
101
102 ;;; @ MIME charset
103 ;;;
104
105 (defun charsets-to-mime-charset (charsets)
106   "Return MIME charset from list of charset CHARSETS.
107 This function refers variable `charsets-mime-charset-alist'
108 and `default-mime-charset'."
109   (if charsets
110       (or (catch 'tag
111             (let ((rest charsets-mime-charset-alist)
112                   cell)
113               (while (setq cell (car rest))
114                 (if (catch 'not-subset
115                       (let ((set1 charsets)
116                             (set2 (car cell))
117                             obj)
118                         (while set1
119                           (setq obj (car set1))
120                           (or (memq obj set2)
121                               (throw 'not-subset nil))
122                           (setq set1 (cdr set1)))
123                         t))
124                     (throw 'tag (cdr cell)))
125                 (setq rest (cdr rest)))))
126           default-mime-charset)))
127
128
129 ;;; @ Emacs 19.30 emulation
130 ;;;
131
132 ;; This function was imported Emacs 19.30.
133 (defun-maybe add-to-list (list-var element)
134   "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
135 If you want to use `add-to-list' on a variable that is not defined
136 until a certain package is loaded, you should put the call to `add-to-list'
137 into a hook function that will be run only after loading the package.
138 \[Emacs 19.30 emulating function]"
139   (or (member element (symbol-value list-var))
140       (set list-var (cons element (symbol-value list-var)))))
141
142 (cond ((fboundp 'insert-file-contents-literally)
143        )
144       ((boundp 'file-name-handler-alist)
145        (defun insert-file-contents-literally
146          (filename &optional visit beg end replace)
147          "Like `insert-file-contents', q.v., but only reads in the file.
148 A buffer may be modified in several ways after reading into the buffer due
149 to advanced Emacs features, such as file-name-handlers, format decoding,
150 find-file-hooks, etc.
151   This function ensures that none of these modifications will take place.
152 \[Emacs 19.30 emulating function]"
153          (let (file-name-handler-alist)
154            (insert-file-contents filename visit beg end replace)))
155        )
156       (t
157        (defalias 'insert-file-contents-literally 'insert-file-contents)
158        ))
159
160
161 ;;; @ Emacs 19.31 emulation
162 ;;;
163
164 (defun-maybe buffer-live-p (object)
165   "Return non-nil if OBJECT is a buffer which has not been killed.
166 Value is nil if OBJECT is not a buffer or if it has been killed.
167 \[Emacs 19.31 emulating function]"
168   (and object
169        (get-buffer object)
170        (buffer-name (get-buffer object))))
171
172 ;; This macro was imported Emacs 19.33.
173 (defmacro-maybe save-selected-window (&rest body)
174   "Execute BODY, then select the window that was selected before BODY.
175 \[Emacs 19.31 emulating function]"
176   (list 'let
177         '((save-selected-window-window (selected-window)))
178         (list 'unwind-protect
179               (cons 'progn body)
180               (list 'select-window 'save-selected-window-window))))
181
182
183 ;;; @ Emacs 20.1 emulation
184 ;;;
185
186 ;; This macro was imported Emacs 20.2.
187 (defmacro-maybe when (cond &rest body)
188   "(when COND BODY...): if COND yields non-nil, do BODY, else return nil."
189   (list 'if cond (cons 'progn body)))
190
191 (defmacro-maybe save-current-buffer (&rest body)
192   "Save the current buffer; execute BODY; restore the current buffer.
193 Executes BODY just like `progn'."
194   (` (let ((orig-buffer (current-buffer)))
195        (unwind-protect
196            (progn (,@ body))
197          (set-buffer orig-buffer)))))
198
199 ;; This macro was imported Emacs 20.2.
200 (defmacro-maybe with-current-buffer (buffer &rest body)
201   "Execute the forms in BODY with BUFFER as the current buffer.
202 The value returned is the value of the last form in BODY.
203 See also `with-temp-buffer'."
204   (` (save-current-buffer
205        (set-buffer (, buffer))
206        (,@ body))))
207
208 ;; This macro was imported Emacs 20.2.
209 (defmacro-maybe with-temp-file (file &rest forms)
210   "Create a new buffer, evaluate FORMS there, and write the buffer to FILE.
211 The value of the last form in FORMS is returned, like `progn'.
212 See also `with-temp-buffer'."
213   (let ((temp-file (make-symbol "temp-file"))
214         (temp-buffer (make-symbol "temp-buffer")))
215     (` (let (((, temp-file) (, file))
216              ((, temp-buffer)
217               (get-buffer-create (generate-new-buffer-name " *temp file*"))))
218          (unwind-protect
219              (prog1
220                  (with-current-buffer (, temp-buffer)
221                    (,@ forms))
222                (with-current-buffer (, temp-buffer)
223                  (widen)
224                  (write-region (point-min) (point-max) (, temp-file) nil 0)))
225            (and (buffer-name (, temp-buffer))
226                 (kill-buffer (, temp-buffer))))))))
227
228 ;; This macro was imported Emacs 20.2.
229 (defmacro-maybe with-temp-buffer (&rest forms)
230   "Create a temporary buffer, and evaluate FORMS there like `progn'.
231 See also `with-temp-file' and `with-output-to-string'."
232   (let ((temp-buffer (make-symbol "temp-buffer")))
233     (` (let (((, temp-buffer)
234               (get-buffer-create (generate-new-buffer-name " *temp*"))))
235          (unwind-protect
236              (with-current-buffer (, temp-buffer)
237                (,@ forms))
238            (and (buffer-name (, temp-buffer))
239                 (kill-buffer (, temp-buffer))))))))
240
241 ;; This function was imported Emacs 20.3.
242 (defun-maybe last (x &optional n)
243   "Return the last link of the list X.  Its car is the last element.
244 If X is nil, return nil.
245 If N is non-nil, return the Nth-to-last link of X.
246 If N is bigger than the length of X, return X."
247   (if n
248       (let ((m 0) (p x))
249         (while (consp p)
250           (setq m (1+ m) p (cdr p)))
251         (if (<= n 0) p
252           (if (< n m) (nthcdr (- m n) x) x)))
253     (while (cdr x)
254       (setq x (cdr x)))
255     x))
256
257 ;; This function was imported Emacs 20.3. (cl function)
258 (defun-maybe butlast (x &optional n)
259   "Returns a copy of LIST with the last N elements removed."
260   (if (and n (<= n 0)) x
261     (nbutlast (copy-sequence x) n)))
262   
263 ;; This function was imported Emacs 20.3. (cl function)
264 (defun-maybe nbutlast (x &optional n)
265   "Modifies LIST to remove the last N elements."
266   (let ((m (length x)))
267     (or n (setq n 1))
268     (and (< n m)
269          (progn
270            (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil))
271            x))))
272
273 ;; This function was imported from XEmacs 21.
274 (defun-maybe split-string (string &optional pattern)
275   "Return a list of substrings of STRING which are separated by PATTERN.
276 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
277   (or pattern
278       (setq pattern "[ \f\t\n\r\v]+"))
279   ;; The FSF version of this function takes care not to cons in case
280   ;; of infloop.  Maybe we should synch?
281   (let (parts (start 0))
282     (while (string-match pattern string start)
283       (setq parts (cons (substring string start (match-beginning 0)) parts)
284             start (match-end 0)))
285     (nreverse (cons (substring string start) parts))))
286
287
288 ;;; @ Emacs 20.3 emulation
289 ;;;
290
291 (defmacro-maybe string-as-unibyte (string)
292   "Return a unibyte string with the same individual bytes as STRING.
293 If STRING is unibyte, the result is STRING itself.
294 \[Emacs 20.3 emulating macro]"
295   string)
296
297 (defmacro-maybe string-as-multibyte (string)
298   "Return a multibyte string with the same individual bytes as STRING.
299 If STRING is multibyte, the result is STRING itself.
300 \[Emacs 20.3 emulating macro]"
301   string)
302
303
304 ;;; @ XEmacs emulation
305 ;;;
306
307 (defun-maybe functionp (obj)
308   "Returns t if OBJ is a function, nil otherwise.
309 \[XEmacs emulating function]"
310   (or (subrp obj)
311       (byte-code-function-p obj)
312       (and (symbolp obj)(fboundp obj))
313       (and (consp obj)(eq (car obj) 'lambda))
314       ))
315
316 (defun-maybe point-at-eol (&optional arg buffer)
317   "Return the character position of the last character on the current line.
318 With argument N not nil or 1, move forward N - 1 lines first.
319 If scan reaches end of buffer, return that position.
320 This function does not move point. [XEmacs emulating function]"
321   (save-excursion
322     (if buffer
323         (set-buffer buffer)
324       )
325     (if arg
326         (forward-line (1- arg))
327       )
328     (end-of-line)
329     (point)))
330
331
332 ;;; @ for XEmacs 20
333 ;;;
334
335 (or (fboundp 'char-int)
336     (fset 'char-int (symbol-function 'identity))
337     )
338 (or (fboundp 'int-char)
339     (fset 'int-char (symbol-function 'identity))
340     )
341 (or (fboundp 'char-or-char-int-p)
342     (fset 'char-or-char-int-p (symbol-function 'integerp))
343     )
344
345
346 ;;; @ for text/richtext and text/enriched
347 ;;;
348
349 (cond ((fboundp 'richtext-decode)
350        ;; have richtext.el
351        )
352       ((or running-emacs-19_29-or-later running-xemacs-19_14-or-later)
353        ;; have enriched.el
354        (autoload 'richtext-decode "richtext")
355        (or (assq 'text/richtext format-alist)
356            (setq format-alist
357                  (cons
358                   (cons 'text/richtext
359                         '("Extended MIME text/richtext format."
360                           "Content-[Tt]ype:[ \t]*text/richtext"
361                           richtext-decode richtext-encode t enriched-mode))
362                   format-alist)))
363        )
364       (t
365        ;; don't have enriched.el
366        (autoload 'richtext-decode "tinyrich")
367        (autoload 'enriched-decode "tinyrich")
368        ))
369
370
371 ;;; @ end
372 ;;;
373
374 (provide 'emu)
375
376 ;;; emu.el ends here