1 |
william |
31 |
///////////////////////////////////////////////////////////////////////////// |
2 |
|
|
// Name: src/common/filefn.cpp |
3 |
|
|
// Purpose: File- and directory-related functions |
4 |
|
|
// Author: Julian Smart |
5 |
|
|
// Modified by: |
6 |
|
|
// Created: 29/01/98 |
7 |
|
|
// RCS-ID: $Id: filefn.cpp 58220 2009-01-19 11:40:24Z VZ $ |
8 |
|
|
// Copyright: (c) 1998 Julian Smart |
9 |
|
|
// Licence: wxWindows licence |
10 |
|
|
///////////////////////////////////////////////////////////////////////////// |
11 |
|
|
|
12 |
|
|
// ============================================================================ |
13 |
|
|
// declarations |
14 |
|
|
// ============================================================================ |
15 |
|
|
|
16 |
|
|
// ---------------------------------------------------------------------------- |
17 |
|
|
// headers |
18 |
|
|
// ---------------------------------------------------------------------------- |
19 |
|
|
|
20 |
|
|
// For compilers that support precompilation, includes "wx.h". |
21 |
|
|
#include "wx/wxprec.h" |
22 |
|
|
|
23 |
|
|
#ifdef __BORLANDC__ |
24 |
|
|
#pragma hdrstop |
25 |
|
|
#endif |
26 |
|
|
|
27 |
|
|
#include "wx/filefn.h" |
28 |
|
|
|
29 |
|
|
#ifndef WX_PRECOMP |
30 |
|
|
#include "wx/intl.h" |
31 |
|
|
#include "wx/log.h" |
32 |
|
|
#include "wx/utils.h" |
33 |
|
|
#endif |
34 |
|
|
|
35 |
|
|
#include "wx/file.h" |
36 |
|
|
#include "wx/filename.h" |
37 |
|
|
#include "wx/dir.h" |
38 |
|
|
|
39 |
|
|
#include "wx/tokenzr.h" |
40 |
|
|
|
41 |
|
|
// there are just too many of those... |
42 |
|
|
#ifdef __VISUALC__ |
43 |
|
|
#pragma warning(disable:4706) // assignment within conditional expression |
44 |
|
|
#endif // VC++ |
45 |
|
|
|
46 |
|
|
#include <ctype.h> |
47 |
|
|
#include <stdio.h> |
48 |
|
|
#include <stdlib.h> |
49 |
|
|
#include <string.h> |
50 |
|
|
#if !wxONLY_WATCOM_EARLIER_THAN(1,4) |
51 |
|
|
#if !(defined(_MSC_VER) && (_MSC_VER > 800)) |
52 |
|
|
#include <errno.h> |
53 |
|
|
#endif |
54 |
|
|
#endif |
55 |
|
|
|
56 |
|
|
#if defined(__WXMAC__) |
57 |
|
|
#include "wx/mac/private.h" // includes mac headers |
58 |
|
|
#endif |
59 |
|
|
|
60 |
|
|
#ifdef __WINDOWS__ |
61 |
|
|
#include "wx/msw/private.h" |
62 |
|
|
#include "wx/msw/mslu.h" |
63 |
|
|
|
64 |
|
|
// sys/cygwin.h is needed for cygwin_conv_to_full_win32_path() |
65 |
|
|
// |
66 |
|
|
// note that it must be included after <windows.h> |
67 |
|
|
#ifdef __GNUWIN32__ |
68 |
|
|
#ifdef __CYGWIN__ |
69 |
|
|
#include <sys/cygwin.h> |
70 |
|
|
#endif |
71 |
|
|
#endif // __GNUWIN32__ |
72 |
|
|
|
73 |
|
|
// io.h is needed for _get_osfhandle() |
74 |
|
|
// Already included by filefn.h for many Windows compilers |
75 |
|
|
#if defined __MWERKS__ || defined __CYGWIN__ |
76 |
|
|
#include <io.h> |
77 |
|
|
#endif |
78 |
|
|
#endif // __WINDOWS__ |
79 |
|
|
|
80 |
|
|
#if defined(__VMS__) |
81 |
|
|
#include <fab.h> |
82 |
|
|
#endif |
83 |
|
|
|
84 |
|
|
// TODO: Borland probably has _wgetcwd as well? |
85 |
|
|
#ifdef _MSC_VER |
86 |
|
|
#define HAVE_WGETCWD |
87 |
|
|
#endif |
88 |
|
|
|
89 |
|
|
// ---------------------------------------------------------------------------- |
90 |
|
|
// constants |
91 |
|
|
// ---------------------------------------------------------------------------- |
92 |
|
|
|
93 |
|
|
#ifndef _MAXPATHLEN |
94 |
|
|
#define _MAXPATHLEN 1024 |
95 |
|
|
#endif |
96 |
|
|
|
97 |
|
|
#ifdef __WXMAC__ |
98 |
|
|
# include "MoreFilesX.h" |
99 |
|
|
#endif |
100 |
|
|
|
101 |
|
|
// ---------------------------------------------------------------------------- |
102 |
|
|
// private globals |
103 |
|
|
// ---------------------------------------------------------------------------- |
104 |
|
|
|
105 |
|
|
// MT-FIXME: get rid of this horror and all code using it |
106 |
|
|
static wxChar wxFileFunctionsBuffer[4*_MAXPATHLEN]; |
107 |
|
|
|
108 |
|
|
#if defined(__VISAGECPP__) && __IBMCPP__ >= 400 |
109 |
|
|
// |
110 |
|
|
// VisualAge C++ V4.0 cannot have any external linkage const decs |
111 |
|
|
// in headers included by more than one primary source |
112 |
|
|
// |
113 |
|
|
const int wxInvalidOffset = -1; |
114 |
|
|
#endif |
115 |
|
|
|
116 |
|
|
// ---------------------------------------------------------------------------- |
117 |
|
|
// macros |
118 |
|
|
// ---------------------------------------------------------------------------- |
119 |
|
|
|
120 |
|
|
// translate the filenames before passing them to OS functions |
121 |
|
|
#define OS_FILENAME(s) (s.fn_str()) |
122 |
|
|
|
123 |
|
|
// ============================================================================ |
124 |
|
|
// implementation |
125 |
|
|
// ============================================================================ |
126 |
|
|
|
127 |
|
|
// ---------------------------------------------------------------------------- |
128 |
|
|
// wrappers around standard POSIX functions |
129 |
|
|
// ---------------------------------------------------------------------------- |
130 |
|
|
|
131 |
|
|
#ifdef wxNEED_WX_UNISTD_H |
132 |
|
|
|
133 |
|
|
WXDLLEXPORT int wxStat( const wxChar *file_name, wxStructStat *buf ) |
134 |
|
|
{ |
135 |
|
|
return stat( wxConvFile.cWX2MB( file_name ), buf ); |
136 |
|
|
} |
137 |
|
|
|
138 |
|
|
WXDLLEXPORT int wxLstat( const wxChar *file_name, wxStructStat *buf ) |
139 |
|
|
{ |
140 |
|
|
return lstat( wxConvFile.cWX2MB( file_name ), buf ); |
141 |
|
|
} |
142 |
|
|
|
143 |
|
|
WXDLLEXPORT int wxAccess( const wxChar *pathname, int mode ) |
144 |
|
|
{ |
145 |
|
|
return access( wxConvFile.cWX2MB( pathname ), mode ); |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode ) |
149 |
|
|
{ |
150 |
|
|
return open( wxConvFile.cWX2MB( pathname ), flags, mode ); |
151 |
|
|
} |
152 |
|
|
|
153 |
|
|
#endif // wxNEED_WX_UNISTD_H |
154 |
|
|
|
155 |
|
|
#if wxUSE_UNICODE && defined __BORLANDC__ \ |
156 |
|
|
&& __BORLANDC__ >= 0x550 && __BORLANDC__ <= 0x551 |
157 |
|
|
|
158 |
|
|
// BCC 5.5 and 5.5.1 have a bug in _wopen where files are created read only |
159 |
|
|
// regardless of the mode parameter. This hack works around the problem by |
160 |
|
|
// setting the mode with _wchmod. |
161 |
|
|
// |
162 |
|
|
int wxOpen(const wchar_t *pathname, int flags, mode_t mode) |
163 |
|
|
{ |
164 |
|
|
int moreflags = 0; |
165 |
|
|
|
166 |
|
|
// we only want to fix the mode when the file is actually created, so |
167 |
|
|
// when creating first try doing it O_EXCL so we can tell if the file |
168 |
|
|
// was already there. |
169 |
|
|
if ((flags & O_CREAT) && !(flags & O_EXCL) && (mode & wxS_IWUSR) != 0) |
170 |
|
|
moreflags = O_EXCL; |
171 |
|
|
|
172 |
|
|
int fd = _wopen(pathname, flags | moreflags, mode); |
173 |
|
|
|
174 |
|
|
// the file was actually created and needs fixing |
175 |
|
|
if (fd != -1 && (flags & O_CREAT) != 0 && (mode & wxS_IWUSR) != 0) |
176 |
|
|
{ |
177 |
|
|
close(fd); |
178 |
|
|
_wchmod(pathname, mode); |
179 |
|
|
fd = _wopen(pathname, flags & ~(O_EXCL | O_CREAT)); |
180 |
|
|
} |
181 |
|
|
// the open failed, but it may have been because the added O_EXCL stopped |
182 |
|
|
// the opening of an existing file, so try again without. |
183 |
|
|
else if (fd == -1 && moreflags != 0) |
184 |
|
|
{ |
185 |
|
|
fd = _wopen(pathname, flags & ~O_CREAT); |
186 |
|
|
} |
187 |
|
|
|
188 |
|
|
return fd; |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
#endif |
192 |
|
|
|
193 |
|
|
// ---------------------------------------------------------------------------- |
194 |
|
|
// wxPathList |
195 |
|
|
// ---------------------------------------------------------------------------- |
196 |
|
|
|
197 |
|
|
bool wxPathList::Add(const wxString& path) |
198 |
|
|
{ |
199 |
|
|
// add a path separator to force wxFileName to interpret it always as a directory |
200 |
|
|
// (i.e. if we are called with '/home/user' we want to consider it a folder and |
201 |
|
|
// not, as wxFileName would consider, a filename). |
202 |
|
|
wxFileName fn(path + wxFileName::GetPathSeparator()); |
203 |
|
|
|
204 |
|
|
// add only normalized relative/absolute paths |
205 |
|
|
// NB: we won't do wxPATH_NORM_DOTS in order to avoid problems when trying to |
206 |
|
|
// normalize paths which starts with ".." (which can be normalized only if |
207 |
|
|
// we use also wxPATH_NORM_ABSOLUTE - which we don't want to use). |
208 |
|
|
if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS)) |
209 |
|
|
return false; |
210 |
|
|
|
211 |
|
|
wxString toadd = fn.GetPath(); |
212 |
|
|
if (Index(toadd) == wxNOT_FOUND) |
213 |
|
|
wxArrayString::Add(toadd); // do not add duplicates |
214 |
|
|
|
215 |
|
|
return true; |
216 |
|
|
} |
217 |
|
|
|
218 |
|
|
void wxPathList::Add(const wxArrayString &arr) |
219 |
|
|
{ |
220 |
|
|
for (size_t j=0; j < arr.GetCount(); j++) |
221 |
|
|
Add(arr[j]); |
222 |
|
|
} |
223 |
|
|
|
224 |
|
|
// Add paths e.g. from the PATH environment variable |
225 |
|
|
void wxPathList::AddEnvList (const wxString& WXUNUSED_IN_WINCE(envVariable)) |
226 |
|
|
{ |
227 |
|
|
// No environment variables on WinCE |
228 |
|
|
#ifndef __WXWINCE__ |
229 |
|
|
|
230 |
|
|
// The space has been removed from the tokenizers, otherwise a |
231 |
|
|
// path such as "C:\Program Files" would be split into 2 paths: |
232 |
|
|
// "C:\Program" and "Files"; this is true for both Windows and Unix. |
233 |
|
|
|
234 |
|
|
static const wxChar PATH_TOKS[] = |
235 |
|
|
#if defined(__WINDOWS__) || defined(__OS2__) |
236 |
|
|
wxT(";"); // Don't separate with colon in DOS (used for drive) |
237 |
|
|
#else |
238 |
|
|
wxT(":;"); |
239 |
|
|
#endif |
240 |
|
|
|
241 |
|
|
wxString val; |
242 |
|
|
if ( wxGetEnv(envVariable, &val) ) |
243 |
|
|
{ |
244 |
|
|
// split into an array of string the value of the env var |
245 |
|
|
wxArrayString arr = wxStringTokenize(val, PATH_TOKS); |
246 |
|
|
WX_APPEND_ARRAY(*this, arr); |
247 |
|
|
} |
248 |
|
|
#endif // !__WXWINCE__ |
249 |
|
|
} |
250 |
|
|
|
251 |
|
|
// Given a full filename (with path), ensure that that file can |
252 |
|
|
// be accessed again USING FILENAME ONLY by adding the path |
253 |
|
|
// to the list if not already there. |
254 |
|
|
bool wxPathList::EnsureFileAccessible (const wxString& path) |
255 |
|
|
{ |
256 |
|
|
return Add(wxPathOnly(path)); |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
#if WXWIN_COMPATIBILITY_2_6 |
260 |
|
|
bool wxPathList::Member (const wxString& path) const |
261 |
|
|
{ |
262 |
|
|
return Index(path) != wxNOT_FOUND; |
263 |
|
|
} |
264 |
|
|
#endif |
265 |
|
|
|
266 |
|
|
wxString wxPathList::FindValidPath (const wxString& file) const |
267 |
|
|
{ |
268 |
|
|
// normalize the given string as it could be a path + a filename |
269 |
|
|
// and not only a filename |
270 |
|
|
wxFileName fn(file); |
271 |
|
|
wxString strend; |
272 |
|
|
|
273 |
|
|
// NB: normalize without making absolute otherwise calling this function with |
274 |
|
|
// e.g. "b/c.txt" would result in removing the directory 'b' and the for loop |
275 |
|
|
// below would only add to the paths of this list the 'c.txt' part when doing |
276 |
|
|
// the existence checks... |
277 |
|
|
// NB: we don't use wxPATH_NORM_DOTS here, too (see wxPathList::Add for more info) |
278 |
|
|
if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS)) |
279 |
|
|
return wxEmptyString; |
280 |
|
|
|
281 |
|
|
wxASSERT_MSG(!fn.IsDir(), wxT("Cannot search for directories; only for files")); |
282 |
|
|
if (fn.IsAbsolute()) |
283 |
|
|
strend = fn.GetFullName(); // search for the file name and ignore the path part |
284 |
|
|
else |
285 |
|
|
strend = fn.GetFullPath(); |
286 |
|
|
|
287 |
|
|
for (size_t i=0; i<GetCount(); i++) |
288 |
|
|
{ |
289 |
|
|
wxString strstart = Item(i); |
290 |
|
|
if (!strstart.IsEmpty() && strstart.Last() != wxFileName::GetPathSeparator()) |
291 |
|
|
strstart += wxFileName::GetPathSeparator(); |
292 |
|
|
|
293 |
|
|
if (wxFileExists(strstart + strend)) |
294 |
|
|
return strstart + strend; // Found! |
295 |
|
|
} |
296 |
|
|
|
297 |
|
|
return wxEmptyString; // Not found |
298 |
|
|
} |
299 |
|
|
|
300 |
|
|
wxString wxPathList::FindAbsoluteValidPath (const wxString& file) const |
301 |
|
|
{ |
302 |
|
|
wxString f = FindValidPath(file); |
303 |
|
|
if ( f.empty() || wxIsAbsolutePath(f) ) |
304 |
|
|
return f; |
305 |
|
|
|
306 |
|
|
wxString buf = ::wxGetCwd(); |
307 |
|
|
|
308 |
|
|
if ( !wxEndsWithPathSeparator(buf) ) |
309 |
|
|
{ |
310 |
|
|
buf += wxFILE_SEP_PATH; |
311 |
|
|
} |
312 |
|
|
buf += f; |
313 |
|
|
|
314 |
|
|
return buf; |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
// ---------------------------------------------------------------------------- |
318 |
|
|
// miscellaneous global functions (TOFIX!) |
319 |
|
|
// ---------------------------------------------------------------------------- |
320 |
|
|
|
321 |
|
|
static inline wxChar* MYcopystring(const wxString& s) |
322 |
|
|
{ |
323 |
|
|
wxChar* copy = new wxChar[s.length() + 1]; |
324 |
|
|
return wxStrcpy(copy, s.c_str()); |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
static inline wxChar* MYcopystring(const wxChar* s) |
328 |
|
|
{ |
329 |
|
|
wxChar* copy = new wxChar[wxStrlen(s) + 1]; |
330 |
|
|
return wxStrcpy(copy, s); |
331 |
|
|
} |
332 |
|
|
|
333 |
|
|
|
334 |
|
|
bool |
335 |
|
|
wxFileExists (const wxString& filename) |
336 |
|
|
{ |
337 |
|
|
#if defined(__WXPALMOS__) |
338 |
|
|
return false; |
339 |
|
|
#elif defined(__WIN32__) && !defined(__WXMICROWIN__) |
340 |
|
|
// we must use GetFileAttributes() instead of the ANSI C functions because |
341 |
|
|
// it can cope with network (UNC) paths unlike them |
342 |
|
|
DWORD ret = ::GetFileAttributes(filename); |
343 |
|
|
|
344 |
|
|
return (ret != (DWORD)-1) && !(ret & FILE_ATTRIBUTE_DIRECTORY); |
345 |
|
|
#else // !__WIN32__ |
346 |
|
|
#ifndef S_ISREG |
347 |
|
|
#define S_ISREG(mode) ((mode) & S_IFREG) |
348 |
|
|
#endif |
349 |
|
|
wxStructStat st; |
350 |
|
|
#ifndef wxNEED_WX_UNISTD_H |
351 |
|
|
return (wxStat( filename.fn_str() , &st) == 0 && S_ISREG(st.st_mode)) |
352 |
|
|
#ifdef __OS2__ |
353 |
|
|
|| (errno == EACCES) // if access is denied something with that name |
354 |
|
|
// exists and is opened in exclusive mode. |
355 |
|
|
#endif |
356 |
|
|
; |
357 |
|
|
#else |
358 |
|
|
return wxStat( filename , &st) == 0 && S_ISREG(st.st_mode); |
359 |
|
|
#endif |
360 |
|
|
#endif // __WIN32__/!__WIN32__ |
361 |
|
|
} |
362 |
|
|
|
363 |
|
|
bool |
364 |
|
|
wxIsAbsolutePath (const wxString& filename) |
365 |
|
|
{ |
366 |
|
|
if (!filename.empty()) |
367 |
|
|
{ |
368 |
|
|
#if defined(__WXMAC__) && !defined(__DARWIN__) |
369 |
|
|
// Classic or Carbon CodeWarrior like |
370 |
|
|
// Carbon with Apple DevTools is Unix like |
371 |
|
|
|
372 |
|
|
// This seems wrong to me, but there is no fix. since |
373 |
|
|
// "MacOS:MyText.txt" is absolute whereas "MyDir:MyText.txt" |
374 |
|
|
// is not. Or maybe ":MyDir:MyText.txt" has to be used? RR. |
375 |
|
|
if (filename.Find(':') != wxNOT_FOUND && filename[0] != ':') |
376 |
|
|
return true ; |
377 |
|
|
#else |
378 |
|
|
// Unix like or Windows |
379 |
|
|
if (filename[0] == wxT('/')) |
380 |
|
|
return true; |
381 |
|
|
#endif |
382 |
|
|
#ifdef __VMS__ |
383 |
|
|
if ((filename[0] == wxT('[') && filename[1] != wxT('.'))) |
384 |
|
|
return true; |
385 |
|
|
#endif |
386 |
|
|
#if defined(__WINDOWS__) || defined(__OS2__) |
387 |
|
|
// MSDOS like |
388 |
|
|
if (filename[0] == wxT('\\') || (wxIsalpha (filename[0]) && filename[1] == wxT(':'))) |
389 |
|
|
return true; |
390 |
|
|
#endif |
391 |
|
|
} |
392 |
|
|
return false ; |
393 |
|
|
} |
394 |
|
|
|
395 |
|
|
/* |
396 |
|
|
* Strip off any extension (dot something) from end of file, |
397 |
|
|
* IF one exists. Inserts zero into buffer. |
398 |
|
|
* |
399 |
|
|
*/ |
400 |
|
|
|
401 |
|
|
void wxStripExtension(wxChar *buffer) |
402 |
|
|
{ |
403 |
|
|
int len = wxStrlen(buffer); |
404 |
|
|
int i = len-1; |
405 |
|
|
while (i > 0) |
406 |
|
|
{ |
407 |
|
|
if (buffer[i] == wxT('.')) |
408 |
|
|
{ |
409 |
|
|
buffer[i] = 0; |
410 |
|
|
break; |
411 |
|
|
} |
412 |
|
|
i --; |
413 |
|
|
} |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
void wxStripExtension(wxString& buffer) |
417 |
|
|
{ |
418 |
|
|
//RN: Be careful about the handling the case where |
419 |
|
|
//buffer.length() == 0 |
420 |
|
|
for(size_t i = buffer.length() - 1; i != wxString::npos; --i) |
421 |
|
|
{ |
422 |
|
|
if (buffer.GetChar(i) == wxT('.')) |
423 |
|
|
{ |
424 |
|
|
buffer = buffer.Left(i); |
425 |
|
|
break; |
426 |
|
|
} |
427 |
|
|
} |
428 |
|
|
} |
429 |
|
|
|
430 |
|
|
// Destructive removal of /./ and /../ stuff |
431 |
|
|
wxChar *wxRealPath (wxChar *path) |
432 |
|
|
{ |
433 |
|
|
#ifdef __WXMSW__ |
434 |
|
|
static const wxChar SEP = wxT('\\'); |
435 |
|
|
wxUnix2DosFilename(path); |
436 |
|
|
#else |
437 |
|
|
static const wxChar SEP = wxT('/'); |
438 |
|
|
#endif |
439 |
|
|
if (path[0] && path[1]) { |
440 |
|
|
/* MATTHEW: special case "/./x" */ |
441 |
|
|
wxChar *p; |
442 |
|
|
if (path[2] == SEP && path[1] == wxT('.')) |
443 |
|
|
p = &path[0]; |
444 |
|
|
else |
445 |
|
|
p = &path[2]; |
446 |
|
|
for (; *p; p++) |
447 |
|
|
{ |
448 |
|
|
if (*p == SEP) |
449 |
|
|
{ |
450 |
|
|
if (p[1] == wxT('.') && p[2] == wxT('.') && (p[3] == SEP || p[3] == wxT('\0'))) |
451 |
|
|
{ |
452 |
|
|
wxChar *q; |
453 |
|
|
for (q = p - 1; q >= path && *q != SEP; q--) |
454 |
|
|
{ |
455 |
|
|
// Empty |
456 |
|
|
} |
457 |
|
|
|
458 |
|
|
if (q[0] == SEP && (q[1] != wxT('.') || q[2] != wxT('.') || q[3] != SEP) |
459 |
|
|
&& (q - 1 <= path || q[-1] != SEP)) |
460 |
|
|
{ |
461 |
|
|
wxStrcpy (q, p + 3); |
462 |
|
|
if (path[0] == wxT('\0')) |
463 |
|
|
{ |
464 |
|
|
path[0] = SEP; |
465 |
|
|
path[1] = wxT('\0'); |
466 |
|
|
} |
467 |
|
|
#if defined(__WXMSW__) || defined(__OS2__) |
468 |
|
|
/* Check that path[2] is NULL! */ |
469 |
|
|
else if (path[1] == wxT(':') && !path[2]) |
470 |
|
|
{ |
471 |
|
|
path[2] = SEP; |
472 |
|
|
path[3] = wxT('\0'); |
473 |
|
|
} |
474 |
|
|
#endif |
475 |
|
|
p = q - 1; |
476 |
|
|
} |
477 |
|
|
} |
478 |
|
|
else if (p[1] == wxT('.') && (p[2] == SEP || p[2] == wxT('\0'))) |
479 |
|
|
wxStrcpy (p, p + 2); |
480 |
|
|
} |
481 |
|
|
} |
482 |
|
|
} |
483 |
|
|
return path; |
484 |
|
|
} |
485 |
|
|
|
486 |
|
|
wxString wxRealPath(const wxString& path) |
487 |
|
|
{ |
488 |
|
|
wxChar *buf1=MYcopystring(path); |
489 |
|
|
wxChar *buf2=wxRealPath(buf1); |
490 |
|
|
wxString buf(buf2); |
491 |
|
|
delete [] buf1; |
492 |
|
|
return buf; |
493 |
|
|
} |
494 |
|
|
|
495 |
|
|
|
496 |
|
|
// Must be destroyed |
497 |
|
|
wxChar *wxCopyAbsolutePath(const wxString& filename) |
498 |
|
|
{ |
499 |
|
|
if (filename.empty()) |
500 |
|
|
return (wxChar *) NULL; |
501 |
|
|
|
502 |
|
|
if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) |
503 |
|
|
{ |
504 |
|
|
wxString buf = ::wxGetCwd(); |
505 |
|
|
wxChar ch = buf.Last(); |
506 |
|
|
#ifdef __WXMSW__ |
507 |
|
|
if (ch != wxT('\\') && ch != wxT('/')) |
508 |
|
|
buf << wxT("\\"); |
509 |
|
|
#else |
510 |
|
|
if (ch != wxT('/')) |
511 |
|
|
buf << wxT("/"); |
512 |
|
|
#endif |
513 |
|
|
buf << wxFileFunctionsBuffer; |
514 |
|
|
buf = wxRealPath( buf ); |
515 |
|
|
return MYcopystring( buf ); |
516 |
|
|
} |
517 |
|
|
return MYcopystring( wxFileFunctionsBuffer ); |
518 |
|
|
} |
519 |
|
|
|
520 |
|
|
/*- |
521 |
|
|
Handles: |
522 |
|
|
~/ => home dir |
523 |
|
|
~user/ => user's home dir |
524 |
|
|
If the environment variable a = "foo" and b = "bar" then: |
525 |
|
|
Unix: |
526 |
|
|
$a => foo |
527 |
|
|
$a$b => foobar |
528 |
|
|
$a.c => foo.c |
529 |
|
|
xxx$a => xxxfoo |
530 |
|
|
${a}! => foo! |
531 |
|
|
$(b)! => bar! |
532 |
|
|
\$a => \$a |
533 |
|
|
MSDOS: |
534 |
|
|
$a ==> $a |
535 |
|
|
$(a) ==> foo |
536 |
|
|
$(a)$b ==> foo$b |
537 |
|
|
$(a)$(b)==> foobar |
538 |
|
|
test.$$ ==> test.$$ |
539 |
|
|
*/ |
540 |
|
|
|
541 |
|
|
/* input name in name, pathname output to buf. */ |
542 |
|
|
|
543 |
|
|
wxChar *wxExpandPath(wxChar *buf, const wxChar *name) |
544 |
|
|
{ |
545 |
|
|
register wxChar *d, *s, *nm; |
546 |
|
|
wxChar lnm[_MAXPATHLEN]; |
547 |
|
|
int q; |
548 |
|
|
|
549 |
|
|
// Some compilers don't like this line. |
550 |
|
|
// const wxChar trimchars[] = wxT("\n \t"); |
551 |
|
|
|
552 |
|
|
wxChar trimchars[4]; |
553 |
|
|
trimchars[0] = wxT('\n'); |
554 |
|
|
trimchars[1] = wxT(' '); |
555 |
|
|
trimchars[2] = wxT('\t'); |
556 |
|
|
trimchars[3] = 0; |
557 |
|
|
|
558 |
|
|
#ifdef __WXMSW__ |
559 |
|
|
const wxChar SEP = wxT('\\'); |
560 |
|
|
#else |
561 |
|
|
const wxChar SEP = wxT('/'); |
562 |
|
|
#endif |
563 |
|
|
buf[0] = wxT('\0'); |
564 |
|
|
if (name == NULL || *name == wxT('\0')) |
565 |
|
|
return buf; |
566 |
|
|
nm = MYcopystring(name); // Make a scratch copy |
567 |
|
|
wxChar *nm_tmp = nm; |
568 |
|
|
|
569 |
|
|
/* Skip leading whitespace and cr */ |
570 |
|
|
while (wxStrchr((wxChar *)trimchars, *nm) != NULL) |
571 |
|
|
nm++; |
572 |
|
|
/* And strip off trailing whitespace and cr */ |
573 |
|
|
s = nm + (q = wxStrlen(nm)) - 1; |
574 |
|
|
while (q-- && wxStrchr((wxChar *)trimchars, *s) != NULL) |
575 |
|
|
*s = wxT('\0'); |
576 |
|
|
|
577 |
|
|
s = nm; |
578 |
|
|
d = lnm; |
579 |
|
|
#ifdef __WXMSW__ |
580 |
|
|
q = FALSE; |
581 |
|
|
#else |
582 |
|
|
q = nm[0] == wxT('\\') && nm[1] == wxT('~'); |
583 |
|
|
#endif |
584 |
|
|
|
585 |
|
|
/* Expand inline environment variables */ |
586 |
|
|
#ifdef __VISAGECPP__ |
587 |
|
|
while (*d) |
588 |
|
|
{ |
589 |
|
|
*d++ = *s; |
590 |
|
|
if(*s == wxT('\\')) |
591 |
|
|
{ |
592 |
|
|
*(d - 1) = *++s; |
593 |
|
|
if (*d) |
594 |
|
|
{ |
595 |
|
|
s++; |
596 |
|
|
continue; |
597 |
|
|
} |
598 |
|
|
else |
599 |
|
|
break; |
600 |
|
|
} |
601 |
|
|
else |
602 |
|
|
#else |
603 |
|
|
while ((*d++ = *s) != 0) { |
604 |
|
|
# ifndef __WXMSW__ |
605 |
|
|
if (*s == wxT('\\')) { |
606 |
|
|
if ((*(d - 1) = *++s)!=0) { |
607 |
|
|
s++; |
608 |
|
|
continue; |
609 |
|
|
} else |
610 |
|
|
break; |
611 |
|
|
} else |
612 |
|
|
# endif |
613 |
|
|
#endif |
614 |
|
|
// No env variables on WinCE |
615 |
|
|
#ifndef __WXWINCE__ |
616 |
|
|
#ifdef __WXMSW__ |
617 |
|
|
if (*s++ == wxT('$') && (*s == wxT('{') || *s == wxT(')'))) |
618 |
|
|
#else |
619 |
|
|
if (*s++ == wxT('$')) |
620 |
|
|
#endif |
621 |
|
|
{ |
622 |
|
|
register wxChar *start = d; |
623 |
|
|
register int braces = (*s == wxT('{') || *s == wxT('(')); |
624 |
|
|
register wxChar *value; |
625 |
|
|
while ((*d++ = *s) != 0) |
626 |
|
|
if (braces ? (*s == wxT('}') || *s == wxT(')')) : !(wxIsalnum(*s) || *s == wxT('_')) ) |
627 |
|
|
break; |
628 |
|
|
else |
629 |
|
|
s++; |
630 |
|
|
*--d = 0; |
631 |
|
|
value = wxGetenv(braces ? start + 1 : start); |
632 |
|
|
if (value) { |
633 |
|
|
for ((d = start - 1); (*d++ = *value++) != 0;) |
634 |
|
|
{ |
635 |
|
|
// Empty |
636 |
|
|
} |
637 |
|
|
|
638 |
|
|
d--; |
639 |
|
|
if (braces && *s) |
640 |
|
|
s++; |
641 |
|
|
} |
642 |
|
|
} |
643 |
|
|
#endif |
644 |
|
|
// __WXWINCE__ |
645 |
|
|
} |
646 |
|
|
|
647 |
|
|
/* Expand ~ and ~user */ |
648 |
|
|
nm = lnm; |
649 |
|
|
if (nm[0] == wxT('~') && !q) |
650 |
|
|
{ |
651 |
|
|
/* prefix ~ */ |
652 |
|
|
if (nm[1] == SEP || nm[1] == 0) |
653 |
|
|
{ /* ~/filename */ |
654 |
|
|
// FIXME: wxGetUserHome could return temporary storage in Unicode mode |
655 |
|
|
if ((s = WXSTRINGCAST wxGetUserHome(wxEmptyString)) != NULL) { |
656 |
|
|
if (*++nm) |
657 |
|
|
nm++; |
658 |
|
|
} |
659 |
|
|
} else |
660 |
|
|
{ /* ~user/filename */ |
661 |
|
|
register wxChar *nnm; |
662 |
|
|
register wxChar *home; |
663 |
|
|
for (s = nm; *s && *s != SEP; s++) |
664 |
|
|
{ |
665 |
|
|
// Empty |
666 |
|
|
} |
667 |
|
|
int was_sep; /* MATTHEW: Was there a separator, or NULL? */ |
668 |
|
|
was_sep = (*s == SEP); |
669 |
|
|
nnm = *s ? s + 1 : s; |
670 |
|
|
*s = 0; |
671 |
|
|
// FIXME: wxGetUserHome could return temporary storage in Unicode mode |
672 |
|
|
if ((home = WXSTRINGCAST wxGetUserHome(wxString(nm + 1))) == NULL) |
673 |
|
|
{ |
674 |
|
|
if (was_sep) /* replace only if it was there: */ |
675 |
|
|
*s = SEP; |
676 |
|
|
s = NULL; |
677 |
|
|
} |
678 |
|
|
else |
679 |
|
|
{ |
680 |
|
|
nm = nnm; |
681 |
|
|
s = home; |
682 |
|
|
} |
683 |
|
|
} |
684 |
|
|
} |
685 |
|
|
|
686 |
|
|
d = buf; |
687 |
|
|
if (s && *s) { /* MATTHEW: s could be NULL if user '~' didn't exist */ |
688 |
|
|
/* Copy home dir */ |
689 |
|
|
while (wxT('\0') != (*d++ = *s++)) |
690 |
|
|
/* loop */; |
691 |
|
|
// Handle root home |
692 |
|
|
if (d - 1 > buf && *(d - 2) != SEP) |
693 |
|
|
*(d - 1) = SEP; |
694 |
|
|
} |
695 |
|
|
s = nm; |
696 |
|
|
while ((*d++ = *s++) != 0) |
697 |
|
|
{ |
698 |
|
|
// Empty |
699 |
|
|
} |
700 |
|
|
delete[] nm_tmp; // clean up alloc |
701 |
|
|
/* Now clean up the buffer */ |
702 |
|
|
return wxRealPath(buf); |
703 |
|
|
} |
704 |
|
|
|
705 |
|
|
/* Contract Paths to be build upon an environment variable |
706 |
|
|
component: |
707 |
|
|
|
708 |
|
|
example: "/usr/openwin/lib", OPENWINHOME --> ${OPENWINHOME}/lib |
709 |
|
|
|
710 |
|
|
The call wxExpandPath can convert these back! |
711 |
|
|
*/ |
712 |
|
|
wxChar * |
713 |
|
|
wxContractPath (const wxString& filename, |
714 |
|
|
const wxString& WXUNUSED_IN_WINCE(envname), |
715 |
|
|
const wxString& user) |
716 |
|
|
{ |
717 |
|
|
static wxChar dest[_MAXPATHLEN]; |
718 |
|
|
|
719 |
|
|
if (filename.empty()) |
720 |
|
|
return (wxChar *) NULL; |
721 |
|
|
|
722 |
|
|
wxStrcpy (dest, WXSTRINGCAST filename); |
723 |
|
|
#ifdef __WXMSW__ |
724 |
|
|
wxUnix2DosFilename(dest); |
725 |
|
|
#endif |
726 |
|
|
|
727 |
|
|
// Handle environment |
728 |
|
|
const wxChar *val; |
729 |
|
|
#ifndef __WXWINCE__ |
730 |
|
|
wxChar *tcp; |
731 |
|
|
if (!envname.empty() && (val = wxGetenv (WXSTRINGCAST envname)) != NULL && |
732 |
|
|
(tcp = wxStrstr (dest, val)) != NULL) |
733 |
|
|
{ |
734 |
|
|
wxStrcpy (wxFileFunctionsBuffer, tcp + wxStrlen (val)); |
735 |
|
|
*tcp++ = wxT('$'); |
736 |
|
|
*tcp++ = wxT('{'); |
737 |
|
|
wxStrcpy (tcp, WXSTRINGCAST envname); |
738 |
|
|
wxStrcat (tcp, wxT("}")); |
739 |
|
|
wxStrcat (tcp, wxFileFunctionsBuffer); |
740 |
|
|
} |
741 |
|
|
#endif |
742 |
|
|
|
743 |
|
|
// Handle User's home (ignore root homes!) |
744 |
|
|
val = wxGetUserHome (user); |
745 |
|
|
if (!val) |
746 |
|
|
return dest; |
747 |
|
|
|
748 |
|
|
const size_t len = wxStrlen(val); |
749 |
|
|
if (len <= 2) |
750 |
|
|
return dest; |
751 |
|
|
|
752 |
|
|
if (wxStrncmp(dest, val, len) == 0) |
753 |
|
|
{ |
754 |
|
|
wxStrcpy(wxFileFunctionsBuffer, wxT("~")); |
755 |
|
|
if (!user.empty()) |
756 |
|
|
wxStrcat(wxFileFunctionsBuffer, (const wxChar*) user); |
757 |
|
|
wxStrcat(wxFileFunctionsBuffer, dest + len); |
758 |
|
|
wxStrcpy (dest, wxFileFunctionsBuffer); |
759 |
|
|
} |
760 |
|
|
|
761 |
|
|
return dest; |
762 |
|
|
} |
763 |
|
|
|
764 |
|
|
// Return just the filename, not the path (basename) |
765 |
|
|
wxChar *wxFileNameFromPath (wxChar *path) |
766 |
|
|
{ |
767 |
|
|
wxString p = path; |
768 |
|
|
wxString n = wxFileNameFromPath(p); |
769 |
|
|
|
770 |
|
|
return path + p.length() - n.length(); |
771 |
|
|
} |
772 |
|
|
|
773 |
|
|
wxString wxFileNameFromPath (const wxString& path) |
774 |
|
|
{ |
775 |
|
|
wxString name, ext; |
776 |
|
|
wxFileName::SplitPath(path, NULL, &name, &ext); |
777 |
|
|
|
778 |
|
|
wxString fullname = name; |
779 |
|
|
if ( !ext.empty() ) |
780 |
|
|
{ |
781 |
|
|
fullname << wxFILE_SEP_EXT << ext; |
782 |
|
|
} |
783 |
|
|
|
784 |
|
|
return fullname; |
785 |
|
|
} |
786 |
|
|
|
787 |
|
|
// Return just the directory, or NULL if no directory |
788 |
|
|
wxChar * |
789 |
|
|
wxPathOnly (wxChar *path) |
790 |
|
|
{ |
791 |
|
|
if (path && *path) |
792 |
|
|
{ |
793 |
|
|
static wxChar buf[_MAXPATHLEN]; |
794 |
|
|
|
795 |
|
|
// Local copy |
796 |
|
|
wxStrcpy (buf, path); |
797 |
|
|
|
798 |
|
|
int l = wxStrlen(path); |
799 |
|
|
int i = l - 1; |
800 |
|
|
|
801 |
|
|
// Search backward for a backward or forward slash |
802 |
|
|
while (i > -1) |
803 |
|
|
{ |
804 |
|
|
#if defined(__WXMAC__) && !defined(__DARWIN__) |
805 |
|
|
// Classic or Carbon CodeWarrior like |
806 |
|
|
// Carbon with Apple DevTools is Unix like |
807 |
|
|
if (path[i] == wxT(':') ) |
808 |
|
|
{ |
809 |
|
|
buf[i] = 0; |
810 |
|
|
return buf; |
811 |
|
|
} |
812 |
|
|
#else |
813 |
|
|
// Unix like or Windows |
814 |
|
|
if (path[i] == wxT('/') || path[i] == wxT('\\')) |
815 |
|
|
{ |
816 |
|
|
buf[i] = 0; |
817 |
|
|
return buf; |
818 |
|
|
} |
819 |
|
|
#endif |
820 |
|
|
#ifdef __VMS__ |
821 |
|
|
if (path[i] == wxT(']')) |
822 |
|
|
{ |
823 |
|
|
buf[i+1] = 0; |
824 |
|
|
return buf; |
825 |
|
|
} |
826 |
|
|
#endif |
827 |
|
|
i --; |
828 |
|
|
} |
829 |
|
|
|
830 |
|
|
#if defined(__WXMSW__) || defined(__OS2__) |
831 |
|
|
// Try Drive specifier |
832 |
|
|
if (wxIsalpha (buf[0]) && buf[1] == wxT(':')) |
833 |
|
|
{ |
834 |
|
|
// A:junk --> A:. (since A:.\junk Not A:\junk) |
835 |
|
|
buf[2] = wxT('.'); |
836 |
|
|
buf[3] = wxT('\0'); |
837 |
|
|
return buf; |
838 |
|
|
} |
839 |
|
|
#endif |
840 |
|
|
} |
841 |
|
|
return (wxChar *) NULL; |
842 |
|
|
} |
843 |
|
|
|
844 |
|
|
// Return just the directory, or NULL if no directory |
845 |
|
|
wxString wxPathOnly (const wxString& path) |
846 |
|
|
{ |
847 |
|
|
if (!path.empty()) |
848 |
|
|
{ |
849 |
|
|
wxChar buf[_MAXPATHLEN]; |
850 |
|
|
|
851 |
|
|
// Local copy |
852 |
|
|
wxStrcpy (buf, WXSTRINGCAST path); |
853 |
|
|
|
854 |
|
|
int l = path.length(); |
855 |
|
|
int i = l - 1; |
856 |
|
|
|
857 |
|
|
// Search backward for a backward or forward slash |
858 |
|
|
while (i > -1) |
859 |
|
|
{ |
860 |
|
|
#if defined(__WXMAC__) && !defined(__DARWIN__) |
861 |
|
|
// Classic or Carbon CodeWarrior like |
862 |
|
|
// Carbon with Apple DevTools is Unix like |
863 |
|
|
if (path[i] == wxT(':') ) |
864 |
|
|
{ |
865 |
|
|
buf[i] = 0; |
866 |
|
|
return wxString(buf); |
867 |
|
|
} |
868 |
|
|
#else |
869 |
|
|
// Unix like or Windows |
870 |
|
|
if (path[i] == wxT('/') || path[i] == wxT('\\')) |
871 |
|
|
{ |
872 |
|
|
// Don't return an empty string |
873 |
|
|
if (i == 0) |
874 |
|
|
i ++; |
875 |
|
|
buf[i] = 0; |
876 |
|
|
return wxString(buf); |
877 |
|
|
} |
878 |
|
|
#endif |
879 |
|
|
#ifdef __VMS__ |
880 |
|
|
if (path[i] == wxT(']')) |
881 |
|
|
{ |
882 |
|
|
buf[i+1] = 0; |
883 |
|
|
return wxString(buf); |
884 |
|
|
} |
885 |
|
|
#endif |
886 |
|
|
i --; |
887 |
|
|
} |
888 |
|
|
|
889 |
|
|
#if defined(__WXMSW__) || defined(__OS2__) |
890 |
|
|
// Try Drive specifier |
891 |
|
|
if (wxIsalpha (buf[0]) && buf[1] == wxT(':')) |
892 |
|
|
{ |
893 |
|
|
// A:junk --> A:. (since A:.\junk Not A:\junk) |
894 |
|
|
buf[2] = wxT('.'); |
895 |
|
|
buf[3] = wxT('\0'); |
896 |
|
|
return wxString(buf); |
897 |
|
|
} |
898 |
|
|
#endif |
899 |
|
|
} |
900 |
|
|
return wxEmptyString; |
901 |
|
|
} |
902 |
|
|
|
903 |
|
|
// Utility for converting delimiters in DOS filenames to UNIX style |
904 |
|
|
// and back again - or we get nasty problems with delimiters. |
905 |
|
|
// Also, convert to lower case, since case is significant in UNIX. |
906 |
|
|
|
907 |
|
|
#if defined(__WXMAC__) |
908 |
|
|
|
909 |
|
|
#if TARGET_API_MAC_OSX |
910 |
|
|
#define kDefaultPathStyle kCFURLPOSIXPathStyle |
911 |
|
|
#else |
912 |
|
|
#define kDefaultPathStyle kCFURLHFSPathStyle |
913 |
|
|
#endif |
914 |
|
|
|
915 |
|
|
wxString wxMacFSRefToPath( const FSRef *fsRef , CFStringRef additionalPathComponent ) |
916 |
|
|
{ |
917 |
|
|
CFURLRef fullURLRef; |
918 |
|
|
fullURLRef = CFURLCreateFromFSRef(NULL, fsRef); |
919 |
|
|
if ( additionalPathComponent ) |
920 |
|
|
{ |
921 |
|
|
CFURLRef parentURLRef = fullURLRef ; |
922 |
|
|
fullURLRef = CFURLCreateCopyAppendingPathComponent(NULL, parentURLRef, |
923 |
|
|
additionalPathComponent,false); |
924 |
|
|
CFRelease( parentURLRef ) ; |
925 |
|
|
} |
926 |
|
|
CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, kDefaultPathStyle); |
927 |
|
|
CFRelease( fullURLRef ) ; |
928 |
|
|
CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString); |
929 |
|
|
CFRelease( cfString ); |
930 |
|
|
CFStringNormalize(cfMutableString,kCFStringNormalizationFormC); |
931 |
|
|
return wxMacCFStringHolder(cfMutableString).AsString(); |
932 |
|
|
} |
933 |
|
|
|
934 |
|
|
OSStatus wxMacPathToFSRef( const wxString&path , FSRef *fsRef ) |
935 |
|
|
{ |
936 |
|
|
OSStatus err = noErr ; |
937 |
|
|
CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, wxMacCFStringHolder(path)); |
938 |
|
|
CFStringNormalize(cfMutableString,kCFStringNormalizationFormD); |
939 |
|
|
CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kDefaultPathStyle, false); |
940 |
|
|
CFRelease( cfMutableString ); |
941 |
|
|
if ( NULL != url ) |
942 |
|
|
{ |
943 |
|
|
if ( CFURLGetFSRef(url, fsRef) == false ) |
944 |
|
|
err = fnfErr ; |
945 |
|
|
CFRelease( url ) ; |
946 |
|
|
} |
947 |
|
|
else |
948 |
|
|
{ |
949 |
|
|
err = fnfErr ; |
950 |
|
|
} |
951 |
|
|
return err ; |
952 |
|
|
} |
953 |
|
|
|
954 |
|
|
wxString wxMacHFSUniStrToString( ConstHFSUniStr255Param uniname ) |
955 |
|
|
{ |
956 |
|
|
CFStringRef cfname = CFStringCreateWithCharacters( kCFAllocatorDefault, |
957 |
|
|
uniname->unicode, |
958 |
|
|
uniname->length ); |
959 |
|
|
CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfname); |
960 |
|
|
CFRelease( cfname ); |
961 |
|
|
CFStringNormalize(cfMutableString,kCFStringNormalizationFormC); |
962 |
|
|
return wxMacCFStringHolder(cfMutableString).AsString() ; |
963 |
|
|
} |
964 |
|
|
|
965 |
|
|
#ifndef __LP64__ |
966 |
|
|
|
967 |
|
|
wxString wxMacFSSpec2MacFilename( const FSSpec *spec ) |
968 |
|
|
{ |
969 |
|
|
FSRef fsRef ; |
970 |
|
|
if ( FSpMakeFSRef( spec , &fsRef) == noErr ) |
971 |
|
|
{ |
972 |
|
|
return wxMacFSRefToPath( &fsRef ) ; |
973 |
|
|
} |
974 |
|
|
return wxEmptyString ; |
975 |
|
|
} |
976 |
|
|
|
977 |
|
|
void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec ) |
978 |
|
|
{ |
979 |
|
|
OSStatus err = noErr ; |
980 |
|
|
FSRef fsRef ; |
981 |
|
|
wxMacPathToFSRef( path , &fsRef ) ; |
982 |
|
|
err = FSRefMakeFSSpec( &fsRef , spec ) ; |
983 |
|
|
} |
984 |
|
|
#endif |
985 |
|
|
|
986 |
|
|
#endif // __WXMAC__ |
987 |
|
|
|
988 |
|
|
void |
989 |
|
|
wxDos2UnixFilename (wxChar *s) |
990 |
|
|
{ |
991 |
|
|
if (s) |
992 |
|
|
while (*s) |
993 |
|
|
{ |
994 |
|
|
if (*s == _T('\\')) |
995 |
|
|
*s = _T('/'); |
996 |
|
|
#ifdef __WXMSW__ |
997 |
|
|
else |
998 |
|
|
*s = (wxChar)wxTolower (*s); // Case INDEPENDENT |
999 |
|
|
#endif |
1000 |
|
|
s++; |
1001 |
|
|
} |
1002 |
|
|
} |
1003 |
|
|
|
1004 |
|
|
void |
1005 |
|
|
#if defined(__WXMSW__) || defined(__OS2__) |
1006 |
|
|
wxUnix2DosFilename (wxChar *s) |
1007 |
|
|
#else |
1008 |
|
|
wxUnix2DosFilename (wxChar *WXUNUSED(s) ) |
1009 |
|
|
#endif |
1010 |
|
|
{ |
1011 |
|
|
// Yes, I really mean this to happen under DOS only! JACS |
1012 |
|
|
#if defined(__WXMSW__) || defined(__OS2__) |
1013 |
|
|
if (s) |
1014 |
|
|
while (*s) |
1015 |
|
|
{ |
1016 |
|
|
if (*s == wxT('/')) |
1017 |
|
|
*s = wxT('\\'); |
1018 |
|
|
s++; |
1019 |
|
|
} |
1020 |
|
|
#endif |
1021 |
|
|
} |
1022 |
|
|
|
1023 |
|
|
// Concatenate two files to form third |
1024 |
|
|
bool |
1025 |
|
|
wxConcatFiles (const wxString& file1, const wxString& file2, const wxString& file3) |
1026 |
|
|
{ |
1027 |
|
|
#if wxUSE_FILE |
1028 |
|
|
|
1029 |
|
|
wxFile in1(file1), in2(file2); |
1030 |
|
|
wxTempFile out(file3); |
1031 |
|
|
|
1032 |
|
|
if ( !in1.IsOpened() || !in2.IsOpened() || !out.IsOpened() ) |
1033 |
|
|
return false; |
1034 |
|
|
|
1035 |
|
|
ssize_t ofs; |
1036 |
|
|
unsigned char buf[1024]; |
1037 |
|
|
|
1038 |
|
|
for( int i=0; i<2; i++) |
1039 |
|
|
{ |
1040 |
|
|
wxFile *in = i==0 ? &in1 : &in2; |
1041 |
|
|
do{ |
1042 |
|
|
if ( (ofs = in->Read(buf,WXSIZEOF(buf))) == wxInvalidOffset ) return false; |
1043 |
|
|
if ( ofs > 0 ) |
1044 |
|
|
if ( !out.Write(buf,ofs) ) |
1045 |
|
|
return false; |
1046 |
|
|
} while ( ofs == (ssize_t)WXSIZEOF(buf) ); |
1047 |
|
|
} |
1048 |
|
|
|
1049 |
|
|
return out.Commit(); |
1050 |
|
|
|
1051 |
|
|
#else |
1052 |
|
|
|
1053 |
|
|
wxUnusedVar(file1); |
1054 |
|
|
wxUnusedVar(file2); |
1055 |
|
|
wxUnusedVar(file3); |
1056 |
|
|
return false; |
1057 |
|
|
|
1058 |
|
|
#endif |
1059 |
|
|
} |
1060 |
|
|
|
1061 |
|
|
// Copy files |
1062 |
|
|
bool |
1063 |
|
|
wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) |
1064 |
|
|
{ |
1065 |
|
|
#if defined(__WIN32__) && !defined(__WXMICROWIN__) |
1066 |
|
|
// CopyFile() copies file attributes and modification time too, so use it |
1067 |
|
|
// instead of our code if available |
1068 |
|
|
// |
1069 |
|
|
// NB: 3rd parameter is bFailIfExists i.e. the inverse of overwrite |
1070 |
|
|
if ( !::CopyFile(file1, file2, !overwrite) ) |
1071 |
|
|
{ |
1072 |
|
|
wxLogSysError(_("Failed to copy the file '%s' to '%s'"), |
1073 |
|
|
file1.c_str(), file2.c_str()); |
1074 |
|
|
|
1075 |
|
|
return false; |
1076 |
|
|
} |
1077 |
|
|
#elif defined(__OS2__) |
1078 |
|
|
if ( ::DosCopy((PSZ)file1.c_str(), (PSZ)file2.c_str(), overwrite ? DCPY_EXISTING : 0) != 0 ) |
1079 |
|
|
return false; |
1080 |
|
|
#elif defined(__PALMOS__) |
1081 |
|
|
// TODO with http://www.palmos.com/dev/support/docs/protein_books/Memory_Databases_Files/ |
1082 |
|
|
return false; |
1083 |
|
|
#elif wxUSE_FILE // !Win32 |
1084 |
|
|
|
1085 |
|
|
wxStructStat fbuf; |
1086 |
|
|
// get permissions of file1 |
1087 |
|
|
if ( wxStat( file1.c_str(), &fbuf) != 0 ) |
1088 |
|
|
{ |
1089 |
|
|
// the file probably doesn't exist or we haven't the rights to read |
1090 |
|
|
// from it anyhow |
1091 |
|
|
wxLogSysError(_("Impossible to get permissions for file '%s'"), |
1092 |
|
|
file1.c_str()); |
1093 |
|
|
return false; |
1094 |
|
|
} |
1095 |
|
|
|
1096 |
|
|
// open file1 for reading |
1097 |
|
|
wxFile fileIn(file1, wxFile::read); |
1098 |
|
|
if ( !fileIn.IsOpened() ) |
1099 |
|
|
return false; |
1100 |
|
|
|
1101 |
|
|
// remove file2, if it exists. This is needed for creating |
1102 |
|
|
// file2 with the correct permissions in the next step |
1103 |
|
|
if ( wxFileExists(file2) && (!overwrite || !wxRemoveFile(file2))) |
1104 |
|
|
{ |
1105 |
|
|
wxLogSysError(_("Impossible to overwrite the file '%s'"), |
1106 |
|
|
file2.c_str()); |
1107 |
|
|
return false; |
1108 |
|
|
} |
1109 |
|
|
|
1110 |
|
|
// reset the umask as we want to create the file with exactly the same |
1111 |
|
|
// permissions as the original one |
1112 |
|
|
wxCHANGE_UMASK(0); |
1113 |
|
|
|
1114 |
|
|
// create file2 with the same permissions than file1 and open it for |
1115 |
|
|
// writing |
1116 |
|
|
|
1117 |
|
|
wxFile fileOut; |
1118 |
|
|
if ( !fileOut.Create(file2, overwrite, fbuf.st_mode & 0777) ) |
1119 |
|
|
return false; |
1120 |
|
|
|
1121 |
|
|
// copy contents of file1 to file2 |
1122 |
|
|
char buf[4096]; |
1123 |
|
|
size_t count; |
1124 |
|
|
for ( ;; ) |
1125 |
|
|
{ |
1126 |
|
|
count = fileIn.Read(buf, WXSIZEOF(buf)); |
1127 |
|
|
if ( fileIn.Error() ) |
1128 |
|
|
return false; |
1129 |
|
|
|
1130 |
|
|
// end of file? |
1131 |
|
|
if ( !count ) |
1132 |
|
|
break; |
1133 |
|
|
|
1134 |
|
|
if ( fileOut.Write(buf, count) < count ) |
1135 |
|
|
return false; |
1136 |
|
|
} |
1137 |
|
|
|
1138 |
|
|
// we can expect fileIn to be closed successfully, but we should ensure |
1139 |
|
|
// that fileOut was closed as some write errors (disk full) might not be |
1140 |
|
|
// detected before doing this |
1141 |
|
|
if ( !fileIn.Close() || !fileOut.Close() ) |
1142 |
|
|
return false; |
1143 |
|
|
|
1144 |
|
|
#if !defined(__VISAGECPP__) && !defined(__WXMAC__) || defined(__UNIX__) |
1145 |
|
|
// no chmod in VA. Should be some permission API for HPFS386 partitions |
1146 |
|
|
// however |
1147 |
|
|
if ( chmod(OS_FILENAME(file2), fbuf.st_mode) != 0 ) |
1148 |
|
|
{ |
1149 |
|
|
wxLogSysError(_("Impossible to set permissions for the file '%s'"), |
1150 |
|
|
file2.c_str()); |
1151 |
|
|
return false; |
1152 |
|
|
} |
1153 |
|
|
#endif // OS/2 || Mac |
1154 |
|
|
|
1155 |
|
|
#else // !Win32 && ! wxUSE_FILE |
1156 |
|
|
|
1157 |
|
|
// impossible to simulate with wxWidgets API |
1158 |
|
|
wxUnusedVar(file1); |
1159 |
|
|
wxUnusedVar(file2); |
1160 |
|
|
wxUnusedVar(overwrite); |
1161 |
|
|
return false; |
1162 |
|
|
|
1163 |
|
|
#endif // __WXMSW__ && __WIN32__ |
1164 |
|
|
|
1165 |
|
|
return true; |
1166 |
|
|
} |
1167 |
|
|
|
1168 |
|
|
bool |
1169 |
|
|
wxRenameFile(const wxString& file1, const wxString& file2, bool overwrite) |
1170 |
|
|
{ |
1171 |
|
|
if ( !overwrite && wxFileExists(file2) ) |
1172 |
|
|
{ |
1173 |
|
|
wxLogSysError |
1174 |
|
|
( |
1175 |
|
|
_("Failed to rename the file '%s' to '%s' because the destination file already exists."), |
1176 |
|
|
file1.c_str(), file2.c_str() |
1177 |
|
|
); |
1178 |
|
|
|
1179 |
|
|
return false; |
1180 |
|
|
} |
1181 |
|
|
|
1182 |
william |
273 |
#ifdef __WXMSW__ |
1183 |
|
|
return ::MoveFileEx(file1,file2, MOVEFILE_REPLACE_EXISTING) != 0; |
1184 |
|
|
#else |
1185 |
william |
31 |
#if !defined(__WXWINCE__) && !defined(__WXPALMOS__) |
1186 |
|
|
// Normal system call |
1187 |
|
|
if ( wxRename (file1, file2) == 0 ) |
1188 |
|
|
return true; |
1189 |
|
|
#endif |
1190 |
|
|
|
1191 |
|
|
// Try to copy |
1192 |
|
|
if (wxCopyFile(file1, file2, overwrite)) { |
1193 |
|
|
wxRemoveFile(file1); |
1194 |
|
|
return true; |
1195 |
|
|
} |
1196 |
|
|
// Give up |
1197 |
|
|
return false; |
1198 |
william |
273 |
#endif |
1199 |
william |
31 |
} |
1200 |
|
|
|
1201 |
|
|
bool wxRemoveFile(const wxString& file) |
1202 |
|
|
{ |
1203 |
|
|
#if defined(__VISUALC__) \ |
1204 |
|
|
|| defined(__BORLANDC__) \ |
1205 |
|
|
|| defined(__WATCOMC__) \ |
1206 |
|
|
|| defined(__DMC__) \ |
1207 |
|
|
|| defined(__GNUWIN32__) \ |
1208 |
|
|
|| (defined(__MWERKS__) && defined(__MSL__)) |
1209 |
|
|
int res = wxRemove(file); |
1210 |
|
|
#elif defined(__WXMAC__) |
1211 |
|
|
int res = unlink(wxFNCONV(file)); |
1212 |
|
|
#elif defined(__WXPALMOS__) |
1213 |
|
|
int res = 1; |
1214 |
|
|
// TODO with VFSFileDelete() |
1215 |
|
|
#else |
1216 |
|
|
int res = unlink(OS_FILENAME(file)); |
1217 |
|
|
#endif |
1218 |
|
|
|
1219 |
|
|
return res == 0; |
1220 |
|
|
} |
1221 |
|
|
|
1222 |
|
|
bool wxMkdir(const wxString& dir, int perm) |
1223 |
|
|
{ |
1224 |
|
|
#if defined(__WXPALMOS__) |
1225 |
|
|
return false; |
1226 |
|
|
#elif defined(__WXMAC__) && !defined(__UNIX__) |
1227 |
|
|
return (mkdir( wxFNCONV(dir) , 0 ) == 0); |
1228 |
|
|
#else // !Mac |
1229 |
|
|
const wxChar *dirname = dir.c_str(); |
1230 |
|
|
|
1231 |
|
|
// assume mkdir() has 2 args on non Windows-OS/2 platforms and on Windows too |
1232 |
|
|
// for the GNU compiler |
1233 |
|
|
#if (!(defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__))) || (defined(__GNUWIN32__) && !defined(__MINGW32__)) || defined(__WINE__) || defined(__WXMICROWIN__) |
1234 |
|
|
#if defined(MSVCRT) |
1235 |
|
|
wxUnusedVar(perm); |
1236 |
|
|
if ( mkdir(wxFNCONV(dirname)) != 0 ) |
1237 |
|
|
#else |
1238 |
|
|
if ( mkdir(wxFNCONV(dirname), perm) != 0 ) |
1239 |
|
|
#endif |
1240 |
|
|
#elif defined(__OS2__) |
1241 |
|
|
wxUnusedVar(perm); |
1242 |
|
|
if (::DosCreateDir((PSZ)dirname, NULL) != 0) // enhance for EAB's?? |
1243 |
|
|
#elif defined(__DOS__) |
1244 |
|
|
#if defined(__WATCOMC__) |
1245 |
|
|
(void)perm; |
1246 |
|
|
if ( wxMkDir(wxFNSTRINGCAST wxFNCONV(dirname)) != 0 ) |
1247 |
|
|
#elif defined(__DJGPP__) |
1248 |
|
|
if ( mkdir(wxFNCONV(dirname), perm) != 0 ) |
1249 |
|
|
#else |
1250 |
|
|
#error "Unsupported DOS compiler!" |
1251 |
|
|
#endif |
1252 |
|
|
#else // !MSW, !DOS and !OS/2 VAC++ |
1253 |
|
|
wxUnusedVar(perm); |
1254 |
|
|
#ifdef __WXWINCE__ |
1255 |
|
|
if ( !CreateDirectory(dirname, NULL) ) |
1256 |
|
|
#else |
1257 |
|
|
if ( wxMkDir(dir.fn_str()) != 0 ) |
1258 |
|
|
#endif |
1259 |
|
|
#endif // !MSW/MSW |
1260 |
|
|
{ |
1261 |
|
|
wxLogSysError(_("Directory '%s' couldn't be created"), dirname); |
1262 |
|
|
|
1263 |
|
|
return false; |
1264 |
|
|
} |
1265 |
|
|
|
1266 |
|
|
return true; |
1267 |
|
|
#endif // Mac/!Mac |
1268 |
|
|
} |
1269 |
|
|
|
1270 |
|
|
bool wxRmdir(const wxString& dir, int WXUNUSED(flags)) |
1271 |
|
|
{ |
1272 |
|
|
#if defined(__VMS__) |
1273 |
|
|
return false; //to be changed since rmdir exists in VMS7.x |
1274 |
|
|
#elif defined(__OS2__) |
1275 |
|
|
return (::DosDeleteDir((PSZ)dir.c_str()) == 0); |
1276 |
|
|
#elif defined(__WXWINCE__) |
1277 |
|
|
return (RemoveDirectory(dir) != 0); |
1278 |
|
|
#elif defined(__WXPALMOS__) |
1279 |
|
|
// TODO with VFSFileRename() |
1280 |
|
|
return false; |
1281 |
|
|
#else |
1282 |
|
|
return (wxRmDir(OS_FILENAME(dir)) == 0); |
1283 |
|
|
#endif |
1284 |
|
|
} |
1285 |
|
|
|
1286 |
|
|
// does the path exists? (may have or not '/' or '\\' at the end) |
1287 |
|
|
bool wxDirExists(const wxChar *pszPathName) |
1288 |
|
|
{ |
1289 |
|
|
wxString strPath(pszPathName); |
1290 |
|
|
|
1291 |
|
|
#if defined(__WINDOWS__) || defined(__OS2__) |
1292 |
|
|
// Windows fails to find directory named "c:\dir\" even if "c:\dir" exists, |
1293 |
|
|
// so remove all trailing backslashes from the path - but don't do this for |
1294 |
|
|
// the paths "d:\" (which are different from "d:") nor for just "\" |
1295 |
|
|
while ( wxEndsWithPathSeparator(strPath) ) |
1296 |
|
|
{ |
1297 |
|
|
size_t len = strPath.length(); |
1298 |
|
|
if ( len == 1 || (len == 3 && strPath[len - 2] == _T(':')) ) |
1299 |
|
|
break; |
1300 |
|
|
|
1301 |
|
|
strPath.Truncate(len - 1); |
1302 |
|
|
} |
1303 |
|
|
#endif // __WINDOWS__ |
1304 |
|
|
|
1305 |
|
|
#ifdef __OS2__ |
1306 |
|
|
// OS/2 can't handle "d:", it wants either "d:\" or "d:." |
1307 |
|
|
if (strPath.length() == 2 && strPath[1u] == _T(':')) |
1308 |
|
|
strPath << _T('.'); |
1309 |
|
|
#endif |
1310 |
|
|
|
1311 |
|
|
#if defined(__WXPALMOS__) |
1312 |
|
|
return false; |
1313 |
|
|
#elif defined(__WIN32__) && !defined(__WXMICROWIN__) |
1314 |
|
|
// stat() can't cope with network paths |
1315 |
|
|
DWORD ret = ::GetFileAttributes(strPath); |
1316 |
|
|
|
1317 |
|
|
return (ret != (DWORD)-1) && (ret & FILE_ATTRIBUTE_DIRECTORY); |
1318 |
|
|
#elif defined(__OS2__) |
1319 |
|
|
FILESTATUS3 Info = {{0}}; |
1320 |
|
|
APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD, |
1321 |
|
|
(void*) &Info, sizeof(FILESTATUS3)); |
1322 |
|
|
|
1323 |
|
|
return ((rc == NO_ERROR) && (Info.attrFile & FILE_DIRECTORY)) || |
1324 |
|
|
(rc == ERROR_SHARING_VIOLATION); |
1325 |
|
|
// If we got a sharing violation, there must be something with this name. |
1326 |
|
|
#else // !__WIN32__ |
1327 |
|
|
|
1328 |
|
|
wxStructStat st; |
1329 |
|
|
#ifndef __VISAGECPP__ |
1330 |
|
|
return wxStat(strPath.c_str(), &st) == 0 && ((st.st_mode & S_IFMT) == S_IFDIR); |
1331 |
|
|
#else |
1332 |
|
|
// S_IFMT not supported in VA compilers.. st_mode is a 2byte value only |
1333 |
|
|
return wxStat(pszPathName, &st) == 0 && (st.st_mode == S_IFDIR); |
1334 |
|
|
#endif |
1335 |
|
|
|
1336 |
|
|
#endif // __WIN32__/!__WIN32__ |
1337 |
|
|
} |
1338 |
|
|
|
1339 |
|
|
// Get a temporary filename, opening and closing the file. |
1340 |
|
|
wxChar *wxGetTempFileName(const wxString& prefix, wxChar *buf) |
1341 |
|
|
{ |
1342 |
|
|
wxString filename; |
1343 |
|
|
if ( !wxGetTempFileName(prefix, filename) ) |
1344 |
|
|
return NULL; |
1345 |
|
|
|
1346 |
|
|
if ( buf ) |
1347 |
|
|
wxStrcpy(buf, filename); |
1348 |
|
|
else |
1349 |
|
|
buf = MYcopystring(filename); |
1350 |
|
|
|
1351 |
|
|
return buf; |
1352 |
|
|
} |
1353 |
|
|
|
1354 |
|
|
bool wxGetTempFileName(const wxString& prefix, wxString& buf) |
1355 |
|
|
{ |
1356 |
|
|
#if wxUSE_FILE |
1357 |
|
|
buf = wxFileName::CreateTempFileName(prefix); |
1358 |
|
|
|
1359 |
|
|
return !buf.empty(); |
1360 |
|
|
#else // !wxUSE_FILE |
1361 |
|
|
wxUnusedVar(prefix); |
1362 |
|
|
wxUnusedVar(buf); |
1363 |
|
|
|
1364 |
|
|
return false; |
1365 |
|
|
#endif // wxUSE_FILE/!wxUSE_FILE |
1366 |
|
|
} |
1367 |
|
|
|
1368 |
|
|
// Get first file name matching given wild card. |
1369 |
|
|
|
1370 |
|
|
static wxDir *gs_dir = NULL; |
1371 |
|
|
static wxString gs_dirPath; |
1372 |
|
|
|
1373 |
|
|
wxString wxFindFirstFile(const wxChar *spec, int flags) |
1374 |
|
|
{ |
1375 |
|
|
wxSplitPath(spec, &gs_dirPath, NULL, NULL); |
1376 |
|
|
if ( gs_dirPath.empty() ) |
1377 |
|
|
gs_dirPath = wxT("."); |
1378 |
|
|
if ( !wxEndsWithPathSeparator(gs_dirPath ) ) |
1379 |
|
|
gs_dirPath << wxFILE_SEP_PATH; |
1380 |
|
|
|
1381 |
|
|
if (gs_dir) |
1382 |
|
|
delete gs_dir; |
1383 |
|
|
gs_dir = new wxDir(gs_dirPath); |
1384 |
|
|
|
1385 |
|
|
if ( !gs_dir->IsOpened() ) |
1386 |
|
|
{ |
1387 |
|
|
wxLogSysError(_("Can not enumerate files '%s'"), spec); |
1388 |
|
|
return wxEmptyString; |
1389 |
|
|
} |
1390 |
|
|
|
1391 |
|
|
int dirFlags; |
1392 |
|
|
switch (flags) |
1393 |
|
|
{ |
1394 |
|
|
case wxDIR: dirFlags = wxDIR_DIRS; break; |
1395 |
|
|
case wxFILE: dirFlags = wxDIR_FILES; break; |
1396 |
|
|
default: dirFlags = wxDIR_DIRS | wxDIR_FILES; break; |
1397 |
|
|
} |
1398 |
|
|
|
1399 |
|
|
wxString result; |
1400 |
|
|
gs_dir->GetFirst(&result, wxFileNameFromPath(wxString(spec)), dirFlags); |
1401 |
|
|
if ( result.empty() ) |
1402 |
|
|
{ |
1403 |
|
|
wxDELETE(gs_dir); |
1404 |
|
|
return result; |
1405 |
|
|
} |
1406 |
|
|
|
1407 |
|
|
return gs_dirPath + result; |
1408 |
|
|
} |
1409 |
|
|
|
1410 |
|
|
wxString wxFindNextFile() |
1411 |
|
|
{ |
1412 |
|
|
wxASSERT_MSG( gs_dir, wxT("You must call wxFindFirstFile before!") ); |
1413 |
|
|
|
1414 |
|
|
wxString result; |
1415 |
|
|
gs_dir->GetNext(&result); |
1416 |
|
|
|
1417 |
|
|
if ( result.empty() ) |
1418 |
|
|
{ |
1419 |
|
|
wxDELETE(gs_dir); |
1420 |
|
|
return result; |
1421 |
|
|
} |
1422 |
|
|
|
1423 |
|
|
return gs_dirPath + result; |
1424 |
|
|
} |
1425 |
|
|
|
1426 |
|
|
|
1427 |
|
|
// Get current working directory. |
1428 |
|
|
// If buf is NULL, allocates space using new, else copies into buf. |
1429 |
|
|
// wxGetWorkingDirectory() is obsolete, use wxGetCwd() |
1430 |
|
|
// wxDoGetCwd() is their common core to be moved |
1431 |
|
|
// to wxGetCwd() once wxGetWorkingDirectory() will be removed. |
1432 |
|
|
// Do not expose wxDoGetCwd in headers! |
1433 |
|
|
|
1434 |
|
|
wxChar *wxDoGetCwd(wxChar *buf, int sz) |
1435 |
|
|
{ |
1436 |
|
|
#if defined(__WXPALMOS__) |
1437 |
|
|
// TODO |
1438 |
|
|
if(buf && sz>0) buf[0] = _T('\0'); |
1439 |
|
|
return buf; |
1440 |
|
|
#elif defined(__WXWINCE__) |
1441 |
|
|
// TODO |
1442 |
|
|
if(buf && sz>0) buf[0] = _T('\0'); |
1443 |
|
|
return buf; |
1444 |
|
|
#else |
1445 |
|
|
if ( !buf ) |
1446 |
|
|
{ |
1447 |
|
|
buf = new wxChar[sz + 1]; |
1448 |
|
|
} |
1449 |
|
|
|
1450 |
|
|
bool ok wxDUMMY_INITIALIZE(false); |
1451 |
|
|
|
1452 |
|
|
// for the compilers which have Unicode version of _getcwd(), call it |
1453 |
|
|
// directly, for the others call the ANSI version and do the translation |
1454 |
|
|
#if !wxUSE_UNICODE |
1455 |
|
|
#define cbuf buf |
1456 |
|
|
#else // wxUSE_UNICODE |
1457 |
|
|
bool needsANSI = true; |
1458 |
|
|
|
1459 |
|
|
#if !defined(HAVE_WGETCWD) || wxUSE_UNICODE_MSLU |
1460 |
|
|
char cbuf[_MAXPATHLEN]; |
1461 |
|
|
#endif |
1462 |
|
|
|
1463 |
|
|
#ifdef HAVE_WGETCWD |
1464 |
|
|
#if wxUSE_UNICODE_MSLU |
1465 |
|
|
if ( wxGetOsVersion() != wxOS_WINDOWS_9X ) |
1466 |
|
|
#else |
1467 |
|
|
char *cbuf = NULL; // never really used because needsANSI will always be false |
1468 |
|
|
#endif |
1469 |
|
|
{ |
1470 |
|
|
ok = _wgetcwd(buf, sz) != NULL; |
1471 |
|
|
needsANSI = false; |
1472 |
|
|
} |
1473 |
|
|
#endif |
1474 |
|
|
|
1475 |
|
|
if ( needsANSI ) |
1476 |
|
|
#endif // wxUSE_UNICODE |
1477 |
|
|
{ |
1478 |
|
|
#if defined(_MSC_VER) || defined(__MINGW32__) |
1479 |
|
|
ok = _getcwd(cbuf, sz) != NULL; |
1480 |
|
|
#elif defined(__WXMAC__) && !defined(__DARWIN__) |
1481 |
|
|
char lbuf[1024] ; |
1482 |
|
|
if ( getcwd( lbuf , sizeof( lbuf ) ) ) |
1483 |
|
|
{ |
1484 |
|
|
wxString res( lbuf , *wxConvCurrent ) ; |
1485 |
|
|
wxStrcpy( buf , res ) ; |
1486 |
|
|
ok = true; |
1487 |
|
|
} |
1488 |
|
|
else |
1489 |
|
|
ok = false ; |
1490 |
|
|
#elif defined(__OS2__) |
1491 |
|
|
APIRET rc; |
1492 |
|
|
ULONG ulDriveNum = 0; |
1493 |
|
|
ULONG ulDriveMap = 0; |
1494 |
|
|
rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap); |
1495 |
|
|
ok = rc == 0; |
1496 |
|
|
if (ok) |
1497 |
|
|
{ |
1498 |
|
|
sz -= 3; |
1499 |
|
|
rc = ::DosQueryCurrentDir( 0 // current drive |
1500 |
|
|
,(PBYTE)cbuf + 3 |
1501 |
|
|
,(PULONG)&sz |
1502 |
|
|
); |
1503 |
|
|
cbuf[0] = char('A' + (ulDriveNum - 1)); |
1504 |
|
|
cbuf[1] = ':'; |
1505 |
|
|
cbuf[2] = '\\'; |
1506 |
|
|
ok = rc == 0; |
1507 |
|
|
} |
1508 |
|
|
#else // !Win32/VC++ !Mac !OS2 |
1509 |
|
|
ok = getcwd(cbuf, sz) != NULL; |
1510 |
|
|
#endif // platform |
1511 |
|
|
|
1512 |
|
|
#if wxUSE_UNICODE && !(defined(__WXMAC__) && !defined(__DARWIN__)) |
1513 |
|
|
// finally convert the result to Unicode if needed |
1514 |
|
|
wxConvFile.MB2WC(buf, cbuf, sz); |
1515 |
|
|
#endif // wxUSE_UNICODE |
1516 |
|
|
} |
1517 |
|
|
|
1518 |
|
|
if ( !ok ) |
1519 |
|
|
{ |
1520 |
|
|
wxLogSysError(_("Failed to get the working directory")); |
1521 |
|
|
|
1522 |
|
|
// VZ: the old code used to return "." on error which didn't make any |
1523 |
|
|
// sense at all to me - empty string is a better error indicator |
1524 |
|
|
// (NULL might be even better but I'm afraid this could lead to |
1525 |
|
|
// problems with the old code assuming the return is never NULL) |
1526 |
|
|
buf[0] = _T('\0'); |
1527 |
|
|
} |
1528 |
|
|
else // ok, but we might need to massage the path into the right format |
1529 |
|
|
{ |
1530 |
|
|
#ifdef __DJGPP__ |
1531 |
|
|
// VS: DJGPP is a strange mix of DOS and UNIX API and returns paths |
1532 |
|
|
// with / deliminers. We don't like that. |
1533 |
|
|
for (wxChar *ch = buf; *ch; ch++) |
1534 |
|
|
{ |
1535 |
|
|
if (*ch == wxT('/')) |
1536 |
|
|
*ch = wxT('\\'); |
1537 |
|
|
} |
1538 |
|
|
#endif // __DJGPP__ |
1539 |
|
|
|
1540 |
|
|
// MBN: we hope that in the case the user is compiling a GTK+/Motif app, |
1541 |
|
|
// he needs Unix as opposed to Win32 pathnames |
1542 |
|
|
#if defined( __CYGWIN__ ) && defined( __WINDOWS__ ) |
1543 |
|
|
// another example of DOS/Unix mix (Cygwin) |
1544 |
|
|
wxString pathUnix = buf; |
1545 |
|
|
#if wxUSE_UNICODE |
1546 |
|
|
char bufA[_MAXPATHLEN]; |
1547 |
|
|
cygwin_conv_to_full_win32_path(pathUnix.mb_str(wxConvFile), bufA); |
1548 |
|
|
wxConvFile.MB2WC(buf, bufA, sz); |
1549 |
|
|
#else |
1550 |
|
|
cygwin_conv_to_full_win32_path(pathUnix, buf); |
1551 |
|
|
#endif // wxUSE_UNICODE |
1552 |
|
|
#endif // __CYGWIN__ |
1553 |
|
|
} |
1554 |
|
|
|
1555 |
|
|
return buf; |
1556 |
|
|
|
1557 |
|
|
#if !wxUSE_UNICODE |
1558 |
|
|
#undef cbuf |
1559 |
|
|
#endif |
1560 |
|
|
|
1561 |
|
|
#endif |
1562 |
|
|
// __WXWINCE__ |
1563 |
|
|
} |
1564 |
|
|
|
1565 |
|
|
#if WXWIN_COMPATIBILITY_2_6 |
1566 |
|
|
wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) |
1567 |
|
|
{ |
1568 |
|
|
return wxDoGetCwd(buf,sz); |
1569 |
|
|
} |
1570 |
|
|
#endif // WXWIN_COMPATIBILITY_2_6 |
1571 |
|
|
|
1572 |
|
|
wxString wxGetCwd() |
1573 |
|
|
{ |
1574 |
|
|
wxString str; |
1575 |
|
|
wxDoGetCwd(wxStringBuffer(str, _MAXPATHLEN), _MAXPATHLEN); |
1576 |
|
|
return str; |
1577 |
|
|
} |
1578 |
|
|
|
1579 |
|
|
bool wxSetWorkingDirectory(const wxString& d) |
1580 |
|
|
{ |
1581 |
|
|
#if defined(__OS2__) |
1582 |
|
|
if (d[1] == ':') |
1583 |
|
|
{ |
1584 |
|
|
::DosSetDefaultDisk(1 + wxToupper(d[0]) - _T('A')); |
1585 |
|
|
// do not call DosSetCurrentDir when just changing drive, |
1586 |
|
|
// since it requires e.g. "d:." instead of "d:"! |
1587 |
|
|
if (d.length() == 2) |
1588 |
|
|
return true; |
1589 |
|
|
} |
1590 |
|
|
return (::DosSetCurrentDir((PSZ)d.c_str()) == 0); |
1591 |
|
|
#elif defined(__UNIX__) || defined(__WXMAC__) || defined(__DOS__) |
1592 |
|
|
return (chdir(wxFNSTRINGCAST d.fn_str()) == 0); |
1593 |
|
|
#elif defined(__WINDOWS__) |
1594 |
|
|
|
1595 |
|
|
#ifdef __WIN32__ |
1596 |
|
|
#ifdef __WXWINCE__ |
1597 |
|
|
// No equivalent in WinCE |
1598 |
|
|
wxUnusedVar(d); |
1599 |
|
|
return false; |
1600 |
|
|
#else |
1601 |
|
|
return (bool)(SetCurrentDirectory(d) != 0); |
1602 |
|
|
#endif |
1603 |
|
|
#else |
1604 |
|
|
// Must change drive, too. |
1605 |
|
|
bool isDriveSpec = ((strlen(d) > 1) && (d[1] == ':')); |
1606 |
|
|
if (isDriveSpec) |
1607 |
|
|
{ |
1608 |
|
|
wxChar firstChar = d[0]; |
1609 |
|
|
|
1610 |
|
|
// To upper case |
1611 |
|
|
if (firstChar > 90) |
1612 |
|
|
firstChar = firstChar - 32; |
1613 |
|
|
|
1614 |
|
|
// To a drive number |
1615 |
|
|
unsigned int driveNo = firstChar - 64; |
1616 |
|
|
if (driveNo > 0) |
1617 |
|
|
{ |
1618 |
|
|
unsigned int noDrives; |
1619 |
|
|
_dos_setdrive(driveNo, &noDrives); |
1620 |
|
|
} |
1621 |
|
|
} |
1622 |
|
|
bool success = (chdir(WXSTRINGCAST d) == 0); |
1623 |
|
|
|
1624 |
|
|
return success; |
1625 |
|
|
#endif |
1626 |
|
|
|
1627 |
|
|
#endif |
1628 |
|
|
} |
1629 |
|
|
|
1630 |
|
|
// Get the OS directory if appropriate (such as the Windows directory). |
1631 |
|
|
// On non-Windows platform, probably just return the empty string. |
1632 |
|
|
wxString wxGetOSDirectory() |
1633 |
|
|
{ |
1634 |
|
|
#ifdef __WXWINCE__ |
1635 |
|
|
return wxString(wxT("\\Windows")); |
1636 |
|
|
#elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) |
1637 |
|
|
wxChar buf[256]; |
1638 |
|
|
GetWindowsDirectory(buf, 256); |
1639 |
|
|
return wxString(buf); |
1640 |
|
|
#elif defined(__WXMAC__) |
1641 |
|
|
return wxMacFindFolder(kOnSystemDisk, 'macs', false); |
1642 |
|
|
#else |
1643 |
|
|
return wxEmptyString; |
1644 |
|
|
#endif |
1645 |
|
|
} |
1646 |
|
|
|
1647 |
|
|
bool wxEndsWithPathSeparator(const wxChar *pszFileName) |
1648 |
|
|
{ |
1649 |
|
|
size_t len = wxStrlen(pszFileName); |
1650 |
|
|
|
1651 |
|
|
return len && wxIsPathSeparator(pszFileName[len - 1]); |
1652 |
|
|
} |
1653 |
|
|
|
1654 |
|
|
// find a file in a list of directories, returns false if not found |
1655 |
|
|
bool wxFindFileInPath(wxString *pStr, const wxChar *pszPath, const wxChar *pszFile) |
1656 |
|
|
{ |
1657 |
|
|
// we assume that it's not empty |
1658 |
|
|
wxCHECK_MSG( !wxIsEmpty(pszFile), false, |
1659 |
|
|
_T("empty file name in wxFindFileInPath")); |
1660 |
|
|
|
1661 |
|
|
// skip path separator in the beginning of the file name if present |
1662 |
|
|
if ( wxIsPathSeparator(*pszFile) ) |
1663 |
|
|
pszFile++; |
1664 |
|
|
|
1665 |
|
|
// copy the path (strtok will modify it) |
1666 |
|
|
wxChar *szPath = new wxChar[wxStrlen(pszPath) + 1]; |
1667 |
|
|
wxStrcpy(szPath, pszPath); |
1668 |
|
|
|
1669 |
|
|
wxString strFile; |
1670 |
|
|
wxChar *pc, *save_ptr; |
1671 |
|
|
for ( pc = wxStrtok(szPath, wxPATH_SEP, &save_ptr); |
1672 |
|
|
pc != NULL; |
1673 |
|
|
pc = wxStrtok((wxChar *) NULL, wxPATH_SEP, &save_ptr) ) |
1674 |
|
|
{ |
1675 |
|
|
// search for the file in this directory |
1676 |
|
|
strFile = pc; |
1677 |
|
|
if ( !wxEndsWithPathSeparator(pc) ) |
1678 |
|
|
strFile += wxFILE_SEP_PATH; |
1679 |
|
|
strFile += pszFile; |
1680 |
|
|
|
1681 |
|
|
if ( wxFileExists(strFile) ) { |
1682 |
|
|
*pStr = strFile; |
1683 |
|
|
break; |
1684 |
|
|
} |
1685 |
|
|
} |
1686 |
|
|
|
1687 |
|
|
// suppress warning about unused variable save_ptr when wxStrtok() is a |
1688 |
|
|
// macro which throws away its third argument |
1689 |
|
|
save_ptr = pc; |
1690 |
|
|
|
1691 |
|
|
delete [] szPath; |
1692 |
|
|
|
1693 |
|
|
return pc != NULL; // if true => we breaked from the loop |
1694 |
|
|
} |
1695 |
|
|
|
1696 |
|
|
void WXDLLEXPORT wxSplitPath(const wxChar *pszFileName, |
1697 |
|
|
wxString *pstrPath, |
1698 |
|
|
wxString *pstrName, |
1699 |
|
|
wxString *pstrExt) |
1700 |
|
|
{ |
1701 |
|
|
// it can be empty, but it shouldn't be NULL |
1702 |
|
|
wxCHECK_RET( pszFileName, wxT("NULL file name in wxSplitPath") ); |
1703 |
|
|
|
1704 |
|
|
wxFileName::SplitPath(pszFileName, pstrPath, pstrName, pstrExt); |
1705 |
|
|
} |
1706 |
|
|
|
1707 |
|
|
#if wxUSE_DATETIME |
1708 |
|
|
|
1709 |
|
|
time_t WXDLLEXPORT wxFileModificationTime(const wxString& filename) |
1710 |
|
|
{ |
1711 |
|
|
wxDateTime mtime; |
1712 |
|
|
if ( !wxFileName(filename).GetTimes(NULL, &mtime, NULL) ) |
1713 |
|
|
return (time_t)-1; |
1714 |
|
|
|
1715 |
|
|
return mtime.GetTicks(); |
1716 |
|
|
} |
1717 |
|
|
|
1718 |
|
|
#endif // wxUSE_DATETIME |
1719 |
|
|
|
1720 |
|
|
|
1721 |
|
|
// Parses the filterStr, returning the number of filters. |
1722 |
|
|
// Returns 0 if none or if there's a problem. |
1723 |
|
|
// filterStr is in the form: "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpeg" |
1724 |
|
|
|
1725 |
|
|
int WXDLLEXPORT wxParseCommonDialogsFilter(const wxString& filterStr, |
1726 |
|
|
wxArrayString& descriptions, |
1727 |
|
|
wxArrayString& filters) |
1728 |
|
|
{ |
1729 |
|
|
descriptions.Clear(); |
1730 |
|
|
filters.Clear(); |
1731 |
|
|
|
1732 |
|
|
wxString str(filterStr); |
1733 |
|
|
|
1734 |
|
|
wxString description, filter; |
1735 |
|
|
int pos = 0; |
1736 |
|
|
while( pos != wxNOT_FOUND ) |
1737 |
|
|
{ |
1738 |
|
|
pos = str.Find(wxT('|')); |
1739 |
|
|
if ( pos == wxNOT_FOUND ) |
1740 |
|
|
{ |
1741 |
|
|
// if there are no '|'s at all in the string just take the entire |
1742 |
|
|
// string as filter and make description empty for later autocompletion |
1743 |
|
|
if ( filters.IsEmpty() ) |
1744 |
|
|
{ |
1745 |
|
|
descriptions.Add(wxEmptyString); |
1746 |
|
|
filters.Add(filterStr); |
1747 |
|
|
} |
1748 |
|
|
else |
1749 |
|
|
{ |
1750 |
|
|
wxFAIL_MSG( _T("missing '|' in the wildcard string!") ); |
1751 |
|
|
} |
1752 |
|
|
|
1753 |
|
|
break; |
1754 |
|
|
} |
1755 |
|
|
|
1756 |
|
|
description = str.Left(pos); |
1757 |
|
|
str = str.Mid(pos + 1); |
1758 |
|
|
pos = str.Find(wxT('|')); |
1759 |
|
|
if ( pos == wxNOT_FOUND ) |
1760 |
|
|
{ |
1761 |
|
|
filter = str; |
1762 |
|
|
} |
1763 |
|
|
else |
1764 |
|
|
{ |
1765 |
|
|
filter = str.Left(pos); |
1766 |
|
|
str = str.Mid(pos + 1); |
1767 |
|
|
} |
1768 |
|
|
|
1769 |
|
|
descriptions.Add(description); |
1770 |
|
|
filters.Add(filter); |
1771 |
|
|
} |
1772 |
|
|
|
1773 |
|
|
#if defined(__WXMOTIF__) |
1774 |
|
|
// split it so there is one wildcard per entry |
1775 |
|
|
for( size_t i = 0 ; i < descriptions.GetCount() ; i++ ) |
1776 |
|
|
{ |
1777 |
|
|
pos = filters[i].Find(wxT(';')); |
1778 |
|
|
if (pos != wxNOT_FOUND) |
1779 |
|
|
{ |
1780 |
|
|
// first split only filters |
1781 |
|
|
descriptions.Insert(descriptions[i],i+1); |
1782 |
|
|
filters.Insert(filters[i].Mid(pos+1),i+1); |
1783 |
|
|
filters[i]=filters[i].Left(pos); |
1784 |
|
|
|
1785 |
|
|
// autoreplace new filter in description with pattern: |
1786 |
|
|
// C/C++ Files(*.cpp;*.c;*.h)|*.cpp;*.c;*.h |
1787 |
|
|
// cause split into: |
1788 |
|
|
// C/C++ Files(*.cpp)|*.cpp |
1789 |
|
|
// C/C++ Files(*.c;*.h)|*.c;*.h |
1790 |
|
|
// and next iteration cause another split into: |
1791 |
|
|
// C/C++ Files(*.cpp)|*.cpp |
1792 |
|
|
// C/C++ Files(*.c)|*.c |
1793 |
|
|
// C/C++ Files(*.h)|*.h |
1794 |
|
|
for ( size_t k=i;k<i+2;k++ ) |
1795 |
|
|
{ |
1796 |
|
|
pos = descriptions[k].Find(filters[k]); |
1797 |
|
|
if (pos != wxNOT_FOUND) |
1798 |
|
|
{ |
1799 |
|
|
wxString before = descriptions[k].Left(pos); |
1800 |
|
|
wxString after = descriptions[k].Mid(pos+filters[k].Len()); |
1801 |
|
|
pos = before.Find(_T('('),true); |
1802 |
|
|
if (pos>before.Find(_T(')'),true)) |
1803 |
|
|
{ |
1804 |
|
|
before = before.Left(pos+1); |
1805 |
|
|
before << filters[k]; |
1806 |
|
|
pos = after.Find(_T(')')); |
1807 |
|
|
int pos1 = after.Find(_T('(')); |
1808 |
|
|
if (pos != wxNOT_FOUND && (pos<pos1 || pos1==wxNOT_FOUND)) |
1809 |
|
|
{ |
1810 |
|
|
before << after.Mid(pos); |
1811 |
|
|
descriptions[k] = before; |
1812 |
|
|
} |
1813 |
|
|
} |
1814 |
|
|
} |
1815 |
|
|
} |
1816 |
|
|
} |
1817 |
|
|
} |
1818 |
|
|
#endif |
1819 |
|
|
|
1820 |
|
|
// autocompletion |
1821 |
|
|
for( size_t j = 0 ; j < descriptions.GetCount() ; j++ ) |
1822 |
|
|
{ |
1823 |
|
|
if ( descriptions[j].empty() && !filters[j].empty() ) |
1824 |
|
|
{ |
1825 |
|
|
descriptions[j].Printf(_("Files (%s)"), filters[j].c_str()); |
1826 |
|
|
} |
1827 |
|
|
} |
1828 |
|
|
|
1829 |
|
|
return filters.GetCount(); |
1830 |
|
|
} |
1831 |
|
|
|
1832 |
|
|
#if defined(__WINDOWS__) && !(defined(__UNIX__) || defined(__OS2__)) |
1833 |
|
|
static bool wxCheckWin32Permission(const wxString& path, DWORD access) |
1834 |
|
|
{ |
1835 |
|
|
// quoting the MSDN: "To obtain a handle to a directory, call the |
1836 |
|
|
// CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag", but this |
1837 |
|
|
// doesn't work under Win9x/ME but then it's not needed there anyhow |
1838 |
|
|
bool isdir = wxDirExists(path); |
1839 |
|
|
if ( isdir && wxGetOsVersion() == wxOS_WINDOWS_9X ) |
1840 |
|
|
{ |
1841 |
|
|
// FAT directories always allow all access, even if they have the |
1842 |
|
|
// readonly flag set |
1843 |
|
|
return true; |
1844 |
|
|
} |
1845 |
|
|
|
1846 |
|
|
HANDLE h = ::CreateFile |
1847 |
|
|
( |
1848 |
|
|
path.c_str(), |
1849 |
|
|
access, |
1850 |
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
1851 |
|
|
NULL, |
1852 |
|
|
OPEN_EXISTING, |
1853 |
|
|
isdir ? FILE_FLAG_BACKUP_SEMANTICS : 0, |
1854 |
|
|
NULL |
1855 |
|
|
); |
1856 |
|
|
if ( h != INVALID_HANDLE_VALUE ) |
1857 |
|
|
CloseHandle(h); |
1858 |
|
|
|
1859 |
|
|
return h != INVALID_HANDLE_VALUE; |
1860 |
|
|
} |
1861 |
|
|
#endif // __WINDOWS__ |
1862 |
|
|
|
1863 |
|
|
bool wxIsWritable(const wxString &path) |
1864 |
|
|
{ |
1865 |
|
|
#if defined( __UNIX__ ) || defined(__OS2__) |
1866 |
|
|
// access() will take in count also symbolic links |
1867 |
|
|
return wxAccess(path.c_str(), W_OK) == 0; |
1868 |
|
|
#elif defined( __WINDOWS__ ) |
1869 |
|
|
return wxCheckWin32Permission(path, GENERIC_WRITE); |
1870 |
|
|
#else |
1871 |
|
|
wxUnusedVar(path); |
1872 |
|
|
// TODO |
1873 |
|
|
return false; |
1874 |
|
|
#endif |
1875 |
|
|
} |
1876 |
|
|
|
1877 |
|
|
bool wxIsReadable(const wxString &path) |
1878 |
|
|
{ |
1879 |
|
|
#if defined( __UNIX__ ) || defined(__OS2__) |
1880 |
|
|
// access() will take in count also symbolic links |
1881 |
|
|
return wxAccess(path.c_str(), R_OK) == 0; |
1882 |
|
|
#elif defined( __WINDOWS__ ) |
1883 |
|
|
return wxCheckWin32Permission(path, GENERIC_READ); |
1884 |
|
|
#else |
1885 |
|
|
wxUnusedVar(path); |
1886 |
|
|
// TODO |
1887 |
|
|
return false; |
1888 |
|
|
#endif |
1889 |
|
|
} |
1890 |
|
|
|
1891 |
|
|
bool wxIsExecutable(const wxString &path) |
1892 |
|
|
{ |
1893 |
|
|
#if defined( __UNIX__ ) || defined(__OS2__) |
1894 |
|
|
// access() will take in count also symbolic links |
1895 |
|
|
return wxAccess(path.c_str(), X_OK) == 0; |
1896 |
|
|
#elif defined( __WINDOWS__ ) |
1897 |
|
|
return wxCheckWin32Permission(path, GENERIC_EXECUTE); |
1898 |
|
|
#else |
1899 |
|
|
wxUnusedVar(path); |
1900 |
|
|
// TODO |
1901 |
|
|
return false; |
1902 |
|
|
#endif |
1903 |
|
|
} |
1904 |
|
|
|
1905 |
|
|
// Return the type of an open file |
1906 |
|
|
// |
1907 |
|
|
// Some file types on some platforms seem seekable but in fact are not. |
1908 |
|
|
// The main use of this function is to allow such cases to be detected |
1909 |
|
|
// (IsSeekable() is implemented as wxGetFileKind() == wxFILE_KIND_DISK). |
1910 |
|
|
// |
1911 |
|
|
// This is important for the archive streams, which benefit greatly from |
1912 |
|
|
// being able to seek on a stream, but which will produce corrupt archives |
1913 |
|
|
// if they unknowingly seek on a non-seekable stream. |
1914 |
|
|
// |
1915 |
|
|
// wxFILE_KIND_DISK is a good catch all return value, since other values |
1916 |
|
|
// disable features of the archive streams. Some other value must be returned |
1917 |
|
|
// for a file type that appears seekable but isn't. |
1918 |
|
|
// |
1919 |
|
|
// Known examples: |
1920 |
|
|
// * Pipes on Windows |
1921 |
|
|
// * Files on VMS with a record format other than StreamLF |
1922 |
|
|
// |
1923 |
|
|
wxFileKind wxGetFileKind(int fd) |
1924 |
|
|
{ |
1925 |
|
|
#if defined __WXMSW__ && !defined __WXWINCE__ && defined wxGetOSFHandle |
1926 |
|
|
switch (::GetFileType(wxGetOSFHandle(fd)) & ~FILE_TYPE_REMOTE) |
1927 |
|
|
{ |
1928 |
|
|
case FILE_TYPE_CHAR: |
1929 |
|
|
return wxFILE_KIND_TERMINAL; |
1930 |
|
|
case FILE_TYPE_DISK: |
1931 |
|
|
return wxFILE_KIND_DISK; |
1932 |
|
|
case FILE_TYPE_PIPE: |
1933 |
|
|
return wxFILE_KIND_PIPE; |
1934 |
|
|
} |
1935 |
|
|
|
1936 |
|
|
return wxFILE_KIND_UNKNOWN; |
1937 |
|
|
|
1938 |
|
|
#elif defined(__UNIX__) |
1939 |
|
|
if (isatty(fd)) |
1940 |
|
|
return wxFILE_KIND_TERMINAL; |
1941 |
|
|
|
1942 |
|
|
struct stat st; |
1943 |
|
|
fstat(fd, &st); |
1944 |
|
|
|
1945 |
|
|
if (S_ISFIFO(st.st_mode)) |
1946 |
|
|
return wxFILE_KIND_PIPE; |
1947 |
|
|
if (!S_ISREG(st.st_mode)) |
1948 |
|
|
return wxFILE_KIND_UNKNOWN; |
1949 |
|
|
|
1950 |
|
|
#if defined(__VMS__) |
1951 |
|
|
if (st.st_fab_rfm != FAB$C_STMLF) |
1952 |
|
|
return wxFILE_KIND_UNKNOWN; |
1953 |
|
|
#endif |
1954 |
|
|
|
1955 |
|
|
return wxFILE_KIND_DISK; |
1956 |
|
|
|
1957 |
|
|
#else |
1958 |
|
|
#define wxFILEKIND_STUB |
1959 |
|
|
(void)fd; |
1960 |
|
|
return wxFILE_KIND_DISK; |
1961 |
|
|
#endif |
1962 |
|
|
} |
1963 |
|
|
|
1964 |
|
|
wxFileKind wxGetFileKind(FILE *fp) |
1965 |
|
|
{ |
1966 |
|
|
// Note: The watcom rtl dll doesn't have fileno (the static lib does). |
1967 |
|
|
// Should be fixed in version 1.4. |
1968 |
|
|
#if defined(wxFILEKIND_STUB) || wxONLY_WATCOM_EARLIER_THAN(1,4) |
1969 |
|
|
(void)fp; |
1970 |
|
|
return wxFILE_KIND_DISK; |
1971 |
|
|
#elif defined(__WINDOWS__) && !defined(__CYGWIN__) && !defined(__WATCOMC__) && !defined(__WINE__) |
1972 |
|
|
return fp ? wxGetFileKind(_fileno(fp)) : wxFILE_KIND_UNKNOWN; |
1973 |
|
|
#else |
1974 |
|
|
return fp ? wxGetFileKind(fileno(fp)) : wxFILE_KIND_UNKNOWN; |
1975 |
|
|
#endif |
1976 |
|
|
} |
1977 |
|
|
|
1978 |
|
|
|
1979 |
|
|
//------------------------------------------------------------------------ |
1980 |
|
|
// wild character routines |
1981 |
|
|
//------------------------------------------------------------------------ |
1982 |
|
|
|
1983 |
|
|
bool wxIsWild( const wxString& pattern ) |
1984 |
|
|
{ |
1985 |
|
|
wxString tmp = pattern; |
1986 |
|
|
wxChar *pat = WXSTRINGCAST(tmp); |
1987 |
|
|
while (*pat) |
1988 |
|
|
{ |
1989 |
|
|
switch (*pat++) |
1990 |
|
|
{ |
1991 |
|
|
case wxT('?'): case wxT('*'): case wxT('['): case wxT('{'): |
1992 |
|
|
return true; |
1993 |
|
|
case wxT('\\'): |
1994 |
|
|
if (!*pat++) |
1995 |
|
|
return false; |
1996 |
|
|
} |
1997 |
|
|
} |
1998 |
|
|
return false; |
1999 |
|
|
} |
2000 |
|
|
|
2001 |
|
|
/* |
2002 |
|
|
* Written By Douglas A. Lewis <dalewis@cs.Buffalo.EDU> |
2003 |
|
|
* |
2004 |
|
|
* The match procedure is public domain code (from ircII's reg.c) |
2005 |
|
|
* but modified to suit our tastes (RN: No "%" syntax I guess) |
2006 |
|
|
*/ |
2007 |
|
|
|
2008 |
|
|
bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special ) |
2009 |
|
|
{ |
2010 |
|
|
if (text.empty()) |
2011 |
|
|
{ |
2012 |
|
|
/* Match if both are empty. */ |
2013 |
|
|
return pat.empty(); |
2014 |
|
|
} |
2015 |
|
|
|
2016 |
|
|
const wxChar *m = pat.c_str(), |
2017 |
|
|
*n = text.c_str(), |
2018 |
|
|
*ma = NULL, |
2019 |
|
|
*na = NULL; |
2020 |
|
|
int just = 0, |
2021 |
|
|
acount = 0, |
2022 |
|
|
count = 0; |
2023 |
|
|
|
2024 |
|
|
if (dot_special && (*n == wxT('.'))) |
2025 |
|
|
{ |
2026 |
|
|
/* Never match so that hidden Unix files |
2027 |
|
|
* are never found. */ |
2028 |
|
|
return false; |
2029 |
|
|
} |
2030 |
|
|
|
2031 |
|
|
for (;;) |
2032 |
|
|
{ |
2033 |
|
|
if (*m == wxT('*')) |
2034 |
|
|
{ |
2035 |
|
|
ma = ++m; |
2036 |
|
|
na = n; |
2037 |
|
|
just = 1; |
2038 |
|
|
acount = count; |
2039 |
|
|
} |
2040 |
|
|
else if (*m == wxT('?')) |
2041 |
|
|
{ |
2042 |
|
|
m++; |
2043 |
|
|
if (!*n++) |
2044 |
|
|
return false; |
2045 |
|
|
} |
2046 |
|
|
else |
2047 |
|
|
{ |
2048 |
|
|
if (*m == wxT('\\')) |
2049 |
|
|
{ |
2050 |
|
|
m++; |
2051 |
|
|
/* Quoting "nothing" is a bad thing */ |
2052 |
|
|
if (!*m) |
2053 |
|
|
return false; |
2054 |
|
|
} |
2055 |
|
|
if (!*m) |
2056 |
|
|
{ |
2057 |
|
|
/* |
2058 |
|
|
* If we are out of both strings or we just |
2059 |
|
|
* saw a wildcard, then we can say we have a |
2060 |
|
|
* match |
2061 |
|
|
*/ |
2062 |
|
|
if (!*n) |
2063 |
|
|
return true; |
2064 |
|
|
if (just) |
2065 |
|
|
return true; |
2066 |
|
|
just = 0; |
2067 |
|
|
goto not_matched; |
2068 |
|
|
} |
2069 |
|
|
/* |
2070 |
|
|
* We could check for *n == NULL at this point, but |
2071 |
|
|
* since it's more common to have a character there, |
2072 |
|
|
* check to see if they match first (m and n) and |
2073 |
|
|
* then if they don't match, THEN we can check for |
2074 |
|
|
* the NULL of n |
2075 |
|
|
*/ |
2076 |
|
|
just = 0; |
2077 |
|
|
if (*m == *n) |
2078 |
|
|
{ |
2079 |
|
|
m++; |
2080 |
|
|
count++; |
2081 |
|
|
n++; |
2082 |
|
|
} |
2083 |
|
|
else |
2084 |
|
|
{ |
2085 |
|
|
|
2086 |
|
|
not_matched: |
2087 |
|
|
|
2088 |
|
|
/* |
2089 |
|
|
* If there are no more characters in the |
2090 |
|
|
* string, but we still need to find another |
2091 |
|
|
* character (*m != NULL), then it will be |
2092 |
|
|
* impossible to match it |
2093 |
|
|
*/ |
2094 |
|
|
if (!*n) |
2095 |
|
|
return false; |
2096 |
|
|
|
2097 |
|
|
if (ma) |
2098 |
|
|
{ |
2099 |
|
|
m = ma; |
2100 |
|
|
n = ++na; |
2101 |
|
|
count = acount; |
2102 |
|
|
} |
2103 |
|
|
else |
2104 |
|
|
return false; |
2105 |
|
|
} |
2106 |
|
|
} |
2107 |
|
|
} |
2108 |
|
|
} |
2109 |
|
|
|
2110 |
|
|
#ifdef __VISUALC__ |
2111 |
|
|
#pragma warning(default:4706) // assignment within conditional expression |
2112 |
|
|
#endif // VC++ |