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 158 kB image not shown  

Quelle  frmtool.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 <svx/svdpage.hxx>
#include <editeng/brushitem.hxx>
#include <editeng/shaditem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/lspcitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <sal/log.hxx>
#include <o3tl/deleter.hxx>
#include <osl/diagnose.h>

#include <drawdoc.hxx>
#include <fmtornt.hxx>
#include <fmthdft.hxx>
#include <fmtfsize.hxx>
#include <fmtsrnd.hxx>
#include <docary.hxx>
#include <lineinfo.hxx>
#include <swmodule.hxx>
#include <pagefrm.hxx>
#include <colfrm.hxx>
#include <fesh.hxx>
#include <viewimp.hxx>
#include <viewopt.hxx>
#include <dflyobj.hxx>
#include <dcontact.hxx>
#include <frmatr.hxx>
#include <frmtool.hxx>
#include <tabfrm.hxx>
#include <rowfrm.hxx>
#include <ftnfrm.hxx>
#include <txtfrm.hxx>
#include <notxtfrm.hxx>
#include <flyfrms.hxx>
#include <layact.hxx>
#include <pagedesc.hxx>
#include <section.hxx>
#include <sectfrm.hxx>
#include <node2lay.hxx>
#include <ndole.hxx>
#include <hints.hxx>
#include "layhelp.hxx"
#include <laycache.hxx>
#include <rootfrm.hxx>
#include <paratr.hxx>
#include <redline.hxx>
#include <sortedobjs.hxx>
#include <objectformatter.hxx>
#include <calbck.hxx>
#include <ndtxt.hxx>
#include <undobj.hxx>
#include <DocumentSettingManager.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentTimerAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentState.hxx>
#include <frameformats.hxx>
#include <boost/circular_buffer.hpp>
#include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
#include <officecfg/Office/Writer.hxx>

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

namespace {
    // FIXME: would likely better be a member of SwRootFrame instead of a global flag
    bool isFlyCreationSuppressed = false;
}
namespace sw {
    FlyCreationSuppressor::FlyCreationSuppressor(bool wasAlreadySuppressedAllowed)
        : m_wasAlreadySuppressed(isFlyCreationSuppressed)
    {
        (void)wasAlreadySuppressedAllowed;
        assert(wasAlreadySuppressedAllowed || !isFlyCreationSuppressed);
        isFlyCreationSuppressed = true;
    }
    FlyCreationSuppressor::~FlyCreationSuppressor()
    {
        isFlyCreationSuppressed = m_wasAlreadySuppressed;
    }
}

bool bObjsDirect = true;
bool bSetCompletePaintOnInvalidate = false;

sal_uInt8 StackHack::s_nCnt = 0;
bool StackHack::s_bLocked = false;

SwFrameNotify::SwFrameNotify( SwFrame *pF ) :
    mpFrame( pF ),
    maFrame( pF->getFrameArea() ),
    maPrt( pF->getFramePrintArea() ),
    mbInvaKeep( false ),
    mbValidSize( pF->isFrameAreaSizeValid() )
{
    if ( pF->IsTextFrame() )
    {
        mnFlyAnchorOfst = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( true );
        mnFlyAnchorOfstNoWrap = static_cast<SwTextFrame*>(pF)->GetBaseOffsetForFly( false );
    }
    else
    {
        mnFlyAnchorOfst = 0;
        mnFlyAnchorOfstNoWrap = 0;
    }

    mbHadFollow = pF->IsContentFrame() && static_cast<SwContentFrame*>(pF)->GetFollow();
}

SwFrameNotify::~SwFrameNotify()
{
    suppress_fun_call_w_exception(ImplDestroy());
}

void SwFrameNotify::ImplDestroy()
{
    SwRectFnSet aRectFnSet(mpFrame);
    const bool bAbsP = aRectFnSet.PosDiff(maFrame, mpFrame->getFrameArea());
    const bool bChgWidth =
            aRectFnSet.GetWidth(maFrame) != aRectFnSet.GetWidth(mpFrame->getFrameArea());
    const bool bChgHeight =
            aRectFnSet.GetHeight(maFrame)!=aRectFnSet.GetHeight(mpFrame->getFrameArea());
    const bool bChgFlyBasePos = mpFrame->IsTextFrame() &&
       ( ( mnFlyAnchorOfst != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( true ) ) ||
         ( mnFlyAnchorOfstNoWrap != static_cast<SwTextFrame*>(mpFrame)->GetBaseOffsetForFly( false ) ) );

    if ( mpFrame->IsFlowFrame() && !mpFrame->IsInFootnote() )
    {
        SwFlowFrame *pFlow = SwFlowFrame::CastFlowFrame( mpFrame );

        if ( !pFlow->IsFollow() )
        {
            if ( !mpFrame->GetIndPrev() )
            {
                if ( mbInvaKeep )
                {
                    SwFrame *pPre = pFlow->FindPrevIgnoreHidden();
                    if ( pPre && pPre->IsFlowFrame() )
                    {
                        // 1. pPre wants to keep with me:
                        bool bInvalidPrePos = SwFlowFrame::CastFlowFrame(pPre)->IsKeep(pPre->GetAttrSet()->GetKeep(), pPre->GetBreakItem())
                            && pPre->GetIndPrev();

                        // 2. pPre is a table and the last row wants to keep with me:
                        if ( !bInvalidPrePos && pPre->IsTabFrame() )
                        {
                            SwTabFrame* pPreTab = static_cast<SwTabFrame*>(pPre);
                            if ( pPreTab->GetFormat()->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP) )
                            {
                                SwRowFrame* pLastRow = static_cast<SwRowFrame*>(pPreTab->GetLastLower());
                                if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
                                    bInvalidPrePos = true;
                            }
                        }

                        if ( bInvalidPrePos )
                            pPre->InvalidatePos();
                    }
                }
            }
            else if ( !pFlow->HasFollow() )
            {
                tools::Long nOldHeight = aRectFnSet.GetHeight(maFrame);
                tools::Long nNewHeight = aRectFnSet.GetHeight(mpFrame->getFrameArea());
                if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
                    pFlow->CheckKeep();
            }
        }
    }

    if ( bAbsP )
    {
        mpFrame->SetCompletePaint();

        SwFrame* pNxt = mpFrame->GetIndNext();
        // #121888# - skip empty section frames
        while ( pNxt &&
                pNxt->IsSctFrame() && !static_cast<SwSectionFrame*>(pNxt)->GetSection() )
        {
            pNxt = pNxt->GetIndNext();
        }

        if ( pNxt )
        {
            pNxt->InvalidatePos();
            if (pNxt->IsTextFrame() && static_cast<SwTextFrame*>(pNxt)->IsUndersized())
            {   // tdf#137523 it could have more space at new pos
                pNxt->InvalidateSize();
                pNxt->Prepare(PrepareHint::AdjustSizeWithoutFormatting);
            }
        }
        else
        {
            // #104100# - correct condition for setting retouche
            // flag for vertical layout.
            if( mpFrame->IsRetoucheFrame() &&
                aRectFnSet.TopDist( maFrame, aRectFnSet.GetTop(mpFrame->getFrameArea()) ) > 0 )
            {
                mpFrame->SetRetouche();
            }

            // A fresh follow frame does not have to be invalidated, because
            // it is already formatted:
            if ( mbHadFollow || !mpFrame->IsContentFrame() || !static_cast<SwContentFrame*>(mpFrame)->GetFollow() )
            {
                if ( !mpFrame->IsTabFrame() || !static_cast<SwTabFrame*>(mpFrame)->GetFollow() )
                    mpFrame->InvalidateNextPos();
            }
        }
    }

    //For each resize of the background graphics is a repaint necessary.
    const bool bPrtWidth =
            aRectFnSet.GetWidth(maPrt) != aRectFnSet.GetWidth(mpFrame->getFramePrintArea());
    const bool bPrtHeight =
            aRectFnSet.GetHeight(maPrt)!=aRectFnSet.GetHeight(mpFrame->getFramePrintArea());
    if ( bPrtWidth || bPrtHeight )
    {
        bool bUseNewFillProperties(false);
        if (mpFrame->supportsFullDrawingLayerFillAttributeSet())
        {
            drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(mpFrame->getSdrAllFillAttributesHelper());
            if(aFillAttributes && aFillAttributes->isUsed())
            {
                bUseNewFillProperties = true;
                // use SetCompletePaint if needed
                if(aFillAttributes->needCompleteRepaint())
                {
                    mpFrame->SetCompletePaint();
                }
            }
        }
        if (!bUseNewFillProperties)
        {
            const SvxGraphicPosition ePos = mpFrame->GetAttrSet()->GetBackground().GetGraphicPos();
            if(GPOS_NONE != ePos && GPOS_TILED != ePos)
                mpFrame->SetCompletePaint();
        }
    }
    else
    {
        // #97597# - consider case that *only* margins between
        // frame and printing area has changed. Then, frame has to be repainted,
        // in order to force paint of the margin areas.
        if ( !bAbsP && (bChgWidth || bChgHeight) )
        {
            mpFrame->SetCompletePaint();
        }
    }

    const bool bPrtP = aRectFnSet.PosDiff( maPrt, mpFrame->getFramePrintArea() );
    if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
         bPrtWidth || bPrtHeight || bChgFlyBasePos )
    {
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
        if( mpFrame->IsAccessibleFrame() )
        {
            SwRootFrame *pRootFrame = mpFrame->getRootFrame();
            if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
                pRootFrame->GetCurrShell() )
            {
                pRootFrame->GetCurrShell()->Imp()->MoveAccessibleFrame( mpFrame, maFrame );
            }
        }
#endif

        // Notification of anchored objects
        if ( mpFrame->GetDrawObjs() )
        {
            const SwSortedObjs &rObjs = *mpFrame->GetDrawObjs();
            SwPageFrame* pPageFrame = nullptr;
            for (SwAnchoredObject* pObj : rObjs)
            {
                // OD 2004-03-31 #i26791# - no general distinction between
                // Writer fly frames and drawing objects
                bool bNotify = false;
                bool bNotifySize = false;
                SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
                if (!pContact)
                    continue;
                const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
                if ( !bAnchoredAsChar )
                {
                    // Notify object, which aren't anchored as-character:

                    // always notify objects, if frame position has changed
                    // or if the object is to-page|to-fly anchored.
                    if ( bAbsP ||
                         pContact->ObjAnchoredAtPage() ||
                         pContact->ObjAnchoredAtFly() )
                    {
                        bNotify = true;

                        // assure that to-fly anchored Writer fly frames are
                        // registered at the correct page frame, if frame
                        // position has changed.
                        if ( bAbsP && pContact->ObjAnchoredAtFly() &&
                             pObj->DynCastFlyFrame() !=  nullptr )
                        {
                            // determine to-fly anchored Writer fly frame
                            SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj);
                            // determine page frame of to-fly anchored
                            // Writer fly frame
                            SwPageFrame* pFlyPageFrame = pFlyFrame->FindPageFrame();
                            // determine page frame, if needed.
                            if ( !pPageFrame )
                            {
                                pPageFrame = mpFrame->FindPageFrame();
                            }
                            if ( pPageFrame != pFlyPageFrame )
                            {
                                OSL_ENSURE( pFlyPageFrame, "~SwFrameNotify: Fly from Nowhere" );
                                if( pFlyPageFrame )
                                    pFlyPageFrame->MoveFly( pFlyFrame, pPageFrame );
                                else
                                    pPageFrame->AppendFlyToPage( pFlyFrame );
                            }
                        }
                    }
                    // otherwise the objects are notified in dependence to
                    // its positioning and alignment
                    else
                    {
                        const SwFormatVertOrient& rVert =
                                        pContact->GetFormat()->GetVertOrient();
                        if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
                               rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
                               rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
                             ( bChgHeight || bPrtHeight ) )
                        {
                            bNotify = true;
                        }
                        if ( !bNotify )
                        {
                            const SwFormatHoriOrient& rHori =
                                        pContact->GetFormat()->GetHoriOrient();
                            if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
                                   rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
                                   rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
                                 ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
                            {
                                bNotify = true;
                            }
                        }
                    }
                }
                else if ( bPrtWidth )
                {
                    // Notify as-character anchored objects, if printing area
                    // width has changed.
                    bNotify = true;
                    bNotifySize = true;
                }

                // perform notification via the corresponding invalidations
                if ( bNotify )
                {
                    if ( auto pFlyFrame = pObj->DynCastFlyFrame() )
                    {
                        if ( bNotifySize )
                            pFlyFrame->InvalidateSize_();
                        // #115759# - no invalidation of
                        // position for as-character anchored objects.
                        if ( !bAnchoredAsChar )
                        {
                            pFlyFrame->InvalidatePos_();
                        }
                        pFlyFrame->Invalidate_();
                    }
                    else if ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) !=  nullptr )
                    {
                        // #115759# - no invalidation of
                        // position for as-character anchored objects.
                        if ( !bAnchoredAsChar )
                        {
                            pObj->InvalidateObjPos();
                        }
                    }
                    else
                    {
                        OSL_FAIL( " - unknown anchored object type." );
                    }
                }
            }
        }
    }
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
    else if( mpFrame->IsTextFrame() && mbValidSize != mpFrame->isFrameAreaSizeValid() )
    {
        SwRootFrame *pRootFrame = mpFrame->getRootFrame();
        if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
            pRootFrame->GetCurrShell() )
        {
            pRootFrame->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame );
        }
    }
#endif

    // #i9046# Automatic frame width
    SwFlyFrame* pFly = nullptr;
    // #i35879# Do not trust the inf flags. pFrame does not
    // necessarily have to have an upper!
    if ( mpFrame->IsFlyFrame() || nullptr == ( pFly = mpFrame->ImplFindFlyFrame() ))
        return;

    // #i61999#
    // no invalidation of columned Writer fly frames, because automatic
    // width doesn't make sense for such Writer fly frames.
    SwFrame* pLower = pFly->Lower();
    if ( !pLower || pLower->IsColumnFrame() )
        return;

    const SwFormatFrameSize &rFrameSz = pFly->GetFormat()->GetFrameSize();

    // This could be optimized. Basically the fly frame only has to
    // be invalidated, if the first line of pFrame (if pFrame is a content
    // frame, for other frame types it's the print area) has changed its
    // size and pFrame was responsible for the current width of pFly. On
    // the other hand, this is only rarely used and re-calculation of
    // the fly frame does not cause too much trouble. So we keep it this
    // way:
    if ( SwFrameSize::Fixed != rFrameSz.GetWidthSizeType() )
    {
        // #i50668#, #i50998# - invalidation of position
        // of as-character anchored fly frames not needed and can cause
        // layout loops
        if ( dynamic_cast<const SwFlyInContentFrame*>( pFly) ==  nullptr )
        {
            pFly->InvalidatePos();
        }
        pFly->InvalidateSize();
    }
}

SwLayNotify::SwLayNotify( SwLayoutFrame *pLayFrame ) :
    SwFrameNotify( pLayFrame ),
    m_bLowersComplete( false )
{
}

// OD 2004-05-11 #i28701# - local method to invalidate the position of all
// frames inclusive its floating screen objects, which are lowers of the given
// layout frame
static void lcl_InvalidatePosOfLowers( SwLayoutFrame& _rLayoutFrame )
{
    if( _rLayoutFrame.IsFlyFrame() && _rLayoutFrame.GetDrawObjs() )
    {
        _rLayoutFrame.InvalidateObjs( false );
    }

    SwFrame* pLowerFrame = _rLayoutFrame.Lower();
    while ( pLowerFrame )
    {
        pLowerFrame->InvalidatePos();
        if ( pLowerFrame->IsTextFrame() )
        {
            static_cast<SwTextFrame*>(pLowerFrame)->Prepare( PrepareHint::FramePositionChanged );
        }
        else if ( pLowerFrame->IsTabFrame() )
        {
            pLowerFrame->InvalidatePrt();
        }

        pLowerFrame->InvalidateObjs( false );

        pLowerFrame = pLowerFrame->GetNext();
    }
}

void SwLayNotify::ImplDestroy()
{
    SwLayoutFrame *pLay = static_cast<SwLayoutFrame*>(mpFrame);
    SwRectFnSet aRectFnSet(pLay);
    bool bNotify = false;
    if ( pLay->getFramePrintArea().SSize() != maPrt.SSize() )
    {
        if ( !IsLowersComplete() )
        {
            bool bInvaPercent;

            if ( pLay->IsRowFrame() )
            {
                bInvaPercent = true;
                tools::Long nNew = aRectFnSet.GetHeight(pLay->getFramePrintArea());
                if( nNew != aRectFnSet.GetHeight(maPrt) )
                     static_cast<SwRowFrame*>(pLay)->AdjustCells( nNew, true);
                if( aRectFnSet.GetWidth(pLay->getFramePrintArea())
                    != aRectFnSet.GetWidth(maPrt) )
                     static_cast<SwRowFrame*>(pLay)->AdjustCells( 0, false );
            }
            else
            {
                //Proportional adoption of the internal.
                //1. If the formatted is no Fly
                //2. If he contains no columns
                //3. If the Fly has a fixed height and the columns
                //   are next to be.
                //   Hoehe danebenliegen.
                //4. Never at SectionFrames.
                bool bLow;
                if( pLay->IsFlyFrame() )
                {
                    if ( pLay->Lower() )
                    {
                        bLow = !pLay->Lower()->IsColumnFrame() ||
                            aRectFnSet.GetHeight(pLay->Lower()->getFrameArea())
                             != aRectFnSet.GetHeight(pLay->getFramePrintArea());
                    }
                    else
                        bLow = false;
                }
                else if( pLay->IsSctFrame() )
                {
                    if ( pLay->Lower() )
                    {
                        if( pLay->Lower()->IsColumnFrame() && pLay->Lower()->GetNext() )
                            bLow = pLay->Lower()->getFrameArea().Height() != pLay->getFramePrintArea().Height();
                        else
                            bLow = pLay->getFramePrintArea().Width() != maPrt.Width();
                    }
                    else
                        bLow = false;
                }
                else if( pLay->IsFooterFrame() && !pLay->HasFixSize() )
                    bLow = pLay->getFramePrintArea().Width() != maPrt.Width();
                else
                    bLow = true;
                bInvaPercent = bLow;
                if ( bLow )
                {
                    pLay->ChgLowersProp( maPrt.SSize() );
                }
                // If the PrtArea has been extended, it might be possible that the chain of parts
                // can take another frame. As a result, the "possible right one" needs to be
                // invalidated. This only pays off if this or its Uppers are moveable sections.
                // A PrtArea has been extended if width or height are larger than before.
                if ( (pLay->getFramePrintArea().Height() > maPrt.Height() ||
                      pLay->getFramePrintArea().Width()  > maPrt.Width()) &&
                     (pLay->IsMoveable() || pLay->IsFlyFrame()) )
                {
                    SwFrame *pTmpFrame = pLay->Lower();
                    if ( pTmpFrame && pTmpFrame->IsFlowFrame() )
                    {
                        while ( pTmpFrame->GetNext() )
                            pTmpFrame = pTmpFrame->GetNext();
                        pTmpFrame->InvalidateNextPos();
                    }
                }
            }
            bNotify = true;
            //EXPENSIVE!! But how we do it more elegant?
            if( bInvaPercent )
                pLay->InvaPercentLowers( pLay->getFramePrintArea().Height() - maPrt.Height() );
        }
        if ( pLay->IsTabFrame() )
            //So that _only_ the shadow is drawn while resizing.
            static_cast<SwTabFrame*>(pLay)->SetComplete();
        else
        {
            const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell();
            if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
                  !(pLay->GetType() & (SwFrameType::Body | SwFrameType::Page)) )
            //Thereby the subordinates are retouched clean.
            //Example problem: Take the Flys with the handles and downsize.
            //Not for body and page, otherwise it flickers when loading HTML.
                pLay->SetCompletePaint();
        }
    }
    //Notify Lower if the position has changed.
    const bool bPrtPos = aRectFnSet.PosDiff( maPrt, pLay->getFramePrintArea() );
    const bool bPos = bPrtPos || aRectFnSet.PosDiff( maFrame, pLay->getFrameArea() );
    const bool bSize = pLay->getFrameArea().SSize() != maFrame.SSize();

    if ( bPos && pLay->Lower() && !IsLowersComplete() )
    {
        pLay->Lower()->InvalidatePos();
        SwFootnoteFrame* pFtnFrame = pLay->Lower()->IsFootnoteFrame() ?
            static_cast<SwFootnoteFrame*>(pLay->Lower()) : nullptr;
        SwFrame* pFtnLower = pFtnFrame ? pFtnFrame->Lower() : nullptr;
        if (pFtnLower)
            pFtnLower->InvalidatePos();
    }

    if ( bPrtPos )
        pLay->SetCompletePaint();

    //Inform the Follower if the SSize has changed.
    if ( bSize )
    {
        if( pLay->GetNext() )
        {
            if ( pLay->GetNext()->IsLayoutFrame() )
                pLay->GetNext()->InvalidatePos_();
            else
                pLay->GetNext()->InvalidatePos();
        }
        else if( pLay->IsSctFrame() )
            pLay->InvalidateNextPos();
    }

    SwFrame* pLower = pLay->Lower();
    if ( !IsLowersComplete() &&
         !(pLay->GetType()&(SwFrameType::Fly|SwFrameType::Section) &&
            pLower && pLower->IsColumnFrame()) &&
         (bPos || bNotify) &&
         !(pLay->GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FootnoteContainer|SwFrameType::Page|SwFrameType::Root)))
    {
        // #i44016# - force unlock of position of lower objects.
        // #i43913# - no unlock of position of objects,
        // if <pLay> is a cell frame, and its table frame resp. its parent table
        // frame is locked.
        // #i47458# - force unlock of position of lower objects,
        // only if position of layout frame has changed.
        bool bUnlockPosOfObjs( bPos );
        if ( bUnlockPosOfObjs && pLay->IsCellFrame() )
        {
            SwTabFrame* pTabFrame( pLay->FindTabFrame() );
            if ( pTabFrame &&
                 ( pTabFrame->IsJoinLocked() ||
                   ( pTabFrame->IsFollow() &&
                     pTabFrame->FindMaster()->IsJoinLocked() ) ) )
            {
                bUnlockPosOfObjs = false;
            }
        }
        // #i49383# - check for footnote frame, if unlock
        // of position of lower objects is allowed.
        else if ( bUnlockPosOfObjs && pLay->IsFootnoteFrame() )
        {
            bUnlockPosOfObjs = static_cast<SwFootnoteFrame*>(pLay)->IsUnlockPosOfLowerObjs();
        }
        // #i51303# - no unlock of object positions for sections
        else if ( bUnlockPosOfObjs && pLay->IsSctFrame() )
        {
            bUnlockPosOfObjs = false;
        }
        pLay->NotifyLowerObjs( bUnlockPosOfObjs );
    }
    if ( bPos && pLay->IsFootnoteFrame() && pLay->Lower() )
    {
        // OD 2004-05-11 #i28701#
        ::lcl_InvalidatePosOfLowers( *pLay );
    }
    if( ( bPos || bSize ) && pLay->IsFlyFrame() && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()
          && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()->IsFlyFrame() )
        static_cast<SwFlyFrame*>(pLay)->AnchorFrame()->InvalidateSize();
}

SwLayNotify::~SwLayNotify()
{
    suppress_fun_call_w_exception(ImplDestroy());
}

SwFlyNotify::SwFlyNotify( SwFlyFrame *pFlyFrame ) :
    SwLayNotify( pFlyFrame ),
    // #115759# - keep correct page frame - the page frame
    // the Writer fly frame is currently registered at.
    m_pOldPage( pFlyFrame->GetPageFrame() ),
    m_aFrameAndSpace( pFlyFrame->GetObjRectWithSpaces() )
{
}

void SwFlyNotify::ImplDestroy()
{
    SwFlyFrame *pFly = static_cast<SwFlyFrame*>(mpFrame);
    if ( pFly->IsNotifyBack() )
    {
        SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell();
        SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr;
        if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
        {
            //If in the LayAction the IsAgain is set it can be
            //that the old page is destroyed in the meantime!
            ::Notify( pFly, m_pOldPage, m_aFrameAndSpace, &maPrt );
            // #i35640# - additional notify anchor text frame,
            // if Writer fly frame has changed its page
            if ( pFly->GetAnchorFrame()->IsTextFrame() &&
                 pFly->GetPageFrame() != m_pOldPage )
            {
                pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
            }
        }
        pFly->ResetNotifyBack();
    }
    if (pFly->IsForceNotifyNewBackground())
    {
        pFly->NotifyBackground(pFly->FindPageFrame(), pFly->GetObjRectWithSpaces(), PrepareHint::FlyFrameArrive);
        pFly->SetForceNotifyNewBackground(false);
    }

    //Have the size or the position changed,
    //so should the view know this.
    SwRectFnSet aRectFnSet(pFly);
    const bool bPosChgd = aRectFnSet.PosDiff( maFrame, pFly->getFrameArea() );
    const bool bFrameChgd = pFly->getFrameArea().SSize() != maFrame.SSize();
    const bool bPrtChgd = maPrt != pFly->getFramePrintArea();
    if ( bPosChgd || bFrameChgd || bPrtChgd )
    {
        pFly->NotifyDrawObj();
    }
    if ( bPosChgd && maFrame.Pos().X() != FAR_AWAY )
    {
        // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
        // reason: New positioning and alignment (e.g. to-paragraph anchored,
        // but aligned at page) are introduced.
        // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
        // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.

        if ( pFly->IsFlyAtContentFrame() )
        {
            SwFrame *pNxt = pFly->AnchorFrame()->FindNext();
            while (pNxt)
            {
                pNxt->InvalidatePos();
                if (!pNxt->IsSctFrame())
                {
                    break;
                }
                // invalidating pos of a section frame doesn't have much
                // effect, so try again with its lower
                pNxt = static_cast<SwSectionFrame*>(pNxt)->Lower();
            }
        }

        // #i26945# - notify anchor.
        // Needed for negative positioned Writer fly frames
        if ( pFly->GetAnchorFrame()->IsTextFrame() )
        {
            pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
        }
    }

    // OD 2004-05-13 #i28701#
    // #i45180# - no adjustment of layout process flags and
    // further notifications/invalidations, if format is called by grow/shrink
    if ( !pFly->ConsiderObjWrapInfluenceOnObjPos() )
        return;
    if (pFly->IsFlyFreeFrame())
    {
        if (static_cast<SwFlyFreeFrame*>(pFly)->IsNoMoveOnCheckClip())
            return;
    }

    // #i54138# - suppress restart of the layout process
    // on changed frame height.
    // Note: It doesn't seem to be necessary and can cause layout loops.
    if ( bPosChgd )
    {
        // indicate a restart of the layout process
        pFly->SetRestartLayoutProcess( true );
    }
    else
    {
        // lock position
        pFly->LockPosition();
    }

    if ( pFly->ConsiderForTextWrap() )
        return;

    // indicate that object has to be considered for text wrap
    pFly->SetConsiderForTextWrap( true );
    // invalidate 'background' in order to allow its 'background'
    // to wrap around it.
    pFly->NotifyBackground( pFly->GetPageFrame(),
                            pFly->GetObjRectWithSpaces(),
                            PrepareHint::FlyFrameArrive );
    // invalidate position of anchor frame in order to force
    // a re-format of the anchor frame, which also causes a
    // re-format of the invalid previous frames of the anchor frame.
    pFly->AnchorFrame()->InvalidatePos();
}

SwFlyNotify::~SwFlyNotify()
{
    suppress_fun_call_w_exception(ImplDestroy());
}

SwContentNotify::SwContentNotify( SwContentFrame *pContentFrame ) :
    SwFrameNotify( pContentFrame ),
    // OD 08.01.2004 #i11859#
    mbChkHeightOfLastLine( false ),
    mnHeightOfLastLine( 0 ),
    // OD 2004-02-26 #i25029#
    mbInvalidatePrevPrtArea( false ),
    mbBordersJoinedWithPrev( false )
{
    // OD 08.01.2004 #i11859#
    if ( !pContentFrame->IsTextFrame() )
        return;

    SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pContentFrame);
    if (!pTextFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::OLD_LINE_SPACING))
    {
        const SvxLineSpacingItem &rSpace = pTextFrame->GetAttrSet()->GetLineSpacing();
        if ( rSpace.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop )
        {
            mbChkHeightOfLastLine = true;
            mnHeightOfLastLine = pTextFrame->GetHeightOfLastLine();
        }
    }
}

void SwContentNotify::ImplDestroy()
{
    SwContentFrame *pCnt = static_cast<SwContentFrame*>(mpFrame);
    if ( bSetCompletePaintOnInvalidate )
        pCnt->SetCompletePaint();

    SwRectFnSet aRectFnSet(pCnt);
    if ( pCnt->IsInTab() && ( aRectFnSet.PosDiff( pCnt->getFrameArea(), maFrame ) ||
                             pCnt->getFrameArea().SSize() != maFrame.SSize()))
    {
        SwLayoutFrame* pCell = pCnt->GetUpper();
        while( !pCell->IsCellFrame() && pCell->GetUpper() )
            pCell = pCell->GetUpper();
        OSL_ENSURE( pCell->IsCellFrame(), "Where's my cell?" );
        if ( text::VertOrientation::NONE != pCell->GetFormat()->GetVertOrient().GetVertOrient() )
            pCell->InvalidatePrt(); //for the vertical align.
    }

    // OD 2004-02-26 #i25029#
    if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
         pCnt->IsTextFrame() &&
         !pCnt->IsFollow() && !pCnt->GetIndPrev() )
    {
        // determine previous frame
        SwFrame* pPrevFrame = pCnt->FindPrev();
        // skip empty section frames and hidden text frames
        {
            while (pPrevFrame && pPrevFrame->IsHiddenNow())
            {
                pPrevFrame = pPrevFrame->FindPrev();
            }
        }

        // Invalidate printing area of found previous frame
        if ( pPrevFrame )
        {
            if ( pPrevFrame->IsSctFrame() )
            {
                if ( pCnt->IsInSct() )
                {
                    // Note: found previous frame is a section frame and
                    //       <pCnt> is also inside a section.
                    //       Thus due to <mbBordersJoinedWithPrev>,
                    //       <pCnt> had joined its borders/shadow with the
                    //       last content of the found section.
                    // Invalidate printing area of last content in found section.
                    SwFrame* pLstContentOfSctFrame =
                            static_cast<SwSectionFrame*>(pPrevFrame)->FindLastContent();
                    if ( pLstContentOfSctFrame )
                    {
                        pLstContentOfSctFrame->InvalidatePrt();
                    }
                }
            }
            else
            {
                pPrevFrame->InvalidatePrt();
            }
        }
    }

    const bool bFirst = aRectFnSet.GetWidth(maFrame) == 0;

    if ( pCnt->IsNoTextFrame() )
    {
        //Active PlugIn's or OLE-Objects should know something of the change
        //thereby they move their window appropriate.
        SwViewShell *pSh  = pCnt->getRootFrame()->GetCurrShell();
        if ( pSh )
        {
            SwOLENode *const pNd(static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetOLENode());
            if (nullptr != pNd &&
                 (pNd->GetOLEObj().IsOleRef() ||
                  pNd->IsOLESizeInvalid()) )
            {
                const bool bNoTextFramePrtAreaChanged =
                        ( maPrt.SSize().Width() != 0 &&
                          maPrt.SSize().Height() != 0 ) &&
                        maPrt.SSize() != pCnt->getFramePrintArea().SSize();
                OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrame" );
                SwFlyFrame *pFly = pCnt->FindFlyFrame();
                svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
                SwFEShell *pFESh = nullptr;
                for(SwViewShell& rCurrentShell : pSh->GetRingContainer())
                {   if ( dynamic_cast<const SwCursorShell*>( &rCurrentShell) !=  nullptr )
                    {
                        pFESh = static_cast<SwFEShell*>(&rCurrentShell);
                        // #108369#: Here used to be the condition if (!bFirst).
                        // I think this should mean "do not call CalcAndSetScale"
                        // if the frame is formatted for the first time.
                        // Unfortunately this is not valid anymore since the
                        // SwNoTextFrame already gets a width during CalcLowerPreps.
                        // Nevertheless, the indention of !bFirst seemed to be
                        // to assure that the OLE objects have already been notified
                        // if necessary before calling CalcAndSetScale.
                        // So I replaced !bFirst by !IsOLESizeInvalid. There is
                        // one additional problem specific to the word import:
                        // The layout is calculated _before_ calling PrtOLENotify,
                        // and the OLE objects are not invalidated during import.
                        // Therefore I added the condition !IsUpdateExpField,
                        // have a look at the occurrence of CalcLayout in
                        // uiview/view.cxx.
                        if ( !pNd->IsOLESizeInvalid() &&
                             !pSh->GetDoc()->getIDocumentState().IsUpdateExpField() )
                            pFESh->CalcAndSetScale( xObj,
                                                    &pFly->getFramePrintArea(), &pFly->getFrameArea(),
                                                    bNoTextFramePrtAreaChanged );
                    }
                }

                if ( pFESh && pNd->IsOLESizeInvalid() )
                {
                    pNd->SetOLESizeInvalid( false );
                    pFESh->CalcAndSetScale( xObj ); // create client
                }
            }
            // ditto animated graphics
            if ( getFrameArea().HasArea() && static_cast<SwNoTextFrame*>(pCnt)->HasAnimation() )
            {
                static_cast<SwNoTextFrame*>(pCnt)->StopAnimation();
                pSh->InvalidateWindows( getFrameArea() );
            }
        }
    }

    if ( bFirst )
    {
        pCnt->SetRetouche();    //fix(13870)

        SwDoc& rDoc = pCnt->IsTextFrame()
            ? static_cast<SwTextFrame*>(pCnt)->GetDoc()
            : static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetDoc();
        if ( !rDoc.GetSpzFrameFormats()->empty() &&
             rDoc.DoesContainAtPageObjWithContentAnchor() && !rDoc.getIDocumentState().IsNewDoc() )
        {
            // If certain import filters for foreign file format import
            // AT_PAGE anchored objects, the corresponding page number is
            // typically not known. In this case the content position is
            // stored at which the anchored object is found in the
            // imported document.
            // When this content is formatted it is the time at which
            // the page is known. Thus, this data can be corrected now.

            const SwPageFrame *pPage = nullptr;
            for(sw::SpzFrameFormat* pFormat: *rDoc.GetSpzFrameFormats())
            {
                const SwFormatAnchor &rAnch = pFormat->GetAnchor();
                if ( RndStdIds::FLY_AT_PAGE != rAnch.GetAnchorId() ||
                     rAnch.GetAnchorNode() == nullptr )
                {
                    continue;
                }

                if (FrameContainsNode(*pCnt, rAnch.GetAnchorNode()->GetIndex()))
                {
                    OSL_FAIL( " - to page anchored object with content position." );
                    if ( !pPage )
                    {
                        pPage = pCnt->FindPageFrame();
                    }
                    SwFormatAnchor aAnch( rAnch );
                    aAnch.SetAnchor( nullptr );
                    aAnch.SetPageNum( pPage->GetPhyPageNum() );
                    pFormat->SetFormatAttr( aAnch );
                    if ( RES_DRAWFRMFMT != pFormat->Which() )
                    {
                        pFormat->MakeFrames();
                    }
                }
            }
        }
    }

    // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
    //  if height of last line has changed.
    if ( pCnt->IsTextFrame() && mbChkHeightOfLastLine )
    {
        if ( mnHeightOfLastLine != static_cast<SwTextFrame*>(pCnt)->GetHeightOfLastLine() )
        {
            pCnt->InvalidateNextPrtArea();
        }
    }

    // #i44049#
    if ( pCnt->IsTextFrame() && aRectFnSet.PosDiff( maFrame, pCnt->getFrameArea() ) )
    {
        pCnt->InvalidateObjs();
    }

    // #i43255# - move code to invalidate at-character
    // anchored objects due to a change of its anchor character from
    // method <SwTextFrame::Format(..)>.
    if ( !pCnt->IsTextFrame() )
        return;

    SwTextFrame* pMasterFrame = pCnt->IsFollow()
                           ? static_cast<SwTextFrame*>(pCnt)->FindMaster()
                           : static_cast<SwTextFrame*>(pCnt);
    if ( pMasterFrame && !pMasterFrame->IsFlyLock() &&
         pMasterFrame->GetDrawObjs() )
    {
        SwSortedObjs* pObjs = pMasterFrame->GetDrawObjs();
        for (SwAnchoredObject* pAnchoredObj : *pObjs)
        {
            if ( pAnchoredObj->GetFrameFormat()->GetAnchor().GetAnchorId()
                    == RndStdIds::FLY_AT_CHAR )
            {
                pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrame->IsEmpty() );
            }
        }
    }
}

SwContentNotify::~SwContentNotify()
{
    suppress_fun_call_w_exception(ImplDestroy());
}

// note this *cannot* be static because it's a friend
void AppendObj(SwFrame *const pFrame, SwPageFrame *const pPage, SwFrameFormat *const pFormat, const SwFormatAnchor & rAnch)
{
            const bool bFlyAtFly = rAnch.GetAnchorId() == RndStdIds::FLY_AT_FLY; // LAYER_IMPL
            //Is a frame or a SdrObject described?
            const bool bSdrObj = RES_DRAWFRMFMT == pFormat->Which();
            // OD 23.06.2003 #108784# - append also drawing objects anchored
            // as character.
            const bool bDrawObjInContent = bSdrObj &&
                                         (rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR);

            if( !(bFlyAtFly ||
                (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) ||
                (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR) ||
                bDrawObjInContent) )
                return;

            SdrObject* pSdrObj = nullptr;
            if ( bSdrObj && nullptr == (pSdrObj = pFormat->FindSdrObject()) )
            {
                OSL_ENSURE( !bSdrObj, "DrawObject not found." );
                pFormat->GetDoc().DelFrameFormat( pFormat );
                return;
            }
            if ( pSdrObj )
            {
                if ( !pSdrObj->getSdrPageFromSdrObject() )
                {
                    pFormat->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0)->
                            InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
                }

                if (SwDrawContact* pNew = static_cast<SwDrawContact*>(GetUserCall( pSdrObj )))
                {
                    if ( !pNew->GetAnchorFrame() )
                    {
                        pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( nullptr )) );
                    }
                    // OD 19.06.2003 #108784# - add 'virtual' drawing object,
                    // if necessary. But control objects have to be excluded.
                    else if ( !::CheckControlLayer( pSdrObj ) &&
                              pNew->GetAnchorFrame() != pFrame &&
                              !pNew->GetDrawObjectByAnchorFrame( *pFrame ) )
                    {
                        SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj(*pFrame);
                        pFrame->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );

                        pDrawVirtObj->ActionChanged();
                    }
                }
            }
            else
            {
                SwFlyFrame *pFly;
                if( bFlyAtFly )
                    pFly = new SwFlyLayFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame );
                else
                    pFly = new SwFlyAtContentFrame( static_cast<SwFlyFrameFormat*>(pFormat), pFrame, pFrame );
                pFly->Lock();
                pFrame->AppendFly( pFly );
                pFly->Unlock();
                if ( pPage )
                    ::RegistFlys( pPage, pFly );
            }
}

static bool IsShown(SwNodeOffset const nIndex,
    const SwFormatAnchor & rAnch,
    std::vector<sw::Extent>::const_iterator const*const pIter,
    std::vector<sw::Extent>::const_iterator const*const pEnd,
    SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
{
    assert(!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex);
    SwNode* pAnchorNode = rAnch.GetAnchorNode();
    if (pAnchorNode->GetIndex() != nIndex)
    {
        return false;
    }
    if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA)
    {
        return pIter == nullptr // not merged
            || pIter != pEnd    // at least one char visible in node
            || !IsSelectFrameAnchoredAtPara(*rAnch.GetContentAnchor(),
                    SwPosition(*pFirstNode, 0),
                    SwPosition(*pLastNode, pLastNode->Len()));
    }
    if (pIter)
    {
        // note: frames are not sorted by anchor position.
        assert(pEnd);
        assert(pFirstNode);
        assert(pLastNode);
        assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY);
        if (*pIter == *pEnd && rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
        {   // tdf#149595 special case - it *could* be shown if first == last
            return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(),
                        SwPosition(*pFirstNode, 0),
                        SwPosition(*pLastNode, pLastNode->Len()));
        }
        for (auto iter = *pIter; iter != *pEnd; ++iter)
        {
            assert(iter->nStart != iter->nEnd); // TODO possible?
            assert(iter->pNode->GetIndex() == nIndex);
            if (rAnch.GetAnchorContentOffset() < iter->nStart)
            {
                return false;
            }
            if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
            {
                // if there is an extent then obviously the node was not
                // deleted fully...
                // show if start <= pos <= end
                // *or* if first-node/0  *and* not StartOfSection
                // *or* if last-node/Len *and* not EndOfSection

                // first determine the extent to compare to, then
                // construct start/end positions for the deletion *before* the
                // extent and compare once.
                // the interesting corner cases are on the edge of the extent!
                // no need to check for > the last extent because those
                // are never visible.
                if (rAnch.GetAnchorContentOffset() <= iter->nEnd)
                {
                    if (iter->nStart == 0)
                    {
                        return true;
                    }
                    else
                    {
                        SwPosition const start(
                            iter == *pIter
                                ? *pFirstNode // simplification
                                : *iter->pNode,
                            iter == *pIter // first extent?
                                ? iter->pNode == pFirstNode
                                    ? 0 // at start of 1st node
                                    : pFirstNode->Len() // previous node; simplification but should get right result
                                : (iter-1)->nEnd); // previous extent
                        SwPosition const end(*iter->pNode, iter->nStart);
                        return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(), start, end);
                    }
                }
                else if (iter == *pEnd - 1) // special case: after last extent
                {
                    if (iter->nEnd == iter->pNode->Len())
                    {
                        return true// special case: end of node
                    }
                    else
                    {
                        SwPosition const start(*iter->pNode, iter->nEnd);
                        SwPosition const end(
                            *pLastNode, // simplification
                            iter->pNode == pLastNode
                                ? iter->pNode->Len()
                                : 0);
                        return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(), start, end);
                   }
                }
            }
            else
            {
                assert(rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR);
                // for AS_CHAR obviously must be <
                if (rAnch.GetAnchorContentOffset() < iter->nEnd)
                {
                    return true;
                }
            }
        }
        return false;
    }
    else
    {
        return true;
    }
}

void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
    std::vector<sw::Extent>::const_iterator const*const pIter,
    std::vector<sw::Extent>::const_iterator const*const pEnd,
    SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
{
    std::vector<SwFrameFormat*> const & rFlys(rNode.GetAnchoredFlys());
    for (SwFrameFormat * pFrameFormat : rFlys)
    {
        SwFormatAnchor const& rAnchor = pFrameFormat->GetAnchor();
        if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
            || rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
        {
            assert(rAnchor.GetAnchorNode()->GetIndex() == rNode.GetIndex());
            if (!IsShown(rNode.GetIndex(), rAnchor, pIter, pEnd, pFirstNode, pLastNode))
            {
                pFrameFormat->DelFrames();
            }
        }
    }
}

void AppendObjsOfNode(sw::FrameFormats<sw::SpzFrameFormat*> const*const pTable, SwNodeOffset const nIndex,
    SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc& rDoc,
    std::vector<sw::Extent>::const_iterator const*const pIter,
    std::vector<sw::Extent>::const_iterator const*const pEnd,
    SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
{
#if OSL_DEBUG_LEVEL > 0
    std::vector<SwFrameFormat*> checkFormats;
    for(auto pFormat: *pTable)
    {
        const SwFormatAnchor &rAnch = pFormat->GetAnchor();
        if ( rAnch.GetAnchorNode() &&
            IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode))
        {
            checkFormats.push_back( pFormat );
        }
    }
#else
    (void)pTable;
#endif

    SwNode const& rNode(*rDoc.GetNodes()[nIndex]);
    std::vector<SwFrameFormat*> const & rFlys(rNode.GetAnchoredFlys());
    for (size_t it = 0; it != rFlys.size(); )
    {
        SwFrameFormat *const pFormat = rFlys[it];
        const SwFormatAnchor &rAnch = pFormat->GetAnchor();
        if ( rAnch.GetAnchorNode() &&
            IsShown(nIndex, rAnch, pIter, pEnd, pFirstNode, pLastNode))
        {
#if OSL_DEBUG_LEVEL > 0
            std::vector<SwFrameFormat*>::iterator checkPos = std::find( checkFormats.begin(), checkFormats.end(), pFormat );
            assert( checkPos != checkFormats.end());
            checkFormats.erase( checkPos );
#endif
            AppendObj(pFrame, pPage, pFormat, rAnch);
        }
        ++it;
    }

#if OSL_DEBUG_LEVEL > 0
    assert( checkFormats.empty());
#endif
}


void AppendObjs(const sw::FrameFormats<sw::SpzFrameFormat*> *const pTable, SwNodeOffset const nIndex,
        SwFrame *const pFrame, SwPageFrame *const pPage, SwDoc& rDoc)
{
    if (pFrame->IsTextFrame())
    {
        SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pFrame));
        if (sw::MergedPara const*const pMerged = pTextFrame->GetMergedPara())
        {
            std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin());
            std::vector<sw::Extent>::const_iterator iter(iterFirst);
            SwTextNode const* pNode(pMerged->pFirstNode);
            for ( ; ; ++iter)
            {
                if (iter == pMerged->extents.end()
                    || iter->pNode != pNode)
                {
                    AppendObjsOfNode(pTable, pNode->GetIndex(), pFrame, pPage, rDoc,
                        &iterFirst, &iter, pMerged->pFirstNode, pMerged->pLastNode);
                    SwNodeOffset const until = iter == pMerged->extents.end()
                        ? pMerged->pLastNode->GetIndex() + 1
                        : iter->pNode->GetIndex();
                    for (SwNodeOffset i = pNode->GetIndex() + 1; i < until; ++i)
                    {
                        // let's show at-para flys on nodes that contain start/end of
                        // redline too, even if there's no text there
                        SwNode const*const pTmp(pNode->GetNodes()[i]);
                        if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
                        {
                            AppendObjsOfNode(pTable, pTmp->GetIndex(), pFrame, pPage, rDoc, &iter, &iter, pMerged->pFirstNode, pMerged->pLastNode);
                        }
                    }
                    if (iter == pMerged->extents.end())
                    {
                        break;
                    }
                    pNode = iter->pNode;
                    iterFirst = iter;
                }
            }
        }
        else
        {
            return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, rDoc, nullptr, nullptr, nullptr, nullptr);
        }
    }
    else
    {
        return AppendObjsOfNode(pTable, nIndex, pFrame, pPage, rDoc, nullptr, nullptr, nullptr, nullptr);
    }
}

bool IsAnchoredObjShown(SwTextFrame const& rFrame, SwFormatAnchor const& rAnchor)
{
    assert(rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA ||
           rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR ||
           rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR);
    bool ret(true);
    if (auto const pMergedPara = rFrame.GetMergedPara())
    {
        ret = false;
        SwNode* pAnchorNode(rAnchor.GetAnchorNode());
        auto iterFirst(pMergedPara->extents.cbegin());
        if (iterFirst == pMergedPara->extents.end()
            && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
                || rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR))
        {
            ret = (pAnchorNode == pMergedPara->pFirstNode
                    && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
                        || rAnchor.GetAnchorContentOffset() == 0))
                || (pAnchorNode == pMergedPara->pLastNode
                    && (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA
                        || rAnchor.GetAnchorContentOffset() == pMergedPara->pLastNode->Len()));
        }
        auto iter(iterFirst);
        SwTextNode const* pNode(pMergedPara->pFirstNode);
        for ( ; ; ++iter)
        {
            if (iter == pMergedPara->extents.end()
                || iter->pNode != pNode)
            {
                assert(pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden);
                if (pNode == pAnchorNode)
                {
                    ret = IsShown(pNode->GetIndex(), rAnchor, &iterFirst, &iter,
                            pMergedPara->pFirstNode, pMergedPara->pLastNode);
                    break;
                }
                if (iter == pMergedPara->extents.end())
                {
                    break;
                }
                pNode = iter->pNode;
                if (pAnchorNode->GetIndex() < pNode->GetIndex())
                {
                    break;
                }
                iterFirst = iter;
            }
        }
    }
    return ret;
}

void AppendAllObjs(const sw::FrameFormats<sw::SpzFrameFormat*>* pTable, const SwFrame* pSib)
{
    //Connecting of all Objects, which are described in the SpzTable with the
    //layout.

    boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size());
    for(const auto& pFormat : *pTable)
    {
        const auto& rAnch = pFormat->GetAnchor();
        // Formats can still remain, because we neither use character bound
        // frames nor objects which are anchored to character bounds.
        if ((rAnch.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && (rAnch.GetAnchorId() != RndStdIds::FLY_AS_CHAR))
        {
            const SwNode* pAnchorNode = rAnch.GetAnchorNode();
            // formats in header/footer have no dependencies
            if(pAnchorNode && pFormat->GetDoc().IsInHeaderFooter(*pAnchorNode))
                pFormat->MakeFrames();
            else
                vFormatsToConnect.push_back(pFormat);
        }
    }
    const SwRootFrame* pRoot = pSib ? pSib->getRootFrame() : nullptr;
    const SwFrameFormat* pFirstRequeued(nullptr);
    while(!vFormatsToConnect.empty())
    {
        SwFrameFormat* pFormat = vFormatsToConnect.front();
        bool isConnected(false);
        pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot));
        if(!isConnected)
        {
            pFormat->MakeFrames();
            pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot));
        }
        // do this *before* push_back! the circular_buffer can be "full"!
        vFormatsToConnect.pop_front();
        if (!isConnected)
        {
            if(pFirstRequeued == pFormat)
                // If nothing happens anymore we can stop.
                break;
            if(!pFirstRequeued)
                pFirstRequeued = pFormat;
            assert(!vFormatsToConnect.full());
            vFormatsToConnect.push_back(pFormat);
        }
        else
        {
            pFirstRequeued = nullptr;
        }
    }
}

namespace sw {

void RecreateStartTextFrames(SwTextNode & rNode)
{
    std::vector<SwTextFrame*> frames;
    SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode);
    for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
    {
        if (pFrame->getRootFrame()->HasMergedParas())
        {
            frames.push_back(pFrame);
        }
    }
    auto eMode(sw::FrameMode::Existing);
    for (SwTextFrame * pFrame : frames)
    {
        // SplitNode could have moved the original frame to the start node
        // & created a new one on end, or could have created new frame on
        // start node... grab start node's frame and recreate MergedPara.
        SwTextNode & rFirstNode(pFrame->GetMergedPara()
            ? *pFrame->GetMergedPara()->pFirstNode
            : rNode);
        assert(rFirstNode.GetIndex() <= rNode.GetIndex());
        // clear old one first to avoid DelFrames confusing updates & asserts...
        pFrame->SetMergedPara(nullptr);
        pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
                    *pFrame, rFirstNode, eMode));
        eMode = sw::FrameMode::New// Existing is not idempotent!
        // note: this may or may not delete frames on the end node
    }
}

// namespace sw

/** local method to set 'working' position for newly inserted frames

    OD 12.08.2003 #i17969#
*/

static void lcl_SetPos( SwFrame&             _rNewFrame,
                 const SwLayoutFrame& _rLayFrame )
{
    SwRectFnSet aRectFnSet(&_rLayFrame);
    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(_rNewFrame);
    aRectFnSet.SetPos( aFrm, aRectFnSet.GetPos(_rLayFrame.getFrameArea()) );

    // move position by one SwTwip in text flow direction in order to get
    // notifications for a new calculated position after its formatting.
    if ( aRectFnSet.IsVert() )
    {
        aFrm.Pos().AdjustX( -1 );
    }
    else
    {
        aFrm.Pos().AdjustY(1 );
    }
}

void InsertCnt_( SwLayoutFrame *pLay, SwDoc& rDoc,
                             SwNodeOffset nIndex, bool bPages, SwNodeOffset nEndIndex,
                             SwFrame *pPrv, sw::FrameMode const eMode )
{
    rDoc.getIDocumentTimerAccess().BlockIdling();
    SwRootFrame* pLayout = pLay->getRootFrame();
    const bool bOldCallbackActionEnabled = pLayout && pLayout->IsCallbackActionEnabled();
    if( bOldCallbackActionEnabled )
        pLayout->SetCallbackActionEnabled( false );

    //In the generation of the Layout bPages=true will be handed over.
    //Then will be new pages generated all x paragraphs already times in advance.
    //On breaks and/or pagedescriptorchanges the corresponding will be generated
    //immediately.
    //The advantage is, that on one hand already a nearly realistic number of
    //pages are created, but above all there are no almost endless long chain
    //of paragraphs, which must be moved expensively until it reaches a tolerable
    //reduced level.
    //We'd like to think that 20 Paragraphs fit on one page.
    //So that it does not become in extreme situations so violent we calculate depending
    //on the node something to it.
    //If in the DocStatistic a usable given pagenumber
    //(Will be cared for while writing), so it will be presumed that this will be
    //number of pages.
    const bool bStartPercent = bPages && !nEndIndex;

    SwPageFrame *pPage = pLay->FindPageFrame();
    sw::SpzFrameFormats* pTable = rDoc.GetSpzFrameFormats();
    SwFrame       *pFrame = nullptr;
    std::unique_ptr<SwActualSection> pActualSection;
    std::unique_ptr<SwLayHelper> pPageMaker;

    //If the layout will be created (bPages == true) we do head on the progress
    //Flys and DrawObjects are not connected immediately, this
    //happens only at the end of the function.
    if ( bPages )
    {
        // Attention: the SwLayHelper class uses references to the content-,
        // page-, layout-frame etc. and may change them!
        pPageMaker.reset(new SwLayHelper( rDoc, pFrame, pPrv, pPage, pLay,
                pActualSection, nIndex, SwNodeOffset(0) == nEndIndex ));
        if( bStartPercent )
        {
            const sal_uLong nPageCount = pPageMaker->CalcPageCount();
            if( nPageCount )
                bObjsDirect = false;
        }
    }

    if( pLay->IsInSct() &&
        ( pLay->IsSctFrame() || pLay->GetUpper() ) ) // Hereby will newbies
            // be intercepted, of which flags could not determined yet,
            // for e.g. while inserting a table
    {
        SwSectionFrame* pSct = pLay->FindSctFrame();
        // If content will be inserted in a footnote, which in a column area,
        // the column area it is not allowed to be broken up.
        // Only if in the inner of the footnote lies an area, is this a candidate
        // for pActualSection.
        // The same applies for areas in tables, if inside the table will be
        // something inserted, it's only allowed to break up areas, which
        // lies in the inside also.
        if( ( !pLay->IsInFootnote() || pSct->IsInFootnote() ) &&
            ( !pLay->IsInTab() || pSct->IsInTab() ) )
        {
            pActualSection.reset(new SwActualSection(nullptr, pSct, pSct->GetSection()->GetFormat()->GetSectionNode()));
            // tdf#132236 for SwUndoDelete: find outer sections whose start
            // nodes aren't contained in the range but whose end nodes are,
            // because section frames may need to be created for them
            SwActualSection * pUpperSection(pActualSection.get());
            while (pUpperSection->GetSectionNode()->EndOfSectionIndex() < nEndIndex)
            {
                SwStartNode *const pStart(pUpperSection->GetSectionNode()->StartOfSectionNode());
                if (!pStart->IsSectionNode())
                {
                    break;
                }
                // note: these don't have a section frame, check it in EndNode case!
                auto const pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode*>(pStart)));
                pUpperSection->SetUpper(pTmp);
                pUpperSection = pTmp;
            }
            OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrame(),
                "InsertCnt_: Wrong Call" );
        }
    }

    //If a section is "open", the pActualSection points to an SwActualSection.
    //If the page breaks, for "open" sections a follow will created.
    //For nested sections (which have, however, not a nested layout),
    //the SwActualSection class has a member, which points to an upper(section).
    //When the "inner" section finishes, the upper will used instead.

    std::vector<SwSectionFrame *> newHiddenSections;

    // Do not consider the end node. The caller (Section/MakeFrames()) has to
    // ensure that the end of this range is positioned before EndIndex!
    for ( ; nEndIndex == SwNodeOffset(0) || nIndex < nEndIndex; ++nIndex)
    {
        assert(pLayout);
        SwNode *pNd = rDoc.GetNodes()[nIndex];
        if ( pNd->IsContentNode() )
        {
            SwContentNode* pNode = static_cast<SwContentNode*>(pNd);
            if (pLayout->HasMergedParas() && !pNd->IsCreateFrameWhenHidingRedlines())
            {
                if (pNd->IsTextNode()
                    && pNd->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
                {   // must have a frame already
                    assert(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara());
                }
                continue// skip it
            }
            pFrame = pNode->IsTextNode()
                        ? sw::MakeTextFrame(*pNode->GetTextNode(), pLay, eMode)
                        : pNode->MakeFrame(pLay);
            if (pPageMaker && !pLay->IsHiddenNow())
                pPageMaker->CheckInsert( nIndex );

            pFrame->InsertBehind( pLay, pPrv );
            if (!pPrv)
            {
--> --------------------

--> maximum size reached

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

Messung V0.5
C=89 H=95 G=91

¤ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ¤

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