    /* -*- 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 <comphelper/lok.hxx>
    #include <ndole.hxx>
    #include <sal/log.hxx>
    #include <svl/itemiter.hxx>
    #include <fmtfsize.hxx>
    #include <fmthdft.hxx>
    #include <fmtclds.hxx>
    #include <fmtpdsc.hxx>
    #include <fmtornt.hxx>
    #include <fmtsrnd.hxx>
    #include <ftninfo.hxx>
    #include <tgrditem.hxx>
    #include <viewopt.hxx>
    #include <docsh.hxx>
    #include <wrtsh.hxx>
    #include <view.hxx>
    #include <edtwin.hxx>
    #include <docary.hxx>

    #include <viewimp.hxx>
    #include <pagefrm.hxx>
    #include <rootfrm.hxx>
    #include <IDocumentSettingAccess.hxx>
    #include <IDocumentFieldsAccess.hxx>
    #include <dcontact.hxx>
    #include <hints.hxx>
    #include <FrameControlsManager.hxx>

    #include <ftnidx.hxx>
    #include <bodyfrm.hxx>
    #include <ftnfrm.hxx>
    #include <tabfrm.hxx>
    #include <txtfrm.hxx>
    #include <notxtfrm.hxx>
    #include <layact.hxx>
    #include <flyfrms.hxx>
    #include <htmltbl.hxx>
    #include <pagedesc.hxx>
    #include <editeng/frmdiritem.hxx>
    #include <sortedobjs.hxx>
    #include <calbck.hxx>
    #include <txtfly.hxx>

    using namespace ::com::sun::star;

    SwBodyFrame::SwBodyFrame( SwFrameFormat *pFormat, SwFrame* pSib ):
        SwLayoutFrame( pFormat, pSib )
    {
        mnFrameType = SwFrameType::Body;
    }

    void SwBodyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs * )
    {
        // Formatting of the body is too simple, thus, it gets its own format method.
        // Borders etc. are not taken into account here.
        // Width is taken from the PrtArea of the Upper. Height is the height of the
        // PrtArea of the Upper minus any neighbors (for robustness).
        // The PrtArea has always the size of the frame.

        if ( !isFrameAreaSizeValid() )
        {
            SwTwips nHeight = GetUpper()->getFramePrintArea().Height();
            SwTwips nWidth = GetUpper()->getFramePrintArea().Width();
            const SwFrame *pFrame = GetUpper()->Lower();
            do
            {
                if ( pFrame != this )
                {
                    if( pFrame->IsVertical() )
                        nWidth -= pFrame->getFrameArea().Width();
                    else
                        nHeight -= pFrame->getFrameArea().Height();
                }
                pFrame = pFrame->GetNext();
            } while ( pFrame );

            if ( nHeight < 0 )
            {
                nHeight = 0;
            }

            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.Height( nHeight );

            if( IsVertical() && !IsVertLR() && nWidth != aFrm.Width() )
            {
                aFrm.Pos().setX(aFrm.Pos().getX() + aFrm.Width() - nWidth);
            }

            aFrm.Width( nWidth );
        }

        bool bNoGrid = true;
        if( GetUpper()->IsPageFrame() && static_cast<SwPageFrame*>(GetUpper())->HasGrid() )
        {
            SwTextGridItem const*const pGrid(
                    GetGridItem(static_cast<SwPageFrame*>(GetUpper())));
            if( pGrid )
            {
                bNoGrid = false;
                long nSum = pGrid->GetBaseHeight() + pGrid->GetRubyHeight();
                SwRectFnSet aRectFnSet(this);
                long nSize = aRectFnSet.GetWidth(getFrameArea());
                long nBorder = 0;
                if( GRID_LINES_CHARS == pGrid->GetGridType() )
                {
                    //for textgrid refactor
                    SwDoc *pDoc = GetFormat()->GetDoc();
                    nBorder = nSize % (GetGridWidth(*pGrid, *pDoc));
                    nSize -= nBorder;
                    nBorder /= 2;
                }

                SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                aRectFnSet.SetPosX( aPrt, nBorder );
                aRectFnSet.SetWidth( aPrt, nSize );

                // Height of body frame:
                nBorder = aRectFnSet.GetHeight(getFrameArea());

                // Number of possible lines in area of body frame:
                long nNumberOfLines = nBorder / nSum;
                if( nNumberOfLines > pGrid->GetLines() )
                    nNumberOfLines = pGrid->GetLines();

                // Space required for nNumberOfLines lines:
                nSize = nNumberOfLines * nSum;
                nBorder -= nSize;
                nBorder /= 2;

                // #i21774# Footnotes and centering the grid does not work together:
                const bool bAdjust = static_cast<SwPageFrame*>(GetUpper())->GetFormat()->GetDoc()->
                                            GetFootnoteIdxs().empty();

                aRectFnSet.SetPosY( aPrt, bAdjust ? nBorder : 0 );
                aRectFnSet.SetHeight( aPrt, nSize );
            }
        }

        if( bNoGrid )
        {
            SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
            aPrt.Pos().setX(0);
            aPrt.Pos().setY(0);
            aPrt.Height( getFrameArea().Height() );
            aPrt.Width( getFrameArea().Width() );
        }

        setFrameAreaSizeValid(true);
        setFramePrintAreaValid(true);
    }

    SwPageFrame::SwPageFrame( SwFrameFormat *pFormat, SwFrame* pSib, SwPageDesc *pPgDsc ) :
        SwFootnoteBossFrame( pFormat, pSib ),
        m_pDesc( pPgDsc ),
        m_nPhyPageNum( 0 )
    {
        SetDerivedVert( false );
        SetDerivedR2L( false );
        if( m_pDesc )
        {
            m_bHasGrid = true;
            SwTextGridItem const*const pGrid(GetGridItem(this));
            if( !pGrid )
                m_bHasGrid = false;
        }
        else
            m_bHasGrid = false;
        SetMaxFootnoteHeight( pPgDsc->GetFootnoteInfo().GetHeight() ?
                         pPgDsc->GetFootnoteInfo().GetHeight() : LONG_MAX );
        mnFrameType = SwFrameType::Page;
        m_bInvalidLayout = m_bInvalidContent = m_bInvalidSpelling = m_bInvalidSmartTags = m_bInvalidAutoCmplWrds = m_bInvalidWordCount = true;
        m_bInvalidFlyLayout = m_bInvalidFlyContent = m_bInvalidFlyInCnt = m_bFootnotePage = m_bEndNotePage = false;

        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        vcl::RenderContext* pRenderContext = pSh ? pSh->GetOut() : nullptr;

        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);

            if ( bBrowseMode )
            {
                aFrm.Height( 0 );
                long nWidth = pSh->VisArea().Width();

                if ( !nWidth )
                {
                    nWidth = 5000;     // changes anyway
                }

                aFrm.Width ( nWidth );
            }
            else
            {
                aFrm.SSize( pFormat->GetFrameSize().GetSize() );
            }
        }

        // create and insert body area if it is not a blank page
        SwDoc* pDoc(pFormat->GetDoc());
        m_bEmptyPage = (pFormat == pDoc->GetEmptyPageFormat());

        if(m_bEmptyPage)
        {
            return;
        }

        Calc(pRenderContext); // so that the PrtArea is correct
        SwBodyFrame *pBodyFrame = new SwBodyFrame( pDoc->GetDfltFrameFormat(), this );
        pBodyFrame->ChgSize( getFramePrintArea().SSize() );
        pBodyFrame->Paste( this );
        pBodyFrame->Calc(pRenderContext); // so that the columns can be inserted correctly
        pBodyFrame->InvalidatePos();

        if ( bBrowseMode )
            InvalidateSize_();

        // insert header/footer,, but only if active.
        if ( pFormat->GetHeader().IsActive() )
            PrepareHeader();
        if ( pFormat->GetFooter().IsActive() )
            PrepareFooter();

        const SwFormatCol &rCol = pFormat->GetCol();
        if ( rCol.GetNumCols() > 1 )
        {
            const SwFormatCol aOld; //ChgColumns() needs an old value
            pBodyFrame->ChgColumns( aOld, rCol );
        }

    }

    void SwPageFrame::DestroyImpl()
    {
        // Cleanup the header-footer controls in the SwEditWin
        SwViewShell* pSh = getRootFrame()->GetCurrShell();
        SwWrtShell* pWrtSh = dynamic_cast< SwWrtShell* >( pSh );
        if ( pWrtSh )
        {
            SwEditWin& rEditWin = pWrtSh->GetView().GetEditWin();
            rEditWin.GetFrameControlsManager( ).RemoveControls( this );
        }

        // empty FlyContainer, deletion of the Flys is done by the anchor (in base class SwFrame)
        if (m_pSortedObjs)
        {
            // Objects can be anchored at pages that are before their anchors (why ever...).
            // In such cases, we would access already freed memory.
            for (SwAnchoredObject* pAnchoredObj : *m_pSortedObjs)
            {
                pAnchoredObj->SetPageFrame( nullptr );
            }
            m_pSortedObjs.reset(); // reset to zero to prevent problems when detaching the Flys
        }

        // prevent access to destroyed pages
        SwDoc *pDoc = GetFormat() ? GetFormat()->GetDoc() : nullptr;
        if( pDoc && !pDoc->IsInDtor() )
        {
            if ( pSh )
            {
                SwViewShellImp *pImp = pSh->Imp();
                pImp->SetFirstVisPageInvalid();
                if ( pImp->IsAction() )
                    pImp->GetLayAction().SetAgain();
                // #i9719# - retouche area of page
                // including border and shadow area.
                const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT);
                SwRect aRetoucheRect;
                SwPageFrame::GetBorderAndShadowBoundRect( getFrameArea(), pSh, pSh->GetOut(), aRetoucheRect, IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
                pSh->AddPaintRect( aRetoucheRect );
            }
        }

        SwFootnoteBossFrame::DestroyImpl();
    }

    SwPageFrame::~SwPageFrame()
    {
    }

    void SwPageFrame::CheckGrid( bool bInvalidate )
    {
        bool bOld = m_bHasGrid;
        m_bHasGrid = true;
        SwTextGridItem const*const pGrid(GetGridItem(this));
        m_bHasGrid = nullptr != pGrid;
        if( bInvalidate || bOld != m_bHasGrid )
        {
            SwLayoutFrame* pBody = FindBodyCont();
            if( pBody )
            {
                pBody->InvalidatePrt();
                SwContentFrame* pFrame = pBody->ContainsContent();
                while( pBody->IsAnLower( pFrame ) )
                {
                    static_cast<SwTextFrame*>(pFrame)->Prepare();
                    pFrame = pFrame->GetNextContentFrame();
                }
            }
            SetCompletePaint();
        }
    }

    void SwPageFrame::CheckDirection( bool bVert )
    {
        SvxFrameDirection nDir = GetFormat()->GetFormatAttr( RES_FRAMEDIR ).GetValue();
        if( bVert )
        {
            if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir )
            {
                mbVertLR = false;
                mbVertical = false;
            }
            else
            {
                const SwViewShell *pSh = getRootFrame()->GetCurrShell();
                if( pSh && pSh->GetViewOptions()->getBrowseMode() )
                {
                    mbVertLR = false;
                    mbVertical = false;
                }
                else
                {
                    mbVertical = true;

                    if(SvxFrameDirection::Vertical_RL_TB == nDir)
                        mbVertLR = false;
                        else if(SvxFrameDirection::Vertical_LR_TB==nDir)
                           mbVertLR = true;
                }
            }

            mbInvalidVert = false;
        }
        else
        {
            if( SvxFrameDirection::Horizontal_RL_TB == nDir )
                mbRightToLeft = true;
            else
                mbRightToLeft = false;
            mbInvalidR2L = false;
        }
    }

    /// create specific Flys for this page and format generic content
    static void lcl_FormatLay( SwLayoutFrame *pLay )
    {
        vcl::RenderContext* pRenderContext = pLay->getRootFrame()->GetCurrShell()->GetOut();
        // format all LayoutFrames - no tables, Flys etc.

        SwFrame *pTmp = pLay->Lower();
        // first the low-level ones
        while ( pTmp )
        {
            const SwFrameType nTypes = SwFrameType::Root | SwFrameType::Page | SwFrameType::Column
                               | SwFrameType::Header | SwFrameType::Footer | SwFrameType::FtnCont
                               | SwFrameType::Ftn | SwFrameType::Body;
            if ( pTmp->GetType() & nTypes )
                ::lcl_FormatLay( static_cast<SwLayoutFrame*>(pTmp) );
            pTmp = pTmp->GetNext();
        }
        pLay->Calc(pRenderContext);
    }

    /// Create Flys or register draw objects
    static void lcl_MakeObjs( const SwFrameFormats &rTable, SwPageFrame *pPage )
    {
        // formats are in the special table of the document

        for ( size_t i = 0; i < rTable.size(); ++i )
        {
            SwFrameFormat *pFormat = rTable[i];
            const SwFormatAnchor &rAnch = pFormat->GetAnchor();
            if ( rAnch.GetPageNum() == pPage->GetPhyPageNum() )
            {
                if( rAnch.GetContentAnchor() )
                {
                    if (RndStdIds::FLY_AT_PAGE == rAnch.GetAnchorId())
                    {
                        SwFormatAnchor aAnch( rAnch );
                        aAnch.SetAnchor( nullptr );
                        pFormat->SetFormatAttr( aAnch );
                    }
                    else
                        continue;
                }

                // is it a border or a SdrObject?
                bool bSdrObj = RES_DRAWFRMFMT == pFormat->Which();
                SdrObject *pSdrObj = nullptr;
                if ( bSdrObj  && nullptr == (pSdrObj = pFormat->FindSdrObject()) )
                {
                    OSL_FAIL( "DrawObject not found." );
                    pFormat->GetDoc()->DelFrameFormat( pFormat );
                    --i;
                    continue;
                }
                // The object might be anchored to another page, e.g. when inserting
                // a new page due to a page descriptor change. In such cases, the
                // object needs to be moved.
                // In some cases the object is already anchored to the correct page.
                // This will be handled here and does not need to be coded extra.
                SwPageFrame *pPg = pPage->IsEmptyPage() ? static_cast<SwPageFrame*>(pPage->GetNext()) : pPage;
                if ( bSdrObj )
                {
                    // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
                    SwDrawContact *pContact =
                                static_cast<SwDrawContact*>(::GetUserCall(pSdrObj));
                    if ( dynamic_cast< const SwDrawVirtObj *>( pSdrObj ) !=  nullptr )
                    {
                        SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pSdrObj);
                        if ( pContact )
                        {
                            pDrawVirtObj->RemoveFromWriterLayout();
                            pDrawVirtObj->RemoveFromDrawingPage();
                            pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pDrawVirtObj )) );
                        }
                    }
                    else
                    {
                        if ( pContact->GetAnchorFrame() )
                            pContact->DisconnectFromLayout( false );
                        pPg->AppendDrawObj( *(pContact->GetAnchoredObj( pSdrObj )) );
                    }
                }
                else
                {
                    SwIterator<SwFlyFrame,SwFormat> aIter( *pFormat );
                    SwFlyFrame *pFly = aIter.First();
                    if ( pFly)
                    {
                        if( pFly->GetAnchorFrame() )
                            pFly->AnchorFrame()->RemoveFly( pFly );
                    }
                    else
                        pFly = new SwFlyLayFrame( static_cast<SwFlyFrameFormat*>(pFormat), pPg, pPg );
                    pPg->AppendFly( pFly );
                    ::RegistFlys( pPg, pFly );
                }
            }
        }
    }

    void SwPageFrame::PreparePage( bool bFootnote )
    {
        SetFootnotePage( bFootnote );

        // #i82258#
        // Due to made change on OOo 2.0 code line, method <::lcl_FormatLay(..)> has
        // the side effect, that the content of page header and footer are formatted.
        // For this formatting it is needed that the anchored objects are registered
        // at the <SwPageFrame> instance.
        // Thus, first calling <::RegistFlys(..)>, then call <::lcl_FormatLay(..)>
        ::RegistFlys( this, this );

        if ( Lower() )
        {
                    ::lcl_FormatLay( this );
        }

        // Flys and draw objects that are still attached to the document.
        // Footnote pages do not have page-bound Flys!
        // There might be Flys or draw objects that want to be placed on
        // empty pages, however, the empty pages ignore that and the following
        // pages take care of them.
        if ( !bFootnote && !IsEmptyPage() )
        {
            SwDoc *pDoc = GetFormat()->GetDoc();

            if ( GetPrev() && static_cast<SwPageFrame*>(GetPrev())->IsEmptyPage() )
                lcl_MakeObjs( *pDoc->GetSpzFrameFormats(), static_cast<SwPageFrame*>(GetPrev()) );
            lcl_MakeObjs( *pDoc->GetSpzFrameFormats(), this );
        }
    }

    void SwPageFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
    {
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( pSh )
            pSh->SetFirstVisPageInvalid();
        sal_uInt8 nInvFlags = 0;

        if( pNew && RES_ATTRSET_CHG == pNew->Which() )
        {
            SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
            SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
            SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
            SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
            while( true )
            {
                UpdateAttr_( aOIter.GetCurItem(),
                             aNIter.GetCurItem(), nInvFlags,
                             &aOldSet, &aNewSet );
                if( aNIter.IsAtEnd() )
                    break;
                aNIter.NextItem();
                aOIter.NextItem();
            }
            if ( aOldSet.Count() || aNewSet.Count() )
                SwLayoutFrame::Modify( &aOldSet, &aNewSet );
        }
        else
            UpdateAttr_( pOld, pNew, nInvFlags );

        if ( nInvFlags != 0 )
        {
            InvalidatePage( this );
            if ( nInvFlags & 0x01 )
                InvalidatePrt_();
            if ( nInvFlags & 0x02 )
                SetCompletePaint();
            if ( nInvFlags & 0x04 && GetNext() )
                GetNext()->InvalidatePos();
            if ( nInvFlags & 0x08 )
                PrepareHeader();
            if ( nInvFlags & 0x10 )
                PrepareFooter();
            if ( nInvFlags & 0x20 )
                CheckGrid( nInvFlags & 0x40 );
        }
    }

    void SwPageFrame::SwClientNotify(const SwModify& rModify, const SfxHint& rHint)
    {
        if(typeid(sw::PageFootnoteHint) == typeid(rHint))
        {
            // currently the savest way:
            static_cast<SwRootFrame*>(GetUpper())->SetSuperfluous();
            SetMaxFootnoteHeight(m_pDesc->GetFootnoteInfo().GetHeight());
            if(!GetMaxFootnoteHeight())
                SetMaxFootnoteHeight(LONG_MAX);
            SetColMaxFootnoteHeight();
            // here, the page might be destroyed:
            static_cast<SwRootFrame*>(GetUpper())->RemoveFootnotes(nullptr, false, true);
        }
        else
            SwFrame::SwClientNotify(rModify, rHint);
    }

    void SwPageFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
                                 sal_uInt8 &rInvFlags,
                                 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
    {
        bool bClear = true;
        const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
        switch( nWhich )
        {
            case RES_FMT_CHG:
            {
                // state of m_bEmptyPage needs to be determined newly
                const bool bNewState(GetFormat() == GetFormat()->GetDoc()->GetEmptyPageFormat());

                if(m_bEmptyPage != bNewState)
                {
                    // copy new state
                    m_bEmptyPage = bNewState;

                    if(nullptr == GetLower())
                    {
                        // if we were an empty page before there is not yet a BodyArea in the
                        // form of a SwBodyFrame, see constructor
                        SwViewShell* pSh(getRootFrame()->GetCurrShell());
                        vcl::RenderContext* pRenderContext(pSh ? pSh->GetOut() : nullptr);
                        Calc(pRenderContext); // so that the PrtArea is correct
                        SwBodyFrame* pBodyFrame = new SwBodyFrame(GetFormat(), this);
                        pBodyFrame->ChgSize(getFramePrintArea().SSize());
                        pBodyFrame->Paste(this);
                        pBodyFrame->InvalidatePos();
                    }
                }

                // If the frame format is changed, several things might also change:
                // 1. columns:
                assert(pOld && pNew); //FMT_CHG Missing Format
                const SwFormat *const pOldFormat = static_cast<const SwFormatChg*>(pOld)->pChangedFormat;
                const SwFormat *const pNewFormat = static_cast<const SwFormatChg*>(pNew)->pChangedFormat;
                assert(pOldFormat && pNewFormat); //FMT_CHG Missing Format
                const SwFormatCol &rOldCol = pOldFormat->GetCol();
                const SwFormatCol &rNewCol = pNewFormat->GetCol();
                if( rOldCol != rNewCol )
                {
                    SwLayoutFrame *pB = FindBodyCont();
                    assert(pB && "Page without Body.");
                    pB->ChgColumns( rOldCol, rNewCol );
                    rInvFlags |= 0x20;
                }

                // 2. header and footer:
                const SwFormatHeader &rOldH = pOldFormat->GetHeader();
                const SwFormatHeader &rNewH = pNewFormat->GetHeader();
                if( rOldH != rNewH )
                    rInvFlags |= 0x08;

                const SwFormatFooter &rOldF = pOldFormat->GetFooter();
                const SwFormatFooter &rNewF = pNewFormat->GetFooter();
                if( rOldF != rNewF )
                    rInvFlags |= 0x10;
                CheckDirChange();

                SAL_FALLTHROUGH;
            }
            case RES_FRM_SIZE:
            {
                const SwRect aOldPageFrameRect( getFrameArea() );
                SwViewShell *pSh = getRootFrame()->GetCurrShell();
                if( pSh && pSh->GetViewOptions()->getBrowseMode() )
                {
                    setFrameAreaSizeValid(false);
                    // OD 28.10.2002 #97265# - Don't call <SwPageFrame::MakeAll()>
                    // Calculation of the page is not necessary, because its size is
                    // invalidated here and further invalidation is done in the
                    // calling method <SwPageFrame::Modify(..)> and probably by calling
                    // <SwLayoutFrame::Modify(..)> at the end.
                    // It can also causes inconsistences, because the lowers are
                    // adjusted, but not calculated, and a <SwPageFrame::MakeAll()> of
                    // a next page is called. This is performed on the switch to the
                    // online layout.
                    //MakeAll();
                }
                else if (pNew)
                {
                    const SwFormatFrameSize &rSz = nWhich == RES_FMT_CHG ?
                            static_cast<const SwFormatChg*>(pNew)->pChangedFormat->GetFrameSize() :
                            static_cast<const SwFormatFrameSize&>(*pNew);

                    {
                        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                        aFrm.Height( std::max( rSz.GetHeight(), long(MINLAY) ) );
                        aFrm.Width ( std::max( rSz.GetWidth(),  long(MINLAY) ) );
                    }

                    if ( GetUpper() )
                    {
                        static_cast<SwRootFrame*>(GetUpper())->CheckViewLayout( nullptr, nullptr );
                    }
                }
                // cleanup Window
                if( pSh && pSh->GetWin() && aOldPageFrameRect.HasArea() )
                {
                    // #i9719# - consider border and shadow of
                    // page frame for determine 'old' rectangle - it's used for invalidating.
                    const bool bRightSidebar = (SidebarPosition() == sw::sidebarwindows::SidebarPosition::RIGHT);
                    SwRect aOldRectWithBorderAndShadow;
                    SwPageFrame::GetBorderAndShadowBoundRect( aOldPageFrameRect, pSh, pSh->GetOut(), aOldRectWithBorderAndShadow,
                        IsLeftShadowNeeded(), IsRightShadowNeeded(), bRightSidebar );
                    pSh->InvalidateWindows( aOldRectWithBorderAndShadow );
                }
                rInvFlags |= 0x03;
                if ( aOldPageFrameRect.Height() != getFrameArea().Height() )
                    rInvFlags |= 0x04;
            }
            break;

            case RES_COL:
                assert(pOld && pNew); //COL Missing Format
                if (pOld && pNew)
                {
                    SwLayoutFrame *pB = FindBodyCont();
                    assert(pB); //page without body
                    pB->ChgColumns( *static_cast<const SwFormatCol*>(pOld), *static_cast<const SwFormatCol*>(pNew) );
                    rInvFlags |= 0x22;
                }
            break;

            case RES_HEADER:
                rInvFlags |= 0x08;
                break;

            case RES_FOOTER:
                rInvFlags |= 0x10;
                break;
            case RES_TEXTGRID:
                rInvFlags |= 0x60;
                break;
            case RES_FRAMEDIR :
                CheckDirChange();
                break;

            default:
                bClear = false;
        }
        if ( bClear )
        {
            if ( pOldSet || pNewSet )
            {
                if ( pOldSet )
                    pOldSet->ClearItem( nWhich );
                if ( pNewSet )
                    pNewSet->ClearItem( nWhich );
            }
            else
                SwLayoutFrame::Modify( pOld, pNew );
        }
    }

    /// get information from Modify
    bool SwPageFrame::GetInfo( SfxPoolItem & rInfo ) const
    {
        if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
        {
            // a page frame exists, so use this one
            return false;
        }
        return true; // continue searching
    }

    void  SwPageFrame::SetPageDesc( SwPageDesc *pNew, SwFrameFormat *pFormat )
    {
        m_pDesc = pNew;
        if ( pFormat )
            SetFrameFormat( pFormat );
    }

    /* determine the right PageDesc:
     *  0.  from the document for footnote and endnote pages
     *  1.  from the first BodyContent below a page
     *  2.  from PageDesc of the predecessor page
     *  3.  from PageDesc of the previous page if blank page
     *  3.1 from PageDesc of the next page if no predecessor exists
     *  4.  default PageDesc
     *  5.  In BrowseMode use the first paragraph or default PageDesc.
     */
    SwPageDesc *SwPageFrame::FindPageDesc()
    {
        // 0.
        if ( IsFootnotePage() )
        {
            SwDoc *pDoc = GetFormat()->GetDoc();
            if ( IsEndNotePage() )
                return pDoc->GetEndNoteInfo().GetPageDesc( *pDoc );
            else
                return pDoc->GetFootnoteInfo().GetPageDesc( *pDoc );
        }

        SwPageDesc *pRet = nullptr;

        //5.
        const SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if( pSh && pSh->GetViewOptions()->getBrowseMode() )
        {
            SwContentFrame *pFrame = GetUpper()->ContainsContent();
            while (pFrame && !pFrame->IsInDocBody())
                pFrame = pFrame->GetNextContentFrame();
            if (pFrame)
            {
                SwFrame *pFlow = pFrame;
                if ( pFlow->IsInTab() )
                    pFlow = pFlow->FindTabFrame();
                pRet = const_cast<SwPageDesc*>(pFlow->GetPageDescItem().GetPageDesc());
            }
            if ( !pRet )
                pRet = &GetFormat()->GetDoc()->GetPageDesc( 0 );
            return pRet;
        }

        SwFrame *pFlow = FindFirstBodyContent();
        if ( pFlow && pFlow->IsInTab() )
            pFlow = pFlow->FindTabFrame();

        //1.
        if ( pFlow )
        {
            SwFlowFrame *pTmp = SwFlowFrame::CastFlowFrame( pFlow );
            if ( !pTmp->IsFollow() )
                pRet = const_cast<SwPageDesc*>(pFlow->GetPageDescItem().GetPageDesc());
        }

        //3. and 3.1
        if ( !pRet && IsEmptyPage() )
                // FME 2008-03-03 #i81544# lijian/fme: an empty page should have
                // the same page description as its prev, just like after construction
                // of the empty page.
            pRet = GetPrev() ? static_cast<SwPageFrame*>(GetPrev())->GetPageDesc() :
                   GetNext() ? static_cast<SwPageFrame*>(GetNext())->GetPageDesc() : nullptr;

        //2.
        if ( !pRet )
            pRet = GetPrev() ?
                        static_cast<SwPageFrame*>(GetPrev())->GetPageDesc()->GetFollow() : nullptr;

        //4.
        if ( !pRet )
            pRet = &GetFormat()->GetDoc()->GetPageDesc( 0 );

        OSL_ENSURE( pRet, "could not find page descriptor." );
        return pRet;
    }

    // Notify if the RootFrame changes its size
    void AdjustSizeChgNotify( SwRootFrame *pRoot )
    {
        const bool bOld = pRoot->IsSuperfluous();
        pRoot->mbCheckSuperfluous = false;
        if ( pRoot->GetCurrShell() )
        {
            for(SwViewShell& rSh : pRoot->GetCurrShell()->GetRingContainer())
            {
                if( pRoot == rSh.GetLayout() )
                {
                    rSh.SizeChgNotify();
                    if ( rSh.Imp() )
                        rSh.Imp()->NotifySizeChg( pRoot->getFrameArea().SSize() );
                }
            }
        }
        pRoot->mbCheckSuperfluous = bOld;
    }

    inline void SetLastPage( SwPageFrame *pPage )
    {
        static_cast<SwRootFrame*>(pPage->GetUpper())->mpLastPage = pPage;
    }

    void SwPageFrame::Cut()
    {
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( !IsEmptyPage() )
        {
            if ( GetNext() )
                GetNext()->InvalidatePos();

            // move Flys whose anchor is on a different page (draw objects are not relevant here)
            if ( GetSortedObjs() )
            {
                size_t i = 0;
                while ( GetSortedObjs() && i < GetSortedObjs()->size() )
                {
                    // #i28701#
                    SwAnchoredObject* pAnchoredObj = (*GetSortedObjs())[i];

                    if ( dynamic_cast< const SwFlyAtContentFrame *>( pAnchoredObj ) !=  nullptr )
                    {
                        SwFlyFrame* pFly = static_cast<SwFlyAtContentFrame*>(pAnchoredObj);
                        SwPageFrame *pAnchPage = pFly->GetAnchorFrame() ?
                                    pFly->AnchorFrame()->FindPageFrame() : nullptr;
                        if ( pAnchPage && (pAnchPage != this) )
                        {
                            MoveFly( pFly, pAnchPage );
                            pFly->InvalidateSize();
                            pFly->InvalidatePos_();
                            // Do not increment index, in this case
                            continue;
                        }
                    }
                    ++i;
                }
            }
            // cleanup Window
            if ( pSh && pSh->GetWin() )
                pSh->InvalidateWindows( getFrameArea() );
        }

        // decrease the root's page number
        static_cast<SwRootFrame*>(GetUpper())->DecrPhyPageNums();
        SwPageFrame *pPg = static_cast<SwPageFrame*>(GetNext());
        if ( pPg )
        {
            while ( pPg )
            {
                --pPg->m_nPhyPageNum;
                pPg = static_cast<SwPageFrame*>(pPg->GetNext());
            }
        }
        else
            ::SetLastPage( static_cast<SwPageFrame*>(GetPrev()) );

        SwFrame* pRootFrame = GetUpper();

        // cut all connections
        RemoveFromLayout();

        if ( pRootFrame )
            static_cast<SwRootFrame*>(pRootFrame)->CheckViewLayout( nullptr, nullptr );
    }

    void SwPageFrame::Paste( SwFrame* pParent, SwFrame* pSibling )
    {
        OSL_ENSURE( pParent->IsRootFrame(), "Parent is no Root." );
        OSL_ENSURE( pParent, "No parent for Paste()." );
        OSL_ENSURE( pParent != this, "I'm my own parent." );
        OSL_ENSURE( pSibling != this, "I'm my own neighbour." );
        OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
                "I am still registered somewhere." );

        // insert into tree structure
        InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );

        // increase the root's page number
        static_cast<SwRootFrame*>(GetUpper())->IncrPhyPageNums();
        if( GetPrev() )
            SetPhyPageNum( static_cast<SwPageFrame*>(GetPrev())->GetPhyPageNum() + 1 );
        else
            SetPhyPageNum( 1 );
        SwPageFrame *pPg = static_cast<SwPageFrame*>(GetNext());
        if ( pPg )
        {
            while ( pPg )
            {
                ++pPg->m_nPhyPageNum;
                pPg->InvalidatePos_();
                pPg->InvalidateLayout();
                pPg = static_cast<SwPageFrame*>(pPg->GetNext());
            }
        }
        else
            ::SetLastPage( this );

        if( getFrameArea().Width() != pParent->getFramePrintArea().Width() )
            InvalidateSize_();

        InvalidatePos();

        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( pSh )
            pSh->SetFirstVisPageInvalid();

        getRootFrame()->CheckViewLayout( nullptr, nullptr );
    }

    static void lcl_PrepFlyInCntRegister( SwContentFrame *pFrame )
    {
        pFrame->Prepare( PREP_REGISTER );
        if( pFrame->GetDrawObjs() )
        {
            for(SwAnchoredObject* pAnchoredObj : *pFrame->GetDrawObjs())
            {
                // #i28701#
                if ( dynamic_cast< const SwFlyInContentFrame *>( pAnchoredObj ) !=  nullptr )
                {
                    SwFlyFrame* pFly = static_cast<SwFlyInContentFrame*>(pAnchoredObj);
                    SwContentFrame *pCnt = pFly->ContainsContent();
                    while ( pCnt )
                    {
                        lcl_PrepFlyInCntRegister( pCnt );
                        pCnt = pCnt->GetNextContentFrame();
                    }
                }
            }
        }
    }

    void SwPageFrame::PrepareRegisterChg()
    {
        SwContentFrame *pFrame = FindFirstBodyContent();
        while( pFrame )
        {
            lcl_PrepFlyInCntRegister( pFrame );
            pFrame = pFrame->GetNextContentFrame();
            if( !IsAnLower( pFrame ) )
                break;
        }
        if( GetSortedObjs() )
        {
            for(SwAnchoredObject* pAnchoredObj : *GetSortedObjs())
            {
                // #i28701#
                if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) !=  nullptr )
                {
                    SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
                    pFrame = pFly->ContainsContent();
                    while ( pFrame )
                    {
                        ::lcl_PrepFlyInCntRegister( pFrame );
                        pFrame = pFrame->GetNextContentFrame();
                    }
                }
            }
        }
    }

    //FIXME: provide missing documentation
    /** Check all pages (starting from the given one) if they use the right frame format.
     *
     * If "wrong" pages are found, try to fix this as simple as possible.
     *
     * @param pStart        the page from where to start searching
     * @param bNotifyFields
     * @param ppPrev
     */
    void SwFrame::CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields, SwPageFrame** ppPrev )
    {
        SAL_INFO( "sw.pageframe", "(CheckPageDescs in phy: " << pStart->GetPhyPageNum() );
        assert(pStart && "no starting page.");

        SwViewShell *pSh   = pStart->getRootFrame()->GetCurrShell();
        SwViewShellImp *pImp  = pSh ? pSh->Imp() : nullptr;

        if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
        {
            pImp->GetLayAction().SetCheckPageNum( pStart->GetPhyPageNum() );
            SAL_INFO( "sw.pageframe", "CheckPageDescs out fast - via SetCheckPageNum: "
                      << pStart->GetPhyPageNum() << ")" );
            return;
        }

        // For the update of page numbering fields, nDocPos provides
        // the page position from where invalidation should start.
        SwTwips nDocPos  = LONG_MAX;

        SwRootFrame *pRoot = static_cast<SwRootFrame*>(pStart->GetUpper());
        SwDoc* pDoc      = pStart->GetFormat()->GetDoc();
        const bool bFootnotes = !pDoc->GetFootnoteIdxs().empty();

        SwPageFrame *pPage = pStart;
        if( pPage->GetPrev() && static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage() )
            pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
        while ( pPage )
        {
            SwPageFrame *pPrevPage = static_cast<SwPageFrame*>(pPage->GetPrev());
            SwPageFrame *pNextPage = static_cast<SwPageFrame*>(pPage->GetNext());

            SwPageDesc *pDesc = pPage->FindPageDesc();
            bool bIsEmpty = pPage->IsEmptyPage();
            bool bIsOdd = pPage->OnRightPage();
            bool bWantOdd = pPage->WannaRightPage();
            bool bFirst = pPage->OnFirstPage();
            SwFrameFormat *pFormatWish = bWantOdd
                ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst);

            if ( bIsOdd != bWantOdd ||
                 pDesc != pPage->GetPageDesc() ||        // wrong Desc
                 ( pFormatWish != pPage->GetFormat() &&       // wrong format and
                   ( !bIsEmpty || pFormatWish ) // not blank /empty
                 )
               )
            {
                // Updating a page might take a while, so check the WaitCursor
                if( pImp )
                    pImp->CheckWaitCursor();

                // invalidate the field, starting from here
                if ( nDocPos == LONG_MAX )
                    nDocPos = pPrevPage ? pPrevPage->getFrameArea().Top() : pPage->getFrameArea().Top();

                // Cases:
                //  1. Empty page should be "normal" page -> remove empty page and take next one
                //  2. Empty page should have different descriptor -> change
                //  3. Normal page should be empty -> insert empty page if previous page
                //     is not empty, otherwise see (6).
                //  4. Normal page should have different descriptor -> change
                //  5. Normal page should have different format -> change
                //  6. No "wish" format provided -> take the "other" format (left/right) of the PageDesc

                if ( bIsEmpty && ( pFormatWish ||          //1.
                     ( !bWantOdd && !pPrevPage ) ) )
                {
                    // Check all cases for the next page, so we don't oscillate empty pages
                    // Skip case 1 and 2, as we require a non-empty next page to save the empty page
                    // Case 3 is the one we actually want to predict and skip
                    // We can skip the empty check of case 3, as we just work on an existing next page
                    bool bNextWantOdd;
                    SwPageDesc *pNextDesc;
                    if ( pNextPage && !pNextPage->IsEmptyPage() &&    //3.
                         pNextPage->OnRightPage() == (bNextWantOdd = pNextPage->WannaRightPage()) &&
                         pNextPage->GetPageDesc() == (pNextDesc = pNextPage->FindPageDesc()) )   //4.
                    {
                        bool bNextFirst = pNextPage->OnFirstPage();
                        SwFrameFormat *pNextFormatWish = bNextWantOdd ?   //5.
                            pNextDesc->GetRightFormat(bNextFirst) : pNextDesc->GetLeftFormat(bNextFirst);
                        if ( !pNextFormatWish )    // 6.
                            pNextFormatWish = bNextWantOdd ? pNextDesc->GetLeftFormat() : pNextDesc->GetRightFormat();
                        if ( pNextFormatWish && pNextPage->GetFormat() == pNextFormatWish )
                        {
                            SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                                      << " c: 1+3 - skip next page of p: " << pPage );
                            if (pPrevPage && pPage->GetPageDesc() != pPrevPage->GetPageDesc())
                                pPage->SetPageDesc( pPrevPage->GetPageDesc(), nullptr );
                            // We can skip the next page, as all checks were already done!
                            pPage = static_cast<SwPageFrame*>(pNextPage->GetNext());
                            continue;
                        }
                    }

                    pPage->Cut();
                    bool bUpdatePrev = false;
                    if (ppPrev && *ppPrev == pPage)
                        bUpdatePrev = true;
                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                              << " c: 1 - destroy p: " << pPage );
                    SwFrame::DestroyFrame(pPage);
                    if ( pStart == pPage )
                        pStart = pNextPage;
                    pPage = pNextPage;
                    if (bUpdatePrev)
                        *ppPrev = pNextPage;
                    continue;
                }
                else if ( bIsEmpty && !pFormatWish &&  //2.
                          pDesc != pPage->GetPageDesc() )
                {
                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                              << " c: 2 - set desc p: " << pPage << " d: " << pDesc );
                    pPage->SetPageDesc( pDesc, nullptr );
                }
                else if ( !bIsEmpty &&      //3.
                          bIsOdd != bWantOdd &&
                          ( ( !pPrevPage && !bWantOdd ) ||
                            ( pPrevPage && !pPrevPage->IsEmptyPage() )
                          )
                        )
                {
                    if ( pPrevPage )
                        pDesc = pPrevPage->GetPageDesc();
                    SwPageFrame *pTmp = new SwPageFrame( pDoc->GetEmptyPageFormat(), pRoot, pDesc );
                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                              << " c: 3 - insert empty p: " << pTmp << " d: " << pDesc );
                    pTmp->Paste( pRoot, pPage );
                    pTmp->PreparePage( false );
                    pPage = pTmp;
                }
                else if ( pPage->GetPageDesc() != pDesc )           //4.
                {
                    SwPageDesc *pOld = pPage->GetPageDesc();
                    pPage->SetPageDesc( pDesc, pFormatWish );
                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                              << " c: 4 - set desc + format p: " << pPage
                              << " d: " << pDesc << " f: " << pFormatWish );
                    if ( bFootnotes )
                    {
                        // If specific values of the FootnoteInfo are changed, something has to happen.
                        // We try to limit the damage...
                        // If the page has no FootnoteCont it might be problematic.
                        // Let's hope that invalidation is enough.
                        SwFootnoteContFrame *pCont = pPage->FindFootnoteCont();
                        if ( pCont && !(pOld->GetFootnoteInfo() == pDesc->GetFootnoteInfo()) )
                            pCont->InvalidateAll_();
                    }
                }
                else if ( pFormatWish && pPage->GetFormat() != pFormatWish )         //5.
                {
                    pPage->SetFrameFormat( pFormatWish );
                    SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                              << " c: 5 - set format p: " << pPage << " f: " << pFormatWish );
                }
                else if ( !pFormatWish )                                       //6.
                {
                    // get format with inverted logic
                    pFormatWish = bWantOdd ? pDesc->GetLeftFormat() : pDesc->GetRightFormat();
                    if ( pFormatWish && pPage->GetFormat() != pFormatWish )
                    {
                        pPage->SetFrameFormat( pFormatWish );
                        SAL_INFO( "sw.pageframe", "CheckPageDescs phys: " << pPage->GetPhyPageNum()
                                  << " c: 6 - set format p: " << pPage << " f: " << pFormatWish );
                    }
                }
    #if OSL_DEBUG_LEVEL > 0
                else
                {
                    OSL_FAIL( "CheckPageDescs, missing solution" );
                }
    #endif
            }
            if ( bIsEmpty )
            {
                // It also might be that an empty page is not needed at all.
                // However, the algorithm above cannot determine that. It is not needed if the following
                // page can live without it. Do obtain that information, we need to dig deeper...
                SwPageFrame *pPg = static_cast<SwPageFrame*>(pPage->GetNext());
                if( !pPg || pPage->OnRightPage() == pPg->WannaRightPage() )
                {
                    // The following page can find a FrameFormat or has no successor -> empty page not needed
                    SwPageFrame *pTmp = static_cast<SwPageFrame*>(pPage->GetNext());
                    pPage->Cut();
                    bool bUpdatePrev = false;
                    if (ppPrev && *ppPrev == pPage)
                        bUpdatePrev = true;
                    SwFrame::DestroyFrame(pPage);
                    SAL_INFO( "sw.pageframe", "CheckPageDescs - handle bIsEmpty - destroy p: " << pPage );
                    if ( pStart == pPage )
                        pStart = pTmp;
                    pPage = pTmp;
                    if (bUpdatePrev)
                        *ppPrev = pTmp;
                    continue;
                }
            }
            pPage = static_cast<SwPageFrame*>(pPage->GetNext());
        }

        pRoot->SetAssertFlyPages();
        SwRootFrame::AssertPageFlys( pStart );

        if ( bNotifyFields && (!pImp || !pImp->IsUpdateExpFields()) )
        {
            SwDocPosUpdate aMsgHint( nDocPos );
            pDoc->getIDocumentFieldsAccess().UpdatePageFields( &aMsgHint );
        }

    #if OSL_DEBUG_LEVEL > 0
        //1. check if two empty pages are behind one another
        bool bEmpty = false;
        SwPageFrame *pPg = pStart;
        while ( pPg )
        {
            if ( pPg->IsEmptyPage() )
            {
                if ( bEmpty )
                {
                    OSL_FAIL( "double empty pages." );
                    break;  // once is enough
                }
                bEmpty = true;
            }
            else
                bEmpty = false;

            pPg = static_cast<SwPageFrame*>(pPg->GetNext());
        }
    #endif
        SAL_INFO( "sw.pageframe", "CheckPageDescs out)" );
    }

    namespace
    {
        bool isDeleteForbidden(const SwPageFrame *pDel)
        {
            if (pDel->IsDeleteForbidden())
                return true;
            const SwLayoutFrame* pBody = pDel->FindBodyCont();
            const SwFrame* pBodyContent = pBody ? pBody->Lower() : nullptr;
            return pBodyContent && pBodyContent->IsDeleteForbidden();
        }

        bool doInsertPage( SwRootFrame *pRoot, SwPageFrame **pRefSibling,
                           SwFrameFormat *pFormat, SwPageDesc *pDesc,
                           bool bFootnote, SwPageFrame **pRefPage )
        {
            SwPageFrame *pPage = new SwPageFrame(pFormat, pRoot, pDesc);
            SwPageFrame *pSibling = *pRefSibling;
            if ( pRefPage )
            {
                *pRefPage = pPage;
                SAL_INFO( "sw.pageframe", "doInsertPage p: " << pPage
                                          << " d: " << pDesc << " f: " << pFormat );
            }
            else
                SAL_INFO( "sw.pageframe", "doInsertPage - insert empty p: "
                                          << pPage << " d: " << pDesc );
            pPage->Paste( pRoot, pSibling );
            pPage->PreparePage( bFootnote );
            // If the sibling has no body text, destroy it as long as it is no footnote page.
            if ( pSibling && !pSibling->IsFootnotePage() &&
                 !pSibling->FindFirstBodyContent() &&
                 (!pRefPage || !isDeleteForbidden(pSibling)) )
            {
                pRoot->RemovePage( pRefSibling, SwRemoveResult::Next ) ;
                return false;
            }
            return true;
        }
    }

    SwPageFrame *SwFrame::InsertPage( SwPageFrame *pPrevPage, bool bFootnote )
    {
        SwRootFrame *pRoot = static_cast<SwRootFrame*>(pPrevPage->GetUpper());
        SwPageFrame *pSibling = static_cast<SwPageFrame*>(pPrevPage->GetNext());
        SwPageDesc *pDesc = nullptr;

        // insert right (odd) or left (even) page?
        bool bNextOdd = !pPrevPage->OnRightPage();
        bool bWishedOdd = bNextOdd;

        // Which PageDesc is relevant?
        // For ContentFrame take the one from format if provided,
        // otherwise from the Follow of the PrevPage
        if ( IsFlowFrame() && !SwFlowFrame::CastFlowFrame( this )->IsFollow() )
        {
            SwFormatPageDesc &rDesc = const_cast<SwFormatPageDesc&>(GetPageDescItem());
            pDesc = rDesc.GetPageDesc();
            if ( rDesc.GetNumOffset() )
            {
                ::boost::optional<sal_uInt16> oNumOffset = rDesc.GetNumOffset();
                bWishedOdd = oNumOffset && (oNumOffset.get() % 2) != 0;
                // use the opportunity to set the flag at root
                pRoot->SetVirtPageNum( true );
            }
        }
        if ( !pDesc )
            pDesc = pPrevPage->GetPageDesc()->GetFollow();

        assert(pDesc && "Missing PageDesc");
        if( !(bWishedOdd ? pDesc->GetRightFormat() : pDesc->GetLeftFormat()) )
            bWishedOdd = !bWishedOdd;
        bool const bWishedFirst = pDesc != pPrevPage->GetPageDesc();

        SwDoc *pDoc = pPrevPage->GetFormat()->GetDoc();
        bool bCheckPages = false;
        // If there is no FrameFormat for this page, create an empty page.
        if( bWishedOdd != bNextOdd )
        {
            if( doInsertPage( pRoot, &pSibling, pDoc->GetEmptyPageFormat(),
                              pPrevPage->GetPageDesc(), bFootnote, nullptr ) )
                bCheckPages = true;
        }
        SwFrameFormat *const pFormat( bWishedOdd
                ? pDesc->GetRightFormat(bWishedFirst)
                : pDesc->GetLeftFormat(bWishedFirst) );
        assert(pFormat);
        SwPageFrame *pPage = nullptr;
        if( doInsertPage( pRoot, &pSibling, pFormat, pDesc, bFootnote, &pPage ) )
            bCheckPages = true;

        if ( pSibling )
        {
            if ( bCheckPages )
            {
                CheckPageDescs( pSibling, false );
                SwViewShell *pSh = getRootFrame()->GetCurrShell();
                SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr;
                if ( pImp && pImp->IsAction() && !pImp->GetLayAction().IsCheckPages() )
                {
                    const sal_uInt16 nNum = pImp->GetLayAction().GetCheckPageNum();
                    if ( nNum == pPrevPage->GetPhyPageNum() + 1 )
                    {
                        pImp->GetLayAction().SetCheckPageNumDirect(
                                                        pSibling->GetPhyPageNum() );
                        SAL_INFO( "sw.pageframe", "InsertPage - SetCheckPageNumDirect: "
                                  << pSibling->GetPhyPageNum() );
                    }
                    return pPage;
                }
            }
            else
                SwRootFrame::AssertPageFlys( pSibling );
        }

        // For the update of page numbering fields, nDocPos provides
        // the page position from where invalidation should start.
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( !pSh || !pSh->Imp()->IsUpdateExpFields() )
        {
            SwDocPosUpdate aMsgHint( pPrevPage->getFrameArea().Top() );
            pDoc->getIDocumentFieldsAccess().UpdatePageFields( &aMsgHint );
        }
        return pPage;
    }

    sw::sidebarwindows::SidebarPosition SwPageFrame::SidebarPosition() const
    {
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if( !pSh || pSh->GetViewOptions()->getBrowseMode() )
        {
            return sw::sidebarwindows::SidebarPosition::RIGHT;
        }
        else
        {
            const bool bLTR = getRootFrame()->IsLeftToRightViewLayout();
            const bool bBookMode = pSh->GetViewOptions()->IsViewLayoutBookMode();
            const bool bRightSidebar = bLTR ? (!bBookMode || OnRightPage()) : (bBookMode && !OnRightPage());

            return bRightSidebar
                   ? sw::sidebarwindows::SidebarPosition::RIGHT
                   : sw::sidebarwindows::SidebarPosition::LEFT;
        }
    }

    SwTwips SwRootFrame::GrowFrame( SwTwips nDist, bool bTst, bool )
    {
        if ( !bTst )
        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.SSize().AdjustHeight(nDist );
        }

        return nDist;
    }

    SwTwips SwRootFrame::ShrinkFrame( SwTwips nDist, bool bTst, bool )
    {
        OSL_ENSURE( nDist >= 0, "nDist < 0." );
        OSL_ENSURE( nDist <= getFrameArea().Height(), "nDist greater than current size." );

        if ( !bTst )
        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.SSize().AdjustHeight( -nDist );
        }

        return nDist;
    }

    void SwRootFrame::RemovePage( SwPageFrame **pDelRef, SwRemoveResult eResult )
    {
        SwPageFrame *pDel = *pDelRef;
        (*pDelRef) = static_cast<SwPageFrame*>(
            eResult == SwRemoveResult::Next ? pDel->GetNext() : pDel->GetPrev() );
        if ( !GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
            RemoveFootnotes( pDel, true );
        pDel->Cut();
        SwFrame::DestroyFrame( pDel );
    }

    /// remove pages that are not needed at all
    void SwRootFrame::RemoveSuperfluous()
    {
        // A page is empty if the body text area has no ContentFrame, but not if there
        // is at least one Fly or one footnote attached to the page. Two runs are
        // needed: one for endnote pages and one for the pages of the body text.

        if ( !IsSuperfluous() )
            return;
        mbCheckSuperfluous = false;

        SwPageFrame *pPage = GetLastPage();
        long nDocPos = LONG_MAX;

        // Check the corresponding last page if it is empty and stop loop at the last non-empty page.
        do
        {
            bool bExistEssentialObjs = ( nullptr != pPage->GetSortedObjs() );
            if ( bExistEssentialObjs )
            {
                // Only because the page has Flys does not mean that it is needed. If all Flys are
                // attached to generic content it is also superfluous (checking DocBody should be enough)
                // OD 19.06.2003 #108784# - consider that drawing objects in
                // header/footer are supported now.
                bool bOnlySuperfluosObjs = true;
                SwSortedObjs &rObjs = *pPage->GetSortedObjs();
                for ( size_t i = 0; bOnlySuperfluosObjs && i < rObjs.size(); ++i )
                {
                    // #i28701#
                    SwAnchoredObject* pAnchoredObj = rObjs[i];
                    // OD 2004-01-19 #110582# - do not consider hidden objects
                    if ( pPage->GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId(
                                        pAnchoredObj->GetDrawObj()->GetLayer() ) &&
                         !pAnchoredObj->GetAnchorFrame()->FindFooterOrHeader() )
                    {
                        bOnlySuperfluosObjs = false;
                    }
                }
                bExistEssentialObjs = !bOnlySuperfluosObjs;
            }

            // OD 19.06.2003 #108784# - optimization: check first, if essential objects
            // exists.
            const SwLayoutFrame* pBody = nullptr;
            if ( bExistEssentialObjs ||
                 pPage->FindFootnoteCont() ||
                 ( nullptr != ( pBody = pPage->FindBodyCont() ) &&
                    ( pBody->ContainsContent() ||
                        // #i47580#
                        // Do not delete page if there's an empty tabframe
                        // left. I think it might be correct to use ContainsAny()
                        // instead of ContainsContent() to cover the empty-table-case,
                        // but I'm not fully sure, since ContainsAny() also returns
                        // SectionFrames. Therefore I prefer to do it the safe way:
                      ( pBody->Lower() && pBody->Lower()->IsTabFrame() ) ) ) )
            {
                if ( pPage->IsFootnotePage() )
                {
                    while ( pPage->IsFootnotePage() )
                    {
                        pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
                        OSL_ENSURE( pPage, "only endnote pages remain." );
                    }
                    continue;
                }
                else
                    pPage = nullptr;
            }

            if ( pPage )
            {
                SAL_INFO( "sw.pageframe", "RemoveSuperfluous - DestroyFrm p: " << pPage );
                RemovePage( &pPage, SwRemoveResult::Prev );
                nDocPos = pPage ? pPage->getFrameArea().Top() : 0;
            }
        } while ( pPage );

        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        if ( nDocPos != LONG_MAX &&
             (!pSh || !pSh->Imp()->IsUpdateExpFields()) )
        {
            SwDocPosUpdate aMsgHint( nDocPos );
            GetFormat()->GetDoc()->getIDocumentFieldsAccess().UpdatePageFields( &aMsgHint );
        }
    }

    /// Ensures that enough pages exist, so that all page bound frames and draw objects can be placed
    void SwRootFrame::AssertFlyPages()
    {
        if ( !IsAssertFlyPages() )
            return;
        mbAssertFlyPages = false;

        SwDoc *pDoc = GetFormat()->GetDoc();
        const SwFrameFormats *pTable = pDoc->GetSpzFrameFormats();

        // what page targets the "last" Fly?
        // note the needed pages in a set
        sal_uInt16 nMaxPg(0);
        std::set< sal_uInt16 > neededPages;

        for ( size_t i = 0; i < pTable->size(); ++i )
        {
            const SwFormatAnchor &rAnch = (*pTable)[i]->GetAnchor();
            if(!rAnch.GetContentAnchor())
            {
                const sal_uInt16 nPageNum(rAnch.GetPageNum());

                // calc MaxPage (as before)
                nMaxPg = std::max(nMaxPg, nPageNum);

                // note as needed page
                neededPages.insert(nPageNum);
            }
        }

        // How many pages exist at the moment?
        // And are there EmptyPages that are needed?
        SwPageFrame* pPage(static_cast<SwPageFrame*>(Lower()));
        SwPageFrame* pPrevPage(nullptr);
        SwPageFrame* pFirstRevivedEmptyPage(nullptr);

        while(pPage) // moved two while-conditions to break-statements (see below)
        {
            const sal_uInt16 nPageNum(pPage->GetPhyPageNum());

            if(pPage->IsEmptyPage() &&
                nullptr != pPrevPage &&
                neededPages.find(nPageNum) != neededPages.end())
            {
                // This is an empty page, but it *is* needed since a SwFrame
                // is anchored at it directly. Initially these SwFrames are
                // not fully initialized. Need to change the format of this SwFrame
                // and let the ::Notify mechanism newly evaluate
                // m_bEmptyPage (see SwPageFrame::UpdateAttr_). Code is taken and
                // adapted from ::InsertPage (used below), this needs previous page
                bool bWishedOdd(!pPrevPage->OnRightPage());
                SwPageDesc* pDesc(pPrevPage->GetPageDesc()->GetFollow());
                assert(pDesc && "Missing PageDesc");

                if(!(bWishedOdd ? pDesc->GetRightFormat() : pDesc->GetLeftFormat()))
                {
                    bWishedOdd = !bWishedOdd;
                }

                bool const bWishedFirst(pDesc != pPrevPage->GetPageDesc());
                SwFrameFormat* pFormat(bWishedOdd ? pDesc->GetRightFormat(bWishedFirst) : pDesc->GetLeftFormat(bWishedFirst));

                // set SwFrameFormat, this will trigger SwPageFrame::UpdateAttr_ and re-evaluate
                // m_bEmptyPage, too
                pPage->SetFrameFormat(pFormat);

                if(nullptr == pFirstRevivedEmptyPage)
                {
                    // remember first (lowest) SwPageFrame which needed correction
                    pFirstRevivedEmptyPage = pPage;
                }
            }

            // original while-condition II
            if(nullptr == pPage->GetNext())
            {
                break;
            }

            // original while-condition III
            if(static_cast< SwPageFrame* >(pPage->GetNext())->IsFootnotePage())
            {
                break;
            }

            pPrevPage = pPage;
            pPage = static_cast<SwPageFrame*>(pPage->GetNext());
        }

        if ( nMaxPg > pPage->GetPhyPageNum() )
        {
            for ( sal_uInt16 i = pPage->GetPhyPageNum(); i < nMaxPg; ++i )
                pPage = InsertPage( pPage, false );

            // If the endnote pages are now corrupt, destroy them.
            if ( !pDoc->GetFootnoteIdxs().empty() )
            {
                pPage = static_cast<SwPageFrame*>(Lower());
                while ( pPage && !pPage->IsFootnotePage() )
                    pPage = static_cast<SwPageFrame*>(pPage->GetNext());

                if ( pPage )
                {
                    SwPageDesc *pTmpDesc = pPage->FindPageDesc();
                    bool bOdd = pPage->OnRightPage();
                    if ( pPage->GetFormat() !=
                         (bOdd ? pTmpDesc->GetRightFormat() : pTmpDesc->GetLeftFormat()) )
                        RemoveFootnotes( pPage, false, true );
                }
            }
        }

        // if we corrected SwFrameFormat and changed one (or more) m_bEmptyPage
        // flags, we need to correct evtl. currently wrong positioned SwFrame(s)
        // which did think until now that these Page(s) are empty.
        // After trying to correct myself I found SwRootFrame::AssertPageFlys
        // directly below that already does that, so use it.
        if(nullptr != pFirstRevivedEmptyPage)
        {
            AssertPageFlys(pFirstRevivedEmptyPage);
        }

    #if OSL_DEBUG_LEVEL > 0
        pPage = static_cast<SwPageFrame*>(Lower());
        while ( pPage && pPage->GetNext() &&
                !static_cast<SwPageFrame*>(pPage->GetNext())->IsFootnotePage() )
        {
            SAL_INFO( "sw.pageframe",  "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc()
                       << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum()
                       << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() );
            pPage = static_cast<SwPageFrame*>(pPage->GetNext());
        }
        SAL_INFO( "sw.pageframe", "AssertFlyPages p: " << pPage << " d: " << pPage->GetPageDesc()
                  << " f: " << pPage->GetFormat() << " virt: " << pPage->GetVirtPageNum()
                  << " phys: " << pPage->GetPhyPageNum() << " empty: " << pPage->IsEmptyPage() );
    #endif
    }

    /// Ensure that after the given page all page-bound objects are located on the correct page
    void SwRootFrame::AssertPageFlys( SwPageFrame *pPage )
    {
        SAL_INFO( "sw.pageframe", "(AssertPageFlys in" );
        while ( pPage )
        {
            if (pPage->GetSortedObjs())
            {
                size_t i = 0;
                while ( pPage->GetSortedObjs() && i< pPage->GetSortedObjs()->size() )
                {
                    // #i28701#
                    SwFrameFormat& rFormat = (*pPage->GetSortedObjs())[i]->GetFrameFormat();
                    const SwFormatAnchor &rAnch = rFormat.GetAnchor();
                    const sal_uInt16 nPg = rAnch.GetPageNum();
                    if ((rAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE) &&
                         nPg != pPage->GetPhyPageNum() )
                    {
                        SAL_INFO( "sw.pageframe", nPg << " " << pPage->GetPhyPageNum() );
                        // If on the wrong page, check if previous page is empty
                        if( nPg && !(pPage->GetPhyPageNum()-1 == nPg &&
                            static_cast<SwPageFrame*>(pPage->GetPrev())->IsEmptyPage()) )
                        {
                            // It can move by itself. Just send a modify to its anchor attribute.
    #if OSL_DEBUG_LEVEL > 1
                            const size_t nCnt = pPage->GetSortedObjs()->size();
                            rFormat.NotifyClients( nullptr, &rAnch );
                            OSL_ENSURE( !pPage->GetSortedObjs() ||
                                    nCnt != pPage->GetSortedObjs()->size(),
                                    "Object couldn't be reattached!" );
    #else
                            rFormat.NotifyClients( nullptr, &rAnch );
    #endif
                            // Do not increment index, in this case
                            continue;
                        }
                    }
                    ++i;
                }
            }
            pPage = static_cast<SwPageFrame*>(pPage->GetNext());
        }
        SAL_INFO( "sw.pageframe", "AssertPageFlys out)" );
    }

    Size SwRootFrame::ChgSize( const Size& aNewSize )
    {
        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.SSize() = aNewSize;
        }

        InvalidatePrt_();
        mbFixSize = false;
        return getFrameArea().SSize();
    }

    void SwRootFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
    {
        if ( !isFrameAreaPositionValid() )
        {
            setFrameAreaPositionValid(true);
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.Pos().setX(DOCUMENTBORDER);
            aFrm.Pos().setY(DOCUMENTBORDER);
        }

        if ( !isFramePrintAreaValid() )
        {
            setFramePrintAreaValid(true);
            SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
            aPrt.Pos().setX(0);
            aPrt.Pos().setY(0);
            aPrt.SSize( getFrameArea().SSize() );
        }

        if ( !isFrameAreaSizeValid() )
        {
            // SSize is set by the pages (Cut/Paste).
            setFrameAreaSizeValid(true);
        }
    }

    void SwRootFrame::ImplInvalidateBrowseWidth()
    {
        mbBrowseWidthValid = false;
        SwFrame *pPg = Lower();
        while ( pPg )
        {
            pPg->InvalidateSize();
            pPg = pPg->GetNext();
        }
    }

    void SwRootFrame::ImplCalcBrowseWidth()
    {
        OSL_ENSURE( GetCurrShell() && GetCurrShell()->GetViewOptions()->getBrowseMode(),
                "CalcBrowseWidth and not in BrowseView" );

        // The (minimal) with is determined from borders, tables and paint objects.
        // It is calculated based on the attributes. Thus, it is not relevant how wide they are
        // currently but only how wide they want to be.
        // Frames and paint objects inside other objects (frames, tables) do not count.
        // Borders and columns are not taken into account.

        SwFrame *pFrame = ContainsContent();
        while ( pFrame && !pFrame->IsInDocBody() )
            pFrame = static_cast<SwContentFrame*>(pFrame)->GetNextContentFrame();
        if ( !pFrame )
            return;

        mbBrowseWidthValid = true;
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        mnBrowseWidth = (!comphelper::LibreOfficeKit::isActive() && pSh)? MINLAY + 2 * pSh->GetOut()-> PixelToLogic( pSh->GetBrowseBorder() ).Width(): MIN_BROWSE_WIDTH;

        do
        {
            if ( pFrame->IsInTab() )
                pFrame = pFrame->FindTabFrame();

            if ( pFrame->IsTabFrame() &&
                 !static_cast<SwLayoutFrame*>(pFrame)->GetFormat()->GetFrameSize().GetWidthPercent() )
            {
                SwBorderAttrAccess aAccess( SwFrame::GetCache(), pFrame );
                const SwBorderAttrs &rAttrs = *aAccess.Get();
                const SwFormatHoriOrient &rHori = rAttrs.GetAttrSet().GetHoriOrient();
                long nWidth = rAttrs.GetSize().Width();
                if ( nWidth < int(USHRT_MAX)-2000 && //-2k, because USHRT_MAX gets missing while trying to resize!  (and cast to int to avoid -Wsign-compare due to broken USHRT_MAX on Android)
                     text::HoriOrientation::FULL != rHori.GetHoriOrient() )
                {
                    const SwHTMLTableLayout *pLayoutInfo =
                        static_cast<const SwTabFrame *>(pFrame)->GetTable()
                                                ->GetHTMLTableLayout();
                    if ( pLayoutInfo )
                        nWidth = std::min( nWidth, pLayoutInfo->GetBrowseWidthMin() );

                    switch ( rHori.GetHoriOrient() )
                    {
                        case text::HoriOrientation::NONE:
                            // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
                            nWidth += rAttrs.CalcLeft( pFrame ) + rAttrs.CalcRight( pFrame );
                            break;
                        case text::HoriOrientation::LEFT_AND_WIDTH:
                            nWidth += rAttrs.CalcLeft( pFrame );
                            break;
                        default:
                            break;
                    }
                    mnBrowseWidth = std::max( mnBrowseWidth, nWidth );
                }
            }
            else if ( pFrame->GetDrawObjs() )
            {
                for ( size_t i = 0; i < pFrame->GetDrawObjs()->size(); ++i )
                {
                    // #i28701#
                    SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[i];
                    const SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
                    const bool bFly = dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) !=  nullptr;
                    if ((bFly && (FAR_AWAY == pAnchoredObj->GetObjRect().Width()))
                        || rFormat.GetFrameSize().GetWidthPercent())
                    {
                        continue;
                    }

                    long nWidth = 0;
                    switch ( rFormat.GetAnchor().GetAnchorId() )
                    {
                        case RndStdIds::FLY_AS_CHAR:
                            nWidth = bFly ? rFormat.GetFrameSize().GetWidth() :
                                            pAnchoredObj->GetObjRect().Width();
                            break;
                        case RndStdIds::FLY_AT_PARA:
                            {
                                // #i33170#
                                // Reactivated old code because
                                // nWidth = pAnchoredObj->GetObjRect().Right()
                                // gives wrong results for objects that are still
                                // at position FAR_AWAY.
                                if ( bFly )
                                {
                                    nWidth = rFormat.GetFrameSize().GetWidth();
                                    const SwFormatHoriOrient &rHori = rFormat.GetHoriOrient();
                                    switch ( rHori.GetHoriOrient() )
                                    {
                                        case text::HoriOrientation::NONE:
                                            nWidth += rHori.GetPos();
                                            break;
                                        case text::HoriOrientation::INSIDE:
                                        case text::HoriOrientation::LEFT:
                                            if ( text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() )
                                                nWidth += pFrame->getFramePrintArea().Left();
                                            break;
                                        default:
                                            break;
                                    }
                                }
                                else
                                    // Paint objects to not have attributes and
                                    // are defined by their current size
                                    nWidth = pAnchoredObj->GetObjRect().Right() -
                                             pAnchoredObj->GetDrawObj()->GetAnchorPos().X();
                            }
                            break;
                        default:    /* do nothing */;
                    }
                    mnBrowseWidth = std::max( mnBrowseWidth, nWidth );
                }
            }
            pFrame = pFrame->FindNextCnt();
        } while ( pFrame );
    }

    void SwRootFrame::StartAllAction()
    {
        if ( GetCurrShell() )
            for(SwViewShell& rSh : GetCurrShell()->GetRingContainer())
            {
                if ( dynamic_cast<const SwCursorShell*>( &rSh) !=  nullptr )
                    static_cast<SwCursorShell*>(&rSh)->StartAction();
                else
                    rSh.StartAction();
            }
    }

    void SwRootFrame::EndAllAction( bool bVirDev )
    {
        if ( GetCurrShell() )
            for(SwViewShell& rSh : GetCurrShell()->GetRingContainer())
            {
                const bool bOldEndActionByVirDev = rSh.IsEndActionByVirDev();
                rSh.SetEndActionByVirDev( bVirDev );
                if ( dynamic_cast<const SwCursorShell*>( &rSh) !=  nullptr )
                {
                    static_cast<SwCursorShell*>(&rSh)->EndAction();
                    static_cast<SwCursorShell*>(&rSh)->CallChgLnk();
                    if ( dynamic_cast<const SwFEShell*>( &rSh) !=  nullptr )
                        static_cast<SwFEShell*>(&rSh)->SetChainMarker();
                }
                else
                    rSh.EndAction();
                rSh.SetEndActionByVirDev( bOldEndActionByVirDev );
            }
    }

    void SwRootFrame::UnoRemoveAllActions()
    {
        if ( GetCurrShell() )
            for(SwViewShell& rSh : GetCurrShell()->GetRingContainer())
            {
                // #i84729#
                // No end action, if <SwViewShell> instance is currently in its end action.
                // Recursives calls to <::EndAction()> are not allowed.
                if ( !rSh.IsInEndAction() )
                {
                    OSL_ENSURE(!rSh.GetRestoreActions(), "Restore action count is already set!");
                    bool bCursor = dynamic_cast<const SwCursorShell*>( &rSh) !=  nullptr;
                    bool bFE = dynamic_cast<const SwFEShell*>( &rSh) !=  nullptr;
                    sal_uInt16 nRestore = 0;
                    while( rSh.ActionCount() )
                    {
                        if( bCursor )
                        {
                            static_cast<SwCursorShell*>(&rSh)->EndAction();
                            static_cast<SwCursorShell*>(&rSh)->CallChgLnk();
                            if ( bFE )
                                static_cast<SwFEShell*>(&rSh)->SetChainMarker();
                        }
                        else
                            rSh.EndAction();
                        nRestore++;
                    }
                    rSh.SetRestoreActions(nRestore);
                }
                rSh.LockView(true);
            }
    }

    void SwRootFrame::UnoRestoreAllActions()
    {
        if ( GetCurrShell() )
            for(SwViewShell& rSh : GetCurrShell()->GetRingContainer())
            {
                sal_uInt16 nActions = rSh.GetRestoreActions();
                while( nActions-- )
                {
                    if ( dynamic_cast<const SwCursorShell*>( &rSh) !=  nullptr )
                        static_cast<SwCursorShell*>(&rSh)->StartAction();
                    else
                        rSh.StartAction();
                }
                rSh.SetRestoreActions(0);
                rSh.LockView(false);
            }
    }

    // Helper functions for SwRootFrame::CheckViewLayout
    static void lcl_MoveAllLowers( SwFrame* pFrame, const Point& rOffset );

    static void lcl_MoveAllLowerObjs( SwFrame* pFrame, const Point& rOffset )
    {
        const bool bPage = pFrame->IsPageFrame();
        const SwSortedObjs* pSortedObj = bPage
                            ? static_cast<SwPageFrame*>(pFrame)->GetSortedObjs()
                            : pFrame->GetDrawObjs();
        if (pSortedObj == nullptr)
            return;

        // note: pSortedObj elements may be removed and inserted from
        // MoveObjectIfActive(), invalidating iterators
        // DO NOT CONVERT THIS TO A C++11 FOR LOOP, IT DID NOT WORK THE LAST 2 TIMES
        for (size_t i = 0; i < pSortedObj->size(); ++i)
        {
            SwAnchoredObject *const pAnchoredObj = (*pSortedObj)[i];
            const SwFrameFormat& rObjFormat = pAnchoredObj->GetFrameFormat();
            const SwFormatAnchor& rAnchor = rObjFormat.GetAnchor();

            // all except from the as character anchored objects are moved
            // when processing the page frame:
            if ( !bPage && (rAnchor.GetAnchorId() != RndStdIds::FLY_AS_CHAR) )
                continue;

            SwObjPositioningInProgress aPosInProgress( *pAnchoredObj );

            if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
            {
                SwFlyFrame* pFlyFrame( static_cast<SwFlyFrame*>(pAnchoredObj) );
                lcl_MoveAllLowers( pFlyFrame, rOffset );
                pFlyFrame->NotifyDrawObj();
                // --> let the active embedded object be moved
                SwFrame* pLower = pFlyFrame->Lower();
                if ( pLower )
                {
                    if ( pLower->IsNoTextFrame() )
                    {
                        SwRootFrame* pRoot = pLower->getRootFrame();
                        SwViewShell *pSh = pRoot ? pRoot->GetCurrShell() : nullptr;
                        if ( pSh )
                        {
                            SwNoTextFrame *const pContentFrame = static_cast<SwNoTextFrame*>(pLower);
                            SwOLENode* pNode = pContentFrame->GetNode()->GetOLENode();
                            if ( pNode )
                            {
                                svt::EmbeddedObjectRef& xObj = pNode->GetOLEObj().GetObject();
                                if ( xObj.is() )
                                {
                                    for(SwViewShell& rSh : pSh->GetRingContainer())
                                    {
                                        SwFEShell* pFEShell = dynamic_cast< SwFEShell* >( &rSh );
                                        if ( pFEShell )
                                            pFEShell->MoveObjectIfActive( xObj, rOffset );
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else if ( dynamic_cast< const SwAnchoredDrawObject *>( pAnchoredObj ) !=  nullptr )
            {
                SwAnchoredDrawObject* pAnchoredDrawObj( static_cast<SwAnchoredDrawObject*>(pAnchoredObj) );

                // don't touch objects that are not yet positioned:
                if ( pAnchoredDrawObj->NotYetPositioned() )
                    continue;

                const Point& aCurrAnchorPos = pAnchoredDrawObj->GetDrawObj()->GetAnchorPos();
                const Point aNewAnchorPos( ( aCurrAnchorPos + rOffset ) );
                pAnchoredDrawObj->DrawObj()->SetAnchorPos( aNewAnchorPos );
                pAnchoredDrawObj->SetLastObjRect( pAnchoredDrawObj->GetObjRect().SVRect() );

                // clear contour cache
                if ( pAnchoredDrawObj->GetFrameFormat().GetSurround().IsContour() )
                    ClrContourCache( pAnchoredDrawObj->GetDrawObj() );
            }
            // #i92511#
            // cache for object rectangle inclusive spaces has to be invalidated.
            pAnchoredObj->InvalidateObjRectWithSpaces();
        }
    }

    static void lcl_MoveAllLowers( SwFrame* pFrame, const Point& rOffset )
    {
        const SwRect aFrame( pFrame->getFrameArea() );

        // first move the current frame
        // RotateFlyFrame3: moved to transform_translate instead of
        // direct modification to allow the SwFrame evtl. needed own reactions
        pFrame->transform_translate(rOffset);

        // Don't forget accessibility:
        if( pFrame->IsAccessibleFrame() )
        {
            SwRootFrame *pRootFrame = pFrame->getRootFrame();
            if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
                pRootFrame->GetCurrShell() )
            {
                pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( pFrame, aFrame );
            }
        }

        // the move any objects
        lcl_MoveAllLowerObjs( pFrame, rOffset );

        // finally, for layout frames we have to call this function recursively:
        if ( dynamic_cast< const SwLayoutFrame *>( pFrame ) !=  nullptr )
        {
            SwFrame* pLowerFrame = pFrame->GetLower();
            while ( pLowerFrame )
            {
                lcl_MoveAllLowers( pLowerFrame, rOffset );
                pLowerFrame = pLowerFrame->GetNext();
            }
        }
    }

    // Calculate how the pages have to be positioned
    void SwRootFrame::CheckViewLayout( const SwViewOption* pViewOpt, const SwRect* pVisArea )
    {
        SwViewShell* pSh = GetCurrShell();
        vcl::RenderContext* pRenderContext = pSh ? pSh->GetOut() : nullptr;
        // #i91432#
        // No calculation of page positions, if only an empty page is present.
        // This situation occurs when <SwRootFrame> instance is in construction
        // and the document contains only left pages.
        if ( Lower()->GetNext() == nullptr &&
             static_cast<SwPageFrame*>(Lower())->IsEmptyPage() )
        {
            return;
        }

        if ( !pVisArea )
        {
            // no early return for bNewPage
            if ( mnViewWidth < 0 )
                mnViewWidth = 0;
        }
        else
        {
            assert(pViewOpt && "CheckViewLayout required ViewOptions");

            const sal_uInt16 nColumns = pViewOpt->GetViewLayoutColumns();
            const bool bBookMode = pViewOpt->IsViewLayoutBookMode();

            if ( nColumns == mnColumns && bBookMode == mbBookMode && pVisArea->Width() == mnViewWidth && !mbSidebarChanged )
                return;

            mnColumns = nColumns;
            mbBookMode = bBookMode;
            mnViewWidth = pVisArea->Width();
            mbSidebarChanged = false;
        }

        if( GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE ) )
        {
            mnColumns = 1;
            mbBookMode = false;
        }

        Calc(pRenderContext);

        const bool bOldCallbackActionEnabled = IsCallbackActionEnabled();
        SetCallbackActionEnabled( false );

        maPageRects.clear();

        const long nBorder = getFrameArea().Pos().getX();
        const long nVisWidth = mnViewWidth - 2 * nBorder;
        const long nGapBetweenPages = pViewOpt ? pViewOpt->GetGapBetweenPages()
                                               : (pSh ? pSh->GetViewOptions()->GetGapBetweenPages()
                                                      : SwViewOption::defGapBetweenPages);

        // check how many pages fit into the first page layout row:
        SwPageFrame* pPageFrame = static_cast<SwPageFrame*>(Lower());

        // will contain the number of pages per row. 0 means that
        // the page does not fit.
        long nWidthRemain = nVisWidth;

        // after one row has been processed, these variables contain
        // the width of the row and the maximum of the page heights
        long nCurrentRowHeight = 0;
        long nCurrentRowWidth = 0;

        // these variables are used to finally set the size of the
        // root frame
        long nSumRowHeight = 0;
        SwTwips nMinPageLeft = TWIPS_MAX;
        SwTwips nMaxPageRight = 0;
        SwPageFrame* pStartOfRow = pPageFrame;
        sal_uInt16 nNumberOfPagesInRow = mbBookMode ? 1 : 0; // in book view, start with right page
        bool bFirstRow = true;

        bool bPageChanged = false;
        const bool bRTL = !IsLeftToRightViewLayout();
        const SwTwips nSidebarWidth = SwPageFrame::GetSidebarBorderWidth( pSh );

        while ( pPageFrame )
        {
            // we consider the current page to be "start of row" if
            // 1. it is the first page in the current row or
            // 2. it is the second page in the row and the first page is an empty page in non-book view:
            const bool bStartOfRow = pPageFrame == pStartOfRow ||
                                                 ( pStartOfRow->IsEmptyPage() && pPageFrame == pStartOfRow->GetNext() && !mbBookMode );

            const bool bEmptyPage = pPageFrame->IsEmptyPage() && !mbBookMode;

            // no half doc border space for first page in each row and
            long nPageWidth = 0;
            long nPageHeight = 0;

            if ( mbBookMode )
            {
                const SwFrame& rFormatPage = pPageFrame->GetFormatPage();

                nPageWidth  = rFormatPage.getFrameArea().Width()  + nSidebarWidth + ((bStartOfRow || 1 == (pPageFrame->GetPhyPageNum()%2)) ? 0 : nGapBetweenPages);
                nPageHeight = rFormatPage.getFrameArea().Height() + nGapBetweenPages;
            }
            else
            {
                if ( !pPageFrame->IsEmptyPage() )
                {
                    nPageWidth  = pPageFrame->getFrameArea().Width() + nSidebarWidth + (bStartOfRow ? 0 : nGapBetweenPages);
                    nPageHeight = pPageFrame->getFrameArea().Height() + nGapBetweenPages;
                }
            }

            if ( !bEmptyPage )
                ++nNumberOfPagesInRow;

            // finish current row if
            // 1. in dynamic mode the current page does not fit anymore or
            // 2. the current page exceeds the maximum number of columns
            bool bRowFinished = (0 == mnColumns && nWidthRemain < nPageWidth ) ||
                                (0 != mnColumns && mnColumns < nNumberOfPagesInRow);

            // make sure that at least one page goes to the current row:
            if ( !bRowFinished || bStartOfRow )
            {
                // current page is allowed to be in current row
                nWidthRemain = nWidthRemain - nPageWidth;

                nCurrentRowWidth = nCurrentRowWidth + nPageWidth;
                nCurrentRowHeight = std::max( nCurrentRowHeight, nPageHeight );

                pPageFrame = static_cast<SwPageFrame*>(pPageFrame->GetNext());

                if ( !pPageFrame )
                    bRowFinished = true;
            }

            if ( bRowFinished )
            {
                // pPageFrame now points to the first page in the new row or null
                // pStartOfRow points to the first page in the current row

                // special centering for last row. pretend to fill the last row with virtual copies of the last page before centering:
                if ( !pPageFrame && nWidthRemain > 0 )
                {
                    // find last page in current row:
                    const SwPageFrame* pLastPageInCurrentRow = pStartOfRow;
                    while( pLastPageInCurrentRow->GetNext() )
                        pLastPageInCurrentRow = static_cast<const SwPageFrame*>(pLastPageInCurrentRow->GetNext());

                    if ( pLastPageInCurrentRow->IsEmptyPage() )
                        pLastPageInCurrentRow = static_cast<const SwPageFrame*>(pLastPageInCurrentRow->GetPrev());

                    // check how many times the last page would still fit into the remaining space:
                    sal_uInt16 nNumberOfVirtualPages = 0;
                    const sal_uInt16 nMaxNumberOfVirtualPages = mnColumns > 0 ? mnColumns - nNumberOfPagesInRow : USHRT_MAX;
                    SwTwips nRemain = nWidthRemain;
                    SwTwips nVirtualPagesWidth = 0;
                    SwTwips nLastPageWidth = pLastPageInCurrentRow->getFrameArea().Width() + nSidebarWidth;

                    while ( ( mnColumns > 0 || nRemain > 0 ) && nNumberOfVirtualPages < nMaxNumberOfVirtualPages )
                    {
                        SwTwips nLastPageWidthWithGap = nLastPageWidth;
                        if ( !mbBookMode || ( 0 == (nNumberOfVirtualPages + nNumberOfPagesInRow) %2) )
                            nLastPageWidthWithGap += nGapBetweenPages;

                        if ( mnColumns > 0 || nLastPageWidthWithGap < nRemain )
                        {
                            ++nNumberOfVirtualPages;
                            nVirtualPagesWidth += nLastPageWidthWithGap;
                        }
                        nRemain = nRemain - nLastPageWidthWithGap;
                    }

                    nCurrentRowWidth = nCurrentRowWidth + nVirtualPagesWidth;
                }

                // first page in book mode is always special:
                if ( bFirstRow && mbBookMode )
                {
                    // #i88036#
                    nCurrentRowWidth +=
                        pStartOfRow->GetFormatPage().getFrameArea().Width() + nSidebarWidth;
                }

                // center page if possible
                long nSizeDiff = 0;
                if (nVisWidth > nCurrentRowWidth && !comphelper::LibreOfficeKit::isActive())
                    nSizeDiff = ( nVisWidth - nCurrentRowWidth ) / 2;

                // adjust positions of pages in current row
                long nX = nSizeDiff;

                const long nRowStart = nBorder + nSizeDiff;
                const long nRowEnd   = nRowStart + nCurrentRowWidth;

                if ( bFirstRow && mbBookMode )
                {
                    // #i88036#
                    nX += pStartOfRow->GetFormatPage().getFrameArea().Width() + nSidebarWidth;
                }

                SwPageFrame* pEndOfRow = pPageFrame;
                SwPageFrame* pPageToAdjust = pStartOfRow;

                do
                {
                    const SwPageFrame* pFormatPage = pPageToAdjust;
                    if ( mbBookMode )
                        pFormatPage = &pPageToAdjust->GetFormatPage();

                    const SwTwips nCurrentPageWidth = pFormatPage->getFrameArea().Width() + (pFormatPage->IsEmptyPage() ? 0 : nSidebarWidth);
                    const Point aOldPagePos = pPageToAdjust->getFrameArea().Pos();
                    const bool bLeftSidebar = pPageToAdjust->SidebarPosition() == sw::sidebarwindows::SidebarPosition::LEFT;
                    const SwTwips nLeftPageAddOffset = bLeftSidebar ?
                                                       nSidebarWidth :
                                                       0;

                    Point aNewPagePos( nBorder + nX, nBorder + nSumRowHeight );
                    Point aNewPagePosWithLeftOffset( nBorder + nX + nLeftPageAddOffset, nBorder + nSumRowHeight );

                    // RTL view layout: Calculate mirrored page position
                    if ( bRTL )
                    {
                        const long nXOffsetInRow = aNewPagePos.getX() - nRowStart;
                        aNewPagePos.setX(nRowEnd - nXOffsetInRow - nCurrentPageWidth);
                        aNewPagePosWithLeftOffset = aNewPagePos;
                        aNewPagePosWithLeftOffset.setX(aNewPagePosWithLeftOffset.getX() + nLeftPageAddOffset);
                    }

                    if ( aNewPagePosWithLeftOffset != aOldPagePos )
                    {
                        lcl_MoveAllLowers( pPageToAdjust, aNewPagePosWithLeftOffset - aOldPagePos );
                        pPageToAdjust->SetCompletePaint();
                        bPageChanged = true;
                    }

                    // calculate area covered by the current page and store to
                    // maPageRects. This is used e.g., for cursor setting
                    const bool bFirstColumn = pPageToAdjust == pStartOfRow;
                    const bool bLastColumn = pPageToAdjust->GetNext() == pEndOfRow;
                    const bool bLastRow = !pEndOfRow;

                    nMinPageLeft  = std::min( nMinPageLeft, aNewPagePos.getX() );
                    nMaxPageRight = std::max( nMaxPageRight, aNewPagePos.getX() + nCurrentPageWidth);

                    // border of nGapBetweenPages around the current page:
                    SwRect aPageRectWithBorders( aNewPagePos.getX() - nGapBetweenPages,
                                                 aNewPagePos.getY(),
                                                 pPageToAdjust->getFrameArea().SSize().Width() + nGapBetweenPages + nSidebarWidth,
                                                 nCurrentRowHeight );

                    static const long nOuterClickDiff = 1000000;

                    // adjust borders for these special cases:
                    if ( (bFirstColumn && !bRTL) || (bLastColumn && bRTL) )
                        aPageRectWithBorders.SubLeft( nOuterClickDiff );
                    if ( (bLastColumn && !bRTL) || (bFirstColumn && bRTL) )
                        aPageRectWithBorders.AddRight( nOuterClickDiff );
                    if ( bFirstRow )
                        aPageRectWithBorders.SubTop( nOuterClickDiff );
                    if ( bLastRow )
                        aPageRectWithBorders.AddBottom( nOuterClickDiff );

                    maPageRects.push_back( aPageRectWithBorders );

                    nX = nX + nCurrentPageWidth;
                    pPageToAdjust = static_cast<SwPageFrame*>(pPageToAdjust->GetNext());

                    // distance to next page
                    if ( pPageToAdjust && pPageToAdjust != pEndOfRow )
                    {
                        // in book view, we add the x gap before left (even) pages:
                        if ( mbBookMode )
                        {
                            if ( 0 == (pPageToAdjust->GetPhyPageNum()%2) )
                                nX = nX + nGapBetweenPages;
                        }
                        else
                        {
                            // in non-book view, don't add x gap before
                            // 1. the last empty page in a row
                            // 2. after an empty page
                            const bool bDontAddGap = ( pPageToAdjust->IsEmptyPage() && pPageToAdjust->GetNext() == pEndOfRow ) ||
                                                     ( static_cast<SwPageFrame*>(pPageToAdjust->GetPrev())->IsEmptyPage() );

                            if  ( !bDontAddGap )
                                nX = nX + nGapBetweenPages;
                        }
                    }
                }
                while (pPageToAdjust && pPageToAdjust != pEndOfRow);

                // adjust values for root frame size
                nSumRowHeight = nSumRowHeight + nCurrentRowHeight;

                // start new row:
                nCurrentRowHeight = 0;
                nCurrentRowWidth = 0;
                pStartOfRow = pEndOfRow;
                nWidthRemain = nVisWidth;
                nNumberOfPagesInRow = 0;
                bFirstRow = false;
            } // end row finished
        } // end while

        // set size of root frame:
        const Size aOldSize( getFrameArea().SSize() );
        const Size aNewSize( nMaxPageRight - nBorder, nSumRowHeight - nGapBetweenPages );

        if ( bPageChanged || aNewSize != aOldSize )
        {
            ChgSize( aNewSize );
            ::AdjustSizeChgNotify( this );
            Calc(pRenderContext);

            if ( pSh && pSh->GetDoc()->GetDocShell() )
            {
                pSh->SetFirstVisPageInvalid();
                if (bOldCallbackActionEnabled)
                {
                    pSh->InvalidateWindows( SwRect( 0, 0, SAL_MAX_INT32, SAL_MAX_INT32 ) );
                    pSh->GetDoc()->GetDocShell()->Broadcast(SfxHint(SfxHintId::DocChanged));
                }
            }
        }

        maPagesArea.Pos( getFrameArea().Pos() );
        maPagesArea.SSize( aNewSize );
        if ( TWIPS_MAX != nMinPageLeft )
            maPagesArea.Left_( nMinPageLeft );

        SetCallbackActionEnabled( bOldCallbackActionEnabled );
    }

    bool SwRootFrame::IsLeftToRightViewLayout() const
    {
        // Layout direction determined by layout direction of the first page.
        // #i88036#
        // Only ask a non-empty page frame for its layout direction
        assert(dynamic_cast<const SwPageFrame *>(Lower()) != nullptr);
        const SwPageFrame& rPage = static_cast<const SwPageFrame&>(*Lower()).GetFormatPage();
        return !rPage.IsRightToLeft() && !rPage.IsVertical();
    }

    const SwPageFrame& SwPageFrame::GetFormatPage() const
    {
        const SwPageFrame* pRet = this;
        if ( IsEmptyPage() )
        {
            pRet = static_cast<const SwPageFrame*>( OnRightPage() ? GetNext() : GetPrev() );
            // #i88035#
            // Typically a right empty page frame has a next non-empty page frame and
            // a left empty page frame has a previous non-empty page frame.
            // But under certain circumstances this assumption is not true -
            // e.g. during insertion of a left page at the end of the document right
            // after a left page in an intermediate state a right empty page does not
            // have a next page frame.
            if ( pRet == nullptr )
            {
                if ( OnRightPage() )
                {
                    pRet = static_cast<const SwPageFrame*>( GetPrev() );
                }
                else
                {
                    pRet = static_cast<const SwPageFrame*>( GetNext() );
                }
            }
            assert(pRet &&
                    "<SwPageFrame::GetFormatPage()> - inconsistent layout: empty page without previous and next page frame --> crash.");
        }
        return *pRet;
    }

    bool SwPageFrame::IsOverHeaderFooterArea( const Point& rPt, FrameControlType &rControl ) const
    {
        long nUpperLimit = 0;
        long nLowerLimit = 0;
        const SwFrame* pFrame = Lower();
        while ( pFrame )
        {
            if ( pFrame->IsBodyFrame() )
            {
                nUpperLimit = pFrame->getFrameArea().Top();
                nLowerLimit = pFrame->getFrameArea().Bottom();
            }
            else if ( pFrame->IsFootnoteContFrame() )
                nLowerLimit = pFrame->getFrameArea().Bottom();

            pFrame = pFrame->GetNext();
        }

        SwRect aHeaderArea( getFrameArea().TopLeft(),
               Size( getFrameArea().Width(), nUpperLimit - getFrameArea().Top() ) );

        SwViewShell* pViewShell = getRootFrame()->GetCurrShell();
        const bool bHideWhitespaceMode = pViewShell->GetViewOptions()->IsHideWhitespaceMode();
        if ( aHeaderArea.IsInside( rPt ) )
        {
            if (!bHideWhitespaceMode || static_cast<const SwFrameFormat*>(GetDep())->GetHeader().IsActive())
            {
                rControl = Header;
                return true;
            }
        }
        else
        {
            SwRect aFooterArea( Point( getFrameArea().Left(), nLowerLimit ),
                    Size( getFrameArea().Width(), getFrameArea().Bottom() - nLowerLimit ) );

            if ( aFooterArea.IsInside( rPt ) &&
                 (!bHideWhitespaceMode || static_cast<const SwFrameFormat*>(GetDep())->GetFooter().IsActive()) )
            {
                rControl = Footer;
                return true;
            }
        }

        return false;
    }

    bool SwPageFrame::CheckPageHeightValidForHideWhitespace(SwTwips nDiff)
    {
        SwViewShell* pShell = getRootFrame()->GetCurrShell();
        if (pShell && pShell->GetViewOptions()->IsWhitespaceHidden())
        {
            // When whitespace is hidden, the page frame has two heights: the
            // nominal (defined by the frame format), and the actual (which is
            // at most the nominal height, but can be smaller in case there is
            // no content for the whole page).
            // The layout size is the actual one, but we want to move the
            // content frame to a new page only in case it doesn't fit the
            // nominal size.
            if (nDiff < 0)
            {
                // Content frame doesn't fit the actual size, check if it fits the nominal one.
                const SwFrameFormat* pPageFormat = static_cast<const SwFrameFormat*>(GetDep());
                const Size& rPageSize = pPageFormat->GetFrameSize().GetSize();
                long nWhitespace = rPageSize.getHeight() - getFrameArea().Height();
                if (nWhitespace > -nDiff)
                {
                    // It does: don't move it and invalidate our page frame so
                    // that it gets a larger height.
                    return false;
                }
            }
        }

        return true;
    }

    SwTextGridItem const* GetGridItem(SwPageFrame const*const pPage)
    {
        if (pPage && pPage->HasGrid())
        {
            SwTextGridItem const& rGridItem(
                    pPage->GetPageDesc()->GetMaster().GetTextGrid());
            if (GRID_NONE != rGridItem.GetGridType())
            {
                return &rGridItem;
            }
        }
        return nullptr;
    }

    sal_uInt16 GetGridWidth(SwTextGridItem const& rG, SwDoc const& rDoc)
    {
        return (rDoc.IsSquaredPageMode()) ? rG.GetBaseHeight() : rG.GetBaseWidth();
    }

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V773 Visibility scope of the 'pBodyFrame' pointer was exited without releasing the memory. A memory leak is possible.

↑ V595 The 'pViewOpt' pointer was utilized before it was verified against nullptr. Check lines: 2081, 2107.