PageRenderTime 71ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/ExtLibs/wxWidgets/src/common/filefn.cpp

https://bitbucket.org/sycoso/cafu
C++ | 2071 lines | 1819 code | 98 blank | 154 comment | 159 complexity | 686262949d578f8a748763e9b9ea73c5 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, LGPL-2.0, GPL-2.0, BSD-3-Clause, LGPL-3.0, LGPL-2.1

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 __MWERKS__ || 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 __WXMSW__
  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(__WXMSW__) || 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 __WXMSW__
  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 __WXMSW__
  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 __WXMSW__
  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 __WXMSW__
  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 __WXMSW__
  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 __WXMSW__
  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(__WXMSW__) || 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(__WXMSW__) || 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 ( additionalPathComponent )
  732. {
  733. CFURLRef parentURLRef = fullURLRef ;
  734. fullURLRef = CFURLCreateCopyAppendingPathComponent(NULL, parentURLRef,
  735. additionalPathComponent,false);
  736. CFRelease( parentURLRef ) ;
  737. }
  738. CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, kDefaultPathStyle);
  739. CFRelease( fullURLRef ) ;
  740. CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
  741. CFRelease( cfString );
  742. CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
  743. return wxCFStringRef(cfMutableString).AsString();
  744. }
  745. OSStatus wxMacPathToFSRef( const wxString&path , FSRef *fsRef )
  746. {
  747. OSStatus err = noErr ;
  748. CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, wxCFStringRef(path));
  749. CFStringNormalize(cfMutableString,kCFStringNormalizationFormD);
  750. CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kDefaultPathStyle, false);
  751. CFRelease( cfMutableString );
  752. if ( NULL != url )
  753. {
  754. if ( CFURLGetFSRef(url, fsRef) == false )
  755. err = fnfErr ;
  756. CFRelease( url ) ;
  757. }
  758. else
  759. {
  760. err = fnfErr ;
  761. }
  762. return err ;
  763. }
  764. wxString wxMacHFSUniStrToString( ConstHFSUniStr255Param uniname )
  765. {
  766. CFStringRef cfname = CFStringCreateWithCharacters( kCFAllocatorDefault,
  767. uniname->unicode,
  768. uniname->length );
  769. CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfname);
  770. CFRelease( cfname );
  771. CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
  772. return wxCFStringRef(cfMutableString).AsString() ;
  773. }
  774. #ifndef __LP64__
  775. wxString wxMacFSSpec2MacFilename( const FSSpec *spec )
  776. {
  777. FSRef fsRef ;
  778. if ( FSpMakeFSRef( spec , &fsRef) == noErr )
  779. {
  780. return wxMacFSRefToPath( &fsRef ) ;
  781. }
  782. return wxEmptyString ;
  783. }
  784. void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec )
  785. {
  786. OSStatus err = noErr;
  787. FSRef fsRef;
  788. wxMacPathToFSRef( path , &fsRef );
  789. err = FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, spec, NULL);
  790. verify_noerr( err );
  791. }
  792. #endif
  793. #endif // __WXMAC__
  794. #if WXWIN_COMPATIBILITY_2_8
  795. template<typename T>
  796. static void wxDoDos2UnixFilename(T *s)
  797. {
  798. if (s)
  799. while (*s)
  800. {
  801. if (*s == wxT('\\'))
  802. *s = wxT('/');
  803. #ifdef __WXMSW__
  804. else
  805. *s = wxTolower(*s); // Case INDEPENDENT
  806. #endif
  807. s++;
  808. }
  809. }
  810. void wxDos2UnixFilename(char *s) { wxDoDos2UnixFilename(s); }
  811. void wxDos2UnixFilename(wchar_t *s) { wxDoDos2UnixFilename(s); }
  812. template<typename T>
  813. static void
  814. #if defined(__WXMSW__) || defined(__OS2__)
  815. wxDoUnix2DosFilename(T *s)
  816. #else
  817. wxDoUnix2DosFilename(T *WXUNUSED(s) )
  818. #endif
  819. {
  820. // Yes, I really mean this to happen under DOS only! JACS
  821. #if defined(__WXMSW__) || defined(__OS2__)
  822. if (s)
  823. while (*s)
  824. {
  825. if (*s == wxT('/'))
  826. *s = wxT('\\');
  827. s++;
  828. }
  829. #endif
  830. }
  831. void wxUnix2DosFilename(char *s) { wxDoUnix2DosFilename(s); }
  832. void wxUnix2DosFilename(wchar_t *s) { wxDoUnix2DosFilename(s); }
  833. #endif // #if WXWIN_COMPATIBILITY_2_8
  834. // Concatenate two files to form third
  835. bool
  836. wxConcatFiles (const wxString& file1, const wxString& file2, const wxString& file3)
  837. {
  838. #if wxUSE_FILE
  839. wxFile in1(file1), in2(file2);
  840. wxTempFile out(file3);
  841. if ( !in1.IsOpened() || !in2.IsOpened() || !out.IsOpened() )
  842. return false;
  843. ssize_t ofs;
  844. unsigned char buf[1024];
  845. for( int i=0; i<2; i++)
  846. {
  847. wxFile *in = i==0 ? &in1 : &in2;
  848. do{
  849. if ( (ofs = in->Read(buf,WXSIZEOF(buf))) == wxInvalidOffset ) return false;
  850. if ( ofs > 0 )
  851. if ( !out.Write(buf,ofs) )
  852. return false;
  853. } while ( ofs == (ssize_t)WXSIZEOF(buf) );
  854. }
  855. return out.Commit();
  856. #else
  857. wxUnusedVar(file1);
  858. wxUnusedVar(file2);
  859. wxUnusedVar(file3);
  860. return false;
  861. #endif
  862. }
  863. // helper of generic implementation of wxCopyFile()
  864. #if !(defined(__WIN32__) || defined(__OS2__) || defined(__PALMOS__)) && \
  865. wxUSE_FILE
  866. static bool
  867. wxDoCopyFile(wxFile& fileIn,
  868. const wxStructStat& fbuf,
  869. const wxString& filenameDst,
  870. bool overwrite)
  871. {
  872. // reset the umask as we want to create the file with exactly the same
  873. // permissions as the original one
  874. wxCHANGE_UMASK(0);
  875. // create file2 with the same permissions than file1 and open it for
  876. // writing
  877. wxFile fileOut;
  878. if ( !fileOut.Create(filenameDst, overwrite, fbuf.st_mode & 0777) )
  879. return false;
  880. // copy contents of file1 to file2
  881. char buf[4096];
  882. for ( ;; )
  883. {
  884. ssize_t count = fileIn.Read(buf, WXSIZEOF(buf));
  885. if ( count == wxInvalidOffset )
  886. return false;
  887. // end of file?
  888. if ( !count )
  889. break;
  890. if ( fileOut.Write(buf, count) < (size_t)count )
  891. return false;
  892. }
  893. // we can expect fileIn to be closed successfully, but we should ensure
  894. // that fileOut was closed as some write errors (disk full) might not be
  895. // detected before doing this
  896. return fileIn.Close() && fileOut.Close();
  897. }
  898. #endif // generic implementation of wxCopyFile
  899. // Copy files
  900. bool
  901. wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite)
  902. {
  903. #if defined(__WIN32__) && !defined(__WXMICROWIN__)
  904. // CopyFile() copies file attributes and modification time too, so use it
  905. // instead of our code if available
  906. //
  907. // NB: 3rd parameter is bFailIfExists i.e. the inverse of overwrite
  908. if ( !::CopyFile(file1.t_str(), file2.t_str(), !overwrite) )
  909. {
  910. wxLogSysError(_("Failed to copy the file '%s' to '%s'"),
  911. file1.c_str(), file2.c_str());
  912. return false;
  913. }
  914. #elif defined(__OS2__)
  915. if ( ::DosCopy(file1.c_str(), file2.c_str(), overwrite ? DCPY_EXISTING : 0) != 0 )
  916. return false;
  917. #elif defined(__PALMOS__)
  918. // TODO with http://www.palmos.com/dev/support/docs/protein_books/Memory_Databases_Files/
  919. return false;
  920. #elif wxUSE_FILE // !Win32
  921. wxStructStat fbuf;
  922. // get permissions of file1
  923. if ( wxStat( file1, &fbuf) != 0 )
  924. {
  925. // the file probably doesn't exist or we haven't the rights to read
  926. // from it anyhow
  927. wxLogSysError(_("Impossible to get permissions for file '%s'"),
  928. file1.c_str());
  929. return false;
  930. }
  931. // open file1 for reading
  932. wxFile fileIn(file1, wxFile::read);
  933. if ( !fileIn.IsOpened() )
  934. return false;
  935. // remove file2, if it exists. This is needed for creating
  936. // file2 with the correct permissions in the next step
  937. if ( wxFileExists(file2) && (!overwrite || !wxRemoveFile(file2)))
  938. {
  939. wxLogSysError(_("Impossible to overwrite the file '%s'"),
  940. file2.c_str());
  941. return false;
  942. }
  943. wxDoCopyFile(fileIn, fbuf, file2, overwrite);
  944. #if defined(__WXMAC__) || defined(__WXCOCOA__)
  945. // copy the resource fork of the file too if it's present
  946. wxString pathRsrcOut;
  947. wxFile fileRsrcIn;
  948. {
  949. // suppress error messages from this block as resource forks don't have
  950. // to exist
  951. wxLogNull noLog;
  952. // it's not enough to check for file existence: it always does on HFS
  953. // but is empty for files without resources
  954. if ( fileRsrcIn.Open(file1 + wxT("/..namedfork/rsrc")) &&
  955. fileRsrcIn.Length() > 0 )
  956. {
  957. // we must be using HFS or another filesystem with resource fork
  958. // support, suppose that destination file system also is HFS[-like]
  959. pathRsrcOut = file2 + wxT("/..namedfork/rsrc");
  960. }
  961. else // check if we have resource fork in separate file (non-HFS case)
  962. {
  963. wxFileName fnRsrc(file1);
  964. fnRsrc.SetName(wxT("._") + fnRsrc.GetName());
  965. fileRsrcIn.Close();
  966. if ( fileRsrcIn.Open( fnRsrc.GetFullPath() ) )
  967. {
  968. fnRsrc = file2;
  969. fnRsrc.SetName(wxT("._") + fnRsrc.GetName());
  970. pathRsrcOut = fnRsrc.GetFullPath();
  971. }
  972. }
  973. }
  974. if ( !pathRsrcOut.empty() )
  975. {
  976. if ( !wxDoCopyFile(fileRsrcIn, fbuf, pathRsrcOut, overwrite) )
  977. return false;
  978. }
  979. #endif // wxMac || wxCocoa
  980. #if !defined(__VISAGECPP__) && !defined(__WXMAC__) || defined(__UNIX__)
  981. // no chmod in VA. Should be some permission API for HPFS386 partitions
  982. // however
  983. if ( chmod(file2.fn_str(), fbuf.st_mode) != 0 )
  984. {
  985. wxLogSysError(_("Impossible to set permissions for the file '%s'"),
  986. file2.c_str());
  987. return false;
  988. }
  989. #endif // OS/2 || Mac
  990. #else // !Win32 && ! wxUSE_FILE
  991. // impossible to simulate with wxWidgets API
  992. wxUnusedVar(file1);
  993. wxUnusedVar(file2);
  994. wxUnusedVar(overwrite);
  995. return false;
  996. #endif // __WXMSW__ && __WIN32__
  997. return true;
  998. }
  999. bool
  1000. wxRenameFile(const wxString& file1, const wxString& file2, bool overwrite)
  1001. {
  1002. if ( !overwrite && wxFileExists(file2) )
  1003. {
  1004. wxLogSysError
  1005. (
  1006. _("Failed to rename the file '%s' to '%s' because the destination file already exists."),
  1007. file1.c_str(), file2.c_str()
  1008. );
  1009. return false;
  1010. }
  1011. #if !defined(__WXWINCE__) && !defined(__WXPALMOS__)
  1012. // Normal system call
  1013. if ( wxRename (file1, file2) == 0 )
  1014. return true;
  1015. #endif
  1016. // Try to copy
  1017. if (wxCopyFile(file1, file2, overwrite)) {
  1018. wxRemoveFile(file1);
  1019. return true;
  1020. }
  1021. // Give up
  1022. return false;
  1023. }
  1024. bool wxRemoveFile(const wxString& file)
  1025. {
  1026. #if defined(__VISUALC__) \
  1027. || defined(__BORLANDC__) \
  1028. || defined(__WATCOMC__) \
  1029. || defined(__DMC__) \
  1030. || defined(__GNUWIN32__) \
  1031. || (defined(__MWERKS__) && defined(__MSL__))
  1032. int res = wxRemove(file);
  1033. #elif defined(__WXMAC__)
  1034. int res = unlink(file.fn_str());
  1035. #elif defined(__WXPALMOS__)
  1036. int res = 1;
  1037. // TODO with VFSFileDelete()
  1038. #else
  1039. int res = unlink(file.fn_str());
  1040. #endif
  1041. return res == 0;
  1042. }
  1043. bool wxMkdir(const wxString& dir, int perm)
  1044. {
  1045. #if defined(__WXPALMOS__)
  1046. return false;
  1047. #else
  1048. #if defined(__WXMAC__) && !defined(__UNIX__)
  1049. if ( mkdir(dir.fn_str(), 0) != 0 )
  1050. // assume mkdir() has 2 args on non Windows-OS/2 platforms and on Windows too
  1051. // for the GNU compiler
  1052. #elif (!(defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__))) || \
  1053. (defined(__GNUWIN32__) && !defined(__MINGW32__)) || \
  1054. defined(__WINE__) || defined(__WXMICROWIN__)
  1055. const wxChar *dirname = dir.c_str();
  1056. #if defined(MSVCRT)
  1057. wxUnusedVar(perm);
  1058. if ( mkdir(wxFNCONV(dirname)) != 0 )
  1059. #else
  1060. if ( mkdir(wxFNCONV(dirname), perm) != 0 )
  1061. #endif
  1062. #elif defined(__OS2__)
  1063. wxUnusedVar(perm);
  1064. if (::DosCreateDir(dir.c_str(), NULL) != 0) // enhance for EAB's??
  1065. #elif defined(__DOS__)
  1066. const wxChar *dirname = dir.c_str();
  1067. #if defined(__WATCOMC__)
  1068. (void)perm;
  1069. if ( wxMkDir(wxFNSTRINGCAST wxFNCONV(dirname)) != 0 )
  1070. #elif defined(__DJGPP__)
  1071. if ( mkdir(wxFNCONV(dirname), perm) != 0 )
  1072. #else
  1073. #error "Unsupported DOS compiler!"
  1074. #endif
  1075. #else // !MSW, !DOS and !OS/2 VAC++
  1076. wxUnusedVar(perm);
  1077. #ifdef __WXWINCE__
  1078. if ( CreateDirectory(dir.fn_str(), NULL) == 0 )
  1079. #else
  1080. if ( wxMkDir(dir.fn_str()) != 0 )
  1081. #endif
  1082. #endif // !MSW/MSW
  1083. {
  1084. wxLogSysError(_("Directory '%s' couldn't be created"), dir);
  1085. return false;
  1086. }
  1087. return true;
  1088. #endif // PALMOS/!PALMOS
  1089. }
  1090. bool wxRmdir(const wxString& dir, int WXUNUSED(flags))
  1091. {
  1092. #if defined(__VMS__)
  1093. return false; //to be changed since rmdir exists in VMS7.x
  1094. #elif defined(__WXPALMOS__)
  1095. // TODO with VFSFileRename()
  1096. return false;
  1097. #else
  1098. #if defined(__OS2__)
  1099. if ( ::DosDeleteDir(dir.c_str()) != 0 )
  1100. #elif defined(__WXWINCE__)
  1101. if ( RemoveDirectory(dir.fn_str()) == 0 )
  1102. #else
  1103. if ( wxRmDir(dir.fn_str()) != 0 )
  1104. #endif
  1105. {
  1106. wxLogSysError(_("Directory '%s' couldn't be deleted"), dir);
  1107. return false;
  1108. }
  1109. return true;
  1110. #endif // PALMOS/!PALMOS
  1111. }
  1112. // does the path exists? (may have or not '/' or '\\' at the end)
  1113. bool wxDirExists(const wxString& pathName)
  1114. {
  1115. return wxFileName::DirExists(pathName);
  1116. }
  1117. #if WXWIN_COMPATIBILITY_2_8
  1118. // Get a temporary filename, opening and closing the file.
  1119. wxChar *wxGetTempFileName(const wxString& prefix, wxChar *buf)
  1120. {
  1121. wxString filename;
  1122. if ( !wxGetTempFileName(prefix, filename) )
  1123. return NULL;
  1124. if ( buf )
  1125. #ifdef _PACC_VER
  1126. // work around the PalmOS pacc compiler bug
  1127. wxStrcpy(buf, filename.data());
  1128. #else
  1129. wxStrcpy(buf, filename);
  1130. #endif
  1131. else
  1132. buf = MYcopystring(filename);
  1133. return buf;
  1134. }
  1135. bool wxGetTempFileName(const wxString& prefix, wxString& buf)
  1136. {
  1137. #if wxUSE_FILE
  1138. buf = wxFileName::CreateTempFileName(prefix);
  1139. return !buf.empty();
  1140. #else // !wxUSE_FILE
  1141. wxUnusedVar(prefix);
  1142. wxUnusedVar(buf);
  1143. return false;
  1144. #endif // wxUSE_FILE/!wxUSE_FILE
  1145. }
  1146. #endif // #if WXWIN_COMPATIBILITY_2_8
  1147. // Get first file name matching given wild card.
  1148. static wxDir *gs_dir = NULL;
  1149. static wxString gs_dirPath;
  1150. wxString wxFindFirstFile(const wxString& spec, int flags)
  1151. {
  1152. wxFileName::SplitPath(spec, &gs_dirPath, NULL, NULL);
  1153. if ( gs_dirPath.empty() )
  1154. gs_dirPath = wxT(".");
  1155. if ( !wxEndsWithPathSeparator(gs_dirPath ) )
  1156. gs_dirPath << wxFILE_SEP_PATH;
  1157. delete gs_dir; // can be NULL, this is ok
  1158. gs_dir = new wxDir(gs_dirPath);
  1159. if ( !gs_dir->IsOpened() )
  1160. {
  1161. wxLogSysError(_("Cannot enumerate files '%s'"), spec);
  1162. return wxEmptyString;
  1163. }
  1164. int dirFlags;
  1165. switch (flags)
  1166. {
  1167. case wxDIR: dirFlags = wxDIR_DIRS; break;
  1168. case wxFILE: dirFlags = wxDIR_FILES; break;
  1169. default: dirFlags = wxDIR_DIRS | wxDIR_FILES; break;
  1170. }
  1171. wxString result;
  1172. gs_dir->GetFirst(&result, wxFileNameFromPath(spec), dirFlags);
  1173. if ( result.empty() )
  1174. {
  1175. wxDELETE(gs_dir);
  1176. return result;
  1177. }
  1178. return gs_dirPath + result;
  1179. }
  1180. wxString wxFindNextFile()
  1181. {
  1182. wxCHECK_MSG( gs_dir, "", "You must call wxFindFirstFile before!" );
  1183. wxString result;
  1184. gs_dir->GetNext(&result);
  1185. if ( result.empty() )
  1186. {
  1187. wxDELETE(gs_dir);
  1188. return result;
  1189. }
  1190. return gs_dirPath + result;
  1191. }
  1192. // Get current working directory.
  1193. // If buf is NULL, allocates space using new, else copies into buf.
  1194. // wxGetWorkingDirectory() is obsolete, use wxGetCwd()
  1195. // wxDoGetCwd() is their common core to be moved
  1196. // to wxGetCwd() once wxGetWorkingDirectory() will be removed.
  1197. // Do not expose wxDoGetCwd in headers!
  1198. wxChar *wxDoGetCwd(wxChar *buf, int sz)
  1199. {
  1200. #if defined(__WXPALMOS__)
  1201. // TODO
  1202. if(buf && sz>0) buf[0] = wxT('\0');
  1203. return buf;
  1204. #elif defined(__WXWINCE__)
  1205. // TODO
  1206. if(buf && sz>0) buf[0] = wxT('\0');
  1207. return buf;
  1208. #else
  1209. if ( !buf )
  1210. {
  1211. buf = new wxChar[sz + 1];
  1212. }
  1213. bool ok wxDUMMY_INITIALIZE(false);
  1214. // for the compilers which have Unicode version of _getcwd(), call it
  1215. // directly, for the others call the ANSI version and do the translation
  1216. #if !wxUSE_UNICODE
  1217. #define cbuf buf
  1218. #else // wxUSE_UNICODE
  1219. bool needsANSI = true;
  1220. #if !defined(HAVE_WGETCWD) || wxUSE_UNICODE_MSLU
  1221. char cbuf[_MAXPATHLEN];
  1222. #endif
  1223. #ifdef HAVE_WGETCWD
  1224. #if wxUSE_UNICODE_MSLU
  1225. if ( wxGetOsVersion() != wxOS_WINDOWS_9X )
  1226. #else
  1227. char *cbuf = NULL; // never really used because needsANSI will always be false
  1228. #endif
  1229. {
  1230. ok = _wgetcwd(buf, sz) != NULL;
  1231. needsANSI = false;
  1232. }
  1233. #endif
  1234. if ( needsANSI )
  1235. #endif // wxUSE_UNICODE
  1236. {
  1237. #if defined(_MSC_VER) || defined(__MINGW32__)
  1238. ok = _getcwd(cbuf, sz) != NULL;
  1239. #elif defined(__OS2__)
  1240. APIRET rc;
  1241. ULONG ulDriveNum = 0;
  1242. ULONG ulDriveMap = 0;
  1243. rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
  1244. ok = rc == 0;
  1245. if (ok)
  1246. {
  1247. sz -= 3;
  1248. rc = ::DosQueryCurrentDir( 0 // current drive
  1249. ,(PBYTE)cbuf + 3
  1250. ,(PULONG)&sz
  1251. );
  1252. cbuf[0] = char('A' + (ulDriveNum - 1));
  1253. cbuf[1] = ':';
  1254. cbuf[2] = '\\';
  1255. ok = rc == 0;
  1256. }
  1257. #else // !Win32/VC++ !Mac !OS2
  1258. ok = getcwd(cbuf, sz) != NULL;
  1259. #endif // platform
  1260. #if wxUSE_UNICODE
  1261. // finally convert the result to Unicode if needed
  1262. wxConvFile.MB2WC(buf, cbuf, sz);
  1263. #endif // wxUSE_UNICODE
  1264. }
  1265. if ( !ok )
  1266. {
  1267. wxLogSysError(_("Failed to get the working directory"));
  1268. // VZ: the old code used to return "." on error which didn't make any
  1269. // sense at all to me - empty string is a better error indicator
  1270. // (NULL might be even better but I'm afraid this could lead to
  1271. // problems with the old code assuming the return is never NULL)
  1272. buf[0] = wxT('\0');
  1273. }
  1274. else // ok, but we might need to massage the path into the right format
  1275. {
  1276. #ifdef __DJGPP__
  1277. // VS: DJGPP is a strange mix of DOS and UNIX API and returns paths
  1278. // with / deliminers. We don't like that.
  1279. for (wxChar *ch = buf; *ch; ch++)
  1280. {
  1281. if (*ch == wxT('/'))
  1282. *ch = wxT('\\');
  1283. }
  1284. #endif // __DJGPP__
  1285. // MBN: we hope that in the case the user is compiling a GTK+/Motif app,
  1286. // he needs Unix as opposed to Win32 pathnames
  1287. #if defined( __CYGWIN__ ) && defined( __WINDOWS__ )
  1288. // another example of DOS/Unix mix (Cygwin)
  1289. wxString pathUnix = buf;
  1290. #if wxUSE_UNICODE
  1291. #if CYGWIN_VERSION_DLL_MAJOR >= 1007
  1292. cygwin_conv_path(CCP_POSIX_TO_WIN_W, pathUnix.mb_str(wxConvFile), buf, sz);
  1293. #else
  1294. char bufA[_MAXPATHLEN];
  1295. cygwin_conv_to_full_win32_path(pathUnix.mb_str(wxConvFile), bufA);
  1296. wxConvFile.MB2WC(buf, bufA, sz);
  1297. #endif
  1298. #else
  1299. #if CYGWIN_VERSION_DLL_MAJOR >= 1007
  1300. cygwin_conv_path(CCP_POSIX_TO_WIN_A, pathUnix, buf, sz);
  1301. #else
  1302. cygwin_conv_to_full_win32_path(pathUnix, buf);
  1303. #endif
  1304. #endif // wxUSE_UNICODE
  1305. #endif // __CYGWIN__
  1306. }
  1307. return buf;
  1308. #if !wxUSE_UNICODE
  1309. #undef cbuf
  1310. #endif
  1311. #endif
  1312. // __WXWINCE__
  1313. }
  1314. #if WXWIN_COMPATIBILITY_2_6
  1315. wxChar *wxGetWorkingDirectory(wxChar *buf, int sz)
  1316. {
  1317. return wxDoGetCwd(buf,sz);
  1318. }
  1319. #endif // WXWIN_COMPATIBILITY_2_6
  1320. wxString wxGetCwd()
  1321. {
  1322. wxString str;
  1323. wxDoGetCwd(wxStringBuffer(str, _MAXPATHLEN), _MAXPATHLEN);
  1324. return str;
  1325. }
  1326. bool wxSetWorkingDirectory(const wxString& d)
  1327. {
  1328. #if defined(__OS2__)
  1329. if (d[1] == ':')
  1330. {
  1331. ::DosSetDefaultDisk(wxToupper(d[0]) - wxT('A') + 1);
  1332. // do not call DosSetCurrentDir when just changing drive,
  1333. // since it requires e.g. "d:." instead of "d:"!
  1334. if (d.length() == 2)
  1335. return true;
  1336. }
  1337. return (::DosSetCurrentDir(d.c_str()) == 0);
  1338. #elif defined(__UNIX__) || defined(__WXMAC__) || defined(__DOS__)
  1339. return (chdir(wxFNSTRINGCAST d.fn_str()) == 0);
  1340. #elif defined(__WINDOWS__)
  1341. #ifdef __WIN32__
  1342. #ifdef __WXWINCE__
  1343. // No equivalent in WinCE
  1344. wxUnusedVar(d);
  1345. return false;
  1346. #else
  1347. return (bool)(SetCurrentDirectory(d.fn_str()) != 0);
  1348. #endif
  1349. #else
  1350. // Must change drive, too.
  1351. bool isDriveSpec = ((strlen(d) > 1) && (d[1] == ':'));
  1352. if (isDriveSpec)
  1353. {
  1354. wxChar firstChar = d[0];
  1355. // To upper case
  1356. if (firstChar > 90)
  1357. firstChar = firstChar - 32;
  1358. // To a drive number
  1359. unsigned int driveNo = firstChar - 64;
  1360. if (driveNo > 0)
  1361. {
  1362. unsigned int noDrives;
  1363. _dos_setdrive(driveNo, &noDrives);
  1364. }
  1365. }
  1366. bool success = (chdir(WXSTRINGCAST d) == 0);
  1367. return success;
  1368. #endif
  1369. #endif
  1370. }
  1371. // Get the OS directory if appropriate (such as the Windows directory).
  1372. // On non-Windows platform, probably just return the empty string.
  1373. wxString wxGetOSDirectory()
  1374. {
  1375. #ifdef __WXWINCE__
  1376. return wxString(wxT("\\Windows"));
  1377. #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__)
  1378. wxChar buf[256];
  1379. GetWindowsDirectory(buf, 256);
  1380. return wxString(buf);
  1381. #elif defined(__WXMAC__) && wxOSX_USE_CARBON
  1382. return wxMacFindFolderNoSeparator(kOnSystemDisk, 'macs', false);
  1383. #else
  1384. return wxEmptyString;
  1385. #endif
  1386. }
  1387. bool wxEndsWithPathSeparator(const wxString& filename)
  1388. {
  1389. return !filename.empty() && wxIsPathSeparator(filename.Last());
  1390. }
  1391. // find a file in a list of directories, returns false if not found
  1392. bool wxFindFileInPath(wxString *pStr, const wxString& szPath, const wxString& szFile)
  1393. {
  1394. // we assume that it's not empty
  1395. wxCHECK_MSG( !szFile.empty(), false,
  1396. wxT("empty file name in wxFindFileInPath"));
  1397. // skip path separator in the beginning of the file name if present
  1398. wxString szFile2;
  1399. if ( wxIsPathSeparator(szFile[0u]) )
  1400. szFile2 = szFile.Mid(1);
  1401. else
  1402. szFile2 = szFile;
  1403. wxStringTokenizer tkn(szPath, wxPATH_SEP);
  1404. while ( tkn.HasMoreTokens() )
  1405. {
  1406. wxString strFile = tkn.GetNextToken();
  1407. if ( !wxEndsWithPathSeparator(strFile) )
  1408. strFile += wxFILE_SEP_PATH;
  1409. strFile += szFile2;
  1410. if ( wxFileExists(strFile) )
  1411. {
  1412. *pStr = strFile;
  1413. return true;
  1414. }
  1415. }
  1416. return false;
  1417. }
  1418. #if WXWIN_COMPATIBILITY_2_8
  1419. void WXDLLIMPEXP_BASE wxSplitPath(const wxString& fileName,
  1420. wxString *pstrPath,
  1421. wxString *pstrName,
  1422. wxString *pstrExt)
  1423. {
  1424. wxFileName::SplitPath(fileName, pstrPath, pstrName, pstrExt);
  1425. }
  1426. #endif // #if WXWIN_COMPATIBILITY_2_8
  1427. #if wxUSE_DATETIME
  1428. time_t WXDLLIMPEXP_BASE wxFileModificationTime(const wxString& filename)
  1429. {
  1430. wxDateTime mtime;
  1431. if ( !wxFileName(filename).GetTimes(NULL, &mtime, NULL) )
  1432. return (time_t)-1;
  1433. return mtime.GetTicks();
  1434. }
  1435. #endif // wxUSE_DATETIME
  1436. // Parses the filterStr, returning the number of filters.
  1437. // Returns 0 if none or if there's a problem.
  1438. // filterStr is in the form: "All files (*.*)|*.*|JPEG Files (*.jpeg)|*.jpeg"
  1439. int WXDLLIMPEXP_BASE wxParseCommonDialogsFilter(const wxString& filterStr,
  1440. wxArrayString& descriptions,
  1441. wxArrayString& filters)
  1442. {
  1443. descriptions.Clear();
  1444. filters.Clear();
  1445. wxString str(filterStr);
  1446. wxString description, filter;
  1447. int pos = 0;
  1448. while( pos != wxNOT_FOUND )
  1449. {
  1450. pos = str.Find(wxT('|'));
  1451. if ( pos == wxNOT_FOUND )
  1452. {
  1453. // if there are no '|'s at all in the string just take the entire
  1454. // string as filter and make description empty for later autocompletion
  1455. if ( filters.IsEmpty() )
  1456. {
  1457. descriptions.Add(wxEmptyString);
  1458. filters.Add(filterStr);
  1459. }
  1460. else
  1461. {
  1462. wxFAIL_MSG( wxT("missing '|' in the wildcard string!") );
  1463. }
  1464. break;
  1465. }
  1466. description = str.Left(pos);
  1467. str = str.Mid(pos + 1);
  1468. pos = str.Find(wxT('|'));
  1469. if ( pos == wxNOT_FOUND )
  1470. {
  1471. filter = str;
  1472. }
  1473. else
  1474. {
  1475. filter = str.Left(pos);
  1476. str = str.Mid(pos + 1);
  1477. }
  1478. descriptions.Add(description);
  1479. filters.Add(filter);
  1480. }
  1481. #if defined(__WXMOTIF__)
  1482. // split it so there is one wildcard per entry
  1483. for( size_t i = 0 ; i < descriptions.GetCount() ; i++ )
  1484. {
  1485. pos = filters[i].Find(wxT(';'));
  1486. if (pos != wxNOT_FOUND)
  1487. {
  1488. // first split only filters
  1489. descriptions.Insert(descriptions[i],i+1);
  1490. filters.Insert(filters[i].Mid(pos+1),i+1);
  1491. filters[i]=filters[i].Left(pos);
  1492. // autoreplace new filter in description with pattern:
  1493. // C/C++ Files(*.cpp;*.c;*.h)|*.cpp;*.c;*.h
  1494. // cause split into:
  1495. // C/C++ Files(*.cpp)|*.cpp
  1496. // C/C++ Files(*.c;*.h)|*.c;*.h
  1497. // and next iteration cause another split into:
  1498. // C/C++ Files(*.cpp)|*.cpp
  1499. // C/C++ Files(*.c)|*.c
  1500. // C/C++ Files(*.h)|*.h
  1501. for ( size_t k=i;k<i+2;k++ )
  1502. {
  1503. pos = descriptions[k].Find(filters[k]);
  1504. if (pos != wxNOT_FOUND)
  1505. {
  1506. wxString before = descriptions[k].Left(pos);
  1507. wxString after = descriptions[k].Mid(pos+filters[k].Len());
  1508. pos = before.Find(wxT('('),true);
  1509. if (pos>before.Find(wxT(')'),true))
  1510. {
  1511. before = before.Left(pos+1);
  1512. before << filters[k];
  1513. pos = after.Find(wxT(')'));
  1514. int pos1 = after.Find(wxT('('));
  1515. if (pos != wxNOT_FOUND && (pos<pos1 || pos1==wxNOT_FOUND))
  1516. {
  1517. before << after.Mid(pos);
  1518. descriptions[k] = before;
  1519. }
  1520. }
  1521. }
  1522. }
  1523. }
  1524. }
  1525. #endif
  1526. // autocompletion
  1527. for( size_t j = 0 ; j < descriptions.GetCount() ; j++ )
  1528. {
  1529. if ( descriptions[j].empty() && !filters[j].empty() )
  1530. {
  1531. descriptions[j].Printf(_("Files (%s)"), filters[j].c_str());
  1532. }
  1533. }
  1534. return filters.GetCount();
  1535. }
  1536. #if defined(__WINDOWS__) && !(defined(__UNIX__) || defined(__OS2__))
  1537. static bool wxCheckWin32Permission(const wxString& path, DWORD access)
  1538. {
  1539. // quoting the MSDN: "To obtain a handle to a directory, call the
  1540. // CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag", but this
  1541. // doesn't work under Win9x/ME but then it's not needed there anyhow
  1542. const DWORD dwAttr = ::GetFileAttributes(path.fn_str());
  1543. if ( dwAttr == INVALID_FILE_ATTRIBUTES )
  1544. {
  1545. // file probably doesn't exist at all
  1546. return false;
  1547. }
  1548. if ( wxGetOsVersion() == wxOS_WINDOWS_9X )
  1549. {
  1550. // FAT directories always allow all access, even if they have the
  1551. // readonly flag set, and FAT files can only be read-only
  1552. return (dwAttr & FILE_ATTRIBUTE_DIRECTORY) ||
  1553. (access != GENERIC_WRITE ||
  1554. !(dwAttr & FILE_ATTRIBUTE_READONLY));
  1555. }
  1556. HANDLE h = ::CreateFile
  1557. (
  1558. path.t_str(),
  1559. access,
  1560. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1561. NULL,
  1562. OPEN_EXISTING,
  1563. dwAttr & FILE_ATTRIBUTE_DIRECTORY
  1564. ? FILE_FLAG_BACKUP_SEMANTICS
  1565. : 0,
  1566. NULL
  1567. );
  1568. if ( h != INVALID_HANDLE_VALUE )
  1569. CloseHandle(h);
  1570. return h != INVALID_HANDLE_VALUE;
  1571. }
  1572. #endif // __WINDOWS__
  1573. bool wxIsWritable(const wxString &path)
  1574. {
  1575. #if defined( __UNIX__ ) || defined(__OS2__)
  1576. // access() will take in count also symbolic links
  1577. return wxAccess(path.c_str(), W_OK) == 0;
  1578. #elif def

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