summaryrefslogtreecommitdiff
path: root/sw/source/core/doc
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2022-04-05 18:27:35 +0200
committerThorsten Behrens <thorsten.behrens@allotropia.de>2022-04-08 00:48:27 +0200
commit855e2af1bf6eb216d63ca7baeb9161c7cd501a42 (patch)
tree10560f1023ad6784ecad8e34f932bb25d132ac70 /sw/source/core/doc
parente342185c4650ca2678ccbea92770e1ae147d08bc (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.cxx25
-rw-r--r--sw/source/core/doc/docfld.cxx45
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) );
}