diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-04-05 18:27:35 +0200 |
---|---|---|
committer | Thorsten Behrens <thorsten.behrens@allotropia.de> | 2022-04-08 00:48:27 +0200 |
commit | 855e2af1bf6eb216d63ca7baeb9161c7cd501a42 (patch) | |
tree | 10560f1023ad6784ecad8e34f932bb25d132ac70 /sw/source/core/doc | |
parent | e342185c4650ca2678ccbea92770e1ae147d08bc (diff) |
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 <michael.stahl@allotropia.de>
(cherry picked from commit 9dc6e2c9062725ef1f9d7e321cae5f4dbe8ca749)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132645
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
Diffstat (limited to 'sw/source/core/doc')
-rw-r--r-- | sw/source/core/doc/DocumentFieldsManager.cxx | 25 | ||||
-rw-r--r-- | sw/source/core/doc/docfld.cxx | 45 |
2 files changed, 55 insertions, 15 deletions
diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx b/sw/source/core/doc/DocumentFieldsManager.cxx index c7915021be87..59f3b0b0fefa 100644 --- a/sw/source/core/doc/DocumentFieldsManager.cxx +++ b/sw/source/core/doc/DocumentFieldsManager.cxx @@ -34,6 +34,7 @@ #include <SwUndoField.hxx> #include <flddat.hxx> #include <cntfrm.hxx> +#include <node2lay.hxx> #include <section.hxx> #include <docufld.hxx> #include <calbck.hxx> @@ -725,9 +726,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; } @@ -736,8 +740,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); } @@ -797,8 +804,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; } @@ -808,7 +818,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 <IDocumentMarkAccess.hxx> #include <IDocumentState.hxx> #include <IDocumentLayoutAccess.hxx> +#include <node2lay.hxx> #include <cntfrm.hxx> +#include <pagefrm.hxx> #include <txtfrm.hxx> #include <notxtfrm.hxx> #include <pam.hxx> @@ -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<Point, bool> 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<SwTextNode&>(rTextNd), rTField.GetStart()); + const SwFrame* pFrame = rTextNd.getLayoutFrame( + rDoc.getIDocumentLayoutAccess().GetCurrentLayout(), &pos, &tmp); std::unique_ptr<SetGetExpField> 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) ); } |