Mercurial > hg > xemacs-beta
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 } |