d30d8a5381b9e58a7247984ac7309b9b3279c610
[chise/xemacs-chise.git.1] / lisp / win32-native.el
1 ;;; win32-native.el --- Lisp routines for MS Windows.
2
3 ;; Copyright (C) 1994 Free Software Foundation, Inc.
4 ;; Copyright (C) 2000 Ben Wing.
5
6 ;; Maintainer: XEmacs Development Team
7 ;; Keywords: mouse, dumped
8
9 ;; This file is part of XEmacs.
10
11 ;; XEmacs is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; XEmacs is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ;; General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Synched up with: Not synched with FSF.  Almost completely divergent.
27 ;;; (FSF has stuff in w32-fns.el and term/w32-win.el.)
28
29 ;;; Commentary:
30
31 ;; This file is dumped with XEmacs for MS Windows (without cygwin).
32
33 ;; Based on NT Emacs version by Geoff Voelker (voelker@cs.washington.edu)
34 ;; Ported to XEmacs by Marc Paquette <marcpa@cam.org>
35 ;; Largely modified by Kirill M. Katsnelson <kkm@kis.ru>
36
37 ;;; Code:
38
39 ;; The cmd.exe shell uses the "/c" switch instead of the "-c" switch
40 ;; for executing its command line argument (from simple.el).
41 ;; #### Oh if we had an alist of shells and their command switches.
42 (setq shell-command-switch "/c")
43
44 ;; For appending suffixes to directories and files in shell
45 ;; completions.  This screws up cygwin users so we leave it out for
46 ;; now. Uncomment this if you only ever want to use cmd.
47
48 ;(defun nt-shell-mode-hook ()
49 ;  (setq comint-completion-addsuffix '("\\" . " ")
50 ;       comint-process-echoes t))
51 ;(add-hook 'shell-mode-hook 'nt-shell-mode-hook)
52
53 ;; Use ";" instead of ":" as a path separator (from files.el).
54 (setq path-separator ";")
55
56 ;; Set the null device (for compile.el).
57 ;; #### There should be such a global thingy as null-device - kkm
58 (setq grep-null-device "NUL")
59
60 ;; Set the grep regexp to match entries with drive letters.
61 (setq grep-regexp-alist
62   '(("^\\(\\([a-zA-Z]:\\)?[^:( \t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 3)))
63
64 ;;----------------------------------------------------------------------
65 ;; Quoting process args
66 ;;--------------------
67
68 (defvar debug-mswindows-process-command-lines nil
69   "If non-nil, output debug information about the command lines constructed.
70 This can be useful if you are getting process errors where the arguments
71 to the process appear to be getting passed incorrectly.")
72
73 ;; properly quotify one arg for the vc runtime argv constructor.
74 (defun mswindows-quote-one-vc-runtime-arg (arg &optional quote-shell)
75   ;; we mess with any arg with whitespace, quotes, or globbing chars in it.
76   ;; we also include shell metachars if asked.
77   ;; note that \ is NOT included!  it's perfectly OK to include an
78   ;; arg like c:\ or c:\foo.
79   (if (string-match (if quote-shell "[ \t\n\r\f*?\"<>|&^%]" "[ \t\n\r\f*?\"]")
80                     arg)
81       (progn
82         ;; handle nested quotes, possibly preceded by backslashes
83         (setq arg (replace-in-string arg "\\([\\]*\\)\"" "\\1\\1\\\\\""))
84         ;; handle trailing backslashes
85         (setq arg (replace-in-string arg "\\([\\]+\\)$" "\\1\\1"))
86         (concat "\"" arg "\""))
87     arg))
88
89 (defun mswindows-quote-one-simple-arg (arg &optional quote-shell)
90   ;; just put double quotes around args with spaces (and maybe shell
91   ;; metachars).
92   (if (string-match (if quote-shell "[ \t\n\r\f*?\"<>|&^%]" "[ \t\n\r\f*?]")
93                     arg)
94       (concat "\"" arg "\"")
95     arg))
96
97 (defun mswindows-quote-one-command-arg (arg)
98   ;; quote an arg to get it past COMMAND.COM/CMD.EXE: need to quote shell
99   ;; metachars with ^.
100   (replace-in-string "[<>|&^%]" "^\\1" arg))
101
102 (defun mswindows-construct-verbatim-command-line (program args)
103   (mapconcat #'identity args " "))
104
105 ;; for use with either standard VC++ compiled programs or Cygwin programs,
106 ;; which emulate the same behavior.
107 (defun mswindows-construct-vc-runtime-command-line (program args)
108   (mapconcat #'mswindows-quote-one-vc-runtime-arg args " "))
109
110 ;; note: for pulling apart an arg:
111 ;; each arg consists of either
112
113 ;; something surrounded by single quotes
114
115 ;; or
116
117 ;; one or more of
118
119 ;; 1. a non-ws, non-" char
120 ;; 2. a section of double-quoted text
121 ;; 3. a section of double-quoted text with end-of-string instead of the final
122 ;; quote.
123
124 ;; 2 and 3 get handled together.
125
126 ;; quoted text is one of
127 ;;
128 ;; 1. quote + even number of backslashes + quote, or
129 ;; 2. quote + non-greedy anything + non-backslash + even number of
130 ;;    backslashes + quote.
131
132 ;; we need to separate the two because we unfortunately have no non-greedy
133 ;; ? operator. (urk! we actually do, but it wasn't documented.) --ben
134
135 ;; if you want to mess around, keep this test case in mind:
136
137 ;; this string
138
139 ;; " as'f 'FOO BAR' '' \"\" \"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\" foo\" "
140
141 ;; should tokenize into this:
142
143 ;; (" " "as'f" " " "'FOO BAR' " "'' " "\"\"" " " "\"asdf \\ \\\" \\\\\\\" asdfasdf\\\\\"" " " "foo" "\" ")
144
145 ;; this regexp actually separates the arg into individual args, like a
146 ;; shell (such as sh) does, but using vc-runtime rules.  it's easy to
147 ;; derive the tokenizing regexp from it, and that's exactly what i did.
148 ;; but oh was it hard to get this first regexp right. --ben
149 ;(defvar mswindows-match-one-cmd-exe-arg-regexp
150 ;  (concat
151 ;   "^\\("
152 ;   "'\\([\\]*\\)\\2'" "\\|"
153 ;   "'.*?[^\\]\\(\\([\\]*\\)\\4'\\)" "\\|"
154 ;   "\\("
155 ;   "[^ \t\n\r\f\v\"]" "\\|"
156 ;   "\"\\([\\]*\\)\\6\"" "\\|"
157 ;   "\".*?[^\\]\\(\\([\\]*\\)\\8\"\\|$\\)"
158 ;   "\\)+"
159 ;   "\\)"
160 ;   "\\([ \t\n\r\f\v]+\\|$\\)"))
161
162 (defvar mswindows-match-one-cmd-exe-token-regexp
163   (concat
164    "^\\("
165    "[ \t\n\r\f\v]+" "\\|"
166    "'\\([\\]*\\)\\2'" "\\([ \t\n\r\f\v]+\\|$\\)" "\\|"
167    "'.*?[^\\]\\(\\([\\]*\\)\\5'\\)" "\\([ \t\n\r\f\v]+\\|$\\)" "\\|"
168    "[^ \t\n\r\f\v\"]+" "\\|"
169    "\"\\([\\]*\\)\\7\"" "\\|"
170    "\".*?[^\\]\\(\\([\\]*\\)\\9\"\\|$\\)"
171    "\\)"))
172
173 (defun mswindows-construct-command-command-line (program args)
174   ;; for use with COMMAND.COM and CMD.EXE:
175   ;; for each arg, tokenize it into quoted and non-quoted sections;
176   ;; then quote all the shell meta-chars with ^; then put everything
177   ;; back together.  the truly hard part is the tokenizing -- typically
178   ;; we get a single argument (the command to execute) and we have to
179   ;; worry about quotes that are backslash-quoted and such.
180   (mapconcat
181    #'(lambda (arg)
182        (mapconcat
183         #'(lambda (part)
184             (if (string-match "^'" part)
185                 (replace-in-string part "\\([<>|^&%]\\)" "^\\1")
186               part))
187         (let (parts)
188           (while (and (> (length arg) 0)
189                       (string-match
190                        mswindows-match-one-cmd-exe-token-regexp
191                        arg))
192             (push (match-string 0 arg) parts)
193             (setq arg (substring arg (match-end 0))))
194           (if (> (length arg) 0)
195               (push arg parts))
196           (nreverse parts))
197         ""))
198    args " "))
199
200 (defvar mswindows-construct-process-command-line-alist
201   '(("[\\/].?.?sh\\." . mswindows-construct-verbatim-command-line)
202     ("[\\/]command\\.com$" . mswindows-construct-command-command-line)
203     ("[\\/]cmd\\.exe$" . mswindows-construct-command-command-line)
204     ("" . mswindows-construct-vc-runtime-command-line))
205   "An alist for determining proper argument quoting given executable
206 file name.  Car of each cons should be a string, a regexp against
207 which the file name is matched.  Matching is case-insensitive but does
208 include the directory, so you should begin your regexp with [\\\\/] if
209 you don't want the directory to matter.  Alternatively, the car can be
210 a function of one arg, which is called with the executable's name and
211 should return t if this entry should be processed.  Cdr is a function
212 symbol, which is called with two args, the executable name and a list
213 of the args passed to it.  It should return a string, which includes
214 the executable's args (but not the executable name itself) properly
215 quoted and pasted together.  The list is matched in order, and the
216 first matching entry specifies how the processing will happen.")
217
218 (defun mswindows-construct-process-command-line (args)
219   ;;Properly quote process ARGS for executing (car ARGS).
220   ;;Called from the C code.
221   (let ((fname (car args))
222         (alist mswindows-construct-process-command-line-alist)
223         (case-fold-search t)
224         (return-me nil)
225         (assoc nil))
226     (while (and alist
227                 (null return-me))
228       (setq assoc (pop alist))
229       (if (if (stringp (car assoc))
230               (string-match (car assoc) fname)
231             (funcall (car assoc) fname))
232           (setq return-me (cdr assoc))))
233     (let* ((called-fun (or return-me
234                             #'mswindows-construct-vc-runtime-command-line))
235            (retval
236             (let ((str (funcall called-fun fname (cdr args)))
237                   (quoted-fname (mswindows-quote-one-simple-arg fname)))
238               (if (and str (> (length str) 0))
239                   (concat quoted-fname " " str)
240                 quoted-fname))))
241       (when debug-mswindows-process-command-lines
242         (debug-print "mswindows-construct-process-command-line called:\n")
243         (debug-print "received args: \n%s"
244                      (let ((n -1))
245                        (mapconcat #'(lambda (arg)
246                                       (incf n)
247                                       (format "  %d %s\n" n arg))
248                                   args
249                                   "")))
250         (debug-print "called fun %s\n" called-fun)
251         (debug-print "resulting command line: %s\n" retval))
252       retval)))
253
254 ;;; win32-native.el ends here