]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/filename.cpp
removed 68K targets and preferences and renamed output libraries
[wxWidgets.git] / src / common / filename.cpp
index 6e4fe199f635ea194c776e29e491ed3f21a9dd0e..486f75b109691c5546f070d48dd6ff220a0a9e61 100644 (file)
 class wxFileHandle
 {
 public:
-    wxFileHandle(const wxString& filename)
+    enum OpenMode
+    {
+        Read,
+        Write
+    };
+
+    wxFileHandle(const wxString& filename, OpenMode mode)
     {
         m_hFile = ::CreateFile
                     (
-                     filename,          // name
-                     GENERIC_READ,      // access mask
-                     0,                 // no sharing
-                     NULL,              // no secutity attr
-                     OPEN_EXISTING,     // creation disposition
-                     0,                 // no flags
-                     NULL               // no template file
+                     filename,                      // name
+                     mode == Read ? GENERIC_READ    // access mask 
+                                  : GENERIC_WRITE,
+                     0,                             // no sharing
+                     NULL,                          // no secutity attr
+                     OPEN_EXISTING,                 // creation disposition
+                     0,                             // no flags
+                     NULL                           // no template file
                     );
 
         if ( m_hFile == INVALID_HANDLE_VALUE )
         {
-            wxLogSysError(_("Failed to open '%s' for reading"),
-                          filename.c_str());
+            wxLogSysError(_("Failed to open '%s' for %s"),
+                          filename.c_str(),
+                          mode == Read ? _("reading") : _("writing"));
         }
     }
 
@@ -187,32 +195,46 @@ private:
 // convert between wxDateTime and FILETIME which is a 64-bit value representing
 // the number of 100-nanosecond intervals since January 1, 1601.
 
-// the number of milliseconds between the Unix Epoch (January 1, 1970) and the
-// FILETIME reference point (January 1, 1601)
-static const wxLongLong FILETIME_EPOCH_OFFSET = wxLongLong(0xa97, 0x30b66800);
-
 static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft)
 {
-    wxLongLong ll(ft.dwHighDateTime, ft.dwLowDateTime);
-
-    // convert 100ns to ms
-    ll /= 10000;
+    FILETIME ftcopy = ft;
+    FILETIME ftLocal;
+    if ( !::FileTimeToLocalFileTime(&ftcopy, &ftLocal) )
+    {
+        wxLogLastError(_T("FileTimeToLocalFileTime"));
+    }
 
-    // move it to our Epoch
-    ll -= FILETIME_EPOCH_OFFSET;
+    SYSTEMTIME st;
+    if ( !::FileTimeToSystemTime(&ftLocal, &st) )
+    {
+        wxLogLastError(_T("FileTimeToSystemTime"));
+    }
 
-    *dt = wxDateTime(ll);
+    dt->Set(st.wDay, wxDateTime::Month(st.wMonth - 1), st.wYear,
+            st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
 }
 
 static void ConvertWxToFileTime(FILETIME *ft, const wxDateTime& dt)
 {
-    // do the reverse of ConvertFileTimeToWx()
-    wxLongLong ll = dt.GetValue();
-    ll *= 10000;
-    ll += FILETIME_EPOCH_OFFSET;
+    SYSTEMTIME st;
+    st.wDay = dt.GetDay();
+    st.wMonth = dt.GetMonth() + 1;
+    st.wYear = dt.GetYear();
+    st.wHour = dt.GetHour();
+    st.wMinute = dt.GetMinute();
+    st.wSecond = dt.GetSecond();
+    st.wMilliseconds = dt.GetMillisecond();
+
+    FILETIME ftLocal;
+    if ( !::SystemTimeToFileTime(&st, &ftLocal) )
+    {
+        wxLogLastError(_T("SystemTimeToFileTime"));
+    }
 
-    ft->dwHighDateTime = ll.GetHi();
-    ft->dwLowDateTime = ll.GetLo();
+    if ( !::LocalFileTimeToFileTime(&ftLocal, ft) )
+    {
+        wxLogLastError(_T("LocalFileTimeToFileTime"));
+    }
 }
 
 #endif // __WIN32__
@@ -231,7 +253,7 @@ void wxFileName::Assign( const wxFileName &filepath )
     m_dirs = filepath.GetDirs();
     m_name = filepath.GetName();
     m_ext = filepath.GetExt();
-    m_relative = filepath.IsRelative();
+    m_relative = filepath.m_relative;
 }
 
 void wxFileName::Assign(const wxString& volume,
@@ -249,19 +271,21 @@ void wxFileName::Assign(const wxString& volume,
 
 void wxFileName::SetPath( const wxString &path, wxPathFormat format )
 {
-    wxPathFormat my_format = GetFormat( format );
-    wxString my_path = path;
-
     m_dirs.Clear();
 
-    if (!my_path.empty())
+    if ( !path.empty() )
     {
+        wxPathFormat my_format = GetFormat( format );
+        wxString my_path = path;
+
         // 1) Determine if the path is relative or absolute.
+        wxChar leadingChar = my_path[0u];
 
         switch (my_format)
         {
             case wxPATH_MAC:
-                m_relative = ( my_path[0u] == wxT(':') );
+                m_relative = leadingChar == 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
@@ -273,18 +297,23 @@ void wxFileName::SetPath( const wxString &path, wxPathFormat format )
                 // actually means <UP>, whereas under DOS, double
                 // slashes can be ignored: "\\\\" is the same as "\\".
                 if (m_relative)
-                    my_path.Remove( 0, 1 );
+                    my_path.erase( 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('/') );
+                // the paths of the form "~" or "~username" are absolute
+                m_relative = leadingChar != wxT('/') && leadingChar != _T('~');
                 break;
+
             case wxPATH_DOS:
-                m_relative = ( (my_path[0u] != wxT('/')) && (my_path[0u] != wxT('\\')) );
+                m_relative = !IsPathSeparator(leadingChar, my_format);
                 break;
+
             default:
                 wxFAIL_MSG( wxT("error") );
                 break;
@@ -314,7 +343,7 @@ void wxFileName::SetPath( const wxString &path, wxPathFormat format )
             }
         }
     }
-    else
+    else // no path at all
     {
         m_relative = TRUE;
     }
@@ -359,7 +388,7 @@ 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 path */, &name, &ext, format); 
     SplitPath(fullpath, &volume, &path, NULL, NULL, format);
 #endif // __WXDEBUG__/!__WXDEBUG__
 
@@ -510,6 +539,12 @@ wxFileName::CreateTempFileName(const wxString& prefix, wxFile *fileTemp)
             dir = _T('.');
         }
     }
+    else // we have a dir to create the file in
+    {
+        // ensure we use only the back slashes as GetTempFileName(), unlike all
+        // the other APIs, is picky and doesn't accept the forward ones
+        dir.Replace(_T("/"), _T("\\"));
+    }
 
     if ( !::GetTempFileName(dir, name, 0, wxStringBuffer(path, MAX_PATH + 1)) )
     {
@@ -732,7 +767,7 @@ bool wxFileName::Rmdir( const wxString &dir )
 // path normalization
 // ----------------------------------------------------------------------------
 
-bool wxFileName::Normalize(wxPathNormalize flags,
+bool wxFileName::Normalize(int flags,
                            const wxString& cwd,
                            wxPathFormat format)
 {
@@ -745,7 +780,7 @@ bool wxFileName::Normalize(wxPathNormalize flags,
     format = GetFormat(format);
 
     // make the path absolute
-    if ( (flags & wxPATH_NORM_ABSOLUTE) && m_relative )
+    if ( (flags & wxPATH_NORM_ABSOLUTE) && !IsAbsolute(format) )
     {
         if ( cwd.empty() )
         {
@@ -756,7 +791,6 @@ bool wxFileName::Normalize(wxPathNormalize flags,
             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
@@ -764,14 +798,12 @@ bool wxFileName::Normalize(wxPathNormalize flags,
         {
             SetVolume(curDir.GetVolume());
 
-            if ( IsAbsolute() )
+            if ( !m_relative )
             {
                 // yes, it was the case - we don't need curDir then
                 curDir.Clear();
             }
         }
-#endif
-        m_relative = FALSE;
     }
 
     // handle ~ stuff under Unix only
@@ -859,6 +891,31 @@ bool wxFileName::Normalize(wxPathNormalize flags,
     }
 #endif // Win32
 
+    // we do have the path now
+    m_relative = FALSE;
+
+    return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// absolute/relative paths
+// ----------------------------------------------------------------------------
+
+bool wxFileName::IsAbsolute(wxPathFormat format) const
+{
+    // if our path doesn't start with a path separator, it's not an absolute
+    // path
+    if ( m_relative )
+        return FALSE;
+
+    if ( !GetVolumeSeparator(format).empty() )
+    {
+        // this format has volumes and an absolute path must have one, it's not
+        // enough to have the full path to bean absolute file under Windows
+        if ( GetVolume().empty() )
+            return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -898,6 +955,17 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format)
         m_dirs.Insert(wxT(".."), 0u);
     }
 
+    if ( format == wxPATH_UNIX || format == wxPATH_DOS )
+    {
+        // a directory made relative with respect to itself is '.' under Unix
+        // and DOS, by definition (but we don't have to insert "./" for the
+        // files)
+        if ( m_dirs.IsEmpty() && IsDir() )
+        {
+            m_dirs.Add(_T('.'));
+        }   
+    }
+
     m_relative = TRUE;
 
     // we were modified
@@ -991,14 +1059,6 @@ bool wxFileName::IsPathSeparator(wxChar ch, wxPathFormat format)
     return GetPathSeparators(format).Find(ch) != wxNOT_FOUND;
 }
 
-bool wxFileName::IsWild( wxPathFormat format )
-{
-    // FIXME: this is probably false for Mac and this is surely wrong for most
-    //        of Unix shells (think about "[...]")
-    (void)format;
-    return m_name.find_first_of(_T("*?")) != wxString::npos;
-}
-
 // ----------------------------------------------------------------------------
 // path components manipulation
 // ----------------------------------------------------------------------------
@@ -1120,7 +1180,10 @@ wxString wxFileName::GetPath( bool add_separator, wxPathFormat format ) const
         }
     }
 
-
+    if ( add_separator && !fullpath.empty() )
+    {
+        fullpath += GetPathSeparators(format)[0u];
+    }
 
     return fullpath;
 }
@@ -1152,19 +1215,27 @@ wxString wxFileName::GetFullPath( wxPathFormat format ) const
     }
 
     // the leading character
-    if ( format == wxPATH_MAC && m_relative )
+    if ( format == wxPATH_MAC )
     {
-         fullpath += wxFILE_SEP_PATH_MAC;
+        if ( m_relative )
+            fullpath += wxFILE_SEP_PATH_MAC;
     }
     else if ( format == wxPATH_DOS )
     {
-         if (!m_relative)
-             fullpath += wxFILE_SEP_PATH_DOS;
+        if ( !m_relative )
+            fullpath += wxFILE_SEP_PATH_DOS;
     }
     else if ( format == wxPATH_UNIX )
     {
-         if (!m_relative)
-             fullpath += wxFILE_SEP_PATH_UNIX;
+        if ( !m_relative )
+        {
+            // normally the absolute file names starts with a slash with one
+            // exception: file names like "~/foo.bar" don't have it
+            if ( m_dirs.IsEmpty() || m_dirs[0u] != _T('~') )
+            {
+                fullpath += wxFILE_SEP_PATH_UNIX;
+            }
+        }
     }
 
     // then concatenate all the path components using the path separator
@@ -1264,7 +1335,7 @@ wxString wxFileName::GetLongPath() const
 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
     bool success = FALSE;
 
-    // VZ: this code was disabled, why?
+    // VZ: why was this code disabled?
 #if 0 // wxUSE_DYNAMIC_LOADER
     typedef DWORD (*GET_LONG_PATH_NAME)(const wxChar *, wxChar *, DWORD);
 
@@ -1559,9 +1630,9 @@ void wxFileName::SplitPath(const wxString& fullpath,
 // time functions
 // ----------------------------------------------------------------------------
 
-bool wxFileName::SetTimes(const wxDateTime *dtCreate,
-                          const wxDateTime *dtAccess,
-                          const wxDateTime *dtMod)
+bool wxFileName::SetTimes(const wxDateTime *dtAccess,
+                          const wxDateTime *dtMod,
+                          const wxDateTime *dtCreate)
 {
 #if defined(__UNIX_LIKE__) || (defined(__DOS__) && defined(__WATCOMC__))
     if ( !dtAccess && !dtMod )
@@ -1580,7 +1651,7 @@ bool wxFileName::SetTimes(const wxDateTime *dtCreate,
         return TRUE;
     }
 #elif defined(__WIN32__)
-    wxFileHandle fh(GetFullPath());
+    wxFileHandle fh(GetFullPath(), wxFileHandle::Write);
     if ( fh.IsOk() )
     {
         FILETIME ftAccess, ftCreate, ftWrite;
@@ -1624,13 +1695,13 @@ bool wxFileName::Touch()
 #else // other platform
     wxDateTime dtNow = wxDateTime::Now();
 
-    return SetTimes(NULL /* don't change create time */, &dtNow, &dtNow);
+    return SetTimes(&dtNow, &dtNow, NULL /* don't change create time */);
 #endif // platforms
 }
 
 bool wxFileName::GetTimes(wxDateTime *dtAccess,
                           wxDateTime *dtMod,
-                          wxDateTime *dtChange) const
+                          wxDateTime *dtCreate) const
 {
 #if defined(__UNIX_LIKE__) || defined(__WXMAC__) || (defined(__DOS__) && defined(__WATCOMC__))
     wxStructStat stBuf;
@@ -1640,13 +1711,13 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
             dtAccess->Set(stBuf.st_atime);
         if ( dtMod )
             dtMod->Set(stBuf.st_mtime);
-        if ( dtChange )
-            dtChange->Set(stBuf.st_ctime);
+        if ( dtCreate )
+            dtCreate->Set(stBuf.st_ctime);
 
         return TRUE;
     }
 #elif defined(__WIN32__)
-    wxFileHandle fh(GetFullPath());
+    wxFileHandle fh(GetFullPath(), wxFileHandle::Read);
     if ( fh.IsOk() )
     {
         FILETIME ftAccess, ftCreate, ftWrite;
@@ -1654,14 +1725,14 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess,
         if ( ::GetFileTime(fh,
                            dtMod ? &ftCreate : NULL,
                            dtAccess ? &ftAccess : NULL,
-                           dtChange ? &ftWrite : NULL) )
+                           dtCreate ? &ftWrite : NULL) )
         {
             if ( dtMod )
                 ConvertFileTimeToWx(dtMod, ftCreate);
             if ( dtAccess )
                 ConvertFileTimeToWx(dtAccess, ftAccess);
-            if ( dtChange )
-                ConvertFileTimeToWx(dtChange, ftWrite);
+            if ( dtCreate )
+                ConvertFileTimeToWx(dtCreate, ftWrite);
 
             return TRUE;
         }
@@ -1776,4 +1847,3 @@ void wxFileName::MacRegisterDefaultTypeAndCreator( const wxString& ext , wxUint3
   gMacDefaultExtensions.Add( rec ) ;
 }
 #endif
-