From 82929611ba2a996c8e3425ed352da7a053cd7c3d Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Mon, 12 Oct 2015 23:49:04 +0200 Subject: tdf#94804 sw: allow duplicate heading cross reference bookmarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... in ODF import, so that reference fields do not break that reference numbering cross reference bookmarks that were corrupted by commit 679faffc68bb854af0f55d0f218698e2f372f00b. This used to work by accident before commit 9d0c51daea67104349cac26de9839afa8baeb099 fixed it to actually check for duplicates properly. (cherry picked from commit 7c3c3006deaaaf1bb3f2f4eeeaf11da3bcebe53c) Change-Id: I5ed58eda7f3f2ce470a778852f6dda7a14356860 Reviewed-on: https://gerrit.libreoffice.org/19339 Reviewed-by: Caolán McNamara Tested-by: Caolán McNamara (cherry picked from commit e95b9fd796e3a52afbb52bc142019115653c6099) --- sw/inc/IDocumentMarkAccess.hxx | 2 +- .../odfexport/data/CrossRefHeadingBookmark.fodt | 120 +++++++++++++++++++++ sw/qa/extras/odfexport/odfexport.cxx | 30 ++++++ sw/source/core/doc/docbm.cxx | 6 +- sw/source/core/inc/MarkManager.hxx | 2 +- sw/source/core/unocore/unobkm.cxx | 9 +- 6 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 sw/qa/extras/odfexport/data/CrossRefHeadingBookmark.fodt diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index e7500feafe31..0bd2add3aabe 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -77,7 +77,7 @@ class IDocumentMarkAccess */ virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const OUString& rProposedName, - MarkType eMark) =0; + MarkType eMark, bool = false) = 0; virtual sw::mark::IFieldmark* makeFieldBookmark( const SwPaM& rPaM, const OUString& rName, diff --git a/sw/qa/extras/odfexport/data/CrossRefHeadingBookmark.fodt b/sw/qa/extras/odfexport/data/CrossRefHeadingBookmark.fodt new file mode 100644 index 000000000000..64d6205372d5 --- /dev/null +++ b/sw/qa/extras/odfexport/data/CrossRefHeadingBookmark.fodt @@ -0,0 +1,120 @@ + + + + ms 2015-08-24T21:49:45.305718699LibreOfficeDev/4.3.7.2$Linux_X86_64 LibreOffice_project/8a35821d8636a03b8bf4e15b48f59794652c68ba + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text + + + cross-reference to 1.1 (Numbered paragraph - Number) and 1.1(Numbered paragraph - no context) + + + + + + + diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx index 22083c7292bd..ace9e355317f 100644 --- a/sw/qa/extras/odfexport/odfexport.cxx +++ b/sw/qa/extras/odfexport/odfexport.cxx @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -212,6 +213,35 @@ DECLARE_ODFEXPORT_TEST(testTextframeGradient, "textframe-gradient.odt") CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_AXIAL, aGradient.Style); } +DECLARE_ODFEXPORT_TEST(testDuplicateCrossRefHeadingBookmark, "CrossRefHeadingBookmark.fodt") +{ + // the file contains invalid duplicate heading cross reference bookmarks + // but we have to round trip them, tdf#94804 + + uno::Reference xBookmarksSupplier(mxComponent, + uno::UNO_QUERY); + uno::Reference xBookmarks( + xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY); + uno::Reference xBookmark1( + xBookmarks->getByName("__RefHeading__8284_1826734303"), uno::UNO_QUERY); + CPPUNIT_ASSERT(xBookmark1.is()); + uno::Reference xBookmark2( + xBookmarks->getByName("__RefHeading__1673_25705824"), uno::UNO_QUERY); + CPPUNIT_ASSERT(xBookmark2.is()); + + uno::Reference xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY)->refresh(); + + uno::Reference xFieldsAccess(xTextFieldsSupplier->getTextFields()); + uno::Reference xFields(xFieldsAccess->createEnumeration()); + uno::Any aField1 = xFields->nextElement(); + uno::Reference xField1(aField1, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("1.1"), xField1->getPresentation(false)); + uno::Any aField2 = xFields->nextElement(); + uno::Reference xField2(aField2, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString("1.1"), xField2->getPresentation(false)); +} + DECLARE_ODFEXPORT_TEST(testFdo60769, "fdo60769.odt") { // Test multi-paragraph comment range feature. diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index ce0ff19b1b3f..ae6342e989e4 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -354,7 +354,8 @@ namespace sw { namespace mark ::sw::mark::IMark* MarkManager::makeMark(const SwPaM& rPaM, const OUString& rName, - const IDocumentMarkAccess::MarkType eType) + const IDocumentMarkAccess::MarkType eType, + bool const isHorribleHackIgnoreDuplicates) { #if 0 { @@ -377,7 +378,8 @@ namespace sw { namespace mark " - more than USHRT_MAX marks are not supported correctly"); // There should only be one CrossRefBookmark per Textnode per Type if ((eType == CROSSREF_NUMITEM_BOOKMARK || eType == CROSSREF_HEADING_BOOKMARK) - && (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.Start(), eType) != m_vBookmarks.end())) + && (lcl_FindMarkAtPos(m_vBookmarks, *rPaM.Start(), eType) != m_vBookmarks.end()) + && !isHorribleHackIgnoreDuplicates) { // this can happen via UNO API SAL_WARN("sw.core", "MarkManager::makeMark(..)" " - refusing to create duplicate CrossRefBookmark"); diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index 52fea0a07d91..74e37c1ee92d 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -35,7 +35,7 @@ namespace sw { public: MarkManager(/*[in/out]*/ SwDoc& rDoc); // IDocumentMarkAccess - virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const OUString& rName, IDocumentMarkAccess::MarkType eMark) SAL_OVERRIDE; + virtual ::sw::mark::IMark* makeMark(const SwPaM& rPaM, const OUString& rName, IDocumentMarkAccess::MarkType eMark, bool = false) SAL_OVERRIDE; virtual sw::mark::IFieldmark* makeFieldBookmark( const SwPaM& rPaM, const OUString& rName, diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx index 2f252f99d1a3..65d2168ce04b 100644 --- a/sw/source/core/unocore/unobkm.cxx +++ b/sw/source/core/unocore/unobkm.cxx @@ -225,6 +225,7 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) SwUnoInternalPaM aPam(*m_pImpl->m_pDoc); ::sw::XTextRangeToSwPaM(aPam, xTextRange); UnoActionContext aCont(m_pImpl->m_pDoc); + bool isHorribleHackIgnoreDuplicates(false); if (m_pImpl->m_sMarkName.isEmpty()) { m_pImpl->m_sMarkName = "Bookmark"; @@ -239,10 +240,16 @@ throw (lang::IllegalArgumentException, uno::RuntimeException) IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( aPam ) ) { eType = IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK; + // tdf#94804 LO 4.2-5.0 create invalid duplicates that must be preserved + // note: do not check meta:generator, may be preserved by other versions + if (m_pImpl->m_pDoc->IsInXMLImport()) + { + isHorribleHackIgnoreDuplicates = true; + } } m_pImpl->registerInMark(*this, m_pImpl->m_pDoc->getIDocumentMarkAccess()->makeMark( - aPam, m_pImpl->m_sMarkName, eType)); + aPam, m_pImpl->m_sMarkName, eType, isHorribleHackIgnoreDuplicates)); // #i81002# // Check, if bookmark has been created. // E.g., the creation of a cross-reference bookmark is suppress, -- cgit v1.2.3