]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filename.cpp
removed wxYield from wxHtmlWindow (seems to work w/o it and yielding caused reentranc...
[wxWidgets.git] / src / common / filename.cpp
index 359ef50fc06a236db36e5bd5315cd32452eabac0..ffffe53275f47ba31992c84db2102f12764da4f1 100644 (file)
@@ -24,7 +24,7 @@
 
                 There are also UNC names of the form \\share\fullpath
 
 
                 There are also UNC names of the form \\share\fullpath
 
-   wxPATH_MAC:  Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file 
+   wxPATH_MAC:  Mac OS 8/9 and Mac OS X under CodeWarrior 7 format, absolute file
                 names have the form
                     volume:dir1:...:dirN:filename
                 and the relative file names are either
                 names have the form
                     volume:dir1:...:dirN:filename
                 and the relative file names are either
@@ -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
 // ----------------------------------------------------------------------------
 
 #ifdef __GNUG__
 // ----------------------------------------------------------------------------
 
 #ifdef __GNUG__
-    #pragma implementation "filename.h"
+#pragma implementation "filename.h"
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #endif
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-  #pragma hdrstop
+#pragma hdrstop
 #endif
 
 #ifndef WX_PRECOMP
 #endif
 
 #ifndef WX_PRECOMP
-    #include "wx/intl.h"
-    #include "wx/log.h"
+#include "wx/intl.h"
+#include "wx/log.h"
+#include "wx/file.h"
 #endif
 
 #include "wx/filename.h"
 #include "wx/tokenzr.h"
 #include "wx/config.h"          // for wxExpandEnvVars
 #include "wx/utils.h"
 #endif
 
 #include "wx/filename.h"
 #include "wx/tokenzr.h"
 #include "wx/config.h"          // for wxExpandEnvVars
 #include "wx/utils.h"
-
-#if wxUSE_DYNLIB_CLASS
-    #include "wx/dynlib.h"
-#endif
+#include "wx/file.h"
+//#include "wx/dynlib.h"        // see GetLongPath below, code disabled.
 
 // For GetShort/LongPathName
 #ifdef __WIN32__
 
 // For GetShort/LongPathName
 #ifdef __WIN32__
-    #include <windows.h>
+#include <windows.h>
+#include "wx/msw/winundef.h"
+#endif
 
 
-    #include "wx/msw/winundef.h"
+#if defined(__WXMAC__)
+  #include  "wx/mac/private.h"  // includes mac headers
 #endif
 
 // utime() is POSIX so should normally be available on all Unices
 #ifdef __UNIX_LIKE__
 #endif
 
 // utime() is POSIX so should normally be available on all Unices
 #ifdef __UNIX_LIKE__
-    #include <sys/types.h>
-    #include <utime.h>
-    #include <sys/stat.h>
-    #include <unistd.h>
+#include <sys/types.h>
+#include <utime.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
+#ifdef __DJGPP__
+#include <unistd.h>
 #endif
 
 #ifdef __MWERKS__
 #endif
 
 #ifdef __MWERKS__
-    #include <stat.h>
-    #include <unistd.h>
-    #include <unix.h>
+#include <stat.h>
+#include <unistd.h>
+#include <unix.h>
+#endif
+
+#ifdef __WATCOMC__
+#include <io.h>
+#include <sys/utime.h>
+#include <sys/stat.h>
+#endif
+
+#ifdef __VISAGECPP__
+#ifndef MAX_PATH
+#define MAX_PATH 256
+#endif
 #endif
 
 // ----------------------------------------------------------------------------
 #endif
 
 // ----------------------------------------------------------------------------
@@ -213,6 +231,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,
@@ -221,23 +240,84 @@ void wxFileName::Assign(const wxString& volume,
                         const wxString& ext,
                         wxPathFormat format )
 {
                         const wxString& ext,
                         wxPathFormat format )
 {
-    wxStringTokenizer tn(path, GetPathSeparators(format));
+    SetPath( path, format );
+
+    m_volume = volume;
+    m_ext = ext;
+    m_name = name;
+}
+
+void wxFileName::SetPath( const wxString &path, wxPathFormat 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.
 
 
-        // 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 );
-    }
+        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( wxT("error") );
+                break;
+        }
 
 
-    m_volume = volume;
-    m_ext = ext;
-    m_name = name;
+        // 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();
+
+            // 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 );
+            }
+        }
+    }
+    else
+    {
+        m_relative = TRUE;
+    }
 }
 
 void wxFileName::Assign(const wxString& fullpath,
 }
 
 void wxFileName::Assign(const wxString& fullpath,
@@ -264,7 +344,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;
 
@@ -367,7 +447,7 @@ wxString wxFileName::GetCwd(const wxString& volume)
     {
         SetCwd(cwdOld);
     }
     {
         SetCwd(cwdOld);
     }
-    
+
     return cwd;
 }
 
     return cwd;
 }
 
@@ -391,9 +471,9 @@ wxString wxFileName::GetHomeDir()
     return ::wxGetHomeDir();
 }
 
     return ::wxGetHomeDir();
 }
 
-void wxFileName::AssignTempFileName( const wxString& prefix )
+void wxFileName::AssignTempFileName(const wxString& prefix, wxFile *fileTemp)
 {
 {
-    wxString tempname = CreateTempFileName(prefix);
+    wxString tempname = CreateTempFileName(prefix, fileTemp);
     if ( tempname.empty() )
     {
         // error, failed to get temp file name
     if ( tempname.empty() )
     {
         // error, failed to get temp file name
@@ -406,7 +486,8 @@ void wxFileName::AssignTempFileName( const wxString& prefix )
 }
 
 /* static */
 }
 
 /* static */
-wxString wxFileName::CreateTempFileName(const wxString& prefix)
+wxString
+wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
 {
     wxString path, dir, name;
 
 {
     wxString path, dir, name;
 
@@ -454,14 +535,17 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
 
     // Temporarily remove - MN
     #ifndef __WATCOMC__
 
     // Temporarily remove - MN
     #ifndef __WATCOMC__
-        ::DosCreateDir(wxStringBuffer(MAX_PATH), NULL);
+        ::DosCreateDir(wxStringBuffer(path, MAX_PATH), NULL);
     #endif
 
 #else // !Windows, !OS/2
     if ( dir.empty() )
     {
     #endif
 
 #else // !Windows, !OS/2
     if ( dir.empty() )
     {
+#if defined(__WXMAC__) && !defined(__DARWIN__)
+        dir = wxMacFindFolder(  (short) kOnSystemDisk, kTemporaryFolderType, kCreateFolder ) ;
+#else // !Mac
         dir = wxGetenv(_T("TMP"));
         dir = wxGetenv(_T("TMP"));
-        if ( path.empty() )
+        if ( dir.empty() )
         {
             dir = wxGetenv(_T("TEMP"));
         }
         {
             dir = wxGetenv(_T("TEMP"));
         }
@@ -469,8 +553,13 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
         if ( dir.empty() )
         {
             // default
         if ( dir.empty() )
         {
             // default
-            dir = _T("/tmp");
+            #ifdef __DOS__
+                dir = _T(".");
+            #else
+                dir = _T("/tmp");
+            #endif
         }
         }
+#endif // Mac/!Mac
     }
 
     path = dir;
     }
 
     path = dir;
@@ -478,24 +567,36 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
     if ( !wxEndsWithPathSeparator(dir) &&
             (name.empty() || !wxIsPathSeparator(name[0u])) )
     {
     if ( !wxEndsWithPathSeparator(dir) &&
             (name.empty() || !wxIsPathSeparator(name[0u])) )
     {
-        path += _T('/');
+        path += wxFILE_SEP_PATH;
     }
 
     path += name;
 
     }
 
     path += name;
 
-#ifdef HAVE_MKSTEMP
+#if defined(HAVE_MKSTEMP)
     // scratch space for mkstemp()
     path += _T("XXXXXX");
 
     // can use the cast here because the length doesn't change and the string
     // is not shared
     // 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 ( mkstemp((char *)path.mb_str()) == -1 )
+    int fdTemp = mkstemp((char *)path.mb_str());
+    if ( fdTemp == -1 )
     {
         // this might be not necessary as mkstemp() on most systems should have
         // already done it but it doesn't hurt neither...
         path.clear();
     }
     {
         // this might be not necessary as mkstemp() on most systems should have
         // already done it but it doesn't hurt neither...
         path.clear();
     }
-    //else: file already created
+    else // mkstemp() succeeded
+    {
+        // avoid leaking the fd
+        if ( fileTemp )
+        {
+            fileTemp->Attach(fdTemp);
+        }
+        else
+        {
+            close(fdTemp);
+        }
+    }
 #else // !HAVE_MKSTEMP
 
 #ifdef HAVE_MKTEMP
 #else // !HAVE_MKSTEMP
 
 #ifdef HAVE_MKTEMP
@@ -506,9 +607,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;
 
@@ -530,10 +633,29 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
 
     if ( !path.empty() )
     {
 
     if ( !path.empty() )
     {
-        // create the file - of course, there is a race condition here, this is
+    }
+#endif // HAVE_MKSTEMP/!HAVE_MKSTEMP
+
+#endif // Windows/!Windows
+
+    if ( path.empty() )
+    {
+        wxLogSysError(_("Failed to create a temporary file name"));
+    }
+    else if ( fileTemp && !fileTemp->IsOpened() )
+    {
+        // open the file - of course, there is a race condition here, this is
         // why we always prefer using mkstemp()...
         // why we always prefer using mkstemp()...
-        wxFile file;
-        if ( !file.Open(path, wxFile::write_excl, wxS_IRUSR | wxS_IWUSR) )
+        //
+        // NB: GetTempFileName() under Windows creates the file, so using
+        //     write_excl there would fail
+        if ( !fileTemp->Open(path,
+#if defined(__WINDOWS__) && !defined(__WXMICROWIN__)
+                             wxFile::write,
+#else
+                             wxFile::write_excl,
+#endif
+                             wxS_IRUSR | wxS_IWUSR) )
         {
             // FIXME: If !ok here should we loop and try again with another
             //        file name?  That is the standard recourse if open(O_EXCL)
         {
             // FIXME: If !ok here should we loop and try again with another
             //        file name?  That is the standard recourse if open(O_EXCL)
@@ -545,14 +667,6 @@ wxString wxFileName::CreateTempFileName(const wxString& prefix)
             path.clear();
         }
     }
             path.clear();
         }
     }
-#endif // HAVE_MKSTEMP/!HAVE_MKSTEMP
-
-#endif // Windows/!Windows
-
-    if ( path.empty() )
-    {
-        wxLogSysError(_("Failed to create a temporary file name"));
-    }
 
     return path;
 }
 
     return path;
 }
@@ -629,9 +743,9 @@ bool wxFileName::Normalize(wxPathNormalize flags,
     wxFileName curDir;
 
     format = GetFormat(format);
     wxFileName curDir;
 
     format = GetFormat(format);
-    
+
     // make the path absolute
     // make the path absolute
-    if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute() )
+    if ( (flags & wxPATH_NORM_ABSOLUTE) && m_relative )
     {
         if ( cwd.empty() )
         {
     {
         if ( cwd.empty() )
         {
@@ -642,6 +756,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
@@ -655,8 +770,10 @@ bool wxFileName::Normalize(wxPathNormalize flags,
                 curDir.Clear();
             }
         }
                 curDir.Clear();
             }
         }
+#endif
+        m_relative = FALSE;
     }
     }
-    
+
     // handle ~ stuff under Unix only
     if ( (format == wxPATH_UNIX) && (flags & wxPATH_NORM_TILDE) )
     {
     // handle ~ stuff under Unix only
     if ( (format == wxPATH_UNIX) && (flags & wxPATH_NORM_TILDE) )
     {
@@ -709,7 +826,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
                     return FALSE;
                 }
 
                     return FALSE;
                 }
 
-                m_dirs.Remove(m_dirs.GetCount() - 1);
+                m_dirs.RemoveAt(m_dirs.GetCount() - 1);
                 continue;
             }
         }
                 continue;
             }
         }
@@ -770,8 +887,8 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format)
     while ( !m_dirs.IsEmpty() && !fnBase.m_dirs.IsEmpty() &&
                 m_dirs[0u].IsSameAs(fnBase.m_dirs[0u], withCase) )
     {
     while ( !m_dirs.IsEmpty() && !fnBase.m_dirs.IsEmpty() &&
                 m_dirs[0u].IsSameAs(fnBase.m_dirs[0u], withCase) )
     {
-        m_dirs.Remove(0u);
-        fnBase.m_dirs.Remove(0u);
+        m_dirs.RemoveAt(0);
+        fnBase.m_dirs.RemoveAt(0);
     }
 
     // add as many ".." as needed
     }
 
     // add as many ".." as needed
@@ -781,6 +898,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;
 }
@@ -815,56 +934,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)
 {
@@ -978,16 +1047,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 )
     {
     {
-        ret += m_dirs[i];
-        if ( add_separator || (i < count) )
-            ret += wxFILE_SEP_PATH;
+         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 )
+    {
+        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( wxT("error") );
+                }
+            }
+        }
+    }
+
 
 
-    return ret;
+
+    return fullpath;
 }
 
 wxString wxFileName::GetFullPath( wxPathFormat format ) const
 }
 
 wxString wxFileName::GetFullPath( wxPathFormat format ) const
@@ -999,59 +1134,91 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const
     // first put the volume
     if ( !m_volume.empty() )
     {
     // first put the volume
     if ( !m_volume.empty() )
     {
-       {
-               // Special Windows UNC paths hack, part 2: undo what we did in
-               // SplitPath() and make an UNC path if we have a drive which is not a
-               // single letter (hopefully the network shares can't be one letter only
-               // although I didn't find any authoritative docs on this)
-               if ( format == wxPATH_DOS && m_volume.length() > 1 )
-               {
-               fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume;
-               }
-               else // !UNC
-               {
-               fullpath << m_volume << GetVolumeSeparator(format);
+        {
+            // Special Windows UNC paths hack, part 2: undo what we did in
+            // SplitPath() and make an UNC path if we have a drive which is not a
+            // single letter (hopefully the network shares can't be one letter only
+            // although I didn't find any authoritative docs on this)
+            if ( format == wxPATH_DOS && m_volume.length() > 1 )
+            {
+                fullpath << wxFILE_SEP_PATH_DOS << wxFILE_SEP_PATH_DOS << m_volume;
+            }
+            else if  ( format == wxPATH_DOS || format == wxPATH_VMS )
+            {
+                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( wxT("error") );
+                }
+            }
         }
     }
 
         }
     }
 
@@ -1098,7 +1265,7 @@ wxString wxFileName::GetLongPath() const
     bool success = FALSE;
 
     // VZ: this code was disabled, why?
     bool success = FALSE;
 
     // VZ: this code was disabled, why?
-#if 0 // wxUSE_DYNLIB_CLASS
+#if 0 // wxUSE_DYNAMIC_LOADER
     typedef DWORD (*GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
 
     static bool s_triedToLoad = FALSE;
     typedef DWORD (*GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
 
     static bool s_triedToLoad = FALSE;
@@ -1106,19 +1273,17 @@ wxString wxFileName::GetLongPath() const
     if ( !s_triedToLoad )
     {
         s_triedToLoad = TRUE;
     if ( !s_triedToLoad )
     {
         s_triedToLoad = TRUE;
-        wxDllType dllKernel = wxDllLoader::LoadLibrary(_T("kernel32"));
-        if ( dllKernel )
+        wxDynamicLibrary dllKernel(_T("kernel32"));
+        if ( dllKernel.IsLoaded() )
         {
             // may succeed or fail depending on the Windows version
             static GET_LONG_PATH_NAME s_pfnGetLongPathName = NULL;
 #ifdef _UNICODE
         {
             // 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) wxDllLoader::GetSymbol(dllKernel, _T("GetLongPathNameW"));
+            s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameW"));
 #else
 #else
-            s_pfnGetLongPathName = (GET_LONG_PATH_NAME) wxDllLoader::GetSymbol(dllKernel, _T("GetLongPathNameA"));
+            s_pfnGetLongPathName = (GET_LONG_PATH_NAME) dllKernel.GetSymbol(_T("GetLongPathNameA"));
 #endif
 
 #endif
 
-            wxDllLoader::UnloadLibrary(dllKernel);
-
             if ( s_pfnGetLongPathName )
             {
                 DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0);
             if ( s_pfnGetLongPathName )
             {
                 DWORD dwSize = (*s_pfnGetLongPathName)(path, NULL, 0);
@@ -1146,7 +1311,7 @@ wxString wxFileName::GetLongPath() const
     }
     if (success)
         return pathOut;
     }
     if (success)
         return pathOut;
-#endif // wxUSE_DYNLIB_CLASS
+#endif // wxUSE_DYNAMIC_LOADER
 
     if (!success)
     {
 
     if (!success)
     {
@@ -1207,7 +1372,7 @@ wxPathFormat wxFileName::GetFormat( wxPathFormat format )
 {
     if (format == wxPATH_NATIVE)
     {
 {
     if (format == wxPATH_NATIVE)
     {
-#if defined(__WXMSW__) || defined(__WXPM__)
+#if defined(__WXMSW__) || defined(__WXPM__) || defined(__DOS__)
         format = wxPATH_DOS;
 #elif defined(__WXMAC__) && !defined(__DARWIN__)
         format = wxPATH_MAC;
         format = wxPATH_DOS;
 #elif defined(__WXMAC__) && !defined(__DARWIN__)
         format = wxPATH_MAC;
@@ -1265,7 +1430,7 @@ void wxFileName::SplitPath(const wxString& fullpathWithVolume,
     if ( format == wxPATH_DOS || format == wxPATH_VMS )
     {
         wxString sepVol = GetVolumeSeparator(format);
     if ( format == wxPATH_DOS || format == wxPATH_VMS )
     {
         wxString sepVol = GetVolumeSeparator(format);
-        
+
         size_t posFirstColon = fullpath.find_first_of(sepVol);
         if ( posFirstColon != wxString::npos )
         {
         size_t posFirstColon = fullpath.find_first_of(sepVol);
         if ( posFirstColon != wxString::npos )
         {
@@ -1316,7 +1481,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 )
@@ -1395,7 +1560,7 @@ bool wxFileName::SetTimes(const wxDateTime *dtCreate,
                           const wxDateTime *dtAccess,
                           const wxDateTime *dtMod)
 {
                           const wxDateTime *dtAccess,
                           const wxDateTime *dtMod)
 {
-#if defined(__UNIX_LIKE__)
+#if defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__))
     if ( !dtAccess && !dtMod )
     {
         // can't modify the creation time anyhow, don't try
     if ( !dtAccess && !dtMod )
     {
         // can't modify the creation time anyhow, don't try
@@ -1464,20 +1629,7 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
                           wxDateTime *dtMod,
                           wxDateTime *dtChange) const
 {
                           wxDateTime *dtMod,
                           wxDateTime *dtChange) const
 {
-#if defined(__UNIX_LIKE__)
-    wxStructStat stBuf;
-    if ( wxStat(GetFullPath(), &stBuf) == 0 )
-    {
-        if ( dtAccess )
-            dtAccess->Set(stBuf.st_atime);
-        if ( dtMod )
-            dtMod->Set(stBuf.st_mtime);
-        if ( dtChange )
-            dtChange->Set(stBuf.st_ctime);
-
-        return TRUE;
-    }
-#elif defined(__WXMAC__)
+#if defined(__UNIX_LIKE__) || defined(__WXMAC__) || (defined(__DOS__) && defined(__WATCOMC__))
     wxStructStat stBuf;
     if ( wxStat(GetFullPath(), &stBuf) == 0 )
     {
     wxStructStat stBuf;
     if ( wxStat(GetFullPath(), &stBuf) == 0 )
     {
@@ -1520,3 +1672,104 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
     return FALSE;
 }
 
     return FALSE;
 }
 
+#ifdef __WXMAC__
+
+const short kMacExtensionMaxLength = 16 ;
+typedef struct
+{
+  char m_ext[kMacExtensionMaxLength] ;
+  OSType m_type ;
+  OSType m_creator ;
+} MacDefaultExtensionRecord ;
+
+#include "wx/dynarray.h"
+WX_DECLARE_OBJARRAY(MacDefaultExtensionRecord, MacDefaultExtensionArray) ;
+#include "wx/arrimpl.cpp"
+WX_DEFINE_OBJARRAY(MacDefaultExtensionArray) ;
+
+MacDefaultExtensionArray gMacDefaultExtensions ;
+bool gMacDefaultExtensionsInited = false ;
+
+static void MacEnsureDefaultExtensionsLoaded()
+{
+  if ( !gMacDefaultExtensionsInited )
+  {
+    // load the default extensions
+    MacDefaultExtensionRecord defaults[] =
+    {
+      { "txt" , 'TEXT' , 'ttxt' } ,
+      
+    } ;
+    // we could load the pc exchange prefs here too
+    
+    for ( int i = 0 ; i < WXSIZEOF( defaults ) ; ++i )
+    {
+      gMacDefaultExtensions.Add( defaults[i] ) ;
+    } 
+    gMacDefaultExtensionsInited = true ;
+  }
+}
+bool wxFileName::MacSetTypeAndCreator( wxUint32 type , wxUint32 creator ) 
+{
+  FInfo fndrInfo ;
+  FSSpec spec ;
+  wxMacFilename2FSSpec(GetFullPath(),&spec) ;
+  OSErr err = FSpGetFInfo( &spec , &fndrInfo ) ;
+  wxCHECK( err == noErr , false ) ;
+
+  fndrInfo.fdType = type ;
+  fndrInfo.fdCreator = creator ;
+  FSpSetFInfo( &spec , &fndrInfo ) ;
+  return true ;
+}
+
+bool wxFileName::MacGetTypeAndCreator( wxUint32 *type , wxUint32 *creator ) 
+{
+  FInfo fndrInfo ;
+  FSSpec spec ;
+  wxMacFilename2FSSpec(GetFullPath(),&spec) ;
+  OSErr err = FSpGetFInfo( &spec , &fndrInfo ) ;
+  wxCHECK( err == noErr , false ) ;
+
+  *type = fndrInfo.fdType ;
+  *creator = fndrInfo.fdCreator ;
+  return true ;
+}
+
+bool wxFileName::MacSetDefaultTypeAndCreator()
+{
+    wxUint32 type , creator ;
+    if ( wxFileName::MacFindDefaultTypeAndCreator(GetExt() , &type ,
+      &creator ) )
+    {
+      MacSetTypeAndCreator( type , creator ) ;
+    }  
+}
+
+bool wxFileName::MacFindDefaultTypeAndCreator( const wxString& ext , wxUint32 *type , wxUint32 *creator ) 
+{
+  MacEnsureDefaultExtensionsLoaded() ;
+  wxString extl = ext.Lower() ;
+  for( int i = gMacDefaultExtensions.Count() - 1 ; i >= 0 ; --i )
+  {
+    if ( gMacDefaultExtensions.Item(i).m_ext == extl )
+    {
+      *type = gMacDefaultExtensions.Item(i).m_type ;
+      *creator = gMacDefaultExtensions.Item(i).m_creator ;
+      return true ;
+    }
+  }
+  return false ;
+}
+
+void wxFileName::MacRegisterDefaultTypeAndCreator( const wxString& ext , wxUint32 type , wxUint32 creator )
+{
+  MacEnsureDefaultExtensionsLoaded() ;
+  MacDefaultExtensionRecord rec ;
+  rec.m_type = type ;
+  rec.m_creator = creator ;
+  strncpy( rec.m_ext , ext.Lower().c_str() , kMacExtensionMaxLength ) ;
+  gMacDefaultExtensions.Add( rec ) ;
+}
+#endif
+