summaryrefslogtreecommitdiffstats
path: root/sw/source/core/layout/ssfrm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/ssfrm.cxx')
-rw-r--r--sw/source/core/layout/ssfrm.cxx739
1 files changed, 739 insertions, 0 deletions
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
new file mode 100644
index 000000000..1a92144a5
--- /dev/null
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -0,0 +1,739 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <pagefrm.hxx>
+#include <rootfrm.hxx>
+#include <dcontact.hxx>
+#include <flyfrm.hxx>
+#include <txtfrm.hxx>
+#include <cellfrm.hxx>
+#include <swtable.hxx>
+#include <fmtfsize.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <fmtclds.hxx>
+#include <viewimp.hxx>
+#include <sortedobjs.hxx>
+#include <hints.hxx>
+#include <frmtool.hxx>
+#include <ndtxt.hxx>
+
+ // No inline cause we need the function pointers
+long SwFrame::GetTopMargin() const
+ { return getFramePrintArea().Top(); }
+long SwFrame::GetBottomMargin() const
+ { return getFrameArea().Height() -getFramePrintArea().Height() -getFramePrintArea().Top(); }
+long SwFrame::GetLeftMargin() const
+ { return getFramePrintArea().Left(); }
+long SwFrame::GetRightMargin() const
+ { return getFrameArea().Width() - getFramePrintArea().Width() - getFramePrintArea().Left(); }
+long SwFrame::GetPrtLeft() const
+ { return getFrameArea().Left() + getFramePrintArea().Left(); }
+long SwFrame::GetPrtBottom() const
+ { return getFrameArea().Top() + getFramePrintArea().Height() + getFramePrintArea().Top(); }
+long SwFrame::GetPrtRight() const
+ { return getFrameArea().Left() + getFramePrintArea().Width() + getFramePrintArea().Left(); }
+long SwFrame::GetPrtTop() const
+ { return getFrameArea().Top() + getFramePrintArea().Top(); }
+
+bool SwFrame::SetMinLeft( long nDeadline )
+{
+ SwTwips nDiff = nDeadline - getFrameArea().Left();
+ if( nDiff > 0 )
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aFrm.Left( nDeadline );
+
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Width( aPrt.Width() - nDiff );
+
+ return true;
+ }
+ return false;
+}
+
+bool SwFrame::SetMaxBottom( long nDeadline )
+{
+ SwTwips nDiff = getFrameArea().Top() + getFrameArea().Height() - nDeadline;
+ if( nDiff > 0 )
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aFrm.Height( aFrm.Height() - nDiff );
+
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Height( aPrt.Height() - nDiff );
+
+ return true;
+ }
+ return false;
+}
+
+bool SwFrame::SetMaxRight( long nDeadline )
+{
+ SwTwips nDiff = getFrameArea().Left() + getFrameArea().Width() - nDeadline;
+ if( nDiff > 0 )
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aFrm.Width( aFrm.Width() - nDiff );
+
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Width( aPrt.Width() - nDiff );
+
+ return true;
+ }
+ return false;
+}
+
+void SwFrame::MakeBelowPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify )
+{
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->getFrameArea().Pos() );
+ aFrm.Pos().AdjustY(pPrv->getFrameArea().Height() );
+ }
+ else
+ {
+ aFrm.Pos( pUp->getFrameArea().Pos() );
+ aFrm.Pos() += pUp->getFramePrintArea().Pos();
+ }
+
+ if( bNotify )
+ {
+ aFrm.Pos().AdjustY(1 );
+ }
+}
+
+void SwFrame::MakeLeftPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify )
+{
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->getFrameArea().Pos() );
+ aFrm.Pos().AdjustX( -(aFrm.Width()) );
+ }
+ else
+ {
+ aFrm.Pos( pUp->getFrameArea().Pos() );
+ aFrm.Pos() += pUp->getFramePrintArea().Pos();
+ aFrm.Pos().AdjustX(pUp->getFramePrintArea().Width() - aFrm.Width() );
+ }
+
+ if( bNotify )
+ {
+ aFrm.Pos().AdjustX( -1 );
+ }
+}
+
+void SwFrame::MakeRightPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify )
+{
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+
+ if( pPrv )
+ {
+ aFrm.Pos( pPrv->getFrameArea().Pos() );
+ aFrm.Pos().AdjustX(pPrv->getFrameArea().Width() );
+ }
+ else
+ {
+ aFrm.Pos( pUp->getFrameArea().Pos() );
+ aFrm.Pos() += pUp->getFramePrintArea().Pos();
+ }
+
+ if( bNotify )
+ {
+ aFrm.Pos().AdjustX(1 );
+ }
+}
+
+void SwFrame::SetTopBottomMargins( long nTop, long nBot )
+{
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Top( nTop );
+ aPrt.Height( getFrameArea().Height() - nTop - nBot );
+}
+
+void SwFrame::SetLeftRightMargins( long nLeft, long nRight)
+{
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Left( nLeft );
+ aPrt.Width( getFrameArea().Width() - nLeft - nRight );
+}
+
+void SwFrame::SetRightLeftMargins( long nRight, long nLeft)
+{
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.Left( nLeft );
+ aPrt.Width( getFrameArea().Width() - nLeft - nRight );
+}
+
+/// checks the layout direction and invalidates the lower frames recursively, if necessary.
+void SwFrame::CheckDirChange()
+{
+ bool bOldVert = mbVertical;
+ bool bOldR2L = mbRightToLeft;
+ SetInvalidVert( true );
+ mbInvalidR2L = true;
+ bool bChg = bOldR2L != IsRightToLeft();
+ bool bOldVertL2R = IsVertLR();
+ if( ( IsVertical() != bOldVert ) || bChg || bOldVertL2R != IsVertLR() )
+ {
+ InvalidateAll();
+ if( IsLayoutFrame() )
+ {
+ // set minimum row height for vertical cells in horizontal table:
+ if ( IsCellFrame() && GetUpper() )
+ {
+ if ( IsVertical() != GetUpper()->IsVertical() &&
+ static_cast<SwCellFrame*>(this)->GetTabBox()->getRowSpan() == 1 )
+ {
+ enum {
+ MIN_VERT_CELL_HEIGHT = 1135
+ };
+
+ SwTableLine* pLine = const_cast<SwTableLine*>(static_cast<SwCellFrame*>(this)->GetTabBox()->GetUpper());
+ SwFrameFormat* pFrameFormat = pLine->GetFrameFormat();
+ SwFormatFrameSize aNew( pFrameFormat->GetFrameSize() );
+ if ( SwFrameSize::Fixed != aNew.GetHeightSizeType() )
+ aNew.SetHeightSizeType( SwFrameSize::Minimum );
+ if ( aNew.GetHeight() < MIN_VERT_CELL_HEIGHT )
+ aNew.SetHeight( MIN_VERT_CELL_HEIGHT );
+ SwDoc* pDoc = pFrameFormat->GetDoc();
+ pDoc->SetAttr( aNew, *pLine->ClaimFrameFormat() );
+ }
+ }
+
+ SwFrame* pFrame = static_cast<SwLayoutFrame*>(this)->Lower();
+ const SwFormatCol* pCol = nullptr;
+ SwLayoutFrame* pBody = nullptr;
+ if( pFrame )
+ {
+ if( IsPageFrame() )
+ {
+ // If we're a page frame and we change our layout direction,
+ // we have to look for columns and rearrange them.
+ pBody = static_cast<SwPageFrame*>(this)->FindBodyCont();
+ if(pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame())
+ pCol = &static_cast<SwPageFrame*>(this)->GetFormat()->GetCol();
+ }
+ else if( pFrame->IsColumnFrame() )
+ {
+ pBody = static_cast<SwLayoutFrame*>(this);
+ const SwFrameFormat *pFormat = pBody->GetFormat();
+ if( pFormat )
+ pCol = &pFormat->GetCol();
+ }
+ }
+ while( pFrame )
+ {
+ pFrame->CheckDirChange();
+ pFrame = pFrame->GetNext();
+ }
+ if( pCol )
+ pBody->AdjustColumns( pCol, true );
+ }
+ else if( IsTextFrame() )
+ static_cast<SwTextFrame*>(this)->Prepare();
+
+ // #i31698# - notify anchored objects also for page frames.
+ // Remove code above for special handling of page frames
+ if ( GetDrawObjs() )
+ {
+ const SwSortedObjs *pObjs = GetDrawObjs();
+ const size_t nCnt = pObjs->size();
+ for ( size_t i = 0; i < nCnt; ++i )
+ {
+ SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
+ if( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
+ static_cast<SwFlyFrame*>(pAnchoredObj)->CheckDirChange();
+ else
+ {
+ // OD 2004-04-06 #i26791# - direct object
+ // positioning no longer needed. Instead
+ // invalidate
+ pAnchoredObj->InvalidateObjPos();
+ }
+ // #i31698# - update layout direction of
+ // anchored object
+ {
+ ::setContextWritingMode( pAnchoredObj->DrawObj(), pAnchoredObj->GetAnchorFrameContainingAnchPos() );
+ pAnchoredObj->UpdateLayoutDir();
+ }
+ }
+ }
+ }
+}
+
+/// returns the position for anchors based on frame direction
+// OD 2004-03-10 #i11860# - consider lower space and line spacing of
+// previous frame according to new option 'Use former object positioning'
+Point SwFrame::GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const
+{
+ Point aAnchor = getFrameArea().Pos();
+
+ if ( ( IsVertical() && !IsVertLR() ) || IsRightToLeft() )
+ aAnchor.AdjustX(getFrameArea().Width() );
+
+ if ( IsTextFrame() )
+ {
+ SwTwips nBaseOfstForFly =
+ static_cast<const SwTextFrame*>(this)->GetBaseOffsetForFly( bIgnoreFlysAnchoredAtThisFrame );
+ if ( IsVertical() )
+ aAnchor.AdjustY(nBaseOfstForFly );
+ else
+ aAnchor.AdjustX(nBaseOfstForFly );
+
+ // OD 2004-03-10 #i11860# - if option 'Use former object positioning'
+ // is OFF, consider the lower space and the line spacing of the
+ // previous frame and the spacing considered for the page grid
+ const SwTextFrame* pThisTextFrame = static_cast<const SwTextFrame*>(this);
+ const SwTwips nUpperSpaceAmountConsideredForPrevFrameAndPageGrid =
+ pThisTextFrame->GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid();
+ if ( IsVertical() )
+ {
+ aAnchor.AdjustX( -nUpperSpaceAmountConsideredForPrevFrameAndPageGrid );
+ }
+ else
+ {
+ aAnchor.AdjustY(nUpperSpaceAmountConsideredForPrevFrameAndPageGrid );
+ }
+ }
+
+ return aAnchor;
+}
+
+void SwFrame::DestroyImpl()
+{
+ mbInDtor = true;
+
+ // accessible objects for fly and cell frames have been already disposed
+ // by the destructors of the derived classes.
+ if (IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame())
+ && (GetDep() || IsTextFrame())) // sw_redlinehide: text frame may not have Dep!
+ {
+ assert(!IsTextFrame() || GetDep() || static_cast<SwTextFrame*>(this)->GetMergedPara());
+ SwRootFrame *pRootFrame = getRootFrame();
+ if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
+ {
+ SwViewShell *pVSh = pRootFrame->GetCurrShell();
+ if( pVSh && pVSh->Imp() )
+ {
+ OSL_ENSURE( !GetLower(), "Lowers should be dispose already!" );
+ pVSh->Imp()->DisposeAccessibleFrame( this );
+ }
+ }
+ }
+
+ if (m_pDrawObjs)
+ {
+ for (size_t i = m_pDrawObjs->size(); i; )
+ {
+ SwAnchoredObject* pAnchoredObj = (*m_pDrawObjs)[--i];
+ if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
+ {
+ SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj));
+ }
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrame::~SwFrame> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+ }
+ }
+ m_pDrawObjs.reset();
+ }
+}
+
+SwFrame::~SwFrame()
+{
+ assert(m_isInDestroy); // check that only DestroySwFrame does "delete"
+ assert(!IsDeleteForbidden()); // check that it's not deleted while deletes are forbidden
+#if OSL_DEBUG_LEVEL > 0
+ // JP 15.10.2001: for detection of access to deleted frames
+ mpRoot = reinterpret_cast<SwRootFrame*>(0x33333333);
+#endif
+}
+
+void SwFrame::DestroyFrame(SwFrame *const pFrame)
+{
+ if (pFrame)
+ {
+ pFrame->m_isInDestroy = true;
+ pFrame->DestroyImpl();
+ assert(pFrame->mbInDtor); // check that nobody forgot to call base class
+ delete pFrame;
+ }
+}
+
+const SwFrameFormat * SwLayoutFrame::GetFormat() const
+{
+ return static_cast< const SwFrameFormat * >( GetDep() );
+}
+
+SwFrameFormat * SwLayoutFrame::GetFormat()
+{
+ return static_cast< SwFrameFormat * >( GetDep() );
+}
+
+void SwLayoutFrame::SetFrameFormat( SwFrameFormat *pNew )
+{
+ if ( pNew != GetFormat() )
+ {
+ SwFormatChg aOldFormat( GetFormat() );
+ pNew->Add( this );
+ SwFormatChg aNewFormat( pNew );
+ ModifyNotification( &aOldFormat, &aNewFormat );
+ }
+}
+
+SwContentFrame::SwContentFrame( SwContentNode * const pContent, SwFrame* pSib ) :
+ SwFrame( pContent, pSib ),
+ SwFlowFrame( static_cast<SwFrame&>(*this) )
+{
+ assert(!getRootFrame()->IsHideRedlines() || pContent->IsCreateFrameWhenHidingRedlines());
+}
+
+void SwContentFrame::DestroyImpl()
+{
+ const SwContentNode* pCNd(dynamic_cast<SwContentNode*>(GetDep()));
+ if (nullptr == pCNd && IsTextFrame())
+ {
+ pCNd = static_cast<SwTextFrame*>(this)->GetTextNodeFirst();
+ }
+ // IsInDtor shouldn't be happening with ViewShell owning layout
+ assert(nullptr == pCNd || !pCNd->GetDoc()->IsInDtor());
+ if (nullptr != pCNd && !pCNd->GetDoc()->IsInDtor())
+ {
+ //Unregister from root if I'm still in turbo there.
+ SwRootFrame *pRoot = getRootFrame();
+ if( pRoot && pRoot->GetTurbo() == this )
+ {
+ pRoot->DisallowTurbo();
+ pRoot->ResetTurbo();
+ }
+ }
+
+ SwFrame::DestroyImpl();
+}
+
+SwContentFrame::~SwContentFrame()
+{
+}
+
+void SwTextFrame::RegisterToNode(SwTextNode & rNode, bool const isForceNodeAsFirst)
+{
+ if (isForceNodeAsFirst && m_pMergedPara)
+ { // nothing registered here, in particular no delete redlines (insert
+ // redline might end on empty node where delete rl starts, should be ok)
+ assert(m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex());
+ assert(rNode.GetDoc()->getIDocumentRedlineAccess().GetRedlinePos(
+ *m_pMergedPara->pFirstNode, RedlineType::Delete) == SwRedlineTable::npos);
+ }
+ assert(&rNode != GetDep());
+ assert(!m_pMergedPara
+ || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+ || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex()));
+ SwTextNode & rFirstNode(
+ (!isForceNodeAsFirst && m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+ ? *m_pMergedPara->pFirstNode
+ : rNode);
+ // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef
+ m_pMergedPara = sw::CheckParaRedlineMerge(*this, rFirstNode, sw::FrameMode::New);
+ if (!m_pMergedPara)
+ {
+ rNode.Add(this);
+ }
+}
+
+void SwLayoutFrame::DestroyImpl()
+{
+ while (!m_VertPosOrientFramesFor.empty())
+ {
+ SwAnchoredObject *pObj = *m_VertPosOrientFramesFor.begin();
+ pObj->ClearVertPosOrientFrame();
+ }
+
+ assert(m_VertPosOrientFramesFor.empty());
+
+ SwFrame *pFrame = m_pLower;
+
+ if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() )
+ {
+ while ( pFrame )
+ {
+ //First delete the Objs of the Frame because they can't unregister
+ //from the page after remove.
+ //We don't want to create an endless loop only because one couldn't
+ //unregister.
+
+ while ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() )
+ {
+ const size_t nCnt = pFrame->GetDrawObjs()->size();
+ // #i28701#
+ SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[0];
+ if (SwFlyFrame* pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj))
+ {
+ SwFrame::DestroyFrame(pFlyFrame);
+ assert(!pFrame->GetDrawObjs() || nCnt > pFrame->GetDrawObjs()->size());
+ }
+ else
+ {
+ pAnchoredObj->ClearTmpConsiderWrapInfluence();
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrame::~SwFrame> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+
+ if ( pFrame->GetDrawObjs() &&
+ nCnt == pFrame->GetDrawObjs()->size() )
+ {
+ pFrame->GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ }
+ }
+ pFrame->RemoveFromLayout();
+ SwFrame::DestroyFrame(pFrame);
+ pFrame = m_pLower;
+ }
+ //Delete the Flys, the last one also deletes the array.
+ while ( GetDrawObjs() && GetDrawObjs()->size() )
+ {
+ const size_t nCnt = GetDrawObjs()->size();
+
+ // #i28701#
+ SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[0];
+ if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
+ {
+ SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj));
+ assert(!GetDrawObjs() || nCnt > GetDrawObjs()->size());
+ }
+ else
+ {
+ SdrObject* pSdrObj = pAnchoredObj->DrawObj();
+ SwDrawContact* pContact =
+ static_cast<SwDrawContact*>(pSdrObj->GetUserCall());
+ OSL_ENSURE( pContact,
+ "<SwFrame::~SwFrame> - missing contact for drawing object" );
+ if ( pContact )
+ {
+ pContact->DisconnectObjFromLayout( pSdrObj );
+ }
+
+ if ( GetDrawObjs() && nCnt == GetDrawObjs()->size() )
+ {
+ GetDrawObjs()->Remove( *pAnchoredObj );
+ }
+ }
+ }
+ }
+ else
+ {
+ while( pFrame )
+ {
+ SwFrame *pNxt = pFrame->GetNext();
+ SwFrame::DestroyFrame(pFrame);
+ pFrame = pNxt;
+ }
+ }
+
+ SwFrame::DestroyImpl();
+}
+
+SwLayoutFrame::~SwLayoutFrame()
+{
+}
+
+/**
+|* The paintarea is the area, in which the content of a frame is allowed
+|* to be displayed. This region could be larger than the printarea (getFramePrintArea())
+|* of the upper, it includes e.g. often the margin of the page.
+|*/
+SwRect SwFrame::GetPaintArea() const
+{
+ // NEW TABLES
+ // Cell frames may not leave their upper:
+ SwRect aRect = IsRowFrame() ? GetUpper()->getFrameArea() : getFrameArea();
+ const bool bVert = IsVertical();
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori;
+ SwRectFnSet aRectFnSet(this);
+ long nRight = (aRect.*fnRect->fnGetRight)();
+ long nLeft = (aRect.*fnRect->fnGetLeft)();
+ const SwFrame* pTmp = this;
+ bool bLeft = true;
+ bool bRight = true;
+ long nRowSpan = 0;
+ while( pTmp )
+ {
+ if( pTmp->IsCellFrame() && pTmp->GetUpper() &&
+ pTmp->GetUpper()->IsVertical() != pTmp->IsVertical() )
+ nRowSpan = static_cast<const SwCellFrame*>(pTmp)->GetTabBox()->getRowSpan();
+ long nTmpRight = (pTmp->getFrameArea().*fnRect->fnGetRight)();
+ long nTmpLeft = (pTmp->getFrameArea().*fnRect->fnGetLeft)();
+ if( pTmp->IsRowFrame() && nRowSpan > 1 )
+ {
+ const SwFrame* pNxt = pTmp;
+ while( --nRowSpan > 0 && pNxt->GetNext() )
+ pNxt = pNxt->GetNext();
+ if( pTmp->IsVertical() )
+ nTmpLeft = (pNxt->getFrameArea().*fnRect->fnGetLeft)();
+ else
+ {
+ // pTmp is a row frame, but it's not vertical.
+ if (IsVertLRBT())
+ {
+ // This frame cell is OK to expand towards the physical down direction.
+ // Physical down is left.
+ nTmpLeft = (pNxt->getFrameArea().*fnRect->fnGetLeft)();
+ }
+ else
+ {
+ nTmpRight = (pNxt->getFrameArea().*fnRect->fnGetRight)();
+ }
+ }
+ }
+ OSL_ENSURE( pTmp, "GetPaintArea lost in time and space" );
+ if( pTmp->IsPageFrame() || pTmp->IsFlyFrame() ||
+ pTmp->IsCellFrame() || pTmp->IsRowFrame() || //nobody leaves a table!
+ pTmp->IsRootFrame() )
+ {
+ if( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 )
+ nLeft = nTmpLeft;
+ if( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 )
+ nRight = nTmpRight;
+ if( pTmp->IsPageFrame() || pTmp->IsFlyFrame() || pTmp->IsRootFrame() )
+ break;
+ bLeft = false;
+ bRight = false;
+ }
+ else if( pTmp->IsColumnFrame() ) // nobody enters neighbour columns
+ {
+ bool bR2L = pTmp->IsRightToLeft();
+ // the first column has _no_ influence to the left range
+ if( bR2L ? pTmp->GetNext() : pTmp->GetPrev() )
+ {
+ if( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 )
+ nLeft = nTmpLeft;
+ bLeft = false;
+ }
+ // the last column has _no_ influence to the right range
+ if( bR2L ? pTmp->GetPrev() : pTmp->GetNext() )
+ {
+ if( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 )
+ nRight = nTmpRight;
+ bRight = false;
+ }
+ }
+ else if( bVert && pTmp->IsBodyFrame() )
+ {
+ // Header and footer frames have always horizontal direction and
+ // limit the body frame.
+ // A previous frame of a body frame must be a header,
+ // the next frame of a body frame may be a footnotecontainer or
+ // a footer. The footnotecontainer has the same direction like
+ // the body frame.
+ if( pTmp->GetPrev() && ( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 ) )
+ {
+ nLeft = nTmpLeft;
+ bLeft = false;
+ }
+ if( pTmp->GetNext() &&
+ ( pTmp->GetNext()->IsFooterFrame() || pTmp->GetNext()->GetNext() )
+ && ( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 ) )
+ {
+ nRight = nTmpRight;
+ bRight = false;
+ }
+ }
+ pTmp = pTmp->GetUpper();
+ }
+ (aRect.*fnRect->fnSetLeft)( nLeft );
+ (aRect.*fnRect->fnSetRight)( nRight );
+ return aRect;
+}
+
+/**
+|* The unionframe is the framearea (getFrameArea()) of a frame expanded by the
+|* printarea, if there's a negative margin at the left or right side.
+|*/
+SwRect SwFrame::UnionFrame( bool bBorder ) const
+{
+ bool bVert = IsVertical();
+ SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori;
+ long nLeft = (getFrameArea().*fnRect->fnGetLeft)();
+ long nWidth = (getFrameArea().*fnRect->fnGetWidth)();
+ long nPrtLeft = (getFramePrintArea().*fnRect->fnGetLeft)();
+ long nPrtWidth = (getFramePrintArea().*fnRect->fnGetWidth)();
+ SwRectFnSet aRectFnSet(this);
+ if (aRectFnSet.XInc(nPrtLeft, nPrtWidth) > nWidth)
+ nWidth = nPrtLeft + nPrtWidth;
+ if( nPrtLeft < 0 )
+ {
+ nLeft += nPrtLeft;
+ nWidth -= nPrtLeft;
+ }
+ SwTwips nRight = aRectFnSet.XInc(nLeft, nWidth);
+ long nAdd = 0;
+ if( bBorder )
+ {
+ SwBorderAttrAccess aAccess( SwFrame::GetCache(), this );
+ const SwBorderAttrs &rAttrs = *aAccess.Get();
+ const SvxBoxItem &rBox = rAttrs.GetBox();
+ if ( rBox.GetLeft() )
+ nLeft -= rBox.CalcLineSpace( SvxBoxItemLine::LEFT );
+ else
+ nLeft -= rBox.GetDistance( SvxBoxItemLine::LEFT ) + 1;
+ if ( rBox.GetRight() )
+ nAdd += rBox.CalcLineSpace( SvxBoxItemLine::RIGHT );
+ else
+ nAdd += rBox.GetDistance( SvxBoxItemLine::RIGHT ) + 1;
+ if( rAttrs.GetShadow().GetLocation() != SvxShadowLocation::NONE )
+ {
+ const SvxShadowItem &rShadow = rAttrs.GetShadow();
+ nLeft -= rShadow.CalcShadowSpace( SvxShadowItemSide::LEFT );
+ nAdd += rShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT );
+ }
+ }
+ if( IsTextFrame() && static_cast<const SwTextFrame*>(this)->HasPara() )
+ {
+ long nTmp = static_cast<const SwTextFrame*>(this)->HangingMargin();
+ if( nTmp > nAdd )
+ nAdd = nTmp;
+ }
+ nWidth = aRectFnSet.XDiff(aRectFnSet.XInc(nRight, nAdd), nLeft);
+ SwRect aRet( getFrameArea() );
+ (aRet.*fnRect->fnSetLeft)(nLeft);
+ (aRet.*fnRect->fnSetWidth)( nWidth );
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */