sw/qa/core/doc/DocumentRedlineManager.cxx | 44 ++++++++++++++++ sw/source/core/doc/DocumentContentOperationsManager.cxx | 7 ++ 2 files changed, 50 insertions(+), 1 deletion(-)
New commits: commit 0c7eaa023a840a6f0967fe119463a936241a8130 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Sep 18 08:50:41 2025 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Sep 18 15:56:53 2025 +0200 tdf#168325 sw format redline, char style: improve recording Create a new Writer document with a single word in it, set the Emphasis character style on it, enable redline record, change char style to Strong Emphasis, save to ODT. The format redline refers to an automatic style, while it should refer to the old char style (Emphasis). This happens because the redline record for format redline works incorrectly: it not only records the char style (before changing the char style), but also the expanded value of the char style, which leads to the creation of an automatic style on ODT export. This doesn't happen if exporting an originally DOCX file to ODT. Fix the problem by explicitly asking for the current character properties in a way so that char styles are not expanded, when making a copy of the old formatting & storing it in a format redline. Also drop storing RSIDs in format redlines, they are not interesting and again would lead to unwanted creation of automatic styles. Change-Id: Idd34afb1f0570589254a9eb259af4fc3465aec22 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191120 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/doc/DocumentRedlineManager.cxx b/sw/qa/core/doc/DocumentRedlineManager.cxx index 8fac406a45aa..10221f79664a 100644 --- a/sw/qa/core/doc/DocumentRedlineManager.cxx +++ b/sw/qa/core/doc/DocumentRedlineManager.cxx @@ -11,6 +11,7 @@ #include <editeng/wghtitem.hxx> #include <comphelper/scopeguard.hxx> +#include <comphelper/propertyvalue.hxx> #include <IDocumentRedlineAccess.hxx> #include <docsh.hxx> @@ -19,6 +20,7 @@ #include <wrtsh.hxx> #include <swmodule.hxx> #include <strings.hrc> +#include <fchrfmt.hxx> namespace { @@ -128,6 +130,48 @@ CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatSelf) // i.e. a delete was created instead of removing the insert. CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); } + +CPPUNIT_TEST_FIXTURE(Test, testFormatRedlineRecordOldCharStyle) +{ + // Given a document with one char style applied + redline record on: + createSwDoc(); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + pWrtShell->Insert(u"x"_ustr); + pWrtShell->SelAll(); + uno::Sequence<beans::PropertyValue> aPropertyValues = { + comphelper::makePropertyValue(u"Style"_ustr, uno::Any(u"Emphasis"_ustr)), + comphelper::makePropertyValue(u"FamilyName"_ustr, uno::Any(u"CharacterStyles"_ustr)), + }; + dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues); + pDocShell->SetChangeRecording(true); + + // When changing to a second char style: + aPropertyValues = { + comphelper::makePropertyValue(u"Style"_ustr, uno::Any(u"Strong Emphasis"_ustr)), + comphelper::makePropertyValue(u"FamilyName"_ustr, uno::Any(u"CharacterStyles"_ustr)), + }; + dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues); + + // Then make sure the redline refers to the old char style and just to that: + SwDoc* pDoc = pDocShell->GetDoc(); + IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess(); + SwRedlineTable& rRedlines = rIDRA.GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size()); + const SwRangeRedline& rRedline = *rRedlines[0]; + CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedline.GetType()); + auto pExtraData = dynamic_cast<const SwRedlineExtraData_FormatColl*>(rRedline.GetExtraData()); + CPPUNIT_ASSERT(pExtraData); + std::shared_ptr<SfxItemSet> pRedlineSet = pExtraData->GetItemSet(); + CPPUNIT_ASSERT(pRedlineSet); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 5 + // i.e. more than just the char style change was recorded, which was unexpected. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pRedlineSet->Count()); + const SwFormatCharFormat& rOldCharFormat = pRedlineSet->Get(RES_TXTATR_CHARFMT); + CPPUNIT_ASSERT_EQUAL(u"Emphasis"_ustr, rOldCharFormat.GetCharFormat()->GetName().toString()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index c18cb0186323..61b9297ca4ef 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -1303,7 +1303,11 @@ namespace //local functions originally from docfmt.cxx SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_CHRATR_BEGIN, RES_TXTATR_WITHEND_END - 1, RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1>(rDoc.GetAttrPool())); SwTextNode * pNode = rRg.Start()->GetNode().GetTextNode(); - pNode->GetParaAttr( aSet, rRg.Start()->GetContentIndex() + 1, rRg.End()->GetContentIndex() ); + // bGetFromChrFormat would be true by default and we want no expansion of the character + // style to direct formatting for redline purposes. + pNode->GetParaAttr(aSet, rRg.Start()->GetContentIndex() + 1, + rRg.End()->GetContentIndex(), /*bOnlyTextAttr=*/false, + /*bGetFromChrFormat=*/false); aSet.ClearItem( RES_TXTATR_REFMARK ); aSet.ClearItem( RES_TXTATR_TOXMARK ); @@ -1311,6 +1315,7 @@ namespace //local functions originally from docfmt.cxx aSet.ClearItem( RES_TXTATR_INETFMT ); aSet.ClearItem( RES_TXTATR_META ); aSet.ClearItem( RES_TXTATR_METAFIELD ); + aSet.ClearItem(RES_CHRATR_RSID); // After GetParaAttr aSet can contain invalid/dontcare items (true == IsInvalidItem, // DONTCARE == SfxItemState), e.g. RES_TXTATR_CHARFMT and (a copy of) this