]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filename.cpp
removed the strange __WXMSW__ test in AddFile(bitmap) -- why should this function...
[wxWidgets.git] / src / common / filename.cpp
index 234ac801380c964f309a0d55bb62e051da451650..9285be0e5d3e46942498dffda10d8476d855cd54 100644 (file)
@@ -75,6 +75,7 @@
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/utils.h"
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/utils.h"
+    #include "wx/crt.h"
 #endif
 
 #include "wx/filename.h"
 #endif
 
 #include "wx/filename.h"
@@ -92,7 +93,7 @@
 #endif
 
 #if defined(__WXMAC__)
 #endif
 
 #if defined(__WXMAC__)
-  #include  "wx/mac/private.h"  // includes mac headers
+  #include  "wx/osx/private.h"  // includes mac headers
 #endif
 
 // utime() is POSIX so should normally be available on all Unices
 #endif
 
 // utime() is POSIX so should normally be available on all Unices
 #endif
 
 
 #endif
 
 
-wxULongLong wxInvalidSize = (unsigned)-1;
+#if wxUSE_LONGLONG
+extern const wxULongLong wxInvalidSize = (unsigned)-1;
+#endif // wxUSE_LONGLONG
 
 
 // ----------------------------------------------------------------------------
 
 
 // ----------------------------------------------------------------------------
@@ -162,7 +165,7 @@ public:
     {
         m_hFile = ::CreateFile
                     (
     {
         m_hFile = ::CreateFile
                     (
-                     filename,                      // name
+                     filename.fn_str(),             // name
                      mode == Read ? GENERIC_READ    // access mask
                                   : GENERIC_WRITE,
                      FILE_SHARE_READ |              // sharing mode
                      mode == Read ? GENERIC_READ    // access mask
                                   : GENERIC_WRITE,
                      FILE_SHARE_READ |              // sharing mode
@@ -175,9 +178,12 @@ public:
 
         if ( m_hFile == INVALID_HANDLE_VALUE )
         {
 
         if ( m_hFile == INVALID_HANDLE_VALUE )
         {
-            wxLogSysError(_("Failed to open '%s' for %s"),
-                          filename.c_str(),
-                          mode == Read ? _("reading") : _("writing"));
+            if ( mode == Read )
+                wxLogSysError(_("Failed to open '%s' for reading"),
+                              filename.c_str());
+            else
+                wxLogSysError(_("Failed to open '%s' for writing"),
+                              filename.c_str());
         }
     }
 
         }
     }
 
@@ -284,6 +290,17 @@ static wxString wxGetVolumeString(const wxString& volume, wxPathFormat format)
     return path;
 }
 
     return path;
 }
 
+// return true if the format used is the DOS/Windows one and the string looks
+// like a UNC path
+static bool IsUNCPath(const wxString& path, wxPathFormat format)
+{
+    return format == wxPATH_DOS &&
+                path.length() >= 4 && // "\\a" can't be a UNC path
+                    path[0u] == wxFILE_SEP_PATH_DOS &&
+                        path[1u] == wxFILE_SEP_PATH_DOS &&
+                            path[2u] != wxFILE_SEP_PATH_DOS;
+}
+
 // ============================================================================
 // implementation
 // ============================================================================
 // ============================================================================
 // implementation
 // ============================================================================
@@ -307,9 +324,28 @@ void wxFileName::Assign(const wxString& volume,
                         const wxString& name,
                         const wxString& ext,
                         bool hasExt,
                         const wxString& name,
                         const wxString& ext,
                         bool hasExt,
-                        wxPathFormat format )
+                        wxPathFormat format)
 {
 {
-    SetPath( path, format );
+    // we should ignore paths which look like UNC shares because we already
+    // have the volume here and the UNC notation (\\server\path) is only valid
+    // for paths which don't start with a volume, so prevent SetPath() from
+    // recognizing "\\foo\bar" in "c:\\foo\bar" as an UNC path
+    //
+    // note also that this is a rather ugly way to do what we want (passing
+    // some kind of flag telling to ignore UNC paths to SetPath() would be
+    // better) but this is the safest thing to do to avoid breaking backwards
+    // compatibility in 2.8
+    if ( IsUNCPath(path, format) )
+    {
+        // remove one of the 2 leading backslashes to ensure that it's not
+        // recognized as an UNC path by SetPath()
+        wxString pathNonUNC(path, 1, wxString::npos);
+        SetPath(pathNonUNC, format);
+    }
+    else // no UNC complications
+    {
+        SetPath(path, format);
+    }
 
     m_volume = volume;
     m_ext = ext;
 
     m_volume = volume;
     m_ext = ext;
@@ -427,7 +463,7 @@ void wxFileName::Assign(const wxString& fullpathOrig,
     // always recognize fullpath as directory, even if it doesn't end with a
     // slash
     wxString fullpath = fullpathOrig;
     // always recognize fullpath as directory, even if it doesn't end with a
     // slash
     wxString fullpath = fullpathOrig;
-    if ( !wxEndsWithPathSeparator(fullpath) )
+    if ( !fullpath.empty() && !wxEndsWithPathSeparator(fullpath) )
     {
         fullpath += GetPathSeparator(format);
     }
     {
         fullpath += GetPathSeparator(format);
     }
@@ -616,7 +652,7 @@ static int wxOpenWithDeleteOnClose(const wxString& filename)
     DWORD attributes = FILE_ATTRIBUTE_TEMPORARY |
                        FILE_FLAG_DELETE_ON_CLOSE;
 
     DWORD attributes = FILE_ATTRIBUTE_TEMPORARY |
                        FILE_FLAG_DELETE_ON_CLOSE;
 
-    HANDLE h = ::CreateFile(filename, access, 0, NULL,
+    HANDLE h = ::CreateFile(filename.fn_str(), access, 0, NULL,
                             disposition, attributes, NULL);
 
     return wxOpenOSFHandle(h, wxO_BINARY);
                             disposition, attributes, NULL);
 
     return wxOpenOSFHandle(h, wxO_BINARY);
@@ -711,7 +747,8 @@ static wxString wxCreateTempImpl(
     }
 
 #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__)
     }
 
 #elif defined(__WINDOWS__) && !defined(__WXMICROWIN__)
-    if ( !::GetTempFileName(dir, name, 0, wxStringBuffer(path, MAX_PATH + 1)) )
+    if ( !::GetTempFileName(dir.fn_str(), name.fn_str(), 0,
+                            wxStringBuffer(path, MAX_PATH + 1)) )
     {
         wxLogLastError(_T("GetTempFileName"));
 
     {
         wxLogLastError(_T("GetTempFileName"));
 
@@ -734,7 +771,7 @@ static wxString wxCreateTempImpl(
     path += _T("XXXXXX");
 
     // we need to copy the path to the buffer in which mkstemp() can modify it
     path += _T("XXXXXX");
 
     // we need to copy the path to the buffer in which mkstemp() can modify it
-    wxCharBuffer buf( wxConvFile.cWX2MB( path ) );
+    wxCharBuffer buf(path.fn_str());
 
     // cast is safe because the string length doesn't change
     int fdTemp = mkstemp( (char*)(const char*) buf );
 
     // cast is safe because the string length doesn't change
     int fdTemp = mkstemp( (char*)(const char*) buf );
@@ -989,55 +1026,55 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFFile *fileTemp)
 // directory operations
 // ----------------------------------------------------------------------------
 
 // directory operations
 // ----------------------------------------------------------------------------
 
-wxString wxFileName::GetTempDir()
+// helper of GetTempDir(): check if the given directory exists and return it if
+// it does or an empty string otherwise
+namespace
 {
 {
-    wxString dir;
-    dir = wxGetenv(_T("TMPDIR"));
-    if (dir.empty())
-    {
-        dir = wxGetenv(_T("TMP"));
-        if (dir.empty())
-        {
-            dir = wxGetenv(_T("TEMP"));
-        }
-    }
 
 
-#if defined(__WXWINCE__)
-    if (dir.empty())
+wxString CheckIfDirExists(const wxString& dir)
+{
+    return wxFileName::DirExists(dir) ? dir : wxString();
+}
+
+} // anonymous namespace
+
+wxString wxFileName::GetTempDir()
+{
+    // 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() )
     {
     {
-        // FIXME. Create \temp dir?
-        if (DirExists(wxT("\\temp")))
-            dir = wxT("\\temp");
+        dir = CheckIfDirExists(wxGetenv("TMP"));
+        if ( dir.empty() )
+            dir = CheckIfDirExists(wxGetenv("TEMP"));
     }
     }
-#elif defined(__WINDOWS__) && !defined(__WXMICROWIN__)
 
 
+    // if no environment variables are set, use the system default
     if ( dir.empty() )
     {
     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 ( !::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() )
     {
     if ( dir.empty() )
     {
-        // default
-#if defined(__DOS__) || defined(__OS2__)
-        dir = _T(".");
-#elif defined(__WXMAC__)
-        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;
 }
 
     return dir;
 }
@@ -1065,14 +1102,7 @@ bool wxFileName::Mkdir( const wxString& dir, int perm, int flags )
         size_t count = dirs.GetCount();
         for ( size_t i = 0; i < count; i++ )
         {
         size_t count = dirs.GetCount();
         for ( size_t i = 0; i < count; i++ )
         {
-            if ( i > 0 ||
-#if defined(__WXMAC__) && !defined(__DARWIN__)
-            // relative pathnames are exactely the other way round under mac...
-                !filename.IsAbsolute()
-#else
-                filename.IsAbsolute()
-#endif
-            )
+            if ( i > 0 || filename.IsAbsolute() )
                 currPath += wxFILE_SEP_PATH;
             currPath += dirs[i];
 
                 currPath += wxFILE_SEP_PATH;
             currPath += dirs[i];
 
@@ -1231,11 +1261,6 @@ bool wxFileName::Normalize(int flags,
             }
         }
 
             }
         }
 
-        if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
-        {
-            dir.MakeLower();
-        }
-
         m_dirs.Add(dir);
     }
 
         m_dirs.Add(dir);
     }
 
@@ -1245,32 +1270,34 @@ bool wxFileName::Normalize(int flags,
         wxString filename;
         if (GetShortcutTarget(GetFullPath(format), filename))
         {
         wxString filename;
         if (GetShortcutTarget(GetFullPath(format), filename))
         {
-            // Repeat this since we may now have a new path
-            if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
-            {
-                filename.MakeLower();
-            }
             m_relative = false;
             Assign(filename);
         }
     }
 #endif
 
             m_relative = false;
             Assign(filename);
         }
     }
 #endif
 
-    if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
+#if defined(__WIN32__)
+    if ( (flags & wxPATH_NORM_LONG) && (format == wxPATH_DOS) )
     {
     {
-        // VZ: expand env vars here too?
+        Assign(GetLongPath());
+    }
+#endif // Win32
 
 
+    // Change case  (this should be kept at the end of the function, to ensure
+    // that the path doesn't change any more after we normalize its case)
+    if ( (flags & wxPATH_NORM_CASE) && !IsCaseSensitive(format) )
+    {
         m_volume.MakeLower();
         m_name.MakeLower();
         m_ext.MakeLower();
         m_volume.MakeLower();
         m_name.MakeLower();
         m_ext.MakeLower();
-    }
 
 
-#if defined(__WIN32__)
-    if ( (flags & wxPATH_NORM_LONG) && (format == wxPATH_DOS) )
-    {
-        Assign(GetLongPath());
+        // directory entries must be made lower case as well
+        count = m_dirs.GetCount();
+        for ( size_t i = 0; i < count; i++ )
+        {
+            m_dirs[i].MakeLower();
+        }
     }
     }
-#endif // Win32
 
     return true;
 }
 
     return true;
 }
@@ -1768,13 +1795,13 @@ wxString wxFileName::GetShortPath() const
     wxString path(GetFullPath());
 
 #if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
     wxString path(GetFullPath());
 
 #if defined(__WXMSW__) && defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
-    DWORD sz = ::GetShortPathName(path, NULL, 0);
+    DWORD sz = ::GetShortPathName(path.fn_str(), NULL, 0);
     if ( sz != 0 )
     {
         wxString pathOut;
         if ( ::GetShortPathName
                (
     if ( sz != 0 )
     {
         wxString pathOut;
         if ( ::GetShortPathName
                (
-                path,
+                path.fn_str(),
                 wxStringBuffer(pathOut, sz),
                 sz
                ) != 0 )
                 wxStringBuffer(pathOut, sz),
                 sz
                ) != 0 )
@@ -1795,7 +1822,7 @@ wxString wxFileName::GetLongPath() const
 
 #if defined(__WIN32__) && !defined(__WXWINCE__) && !defined(__WXMICROWIN__)
 
 
 #if defined(__WIN32__) && !defined(__WXWINCE__) && !defined(__WXMICROWIN__)
 
-#if wxUSE_DYNAMIC_LOADER
+#if wxUSE_DYNLIB_CLASS
     typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
 
     // this is MT-safe as in the worst case we're going to resolve the function
     typedef DWORD (WINAPI *GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
 
     // this is MT-safe as in the worst case we're going to resolve the function
@@ -1832,12 +1859,12 @@ wxString wxFileName::GetLongPath() const
 
     if ( s_pfnGetLongPathName )
     {
 
     if ( s_pfnGetLongPathName )
     {
-        DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0);
+        DWORD dwSize = (*s_pfnGetLongPathName)(path.fn_str(), NULL, 0);
         if ( dwSize > 0 )
         {
             if ( (*s_pfnGetLongPathName)
                  (
         if ( dwSize > 0 )
         {
             if ( (*s_pfnGetLongPathName)
                  (
-                  path,
+                  path.fn_str(),
                   wxStringBuffer(pathOut, dwSize),
                   dwSize
                  ) != 0 )
                   wxStringBuffer(pathOut, dwSize),
                   dwSize
                  ) != 0 )
@@ -1846,7 +1873,7 @@ wxString wxFileName::GetLongPath() const
             }
         }
     }
             }
         }
     }
-#endif // wxUSE_DYNAMIC_LOADER
+#endif // wxUSE_DYNLIB_CLASS
 
     // 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.
@@ -1887,7 +1914,7 @@ wxString wxFileName::GetLongPath() const
             continue;
         }
 
             continue;
         }
 
-        hFind = ::FindFirstFile(tmpPath, &findFileData);
+        hFind = ::FindFirstFile(tmpPath.fn_str(), &findFileData);
         if (hFind == INVALID_HANDLE_VALUE)
         {
             // Error: most likely reason is that path doesn't exist, so
         if (hFind == INVALID_HANDLE_VALUE)
         {
             // Error: most likely reason is that path doesn't exist, so
@@ -1917,8 +1944,6 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format )
     {
 #if defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__)
         format = wxPATH_DOS;
     {
 #if defined(__WXMSW__) || defined(__OS2__) || defined(__DOS__)
         format = wxPATH_DOS;
-#elif defined(__WXMAC__) && !defined(__DARWIN__)
-        format = wxPATH_MAC;
 #elif defined(__VMS)
         format = wxPATH_VMS;
 #else
 #elif defined(__VMS)
         format = wxPATH_VMS;
 #else
@@ -1928,6 +1953,23 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format )
     return 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
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // path splitting function
 // ----------------------------------------------------------------------------
@@ -1944,23 +1986,18 @@ wxFileName::SplitVolume(const wxString& fullpathWithVolume,
     wxString fullpath = fullpathWithVolume;
 
     // special Windows UNC paths hack: transform \\share\path into share:path
     wxString fullpath = fullpathWithVolume;
 
     // special Windows UNC paths hack: transform \\share\path into share:path
-    if ( format == wxPATH_DOS )
+    if ( IsUNCPath(fullpath, format) )
     {
     {
-        if ( fullpath.length() >= 4 &&
-                fullpath[0u] == wxFILE_SEP_PATH_DOS &&
-                    fullpath[1u] == wxFILE_SEP_PATH_DOS )
-        {
-            fullpath.erase(0, 2);
+        fullpath.erase(0, 2);
 
 
-            size_t posFirstSlash =
-                fullpath.find_first_of(GetPathTerminators(format));
-            if ( posFirstSlash != wxString::npos )
-            {
-                fullpath[posFirstSlash] = wxFILE_SEP_DSK;
+        size_t posFirstSlash =
+            fullpath.find_first_of(GetPathTerminators(format));
+        if ( posFirstSlash != wxString::npos )
+        {
+            fullpath[posFirstSlash] = wxFILE_SEP_DSK;
 
 
-                // UNC paths are always absolute, right? (FIXME)
-                fullpath.insert(posFirstSlash + 1, 1, wxFILE_SEP_PATH_DOS);
-            }
+            // UNC paths are always absolute, right? (FIXME)
+            fullpath.insert(posFirstSlash + 1, 1, wxFILE_SEP_PATH_DOS);
         }
     }
 
         }
     }
 
@@ -2216,7 +2253,7 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
     // not 9x
     bool ok;
     FILETIME ftAccess, ftCreate, ftWrite;
     // not 9x
     bool ok;
     FILETIME ftAccess, ftCreate, ftWrite;
-    if ( IsDir() ) 
+    if ( IsDir() )
     {
         // implemented in msw/dir.cpp
         extern bool wxGetDirectoryTimes(const wxString& dirname,
     {
         // implemented in msw/dir.cpp
         extern bool wxGetDirectoryTimes(const wxString& dirname,
@@ -2287,6 +2324,8 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
 // file size functions
 // ----------------------------------------------------------------------------
 
 // file size functions
 // ----------------------------------------------------------------------------
 
+#if wxUSE_LONGLONG
+
 /* static */
 wxULongLong wxFileName::GetSize(const wxString &filename)
 {
 /* static */
 wxULongLong wxFileName::GetSize(const wxString &filename)
 {
@@ -2303,14 +2342,11 @@ wxULongLong wxFileName::GetSize(const wxString &filename)
 
     DWORD lpFileSizeHigh;
     DWORD ret = GetFileSize(f, &lpFileSizeHigh);
 
     DWORD lpFileSizeHigh;
     DWORD ret = GetFileSize(f, &lpFileSizeHigh);
-    if (ret == INVALID_FILE_SIZE)
+    if ( ret == INVALID_FILE_SIZE && ::GetLastError() != NO_ERROR )
         return wxInvalidSize;
 
         return wxInvalidSize;
 
-    // compose the low-order and high-order byte sizes
-    return wxULongLong(ret | (lpFileSizeHigh << sizeof(WORD)*2));
-
-#else           // ! __WIN32__
-
+    return wxULongLong(lpFileSizeHigh, ret);
+#else // ! __WIN32__
     wxStructStat st;
 #ifndef wxNEED_WX_UNISTD_H
     if (wxStat( filename.fn_str() , &st) != 0)
     wxStructStat st;
 #ifndef wxNEED_WX_UNISTD_H
     if (wxStat( filename.fn_str() , &st) != 0)
@@ -2358,12 +2394,13 @@ wxString wxFileName::GetHumanReadableSize(const wxString &failmsg, int precision
     return GetHumanReadableSize(GetSize(), failmsg, precision);
 }
 
     return GetHumanReadableSize(GetSize(), failmsg, precision);
 }
 
+#endif // wxUSE_LONGLONG
 
 // ----------------------------------------------------------------------------
 // Mac-specific functions
 // ----------------------------------------------------------------------------
 
 
 // ----------------------------------------------------------------------------
 // Mac-specific functions
 // ----------------------------------------------------------------------------
 
-#ifdef __WXMAC__
+#if defined( __WXOSX_MAC__ ) && wxOSX_USE_CARBON
 
 const short kMacExtensionMaxLength = 16 ;
 class MacDefaultExtensionRecord
 
 const short kMacExtensionMaxLength = 16 ;
 class MacDefaultExtensionRecord