X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7bea7b91482dd41568e11fc9e91ce485db680ddd..194b22676876a5d30bdb605932a429b2fbabda4a:/src/common/filefn.cpp diff --git a/src/common/filefn.cpp b/src/common/filefn.cpp index 7b7a499f5f..caaf99caf1 100644 --- a/src/common/filefn.cpp +++ b/src/common/filefn.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: filefn.cpp +// Name: src/common/filefn.cpp // Purpose: File- and directory-related functions // Author: Julian Smart // Modified by: @@ -17,24 +17,25 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "filefn.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#include "wx/defs.h" #ifdef __BORLANDC__ #pragma hdrstop #endif -#include "wx/utils.h" -#include "wx/intl.h" +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/utils.h" +#endif + #include "wx/file.h" // This does include filefn.h #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 @@ -44,7 +45,7 @@ #include #include #include -#if !defined(__WATCOMC__) +#if !wxONLY_WATCOM_EARLIER_THAN(1,4) #if !(defined(_MSC_VER) && (_MSC_VER > 800)) #include #endif @@ -54,8 +55,6 @@ #include "wx/mac/private.h" // includes mac headers #endif -#include "wx/log.h" - #ifdef __WINDOWS__ #include "wx/msw/private.h" #include "wx/msw/mslu.h" @@ -116,13 +115,17 @@ const int wxInvalidOffset = -1; // macros // ---------------------------------------------------------------------------- -// we need to translate Mac filenames before passing them to OS functions +// translate the filenames before passing them to OS functions #define OS_FILENAME(s) (s.fn_str()) // ============================================================================ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wrappers around standard POSIX functions +// ---------------------------------------------------------------------------- + #ifdef wxNEED_WX_UNISTD_H WXDLLEXPORT int wxStat( const wxChar *file_name, wxStructStat *buf ) @@ -130,6 +133,11 @@ WXDLLEXPORT int wxStat( const wxChar *file_name, wxStructStat *buf ) return stat( wxConvFile.cWX2MB( file_name ), buf ); } +WXDLLEXPORT int wxLstat( const wxChar *file_name, wxStructStat *buf ) +{ + return lstat( wxConvFile.cWX2MB( file_name ), buf ); +} + WXDLLEXPORT int wxAccess( const wxChar *pathname, int mode ) { return access( wxConvFile.cWX2MB( pathname ), mode ); @@ -140,30 +148,31 @@ WXDLLEXPORT int wxOpen( const wxChar *pathname, int flags, mode_t mode ) return open( wxConvFile.cWX2MB( pathname ), flags, mode ); } -#endif - // wxNEED_WX_UNISTD_H +#endif // wxNEED_WX_UNISTD_H // ---------------------------------------------------------------------------- // 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 @@ -171,43 +180,24 @@ void wxPathList::AddEnvList (const wxString& WXUNUSED_IN_WINCE(envVariable)) { // 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__ } @@ -220,68 +210,53 @@ void wxPathList::EnsureFileAccessible (const wxString& path) 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 { - if (wxFileExists (wxExpandPath(wxFileFunctionsBuffer, file))) - return wxString(wxFileFunctionsBuffer); + // 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; iGetData(); - 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 f; - wxString buf; - wxGetWorkingDirectory(wxStringBuffer(buf, _MAXPATHLEN), _MAXPATHLEN); + wxString buf = ::wxGetCwd(); if ( !wxEndsWithPathSeparator(buf) ) { @@ -292,6 +267,23 @@ wxString wxPathList::FindAbsoluteValidPath (const wxString& file) 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) { @@ -304,11 +296,19 @@ wxFileExists (const wxString& filename) return (ret != (DWORD)-1) && !(ret & FILE_ATTRIBUTE_DIRECTORY); #else // !__WIN32__ + #ifndef S_ISREG + #define S_ISREG(mode) ((mode) & S_IFREG) + #endif wxStructStat st; #ifndef wxNEED_WX_UNISTD_H - return wxStat( filename.fn_str() , &st) == 0 && (st.st_mode & S_IFREG); + return (wxStat( filename.fn_str() , &st) == 0 && S_ISREG(st.st_mode)) +#ifdef __OS2__ + || (errno == EACCES) // if access is denied something with that name + // exists and is opened in exclusive mode. +#endif + ; #else - return wxStat( filename , &st) == 0 && (st.st_mode & S_IFREG); + return wxStat( filename , &st) == 0 && S_ISREG(st.st_mode); #endif #endif // __WIN32__/!__WIN32__ } @@ -369,8 +369,8 @@ void wxStripExtension(wxChar *buffer) void wxStripExtension(wxString& buffer) { //RN: Be careful about the handling the case where - //buffer.Length() == 0 - for(size_t i = buffer.Length() - 1; i != wxString::npos; --i) + //buffer.length() == 0 + for(size_t i = buffer.length() - 1; i != wxString::npos; --i) { if (buffer.GetChar(i) == wxT('.')) { @@ -436,28 +436,38 @@ wxChar *wxRealPath (wxChar *path) return path; } +wxString wxRealPath(const wxString& path) +{ + wxChar *buf1=MYcopystring(path); + wxChar *buf2=wxRealPath(buf1); + wxString buf(buf2); + delete [] buf1; + return buf; +} + + // Must be destroyed wxChar *wxCopyAbsolutePath(const wxString& filename) { - if (filename.empty()) - return (wxChar *) NULL; + if (filename.empty()) + return (wxChar *) NULL; - if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) { - wxChar buf[_MAXPATHLEN]; - buf[0] = wxT('\0'); - wxGetWorkingDirectory(buf, WXSIZEOF(buf)); - wxChar ch = buf[wxStrlen(buf) - 1]; + if (! wxIsAbsolutePath(wxExpandPath(wxFileFunctionsBuffer, filename))) + { + wxString buf = ::wxGetCwd(); + wxChar ch = buf.Last(); #ifdef __WXMSW__ - if (ch != wxT('\\') && ch != wxT('/')) - wxStrcat(buf, wxT("\\")); + if (ch != wxT('\\') && ch != wxT('/')) + buf << wxT("\\"); #else - if (ch != wxT('/')) - wxStrcat(buf, wxT("/")); + if (ch != wxT('/')) + buf << wxT("/"); #endif - wxStrcat(buf, wxFileFunctionsBuffer); - return MYcopystring( wxRealPath(buf) ); - } - return MYcopystring( wxFileFunctionsBuffer ); + buf << wxFileFunctionsBuffer; + buf = wxRealPath( buf ); + return MYcopystring( buf ); + } + return MYcopystring( wxFileFunctionsBuffer ); } /*- @@ -546,7 +556,7 @@ wxChar *wxExpandPath(wxChar *buf, const wxChar *name) while ((*d++ = *s) != 0) { # ifndef __WXMSW__ if (*s == wxT('\\')) { - if ((*(d - 1) = *++s)) { + if ((*(d - 1) = *++s)!=0) { s++; continue; } else @@ -612,11 +622,14 @@ wxChar *wxExpandPath(wxChar *buf, const wxChar *name) nnm = *s ? s + 1 : s; *s = 0; // FIXME: wxGetUserHome could return temporary storage in Unicode mode - if ((home = WXSTRINGCAST wxGetUserHome(wxString(nm + 1))) == NULL) { - if (was_sep) /* replace only if it was there: */ - *s = SEP; + if ((home = WXSTRINGCAST wxGetUserHome(wxString(nm + 1))) == NULL) + { + if (was_sep) /* replace only if it was there: */ + *s = SEP; s = NULL; - } else { + } + else + { nm = nnm; s = home; } @@ -791,7 +804,7 @@ wxString wxPathOnly (const wxString& path) // Local copy wxStrcpy (buf, WXSTRINGCAST path); - int l = path.Length(); + int l = path.length(); int i = l - 1; // Search backward for a backward or forward slash @@ -865,13 +878,19 @@ wxString wxMacFSRefToPath( const FSRef *fsRef , CFStringRef additionalPathCompon } 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 ) @@ -890,9 +909,14 @@ wxString wxMacHFSUniStrToString( ConstHFSUniStr255Param uniname ) 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() ; } +#ifndef __LP64__ + wxString wxMacFSSpec2MacFilename( const FSSpec *spec ) { FSRef fsRef ; @@ -910,6 +934,7 @@ void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec ) wxMacPathToFSRef( path , &fsRef ) ; err = FSRefMakeFSSpec( &fsRef , spec ) ; } +#endif #endif // __WXMAC__ @@ -1094,8 +1119,19 @@ wxCopyFile (const wxString& file1, const wxString& file2, bool overwrite) } bool -wxRenameFile (const wxString& file1, const wxString& file2) +wxRenameFile(const wxString& file1, const wxString& file2, bool overwrite) { + if ( !overwrite && wxFileExists(file2) ) + { + wxLogSysError + ( + _("Failed to rename the file '%s' to '%s' because the destination file already exists."), + file1.c_str(), file2.c_str() + ); + + return false; + } + #if !defined(__WXWINCE__) && !defined(__WXPALMOS__) // Normal system call if ( wxRename (file1, file2) == 0 ) @@ -1103,7 +1139,7 @@ wxRenameFile (const wxString& file1, const wxString& file2) #endif // Try to copy - if (wxCopyFile(file1, file2)) { + if (wxCopyFile(file1, file2, overwrite)) { wxRemoveFile(file1); return true; } @@ -1151,6 +1187,7 @@ bool wxMkdir(const wxString& dir, int perm) if ( mkdir(wxFNCONV(dirname), perm) != 0 ) #endif #elif defined(__OS2__) + wxUnusedVar(perm); if (::DosCreateDir((PSZ)dirname, NULL) != 0) // enhance for EAB's?? #elif defined(__DOS__) #if defined(__WATCOMC__) @@ -1203,7 +1240,7 @@ bool wxDirExists(const wxChar *pszPathName) #if defined(__WINDOWS__) || defined(__OS2__) // Windows fails to find directory named "c:\dir\" even if "c:\dir" exists, // so remove all trailing backslashes from the path - but don't do this for - // the pathes "d:\" (which are different from "d:") nor for just "\" + // the paths "d:\" (which are different from "d:") nor for just "\" while ( wxEndsWithPathSeparator(strPath) ) { size_t len = strPath.length(); @@ -1228,7 +1265,13 @@ bool wxDirExists(const wxChar *pszPathName) return (ret != (DWORD)-1) && (ret & FILE_ATTRIBUTE_DIRECTORY); #elif defined(__OS2__) - return (::DosSetCurrentDir((PSZ)(WXSTRINGCAST strPath))); + FILESTATUS3 Info = {{0}}; + APIRET rc = ::DosQueryPathInfo((PSZ)(WXSTRINGCAST strPath), FIL_STANDARD, + (void*) &Info, sizeof(FILESTATUS3)); + + return ((rc == NO_ERROR) && (Info.attrFile & FILE_DIRECTORY)) || + (rc == ERROR_SHARING_VIOLATION); + // If we got a sharing violation, there must be something with this name. #else // !__WIN32__ wxStructStat st; @@ -1245,9 +1288,8 @@ bool wxDirExists(const wxChar *pszPathName) // Get a temporary filename, opening and closing the file. wxChar *wxGetTempFileName(const wxString& prefix, wxChar *buf) { -#if wxUSE_FILE - wxString filename = wxFileName::CreateTempFileName(prefix); - if ( filename.empty() ) + wxString filename; + if ( !wxGetTempFileName(prefix, filename) ) return NULL; if ( buf ) @@ -1256,19 +1298,20 @@ wxChar *wxGetTempFileName(const wxString& prefix, wxChar *buf) buf = MYcopystring(filename); return buf; -#else - wxUnusedVar(prefix); - wxUnusedVar(buf); - // wxFileName::CreateTempFileName needs wxFile class enabled - return NULL; -#endif } bool wxGetTempFileName(const wxString& prefix, wxString& buf) { - buf = wxGetTempFileName(prefix); +#if wxUSE_FILE + buf = wxFileName::CreateTempFileName(prefix); return !buf.empty(); +#else // !wxUSE_FILE + wxUnusedVar(prefix); + wxUnusedVar(buf); + + return false; +#endif // wxUSE_FILE/!wxUSE_FILE } // Get first file name matching given wild card. @@ -1331,18 +1374,22 @@ wxString wxFindNextFile() // Get current working directory. -// If buf is NULL, allocates space using new, else -// copies into buf. -wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) +// If buf is NULL, allocates space using new, else copies into buf. +// wxGetWorkingDirectory() is obsolete, use wxGetCwd() +// wxDoGetCwd() is their common core to be moved +// to wxGetCwd() once wxGetWorkingDirectory() will be removed. +// Do not expose wxDoGetCwd in headers! + +wxChar *wxDoGetCwd(wxChar *buf, int sz) { #if defined(__WXPALMOS__) - // TODO ? - return NULL; + // TODO + if(buf && sz>0) buf[0] = _T('\0'); + return buf; #elif defined(__WXWINCE__) // TODO - wxUnusedVar(buf); - wxUnusedVar(sz); - return NULL; + if(buf && sz>0) buf[0] = _T('\0'); + return buf; #else if ( !buf ) { @@ -1359,16 +1406,12 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) bool needsANSI = true; #if !defined(HAVE_WGETCWD) || wxUSE_UNICODE_MSLU - // This is not legal code as the compiler - // is allowed destroy the wxCharBuffer. - // wxCharBuffer c_buffer(sz); - // char *cbuf = (char*)(const char*)c_buffer; char cbuf[_MAXPATHLEN]; #endif #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 @@ -1406,7 +1449,7 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) ,cbuf + 3 ,(PULONG)&sz ); - cbuf[0] = 'A' + (ulDriveNum - 1); + cbuf[0] = char('A' + (ulDriveNum - 1)); cbuf[1] = ':'; cbuf[2] = '\\'; ok = rc == 0; @@ -1448,7 +1491,13 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) #if defined( __CYGWIN__ ) && defined( __WINDOWS__ ) // another example of DOS/Unix mix (Cygwin) wxString pathUnix = buf; +#if wxUSE_UNICODE + char bufA[_MAXPATHLEN]; + cygwin_conv_to_full_win32_path(pathUnix.mb_str(wxConvFile), bufA); + wxConvFile.MB2WC(buf, bufA, sz); +#else cygwin_conv_to_full_win32_path(pathUnix, buf); +#endif // wxUSE_UNICODE #endif // __CYGWIN__ } @@ -1462,13 +1511,17 @@ wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) // __WXWINCE__ } -wxString wxGetCwd() +#if WXWIN_COMPATIBILITY_2_6 +wxChar *wxGetWorkingDirectory(wxChar *buf, int sz) { - wxChar *buffer = new wxChar[_MAXPATHLEN]; - wxGetWorkingDirectory(buffer, _MAXPATHLEN); - wxString str( buffer ); - delete [] buffer; + return wxDoGetCwd(buf,sz); +} +#endif // WXWIN_COMPATIBILITY_2_6 +wxString wxGetCwd() +{ + wxString str; + wxDoGetCwd(wxStringBuffer(str, _MAXPATHLEN), _MAXPATHLEN); return str; } @@ -1592,48 +1645,19 @@ void WXDLLEXPORT wxSplitPath(const wxChar *pszFileName, wxFileName::SplitPath(pszFileName, pstrPath, pstrName, pstrExt); } +#if wxUSE_DATETIME + time_t WXDLLEXPORT wxFileModificationTime(const wxString& filename) { -#if defined(__WXPALMOS__) - return 0; -#elif defined(__WXWINCE__) - FILETIME ftLastWrite; - AutoHANDLE hFile(::CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, - NULL, 0, FILE_ATTRIBUTE_NORMAL, 0)); - - if ( !hFile.IsOk() ) - return 0; - - if ( !::GetFileTime(hFile, NULL, NULL, &ftLastWrite) ) - return 0; - - // sure we want to translate to local time here? - FILETIME ftLocal; - if ( !::FileTimeToLocalFileTime(&ftLastWrite, &ftLocal) ) - { - wxLogLastError(_T("FileTimeToLocalFileTime")); - } - - // FILETIME is a counted in 100-ns since 1601-01-01, convert it to - // number of seconds since 1970-01-01 - ULARGE_INTEGER uli; - uli.LowPart = ftLocal.dwLowDateTime; - uli.HighPart = ftLocal.dwHighDateTime; + wxDateTime mtime; + if ( !wxFileName(filename).GetTimes(NULL, &mtime, NULL) ) + return (time_t)-1; - ULONGLONG ull = uli.QuadPart; - ull /= wxULL(10000000); // number of 100ns intervals in 1s - ull -= wxULL(11644473600); // 1970-01-01 - 1601-01-01 in seconds - - return wx_static_cast(time_t, ull); -#else - wxStructStat buf; - if ( wxStat( filename, &buf) != 0 ) - return 0; - - return buf.st_mtime; -#endif + return mtime.GetTicks(); } +#endif // wxUSE_DATETIME + // Parses the filterStr, returning the number of filters. // Returns 0 if none or if there's a problem. @@ -1746,6 +1770,82 @@ int WXDLLEXPORT wxParseCommonDialogsFilter(const wxString& filterStr, 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 + wxUnusedVar(path); + // 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 + wxUnusedVar(path); + // 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 + wxUnusedVar(path); + // TODO + return false; +#endif +} + //------------------------------------------------------------------------ // wild character routines @@ -1773,127 +1873,109 @@ bool wxIsWild( const wxString& pattern ) * Written By Douglas A. Lewis * * The match procedure is public domain code (from ircII's reg.c) +* but modified to suit our tastes (RN: No "%" syntax I guess) */ bool wxMatchWild( const wxString& pat, const wxString& text, bool dot_special ) { - if (text.empty()) + if (text.empty()) + { + /* Match if both are empty. */ + return pat.empty(); + } + + const wxChar *m = pat.c_str(), + *n = text.c_str(), + *ma = NULL, + *na = NULL; + int just = 0, + acount = 0, + count = 0; + + if (dot_special && (*n == wxT('.'))) + { + /* Never match so that hidden Unix files + * are never found. */ + return false; + } + + for (;;) + { + if (*m == wxT('*')) { - /* Match if both are empty. */ - return pat.empty(); + ma = ++m; + na = n; + just = 1; + acount = count; } - - const wxChar *m = pat.c_str(), - *n = text.c_str(), - *ma = NULL, - *na = NULL, - *mp = NULL, - *np = NULL; - int just = 0, - pcount = 0, - acount = 0, - count = 0; - - if (dot_special && (*n == wxT('.'))) + else if (*m == wxT('?')) { - /* Never match so that hidden Unix files - * are never found. */ + m++; + if (!*n++) return false; } - - for (;;) + else { - if (*m == wxT('*')) - { - ma = ++m; - na = n; - just = 1; - mp = NULL; - acount = count; - } - else if (*m == wxT('?')) + if (*m == wxT('\\')) + { + m++; + /* Quoting "nothing" is a bad thing */ + if (!*m) + return false; + } + if (!*m) + { + /* + * If we are out of both strings or we just + * saw a wildcard, then we can say we have a + * match + */ + if (!*n) + return true; + if (just) + return true; + just = 0; + goto not_matched; + } + /* + * We could check for *n == NULL at this point, but + * since it's more common to have a character there, + * check to see if they match first (m and n) and + * then if they don't match, THEN we can check for + * the NULL of n + */ + just = 0; + if (*m == *n) + { + m++; + count++; + n++; + } + else + { + + not_matched: + + /* + * If there are no more characters in the + * string, but we still need to find another + * character (*m != NULL), then it will be + * impossible to match it + */ + if (!*n) + return false; + + if (ma) { - m++; - if (!*n++) - return false; + m = ma; + n = ++na; + count = acount; } else - { - if (*m == wxT('\\')) - { - m++; - /* Quoting "nothing" is a bad thing */ - if (!*m) - return false; - } - if (!*m) - { - /* - * If we are out of both strings or we just - * saw a wildcard, then we can say we have a - * match - */ - if (!*n) - return true; - if (just) - return true; - just = 0; - goto not_matched; - } - /* - * We could check for *n == NULL at this point, but - * since it's more common to have a character there, - * check to see if they match first (m and n) and - * then if they don't match, THEN we can check for - * the NULL of n - */ - just = 0; - if (*m == *n) - { - m++; - if (*n == wxT(' ')) - mp = NULL; - count++; - n++; - } - else - { - - not_matched: - - /* - * If there are no more characters in the - * string, but we still need to find another - * character (*m != NULL), then it will be - * impossible to match it - */ - if (!*n) - return false; - if (mp) - { - m = mp; - if (*np == wxT(' ')) - { - mp = NULL; - goto check_percent; - } - n = ++np; - count = pcount; - } - else - check_percent: - - if (ma) - { - m = ma; - n = ++na; - count = acount; - } - else - return false; - } - } + return false; + } } + } } // Return the type of an open file @@ -1959,12 +2041,11 @@ wxFileKind wxGetFileKind(FILE *fp) { // Note: The watcom rtl dll doesn't have fileno (the static lib does). // Should be fixed in version 1.4. -#if defined(wxFILEKIND_STUB) || \ - (defined(__WATCOMC__) && __WATCOMC__ <= 1230 && defined(__SW_BR)) +#if defined(wxFILEKIND_STUB) || wxONLY_WATCOM_EARLIER_THAN(1,4) (void)fp; return wxFILE_KIND_DISK; #else - return wxGetFileKind(fileno(fp)); + return fp ? wxGetFileKind(fileno(fp)) : wxFILE_KIND_UNKNOWN; #endif }