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

Reply via email to