/* -*- 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 <flyfrms.hxx>
#include <ftnfrm.hxx>
#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <fmtpdsc.hxx>
#include <txtfrm.hxx>
#include <calbck.hxx>
#include <viewopt.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 && ( nullptr != (p = lcl_GetLower( pFrame, bFwd ) ) ) );
         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:
             bGoingFwdOrBwd = (nullptr != (p = lcl_FindLayoutFrame( pFrame, bFwd ) ) );
             if ( !bGoingFwdOrBwd )
             {
                 // I cannot go forward, because there is no next frame.
                 // I'll try to go up:
                 bGoingUp = (nullptr != (p = pFrame->GetUpper() ) );
                 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 && ( nullptr != ( p = lcl_GetLower( pFrame, true ) ) ) );
        if ( !bGoingDown )
        {
            bGoingFwdOrBwd = ( nullptr != ( p = lcl_FindLayoutFrame( pFrame, bFwd ) ) );
            if ( !bGoingFwdOrBwd )
            {
                bGoingUp = ( nullptr != ( p = pFrame->GetUpper() ) );
                if ( !bGoingUp )
                {
                    return nullptr;
                }
            }
        }
 
        bGoingUp = !(bGoingFwdOrBwd || bGoingDown);
 
        if ( !bFwd )
        {
            if( bGoingDown && p )
                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);
}
 
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 && ( nullptr != (p = pFrame->IsLayoutFrame() ? static_cast<SwLayoutFrame*>(pFrame)->Lower() : nullptr)));
 
        if( !bGoingDown )
        {
            bGoingFwd = (nullptr != (p = ( pFrame->IsFlyFrame() ? static_cast<SwFlyFrame*>(pFrame)->GetNextLink() : pFrame->GetNext())));
            if ( !bGoingFwd )
            {
                bGoingUp = (nullptr != (p = pFrame->GetUpper()));
                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)->FindLastContent();
        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)->FindLastContent();
        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 its 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();
 
                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 SwCellFrame* pRet = nullptr;
 
    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 )
                {
                    pRet = pMasterCell;
                    break;
                }
            }
        }
    }
 
    assert(pRet && "SwCellFrame::FindStartRowSpanCell: No result");
 
    return *pRet;
}
// <-- 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 splitted 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: */

V560 A part of conditional expression is always true: p.