diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 429501de75c8..a38fc9fb8742 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -2847,6 +2847,51 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf50447) } } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf143918) +{ + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf126206.docx"); + + SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // bold text + auto xText = getParagraph(1)->getText(); + CPPUNIT_ASSERT(xText.is()); + { + auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1))); + CPPUNIT_ASSERT(xCursor.is()); + CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString()); + CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty(xCursor, "CharWeight")); + } + + // remove bold formatting with change tracking and after that, apply underline, too + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 6, /*bBasicCall=*/false); + dispatchCommand(mxComponent, ".uno:Bold", {}); + dispatchCommand(mxComponent, ".uno:Underline", {}); + + xText = getParagraph(1)->getText(); + CPPUNIT_ASSERT(xText.is()); + { + auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 2))); + CPPUNIT_ASSERT(xCursor.is()); + CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString()); + CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty(xCursor, "CharWeight")); + } + + // reject tracked changes + dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {}); + + // bold text again + xText = getParagraph(1)->getText(); + CPPUNIT_ASSERT(xText.is()); + { + auto xCursor(xText->createTextCursorByRange(getRun(getParagraph(1), 1))); + CPPUNIT_ASSERT(xCursor.is()); + CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xCursor->getString()); + // This was NORMAL (only underlining was removed) + CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty(xCursor, "CharWeight")); + } +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf101873) { SwDoc* pDoc = createSwDoc(); diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index a3e13851130b..29e9e372804d 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -1645,11 +1645,43 @@ namespace //local functions originally from docfmt.cxx } SwRangeRedline * pRedline = nullptr; + SwRedlineExtraData_FormatColl* pExtra = nullptr; if( rDoc.getIDocumentRedlineAccess().IsRedlineOn() && pCharSet && pCharSet->Count() ) { if( pUndo ) pUndo->SaveRedlineData( rRg, false ); + // check existing redline on the same range, and use its extra data, if it exists + SwRedlineTable::size_type nRedlPos = rDoc.getIDocumentRedlineAccess().GetRedlinePos( + rRg.Start()->nNode.GetNode(), RedlineType::Format ); + if( SwRedlineTable::npos != nRedlPos ) + { + const SwPosition *pRStt, *pREnd; + do { + SwRangeRedline* pTmp = rDoc.getIDocumentRedlineAccess().GetRedlineTable()[ nRedlPos ]; + pRStt = pTmp->Start(); + pREnd = pTmp->End(); + SwComparePosition eCompare = ComparePosition( *rRg.Start(), *rRg.End(), *pRStt, *pREnd ); + if ( eCompare == SwComparePosition::Inside || eCompare == SwComparePosition::Equal ) + { + if (pTmp->GetExtraData()) + { + const SwRedlineExtraData* pExtraData = pTmp->GetExtraData(); + const SwRedlineExtraData_FormatColl* pFormattingChanges = + dynamic_cast(pExtraData); + // Check if the extra data is of type 'formatting changes' + if (pFormattingChanges) + { + // Get the item set that holds all the changes properties + const SfxItemSet *pChangesSet = pFormattingChanges->GetItemSet(); + pExtra = new SwRedlineExtraData_FormatColl( "", USHRT_MAX, pChangesSet ); + break; + } + } + } + } while( pRStt <= rRg.Start() && ++nRedlPos < rDoc.getIDocumentRedlineAccess().GetRedlineTable().size()); + } + pRedline = new SwRangeRedline( RedlineType::Format, rRg ); auto const result(rDoc.getIDocumentRedlineAccess().AppendRedline( pRedline, true)); if (IDocumentRedlineAccess::AppendResult::IGNORED == result) @@ -1679,20 +1711,24 @@ namespace //local functions originally from docfmt.cxx // store original text attributes to reject formatting change if (pRedline) { - // Apply the first character's attributes to the ReplaceText - SfxItemSet aSet( rDoc.GetAttrPool(), - svl::Items ); - pNode->GetTextNode()->GetParaAttr( aSet, pStt->nContent.GetIndex() + 1, aCntEnd.GetIndex() ); + // no existing format redline in the range + if (!pExtra) + { + // Apply the first character's attributes to the ReplaceText + SfxItemSet aSet( rDoc.GetAttrPool(), + svl::Items ); + pNode->GetTextNode()->GetParaAttr( aSet, pStt->nContent.GetIndex() + 1, aCntEnd.GetIndex() ); - aSet.ClearItem( RES_TXTATR_REFMARK ); - aSet.ClearItem( RES_TXTATR_TOXMARK ); - aSet.ClearItem( RES_TXTATR_CJK_RUBY ); - aSet.ClearItem( RES_TXTATR_INETFMT ); - aSet.ClearItem( RES_TXTATR_META ); - aSet.ClearItem( RES_TXTATR_METAFIELD ); + aSet.ClearItem( RES_TXTATR_REFMARK ); + aSet.ClearItem( RES_TXTATR_TOXMARK ); + aSet.ClearItem( RES_TXTATR_CJK_RUBY ); + aSet.ClearItem( RES_TXTATR_INETFMT ); + aSet.ClearItem( RES_TXTATR_META ); + aSet.ClearItem( RES_TXTATR_METAFIELD ); + pExtra = new SwRedlineExtraData_FormatColl( "", USHRT_MAX, &aSet ); + } - auto pExtra = new SwRedlineExtraData_FormatColl( "", USHRT_MAX, &aSet ); if ( pExtra ) { std::unique_ptr xRedlineExtraData;