sw/inc/doc.hxx                                          |    8 +-
 sw/qa/extras/uiwriter/uiwriter8.cxx                     |   46 ++++++++++++-
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   11 ++-
 sw/source/core/doc/docnum.cxx                           |   55 +++++++++++++++-
 4 files changed, 109 insertions(+), 11 deletions(-)

New commits:
commit 2bcaa374ea418cd81f9dbf62cd7e896f5977992a
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri May 17 13:58:41 2024 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri May 17 19:24:29 2024 +0200

    tdf#161137 sw: AutoText or Paste should copy paragraph indents for lists
    
    The first commit made the start and end node of the paste look like the
    list it was inserted into, but the middle nodes may have different
    paragraph styles and may have different left margin / first line indent.
    
    In addition to the SwNumRule, also copy any left margin or first line
    indent if it is effective on the node that the SwNumRule was taken from.
    
    Now all the list labels should be in the same place.
    
    Change-Id: Ia5794687ea0ff542f23289b1ca63ea99dae85bc3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167777
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 659af3ba1e91..b1b68bec2dba 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1073,7 +1073,9 @@ public:
                      const SwNumRule&,
                      SetNumRuleMode mode,
                      SwRootFrame const* pLayout = nullptr,
-                     const OUString& sContinuedListId = OUString());
+                     const OUString& sContinuedListId = OUString(),
+                     SvxTextLeftMarginItem const* pTextLeftMarginToPropagate = 
nullptr,
+                     SvxFirstLineIndentItem const* pFirstLineIndentToPropagate 
= nullptr);
     void SetCounted(const SwPaM&, bool bCounted, SwRootFrame const* pLayout);
 
     void MakeUniqueNumRules(const SwPaM & rPaM);
@@ -1151,7 +1153,9 @@ public:
                                     int nNonEmptyAllowed,
                                     OUString& sListId,
                                     SwRootFrame const* pLayout,
-                                    const bool bInvestigateStartNode = false );
+                                    const bool bInvestigateStartNode = false,
+                                    SvxTextLeftMarginItem const** 
o_ppTextLeftMargin = nullptr,
+                                    SvxFirstLineIndentItem const** 
o_ppFirstLineIndent = nullptr);
 
     // Paragraphs without numbering but with indents.
     bool NoNum( const SwPaM& );
diff --git a/sw/qa/extras/uiwriter/uiwriter8.cxx 
b/sw/qa/extras/uiwriter/uiwriter8.cxx
index 2ff8bc3472b6..e1924b16a512 100644
--- a/sw/qa/extras/uiwriter/uiwriter8.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter8.cxx
@@ -25,6 +25,7 @@
 #include <frameformats.hxx>
 #include <tools/json_writer.hxx>
 #include <unotools/streamwrap.hxx>
+#include <editeng/lrspitem.hxx>
 #include <sfx2/linkmgr.hxx>
 
 #include <wrtsh.hxx>
@@ -877,7 +878,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, 
testInsertAutoTextIntoListFromParaStyle)
     pWrtShell->FwdPara();
     pWrtShell->EndPara(/*bSelect=*/false);
     // expands autotext (via F3)
-    pWrtShell->Insert(" dt");
+    pWrtShell->Insert(" jacr");
 
     SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
     pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_F3);
@@ -886,6 +887,10 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, 
testInsertAutoTextIntoListFromParaStyle)
     pWrtShell->SttEndDoc(/*bStt=*/true);
     pWrtShell->FwdPara();
 
+    SwNumRule* pNumRule;
+    SvxTextLeftMarginItem const* pTextLeftMargin;
+    SvxFirstLineIndentItem const* pFirstLineIndent;
+
     {
         SwTextNode& rNode{ 
*pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() };
         // numrule from paragraph style, but not from direct formatting
@@ -902,7 +907,32 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, 
testInsertAutoTextIntoListFromParaStyle)
         CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, false));
         CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, true));
         CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, 
rNode.GetTextColl()->GetName());
-        CPPUNIT_ASSERT(rNode.GetText().startsWith("Item He heard quiet 
steps"));
+        CPPUNIT_ASSERT_EQUAL(u"Item We confirm receipt of your application 
material."_ustr,
+                             rNode.GetText());
+        pNumRule = rNode.GetNumRule();
+        pTextLeftMargin = &rNode.GetAttr(RES_MARGIN_TEXTLEFT);
+        pFirstLineIndent = &rNode.GetAttr(RES_MARGIN_FIRSTLINE);
+    }
+
+    pWrtShell->FwdPara();
+
+    {
+        SwTextNode& rNode{ 
*pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode() };
+        auto pSet{ rNode.GetpSwAttrSet() };
+        CPPUNIT_ASSERT(pSet);
+        // list id was set
+        CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_PARATR_LIST_ID, false));
+        // middle paragraph was pasted - has numrule and indents applied 
directly
+        CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_PARATR_NUMRULE, false));
+        CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_MARGIN_FIRSTLINE, false));
+        CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, false));
+        CPPUNIT_ASSERT_EQUAL(u"Default Paragraph Style"_ustr, 
rNode.GetTextColl()->GetName());
+        CPPUNIT_ASSERT(rNode.GetText().startsWith("As more applicants 
applied"));
+        CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule());
+        CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(),
+                             rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft());
+        CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(),
+                             
rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset());
     }
 
     pWrtShell->FwdPara();
@@ -923,7 +953,12 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, 
testInsertAutoTextIntoListFromParaStyle)
         CPPUNIT_ASSERT_EQUAL(SfxItemState::DEFAULT, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, false));
         CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, true));
         CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, 
rNode.GetTextColl()->GetName());
-        CPPUNIT_ASSERT_EQUAL(u""_ustr, rNode.GetText()); // this is a new 
empty paragraph
+        CPPUNIT_ASSERT(rNode.GetText().endsWith("as soon as we have come to a 
decision."));
+        CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule());
+        CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(),
+                             rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft());
+        CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(),
+                             
rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset());
     }
 
     pWrtShell->FwdPara();
@@ -945,6 +980,11 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest8, 
testInsertAutoTextIntoListFromParaStyle)
         CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, 
pSet->GetItemState(RES_MARGIN_TEXTLEFT, true));
         CPPUNIT_ASSERT_EQUAL(u"ListAndIndents"_ustr, 
rNode.GetTextColl()->GetName());
         CPPUNIT_ASSERT_EQUAL(u"more"_ustr, rNode.GetText()); // pre-exising 
list item
+        CPPUNIT_ASSERT_EQUAL(pNumRule, rNode.GetNumRule());
+        CPPUNIT_ASSERT_EQUAL(pTextLeftMargin->GetTextLeft(),
+                             rNode.GetAttr(RES_MARGIN_TEXTLEFT).GetTextLeft());
+        CPPUNIT_ASSERT_EQUAL(pFirstLineIndent->GetTextFirstLineOffset(),
+                             
rNode.GetAttr(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset());
     }
 }
 
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 1f7857b6e407..0e5e0db06be1 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -5119,12 +5119,16 @@ bool 
DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
     // bullet list.
     // Keep also the <ListId> value for possible propagation.
     OUString aListIdToPropagate;
+    SvxTextLeftMarginItem const* pTextLeftMarginToPropagate{nullptr};
+    SvxFirstLineIndentItem const* pFirstLineIndentToPropagate{nullptr};
     const SwNumRule* pNumRuleToPropagate =
-        rDoc.SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, 
nullptr, true );
+        rDoc.SearchNumRule(rPos, false, true, false, 0, aListIdToPropagate, 
nullptr,
+                true, &pTextLeftMarginToPropagate, 
&pFirstLineIndentToPropagate);
     if ( !pNumRuleToPropagate )
     {
         pNumRuleToPropagate =
-            rDoc.SearchNumRule( rPos, false, false, false, 0, 
aListIdToPropagate, nullptr, true );
+            rDoc.SearchNumRule(rPos, false, false, false, 0, 
aListIdToPropagate, nullptr,
+                true, &pTextLeftMarginToPropagate, 
&pFirstLineIndentToPropagate);
     }
     // #i86492#
     // Do not propagate previous found list, if
@@ -5524,7 +5528,8 @@ bool 
DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
         // the paragraph style, in that case applying it again in mpAttrSet 
could
         // override indents, so avoid that.
         rDoc.SetNumRule(*pCopyPam, *pNumRuleToPropagate,
-            SwDoc::SetNumRuleMode::DontSetIfAlreadyApplied, nullptr, 
aListIdToPropagate);
+            SwDoc::SetNumRuleMode::DontSetIfAlreadyApplied, nullptr, 
aListIdToPropagate,
+            pTextLeftMarginToPropagate, pFirstLineIndentToPropagate);
     }
 
     rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
index 59893782fda4..adf0f5b9f699 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -46,6 +46,7 @@
 #include <SwNodeNum.hxx>
 #include <list.hxx>
 #include <calbck.hxx>
+#include <editeng/lrspitem.hxx>
 #include <comphelper/string.hxx>
 #include <comphelper/random.hxx>
 #include <o3tl/safeint.hxx>
@@ -862,7 +863,9 @@ OUString SwDoc::SetNumRule( const SwPaM& rPam,
                         const SwNumRule& rRule,
                         SetNumRuleMode eMode,
                         SwRootFrame const*const pLayout,
-                        const OUString& sContinuedListId)
+                        const OUString& sContinuedListId,
+                        SvxTextLeftMarginItem const*const 
pTextLeftMarginToPropagate,
+                        SvxFirstLineIndentItem const*const 
pFirstLineIndentToPropagate)
 {
     OUString sListId;
 
@@ -982,6 +985,19 @@ OUString SwDoc::SetNumRule( const SwPaM& rPam,
                         getIDocumentContentOperations().InsertPoolItem(temp,
                                 SwNumRuleItem(pNewOrChangedNumRule->GetName()),
                                 SetAttrMode::DEFAULT, pLayout);
+                        // apply provided margins to get visually same result
+                        if (pTextLeftMarginToPropagate)
+                        {
+                            
getIDocumentContentOperations().InsertPoolItem(temp,
+                                    *pTextLeftMarginToPropagate,
+                                    SetAttrMode::DEFAULT, pLayout);
+                        }
+                        if (pFirstLineIndentToPropagate)
+                        {
+                            
getIDocumentContentOperations().InsertPoolItem(temp,
+                                    *pFirstLineIndentToPropagate,
+                                    SetAttrMode::DEFAULT, pLayout);
+                        }
                     }
                 }
             }
@@ -991,6 +1007,18 @@ OUString SwDoc::SetNumRule( const SwPaM& rPam,
             getIDocumentContentOperations().InsertPoolItem(aPam,
                     SwNumRuleItem(pNewOrChangedNumRule->GetName()),
                     SetAttrMode::DEFAULT, pLayout);
+            if (pTextLeftMarginToPropagate)
+            {
+                getIDocumentContentOperations().InsertPoolItem(aPam,
+                        *pTextLeftMarginToPropagate,
+                        SetAttrMode::DEFAULT, pLayout);
+            }
+            if (pFirstLineIndentToPropagate)
+            {
+                getIDocumentContentOperations().InsertPoolItem(aPam,
+                        *pFirstLineIndentToPropagate,
+                        SetAttrMode::DEFAULT, pLayout);
+            }
         }
     }
 
@@ -1648,7 +1676,9 @@ const SwNumRule *  SwDoc::SearchNumRule(const SwPosition 
& rPos,
                                         int nNonEmptyAllowed,
                                         OUString& sListId,
                                         SwRootFrame const* pLayout,
-                                        const bool bInvestigateStartNode)
+                                        const bool bInvestigateStartNode,
+                                        SvxTextLeftMarginItem const** 
o_ppTextLeftMargin,
+                                        SvxFirstLineIndentItem const** 
o_ppFirstLineIndent)
 {
     const SwNumRule * pResult = nullptr;
     SwTextNode * pTextNd = rPos.GetNode().GetTextNode();
@@ -1685,9 +1715,28 @@ const SwNumRule *  SwDoc::SearchNumRule(const SwPosition 
& rPos,
                          ( ( bNum && pNumRule->Get(0).IsEnumeration()) ||
                            ( !bNum && pNumRule->Get(0).IsItemize() ) ) ) // 
#i22362#, #i29560#
                     {
-                        pResult = pTextNd->GetNumRule();
+                        pResult = pNumRule;
                         // provide also the list id, to which the text node 
belongs.
                         sListId = pTextNd->GetListId();
+                        // also get the margins that override the numrule
+                        int const nListLevel{pTextNd->GetActualListLevel()};
+                        if ((o_ppTextLeftMargin || o_ppFirstLineIndent)
+                            && 0 <= nListLevel
+                            && 
pNumRule->Get(o3tl::narrowing<sal_uInt16>(nListLevel))
+                                .GetPositionAndSpaceMode() == 
SvxNumberFormat::LABEL_ALIGNMENT)
+                        {
+                            ::sw::ListLevelIndents const 
indents{pTextNd->AreListLevelIndentsApplicable()};
+                            if (!(indents & ::sw::ListLevelIndents::LeftMargin)
+                                && o_ppTextLeftMargin)
+                            {
+                                *o_ppTextLeftMargin = 
&pTextNd->SwContentNode::GetAttr(RES_MARGIN_TEXTLEFT);
+                            }
+                            if (!(indents & ::sw::ListLevelIndents::FirstLine)
+                                && o_ppFirstLineIndent)
+                            {
+                                *o_ppFirstLineIndent = 
&pTextNd->SwContentNode::GetAttr(RES_MARGIN_FIRSTLINE);
+                            }
+                        }
                     }
 
                     break;

Reply via email to