PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/wxWidgets/src/common/filefn.cpp

https://bitbucket.org/okuoku/nmosh-dist
C++ | 2052 lines | 1800 code | 98 blank | 154 comment | 158 complexity | fe012f2670053e5246cf3241ddf2a8bf MD5 | raw file
Possible License(s): BSD-2-Clause, GPL-2.0, LGPL-3.0, AGPL-3.0, BSD-3-Clause, GPL-3.0, CPL-1.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /////////////////////////////////////////////////////////////////////////////
  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$
  8. // Copyright: (c) 1998 Julian Smart
  9. // Licence: wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11. // ============================================================================
  12. // declarations
  13. // ============================================================================
  14. // ----------------------------------------------------------------------------
  15. // headers
  16. // ----------------------------------------------------------------------------
  17. // For compilers that support precompilation, includes "wx.h".
  18. #include "wx/wxprec.h"
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22. #include "wx/filefn.h"
  23. #ifndef WX_PRECOMP
  24. #include "wx/intl.h"
  25. #include "wx/log.h"
  26. #include "wx/utils.h"
  27. #include "wx/crt.h"
  28. #endif
  29. #include "wx/dynarray.h"
  30. #include "wx/file.h"
  31. #include "wx/filename.h"
  32. #include "wx/dir.h"
  33. #include "wx/tokenzr.h"
  34. // there are just too many of those...
  35. #ifdef __VISUALC__
  36. #pragma warning(disable:4706) // assignment within conditional expression
  37. #endif // VC++
  38. #include <ctype.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #if !wxONLY_WATCOM_EARLIER_THAN(1,4)
  43. #if !(defined(_MSC_VER) && (_MSC_VER > 800))
  44. #include <errno.h>
  45. #endif
  46. #endif
  47. #if defined(__WXMAC__)
  48. #include "wx/osx/private.h" // includes mac headers
  49. #endif
  50. #ifdef __WINDOWS__
  51. #include "wx/msw/private.h"
  52. #include "wx/msw/mslu.h"
  53. // sys/cygwin.h is needed for cygwin_conv_to_full_win32_path()
  54. // and for cygwin_conv_path()
  55. //
  56. // note that it must be included after <windows.h>
  57. #ifdef __GNUWIN32__
  58. #ifdef __CYGWIN__
  59. #include <sys/cygwin.h>
  60. #include <cygwin/version.h>
  61. #endif
  62. #endif // __GNUWIN32__
  63. // io.h is needed for _get_osfhandle()
  64. // Already included by filefn.h for many Windows compilers
  65. #if defined __CYGWIN__
  66. #include <io.h>
  67. #endif
  68. #endif // __WINDOWS__
  69. #if defined(__VMS__)
  70. #include <fab.h>
  71. #endif
  72. // TODO: Borland probably has _wgetcwd as well?
  73. #ifdef _MSC_VER
  74. #define HAVE_WGETCWD
  75. #endif
  76. // ----------------------------------------------------------------------------
  77. // constants
  78. // ----------------------------------------------------------------------------
  79. #ifndef _MAXPATHLEN
  80. #define _MAXPATHLEN 1024
  81. #endif
  82. // ----------------------------------------------------------------------------
  83. // private globals
  84. // ----------------------------------------------------------------------------
  85. #if WXWIN_COMPATIBILITY_2_8
  86. static wxChar wxFileFunctionsBuffer[4*_MAXPATHLEN];
  87. #endif
  88. #if defined(__VISAGECPP__) && __IBMCPP__ >= 400
  89. //
  90. // VisualAge C++ V4.0 cannot have any external linkage const decs
  91. // in headers included by more than one primary source
  92. //
  93. const int wxInvalidOffset = -1;
  94. #endif
  95. // ============================================================================
  96. // implementation
  97. // ============================================================================
  98. // ----------------------------------------------------------------------------
  99. // wrappers around standard POSIX functions
  100. // ----------------------------------------------------------------------------
  101. #if wxUSE_UNICODE && defined __BORLANDC__ \
  102. && __BORLANDC__ >= 0x550 && __BORLANDC__ <= 0x551
  103. // BCC 5.5 and 5.5.1 have a bug in _wopen where files are created read only
  104. // regardless of the mode parameter. This hack works around the problem by
  105. // setting the mode with _wchmod.
  106. //
  107. int wxCRT_OpenW(const wchar_t *pathname, int flags, mode_t mode)
  108. {
  109. int moreflags = 0;
  110. // we only want to fix the mode when the file is actually created, so
  111. // when creating first try doing it O_EXCL so we can tell if the file
  112. // was already there.
  113. if ((flags & O_CREAT) && !(flags & O_EXCL) && (mode & wxS_IWUSR) != 0)
  114. moreflags = O_EXCL;
  115. int fd = _wopen(pathname, flags | moreflags, mode);
  116. // the file was actually created and needs fixing
  117. if (fd != -1 && (flags & O_CREAT) != 0 && (mode & wxS_IWUSR) != 0)
  118. {
  119. close(fd);
  120. _wchmod(pathname, mode);
  121. fd = _wopen(pathname, flags & ~(O_EXCL | O_CREAT));
  122. }
  123. // the open failed, but it may have been because the added O_EXCL stopped
  124. // the opening of an existing file, so try again without.
  125. else if (fd == -1 && moreflags != 0)
  126. {
  127. fd = _wopen(pathname, flags & ~O_CREAT);
  128. }
  129. return fd;
  130. }
  131. #endif
  132. // ----------------------------------------------------------------------------
  133. // wxPathList
  134. // ----------------------------------------------------------------------------
  135. bool wxPathList::Add(const wxString& path)
  136. {
  137. // add a path separator to force wxFileName to interpret it always as a directory
  138. // (i.e. if we are called with '/home/user' we want to consider it a folder and
  139. // not, as wxFileName would consider, a filename).
  140. wxFileName fn(path + wxFileName::GetPathSeparator());
  141. // add only normalized relative/absolute paths
  142. // NB: we won't do wxPATH_NORM_DOTS in order to avoid problems when trying to
  143. // normalize paths which starts with ".." (which can be normalized only if
  144. // we use also wxPATH_NORM_ABSOLUTE - which we don't want to use).
  145. if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS))
  146. return false;
  147. wxString toadd = fn.GetPath();
  148. if (Index(toadd) == wxNOT_FOUND)
  149. wxArrayString::Add(toadd); // do not add duplicates
  150. return true;
  151. }
  152. void wxPathList::Add(const wxArrayString &arr)
  153. {
  154. for (size_t j=0; j < arr.GetCount(); j++)
  155. Add(arr[j]);
  156. }
  157. // Add paths e.g. from the PATH environment variable
  158. void wxPathList::AddEnvList (const wxString& WXUNUSED_IN_WINCE(envVariable))
  159. {
  160. // No environment variables on WinCE
  161. #ifndef __WXWINCE__
  162. // The space has been removed from the tokenizers, otherwise a
  163. // path such as "C:\Program Files" would be split into 2 paths:
  164. // "C:\Program" and "Files"; this is true for both Windows and Unix.
  165. static const wxChar PATH_TOKS[] =
  166. #if defined(__WINDOWS__) || defined(__OS2__)
  167. wxT(";"); // Don't separate with colon in DOS (used for drive)
  168. #else
  169. wxT(":;");
  170. #endif
  171. wxString val;
  172. if ( wxGetEnv(envVariable, &val) )
  173. {
  174. // split into an array of string the value of the env var
  175. wxArrayString arr = wxStringTokenize(val, PATH_TOKS);
  176. WX_APPEND_ARRAY(*this, arr);
  177. }
  178. #endif // !__WXWINCE__
  179. }
  180. // Given a full filename (with path), ensure that that file can
  181. // be accessed again USING FILENAME ONLY by adding the path
  182. // to the list if not already there.
  183. bool wxPathList::EnsureFileAccessible (const wxString& path)
  184. {
  185. return Add(wxPathOnly(path));
  186. }
  187. #if WXWIN_COMPATIBILITY_2_6
  188. bool wxPathList::Member (const wxString& path) const
  189. {
  190. return Index(path) != wxNOT_FOUND;
  191. }
  192. #endif
  193. wxString wxPathList::FindValidPath (const wxString& file) const
  194. {
  195. // normalize the given string as it could be a path + a filename
  196. // and not only a filename
  197. wxFileName fn(file);
  198. wxString strend;
  199. // NB: normalize without making absolute otherwise calling this function with
  200. // e.g. "b/c.txt" would result in removing the directory 'b' and the for loop
  201. // below would only add to the paths of this list the 'c.txt' part when doing
  202. // the existence checks...
  203. // NB: we don't use wxPATH_NORM_DOTS here, too (see wxPathList::Add for more info)
  204. if (!fn.Normalize(wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS))
  205. return wxEmptyString;
  206. wxASSERT_MSG(!fn.IsDir(), wxT("Cannot search for directories; only for files"));
  207. if (fn.IsAbsolute())
  208. strend = fn.GetFullName(); // search for the file name and ignore the path part
  209. else
  210. strend = fn.GetFullPath();
  211. for (size_t i=0; i<GetCount(); i++)
  212. {
  213. wxString strstart = Item(i);
  214. if (!strstart.IsEmpty() && strstart.Last() != wxFileName::GetPathSeparator())
  215. strstart += wxFileName::GetPathSeparator();
  216. if (wxFileExists(strstart + strend))
  217. return strstart + strend; // Found!
  218. }
  219. return wxEmptyString; // Not found
  220. }
  221. wxString wxPathList::FindAbsoluteValidPath (const wxString& file) const
  222. {
  223. wxString f = FindValidPath(file);
  224. if ( f.empty() || wxIsAbsolutePath(f) )
  225. return f;
  226. wxString buf = ::wxGetCwd();
  227. if ( !wxEndsWithPathSeparator(buf) )
  228. {
  229. buf += wxFILE_SEP_PATH;
  230. }
  231. buf += f;
  232. return buf;
  233. }
  234. // ----------------------------------------------------------------------------
  235. // miscellaneous global functions
  236. // ----------------------------------------------------------------------------
  237. #if WXWIN_COMPATIBILITY_2_8
  238. static inline wxChar* MYcopystring(const wxString& s)
  239. {
  240. wxChar* copy = new wxChar[s.length() + 1];
  241. return wxStrcpy(copy, s.c_str());
  242. }
  243. template<typename CharType>
  244. static inline CharType* MYcopystring(const CharType* s)
  245. {
  246. CharType* copy = new CharType[wxStrlen(s) + 1];
  247. return wxStrcpy(copy, s);
  248. }
  249. #endif
  250. bool
  251. wxFileExists (const wxString& filename)
  252. {
  253. return wxFileName::FileExists(filename);
  254. }
  255. bool
  256. wxIsAbsolutePath (const wxString& filename)
  257. {
  258. if (!filename.empty())
  259. {
  260. // Unix like or Windows
  261. if (filename[0] == wxT('/'))
  262. return true;
  263. #ifdef __VMS__
  264. if ((filename[0] == wxT('[') && filename[1] != wxT('.')))
  265. return true;
  266. #endif
  267. #if defined(__WINDOWS__) || defined(__OS2__)
  268. // MSDOS like
  269. if (filename[0] == wxT('\\') || (wxIsalpha (filename[0]) && filename[1] == wxT(':')))
  270. return true;
  271. #endif
  272. }
  273. return false ;
  274. }
  275. #if WXWIN_COMPATIBILITY_2_8
  276. /*
  277. * Strip off any extension (dot something) from end of file,
  278. * IF one exists. Inserts zero into buffer.
  279. *
  280. */
  281. template<typename T>
  282. static void wxDoStripExtension(T *buffer)
  283. {
  284. int len = wxStrlen(buffer);
  285. int i = len-1;
  286. while (i > 0)
  287. {
  288. if (buffer[i] == wxT('.'))
  289. {
  290. buffer[i] = 0;
  291. break;
  292. }
  293. i --;
  294. }
  295. }
  296. void wxStripExtension(char *buffer) { wxDoStripExtension(buffer); }
  297. void wxStripExtension(wchar_t *buffer) { wxDoStripExtension(buffer); }
  298. void wxStripExtension(wxString& buffer)
  299. {
  300. buffer = wxFileName::StripExtension(buffer);
  301. }
  302. // Destructive removal of /./ and /../ stuff
  303. template<typename CharType>
  304. static CharType *wxDoRealPath (CharType *path)
  305. {
  306. static const CharType SEP = wxFILE_SEP_PATH;
  307. #ifdef __WINDOWS__
  308. wxUnix2DosFilename(path);
  309. #endif
  310. if (path[0] && path[1]) {
  311. /* MATTHEW: special case "/./x" */
  312. CharType *p;
  313. if (path[2] == SEP && path[1] == wxT('.'))
  314. p = &path[0];
  315. else
  316. p = &path[2];
  317. for (; *p; p++)
  318. {
  319. if (*p == SEP)
  320. {
  321. if (p[1] == wxT('.') && p[2] == wxT('.') && (p[3] == SEP || p[3] == wxT('\0')))
  322. {
  323. CharType *q;
  324. for (q = p - 1; q >= path && *q != SEP; q--)
  325. {
  326. // Empty
  327. }
  328. if (q[0] == SEP && (q[1] != wxT('.') || q[2] != wxT('.') || q[3] != SEP)
  329. && (q - 1 <= path || q[-1] != SEP))
  330. {
  331. wxStrcpy (q, p + 3);
  332. if (path[0] == wxT('\0'))
  333. {
  334. path[0] = SEP;
  335. path[1] = wxT('\0');
  336. }
  337. #if defined(__WINDOWS__) || defined(__OS2__)
  338. /* Check that path[2] is NULL! */
  339. else if (path[1] == wxT(':') && !path[2])
  340. {
  341. path[2] = SEP;
  342. path[3] = wxT('\0');
  343. }
  344. #endif
  345. p = q - 1;
  346. }
  347. }
  348. else if (p[1] == wxT('.') && (p[2] == SEP || p[2] == wxT('\0')))
  349. wxStrcpy (p, p + 2);
  350. }
  351. }
  352. }
  353. return path;
  354. }
  355. char *wxRealPath(char *path)
  356. {
  357. return wxDoRealPath(path);
  358. }
  359. wchar_t *wxRealPath(wchar_t *path)
  360. {
  361. return wxDoRealPath(path);
  362. }
  363. wxString wxRealPath(const wxString& path)
  364. {
  365. wxChar *buf1=MYcopystring(path);
  366. wxChar *buf2=wxRealPath(buf1);
  367. wxString buf(buf2);
  368. delete [] buf1;
  369. return buf;
  370. }
  371. // Must be destroyed
  372. wxChar *wxCopyAbsolutePath(const wxString& filename)
  373. {
  374. if (filename.empty())
  375. return NULL;
  376. if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename)))
  377. {
  378. wxString buf = ::wxGetCwd();
  379. wxChar ch = buf.Last();
  380. #ifdef __WINDOWS__
  381. if (ch != wxT('\\') && ch != wxT('/'))
  382. buf << wxT("\\");
  383. #else
  384. if (ch != wxT('/'))
  385. buf << wxT("/");
  386. #endif
  387. buf << wxFileFunctionsBuffer;
  388. buf = wxRealPath( buf );
  389. return MYcopystring( buf );
  390. }
  391. return MYcopystring( wxFileFunctionsBuffer );
  392. }
  393. /*-
  394. Handles:
  395. ~/ => home dir
  396. ~user/ => user's home dir
  397. If the environment variable a = "foo" and b = "bar" then:
  398. Unix:
  399. $a => foo
  400. $a$b => foobar
  401. $a.c => foo.c
  402. xxx$a => xxxfoo
  403. ${a}! => foo!
  404. $(b)! => bar!
  405. \$a => \$a
  406. MSDOS:
  407. $a ==> $a
  408. $(a) ==> foo
  409. $(a)$b ==> foo$b
  410. $(a)$(b)==> foobar
  411. test.$$ ==> test.$$
  412. */
  413. /* input name in name, pathname output to buf. */
  414. template<typename CharType>
  415. static CharType *wxDoExpandPath(CharType *buf, const wxString& name)
  416. {
  417. register CharType *d, *s, *nm;
  418. CharType lnm[_MAXPATHLEN];
  419. int q;
  420. // Some compilers don't like this line.
  421. // const CharType trimchars[] = wxT("\n \t");
  422. CharType trimchars[4];
  423. trimchars[0] = wxT('\n');
  424. trimchars[1] = wxT(' ');
  425. trimchars[2] = wxT('\t');
  426. trimchars[3] = 0;
  427. static const CharType SEP = wxFILE_SEP_PATH;
  428. #ifdef __WINDOWS__
  429. //wxUnix2DosFilename(path);
  430. #endif
  431. buf[0] = wxT('\0');
  432. if (name.empty())
  433. return buf;
  434. nm = ::MYcopystring(static_cast<const CharType*>(name.c_str())); // Make a scratch copy
  435. CharType *nm_tmp = nm;
  436. /* Skip leading whitespace and cr */
  437. while (wxStrchr(trimchars, *nm) != NULL)
  438. nm++;
  439. /* And strip off trailing whitespace and cr */
  440. s = nm + (q = wxStrlen(nm)) - 1;
  441. while (q-- && wxStrchr(trimchars, *s) != NULL)
  442. *s = wxT('\0');
  443. s = nm;
  444. d = lnm;
  445. #ifdef __WINDOWS__
  446. q = FALSE;
  447. #else
  448. q = nm[0] == wxT('\\') && nm[1] == wxT('~');
  449. #endif
  450. /* Expand inline environment variables */
  451. #ifdef __VISAGECPP__
  452. while (*d)
  453. {
  454. *d++ = *s;
  455. if(*s == wxT('\\'))
  456. {
  457. *(d - 1) = *++s;
  458. if (*d)
  459. {
  460. s++;
  461. continue;
  462. }
  463. else
  464. break;
  465. }
  466. else
  467. #else
  468. while ((*d++ = *s) != 0) {
  469. # ifndef __WINDOWS__
  470. if (*s == wxT('\\')) {
  471. if ((*(d - 1) = *++s)!=0) {
  472. s++;
  473. continue;
  474. } else
  475. break;
  476. } else
  477. # endif
  478. #endif
  479. // No env variables on WinCE
  480. #ifndef __WXWINCE__
  481. #ifdef __WINDOWS__
  482. if (*s++ == wxT('$') && (*s == wxT('{') || *s == wxT(')')))
  483. #else
  484. if (*s++ == wxT('$'))
  485. #endif
  486. {
  487. register CharType *start = d;
  488. register int braces = (*s == wxT('{') || *s == wxT('('));
  489. register CharType *value;
  490. while ((*d++ = *s) != 0)
  491. if (braces ? (*s == wxT('}') || *s == wxT(')')) : !(wxIsalnum(*s) || *s == wxT('_')) )
  492. break;
  493. else
  494. s++;
  495. *--d = 0;
  496. value = wxGetenv(braces ? start + 1 : start);
  497. if (value) {
  498. for ((d = start - 1); (*d++ = *value++) != 0;)
  499. {
  500. // Empty
  501. }
  502. d--;
  503. if (braces && *s)
  504. s++;
  505. }
  506. }
  507. #endif
  508. // __WXWINCE__
  509. }
  510. /* Expand ~ and ~user */
  511. wxString homepath;
  512. nm = lnm;
  513. if (nm[0] == wxT('~') && !q)
  514. {
  515. /* prefix ~ */
  516. if (nm[1] == SEP || nm[1] == 0)
  517. { /* ~/filename */
  518. homepath = wxGetUserHome(wxEmptyString);
  519. if (!homepath.empty()) {
  520. s = (CharType*)(const CharType*)homepath.c_str();
  521. if (*++nm)
  522. nm++;
  523. }
  524. } else
  525. { /* ~user/filename */
  526. register CharType *nnm;
  527. for (s = nm; *s && *s != SEP; s++)
  528. {
  529. // Empty
  530. }
  531. int was_sep; /* MATTHEW: Was there a separator, or NULL? */
  532. was_sep = (*s == SEP);
  533. nnm = *s ? s + 1 : s;
  534. *s = 0;
  535. homepath = wxGetUserHome(wxString(nm + 1));
  536. if (homepath.empty())
  537. {
  538. if (was_sep) /* replace only if it was there: */
  539. *s = SEP;
  540. s = NULL;
  541. }
  542. else
  543. {
  544. nm = nnm;
  545. s = (CharType*)(const CharType*)homepath.c_str();
  546. }
  547. }
  548. }
  549. d = buf;
  550. if (s && *s) { /* MATTHEW: s could be NULL if user '~' didn't exist */
  551. /* Copy home dir */
  552. while (wxT('\0') != (*d++ = *s++))
  553. /* loop */;
  554. // Handle root home
  555. if (d - 1 > buf && *(d - 2) != SEP)
  556. *(d - 1) = SEP;
  557. }
  558. s = nm;
  559. while ((*d++ = *s++) != 0)
  560. {
  561. // Empty
  562. }
  563. delete[] nm_tmp; // clean up alloc
  564. /* Now clean up the buffer */
  565. return wxRealPath(buf);
  566. }
  567. char *wxExpandPath(char *buf, const wxString& name)
  568. {
  569. return wxDoExpandPath(buf, name);
  570. }
  571. wchar_t *wxExpandPath(wchar_t *buf, const wxString& name)
  572. {
  573. return wxDoExpandPath(buf, name);
  574. }
  575. /* Contract Paths to be build upon an environment variable
  576. component:
  577. example: "/usr/openwin/lib", OPENWINHOME --> ${OPENWINHOME}/lib
  578. The call wxExpandPath can convert these back!
  579. */
  580. wxChar *
  581. wxContractPath (const wxString& filename,
  582. const wxString& WXUNUSED_IN_WINCE(envname),
  583. const wxString& user)
  584. {
  585. static wxChar dest[_MAXPATHLEN];
  586. if (filename.empty())
  587. return NULL;
  588. wxStrcpy (dest, filename);
  589. #ifdef __WINDOWS__
  590. wxUnix2DosFilename(dest);
  591. #endif
  592. // Handle environment
  593. wxString val;
  594. #ifndef __WXWINCE__
  595. wxChar *tcp;
  596. if (!envname.empty() && !(val = wxGetenv (envname)).empty() &&
  597. (tcp = wxStrstr (dest, val)) != NULL)
  598. {
  599. wxStrcpy (wxFileFunctionsBuffer, tcp + val.length());
  600. *tcp++ = wxT('$');
  601. *tcp++ = wxT('{');
  602. wxStrcpy (tcp, envname);
  603. wxStrcat (tcp, wxT("}"));
  604. wxStrcat (tcp, wxFileFunctionsBuffer);
  605. }
  606. #endif
  607. // Handle User's home (ignore root homes!)
  608. val = wxGetUserHome (user);
  609. if (val.empty())
  610. return dest;
  611. const size_t len = val.length();
  612. if (len <= 2)
  613. return dest;
  614. if (wxStrncmp(dest, val, len) == 0)
  615. {
  616. wxStrcpy(wxFileFunctionsBuffer, wxT("~"));
  617. if (!user.empty())
  618. wxStrcat(wxFileFunctionsBuffer, user);
  619. wxStrcat(wxFileFunctionsBuffer, dest + len);
  620. wxStrcpy (dest, wxFileFunctionsBuffer);
  621. }
  622. return dest;
  623. }
  624. #endif // #if WXWIN_COMPATIBILITY_2_8
  625. // Return just the filename, not the path (basename)
  626. wxChar *wxFileNameFromPath (wxChar *path)
  627. {
  628. wxString p = path;
  629. wxString n = wxFileNameFromPath(p);
  630. return path + p.length() - n.length();
  631. }
  632. wxString wxFileNameFromPath (const wxString& path)
  633. {
  634. return wxFileName(path).GetFullName();
  635. }
  636. // Return just the directory, or NULL if no directory
  637. wxChar *
  638. wxPathOnly (wxChar *path)
  639. {
  640. if (path && *path)
  641. {
  642. static wxChar buf[_MAXPATHLEN];
  643. // Local copy
  644. wxStrcpy (buf, path);
  645. int l = wxStrlen(path);
  646. int i = l - 1;
  647. // Search backward for a backward or forward slash
  648. while (i > -1)
  649. {
  650. // Unix like or Windows
  651. if (path[i] == wxT('/') || path[i] == wxT('\\'))
  652. {
  653. buf[i] = 0;
  654. return buf;
  655. }
  656. #ifdef __VMS__
  657. if (path[i] == wxT(']'))
  658. {
  659. buf[i+1] = 0;
  660. return buf;
  661. }
  662. #endif
  663. i --;
  664. }
  665. #if defined(__WINDOWS__) || defined(__OS2__)
  666. // Try Drive specifier
  667. if (wxIsalpha (buf[0]) && buf[1] == wxT(':'))
  668. {
  669. // A:junk --> A:. (since A:.\junk Not A:\junk)
  670. buf[2] = wxT('.');
  671. buf[3] = wxT('\0');
  672. return buf;
  673. }
  674. #endif
  675. }
  676. return NULL;
  677. }
  678. // Return just the directory, or NULL if no directory
  679. wxString wxPathOnly (const wxString& path)
  680. {
  681. if (!path.empty())
  682. {
  683. wxChar buf[_MAXPATHLEN];
  684. // Local copy
  685. wxStrcpy(buf, path);
  686. int l = path.length();
  687. int i = l - 1;
  688. // Search backward for a backward or forward slash
  689. while (i > -1)
  690. {
  691. // Unix like or Windows
  692. if (path[i] == wxT('/') || path[i] == wxT('\\'))
  693. {
  694. // Don't return an empty string
  695. if (i == 0)
  696. i ++;
  697. buf[i] = 0;
  698. return wxString(buf);
  699. }
  700. #ifdef __VMS__
  701. if (path[i] == wxT(']'))
  702. {
  703. buf[i+1] = 0;
  704. return wxString(buf);
  705. }
  706. #endif
  707. i --;
  708. }
  709. #if defined(__WINDOWS__) || defined(__OS2__)
  710. // Try Drive specifier
  711. if (wxIsalpha (buf[0]) && buf[1] == wxT(':'))
  712. {
  713. // A:junk --> A:. (since A:.\junk Not A:\junk)
  714. buf[2] = wxT('.');
  715. buf[3] = wxT('\0');
  716. return wxString(buf);
  717. }
  718. #endif
  719. }
  720. return wxEmptyString;
  721. }
  722. // Utility for converting delimiters in DOS filenames to UNIX style
  723. // and back again - or we get nasty problems with delimiters.
  724. // Also, convert to lower case, since case is significant in UNIX.
  725. #if defined(__WXMAC__) && !defined(__WXOSX_IPHONE__)
  726. #define kDefaultPathStyle kCFURLPOSIXPathStyle
  727. wxString wxMacFSRefToPath( const FSRef *fsRef , CFStringRef additionalPathComponent )
  728. {
  729. CFURLRef fullURLRef;
  730. fullURLRef = CFURLCreateFromFSRef(NULL, fsRef);
  731. if ( fullURLRef == NULL)
  732. return wxEmptyString;
  733. if ( additionalPathComponent )
  734. {
  735. CFURLRef parentURLRef = fullURLRef ;
  736. fullURLRef = CFURLCreateCopyAppendingPathComponent(NULL, parentURLRef,
  737. additionalPathComponent,false);
  738. CFRelease( parentURLRef ) ;
  739. }
  740. wxCFStringRef cfString( CFURLCopyFileSystemPath(fullURLRef, kDefaultPathStyle ));
  741. CFRelease( fullURLRef ) ;
  742. return wxCFStringRef::AsStringWithNormalizationFormC(cfString);
  743. }
  744. OSStatus wxMacPathToFSRef( const wxString&path , FSRef *fsRef )
  745. {
  746. OSStatus err = noErr ;
  747. CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, wxCFStringRef(path));
  748. CFStringNormalize(cfMutableString,kCFStringNormalizationFormD);
  749. CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kDefaultPathStyle, false);
  750. CFRelease( cfMutableString );
  751. if ( NULL != url )
  752. {
  753. if ( CFURLGetFSRef(url, fsRef) == false )
  754. err = fnfErr ;
  755. CFRelease( url ) ;
  756. }
  757. else
  758. {
  759. err = fnfErr ;
  760. }
  761. return err ;
  762. }
  763. wxString wxMacHFSUniStrToString( ConstHFSUniStr255Param uniname )
  764. {
  765. wxCFStringRef cfname( CFStringCreateWithCharacters( kCFAllocatorDefault,
  766. uniname->unicode,
  767. uniname->length ) );
  768. return wxCFStringRef::AsStringWithNormalizationFormC(cfname);
  769. }
  770. #ifndef __LP64__
  771. wxString wxMacFSSpec2MacFilename( const FSSpec *spec )
  772. {
  773. FSRef fsRef ;
  774. if ( FSpMakeFSRef( spec , &fsRef) == noErr )
  775. {
  776. return wxMacFSRefToPath( &fsRef ) ;
  777. }
  778. return wxEmptyString ;
  779. }
  780. void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec )
  781. {
  782. OSStatus err = noErr;
  783. FSRef fsRef;
  784. wxMacPathToFSRef( path , &fsRef );
  785. err = FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, spec, NULL);
  786. verify_noerr( err );
  787. }
  788. #endif
  789. #endif // __WXMAC__
  790. #if WXWIN_COMPATIBILITY_2_8
  791. template<typename T>
  792. static void wxDoDos2UnixFilename(T *s)
  793. {
  794. if (s)
  795. while (*s)
  796. {
  797. if (*s == wxT('\\'))
  798. *s = wxT('/');
  799. #ifdef __WINDOWS__
  800. else
  801. *s = wxTolower(*s); // Case INDEPENDENT
  802. #endif
  803. s++;
  804. }
  805. }
  806. void wxDos2UnixFilename(char *s) { wxDoDos2UnixFilename(s); }
  807. void wxDos2UnixFilename(wchar_t *s) { wxDoDos2UnixFilename(s); }
  808. template<typename T>
  809. static void
  810. #if defined(__WINDOWS__) || defined(__OS2__)
  811. wxDoUnix2DosFilename(T *s)
  812. #else
  813. wxDoUnix2DosFilename(T *WXUNUSED(s) )
  814. #endif
  815. {
  816. // Yes, I really mean this to happen under DOS only! JACS
  817. #if defined(__WINDOWS__) || defined(__OS2__)
  818. if (s)
  819. while (*s)
  820. {
  821. if (*s == wxT('/'))
  822. *s = wxT('\\');
  823. s++;
  824. }
  825. #endif
  826. }
  827. void wxUnix2DosFilename(char *s) { wxDoUnix2DosFilename(s); }
  828. void wxUnix2DosFilename(wchar_t *s) { wxDoUnix2DosFilename(s); }
  829. #endif // #if WXWIN_COMPATIBILITY_2_8
  830. // Concatenate two files to form third
  831. bool
  832. wxConcatFiles (const wxString& file1, const wxString& file2, const wxString& file3)
  833. {
  834. #if wxUSE_FILE
  835. wxFile in1(file1), in2(file2);
  836. wxTempFile out(file3);
  837. if ( !in1.IsOpened() || !in2.IsOpened() || !out.IsOpened() )
  838. return false;
  839. ssize_t ofs;
  840. unsigned char buf[1024];
  841. for( int i=0; i<2; i++)
  842. {
  843. wxFile *in = i==0 ? &in1 : &in2;
  844. do{
  845. if ( (ofs = in->Read(buf,WXSIZEOF(buf))) == wxInvalidOffset ) return false;
  846. if ( ofs > 0 )
  847. if ( !out.Write(buf,ofs) )
  848. return false;
  849. } while ( ofs == (ssize_t)WXSIZEOF(buf) );
  850. }
  851. return out.Commit();
  852. #else
  853. wxUnusedVar(file1);
  854. wxUnusedVar(file2);
  855. wxUnusedVar(file3);
  856. return false;
  857. #endif
  858. }
  859. // helper of generic implementation of wxCopyFile()
  860. #if !(defined(__WIN32__) || defined(__OS2__)) && wxUSE_FILE
  861. static bool
  862. wxDoCopyFile(wxFile& fileIn,
  863. const wxStructStat& fbuf,
  864. const wxString& filenameDst,
  865. bool overwrite)
  866. {
  867. // reset the umask as we want to create the file with exactly the same
  868. // permissions as the original one
  869. wxCHANGE_UMASK(0);
  870. // create file2 with the same permissions than file1 and open it for
  871. // writing
  872. wxFile fileOut;
  873. if ( !fileOut.Create(filenameDst, overwrite, fbuf.st_mode & 0777) )
  874. return false;
  875. // copy contents of file1 to file2
  876. char buf[4096];
  877. for ( ;; )
  878. {
  879. ssize_t count = fileIn.Read(buf, WXSIZEOF(buf));
  880. if ( count == wxInvalidOffset )
  881. return false;
  882. // end of file?
  883. if ( !count )
  884. break;
  885. if ( fileOut.Write(buf, count) < (size_t)count )
  886. return false;
  887. }
  888. // we can expect fileIn to be closed successfully, but we should ensure
  889. // that fileOut was closed as some write errors (disk full) might not be
  890. // detected before doing this
  891. return fileIn.Close() && fileOut.Close();
  892. }
  893. #endif // generic implementation of wxCopyFile
  894. // Copy files
  895. bool
  896. wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite)
  897. {
  898. #if defined(__WIN32__) && !defined(__WXMICROWIN__)
  899. // CopyFile() copies file attributes and modification time too, so use it
  900. // instead of our code if available
  901. //
  902. // NB: 3rd parameter is bFailIfExists i.e. the inverse of overwrite
  903. if ( !::CopyFile(file1.t_str(), file2.t_str(), !overwrite) )
  904. {
  905. wxLogSysError(_("Failed to copy the file '%s' to '%s'"),
  906. file1.c_str(), file2.c_str());
  907. return false;
  908. }
  909. #elif defined(__OS2__)
  910. if ( ::DosCopy(file1.c_str(), file2.c_str(), overwrite ? DCPY_EXISTING : 0) != 0 )
  911. return false;
  912. #elif wxUSE_FILE // !Win32
  913. wxStructStat fbuf;
  914. // get permissions of file1
  915. if ( wxStat( file1, &fbuf) != 0 )
  916. {
  917. // the file probably doesn't exist or we haven't the rights to read
  918. // from it anyhow
  919. wxLogSysError(_("Impossible to get permissions for file '%s'"),
  920. file1.c_str());
  921. return false;
  922. }
  923. // open file1 for reading
  924. wxFile fileIn(file1, wxFile::read);
  925. if ( !fileIn.IsOpened() )
  926. return false;
  927. // remove file2, if it exists. This is needed for creating
  928. // file2 with the correct permissions in the next step
  929. if ( wxFileExists(file2) && (!overwrite || !wxRemoveFile(file2)))
  930. {
  931. wxLogSysError(_("Impossible to overwrite the file '%s'"),
  932. file2.c_str());
  933. return false;
  934. }
  935. wxDoCopyFile(fileIn, fbuf, file2, overwrite);
  936. #if defined(__WXMAC__) || defined(__WXCOCOA__)
  937. // copy the resource fork of the file too if it's present
  938. wxString pathRsrcOut;
  939. wxFile fileRsrcIn;
  940. {
  941. // suppress error messages from this block as resource forks don't have
  942. // to exist
  943. wxLogNull noLog;
  944. // it's not enough to check for file existence: it always does on HFS
  945. // but is empty for files without resources
  946. if ( fileRsrcIn.Open(file1 + wxT("/..namedfork/rsrc")) &&
  947. fileRsrcIn.Length() > 0 )
  948. {
  949. // we must be using HFS or another filesystem with resource fork
  950. // support, suppose that destination file system also is HFS[-like]
  951. pathRsrcOut = file2 + wxT("/..namedfork/rsrc");
  952. }
  953. else // check if we have resource fork in separate file (non-HFS case)
  954. {
  955. wxFileName fnRsrc(file1);
  956. fnRsrc.SetName(wxT("._") + fnRsrc.GetName());
  957. fileRsrcIn.Close();
  958. if ( fileRsrcIn.Open( fnRsrc.GetFullPath() ) )
  959. {
  960. fnRsrc = file2;
  961. fnRsrc.SetName(wxT("._") + fnRsrc.GetName());
  962. pathRsrcOut = fnRsrc.GetFullPath();
  963. }
  964. }
  965. }
  966. if ( !pathRsrcOut.empty() )
  967. {
  968. if ( !wxDoCopyFile(fileRsrcIn, fbuf, pathRsrcOut, overwrite) )
  969. return false;
  970. }
  971. #endif // wxMac || wxCocoa
  972. #if !defined(__VISAGECPP__) && !defined(__WXMAC__) || defined(__UNIX__)
  973. // no chmod in VA. Should be some permission API for HPFS386 partitions
  974. // however
  975. if ( chmod(file2.fn_str(), fbuf.st_mode) != 0 )
  976. {
  977. wxLogSysError(_("Impossible to set permissions for the file '%s'"),
  978. file2.c_str());
  979. return false;
  980. }
  981. #endif // OS/2 || Mac
  982. #else // !Win32 && ! wxUSE_FILE
  983. // impossible to simulate with wxWidgets API
  984. wxUnusedVar(file1);
  985. wxUnusedVar(file2);
  986. wxUnusedVar(overwrite);
  987. return false;
  988. #endif // __WINDOWS__ && __WIN32__
  989. return true;
  990. }
  991. bool
  992. wxRenameFile(const wxString& file1, const wxString& file2, bool overwrite)
  993. {
  994. if ( !overwrite && wxFileExists(file2) )
  995. {
  996. wxLogSysError
  997. (
  998. _("Failed to rename the file '%s' to '%s' because the destination file already exists."),
  999. file1.c_str(), file2.c_str()
  1000. );
  1001. return false;
  1002. }
  1003. #if !defined(__WXWINCE__)
  1004. // Normal system call
  1005. if ( wxRename (file1, file2) == 0 )
  1006. return true;
  1007. #endif
  1008. // Try to copy
  1009. if (wxCopyFile(file1, file2, overwrite)) {
  1010. wxRemoveFile(file1);
  1011. return true;
  1012. }
  1013. // Give up
  1014. wxLogSysError(_("File '%s' couldn't be renamed '%s'"), file1, file2);
  1015. return false;
  1016. }
  1017. bool wxRemoveFile(const wxString& file)
  1018. {
  1019. #if defined(__VISUALC__) \
  1020. || defined(__BORLANDC__) \
  1021. || defined(__WATCOMC__) \
  1022. || defined(__DMC__) \
  1023. || defined(__GNUWIN32__)
  1024. int res = wxRemove(file);
  1025. #elif defined(__WXMAC__)
  1026. int res = unlink(file.fn_str());
  1027. #else
  1028. int res = unlink(file.fn_str());
  1029. #endif
  1030. if ( res )
  1031. {
  1032. wxLogSysError(_("File '%s' couldn't be removed"), file);
  1033. }
  1034. return res == 0;
  1035. }
  1036. bool wxMkdir(const wxString& dir, int perm)
  1037. {
  1038. #if defined(__WXMAC__) && !defined(__UNIX__)
  1039. if ( mkdir(dir.fn_str(), 0) != 0 )
  1040. // assume mkdir() has 2 args on non Windows-OS/2 platforms and on Windows too
  1041. // for the GNU compiler
  1042. #elif (!(defined(__WINDOWS__) || defined(__OS2__) || defined(__DOS__))) || \
  1043. (defined(__GNUWIN32__) && !defined(__MINGW32__)) || \
  1044. defined(__WINE__) || defined(__WXMICROWIN__)
  1045. const wxChar *dirname = dir.c_str();
  1046. #if defined(MSVCRT)
  1047. wxUnusedVar(perm);
  1048. if ( mkdir(wxFNCONV(dirname)) != 0 )
  1049. #else
  1050. if ( mkdir(wxFNCONV(dirname), perm) != 0 )
  1051. #endif
  1052. #elif defined(__OS2__)
  1053. wxUnusedVar(perm);
  1054. if (::DosCreateDir(dir.c_str(), NULL) != 0) // enhance for EAB's??
  1055. #elif defined(__DOS__)
  1056. const wxChar *dirname = dir.c_str();
  1057. #if defined(__WATCOMC__)
  1058. (void)perm;
  1059. if ( wxMkDir(wxFNSTRINGCAST wxFNCONV(dirname)) != 0 )
  1060. #elif defined(__DJGPP__)
  1061. if ( mkdir(wxFNCONV(dirname), perm) != 0 )
  1062. #else
  1063. #error "Unsupported DOS compiler!"
  1064. #endif
  1065. #else // !MSW, !DOS and !OS/2 VAC++
  1066. wxUnusedVar(perm);
  1067. #ifdef __WXWINCE__
  1068. if ( CreateDirectory(dir.fn_str(), NULL) == 0 )
  1069. #else
  1070. if ( wxMkDir(dir.fn_str()) != 0 )
  1071. #endif
  1072. #endif // !MSW/MSW
  1073. {
  1074. wxLogSysError(_("Directory '%s' couldn't be created"), dir);
  1075. return false;
  1076. }
  1077. return true;
  1078. }
  1079. bool wxRmdir(const wxString& dir, int WXUNUSED(flags))
  1080. {
  1081. #if defined(__VMS__)
  1082. return false; //to be changed since rmdir exists in VMS7.x
  1083. #else
  1084. #if defined(__OS2__)
  1085. if ( ::DosDeleteDir(dir.c_str()) != 0 )
  1086. #elif defined(__WXWINCE__)
  1087. if ( RemoveDirectory(dir.fn_str()) == 0 )
  1088. #else
  1089. if ( wxRmDir(dir.fn_str()) != 0 )
  1090. #endif
  1091. {
  1092. wxLogSysError(_("Directory '%s' couldn't be deleted"), dir);
  1093. return false;
  1094. }
  1095. return true;
  1096. #endif
  1097. }
  1098. // does the path exists? (may have or not '/' or '\\' at the end)
  1099. bool wxDirExists(const wxString& pathName)
  1100. {
  1101. return wxFileName::DirExists(pathName);
  1102. }
  1103. #if WXWIN_COMPATIBILITY_2_8
  1104. // Get a temporary filename, opening and closing the file.
  1105. wxChar *wxGetTempFileName(const wxString& prefix, wxChar *buf)
  1106. {
  1107. wxString filename;
  1108. if ( !wxGetTempFileName(prefix, filename) )
  1109. return NULL;
  1110. if ( buf )
  1111. wxStrcpy(buf, filename);
  1112. else
  1113. buf = MYcopystring(filename);
  1114. return buf;
  1115. }
  1116. bool wxGetTempFileName(const wxString& prefix, wxString& buf)
  1117. {
  1118. #if wxUSE_FILE
  1119. buf = wxFileName::CreateTempFileName(prefix);
  1120. return !buf.empty();
  1121. #else // !wxUSE_FILE
  1122. wxUnusedVar(prefix);
  1123. wxUnusedVar(buf);
  1124. return false;
  1125. #endif // wxUSE_FILE/!wxUSE_FILE
  1126. }
  1127. #endif // #if WXWIN_COMPATIBILITY_2_8
  1128. // Get first file name matching given wild card.
  1129. static wxDir *gs_dir = NULL;
  1130. static wxString gs_dirPath;
  1131. wxString wxFindFirstFile(const wxString& spec, int flags)
  1132. {
  1133. wxFileName::SplitPath(spec, &gs_dirPath, NULL, NULL);
  1134. if ( gs_dirPath.empty() )
  1135. gs_dirPath = wxT(".");
  1136. if ( !wxEndsWithPathSeparator(gs_dirPath ) )
  1137. gs_dirPath << wxFILE_SEP_PATH;
  1138. delete gs_dir; // can be NULL, this is ok
  1139. gs_dir = new wxDir(gs_dirPath);
  1140. if ( !gs_dir->IsOpened() )
  1141. {
  1142. wxLogSysError(_("Cannot enumerate files '%s'"), spec);
  1143. return wxEmptyString;
  1144. }
  1145. int dirFlags;
  1146. switch (flags)
  1147. {
  1148. case wxDIR: dirFlags = wxDIR_DIRS; break;
  1149. case wxFILE: dirFlags = wxDIR_FILES; break;
  1150. default: dirFlags = wxDIR_DIRS | wxDIR_FILES; break;
  1151. }
  1152. wxString result;
  1153. gs_dir->GetFirst(&result, wxFileNameFromPath(spec), dirFlags);
  1154. if ( result.empty() )
  1155. {
  1156. wxDELETE(gs_dir);
  1157. return result;
  1158. }
  1159. return gs_dirPath + result;
  1160. }
  1161. wxString wxFindNextFile()
  1162. {
  1163. wxCHECK_MSG( gs_dir, "", "You must call wxFindFirstFile before!" );
  1164. wxString result;
  1165. gs_dir->GetNext(&result);
  1166. if ( result.empty() )
  1167. {
  1168. wxDELETE(gs_dir);
  1169. return result;
  1170. }
  1171. return gs_dirPath + result;
  1172. }
  1173. // Get current working directory.
  1174. // If buf is NULL, allocates space using new, else copies into buf.
  1175. // wxGetWorkingDirectory() is obsolete, use wxGetCwd()
  1176. // wxDoGetCwd() is their common core to be moved
  1177. // to wxGetCwd() once wxGetWorkingDirectory() will be removed.
  1178. // Do not expose wxDoGetCwd in headers!
  1179. wxChar *wxDoGetCwd(wxChar *buf, int sz)
  1180. {
  1181. #if defined(__WXWINCE__)
  1182. // TODO
  1183. if(buf && sz>0) buf[0] = wxT('\0');
  1184. return buf;
  1185. #else
  1186. if ( !buf )
  1187. {
  1188. buf = new wxChar[sz + 1];
  1189. }
  1190. bool ok wxDUMMY_INITIALIZE(false);
  1191. // for the compilers which have Unicode version of _getcwd(), call it
  1192. // directly, for the others call the ANSI version and do the translation
  1193. #if !wxUSE_UNICODE
  1194. #define cbuf buf
  1195. #else // wxUSE_UNICODE
  1196. bool needsANSI = true;
  1197. #if !defined(HAVE_WGETCWD) || wxUSE_UNICODE_MSLU
  1198. char cbuf[_MAXPATHLEN];
  1199. #endif
  1200. #ifdef HAVE_WGETCWD
  1201. #if wxUSE_UNICODE_MSLU
  1202. if ( wxGetOsVersion() != wxOS_WINDOWS_9X )
  1203. #else
  1204. char *cbuf = NULL; // never really used because needsANSI will always be false
  1205. #endif
  1206. {
  1207. ok = _wgetcwd(buf, sz) != NULL;
  1208. needsANSI = false;
  1209. }
  1210. #endif
  1211. if ( needsANSI )
  1212. #endif // wxUSE_UNICODE
  1213. {
  1214. #if defined(_MSC_VER) || defined(__MINGW32__)
  1215. ok = _getcwd(cbuf, sz) != NULL;
  1216. #elif defined(__OS2__)
  1217. APIRET rc;
  1218. ULONG ulDriveNum = 0;
  1219. ULONG ulDriveMap = 0;
  1220. rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
  1221. ok = rc == 0;
  1222. if (ok)
  1223. {
  1224. sz -= 3;
  1225. rc = ::DosQueryCurrentDir( 0 // current drive
  1226. ,(PBYTE)cbuf + 3
  1227. ,(PULONG)&sz
  1228. );
  1229. cbuf[0] = char('A' + (ulDriveNum - 1));
  1230. cbuf[1] = ':';
  1231. cbuf[2] = '\\';
  1232. ok = rc == 0;
  1233. }
  1234. #else // !Win32/VC++ !Mac !OS2
  1235. ok = getcwd(cbuf, sz) != NULL;
  1236. #endif // platform
  1237. #if wxUSE_UNICODE
  1238. // finally convert the result to Unicode if needed
  1239. wxConvFile.MB2WC(buf, cbuf, sz);
  1240. #endif // wxUSE_UNICODE
  1241. }
  1242. if ( !ok )
  1243. {
  1244. wxLogSysError(_("Failed to get the working directory"));
  1245. // VZ: the old code used to return "." on error which didn't make any
  1246. // sense at all to me - empty string is a better error indicator
  1247. // (NULL might be even better but I'm afraid this could lead to
  1248. // problems with the old code assuming the return is never NULL)
  1249. buf[0] = wxT('\0');
  1250. }
  1251. else // ok, but we might need to massage the path into the right format
  1252. {
  1253. #ifdef __DJGPP__
  1254. // VS: DJGPP is a strange mix of DOS and UNIX API and returns paths
  1255. // with / deliminers. We don't like that.
  1256. for (wxChar *ch = buf; *ch; ch++)
  1257. {
  1258. if (*ch == wxT('/'))
  1259. *ch = wxT('\\');
  1260. }
  1261. #endif // __DJGPP__
  1262. // MBN: we hope that in the case the user is compiling a GTK+/Motif app,
  1263. // he needs Unix as opposed to Win32 pathnames
  1264. #if defined( __CYGWIN__ ) && defined( __WINDOWS__ )
  1265. // another example of DOS/Unix mix (Cygwin)
  1266. wxString pathUnix = buf;
  1267. #if wxUSE_UNICODE
  1268. #if CYGWIN_VERSION_DLL_MAJOR >= 1007
  1269. cygwin_conv_path(CCP_POSIX_TO_WIN_W, pathUnix.mb_str(wxConvFile), buf, sz);
  1270. #else
  1271. char bufA[_MAXPATHLEN];
  1272. cygwin_conv_to_full_win32_path(pathUnix.mb_str(wxConvFile), bufA);
  1273. wxConvFile.MB2WC(buf, bufA, sz);
  1274. #endif
  1275. #else
  1276. #if CYGWIN_VERSION_DLL_MAJOR >= 1007
  1277. cygwin_conv_path(CCP_POSIX_TO_WIN_A, pathUnix, buf, sz);
  1278. #else
  1279. cygwin_conv_to_full_win32_path(pathUnix, buf);
  1280. #endif
  1281. #endif // wxUSE_UNICODE
  1282. #endif // __CYGWIN__
  1283. }
  1284. return buf;
  1285. #if !wxUSE_UNICODE
  1286. #undef cbuf
  1287. #endif
  1288. #endif
  1289. // __WXWINCE__
  1290. }
  1291. #if WXWIN_COMPATIBILITY_2_6
  1292. wxChar *wxGetWorkingDirectory(wxChar *buf, int sz)
  1293. {
  1294. return wxDoGetCwd(buf,sz);
  1295. }
  1296. #endif // WXWIN_COMPATIBILITY_2_6
  1297. wxString wxGetCwd()
  1298. {
  1299. wxString str;
  1300. wxDoGetCwd(wxStringBuffer(str, _MAXPATHLEN), _MAXPATHLEN);
  1301. return str;
  1302. }
  1303. bool wxSetWorkingDirectory(const wxString& d)
  1304. {
  1305. bool success = false;
  1306. #if defined(__OS2__)
  1307. if (d[1] == ':')
  1308. {
  1309. ::DosSetDefaultDisk(wxToupper(d[0]) - wxT('A') + 1);
  1310. // do not call DosSetCurrentDir when just changing drive,
  1311. // since it requires e.g. "d:." instead of "d:"!
  1312. if (d.length() == 2)
  1313. return true;
  1314. }
  1315. success = (::DosSetCurrentDir(d.c_str()) == 0);
  1316. #elif defined(__UNIX__) || defined(__WXMAC__) || defined(__DOS__)
  1317. success = (chdir(wxFNSTRINGCAST d.fn_str()) == 0);
  1318. #elif defined(__WINDOWS__)
  1319. #ifdef __WIN32__
  1320. #ifdef __WXWINCE__
  1321. // No equivalent in WinCE
  1322. wxUnusedVar(d);
  1323. #else
  1324. success = (SetCurrentDirectory(d.t_str()) != 0);
  1325. #endif
  1326. #else
  1327. // Must change drive, too.
  1328. bool isDriveSpec = ((strlen(d) > 1) && (d[1] == ':'));
  1329. if (isDriveSpec)
  1330. {
  1331. wxChar firstChar = d[0];
  1332. // To upper case
  1333. if (firstChar > 90)
  1334. firstChar = firstChar - 32;
  1335. // To a drive number
  1336. unsigned int driveNo = firstChar - 64;
  1337. if (driveNo > 0)
  1338. {
  1339. unsigned int noDrives;
  1340. _dos_setdrive(driveNo, &noDrives);
  1341. }
  1342. }
  1343. success = (chdir(WXSTRINGCAST d) == 0);
  1344. #endif
  1345. #endif
  1346. if ( !success )
  1347. {
  1348. wxLogSysError(_("Could not set current working directory"));
  1349. }
  1350. return success;
  1351. }
  1352. // Get the OS directory if appropriate (such as the Windows directory).
  1353. // On non-Windows platform, probably just return the empty string.
  1354. wxString wxGetOSDirectory()
  1355. {
  1356. #ifdef __WXWINCE__
  1357. return wxString(wxT("\\Windows"));
  1358. #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__)
  1359. wxChar buf[256];
  1360. GetWindowsDirectory(buf, 256);
  1361. return wxString(buf);
  1362. #elif defined(__WXMAC__) && wxOSX_USE_CARBON
  1363. return wxMacFindFolderNoSeparator(kOnSystemDisk, 'macs', false);
  1364. #else
  1365. return wxEmptyString;
  1366. #endif
  1367. }
  1368. bool wxEndsWithPathSeparator(const wxString& filename)
  1369. {
  1370. return !filename.empty() && wxIsPathSeparator(filename.Last());
  1371. }
  1372. // find a file in a list of directories, returns false if not found
  1373. bool wxFindFileInPath(wxString *pStr, const wxString& szPath, const wxString& szFile)
  1374. {
  1375. // we assume that it's not empty
  1376. wxCHECK_MSG( !szFile.empty(), false,
  1377. wxT("empty file name in wxFindFileInPath"));
  1378. // skip path separator in the beginning of the file name if present
  1379. wxString szFile2;
  1380. if ( wxIsPathSeparator(szFile[0u]) )
  1381. szFile2 = szFile.Mid(1);
  1382. else
  1383. szFile2 = szFile;
  1384. wxStringTokenizer tkn(szPath, wxPATH_SEP);
  1385. while ( tkn.HasMoreTokens() )
  1386. {
  1387. wxString strFile = tkn.GetNextToken();
  1388. if ( !wxEndsWithPathSeparator(strFile) )
  1389. strFile += wxFILE_SEP_PATH;
  1390. strFile += szFile2;
  1391. if ( wxFileExists(strFile) )
  1392. {
  1393. *pStr = strFile;
  1394. return true;
  1395. }
  1396. }
  1397. return false;
  1398. }
  1399. #if WXWIN_COMPATIBILITY_2_8
  1400. void WXDLLIMPEXP_BASE wxSplitPath(const wxString& fileName,
  1401. wxString *pstrPath,
  1402. wxString *pstrName,
  1403. wxString *pstrExt)
  1404. {
  1405. wxFileName::SplitPath(fileName, pstrPath, pstrName, pstrExt);
  1406. }
  1407. #endif // #if WXWIN_COMPATIBILITY_2_8
  1408. #if wxUSE_DATETIME
  1409. time_t WXDLLIMPEXP_BASE wxFileModificationTime(const wxString& filename)
  1410. {
  1411. wxDateTime mtime;
  1412. if ( !wxFileName(filename).GetTimes(NULL, &mtime, NULL) )
  1413. return (time_t)-1;
  1414. return mtime.GetTicks();
  1415. }
  1416. #endif // wxUSE_DATETIME
  1417. // Parses the filterStr, returning the number of filters.
  1418. // Returns 0 if none or if there's a problem.
  1419. // filterStr is in the form: "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpeg"
  1420. int WXDLLIMPEXP_BASE wxParseCommonDialogsFilter(const wxString& filterStr,
  1421. wxArrayString& descriptions,
  1422. wxArrayString& filters)
  1423. {
  1424. descriptions.Clear();
  1425. filters.Clear();
  1426. wxString str(filterStr);
  1427. wxString description, filter;
  1428. int pos = 0;
  1429. while( pos != wxNOT_FOUND )
  1430. {
  1431. pos = str.Find(wxT('|'));
  1432. if ( pos == wxNOT_FOUND )
  1433. {
  1434. // if there are no '|'s at all in the string just take the entire
  1435. // string as filter and make description empty for later autocompletion
  1436. if ( filters.IsEmpty() )
  1437. {
  1438. descriptions.Add(wxEmptyString);
  1439. filters.Add(filterStr);
  1440. }
  1441. else
  1442. {
  1443. wxFAIL_MSG( wxT("missing '|' in the wildcard string!") );
  1444. }
  1445. break;
  1446. }
  1447. description = str.Left(pos);
  1448. str = str.Mid(pos + 1);
  1449. pos = str.Find(wxT('|'));
  1450. if ( pos == wxNOT_FOUND )
  1451. {
  1452. filter = str;
  1453. }
  1454. else
  1455. {
  1456. filter = str.Left(pos);
  1457. str = str.Mid(pos + 1);
  1458. }
  1459. descriptions.Add(description);
  1460. filters.Add(filter);
  1461. }
  1462. #if defined(__WXMOTIF__)
  1463. // split it so there is one wildcard per entry
  1464. for( size_t i = 0 ; i < descriptions.GetCount() ; i++ )
  1465. {
  1466. pos = filters[i].Find(wxT(';'));
  1467. if (pos != wxNOT_FOUND)
  1468. {
  1469. // first split only filters
  1470. descriptions.Insert(descriptions[i],i+1);
  1471. filters.Insert(filters[i].Mid(pos+1),i+1);
  1472. filters[i]=filters[i].Left(pos);
  1473. // autoreplace new filter in description with pattern:
  1474. // C/C++ Files(*.cpp;*.c;*.h)|*.cpp;*.c;*.h
  1475. // cause split into:
  1476. // C/C++ Files(*.cpp)|*.cpp
  1477. // C/C++ Files(*.c;*.h)|*.c;*.h
  1478. // and next iteration cause another split into:
  1479. // C/C++ Files(*.cpp)|*.cpp
  1480. // C/C++ Files(*.c)|*.c
  1481. // C/C++ Files(*.h)|*.h
  1482. for ( size_t k=i;k<i+2;k++ )
  1483. {
  1484. pos = descriptions[k].Find(filters[k]);
  1485. if (pos != wxNOT_FOUND)
  1486. {
  1487. wxString before = descriptions[k].Left(pos);
  1488. wxString after = descriptions[k].Mid(pos+filters[k].Len());
  1489. pos = before.Find(wxT('('),true);
  1490. if (pos>before.Find(wxT(')'),true))
  1491. {
  1492. before = before.Left(pos+1);
  1493. before << filters[k];
  1494. pos = after.Find(wxT(')'));
  1495. int pos1 = after.Find(wxT('('));
  1496. if (pos != wxNOT_FOUND && (pos<pos1 || pos1==wxNOT_FOUND))
  1497. {
  1498. before << after.Mid(pos);
  1499. descriptions[k] = before;
  1500. }
  1501. }
  1502. }
  1503. }
  1504. }
  1505. }
  1506. #endif
  1507. // autocompletion
  1508. for( size_t j = 0 ; j < descriptions.GetCount() ; j++ )
  1509. {
  1510. if ( descriptions[j].empty() && !filters[j].empty() )
  1511. {
  1512. descriptions[j].Printf(_("Files (%s)"), filters[j].c_str());
  1513. }
  1514. }
  1515. return filters.GetCount();
  1516. }
  1517. #if defined(__WINDOWS__) && !(defined(__UNIX__) || defined(__OS2__))
  1518. static bool wxCheckWin32Permission(const wxString& path, DWORD access)
  1519. {
  1520. // quoting the MSDN: "To obtain a handle to a directory, call the
  1521. // CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag", but this
  1522. // doesn't work under Win9x/ME but then it's not needed there anyhow
  1523. const DWORD dwAttr = ::GetFileAttributes(path.t_str());
  1524. if ( dwAttr == INVALID_FILE_ATTRIBUTES )
  1525. {
  1526. // file probably doesn't exist at all
  1527. return false;
  1528. }
  1529. if ( wxGetOsVersion() == wxOS_WINDOWS_9X )
  1530. {
  1531. // FAT directories always allow all access, even if they have the
  1532. // readonly flag set, and FAT files can only be read-only
  1533. return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) ||
  1534. (access != GENERIC_WRITE ||
  1535. !(dwAttr & FILE_ATTRIBUTE_READONLY));
  1536. }
  1537. HANDLE h = ::CreateFile
  1538. (
  1539. path.t_str(),
  1540. access,
  1541. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1542. NULL,
  1543. OPEN_EXISTING,
  1544. dwAttr & FILE_ATTRIBUTE_DIRECTORY
  1545. ? FILE_FLAG_BACKUP_SEMANTICS
  1546. : 0,
  1547. NULL
  1548. );
  1549. if ( h != INVALID_HANDLE_VALUE )
  1550. CloseHandle(h);
  1551. return h != INVALID_HANDLE_VALUE;
  1552. }
  1553. #endif // __WINDOWS__
  1554. bool wxIsWritable(const wxString &path)
  1555. {
  1556. #if defined( __UNIX__ ) || defined(__OS2__)
  1557. // access() will take in count also symbolic links
  1558. return wxAccess(path.c_str(), W_OK) == 0;
  1559. #elif defined( __WINDOWS__ )
  1560. return wxCheckWin32Permission(path, GENERIC_WRITE);
  1561. #else
  1562. wxUnusedVar(path);
  1563. // TODO
  1564. return false;
  1565. #endif
  1566. }
  1567. bool wxIsReadable(const wxString &path)
  1568. {
  1569. #if defined( __UNIX__ ) || defined(__OS2__)
  1570. // access() will take in count also symbolic links
  1571. return wxAccess(path.c_str(), R_OK) == 0;
  1572. #elif defined( __WINDOWS__ )
  1573. return wxCheckWin32Permission(path, GENERIC_READ);
  1574. #else
  1575. wxUnusedVar(path);
  1576. // TODO
  1577. return false;
  1578. #endif
  1579. }
  1580. bool wxIsExecutable(const wxString &path)
  1581. {
  1582. #if defined( __UNIX__ ) || defined(__OS2__)
  1583. // access() will take in count also symbolic links
  1584. return wxAccess(path.c_str(), X_OK) == 0;
  1585. #elif defined( __WINDOWS_

Large files files are truncated, but you can click here to view the full file