diff --git a/docs/changes.txt b/docs/changes.txt index eb5982c033..ab1c99876b 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -612,6 +612,7 @@ wxMSW: - Fix order of radial gradient stops (Alexandru Pana). - Fix font created using wxFont(wxFontInfo()) ctor. - Fix wxFileName::GetShortcutTarget() in console applications. +- Fix wxFileName::MakeRelativeTo() for shortcut files (gafatoa). 3.0.1: (released 2014-06-15) diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 51e80c1c83..fcbc0e7206 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -1797,8 +1797,13 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format) // get cwd only once - small time saving wxString cwd = wxGetCwd(); - Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); - fnBase.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, cwd, format); + + // Normalize the paths but avoid changing the case or turning a shortcut + // into a file that it points to. + const int normFlags = wxPATH_NORM_ALL & + ~(wxPATH_NORM_CASE | wxPATH_NORM_SHORTCUT); + Normalize(normFlags, cwd, format); + fnBase.Normalize(normFlags, cwd, format); bool withCase = IsCaseSensitive(format); diff --git a/tests/filename/filenametest.cpp b/tests/filename/filenametest.cpp index f54e8e8376..29bcfaf685 100644 --- a/tests/filename/filenametest.cpp +++ b/tests/filename/filenametest.cpp @@ -27,6 +27,9 @@ #ifdef __WINDOWS__ #include "wx/msw/registry.h" + #include + #include "wx/msw/ole/oleutils.h" + #include "wx/msw/private/comptr.h" #endif // __WINDOWS__ #ifdef __UNIX__ @@ -145,6 +148,9 @@ private: #if defined(__UNIX__) CPPUNIT_TEST( TestSymlinks ); #endif // __UNIX__ +#ifdef __WINDOWS__ + CPPUNIT_TEST( TestShortcuts ); +#endif // __WINDOWS__ CPPUNIT_TEST_SUITE_END(); void TestConstruction(); @@ -168,6 +174,9 @@ private: #if defined(__UNIX__) void TestSymlinks(); #endif // __UNIX__ +#ifdef __WINDOWS__ + void TestShortcuts(); +#endif // __WINDOWS__ DECLARE_NO_COPY_CLASS(FileNameTestCase) }; @@ -996,3 +1005,53 @@ void FileNameTestCase::TestSymlinks() } #endif // __UNIX__ + +#ifdef __WINDOWS__ + +namespace +{ + +void CreateShortcut(const wxString& pathFile, const wxString& pathLink) +{ + wxOleInitializer oleInit; + + HRESULT hr; + + wxCOMPtr sl; + hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (void **)&sl); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + wxCOMPtr pf; + hr = sl->QueryInterface(IID_IPersistFile, (void **)&pf); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + hr = sl->SetPath(pathFile.wx_str()); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); + + hr = pf->Save(pathLink.wx_str(), TRUE); + CPPUNIT_ASSERT( SUCCEEDED(hr) ); +} + +} // anonymous namespace + +void FileNameTestCase::TestShortcuts() +{ + wxFileName fn(wxFileName::CreateTempFileName("filenametest")); + CPPUNIT_ASSERT( fn.IsOk() ); + wxON_BLOCK_EXIT1( wxRemoveFile, fn.GetFullPath() ); + + wxFileName fnLink(fn.GetPath(), "sc_" + fn.GetName(), "lnk"); + CPPUNIT_ASSERT( fnLink.IsOk() ); + wxON_BLOCK_EXIT1( wxRemoveFile, fnLink.GetFullPath() ); + + CreateShortcut(fn.GetFullPath(), fnLink.GetFullPath()); + + // MakeRelativeTo() is supposed to change only the path of the file, not its + // name. + wxFileName fnLinkRel(fnLink); + fnLink.MakeRelativeTo("."); + CPPUNIT_ASSERT_EQUAL(fnLink.GetFullName(), fnLinkRel.GetFullName()); +} + +#endif // __WINDOWS__