diff options
-rw-r--r-- | sw/inc/IDocumentContentOperations.hxx | 3 | ||||
-rw-r--r-- | sw/qa/core/doc/data/copy-flag-skip-bookmarks.docx | bin | 0 -> 14728 bytes | |||
-rw-r--r-- | sw/qa/core/doc/doc.cxx | 16 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 16 | ||||
-rw-r--r-- | sw/source/core/doc/docdesc.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/doc/docfmt.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/inc/DocumentContentOperationsManager.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/unocore/unotext.cxx | 22 | ||||
-rw-r--r-- | writerfilter/source/dmapper/PropertyMap.cxx | 11 |
9 files changed, 64 insertions, 12 deletions
diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx index 5a95d0ba95b8..60d45d47a0a3 100644 --- a/sw/inc/IDocumentContentOperations.hxx +++ b/sw/inc/IDocumentContentOperations.hxx @@ -75,11 +75,12 @@ enum class SwCopyFlags CopyAll = (1<<0), ///< copy break attributes even when source is single node CheckPosInFly = (1<<1), ///< check if target position is in fly anchored at source range IsMoveToFly = (1<<2), ///< MakeFlyAndMove + SkipBookmarks = (1<<3), ///< skip bookmarks, but not other kind of marks // TODO: mbCopyIsMove? mbIsRedlineMove? }; namespace o3tl { - template<> struct typed_flags<SwCopyFlags> : is_typed_flags<SwCopyFlags, 0x07> {}; + template<> struct typed_flags<SwCopyFlags> : is_typed_flags<SwCopyFlags, 0x0f> {}; } enum class SwDeleteFlags diff --git a/sw/qa/core/doc/data/copy-flag-skip-bookmarks.docx b/sw/qa/core/doc/data/copy-flag-skip-bookmarks.docx Binary files differnew file mode 100644 index 000000000000..3fb27b430a17 --- /dev/null +++ b/sw/qa/core/doc/data/copy-flag-skip-bookmarks.docx diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 87bfd2697621..2ee2ee342bd3 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -255,6 +255,22 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testContentControlDelete) CPPUNIT_ASSERT_EQUAL(OUString("\x0001test\x0001"), pTextNode->GetText()); } +CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testCopyFlagSkipBookmarks) +{ + // Given a document with a bookmark in a header that is linked later: + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "copy-flag-skip-bookmarks.docx"); + + // When checking the # of bookmarks in the resulting doc model: + sal_Int32 nActual = pDoc->getIDocumentMarkAccess()->getAllMarksCount(); + + // Then make sure we have a single bookmark, with no duplications: + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. the 2nd header had a duplicated bookmark. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nActual); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index c642cde1c8c7..62c362eba181 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -232,7 +232,7 @@ namespace namespace sw { // TODO: use SaveBookmark (from DelBookmarks) - void CopyBookmarks(const SwPaM& rPam, const SwPosition& rCpyPam) + void CopyBookmarks(const SwPaM& rPam, const SwPosition& rCpyPam, SwCopyFlags eFlags) { const SwDoc& rSrcDoc = rPam.GetDoc(); SwDoc& rDestDoc = rCpyPam.GetDoc(); @@ -283,6 +283,7 @@ namespace sw // We have to count the "non-copied" nodes... SwNodeOffset nDelCount; SwNodeIndex aCorrIdx(InitDelCount(rPam, nDelCount)); + auto bSkipBookmarks = static_cast<bool>(eFlags & SwCopyFlags::SkipBookmarks); for(const sw::mark::IMark* const pMark : vMarksToCopy) { SwPaM aTmpPam(*pCpyStt); @@ -295,10 +296,17 @@ namespace sw lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount); } + IDocumentMarkAccess::MarkType eType = IDocumentMarkAccess::GetType(*pMark); + if (bSkipBookmarks && eType == IDocumentMarkAccess::MarkType::BOOKMARK) + { + // It was requested to skip bookmarks while copying. Do that, but continue to copy + // other kind of marks, like fieldmarks. + continue; + } ::sw::mark::IMark* const pNewMark = rDestDoc.getIDocumentMarkAccess()->makeMark( aTmpPam, pMark->GetName(), - IDocumentMarkAccess::GetType(*pMark), + eType, ::sw::mark::InsertMode::CopyText); // Explicitly try to get exactly the same name as in the source // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name @@ -3672,7 +3680,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly( targetPos = pCopiedPaM->second; } - sw::CopyBookmarks(pCopiedPaM ? pCopiedPaM->first : aRgTmp, targetPos); + sw::CopyBookmarks(pCopiedPaM ? pCopiedPaM->first : aRgTmp, targetPos, flags); } if (rRg.aStart != rRg.aEnd) @@ -5301,7 +5309,7 @@ bool DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo // Also copy all bookmarks if( bCopyBookmarks && m_rDoc.getIDocumentMarkAccess()->getAllMarksCount() ) { - sw::CopyBookmarks(rPam, *pCopyPam->Start()); + sw::CopyBookmarks(rPam, *pCopyPam->Start(), SwCopyFlags::Default); } if( RedlineFlags::DeleteRedlines & eOld ) diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx index d75caf8cac0b..a5642f053b7c 100644 --- a/sw/source/core/doc/docdesc.cxx +++ b/sw/source/core/doc/docdesc.cxx @@ -302,7 +302,7 @@ void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHe GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, *pSttNd); SwPaM const source(aRange.aStart, aRange.aEnd); SwPosition dest(*pSttNd); - sw::CopyBookmarks(source, dest); + sw::CopyBookmarks(source, dest, SwCopyFlags::Default); pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); rDescFrameFormat.SetFormatAttr( SwFormatHeader( pFormat ) ); } @@ -379,7 +379,7 @@ void SwDoc::CopyMasterFooter(const SwPageDesc &rChged, const SwFormatFooter &rFo GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, *pSttNd); SwPaM const source(aRange.aStart, aRange.aEnd); SwPosition dest(*pSttNd); - sw::CopyBookmarks(source, dest); + sw::CopyBookmarks(source, dest, SwCopyFlags::Default); pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); rDescFrameFormat.SetFormatAttr( SwFormatFooter( pFormat ) ); } diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx index 357ca66aeb8d..51c0e935e7b2 100644 --- a/sw/source/core/doc/docfmt.cxx +++ b/sw/source/core/doc/docfmt.cxx @@ -1406,7 +1406,7 @@ void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader, // TODO: investigate calling CopyWithFlyInFly? SwPaM const source(aRg.aStart, aRg.aEnd); SwPosition dest(*pSttNd); - sw::CopyBookmarks(source, dest); + sw::CopyBookmarks(source, dest, SwCopyFlags::Default); pNewFormat->SetFormatAttr( SwFormatContent( pSttNd )); } else diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx index 49473930f7fe..d2b61500c8c6 100644 --- a/sw/source/core/inc/DocumentContentOperationsManager.hxx +++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx @@ -182,7 +182,7 @@ private: }; -void CopyBookmarks(const SwPaM& rPam, const SwPosition& rTarget); +void CopyBookmarks(const SwPaM& rPam, const SwPosition& rTarget, SwCopyFlags eFlags); void CalcBreaks(std::vector<std::pair<SwNodeOffset, sal_Int32>> & rBreaks, SwPaM const & rPam, bool const isOnlyFieldmarks = false); diff --git a/sw/source/core/unocore/unotext.cxx b/sw/source/core/unocore/unotext.cxx index c68a1a331c90..5d65f5ef8b63 100644 --- a/sw/source/core/unocore/unotext.cxx +++ b/sw/source/core/unocore/unotext.cxx @@ -86,6 +86,7 @@ public: const CursorType m_eType; SwDoc * m_pDoc; bool m_bIsValid; + bool m_bCopySkipsBookmarks; Impl( SwXText & rThis, SwDoc *const pDoc, const CursorType eType) @@ -94,6 +95,7 @@ public: , m_eType(eType) , m_pDoc(pDoc) , m_bIsValid(nullptr != pDoc) + , m_bCopySkipsBookmarks(false) { } @@ -1121,9 +1123,18 @@ SwXText::getPropertySetInfo() } void SAL_CALL -SwXText::setPropertyValue(const OUString& /*aPropertyName*/, - const uno::Any& /*aValue*/) +SwXText::setPropertyValue(const OUString& aPropertyName, + const uno::Any& aValue) { + if (aPropertyName == "CopySkipsBookmarks") + { + bool bValue{}; + if (aValue >>= bValue) + { + m_pImpl->m_bCopySkipsBookmarks = bValue; + } + return; + } throw lang::IllegalArgumentException(); } @@ -2402,7 +2413,12 @@ SwXText::copyText( // Explicitly request copy text mode, so // sw::DocumentContentOperationsManager::CopyFlyInFlyImpl() will copy shapes anchored to // us, even if we have only a single paragraph. - m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, SwCopyFlags::CheckPosInFly); + SwCopyFlags eFlags = SwCopyFlags::CheckPosInFly; + if (m_pImpl->m_bCopySkipsBookmarks) + { + eFlags |= SwCopyFlags::SkipBookmarks; + } + m_pImpl->m_pDoc->getIDocumentContentOperations().CopyRange(temp, rPos, eFlags); } if (!pFirstNode) { // the node at rPos was split; get rid of the first empty one so diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index eec9b678a209..e848a5780ebf 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -874,7 +874,18 @@ void SectionPropertyMap::CopyHeaderFooterTextProperty( const uno::Reference< bea if ( xPrevStyle.is() ) xPrevTxt.set( xPrevStyle->getPropertyValue( sName ), uno::UNO_QUERY_THROW ); + uno::Reference<beans::XPropertySet> xTxtProps(xTxt, uno::UNO_QUERY); + if (xTxtProps.is()) + { + // Skip copying bookmarks, so the number of bookmarks in the source document and in the + // resulting doc model match. + xTxtProps->setPropertyValue("CopySkipsBookmarks", uno::Any(true)); + } xTxt->copyText( xPrevTxt ); + if (xTxtProps.is()) + { + xTxtProps->setPropertyValue("CopySkipsBookmarks", uno::Any(false)); + } } catch ( const uno::Exception& ) { |