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

Quelle  fefly1.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 <hintids.hxx>
#include <o3tl/any.hxx>
#include <svl/itemiter.hxx>
#include <vcl/imapobj.hxx>
#include <editeng/protitem.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdouno.hxx>
#include <tools/globname.hxx>
#include <sot/exchange.hxx>
#include <com/sun/star/form/FormButtonType.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <comphelper/types.hxx>
#include <osl/diagnose.h>
#include <comphelper/scopeguard.hxx>
#include <fmtanchr.hxx>
#include <fmtcntnt.hxx>
#include <fmtornt.hxx>
#include <fmturl.hxx>
#include <fmtfsize.hxx>
#include <fesh.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <cntfrm.hxx>
#include <txtfrm.hxx>
#include <viewimp.hxx>
#include <viscrs.hxx>
#include <doc.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentState.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <redline.hxx>
#include <dview.hxx>
#include <dflyobj.hxx>
#include <dcontact.hxx>
#include <frmfmt.hxx>
#include <flyfrm.hxx>
#include <ndtxt.hxx>
#include <swtable.hxx>
#include <ndgrf.hxx>
#include <flyfrms.hxx>
#include <fldbas.hxx>
#include <fmtfld.hxx>
#include <swundo.hxx>
#include <txatbase.hxx>
#include <frame.hxx>
#include <notxtfrm.hxx>
#include <HandleAnchorNodeChg.hxx>
#include <frmatr.hxx>
#include <fmtsrnd.hxx>
#include <ndole.hxx>
#include <fefly.hxx>
#include <fmtcnct.hxx>
#include <frameformats.hxx>
#include <textboxhelper.hxx>


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

// Based on the request, changes to the specific layouts will be made, to
// fit to the format
static bool lcl_SetNewFlyPos( const SwNode& rNode, SwFormatAnchor& rAnchor,
                        const Point& rPt )
{
    bool bRet = false;
    const SwStartNode* pStNode = rNode.FindFlyStartNode();
    if( pStNode )
    {
        SwPosition aPos( *pStNode );
        rAnchor.SetAnchor( &aPos );
        bRet = true;
    }
    else
    {
        const SwContentNode *pCntNd = rNode.GetContentNode();
        std::pair<Point, boolconst tmp(rPt, false);
        const SwContentFrame* pCFrame = pCntNd ? pCntNd->getLayoutFrame(
            pCntNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
            nullptr, &tmp) : nullptr;
        const SwPageFrame *pPg = pCFrame ? pCFrame->FindPageFrame() : nullptr;

        rAnchor.SetPageNum( pPg ? pPg->GetPhyPageNum() : 1 );
        rAnchor.SetType( RndStdIds::FLY_AT_PAGE );
    }
    return bRet;
}

static bool lcl_FindAnchorPos(
    SwDoc& rDoc,
    const Point& rPt,
    const SwFrame& rFrame,
    SfxItemSet& rSet )
{
    bool bRet = true;
    SwFormatAnchor aNewAnch( rSet.Get( RES_ANCHOR ) );
    RndStdIds nNew = aNewAnch.GetAnchorId();
    const SwFrame *pNewAnch;

    //determine new anchor
    Point aTmpPnt( rPt );
    switch( nNew )
    {
    case RndStdIds::FLY_AS_CHAR:  // also include this?
    case RndStdIds::FLY_AT_PARA:
    case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL
        {
            // starting from the upper-left corner of the Fly,
            // search nearest ContentFrame
            const SwFrame* pFrame = rFrame.IsFlyFrame() ? static_cast<const SwFlyFrame&>(rFrame).GetAnchorFrame()
                                                : &rFrame;
            pNewAnch = ::FindAnchor( pFrame, aTmpPnt );
            if( pNewAnch->IsProtected() )
            {
                bRet = false;
                break;
            }
            SwPosition aPos( pNewAnch->IsTextFrame()
                ? *static_cast<SwTextFrame const*>(pNewAnch)->GetTextNodeForParaProps()
                : *static_cast<const SwNoTextFrame*>(pNewAnch)->GetNode() );
            if ((RndStdIds::FLY_AT_CHAR == nNew) || (RndStdIds::FLY_AS_CHAR == nNew))
            {
                // textnode should be found, as only in those
                // a content bound frame can be anchored
                SwCursorMoveState aState( CursorMoveState::SetOnlyText );
                aTmpPnt.setX(aTmpPnt.getX() - 1);                   // do not land in the fly!
                if( !pNewAnch->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState ) )
                {
                    assert(pNewAnch->IsTextFrame()); // because AT_CHAR/AS_CHAR
                    SwTextFrame const*const pTextFrame(
                            static_cast<SwTextFrame const*>(pNewAnch));
                    if( pNewAnch->getFrameArea().Bottom() < aTmpPnt.Y() )
                    {
                        aPos = pTextFrame->MapViewToModelPos(TextFrameIndex(0));
                    }
                    else
                    {
                        aPos = pTextFrame->MapViewToModelPos(
                            TextFrameIndex(pTextFrame->GetText().getLength()));
                    }
                }
                else
                {
                    if ( SwCursorShell::PosInsideInputField( aPos ) )
                    {
                        aPos.SetContent( SwCursorShell::StartOfInputFieldAtPos( aPos ) );
                    }
                }
            }
            aNewAnch.SetAnchor( &aPos );
        }
        break;

    case RndStdIds::FLY_AT_FLY: // LAYER_IMPL
        {
            // starting from the upper-left corner of the Fly
            // search nearest SwFlyFrame
            SwCursorMoveState aState( CursorMoveState::SetOnlyText );
            SwPosition aPos( rDoc.GetNodes() );
            aTmpPnt.setX(aTmpPnt.getX() - 1);                   // do not land in the fly!
            rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( &aPos,&nbsp;aTmpPnt, &aState );
            pNewAnch = ::FindAnchor(
                aPos.GetNode().GetContentNode()->getLayoutFrame(rFrame.getRootFrame(), nullptr, nullptr),
                aTmpPnt )->FindFlyFrame();

            if( pNewAnch && &rFrame != pNewAnch && !pNewAnch->IsProtected() )
            {
                aPos.Assign( *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()->GetContent().
                                GetContentIdx() );
                aNewAnch.SetAnchor( &aPos );
                break;
            }
        }

        nNew = RndStdIds::FLY_AT_PAGE;
        aNewAnch.SetType( nNew );
        [[fallthrough]];

    case RndStdIds::FLY_AT_PAGE:
        pNewAnch = rFrame.FindPageFrame();
        aNewAnch.SetPageNum( pNewAnch->GetPhyPageNum() );
        break;

    default:
        OSL_ENSURE( false"Wrong Id for new anchor." );
    }

    rSet.Put( aNewAnch );
    return bRet;
}

//! also used in unoframe.cxx

bool sw_ChkAndSetNewAnchor(
    const SwFlyFrame& rFly,
    SfxItemSet& rSet )
{
    const SwFrameFormat& rFormat = *rFly.GetFormat();
    const SwFormatAnchor &rOldAnch = rFormat.GetAnchor();
    const RndStdIds nOld = rOldAnch.GetAnchorId();

    RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId();

    if( nOld == nNew )
        return false;

    SwDoc& rDoc = const_cast<SwDoc&>(rFormat.GetDoc());

#if OSL_DEBUG_LEVEL > 0
    OSL_ENSURE( !(nNew == RndStdIds::FLY_AT_PAGE &&
        (RndStdIds::FLY_AT_PARA==nOld || RndStdIds::FLY_AT_CHAR==nOld || RndStdIds::FLY_AS_CHAR==nOld ) &&
        rDoc.IsInHeaderFooter( *rOldAnch.GetAnchorNode() )),
            "forbidden anchor change in Head/Foot." );
#endif

    return ::lcl_FindAnchorPos( rDoc, rFly.getFrameArea().Pos(), rFly, rSet );
}

void SwFEShell::SelectFlyFrame( SwFlyFrame& rFrame )
{
    CurrShell aCurr( this );

    // The frame is new, thus select it.
    // !! Always select the frame, if it's not selected.
    // - it could be a new "old" one because the anchor was changed
    // - "old" frames have had to be selected previously otherwise they could
    //   not have been changed
    // The frames should not be selected by the document position, because
    // it should have been selected!
    SwViewShellImp *pImpl = Imp();
    if( !GetWin() )
        return;

    OSL_ENSURE( rFrame.IsFlyFrame(), "SelectFlyFrame wants a Fly" );

   // nothing to be done if the Fly already was selected
    if (GetSelectedFlyFrame() == &rFrame)
        return;

    // assure the anchor is drawn
    if( rFrame.IsFlyInContentFrame() && rFrame.GetAnchorFrame() )
         rFrame.GetAnchorFrame()->SetCompletePaint();

    if( pImpl->GetDrawView()->GetMarkedObjectList().GetMarkCount() != 0 )
        pImpl->GetDrawView()->UnmarkAll();

    pImpl->GetDrawView()->MarkObj( rFrame.GetVirtDrawObj(),
                                  pImpl->GetPageView() );

    rFrame.SelectionHasChanged(this);

    KillPams();
    ClearMark();
    SelFlyGrabCursor();
}

void SwFEShell::UnfloatFlyFrame()
{
    GetIDocumentUndoRedo().StartUndo(SwUndoId::DELLAYFMT, nullptr);
    comphelper::ScopeGuard g([this]
                             { GetIDocumentUndoRedo().EndUndo(SwUndoId::DELLAYFMT, nullptr); });

    SwFlyFrame* pFly = GetSelectedFlyFrame();
    if (!pFly)
    {
        return;
    }

    SwFrameFormat* pFlyFormat = pFly->GetFrameFormat();
    const SwFormatContent& rContent = pFlyFormat->GetContent();
    const SwNodeIndex* pFlyStart = rContent.GetContentIdx();
    if (!pFlyStart)
    {
        return;
    }

    const SwEndNode* pFlyEnd = pFlyStart->GetNode().EndOfSectionNode();
    if (!pFlyEnd)
    {
        return;
    }

    // Create an empty paragraph after the table, so the frame's SwNodes section is non-empty after
    // MoveNodeRange(). Undo would ensure it's non-empty and then node offsets won't match.
    IDocumentContentOperations& rIDCO = GetDoc()->getIDocumentContentOperations();
    {
        SwNodeIndex aInsertIndex(*pFlyEnd);
        --aInsertIndex;
        SwPosition aInsertPos(aInsertIndex);
        StartAllAction();
        rIDCO.AppendTextNode(aInsertPos);
        // Make sure that a layout frame is created for the node, so the fly frame is not deleted,
        // during MoveNodeRange(), either.
        EndAllAction();
    }

    SwNodeRange aRange(pFlyStart->GetNode(), SwNodeOffset(1), *pFlyEnd, SwNodeOffset(-1));
    const SwFormatAnchor& rAnchor = pFlyFormat->GetAnchor();
    SwNode* pAnchor = rAnchor.GetAnchorNode();
    if (!pAnchor)
    {
        return;
    }

    // Move the content outside of the text frame.
    SwNodeIndex aInsertPos(*pAnchor);
    rIDCO.MoveNodeRange(aRange, aInsertPos.GetNode(), SwMoveFlags::CREATEUNDOOBJ);

    // Remove the fly frame frame.
    IDocumentLayoutAccess& rIDLA = pFlyFormat->getIDocumentLayoutAccess();
    rIDLA.DelLayoutFormat(pFlyFormat);
}

// Get selected fly
SwFlyFrame* SwFEShell::GetSelectedFlyFrame() const
{
    if ( Imp()->HasDrawView() )
    {
        // A Fly is only accessible if it is selected
        const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
        if( rMrkList.GetMarkCount() != 1 )
            return nullptr;

        SdrObject *pO = rMrkList.GetMark( 0 )->GetMarkedSdrObj();

        SwVirtFlyDrawObj *pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pO);

        return pFlyObj ? pFlyObj->GetFlyFrame() : nullptr;
    }
    return nullptr;
}

// Get current fly in which the cursor is positioned
SwFlyFrame* SwFEShell::GetCurrFlyFrame(const bool bCalcFrame) const
{
    SwContentFrame *pContent = GetCurrFrame(bCalcFrame);
    return pContent ? pContent->FindFlyFrame() : nullptr;
}

// Get selected fly, but if none Get current fly in which the cursor is positioned
SwFlyFrame* SwFEShell::GetSelectedOrCurrFlyFrame() const
{
    SwFlyFrame *pFly = GetSelectedFlyFrame();
    if (pFly)
        return pFly;
    return GetCurrFlyFrame();
}

// Returns non-null pointer, if the current Fly could be anchored to another one (so it is inside)
const SwFrameFormat* SwFEShell::IsFlyInFly()
{
    CurrShell aCurr( this );

    if ( !Imp()->HasDrawView() )
        return nullptr;

    const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
    if ( !rMrkList.GetMarkCount() )
    {
        SwFlyFrame *pFly = GetCurrFlyFrame(false);
        if (!pFly)
            return nullptr;
        return pFly->GetFormat();
    }
    else if ( rMrkList.GetMarkCount() != 1 )
        return nullptr;

    SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
    SwContact* pContact = GetUserCall( pObj );
    if (!pContact)
        return nullptr;

    SwFrameFormat *pFormat = FindFrameFormat( pObj );
    if( pFormat && RndStdIds::FLY_AT_FLY == pFormat->GetAnchor().GetAnchorId() )
    {
        const SwFrame* pFly;
        if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj *>(pObj))
        {
            pFly = pFlyObj->GetFlyFrame()->GetAnchorFrame();
        }
        else
        {
            pFly = static_cast<SwDrawContact*>(pContact)->GetAnchorFrame(pObj);
        }

        assert(pFly && "IsFlyInFly: Where's my anchor?");
        OSL_ENSURE( pFly->IsFlyFrame(), "IsFlyInFly: Funny anchor!" );
        return static_cast<const SwFlyFrame*>(pFly)->GetFormat();
    }

    Point aTmpPos = pObj->GetCurrentBoundRect().TopLeft();

    SwFrame *pTextFrame;
    {
        SwCursorMoveState aState( CursorMoveState::SetOnlyText );
        SwNodeIndex aSwNodeIndex( GetDoc()->GetNodes() );
        SwPosition aPos( aSwNodeIndex );
        Point aPoint( aTmpPos );
        aPoint.setX(aPoint.getX() - 1);                    //do not land in the fly!!
        GetLayout()->GetModelPositionForViewPoint( &aPos, aPoint, &aState );
        // determine text frame by left-top-corner of object
        SwContentNode *pNd = aPos.GetNode().GetContentNode();
        std::pair<Point, boolconst tmp(aTmpPos, false);
        pTextFrame = pNd ? pNd->getLayoutFrame(GetLayout(), nullptr, &tmp) : nullptr;
    }
    const SwFrame *pTmp = pTextFrame ? ::FindAnchor(pTextFrame, aTmpPos) : nullptr;
    const SwFlyFrame *pFly = pTmp ? pTmp->FindFlyFrame() : nullptr;
    if( pFly )
        return pFly->GetFormat();
    return nullptr;
}

void SwFEShell::SetFlyPos( const Point& rAbsPos )
{
    CurrShell aCurr( this );

    // Determine reference point in document coordinates
    SwFlyFrame *pFly = GetCurrFlyFrame(false);
    if (!pFly)
        return;

    //SwSaveHdl aSaveX( Imp() );

    // Set an anchor starting from the absolute position for paragraph bound Flys
    // Anchor and new RelPos will be calculated and set by the Fly
    if ( pFly->IsFlyAtContentFrame() )
    {
        if(pFly->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(pFly)->isTransformableSwFrame())
        {
            // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
            // we need to correct the absolute position (rAbsPos) which was created in
            // transformed coordinates to untransformed state
            TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(pFly)->getTransformableSwFrame());
            const SwRect aUntransformedFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
            const Point aNewAbsPos(
                rAbsPos.X() + aUntransformedFrameArea.Left() - pFly->getFrameArea().Left(),
                rAbsPos.Y() + aUntransformedFrameArea.Top() - pFly->getFrameArea().Top());
            static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos(aNewAbsPos);
        }
        else
        {
            static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos );
        }
    }
    else
    {
        const SwFrame *pAnch = pFly->GetAnchorFrame();
        Point aOrient( pAnch->getFrameArea().Pos() );

        if ( pFly->IsFlyInContentFrame() )
            aOrient.setX(rAbsPos.getX());

        // calculate RelPos.
        aOrient.setX(rAbsPos.getX() - aOrient.getX());
        aOrient.setY(rAbsPos.getY() - aOrient.getY());
        pFly->ChgRelPos( aOrient );
    }
    CallChgLnk();       // call the AttrChangeNotify on the UI-side.
}

Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool bMoveIt )
{
    Point aRet;

    CurrShell aCurr( this );

    if ( !Imp()->HasDrawView() )
        return aRet;

    const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
    if (rMrkList.GetMarkCount() != 1)
        return aRet;

    SdrObject* pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();

    SwContact* pContact = ::GetUserCall( pObj );
    if (!pContact)
        return aRet;

    assert(pObj);

    // #i28701#
    SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( pObj );
    SwFrameFormat* pFormat = pAnchoredObj->GetFrameFormat();
    const RndStdIds nAnchorId = pFormat->GetAnchor().GetAnchorId();

    if ( RndStdIds::FLY_AS_CHAR == nAnchorId )
        return aRet;

    bool bFlyFrame = dynamic_cast<SwVirtFlyDrawObj *>(pObj) != nullptr;

    bool bTextBox = false;
    if (pFormat->Which() == RES_DRAWFRMFMT)
    {
        bTextBox = SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT, pObj);
    }

    SwFlyFrame* pFly = nullptr;
    const SwFrame* pFooterOrHeader = nullptr;

    if( bFlyFrame )
    {
        // Calculate reference point in document coordinates
        SwContentFrame *pContent = GetCurrFrame( false );
        if( !pContent )
            return aRet;
        pFly = pContent->FindFlyFrame();
        if ( !pFly )
            return aRet;
        const SwFrame* pOldAnch = pFly->GetAnchorFrame();
        if( !pOldAnch )
            return aRet;
        if ( RndStdIds::FLY_AT_PAGE != nAnchorId )
        {
            pFooterOrHeader = pContent->FindFooterOrHeader();
        }
    }
    else if (bTextBox)
    {
        auto pFlyFormat
            = dynamic_cast<const SwFlyFrameFormat*>(SwTextBoxHelper::getOtherTextBoxFormat(
                pFormat, RES_DRAWFRMFMT, pObj));
        if (pFlyFormat)
        {
            pFly = pFlyFormat->GetFrame();
        }
    }

    // set <pFooterOrHeader> also for drawing
    // objects, but not for control objects.
    // Necessary for moving 'anchor symbol' at the user interface inside header/footer.
    else if ( !::CheckControlLayer( pObj ) )
    {
        SwContentFrame *pContent = GetCurrFrame( false );
        if( !pContent )
            return aRet;
        pFooterOrHeader = pContent->FindFooterOrHeader();
    }

    // Search nearest SwFlyFrame starting from the upper-left corner
    // of the fly
    SwContentFrame *pTextFrame = nullptr;
    {
        SwCursorMoveState aState( CursorMoveState::SetOnlyText );
        SwPosition aPos( GetDoc()->GetNodes().GetEndOfExtras() );
        Point aTmpPnt( rAbsPos );
        GetLayout()->GetModelPositionForViewPoint( &aPos, aTmpPnt, &aState );
        if (aPos.GetNode() != GetDoc()->GetNodes().GetEndOfExtras()
            && (nAnchorId != RndStdIds::FLY_AT_CHAR || !PosInsideInputField(aPos)))
        {
            SwContentNode* pCNode = aPos.GetNode().GetContentNode();
            assert(pCNode);
            pTextFrame = pCNode->getLayoutFrame(GetLayout(), &aPos, nullptr);
        }
    }
    const SwFrame *pNewAnch = nullptr;
    if( pTextFrame != nullptr )
    {
        if ( RndStdIds::FLY_AT_PAGE == nAnchorId )
        {
            pNewAnch = pTextFrame->FindPageFrame();
        }
        else
        {
            pNewAnch = ::FindAnchor( pTextFrame, rAbsPos );

            if( RndStdIds::FLY_AT_FLY == nAnchorId ) // LAYER_IMPL
            {
                pNewAnch = pNewAnch->FindFlyFrame();
            }
        }
    }

    if( pNewAnch && !pNewAnch->IsProtected() )
    {
        const SwFlyFrame* pCheck = (bFlyFrame || bTextBox) ? pNewAnch->FindFlyFrame() : nullptr;
        // If we land inside the frame, make sure
        // that the frame does not land inside its own content
        while( pCheck )
        {
            if( pCheck == pFly )
                break;
            const SwFrame *pTmp = pCheck->GetAnchorFrame();
            pCheck = pTmp ? pTmp->FindFlyFrame() : nullptr;
        }

        // Do not switch from header/footer to another area,
        // do not switch to a header/footer
        if( !pCheck &&
            pFooterOrHeader == pNewAnch->FindFooterOrHeader() )
        {
            aRet = pNewAnch->GetFrameAnchorPos( ::HasWrap( pObj ) );

            if ( bMoveIt || (nAnchorId == RndStdIds::FLY_AT_CHAR) )
            {
                SwFormatAnchor aAnch( pFormat->GetAnchor() );
                switch ( nAnchorId )
                {
                    case RndStdIds::FLY_AT_PARA:
                    {
                        SwPosition pos(pTextFrame->IsTextFrame()
                            ? *static_cast<SwTextFrame const*>(pTextFrame)->GetTextNodeForParaProps()
                            : *static_cast<const SwNoTextFrame*>(pTextFrame)->GetNode());
                        aAnch.SetAnchor( &pos );
                        break;
                    }
                    case RndStdIds::FLY_AT_PAGE:
                    {
                        aAnch.SetPageNum( static_cast<const SwPageFrame*>(pNewAnch)->
                                          GetPhyPageNum() );
                        break;
                    }

                    case RndStdIds::FLY_AT_FLY:
                    {
                        SwPosition aPos( *static_cast<const SwFlyFrame*>(pNewAnch)->GetFormat()->
                                                  GetContent().GetContentIdx() );
                        aAnch.SetAnchor( &aPos );
                        break;
                    }

                    case RndStdIds::FLY_AT_CHAR:
                        {
                            SwPosition pos = *aAnch.GetContentAnchor();
                            Point aTmpPnt( rAbsPos );
                            if( pTextFrame->GetModelPositionForViewPoint( &pos, aTmpPnt ) )
                            {
                                SwRect aTmpRect;
                                pTextFrame->GetCharRect( aTmpRect, pos );
                                aRet = aTmpRect.Pos();
                            }
                            else
                            {
                                pos = static_cast<SwTextFrame const*>(pTextFrame)->MapViewToModelPos(TextFrameIndex(0));
                            }
                            aAnch.SetAnchor( &pos );
                            break;
                        }
                    default:
                        break;

                }

                if( bMoveIt )
                {
                    StartAllAction();
                    // --> handle change of anchor node:
                    // if count of the anchor frame also change, the fly frames have to be
                    // re-created. Thus, delete all fly frames except the <this> before the
                    // anchor attribute is change and re-create them afterwards.
                    {
                        std::unique_ptr<SwHandleAnchorNodeChg> pHandleAnchorNodeChg;
                        SwFlyFrameFormat* pFlyFrameFormat( dynamic_cast<SwFlyFrameFormat*>(pFormat) );
                        if ( pFlyFrameFormat )
                        {
                            pHandleAnchorNodeChg.reset(
                                new SwHandleAnchorNodeChg( *pFlyFrameFormat, aAnch ));
                        }
                        pFormat->GetDoc().SetAttr( aAnch, *pFormat );
                        if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT,
                            pObj))
                        {
                            if (SdrObjList* pObjList = pObj->getChildrenOfSdrObject())
                            {
                                for (const rtl::Reference<SdrObject>& pChild : *pObjList)
                                    SwTextBoxHelper::changeAnchor(pFormat, pChild.get());
                            }
                            else
                                SwTextBoxHelper::syncFlyFrameAttr(
                                    *pFormat, pFormat->GetAttrSet(), pObj);
                        }
                    }
                    // #i28701# - no call of method
                    // <CheckCharRectAndTopOfLine()> for to-character anchored
                    // Writer fly frame needed. This method call can cause a
                    // format of the anchor frame, which is no longer intended.
                    // Instead clear the anchor character rectangle and
                    // the top of line values for all to-character anchored objects.
                    pAnchoredObj->ClearCharRectAndTopOfLine();
                    EndAllAction();
                }
            }

            SwRect aTmpRect( aRet, rAbsPos );
            if( aTmpRect.HasArea() )
                MakeVisible( aTmpRect );
#if OSL_DEBUG_LEVEL > 0
            //TODO: That doesn't seem to be intended
            if( COL_TRANSPARENT != GetOut()->GetLineColor() )
            {
                OSL_FAIL( "Hey, Joe: Where's my Null Pen?" );
                GetOut()->SetLineColor( COL_TRANSPARENT );
            }
#endif
        }
    }

    return aRet;
}

const SwFrameFormat *SwFEShell::NewFlyFrame( const SfxItemSet& rSet, bool bAnchValid,
                           SwFrameFormat *pParent )
{
    CurrShell aCurr( this );
    StartAllAction();

    SwPaM* pCursor = GetCursor();
    const Point aPt( GetCursorDocPos() );

    SwSelBoxes aBoxes;
    bool bMoveContent = true;
    if( IsTableMode() )
    {
        GetTableSel( *this, aBoxes );
        if( !aBoxes.empty() )
        {
            // Cursor should be removed from the removal area.
            // Always put it after/on the table; via the
            // document position they will be set to the old
            // position
            ParkCursor( *aBoxes[0]->GetSttNd() );

            // #i127787# pCurrentCursor will be deleted in ParkCursor,
            // we better get the current pCurrentCursor instead of working with the
            // deleted one:
            pCursor = GetCursor();
        }
        else
            bMoveContent = false;
    }
    else if( !pCursor->HasMark() && !pCursor->IsMultiSelection() )
        bMoveContent = false;

    const SwPosition& rPos = *pCursor->Start();

    SwFormatAnchor& rAnch = const_cast<SwFormatAnchor&>(rSet.Get( RES_ANCHOR ));
    RndStdIds eRndId = rAnch.GetAnchorId();
    switch( eRndId )
    {
    case RndStdIds::FLY_AT_PAGE:
        if( !rAnch.GetPageNum() )       //HotFix: Bug in UpdateByExample
            rAnch.SetPageNum( 1 );
        break;

    case RndStdIds::FLY_AT_FLY:
    case RndStdIds::FLY_AT_PARA:
    case RndStdIds::FLY_AT_CHAR:
    case RndStdIds::FLY_AS_CHAR:
        if( !bAnchValid )
        {
            if( RndStdIds::FLY_AT_FLY != eRndId )
            {
                rAnch.SetAnchor( &rPos );
            }
            else if( lcl_SetNewFlyPos( rPos.GetNode(), rAnch, aPt ) )
            {
                eRndId = RndStdIds::FLY_AT_PAGE;
            }
        }
        break;

    default:
        OSL_ENSURE( false"What is the purpose of this Fly?" );
        break;
    }

    SwFlyFrameFormat *pRet;
    if( bMoveContent )
    {
        GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSLAYFMT, nullptr );
        std::unique_ptr<SwFormatAnchor> pOldAnchor;
        bool bHOriChgd = false, bVOriChgd = false;
        std::shared_ptr<SwFormatVertOrient> aOldV;
        std::shared_ptr<SwFormatHoriOrient> aOldH;

        if ( RndStdIds::FLY_AT_PAGE != eRndId )
        {
           // First as with page link. Paragraph/character link on if
            // everything was shifted. Then the position is valid!
            // JP 13.05.98: if necessary also convert the horizontal/vertical
            //              orientation, to prevent correction during re-anchoring
            pOldAnchor.reset(new SwFormatAnchor( rAnch ));
            const_cast<SfxItemSet&>(rSet).Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, 1 ) );

            const SwFormatHoriOrient* pHoriOrientItem;
            if( (pHoriOrientItem = rSet.GetItemIfSet( RES_HORI_ORIENT, false ))
                && text::HoriOrientation::NONE == pHoriOrientItem->GetHoriOrient() )
            {
                bHOriChgd = true;
                aOldH.reset(pHoriOrientItem->Clone());
                const_cast<SfxItemSet&>(rSet).Put( SwFormatHoriOrient( 0, text::HoriOrientation::LEFT ) );
            }
            const SwFormatVertOrient* pVertOrientItem;
            if( (pVertOrientItem = rSet.GetItemIfSet( RES_VERT_ORIENT, false ))
                && text::VertOrientation::NONE == pVertOrientItem->GetVertOrient() )
            {
                bVOriChgd = true;
                aOldV.reset(pVertOrientItem->Clone());
                const_cast<SfxItemSet&>(rSet).Put( SwFormatVertOrient( 0, text::VertOrientation::TOP ) );
            }
        }

        pRet = GetDoc()->MakeFlyAndMove( *pCursor, rSet, &aBoxes, pParent );

        KillPams();

        if( pOldAnchor )
        {
            if( pRet )
            {
                // calculate new position
                // JP 24.03.97: also go via page links
                //              anchor should not lie in the shifted area
                pRet->DelFrames();

                const SwFrame* pAnch = ::FindAnchor( GetLayout(), aPt );
                SwPosition aPos( pAnch->IsTextFrame()
                    ? *static_cast<SwTextFrame const*>(pAnch)->GetTextNodeForParaProps()
                    : *static_cast<const SwNoTextFrame*>(pAnch)->GetNode() );

                if ( RndStdIds::FLY_AS_CHAR == eRndId )
                {
                    assert(pAnch->IsTextFrame());
                    aPos = static_cast<SwTextFrame const*>(pAnch)->MapViewToModelPos(TextFrameIndex(0));
                }
                pOldAnchor->SetAnchor( &aPos );

                // shifting of table selection is not Undo-capable. therefore
                // changing the anchors should not be recorded
                bool const bDoesUndo =
                    GetDoc()->GetIDocumentUndoRedo().DoesUndo();
                SwUndoId nLastUndoId(SwUndoId::EMPTY);
                if (bDoesUndo &&
                    GetDoc()->GetIDocumentUndoRedo().GetLastUndoInfo(nullptr,
                        & nLastUndoId))
                {
                    if (SwUndoId::INSLAYFMT == nLastUndoId)
                    {
                        GetDoc()->GetIDocumentUndoRedo().DoUndo(false);
                    }
                }

                const_cast<SfxItemSet&>(rSet).Put( std::move(pOldAnchor) );

                if( bHOriChgd )
                    const_cast<SfxItemSet&>(rSet).Put( *aOldH );
                if( bVOriChgd )
                    const_cast<SfxItemSet&>(rSet).Put( *aOldV );

                GetDoc()->SetFlyFrameAttr( *pRet, const_cast<SfxItemSet&>(rSet) );
                GetDoc()->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
            }
        }
        GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSLAYFMT, nullptr );
    }
    else
        /* If called from a shell try to propagate an
            existing adjust item from rPos to the content node of the
            new frame. */

        pRet = GetDoc()->MakeFlySection( eRndId, &rPos, &rSet, pParent, true );

    if( pRet )
    {
        SwFlyFrame* pFrame = pRet->GetFrame( &aPt );
        if( pFrame )
            SelectFlyFrame( *pFrame );
        else
        {
            GetLayout()->SetAssertFlyPages();
            pRet = nullptr;
        }
    }
    EndAllActionAndCall();

    return pRet;
}

namespace
{
/// If pCursor points to an as-char anchored graphic node, then set the node's anchor position on
/// pAnchor and rPam.
bool SetAnchorOnGrfNodeForAsChar(SwShellCursor *pCursor, SwFormatAnchor* pAnchor, std::optional<SwPaM>& rPam)
{
    const SwPosition* pPoint = pCursor->GetPoint();
    if (pAnchor->GetAnchorId() != RndStdIds::FLY_AS_CHAR)
    {
        return false;
    }

    if (!pPoint->GetNode().IsGrfNode())
    {
        return false;
    }

    SwFrameFormat* pFrameFormat = pPoint->GetNode().GetFlyFormat();
    if (!pFrameFormat)
    {
        return false;
    }

    const SwPosition* pContentAnchor = pFrameFormat->GetAnchor().GetContentAnchor();
    if (!pContentAnchor)
    {
        return false;
    }

    SwPosition aPosition(*pContentAnchor);
    ++aPosition.nContent;
    pAnchor->SetAnchor(&aPosition);
    rPam.emplace(aPosition);
    return true;
}
}

void SwFEShell::Insert( const OUString& rGrfName, const OUString& rFltName,
                        const Graphic* pGraphic,
                        const SfxItemSet* pFlyAttrSet )
{
    SwFlyFrameFormat* pFormat = nullptr;
    CurrShell aCurr( this );
    StartAllAction();
    SwShellCursor *pStartCursor = dynamic_cast<SwShellCursor*>(GetCursor());
    SwShellCursor *pCursor = pStartCursor;
    do
    {
        if (!pCursor)
            break;

        // Has the anchor not been set or been set incompletely?
        std::optional<SwPaM> oPam;
        if( pFlyAttrSet )
        {
            ifconst SwFormatAnchor* pItem = pFlyAttrSet->GetItemIfSet( RES_ANCHOR, false ) )
            {
                SwFormatAnchor* pAnchor = const_cast<SwFormatAnchor*>(pItem);
                switch( pAnchor->GetAnchorId())
                {
                case RndStdIds::FLY_AT_PARA:
                case RndStdIds::FLY_AT_CHAR: // LAYER_IMPL
                case RndStdIds::FLY_AS_CHAR:
                    if( !pAnchor->GetAnchorNode() )
                    {
                        if (SetAnchorOnGrfNodeForAsChar(pCursor, pAnchor, oPam))
                        {
                            // Don't anchor the image on the previous image, rather insert them next
                            // to each other.
                            break;
                        }

                        pAnchor->SetAnchor( pCursor->GetPoint() );
                    }
                    break;
                case RndStdIds::FLY_AT_FLY:
                    if( !pAnchor->GetAnchorNode() )
                    {
                        lcl_SetNewFlyPos( pCursor->GetPointNode(),
                                *pAnchor, GetCursorDocPos() );
                    }
                    break;
                case RndStdIds::FLY_AT_PAGE:
                    if( !pAnchor->GetPageNum() )
                    {
                        pAnchor->SetPageNum( pCursor->GetPageNum(
                                true, &pCursor->GetPtPos() ) );
                    }
                    break;
                default :
                    break;
                }
            }
        }
        pFormat = GetDoc()->getIDocumentContentOperations().InsertGraphic(
                                oPam.has_value() ? *oPam : *pCursor, rGrfName,
                                rFltName, pGraphic,
                                pFlyAttrSet,
                                nullptr, nullptr );
        OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertGraphic failed.");

        pCursor = pCursor->GetNext();
    } while( pCursor != pStartCursor );

    EndAllAction();

    if( !pFormat )
        return;

    const Point aPt( GetCursorDocPos() );
    SwFlyFrame* pFrame = pFormat->GetFrame( &aPt );

    if( pFrame )
    {
        // add a redline to the anchor point at tracked insertion of picture
        if ( IsRedlineOn() )
        {
            const SwPosition & rPos(*pFormat->GetAnchor().GetContentAnchor());
            SwPaM aPaM(rPos.GetNode(), rPos.GetContentIndex(),
                    rPos.GetNode(), rPos.GetContentIndex() + 1);
            GetDoc()->getIDocumentRedlineAccess().AppendRedline(
                    new SwRangeRedline( RedlineType::Insert, aPaM ), true);
        }

        // fdo#36681: Invalidate the content and layout to refresh
        // the picture anchoring properly
        SwPageFrame* pPageFrame = pFrame->FindPageFrameOfAnchor();
        pPageFrame->InvalidateFlyLayout();
        pPageFrame->InvalidateContent();

        SelectFlyFrame( *pFrame );
    }
    else
        GetLayout()->SetAssertFlyPages();
}

SwFlyFrameFormat* SwFEShell::InsertObject( const svt::EmbeddedObjectRef&  xObj,
                        SfxItemSet* pFlyAttrSet )
{
    SwFlyFrameFormat* pFormat = nullptr;
    CurrShell aCurr( this );
    StartAllAction();
    {
        for(const SwPaM& rPaM : GetCursor()->GetRingContainer())
        {
            pFormat = GetDoc()->getIDocumentContentOperations().InsertEmbObject(
                            rPaM, xObj, pFlyAttrSet );
            OSL_ENSURE(pFormat, "IDocumentContentOperations::InsertEmbObject failed.");
        }
    }
    EndAllAction();

    if( pFormat )
    {
        const Point aPt( GetCursorDocPos() );
        SwFlyFrame* pFrame = pFormat->GetFrame( &aPt );

        if( pFrame )
            SelectFlyFrame( *pFrame );
        else
            GetLayout()->SetAssertFlyPages();
    }

    return pFormat;
}

void SwFEShell::InsertDrawObj( SdrObject& rDrawObj,
                               const Point& rInsertPosition )
{
    CurrShell aCurr( this );

    SfxItemSet rFlyAttrSet( GetDoc()->GetAttrPool(), aFrameFormatSetRange );
    rFlyAttrSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PARA ));
    // #i89920#
    rFlyAttrSet.Put( SwFormatSurround( css::text::WrapTextMode_THROUGH ) );
    rDrawObj.SetLayer( getIDocumentDrawModelAccess().GetHeavenId() );

    // find anchor position
    SwPaM aPam( mxDoc->GetNodes() );
    {
        SwCursorMoveState aState( CursorMoveState::SetOnlyText );
        Point aTmpPt( rInsertPosition );
        GetLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmpPt, &aState );
        const SwFrame* pFrame = aPam.GetPointContentNode()->getLayoutFrame(GetLayout(), nullptr, nullptr);
        const Point aRelPos( rInsertPosition.X() - pFrame->getFrameArea().Left(),
                             rInsertPosition.Y() - pFrame->getFrameArea().Top() );
        rDrawObj.SetRelativePos( aRelPos );
        ::lcl_FindAnchorPos( *GetDoc(), rInsertPosition, *pFrame, rFlyAttrSet );
    }
    // insert drawing object into the document creating a new <SwDrawFrameFormat> instance
    SwDrawFrameFormat* pFormat = GetDoc()->getIDocumentContentOperations().InsertDrawObj( aPam, rDrawObj, rFlyAttrSet );

    // move object to visible layer
    SwContact* pContact = static_cast<SwContact*>(rDrawObj.GetUserCall());
    if ( pContact )
    {
        pContact->MoveObjToVisibleLayer( &rDrawObj );
    }

    if (pFormat)
    {
        pFormat->SetFormatName(UIName(rDrawObj.GetName()));
        // select drawing object
        Imp()->GetDrawView()->MarkObj( &rDrawObj, Imp()->GetPageView() );
    }
    else
    {
        GetLayout()->SetAssertFlyPages();
    }
}

void SwFEShell::GetPageObjs( std::vector<SwFrameFormat*>& rFillArr )
{
    rFillArr.clear();

    for(sw::SpzFrameFormat* pFormat : *mxDoc->GetSpzFrameFormats() )
    {
        if (RndStdIds::FLY_AT_PAGE == pFormat->GetAnchor().GetAnchorId())
        {
            rFillArr.push_back( pFormat );
        }
    }
}

void SwFEShell::SetPageObjsNewPage( std::vector<SwFrameFormat*>& rFillArr )
{
    if( rFillArr.empty() )
        return;

    StartAllAction();
    StartUndo();

    SwRootFrame* pTmpRootFrame = GetLayout();
    sal_uInt16 nMaxPage = pTmpRootFrame->GetPageNum();
    bool bTmpAssert = false;
    forauto pFormat : rFillArr )
    {
        if (mxDoc->GetSpzFrameFormats()->IsAlive(static_cast<sw::SpzFrameFormat*>(pFormat)))
        {
            // FlyFormat is still valid, therefore process

            SwFormatAnchor aNewAnchor( pFormat->GetAnchor() );
            if (RndStdIds::FLY_AT_PAGE != aNewAnchor.GetAnchorId())
                // Anchor has been changed, therefore: do not change!
                continue;
            sal_uInt16 nNewPage = aNewAnchor.GetPageNum() + 1;
            if (nNewPage > nMaxPage)
            {
                if ( RES_DRAWFRMFMT == pFormat->Which() )
                    pFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PAGE_OUT_OF_BOUNDS));
                else
                    pFormat->DelFrames();
                bTmpAssert = true;
            }
            aNewAnchor.SetPageNum(nNewPage);
            mxDoc->SetAttr( aNewAnchor, *pFormat );
        }
    }

    if( bTmpAssert )
        pTmpRootFrame->SetAssertFlyPages();

    EndUndo();
    EndAllAction();
}

// All attributes in the "baskets" will be filled with the attributes of the
// current FlyFrames. Attributes which cannot be filled due to being at the
// wrong place or which are ambiguous (multiple selections) will be removed.
bool SwFEShell::GetFlyFrameAttr( SfxItemSet &rSet ) const
{
    SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
    if (!pFly)
    {
        OSL_ENSURE( false"GetFlyFrameAttr, no Fly selected." );
        return false;
    }

    CurrShell aCurr( const_cast<SwFEShell*>(this) );

    if( !rSet.Set( pFly->GetFormat()->GetAttrSet() ) )
        return false;

    // now examine all attributes. Remove forbidden attributes, then
    // get all remaining attributes and enter them

    ifconst SwFormatAnchor* pAnchor = rSet.GetItemIfSet( RES_ANCHOR, false ) )
    {
        RndStdIds eType = pAnchor->GetAnchorId();

        if ( RndStdIds::FLY_AT_PAGE != eType )
        {
            // OD 12.11.2003 #i22341# - content anchor of anchor item is needed.
            // Thus, don't overwrite anchor item by default constructed anchor item.
            if ( RndStdIds::FLY_AS_CHAR == eType )
            {
                rSet.ClearItem( RES_OPAQUE );
                rSet.ClearItem( RES_SURROUND );
            }
        }
    }
    rSet.SetParent( pFly->GetFormat()->GetAttrSet().GetParent() );
    // attributes must be removed
    rSet.ClearItem( RES_FILL_ORDER );
    rSet.ClearItem( RES_CNTNT );
    //MA: remove first (Template by example etc.)
    rSet.ClearItem( RES_CHAIN );
    return true;
}

// Attributes of the current fly will change.
bool SwFEShell::SetFlyFrameAttr( SfxItemSet& rSet )
{
    CurrShell aCurr( this );
    bool bRet = false;

    if( rSet.Count() )
    {
        SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
        OSL_ENSURE(pFly, "SetFlyFrameAttr, no Fly selected.");
        if (pFly)
        {
            StartAllAction();
            const Point aPt( pFly->getFrameArea().Pos() );

            if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false ))
                sw_ChkAndSetNewAnchor( *pFly, rSet );
            SwFlyFrameFormat* pFlyFormat = pFly->GetFormat();

            if( GetDoc()->SetFlyFrameAttr( *pFlyFormat, rSet ))
            {
                bRet = true;
                SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt );
                if( pFrame )
                    SelectFlyFrame( *pFrame );
                else
                    GetLayout()->SetAssertFlyPages();
            }

            EndAllActionAndCall();
        }
    }
    return bRet;
}

SfxItemSet SwFEShell::makeItemSetFromFormatAnchor(SfxItemPool& rPool, const SwFormatAnchor &rAnchor)
{
    // The set also includes VERT/HORI_ORIENT, because the align
    // shall be changed in FEShell::SetFlyFrameAttr/SetFlyFrameAnchor,
    // possibly as a result of the anchor change.
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_VERT_ORIENT, RES_ANCHOR>(rPool));
    aSet.Put(rAnchor);
    return aSet;
}

bool SwFEShell::SetDrawingAttr( SfxItemSet& rSet )
{
    bool bRet = false;
    CurrShell aCurr( this );
    if ( !rSet.Count() ||
            !Imp()->HasDrawView() )
        return bRet;

    const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
    if ( rMrkList.GetMarkCount() != 1 )
        return bRet;

    StartUndo();
    SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
    SwFrameFormat *pFormat = FindFrameFormat( pObj );
    StartAllAction();
    if( SfxItemState::SET == rSet.GetItemState( RES_ANCHOR, false ))
    {
        RndStdIds nNew = rSet.Get( RES_ANCHOR ).GetAnchorId();
        if ( nNew != pFormat->GetAnchor().GetAnchorId() )
        {
            ChgAnchor( nNew );
            // #i26791# - clear anchor attribute in item set,
            // because method <ChgAnchor(..)> takes care of it.
            rSet.ClearItem( RES_ANCHOR );
        }
    }

    if( GetDoc()->SetFlyFrameAttr( *pFormat, rSet ))
    {
        bRet = true;
        SelectObj( Point(), 0, pObj );
    }
    EndAllActionAndCall();
    EndUndo();
    return bRet;
}

// Reset attributes contained in the set.
void SwFEShell::ResetFlyFrameAttr( const SfxItemSet* pSet )
{
    CurrShell aCurr( this );

    SwFlyFrame *pFly = GetSelectedOrCurrFlyFrame();
    OSL_ENSURE( pFly, "SetFlyFrameAttr, no Fly selected." );
    if( !pFly )
        return;

    StartAllAction();

    SfxItemIter aIter( *pSet );
    for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem())
    {
        if( !IsInvalidItem( pItem ) )
        {
            sal_uInt16 nWhich = pItem->Which();
            if( RES_ANCHOR != nWhich && RES_CHAIN != nWhich && RES_CNTNT != nWhich )
                pFly->GetFormat()->ResetFormatAttr( nWhich );
        }
    }

    EndAllActionAndCall();
    GetDoc()->getIDocumentState().SetModified();
}

// Returns frame-format if frame, otherwise 0
SwFrameFormat* SwFEShell::GetSelectedFrameFormat() const
{
    SwFrameFormat* pRet = nullptr;
    SwLayoutFrame *pFly = GetSelectedFlyFrame();
    if( pFly && ( pRet = static_cast<SwFrameFormat*>(pFly->GetFormat()->DerivedFrom()) ) ==
                                            GetDoc()->GetDfltFrameFormat() )
        pRet = nullptr;
    return pRet;
}

void SwFEShell::SetFrameFormat( SwFrameFormat *pNewFormat, bool bKeepOrient, Point const * pDocPos )
{
    SwFlyFrame *pFly = nullptr;
    if(pDocPos)
    {
        const SwFrameFormat* pFormat = GetFormatFromObj( *pDocPos );

        if (const SwFlyFrameFormat* pFlyFormat = dynamic_cast<const SwFlyFrameFormat*>(pFormat))
            pFly = pFlyFormat->GetFrame();
    }
    else
        pFly = GetSelectedFlyFrame();
    OSL_ENSURE( pFly, "SetFrameFormat: no frame" );
    if( !pFly )
        return;

    StartAllAction();
    CurrShell aCurr( this );

    SwFlyFrameFormat* pFlyFormat = pFly->GetFormat();
    const Point aPt( pFly->getFrameArea().Pos() );

    std::optional<SfxItemSet> oSet;
    const SfxPoolItem* pItem;
    if( SfxItemState::SET == pNewFormat->GetItemState( RES_ANCHOR, false, &pItem ))
    {
        oSet.emplace( GetDoc()->GetAttrPool(), aFrameFormatSetRange );
        oSet->Put( *pItem );
        if( !sw_ChkAndSetNewAnchor( *pFly, *oSet ))
        {
            oSet.reset();
        }
    }

    if( GetDoc()->SetFrameFormatToFly( *pFlyFormat, *pNewFormat, oSet ? &*oSet : nullptr, bKeepOrient ))
    {
        SwFlyFrame* pFrame = pFlyFormat->GetFrame( &aPt );
        if( pFrame )
            SelectFlyFrame( *pFrame );
        else
            GetLayout()->SetAssertFlyPages();
    }
    oSet.reset();

    EndAllActionAndCall();
}

const SwFrameFormat* SwFEShell::GetFlyFrameFormat() const
{
    const SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame();
    if (pFly)
        return pFly->GetFormat();
    return nullptr;
}

SwFrameFormat* SwFEShell::GetFlyFrameFormat()
{
    SwFlyFrame* pFly = GetSelectedOrCurrFlyFrame();
    if (pFly)
        return pFly->GetFormat();
    return nullptr;
}

SwRect SwFEShell::GetFlyRect() const
{
    SwFlyFrame *pFly = GetCurrFlyFrame(false);
    if (!pFly)
    {
        SwRect aRect;
        return aRect;
    }
    else
        return pFly->getFrameArea();
}

SwRect SwFEShell::GetObjRect() const
{
    if( Imp()->HasDrawView() )
        return SwRect(Imp()->GetDrawView()->GetAllMarkedRect());
    else
    {
        SwRect aRect;
        return aRect;
    }
}

void SwFEShell::SetObjRect( const SwRect& rRect )
{
    if ( Imp()->HasDrawView() )
    {
        Imp()->GetDrawView()->SetAllMarkedRect( rRect.SVRect() );
        CallChgLnk();   // call AttrChangeNotify on the UI-side.
    }
}

Size SwFEShell::RequestObjectResize( const SwRect &rRect, const uno::Reference < embed::XEmbeddedObject >& xObj )
{
    Size aResult;

    SwFlyFrame *pFly = FindFlyFrame( xObj );
    if ( !pFly )
    {
        aResult = rRect.SSize();
        return aResult;
    }

    aResult = pFly->getFramePrintArea().SSize();

    bool bPosProt = pFly->GetFormat()->GetProtect().IsPosProtected();
    bool bSizeProt = pFly->GetFormat()->GetProtect().IsSizeProtected();

    StartAllAction();

    // MA we do not allow to clip the Fly, as the OLE server can
    // request various wishes. Clipping is done via the formatting.
    // Correct display is done by scaling.
    // Scaling is done by SwNoTextFrame::Format by calling
    // SwWrtShell::CalcAndSetScale()
    if ( rRect.SSize() != pFly->getFramePrintArea().SSize() && !bSizeProt )
    {
        Size aSz( rRect.SSize() );

        //JP 28.02.2001: Task 74707 - ask for fly in fly with automatic size

        const SwFrame* pAnchor;
        const SwFormatFrameSize& rFrameSz = pFly->GetFormat()->GetFrameSize();
        if (m_bCheckForOLEInCaption &&
            0 != rFrameSz.GetWidthPercent() &&
            nullptr != (pAnchor = pFly->GetAnchorFrame()) &&
            pAnchor->IsTextFrame() &&
            !pAnchor->GetNext() && !pAnchor->GetPrev() &&
            pAnchor->GetUpper()->IsFlyFrame())
        {
            // search for a sequence field:
            sw::MergedAttrIter iter(*static_cast<SwTextFrame const*>(pAnchor));
            for (SwTextAttr const* pHint = iter.NextAttr(); pHint; pHint = iter.NextAttr())
            {
                const SfxPoolItem* pItem = &pHint->GetAttr();
                if( RES_TXTATR_FIELD == pItem->Which()
                    && SwFieldTypesEnum::Sequence == static_cast<const SwFormatField*>(pItem)->GetField()->GetTypeId() )
                {
                    // sequence field found
                    SwFlyFrame* pChgFly = const_cast<SwFlyFrame*>(static_cast<const SwFlyFrame*>(pAnchor->GetUpper()));
                    // calculate the changed size:
                    // width must change, height can change
                    Size aNewSz( aSz.Width() + pChgFly->getFrameArea().Width() -
                                   pFly->getFramePrintArea().Width(), aSz.Height() );

                    SwFrameFormat *pFormat = pChgFly->GetFormat();
                    SwFormatFrameSize aFrameSz( pFormat->GetFrameSize() );
                    aFrameSz.SetWidth( aNewSz.Width() );
                    if( SwFrameSize::Minimum != aFrameSz.GetHeightSizeType() )
                    {
                        aNewSz.AdjustHeight(pChgFly->getFrameArea().Height() -
                                               pFly->getFramePrintArea().Height() );
                        if( std::abs( aNewSz.Height() - pChgFly->getFrameArea().Height()) > 1 )
                            aFrameSz.SetHeight( aNewSz.Height() );
                    }
                    // via Doc for the Undo!
                    pFormat->GetDoc().SetAttr( aFrameSz, *pFormat );
                    break;
                }
            }
        }

        // set the new Size at the fly themself
        if ( !pFly->getFramePrintArea().IsEmpty() )
        {
            aSz.AdjustWidth(pFly->getFrameArea().Width() - pFly->getFramePrintArea().Width() );
            aSz.AdjustHeight(pFly->getFrameArea().Height()- pFly->getFramePrintArea().Height() );
        }
        aResult = pFly->ChgSize( aSz );

        // if the object changes, the contour is outside the object
        SwFrame* pLower = pFly->Lower();
        assert(pLower && pLower->IsNoTextFrame());
        SwNoTextNode *pNd = static_cast<SwNoTextFrame*>(pLower)->GetNode()->GetNoTextNode();
        assert(pNd);
        pNd->SetContour( nullptr );
        ClrContourCache();
    }

    // if only the size is to be adjusted, a position is transported with
    // allocated values
    Point aPt( pFly->getFramePrintArea().Pos() );
    aPt += pFly->getFrameArea().Pos();
    if ( rRect.Top() != LONG_MIN && rRect.Pos() != aPt && !bPosProt )
    {
        aPt = rRect.Pos();
        aPt.setX(aPt.getX() - pFly->getFramePrintArea().Left());
        aPt.setY(aPt.getY() - pFly->getFramePrintArea().Top());

        // in case of paragraph-bound Flys, starting from the new position,
        // a new anchor is to be set. The anchor and the new RelPos are
        // calculated by the Fly and set
        if( pFly->IsFlyAtContentFrame() )
            static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( aPt );
        else
        {
            const SwFrameFormat *pFormat = pFly->GetFormat();
            const SwFormatVertOrient &rVert = pFormat->GetVertOrient();
            const SwFormatHoriOrient &rHori = pFormat->GetHoriOrient();
            const tools::Long lXDiff = aPt.getX() - pFly->getFrameArea().Left();
            const tools::Long lYDiff = aPt.getY() - pFly->getFrameArea().Top();
            const Point aTmp( rHori.GetPos() + lXDiff,
                              rVert.GetPos() + lYDiff );
            pFly->ChgRelPos( aTmp );
        }
    }

    SwFlyFrameFormat *pFlyFrameFormat = pFly->GetFormat();
    OSL_ENSURE( pFlyFrameFormat, "fly frame format missing!" );
    if ( pFlyFrameFormat )
        pFlyFrameFormat->SetLastFlyFramePrtRectPos( pFly->getFramePrintArea().Pos() ); //stores the value of last Prt rect

    EndAllAction();

    return aResult;
}

SwFrameFormat* SwFEShell::WizardGetFly()
{
    // do not search the Fly via the layout. Now we can delete a frame
    // without a valid layout. ( e.g. for the wizards )
    sw::SpzFrameFormats& rSpzArr = *mxDoc->GetSpzFrameFormats();
    if( !rSpzArr.empty() )
    {
        SwNode& rCursorNd = GetCursor()->GetPoint()->GetNode();
        if( rCursorNd > mxDoc->GetNodes().GetEndOfExtras() )
            // Cursor is in the body area!
            return nullptr;

        forauto pFormat : rSpzArr )
        {
            const SwNodeIndex* pIdx = pFormat->GetContent( false ).GetContentIdx();
            SwStartNode* pSttNd;
            if( pIdx &&
                nullptr != ( pSttNd = pIdx->GetNode().GetStartNode() ) &&
                *pSttNd < rCursorNd &&
                rCursorNd < *pSttNd->EndOfSectionNode() )
            {
                // found: return immediately
                return pFormat;
            }
        }
    }
    return nullptr;
}

void SwFEShell::SetFlyName( const UIName& rName )
{
    SwLayoutFrame *pFly = GetSelectedFlyFrame();
    if( pFly )
        GetDoc()->SetFlyName( *static_cast<SwFlyFrameFormat*>(pFly->GetFormat()), rName );
    else {
        OSL_ENSURE( false"no FlyFrame selected" );
    }
}

UIName SwFEShell::GetFlyName() const
{
    SwLayoutFrame *pFly = GetSelectedFlyFrame();
    if( pFly )
        return pFly->GetFormat()->GetName();

    OSL_ENSURE( false"no FlyFrame selected" );
    return UIName();
}

uno::Reference < embed::XEmbeddedObject > SwFEShell::GetOleRef() const
{
    uno::Reference < embed::XEmbeddedObject > xObj;
    SwFlyFrame * pFly = GetSelectedFlyFrame();
    SwFrame* pLower = pFly ? pFly->Lower() : nullptr;
    if (pLower && pLower->IsNoTextFrame())
    {
        SwOLENode *pNd = static_cast<SwNoTextFrame*>(pLower)->GetNode()->GetOLENode();
        if (pNd)
            xObj = pNd->GetOLEObj().GetOleRef();
    }
    return xObj;
}

UIName SwFEShell::GetUniqueGrfName() const
{
    return GetDoc()->GetUniqueGrfName();
}

const SwFrameFormat* SwFEShell::IsURLGrfAtPos( const Point& rPt, OUString* pURL,
                                        OUString *pTargetFrameName,
                                        OUString *pDescription ) const
{
    if( !Imp()->HasDrawView() )
        return nullptr;

    SdrPageView* pPV;
    const SwFrameFormat* pRet = nullptr;
    SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());

    const auto nOld = pDView->GetHitTolerancePixel();
    pDView->SetHitTolerancePixel( 2 );

    SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO);
    SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
    if (pFlyObj)
    {
        SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
        const SwFormatURL &rURL = pFly->GetFormat()->GetURL();
        if( !rURL.GetURL().isEmpty() || rURL.GetMap() )
        {
            bool bSetTargetFrameName = pTargetFrameName != nullptr;
            bool bSetDescription = pDescription != nullptr;
            if ( rURL.GetMap() )
            {
                IMapObject *pObject = pFly->GetFormat()->GetIMapObject( rPt, pFly );
                if ( pObject && !pObject->GetURL().isEmpty() )
                {
                    if( pURL )
                        *pURL = pObject->GetURL();
                    if ( bSetTargetFrameName && !pObject->GetTarget().isEmpty() )
                    {
                        bSetTargetFrameName = false;
                        *pTargetFrameName = pObject->GetTarget();
                    }
                    if ( bSetDescription )
                    {
                        bSetDescription = false;
                        *pDescription = pObject->GetAltText();
                    }
                    pRet = pFly->GetFormat();
                }
            }
            else
            {
                if( pURL )
                {
                    *pURL = rURL.GetURL();
                    if( rURL.IsServerMap() )
                    {
                       // append the relative pixel position !!
                        Point aPt( rPt );
                        aPt -= pFly->getFrameArea().Pos();
                        // without MapMode-Offset, without Offset, o ... !!!!!
                        aPt = GetOut()->LogicToPixel(
                                aPt, MapMode( MapUnit::MapTwip ) );
                        *pURL = *pURL + "?" + OUString::number( aPt.getX() )
                                + "," + OUString::number(aPt.getY() );
                    }
                }
                pRet = pFly->GetFormat();
            }
            if ( bSetTargetFrameName )
                *pTargetFrameName = rURL.GetTargetFrameName();
            if ( bSetDescription )
                *pDescription = pFly->GetFormat()->GetName().toString();
        }
    }
    pDView->SetHitTolerancePixel( nOld );
    return pRet;
}

const Graphic *SwFEShell::GetGrfAtPos( const Point &rPt,
                                       OUString &rName, bool &rbLink ) const
{
    if( !Imp()->HasDrawView() )
        return nullptr;

    SdrPageView* pPV;
    SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());

    SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPV);
    SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj);
    if (pFlyObj)
    {
        SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
        SwFrame* pLower = pFly->Lower();
        if ( pLower && pLower->IsNoTextFrame() )
        {
            SwGrfNode *const pNd = static_cast<SwNoTextFrame*>(pLower)->GetNode()->GetGrfNode();
            if ( pNd )
            {
                if ( pNd->IsGrfLink() )
                {
                    // halfway ready graphic?
                    ::sfx2::SvLinkSource* pLnkObj = pNd->GetLink()->GetObj();
                    if( pLnkObj && pLnkObj->IsPending() )
                        return nullptr;
                    rbLink = true;
                }

                pNd->GetFileFilterNms( &rName, nullptr );
                if ( rName.isEmpty() )
                    rName = pFly->GetFormat()->GetName().toString();
                return &pNd->GetGrf(true);
            }
        }
    }
    return nullptr;
}

const SwFrameFormat* SwFEShell::GetFormatFromObj( const Point& rPt, SwRect** pRectToFill ) const
{
    SwFrameFormat* pRet = nullptr;

    if( Imp()->HasDrawView() )
    {
        SdrPageView* pPView;

        SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());

        const auto nOld = pDView->GetHitTolerancePixel();
        // tolerance for Drawing-SS
        pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );

        SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
        if (pObj)
        {
           // first check it:
            if (SwVirtFlyDrawObj* pFlyObj = dynamic_cast<SwVirtFlyDrawObj*>(pObj))
                pRet = pFlyObj->GetFormat();
            else if ( pObj->GetUserCall() ) //not for group objects
                pRet = static_cast<SwDrawContact*>(pObj->GetUserCall())->GetFormat();
            if(pRet && pRectToFill)
                **pRectToFill = SwRect(pObj->GetCurrentBoundRect());
        }
        pDView->SetHitTolerancePixel( nOld );
    }
    return pRet;
}

// returns a format too, if the point is over the text of any fly
const SwFrameFormat* SwFEShell::GetFormatFromAnyObj( const Point& rPt ) const
{
    const SwFrameFormat* pRet = GetFormatFromObj( rPt );
    if( !pRet || RES_FLYFRMFMT == pRet->Which() )
    {
        SwPosition aPos( *GetCursor()->GetPoint() );
        Point aPt( rPt );
        GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
        SwContentNode *pNd = aPos.GetNode().GetContentNode();
        std::pair<Point, boolconst tmp(rPt, false);
        SwFrame* pFrame = pNd->getLayoutFrame(GetLayout(), nullptr, &tmp)->FindFlyFrame();
        pRet = pFrame ? static_cast<SwLayoutFrame*>(pFrame)->GetFormat() : nullptr;
    }
    return pRet;
}

ObjCntType SwFEShell::GetObjCntType( const SdrObject& rObj )
{
    ObjCntType eType = OBJCNT_NONE;

    // investigate 'master' drawing object, if method
    // is called for a 'virtual' drawing object.
    const SdrObject* pInvestigatedObj;
    if (const SwDrawVirtObj* pDrawVirtObj = dynamic_cast<const SwDrawVirtObj*>( &rObj))
    {
        pInvestigatedObj = &(pDrawVirtObj->GetReferencedObj());
    }
    else
    {
        pInvestigatedObj = &rObj;
    }

    if( SdrInventor::FmForm == pInvestigatedObj->GetObjInventor() )
    {
        eType = OBJCNT_CONTROL;
        uno::Reference< awt::XControlModel >  xModel =
                static_cast<const SdrUnoObj&>(*pInvestigatedObj).GetUnoControlModel();
        if( xModel.is() )
        {
            uno::Any aVal;
            OUString sName(u"ButtonType"_ustr);
            uno::Reference< beans::XPropertySet >  xSet(xModel, uno::UNO_QUERY);

            uno::Reference< beans::XPropertySetInfo >  xInfo = xSet->getPropertySetInfo();
            if(xInfo->hasPropertyByName( sName ))
            {
                aVal = xSet->getPropertyValue( sName );
                if( aVal.hasValue() && form::FormButtonType_URL == *o3tl::doAccess<form::FormButtonType>(aVal) )
                    eType = OBJCNT_URLBUTTON;
            }
        }
    }
    else if (const SwVirtFlyDrawObj *pFlyObj = dynamic_cast<const SwVirtFlyDrawObj*>(pInvestigatedObj))
    {
        const SwFlyFrame *pFly = pFlyObj->GetFlyFrame();
        const SwFrame* pLower = pFly->Lower();
        if ( pLower && pLower->IsNoTextFrame() )
        {
            if (static_cast<const SwNoTextFrame*>(pLower)->GetNode()->GetGrfNode())
                eType = OBJCNT_GRF;
            else
                eType = OBJCNT_OLE;
        }
        else
            eType = OBJCNT_FLY;
    }
    else if ( dynamic_cast<const SdrObjGroup*>( pInvestigatedObj) != nullptr )
    {
        SwDrawContact* pDrawContact( dynamic_cast<SwDrawContact*>(GetUserCall( pInvestigatedObj ) ) );
        if ( !pDrawContact )
        {
            OSL_FAIL( " - missing draw contact object" );
            eType = OBJCNT_NONE;
        }
        else
        {
            SwFrameFormat* pFrameFormat( pDrawContact->GetFormat() );
            if ( !pFrameFormat )
            {
                OSL_FAIL( " - missing frame format" );
                eType = OBJCNT_NONE;
            }
            else if ( RndStdIds::FLY_AS_CHAR != pFrameFormat->GetAnchor().GetAnchorId() )
            {
                eType = OBJCNT_GROUPOBJ;
            }
        }
    }
    else
        eType = OBJCNT_SIMPLE;
    return eType;
}

ObjCntType SwFEShell::GetObjCntType( const Point &rPt, SdrObject *&rpObj ) const
{
    ObjCntType eType = OBJCNT_NONE;

    if( Imp()->HasDrawView() )
    {
        SdrPageView* pPView;

        SwDrawView *pDView = const_cast<SwDrawView*>(Imp()->GetDrawView());

        const auto nOld = pDView->GetHitTolerancePixel();
        // tolerance for Drawing-SS
        pDView->SetHitTolerancePixel( pDView->GetMarkHdlSizePixel()/2 );

        SdrObject* pObj = pDView->PickObj(rPt, pDView->getHitTolLog(), pPView, SdrSearchOptions::PICKMARKABLE);
        if (pObj)
        {
            rpObj = pObj;
            eType = GetObjCntType( *rpObj );
        }

        pDView->SetHitTolerancePixel( nOld );
    }
    return eType;
}

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

--> maximum size reached

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

Messung V0.5
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.20 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.