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

Quelle  fecopy.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 <memory>
#include <hintids.hxx>

#include <vcl/graph.hxx>
#include <sot/formats.hxx>
#include <svx/xfillit0.hxx>
#include <svx/svdocapt.hxx>
#include <svx/svdouno.hxx>
#include <svx/xbtmpit.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdogrp.hxx>
#include <svx/svdoole2.hxx>
#include <svx/fmmodel.hxx>
#include <svx/unomodel.hxx>
#include <svx/svditer.hxx>
#include <svx/svdograf.hxx>
#include <tools/stream.hxx>
#include <unotools/streamwrap.hxx>
#include <osl/diagnose.h>
#include <fmtanchr.hxx>
#include <fmtcntnt.hxx>
#include <fmtornt.hxx>
#include <fmtflcnt.hxx>
#include <frmfmt.hxx>
#include <txtfrm.hxx>
#include <txtflcnt.hxx>
#include <fesh.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <DocumentFieldsManager.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <rootfrm.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include <tblsel.hxx>
#include <swtable.hxx>
#include <flyfrm.hxx>
#include <pagefrm.hxx>
#include <fldbas.hxx>
#include <swundo.hxx>
#include <viewimp.hxx>
#include <dview.hxx>
#include <dcontact.hxx>
#include <dflyobj.hxx>
#include <docsh.hxx>
#include <pagedesc.hxx>
#include <mvsave.hxx>
#include <textboxhelper.hxx>
#include <frameformats.hxx>
#include <vcl/virdev.hxx>
#include <svx/svdundo.hxx>

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

// Copy for the internal clipboard. Copies all selections to the clipboard.
void SwFEShell::Copy( SwDoc& rClpDoc, const OUString* pNewClpText, bool bDeleteRedlines )
{
    rClpDoc.GetIDocumentUndoRedo().DoUndo(false); // always false!

    // delete content if ClpDocument contains content
    SwNodeIndex aSttIdx( rClpDoc.GetNodes().GetEndOfExtras(), 2 );
    SwNodeIndex aEndNdIdx( *aSttIdx.GetNode().EndOfSectionNode() );
    SwTextNode* pTextNd = aSttIdx.GetNode().GetTextNode();
    if (!pTextNd || !pTextNd->GetText().isEmpty() ||
        aSttIdx.GetIndex()+1 != rClpDoc.GetNodes().GetEndOfContent().GetIndex() )
    {
        rClpDoc.GetNodes().Delete( aSttIdx,
            rClpDoc.GetNodes().GetEndOfContent().GetIndex() - aSttIdx.GetIndex() );
        pTextNd = rClpDoc.GetNodes().MakeTextNode( aSttIdx.GetNode(),
                            rClpDoc.GetDfltTextFormatColl() );
        --aSttIdx;
    }

    // also delete surrounding FlyFrames if any
    for(sw::SpzFrameFormat* pFly : *rClpDoc.GetSpzFrameFormats() )
    {
        SwFormatAnchor const*const pAnchor = &pFly->GetAnchor();
        SwNode const*const pAnchorNode = pAnchor->GetAnchorNode();
        if (pAnchorNode &&
            ((RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) ||
             (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
            aSttIdx <= *pAnchorNode && *pAnchorNode <= aEndNdIdx.GetNode() )
        {
            rClpDoc.getIDocumentLayoutAccess().DelLayoutFormat( pFly );
        }
    }

    rClpDoc.GetDocumentFieldsManager().GCFieldTypes();        // delete the FieldTypes

    // if a string was passed, copy it to the clipboard-
    // document. Then also the Calculator can use the internal
    // clipboard
    if( pNewClpText )
    {
        pTextNd->InsertText( *pNewClpText, SwContentIndex( pTextNd ) );
        return;                // that's it
    }

    rClpDoc.getIDocumentFieldsAccess().LockExpFields();
    if (bDeleteRedlines)
    {
        rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
    }

    // do we want to copy a FlyFrame?
    if( IsFrameSelected() )
    {
        // get the FlyFormat
        SwFlyFrame* pFly = GetSelectedFlyFrame();
        SwFrameFormat* pFlyFormat = pFly->GetFormat();
        SwFormatAnchor aAnchor( pFlyFormat->GetAnchor() );

        if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
        {
            SwPosition aPos( aSttIdx );
            if ( RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId() )
            {
                aPos.SetContent( 0 );
            }
            aAnchor.SetAnchor( &aPos );
        }
        pFlyFormat = rClpDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat, aAnchor, truetrue );

        // assure the "RootFormat" is the first element in Spz-Array
        // (if necessary Flys were copied in Flys)
        sw::SpzFrameFormats& rSpzFrameFormats = *rClpDoc.GetSpzFrameFormats();
        if( rSpzFrameFormats[ 0 ] != pFlyFormat )
        {
#ifndef NDEBUG
            bool inserted =
#endif
            rSpzFrameFormats.newDefault(static_cast<sw::SpzFrameFormat*>(pFlyFormat));
            assert( !inserted && "Fly not contained in Spz-Array" );
        }

        if ( RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId() )
        {
            // JP 13.02.99  Bug 61863: if a frameselection is passed to the
            //              clipboard, it should be found at pasting. Therefore
            //              the copied TextAttribute should be removed in the node
            //              otherwise it will be recognised as TextSelection
            const SwPosition& rPos = *pFlyFormat->GetAnchor().GetContentAnchor();
            SwTextFlyCnt *const pTextFly = static_cast<SwTextFlyCnt *>(
                pTextNd->GetTextAttrForCharAt(
                    rPos.GetContentIndex(), RES_TXTATR_FLYCNT));
            if( pTextFly )
            {
                const_cast<SwFormatFlyCnt&>(pTextFly->GetFlyCnt()).SetFlyFormat();
                pTextNd->EraseText( rPos, 1 );
            }
        }
    }
    else if ( GetSelectedObjCount() )
    {
        SwPosition aPos( aSttIdx, pTextNd, 0 );
        const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
        for ( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
        {
            SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();

            if( Imp()->GetDrawView()->IsGroupEntered() ||
                ( !pObj->GetUserCall() && pObj->getParentSdrObjectFromSdrObject()) )
            {
                SfxItemSet aSet( rClpDoc.GetAttrPool(), aFrameFormatSetRange );

                SwFormatAnchor aAnchor( RndStdIds::FLY_AT_PARA );
                aAnchor.SetAnchor( &aPos );
                aSet.Put( aAnchor );

                rtl::Reference<SdrObject> xNew = rClpDoc.CloneSdrObj( *pObj );

                SwPaM aTemp(aPos);
                rClpDoc.getIDocumentContentOperations().InsertDrawObj(aTemp, *xNew, aSet );
            }
            else
            {
                if (SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall( pObj )))
                {
                    SwFrameFormat *pFormat = pContact->GetFormat();
                    SwFormatAnchor aAnchor( pFormat->GetAnchor() );
                    if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
                        (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
                        (RndStdIds::FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
                        (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
                    {
                        aAnchor.SetAnchor( &aPos );
                    }

                    rClpDoc.getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, truetrue );
                }
            }
        }
    }
    else
        CopySelToDoc(rClpDoc);     // copy the selections

    rClpDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
    rClpDoc.getIDocumentFieldsAccess().UnlockExpFields();
    if( !rClpDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
        rClpDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
}

static const Point &lcl_FindBasePos( const SwFrame *pFrame, const Point &rPt )
{
    const SwFrame *pF = pFrame;
    while ( pF && !pF->getFrameArea().Contains( rPt ) )
    {
        if ( pF->IsContentFrame() )
            pF = static_cast<const SwContentFrame*>(pF)->GetFollow();
        else
            pF = nullptr;
    }
    if ( pF )
        return pF->getFrameArea().Pos();
    else
        return pFrame->getFrameArea().Pos();
}

static bool lcl_SetAnchor( const SwPosition& rPos, const SwNode& rNd, SwFlyFrame const * pFly,
                const Point& rInsPt, SwFEShell const & rDestShell, SwFormatAnchor& rAnchor,
                Point& rNewPos, bool bCheckFlyRecur )
{
    bool bRet = true;
    rAnchor.SetAnchor( &rPos );
    std::pair<Point, boolconst tmp(rInsPt, false);
    SwContentFrame *const pTmpFrame = rNd.GetContentNode()->getLayoutFrame(
            rDestShell.GetLayout(), nullptr, &tmp);
    SwFlyFrame *pTmpFly = pTmpFrame->FindFlyFrame();
    if( pTmpFly && bCheckFlyRecur && pFly->IsUpperOf( *pTmpFly ) )
    {
        bRet = false;
    }
    else if ( RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId() )
    {
        if( pTmpFly )
        {
            const SwNodeIndex& rIdx = *pTmpFly->GetFormat()->GetContent().GetContentIdx();
            SwPosition aPos( rIdx );
            rAnchor.SetAnchor( &aPos );
            rNewPos = pTmpFly->getFrameArea().Pos();
        }
        else
        {
            rAnchor.SetType( RndStdIds::FLY_AT_PAGE );
            rAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
            const SwFrame *pPg = pTmpFrame->FindPageFrame();
            rNewPos = pPg->getFrameArea().Pos();
        }
    }
    else
        rNewPos = ::lcl_FindBasePos( pTmpFrame, rInsPt );
    return bRet;
}

bool SwFEShell::CopyDrawSel( SwFEShell& rDestShell, const Point& rSttPt,
                    const Point& rInsPt, bool bIsMove, bool bSelectInsert )
{
    bool bRet = true;

    // The list should be copied, because below new objects will be selected
    const SdrMarkList aMrkList( Imp()->GetDrawView()->GetMarkedObjectList() );
    const size_t nMarkCount = aMrkList.GetMarkCount();
    if( !rDestShell.Imp()->GetDrawView() )
        // should create it now
        rDestShell.MakeDrawView();
    else if( bSelectInsert )
        rDestShell.Imp()->GetDrawView()->UnmarkAll();

    SdrPageView *pDestPgView = rDestShell.Imp()->GetPageView(),
                *pSrcPgView = Imp()->GetPageView();
    SwDrawView *pDestDrwView = rDestShell.Imp()->GetDrawView(),
                *pSrcDrwView = Imp()->GetDrawView();
    SwDoc* pDestDoc = rDestShell.GetDoc();

    Size aSiz( rInsPt.X() - rSttPt.X(), rInsPt.Y() - rSttPt.Y() );
    for( size_t i = 0; i < nMarkCount; ++i )
    {
        SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();

        SwDrawContact *pContact = static_cast<SwDrawContact*>(GetUserCall( pObj ));
        if (!pContact)
            continue;

        SwFrameFormat *pFormat = pContact->GetFormat();
        const SwFormatAnchor& rAnchor = pFormat->GetAnchor();

        bool bInsWithFormat = true;

        if( pDestDrwView->IsGroupEntered() )
        {
            // insert into the group, when it belongs to an entered group
            // or when the object is not anchored as a character
            if( pSrcDrwView->IsGroupEntered() ||
                (RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId()) )

            {
                rtl::Reference<SdrObject> xNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
                                        GetDoc() == pDestDoc, false );
                xNew->NbcMove( aSiz );
                pDestDrwView->InsertObjectAtView( xNew.get(), *pDestPgView );
                bInsWithFormat = false;
            }
        }

        if( bInsWithFormat )
        {
            SwFormatAnchor aAnchor( rAnchor );
            Point aNewAnch;

            if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
                (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
                (RndStdIds::FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
                (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
            {
                if ( this == &rDestShell )
                {
                    // same shell? Then request the position
                    // from the passed DocumentPosition
                    SwPosition aPos( *GetCursor()->GetPoint() );
                    Point aPt( rInsPt );
                    aPt -= rSttPt - pObj->GetSnapRect().TopLeft();
                    SwCursorMoveState aState( CursorMoveState::SetOnlyText );
                    GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aState );
                    const SwNode *pNd;
                    if( (pNd = &aPos.GetNode())->IsNoTextNode() )
                        bRet = false;
                    else
                        bRet = ::lcl_SetAnchor( aPos, *pNd, nullptr, rInsPt,
                                rDestShell, aAnchor, aNewAnch, false );
                }
                else
                {
                    SwPaM *pCursor = rDestShell.GetCursor();
                    if( pCursor->GetPointNode().IsNoTextNode() )
                        bRet = false;
                    else
                        bRet = ::lcl_SetAnchor( *pCursor->GetPoint(),
                                                pCursor->GetPointNode(), nullptr, rInsPt,
                                                rDestShell, aAnchor,
                                                aNewAnch, false );
                }
            }
            else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
            {
                aAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
                const SwRootFrame* pTmpRoot = rDestShell.GetLayout();
                const SwFrame* pPg = pTmpRoot->GetPageAtPos( rInsPt, nullptr, true );
                if ( pPg )
                    aNewAnch = pPg->getFrameArea().Pos();
            }

            if( bRet )
            {
                if( pSrcDrwView->IsGroupEntered() ||
                    ( !pObj->GetUserCall() && pObj->getParentSdrObjectFromSdrObject()) )
                {
                    SfxItemSet aSet( pDestDoc->GetAttrPool(),aFrameFormatSetRange);
                    aSet.Put( aAnchor );
                    rtl::Reference<SdrObject> xNew = pDestDoc->CloneSdrObj( *pObj, bIsMove &&
                                                GetDoc() == pDestDoc );
                    pFormat = pDestDoc->getIDocumentContentOperations().InsertDrawObj( *rDestShell.GetCursor(), *xNew, aSet );
                }
                else
                    pFormat = pDestDoc->getIDocumentLayoutAccess().CopyLayoutFormat( *pFormat, aAnchor, truetrue );

                // Can be 0, as Draws are not allowed in Headers/Footers
                if ( pFormat )
                {
                    // #tdf33692 - drawing object has to be made visible on ctrl+drag copy.
                    pFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING));
                    SdrObject* pNew = pFormat->FindSdrObject();
                    if ( RndStdIds::FLY_AS_CHAR != aAnchor.GetAnchorId() )
                    {
                        Point aPos( rInsPt );
                        aPos -= aNewAnch;
                        aPos -= rSttPt - pObj->GetSnapRect().TopLeft();
                        // OD 2004-04-05 #i26791# - change attributes instead of
                        // direct positioning
                        pFormat->SetFormatAttr( SwFormatHoriOrient( aPos.getX(), text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
                        pFormat->SetFormatAttr( SwFormatVertOrient( aPos.getY(), text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
                        // #i47455# - notify draw frame format
                        // that position attributes are already set.
                        if (SwDrawFrameFormat *pDrawFormat = dynamic_cast<SwDrawFrameFormat*>(pFormat))
                            pDrawFormat->PosAttrSet();
                    }
                    if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT, pObj))
                    {
                        SwTextBoxHelper::syncFlyFrameAttr(*pFormat, pFormat->GetAttrSet(), pObj);
                    }

                    if( bSelectInsert )
                        pDestDrwView->MarkObj( pNew, pDestPgView );
                }
            }
        }
    }

    if ( bIsMove && bRet )
    {
        if( &rDestShell == this )
        {
            const SdrMarkList aList( pSrcDrwView->GetMarkedObjectList() );
            pSrcDrwView->UnmarkAll();

            for ( size_t i = 0, nMrkCnt = aMrkList.GetMarkCount(); i < nMrkCnt; ++i )
            {
                SdrObject *pObj = aMrkList.GetMark( i )->GetMarkedSdrObj();
                pSrcDrwView->MarkObj( pObj, pSrcPgView );
            }
            DelSelectedObj();
            for ( size_t i = 0, nMrkCnt = aList.GetMarkCount(); i < nMrkCnt; ++i )
            {
                SdrObject *pObj = aList.GetMark( i )->GetMarkedSdrObj();
                pSrcDrwView->MarkObj( pObj, pSrcPgView );
            }
        }
        else
            DelSelectedObj();
    }

    return bRet;
}

bool SwFEShell::Copy( SwFEShell& rDestShell, const Point& rSttPt,
                    const Point& rInsPt, bool bIsMove, bool bSelectInsert )
{
    bool bRet = false;

    OSL_ENSURE( this == &rDestShell || !rDestShell.GetSelectedObjCount(),
            "Dest-Shell cannot be in Obj-Mode" );

    CurrShell aCurr( &rDestShell );

    rDestShell.StartAllAction();
    rDestShell.GetDoc()->getIDocumentFieldsAccess().LockExpFields();

    // Shift references
    bool bCopyIsMove = mxDoc->IsCopyIsMove();
    if( bIsMove )
        // set a flag in Doc, handled in TextNodes
        mxDoc->SetCopyIsMove( true );

    RedlineFlags eOldRedlMode = rDestShell.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
    rDestShell.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode | RedlineFlags::DeleteRedlines );

    // If there are table formulas in the area, then display the table first
    // so that the table formula can calculate a new value first
    // (individual boxes in the area are retrieved via the layout)
    SwFieldType* pTableFieldTyp = rDestShell.GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table );

    if( IsFrameSelected() )
    {
        SwFlyFrame* pFly = GetSelectedFlyFrame();
        SwFrameFormat* pFlyFormat = pFly->GetFormat();
        SwFormatAnchor aAnchor( pFlyFormat->GetAnchor() );
        bRet = true;
        Point aNewAnch;

        if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AT_FLY  == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
        {
            if ( this == &rDestShell )
            {
                // same shell? Then request the position
                // from the passed DocumentPosition
                SwPosition aPos( *GetCursor()->GetPoint() );
                Point aPt( rInsPt );
                aPt -= rSttPt - pFly->getFrameArea().Pos();
                SwCursorMoveState aState( CursorMoveState::SetOnlyText );
                GetLayout()->GetModelPositionForViewPoint( &aPos, aPt, &aState );
                const SwNode *pNd;
                if( (pNd = &aPos.GetNode())->IsNoTextNode() )
                    bRet = false;
                else
                {
                    // do not copy in itself
                    const SwNodeIndex *pTmp = pFlyFormat->GetContent().GetContentIdx();
                    if ( aPos.GetNodeIndex() > pTmp->GetIndex() &&
                         aPos.GetNodeIndex() < pTmp->GetNode().EndOfSectionIndex() )
                    {
                        bRet = false;
                    }
                    else
                        bRet = ::lcl_SetAnchor( aPos, *pNd, pFly, rInsPt,
                                        rDestShell, aAnchor, aNewAnch, true );
                }
            }
            else
            {
                const SwPaM *pCursor = rDestShell.GetCursor();
                if( pCursor->GetPointNode().IsNoTextNode() )
                    bRet = false;
                else
                    bRet = ::lcl_SetAnchor( *pCursor->GetPoint(), pCursor->GetPointNode(),
                                            pFly, rInsPt, rDestShell, aAnchor,
                                    aNewAnch, GetDoc() == rDestShell.GetDoc());
            }
        }
        else if ( RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId() )
        {
            aAnchor.SetPageNum( rDestShell.GetPageNumber( rInsPt ) );
            const SwRootFrame* pTmpRoot = rDestShell.GetLayout();
            const SwFrame* pPg = pTmpRoot->GetPageAtPos( rInsPt, nullptr, true );
            if ( pPg )
                aNewAnch = pPg->getFrameArea().Pos();
        }
        else {
            OSL_ENSURE( false"what anchor is it?" );
        }

        if( bRet )
        {
            SwFrameFormat *pOldFormat = pFlyFormat;
            pFlyFormat = rDestShell.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pFlyFormat, aAnchor, truetrue );

            if ( RndStdIds::FLY_AS_CHAR != aAnchor.GetAnchorId() )
            {
                Point aPos( rInsPt );
                aPos -= aNewAnch;
                aPos -= rSttPt - pFly->getFrameArea().Pos();
                pFlyFormat->SetFormatAttr( SwFormatHoriOrient( aPos.getX(),text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
                pFlyFormat->SetFormatAttr( SwFormatVertOrient( aPos.getY(),text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
            }

            const Point aPt( rDestShell.GetCursorDocPos() );

            if( bIsMove )
                GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat( pOldFormat );

            // only select if it can be shifted/copied in the same shell
            if( bSelectInsert )
            {
                SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pFlyFormat)->GetFrame( &aPt );
                if( pFlyFrame )
                {
                    //JP 12.05.98: should this be in SelectFlyFrame???
                    rDestShell.Imp()->GetDrawView()->UnmarkAll();
                    rDestShell.SelectFlyFrame( *pFlyFrame );
                }
            }

            if (this != &rDestShell && !rDestShell.HasShellFocus())
                rDestShell.Imp()->GetDrawView()->hideMarkHandles();
        }
    }
    else if ( GetSelectedObjCount() )
        bRet = CopyDrawSel( rDestShell, rSttPt, rInsPt, bIsMove, bSelectInsert );
    else if( IsTableMode() )
    {
        // Copy parts from a table: create a table with the same
        // width as the original and copy the selected boxes.
        // Sizes will be corrected by percentage.

        // find boxes via the layout
        SwSelBoxes aBoxes;
        GetTableSel( *this, aBoxes );
        SwTableNode const*const pTableNd(
            aBoxes.empty() ? nullptr : aBoxes[0]->GetSttNd()->FindTableNode());
        if (nullptr != pTableNd)
        {
            std::optional<SwPosition> oDstPos;
            ifthis == &rDestShell )
            {
                // same shell? Then create new Cursor at the
                // DocumentPosition passed
                oDstPos.emplace( *GetCursor()->GetPoint() );
                Point aPt( rInsPt );
                GetLayout()->GetModelPositionForViewPoint( &*oDstPos, aPt );
                if( !oDstPos->GetNode().IsNoTextNode() )
                    bRet = true;
            }
            else if( !rDestShell.GetCursor()->GetPointNode().IsNoTextNode() )
            {
                oDstPos.emplace( *rDestShell.GetCursor()->GetPoint() );
                bRet = true;
            }

            if( bRet )
            {
                if( GetDoc() == rDestShell.GetDoc() )
                    ParkTableCursor();

                bRet = rDestShell.GetDoc()->InsCopyOfTable( *oDstPos, aBoxes,nullptr,
                                        bIsMove && this == &rDestShell &&
                                        aBoxes.size() == pTableNd->GetTable().
                                        GetTabSortBoxes().size(),
                                        this != &rDestShell );

                ifthis != &rDestShell )
                    *rDestShell.GetCursor()->GetPoint() = *oDstPos;

                // create all parked Cursor?
                if( GetDoc() == rDestShell.GetDoc() )
                    GetCursor();

                // JP 16.04.99: Bug 64908 - Set InsPos, to assure the parked
                //              Cursor is positioned at the insert position
                ifthis == &rDestShell )
                    GetCursorDocPos() = rInsPt;
            }
        }
    }
    else
    {
        bRet = true;
        ifthis == &rDestShell )
        {
            // same shell? then request the position
            // at the passed document position
            SwPosition aPos( *GetCursor()->GetPoint() );
            Point aPt( rInsPt );
            GetLayout()->GetModelPositionForViewPoint( &aPos, aPt );
            bRet = !aPos.GetNode().IsNoTextNode();
        }
        else if( rDestShell.GetCursor()->GetPointNode().IsNoTextNode() )
            bRet = false;

        if( bRet )
            bRet = SwEditShell::Copy( rDestShell );
    }

    rDestShell.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOldRedlMode );
    mxDoc->SetCopyIsMove( bCopyIsMove );

    // have new table formulas been inserted?
    if( pTableFieldTyp->HasWriterListeners() )
    {
        // finish old actions: the table frames are created and
        // a selection can be made
        sal_uInt16 nActCnt;
        for( nActCnt = 0; rDestShell.ActionPend(); ++nActCnt )
            rDestShell.EndAllAction();

        for( ; nActCnt; --nActCnt )
            rDestShell.StartAllAction();
    }
    rDestShell.GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
    rDestShell.GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);

    rDestShell.EndAllAction();
    return bRet;
}

// Paste for the internal clipboard. Copy the content of the clipboard
// in the document
namespace {
    typedef std::shared_ptr<SwPaM> PaMPtr;
    typedef std::shared_ptr<SwPosition> PositionPtr;
    typedef std::pair< PaMPtr, PositionPtr > Insertion;

    bool PamHasSelection(const SwPaM& rPaM)
    {
        return rPaM.HasMark() && *rPaM.GetPoint() != *rPaM.GetMark();
    }

    /// Is pFormat anchored in a fly frame which has an associated draw format?
    bool IsInTextBox(const SwFrameFormat* pFormat)
    {
        const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
        const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
        if (!pAnchorNode)
        {
            return false;
        }

        const SwStartNode* pFlyNode = pAnchorNode->FindFlyStartNode();
        if (!pFlyNode)
        {
            return false;
        }

        for(const sw::SpzFrameFormat* pSpzFormat: *pFormat->GetDoc().GetSpzFrameFormats())
        {
            if (pSpzFormat->Which() != RES_FLYFRMFMT)
            {
                continue;
            }

            const SwNodeIndex* pIdx = pSpzFormat->GetContent().GetContentIdx();
            if (!pIdx || pFlyNode != &pIdx->GetNode())
            {
                continue;
            }

            return SwTextBoxHelper::isTextBox(pSpzFormat, RES_FLYFRMFMT);
        }

        return false;
    }
}

namespace {
    SwFrameFormat* lcl_PasteFlyOrDrawFormat(SwPaM& rPaM, SwFrameFormat* pCpyFormat, SwFEShell& rSh)
    {
        auto& rImp = *rSh.Imp();
        auto& rDoc = *rSh.GetDoc();
        auto& rDrawView = *rImp.GetDrawView();
        if(rDrawView.IsGroupEntered() &&
           RES_DRAWFRMFMT == pCpyFormat->Which() &&
           (RndStdIds::FLY_AS_CHAR != pCpyFormat->GetAnchor().GetAnchorId()))
        {
            const SdrObject* pSdrObj = pCpyFormat->FindSdrObject();
            if(pSdrObj)
            {
                rtl::Reference<SdrObject> xNew = rDoc.CloneSdrObj(*pSdrObj, falsefalse);
                // Insert object sets any anchor position to 0.
                // Therefore we calculate the absolute position here
                // and after the insert the anchor of the object
                // is set to the anchor of the group object.
                tools::Rectangle aSnapRect = xNew->GetSnapRect();
                if(xNew->GetAnchorPos().X() || xNew->GetAnchorPos().Y())
                {
                    const Point aPoint(0, 0);
                    // OD 2004-04-05 #i26791# - direct drawing object
                    // positioning for group members
                    xNew->NbcSetAnchorPos(aPoint);
                    xNew->NbcSetSnapRect(aSnapRect);
                }

                rDrawView.InsertObjectAtView(xNew.get(), *rImp.GetPageView());

                Point aGrpAnchor(0, 0);
                SdrObjList* pList = xNew->getParentSdrObjListFromSdrObject();
                if(pList)
                {
                    SdrObjGroup* pOwner(dynamic_cast<SdrObjGroup*>(pList->getSdrObjectFromSdrObjList()));

                    if(nullptr != pOwner)
                        aGrpAnchor = pOwner->GetAnchorPos();
                }

                // OD 2004-04-05 #i26791# - direct drawing object
                // positioning for group members
                xNew->NbcSetAnchorPos(aGrpAnchor);
                xNew->SetSnapRect(aSnapRect);
                return nullptr;
            }
        }
        SwFormatAnchor aAnchor(pCpyFormat->GetAnchor());
        if ((RndStdIds::FLY_AT_PARA == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AT_CHAR == aAnchor.GetAnchorId()) ||
            (RndStdIds::FLY_AS_CHAR == aAnchor.GetAnchorId()))
        {
            SwPosition* pPos = rPaM.GetPoint();
            // allow shapes (no controls) in header/footer
            if(RES_DRAWFRMFMT == pCpyFormat->Which() && rDoc.IsInHeaderFooter(pPos->GetNode()))
            {
                const SdrObject *pCpyObj = pCpyFormat->FindSdrObject();
                if(pCpyObj && CheckControlLayer(pCpyObj))
                    return nullptr;
            }
            else if(pCpyFormat->Which() == RES_FLYFRMFMT && IsInTextBox(pCpyFormat))
            {
                // This is a fly frame which is anchored in a TextBox, ignore it as
                // it's already copied as part of copying the content of the
                // TextBox.
                return nullptr;
            }
            // Ignore TextBoxes, they are already handled in sw::DocumentLayoutManager::CopyLayoutFormat().
            if(SwTextBoxHelper::isTextBox(pCpyFormat, RES_FLYFRMFMT))
                return nullptr;
            aAnchor.SetAnchor(pPos);
        }
        else if(RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId())
        {
            aAnchor.SetPageNum(rSh.GetPhyPageNum());
        }
        else if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId())
        {
            Point aPt;
            (void)lcl_SetAnchor(*rPaM.GetPoint(), rPaM.GetPointNode(), nullptr, aPt, rSh, aAnchor, aPt, false);
        }

        SwFrameFormat* pNew = rDoc.getIDocumentLayoutAccess().CopyLayoutFormat(*pCpyFormat, aAnchor, truetrue);
        return pNew;
    }

    void lcl_SelectFlyFormat(SwFrameFormat *const pNew, SwFEShell& rSh)
    {
        if(!pNew)
            return;
        switch(pNew->Which())
        {
            case RES_FLYFRMFMT:
            {
                assert(dynamic_cast<SwFlyFrameFormat*>(pNew));
                const Point aPt(rSh.GetCursorDocPos());
                SwFlyFrame* pFlyFrame = static_cast<SwFlyFrameFormat*>(pNew)->GetFrame(&aPt);
                if(pFlyFrame)
                    rSh.SelectFlyFrame(*pFlyFrame);
                break;
            }
            case RES_DRAWFRMFMT:
            {
                auto& rDrawView = *rSh.Imp()->GetDrawView();
                assert(dynamic_cast<SwDrawFrameFormat*>(pNew));
                SwDrawFrameFormat* pDrawFormat = static_cast<SwDrawFrameFormat*>(pNew);
                // #i52780# - drawing object has to be made visible on paste.
                pDrawFormat->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::PREPPASTING));
                SdrObject* pObj = pDrawFormat->FindSdrObject();
                rDrawView.MarkObj(pObj, rDrawView.GetSdrPageView());
                // #i47455# - notify draw frame format
                // that position attributes are already set.
                pDrawFormat->PosAttrSet();
                break;
            }
            default:
                SAL_WARN("sw.core""unknown fly type");
        }
    }
}

bool SwFEShell::Paste(SwDoc& rClpDoc, bool bNestedTable)
{
    CurrShell aCurr( this );
    // then till end of the nodes array
    SwNodeIndex aIdx( rClpDoc.GetNodes().GetEndOfExtras(), 2 );
    // select content section, whatever it may contain
    SwPaM aCpyPam(aIdx, SwNodeIndex(rClpDoc.GetNodes().GetEndOfContent(), -1));
    if (SwContentNode *const pAtEnd = aCpyPam.GetPointNode().GetContentNode())
    {
        aCpyPam.GetPoint()->AssignEndIndex(*pAtEnd);
    }

    // If there are table formulas in the area, then display the table first
    // so that the table formula can calculate a new value first
    // (individual boxes in the area are retrieved via the layout)
    SwFieldType* pTableFieldTyp = GetDoc()->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Table );

    SwTableNode *const pSrcNd = aCpyPam.GetMarkNode().GetTableNode();

    bool bRet = true;
    StartAllAction();
    GetDoc()->GetIDocumentUndoRedo().StartUndo( SwUndoId::INSGLOSSARY, nullptr );
    GetDoc()->getIDocumentFieldsAccess().LockExpFields();

    // When the clipboard content has been created by a rectangular selection
    // the pasting is more sophisticated:
    // every paragraph will be inserted into another position.
    // The first positions are given by the actual cursor ring,
    // if there are more text portions to insert than cursor in this ring,
    // the additional insert positions will be created by moving the last
    // cursor position into the next line (like pressing the cursor down key)
    if( rClpDoc.IsColumnSelection() && !IsTableMode() )
    {
        // Creation of the list of insert positions
        std::vector< Insertion > aCopyVector;
        // The number of text portions of the rectangular selection
        const SwNodeOffset nSelCount = aCpyPam.GetPoint()->GetNodeIndex()
                       - aCpyPam.GetMark()->GetNodeIndex();
        SwNodeOffset nCount = nSelCount;
        SwNodeIndex aClpIdx( aIdx );
        SwPaM* pStartCursor = GetCursor();
        SwPaM* pCurrCursor = pStartCursor;
        SwNodeOffset nCursorCount( pStartCursor->GetRingContainer().size() );
        // If the target selection is a multi-selection, often the last and first
        // cursor of the ring points to identical document positions. Then
        // we should avoid double insertion of text portions...
        while( nCursorCount > SwNodeOffset(1) && *pCurrCursor->GetPoint() ==
            *(pCurrCursor->GetPrev()->GetPoint()) )
        {
            --nCursorCount;
            pCurrCursor = pCurrCursor->GetNext();
            pStartCursor = pCurrCursor;
        }
        SwPosition aStartPos( *pStartCursor->GetPoint() );
        SwPosition aInsertPos( aStartPos ); // first insertion position
        bool bCompletePara = false;
        sal_uInt16 nMove = 0;
        while( nCount )
        {
            --nCount;
            OSL_ENSURE( aIdx.GetNode().GetContentNode(), "Who filled the clipboard?!" );
            if( aIdx.GetNode().GetContentNode() ) // robust
            {
                Insertion aInsertion( std::make_shared<SwPaM>( aIdx ),
                    std::make_shared<SwPosition>( aInsertPos ) );
                ++aIdx;
                aInsertion.first->SetMark();
                if( pStartCursor == pCurrCursor->GetNext() )
                {   // Now we have to look for insertion positions...
                    if( !nMove ) // Annotate the last given insert position
                        aStartPos = aInsertPos;
                    SwCursor aCursor( aStartPos, nullptr);
                    // Check if we find another insert position by moving
                    // down the last given position
                    if (aCursor.UpDown(false, ++nMove, nullptr, 0, *GetLayout()))
                        aInsertPos = *aCursor.GetPoint();
                    else // if there is no paragraph we have to create it
                        bCompletePara = nCount > SwNodeOffset(0);
                    nCursorCount = SwNodeOffset(0);
                }
                else // as long as we find more insert positions in the cursor ring
                {    // we'll take them
                    pCurrCursor = pCurrCursor->GetNext();
                    aInsertPos = *pCurrCursor->GetPoint();
                    --nCursorCount;
                }
                // If there are no more paragraphs e.g. at the end of a document,
                // we insert complete paragraphs instead of text portions
                if( bCompletePara )
                    aInsertion.first->GetPoint()->Assign(aIdx);
                else
                    aInsertion.first->GetPoint()->SetContent(
                        aInsertion.first->GetPointContentNode()->Len() );
                aCopyVector.push_back( aInsertion );
            }
            // If there are no text portions left but there are some more
            // cursor positions to fill we have to restart with the first
            // text portion
            if( !nCount && nCursorCount )
            {
                nCount = min( nSelCount, nCursorCount );
                aIdx = aClpIdx; // Start of clipboard content
            }
        }
        for (auto const& item : aCopyVector)
        {
            SwPosition& rInsPos = *item.second;
            SwPaM& rCopy = *item.first;
            const SwStartNode* pBoxNd = rInsPos.GetNode().FindTableBoxStartNode();
            if( pBoxNd && SwNodeOffset(2) == pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex() &&
                rCopy.GetPoint()->GetNode() != rCopy.GetMark()->GetNode() )
            {
                // if more than one node will be copied into a cell
                // the box attributes have to be removed
                GetDoc()->ClearBoxNumAttrs( rInsPos.GetNode() );
            }
            {
                SwNodeIndex aIndexBefore(rInsPos.GetNode());
                --aIndexBefore;
                rClpDoc.getIDocumentContentOperations().CopyRange(rCopy, rInsPos, SwCopyFlags::CheckPosInFly);
                {
                    ++aIndexBefore;
                    SwPaM aPaM(SwPosition(aIndexBefore),
                               SwPosition(rInsPos.GetNode()));
                    aPaM.GetDoc().MakeUniqueNumRules(aPaM);
                }
            }
            SaveTableBoxContent( &rInsPos );
        }
    }
    else
    {
        bool bDelTable = true;

        for(SwPaM& rPaM : GetCursor()->GetRingContainer())
        {

            SwTableNode *const pDestNd(SwDoc::IsInTable(rPaM.GetPoint()->GetNode()));
            if (pSrcNd && nullptr != pDestNd &&
                // not a forced nested table insertion
                !bNestedTable &&
                // Heuristics to allow copying table rows or nesting tables without
                // using Edit -> Paste Special -> Paste as Nested Table:
                // Using table cursor, or if the text selection starts in the
                // first paragraph, or if there is no selection and the text cursor
                // is there in the first paragraph, overwrite content of the cell(s)
                // (else insert a nested table later, i.e. if nothing selected and
                // the cursor is not in the first paragraph, or the selected text
                // doesn't contain the first paragraph of the cell)
                rPaM.GetPointNode().GetIndex() == rPaM.GetPointNode().FindTableBoxStartNode()->GetIndex() + 1)
            {
                SwPosition aDestPos( *rPaM.GetPoint() );

                bool bParkTableCursor = false;
                const SwStartNode* pSttNd =  rPaM.GetPointNode().FindTableBoxStartNode();

                // TABLE IN TABLE: copy table in table
                // search boxes via the layout
                SwSelBoxes aBoxes;
                if( IsTableMode() )     // table selection?
                {
                    GetTableSel( *this, aBoxes );
                    ParkTableCursor();
                    bParkTableCursor = true;
                }
                else if( !PamHasSelection(rPaM) && rPaM.GetNext() == &rPaM &&
                     ( !pSrcNd->GetTable().IsTableComplex() ||
                       pDestNd->GetTable().IsNewModel() ) )
                {
                    // make relative table copy
                    SwTableBox* pBox = pDestNd->GetTable().GetTableBox(
                                        pSttNd->GetIndex() );
                    OSL_ENSURE( pBox, "Box is not in this table" );
                    aBoxes.insert( pBox );
                }

                SwNodeIndex aNdIdx( *pDestNd->EndOfSectionNode());
                if( !bParkTableCursor )
                {
                    // exit first the complete table
                    // ???? what about only table in a frame ?????
                    SwContentNode* pCNd = SwNodes::GoNext(&aNdIdx);
                    SwPosition aPos( aNdIdx, pCNd, 0 );
                    // #i59539: Don't remove all redline
                    SwPaM const tmpPaM(*pDestNd, *pDestNd->EndOfSectionNode());
                    ::PaMCorrAbs(tmpPaM, aPos);
                }

                bRet = GetDoc()->InsCopyOfTable( aDestPos, aBoxes, &pSrcNd->GetTable() );

                if( bParkTableCursor )
                    GetCursor();
                else
                {
                    // return to the box
                    aNdIdx = *pSttNd;
                    SwContentNode* pCNd = SwNodes::GoNext(&aNdIdx);
                    SwPosition aPos( aNdIdx, pCNd, 0 );
                    // #i59539: Don't remove all redline
                    SwNode & rNode(rPaM.GetPoint()->GetNode());
                    SwContentNode *const pContentNode( rNode.GetContentNode() );
                    SwPaM const tmpPam(rNode, 0,
                                   rNode, pContentNode ? pContentNode->Len() : 0);
                    ::PaMCorrAbs(tmpPam, aPos);
                }

                break;      // exit the "while-loop"
            }
            else if(*aCpyPam.GetPoint() == *aCpyPam.GetMark() && !rClpDoc.GetSpzFrameFormats()->empty())
            {
                // we need a DrawView
                if(!Imp()->GetDrawView())
                    MakeDrawView();
                ::std::vector<SwFrameFormat*> inserted;
                for (sw::SpzFrameFormat* pFlyFormat: *rClpDoc.GetSpzFrameFormats())
                {
                    // if anchored inside other fly, will be copied when copying
                    // top-level fly, so skip here! (other non-body anchor
                    // shouldn't happen here)
                    SwFormatAnchor const& rAnchor(pFlyFormat->GetAnchor());
                    if (RndStdIds::FLY_AT_PAGE == rAnchor.GetAnchorId()
                        || rClpDoc.GetNodes().GetEndOfExtras().GetIndex() < rAnchor.GetAnchorNode()->GetIndex())
                    {
                        inserted.emplace_back(
                            lcl_PasteFlyOrDrawFormat(rPaM, pFlyFormat, *this));
                    }
                }
                for (auto const pFlyFormat : inserted)
                {
                    lcl_SelectFlyFormat(pFlyFormat, *this);
                }
            }
            else
            {
                if( bDelTable && IsTableMode() )
                {
                    SwEditShell::Delete(false);
                    bDelTable = false;
                }

                SwPosition& rInsPos = *rPaM.GetPoint();
                const SwStartNode* pBoxNd = rInsPos.GetNode().
                                                    FindTableBoxStartNode();
                if( pBoxNd && SwNodeOffset(2) == pBoxNd->EndOfSectionIndex() -
                                pBoxNd->GetIndex() &&
                    aCpyPam.GetPoint()->GetNode() != aCpyPam.GetMark()->GetNode() )
                {
                    // Copy more than 1 node in the current box. But
                    // then the BoxAttribute should be removed
                    GetDoc()->ClearBoxNumAttrs( rInsPos.GetNode() );
                }

                // **
                // ** Update SwDoc::Append, if you change the following code **
                // **
                {
                    SwNodeIndex aIndexBefore(rInsPos.GetNode());

                    --aIndexBefore;

                    // copying to the clipboard, the section is inserted
                    // at the start of the nodes, followed by empty text node
                    bool const isSourceSection(aCpyPam.Start()->GetNode().IsSectionNode()
                        && aCpyPam.End()->GetNodeIndex() == aCpyPam.Start()->GetNode().EndOfSectionIndex() + 1
                        && aCpyPam.End()->GetNode().IsTextNode()
                        && aCpyPam.End()->GetNode().GetTextNode()->Len() == 0);

                    rClpDoc.getIDocumentContentOperations().CopyRange(aCpyPam, rInsPos, SwCopyFlags::CheckPosInFly);
                    // Note: aCpyPam is invalid now

                    if (isSourceSection
                        && aIndexBefore.GetNode().IsStartNode()
                        && rInsPos.GetNode().GetTextNode()->Len() == 0)
                    {   // if there is an empty text node at the start, it
                        // should be *replaced* by the section, so delete it
                        GetDoc()->getIDocumentContentOperations().DelFullPara(rPaM);
                    }

                    ++aIndexBefore;
                    SwPaM aPaM(aIndexBefore.GetNode(), rInsPos.GetNode());

                    aPaM.GetDoc().MakeUniqueNumRules(aPaM);

                    // Update the rsid of each pasted text node.
                    SwNodes &rDestNodes = GetDoc()->GetNodes();
                    SwNodeOffset const nEndIdx = aPaM.End()->GetNodeIndex();

                    for (SwNodeOffset nIdx = aPaM.Start()->GetNodeIndex();
                        nIdx <= nEndIdx; ++nIdx)
                    {
                        SwTextNode *const pTextNode = rDestNodes[nIdx]->GetTextNode();
                        if ( pTextNode )
                        {
                            GetDoc()->UpdateParRsid( pTextNode );
                        }
                    }
                }

                SaveTableBoxContent( &rInsPos );
            }
        }
    }

    GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::INSGLOSSARY, nullptr );

    // have new table formulas been inserted?
    if( pTableFieldTyp->HasWriterListeners() )
    {
        // finish old action: table-frames have been created
        // a selection can be made now
        sal_uInt16 nActCnt;
        for( nActCnt = 0; ActionPend(); ++nActCnt )
            EndAllAction();

        for( ; nActCnt; --nActCnt )
            StartAllAction();
    }
    GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
    GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
    EndAllAction();

    return bRet;
}

void SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt16 nEndPage)
{
    Push();
    if(!GotoPage(nStartPage))
    {
        Pop(PopMode::DeleteCurrent);
        return;
    }
    MovePage( GetThisFrame, GetFirstSub );
    ::std::optional<SwPaM> oSourcePam( *GetCursor()->GetPoint() );
    UIName sStartingPageDesc = GetPageDesc( GetCurPageDesc()).GetName();
    SwPageDesc* pDesc = rToFill.FindPageDescByName( sStartingPageDesc, true );
    if( pDesc )
        rToFill.ChgCurPageDesc( *pDesc );

    if(!GotoPage(nEndPage))
    {
        Pop(PopMode::DeleteCurrent);
        return;
    }
    //if the page starts with a table a paragraph has to be inserted before
    SwNode *const pTableNode = oSourcePam->GetPointNode().FindTableNode();
    if(pTableNode)
    {
        //insert a paragraph
        StartUndo(SwUndoId::INSERT);
        SwNodeIndex aTableIdx(  *pTableNode, -1 );
        SwPosition aBefore(aTableIdx);
        if(GetDoc()->getIDocumentContentOperations().AppendTextNode( aBefore ))
        {
            SwPaM aTmp(aBefore);
            *oSourcePam = aTmp;
        }
        EndUndo(SwUndoId::INSERT);
    }

    MovePage( GetThisFrame, GetLastSub );
    oSourcePam->SetMark();
    *oSourcePam->GetMark() = *GetCursor()->GetPoint();

    CurrShell aCurr( this );

    StartAllAction();
    GetDoc()->getIDocumentFieldsAccess().LockExpFields();
    SetSelection(*oSourcePam);
    // copy the text of the selection
    SwEditShell::Copy(rToFill);
    oSourcePam.reset(); // delete it because Undo will remove its node!

    if(pTableNode)
    {
        //remove the inserted paragraph
        Undo();
        //remove the paragraph in the second doc, too
        SwPaM aPara( rToFill.GetDoc()->GetNodes().GetEndOfExtras(), SwNodeOffset(2) ); //DocStart
        rToFill.GetDoc()->getIDocumentContentOperations().DelFullPara(aPara);
    }
    // now the page bound objects
    // additionally copy page bound frames
    if( !GetDoc()->GetSpzFrameFormats()->empty() )
    {
        // create a draw view if necessary
        if( !rToFill.Imp()->GetDrawView() )
            rToFill.MakeDrawView();

        for(sw::SpzFrameFormat* pCpyFormat: *GetDoc()->GetSpzFrameFormats())
        {
            SwFormatAnchor aAnchor( pCpyFormat->GetAnchor() );
            if ((RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()) &&
                    aAnchor.GetPageNum() >= nStartPage && aAnchor.GetPageNum() <= nEndPage)
            {
                aAnchor.SetPageNum( aAnchor.GetPageNum() - nStartPage + 1);
            }
            else
                continue;
            rToFill.GetDoc()->getIDocumentLayoutAccess().CopyLayoutFormat( *pCpyFormat, aAnchortruetrue );
        }
    }
    GetDoc()->getIDocumentFieldsAccess().UnlockExpFields();
    GetDoc()->getIDocumentFieldsAccess().UpdateFields(false);
    Pop(PopMode::DeleteCurrent);
    EndAllAction();
}

comphelper::OInterfaceContainerHelper3<css::text::XPasteListener>& SwFEShell::GetPasteListeners() { return m_aPasteListeners; }

bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat, Graphic& rGrf ) const
{
    OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
    const SdrMarkList &rMrkList = Imp()->GetDrawView()->GetMarkedObjectList();
    bool bConvert = true;
    if( rMrkList.GetMarkCount() )
    {
        if( rMrkList.GetMarkCount() == 1 &&
            dynamic_castconst SwVirtFlyDrawObj* >(rMrkList.GetMark( 0 )->GetMarkedSdrObj()) != nullptr )
        {
            // select frame
            if( CNT_GRF == GetCntType() )
            {
                const Graphic* pGrf( GetGraphic() );
                if ( pGrf )
                {
                    Graphic aGrf( *pGrf );
                    if( SotClipboardFormatId::GDIMETAFILE == nFormat )
                    {
                        if( GraphicType::Bitmap != aGrf.GetType() )
                        {
                            rGrf = std::move(aGrf);
                            bConvert = false;
                        }
                        else if( GetWin() )
                        {
                            Size aSz;
                            Point aPt;
                            GetGrfSize( aSz );

                            ScopedVclPtrInstance< VirtualDevice > pVirtDev;
                            pVirtDev->EnableOutput( false );

                            MapMode aTmp( GetWin()->GetMapMode() );
                            aTmp.SetOrigin( aPt );
                            pVirtDev->SetMapMode( aTmp );

                            GDIMetaFile aMtf;
                            aMtf.Record( pVirtDev.get() );
                            aGrf.Draw(*pVirtDev, aPt, aSz);
                            aMtf.Stop();
                            aMtf.SetPrefMapMode( aTmp );
                            aMtf.SetPrefSize( aSz );
                            rGrf = aMtf;
                        }
                    }
                    else if( GraphicType::Bitmap == aGrf.GetType() )
                    {
                        rGrf = std::move(aGrf);
                        bConvert = false;
                    }
                    else
                    {
                        // Not the original size, but the current one.
                        // Otherwise it could happen that for vector graphics
                        // many MB's of memory are allocated.
                        const Size aSz( GetSelectedFlyFrame()->getFramePrintArea().SSize() );
                        ScopedVclPtrInstance< VirtualDevice > pVirtDev(*GetWin()->GetOutDev());

                        MapMode aTmp( MapUnit::MapTwip );
                        pVirtDev->SetMapMode( aTmp );
                        if( pVirtDev->SetOutputSize( aSz ) )
                        {
                            aGrf.Draw(*pVirtDev, Point(), aSz);
                            rGrf = pVirtDev->GetBitmapEx( Point(), aSz );
                        }
                        else
                        {
                            rGrf = std::move(aGrf);
                            bConvert = false;
                        }
                    }
                }
            }
        }
        else if( SotClipboardFormatId::GDIMETAFILE == nFormat )
            rGrf = Imp()->GetDrawView()->GetMarkedObjMetaFile();
        else if( SotClipboardFormatId::BITMAP == nFormat || SotClipboardFormatId::PNG == nFormat )
            rGrf = Imp()->GetDrawView()->GetMarkedObjBitmapEx();
    }
    return bConvert;
}

// #i50824#
// replace method <lcl_RemoveOleObjsFromSdrModel> by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
static void lcl_ConvertSdrOle2ObjsToSdrGrafObjs( SdrModel& _rModel )
{
    for ( sal_uInt16 nPgNum = 0; nPgNum < _rModel.GetPageCount(); ++nPgNum )
    {
        // setup object iterator in order to iterate through all objects
        // including objects in group objects, but exclusive group objects.
        SdrObjListIter aIter(_rModel.GetPage(nPgNum));
        while( aIter.IsMore() )
        {
            SdrOle2Obj* pOle2Obj = dynamic_cast< SdrOle2Obj* >( aIter.Next() );
            if( pOle2Obj )
            {
                // found an ole2 shape
                SdrObjList* pObjList = pOle2Obj->getParentSdrObjListFromSdrObject();

                // get its graphic
                Graphic aGraphic;
                pOle2Obj->Connect();
                const Graphic* pGraphic = pOle2Obj->GetGraphic();
                if( pGraphic )
                    aGraphic = *pGraphic;
                pOle2Obj->Disconnect();

                // create new graphic shape with the ole graphic and shape size
                rtl::Reference<SdrGrafObj> pGraphicObj = new SdrGrafObj(
                    _rModel,
                    aGraphic,
                    pOle2Obj->GetCurrentBoundRect());
                // apply layer of ole2 shape at graphic shape
                pGraphicObj->SetLayer( pOle2Obj->GetLayer() );

                // replace ole2 shape with the new graphic object and delete the ol2 shape
                pObjList->ReplaceObject( pGraphicObj.get(), pOle2Obj->GetOrdNum() );
            }
        }
    }
}

void SwFEShell::Paste( SvStream& rStrm, SwPasteSdr nAction, const Point* pPt )
{
    CurrShell aCurr( this );
    StartAllAction();
    StartUndo();

    std::unique_ptr< FmFormModel > pModel(
        new FmFormModel(
            nullptr,
            GetDoc()->GetDocShell()));

    rStrm.Seek(0);

    uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rStrm ) );
    SvxDrawingLayerImport( pModel.get(), xInputStream );

    if ( !Imp()->HasDrawView() )
        Imp()->MakeDrawView();

    Point aPos( pPt ? *pPt : GetCharRect().Pos() );
    SdrView *pView = Imp()->GetDrawView();

    // drop on the existing object: replace object or apply new attributes
    if( pModel->GetPageCount() > 0 &&
        1 == pModel->GetPage(0)->GetObjCount() &&
        1 == pView->GetMarkedObjectList().GetMarkCount() )
    {
        // replace a marked 'virtual' drawing object
        // by its corresponding 'master' drawing object in the mark list.
        SwDrawView::ReplaceMarkedDrawVirtObjs( *pView );

        SdrObject* pClpObj = pModel->GetPage(0)->GetObj(0);
        SdrObject* pOldObj = pView->GetMarkedObjectList().GetMark( 0 )->GetMarkedSdrObj();
        assert(pOldObj);

        if( SwPasteSdr::SetAttr == nAction && dynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) !=  nullptr )
            nAction = SwPasteSdr::Replace;

        switch( nAction )
        {
        case SwPasteSdr::Replace:
            {
                const SwFrameFormat* pFormat(nullptr);
                const SwFrame* pAnchor(nullptr);
                ifdynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) !=  nullptr )
                {
                    pFormat = FindFrameFormat( pOldObj );

                    Point aNullPt;
                    SwFlyFrame* pFlyFrame = static_cast<const SwFlyFrameFormat*>(pFormat)->GetFrame( &aNullPt );
                    pAnchor = pFlyFrame ? pFlyFrame->GetAnchorFrame() : nullptr;

                    if (!pAnchor || pAnchor->FindFooterOrHeader())
                    {
                        // if there is a textframe in the header/footer:
                        // do not replace but insert
                        nAction = SwPasteSdr::Insert;
                        break;
                    }
                }

                rtl::Reference<SdrObject> pNewObj(pClpObj->CloneSdrObject(pOldObj->getSdrModelFromSdrObject()));
                tools::Rectangle aOldObjRect( pOldObj->GetCurrentBoundRect() );
                Size aOldObjSize( aOldObjRect.GetSize() );
                tools::Rectangle aNewRect( pNewObj->GetCurrentBoundRect() );
                Size aNewSize( aNewRect.GetSize() );

                Fraction aScaleWidth( aOldObjSize.Width(), aNewSize.Width() );
                Fraction aScaleHeight( aOldObjSize.Height(), aNewSize.Height());
                pNewObj->NbcResize( aNewRect.TopLeft(), aScaleWidth, aScaleHeight);

                Point aVec = aOldObjRect.TopLeft() - aNewRect.TopLeft();
                pNewObj->NbcMove(Size(aVec.getX(), aVec.getY()));

                ifdynamic_cast<const SdrUnoObj*>( pNewObj.get()) !=  nullptr )
                    pNewObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
                else ifdynamic_cast<const SdrUnoObj*>( pOldObj) !=  nullptr )
                    pNewObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
                else
                    pNewObj->SetLayer( pOldObj->GetLayer() );

                ifdynamic_cast<const SwVirtFlyDrawObj*>( pOldObj) !=  nullptr )
                {
                    // store attributes, then set SdrObject
                    SfxItemSetFixed<RES_SURROUND, RES_ANCHOR> aFrameSet( mxDoc->GetAttrPool() );
                    aFrameSet.Set( pFormat->GetAttrSet() );

                    Point aNullPt;
                    if( pAnchor->IsTextFrame() && static_cast<const SwTextFrame*>(pAnchor)->IsFollow() )
                    {
                        const SwTextFrame* pTmp = static_cast<const SwTextFrame*>(pAnchor);
                        do {
                            pTmp = pTmp->FindMaster();
                            assert(pTmp && "Where's my Master?");
                        } while( pTmp->IsFollow() );
                        pAnchor = pTmp;
                    }
                    ifauto pCaptionObj = dynamic_cast<SdrCaptionObj*>( pOldObj))
                        aNullPt = pCaptionObj->GetTailPos();
                    else
                        aNullPt = aOldObjRect.TopLeft();

                    Point aNewAnchor = pAnchor->GetFrameAnchorPos( ::HasWrap( pOldObj ) );
                    // OD 2004-04-05 #i26791# - direct positioning of Writer
                    // fly frame object for <SwDoc::Insert(..)>
                    pNewObj->NbcSetRelativePos( aNullPt - aNewAnchor );
                    pNewObj->NbcSetAnchorPos( aNewAnchor );

                    pOldObj->GetOrdNum();

                    DelSelectedObj();

                    GetDoc()->getIDocumentContentOperations().InsertDrawObj( *GetCursor(), *pNewObj, aFrameSet );
                }
                else
                {
                    // #i123922#  for handling MasterObject and virtual ones correctly, SW
                    // wants us to call ReplaceObject at the page, but that also
                    // triggers the same assertion (I tried it), so stay at the view method
                    pView->ReplaceObjectAtView(pOldObj, *Imp()->GetPageView(), pNewObj.get());
                }
            }
            break;

        case SwPasteSdr::SetAttr:
            {
                SfxItemSet aSet( GetAttrPool() );
                const SdrGrafObj* pSdrGrafObj = dynamic_castconst SdrGrafObj* >(pClpObj);

                if(pSdrGrafObj)
                {
                    SdrObject* pTarget = nullptr;

                    if(0 != pView->GetMarkedObjectList().GetMarkCount())
                    {
                        // try to get target (if it's at least one, take first)
                        SdrMark* pMark = pView->GetMarkedObjectList().GetMark(0);

                        if(pMark)
                        {
                            pTarget = pMark->GetMarkedSdrObj();
                        }
                    }

                    if(pTarget)
                    {
                        // copy ItemSet from target
                        aSet.Set(pTarget->GetMergedItemSet());
                    }

                    // for SdrGrafObj, use the graphic as fill style argument
                    const Graphic& rGraphic = pSdrGrafObj->GetGraphic();

                    if(GraphicType::NONE != rGraphic.GetType() && GraphicType::Default != rGraphic.GetType())
                    {
                        aSet.Put(XFillBitmapItem(OUString(), rGraphic));
                        aSet.Put(XFillStyleItem(drawing::FillStyle_BITMAP));
                    }
                }
                else
                {
                    aSet.Put(pClpObj->GetMergedItemSet());
                }

                pView->SetAttributes( aSet );
            }
            break;

        default:
            nAction = SwPasteSdr::Insert;
            break;
        }
    }
    else
        nAction = SwPasteSdr::Insert;

    if( SwPasteSdr::Insert == nAction )
    {
        ::sw::DrawUndoGuard drawUndoGuard(GetDoc()->GetIDocumentUndoRedo());

        bool bDesignMode = pView->IsDesignMode();
        if( !bDesignMode )
            pView->SetDesignMode();

        // #i50824#
        // method <lcl_RemoveOleObjsFromSdrModel> replaced by <lcl_ConvertSdrOle2ObjsToSdrGrafObjs>
        lcl_ConvertSdrOle2ObjsToSdrGrafObjs(*pModel);
        pView->Paste(*pModel, aPos, nullptr, SdrInsertFlags::NONE);

        const size_t nCnt = pView->GetMarkedObjectList().GetMarkCount();
        if( nCnt )
        {
            const Point aNull( 0, 0 );
            for( size_t i=0; i < nCnt; ++i )
            {
                SdrObject *pObj = pView->GetMarkedObjectList().GetMark(i)->GetMarkedSdrObj();
                pObj->ImpSetAnchorPos( aNull );
            }

            pView->SetCurrentObj( SdrObjKind::Group );
            if ( nCnt > 1 )
                pView->GroupMarked();
            SdrObject *pObj = pView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
            assert(pObj);
            ifdynamic_cast<const SdrUnoObj*>( pObj) !=  nullptr )
            {
                pObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetControlsId() );
                bDesignMode = true;
            }
            else
                pObj->SetLayer( GetDoc()->getIDocumentDrawModelAccess().GetHeavenId() );
            const tools::Rectangle &rSnap = pObj->GetSnapRect();
            const Size aDiff( rSnap.GetWidth()/2, rSnap.GetHeight()/2 );
--> --------------------

--> maximum size reached

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

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

¤ 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.