From 9dc6e2c9062725ef1f9d7e321cae5f4dbe8ca749 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Tue, 5 Apr 2022 18:27:35 +0200 Subject: sw: fix expansion of SetGetExpField in headers with split table rows The problem is that a get field in a header on page N may calculate and show values that do not take into account a set field on page N-1. This happens if a table row with multiple columns is split across the pages: SwGetExpField::ChangeExpansion() calls GetBodyTextNode(), which returns the first node in the first column that is on page N, but in the SwNodes array this node is *before* any node in columns 2..M, any of which may be on page N-1 in the layout. So try to fix this by adding a page number to SetGetExpField and using that as the highest priority in operator<(). This is a bit risky because some of the places that create SetGetExpField don't have a frame to get the page number from; try to adapt all that call into MakeFieldList(), while leaving unrelated ones such as in MakeSetList() unchanged. Change-Id: Ied2a897ad34f0faf1ef3d50baad07b23fafd49bd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132641 Tested-by: Jenkins Reviewed-by: Michael Stahl --- .../variable-field-table-row-split-header.fodt | 270 +++++++++++++++++++++ sw/qa/extras/uiwriter/uiwriter3.cxx | 73 ++++++ sw/source/core/doc/DocumentFieldsManager.cxx | 25 +- sw/source/core/doc/docfld.cxx | 45 +++- sw/source/core/docnode/node2lay.cxx | 77 ++++-- sw/source/core/fields/expfld.cxx | 3 +- sw/source/core/inc/docfld.hxx | 11 +- sw/source/core/inc/node2lay.hxx | 6 + 8 files changed, 477 insertions(+), 33 deletions(-) create mode 100644 sw/qa/extras/uiwriter/data/variable-field-table-row-split-header.fodt diff --git a/sw/qa/extras/uiwriter/data/variable-field-table-row-split-header.fodt b/sw/qa/extras/uiwriter/data/variable-field-table-row-split-header.fodt new file mode 100644 index 000000000000..9d3668b6b2ee --- /dev/null +++ b/sw/qa/extras/uiwriter/data/variable-field-table-row-split-header.fodt @@ -0,0 +1,270 @@ + + + 2022-04-06T17:07:05.9473620632022-04-06T17:17:45.832216066PT10M42S2LibreOfficeDev/7.4.0.0.alpha0$Linux_X86_64 LibreOffice_project/a5b31508f860f07ec86cda3cf992fcea2bee68ef + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 4 + + + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 011 + + + + + + + + + + + + + + + + + + + + + + + + + + 122 + + + + + + + + + + + + + + + + + + + + + + + + + + 233 + + + + + + + + 344 + + + + + + + + + \ No newline at end of file diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx index 654e08ace527..b4819567138e 100644 --- a/sw/qa/extras/uiwriter/uiwriter3.cxx +++ b/sw/qa/extras/uiwriter/uiwriter3.cxx @@ -154,6 +154,79 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf145321) CPPUNIT_ASSERT_EQUAL(3, getPages()); } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testVariableFieldTableRowSplitHeader) +{ + SwDoc* const pDoc = createSwDoc(DATA_DIRECTORY, "variable-field-table-row-split-header.fodt"); + + // finish layout + Scheduler::ProcessEventsToIdle(); + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + // the fields in cell are: variable-get variable-set variable-get + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special", 3); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[1]", "rText", "0"); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[2]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[3]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[1]/header/txt[1]/Special[1]", "rText", "0"); + assertXPath(pXmlDoc, "/root/page[1]/footer/txt[1]/Special[1]", "rText", "1"); + // here the header had shown the wrong value + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[2]/header/txt[1]/Special[1]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[2]/footer/txt[1]/Special[1]", "rText", "2"); + + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[3]/header/txt[1]/Special[1]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[3]/footer/txt[1]/Special[1]", "rText", "3"); + + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[4]/header/txt[1]/Special[1]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[4]/footer/txt[1]/Special[1]", "rText", "4"); + + assertXPath(pXmlDoc, "/root/page[5]/header/txt[1]/Special[1]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[5]/footer/txt[1]/Special[1]", "rText", "4"); + + discardDumpedLayout(); + // update and check again + pDoc->getIDocumentFieldsAccess().UpdateFields(true); + Scheduler::ProcessEventsToIdle(); + pXmlDoc = parseLayoutDump(); + + // the fields in cell are: variable-get variable-set variable-get + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special", 3); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[1]", "rText", "0"); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[2]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[1]/body/tab/row[1]/cell[2]/txt[1]/Special[3]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[1]/header/txt[1]/Special[1]", "rText", "0"); + assertXPath(pXmlDoc, "/root/page[1]/footer/txt[1]/Special[1]", "rText", "1"); + // here the header had shown the wrong value + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[2]/header/txt[1]/Special[1]", "rText", "1"); + assertXPath(pXmlDoc, "/root/page[2]/footer/txt[1]/Special[1]", "rText", "2"); + + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[3]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[3]/header/txt[1]/Special[1]", "rText", "2"); + assertXPath(pXmlDoc, "/root/page[3]/footer/txt[1]/Special[1]", "rText", "3"); + + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[1]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[2]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[4]/body/tab/row[2]/cell[2]/txt[1]/Special[3]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[4]/header/txt[1]/Special[1]", "rText", "3"); + assertXPath(pXmlDoc, "/root/page[4]/footer/txt[1]/Special[1]", "rText", "4"); + + assertXPath(pXmlDoc, "/root/page[5]/header/txt[1]/Special[1]", "rText", "4"); + assertXPath(pXmlDoc, "/root/page[5]/footer/txt[1]/Special[1]", "rText", "4"); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf147126) { createSwDoc(DATA_DIRECTORY, "tdf147126.docx"); diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx b/sw/source/core/doc/DocumentFieldsManager.cxx index e1f3b7a0d58e..bc492046572f 100644 --- a/sw/source/core/doc/DocumentFieldsManager.cxx +++ b/sw/source/core/doc/DocumentFieldsManager.cxx @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -724,9 +725,12 @@ void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt ) { SwPosition aPos( *pTableNd ); if( GetBodyTextNode( m_rDoc, aPos, *pFrame ) ) + { FieldsToCalc( *pCalc, SetGetExpField( - aPos.nNode, pFormatField->GetTextField(), - &aPos.nContent), pLayout); + aPos.nNode, pFormatField->GetTextField(), + &aPos.nContent, pFrame->GetPhyPageNum()), + pLayout); + } else pFrame = nullptr; } @@ -735,8 +739,11 @@ void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt ) { // create index to determine the TextNode SwNodeIndex aIdx( rTextNd ); + SwFrame const*const pFrame2 = ::sw::FindNeighbourFrameForNode(rTextNd); FieldsToCalc( *pCalc, - SetGetExpField(aIdx, pFormatField->GetTextField()), + SetGetExpField(aIdx, pFormatField->GetTextField(), + nullptr, + pFrame2 ? pFrame2->GetPhyPageNum() : 0), pLayout); } @@ -796,8 +803,11 @@ void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt ) { SwPosition aPos( *pCNd ); if( GetBodyTextNode( m_rDoc, aPos, *pFrame ) ) - FieldsToCalc(*pCalc, SetGetExpField(aPos.nNode), - pLayout); + { + FieldsToCalc(*pCalc, SetGetExpField(aPos.nNode, + nullptr, nullptr, pFrame->GetPhyPageNum()), + pLayout); + } else pFrame = nullptr; } @@ -807,7 +817,10 @@ void DocumentFieldsManager::UpdateTableFields( SfxPoolItem* pHt ) { // create index to determine the TextNode SwNodeIndex aIdx( *pTableNd ); - FieldsToCalc(*pCalc, SetGetExpField(aIdx), pLayout); + SwFrame const*const pFrame2 = ::sw::FindNeighbourFrameForNode(*pTableNd); + FieldsToCalc(*pCalc, SetGetExpField(aIdx, nullptr, nullptr, + pFrame2 ? pFrame2->GetPhyPageNum() : 0), + pLayout); } SwTableCalcPara aPara(*pCalc, pTableNd->GetTable(), pLayout); diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx index 2a10c63debc9..652af8a188b9 100644 --- a/sw/source/core/doc/docfld.cxx +++ b/sw/source/core/doc/docfld.cxx @@ -33,7 +33,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -63,7 +65,9 @@ using namespace ::com::sun::star::uno; SetGetExpField::SetGetExpField( const SwNodeIndex& rNdIdx, const SwTextField* pField, - const SwIndex* pIdx ) + const SwIndex* pIdx, + sal_uInt16 const nPageNumber) + : m_nPageNumber(nPageNumber) { m_eSetGetExpFieldType = TEXTFIELD; m_CNTNT.pTextField = pField; @@ -89,7 +93,9 @@ SetGetExpField::SetGetExpField( const SwNodeIndex& rNdIdx, // these always have content position 0xffffffff! // There is never a field on this, only up to COMPLETE_STRING possible SetGetExpField::SetGetExpField( const SwSectionNode& rSectNd, - const SwPosition* pPos ) + const SwPosition* pPos, + sal_uInt16 const nPageNumber) + : m_nPageNumber(nPageNumber) { m_eSetGetExpFieldType = SECTIONNODE; m_CNTNT.pSection = &rSectNd.GetSection(); @@ -107,7 +113,9 @@ SetGetExpField::SetGetExpField( const SwSectionNode& rSectNd, } SetGetExpField::SetGetExpField(::sw::mark::IBookmark const& rBookmark, - SwPosition const*const pPos) + SwPosition const*const pPos, + sal_uInt16 const nPageNumber) + : m_nPageNumber(nPageNumber) { m_eSetGetExpFieldType = BOOKMARK; m_CNTNT.pBookmark = &rBookmark; @@ -220,6 +228,10 @@ bool SetGetExpField::operator==( const SetGetExpField& rField ) const bool SetGetExpField::operator<( const SetGetExpField& rField ) const { + if (m_nPageNumber != 0 && rField.m_nPageNumber != 0 && m_nPageNumber != rField.m_nPageNumber) + { + return m_nPageNumber < rField.m_nPageNumber; + } if( m_nNode < rField.m_nNode || ( m_nNode == rField.m_nNode && m_nContent < rField.m_nContent )) return true; else if( m_nNode != rField.m_nNode || m_nContent != rField.m_nContent ) @@ -1030,8 +1042,10 @@ void SwDocUpdateField::GetBodyNode( const SwTextField& rTField, SwFieldIds nFiel // always the first! (in tab headline, header-/footer) Point aPt; std::pair const tmp(aPt, false); - const SwContentFrame* pFrame = rTextNd.getLayoutFrame( - rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp); + // need pos to get the frame on the correct page + SwPosition const pos(const_cast(rTextNd), rTField.GetStart()); + const SwFrame* pFrame = rTextNd.getLayoutFrame( + rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), &pos, &tmp); std::unique_ptr pNew; bool bIsInBody = false; @@ -1046,8 +1060,16 @@ void SwDocUpdateField::GetBodyNode( const SwTextField& rTField, SwFieldIds nFiel // in frames whose anchor is in redline. However, we do want to update // fields in hidden sections. So: In order to be updated, a field 1) // must have a frame, or 2) it must be in the document body. + if (pFrame == nullptr && bIsInBody) + { // try harder to get a frame for the page number + pFrame = ::sw::FindNeighbourFrameForNode(rTextNd); + // possibly there is no layout at all, happens in mail merge + } if( (pFrame != nullptr) || bIsInBody ) - pNew.reset(new SetGetExpField( aIdx, &rTField )); + { + pNew.reset(new SetGetExpField(aIdx, &rTField, nullptr, + pFrame ? pFrame->GetPhyPageNum() : 0)); + } } else { @@ -1055,7 +1077,8 @@ void SwDocUpdateField::GetBodyNode( const SwTextField& rTField, SwFieldIds nFiel SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() ); bool const bResult = GetBodyTextNode( rDoc, aPos, *pFrame ); OSL_ENSURE(bResult, "where is the Field"); - pNew.reset(new SetGetExpField( aPos.nNode, &rTField, &aPos.nContent )); + pNew.reset(new SetGetExpField(aPos.nNode, &rTField, &aPos.nContent, + pFrame->GetPhyPageNum())); } // always set the BodyTextFlag in GetExp or DB fields @@ -1106,13 +1129,17 @@ void SwDocUpdateField::GetBodyNodeGeneric(SwNode const& rNode, T const& rCond) bool const bResult = GetBodyTextNode( rDoc, aPos, *pFrame ); OSL_ENSURE(bResult, "where is the Field"); - pNew.reset(new SetGetExpField(rCond, &aPos)); + pNew.reset(new SetGetExpField(rCond, &aPos, pFrame->GetPhyPageNum())); } while( false ); } if( !pNew ) - pNew.reset(new SetGetExpField(rCond)); + { + // try harder to get a frame for the page number + SwFrame const*const pFrame = ::sw::FindNeighbourFrameForNode(rNode); + pNew.reset(new SetGetExpField(rCond, nullptr, pFrame ? pFrame->GetPhyPageNum() : 0)); + } m_pFieldSortList->insert( std::move(pNew) ); } diff --git a/sw/source/core/docnode/node2lay.cxx b/sw/source/core/docnode/node2lay.cxx index 591fc6541f4f..5cc15c3106b5 100644 --- a/sw/source/core/docnode/node2lay.cxx +++ b/sw/source/core/docnode/node2lay.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ public: SwFrame* GetFrame( const Point* pDocPos ) const; }; -static SwNode* GoNextWithFrame(const SwNodes& rNodes, SwNodeIndex *pIdx) +static SwNode* GoNextWithFrame(const SwNodes& rNodes, SwNodeIndex *pIdx, SwFlowFrame const**const ppFrame) { if( pIdx->GetIndex() >= rNodes.Count() - 1 ) return nullptr; @@ -67,20 +68,27 @@ static SwNode* GoNextWithFrame(const SwNodes& rNodes, SwNodeIndex *pIdx) while( aTmp < rNodes.Count()-1 ) { pNd = &aTmp.GetNode(); - bool bFound = false; + SwFrame const* pFound(nullptr); if ( pNd->IsContentNode() ) // sw_redlinehide: assume that it's OK to find a node with the same // frame as the caller's one - bFound = SwIterator(*static_cast(pNd)).First(); + pFound = SwIterator(*static_cast(pNd)).First(); else if ( pNd->IsTableNode() ) - bFound = SwIterator(*static_cast(pNd)->GetTable().GetFrameFormat()).First() ; + pFound = SwIterator(*static_cast(pNd)->GetTable().GetFrameFormat()).First() ; else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() ) { pNd = nullptr; break; } - if ( bFound ) - break; + if (pFound != nullptr) + { + if (ppFrame) + { + *ppFrame = SwFlowFrame::CastFlowFrame(pFound); + assert(*ppFrame); + } + break; + } ++aTmp; } @@ -91,7 +99,7 @@ static SwNode* GoNextWithFrame(const SwNodes& rNodes, SwNodeIndex *pIdx) return pNd; } -static SwNode* GoPreviousWithFrame(SwNodeIndex *pIdx) +static SwNode* GoPreviousWithFrame(SwNodeIndex *pIdx, SwFlowFrame const**const ppFrame) { if( !pIdx->GetIndex() ) return nullptr; @@ -101,20 +109,27 @@ static SwNode* GoPreviousWithFrame(SwNodeIndex *pIdx) while( aTmp.GetIndex() ) { pNd = &aTmp.GetNode(); - bool bFound = false; + SwFrame const* pFound(nullptr); if ( pNd->IsContentNode() ) // sw_redlinehide: assume that it's OK to find a node with the same // frame as the caller's one - bFound = SwIterator(*static_cast(pNd)).First(); + pFound = SwIterator(*static_cast(pNd)).First(); else if ( pNd->IsTableNode() ) - bFound = SwIterator(*static_cast(pNd)->GetTable().GetFrameFormat()).First(); + pFound = SwIterator(*static_cast(pNd)->GetTable().GetFrameFormat()).First(); else if( pNd->IsStartNode() && !pNd->IsSectionNode() ) { pNd = nullptr; break; } - if ( bFound ) - break; + if (pFound != nullptr) + { + if (ppFrame) + { + *ppFrame = SwFlowFrame::CastFlowFrame(pFound); + assert(*ppFrame); + } + break; + } --aTmp; } @@ -125,6 +140,40 @@ static SwNode* GoPreviousWithFrame(SwNodeIndex *pIdx) return pNd; } +namespace sw { + +SwFrame const* FindNeighbourFrameForNode(SwNode const& rNode) +{ + SwNodeIndex idx(rNode); + SwFlowFrame const* pFlow(nullptr); + if (SwNode *const pNode = GoPreviousWithFrame(&idx, &pFlow)) + { + if (::CheckNodesRange(rNode, idx, true)) + { + while (pFlow->HasFollow()) + { // try to get the one on the current page + pFlow = pFlow->GetFollow(); + } + return &pFlow->GetFrame(); + } + } + idx = rNode; + if (SwNode *const pNode = GoNextWithFrame(idx.GetNodes(), &idx, &pFlow)) + { + if (::CheckNodesRange(rNode, idx, true)) + { + while (pFlow->IsFollow()) + { // try to get the one on the current page + pFlow = pFlow->GetPrecede(); + } + return &pFlow->GetFrame(); + } + } + return nullptr; +} + +} + /** * The main purpose of this ctor is to find the right sw::BroadcastingModify to iterate over. * @@ -145,7 +194,7 @@ SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, SwNodeOffset nIdx, bool bSe if( !bSearch && rNode.GetIndex() < mnIndex ) { SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 ); - pNd = GoPreviousWithFrame( &aTmp ); + pNd = GoPreviousWithFrame(&aTmp, nullptr); if( pNd && rNode.GetIndex() > pNd->GetIndex() ) pNd = nullptr; // Do not go over the limits mbMaster = false; @@ -153,7 +202,7 @@ SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, SwNodeOffset nIdx, bool bSe else { SwNodeIndex aTmp( rNode, -1 ); - pNd = GoNextWithFrame( rNode.GetNodes(), &aTmp ); + pNd = GoNextWithFrame(rNode.GetNodes(), &aTmp, nullptr); mbMaster = true; if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() ) pNd = nullptr; // Do not go over the limits diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx index 6c5f45f3716d..6bf92cc47f0b 100644 --- a/sw/source/core/fields/expfld.cxx +++ b/sw/source/core/fields/expfld.cxx @@ -375,7 +375,8 @@ void SwGetExpField::ChangeExpansion( const SwFrame& rFrame, const SwTextField& r SwRootFrame const& rLayout(*rFrame.getRootFrame()); OUString & rExpand(rLayout.IsHideRedlines() ? m_sExpandRLHidden : m_sExpand); - SetGetExpField aEndField( aPos.nNode, &rField, &aPos.nContent ); + // here a page number is needed to sort correctly + SetGetExpField aEndField(aPos.nNode, &rField, &aPos.nContent, rFrame.GetPhyPageNum()); if(GetSubType() & nsSwGetSetExpType::GSE_STRING) { SwHashTable aHashTable(0); diff --git a/sw/source/core/inc/docfld.hxx b/sw/source/core/inc/docfld.hxx index 70d6e033dc0d..117ee0408e34 100644 --- a/sw/source/core/inc/docfld.hxx +++ b/sw/source/core/inc/docfld.hxx @@ -44,6 +44,8 @@ enum class SwFieldIds : sal_uInt16; // Update expression fields class SetGetExpField { + // TODO: in case of multiple layouts, storing this only once isn't going to work (although already a problem for cached field value) + sal_uInt16 m_nPageNumber = 0; SwNodeOffset m_nNode; union { const SwTextField* pTextField; @@ -64,15 +66,18 @@ class SetGetExpField public: SetGetExpField( const SwNodeIndex& rNdIdx, const SwTextField* pField = nullptr, - const SwIndex* pIdx = nullptr ); + const SwIndex* pIdx = nullptr, + sal_uInt16 nPageNumber = 0); SetGetExpField( const SwNodeIndex& rNdIdx, const SwTextINetFormat& rINet ); SetGetExpField( const SwSectionNode& rSectNode, - const SwPosition* pPos = nullptr ); + const SwPosition* pPos = nullptr, + sal_uInt16 nPageNumber = 0); SetGetExpField( ::sw::mark::IBookmark const& rBookmark, - SwPosition const* pPos = nullptr ); + SwPosition const* pPos = nullptr, + sal_uInt16 nPageNumber = 0); SetGetExpField( const SwTableBox& rTableBox ); diff --git a/sw/source/core/inc/node2lay.hxx b/sw/source/core/inc/node2lay.hxx index e0334c156435..0ba712f19727 100644 --- a/sw/source/core/inc/node2lay.hxx +++ b/sw/source/core/inc/node2lay.hxx @@ -79,6 +79,12 @@ public: void RestoreUpperFrames(SwNodes& rNds, SwNodeOffset nStt, SwNodeOffset nEnd); }; +namespace sw +{ +SwFrame const* FindNeighbourFrameForNode(SwNode const& rNode); + +} // namespace sw + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit