cool#15451 sw interdependent redlines: fix creating an inner format...

...on top of format-on-delete

Enable track changes, delete a sentence, select the deleted text, format
the selection as bold, then reduce the selection to just one word inside
the sentence, format as italics: the delete redline is lost for that
word.

This is similar to commit bd7f20bdf7d1e66ab13c46074c0482ccab6d6867
(cool#15451 sw interdependent redlines: fix creating a format on top of
format-on-delete, 2026-04-24), which works because comparing the
to-be-inserted format redline with the existing format-on-delete redline
results in SwComparePosition::Equal.

Here we hit the SwComparePosition::Inside case, so fix that in a similar
way. It already has code to drop the to-be-inserted redline when the
existing redline is an "own" one: do the same if the existing redline is
a hierarchical one, too.

The other way around (bold on just one word, italic on the entire
sentence) was working already.

Signed-off-by: Miklos Vajna <vmiklos@collabora.com>
Change-Id: I40b1a06daa8fa158da25825e46abd087adeb767d
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/1698
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
(cherry picked from commit 0e50a49b4c41c7767d51a829c71d3c064f4d5b93)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205160
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Miklos Vajna
2026-05-13 15:39:47 +02:00
committed by Xisco Fauli
parent 7a8988727b
commit 7f05f27f5b
2 changed files with 64 additions and 3 deletions
+55
View File
@@ -490,6 +490,61 @@ CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatFormat)
CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData2.GetType());
CPPUNIT_ASSERT(!rRedlineData2.Next());
}
CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatFormatInside)
{
// Given "AAA BBB CCC" with a delete redline and a bold format redline
// applied on top of the full range:
createSwDoc();
SwDocShell* pDocShell = getSwDocShell();
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
pWrtShell->Insert(u"AAA BBB CCC"_ustr);
pDocShell->SetChangeRecording(true);
SwView& rView = pWrtShell->GetView();
pWrtShell->SelAll();
pWrtShell->DelLeft();
pWrtShell->SelAll();
{
SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
SfxItemSet aSet(
SfxItemSet::makeFixedSfxItemSet<RES_CHRATR_BEGIN, RES_CHRATR_END>(rView.GetPool()));
aSet.Put(aWeightItem);
pWrtShell->SetAttrSet(aSet);
}
// When applying an additional italic format on only the middle word:
pWrtShell->SttEndDoc(/*bStt=*/true);
// Skip "AAA ".
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
// Select "BBB".
pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 3, /*bBasicCall=*/false);
{
SvxPostureItem aPostureItem(ITALIC_NORMAL, RES_CHRATR_POSTURE);
SfxItemSet aSet(
SfxItemSet::makeFixedSfxItemSet<RES_CHRATR_BEGIN, RES_CHRATR_END>(rView.GetPool()));
aSet.Put(aPostureItem);
pWrtShell->SetAttrSet(aSet);
}
// Then make sure the delete-then-format redline is kept unchanged, instead
// of being replaced with a single plain format redline for BBB:
SwDoc* pDoc = pDocShell->GetDoc();
IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
// Without the accompanying fix in place, this test would have failed with:
// - Expected: 1
// - Actual : 3
// i.e. we got a format-then-delete, a format and a format-on-delete redline instead of a single
// format-on-delete redline.
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
CPPUNIT_ASSERT_EQUAL(u"AAA BBB CCC"_ustr, rRedlines[0]->GetText());
const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData.GetType());
CPPUNIT_ASSERT(rRedlineData.Next());
const SwRedlineData& rRedlineData2 = *rRedlineData.Next();
CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData2.GetType());
CPPUNIT_ASSERT(!rRedlineData2.Next());
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@@ -2341,10 +2341,12 @@ void DocumentRedlineManager::PreAppendFormatRedline(AppendRedlineContext& rCtx)
break;
}
case RedlineType::Format:
{
bool bHierarchical = rCtx.pRedl->GetRedlineData(0).Next() != nullptr;
switch( rCtx.eCmpPos )
{
case SwComparePosition::Equal:
if (rCtx.pRedl->GetRedlineData(0).Next())
if (bHierarchical)
{
// rCtx.pRedl already has an underlying redline data entry (insert/delete) and
// rCtx.pRedl already records the old format to be restored on reject, so just leave
@@ -2366,8 +2368,10 @@ void DocumentRedlineManager::PreAppendFormatRedline(AppendRedlineContext& rCtx)
break;
case SwComparePosition::Inside:
if( rCtx.pRedl->IsOwnRedline( *rCtx.pNewRedl ) &&
rCtx.pRedl->CanCombine( *rCtx.pNewRedl ))
{
bool bOwnRedlineToCombine = rCtx.pRedl->IsOwnRedline(*rCtx.pNewRedl)
&& rCtx.pRedl->CanCombine(*rCtx.pNewRedl);
if (bOwnRedlineToCombine || bHierarchical)
{
// own one can be ignored completely
delete rCtx.pNewRedl;
@@ -2399,6 +2403,7 @@ void DocumentRedlineManager::PreAppendFormatRedline(AppendRedlineContext& rCtx)
rCtx.bDec = true;
}
break;
}
case SwComparePosition::OverlapBefore:
case SwComparePosition::OverlapBehind:
@@ -2450,6 +2455,7 @@ void DocumentRedlineManager::PreAppendFormatRedline(AppendRedlineContext& rCtx)
break;
}
break;
}
default:
break;
}