    /* -*- 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.