sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt |binary
 sw/qa/extras/layout/layout5.cxx                     |   26 +++++++
 sw/source/core/doc/doctxm.cxx                       |   66 ++++++++++++++++++++
 3 files changed, 92 insertions(+)

New commits:
commit 441f6354987e2e8cccd58e0cff8408cf6088ad41
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Wed Sep 17 13:02:55 2025 -0400
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Thu Sep 18 19:08:47 2025 +0200

    tdf#92714 sw: transfer breaks when deleting TOC
    
    The table of contents can contain a page break.
    
    When deleting a TOC, the page break
    should be transferred to the following
    paragraph or table.
    
    Something similar happens with DelFullPara and DelTable.
    
    make CppunitTest_sw_layoutwriter5 \
        CPPUNIT_TEST_NAME=testTdf92714_TOC_pageBreak
    
    Change-Id: I3d0e61e0c6a9b7544fe6488f8122316fff37811a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191107
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt 
b/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt
new file mode 100644
index 000000000000..cb9b00d76ab9
Binary files /dev/null and 
b/sw/qa/extras/layout/data/tdf92714_TOC_pageBreak.odt differ
diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx
index 6e8cdd59bc6b..880c03d46857 100644
--- a/sw/qa/extras/layout/layout5.cxx
+++ b/sw/qa/extras/layout/layout5.cxx
@@ -9,18 +9,23 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <com/sun/star/text/XPageCursor.hpp>
 #include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 #include <com/sun/star/linguistic2/XHyphenator.hpp>
 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
 
 #include <comphelper/scopeguard.hxx>
 #include <unotools/syslocaleoptions.hxx>
 #include <editeng/unolingu.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
 #include <vcl/scheduler.hxx>
 
+#include <cmdid.h>
 #include <scriptinfo.hxx>
 #include <rootfrm.hxx>
 #include <wrtsh.hxx>
@@ -133,6 +138,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf72727)
     assertXPathContent(pXmlDoc, "(//textarray)[3]/text", u"3");
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf92714_TOC_pageBreak)
+{
+    // Given a document with a ToC that also defines the page style
+    createSwDoc("tdf92714_TOC_pageBreak.odt");
+
+    // When deleting the ToC
+    SwView* pView = getSwDocShell()->GetView();
+    SfxDispatcher& rDispatcher = *pView->GetViewFrame().GetDispatcher();
+    rDispatcher.Execute(FN_REMOVE_CUR_TOX);
+
+    saveAndReload(u"writer8"_ustr);
+
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
+        xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<text::XPageCursor> 
xCursor(xTextViewCursorSupplier->getViewCursor(),
+                                              uno::UNO_QUERY);
+    // The page style should not be lost
+    CPPUNIT_ASSERT_EQUAL(u"OrangePage"_ustr, getProperty<OUString>(xCursor, 
u"PageStyleName"_ustr));
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf130969)
 {
     createSwDoc("tdf130969.docx");
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index 36f03f1a792d..1c050d30f2ea 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -623,6 +623,72 @@ bool SwDoc::DeleteTOX( const SwTOXBase& rTOXBase, bool 
bDelNodes )
                 }
             }
         }
+        else
+        {
+            // need to transfer potential TOX page breaks to following node
+            const SfxPoolItem* pPageDesc = nullptr;
+            const SfxPoolItem* pBreak = nullptr;
+            SwNodeIndex aSearchIdx(*pMyNode, 1); // the node after the TOX 
SectionNode
+            SwNodeIndex aEndSearchIdx(*pMyNode->EndOfSectionNode());
+
+            // did the TOC contain a page break?
+            while (aSearchIdx < aEndSearchIdx)
+            {
+                const SwNode& rNode = aSearchIdx.GetNode();
+                if (rNode.IsTextNode())
+                {
+                    const SfxItemSet* pSet = 
rNode.GetTextNode()->GetpSwAttrSet();
+                    if (pSet)
+                    {
+                        pBreak = pSet->GetItemIfSet(RES_BREAK, false);
+                        pPageDesc = pSet->GetItemIfSet(RES_PAGEDESC, false);
+                        if (pBreak || pPageDesc)
+                            break;
+                    }
+                }
+                ++aSearchIdx;
+            }
+            if (pBreak || pPageDesc)
+            {
+                // Apply the page break to the next node
+                aSearchIdx = aEndSearchIdx; // EndNode of TOX
+                aEndSearchIdx = *aSearchPam.GetPointNode().EndOfSectionNode(); 
// EndNode of Cursor
+                while (aSearchIdx < aEndSearchIdx)
+                {
+                    ++aSearchIdx;
+                    SwNode& rNode = aSearchIdx.GetNode();
+                    if (rNode.IsTextNode())
+                    {
+                        SwTextNode& rTextNode = *rNode.GetTextNode();
+                        // skip if destination node already defines its own 
page breaks
+                        if (rTextNode.GetSwAttrSet().GetBreak().GetBreak() != 
SvxBreak::NONE)
+                            break;
+                        if 
(rTextNode.GetSwAttrSet().GetPageDesc().GetPageDesc())
+                            break;
+
+                        if (pPageDesc)
+                            rTextNode.SetAttr(*pPageDesc);
+                        if (pBreak)
+                            rTextNode.SetAttr(*pBreak);
+                        break;
+                    }
+                    else if (rNode.IsTableNode())
+                    {
+                        SwFrameFormat* pTable = 
rNode.GetTableNode()->GetTable().GetFrameFormat();
+                        if (!pTable || pTable->GetBreak().GetBreak() != 
SvxBreak::NONE)
+                            break;
+                        if (pTable->GetPageDesc().GetPageDesc())
+                            break;
+
+                        if (pPageDesc)
+                            pTable->SetFormatAttr(*pPageDesc);
+                        if (pBreak)
+                            pTable->SetFormatAttr(*pBreak);
+                        break;
+                    }
+                }
+            }
+        }
 
         DelSectionFormat( const_cast<SwSectionFormat *>(pFormat), bDelNodes );
 

Reply via email to