X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b494c48b31885ee0d9cd91e7931ac837e00144a0..15fa9a1f82dc8e17bc0dc0fc6d330f430650edfb:/src/common/filename.cpp diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 50329cd23a..12bc12daa7 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -60,10 +60,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "filename.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -72,15 +68,16 @@ #endif #ifndef WX_PRECOMP -#include "wx/intl.h" -#include "wx/log.h" -#include "wx/file.h" + #include "wx/dynarray.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/file.h" + #include "wx/utils.h" #endif #include "wx/filename.h" #include "wx/tokenzr.h" #include "wx/config.h" // for wxExpandEnvVars -#include "wx/utils.h" #include "wx/file.h" #include "wx/dynlib.h" @@ -300,12 +297,14 @@ void wxFileName::Assign( const wxFileName &filepath ) m_name = filepath.GetName(); m_ext = filepath.GetExt(); m_relative = filepath.m_relative; + m_hasExt = filepath.m_hasExt; } void wxFileName::Assign(const wxString& volume, const wxString& path, const wxString& name, const wxString& ext, + bool hasExt, wxPathFormat format ) { SetPath( path, format ); @@ -313,6 +312,8 @@ void wxFileName::Assign(const wxString& volume, m_volume = volume; m_ext = ext; m_name = name; + + m_hasExt = hasExt; } void wxFileName::SetPath( const wxString& pathOrig, wxPathFormat format ) @@ -411,9 +412,10 @@ void wxFileName::Assign(const wxString& fullpath, wxPathFormat format) { wxString volume, path, name, ext; - SplitPath(fullpath, &volume, &path, &name, &ext, format); + bool hasExt; + SplitPath(fullpath, &volume, &path, &name, &ext, &hasExt, format); - Assign(volume, path, name, ext, format); + Assign(volume, path, name, ext, hasExt, format); } void wxFileName::Assign(const wxString& fullpathOrig, @@ -429,15 +431,16 @@ 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__ - wxString pathDummy, nameDummy, extDummy; + wxString volDummy, pathDummy, nameDummy, extDummy; - SplitPath(fullname, &pathDummy, &name, &ext, format); + SplitPath(fullname, &volDummy, &pathDummy, &name, &ext, &hasExt, format); - wxASSERT_MSG( pathDummy.empty(), + wxASSERT_MSG( volDummy.empty() && pathDummy.empty(), _T("the file name shouldn't contain the path") ); SplitPath(fullpath, &volume, &path, &nameDummy, &extDummy, format); @@ -446,11 +449,12 @@ void wxFileName::Assign(const wxString& fullpathOrig, _T("the path shouldn't contain file name nor extension") ); #else // !__WXDEBUG__ - SplitPath(fullname, NULL /* no path */, &name, &ext, format); + 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, format); + Assign(volume, path, name, ext, hasExt, format); } void wxFileName::Assign(const wxString& pathOrig, @@ -480,6 +484,9 @@ void wxFileName::Clear() // we don't have any absolute path for now m_relative = true; + + // nor any extension + m_hasExt = false; } /* static */ @@ -512,7 +519,7 @@ bool wxFileName::FileExists( const wxString &file ) bool wxFileName::DirExists() const { - return wxFileName::DirExists( GetFullPath() ); + return wxFileName::DirExists( GetPath() ); } bool wxFileName::DirExists( const wxString &dir ) @@ -555,7 +562,7 @@ wxString wxFileName::GetCwd(const wxString& volume) bool wxFileName::SetCwd() { - return wxFileName::SetCwd( GetFullPath() ); + return wxFileName::SetCwd( GetPath() ); } bool wxFileName::SetCwd( const wxString &cwd ) @@ -573,6 +580,8 @@ wxString wxFileName::GetHomeDir() return ::wxGetHomeDir(); } +#if wxUSE_FILE + void wxFileName::AssignTempFileName(const wxString& prefix, wxFile *fileTemp) { wxString tempname = CreateTempFileName(prefix, fileTemp); @@ -596,17 +605,31 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) // use the directory specified by the prefix SplitPath(prefix, &dir, &name, NULL /* extension */); + if (dir.empty()) + { + dir = wxGetenv(_T("TMPDIR")); + if (dir.empty()) + { + dir = wxGetenv(_T("TMP")); + if (dir.empty()) + { + dir = wxGetenv(_T("TEMP")); + } + } + } + #if defined(__WXWINCE__) if (dir.empty()) { // FIXME. Create \temp dir? - dir = wxT("\\"); + if (DirExists(wxT("\\temp"))) + dir = wxT("\\temp"); } - path = dir + wxT("\\") + prefix; + path = dir + wxT("\\") + name; int i = 1; - while (wxFileExists(path)) + while (FileExists(path)) { - path = dir + wxT("\\") + prefix ; + path = dir + wxT("\\") + name ; path << i; i ++; } @@ -643,25 +666,14 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) #else // !Windows if ( dir.empty() ) { -#if defined(__WXMAC__) && !defined(__DARWIN__) - dir = wxMacFindFolder( (short) kOnSystemDisk, kTemporaryFolderType, kCreateFolder ) ; -#else // !Mac - dir = wxGetenv(_T("TMP")); - if ( dir.empty() ) - { - dir = wxGetenv(_T("TEMP")); - } - - if ( dir.empty() ) - { - // default - #if defined(__DOS__) || defined(__OS2__) - dir = _T("."); - #else - dir = _T("/tmp"); - #endif - } -#endif // Mac/!Mac + // default +#if defined(__DOS__) || defined(__OS2__) + dir = _T("."); +#elif defined(__WXMAC__) + dir = wxMacFindFolder(short(kOnSystemDisk), kTemporaryFolderType, kCreateFolder); +#else + dir = _T("/tmp"); +#endif } path = dir; @@ -720,7 +732,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) } #else // !HAVE_MKTEMP (includes __DOS__) // generate the unique file name ourselves - #if !defined(__DOS__) && (!defined(__MWERKS__) || defined(__DARWIN__) ) + #if !defined(__DOS__) && !defined(__PALMOS__) && (!defined(__MWERKS__) || defined(__DARWIN__) ) path << (unsigned int)getpid(); #endif @@ -731,7 +743,7 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) { // 3 hex digits is enough for numTries == 1000 < 4096 pathTry = path + wxString::Format(_T("%.03x"), (unsigned int) n); - if ( !wxFile::Exists(pathTry) ) + if ( !FileExists(pathTry) ) { break; } @@ -742,9 +754,6 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) path = pathTry; #endif // HAVE_MKTEMP/!HAVE_MKTEMP - if ( !path.empty() ) - { - } #endif // HAVE_MKSTEMP/!HAVE_MKSTEMP #endif // Windows/!Windows @@ -782,13 +791,15 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp) return path; } +#endif // wxUSE_FILE + // ---------------------------------------------------------------------------- // directory operations // ---------------------------------------------------------------------------- bool wxFileName::Mkdir( int perm, int flags ) { - return wxFileName::Mkdir( GetFullPath(), perm, flags ); + return wxFileName::Mkdir(GetPath(), perm, flags); } bool wxFileName::Mkdir( const wxString& dir, int perm, int flags ) @@ -839,7 +850,7 @@ bool wxFileName::Mkdir( const wxString& dir, int perm, int flags ) bool wxFileName::Rmdir() { - return wxFileName::Rmdir( GetFullPath() ); + return wxFileName::Rmdir( GetPath() ); } bool wxFileName::Rmdir( const wxString &dir ) @@ -1042,7 +1053,7 @@ bool wxFileName::GetShortcutTarget(const wxString& shortcutPath, wxString& targe bool success = false; // Assume it's not a shortcut if it doesn't end with lnk - if (ext.Lower() != wxT("lnk")) + if (ext.CmpNoCase(wxT("lnk"))!=0) return false; // create a ShellLink object @@ -1229,8 +1240,11 @@ wxString wxFileName::GetForbiddenChars(wxPathFormat format) } /* static */ -wxString wxFileName::GetVolumeSeparator(wxPathFormat format) +wxString wxFileName::GetVolumeSeparator(wxPathFormat WXUNUSED_IN_WINCE(format)) { +#ifdef __WXWINCE__ + return wxEmptyString; +#else wxString sepVol; if ( (GetFormat(format) == wxPATH_DOS) || @@ -1241,6 +1255,7 @@ wxString wxFileName::GetVolumeSeparator(wxPathFormat format) //else: leave empty return sepVol; +#endif } /* static */ @@ -1320,26 +1335,26 @@ bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format) return true; } -void wxFileName::AppendDir( const wxString &dir ) +void wxFileName::AppendDir( const wxString& dir ) { if ( IsValidDirComponent(dir) ) m_dirs.Add( dir ); } -void wxFileName::PrependDir( const wxString &dir ) +void wxFileName::PrependDir( const wxString& dir ) { InsertDir(0, dir); } -void wxFileName::InsertDir( int before, const wxString &dir ) +void wxFileName::InsertDir(size_t before, const wxString& dir) { if ( IsValidDirComponent(dir) ) - m_dirs.Insert( dir, before ); + m_dirs.Insert(dir, before); } -void wxFileName::RemoveDir( int pos ) +void wxFileName::RemoveDir(size_t pos) { - m_dirs.RemoveAt( (size_t)pos ); + m_dirs.RemoveAt(pos); } // ---------------------------------------------------------------------------- @@ -1348,13 +1363,14 @@ void wxFileName::RemoveDir( int pos ) void wxFileName::SetFullName(const wxString& fullname) { - SplitPath(fullname, NULL /* no path */, &m_name, &m_ext); + SplitPath(fullname, NULL /* no volume */, NULL /* no path */, + &m_name, &m_ext, &m_hasExt); } wxString wxFileName::GetFullName() const { wxString fullname = m_name; - if ( !m_ext.empty() ) + if ( m_hasExt ) { fullname << wxFILE_SEP_EXT << m_ext; } @@ -1438,7 +1454,7 @@ wxString wxFileName::GetPath( int flags, wxPathFormat format ) const } // convert back from ".." to nothing - if ( m_dirs[i] != wxT("..") ) + if ( !m_dirs[i].IsSameAs(wxT("..")) ) fullpath += m_dirs[i]; break; @@ -1455,7 +1471,7 @@ wxString wxFileName::GetPath( int flags, wxPathFormat format ) const // TODO: What to do with ".." under VMS // convert back from ".." to nothing - if ( m_dirs[i] != wxT("..") ) + if ( !m_dirs[i].IsSameAs(wxT("..")) ) fullpath += m_dirs[i]; break; } @@ -1487,27 +1503,26 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const // Return the short form of the path (returns identity on non-Windows platforms) wxString wxFileName::GetShortPath() const { -#if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) wxString path(GetFullPath()); - wxString pathOut; + +#if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) DWORD sz = ::GetShortPathName(path, NULL, 0); - bool ok = sz != 0; - if ( ok ) + if ( sz != 0 ) { - ok = ::GetShortPathName + wxString pathOut; + if ( ::GetShortPathName ( path, wxStringBuffer(pathOut, sz), sz - ) != 0; + ) != 0 ) + { + return pathOut; + } } - if (ok) - return pathOut; +#endif // Windows return path; -#else - return GetFullPath(); -#endif } // Return the long form of the path (returns identity on non-Windows platforms) @@ -1517,116 +1532,115 @@ wxString wxFileName::GetLongPath() const path = GetFullPath(); #if defined(__WIN32__) && !defined(__WXMICROWIN__) - bool success = false; #if wxUSE_DYNAMIC_LOADER typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD); - static bool s_triedToLoad = false; - - if ( !s_triedToLoad ) + // this is MT-safe as in the worst case we're going to resolve the function + // twice -- but as the result is the same in both threads, it's ok + static GET_LONG_PATH_NAME s_pfnGetLongPathName = NULL; + if ( !s_pfnGetLongPathName ) { - // suppress the errors about missing GetLongPathName[AW] - wxLogNull noLog; + static bool s_triedToLoad = false; - s_triedToLoad = true; - wxDynamicLibrary dllKernel(_T("kernel32")); - if ( dllKernel.IsLoaded() ) + if ( !s_triedToLoad ) { - // may succeed or fail depending on the Windows version - static GET_LONG_PATH_NAME s_pfnGetLongPathName = NULL; -#ifdef _UNICODE - s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameW")); -#else - s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameA")); -#endif + s_triedToLoad = true; - if ( s_pfnGetLongPathName ) - { - DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0); - bool ok = dwSize > 0; + wxDynamicLibrary dllKernel(_T("kernel32")); - if ( ok ) - { - DWORD sz = (*s_pfnGetLongPathName)(path, NULL, 0); - ok = sz != 0; - if ( ok ) - { - ok = (*s_pfnGetLongPathName) - ( - path, - wxStringBuffer(pathOut, sz), - sz - ) != 0; - success = true; - } - } + const wxChar* GetLongPathName = _T("GetLongPathName") +#if wxUSE_UNICODE + _T("W"); +#else // ANSI + _T("A"); +#endif // Unicode/ANSI + + if ( dllKernel.HasSymbol(GetLongPathName) ) + { + s_pfnGetLongPathName = (GET_LONG_PATH_NAME) + dllKernel.GetSymbol(GetLongPathName); } + + // note that kernel32.dll can be unloaded, it stays in memory + // anyhow as all Win32 programs link to it and so it's safe to call + // GetLongPathName() even after unloading it } } - if (success) - return pathOut; + if ( s_pfnGetLongPathName ) + { + DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0); + if ( dwSize > 0 ) + { + if ( (*s_pfnGetLongPathName) + ( + path, + wxStringBuffer(pathOut, dwSize), + dwSize + ) != 0 ) + { + return pathOut; + } + } + } #endif // wxUSE_DYNAMIC_LOADER - if (!success) - { - // The OS didn't support GetLongPathName, or some other error. - // We need to call FindFirstFile on each component in turn. + // The OS didn't support GetLongPathName, or some other error. + // We need to call FindFirstFile on each component in turn. - WIN32_FIND_DATA findFileData; - HANDLE hFind; + WIN32_FIND_DATA findFileData; + HANDLE hFind; - if ( HasVolume() ) - pathOut = GetVolume() + - GetVolumeSeparator(wxPATH_DOS) + - GetPathSeparator(wxPATH_DOS); - else - pathOut = wxEmptyString; + if ( HasVolume() ) + pathOut = GetVolume() + + GetVolumeSeparator(wxPATH_DOS) + + GetPathSeparator(wxPATH_DOS); + else + pathOut = wxEmptyString; - wxArrayString dirs = GetDirs(); - dirs.Add(GetFullName()); + wxArrayString dirs = GetDirs(); + dirs.Add(GetFullName()); - wxString tmpPath; + wxString tmpPath; - size_t count = dirs.GetCount(); - for ( size_t i = 0; i < count; 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]; + size_t count = dirs.GetCount(); + for ( size_t i = 0; i < count; 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; + if ( tmpPath.empty() ) + continue; - // can't see this being necessary? MF - if ( 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; - } + // can't see this being necessary? MF + if ( 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; + } - hFind = ::FindFirstFile(tmpPath, &findFileData); - if (hFind == INVALID_HANDLE_VALUE) - { - // Error: most likely reason is that path doesn't exist, so - // append any unprocessed parts and return - for ( i += 1; i < count; i++ ) - tmpPath += wxFILE_SEP_PATH + dirs[i]; + hFind = ::FindFirstFile(tmpPath, &findFileData); + if (hFind == INVALID_HANDLE_VALUE) + { + // Error: most likely reason is that path doesn't exist, so + // append any unprocessed parts and return + for ( i += 1; i < count; i++ ) + tmpPath += wxFILE_SEP_PATH + dirs[i]; - return tmpPath; - } + return tmpPath; + } - pathOut += findFileData.cFileName; - if ( (i < (count-1)) ) - pathOut += wxFILE_SEP_PATH; + pathOut += findFileData.cFileName; + if ( (i < (count-1)) ) + pathOut += wxFILE_SEP_PATH; - ::FindClose(hFind); - } + ::FindClose(hFind); } #else // !Win32 pathOut = path; @@ -1716,6 +1730,7 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, wxString *pstrPath, wxString *pstrName, wxString *pstrExt, + bool *hasExt, wxPathFormat format) { format = GetFormat(format); @@ -1802,18 +1817,25 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume, *pstrName = fullpath.Mid(nStart, count); } - if ( pstrExt ) + // finally deal with the extension here: we have an added complication that + // extension may be empty (but present) as in "foo." where trailing dot + // indicates the empty extension at the end -- and hence we must remember + // that we have it independently of pstrExt + if ( posLastDot == wxString::npos ) { - if ( posLastDot == wxString::npos ) - { - // no extension - pstrExt->Empty(); - } - else - { - // take everything after the dot + // no extension + if ( pstrExt ) + pstrExt->clear(); + if ( hasExt ) + *hasExt = false; + } + else + { + // take everything after the dot + if ( pstrExt ) *pstrExt = fullpath.Mid(posLastDot + 1); - } + if ( hasExt ) + *hasExt = true; } } @@ -1873,6 +1895,8 @@ bool wxFileName::SetTimes(const wxDateTime *dtAccess, } } #elif defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__)) + wxUnusedVar(dtCreate); + if ( !dtAccess && !dtMod ) { // can't modify the creation time anyhow, don't try @@ -1889,6 +1913,9 @@ bool wxFileName::SetTimes(const wxDateTime *dtAccess, return true; } #else // other platform + wxUnusedVar(dtAccess); + wxUnusedVar(dtMod); + wxUnusedVar(dtCreate); #endif // platforms wxLogSysError(_("Failed to modify file times for '%s'"), @@ -1965,7 +1992,7 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, return true; } -#elif defined(__UNIX_LIKE__) || defined(__WXMAC__) || (defined(__DOS__) && defined(__WATCOMC__)) +#elif defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__OS2__) || (defined(__DOS__) && defined(__WATCOMC__)) wxStructStat stBuf; if ( wxStat( GetFullPath().c_str(), &stBuf) == 0 ) { @@ -1979,6 +2006,9 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, return true; } #else // other platform + wxUnusedVar(dtAccess); + wxUnusedVar(dtMod); + wxUnusedVar(dtCreate); #endif // platforms wxLogSysError(_("Failed to retrieve file times for '%s'"), @@ -1998,7 +2028,7 @@ public : MacDefaultExtensionRecord() { m_ext[0] = 0 ; - m_type = m_creator = NULL ; + m_type = m_creator = 0 ; } MacDefaultExtensionRecord( const MacDefaultExtensionRecord& from ) { @@ -2018,7 +2048,6 @@ public : OSType m_creator ; } ; -#include "wx/dynarray.h" WX_DECLARE_OBJARRAY(MacDefaultExtensionRecord, MacDefaultExtensionArray) ; bool gMacDefaultExtensionsInited = false ;