Initial Commit
[packages] / xemacs-packages / ess / lisp / ess-emcs.el
1 ;;; ess-emcs.el --- simple determination of Emacs/XEmacs and version #.
2
3 ;; Copyright (C) 2000--2005 A.J. Rossini, Rich M. Heiberger, Martin
4 ;;      Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
5
6 ;; Original Author: A.J. Rossini <rossini@biostat.washington.edu>
7 ;; Created: 07 June 2000
8 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
9
10 ;; Keywords: start up, configuration.
11
12 ;; This file is part of ESS
13
14 ;; This file is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; any later version.
18
19 ;; This file is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING.  If not, write to
26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27
28 ;;; Commentary:
29
30 ;; This file contains functions for easily determining features of the
31 ;; version of Emacs that we are using.   In particular, it look for
32 ;; version number, customize support, as well as Emacs/XEmacs, for
33 ;; flaggin support later on.
34
35 ;;; Code:
36
37 ;; Older versions of emacs did not have these variables
38 ;; (emacs-major-version and emacs-minor-version.)
39 ;; Let's define them if they're not around, since they make
40 ;; it much easier to conditionalize on the emacs version.
41
42 (if (and (not (boundp 'emacs-major-version))
43          (string-match "^[0-9]+" emacs-version))
44     (setq emacs-major-version
45           (string-to-int (substring emacs-version
46                                     (match-beginning 0) (match-end 0)))))
47 (if (and (not (boundp 'emacs-minor-version))
48          (string-match "^[0-9]+\\.\\([0-9]+\\)" emacs-version))
49     (setq emacs-minor-version
50           (string-to-int (substring emacs-version
51                                     (match-beginning 1) (match-end 1)))))
52
53 ;;; Define a function to make it easier to check which version we're
54 ;;; running.
55
56 (defun ess-running-emacs-version-or-newer (major minor)
57   (or (> emacs-major-version major)
58       (and (= emacs-major-version major)
59            (>= emacs-minor-version minor))))
60
61 ;(defvar ess-running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
62
63 (defvar ess-local-custom-available (featurep 'custom)
64   "Value is nil if custom.el not available, t if available.
65 Only a concern with earlier versions of Emacs.")
66
67 ;; FIXME:  When emacs is started from Cygwin shell in Windows,
68 ;;         we have (equal window-system 'x) -and should use "--ess" in *d-r.el
69 (defvar ess-microsoft-p (or (equal window-system 'w32)
70                             ;; XEmacs only...
71 ;;;                         (equal (console-type) 'pc)
72 ;;;                         (equal (console-type) 'mswindows)
73                             (equal window-system 'win32)
74                             (equal window-system 'mswindows))
75   "Value is t if the OS is one of Microsoft's, nil otherwise.")
76
77
78 ;; These definitions are for Emacs versions < 20.4 or XEmacs
79 ;; These are taken verbatim from the file emacs-20.6/lisp/w32-fns.el
80 ;;
81 ;; Note: 20.3 and 19.x NTemacs users are strongly encouraged to upgrade to
82 ;; version 20.4 or higher.  NTemacs 20.2 is not supported by ESS.
83
84 ;; XEmacs 20.x needs this
85 (if (not (fboundp 'find-buffer-visiting))
86     (fset 'find-buffer-visiting 'get-file-buffer))
87 ;; XEmacs <= 21.4.15 needs this
88 (if (not (fboundp 'line-beginning-position))
89     (defalias 'line-beginning-position 'point-at-bol))
90
91 (if (and (not (featurep 'xemacs))
92          (string-match "XEmacs\\|Lucid" emacs-version))
93     (provide 'xemacs))
94
95 ;; XEmacs 21.x and Emacs 20.x need this
96 (cond ((fboundp 'replace-regexp-in-string)
97        (defalias 'ess-replace-regexp-in-string 'replace-regexp-in-string))
98       ((featurep 'xemacs)
99         (defun ess-replace-regexp-in-string(regexp replace string)
100           "Mimic GNU Emacs function replace-regexp-in-string with XEmacs' replace-in-string"
101           (replace-in-string string regexp replace)))
102
103       ;; GNU emacs <= 20 -- take Emacs' 21(.3)'s definition:
104       (t (defun ess-replace-regexp-in-string (regexp rep string &optional
105                                               fixedcase literal subexp start)
106         "Replace all matches for REGEXP with REP in STRING.
107
108 Return a new string containing the replacements.
109
110 Optional arguments FIXEDCASE, LITERAL and SUBEXP are like the
111 arguments with the same names of function `replace-match'.  If START
112 is non-nil, start replacements at that index in STRING.
113
114 REP is either a string used as the NEWTEXT arg of `replace-match' or a
115 function.  If it is a function it is applied to each match to generate
116 the replacement passed to `replace-match'; the match-data at this
117 point are such that match 0 is the function's argument.
118
119 To replace only the first match (if any), make REGEXP match up to \\'
120 and replace a sub-expression, e.g.
121   (ess-replace-regexp-in-string \"\\(foo\\).*\\'\" \"bar\" \" foo foo\" nil nil 1)
122     => \" bar foo\"
123 "
124
125         ;; To avoid excessive consing from multiple matches in long strings,
126         ;; don't just call `replace-match' continually.  Walk down the
127         ;; string looking for matches of REGEXP and building up a (reversed)
128         ;; list MATCHES.  This comprises segments of STRING which weren't
129         ;; matched interspersed with replacements for segments that were.
130         ;; [For a `large' number of replacments it's more efficient to
131         ;; operate in a temporary buffer; we can't tell from the function's
132         ;; args whether to choose the buffer-based implementation, though it
133         ;; might be reasonable to do so for long enough STRING.]
134         (let ((l (length string))
135               (start (or start 0))
136               matches str mb me)
137           (save-match-data
138             (while (and (< start l) (string-match regexp string start))
139               (setq mb (match-beginning 0)
140                     me (match-end 0))
141               ;; If we matched the empty string, make sure we advance by one char
142               (when (= me mb) (setq me (min l (1+ mb))))
143               ;; Generate a replacement for the matched substring.
144               ;; Operate only on the substring to minimize string consing.
145               ;; Set up match data for the substring for replacement;
146               ;; presumably this is likely to be faster than munging the
147               ;; match data directly in Lisp.
148               (string-match regexp (setq str (substring string mb me)))
149               (setq matches
150                     (cons (replace-match (if (stringp rep)
151                                              rep
152                                            (funcall rep (match-string 0 str)))
153                                          fixedcase literal str subexp)
154                           (cons (substring string start mb) ; unmatched prefix
155                                 matches)))
156               (setq start me))
157             ;; Reconstruct a string from the pieces.
158             (setq matches (cons (substring string start l) matches)) ; leftover
159             (apply #'concat (nreverse matches)))))
160       )
161 )
162
163 ;; remassoc exists as a built-in function in xemacs, but
164 ;; not in GNU emacs
165 ;;
166 (if (not (functionp 'remassoc))
167     (defun remassoc (key a)
168       "remove an association pair from an alist"
169       (if a
170           (let ((pair (car a)))
171             (if (equal (car pair) key)
172                 (cdr a)
173                 (cons pair (remassoc key (cdr a))))))))
174
175 (if (not (fboundp 'w32-using-nt))
176 (defun w32-using-nt ()
177   "Return non-nil if literally running on Windows NT (i.e., not Windows 9X)."
178   (and (eq system-type 'windows-nt) (getenv "SystemRoot"))))
179
180 (if (and (featurep 'xemacs)
181          (fboundp 'extent-at)
182          (fboundp 'make-extent)
183          (fboundp 'set-extent-property))
184   (defun ess-xemacs-insert-glyph (gl)
185      "Insert a glyph at the left edge of point."
186      (let ((prop 'myimage) ;; myimage is an arbitrary name, chosen to
187            ;;                 (hopefully) not conflict with any other
188            ;;                 properties. Change it if necessary.
189             extent)
190        ;; First, check to see if one of our extents already exists at
191        ;; point.  For ease-of-programming, we are creating and using our
192        ;; own extents (multiple extents are allowed to exist/overlap at the
193        ;; same point, and it's quite possible for other applications to
194        ;; embed extents in the current buffer without your knowledge).
195        ;; Basically, if an extent, with the property stored in "prop",
196        ;; exists at point, we assume that it is one of ours, and we re-use
197        ;; it (this is why it is important for the property stored in "prop"
198        ;; to be unique, and only used by us).
199        (if (not (setq extent (extent-at (point) (current-buffer) prop)))
200          (progn
201            ;; If an extent does not already exist, create a zero-length
202            ;; extent, and give it our special property.
203            (setq extent (make-extent (point) (point) (current-buffer)))
204            (set-extent-property extent prop t)
205            ))
206        ;; Display the glyph by storing it as the extent's "begin-glyph".
207        (set-extent-property extent 'begin-glyph gl))))
208
209 ;; XEmacs and NTemacs 19.x need these
210 (if (not (boundp 'w32-system-shells))
211       (defvar w32-system-shells '("cmd" "cmd.exe" "command" "command.com"
212                                   "4nt" "4nt.exe" "4dos" "4dos.exe"
213                                   "ndos" "ndos.exe")
214         "List of strings recognized as Windows NT/9X system shells.")
215 )
216
217 (if (not (fboundp 'w32-system-shell-p))
218       (defun w32-system-shell-p (shell-name)
219         (and shell-name
220              (member (downcase (file-name-nondirectory shell-name))
221                      w32-system-shells)))
222 )
223
224 (if (not (fboundp 'w32-shell-name))
225       (defun w32-shell-name ()
226         "Return the name of the shell being used."
227         (or (and (boundp 'explicit-shell-file-name) explicit-shell-file-name)
228             (getenv "ESHELL")
229             (getenv "SHELL")
230             (and (w32-using-nt) "cmd.exe")
231             "command.com"))
232 )
233
234 ;; XEmacs and NTemacs 20.3 need this
235 (if (not (fboundp 'w32-shell-dos-semantics)) (defun w32-shell-dos-semantics ()
236   "Return t if the interactive shell being used expects msdos shell semantics."
237   (or (w32-system-shell-p (w32-shell-name))
238       (and (member (downcase (file-name-nondirectory (w32-shell-name)))
239                    '("cmdproxy" "cmdproxy.exe"))
240            (w32-system-shell-p (getenv "COMSPEC")))))
241 )
242
243 ;; XEmacs need this (unless configured with  --with-mule=yes)
244 (if (not (boundp 'enable-multibyte-characters))
245     (defvar enable-multibyte-characters nil
246       "Non-nil means the buffer contents are regarded as multi-byte characters.
247  This concept is handled completely differently on Xemacs."))
248
249
250 ;; XEmacs on Windows needs this
251 (if (and ess-microsoft-p
252          (not (fboundp 'w32-short-file-name)))
253     (fset 'w32-short-file-name 'win32-short-file-name))
254
255 (provide 'ess-emcs)
256
257 \f ; Local variables section
258
259 ;;; This file is automatically placed in Outline minor mode.
260 ;;; The file is structured as follows:
261 ;;; Chapters:     ^L ;
262 ;;; Sections:    ;;*;;
263 ;;; Subsections: ;;;*;;;
264 ;;; Components:  defuns, defvars, defconsts
265 ;;;              Random code beginning with a ;;;;* comment
266 ;;; Local variables:
267 ;;; mode: emacs-lisp
268 ;;; mode: outline-minor
269 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
270 ;;; End:
271
272 ;;; ess-emcs.el ends here