Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/core/layout/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 185 kB image not shown  

Quelle  wsfrm.cxx   Sprache: C

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

#include <hints.hxx>
#include <osl/diagnose.h>
#include <o3tl/safeint.hxx>
#include <svl/itemiter.hxx>
#include <editeng/brushitem.hxx>
#include <sfx2/viewsh.hxx>
#include <fmtornt.hxx>
#include <pagefrm.hxx>
#include <section.hxx>
#include <rootfrm.hxx>
#include <anchoreddrawobject.hxx>
#include <fmtanchr.hxx>
#include <viewimp.hxx>
#include <viewopt.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <redline.hxx>
#include <docsh.hxx>
#include <ftninfo.hxx>
#include <ftnidx.hxx>
#include <fmtclbl.hxx>
#include <fmtfsize.hxx>
#include <fmtpdsc.hxx>
#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <fmtsrnd.hxx>
#include <fmtcntnt.hxx>
#include <ftnfrm.hxx>
#include <tabfrm.hxx>
#include <rowfrm.hxx>
#include <flyfrm.hxx>
#include <sectfrm.hxx>
#include <fmtclds.hxx>
#include <txtfrm.hxx>
#include <bodyfrm.hxx>
#include <cellfrm.hxx>
#include <dbg_lay.hxx>
#include <editeng/frmdiritem.hxx>
#include <sortedobjs.hxx>
#include <frmatr.hxx>
#include <frmtool.hxx>
#include <layact.hxx>
#include <ndtxt.hxx>
#include <swtable.hxx>
#include <view.hxx>

// RotateFlyFrame3
#include <basegfx/matrix/b2dhommatrixtools.hxx>

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

SwFrameAreaDefinition::SwFrameAreaDefinition()
:   mnFrameId(SwFrameAreaDefinition::snLastFrameId++),
    mbFrameAreaPositionValid(false),
    mbFrameAreaSizeValid(false),
    mbFramePrintAreaValid(false)
{
}

SwFrameAreaDefinition::~SwFrameAreaDefinition()
{
}

void SwFrameAreaDefinition::setFrameAreaPositionValid(bool bNew)
{
    if(mbFrameAreaPositionValid != bNew)
    {
        mbFrameAreaPositionValid = bNew;
    }
}

void SwFrameAreaDefinition::setFrameAreaSizeValid(bool bNew)
{
    if(mbFrameAreaSizeValid != bNew)
    {
        mbFrameAreaSizeValid = bNew;
    }
}

void SwFrameAreaDefinition::setFramePrintAreaValid(bool bNew)
{
    if(mbFramePrintAreaValid != bNew)
    {
        mbFramePrintAreaValid = bNew;
    }
}

SwFrameAreaDefinition::FrameAreaWriteAccess::~FrameAreaWriteAccess()
{
    if(mrTarget.maFrameArea != *this)
    {
        mrTarget.maFrameArea = *this;
    }
}

SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
{
    if(mrTarget.maFramePrintArea != *this)
    {
        mrTarget.maFramePrintArea = *this;
    }
}

// RotateFlyFrame3 - Support for Transformations
basegfx::B2DHomMatrix SwFrameAreaDefinition::getFrameAreaTransformation() const
{
    // default implementation hands out FrameArea (outer frame)
    const SwRect& rFrameArea(getFrameArea());

    return basegfx::utils::createScaleTranslateB2DHomMatrix(
        rFrameArea.Width(), rFrameArea.Height(),
        rFrameArea.Left(), rFrameArea.Top());
}

basegfx::B2DHomMatrix SwFrameAreaDefinition::getFramePrintAreaTransformation() const
{
    // default implementation hands out FramePrintArea (outer frame)
    // Take into account that FramePrintArea is relative to FrameArea
    const SwRect& rFrameArea(getFrameArea());
    const SwRect& rFramePrintArea(getFramePrintArea());

    return basegfx::utils::createScaleTranslateB2DHomMatrix(
        rFramePrintArea.Width(), rFramePrintArea.Height(),
        rFramePrintArea.Left() + rFrameArea.Left(),
        rFramePrintArea.Top() + rFrameArea.Top());
}

void SwFrameAreaDefinition::transform_translate(const Point& rOffset)
{
    // RotateFlyFrame3: default is to change the FrameArea, FramePrintArea needs no
    // change since it is relative to FrameArea
    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);

    if (aFrm.Pos().X() != FAR_AWAY)
    {
        aFrm.Pos().AdjustX(rOffset.X() );
    }

    if (aFrm.Pos().Y() != FAR_AWAY)
    {
        aFrm.Pos().AdjustY(rOffset.Y() );
    }
}

SwRect TransformableSwFrame::getUntransformedFrameArea() const
{
    const basegfx::B2DHomMatrix& rSource(getLocalFrameAreaTransformation());

    if(rSource.isIdentity())
    {
        return mrSwFrameAreaDefinition.getFrameArea();
    }
    else
    {
        basegfx::B2DVector aScale, aTranslate;
        double fRotate, fShearX;
        rSource.decompose(aScale, aTranslate, fRotate, fShearX);
        const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
        const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));

        return SwRect(
            basegfx::fround<tools::Long>(aCenter.getX() - (0.5 * aAbsScale.getX())),
            basegfx::fround<tools::Long>(aCenter.getY() - (0.5 * aAbsScale.getY())),
            basegfx::fround<tools::Long>(aAbsScale.getX()),
            basegfx::fround<tools::Long>(aAbsScale.getY()));
    }
}

SwRect TransformableSwFrame::getUntransformedFramePrintArea() const
{
    const basegfx::B2DHomMatrix& rSource(getLocalFramePrintAreaTransformation());

    if(rSource.isIdentity())
    {
        return mrSwFrameAreaDefinition.getFramePrintArea();
    }
    else
    {
        basegfx::B2DVector aScale, aTranslate;
        double fRotate, fShearX;
        rSource.decompose(aScale, aTranslate, fRotate, fShearX);
        const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
        const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
        const SwRect aUntransformedFrameArea(getUntransformedFrameArea());

        return SwRect(
            basegfx::fround<tools::Long>(aCenter.getX() - (0.5 * aAbsScale.getX())) - aUntransformedFrameArea.Left(),
            basegfx::fround<tools::Long>(aCenter.getY() - (0.5 * aAbsScale.getY())) - aUntransformedFrameArea.Top(),
            basegfx::fround<tools::Long>(aAbsScale.getX()),
            basegfx::fround<tools::Long>(aAbsScale.getY()));
    }
}

void TransformableSwFrame::createFrameAreaTransformations(
    double fRotation,
    const basegfx::B2DPoint& rCenter)
{
    const basegfx::B2DHomMatrix aRotateAroundCenter(
        basegfx::utils::createRotateAroundPoint(
            rCenter.getX(),
            rCenter.getY(),
            fRotation));
    const SwRect& rFrameArea(mrSwFrameAreaDefinition.getFrameArea());
    const SwRect& rFramePrintArea(mrSwFrameAreaDefinition.getFramePrintArea());

    maFrameAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
        rFrameArea.Width(), rFrameArea.Height(),
        rFrameArea.Left(), rFrameArea.Top());
    maFramePrintAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
        rFramePrintArea.Width(), rFramePrintArea.Height(),
        rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top());
}

void TransformableSwFrame::adaptFrameAreasToTransformations()
{
    if(!getLocalFrameAreaTransformation().isIdentity())
    {
        basegfx::B2DRange aRangeFrameArea(0.0, 0.0, 1.0, 1.0);
        aRangeFrameArea.transform(getLocalFrameAreaTransformation());
        const SwRect aNewFrm(
            basegfx::fround<tools::Long>(aRangeFrameArea.getMinX()), basegfx::fround<tools::Long>(aRangeFrameArea.getMinY()),
            basegfx::fround<tools::Long>(aRangeFrameArea.getWidth()), basegfx::fround<tools::Long>(aRangeFrameArea.getHeight()));

        if(aNewFrm != mrSwFrameAreaDefinition.getFrameArea())
        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
            aFrm.setSwRect(aNewFrm);
        }
    }

    if(getLocalFramePrintAreaTransformation().isIdentity())
        return;

    basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0);
    aRangeFramePrintArea.transform(getLocalFramePrintAreaTransformation());
    const SwRect aNewPrt(
        basegfx::fround<tools::Long>(aRangeFramePrintArea.getMinX()) - mrSwFrameAreaDefinition.getFrameArea().Left(),
        basegfx::fround<tools::Long>(aRangeFramePrintArea.getMinY()) - mrSwFrameAreaDefinition.getFrameArea().Top(),
        basegfx::fround<tools::Long>(aRangeFramePrintArea.getWidth()),
        basegfx::fround<tools::Long>(aRangeFramePrintArea.getHeight()));

    if(aNewPrt != mrSwFrameAreaDefinition.getFramePrintArea())
    {
        SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
        aPrt.setSwRect(aNewPrt);
    }
}

void TransformableSwFrame::restoreFrameAreas()
{
    // This can be done fully based on the Transformations currently
    // set, so use this. Only needed when transformation *is* used
    if(!getLocalFrameAreaTransformation().isIdentity())
    {
        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
        aFrm.setSwRect(getUntransformedFrameArea());
    }

    if(!getLocalFramePrintAreaTransformation().isIdentity())
    {
        SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
        aPrt.setSwRect(getUntransformedFramePrintArea());
    }
}

// transform by given B2DHomMatrix
void TransformableSwFrame::transform(const basegfx::B2DHomMatrix& aTransform)
{
    maFrameAreaTransformation *= aTransform;
    maFramePrintAreaTransformation *= aTransform;
}

void SwFrame::dumpAsXml(xmlTextWriterPtr pWriter) const
{
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("infos"));
    dumpInfosAsXml(pWriter);
    (void)xmlTextWriterEndElement(pWriter);

    if ( m_pDrawObjs && m_pDrawObjs->size() > 0 )
    {
        (void)xmlTextWriterStartElement( pWriter, BAD_CAST( "anchored" ) );

        for (SwAnchoredObject* pObject : *m_pDrawObjs)
        {
            pObject->dumpAsXml( pWriter );
        }

        (void)xmlTextWriterEndElement( pWriter );
    }

    dumpChildrenAsXml(pWriter);
}

void SwFrame::dumpChildrenAsXml( xmlTextWriterPtr writer ) const
{
    const SwFrame *pFrame = GetLower(  );
    for ( ; pFrame != nullptr; pFrame = pFrame->GetNext(  ) )
    {
        pFrame->dumpAsXml( writer );
    }
}

SwFrame::SwFrame( sw::BroadcastingModify *pMod, SwFrame* pSib )
:   SwClient( pMod ),
    mpRoot( pSib ? pSib->getRootFrame() : nullptr ),
    mpUpper(nullptr),
    mpNext(nullptr),
    mpPrev(nullptr),
    mnFrameType(SwFrameType::None),
    mbInDtor(false),
    mbInvalidR2L(true),
    mbDerivedR2L(false),
    mbRightToLeft(false),
    mbInvalidVert(true),
    mbDerivedVert(false),
    mbVertical(false),
    mbVertLR(false),
    mbVertLRBT(false),
    mbValidLineNum(false),
    mbFixSize(false),
    mbCompletePaint(true),
    mbRetouche(false),
    mbInfInvalid(true),
    mbInfBody( false ),
    mbInfTab ( false ),
    mbInfFly ( false ),
    mbInfFootnote ( false ),
    mbInfSct ( false ),
    mbColLocked(false),
    m_isInDestroy(false),
    mnForbidDelete(0)
{
    OSL_ENSURE( pMod, "No frame format given." );
}

const IDocumentDrawModelAccess& SwFrame::getIDocumentDrawModelAccess()
{
    return GetUpper()->GetFormat()->getIDocumentDrawModelAccess();
}

bool SwFrame::KnowsFormat( const SwFormat& rFormat ) const
{
    return GetRegisteredIn() == &rFormat;
}

void SwFrame::RegisterToFormat( SwFormat& rFormat )
{
    rFormat.Add(*this);
}

void SwFrame::CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse )
{
    if( SvxFrameDirection::Environment == nDir || ( bVert && bOnlyBiDi ) )
    {
        mbDerivedVert = true;
        if( SvxFrameDirection::Environment == nDir )
            mbDerivedR2L = true;
        SetDirFlags( bVert );
    }
    else if( bVert )
    {
        mbInvalidVert = false;
        if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir
            || bBrowse )
        {
            mbVertical = false;
            mbVertLR = false;
            mbVertLRBT = false;
        }
        else
        {
            mbVertical = true;
            if(SvxFrameDirection::Vertical_RL_TB == nDir)
            {
                mbVertLR = false;
                mbVertLRBT = false;
            }
            else if(SvxFrameDirection::Vertical_LR_TB==nDir)
            {
                mbVertLR = true;
                mbVertLRBT = false;
            }
            else if (nDir == SvxFrameDirection::Vertical_LR_BT)
            {
                mbVertLR = true;
                mbVertLRBT = true;
            }
            else if (nDir == SvxFrameDirection::Vertical_RL_TB90)
            {
                // not yet implemented, render as RL_TB
                mbVertLR = false;
                mbVertLRBT = false;
            }
        }
    }
    else
    {
        mbInvalidR2L = false;
        if( SvxFrameDirection::Horizontal_RL_TB == nDir )
            mbRightToLeft = true;
        else
            mbRightToLeft = false;
    }
}

void SwFrame::CheckDirection( bool bVert )
{
    if( bVert )
    {
        if( !IsHeaderFrame() && !IsFooterFrame() )
        {
            mbDerivedVert = true;
            SetDirFlags( bVert );
        }
    }
    else
    {
        mbDerivedR2L = true;
        SetDirFlags( bVert );
    }
}

void SwSectionFrame::CheckDirection( bool bVert )
{
    const SwFrameFormat* pFormat = GetFormat();
    if( pFormat )
    {
        const SwViewShell *pSh = getRootFrame()->GetCurrShell();
        const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
                    bVert, true, bBrowseMode );
    }
    else
        SwFrame::CheckDirection( bVert );
}

void SwFlyFrame::CheckDirection( bool bVert )
{
    const SwFrameFormat* pFormat = GetFormat();
    if( pFormat )
    {
        const SwViewShell *pSh = getRootFrame()->GetCurrShell();
        const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
                    bVert, false, bBrowseMode );
    }
    else
        SwFrame::CheckDirection( bVert );
}

void SwTabFrame::CheckDirection( bool bVert )
{
    const SwFrameFormat* pFormat = GetFormat();
    if( pFormat )
    {
        const SwViewShell *pSh = getRootFrame()->GetCurrShell();
        const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir(pFormat->GetFormatAttr(RES_FRAMEDIR).GetValue(),
                    bVert, true, bBrowseMode );
    }
    else
        SwFrame::CheckDirection( bVert );
}

void SwCellFrame::CheckDirection( bool bVert )
{
    const SwFrameFormat* pFormat = GetFormat();
    const SvxFrameDirectionItem* pFrameDirItem;
    // Check if the item is set, before actually
    // using it. Otherwise the dynamic pool default is used, which may be set
    // to LTR in case of OOo 1.0 documents.
    if( pFormat && (pFrameDirItem = pFormat->GetItemIfSet( RES_FRAMEDIR ) ) )
    {
        const SwViewShell *pSh = getRootFrame()->GetCurrShell();
        const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
        CheckDir( pFrameDirItem->GetValue(), bVert, false, bBrowseMode );
    }
    else
        SwFrame::CheckDirection( bVert );
}

void SwTextFrame::CheckDirection( bool bVert )
{
    const SwViewShell *pSh = getRootFrame()->GetCurrShell();
    const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
    CheckDir(GetTextNodeForParaProps()->GetSwAttrSet().GetFrameDir().GetValue(),
             bVert, true, bBrowseMode);
}

void SwFrame::SwClientNotify(const SwModify&, const SfxHint& rHint)
{
    if (rHint.GetId() != SfxHintId::SwLegacyModify && rHint.GetId() != SfxHintId::SwFormatChange
        && rHint.GetId() != SfxHintId::SwAttrSetChange)
        return;

    SwFrameInvFlags eInvFlags = SwFrameInvFlags::NONE;
    if (rHint.GetId() == SfxHintId::SwLegacyModify)
    {
        auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
        UpdateAttrFrame(pLegacy->m_pOld, pLegacy->m_pNew, eInvFlags);
    }
    else if (rHint.GetId() == SfxHintId::SwAttrSetChange)
    {
        auto pChangeHint = static_cast<const sw::AttrSetChangeHint*>(&rHint);
        if(pChangeHint->m_pOld && pChangeHint->m_pNew)
        {
            SfxItemIter aNIter(*pChangeHint->m_pNew->GetChgSet());
            SfxItemIter aOIter(*pChangeHint->m_pOld->GetChgSet());
            const SfxPoolItem* pNItem = aNIter.GetCurItem();
            const SfxPoolItem* pOItem = aOIter.GetCurItem();
            do
            {
                UpdateAttrFrame(pOItem, pNItem, eInvFlags);
                pNItem = aNIter.NextItem();
                pOItem = aOIter.NextItem();
            } while (pNItem);
        }
    }
    else // rHint.GetId() == SfxHintId::SwFormatChange
    {
        UpdateAttrFrameForFormatChange(eInvFlags);
    }

    if(eInvFlags == SwFrameInvFlags::NONE)
        return;

    SwPageFrame* pPage = FindPageFrame();
    InvalidatePage(pPage);
    if(eInvFlags & SwFrameInvFlags::InvalidatePrt)
    {
        InvalidatePrt_();
        if(!GetPrev() && IsTabFrame() && IsInSct())
            FindSctFrame()->InvalidatePrt_();
    }
    if(eInvFlags & SwFrameInvFlags::InvalidateSize)
        InvalidateSize_();
    if(eInvFlags & SwFrameInvFlags::InvalidatePos)
        InvalidatePos_();
    if(eInvFlags & SwFrameInvFlags::SetCompletePaint)
        SetCompletePaint();
    SwFrame *pNxt;
    if (eInvFlags & (SwFrameInvFlags::NextInvalidatePos | SwFrameInvFlags::NextSetCompletePaint)
        && nullptr != (pNxt = GetNext()))
    {
        pNxt->InvalidatePage(pPage);
        if(eInvFlags & SwFrameInvFlags::NextInvalidatePos)
            pNxt->InvalidatePos_();
        if(eInvFlags & SwFrameInvFlags::NextSetCompletePaint)
            pNxt->SetCompletePaint();
    }
}

void SwFrame::UpdateAttrFrame( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
                         SwFrameInvFlags &rInvFlags )
{
    sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
    switch( nWhich )
    {
        case RES_BOX:
        case RES_SHADOW:
            Prepare( PrepareHint::FixSizeChanged );
            [[fallthrough]];
        case RES_MARGIN_FIRSTLINE:
        case RES_MARGIN_TEXTLEFT:
        case RES_MARGIN_RIGHT:
        case RES_LR_SPACE:
        case RES_UL_SPACE:
        case RES_RTL_GUTTER:
            rInvFlags |= SwFrameInvFlags::InvalidatePrt | SwFrameInvFlags::InvalidateSize
                         | SwFrameInvFlags::SetCompletePaint;
            break;

        case RES_HEADER_FOOTER_EAT_SPACING:
            rInvFlags |= SwFrameInvFlags::InvalidatePrt | SwFrameInvFlags::InvalidateSize;
            break;

        case RES_BACKGROUND:
        case RES_BACKGROUND_FULL_SIZE:
            rInvFlags |= SwFrameInvFlags::SetCompletePaint | SwFrameInvFlags::NextSetCompletePaint;
            break;

        case RES_KEEP:
            rInvFlags |= SwFrameInvFlags::InvalidatePos;
            break;

        case RES_FRM_SIZE:
            ReinitializeFrameSizeAttrFlags();
            rInvFlags |= SwFrameInvFlags::InvalidatePrt | SwFrameInvFlags::InvalidateSize
                         | SwFrameInvFlags::NextInvalidatePos;
            break;

        case RES_ROW_SPLIT:
        {
            if ( IsRowFrame() )
            {
                bool bInFollowFlowRow = nullptr != IsInFollowFlowRow();
                if ( bInFollowFlowRow || nullptr != IsInSplitTableRow() )
                {
                    SwTabFrame* pTab = FindTabFrame();
                    if ( bInFollowFlowRow )
                        pTab = pTab->FindMaster();
                    pTab->SetRemoveFollowFlowLinePending( true );
                }
            }
            break;
        }
        case RES_COL:
            OSL_FAIL( "Columns for new FrameType?" );
            break;

        default:
            // the new FillStyle has to do the same as previous RES_BACKGROUND
            if(nWhich >= XATTR_FILL_FIRST && nWhich <= XATTR_FILL_LAST)
            {
                rInvFlags
                    |= SwFrameInvFlags::SetCompletePaint | SwFrameInvFlags::NextSetCompletePaint;
            }
            /* do Nothing */;
    }
}

// static
void SwFrame::UpdateAttrFrameForFormatChange( SwFrameInvFlags &rInvFlags )
{
    rInvFlags |= SwFrameInvFlags::InvalidatePrt | SwFrameInvFlags::InvalidateSize
                 | SwFrameInvFlags::InvalidatePos | SwFrameInvFlags::SetCompletePaint;
}

bool SwFrame::Prepare( const PrepareHint, const void *, bool )
{
    /* Do nothing */
    return false;
}

/**
 * Invalidates the page in which the Frame is currently placed.
 * The page is invalidated depending on the type (Layout, Content, FlyFrame)
 */

void SwFrame::InvalidatePage( const SwPageFrame *pPage ) const
{
    if ( !pPage )
    {
        pPage = FindPageFrame();
        // #i28701# - for at-character and as-character
        // anchored Writer fly frames additionally invalidate also page frame
        // its 'anchor character' is on.
        if ( pPage && pPage->GetUpper() && IsFlyFrame() )
        {
            const SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrame*>(this);
            if ( pFlyFrame->IsAutoPos() || pFlyFrame->IsFlyInContentFrame() )
            {
                // #i33751#, #i34060# - method <GetPageFrameOfAnchor()>
                // is replaced by method <FindPageFrameOfAnchor()>. It's return value
                // have to be checked.
                SwPageFrame* pPageFrameOfAnchor =
                        const_cast<SwFlyFrame*>(pFlyFrame)->FindPageFrameOfAnchor();
                if ( pPageFrameOfAnchor && pPageFrameOfAnchor != pPage )
                {
                    InvalidatePage( pPageFrameOfAnchor );
                }
            }
        }
    }

    if ( !(pPage && pPage->GetUpper()) )
        return;

    if ( pPage->GetFormat()->GetDoc().IsInDtor() )
        return;

    SwRootFrame *pRoot = const_cast<SwRootFrame*>(static_cast<const SwRootFrame*>(pPage->GetUpper()));
    const SwFlyFrame *pFly = FindFlyFrame();
    if ( IsContentFrame() )
    {
        if ( pRoot->IsTurboAllowed() )
        {
            // If a ContentFrame wants to register for a second time, make it a TurboAction.
            if ( !pRoot->GetTurbo() || this == pRoot->GetTurbo() )
                pRoot->SetTurbo( static_cast<const SwContentFrame*>(this) );
            else
            {
                pRoot->DisallowTurbo();
                //The page of the Turbo could be a different one then mine,
                //therefore we have to invalidate it.
                const SwFrame *pTmp = pRoot->GetTurbo();
                pRoot->ResetTurbo();
                pTmp->InvalidatePage();
            }
        }
        if ( !pRoot->GetTurbo() )
        {
            if ( pFly )
            {   if( !pFly->IsLocked() )
                {
                    if ( pFly->IsFlyInContentFrame() )
                    {   pPage->InvalidateFlyInCnt();
                        pFly->GetAnchorFrame()->InvalidatePage();
                    }
                    else
                        pPage->InvalidateFlyContent();
                }
            }
            else
                pPage->InvalidateContent();
        }
    }
    else
    {
        pRoot->DisallowTurbo();
        if ( pFly )
        {
            if ( !pFly->IsLocked() )
            {
                if ( pFly->IsFlyInContentFrame() )
                {
                    pPage->InvalidateFlyInCnt();
                    pFly->GetAnchorFrame()->InvalidatePage();
                }
                else
                    pPage->InvalidateFlyLayout();
            }
        }
        else
            pPage->InvalidateLayout();

        if ( pRoot->GetTurbo() )
        {   const SwFrame *pTmp = pRoot->GetTurbo();
            pRoot->ResetTurbo();
            pTmp->InvalidatePage();
        }
    }
    pRoot->SetIdleFlags();

    if (!IsTextFrame())
        return;

    SwTextFrame const*const pText(static_cast<SwTextFrame const*>(this));
    if (sw::MergedPara const*const pMergedPara = pText->GetMergedPara())
    {
        SwTextNode const* pNode(nullptr);
        for (auto const& e : pMergedPara->extents)
        {
            if (e.pNode != pNode)
            {
                pNode = e.pNode;
                if (pNode->IsGrammarCheckDirty())
                {
                    pRoot->SetNeedGrammarCheck( true );
                    break;
                }
            }
        }
    }
    else
    {
        if (pText->GetTextNodeFirst()->IsGrammarCheckDirty())
        {
            pRoot->SetNeedGrammarCheck( true );
        }
    }
}

Size SwFrame::ChgSize( const Size& aNewSize )
{
    mbFixSize = true;
    const Size aOldSize( getFrameArea().SSize() );
    if ( aNewSize == aOldSize )
        return aOldSize;

    if ( GetUpper() )
    {
        bool bNeighb = IsNeighbourFrame();
        SwRectFnSet fnRect(IsVertical() != bNeighb, IsVertLR(), IsVertLRBT());
        SwRect aNew( Point(0,0), aNewSize );

        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            fnRect.SetWidth(aFrm, fnRect.GetWidth(aNew));
        }

        tools::Long nNew = fnRect.GetHeight(aNew);
        tools::Long nDiff = nNew - fnRect.GetHeight(getFrameArea());

        if( nDiff )
        {
            if ( GetUpper()->IsFootnoteBossFrame() && HasFixSize() &&
                 SwNeighbourAdjust::GrowShrink !=
                 static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment() )
            {
                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    fnRect.SetHeight(aFrm, nNew);
                }

                SwTwips nReal = static_cast<SwLayoutFrame*>(this)->AdjustNeighbourhood(nDiff);

                if ( nReal != nDiff )
                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    fnRect.SetHeight(aFrm, nNew - nDiff + nReal);
                }
            }
            else
            {
                // OD 24.10.2002 #97265# - grow/shrink not for neighbour frames
                // NOTE: neighbour frames are cell and column frames.
                if ( !bNeighb )
                {
                    if ( nDiff > 0 )
                        Grow( nDiff );
                    else
                        Shrink( -nDiff );

                    if (GetUpper() && fnRect.GetHeight(getFrameArea()) != nNew)
                    {
                        GetUpper()->InvalidateSize_();
                    }
                }

                // Even if grow/shrink did not yet set the desired width, for
                // example when called by ChgColumns to set the column width, we
                // set the right width now.
                SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                fnRect.SetHeight(aFrm, nNew);
            }
        }
    }
    else
    {
        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
        aFrm.SSize( aNewSize );
    }

    if ( getFrameArea().SSize() != aOldSize )
    {
        SwPageFrame *pPage = FindPageFrame();
        if ( GetNext() )
        {
            GetNext()->InvalidatePos_();
            GetNext()->InvalidatePage( pPage );
        }
        if( IsLayoutFrame() )
        {
            if( IsRightToLeft() )
                InvalidatePos_();
            ifstatic_cast<SwLayoutFrame*>(this)->Lower() )
                static_cast<SwLayoutFrame*>(this)->Lower()->InvalidateSize_();
        }
        InvalidatePrt_();
        InvalidateSize_();
        InvalidatePage( pPage );
    }

    return getFrameArea().SSize();
}

/** Insert SwFrame into existing structure.
 *
 * Insertion is done below the parent either before pBehind or
 * at the end of the chain if pBehind is empty.
 */

void SwFrame::InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind )
{
    OSL_ENSURE( pParent, "No parent for insert." );
    OSL_ENSURE( (!pBehind || pParent == pBehind->GetUpper()),
            "Frame tree is inconsistent." );

    mpUpper = pParent;
    mpNext = pBehind;
    if( pBehind )
    {   //Insert before pBehind.
        mpPrev = pBehind->mpPrev;
        if( nullptr != mpPrev )
            mpPrev->mpNext = this;
        else
            mpUpper->m_pLower = this;
        pBehind->mpPrev = this;
    }
    else
    {   //Insert at the end, or as first node in the sub tree
        mpPrev = mpUpper->Lower();
        if ( mpPrev )
        {
            while( mpPrev->mpNext )
                mpPrev = mpPrev->mpNext;
            mpPrev->mpNext = this;
        }
        else
            mpUpper->m_pLower = this;
    }
}

/** Insert SwFrame into existing structure.
 *
 * Insertion is done below the parent either after pBehind or
 * at the beginning of the chain if pBehind is empty.
 */

void SwFrame::InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore )
{
    OSL_ENSURE( (!pBefore || pParent == pBefore->GetUpper()),
            "Frame tree is inconsistent." );

    mpUpper = pParent;
    mpPrev = pBefore;
    if ( pBefore )
    {
        //Insert after pBefore
        mpNext = pBefore->mpNext;
        if ( nullptr != mpNext )
            mpNext->mpPrev = this;
        pBefore->mpNext = this;
    }
    else
    {
        assert(pParent && "No Parent for Insert.");
        //Insert at the beginning of the chain
        mpNext = pParent->Lower();
        if ( mpNext )
            mpNext->mpPrev = this;
        pParent->m_pLower = this;
    }
}

/** Insert a chain of SwFrames into an existing structure
 *
 * Currently, this method is used to insert a SectionFrame (which may have some siblings) into an
 * existing structure. If the third parameter is NULL, this method is (besides handling the
 * siblings) equal to SwFrame::InsertBefore(..).
 *
 * If the third parameter is passed, the following happens:
 *  - this becomes mpNext of pParent
 *  - pSct becomes mpNext of the last one in the this-chain
 *  - pBehind is reconnected from pParent to pSct
 * The purpose is: a SectionFrame (this) won't become a child of another SectionFrame (pParent), but
 * pParent gets split into two siblings (pParent+pSect) and this is inserted between.
 */

bool SwFrame::InsertGroupBefore( SwFrame* pParent, SwFrame* pBehind, SwFrame* pSct )
{
    OSL_ENSURE( pParent, "No parent for insert." );
    OSL_ENSURE( (!pBehind || ( (pBehind && (pParent == pBehind->GetUpper()))
            || ((pParent->IsSctFrame() && pBehind->GetUpper()->IsColBodyFrame())) ) ),
            "Frame tree inconsistent." );
    if( pSct )
    {
        mpUpper = pParent->GetUpper();
        SwFrame *pLast = this;
        while( pLast->GetNext() )
        {
            pLast = pLast->GetNext();
            pLast->mpUpper = GetUpper();
        }
        if( pBehind )
        {
            pLast->mpNext = pSct;
            pSct->mpPrev = pLast;
            pSct->mpNext = pParent->GetNext();
        }
        else
        {
            pLast->mpNext = pParent->GetNext();
            if( pLast->GetNext() )
                pLast->GetNext()->mpPrev = pLast;
        }
        pParent->mpNext = this;
        mpPrev = pParent;
        if( pSct->GetNext() )
            pSct->GetNext()->mpPrev = pSct;
        while( pLast->GetNext() )
        {
            pLast = pLast->GetNext();
            pLast->mpUpper = GetUpper();
        }
        if( pBehind )
        {   // Insert before pBehind.
            if( pBehind->GetPrev() )
                pBehind->GetPrev()->mpNext = nullptr;
            else
                pBehind->GetUpper()->m_pLower = nullptr;
            pBehind->mpPrev = nullptr;
            SwLayoutFrame* pTmp = static_cast<SwLayoutFrame*>(pSct);
            SwFrame* pLower = pTmp->Lower();
            if( pLower )
            {
                OSL_ENSURE( pLower->IsColumnFrame(), "InsertGrp: Used SectionFrame" );
                pTmp = static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(pLower)->Lower());
                OSL_ENSURE( pTmp, "InsertGrp: Missing ColBody" );
            }
            pBehind->mpUpper = pTmp;
            pBehind->GetUpper()->m_pLower = pBehind;
            pLast = pBehind->GetNext();
            while ( pLast )
            {
                pLast->mpUpper = pBehind->GetUpper();
                pLast = pLast->GetNext();
            }
        }
        else
        {
            OSL_ENSURE( pSct->IsSctFrame(), "InsertGroup: For SectionFrames only" );
            SwFrame::DestroyFrame(pSct);
            return false;
        }
    }
    else
    {
        mpUpper = static_cast<SwLayoutFrame*>(pParent);
        SwFrame *pLast = this;
        while( pLast->GetNext() )
        {
            pLast = pLast->GetNext();
            pLast->mpUpper = GetUpper();
        }
        pLast->mpNext = pBehind;
        if( pBehind )
        {   // Insert before pBehind.
            mpPrev = pBehind->mpPrev;
            if( nullptr != mpPrev )
                mpPrev->mpNext = this;
            else
                mpUpper->m_pLower = this;
            pBehind->mpPrev = pLast;
        }
        else
        {
            //Insert at the end, or ... the first node in the subtree
            mpPrev = mpUpper->Lower();
            if ( mpPrev )
            {
                while( mpPrev->mpNext )
                    mpPrev = mpPrev->mpNext;
                mpPrev->mpNext = this;
            }
            else
                mpUpper->m_pLower = this;
        }
    }
    return true;
}

void SwFrame::RemoveFromLayout()
{
    OSL_ENSURE( mpUpper, "Remove without upper?" );

    if (mpPrev)
        // one out of the middle is removed
        mpPrev->mpNext = mpNext;
    else if (mpUpper)
    {   // the first in a list is removed //TODO
        OSL_ENSURE( mpUpper->m_pLower == this"Layout is inconsistent." );
        mpUpper->m_pLower = mpNext;
    }
    if( mpNext )
        mpNext->mpPrev = mpPrev;

    // Remove link
    mpNext  = mpPrev  = nullptr;
    mpUpper = nullptr;
}

void SwContentFrame::Paste( SwFrame* pParent, SwFrame* pSibling)
{
    OSL_ENSURE( pParent, "No parent for pasting." );
    OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." );
    OSL_ENSURE( pParent != this"I'm the parent." );
    OSL_ENSURE( pSibling != this"I'm my own neighbour." );
    OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
            "I'm still registered somewhere" );
    OSL_ENSURE( !pSibling || pSibling->IsFlowFrame(),
            " - sibling not of expected type." );

    //Insert in the tree.
    InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );

    SwPageFrame *pPage = FindPageFrame();
    InvalidateAll_();
    InvalidatePage( pPage );

    if( pPage )
    {
        pPage->InvalidateSpelling();
        pPage->InvalidateSmartTags();
        pPage->InvalidateAutoCompleteWords();
        pPage->InvalidateWordCount();
    }

    if ( GetNext() )
    {
        SwFrame* pNxt = GetNext();
        pNxt->InvalidatePrt_();
        pNxt->InvalidatePos_();
        pNxt->InvalidatePage( pPage );
        if( pNxt->IsSctFrame() )
            pNxt = static_cast<SwSectionFrame*>(pNxt)->ContainsContent();
        if( pNxt && pNxt->IsTextFrame() && pNxt->IsInFootnote() )
            pNxt->Prepare( PrepareHint::FootnoteInvalidation, nullptr, false );
    }

    if ( getFrameArea().Height() )
        pParent->Grow( getFrameArea().Height() );

    if ( getFrameArea().Width() != pParent->getFramePrintArea().Width() )
        Prepare( PrepareHint::FixSizeChanged );

    if ( GetPrev() )
    {
        if ( IsFollow() )
            //I'm a direct follower of my master now
            static_cast<SwContentFrame*>(GetPrev())->Prepare( PrepareHint::FollowFollows );
        else
        {
            if ( GetPrev()->getFrameArea().Height() !=
                 GetPrev()->getFramePrintArea().Height() + GetPrev()->getFramePrintArea().Top() )
            {
                // Take the border into account?
                GetPrev()->InvalidatePrt_();
            }
            // OD 18.02.2003 #104989# - force complete paint of previous frame,
            // if frame is inserted at the end of a section frame, in order to
            // get subsidiary lines repainted for the section.
            if ( pParent->IsSctFrame() && !GetNext() )
            {
                // force complete paint of previous frame, if new inserted frame
                // in the section is the last one.
                GetPrev()->SetCompletePaint();
            }
            GetPrev()->InvalidatePage( pPage );
        }
    }
    if ( IsInFootnote() )
    {
        SwFrame* pFrame = GetIndPrev();
        if( pFrame && pFrame->IsSctFrame() )
            pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
        if( pFrame )
            pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
        if( !GetNext() )
        {
            pFrame = FindFootnoteFrame()->GetNext();
            if( pFrame && nullptr != (pFrame=static_cast<SwLayoutFrame*>(pFrame)->ContainsAny()) )
                pFrame->InvalidatePrt_();
        }
    }

    InvalidateLineNum_();
    SwFrame *pNxt = FindNextCnt();
    if ( !pNxt  )
        return;

    while ( pNxt && pNxt->IsInTab() )
    {
        pNxt = pNxt->FindTabFrame();
        if( nullptr != pNxt )
            pNxt = pNxt->FindNextCnt();
    }
    if ( pNxt )
    {
        pNxt->InvalidateLineNum_();
        if ( pNxt != GetNext() )
            pNxt->InvalidatePage();
    }
}

void SwContentFrame::Cut()
{
    OSL_ENSURE( GetUpper(), "Cut without Upper()." );

    SwPageFrame *pPage = FindPageFrame();
    InvalidatePage( pPage );
    SwFrame *pFrame = GetIndPrev();
    if( pFrame )
    {
        if( pFrame->IsSctFrame() )
            pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
        if ( pFrame && pFrame->IsContentFrame() )
        {
            pFrame->InvalidatePrt_();
            if( IsInFootnote() )
                pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
        }
        // #i26250# - invalidate printing area of previous
        // table frame.
        else if ( pFrame && pFrame->IsTabFrame() )
        {
            pFrame->InvalidatePrt();
        }
    }

    SwFrame *pNxt = FindNextCnt();
    if ( pNxt )
    {
        while ( pNxt && pNxt->IsInTab() )
        {
            pNxt = pNxt->FindTabFrame();
            if( nullptr != pNxt )
                pNxt = pNxt->FindNextCnt();
        }
        if ( pNxt )
        {
            pNxt->InvalidateLineNum_();
            if ( pNxt != GetNext() )
                pNxt->InvalidatePage();
        }
    }

    SwTabFrame* pMasterTab(nullptr);
    pFrame = GetIndNext();
    if( pFrame )
    {
        // The old follow may have calculated a gap to the predecessor which
        // now becomes obsolete or different as it becomes the first one itself
        pFrame->InvalidatePrt_();
        pFrame->InvalidatePos_();
        pFrame->InvalidatePage( pPage );
        if( pFrame->IsSctFrame() )
        {
            pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
            if( pFrame )
            {
                pFrame->InvalidatePrt_();
                pFrame->InvalidatePos_();
                pFrame->InvalidatePage( pPage );
            }
        }
        if( pFrame && IsInFootnote() )
            pFrame->Prepare( PrepareHint::ErgoSum, nullptr, false );
        if( IsInSct() && !GetPrev() )
        {
            SwSectionFrame* pSct = FindSctFrame();
            if( !pSct->IsFollow() )
            {
                pSct->InvalidatePrt_();
                pSct->InvalidatePage( pPage );
            }
        }
    }
    else
    {
        InvalidateNextPos();
        //Someone needs to do the retouching: predecessor or upper
        pFrame = GetPrev();
        if ( nullptr != pFrame )
        {   pFrame->SetRetouche();
            pFrame->Prepare( PrepareHint::WidowsOrphans );
            pFrame->InvalidatePos_();
            pFrame->InvalidatePage( pPage );
        }
        // If I'm (was) the only ContentFrame in my upper, it has to do the
        // retouching. Also, perhaps a page became empty.
        else
        {   SwRootFrame *pRoot = getRootFrame();
            if ( pRoot )
            {
                pRoot->SetSuperfluous();
                // RemoveSuperfluous can only remove empty pages at the end;
                // find if there are pages without content following pPage
                // and if so request a call to CheckPageDescs()
                SwViewShell *pSh = pRoot->GetCurrShell();
                // tdf#152983 pPage is null when called from SwHeadFootFrame ctor
                if (pPage && pSh && pSh->Imp()->IsAction())
                {
                    SwPageFrame const* pNext(pPage);
                    while ((pNext = static_cast<SwPageFrame const*>(pNext->GetNext())))
                    {
                        if (!sw::IsPageFrameEmpty(*pNext) && !pNext->IsFootnotePage())
                        {
                            pSh->Imp()->GetLayAction().SetCheckPageNum(pPage->GetPhyPageNum());
                            break;
                        }
                    }
                }
                GetUpper()->SetCompletePaint();
                GetUpper()->InvalidatePage( pPage );
            }
            if( IsInSct() )
            {
                SwSectionFrame* pSct = FindSctFrame();
                if( !pSct->IsFollow() )
                {
                    pSct->InvalidatePrt_();
                    pSct->InvalidatePage( pPage );
                }
            }
            // #i52253# The master table should take care
            // of removing the follow flow line.
            if ( IsInTab() )
            {
                SwTabFrame* pThisTab = FindTabFrame();
                if (pThisTab && pThisTab->IsFollow())
                {
                    pMasterTab = pThisTab->FindMaster();
                }
            }
        }
    }
    //Remove first, then shrink the upper.
    SwLayoutFrame *pUp = GetUpper();
    RemoveFromLayout();
    if ( !pUp )
    {
        assert(!pMasterTab);
        return;
    }

    if (pMasterTab
        && !pMasterTab->GetFollow()->GetFirstNonHeadlineRow()->ContainsContent())
    {   // only do this if there's no content in other cells of the row!
        pMasterTab->InvalidatePos_();
        pMasterTab->SetRemoveFollowFlowLinePending(true);
    }

    SwSectionFrame *pSct = nullptr;
    if ( !pUp->Lower() &&
         ( ( pUp->IsFootnoteFrame() && !pUp->IsColLocked() ) ||
           ( pUp->IsInSct() &&
             // #i29438#
             // We have to consider the case that the section may be "empty"
             // except from a temporary empty table frame.
             // This can happen due to the new cell split feature.
             !pUp->IsCellFrame() &&
             // #126020# - adjust check for empty section
             // #130797# - correct fix #126020#
             !(pSct = pUp->FindSctFrame())->ContainsContent() &&
             !pSct->ContainsAny( true ) ) ) )
    {
        if ( pUp->GetUpper() )
        {

            // prevent delete of <ColLocked> footnote frame
            if ( pUp->IsFootnoteFrame() && !pUp->IsColLocked())
            {
                if( pUp->GetNext() && !pUp->GetPrev() )
                {
                    SwFrame* pTmp = static_cast<SwLayoutFrame*>(pUp->GetNext())->ContainsAny();
                    if( pTmp )
                        pTmp->InvalidatePrt_();
                }
                if (!pUp->IsDeleteForbidden())
                {
                    pUp->Cut();
                    SwFrame::DestroyFrame(pUp);
                }
            }
            else
            {
                assert(pSct);
                if ( pSct->IsColLocked() || !pSct->IsInFootnote() ||
                     ( pUp->IsFootnoteFrame() && pUp->IsColLocked() ) )
                {
                    pSct->DelEmpty( false );
                    // If a locked section may not be deleted then at least
                    // its size became invalid after removing its last
                    // content.
                    pSct->InvalidateSize_();
                }
                else
                {
                    pSct->DelEmpty( true );
                    SwFrame::DestroyFrame(pSct);
                }
            }
        }
    }
    else
    {
        SwRectFnSet aRectFnSet(this);
        tools::Long nFrameHeight = aRectFnSet.GetHeight(getFrameArea());
        if( nFrameHeight )
            pUp->Shrink( nFrameHeight );
    }
}

void SwLayoutFrame::Paste( SwFrame* pParent, SwFrame* pSibling)
{
    OSL_ENSURE( pParent, "No parent for pasting." );
    OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." );
    OSL_ENSURE( pParent != this"I'm the parent oneself." );
    OSL_ENSURE( pSibling != this"I'm my own neighbour." );
    OSL_ENSURE( !GetPrev() && !GetNext() && !GetUpper(),
            "I'm still registered somewhere." );

    //Insert in the tree.
    InsertBefore( static_cast<SwLayoutFrame*>(pParent), pSibling );

    // OD 24.10.2002 #103517# - correct setting of variable <fnRect>
    // <fnRect> is used for the following:
    // (1) To invalidate the frame's size, if its size, which has to be the
    //      same as its upper/parent, differs from its upper's/parent's.
    // (2) To adjust/grow the frame's upper/parent, if it has a dimension in its
    //      size, which is not determined by its upper/parent.
    // Which size is which depends on the frame type and the layout direction
    // (vertical or horizontal).
    // There are the following cases:
    // (A) Header and footer frames both in vertical and in horizontal layout
    //      have to size the width to the upper/parent. A dimension in the height
    //      has to cause an adjustment/grow of the upper/parent.
    //      --> <fnRect> = fnRectHori
    // (B) Cell and column frames in vertical layout, the width has to be the
    //          same as upper/parent and a dimension in height causes adjustment/grow
    //          of the upper/parent.
    //          --> <fnRect> = fnRectHori
    //      in horizontal layout the other way around
    //          --> <fnRect> = fnRectVert
    // (C) Other frames in vertical layout, the height has to be the
    //          same as upper/parent and a dimension in width causes adjustment/grow
    //          of the upper/parent.
    //          --> <fnRect> = fnRectVert
    //      in horizontal layout the other way around
    //          --> <fnRect> = fnRectHori
    //SwRectFn fnRect = IsVertical() ? fnRectHori : fnRectVert;
    bool bVert, bVertL2R, bVertL2RB2T;
    if ( IsHeaderFrame() || IsFooterFrame() )
        bVert = bVertL2R = bVertL2RB2T = false;
    else
    {
        bVert = (IsCellFrame() || IsColumnFrame()) ? !GetUpper()->IsVertical() : GetUpper()->IsVertical();
        bVertL2R = GetUpper()->IsVertLR();
        bVertL2RB2T = GetUpper()->IsVertLRBT();
    }
    SwRectFnSet fnRect(bVert, bVertL2R, bVertL2RB2T);

    if (fnRect.GetWidth(getFrameArea()) != fnRect.GetWidth(pParent->getFramePrintArea()))
        InvalidateSize_();
    InvalidatePos_();
    const SwPageFrame *pPage = FindPageFrame();
    InvalidatePage( pPage );
    if( !IsColumnFrame() )
    {
        SwFrame *pFrame = GetIndNext();
        if( nullptr != pFrame )
        {
            pFrame->InvalidatePos_();
            if( IsInFootnote() )
            {
                if( pFrame->IsSctFrame() )
                    pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
                if( pFrame )
                    pFrame->Prepare( PrepareHint::ErgoSum, nullptr, false );
            }
        }
        if ( IsInFootnote() && nullptr != ( pFrame = GetIndPrev() ) )
        {
            if( pFrame->IsSctFrame() )
                pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
            if( pFrame )
                pFrame->Prepare( PrepareHint::QuoVadis, nullptr, false );
        }
    }

    if (!fnRect.GetHeight(getFrameArea()))
        return;

    // AdjustNeighbourhood is now also called in columns which are not
    // placed inside a frame
    SwNeighbourAdjust nAdjust = GetUpper()->IsFootnoteBossFrame() ?
            static_cast<SwFootnoteBossFrame*>(GetUpper())->NeighbourhoodAdjustment()
            : SwNeighbourAdjust::GrowShrink;
    SwTwips nGrow = fnRect.GetHeight(getFrameArea());
    if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
        AdjustNeighbourhood( nGrow );
    else
    {
        SwTwips nReal = 0;
        if( SwNeighbourAdjust::AdjustGrow == nAdjust )
            nReal = AdjustNeighbourhood( nGrow );
        if( nReal < nGrow )
            nReal += pParent->Grow( nGrow - nReal );
        if( SwNeighbourAdjust::GrowAdjust == nAdjust && nReal < nGrow )
            AdjustNeighbourhood( nGrow - nReal );
    }
}

void SwLayoutFrame::Cut()
{
    if ( GetNext() )
        GetNext()->InvalidatePos_();

    SwRectFnSet aRectFnSet(this);
    SwTwips nShrink = aRectFnSet.GetHeight(getFrameArea());

    // Remove first, then shrink upper.
    SwLayoutFrame *pUp = GetUpper();

    // AdjustNeighbourhood is now also called in columns which are not
    // placed inside a frame.

    // Remove must not be called before an AdjustNeighbourhood, but it has to
    // be called before the upper-shrink-call, if the upper-shrink takes care
    // of its content.
    if ( pUp && nShrink )
    {
        if( pUp->IsFootnoteBossFrame() )
        {
            SwNeighbourAdjust nAdjust= static_cast<SwFootnoteBossFrame*>(pUp)->NeighbourhoodAdjustment();
            if( SwNeighbourAdjust::OnlyAdjust == nAdjust )
                AdjustNeighbourhood( -nShrink );
            else
            {
                SwTwips nReal = 0;
                if( SwNeighbourAdjust::AdjustGrow == nAdjust )
                    nReal = -AdjustNeighbourhood( -nShrink );
                if( nReal < nShrink )
                {
                    const SwTwips nOldHeight = aRectFnSet.GetHeight(getFrameArea());

                    // seems as if this needs to be forwarded to the SwFrame already here,
                    // changing to zero seems temporary anyways
                    {
                        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                        aRectFnSet.SetHeight( aFrm, 0 );
                    }

                    nReal += pUp->Shrink( nShrink - nReal );

                    {
                        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                        aRectFnSet.SetHeight( aFrm, nOldHeight );
                    }
                }

                if( SwNeighbourAdjust::GrowAdjust == nAdjust && nReal < nShrink )
                    AdjustNeighbourhood( nReal - nShrink );
            }
            RemoveFromLayout();
        }
        else
        {
            RemoveFromLayout();
            pUp->Shrink( nShrink );
        }
    }
    else
        RemoveFromLayout();

    if( pUp && !pUp->Lower() )
    {
        pUp->SetCompletePaint();
        pUp->InvalidatePage();
    }
}

SwTwips SwFrame::Grow(SwTwips nDist, SwResizeLimitReason& reason, bool bTst, bool bInfo)
{
    OSL_ENSURE( nDist >= 0, "Negative growth?" );

    PROTOCOL_ENTER( this, bTst ? PROT::GrowTest : PROT::Grow, DbgAction::NONE, &nDist )

    if ( !nDist )
    {
        reason = SwResizeLimitReason::Unspecified;
        return 0;
    }
    if ( IsFlyFrame() )
        return static_cast<SwFlyFrame*>(this)->Grow_(nDist, reason, bTst);
    if ( IsSctFrame() )
        return static_cast<SwSectionFrame*>(this)->Grow_(nDist, reason, bTst);
    if (IsCellFrame())
    {
        const SwCellFrame* pThisCell = static_cast<const SwCellFrame*>(this);
        const SwTabFrame* pTab = FindTabFrame();

        // NEW TABLES
        if ( pTab->IsVertical() != IsVertical() ||
             pThisCell->GetLayoutRowSpan() < 1 )
        {
            reason = SwResizeLimitReason::FixedSizeFrame;
            return 0;
        }
    }

    SwRectFnSet aRectFnSet(this);

    SwTwips nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
    if( nPrtHeight > 0 && nDist > (LONG_MAX - nPrtHeight) )
        nDist = LONG_MAX - nPrtHeight;

    const SwTwips nReal = GrowFrame(nDist, reason, bTst, bInfo);
    if( !bTst )
    {
        nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());

        SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
        aRectFnSet.SetHeight( aPrt, nPrtHeight + ( IsContentFrame() ? nDist : nReal ) );
    }
    return nReal;
}

SwTwips SwFrame::Shrink( SwTwips nDist, bool bTst, bool bInfo )
{
    OSL_ENSURE( nDist >= 0, "Negative reduction?" );

    PROTOCOL_ENTER( this, bTst ? PROT::ShrinkTest : PROT::Shrink, DbgAction::NONE, &nDist )

    if ( nDist )
    {
        if ( IsFlyFrame() )
            return static_cast<SwFlyFrame*>(this)->Shrink_( nDist, bTst );
        else if( IsSctFrame() )
            return static_cast<SwSectionFrame*>(this)->Shrink_( nDist, bTst );
        else
        {
            if (IsCellFrame())
            {
                const SwCellFrame* pThisCell = static_cast<const SwCellFrame*>(this);
                const SwTabFrame* pTab = FindTabFrame();

                // NEW TABLES
                if ( (pTab && pTab->IsVertical() != IsVertical()) ||
                     pThisCell->GetLayoutRowSpan() < 1 )
                    return 0;
            }
            SwRectFnSet aRectFnSet(this);
            SwTwips nReal = aRectFnSet.GetHeight(getFrameArea());
            ShrinkFrame( nDist, bTst, bInfo );
            nReal -= aRectFnSet.GetHeight(getFrameArea());
            if( !bTst )
            {
                const SwTwips nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea());
                SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                aRectFnSet.SetHeight( aPrt, nPrtHeight - ( IsContentFrame() ? nDist : nReal ) );
            }
            return nReal;
        }
    }
    return 0;
}

/** Adjust surrounding neighbourhood after insertion
 *
 * A Frame needs "normalization" if it is directly placed below a footnote boss (page/column) and its
 * size changes. There is always a frame that takes the maximum possible space (the frame that
 * contains the Body text) and zero or more frames which only take the space needed (header/footer
 * area, footnote container). If one of these frames changes, the body-text-frame has to grow or
 * shrink accordingly, even though it's fixed.
 *
 * !! Is it possible to do this in a generic way and not restrict it to the page and a distinct
 * frame which takes the maximum space (controlled using the FrameSize attribute)?
 * Problems:
 *   - What if multiple frames taking the maximum space are placed next to each other?
 *   - How is the maximum space calculated?
 *   - How small can those frames become?
 *
 * In any case, only a certain amount of space is allowed, so we never go below a minimum value for
 * the height of the body.
 *
 * @param nDiff the value around which the space has to be allocated
 */

SwTwips SwFrame::AdjustNeighbourhood( SwTwips nDiff, bool bTst )
{
    PROTOCOL_ENTER( this, PROT::AdjustN, DbgAction::NONE, &nDiff );

    if ( !nDiff || !GetUpper()->IsFootnoteBossFrame() ) // only inside pages/columns
        return 0;

    const SwViewShell *pSh = getRootFrame()->GetCurrShell();
    const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();

    //The (Page-)Body only changes in BrowseMode, but only if it does not
    //contain columns.
    if ( IsPageBodyFrame() && (!bBrowse ||
          (static_cast<SwLayoutFrame*>(this)->Lower() &&
           static_cast<SwLayoutFrame*>(this)->Lower()->IsColumnFrame())) )
        return 0;

    //In BrowseView mode the PageFrame can handle some of the requests.
    tools::Long nBrowseAdd = 0;
    if ( bBrowse && GetUpper()->IsPageFrame() ) // only (Page-)BodyFrames
    {
        SwViewShell *pViewShell = getRootFrame()->GetCurrShell();
        SwLayoutFrame *pUp = GetUpper();
        tools::Long nChg;
        const tools::Long nUpPrtBottom = pUp->getFrameArea().Height() -
                                  pUp->getFramePrintArea().Height() - pUp->getFramePrintArea().Top();
        SwRect aInva( pUp->getFrameArea() );
        if ( pViewShell )
        {
            aInva.Pos().setX( pViewShell->VisArea().Left() );
            aInva.Width( pViewShell->VisArea().Width() );
        }
        if ( nDiff > 0 )
        {
            nChg = BROWSE_HEIGHT - pUp->getFrameArea().Height();
            nChg = std::min( nDiff, SwTwips(nChg) );

            if ( !IsBodyFrame() )
            {
                SetCompletePaint();
                if ( !pViewShell || pViewShell->VisArea().Height() >= pUp->getFrameArea().Height() )
                {
                    //First minimize Body, it will grow again later.
                    SwFrame *pBody = static_cast<SwFootnoteBossFrame*>(pUp)->FindBodyCont();
                    const tools::Long nTmp = nChg - pBody->getFramePrintArea().Height();
                    if ( !bTst )
                    {
                        {
                            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pBody);
                            aFrm.Height(std::max( tools::Long(0), aFrm.Height() - nChg ));
                        }

                        pBody->InvalidatePrt_();
                        pBody->InvalidateSize_();
                        if ( pBody->GetNext() )
                            pBody->GetNext()->InvalidatePos_();
                        if ( !IsHeaderFrame() )
                            pBody->SetCompletePaint();
                    }
                    nChg = nTmp <= 0 ? 0 : nTmp;
                }
            }

            const tools::Long nTmp = nUpPrtBottom + 20;
            aInva.Top( aInva.Bottom() - nTmp );
            aInva.Height( nChg + nTmp );
        }
        else
        {
            //The page can shrink to 0. The first page keeps the same size like
            //VisArea.
            nChg = nDiff;
            tools::Long nInvaAdd = 0;
            if ( pViewShell && !pUp->GetPrev() &&
                 pUp->getFrameArea().Height() + nDiff < pViewShell->VisArea().Height() )
            {
                // This means that we have to invalidate adequately.
                nChg = pViewShell->VisArea().Height() - pUp->getFrameArea().Height();
                nInvaAdd = -(nDiff - nChg);
            }

            //Invalidate including bottom border.
            tools::Long nBorder = nUpPrtBottom + 20;
            nBorder -= nChg;
            aInva.Top( aInva.Bottom() - (nBorder+nInvaAdd) );
            if ( !IsBodyFrame() )
            {
                SetCompletePaint();
                if ( !IsHeaderFrame() )
                    static_cast<SwFootnoteBossFrame*>(pUp)->FindBodyCont()->SetCompletePaint();
            }
            //Invalidate the page because of the frames. Thereby the page becomes
            //the right size again if a frame didn't fit. This only works
            //randomly for paragraph bound frames otherwise (NotifyFlys).
            pUp->InvalidateSize();
        }
        if ( !bTst )
        {
            //Independent from nChg
            if ( pViewShell && aInva.HasArea() && pUp->GetUpper() )
                pViewShell->InvalidateWindows( aInva );
        }
        if ( !bTst && nChg )
        {
            {
                SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pUp);
                aFrm.AddHeight(nChg );
            }

            {
                SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*pUp);
                aPrt.AddHeight(nChg );
            }

            if ( pViewShell )
                pViewShell->Imp()->SetFirstVisPageInvalid();

            if ( GetNext() )
                GetNext()->InvalidatePos_();

            //Trigger a repaint if necessary.
            std::unique_ptr<SvxBrushItem> aBack(pUp->GetFormat()->makeBackgroundBrushItem());
            const SvxGraphicPosition ePos = aBack->GetGraphicPos();
            if ( ePos != GPOS_NONE && ePos != GPOS_TILED )
                pViewShell->InvalidateWindows( pUp->getFrameArea() );

            if ( pUp->GetUpper() )
            {
                if ( pUp->GetNext() )
                    pUp->GetNext()->InvalidatePos();

                //Sad but true: during notify on ViewImp a Calc on the page and
                //its Lower may be called. The values should not be changed
                //because the caller takes care of the adjustment of Frame and
                //Prt.
                const tools::Long nOldFrameHeight = getFrameArea().Height();
                const tools::Long nOldPrtHeight = getFramePrintArea().Height();
                const bool bOldComplete = IsCompletePaint();

                if ( IsBodyFrame() )
                {
                    SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                    aPrt.Height( nOldFrameHeight );
                }

                if ( pUp->GetUpper() )
                {
                    static_cast<SwRootFrame*>(pUp->GetUpper())->CheckViewLayout( nullptr, nullptr );
                }

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

                SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                aPrt.Height( nOldPrtHeight );

                mbCompletePaint = bOldComplete;
            }
            if ( !IsBodyFrame() )
                pUp->InvalidateSize_();
            InvalidatePage( static_cast<SwPageFrame*>(pUp) );
        }
        nDiff -= nChg;
        if ( !nDiff )
            return nChg;
        else
            nBrowseAdd = nChg;
    }

    const SwFootnoteBossFrame *pBoss = static_cast<SwFootnoteBossFrame*>(GetUpper());

    SwTwips nReal = 0,
            nAdd  = 0;
    SwFrame *pFrame = nullptr;
    SwRectFnSet aRectFnSet(this);

    if( IsBodyFrame() )
    {
        if( IsInSct() )
        {
            SwSectionFrame *pSect = FindSctFrame();
            if( nDiff > 0 && pSect->IsEndnAtEnd() && GetNext() &&
                GetNext()->IsFootnoteContFrame() )
            {
                SwFootnoteContFrame* pCont = static_cast<SwFootnoteContFrame*>(GetNext());
                SwTwips nMinH = 0;
                SwFootnoteFrame* pFootnote = static_cast<SwFootnoteFrame*>(pCont->Lower());
                bool bFootnote = false;
                while( pFootnote )
                {
                    if( !pFootnote->GetAttr()->GetFootnote().IsEndNote() )
                    {
                        nMinH += aRectFnSet.GetHeight(pFootnote->getFrameArea());
                        bFootnote = true;
                    }
                    pFootnote = static_cast<SwFootnoteFrame*>(pFootnote->GetNext());
                }
                if( bFootnote )
                    nMinH += aRectFnSet.GetTop(pCont->getFramePrintArea());
                nReal = aRectFnSet.GetHeight(pCont->getFrameArea()) - nMinH;
                if( nReal > nDiff )
                    nReal = nDiff;
                if( nReal > 0 )
                    pFrame = GetNext();
                else
                    nReal = 0;
            }
            if( !bTst && !pSect->IsColLocked() )
                pSect->InvalidateSize();
        }
        if( !pFrame )
            return nBrowseAdd;
    }
    else
    {
        const bool bFootnotePage = pBoss->IsPageFrame() && static_cast<const SwPageFrame*>(pBoss)->IsFootnotePage();
        if ( bFootnotePage && !IsFootnoteContFrame() )
            pFrame = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoss->FindFootnoteCont()));
        if ( !pFrame )
            pFrame = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoss->FindBodyCont()));

        if ( !pFrame )
            return 0;

        //If not one is found, everything else is solved.
        nReal = aRectFnSet.GetHeight(pFrame->getFrameArea());
        if( nReal > nDiff )
            nReal = nDiff;
        if( !bFootnotePage )
        {
            //Respect the minimal boundary!
            if( nReal )
            {
                const SwTwips nMax = pBoss->GetVarSpace();
                if ( nReal > nMax )
                    nReal = nMax;
            }
            if( !IsFootnoteContFrame() && nDiff > nReal &&
                pFrame->GetNext() && pFrame->GetNext()->IsFootnoteContFrame()
                && ( pFrame->GetNext()->IsVertical() == IsVertical() )
                )
            {
                //If the Body doesn't return enough, we look for a footnote, if
                //there is one, we steal there accordingly.
                const SwTwips nAddMax = aRectFnSet.GetHeight(pFrame->GetNext()->getFrameArea());
                nAdd = nDiff - nReal;
                if ( nAdd > nAddMax )
                    nAdd = nAddMax;
                if ( !bTst )
                {
                    {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=95 G=94

¤ Dauer der Verarbeitung: 0.43 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.