summaryrefslogtreecommitdiffstats
path: root/sw/source/core/layout/findfrm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/findfrm.cxx')
-rw-r--r--sw/source/core/layout/findfrm.cxx1827
1 files changed, 1827 insertions, 0 deletions
diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx
new file mode 100644
index 000000000..548399e40
--- /dev/null
+++ b/sw/source/core/layout/findfrm.cxx
@@ -0,0 +1,1827 @@
+/* -*- 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 <cellfrm.hxx>
+#include <rowfrm.hxx>
+#include <swtable.hxx>
+#include <notxtfrm.hxx>
+#include <tabfrm.hxx>
+#include <sectfrm.hxx>
+#include <frmatr.hxx>
+#include <flyfrm.hxx>
+#include <ftnfrm.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+#include <fmtpdsc.hxx>
+#include <txtfrm.hxx>
+#include <bodyfrm.hxx>
+#include <calbck.hxx>
+#include <viewopt.hxx>
+#include <ndtxt.hxx>
+#include <sal/log.hxx>
+
+/// Searches the first ContentFrame in BodyText below the page.
+SwLayoutFrame *SwFootnoteBossFrame::FindBodyCont()
+{
+ SwFrame *pLay = Lower();
+ while ( pLay && !pLay->IsBodyFrame() )
+ pLay = pLay->GetNext();
+ return static_cast<SwLayoutFrame*>(pLay);
+}
+
+/// Searches the last ContentFrame in BodyText below the page.
+SwContentFrame *SwPageFrame::FindLastBodyContent()
+{
+ SwContentFrame *pRet = FindFirstBodyContent();
+ SwContentFrame *pNxt = pRet;
+ while ( pNxt && pNxt->IsInDocBody() && IsAnLower( pNxt ) )
+ { pRet = pNxt;
+ pNxt = pNxt->FindNextCnt();
+ }
+ return pRet;
+}
+
+/**
+ * Checks if the frame contains one or more ContentFrame's anywhere in his
+ * subsidiary structure; if so the first found ContentFrame is returned.
+ */
+const SwContentFrame *SwLayoutFrame::ContainsContent() const
+{
+ //Search downwards the layout leaf and if there is no content, jump to the
+ //next leaf until content is found or we leave "this".
+ //Sections: Content next to sections would not be found this way (empty
+ //sections directly next to ContentFrame) therefore we need to recursively
+ //search for them even if it's more complex.
+
+ const SwLayoutFrame *pLayLeaf = this;
+ do
+ {
+ while ( (!pLayLeaf->IsSctFrame() || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() )
+ pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->Lower());
+
+ if( pLayLeaf->IsSctFrame() && pLayLeaf != this )
+ {
+ const SwContentFrame *pCnt = pLayLeaf->ContainsContent();
+ if( pCnt )
+ return pCnt;
+ if( pLayLeaf->GetNext() )
+ {
+ if( pLayLeaf->GetNext()->IsLayoutFrame() )
+ {
+ pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->GetNext());
+ continue;
+ }
+ else
+ return static_cast<const SwContentFrame*>(pLayLeaf->GetNext());
+ }
+ }
+ else if ( pLayLeaf->Lower() )
+ return static_cast<const SwContentFrame*>(pLayLeaf->Lower());
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( !IsAnLower( pLayLeaf) )
+ return nullptr;
+ } while( pLayLeaf );
+ return nullptr;
+}
+
+/**
+ * Calls ContainsAny first to reach the innermost cell. From there we walk back
+ * up to the first SwCellFrame. Since we use SectionFrames, ContainsContent()->GetUpper()
+ * is not enough anymore.
+ */
+const SwCellFrame *SwLayoutFrame::FirstCell() const
+{
+ const SwFrame* pCnt = ContainsAny();
+ while( pCnt && !pCnt->IsCellFrame() )
+ pCnt = pCnt->GetUpper();
+ return static_cast<const SwCellFrame*>(pCnt);
+}
+
+/** return ContentFrames, sections, and tables.
+ *
+ * @param _bInvestigateFootnoteForSections controls investigation of content of footnotes for sections.
+ * @see ContainsContent
+ */
+const SwFrame *SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSections ) const
+{
+ //Search downwards the layout leaf and if there is no content, jump to the
+ //next leaf until content is found, we leave "this" or until we found
+ //a SectionFrame or a TabFrame.
+
+ const SwLayoutFrame *pLayLeaf = this;
+ const bool bNoFootnote = IsSctFrame() && !_bInvestigateFootnoteForSections;
+ do
+ {
+ while ( ( (!pLayLeaf->IsSctFrame() && !pLayLeaf->IsTabFrame())
+ || pLayLeaf == this ) &&
+ pLayLeaf->Lower() && pLayLeaf->Lower()->IsLayoutFrame() )
+ pLayLeaf = static_cast<const SwLayoutFrame*>(pLayLeaf->Lower());
+
+ if( ( pLayLeaf->IsTabFrame() || pLayLeaf->IsSctFrame() )
+ && pLayLeaf != this )
+ {
+ // Now we also return "deleted" SectionFrames so they can be
+ // maintained on SaveContent and RestoreContent
+ return pLayLeaf;
+ }
+ else if ( pLayLeaf->Lower() )
+ return static_cast<const SwContentFrame*>(pLayLeaf->Lower());
+
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ if( bNoFootnote && pLayLeaf && pLayLeaf->IsInFootnote() )
+ {
+ do
+ {
+ pLayLeaf = pLayLeaf->GetNextLayoutLeaf();
+ } while( pLayLeaf && pLayLeaf->IsInFootnote() );
+ }
+ if( !IsAnLower( pLayLeaf) )
+ return nullptr;
+ } while( pLayLeaf );
+ return nullptr;
+}
+
+const SwFrame* SwFrame::GetLower() const
+{
+ return IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(this)->Lower() : nullptr;
+}
+
+SwFrame* SwFrame::GetLower()
+{
+ return IsLayoutFrame() ? static_cast<SwLayoutFrame*>(this)->Lower() : nullptr;
+}
+
+SwContentFrame* SwFrame::FindPrevCnt( )
+{
+ if ( GetPrev() && GetPrev()->IsContentFrame() )
+ return static_cast<SwContentFrame*>(GetPrev());
+ else
+ return FindPrevCnt_();
+}
+
+const SwContentFrame* SwFrame::FindPrevCnt() const
+{
+ if ( GetPrev() && GetPrev()->IsContentFrame() )
+ return static_cast<const SwContentFrame*>(GetPrev());
+ else
+ return const_cast<SwFrame*>(this)->FindPrevCnt_();
+}
+
+SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote )
+{
+ if ( mpNext && mpNext->IsContentFrame() )
+ return static_cast<SwContentFrame*>(mpNext);
+ else
+ return FindNextCnt_( _bInSameFootnote );
+}
+
+const SwContentFrame *SwFrame::FindNextCnt( const bool _bInSameFootnote ) const
+{
+ if ( mpNext && mpNext->IsContentFrame() )
+ return static_cast<SwContentFrame*>(mpNext);
+ else
+ return const_cast<SwFrame*>(this)->FindNextCnt_( _bInSameFootnote );
+}
+
+bool SwLayoutFrame::IsAnLower( const SwFrame *pAssumed ) const
+{
+ const SwFrame *pUp = pAssumed;
+ while ( pUp )
+ {
+ if ( pUp == this )
+ return true;
+ if ( pUp->IsFlyFrame() )
+ pUp = static_cast<const SwFlyFrame*>(pUp)->GetAnchorFrame();
+ else
+ pUp = pUp->GetUpper();
+ }
+ return false;
+}
+
+/** method to check relative position of layout frame to
+ a given layout frame.
+
+ OD 08.11.2002 - refactoring of pseudo-local method <lcl_Apres(..)> in
+ <txtftn.cxx> for #104840#.
+
+ @param _aCheckRefLayFrame
+ constant reference of an instance of class <SwLayoutFrame> which
+ is used as the reference for the relative position check.
+
+ @return true, if <this> is positioned before the layout frame <p>
+*/
+bool SwLayoutFrame::IsBefore( const SwLayoutFrame* _pCheckRefLayFrame ) const
+{
+ OSL_ENSURE( !IsRootFrame() , "<IsBefore> called at a <SwRootFrame>.");
+ OSL_ENSURE( !_pCheckRefLayFrame->IsRootFrame() , "<IsBefore> called with a <SwRootFrame>.");
+
+ bool bReturn;
+
+ // check, if on different pages
+ const SwPageFrame *pMyPage = FindPageFrame();
+ const SwPageFrame *pCheckRefPage = _pCheckRefLayFrame->FindPageFrame();
+ if( pMyPage != pCheckRefPage )
+ {
+ // being on different page as check reference
+ bReturn = pMyPage->GetPhyPageNum() < pCheckRefPage->GetPhyPageNum();
+ }
+ else
+ {
+ // being on same page as check reference
+ // --> search my supreme parent <pUp>, which doesn't contain check reference.
+ const SwLayoutFrame* pUp = this;
+ while ( pUp->GetUpper() &&
+ !pUp->GetUpper()->IsAnLower( _pCheckRefLayFrame )
+ )
+ pUp = pUp->GetUpper();
+ if( !pUp->GetUpper() )
+ {
+ // can occur, if <this> is a fly frm
+ bReturn = false;
+ }
+ else
+ {
+ // travel through the next's of <pUp> and check if one of these
+ // contain the check reference.
+ const SwLayoutFrame* pUpNext = static_cast<const SwLayoutFrame*>(pUp->GetNext());
+ while ( pUpNext &&
+ !pUpNext->IsAnLower( _pCheckRefLayFrame ) )
+ {
+ pUpNext = static_cast<const SwLayoutFrame*>(pUpNext->GetNext());
+ }
+ bReturn = pUpNext != nullptr;
+ }
+ }
+
+ return bReturn;
+}
+
+// Local helper functions for GetNextLayoutLeaf
+
+static const SwFrame* lcl_FindLayoutFrame( const SwFrame* pFrame, bool bNext )
+{
+ const SwFrame* pRet = nullptr;
+ if ( pFrame->IsFlyFrame() )
+ pRet = bNext ? static_cast<const SwFlyFrame*>(pFrame)->GetNextLink() : static_cast<const SwFlyFrame*>(pFrame)->GetPrevLink();
+ else
+ pRet = bNext ? pFrame->GetNext() : pFrame->GetPrev();
+
+ return pRet;
+}
+
+static const SwFrame* lcl_GetLower( const SwFrame* pFrame, bool bFwd )
+{
+ if ( !pFrame->IsLayoutFrame() )
+ return nullptr;
+
+ return bFwd ?
+ static_cast<const SwLayoutFrame*>(pFrame)->Lower() :
+ static_cast<const SwLayoutFrame*>(pFrame)->GetLastLower();
+}
+
+/**
+ * Finds the next layout leaf. This is a layout frame, which does not
+ * have a lower which is a LayoutFrame. That means, pLower can be 0 or a
+ * content frame.
+ *
+ * However, pLower may be a TabFrame
+ */
+const SwLayoutFrame *SwFrame::ImplGetNextLayoutLeaf( bool bFwd ) const
+{
+ const SwFrame *pFrame = this;
+ const SwLayoutFrame *pLayoutFrame = nullptr;
+ const SwFrame *p = nullptr;
+ bool bGoingUp = !bFwd; // false for forward, true for backward
+ do {
+
+ bool bGoingFwdOrBwd = false;
+
+ bool bGoingDown = !bGoingUp;
+ if (bGoingDown)
+ {
+ p = lcl_GetLower( pFrame, bFwd );
+ bGoingDown = nullptr != p;
+ }
+ if ( !bGoingDown )
+ {
+ // I cannot go down, because either I'm currently going up or
+ // because the is no lower.
+ // I'll try to go forward:
+ p = lcl_FindLayoutFrame( pFrame, bFwd );
+ bGoingFwdOrBwd = nullptr != p;
+ if ( !bGoingFwdOrBwd )
+ {
+ // I cannot go forward, because there is no next frame.
+ // I'll try to go up:
+ p = pFrame->GetUpper();
+ bGoingUp = nullptr != p;
+ if ( !bGoingUp )
+ {
+ // I cannot go up, because there is no upper frame.
+ return nullptr;
+ }
+ }
+ }
+
+ // If I could not go down or forward, I'll have to go up
+ bGoingUp = !bGoingFwdOrBwd && !bGoingDown;
+
+ pFrame = p;
+ p = lcl_GetLower( pFrame, true );
+
+ } while( ( p && !p->IsFlowFrame() ) ||
+ pFrame == this ||
+ nullptr == ( pLayoutFrame = pFrame->IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(pFrame) : nullptr ) ||
+ pLayoutFrame->IsAnLower( this ) );
+
+ return pLayoutFrame;
+}
+
+/**
+ * Walk back inside the tree: grab the subordinate Frame if one exists and the
+ * last step was not moving up a level (this would lead to an infinite up/down
+ * loop!). With this we ensure that during walking back we search through all
+ * sub trees. If we walked downwards we have to go to the end of the chain first
+ * because we go backwards from the last Frame inside another Frame. Walking
+ * forward works the same.
+ *
+ * @warning fixes here may also need to be applied to the @{lcl_NextFrame} method above
+ */
+const SwContentFrame* SwContentFrame::ImplGetNextContentFrame( bool bFwd ) const
+{
+ const SwFrame *pFrame = this;
+ const SwContentFrame *pContentFrame = nullptr;
+ bool bGoingUp = false;
+ do {
+ const SwFrame *p = nullptr;
+ bool bGoingFwdOrBwd = false;
+
+ bool bGoingDown = !bGoingUp;
+ if (bGoingDown)
+ {
+ p = lcl_GetLower( pFrame, true ) ;
+ bGoingDown = nullptr != p;
+ }
+ if ( !bGoingDown )
+ {
+ p = lcl_FindLayoutFrame( pFrame, bFwd );
+ bGoingFwdOrBwd = nullptr != p;
+ if ( !bGoingFwdOrBwd )
+ {
+ p = pFrame->GetUpper();
+ bGoingUp = nullptr != p;
+ if ( !bGoingUp )
+ {
+ return nullptr;
+ }
+ }
+ }
+
+ bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
+ assert(p);
+ if (!bFwd && bGoingDown)
+ {
+ while ( p->GetNext() )
+ p = p->GetNext();
+ }
+
+ pFrame = p;
+ } while ( nullptr == (pContentFrame = (pFrame->IsContentFrame() ? static_cast<const SwContentFrame*>(pFrame) : nullptr) ));
+
+ return pContentFrame;
+}
+
+SwPageFrame* SwFrame::ImplFindPageFrame()
+{
+ SwFrame *pRet = this;
+ while ( pRet && !pRet->IsPageFrame() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrame() )
+ {
+ // #i28701# - use new method <GetPageFrame()>
+ const auto pFly(static_cast<SwFlyFrame*>(pRet));
+ pRet = pFly->GetPageFrame();
+ if (pRet == nullptr)
+ pRet = pFly->AnchorFrame();
+ }
+ else
+ return nullptr;
+ }
+ return static_cast<SwPageFrame*>(pRet);
+}
+
+SwFootnoteBossFrame* SwFrame::FindFootnoteBossFrame( bool bFootnotes )
+{
+ SwFrame *pRet = this;
+ // Footnote bosses can't exist inside a table; also sections with columns
+ // don't contain footnote texts there
+ if( pRet->IsInTab() )
+ pRet = pRet->FindTabFrame();
+ while ( pRet && !pRet->IsFootnoteBossFrame() )
+ {
+ if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrame() )
+ {
+ // #i28701# - use new method <GetPageFrame()>
+ if ( static_cast<SwFlyFrame*>(pRet)->GetPageFrame() )
+ pRet = static_cast<SwFlyFrame*>(pRet)->GetPageFrame();
+ else
+ pRet = static_cast<SwFlyFrame*>(pRet)->AnchorFrame();
+ }
+ else
+ return nullptr;
+ }
+ if( bFootnotes && pRet && pRet->IsColumnFrame() &&
+ !pRet->GetNext() && !pRet->GetPrev() )
+ {
+ SwSectionFrame* pSct = pRet->FindSctFrame();
+ OSL_ENSURE( pSct, "FindFootnoteBossFrame: Single column outside section?" );
+ if( !pSct->IsFootnoteAtEnd() )
+ return pSct->FindFootnoteBossFrame( true );
+ }
+ return static_cast<SwFootnoteBossFrame*>(pRet);
+}
+
+SwTabFrame* SwFrame::ImplFindTabFrame()
+{
+ SwFrame *pRet = this;
+ while ( !pRet->IsTabFrame() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return nullptr;
+ }
+ return static_cast<SwTabFrame*>(pRet);
+}
+
+SwSectionFrame* SwFrame::ImplFindSctFrame()
+{
+ SwFrame *pRet = this;
+ while ( !pRet->IsSctFrame() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return nullptr;
+ }
+ return static_cast<SwSectionFrame*>(pRet);
+}
+
+const SwBodyFrame* SwFrame::ImplFindBodyFrame() const
+{
+ const SwFrame *pRet = this;
+ while ( !pRet->IsBodyFrame() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return nullptr;
+ }
+ return static_cast<const SwBodyFrame*>(pRet);
+}
+
+SwFootnoteFrame *SwFrame::ImplFindFootnoteFrame()
+{
+ SwFrame *pRet = this;
+ while ( !pRet->IsFootnoteFrame() )
+ {
+ pRet = pRet->GetUpper();
+ if ( !pRet )
+ return nullptr;
+ }
+ return static_cast<SwFootnoteFrame*>(pRet);
+}
+
+SwFlyFrame *SwFrame::ImplFindFlyFrame()
+{
+ SwFrame *pRet = this;
+ do
+ {
+ if ( pRet->IsFlyFrame() )
+ return static_cast<SwFlyFrame*>(pRet);
+ else
+ pRet = pRet->GetUpper();
+ } while ( pRet );
+ return nullptr;
+}
+
+SwFrame *SwFrame::FindColFrame()
+{
+ SwFrame *pFrame = this;
+ do
+ { pFrame = pFrame->GetUpper();
+ } while ( pFrame && !pFrame->IsColumnFrame() );
+ return pFrame;
+}
+
+SwRowFrame *SwFrame::FindRowFrame()
+{
+ SwFrame *pFrame = this;
+ do
+ { pFrame = pFrame->GetUpper();
+ } while ( pFrame && !pFrame->IsRowFrame() );
+ return dynamic_cast< SwRowFrame* >( pFrame );
+}
+
+SwFrame* SwFrame::FindFooterOrHeader()
+{
+ SwFrame* pRet = this;
+ do
+ {
+ if (pRet->GetType() & FRM_HEADFOOT) //header and footer
+ return pRet;
+ else if ( pRet->GetUpper() )
+ pRet = pRet->GetUpper();
+ else if ( pRet->IsFlyFrame() )
+ pRet = static_cast<SwFlyFrame*>(pRet)->AnchorFrame();
+ else
+ return nullptr;
+ } while ( pRet );
+ return pRet;
+}
+
+const SwFootnoteFrame* SwFootnoteContFrame::FindFootNote() const
+{
+ const SwFootnoteFrame* pRet = static_cast<const SwFootnoteFrame*>(Lower());
+ if( pRet && !pRet->GetAttr()->GetFootnote().IsEndNote() )
+ return pRet;
+ return nullptr;
+}
+
+const SwPageFrame* SwRootFrame::GetPageAtPos( const Point& rPt, const Size* pSize, bool bExtend ) const
+{
+ const SwPageFrame* pRet = nullptr;
+
+ SwRect aRect;
+ if ( pSize )
+ {
+ aRect.Pos() = rPt;
+ aRect.SSize( *pSize );
+ }
+
+ const SwFrame* pPage = Lower();
+
+ if ( !bExtend )
+ {
+ if( !getFrameArea().IsInside( rPt ) )
+ return nullptr;
+
+ // skip pages above point:
+ while( pPage && rPt.Y() > pPage->getFrameArea().Bottom() )
+ pPage = pPage->GetNext();
+ }
+
+ OSL_ENSURE( GetPageNum() <= maPageRects.size(), "number of pages differs from page rect array size" );
+ size_t nPageIdx = 0;
+
+ while ( pPage && !pRet )
+ {
+ const SwRect& rBoundRect = bExtend ? maPageRects[ nPageIdx++ ] : pPage->getFrameArea();
+
+ if ( (!pSize && rBoundRect.IsInside(rPt)) ||
+ (pSize && rBoundRect.IsOver(aRect)) )
+ {
+ pRet = static_cast<const SwPageFrame*>(pPage);
+ }
+
+ pPage = pPage->GetNext();
+ }
+
+ return pRet;
+}
+
+bool SwRootFrame::IsBetweenPages(const Point& rPt) const
+{
+ if (!getFrameArea().IsInside(rPt))
+ return false;
+
+ // top visible page
+ const SwFrame* pPage = Lower();
+ if (pPage == nullptr)
+ return false;
+
+ // skip pages above point:
+ while (pPage && rPt.Y() > pPage->getFrameArea().Bottom())
+ pPage = pPage->GetNext();
+
+ if (pPage &&
+ rPt.X() >= pPage->getFrameArea().Left() &&
+ rPt.X() <= pPage->getFrameArea().Right())
+ {
+ // Trivial case when we're right in between.
+ if (!pPage->getFrameArea().IsInside(rPt))
+ return true;
+
+ // In normal mode the gap is large enough and
+ // header/footer mouse interaction competes with
+ // handling hide-whitespace within them.
+ // In hide-whitespace, however, the gap is too small
+ // for convenience and there are no headers/footers.
+ const SwViewShell *pSh = GetCurrShell();
+ if (pSh && pSh->GetViewOptions()->IsWhitespaceHidden())
+ {
+ // If we are really close to the bottom or top of a page.
+ const auto toEdge = std::min(std::abs(pPage->getFrameArea().Top() - rPt.Y()),
+ std::abs(pPage->getFrameArea().Bottom() - rPt.Y()));
+ return toEdge <= MmToTwips(2.0);
+ }
+ }
+
+ return false;
+}
+
+const SvxFormatBreakItem& SwFrame::GetBreakItem() const
+{
+ return GetAttrSet()->GetBreak();
+}
+
+const SwFormatPageDesc& SwFrame::GetPageDescItem() const
+{
+ return GetAttrSet()->GetPageDesc();
+}
+
+const SvxFormatBreakItem& SwTextFrame::GetBreakItem() const
+{
+ return GetTextNodeFirst()->GetSwAttrSet().GetBreak();
+}
+
+const SwFormatPageDesc& SwTextFrame::GetPageDescItem() const
+{
+ return GetTextNodeFirst()->GetSwAttrSet().GetPageDesc();
+}
+
+const SwAttrSet* SwFrame::GetAttrSet() const
+{
+ if (IsTextFrame())
+ {
+ return &static_cast<const SwTextFrame*>(this)->GetTextNodeForParaProps()->GetSwAttrSet();
+ }
+ else if (IsNoTextFrame())
+ {
+ return &static_cast<const SwNoTextFrame*>(this)->GetNode()->GetSwAttrSet();
+ }
+ else
+ {
+ assert(IsLayoutFrame());
+ return &static_cast<const SwLayoutFrame*>(this)->GetFormat()->GetAttrSet();
+ }
+}
+
+drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwFrame::getSdrAllFillAttributesHelper() const
+{
+ if (IsTextFrame())
+ {
+ return static_cast<const SwTextFrame*>(this)->GetTextNodeForParaProps()->getSdrAllFillAttributesHelper();
+ }
+ else if (IsNoTextFrame())
+ {
+ return static_cast<const SwNoTextFrame*>(this)->GetNode()->getSdrAllFillAttributesHelper();
+ }
+ else
+ {
+ return static_cast< const SwLayoutFrame* >(this)->GetFormat()->getSdrAllFillAttributesHelper();
+ }
+}
+
+bool SwFrame::supportsFullDrawingLayerFillAttributeSet() const
+{
+ if (IsContentFrame())
+ {
+ return true;
+ }
+ else
+ {
+ return static_cast< const SwLayoutFrame* >(this)->GetFormat()->supportsFullDrawingLayerFillAttributeSet();
+ }
+}
+
+/*
+ * SwFrame::FindNext_(), FindPrev_(), InvalidateNextPos()
+ * FindNextCnt_() visits tables and sections and only returns SwContentFrames.
+ *
+ * Description Invalidates the position of the next frame.
+ * This is the direct successor or in case of ContentFrames the next
+ * ContentFrame which sits in the same flow as I do:
+ * - body,
+ * - footnote,
+ * - in headers/footers the notification only needs to be forwarded
+ * inside the section
+ * - same for Flys
+ * - Contents in tabs remain only inside their cell
+ * - in principle tables behave exactly like the Contents
+ * - sections also
+ */
+// This helper function is an equivalent to the ImplGetNextContentFrame() method,
+// besides ContentFrames this function also returns TabFrames and SectionFrames.
+static SwFrame* lcl_NextFrame( SwFrame* pFrame )
+{
+ SwFrame *pRet = nullptr;
+ bool bGoingUp = false;
+ do {
+ SwFrame *p = nullptr;
+
+ bool bGoingFwd = false;
+ bool bGoingDown = !bGoingUp && pFrame->IsLayoutFrame();
+ if (bGoingDown)
+ {
+ p = static_cast<SwLayoutFrame*>(pFrame)->Lower();
+ bGoingDown = nullptr != p;
+ }
+ if( !bGoingDown )
+ {
+ p = pFrame->IsFlyFrame() ? static_cast<SwFlyFrame*>(pFrame)->GetNextLink() : pFrame->GetNext();
+ bGoingFwd = nullptr != p;
+ if ( !bGoingFwd )
+ {
+ p = pFrame->GetUpper();
+ bGoingUp = nullptr != p;
+ if ( !bGoingUp )
+ {
+ return nullptr;
+ }
+ }
+ }
+ bGoingUp = !(bGoingFwd || bGoingDown);
+ pFrame = p;
+ } while ( nullptr == (pRet = ( ( pFrame->IsContentFrame() || ( !bGoingUp &&
+ ( pFrame->IsTabFrame() || pFrame->IsSctFrame() ) ) )? pFrame : nullptr ) ) );
+ return pRet;
+}
+
+SwFrame *SwFrame::FindNext_()
+{
+ bool bIgnoreTab = false;
+ SwFrame *pThis = this;
+
+ if ( IsTabFrame() )
+ {
+ //The last Content of the table gets picked up and his follower is
+ //returned. To be able to deactivate the special case for tables
+ //(see below) bIgnoreTab will be set.
+ if ( static_cast<SwTabFrame*>(this)->GetFollow() )
+ return static_cast<SwTabFrame*>(this)->GetFollow();
+
+ pThis = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
+ if ( !pThis )
+ pThis = this;
+ bIgnoreTab = true;
+ }
+ else if ( IsSctFrame() )
+ {
+ //The last Content of the section gets picked and his follower is returned.
+ if ( static_cast<SwSectionFrame*>(this)->GetFollow() )
+ return static_cast<SwSectionFrame*>(this)->GetFollow();
+
+ pThis = static_cast<SwSectionFrame*>(this)->FindLastContent();
+ if ( !pThis )
+ pThis = this;
+ }
+ else if ( IsContentFrame() )
+ {
+ if( static_cast<SwContentFrame*>(this)->GetFollow() )
+ return static_cast<SwContentFrame*>(this)->GetFollow();
+ }
+ else if ( IsRowFrame() )
+ {
+ SwFrame* pMyUpper = GetUpper();
+ if ( pMyUpper->IsTabFrame() && static_cast<SwTabFrame*>(pMyUpper)->GetFollow() )
+ return static_cast<SwTabFrame*>(pMyUpper)->GetFollow()->GetLower();
+ else return nullptr;
+ }
+ else
+ return nullptr;
+
+ SwFrame* pRet = nullptr;
+ const bool bFootnote = pThis->IsInFootnote();
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrame *pUp = pThis->GetUpper();
+ while (pUp && !pUp->IsCellFrame())
+ pUp = pUp->GetUpper();
+ assert(pUp && "Content flag says it's in table but it's not in cell.");
+ SwFrame* pNxt = pUp ? static_cast<SwCellFrame*>(pUp)->GetFollowCell() : nullptr;
+ if ( pNxt )
+ pNxt = static_cast<SwCellFrame*>(pNxt)->ContainsContent();
+ if ( !pNxt )
+ {
+ pNxt = lcl_NextFrame( pThis );
+ if (pUp && pUp->IsAnLower(pNxt))
+ pRet = pNxt;
+ }
+ else
+ pRet = pNxt;
+ }
+ else
+ {
+ const bool bBody = pThis->IsInDocBody();
+ SwFrame *pNxtCnt = lcl_NextFrame( pThis );
+ if ( pNxtCnt )
+ {
+ if ( bBody || bFootnote )
+ {
+ while ( pNxtCnt )
+ {
+ // OD 02.04.2003 #108446# - check for endnote, only if found
+ // next content isn't contained in a section, that collect its
+ // endnotes at its end.
+ bool bEndn = IsInSct() && !IsSctFrame() &&
+ ( !pNxtCnt->IsInSct() ||
+ !pNxtCnt->FindSctFrame()->IsEndnAtEnd()
+ );
+ if ( ( bBody && pNxtCnt->IsInDocBody() ) ||
+ ( pNxtCnt->IsInFootnote() &&
+ ( bFootnote ||
+ ( bEndn && pNxtCnt->FindFootnoteFrame()->GetAttr()->GetFootnote().IsEndNote() )
+ )
+ )
+ )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
+ : pNxtCnt;
+ break;
+ }
+ pNxtCnt = lcl_NextFrame( pNxtCnt );
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
+ : pNxtCnt;
+ }
+ else //footer-/or header section
+ {
+ const SwFrame *pUp = pThis->GetUpper();
+ const SwFrame *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
+ : pNxtCnt;
+ }
+ }
+ }
+ }
+ if( pRet && pRet->IsInSct() )
+ {
+ SwSectionFrame* pSct = pRet->FindSctFrame();
+ //Footnotes in frames with columns must not return the section which
+ //contains the footnote
+ if( !pSct->IsAnLower( this ) &&
+ (!bFootnote || pSct->IsInFootnote() ) )
+ return pSct;
+ }
+ return pRet;
+}
+
+// #i27138# - add parameter <_bInSameFootnote>
+SwContentFrame *SwFrame::FindNextCnt_( const bool _bInSameFootnote )
+{
+ SwFrame *pThis = this;
+
+ if ( IsTabFrame() )
+ {
+ if ( static_cast<SwTabFrame*>(this)->GetFollow() )
+ {
+ pThis = static_cast<SwTabFrame*>(this)->GetFollow()->ContainsContent();
+ if( pThis )
+ return static_cast<SwContentFrame*>(pThis);
+ }
+ pThis = static_cast<SwTabFrame*>(this)->FindLastContentOrTable();
+ if ( !pThis )
+ return nullptr;
+ }
+ else if ( IsSctFrame() )
+ {
+ if ( static_cast<SwSectionFrame*>(this)->GetFollow() )
+ {
+ pThis = static_cast<SwSectionFrame*>(this)->GetFollow()->ContainsContent();
+ if( pThis )
+ return static_cast<SwContentFrame*>(pThis);
+ }
+ pThis = static_cast<SwSectionFrame*>(this)->FindLastContent();
+ if ( !pThis )
+ return nullptr;
+ }
+ else if ( IsContentFrame() && static_cast<SwContentFrame*>(this)->GetFollow() )
+ return static_cast<SwContentFrame*>(this)->GetFollow();
+
+ if ( pThis->IsContentFrame() )
+ {
+ const bool bBody = pThis->IsInDocBody();
+ const bool bFootnote = pThis->IsInFootnote();
+ SwContentFrame *pNxtCnt = static_cast<SwContentFrame*>(pThis)->GetNextContentFrame();
+ if ( pNxtCnt )
+ {
+ // #i27138#
+ if ( bBody || ( bFootnote && !_bInSameFootnote ) )
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ while ( pNxtCnt )
+ {
+ if ( (bBody && pNxtCnt->IsInDocBody()) ||
+ (bFootnote && pNxtCnt->IsInFootnote()) )
+ return pNxtCnt;
+ pNxtCnt = pNxtCnt->GetNextContentFrame();
+ }
+ }
+ // #i27138#
+ else if ( bFootnote && _bInSameFootnote )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFootnoteFrame* pFootnoteFrameOfNext( pNxtCnt->FindFootnoteFrame() );
+ const SwFootnoteFrame* pFootnoteFrameOfCurr( pThis->FindFootnoteFrame() );
+ OSL_ENSURE( pFootnoteFrameOfCurr,
+ "<SwFrame::FindNextCnt_() - unknown layout situation: current frame has to have an upper footnote frame." );
+ if ( pFootnoteFrameOfNext == pFootnoteFrameOfCurr )
+ {
+ return pNxtCnt;
+ }
+ else if ( pFootnoteFrameOfCurr->GetFollow() )
+ {
+ // next content frame has to be the first content frame
+ // in the follow footnote, which contains a content frame.
+ SwFootnoteFrame* pFollowFootnoteFrameOfCurr(
+ const_cast<SwFootnoteFrame*>(pFootnoteFrameOfCurr) );
+ pNxtCnt = nullptr;
+ do {
+ pFollowFootnoteFrameOfCurr = pFollowFootnoteFrameOfCurr->GetFollow();
+ pNxtCnt = pFollowFootnoteFrameOfCurr->ContainsContent();
+ } while ( !pNxtCnt && pFollowFootnoteFrameOfCurr->GetFollow() );
+ return pNxtCnt;
+ }
+ else
+ {
+ // current content frame is the last content frame in the
+ // footnote - no next content frame exists.
+ return nullptr;
+ }
+ }
+ else if ( pThis->IsInFly() )
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ return pNxtCnt;
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ const SwFrame *pUp = pThis->GetUpper();
+ const SwFrame *pCntUp = pNxtCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() &&
+ !pCntUp->IsHeaderFrame() && !pCntUp->IsFooterFrame() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ return pNxtCnt;
+ }
+ }
+ }
+ return nullptr;
+}
+
+/** method to determine previous content frame in the same environment
+ for a flow frame (content frame, table frame, section frame)
+
+ OD 2005-11-30 #i27138#
+*/
+SwContentFrame* SwFrame::FindPrevCnt_()
+{
+ if ( !IsFlowFrame() )
+ {
+ // nothing to do, if current frame isn't a flow frame.
+ return nullptr;
+ }
+
+ SwContentFrame* pPrevContentFrame( nullptr );
+
+ // Because method <SwContentFrame::GetPrevContentFrame()> is used to travel
+ // through the layout, a content frame, at which the travel starts, is needed.
+ SwContentFrame* pCurrContentFrame = dynamic_cast<SwContentFrame*>(this);
+
+ // perform shortcut, if current frame is a follow, and
+ // determine <pCurrContentFrame>, if current frame is a table or section frame
+ if ( pCurrContentFrame && pCurrContentFrame->IsFollow() )
+ {
+ // previous content frame is its master content frame
+ pPrevContentFrame = pCurrContentFrame->FindMaster();
+ }
+ else if ( IsTabFrame() )
+ {
+ SwTabFrame* pTabFrame( static_cast<SwTabFrame*>(this) );
+ if ( pTabFrame->IsFollow() )
+ {
+ // previous content frame is the last content of its master table frame
+ pPrevContentFrame = pTabFrame->FindMaster()->FindLastContent();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the table frame.
+ pCurrContentFrame = pTabFrame->ContainsContent();
+ }
+ }
+ else if ( IsSctFrame() )
+ {
+ SwSectionFrame* pSectFrame( static_cast<SwSectionFrame*>(this) );
+ if ( pSectFrame->IsFollow() )
+ {
+ // previous content frame is the last content of its master section frame
+ pPrevContentFrame = pSectFrame->FindMaster()->FindLastContent();
+ }
+ else
+ {
+ // start content frame for the search is the first content frame of
+ // the section frame.
+ pCurrContentFrame = pSectFrame->ContainsContent();
+ }
+ }
+
+ // search for next content frame, depending on the environment, in which
+ // the current frame is in.
+ if ( !pPrevContentFrame && pCurrContentFrame )
+ {
+ pPrevContentFrame = pCurrContentFrame->GetPrevContentFrame();
+ if ( pPrevContentFrame )
+ {
+ if ( pCurrContentFrame->IsInFly() )
+ {
+ // handling for environments 'unlinked fly frame' and
+ // 'group of linked fly frames':
+ // Nothing to do, <pPrevContentFrame> is the one
+ }
+ else
+ {
+ const bool bInDocBody = pCurrContentFrame->IsInDocBody();
+ const bool bInFootnote = pCurrContentFrame->IsInFootnote();
+ if ( bInDocBody )
+ {
+ // handling for environments 'footnotes' and 'document body frames':
+ // Assure that found previous frame is also in one of these
+ // environments. Otherwise, travel further
+ while ( pPrevContentFrame )
+ {
+ if ( ( bInDocBody && pPrevContentFrame->IsInDocBody() ) ||
+ ( bInFootnote && pPrevContentFrame->IsInFootnote() ) )
+ {
+ break;
+ }
+ pPrevContentFrame = pPrevContentFrame->GetPrevContentFrame();
+ }
+ }
+ else if ( bInFootnote )
+ {
+ // handling for environments 'each footnote':
+ // Assure that found next content frame belongs to the same footnotes
+ const SwFootnoteFrame* pFootnoteFrameOfPrev( pPrevContentFrame->FindFootnoteFrame() );
+ const SwFootnoteFrame* pFootnoteFrameOfCurr( pCurrContentFrame->FindFootnoteFrame() );
+ if ( pFootnoteFrameOfPrev != pFootnoteFrameOfCurr )
+ {
+ if ( pFootnoteFrameOfCurr->GetMaster() )
+ {
+ SwFootnoteFrame* pMasterFootnoteFrameOfCurr(
+ const_cast<SwFootnoteFrame*>(pFootnoteFrameOfCurr) );
+ pPrevContentFrame = nullptr;
+ // correct wrong loop-condition
+ do {
+ pMasterFootnoteFrameOfCurr = pMasterFootnoteFrameOfCurr->GetMaster();
+ pPrevContentFrame = pMasterFootnoteFrameOfCurr->FindLastContent();
+ } while ( !pPrevContentFrame &&
+ pMasterFootnoteFrameOfCurr->GetMaster() );
+ }
+ else
+ {
+ // current content frame is the first content in the
+ // footnote - no previous content exists.
+ pPrevContentFrame = nullptr;
+ }
+ }
+ }
+ else
+ {
+ // handling for environments 'page header' and 'page footer':
+ // Assure that found previous frame is also in the same
+ // page header respectively page footer as <pCurrContentFrame>
+ // Note: At this point it's clear that <pCurrContentFrame> has
+ // to be inside a page header or page footer and that
+ // neither <pCurrContentFrame> nor <pPrevContentFrame> are
+ // inside a fly frame.
+ // Thus, method <FindFooterOrHeader()> can be used.
+ OSL_ENSURE( pCurrContentFrame->FindFooterOrHeader(),
+ "<SwFrame::FindPrevCnt_()> - unknown layout situation: current frame should be in page header or page footer" );
+ OSL_ENSURE( !pPrevContentFrame->IsInFly(),
+ "<SwFrame::FindPrevCnt_()> - unknown layout situation: found previous frame should *not* be inside a fly frame." );
+ if ( pPrevContentFrame->FindFooterOrHeader() !=
+ pCurrContentFrame->FindFooterOrHeader() )
+ {
+ pPrevContentFrame = nullptr;
+ }
+ }
+ }
+ }
+ }
+
+ return pPrevContentFrame;
+}
+
+SwFrame *SwFrame::FindPrev_()
+{
+ bool bIgnoreTab = false;
+ SwFrame *pThis = this;
+
+ if ( IsTabFrame() )
+ {
+ //The first Content of the table gets picked up and his predecessor is
+ //returned. To be able to deactivate the special case for tables
+ //(see below) bIgnoreTab will be set.
+ if ( static_cast<SwTabFrame*>(this)->IsFollow() )
+ return static_cast<SwTabFrame*>(this)->FindMaster();
+ else
+ pThis = static_cast<SwTabFrame*>(this)->ContainsContent();
+ bIgnoreTab = true;
+ }
+
+ if ( pThis && pThis->IsContentFrame() )
+ {
+ SwContentFrame *pPrvCnt = static_cast<SwContentFrame*>(pThis)->GetPrevContentFrame();
+ if( !pPrvCnt )
+ return nullptr;
+ if ( !bIgnoreTab && pThis->IsInTab() )
+ {
+ SwLayoutFrame *pUp = pThis->GetUpper();
+ while (pUp && !pUp->IsCellFrame())
+ pUp = pUp->GetUpper();
+ assert(pUp && "Content flag says it's in table but it's not in cell.");
+ if (pUp && pUp->IsAnLower(pPrvCnt))
+ return pPrvCnt;
+ }
+ else
+ {
+ SwFrame* pRet;
+ const bool bBody = pThis->IsInDocBody();
+ const bool bFootnote = !bBody && pThis->IsInFootnote();
+ if ( bBody || bFootnote )
+ {
+ while ( pPrvCnt )
+ {
+ if ( (bBody && pPrvCnt->IsInDocBody()) ||
+ (bFootnote && pPrvCnt->IsInFootnote()) )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
+ : static_cast<SwFrame*>(pPrvCnt);
+ return pRet;
+ }
+ pPrvCnt = pPrvCnt->GetPrevContentFrame();
+ }
+ }
+ else if ( pThis->IsInFly() )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
+ : static_cast<SwFrame*>(pPrvCnt);
+ return pRet;
+ }
+ else // footer or header or Fly
+ {
+ const SwFrame *pUp = pThis->GetUpper();
+ const SwFrame *pCntUp = pPrvCnt->GetUpper();
+ while ( pUp && pUp->GetUpper() &&
+ !pUp->IsHeaderFrame() && !pUp->IsFooterFrame() )
+ pUp = pUp->GetUpper();
+ while ( pCntUp && pCntUp->GetUpper() )
+ pCntUp = pCntUp->GetUpper();
+ if ( pCntUp == pUp )
+ {
+ pRet = pPrvCnt->IsInTab() ? pPrvCnt->FindTabFrame()
+ : static_cast<SwFrame*>(pPrvCnt);
+ return pRet;
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+void SwFrame::ImplInvalidateNextPos( bool bNoFootnote )
+{
+ SwFrame *pFrame;
+ if ( nullptr != (pFrame = FindNext_()) )
+ {
+ if( pFrame->IsSctFrame() )
+ {
+ while( pFrame && pFrame->IsSctFrame() )
+ {
+ if( static_cast<SwSectionFrame*>(pFrame)->GetSection() )
+ {
+ SwFrame* pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ else if( !bNoFootnote )
+ static_cast<SwSectionFrame*>(pFrame)->InvalidateFootnotePos();
+ if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame )
+ pFrame->InvalidatePos();
+ return;
+ }
+ pFrame = pFrame->FindNext();
+ }
+ if( pFrame )
+ {
+ if ( pFrame->IsSctFrame())
+ {
+ // We need to invalidate the section's content so it gets
+ // the chance to flow to a different page.
+ SwFrame* pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
+ if( pTmp )
+ pTmp->InvalidatePos();
+ if( !IsInSct() || FindSctFrame()->GetFollow() != pFrame )
+ pFrame->InvalidatePos();
+ }
+ else
+ pFrame->InvalidatePos();
+ }
+ }
+ else
+ pFrame->InvalidatePos();
+ }
+}
+
+/** method to invalidate printing area of next frame
+
+ OD 09.01.2004 #i11859#
+
+ FME 2004-04-19 #i27145# Moved function from SwTextFrame to SwFrame
+*/
+void SwFrame::InvalidateNextPrtArea()
+{
+ // determine next frame
+ SwFrame* pNextFrame = FindNext();
+ // skip empty section frames and hidden text frames
+ {
+ while ( pNextFrame &&
+ ( ( pNextFrame->IsSctFrame() &&
+ !static_cast<SwSectionFrame*>(pNextFrame)->GetSection() ) ||
+ ( pNextFrame->IsTextFrame() &&
+ static_cast<SwTextFrame*>(pNextFrame)->IsHiddenNow() ) ) )
+ {
+ pNextFrame = pNextFrame->FindNext();
+ }
+ }
+
+ // Invalidate printing area of found next frame
+ if ( pNextFrame )
+ {
+ if ( pNextFrame->IsSctFrame() )
+ {
+ // Invalidate printing area of found section frame, if
+ // (1) this text frame isn't in a section OR
+ // (2) found section frame isn't a follow of the section frame this
+ // text frame is in.
+ if ( !IsInSct() || FindSctFrame()->GetFollow() != pNextFrame )
+ {
+ pNextFrame->InvalidatePrt();
+ }
+
+ // Invalidate printing area of first content in found section.
+ SwFrame* pFstContentOfSctFrame =
+ static_cast<SwSectionFrame*>(pNextFrame)->ContainsAny();
+ if ( pFstContentOfSctFrame )
+ {
+ pFstContentOfSctFrame->InvalidatePrt();
+ }
+ }
+ else
+ {
+ pNextFrame->InvalidatePrt();
+ }
+ }
+}
+
+/// @returns true if the frame _directly_ sits in a section
+/// but not if it sits in a table which itself sits in a section.
+static bool lcl_IsInSectionDirectly( const SwFrame *pUp )
+{
+ bool bSeenColumn = false;
+
+ while( pUp )
+ {
+ if( pUp->IsColumnFrame() )
+ bSeenColumn = true;
+ else if( pUp->IsSctFrame() )
+ {
+ auto pSection = static_cast<const SwSectionFrame*>(pUp);
+ const SwFrame* pHeaderFooter = pSection->FindFooterOrHeader();
+ // When the section frame is not in header/footer:
+ // Allow move of frame in case our only column is not growable.
+ // Also allow if there is a previous section frame (to move back).
+ bool bAllowOutsideHeaderFooter = !pSection->Growable() || pSection->GetPrecede();
+ return bSeenColumn || (!pHeaderFooter && bAllowOutsideHeaderFooter);
+ }
+ else if( pUp->IsTabFrame() )
+ return false;
+ pUp = pUp->GetUpper();
+ }
+ return false;
+}
+
+/** determine, if frame is moveable in given environment
+
+ OD 08.08.2003 #110978#
+ method replaced 'old' method <sal_Bool IsMoveable() const>.
+ Determines, if frame is moveable in given environment. if no environment
+ is given (parameter _pLayoutFrame == 0), the movability in the actual
+ environment (<GetUpper()) is checked.
+*/
+bool SwFrame::IsMoveable( const SwLayoutFrame* _pLayoutFrame ) const
+{
+ bool bRetVal = false;
+
+ if ( !_pLayoutFrame )
+ {
+ _pLayoutFrame = GetUpper();
+ }
+
+ if ( _pLayoutFrame && IsFlowFrame() )
+ {
+ if ( _pLayoutFrame->IsInSct() && lcl_IsInSectionDirectly( _pLayoutFrame ) )
+ {
+ bRetVal = true;
+ }
+ else if ( _pLayoutFrame->IsInFly() ||
+ _pLayoutFrame->IsInDocBody() ||
+ _pLayoutFrame->IsInFootnote() )
+ {
+ // If IsMovable() is called before a MoveFwd() the method
+ // may return false if there is no NextCellLeaf. If
+ // IsMovable() is called before a MoveBwd() the method may
+ // return false if there is no PrevCellLeaf.
+ if ( _pLayoutFrame->IsInTab() && !IsTabFrame() &&
+ ( !IsContentFrame() || (!const_cast<SwFrame*>(this)->GetNextCellLeaf()
+ && !const_cast<SwFrame*>(this)->GetPrevCellLeaf()) )
+ )
+ {
+ bRetVal = false;
+ }
+ else
+ {
+ if ( _pLayoutFrame->IsInFly() )
+ {
+ // if fly frame has a follow (next linked fly frame),
+ // frame is moveable.
+ if ( const_cast<SwLayoutFrame*>(_pLayoutFrame)->FindFlyFrame()->GetNextLink() )
+ {
+ bRetVal = true;
+ }
+ else
+ {
+ // if environment is columned, frame is moveable, if
+ // it isn't in last column.
+ // search for column frame
+ const SwFrame* pCol = _pLayoutFrame;
+ while ( pCol && !pCol->IsColumnFrame() )
+ {
+ pCol = pCol->GetUpper();
+ }
+ // frame is moveable, if found column frame isn't last one.
+ if ( pCol && pCol->GetNext() )
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ else if (!(_pLayoutFrame->IsInFootnote() && (IsTabFrame() || IsInTab())))
+ {
+ bRetVal = true;
+ }
+ }
+ }
+ }
+
+ return bRetVal;
+}
+
+void SwFrame::SetInfFlags()
+{
+ if ( !IsFlyFrame() && !GetUpper() ) //not yet pasted, no information available
+ return;
+
+ mbInfInvalid = mbInfBody = mbInfTab = mbInfFly = mbInfFootnote = mbInfSct = false;
+
+ SwFrame *pFrame = this;
+ if( IsFootnoteContFrame() )
+ mbInfFootnote = true;
+ do
+ {
+ // mbInfBody is only set in the page body, but not in the column body
+ if ( pFrame->IsBodyFrame() && !mbInfFootnote && pFrame->GetUpper()
+ && pFrame->GetUpper()->IsPageFrame() )
+ mbInfBody = true;
+ else if ( pFrame->IsTabFrame() || pFrame->IsCellFrame() )
+ {
+ mbInfTab = true;
+ }
+ else if ( pFrame->IsFlyFrame() )
+ mbInfFly = true;
+ else if ( pFrame->IsSctFrame() )
+ mbInfSct = true;
+ else if ( pFrame->IsFootnoteFrame() )
+ mbInfFootnote = true;
+
+ pFrame = pFrame->GetUpper();
+
+ } while ( pFrame && !pFrame->IsPageFrame() ); //there is nothing above the page
+}
+
+/** Updates the vertical or the righttoleft-flags.
+ *
+ * If the property is derived, it's from the upper or (for fly frames) from
+ * the anchor. Otherwise we've to call a virtual method to check the property.
+ */
+void SwFrame::SetDirFlags( bool bVert )
+{
+ if( bVert )
+ {
+ // OD 2004-01-21 #114969# - if derived, valid vertical flag only if
+ // vertical flag of upper/anchor is valid.
+ if( mbDerivedVert )
+ {
+ const SwFrame* pAsk = IsFlyFrame() ?
+ static_cast<SwFlyFrame*>(this)->GetAnchorFrame() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Autsch! Stack overflow is about to happen" );
+
+ if( pAsk )
+ {
+ mbVertical = pAsk->IsVertical();
+ mbVertLR = pAsk->IsVertLR();
+ mbVertLRBT = pAsk->IsVertLRBT();
+
+ if ( !pAsk->mbInvalidVert )
+ mbInvalidVert = false;
+ }
+ }
+ else
+ CheckDirection( bVert );
+ }
+ else
+ {
+ bool bInv = false;
+ if( !mbDerivedR2L ) // CheckDirection is able to set bDerivedR2L!
+ CheckDirection( bVert );
+ if( mbDerivedR2L )
+ {
+ const SwFrame* pAsk = IsFlyFrame() ?
+ static_cast<SwFlyFrame*>(this)->GetAnchorFrame() : GetUpper();
+
+ OSL_ENSURE( pAsk != this, "Oops! Stack overflow is about to happen" );
+
+ if( pAsk )
+ mbRightToLeft = pAsk->IsRightToLeft();
+ if( !pAsk || pAsk->mbInvalidR2L )
+ bInv = mbInvalidR2L;
+ }
+ mbInvalidR2L = bInv;
+ }
+}
+
+SwLayoutFrame* SwFrame::GetNextCellLeaf()
+{
+ SwFrame* pTmpFrame = this;
+ while (pTmpFrame && !pTmpFrame->IsCellFrame())
+ pTmpFrame = pTmpFrame->GetUpper();
+
+ SAL_WARN_IF(!pTmpFrame, "sw.core", "SwFrame::GetNextCellLeaf() without cell");
+ return pTmpFrame ? static_cast<SwCellFrame*>(pTmpFrame)->GetFollowCell() : nullptr;
+}
+
+SwLayoutFrame* SwFrame::GetPrevCellLeaf()
+{
+ SwFrame* pTmpFrame = this;
+ while (pTmpFrame && !pTmpFrame->IsCellFrame())
+ pTmpFrame = pTmpFrame->GetUpper();
+
+ SAL_WARN_IF(!pTmpFrame, "sw.core", "SwFrame::GetNextPreviousLeaf() without cell");
+ return pTmpFrame ? static_cast<SwCellFrame*>(pTmpFrame)->GetPreviousCell() : nullptr;
+}
+
+static SwCellFrame* lcl_FindCorrespondingCellFrame( const SwRowFrame& rOrigRow,
+ const SwCellFrame& rOrigCell,
+ const SwRowFrame& rCorrRow,
+ bool bInFollow )
+{
+ SwCellFrame* pRet = nullptr;
+ const SwCellFrame* pCell = static_cast<const SwCellFrame*>(rOrigRow.Lower());
+ SwCellFrame* pCorrCell = const_cast<SwCellFrame*>(static_cast<const SwCellFrame*>(rCorrRow.Lower()));
+
+ while ( pCell != &rOrigCell && !pCell->IsAnLower( &rOrigCell ) )
+ {
+ pCell = static_cast<const SwCellFrame*>(pCell->GetNext());
+ pCorrCell = static_cast<SwCellFrame*>(pCorrCell->GetNext());
+ }
+
+ assert(pCell && pCorrCell && "lcl_FindCorrespondingCellFrame does not work");
+
+ if ( pCell != &rOrigCell )
+ {
+ // rOrigCell must be a lower of pCell. We need to recurse into the rows:
+ assert(pCell->Lower() && pCell->Lower()->IsRowFrame() &&
+ "lcl_FindCorrespondingCellFrame does not work");
+
+ const SwRowFrame* pRow = static_cast<const SwRowFrame*>(pCell->Lower());
+ while ( !pRow->IsAnLower( &rOrigCell ) )
+ pRow = static_cast<const SwRowFrame*>(pRow->GetNext());
+
+ SwRowFrame* pCorrRow = nullptr;
+ if ( bInFollow )
+ pCorrRow = pRow->GetFollowRow();
+ else
+ {
+ SwRowFrame* pTmpRow = static_cast<SwRowFrame*>(pCorrCell->GetLastLower());
+
+ if ( pTmpRow && pTmpRow->GetFollowRow() == pRow )
+ pCorrRow = pTmpRow;
+ }
+
+ if ( pCorrRow )
+ pRet = lcl_FindCorrespondingCellFrame( *pRow, rOrigCell, *pCorrRow, bInFollow );
+ }
+ else
+ pRet = pCorrCell;
+
+ return pRet;
+}
+
+// VERSION OF GetFollowCell() that assumes that we always have a follow flow line:
+SwCellFrame* SwCellFrame::GetFollowCell() const
+{
+ SwCellFrame* pRet = nullptr;
+
+ // NEW TABLES
+ // Covered cells do not have follow cells!
+ const long nRowSpan = GetLayoutRowSpan();
+ if ( nRowSpan < 1 )
+ return nullptr;
+
+ // find most upper row frame
+ const SwFrame* pRow = GetUpper();
+
+ while (pRow && (!pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame()))
+ pRow = pRow->GetUpper();
+
+ if (!pRow)
+ return nullptr;
+
+ const SwTabFrame* pTabFrame = static_cast<const SwTabFrame*>(pRow->GetUpper());
+ if (!pTabFrame || !pTabFrame->GetFollow() || !pTabFrame->HasFollowFlowLine())
+ return nullptr;
+
+ const SwCellFrame* pThisCell = this;
+
+ // Get last cell of the current table frame that belongs to the rowspan:
+ if ( nRowSpan > 1 )
+ {
+ // optimization: Will end of row span be in last row or exceed row?
+ long nMax = 0;
+ while ( pRow->GetNext() && ++nMax < nRowSpan )
+ pRow = pRow->GetNext();
+
+ if ( !pRow->GetNext() )
+ {
+ pThisCell = &pThisCell->FindStartEndOfRowSpanCell( false );
+ pRow = pThisCell->GetUpper();
+ }
+ }
+
+ const SwRowFrame* pFollowRow = nullptr;
+ if ( !pRow->GetNext() &&
+ nullptr != ( pFollowRow = pRow->IsInSplitTableRow() ) &&
+ ( !pFollowRow->IsRowSpanLine() || nRowSpan > 1 ) )
+ pRet = lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame*>(pRow), *pThisCell, *pFollowRow, true );
+
+ return pRet;
+}
+
+// VERSION OF GetPreviousCell() THAT ASSUMES THAT WE ALWAYS HAVE A FFL
+SwCellFrame* SwCellFrame::GetPreviousCell() const
+{
+ SwCellFrame* pRet = nullptr;
+
+ // NEW TABLES
+ // Covered cells do not have previous cells!
+ if ( GetLayoutRowSpan() < 1 )
+ return nullptr;
+
+ // find most upper row frame
+ const SwFrame* pRow = GetUpper();
+ while( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() )
+ pRow = pRow->GetUpper();
+
+ OSL_ENSURE( pRow->GetUpper() && pRow->GetUpper()->IsTabFrame(), "GetPreviousCell without Table" );
+
+ const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
+
+ if ( pTab->IsFollow() )
+ {
+ const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( bIsInFirstLine )
+ {
+ SwTabFrame *pMaster = pTab->FindMaster();
+ if ( pMaster && pMaster->HasFollowFlowLine() )
+ {
+ SwRowFrame* pMasterRow = static_cast<SwRowFrame*>(pMaster->GetLastLower());
+ if ( pMasterRow )
+ pRet = lcl_FindCorrespondingCellFrame( *static_cast<const SwRowFrame*>(pRow), *this, *pMasterRow, false );
+ if ( pRet && pRet->GetTabBox()->getRowSpan() < 1 )
+ pRet = &const_cast<SwCellFrame&>(pRet->FindStartEndOfRowSpanCell( true ));
+ }
+ }
+ }
+
+ return pRet;
+}
+
+// --> NEW TABLES
+const SwCellFrame& SwCellFrame::FindStartEndOfRowSpanCell( bool bStart ) const
+{
+ const SwTabFrame* pTableFrame = dynamic_cast<const SwTabFrame*>(GetUpper()->GetUpper());
+
+ if ( !bStart && pTableFrame && pTableFrame->IsFollow() && pTableFrame->IsInHeadline( *this ) )
+ return *this;
+
+ OSL_ENSURE( pTableFrame &&
+ ( (bStart && GetTabBox()->getRowSpan() < 1) ||
+ (!bStart && GetLayoutRowSpan() > 1) ),
+ "SwCellFrame::FindStartRowSpanCell: No rowspan, no table, no cookies" );
+
+ if ( pTableFrame )
+ {
+ const SwTable* pTable = pTableFrame->GetTable();
+
+ sal_uInt16 nMax = USHRT_MAX;
+ const SwFrame* pCurrentRow = GetUpper();
+ const bool bDoNotEnterHeadline = bStart && pTableFrame->IsFollow() &&
+ !pTableFrame->IsInHeadline( *pCurrentRow );
+
+ // check how many rows we are allowed to go up or down until we reach the end of
+ // the current table frame:
+ nMax = 0;
+ while ( bStart ? pCurrentRow->GetPrev() : pCurrentRow->GetNext() )
+ {
+ if ( bStart )
+ {
+ // do not enter a repeated headline:
+ if ( bDoNotEnterHeadline && pTableFrame->IsFollow() &&
+ pTableFrame->IsInHeadline( *pCurrentRow->GetPrev() ) )
+ break;
+
+ pCurrentRow = pCurrentRow->GetPrev();
+ }
+ else
+ pCurrentRow = pCurrentRow->GetNext();
+
+ ++nMax;
+ }
+
+ // By passing the nMax value for Find*OfRowSpan (in case of bCurrentTableOnly
+ // is set) we assure that we find a rMasterBox that has a SwCellFrame in
+ // the current table frame:
+ const SwTableBox& rMasterBox = bStart ?
+ GetTabBox()->FindStartOfRowSpan( *pTable, nMax ) :
+ GetTabBox()->FindEndOfRowSpan( *pTable, nMax );
+
+ SwIterator<SwCellFrame,SwFormat> aIter( *rMasterBox.GetFrameFormat() );
+
+ for ( SwCellFrame* pMasterCell = aIter.First(); pMasterCell; pMasterCell = aIter.Next() )
+ {
+ if ( pMasterCell->GetTabBox() == &rMasterBox )
+ {
+ const SwTabFrame* pMasterTable = static_cast<const SwTabFrame*>(pMasterCell->GetUpper()->GetUpper());
+
+ if ( pMasterTable == pTableFrame )
+ {
+ return *pMasterCell;
+ }
+ }
+ }
+ }
+
+ SAL_WARN("sw.core", "SwCellFrame::FindStartRowSpanCell: No result");
+
+ return *this;
+}
+
+// <-- NEW TABLES
+
+const SwRowFrame* SwFrame::IsInSplitTableRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ const SwFrame* pRow = this;
+
+ // find most upper row frame
+ while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return nullptr;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" );
+
+ const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
+
+ // If most upper row frame is a headline row, the current frame
+ // can't be in a split table row. Thus, add corresponding condition.
+ if ( pRow->GetNext() ||
+ pTab->GetTable()->IsHeadline(
+ *(static_cast<const SwRowFrame*>(pRow)->GetTabLine()) ) ||
+ !pTab->HasFollowFlowLine() ||
+ !pTab->GetFollow() )
+ return nullptr;
+
+ // skip headline
+ const SwRowFrame* pFollowRow = pTab->GetFollow()->GetFirstNonHeadlineRow();
+
+ OSL_ENSURE( pFollowRow, "SwFrame::IsInSplitTableRow() does not work" );
+
+ return pFollowRow;
+}
+
+const SwRowFrame* SwFrame::IsInFollowFlowRow() const
+{
+ OSL_ENSURE( IsInTab(), "IsInSplitTableRow should only be called for frames in tables" );
+
+ // find most upper row frame
+ const SwFrame* pRow = this;
+ while( pRow && ( !pRow->IsRowFrame() || !pRow->GetUpper()->IsTabFrame() ) )
+ pRow = pRow->GetUpper();
+
+ if ( !pRow ) return nullptr;
+
+ OSL_ENSURE( pRow->GetUpper()->IsTabFrame(), "Confusion in table layout" );
+
+ const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pRow->GetUpper());
+
+ const SwTabFrame* pMaster = pTab->IsFollow() ? pTab->FindMaster() : nullptr;
+
+ if ( !pMaster || !pMaster->HasFollowFlowLine() )
+ return nullptr;
+
+ const SwFrame* pTmp = pTab->GetFirstNonHeadlineRow();
+ const bool bIsInFirstLine = ( pTmp == pRow );
+
+ if ( !bIsInFirstLine )
+ return nullptr;
+
+ const SwRowFrame* pMasterRow = static_cast<const SwRowFrame*>(pMaster->GetLastLower());
+ return pMasterRow;
+}
+
+bool SwFrame::IsInBalancedSection() const
+{
+ bool bRet = false;
+
+ if ( IsInSct() )
+ {
+ const SwSectionFrame* pSectionFrame = FindSctFrame();
+ if ( pSectionFrame )
+ bRet = pSectionFrame->IsBalancedSection();
+ }
+ return bRet;
+}
+
+const SwFrame* SwLayoutFrame::GetLastLower() const
+{
+ const SwFrame* pRet = Lower();
+ if ( !pRet )
+ return nullptr;
+ while ( pRet->GetNext() )
+ pRet = pRet->GetNext();
+ return pRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */