(defvar-maybe): New macro.
[elisp/apel.git] / poe.el
1 ;;; poe.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 APEL (A Portable Emacs Library).
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 (defmacro defvar-maybe (name &rest everything-else)
28   (or (and (boundp name)
29            (not (get name 'defvar-maybe))
30            )
31       (` (or (boundp (quote (, name)))
32              (progn
33                (defvar (, name) (,@ everything-else))
34                (put (quote (, name)) 'defvar-maybe t)
35                ))
36          )))
37
38 (defmacro defun-maybe (name &rest everything-else)
39   (or (and (fboundp name)
40            (not (get name 'defun-maybe))
41            )
42       (` (or (fboundp (quote (, name)))
43              (progn
44                (defun (, name) (,@ everything-else))
45                (put (quote (, name)) 'defun-maybe t)
46                ))
47          )))
48
49 (defmacro defsubst-maybe (name &rest everything-else)
50   (or (and (fboundp name)
51            (not (get name 'defsubst-maybe))
52            )
53       (` (or (fboundp (quote (, name)))
54              (progn
55                (defsubst (, name) (,@ everything-else))
56                (put (quote (, name)) 'defsubst-maybe t)
57                ))
58          )))
59
60 (defmacro defmacro-maybe (name &rest everything-else)
61   (or (and (fboundp name)
62            (not (get name 'defmacro-maybe))
63            )
64       (` (or (fboundp (quote (, name)))
65              (progn
66                (defmacro (, name) (,@ everything-else))
67                (put (quote (, name)) 'defmacro-maybe t)
68                ))
69          )))
70
71 (put 'defun-maybe 'lisp-indent-function 'defun)
72 (put 'defsubst-maybe 'lisp-indent-function 'defun)
73 (put 'defmacro-maybe 'lisp-indent-function 'defun)
74
75 (defmacro defconst-maybe (name &rest everything-else)
76   (or (and (boundp name)
77            (not (get name 'defconst-maybe))
78            )
79       (` (or (boundp (quote (, name)))
80              (progn
81                (defconst (, name) (,@ everything-else))
82                (put (quote (, name)) 'defconst-maybe t)
83                ))
84          )))
85
86 (defconst-maybe emacs-major-version (string-to-int emacs-version))
87 (defconst-maybe emacs-minor-version
88   (string-to-int
89    (substring emacs-version
90               (string-match (format "%d\\." emacs-major-version)
91                             emacs-version))))
92
93 (cond ((featurep 'xemacs)
94        (require 'poe-xemacs)
95        )
96       ((string-match "XEmacs" emacs-version)
97        (provide 'xemacs)
98        (require 'poe-xemacs)
99        )
100       ((> emacs-major-version 20))
101       ((= emacs-major-version 20)
102        (cond ((fboundp 'string)
103               ;; Emacs 20.3 or later
104               )
105              ((fboundp 'concat-chars)
106               ;; Emacs 20.1 or later
107               (defalias 'string 'concat-chars)
108               ))
109        )
110       ((= emacs-major-version 19))
111       (t
112        (require 'poe-18)
113        ))
114
115
116 ;;; @ Emacs 19 emulation
117 ;;;
118
119 (defmacro-maybe eval-and-compile (&rest body)
120   "Like `progn', but evaluates the body at compile time and at load time."
121   ;; Remember, it's magic.
122   (cons 'progn body))
123
124 (defun-maybe minibuffer-prompt-width ()
125   "Return the display width of the minibuffer prompt."
126   (save-excursion
127     (set-buffer (window-buffer (minibuffer-window)))
128     (current-column)))
129
130
131 ;;; @ Emacs 19.29 emulation
132 ;;;
133
134 (defvar path-separator ":"
135   "Character used to separate concatenated paths.")
136
137 (defun-maybe buffer-substring-no-properties (start end)
138   "Return the characters of part of the buffer, without the text properties.
139 The two arguments START and END are character positions;
140 they can be in either order. [Emacs 19.29 emulating function]"
141   (let ((string (buffer-substring start end)))
142     (set-text-properties 0 (length string) nil string)
143     string))
144
145 (defun-maybe match-string (num &optional string)
146   "Return string of text matched by last search.
147 NUM specifies which parenthesized expression in the last regexp.
148  Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
149 Zero means the entire text matched by the whole regexp or whole string.
150 STRING should be given if the last search was by `string-match' on STRING.
151 \[Emacs 19.29 emulating function]"
152   (if (match-beginning num)
153       (if string
154           (substring string (match-beginning num) (match-end num))
155         (buffer-substring (match-beginning num) (match-end num)))))
156
157 (or (featurep 'xemacs)
158     (>= emacs-major-version 20)
159     (and (= emacs-major-version 19)
160          (>= emacs-minor-version 29))
161     ;; for Emacs 19.28 or earlier
162     (fboundp 'si:read-string)
163     (eval-and-compile
164       (fset 'si:read-string (symbol-function 'read-string))
165       (defun read-string (prompt &optional initial-input history)
166         "Read a string from the minibuffer, prompting with string PROMPT.
167 If non-nil, second arg INITIAL-INPUT is a string to insert before reading.
168 The third arg HISTORY, is dummy for compatibility. [emu.el]
169 See `read-from-minibuffer' for details of HISTORY argument."
170         (si:read-string prompt initial-input))
171       ))
172
173
174 ;;; @ Emacs 19.30 emulation
175 ;;;
176
177 ;; imported from Emacs 19.30.
178 (defun-maybe add-to-list (list-var element)
179   "Add to the value of LIST-VAR the element ELEMENT if it isn't there yet.
180 If you want to use `add-to-list' on a variable that is not defined
181 until a certain package is loaded, you should put the call to `add-to-list'
182 into a hook function that will be run only after loading the package.
183 \[Emacs 19.30 emulating function]"
184   (or (member element (symbol-value list-var))
185       (set list-var (cons element (symbol-value list-var)))))
186
187 (cond ((fboundp 'insert-file-contents-literally))
188       ((boundp 'file-name-handler-alist)
189        (defun insert-file-contents-literally
190          (filename &optional visit beg end replace)
191          "Like `insert-file-contents', q.v., but only reads in the file.
192 A buffer may be modified in several ways after reading into the buffer due
193 to advanced Emacs features, such as file-name-handlers, format decoding,
194 find-file-hooks, etc.
195   This function ensures that none of these modifications will take place.
196 \[Emacs 19.30 emulating function]"
197          (let (file-name-handler-alist)
198            (insert-file-contents filename visit beg end replace)))
199        )
200       (t
201        (defalias 'insert-file-contents-literally 'insert-file-contents)
202        ))
203
204
205 ;;; @ Emacs 19.31 emulation
206 ;;;
207
208 (defun-maybe buffer-live-p (object)
209   "Return non-nil if OBJECT is a buffer which has not been killed.
210 Value is nil if OBJECT is not a buffer or if it has been killed.
211 \[Emacs 19.31 emulating function]"
212   (and object
213        (get-buffer object)
214        (buffer-name (get-buffer object))))
215
216 ;; imported from Emacs 19.33.
217 (defmacro-maybe save-selected-window (&rest body)
218   "Execute BODY, then select the window that was selected before BODY.
219 \[Emacs 19.31 emulating function]"
220   (list 'let
221         '((save-selected-window-window (selected-window)))
222         (list 'unwind-protect
223               (cons 'progn body)
224               (list 'select-window 'save-selected-window-window))))
225
226
227 ;;; @ Emacs 20.1 emulation
228 ;;;
229
230 ;; imported from Emacs 20.2.
231 (defmacro-maybe when (cond &rest body)
232   "(when COND BODY...): if COND yields non-nil, do BODY, else return nil."
233   (list 'if cond (cons 'progn body)))
234
235 ;; imported from Emacs 20.3.
236 (defmacro-maybe unless (cond &rest body)
237   "(unless COND BODY...): if COND yields nil, do BODY, else return nil."
238   (cons 'if (cons cond (cons nil body))))
239
240 (defmacro-maybe save-current-buffer (&rest body)
241   "Save the current buffer; execute BODY; restore the current buffer.
242 Executes BODY just like `progn'."
243   (` (let ((orig-buffer (current-buffer)))
244        (unwind-protect
245            (progn (,@ body))
246          (set-buffer orig-buffer)))))
247
248 ;; imported from Emacs 20.2.
249 (defmacro-maybe with-current-buffer (buffer &rest body)
250   "Execute the forms in BODY with BUFFER as the current buffer.
251 The value returned is the value of the last form in BODY.
252 See also `with-temp-buffer'."
253   (` (save-current-buffer
254        (set-buffer (, buffer))
255        (,@ body))))
256
257 ;; imported from Emacs 20.2.
258 (defmacro-maybe with-temp-file (file &rest forms)
259   "Create a new buffer, evaluate FORMS there, and write the buffer to FILE.
260 The value of the last form in FORMS is returned, like `progn'.
261 See also `with-temp-buffer'."
262   (let ((temp-file (make-symbol "temp-file"))
263         (temp-buffer (make-symbol "temp-buffer")))
264     (` (let (((, temp-file) (, file))
265              ((, temp-buffer)
266               (get-buffer-create (generate-new-buffer-name " *temp file*"))))
267          (unwind-protect
268              (prog1
269                  (with-current-buffer (, temp-buffer)
270                    (,@ forms))
271                (with-current-buffer (, temp-buffer)
272                  (widen)
273                  (write-region (point-min) (point-max) (, temp-file) nil 0)))
274            (and (buffer-name (, temp-buffer))
275                 (kill-buffer (, temp-buffer))))))))
276
277 ;; imported from Emacs 20.2.
278 (defmacro-maybe with-temp-buffer (&rest forms)
279   "Create a temporary buffer, and evaluate FORMS there like `progn'.
280 See also `with-temp-file' and `with-output-to-string'."
281   (let ((temp-buffer (make-symbol "temp-buffer")))
282     (` (let (((, temp-buffer)
283               (get-buffer-create (generate-new-buffer-name " *temp*"))))
284          (unwind-protect
285              (with-current-buffer (, temp-buffer)
286                (,@ forms))
287            (and (buffer-name (, temp-buffer))
288                 (kill-buffer (, temp-buffer))))))))
289
290 ;; imported from Emacs 20.3.
291 (defun-maybe last (x &optional n)
292   "Return the last link of the list X.  Its car is the last element.
293 If X is nil, return nil.
294 If N is non-nil, return the Nth-to-last link of X.
295 If N is bigger than the length of X, return X."
296   (if n
297       (let ((m 0) (p x))
298         (while (consp p)
299           (setq m (1+ m) p (cdr p)))
300         (if (<= n 0) p
301           (if (< n m) (nthcdr (- m n) x) x)))
302     (while (cdr x)
303       (setq x (cdr x)))
304     x))
305
306 ;; imported from Emacs 20.3. (cl function)
307 (defun-maybe butlast (x &optional n)
308   "Returns a copy of LIST with the last N elements removed."
309   (if (and n (<= n 0)) x
310     (nbutlast (copy-sequence x) n)))
311
312 ;; imported from Emacs 20.3. (cl function)
313 (defun-maybe nbutlast (x &optional n)
314   "Modifies LIST to remove the last N elements."
315   (let ((m (length x)))
316     (or n (setq n 1))
317     (and (< n m)
318          (progn
319            (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil))
320            x))))
321
322 ;; imported from XEmacs 21.
323 (defun-maybe split-string (string &optional pattern)
324   "Return a list of substrings of STRING which are separated by PATTERN.
325 If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
326   (or pattern
327       (setq pattern "[ \f\t\n\r\v]+"))
328   ;; The FSF version of this function takes care not to cons in case
329   ;; of infloop.  Maybe we should synch?
330   (let (parts (start 0))
331     (while (string-match pattern string start)
332       (setq parts (cons (substring string start (match-beginning 0)) parts)
333             start (match-end 0)))
334     (nreverse (cons (substring string start) parts))))
335
336
337 ;;; @ Emacs 20.3 emulation
338 ;;;
339
340 ;; imported from Emacs 20.3.91.
341 (defvar-maybe temporary-file-directory
342   (file-name-as-directory
343    (cond ((memq system-type '(ms-dos windows-nt))
344           (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
345          ((memq system-type '(vax-vms axp-vms))
346           (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "SYS$SCRATCH:"))
347          (t
348           (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
349   "The directory for writing temporary files.")
350
351 (defun-maybe line-beginning-position (&optional n)
352   "Return the character position of the first character on the current line.
353 With argument N not nil or 1, move forward N - 1 lines first.
354 If scan reaches end of buffer, return that position.
355 This function does not move point."
356   (save-excursion
357     (if n
358         (forward-line (1- n))
359       )
360     (beginning-of-line)
361     (point)))
362
363 (defun-maybe line-end-position (&optional n)
364   "Return the character position of the last character on the current line.
365 With argument N not nil or 1, move forward N - 1 lines first.
366 If scan reaches end of buffer, return that position.
367 This function does not move point."
368   (save-excursion
369     (if n
370         (forward-line (1- n))
371       )
372     (end-of-line)
373     (point)))
374
375 (defun-maybe string (&rest chars)
376   "Concatenate all the argument characters and make the result a string."
377   (mapconcat (function char-to-string) chars "")
378   )
379
380     
381 ;;; @ XEmacs emulation
382 ;;;
383
384 (defun-maybe find-face (face-or-name)
385   "Retrieve the face of the given name.
386 If FACE-OR-NAME is a face object, it is simply returned.
387 Otherwise, FACE-OR-NAME should be a symbol.  If there is no such face,
388 nil is returned.  Otherwise the associated face object is returned.
389 \[XEmacs emulating function]"
390   (car (memq face-or-name (face-list)))
391   )
392
393 (defun-maybe point-at-bol (&optional n buffer)
394   "Return the character position of the first character on the current line.
395 With argument N not nil or 1, move forward N - 1 lines first.
396 If scan reaches end of buffer, return that position.
397 This function does not move point. [XEmacs emulating function]"
398   (save-excursion
399     (if buffer
400         (set-buffer buffer)
401       )
402     (line-beginning-position n)
403     ))
404
405 (defun-maybe point-at-eol (&optional n buffer)
406   "Return the character position of the last character on the current line.
407 With argument N not nil or 1, move forward N - 1 lines first.
408 If scan reaches end of buffer, return that position.
409 This function does not move point. [XEmacs emulating function]"
410   (save-excursion
411     (if buffer
412         (set-buffer buffer)
413       )
414     (line-end-position n)
415     ))
416
417 (defun-maybe functionp (obj)
418   "Returns t if OBJ is a function, nil otherwise.
419 \[XEmacs emulating function]"
420   (or (subrp obj)
421       (byte-code-function-p obj)
422       (and (symbolp obj)(fboundp obj))
423       (and (consp obj)(eq (car obj) 'lambda))
424       ))
425
426 (defsubst-maybe define-obsolete-function-alias (oldfun newfun)
427   "Define OLDFUN as an obsolete alias for function NEWFUN.
428 This makes calling OLDFUN equivalent to calling NEWFUN and marks OLDFUN
429 as obsolete. [XEmacs emulating function]"
430   (defalias oldfun newfun)
431   (make-obsolete oldfun newfun)
432   )
433
434
435 ;;; @ end
436 ;;;
437
438 (provide 'poe)
439
440 ;;; poe.el ends here