]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filename.cpp
added sample showing wxTR_FULL_ROW_HIGHLIGHT
[wxWidgets.git] / src / common / filename.cpp
index d1d0a43d76a946131bd564ba644eadc81e226531..17525840a4fa79db8d31feada702994e401c9c6f 100644 (file)
@@ -32,9 +32,9 @@
                 or just
                     filename
                 (although :filename works as well).
                 or just
                     filename
                 (although :filename works as well).
-                :::filename.ext is not yet supported. TODO.
                 Since the volume is just part of the file path, it is not
                 Since the volume is just part of the file path, it is not
-                treated like a separate entity as it is done under DOS.
+                treated like a separate entity as it is done under DOS and
+                VMS, it is just treated as another dir. 
 
    wxPATH_VMS:  VMS native format, absolute file names have the form
                     <device>:[dir1.dir2.dir3]file.txt
 
    wxPATH_VMS:  VMS native format, absolute file names have the form
                     <device>:[dir1.dir2.dir3]file.txt
@@ -225,6 +225,7 @@ void wxFileName::Assign( const wxFileName &filepath )
     m_dirs = filepath.GetDirs();
     m_name = filepath.GetName();
     m_ext = filepath.GetExt();
     m_dirs = filepath.GetDirs();
     m_name = filepath.GetName();
     m_ext = filepath.GetExt();
+    m_relative = filepath.IsRelative();
 }
 
 void wxFileName::Assign(const wxString& volume,
 }
 
 void wxFileName::Assign(const wxString& volume,
@@ -233,18 +234,70 @@ void wxFileName::Assign(const wxString& volume,
                         const wxString& ext,
                         wxPathFormat format )
 {
                         const wxString& ext,
                         wxPathFormat format )
 {
-    wxStringTokenizer tn(path, GetPathSeparators(format));
-
+    wxPathFormat my_format = GetFormat( format );
+    wxString my_path = path;
+    
     m_dirs.Clear();
     m_dirs.Clear();
-    while ( tn.HasMoreTokens() )
+    
+    if (!my_path.empty())
     {
     {
-        wxString token = tn.GetNextToken();
+        // 1) Determine if the path is relative or absolute.
+        
+        switch (my_format)
+        {
+            case wxPATH_MAC:
+                m_relative = ( my_path[0u] == wxT(':') );
+                // We then remove a leading ":". The reason is in our
+                // storage form for relative paths:
+                // ":dir:file.txt" actually means "./dir/file.txt" in
+                // DOS notation and should get stored as 
+                // (relative) (dir) (file.txt)
+                // "::dir:file.txt" actually means "../dir/file.txt"
+                // stored as (relative) (..) (dir) (file.txt)
+                // This is important only for the Mac as an empty dir
+                // actually means <UP>, whereas under DOS, double
+                // slashes can be ignored: "\\\\" is the same as "\\".
+                if (m_relative)
+                    my_path.Remove( 0, 1 );
+                break;
+            case wxPATH_VMS:
+                // TODO: what is the relative path format here?
+                m_relative = FALSE;
+                break;
+            case wxPATH_UNIX:
+                m_relative = ( my_path[0u] != wxT('/') );
+                break;
+            case wxPATH_DOS:
+                m_relative = ( (my_path[0u] != wxT('/')) && (my_path[0u] != wxT('\\')) );
+                break;
+            default:
+                wxFAIL_MSG( "error" );
+                break;
+        }
+        
+        // 2) Break up the path into its members. If the original path
+        //    was just "/" or "\\", m_dirs will be empty. We know from
+        //    the m_relative field, if this means "nothing" or "root dir".
+        
+        wxStringTokenizer tn( my_path, GetPathSeparators(my_format) );
+
+        while ( tn.HasMoreTokens() )
+        {
+            wxString token = tn.GetNextToken();
 
 
-        // if the path starts with a slash, we do need the first empty dir
-        // entry to be able to tell later that it was an absolute path, but
-        // otherwise ignore the double slashes
-        if ( m_dirs.IsEmpty() || !token.IsEmpty() )
-            m_dirs.Add( token );
+            // Remove empty token under DOS and Unix, interpret them
+            // as .. under Mac.
+            if (token.empty())
+            {
+                if (my_format == wxPATH_MAC)
+                    m_dirs.Add( wxT("..") );
+                // else ignore
+            }
+            else
+            {
+               m_dirs.Add( token );
+            }
+        }
     }
 
     m_volume = volume;
     }
 
     m_volume = volume;
@@ -276,7 +329,7 @@ void wxFileName::Assign(const wxString& fullpathOrig,
     wxString volume, path, name, ext;
 
     // do some consistency checks in debug mode: the name should be really just
     wxString volume, path, name, ext;
 
     // do some consistency checks in debug mode: the name should be really just
-    // the filename and the path should be realyl just a path
+    // the filename and the path should be really just a path
 #ifdef __WXDEBUG__
     wxString pathDummy, nameDummy, extDummy;
 
 #ifdef __WXDEBUG__
     wxString pathDummy, nameDummy, extDummy;
 
@@ -468,8 +521,8 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
     #ifndef __WATCOMC__
         ::DosCreateDir(wxStringBuffer(path, MAX_PATH), NULL);
     #endif
     #ifndef __WATCOMC__
         ::DosCreateDir(wxStringBuffer(path, MAX_PATH), NULL);
     #endif
-
-#else // !Windows, !OS/2, !DOS
+    
+#else // !Windows, !OS/2
     if ( dir.empty() )
     {
         dir = wxGetenv(_T("TMP"));
     if ( dir.empty() )
     {
         dir = wxGetenv(_T("TMP"));
@@ -499,19 +552,7 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
 
     path += name;
 
 
     path += name;
 
-#if defined(__DOS__) && defined(__WATCOMC__)
-    // scratch space for mkstemp()
-    path += _T("XXXXXX");
-
-    // can use the cast here because the length doesn't change and the string
-    // is not shared
-    if ( !_mktemp((char *)path.mb_str()) )
-    {
-        // this might be not necessary as mkstemp() on most systems should have
-        // already done it but it doesn't hurt neither...
-        path.clear();
-    }
-#elif defined(HAVE_MKSTEMP)
+#if defined(HAVE_MKSTEMP)
     // scratch space for mkstemp()
     path += _T("XXXXXX");
 
     // scratch space for mkstemp()
     path += _T("XXXXXX");
 
@@ -534,9 +575,11 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
     {
         path.clear();
     }
     {
         path.clear();
     }
-#else // !HAVE_MKTEMP
+#else // !HAVE_MKTEMP (includes __DOS__)
     // generate the unique file name ourselves
     // generate the unique file name ourselves
+    #ifndef __DOS__
     path << (unsigned int)getpid();
     path << (unsigned int)getpid();
+    #endif
 
     wxString pathTry;
 
 
     wxString pathTry;
 
@@ -659,7 +702,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
     format = GetFormat(format);
 
     // make the path absolute
     format = GetFormat(format);
 
     // make the path absolute
-    if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute() )
+    if ( (flags & wxPATH_NORM_ABSOLUTE) && m_relative )
     {
         if ( cwd.empty() )
         {
     {
         if ( cwd.empty() )
         {
@@ -670,6 +713,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
             curDir.AssignDir(cwd);
         }
 
             curDir.AssignDir(cwd);
         }
 
+#if 0
         // the path may be not absolute because it doesn't have the volume name
         // but in this case we shouldn't modify the directory components of it
         // but just set the current volume
         // the path may be not absolute because it doesn't have the volume name
         // but in this case we shouldn't modify the directory components of it
         // but just set the current volume
@@ -683,6 +727,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
                 curDir.Clear();
             }
         }
                 curDir.Clear();
             }
         }
+#endif
     }
 
     // handle ~ stuff under Unix only
     }
 
     // handle ~ stuff under Unix only
@@ -808,6 +853,8 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format)
     {
         m_dirs.Insert(wxT(".."), 0u);
     }
     {
         m_dirs.Insert(wxT(".."), 0u);
     }
+    
+    m_relative = TRUE;
 
     // we were modified
     return TRUE;
 
     // we were modified
     return TRUE;
@@ -843,56 +890,6 @@ bool wxFileName::IsCaseSensitive( wxPathFormat format )
     return GetFormat(format) == wxPATH_UNIX;
 }
 
     return GetFormat(format) == wxPATH_UNIX;
 }
 
-bool wxFileName::IsAbsolute( wxPathFormat format )
-{
-    // if we have no path, we can't be an abs filename
-    if ( m_dirs.IsEmpty() )
-    {
-        return FALSE;
-    }
-
-    format = GetFormat(format);
-
-    if ( format == wxPATH_UNIX )
-    {
-        const wxString& str = m_dirs[0u];
-        if ( str.empty() )
-        {
-            // the path started with '/', it's an absolute one
-            return TRUE;
-        }
-
-        // the path is absolute if it starts with a path separator or
-        // with "~" or "~user"
-        wxChar ch = str[0u];
-
-        return IsPathSeparator(ch, format) || ch == _T('~');
-    }
-    else // !Unix
-    {
-        // must have the drive
-        if ( m_volume.empty() )
-            return FALSE;
-
-        switch ( format )
-        {
-            default:
-                wxFAIL_MSG( _T("unknown wxPATH_XXX style") );
-                // fall through
-
-            case wxPATH_DOS:
-                return m_dirs[0u].empty();
-
-            case wxPATH_VMS:
-                // TODO: what is the relative path format here?
-                return TRUE;
-
-            case wxPATH_MAC:
-                return !m_dirs[0u].empty();
-        }
-    }
-}
-
 /* static */
 wxString wxFileName::GetVolumeSeparator(wxPathFormat format)
 {
 /* static */
 wxString wxFileName::GetVolumeSeparator(wxPathFormat format)
 {
@@ -1006,16 +1003,82 @@ wxString wxFileName::GetPath( bool add_separator, wxPathFormat format ) const
 {
     format = GetFormat( format );
 
 {
     format = GetFormat( format );
 
-    wxString ret;
-    size_t count = m_dirs.GetCount();
-    for ( size_t i = 0; i < count; i++ )
+    wxString fullpath;
+
+    // the leading character
+    if ( format == wxPATH_MAC && m_relative )
+    {
+         fullpath += wxFILE_SEP_PATH_MAC;
+    }
+    else if ( format == wxPATH_DOS )
     {
     {
-        ret += m_dirs[i];
-        if ( add_separator || (i < count) )
-            ret += wxFILE_SEP_PATH;
+         if (!m_relative)
+             fullpath += wxFILE_SEP_PATH_DOS;
     }
     }
+    else if ( format == wxPATH_UNIX )
+    {
+         if (!m_relative)
+             fullpath += wxFILE_SEP_PATH_UNIX;
+    }
+    
+    // then concatenate all the path components using the path separator
+    size_t dirCount = m_dirs.GetCount();
+    if ( dirCount )
+    {
+        if ( format == wxPATH_VMS )
+        {
+            fullpath += wxT('[');
+        }
+
+
+        for ( size_t i = 0; i < dirCount; i++ )
+        {
+            // TODO: What to do with ".." under VMS
+
+            switch (format)
+            {
+                case wxPATH_MAC:
+                {
+                    if (m_dirs[i] == wxT("."))
+                        break;
+                    if (m_dirs[i] != wxT(".."))  // convert back from ".." to nothing
+                         fullpath += m_dirs[i];
+                    fullpath += wxT(':');
+                    break;
+                }
+                case wxPATH_DOS:
+                {
+                    fullpath += m_dirs[i];
+                    fullpath += wxT('\\');
+                    break;
+                }
+                case wxPATH_UNIX:
+                {
+                    fullpath += m_dirs[i];
+                    fullpath += wxT('/');
+                    break;
+                }
+                case wxPATH_VMS:
+                {
+                    if (m_dirs[i] != wxT(".."))  // convert back from ".." to nothing
+                        fullpath += m_dirs[i];
+                    if (i == dirCount-1)
+                        fullpath += wxT(']');
+                    else
+                        fullpath += wxT('.');
+                    break;
+                }
+                default:
+                {
+                    wxFAIL_MSG( "error" );
+                }
+            }
+        }
+    }
+
+
 
 
-    return ret;
+    return fullpath;
 }
 
 wxString wxFileName::GetFullPath( wxPathFormat format ) const
 }
 
 wxString wxFileName::GetFullPath( wxPathFormat format ) const
@@ -1036,50 +1099,82 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const
                {
                fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume;
                }
                {
                fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume;
                }
-               else // !UNC
+               else if  ( format == wxPATH_DOS || format == wxPATH_VMS )
                {
                fullpath << m_volume << GetVolumeSeparator(format);
             }
                {
                fullpath << m_volume << GetVolumeSeparator(format);
             }
+            // else ignore
         }
     }
         }
     }
-
+    
+    // the leading character
+    if ( format == wxPATH_MAC && m_relative )
+    {
+         fullpath += wxFILE_SEP_PATH_MAC;
+    }
+    else if ( format == wxPATH_DOS )
+    {
+         if (!m_relative)
+             fullpath += wxFILE_SEP_PATH_DOS;
+    }
+    else if ( format == wxPATH_UNIX )
+    {
+         if (!m_relative)
+             fullpath += wxFILE_SEP_PATH_UNIX;
+    }
+    
     // then concatenate all the path components using the path separator
     size_t dirCount = m_dirs.GetCount();
     if ( dirCount )
     {
     // then concatenate all the path components using the path separator
     size_t dirCount = m_dirs.GetCount();
     if ( dirCount )
     {
-        // under Mac, we must have a path separator in the beginning of the
-        // relative path - otherwise it would be parsed as an absolute one
-        if ( format == wxPATH_MAC && m_dirs[0].empty() )
-        {
-            fullpath += wxFILE_SEP_PATH_MAC;
-        }
-
-        wxChar chPathSep = GetPathSeparators(format)[0u];
         if ( format == wxPATH_VMS )
         {
         if ( format == wxPATH_VMS )
         {
-            fullpath += _T('[');
+            fullpath += wxT('[');
         }
 
         }
 
+
         for ( size_t i = 0; i < dirCount; i++ )
         {
         for ( size_t i = 0; i < dirCount; i++ )
         {
-            // under VMS, we shouldn't have a leading dot
-            if ( i && (format != wxPATH_VMS || !m_dirs[i - 1].empty()) )
-                fullpath += chPathSep;
+            // TODO: What to do with ".." under VMS
 
 
-            fullpath += m_dirs[i];
-        }
-
-        if ( format == wxPATH_VMS )
-        {
-            fullpath += _T(']');
-        }
-        else // !VMS
-        {
-            // separate the file name from the last directory, notice that we
-            // intentionally do it even if the name and extension are empty as
-            // this allows us to distinguish the directories from the file
-            // names (the directories have the trailing slash)
-            fullpath += chPathSep;
+            switch (format)
+            {
+                case wxPATH_MAC:
+                {
+                    if (m_dirs[i] == wxT("."))
+                        break;
+                    if (m_dirs[i] != wxT(".."))  // convert back from ".." to nothing
+                         fullpath += m_dirs[i];
+                    fullpath += wxT(':');
+                    break;
+                }
+                case wxPATH_DOS:
+                {
+                    fullpath += m_dirs[i];
+                    fullpath += wxT('\\');
+                    break;
+                }
+                case wxPATH_UNIX:
+                {
+                    fullpath += m_dirs[i];
+                    fullpath += wxT('/');
+                    break;
+                }
+                case wxPATH_VMS:
+                {
+                    if (m_dirs[i] != wxT(".."))  // convert back from ".." to nothing
+                        fullpath += m_dirs[i];
+                    if (i == dirCount-1)
+                        fullpath += wxT(']');
+                    else
+                        fullpath += wxT('.');
+                    break;
+                }
+                default:
+                {
+                    wxFAIL_MSG( "error" );
+                }
+            }
         }
     }
 
         }
     }
 
@@ -1344,7 +1439,7 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume,
         else
         {
             // take everything up to the path separator but take care to make
         else
         {
             // take everything up to the path separator but take care to make
-            // tha path equal to something like '/', not empty, for the files
+            // the path equal to something like '/', not empty, for the files
             // immediately under root directory
             size_t len = posLastSlash;
             if ( !len )
             // immediately under root directory
             size_t len = posLastSlash;
             if ( !len )