#include "wx/filename.h"
#include "wx/dir.h"
+#include "wx/tokenzr.h"
+
// there are just too many of those...
#ifdef __VISUALC__
#pragma warning(disable:4706) // assignment within conditional expression
// wxPathList
// ----------------------------------------------------------------------------
-// IMPLEMENT_DYNAMIC_CLASS(wxPathList, wxStringList)
-
-static inline wxChar* MYcopystring(const wxString& s)
+void wxPathList::Add(const wxString& path)
{
- wxChar* copy = new wxChar[s.length() + 1];
- return wxStrcpy(copy, s.c_str());
-}
+ // add a path separator to force wxFileName to interpret it always as a directory
+ // (i.e. if we are called with '/home/user' we want to consider it a folder and
+ // not, as wxFileName would consider, a filename).
+ wxFileName fn(path + wxFileName::GetPathSeparator());
-static inline wxChar* MYcopystring(const wxChar* s)
-{
- wxChar* copy = new wxChar[wxStrlen(s) + 1];
- return wxStrcpy(copy, s);
+ // add only normalized relative/absolute paths
+ fn.Normalize(wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS);
+
+ wxString toadd = fn.GetPath();
+ if (Index(toadd) == wxNOT_FOUND)
+ wxArrayString::Add(toadd); // do not add duplicates
}
-void wxPathList::Add (const wxString& path)
+void wxPathList::Add(const wxArrayString &arr)
{
- wxStringList::Add (WXSTRINGCAST path);
+ for (size_t j=0; j < arr.GetCount(); j++)
+ Add(arr[j]);
}
// Add paths e.g. from the PATH environment variable
{
// No environment variables on WinCE
#ifndef __WXWINCE__
+
+ // The space has been removed from the tokenizers, otherwise a
+ // path such as "C:\Program Files" would be split into 2 paths:
+ // "C:\Program" and "Files"; this is true for both Windows and Unix.
+
static const wxChar PATH_TOKS[] =
#if defined(__WINDOWS__) || defined(__OS2__)
- /*
- The space has been removed from the tokenizers, otherwise a
- path such as "C:\Program Files" would be split into 2 paths:
- "C:\Program" and "Files"
- */
-// wxT(" ;"); // Don't separate with colon in DOS (used for drive)
wxT(";"); // Don't separate with colon in DOS (used for drive)
#else
- wxT(" :;");
+ wxT(":;");
#endif
- wxString val ;
- if (wxGetEnv (WXSTRINGCAST envVariable, &val))
+ wxString val;
+ if ( wxGetEnv(envVariable, &val) )
{
- wxChar *s = MYcopystring (val);
- wxChar *save_ptr, *token = wxStrtok (s, PATH_TOKS, &save_ptr);
-
- if (token)
- {
- Add(token);
- while (token)
- {
- if ( (token = wxStrtok ((wxChar *) NULL, PATH_TOKS, &save_ptr))
- != NULL )
- {
- Add(token);
- }
- }
- }
-
- // suppress warning about unused variable save_ptr when wxStrtok() is a
- // macro which throws away its third argument
- save_ptr = token;
-
- delete [] s;
+ // split into an array of string the value of the env var
+ wxArrayString arr = wxStringTokenize(val, PATH_TOKS);
+ WX_APPEND_ARRAY(*this, arr);
}
#endif // !__WXWINCE__
}
wxString path_only(wxPathOnly(path));
if ( !path_only.empty() )
{
- if ( !Member(path_only) )
+ if ( Index(path_only) == wxNOT_FOUND )
Add(path_only);
}
}
-bool wxPathList::Member (const wxString& path)
+// deprecated !
+bool wxPathList::Member (const wxString& path) const
{
- for (wxStringList::compatibility_iterator node = GetFirst(); node; node = node->GetNext())
- {
- wxString path2( node->GetData() );
- if (
-#if defined(__WINDOWS__) || defined(__OS2__) || defined(__VMS__) || defined(__WXMAC__)
- // Case INDEPENDENT
- path.CompareTo (path2, wxString::ignoreCase) == 0
-#else
- // Case sensitive File System
- path.CompareTo (path2) == 0
-#endif
- )
- return true;
- }
- return false;
+ return Index(path) != wxNOT_FOUND;
}
-wxString wxPathList::FindValidPath (const wxString& file)
+wxString wxPathList::FindValidPath (const wxString& file) const
{
- wxExpandPath(wxFileFunctionsBuffer, file);
+ // normalize the given string as it could be a path + a filename
+ // and not only a filename
+ wxFileName fn(file);
+ wxString strend;
- wxChar buf[_MAXPATHLEN];
- wxStrcpy(buf, wxFileFunctionsBuffer);
+ // NB: normalize without making absolute !
+ fn.Normalize(wxPATH_NORM_DOTS|wxPATH_NORM_TILDE|wxPATH_NORM_LONG|wxPATH_NORM_ENV_VARS);
- wxChar *filename = wxIsAbsolutePath (buf) ? wxFileNameFromPath (buf) : (wxChar *)buf;
+ wxASSERT_MSG(!fn.IsDir(), wxT("Cannot search for directories; only for files"));
+ if (fn.IsAbsolute())
+ strend = fn.GetFullName(); // search for the file name and ignore the path part
+ else
+ strend = fn.GetFullPath();
- for (wxStringList::compatibility_iterator node = GetFirst(); node; node = node->GetNext())
+ for (size_t i=0; i<GetCount(); i++)
{
- const wxString path(node->GetData());
- wxStrcpy (wxFileFunctionsBuffer, path);
- wxChar ch = wxFileFunctionsBuffer[wxStrlen(wxFileFunctionsBuffer)-1];
- if (ch != wxT('\\') && ch != wxT('/'))
- wxStrcat (wxFileFunctionsBuffer, wxT("/"));
- wxStrcat (wxFileFunctionsBuffer, filename);
-#ifdef __WINDOWS__
- wxUnix2DosFilename (wxFileFunctionsBuffer);
-#endif
- if (wxFileExists (wxFileFunctionsBuffer))
- {
- return wxString(wxFileFunctionsBuffer); // Found!
- }
- } // for()
+ wxString strstart = Item(i);
+ if (!strstart.IsEmpty() && strstart.Last() != wxFileName::GetPathSeparator())
+ strstart += wxFileName::GetPathSeparator();
- return wxEmptyString; // Not found
+ if (wxFileExists(strstart + strend))
+ return strstart + strend; // Found!
+ }
+
+ return wxEmptyString; // Not found
}
-wxString wxPathList::FindAbsoluteValidPath (const wxString& file)
+wxString wxPathList::FindAbsoluteValidPath (const wxString& file) const
{
wxString f = FindValidPath(file);
if ( f.empty() || wxIsAbsolutePath(f) )
return buf;
}
+// ----------------------------------------------------------------------------
+// miscellaneous global functions (TOFIX!)
+// ----------------------------------------------------------------------------
+
+static inline wxChar* MYcopystring(const wxString& s)
+{
+ wxChar* copy = new wxChar[s.length() + 1];
+ return wxStrcpy(copy, s.c_str());
+}
+
+static inline wxChar* MYcopystring(const wxChar* s)
+{
+ wxChar* copy = new wxChar[wxStrlen(s) + 1];
+ return wxStrcpy(copy, s);
+}
+
+
bool
wxFileExists (const wxString& filename)
{
}
CFStringRef cfString = CFURLCopyFileSystemPath(fullURLRef, kDefaultPathStyle);
CFRelease( fullURLRef ) ;
- return wxMacCFStringHolder(cfString).AsString(wxLocale::GetSystemEncoding());
+ CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
+ CFRelease( cfString );
+ CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
+ return wxMacCFStringHolder(cfMutableString).AsString();
}
OSStatus wxMacPathToFSRef( const wxString&path , FSRef *fsRef )
{
OSStatus err = noErr ;
- CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, wxMacCFStringHolder(path ,wxLocale::GetSystemEncoding() ) , kDefaultPathStyle, false);
+ CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, wxMacCFStringHolder(path));
+ CFStringNormalize(cfMutableString,kCFStringNormalizationFormD);
+ CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfMutableString , kDefaultPathStyle, false);
+ CFRelease( cfMutableString );
if ( NULL != url )
{
if ( CFURLGetFSRef(url, fsRef) == false )
CFStringRef cfname = CFStringCreateWithCharacters( kCFAllocatorDefault,
uniname->unicode,
uniname->length );
- return wxMacCFStringHolder(cfname).AsString() ;
+ CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfname);
+ CFRelease( cfname );
+ CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
+ return wxMacCFStringHolder(cfMutableString).AsString() ;
}
wxString wxMacFSSpec2MacFilename( const FSSpec *spec )
#ifdef HAVE_WGETCWD
#if wxUSE_UNICODE_MSLU
- if ( wxGetOsVersion() != wxWIN95 )
+ if ( wxGetOsVersion() != wxOS_WINDOWS_9X )
#else
char *cbuf = NULL; // never really used because needsANSI will always be false
#endif
wxFileName::SplitPath(pszFileName, pstrPath, pstrName, pstrExt);
}
+#if wxUSE_DATETIME
+
time_t WXDLLEXPORT wxFileModificationTime(const wxString& filename)
{
wxDateTime mtime;
return mtime.GetTicks();
}
+#endif // wxUSE_DATETIME
+
// Parses the filterStr, returning the number of filters.
// Returns 0 if none or if there's a problem.
return filters.GetCount();
}
+#if defined( __WINDOWS__ )
+bool wxCheckGenericPermission(const wxString &path, DWORD access)
+{
+ // quoting the MSDN: "To obtain a handle to a directory, call the
+ // CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag"
+ wxWinVersion ver = wxGetWinVersion();
+ bool isdir = wxDirExists(path);
+ if (isdir && (ver == wxWinVersion_95 || ver == wxWinVersion_98 || ver == wxWinVersion_ME))
+ {
+ // however Win95/98/ME do not support FILE_FLAG_BACKUP_SEMANTICS...
+ if (access == GENERIC_READ)
+ {
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ if (GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &data) == 0)
+ return false; // cannot query attributes
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
+ }
+
+ // FIXME: is it true that directories are always writable & executable on Win9X family ?
+ return true;
+ }
+ else
+ {
+ HANDLE h = CreateFile(path.c_str(), access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+ OPEN_EXISTING, isdir ? FILE_FLAG_BACKUP_SEMANTICS : 0, NULL);
+ if (h != INVALID_HANDLE_VALUE)
+ CloseHandle(h);
+
+ return h != INVALID_HANDLE_VALUE;
+ }
+}
+#endif
+
+bool wxIsWritable(const wxString &path)
+{
+#if defined( __UNIX__ )
+ // access() will take in count also symbolic links
+ return access(wxConvFile.cWX2MB(path), W_OK) == 0;
+#elif defined( __WINDOWS__ )
+ return wxCheckGenericPermission(path, GENERIC_WRITE);
+#else
+ // TODO
+ return false;
+#endif
+}
+
+bool wxIsReadable(const wxString &path)
+{
+#if defined( __UNIX__ )
+ // access() will take in count also symbolic links
+ return access(wxConvFile.cWX2MB(path), R_OK) == 0;
+#elif defined( __WINDOWS__ )
+ return wxCheckGenericPermission(path, GENERIC_READ);
+#else
+ // TODO
+ return false;
+#endif
+}
+
+bool wxIsExecutable(const wxString &path)
+{
+#if defined( __UNIX__ )
+ // access() will take in count also symbolic links
+ return access(wxConvFile.cWX2MB(path), X_OK) == 0;
+#elif defined( __WINDOWS__ )
+ return wxCheckGenericPermission(path, GENERIC_EXECUTE);
+#else
+ // TODO
+ return false;
+#endif
+}
+
//------------------------------------------------------------------------
// wild character routines