PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Externals/wxWidgets/src/common/filefn.cpp

https://bitbucket.org/primevalbully/dolphin-llvm-dsp
C++ | 2108 lines | 1696 code | 182 blank | 230 comment | 278 complexity | 14bf6f59631b1b89bce7da5568d815b2 MD5 | raw file

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

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