X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/26eef30437813056c86e5c7516995ff05e65cae3..a43a9e5521440dbb28037646ed4a07125c8823a9:/src/common/filename.cpp diff --git a/src/common/filename.cpp b/src/common/filename.cpp index ee7e4d412a..f16ae7127b 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -83,6 +83,7 @@ #include "wx/tokenzr.h" #include "wx/config.h" // for wxExpandEnvVars #include "wx/dynlib.h" +#include "wx/dir.h" #if defined(__WIN32__) && defined(__MINGW32__) #include "wx/msw/gccpriv.h" @@ -161,7 +162,7 @@ public: Write }; - wxFileHandle(const wxString& filename, OpenMode mode) + wxFileHandle(const wxString& filename, OpenMode mode, int flags = 0) { m_hFile = ::CreateFile ( @@ -172,7 +173,7 @@ public: FILE_SHARE_WRITE, // (allow everything) NULL, // no secutity attr OPEN_EXISTING, // creation disposition - 0, // no flags + flags, // flags NULL // no template file ); @@ -471,9 +472,8 @@ void wxFileName::Assign(const wxString& fullpathOrig, wxString volume, path, name, ext; bool hasExt; - // do some consistency checks in debug mode: the name should be really just - // the filename and the path should be really just a path -#ifdef __WXDEBUG__ + // do some consistency checks: the name should be really just the filename + // and the path should be really just a path wxString volDummy, pathDummy, nameDummy, extDummy; SplitPath(fullname, &volDummy, &pathDummy, &name, &ext, &hasExt, format); @@ -486,12 +486,6 @@ void wxFileName::Assign(const wxString& fullpathOrig, wxASSERT_MSG( nameDummy.empty() && extDummy.empty(), _T("the path shouldn't contain file name nor extension") ); -#else // !__WXDEBUG__ - SplitPath(fullname, NULL /* no volume */, NULL /* no path */, - &name, &ext, &hasExt, format); - SplitPath(fullpath, &volume, &path, NULL, NULL, format); -#endif // __WXDEBUG__/!__WXDEBUG__ - Assign(volume, path, name, ext, hasExt, format); } @@ -1026,55 +1020,55 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFFile *fileTemp) // directory operations // ---------------------------------------------------------------------------- +// helper of GetTempDir(): check if the given directory exists and return it if +// it does or an empty string otherwise +namespace +{ + +wxString CheckIfDirExists(const wxString& dir) +{ + return wxFileName::DirExists(dir) ? dir : wxString(); +} + +} // anonymous namespace + wxString wxFileName::GetTempDir() { - wxString dir; - dir = wxGetenv(_T("TMPDIR")); - if (dir.empty()) + // first try getting it from environment: this allows overriding the values + // used by default if the user wants to create temporary files in another + // directory + wxString dir = CheckIfDirExists(wxGetenv("TMPDIR")); + if ( dir.empty() ) { - dir = wxGetenv(_T("TMP")); - if (dir.empty()) - { - dir = wxGetenv(_T("TEMP")); - } + dir = CheckIfDirExists(wxGetenv("TMP")); + if ( dir.empty() ) + dir = CheckIfDirExists(wxGetenv("TEMP")); } -#if defined(__WXWINCE__) - if (dir.empty()) - { - // FIXME. Create \temp dir? - if (DirExists(wxT("\\temp"))) - dir = wxT("\\temp"); - } -#elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) - + // if no environment variables are set, use the system default if ( dir.empty() ) { +#if defined(__WXWINCE__) + dir = CheckIfDirExists(wxT("\\temp")); +#elif defined(__WINDOWS__) && !defined(__WXMICROWIN__) if ( !::GetTempPath(MAX_PATH, wxStringBuffer(dir, MAX_PATH + 1)) ) { wxLogLastError(_T("GetTempPath")); } - - if ( dir.empty() ) - { - // GetTempFileName() fails if we pass it an empty string - dir = _T('.'); - } +#elif defined(__WXMAC__) && wxOSX_USE_CARBON + dir = wxMacFindFolder(short(kOnSystemDisk), kTemporaryFolderType, kCreateFolder); +#endif // systems with native way } -#else // !Windows + // fall back to hard coded value if ( dir.empty() ) { - // default -#if defined(__DOS__) || defined(__OS2__) - dir = _T("."); -#elif defined(__WXMAC__) && wxOSX_USE_CARBON - dir = wxMacFindFolder(short(kOnSystemDisk), kTemporaryFolderType, kCreateFolder); -#else - dir = _T("/tmp"); -#endif +#ifdef __UNIX_LIKE__ + dir = CheckIfDirExists("/tmp"); + if ( dir.empty() ) +#endif // __UNIX_LIKE__ + dir = "."; } -#endif return dir; } @@ -1123,14 +1117,83 @@ bool wxFileName::Mkdir( const wxString& dir, int perm, int flags ) return ::wxMkdir( dir, perm ); } -bool wxFileName::Rmdir() +bool wxFileName::Rmdir(int flags) { - return wxFileName::Rmdir( GetPath() ); + return wxFileName::Rmdir( GetPath(), flags ); } -bool wxFileName::Rmdir( const wxString &dir ) +bool wxFileName::Rmdir(const wxString& dir, int flags) { - return ::wxRmdir( dir ); +#ifdef __WXMSW__ + if ( flags & wxPATH_RMDIR_RECURSIVE ) + { + // SHFileOperation needs double null termination string + // but without separator at the end of the path + wxString path(dir); + if ( path.Last() == wxFILE_SEP_PATH ) + path.RemoveLast(); + path += _T('\0'); + + SHFILEOPSTRUCT fileop; + wxZeroMemory(fileop); + fileop.wFunc = FO_DELETE; + fileop.pFrom = path.fn_str(); + fileop.fFlags = FOF_SILENT | FOF_NOCONFIRMATION; + #ifndef __WXWINCE__ + // FOF_NOERRORUI is not defined in WinCE + fileop.fFlags |= FOF_NOERRORUI; + #endif + + int ret = SHFileOperation(&fileop); + if ( ret != 0 ) + { + // SHFileOperation may return non-Win32 error codes, so the error + // message can be incorrect + wxLogApiError(_T("SHFileOperation"), ret); + return false; + } + + return true; + } + else if ( flags & wxPATH_RMDIR_FULL ) +#else // !__WXMSW__ + if ( flags != 0 ) // wxPATH_RMDIR_FULL or wxPATH_RMDIR_RECURSIVE +#endif // !__WXMSW__ + { + wxString path(dir); + if ( path.Last() != wxFILE_SEP_PATH ) + path += wxFILE_SEP_PATH; + + wxDir d(path); + + if ( !d.IsOpened() ) + return false; + + wxString filename; + + // first delete all subdirectories + bool cont = d.GetFirst(&filename, "", wxDIR_DIRS | wxDIR_HIDDEN); + while ( cont ) + { + wxFileName::Rmdir(path + filename, flags); + cont = d.GetNext(&filename); + } + +#ifndef __WXMSW__ + if ( flags & wxPATH_RMDIR_RECURSIVE ) + { + // delete all files too + cont = d.GetFirst(&filename, "", wxDIR_FILES | wxDIR_HIDDEN); + while ( cont ) + { + ::wxRemoveFile(path + filename); + cont = d.GetNext(&filename); + } + } +#endif // !__WXMSW__ + } + + return ::wxRmdir(dir); } // ---------------------------------------------------------------------------- @@ -1152,7 +1215,6 @@ bool wxFileName::Normalize(int flags, } } - // the existing path components wxArrayString dirs = GetDirs(); @@ -1302,6 +1364,49 @@ bool wxFileName::Normalize(int flags, return true; } +#ifndef __WXWINCE__ +bool wxFileName::ReplaceEnvVariable(const wxString& envname, + const wxString& replacementFmtString, + wxPathFormat format) +{ + // look into stringForm for the contents of the given environment variable + wxString val; + if (envname.empty() || + !wxGetEnv(envname, &val)) + return false; + if (val.empty()) + return false; + + wxString stringForm = GetPath(wxPATH_GET_VOLUME, format); + // do not touch the file name and the extension + + wxString replacement = wxString::Format(replacementFmtString, envname); + stringForm.Replace(val, replacement); + + // Now assign ourselves the modified path: + Assign(stringForm, GetFullName(), format); + + return true; +} +#endif + +bool wxFileName::ReplaceHomeDir(wxPathFormat format) +{ + wxString homedir = wxGetHomeDir(); + if (homedir.empty()) + return false; + + wxString stringForm = GetPath(wxPATH_GET_VOLUME, format); + // do not touch the file name and the extension + + stringForm.Replace(homedir, "~"); + + // Now assign ourselves the modified path: + Assign(stringForm, GetFullName(), format); + + return true; +} + // ---------------------------------------------------------------------------- // get the shortcut target // ---------------------------------------------------------------------------- @@ -1331,7 +1436,7 @@ bool wxFileName::GetShortcutTarget(const wxString& shortcutPath, wxString* arguments) { wxString path, file, ext; - wxSplitPath(shortcutPath, & path, & file, & ext); + wxFileName::SplitPath(shortcutPath, & path, & file, & ext); HRESULT hres; IShellLink* psl; @@ -1896,19 +2001,21 @@ wxString wxFileName::GetLongPath() const size_t count = dirs.GetCount(); for ( size_t i = 0; i < count; i++ ) { + const wxString& dir = dirs[i]; + // We're using pathOut to collect the long-name path, but using a // temporary for appending the last path component which may be // short-name - tmpPath = pathOut + dirs[i]; - - if ( tmpPath.empty() ) - continue; - - // can't see this being necessary? MF - if ( tmpPath.Last() == GetVolumeSeparator(wxPATH_DOS) ) + tmpPath = pathOut + dir; + + // We must not process "." or ".." here as they would be (unexpectedly) + // replaced by the corresponding directory names so just leave them + // alone + // + // And we can't pass a drive and root dir to FindFirstFile (VZ: why?) + if ( tmpPath.empty() || dir == '.' || dir == ".." || + tmpPath.Last() == GetVolumeSeparator(wxPATH_DOS) ) { - // Can't pass a drive and root dir to FindFirstFile, - // so continue to next dir tmpPath += wxFILE_SEP_PATH; pathOut = tmpPath; continue; @@ -1953,6 +2060,23 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format ) return format; } +#ifdef wxHAS_FILESYSTEM_VOLUMES + +/* static */ +wxString wxFileName::GetVolumeString(char drive, int flags) +{ + wxASSERT_MSG( !(flags & ~wxPATH_GET_SEPARATOR), "invalid flag specified" ); + + wxString vol(drive); + vol += wxFILE_SEP_DSK; + if ( flags & wxPATH_GET_SEPARATOR ) + vol += wxFILE_SEP_PATH; + + return vol; +} + +#endif // wxHAS_FILESYSTEM_VOLUMES + // ---------------------------------------------------------------------------- // path splitting function // ---------------------------------------------------------------------------- @@ -2137,6 +2261,14 @@ void wxFileName::SplitPath(const wxString& fullpath, } } +/* static */ +wxString wxFileName::StripExtension(const wxString& fullpath) +{ + wxFileName fn(fullpath); + fn.SetExt(""); + return fn.GetFullPath(); +} + // ---------------------------------------------------------------------------- // time functions // ---------------------------------------------------------------------------- @@ -2148,32 +2280,44 @@ bool wxFileName::SetTimes(const wxDateTime *dtAccess, const wxDateTime *dtCreate) { #if defined(__WIN32__) + FILETIME ftAccess, ftCreate, ftWrite; + + if ( dtCreate ) + ConvertWxToFileTime(&ftCreate, *dtCreate); + if ( dtAccess ) + ConvertWxToFileTime(&ftAccess, *dtAccess); + if ( dtMod ) + ConvertWxToFileTime(&ftWrite, *dtMod); + + wxString path; + int flags; if ( IsDir() ) { - // VZ: please let me know how to do this if you can - wxFAIL_MSG( _T("SetTimes() not implemented for the directories") ); + if ( wxGetOsVersion() == wxOS_WINDOWS_9X ) + { + wxLogError(_("Setting directory access times is not supported " + "under this OS version")); + return false; + } + + path = GetPath(); + flags = FILE_FLAG_BACKUP_SEMANTICS; } else // file { - wxFileHandle fh(GetFullPath(), wxFileHandle::Write); - if ( fh.IsOk() ) - { - FILETIME ftAccess, ftCreate, ftWrite; - - if ( dtCreate ) - ConvertWxToFileTime(&ftCreate, *dtCreate); - if ( dtAccess ) - ConvertWxToFileTime(&ftAccess, *dtAccess); - if ( dtMod ) - ConvertWxToFileTime(&ftWrite, *dtMod); + path = GetFullPath(); + flags = 0; + } - if ( ::SetFileTime(fh, - dtCreate ? &ftCreate : NULL, - dtAccess ? &ftAccess : NULL, - dtMod ? &ftWrite : NULL) ) - { - return true; - } + wxFileHandle fh(path, wxFileHandle::Write, flags); + if ( fh.IsOk() ) + { + if ( ::SetFileTime(fh, + dtCreate ? &ftCreate : NULL, + dtAccess ? &ftAccess : NULL, + dtMod ? &ftWrite : NULL) ) + { + return true; } } #elif defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__)) @@ -2385,52 +2529,51 @@ wxString wxFileName::GetHumanReadableSize(const wxString &failmsg, int precision #if defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON -const short kMacExtensionMaxLength = 16 ; +namespace +{ + class MacDefaultExtensionRecord { -public : - MacDefaultExtensionRecord() - { - m_ext[0] = 0 ; - m_type = m_creator = 0 ; - } - MacDefaultExtensionRecord( const MacDefaultExtensionRecord& from ) - { - wxStrcpy( m_ext , from.m_ext ) ; - m_type = from.m_type ; - m_creator = from.m_creator ; - } - MacDefaultExtensionRecord( const wxChar * extension , OSType type , OSType creator ) - { - wxStrncpy( m_ext , extension , kMacExtensionMaxLength ) ; - m_ext[kMacExtensionMaxLength] = 0 ; - m_type = type ; - m_creator = creator ; - } - wxChar m_ext[kMacExtensionMaxLength] ; - OSType m_type ; - OSType m_creator ; -} ; +public: + MacDefaultExtensionRecord() + { + m_type = + m_creator = 0 ; + } -WX_DECLARE_OBJARRAY(MacDefaultExtensionRecord, MacDefaultExtensionArray) ; + // default copy ctor, assignment operator and dtor are ok -bool gMacDefaultExtensionsInited = false ; + MacDefaultExtensionRecord(const wxString& ext, OSType type, OSType creator) + : m_ext(ext) + { + m_type = type; + m_creator = creator; + } + + wxString m_ext; + OSType m_type; + OSType m_creator; +}; + +WX_DECLARE_OBJARRAY(MacDefaultExtensionRecord, MacDefaultExtensionArray); + +bool gMacDefaultExtensionsInited = false; #include "wx/arrimpl.cpp" -WX_DEFINE_EXPORTED_OBJARRAY(MacDefaultExtensionArray) ; +WX_DEFINE_EXPORTED_OBJARRAY(MacDefaultExtensionArray); -MacDefaultExtensionArray gMacDefaultExtensions ; +MacDefaultExtensionArray gMacDefaultExtensions; // load the default extensions -MacDefaultExtensionRecord gDefaults[] = +const MacDefaultExtensionRecord gDefaults[] = { - MacDefaultExtensionRecord( wxT("txt") , 'TEXT' , 'ttxt' ) , - MacDefaultExtensionRecord( wxT("tif") , 'TIFF' , '****' ) , - MacDefaultExtensionRecord( wxT("jpg") , 'JPEG' , '****' ) , -} ; + MacDefaultExtensionRecord( "txt", 'TEXT', 'ttxt' ), + MacDefaultExtensionRecord( "tif", 'TIFF', '****' ), + MacDefaultExtensionRecord( "jpg", 'JPEG', '****' ), +}; -static void MacEnsureDefaultExtensionsLoaded() +void MacEnsureDefaultExtensionsLoaded() { if ( !gMacDefaultExtensionsInited ) { @@ -2439,10 +2582,12 @@ static void MacEnsureDefaultExtensionsLoaded() { gMacDefaultExtensions.Add( gDefaults[i] ) ; } - gMacDefaultExtensionsInited = true ; + gMacDefaultExtensionsInited = true; } } +} // anonymous namespace + bool wxFileName::MacSetTypeAndCreator( wxUint32 type , wxUint32 creator ) { FSRef fsRef ; @@ -2511,11 +2656,9 @@ bool wxFileName::MacFindDefaultTypeAndCreator( const wxString& ext , wxUint32 *t void wxFileName::MacRegisterDefaultTypeAndCreator( const wxString& ext , wxUint32 type , wxUint32 creator ) { - MacEnsureDefaultExtensionsLoaded() ; - MacDefaultExtensionRecord rec ; - rec.m_type = type ; - rec.m_creator = creator ; - wxStrncpy( rec.m_ext , ext.Lower().c_str() , kMacExtensionMaxLength ) ; - gMacDefaultExtensions.Add( rec ) ; + MacEnsureDefaultExtensionsLoaded(); + MacDefaultExtensionRecord rec(ext.Lower(), type, creator); + gMacDefaultExtensions.Add( rec ); } -#endif + +#endif // defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON