comparison src/win32.c @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents a307f9a2021d
children a634e3b7acc8
comparison
equal deleted inserted replaced
770:336a418893b5 771:943eaba38521
1 /* Utility routines for XEmacs on Windows 9x, NT and Cygwin. 1 /* Utility routines for XEmacs on Windows 9x, NT and Cygwin.
2 Copyright (C) 2000 Ben Wing. 2 Copyright (C) 2000, 2001, 2002 Ben Wing.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify it 6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the 7 under the terms of the GNU General Public License as published by the
20 20
21 #include <config.h> 21 #include <config.h>
22 #include "lisp.h" 22 #include "lisp.h"
23 23
24 #include "buffer.h" 24 #include "buffer.h"
25 25 #include "console-msw.h"
26
27 #include "sysfile.h"
28 #include "sysproc.h"
26 #include "syssignal.h" 29 #include "syssignal.h"
27 #include "systime.h" 30 #include "systime.h"
28 #include "syswindows.h" 31
29 32 /* Control conversion of upper case file names to lower case.
30 typedef BOOL (WINAPI *pfSwitchToThread_t) (VOID); 33 nil means no, t means yes. */
34 Lisp_Object Vmswindows_downcase_file_names;
35
36 int mswindows_windows9x_p;
37
31 pfSwitchToThread_t xSwitchToThread; 38 pfSwitchToThread_t xSwitchToThread;
32 39
33 typedef HKL (WINAPI *pfGetKeyboardLayout_t) (DWORD);
34 pfGetKeyboardLayout_t xGetKeyboardLayout;
35 typedef BOOL (WINAPI *pfSetMenuDefaultItem_t) (HMENU, UINT, UINT);
36 pfSetMenuDefaultItem_t xSetMenuDefaultItem;
37 typedef BOOL (WINAPI *pfInsertMenuItemA_t)
38 (HMENU, UINT, BOOL, LPCMENUITEMINFOA);
39 pfInsertMenuItemA_t xInsertMenuItemA;
40 typedef BOOL (WINAPI *pfInsertMenuItemW_t)
41 (HMENU, UINT, BOOL, LPCMENUITEMINFOW);
42 pfInsertMenuItemW_t xInsertMenuItemW;
43 typedef HANDLE (WINAPI *pfLoadImageA_t)
44 (HINSTANCE, LPCSTR, UINT, int, int, UINT);
45 pfLoadImageA_t xLoadImageA;
46 typedef HANDLE (WINAPI *pfLoadImageW_t)
47 (HINSTANCE, LPCWSTR, UINT, int, int, UINT);
48 pfLoadImageW_t xLoadImageW;
49 typedef ATOM (WINAPI *pfRegisterClassExA_t) (CONST WNDCLASSEXA *);
50 pfRegisterClassExA_t xRegisterClassExA;
51 typedef ATOM (WINAPI *pfRegisterClassExW_t) (CONST WNDCLASSEXW *);
52 pfRegisterClassExW_t xRegisterClassExW;
53
54 typedef int (WINAPI *pfEnumFontFamiliesExA_t)
55 (HDC, LPLOGFONTA, FONTENUMPROCA, LPARAM, DWORD);
56 pfEnumFontFamiliesExA_t xEnumFontFamiliesExA;
57 typedef int (WINAPI *pfEnumFontFamiliesExW_t)
58 (HDC, LPLOGFONTW, FONTENUMPROCW, LPARAM, DWORD);
59 pfEnumFontFamiliesExW_t xEnumFontFamiliesExW;
60
61 typedef DWORD (WINAPI *pfSHGetFileInfoA_t)
62 (LPCSTR, DWORD, SHFILEINFOA FAR *, UINT, UINT);
63 pfSHGetFileInfoA_t xSHGetFileInfoA;
64 typedef DWORD (WINAPI *pfSHGetFileInfoW_t)
65 (LPCWSTR, DWORD, SHFILEINFOW FAR *, UINT, UINT);
66 pfSHGetFileInfoW_t xSHGetFileInfoW;
67
68 typedef NET_API_STATUS (NET_API_FUNCTION *pfNetUserEnum_t)
69 (
70 IN LPCWSTR servername OPTIONAL,
71 IN DWORD level,
72 IN DWORD filter,
73 OUT LPBYTE *bufptr,
74 IN DWORD prefmaxlen,
75 OUT LPDWORD entriesread,
76 OUT LPDWORD totalentries,
77 IN OUT LPDWORD resume_handle OPTIONAL
78 );
79 pfNetUserEnum_t xNetUserEnum; 40 pfNetUserEnum_t xNetUserEnum;
80
81 typedef NET_API_STATUS (NET_API_FUNCTION *pfNetApiBufferFree_t)
82 (
83 IN LPVOID Buffer
84 );
85 pfNetApiBufferFree_t xNetApiBufferFree; 41 pfNetApiBufferFree_t xNetApiBufferFree;
42
43 /* Convert a filename in standard Win32 format into our internal format
44 (which may be significantly different if we're running on Cygwin), and
45 turn it into a file: URL. Return a newly malloc()ed string.
46
47 #### This comes from code that just prepended `file:', which is not
48 good. See comment in mswindows_dde_callback(), case XTYP_EXECUTE.
49 */
50 Intbyte *
51 urlify_filename (Intbyte *filename)
52 {
53 Intbyte *pseudo_url;
54
55 WIN32_TO_LOCAL_FILE_FORMAT (filename, filename);
56 pseudo_url = xnew_array (Intbyte, 5 + qxestrlen (filename) + 1);
57 qxestrcpy_c (pseudo_url, "file:");
58 qxestrcat (pseudo_url, filename);
59 /* URL's only have /, no backslash */
60 for (filename = pseudo_url; *filename; filename++)
61 {
62 if (*filename == '\\')
63 *filename = '/';
64 }
65
66 return pseudo_url;
67 }
86 68
87 Lisp_Object 69 Lisp_Object
88 tstr_to_local_file_format (Extbyte *pathout) 70 tstr_to_local_file_format (Extbyte *pathout)
89 { 71 {
90 Intbyte *ttlff; 72 Intbyte *ttlff;
91 Lisp_Object in; 73
92 74 TSTR_TO_C_STRING (pathout, ttlff);
93 EXTERNAL_TO_C_STRING (pathout, ttlff, Qmswindows_tstr); 75 WIN32_TO_LOCAL_FILE_FORMAT (ttlff, ttlff);
94 WIN32_TO_LOCAL_FILE_FORMAT (ttlff, in); 76
95 77 return build_intstring (ttlff);
96 return in; 78 }
79
80 /* Normalize filename by converting all path separators to the specified
81 separator. Also conditionally convert all-upper-case path name
82 components to lower case. Return a newly malloc()ed string.
83 */
84
85 Intbyte *
86 mswindows_canonicalize_filename (Intbyte *name)
87 {
88 Intbyte *fp = name;
89 DECLARE_EISTRING (newname);
90 DECLARE_EISTRING (component);
91 int do_casefrob = 1;
92
93 /* Always lower-case drive letters a-z, even if the filesystem
94 preserves case in filenames.
95 This is so filenames can be compared by string comparison
96 functions that are case-sensitive. Even case-preserving filesystems
97 do not distinguish case in drive letters. */
98 if (name[0] >= 'A' && name[0] <= 'Z' && name[1] == ':')
99 {
100 eicat_ch (newname, name[0] + 'a' - 'A');
101 eicat_ch (newname, ':');
102 fp += 2;
103 }
104
105 while (1)
106 {
107 Emchar ch = charptr_emchar (fp);
108 if (LOWERCASEP (0, ch))
109 do_casefrob = 0; /* don't convert this element */
110
111 if (ch == 0 || IS_ANY_SEP (ch))
112 {
113 if (do_casefrob && !NILP (Vmswindows_downcase_file_names))
114 eilwr (component);
115 do_casefrob = 1;
116 eicat_ei (newname, component);
117 eireset (component);
118 if (IS_DIRECTORY_SEP (ch))
119 eicat_ch (newname, DIRECTORY_SEP);
120 else if (ch)
121 eicat_ch (newname, ch);
122 else
123 break;
124 }
125 else
126 eicat_ch (component, ch);
127
128 INC_CHARPTR (fp);
129 }
130
131 return eicpyout_malloc (newname, 0);
97 } 132 }
98 133
99 static void 134 static void
100 init_potentially_nonexistent_functions (void) 135 init_potentially_nonexistent_functions (void)
101 { 136 {
102 HMODULE h_kernel = GetModuleHandle ("kernel32"); 137 HMODULE h_kernel = qxeGetModuleHandle (XETEXT ("kernel32"));
103 HMODULE h_user = GetModuleHandle ("user32");
104 HMODULE h_gdi = GetModuleHandle ("gdi32");
105 HMODULE h_shell = GetModuleHandle ("shell32");
106 /* the following does not seem to get mapped in automatically */ 138 /* the following does not seem to get mapped in automatically */
107 HMODULE h_netapi = LoadLibrary ("netapi32.dll"); 139 HMODULE h_netapi = qxeLoadLibrary (XETEXT ("netapi32.dll"));
108 140
109 if (h_kernel) 141 if (h_kernel)
110 { 142 {
111 xSwitchToThread = 143 xSwitchToThread =
112 (pfSwitchToThread_t) GetProcAddress (h_kernel, "SwitchToThread"); 144 (pfSwitchToThread_t) GetProcAddress (h_kernel, "SwitchToThread");
113 }
114
115 if (h_user)
116 {
117 xGetKeyboardLayout =
118 (pfGetKeyboardLayout_t) GetProcAddress (h_user, "GetKeyboardLayout");
119 xSetMenuDefaultItem =
120 (pfSetMenuDefaultItem_t) GetProcAddress (h_user, "SetMenuDefaultItem");
121 xInsertMenuItemA =
122 (pfInsertMenuItemA_t) GetProcAddress (h_user, "InsertMenuItemA");
123 xInsertMenuItemW =
124 (pfInsertMenuItemW_t) GetProcAddress (h_user, "InsertMenuItemW");
125 xLoadImageA =
126 (pfLoadImageA_t) GetProcAddress (h_user, "LoadImageA");
127 xLoadImageW =
128 (pfLoadImageW_t) GetProcAddress (h_user, "LoadImageW");
129 xRegisterClassExA =
130 (pfRegisterClassExA_t) GetProcAddress (h_user, "RegisterClassExA");
131 xRegisterClassExW =
132 (pfRegisterClassExW_t) GetProcAddress (h_user, "RegisterClassExW");
133 }
134
135 if (h_gdi)
136 {
137 xEnumFontFamiliesExA =
138 (pfEnumFontFamiliesExA_t) GetProcAddress (h_gdi, "EnumFontFamiliesExA");
139 xEnumFontFamiliesExW =
140 (pfEnumFontFamiliesExW_t) GetProcAddress (h_gdi, "EnumFontFamiliesExW");
141 }
142
143 if (h_shell)
144 {
145 xSHGetFileInfoA =
146 (pfSHGetFileInfoA_t) GetProcAddress (h_shell, "SHGetFileInfoA");
147 xSHGetFileInfoW =
148 (pfSHGetFileInfoW_t) GetProcAddress (h_shell, "SHGetFileInfoW");
149 } 145 }
150 146
151 if (h_netapi) 147 if (h_netapi)
152 { 148 {
153 xNetUserEnum = 149 xNetUserEnum =
154 (pfNetUserEnum_t) GetProcAddress (h_netapi, "NetUserEnum"); 150 (pfNetUserEnum_t) GetProcAddress (h_netapi, "NetUserEnum");
155 xNetApiBufferFree = 151 xNetApiBufferFree =
156 (pfNetApiBufferFree_t) GetProcAddress (h_netapi, "NetApiBufferFree"); 152 (pfNetApiBufferFree_t) GetProcAddress (h_netapi, "NetApiBufferFree");
157 } 153 }
154 }
155
156 static Lisp_Object
157 mswindows_lisp_error_1 (int errnum, int no_recurse)
158 {
159 LPTSTR lpMsgBuf;
160 Lisp_Object result;
161 Intbyte *inres;
162 Bytecount len;
163 int i;
164
165 /* The docs for FormatMessage say:
166
167 If you pass a specific LANGID in this parameter, FormatMessage
168 will return a message for that LANGID only. If the function
169 cannot find a message for that LANGID, it returns
170 ERROR_RESOURCE_LANG_NOT_FOUND. If you pass in zero, FormatMessage
171 looks for a message for LANGIDs in the following order:
172
173 Language neutral
174 Thread LANGID, based on the thread's locale value
175 User default LANGID, based on the user's default locale value
176 System default LANGID, based on the system default locale value
177 US English
178
179 If FormatMessage doesn't find a message for any of the preceding
180 LANGIDs, it returns any language message string that is present. If
181 that fails, it returns ERROR_RESOURCE_LANG_NOT_FOUND. (Note, this is
182 returned through GetLastError(), not the return value.)
183
184 #### what the hell is "language neutral"? i can find no info on this.
185 so let's do our own language first.
186 */
187
188 for (i = 0; ; i++)
189 {
190 int lang = 0;
191 int retval;
192
193 switch (i)
194 {
195 #ifdef MULE
196 /* Urk! Windows 95 doesn't let you set the thread locale!
197 so we have to maintain our own. */
198 case 0: lang = LANGIDFROMLCID (mswindows_current_locale ()); break;
199 case 1: lang = 0; break;
200 #else
201 case 0: lang = 0; break;
202 #endif
203 default: abort ();
204 }
205
206 retval = qxeFormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
207 | FORMAT_MESSAGE_FROM_SYSTEM,
208 NULL, errnum, lang,
209 /* yeah, i'm casting a char ** to a char *.
210 ya gotta problem widdat? */
211 (Extbyte *) &lpMsgBuf, 0, NULL);
212
213 if (!retval)
214 {
215 if (lang != 0)
216 continue;
217
218 if (no_recurse)
219 return emacs_sprintf_string
220 ("Unknown error code %d (error return %ld from FormatMessage())",
221 errnum, GetLastError ());
222 else
223 return emacs_sprintf_string
224 ("Unknown error code %d (error return %s from FormatMessage())",
225 /* It's OK, emacs_sprintf_string disables GC explicitly */
226 errnum, XSTRING_DATA (mswindows_lisp_error_1 (errnum, 1)));
227 }
228 else
229 break;
230 }
231
232 TSTR_TO_C_STRING (lpMsgBuf, inres);
233 len = qxestrlen (inres);
234 /* Messages tend to end with a period and newline */
235 if (len >= 3 && !intbyte_strcmp (inres + len - 3, ".\r\n"))
236 len -= 3;
237 result = make_string (inres, len);
238
239 LocalFree (lpMsgBuf);
240 return result;
241 }
242
243 Lisp_Object
244 mswindows_lisp_error (int errnum)
245 {
246 return mswindows_lisp_error_1 (errnum, 0);
247 }
248
249 void
250 mswindows_output_last_error (char *frob)
251 {
252 int errval = GetLastError ();
253 Lisp_Object errmess = mswindows_lisp_error (errval);
254
255 stderr_out ("last error during %s is %d: %s\n",
256 frob, errval, XSTRING_DATA (errmess));
257 }
258
259 DOESNT_RETURN
260 mswindows_report_process_error (const char *string, Lisp_Object data,
261 int errnum)
262 {
263 report_file_type_error (Qprocess_error, mswindows_lisp_error (errnum),
264 string, data);
158 } 265 }
159 266
160 DEFUN ("mswindows-shell-execute", Fmswindows_shell_execute, 2, 4, 0, /* 267 DEFUN ("mswindows-shell-execute", Fmswindows_shell_execute, 2, 4, 0, /*
161 Get Windows to perform OPERATION on DOCUMENT. 268 Get Windows to perform OPERATION on DOCUMENT.
162 This is a wrapper around the ShellExecute system function, which 269 This is a wrapper around the ShellExecute system function, which
180 */ 287 */
181 (operation, document, parameters, show_flag)) 288 (operation, document, parameters, show_flag))
182 { 289 {
183 /* Encode filename and current directory. */ 290 /* Encode filename and current directory. */
184 Lisp_Object current_dir = Ffile_name_directory (document); 291 Lisp_Object current_dir = Ffile_name_directory (document);
185 char* path = NULL;
186 #ifdef CYGWIN
187 char* fname1, *fname2;
188 int pos, sz;
189 #endif
190 char* doc = NULL;
191 int ret; 292 int ret;
192 struct gcpro gcpro1, gcpro2;
193 293
194 CHECK_STRING (document); 294 CHECK_STRING (document);
195 295
196 if (NILP (current_dir)) 296 if (NILP (current_dir))
197 current_dir = current_buffer->directory; 297 current_dir = current_buffer->directory;
198 298
199 GCPRO2 (current_dir, document); 299 {
200 300 Extbyte *opext = NULL;
201 /* Use mule and cygwin-safe APIs top get at file data. */ 301 Extbyte *parmext = NULL;
202 if (STRINGP (current_dir)) 302 Extbyte *path = NULL;
203 { 303 Extbyte *doc = NULL;
204 LOCAL_TO_WIN32_FILE_FORMAT (current_dir, path); 304
205 } 305 if (STRINGP (operation))
206 306 LISP_STRING_TO_TSTR (operation, opext);
307 if (STRINGP (parameters))
308 LISP_STRING_TO_TSTR (parameters, parmext);
309 if (STRINGP (current_dir))
310 LOCAL_FILE_FORMAT_TO_TSTR (current_dir, path);
207 if (STRINGP (document)) 311 if (STRINGP (document))
208 { 312 {
209 doc = XSTRING_DATA (document);
210 #ifdef CYGWIN 313 #ifdef CYGWIN
211 if ((fname1 = strchr (doc, ':')) != NULL 314 Intbyte *docint = XSTRING_DATA (document);
212 && *++fname1 == '/' && *++fname1 == '/') 315 /* If URL style file, the innards may have Cygwin mount points and
316 the like. so separate out the innards, process them, and put back
317 together. */
318 if (qxestrncasecmp_c (docint, "file://", 7) == 0)
213 { 319 {
214 // URL-style if we get here, but we must only convert file 320 Intbyte *fname_windows;
215 // arguments, since win32 paths are illegal in http etc. 321 Intbyte *docint_windows;
216 if (strncmp (doc, "file://", 7) == 0) 322
217 { 323 LOCAL_TO_WIN32_FILE_FORMAT (docint + 7, fname_windows);
218 fname1++; 324 docint_windows = alloca_intbytes (7 + qxestrlen (fname_windows) + 1);
219 pos = fname1 - doc; 325 qxestrcpy_c (docint_windows, "file://");
220 if (!(isalpha (fname1[0]) && (IS_DEVICE_SEP (fname1[1])))) 326 qxestrcat (docint_windows, fname_windows);
221 { 327 C_STRING_TO_TSTR (docint, doc);
222 sz = cygwin_posix_to_win32_path_list_buf_size (fname1);
223 fname2 = alloca (sz + pos);
224 strncpy (fname2, doc, pos);
225 doc = fname2;
226 fname2 += pos;
227 cygwin_posix_to_win32_path_list (fname1, fname2);
228 }
229 }
230 } 328 }
231 else { 329 else
232 // Not URL-style, must be a straight filename.
233 LOCAL_TO_WIN32_FILE_FORMAT (document, doc);
234 }
235 #endif 330 #endif
236 } 331 LOCAL_FILE_FORMAT_TO_TSTR (document, doc);
237 332 }
238 UNGCPRO; 333
239 334 ret = (int) qxeShellExecute (NULL, opext, doc, parmext, path,
240 ret = (int) ShellExecute (NULL, 335 (INTP (show_flag) ?
241 (STRINGP (operation) ? 336 XINT (show_flag) : SW_SHOWDEFAULT));
242 /* !!#### more mule bogosity */ 337 }
243 (char *) XSTRING_DATA (operation) : NULL), 338
244 doc, 339 if (ret <= 32)
245 (STRINGP (parameters) ? 340 {
246 /* !!#### more mule bogosity */ 341 /* Convert to more standard errors */
247 (char *) XSTRING_DATA (parameters) : NULL), 342 #define FROB(a, b) if (ret == a) ret = b
248 path, 343 FROB (SE_ERR_ACCESSDENIED, ERROR_ACCESS_DENIED);
249 (INTP (show_flag) ? 344 FROB (SE_ERR_ASSOCINCOMPLETE, ERROR_NO_ASSOCIATION);
250 XINT (show_flag) : SW_SHOWDEFAULT)); 345 FROB (SE_ERR_DDEBUSY, ERROR_DDE_FAIL);
251 346 FROB (SE_ERR_DDEFAIL, ERROR_DDE_FAIL);
252 if (ret > 32) 347 FROB (SE_ERR_DDETIMEOUT, ERROR_DDE_FAIL);
253 return Qt; 348 FROB (SE_ERR_DLLNOTFOUND, ERROR_DLL_NOT_FOUND);
254 349 FROB (SE_ERR_FNF, ERROR_FILE_NOT_FOUND);
255 if (ret == ERROR_FILE_NOT_FOUND) 350 FROB (SE_ERR_NOASSOC, ERROR_NO_ASSOCIATION);
256 signal_error (Qfile_error, "file not found", document); 351 FROB (SE_ERR_OOM, ERROR_NOT_ENOUGH_MEMORY);
257 else if (ret == ERROR_PATH_NOT_FOUND) 352 FROB (SE_ERR_PNF, ERROR_PATH_NOT_FOUND);
258 signal_error (Qfile_error, "path not found", current_dir); 353 FROB (SE_ERR_SHARE, ERROR_SHARING_VIOLATION);
259 else if (ret == ERROR_BAD_FORMAT) 354 #undef FROB
260 signal_error (Qfile_error, "bad executable format", document); 355
261 else 356 mswindows_report_process_error ("Running ShellExecute",
262 signal_error (Qinternal_error, "internal error", Qunbound); 357 ret == ERROR_PATH_NOT_FOUND ?
263 358 list4 (Qunbound, operation, document,
264 return Qnil; 359 current_dir) :
360 list3 (Qunbound, operation, document),
361 ret);
362 }
363
364 return Qt;
265 } 365 }
266 366
267 #ifdef CYGWIN 367 #ifdef CYGWIN
268 DEFUN ("mswindows-cygwin-to-win32-path", Fmswindows_cygwin_to_win32_path, 1, 1, 0, /* 368 DEFUN ("mswindows-cygwin-to-win32-path", Fmswindows_cygwin_to_win32_path, 1, 1, 0, /*
269 Get the cygwin environment to convert the Unix PATH to win32 format. 369 Get the cygwin environment to convert the Unix PATH to win32 format.
270 No expansion is performed, all conversion is done by the cygwin runtime. 370 No expansion is performed, all conversion is done by the cygwin runtime.
271 */ 371 */
272 (path)) 372 (path))
273 { 373 {
274 Extbyte* f; 374 Intbyte *p;
275 Intbyte* p;
276 CHECK_STRING (path); 375 CHECK_STRING (path);
277 376
278 /* There appears to be a bug in the cygwin conversion routines in 377 /* There appears to be a bug in the cygwin conversion routines in
279 that they are not idempotent. */ 378 that they are not idempotent. */
280 p = XSTRING_DATA (path); 379 p = XSTRING_DATA (path);
281 if (isalpha (p[0]) && (IS_DEVICE_SEP (p[1]))) 380 if (isalpha (p[0]) && (IS_DEVICE_SEP (p[1])))
282 return path; 381 return path;
283 382
284 /* Use mule and cygwin-safe APIs top get at file data. */ 383 /* Use mule and cygwin-safe APIs top get at file data. */
285 LOCAL_TO_WIN32_FILE_FORMAT (path, f); 384 LOCAL_TO_WIN32_FILE_FORMAT (p, p);
286 return build_ext_string (f, Qnative); 385 return build_intstring (p);
287 } 386 }
288 #endif 387 #endif
289 388
290 #if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS) 389 #if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS)
291 390
544 DEFSUBR (Fmswindows_cygwin_to_win32_path); 643 DEFSUBR (Fmswindows_cygwin_to_win32_path);
545 #endif 644 #endif
546 } 645 }
547 646
548 void 647 void
648 vars_of_win32 (void)
649 {
650 DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /*
651 Non-nil means convert all-upper case file names to lower case.
652 This applies when performing completions and file name expansion.
653 */ );
654 Vmswindows_downcase_file_names = Qnil;
655 }
656
657 void
549 init_win32 (void) 658 init_win32 (void)
550 { 659 {
551 init_potentially_nonexistent_functions (); 660 init_potentially_nonexistent_functions ();
552 } 661 }
662
663 void
664 init_win32_very_early (void)
665 {
666 mswindows_windows9x_p = GetVersion () & 0x80000000;
667 }