sw/qa/core/layout/data/floattable-wrap-on-all-pages.docx |binary sw/qa/core/layout/flycnt.cxx | 39 +++++++++++++++ sw/source/core/inc/flyfrms.hxx | 1 sw/source/core/layout/flycnt.cxx | 18 ++++++ sw/source/core/text/frmform.cxx | 5 + sw/source/core/text/porrst.cxx | 7 ++ 6 files changed, 68 insertions(+), 2 deletions(-)
New commits: commit 7d7ca347fafa7a06094b00e8fb0d0452c4c81366 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Oct 13 08:48:43 2023 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Oct 13 10:25:26 2023 +0200 sw floattable, wrap on all pages: add layout The anchor text of a floating table is normally wrapped around the table only on the last page of the table. This compat flag requests to wrap on all pages instead. First, disable the SwTextFrame::FormatEmpty() optimization in this case, so not only the last page has portions inside the text frame. Second, improve SwTextFrame::FormatAdjust(), so that anchor content from the last page can flow to previous pages. Note that having a dedicated SwFlyAtContentFrame::IsWrapOnAllPages() means that later it'll be possible to do per-frame decision on this if there is demand for that (this came up on the mailing list, but it's not something Word would support). Change-Id: I75df539df859aaa6c7eaaeddb33f004639b1c004 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157902 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/core/layout/data/floattable-wrap-on-all-pages.docx b/sw/qa/core/layout/data/floattable-wrap-on-all-pages.docx new file mode 100644 index 000000000000..39642002bbed Binary files /dev/null and b/sw/qa/core/layout/data/floattable-wrap-on-all-pages.docx differ diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx index 325b0078ecb0..16cd9cda4a57 100644 --- a/sw/qa/core/layout/flycnt.cxx +++ b/sw/qa/core/layout/flycnt.cxx @@ -30,6 +30,7 @@ #include <cellfrm.hxx> #include <ndtxt.hxx> #include <dflyobj.hxx> +#include <IDocumentSettingAccess.hxx> namespace { @@ -1183,6 +1184,44 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyInTableInSection) SwSortedObjs& rPage3Objs = *pPage3->GetSortedObjs(); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage3Objs.size()); } + +CPPUNIT_TEST_FIXTURE(Test, testSplitFlyWrapOnAllPages) +{ + // Given a document where we want to wrap on all pages, around a split floating table: + createSwDoc("floattable-wrap-on-all-pages.docx"); + SwDoc* pDoc = getSwDoc(); + pDoc->getIDocumentSettingAccess().set(DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK, + true); + + // When formatting that document: + SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell(); + pWrtShell->Reformat(); + + // Then make sure that the anchor text is also split between page 1 and page 2: + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + pLayout->dumpAsXml(); + auto pPage1 = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage1); + auto pPage1Anchor = pPage1->FindLastBodyContent()->DynCastTextFrame(); + CPPUNIT_ASSERT(pPage1Anchor); + OUString aAnchor1Text(pPage1Anchor->GetText().subView( + static_cast<sal_Int32>(pPage1Anchor->GetOffset()), + static_cast<sal_Int32>(pPage1Anchor->GetFollow()->GetOffset() + - pPage1Anchor->GetOffset()))); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: He heard quiet steps behind him. That + // - Actual : + // i.e. the first page had no anchor text, only the second. + CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. That "), aAnchor1Text); + auto pPage2 = pPage1->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage2); + auto pPage2Anchor = pPage2->FindLastBodyContent()->DynCastTextFrame(); + CPPUNIT_ASSERT(pPage2Anchor); + OUString aAnchor2Text( + pPage2Anchor->GetText().subView(static_cast<sal_Int32>(pPage2Anchor->GetOffset()))); + CPPUNIT_ASSERT(!pPage2Anchor->GetFollow()); + CPPUNIT_ASSERT_EQUAL(OUString("didn't bode well."), aAnchor2Text); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index fd4fff11b1d5..051d514fd31e 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -202,6 +202,7 @@ public: SwFlyAtContentFrame* GetPrecede(); /// Like Cut(), except that follow chaining is maintained. void DelEmpty(); + bool IsWrapOnAllPages() const; void dumpAsXmlAttributes(xmlTextWriterPtr pWriter) const override; }; diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx index 98843c2c0d47..c07201f49f43 100644 --- a/sw/source/core/layout/flycnt.cxx +++ b/sw/source/core/layout/flycnt.cxx @@ -1784,6 +1784,24 @@ void SwFlyAtContentFrame::DelEmpty() } } +bool SwFlyAtContentFrame::IsWrapOnAllPages() const +{ + const SwRootFrame* pRootFrame = getRootFrame(); + if (!pRootFrame) + { + return false; + } + + const SwFrameFormat* pFormat = pRootFrame->GetFormat(); + if (!pFormat) + { + return false; + } + + const IDocumentSettingAccess& rIDSA = pFormat->getIDocumentSettingAccess(); + return rIDSA.get(DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK); +} + void SwFlyAtContentFrame::dumpAsXmlAttributes(xmlTextWriterPtr pWriter) const { SwFlyFreeFrame::dumpAsXmlAttributes(pWriter); diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx index 1e20d7e0e9bc..76a1df56210a 100644 --- a/sw/source/core/text/frmform.cxx +++ b/sw/source/core/text/frmform.cxx @@ -1215,10 +1215,11 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, } ChangeOffset( GetFollow(), nEnd ); - if (HasNonLastSplitFlyDrawObj()) + SwFlyAtContentFrame* pNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj(); + if (pNonLastSplitFlyDrawObj && !pNonLastSplitFlyDrawObj->IsWrapOnAllPages()) { // Make sure content from the last floating table anchor is not shifted to previous - // anchors. + // anchors, unless we're in the special "wrap on all pages" mode. nEnd = TextFrameIndex(0); } diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx index bd3589b25676..029adca75336 100644 --- a/sw/source/core/text/porrst.cxx +++ b/sw/source/core/text/porrst.cxx @@ -416,6 +416,13 @@ bool SwTextFrame::FormatEmpty() // content. SwFlyAtContentFrame* pNonLastSplitFlyDrawObj = HasNonLastSplitFlyDrawObj(); bool bHasNonLastSplitFlyDrawObj = pNonLastSplitFlyDrawObj != nullptr; + + if (pNonLastSplitFlyDrawObj && pNonLastSplitFlyDrawObj->IsWrapOnAllPages()) + { + // Split fly: the anchor is non-empty on all pages in the "wrap on all pages" case. + bHasNonLastSplitFlyDrawObj = false; + } + if ((HasFollow() && !bHasNonLastSplitFlyDrawObj) || GetMergedPara() || (GetTextNodeFirst()->GetpSwpHints() && !bHasNonLastSplitFlyDrawObj) || nullptr != GetTextNodeForParaProps()->GetNumRule() || GetTextNodeFirst()->HasHiddenCharAttribute(true) ||