summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx57
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx43
-rw-r--r--sw/source/core/inc/DocumentContentOperationsManager.hxx2
3 files changed, 94 insertions, 8 deletions
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 006cb469d9fd..364439b7ba56 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -67,6 +67,7 @@ public:
//EDITING: undo search&replace corrupt text when searching backward
void testReplaceBackward();
void testRedlineFrame();
+ void testBookmarkCopy();
void testFdo69893();
void testFdo70807();
void testImportRTF();
@@ -108,6 +109,7 @@ public:
CPPUNIT_TEST(testReplaceForward);
CPPUNIT_TEST(testReplaceBackward);
CPPUNIT_TEST(testRedlineFrame);
+ CPPUNIT_TEST(testBookmarkCopy);
CPPUNIT_TEST(testFdo69893);
CPPUNIT_TEST(testFdo70807);
CPPUNIT_TEST(testImportRTF);
@@ -221,6 +223,61 @@ void SwUiWriterTest::testRedlineFrame()
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xDrawPage->getCount());
}
+void SwUiWriterTest::testBookmarkCopy()
+{
+ SwDoc * pDoc(createDoc());
+
+ // add text and bookmark
+ IDocumentMarkAccess & rIDMA(*pDoc->getIDocumentMarkAccess());
+ IDocumentContentOperations & rIDCO(pDoc->getIDocumentContentOperations());
+ SwNodeIndex aIdx(pDoc->GetNodes().GetEndOfContent(), -1);
+ SwCursor aPaM(SwPosition(aIdx), nullptr, false);
+ rIDCO.InsertString(aPaM, OUString("foo"));
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ rIDCO.InsertString(aPaM, OUString("bar"));
+ aPaM.SetMark();
+ aPaM.MovePara(GetfnParaCurr(), GetfnParaStart());
+ rIDMA.makeMark(aPaM, OUString("Mark"), IDocumentMarkAccess::MarkType::BOOKMARK);
+ aPaM.Exchange();
+ aPaM.DeleteMark();
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ rIDCO.InsertString(aPaM, OUString("baz"));
+
+ // copy range
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ SwPosition target(*aPaM.GetPoint());
+ aPaM.Move(fnMoveBackward, fnGoContent);
+ aPaM.SetMark();
+ aPaM.SttEndDoc(true/*start*/);
+ aPaM.Move(fnMoveForward, fnGoContent); // partially select 1st para
+
+ rIDCO.CopyRange(aPaM, target, /*bCopyAll=*/false, /*bCheckPos=*/true);
+
+ // check bookmark was copied to correct position
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), rIDMA.getBookmarksCount());
+ for (auto it(rIDMA.getBookmarksBegin()); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ OUString markText(SwPaM((*it)->GetMarkPos(), (*it)->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), markText);
+ }
+
+ // copy 2nd time, such that bCanMoveBack is false in CopyImpl
+ SwPaM aCopyPaM(*aPaM.GetMark(), *aPaM.GetPoint());
+ aPaM.SttEndDoc(true/*start*/);
+ rIDCO.SplitNode(*aPaM.GetPoint(), false);
+ aPaM.SttEndDoc(true/*start*/);
+
+ rIDCO.CopyRange(aCopyPaM, *aPaM.GetPoint(), /*bCopyAll=*/false, /*bCheckPos=*/true);
+
+ // check bookmark was copied to correct position
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), rIDMA.getBookmarksCount());
+ for (auto it(rIDMA.getBookmarksBegin()); it != rIDMA.getBookmarksEnd(); ++it)
+ {
+ OUString markText(SwPaM((*it)->GetMarkPos(), (*it)->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), markText);
+ }
+}
+
void SwUiWriterTest::testFdo75110()
{
SwDoc* pDoc = createDoc("fdo75110.odt");
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 1f387f4d7d26..77228f05caa3 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3129,11 +3129,14 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
const SwNodeRange& rRg,
const sal_Int32 nEndContentIndex,
const SwNodeIndex& rInsPos,
- const SwPaM* pCopiedPaM,
+ const std::pair<const SwPaM&, const SwPosition&>* pCopiedPaM /*and real insert pos*/,
const bool bMakeNewFrms,
const bool bDelRedlines,
const bool bCopyFlyAtFly ) const
{
+ assert(!pCopiedPaM || pCopiedPaM->first.End()->nContent == nEndContentIndex);
+ assert(!pCopiedPaM || pCopiedPaM->first.End()->nNode == rRg.aEnd);
+
SwDoc* pDest = rInsPos.GetNode().GetDoc();
_SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
@@ -3176,14 +3179,24 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
SwNodeRange aCpyRange( aSavePos, rInsPos );
// Also copy all bookmarks
+ // guess this must be done before the _DelDummyNodes below as that
+ // deletes nodes so would mess up the index arithmetic
if( m_rDoc.getIDocumentMarkAccess()->getAllMarksCount() )
{
SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
- SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
+ SwPaM aCpyPaM(aCpyRange.aStart, aCpyRange.aEnd);
+ if (pCopiedPaM && rRg.aStart != pCopiedPaM->first.Start()->nNode)
+ {
+ // there is 1 (partially selected, maybe) paragraph before
+ assert(SwNodeIndex(rRg.aStart, -1) == pCopiedPaM->first.Start()->nNode);
+ // only use the passed in target SwPosition if the source PaM point
+ // is on a different node; if it was the same node then the target
+ // position was likely moved along by the copy operation and now
+ // points to the end of the range!
+ *aCpyPaM.GetPoint() = pCopiedPaM->second;
+ }
- lcl_CopyBookmarks(
- pCopiedPaM != NULL ? *pCopiedPaM : aRgTmp,
- aCpyTmp );
+ lcl_CopyBookmarks((pCopiedPaM) ? pCopiedPaM->first : aRgTmp, aCpyPaM);
}
if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->getIDocumentRedlineAccess().GetRedlineMode() ))
@@ -3192,6 +3205,12 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
pDest->GetNodes()._DelDummyNodes( aCpyRange );
}
+// TODO: there is a limitation here in that it's not possible to pass a start
+// content index - which means that at-character anchored frames inside
+// partial 1st paragraph of redline is not copied.
+// But the DelFlyInRange() that is called from DelCopyOfSection() does not
+// delete it either, and it also does not delete those on partial last para of
+// redline, so copying those is supressed here too ...
void DocumentContentOperationsManager::CopyFlyInFlyImpl(
const SwNodeRange& rRg,
const sal_Int32 nEndContentIndex,
@@ -4388,16 +4407,26 @@ bool DocumentContentOperationsManager::CopyImpl( SwPaM& rPam, SwPosition& rPos,
pDestTextNd->ResetAttr( RES_PAGEDESC );
}
+ SwPosition startPos(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1),
+ SwIndex(SwNodeIndex(pCopyPam->GetPoint()->nNode, +1).GetNode().GetContentNode()));
+ if (bCanMoveBack)
+ { // pCopyPam is actually 1 before the copy range so move it fwd
+ SwPaM temp(*pCopyPam->GetPoint());
+ temp.Move(fnMoveForward, fnGoContent);
+ startPos = *temp.GetPoint();
+ }
+ assert(startPos.nNode.GetNode().IsContentNode());
+ std::pair<SwPaM const&, SwPosition const&> tmp(rPam, startPos);
if( aInsPos == pEnd->nNode )
{
SwNodeIndex aSaveIdx( aInsPos, -1 );
- CopyWithFlyInFly( aRg, 0,aInsPos, &rPam, bMakeNewFrms, false );
+ CopyWithFlyInFly( aRg, 0, aInsPos, &tmp, bMakeNewFrms, false );
++aSaveIdx;
pEnd->nNode = aSaveIdx;
pEnd->nContent.Assign( aSaveIdx.GetNode().GetTextNode(), 0 );
}
else
- CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &rPam, bMakeNewFrms, false );
+ CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, &tmp, bMakeNewFrms, false );
bCopyBookmarks = false;
diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index 44560fc14840..b6753a582385 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -103,7 +103,7 @@ public:
void CopyWithFlyInFly( const SwNodeRange& rRg,
const sal_Int32 nEndContentIndex,
const SwNodeIndex& rInsPos,
- const SwPaM* pCopiedPaM = NULL,
+ const std::pair<const SwPaM&, const SwPosition&> * pCopiedPaM = nullptr,
bool bMakeNewFrms = true,
bool bDelRedlines = true,
bool bCopyFlyAtFly = false ) const;