summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/inc/fesh.hxx3
-rw-r--r--sw/qa/core/edit/edit.cxx77
-rw-r--r--sw/source/core/edit/edredln.cxx25
-rw-r--r--sw/source/core/frmedt/fecopy.cxx7
-rw-r--r--sw/source/uibase/dochdl/swdtflvr.cxx12
-rw-r--r--sw/source/uibase/inc/swdtflvr.hxx4
6 files changed, 114 insertions, 14 deletions
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index e5c114474425..6b5dd4e47707 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -256,7 +256,8 @@ public:
virtual ~SwFEShell() override;
/// Copy and Paste methods for internal clipboard.
- SW_DLLPUBLIC void Copy( SwDoc& rClpDoc, const OUString* pNewClpText = nullptr );
+ /// bDeleteRedlines: if content inside a delete redline should be stripped away in rClpDoc.
+ SW_DLLPUBLIC void Copy( SwDoc& rClpDoc, const OUString* pNewClpText = nullptr, bool bDeleteRedlines = true );
SW_DLLPUBLIC bool Paste( SwDoc& rClpDoc, bool bNestedTable = false );
/// Paste some pages into another doc - used in mailmerge.
diff --git a/sw/qa/core/edit/edit.cxx b/sw/qa/core/edit/edit.cxx
index 581fdc3af456..21455842da24 100644
--- a/sw/qa/core/edit/edit.cxx
+++ b/sw/qa/core/edit/edit.cxx
@@ -9,6 +9,8 @@
#include <swmodeltestbase.hxx>
+#include <editeng/wghtitem.hxx>
+
#include <docsh.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
@@ -16,6 +18,7 @@
#include <IDocumentRedlineAccess.hxx>
#include <swmodule.hxx>
#include <redline.hxx>
+#include <ndtxt.hxx>
namespace
{
@@ -205,6 +208,80 @@ CPPUNIT_TEST_FIXTURE(Test, testRedlineReinstateSinglePlainDelete)
CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData2.GetType());
}
+CPPUNIT_TEST_FIXTURE(Test, testRedlineReinstateSingleRichDelete)
+{
+ // Given a document: a<del>b<b>c\nd</b>e</del>f:
+ createSwDoc();
+ SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+ pWrtShell->Insert("abc");
+ pWrtShell->SplitNode();
+ pWrtShell->Insert("def");
+ SwModule* pModule = SwModule::get();
+ // Mark cd as bold:
+ pWrtShell->SttPara(/*bSelect=*/false);
+ pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/false, 2, /*bBasicCall=*/false);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 3, /*bBasicCall=*/false);
+ SwPaM* pCursor = pWrtShell->GetCursor();
+ CPPUNIT_ASSERT_EQUAL(u"c\nd"_ustr, pCursor->GetText());
+ SwView& rView = pWrtShell->GetView();
+ {
+ SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aSet(rView.GetPool());
+ aSet.Put(aWeightItem);
+ pWrtShell->SetAttrSet(aSet);
+ }
+ pModule->SetRedlineAuthor("Alice");
+ RedlineFlags nMode = pWrtShell->GetRedlineFlags();
+ pWrtShell->SetRedlineFlags(nMode | RedlineFlags::On);
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 1, /*bBasicCall=*/false);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 5, /*bBasicCall=*/false);
+ pWrtShell->DelRight();
+ pWrtShell->SetRedlineFlags(nMode);
+
+ // When a 2nd user reinstates that change:
+ pModule->SetRedlineAuthor("Bob");
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 2, /*bBasicCall=*/false);
+ dispatchCommand(mxComponent, ".uno:ReinstateTrackedChange", {});
+
+ // Then make sure this results in an insert after a delete:
+ // Expected document: a<del>b<b>c\nd</b>e</del><ins>b<b>c\nd</b>e</ins>f.
+ // First check the content.
+ pWrtShell->SttEndDoc(/*bStt=*/true);
+ const OUString& rPara1 = pCursor->GetPointNode().GetTextNode()->GetText();
+ CPPUNIT_ASSERT_EQUAL(u"abc"_ustr, rPara1);
+ pWrtShell->Down(/*bSelect=*/false);
+ const OUString& rPara2 = pCursor->GetPointNode().GetTextNode()->GetText();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: debc
+ // - Actual : debc\ndef
+ // i.e. multi-paragraph delete was inserted with a literal newline character instead of creating
+ // a new text node.
+ CPPUNIT_ASSERT_EQUAL(u"debc"_ustr, rPara2);
+ pWrtShell->Down(/*bSelect=*/false);
+ const OUString& rPara3 = pCursor->GetPointNode().GetTextNode()->GetText();
+ CPPUNIT_ASSERT_EQUAL(u"def"_ustr, rPara3);
+ // Check if formatting was copied correctly.
+ pWrtShell->Up(/*bSelect=*/false);
+ pWrtShell->EndPara(/*bSelect=*/false);
+ SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aSet(rView.GetPool());
+ pWrtShell->GetCurAttr(aSet);
+ CPPUNIT_ASSERT(aSet.HasItem(RES_CHRATR_WEIGHT));
+ // Check the redline table: now the insert redline should be multi-paragraph.
+ SwDoc* pDoc = pWrtShell->GetDoc();
+ IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
+ SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rRedlines.size());
+ const SwRangeRedline* pRedline1 = rRedlines[0];
+ const SwRedlineData& rRedlineData1 = pRedline1->GetRedlineData(0);
+ CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData1.GetType());
+ const SwRangeRedline* pRedline2 = rRedlines[1];
+ const SwRedlineData& rRedlineData2 = pRedline2->GetRedlineData(0);
+ CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData2.GetType());
+ CPPUNIT_ASSERT_GREATER(pRedline2->Start()->nNode, pRedline2->End()->nNode);
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/edit/edredln.cxx b/sw/source/core/edit/edredln.cxx
index a28dcff4209c..a99a8f2e459d 100644
--- a/sw/source/core/edit/edredln.cxx
+++ b/sw/source/core/edit/edredln.cxx
@@ -24,6 +24,7 @@
#include <editsh.hxx>
#include <frmtool.hxx>
#include <docsh.hxx>
+#include <swdtflvr.hxx>
RedlineFlags SwEditShell::GetRedlineFlags() const
{
@@ -89,11 +90,29 @@ void SwEditShell::ReinstatePaM(const SwRangeRedline& rRedline, SwPaM& rPaM)
else if (rRedline.GetType() == RedlineType::Delete)
{
// Re-insert after the deletion.
- OUString aText = rPaM.GetText();
- ClearMark();
+ SwDocShell* pDocShell = GetDoc()->GetDocShell();
+ if (!pDocShell)
+ {
+ return;
+ }
+
+ SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+ if (!pWrtShell)
+ {
+ return;
+ }
+
SwShellCursor* pCursor = getShellCursor(/*bBlock=*/true);
*pCursor->GetPoint() = *rPaM.End();
- Insert2(aText);
+ SetMark();
+ *pCursor->GetMark() = *rPaM.Start();
+ rtl::Reference<SwTransferable> pTransfer(new SwTransferable(*pWrtShell));
+ // Copy rich text, but don't strip out text inside delete redlines.
+ pTransfer->Copy(/*bIsCut=*/false, /*bDeleteRedlines=*/false);
+ ClearMark();
+ *pCursor->GetPoint() = *rPaM.End();
+ TransferableDataHelper aHelper(pTransfer);
+ SwTransferable::Paste(*pWrtShell, aHelper);
}
}
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 6cc0f9d58e4d..61bf3399cd6b 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -74,7 +74,7 @@
using namespace ::com::sun::star;
// Copy for the internal clipboard. Copies all selections to the clipboard.
-void SwFEShell::Copy( SwDoc& rClpDoc, const OUString* pNewClpText )
+void SwFEShell::Copy( SwDoc& rClpDoc, const OUString* pNewClpText, bool bDeleteRedlines )
{
rClpDoc.GetIDocumentUndoRedo().DoUndo(false); // always false!
@@ -118,7 +118,10 @@ void SwFEShell::Copy( SwDoc& rClpDoc, const OUString* pNewClpText )
}
rClpDoc.getIDocumentFieldsAccess().LockExpFields();
- rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+ if (bDeleteRedlines)
+ {
+ rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+ }
// do we want to copy a FlyFrame?
if( IsFrameSelected() )
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index a5b5e191f3e6..d5fa77cf5ab5 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -403,7 +403,7 @@ namespace
//source, so that we can WYSIWYG paste. If we want that the destinations
//styles are used over the source styles, that's a matter of the
//destination paste code to handle, not the source paste code.
- void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest)
+ void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest, bool bDeleteRedlines = true)
{
const SwDoc &rSrc = *rSrcWrtShell.GetDoc();
@@ -414,7 +414,7 @@ namespace
//by the selection, e.g. apply SwDoc::IsUsed on styles ?
rDest.ReplaceStyles(rSrc, false);
- rSrcWrtShell.Copy(rDest);
+ rSrcWrtShell.Copy(rDest, /*pNewClpText=*/nullptr, bDeleteRedlines);
rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
}
@@ -959,7 +959,7 @@ void SwTransferable::PrepareForCopyTextRange(SwPaM & rPaM)
AddFormat( SotClipboardFormatId::STRING );
}
-int SwTransferable::PrepareForCopy( bool bIsCut )
+int SwTransferable::PrepareForCopy( bool bIsCut, bool bDeleteRedlines )
{
int nRet = 1;
if(!m_pWrtShell)
@@ -1065,7 +1065,7 @@ int SwTransferable::PrepareForCopy( bool bIsCut )
SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);
rTmpDoc.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
- lclOverWriteDoc(*m_pWrtShell, rTmpDoc);
+ lclOverWriteDoc(*m_pWrtShell, rTmpDoc, bDeleteRedlines);
DeleteDDEAndReminderMarks(rTmpDoc);
@@ -1197,12 +1197,12 @@ int SwTransferable::PrepareForCopy( bool bIsCut )
return nRet;
}
-int SwTransferable::Copy( bool bIsCut )
+int SwTransferable::Copy( bool bIsCut, bool bDeleteRedlines )
{
if (m_pWrtShell->GetView().GetObjectShell()->isContentExtractionLocked())
return 0;
- int nRet = PrepareForCopy( bIsCut );
+ int nRet = PrepareForCopy( bIsCut, bDeleteRedlines );
if ( nRet )
{
CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
index c643aa052b0b..e301fa0d7540 100644
--- a/sw/source/uibase/inc/swdtflvr.hxx
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -179,8 +179,8 @@ public:
// copy - methods and helper methods for the copy
SW_DLLPUBLIC int Cut();
- SW_DLLPUBLIC int Copy( bool bIsCut = false );
- int PrepareForCopy( bool bIsCut = false );
+ SW_DLLPUBLIC int Copy( bool bIsCut = false, bool bDeleteRedlines = true );
+ int PrepareForCopy( bool bIsCut = false, bool bDeleteRedlines = true );
void PrepareForCopyTextRange(SwPaM & rPaM);
void CalculateAndCopy(); // special for Calculator
bool CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr );