/* -*- 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 <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/embed/EmbedMisc.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <com/sun/star/embed/EmbedVerbs.hpp>
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
#include <com/sun/star/util/XModifiable.hpp>
 
#include <svx/dialogs.hrc>
 
#include <math.h>
#include <hintids.hxx>
#include <sot/exchange.hxx>
#include <svx/hdft.hxx>
#include <svx/svdview.hxx>
#include <svl/itemiter.hxx>
#include <tools/bigint.hxx>
#include <svtools/insdlg.hxx>
#include <sfx2/frmdescr.hxx>
#include <sfx2/ipclient.hxx>
#include <svtools/ehdl.hxx>
#include <svtools/soerr.hxx>
#include <unotools/moduleoptions.hxx>
#include <editeng/sizeitem.hxx>
#include <editeng/formatbreakitem.hxx>
#include <editeng/svxacorr.hxx>
#include <editeng/ulspitem.hxx>
#include <vcl/graph.hxx>
#include <sfx2/printer.hxx>
#include <unotools/charclass.hxx>
#include <comphelper/storagehelper.hxx>
#include <svx/svxdlg.hxx>
#include <svx/extrusionbar.hxx>
#include <svx/fontworkbar.hxx>
#include <frmfmt.hxx>
#include <fmtftn.hxx>
#include <fmthdft.hxx>
#include <fmtpdsc.hxx>
#include <wdocsh.hxx>
#include <basesh.hxx>
#include <swmodule.hxx>
#include <wrtsh.hxx>
#include <view.hxx>
#include <uitool.hxx>
#include <cmdid.h>
#include <cfgitems.hxx>
#include <pagedesc.hxx>
#include <frmmgr.hxx>
#include <shellio.hxx>
#include <uinums.hxx>
#include <swundo.hxx>
#include <swcli.hxx>
#include <poolfmt.hxx>
#include <wview.hxx>
#include <edtwin.hxx>
#include <fmtcol.hxx>
#include <swtable.hxx>
#include <caption.hxx>
#include <viscrs.hxx>
#include <swdtflvr.hxx>
#include <doc.hxx>
#include <IDocumentSettingAccess.hxx>
#include <SwStyleNameMapper.hxx>
#include <sfx2/request.hxx>
#include <paratr.hxx>
#include <ndtxt.hxx>
#include <editeng/acorrcfg.hxx>
#include <IMark.hxx>
#include <sfx2/bindings.hxx>
 
// -> #111827#
#include <SwRewriter.hxx>
#include <strings.hrc>
// <- #111827#
 
#include <toolkit/helper/vclunohelper.hxx>
#include <sfx2/viewfrm.hxx>
 
#include <PostItMgr.hxx>
#include <FrameControlsManager.hxx>
 
#include <sfx2/msgpool.hxx>
#include <svtools/embedhlp.hxx>
#include <memory>
 
using namespace sw::mark;
using namespace com::sun::star;
 
#define COMMON_INI_LIST \
        m_fnDrag(&SwWrtShell::BeginDrag),\
        m_fnSetCursor(&SwWrtShell::SetCursor),\
        m_fnEndDrag(&SwWrtShell::DefaultEndDrag),\
        m_fnKillSel(&SwWrtShell::Ignore),\
        m_pModeStack(nullptr), \
        m_ePageMove(MV_NO),\
        m_rView(rShell),\
        m_aNavigationMgr(*this), \
        m_bDestOnStack(false)
 
#define BITFLD_INI_LIST \
        m_bClearMark = \
        m_bIns = true;\
        m_bAddMode = \
        m_bBlockMode = \
        m_bExtMode = \
        m_bInSelect = \
        m_bLayoutMode = \
        m_bSelWrd = \
        m_bSelLn = \
        m_bRetainSelection = false; \
        m_bIsInClickToEdit = false;
 
static SvxAutoCorrect* lcl_IsAutoCorr()
{
    SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
    if( pACorr && !pACorr->IsAutoCorrFlag( ACFlags::CapitalStartSentence | ACFlags::CapitalStartWord |
                            ACFlags::AddNonBrkSpace | ACFlags::ChgOrdinalNumber |
                            ACFlags::ChgToEnEmDash | ACFlags::SetINetAttr | ACFlags::Autocorrect ))
        pACorr = nullptr;
    return pACorr;
}
 
void SwWrtShell::NoEdit(bool bHideCursor)
{
    if(bHideCursor)
        HideCursor();
}
 
void SwWrtShell::Edit()
{
    if (CanInsert())
    {
        ShowCursor();
    }
}
 
bool SwWrtShell::IsEndWrd()
{
    SwMvContext aMvContext(this);
    if(IsEndPara() && !IsSttPara())
        return true;
 
    return IsEndWord();
}
 
// Insert string
void SwWrtShell::InsertByWord( const OUString & rStr)
{
    if( !rStr.isEmpty() )
    {
        bool bDelim = GetAppCharClass().isLetterNumeric( rStr, 0 );
        sal_Int32 nPos = 0, nStt = 0;
        for( ; nPos < rStr.getLength(); nPos++ )
           {
            bool bTmpDelim = GetAppCharClass().isLetterNumeric( rStr, nPos );
            if( bTmpDelim != bDelim )
            {
                Insert( rStr.copy( nStt, nPos - nStt ));
                nStt = nPos;
            }
        }
        if( nStt != nPos )
            Insert( rStr.copy( nStt, nPos - nStt ));
    }
}
 
void SwWrtShell::Insert( const OUString &rStr )
{
    ResetCursorStack();
    if( !CanInsert() )
        return;
 
    bool bStarted = false;
    bool bHasSel = HasSelection(),
         bCallIns = m_bIns /*|| bHasSel*/;
    bool bDeleted = false;
 
    if( bHasSel || ( !m_bIns && SelectHiddenRange() ) )
    {
            // Only here parenthesizing, because the normal
            // insert is already in parentheses at Editshell.
        StartAllAction();
 
        SwRewriter aRewriter;
 
        aRewriter.AddRule(UndoArg1, GetCursorDescr());
        aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
        {
            OUString aTmpStr;
            aTmpStr += SwResId(STR_START_QUOTE);
            aTmpStr += rStr;
            aTmpStr += SwResId(STR_END_QUOTE);
 
            aRewriter.AddRule(UndoArg3, aTmpStr);
        }
 
        StartUndo(SwUndoId::REPLACE, &aRewriter);
        bStarted = true;
        bDeleted = DelRight();
    }
 
    bCallIns ?
        SwEditShell::Insert2( rStr, bDeleted ) : SwEditShell::Overwrite( rStr );
 
    if( bStarted )
    {
        EndAllAction();
        EndUndo();
    }
}
 
// Maximum height limit not possible, because the maximum height
// of the current frame can not be obtained.
 
void SwWrtShell::Insert( const OUString &rPath, const OUString &rFilter,
                         const Graphic &rGrf, SwFlyFrameAttrMgr *pFrameMgr,
                         RndStdIds nAnchorType )
{
    ResetCursorStack();
    if ( !CanInsert() )
        return;
 
    StartAllAction();
 
    SwRewriter aRewriter;
    aRewriter.AddRule(UndoArg1, SwResId(STR_GRAPHIC));
 
    StartUndo(SwUndoId::INSERT, &aRewriter);
 
    if ( HasSelection() )
        DelRight();
        // Inserted graphics in its own paragraph,
        // if at the end of a non-empty paragraph.
    //For i120928,avoid to split node
 
    EnterSelFrameMode();
 
    bool bSetGrfSize = true;
    bool bOwnMgr     = false;
 
    if ( !pFrameMgr )
    {
        bOwnMgr = true;
        pFrameMgr = new SwFlyFrameAttrMgr( true, this, Frmmgr_Type::GRF );
 
        // CAUTION
        // GetAttrSet makes an adjustment
        // While pasting is a SwFrameSize present
        // because of the DEF-Framesize
        // These must be removed explicitly for the optimal size.
        pFrameMgr->DelAttr(RES_FRM_SIZE);
 
        if (nAnchorType != RndStdIds::FLY_AT_PARA)
            // Something other than at-para was requested.
            pFrameMgr->SetAnchor(nAnchorType);
    }
    else
    {
        Size aSz( pFrameMgr->GetSize() );
        if ( !aSz.Width() || !aSz.Height() )
        {
            aSz.setWidth(567);
            aSz.setHeight( 567);
            pFrameMgr->SetSize( aSz );
        }
        else if ( aSz.Width() != DFLT_WIDTH && aSz.Height() != DFLT_HEIGHT )
            bSetGrfSize = false;
 
        pFrameMgr->SetHeightSizeType(ATT_FIX_SIZE);
    }
 
    // Insert the graphic
    SwFEShell::Insert(rPath, rFilter, &rGrf, &pFrameMgr->GetAttrSet());
    if ( bOwnMgr )
        pFrameMgr->UpdateAttrMgr();
 
    if( bSetGrfSize )
    {
        Size aGrfSize, aBound = GetGraphicDefaultSize();
        GetGrfSize( aGrfSize );
 
        // Add the margin attributes to GrfSize,
        // because these counts at the margin additionally
        aGrfSize.AdjustWidth(pFrameMgr->CalcWidthBorder() );
        aGrfSize.AdjustHeight(pFrameMgr->CalcHeightBorder() );
 
        const BigInt aTempWidth( aGrfSize.Width() );
        const BigInt aTempHeight( aGrfSize.Height());
 
        // Fit width if necessary, scale down the height proportional thereafter.
        if( aGrfSize.Width() > aBound.Width() )
        {
            aGrfSize.setWidth( aBound.Width() );
            aGrfSize.setHeight( BigInt(aBound.Width()) * aTempHeight / aTempWidth );
        }
        // Fit height if necessary, scale down the width proportional thereafter.
        if( aGrfSize.Height() > aBound.Height() )
        {
            aGrfSize.setHeight( aBound.Height() );
            aGrfSize.setWidth(  BigInt(aBound.Height()) * aTempWidth / aTempHeight );
        }
        pFrameMgr->SetSize( aGrfSize );
        pFrameMgr->UpdateFlyFrame();
    }
    if ( bOwnMgr )
        delete pFrameMgr;
 
    EndUndo();
    EndAllAction();
}
 
// Insert an OLE-Object into the CORE.
// if no object is transferred, then one will be created.
 
void SwWrtShell::InsertObject( const svt::EmbeddedObjectRef& xRef, SvGlobalName const *pName,
                               sal_uInt16 nSlotId )
{
    ResetCursorStack();
    if( !CanInsert() )
        return;
 
    if( !xRef.is() )
    {
        // temporary storage
        svt::EmbeddedObjectRef xObj;
        uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetTemporaryStorage();
        bool bDoVerb = true;
        if ( pName )
        {
            comphelper::EmbeddedObjectContainer aCnt( xStor );
            OUString aName;
            // TODO/LATER: get aspect?
            xObj.Assign( aCnt.CreateEmbeddedObject( pName->GetByteSequence(), aName ), embed::Aspects::MSOLE_CONTENT );
        }
        else
        {
            SvObjectServerList aServerList;
            switch (nSlotId)
            {
                case SID_INSERT_OBJECT:
                {
                    aServerList.FillInsertObjects();
                    aServerList.Remove( SwDocShell::Factory().GetClassId() );
                    SAL_FALLTHROUGH;
                }
 
                // TODO/LATER: recording! Convert properties to items
                case SID_INSERT_FLOATINGFRAME:
                {
                    SfxSlotPool* pSlotPool = SW_MOD()->GetSlotPool();
                    const SfxSlot* pSlot = pSlotPool->GetSlot(nSlotId);
                    OString aCmd(".uno:");
                    aCmd += pSlot->GetUnoName();
                    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
                    vcl::Window* pWin = GetWin();
                    ScopedVclPtr<SfxAbstractInsertObjectDialog> pDlg(pFact->CreateInsertObjectDialog(pWin ? pWin->GetFrameWeld() : nullptr,
                                OUString::fromUtf8( aCmd ), xStor, &aServerList));
                    if (pDlg)
                    {
                        pDlg->Execute();
                        bDoVerb = pDlg->IsCreateNew();
                        OUString aIconMediaType;
                        uno::Reference< io::XInputStream > xIconMetaFile = pDlg->GetIconIfIconified( &aIconMediaType );
                        xObj.Assign( pDlg->GetObject(),
                                     xIconMetaFile.is() ? embed::Aspects::MSOLE_ICON : embed::Aspects::MSOLE_CONTENT );
                        if ( xIconMetaFile.is() )
                            xObj.SetGraphicStream( xIconMetaFile, aIconMediaType );
                    }
 
                    break;
                }
 
                default:
                    break;
            }
        }
 
        if ( xObj.is() )
        {
            if( InsertOleObject( xObj ) && bDoVerb )
            {
                SfxInPlaceClient* pClient = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
                if ( !pClient )
                {
                    pClient = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
                    SetCheckForOLEInCaption( true );
                }
 
                if ( xObj.GetViewAspect() == embed::Aspects::MSOLE_ICON )
                {
                    SwRect aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
                    aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
                    MapMode aMapMode( MapUnit::MapTwip );
                    Size aSize = xObj.GetSize( &aMapMode );
                    aArea.Width( aSize.Width() );
                    aArea.Height( aSize.Height() );
                    RequestObjectResize( aArea, xObj.GetObject() );
                }
                else
                    CalcAndSetScale( xObj );
 
                //#50270# We don't need to handle error, this is handled by the
                //DoVerb in the SfxViewShell
                pClient->DoVerb(embed::EmbedVerbs::MS_OLEVERB_SHOW);
 
                // TODO/LATER: set document name - should be done in Client
            }
        }
    }
    else
    {
        if( HasSelection() )
            DelRight();
        InsertOleObject( xRef );
    }
}
 
// Insert object into the Core.
// From ClipBoard or Insert
 
bool SwWrtShell::InsertOleObject( const svt::EmbeddedObjectRef& xRef, SwFlyFrameFormat **pFlyFrameFormat )
{
    ResetCursorStack();
    StartAllAction();
 
    StartUndo(SwUndoId::INSERT);
 
    //Some differences between StarMath and any other objects:
    //1. Selections should be deleted. For StarMath the Text should be
    //   passed to the Object
    //2. If the cursor is at the end of an non empty paragraph a paragraph
    //   break should be inserted. StarMath objects are character bound and
    //   no break should be inserted.
    //3. If an selection is passed to a StarMath object, this object should
    //   not be activated. false should be returned then.
    bool bStarMath = true;
    bool bActivate = true;
 
    // set parent to get correct VisArea(in case of object needing parent printer)
    uno::Reference < container::XChild > xChild( xRef.GetObject(), uno::UNO_QUERY );
    if ( xChild.is() )
        xChild->setParent( mxDoc->GetDocShell()->GetModel() );
 
    SvGlobalName aCLSID( xRef->getClassID() );
    bStarMath = ( SotExchange::IsMath( aCLSID ) != 0 );
    if( IsSelection() )
    {
        if( bStarMath )
        {
            OUString aMathData;
            GetSelectedText( aMathData, ParaBreakType::ToOnlyCR );
 
            if( !aMathData.isEmpty() && svt::EmbeddedObjectRef::TryRunningState( xRef.GetObject() ) )
            {
                uno::Reference < beans::XPropertySet > xSet( xRef->getComponent(), uno::UNO_QUERY );
                if ( xSet.is() )
                {
                    try
                    {
                        xSet->setPropertyValue("Formula", uno::makeAny( aMathData ) );
                        bActivate = false;
                    }
                    catch (const uno::Exception&)
                    {
                    }
                }
            }
        }
        DelRight();
    }
 
    if ( !bStarMath )
        SwFEShell::SplitNode( false, false );
 
    EnterSelFrameMode();
 
    SwFlyFrameAttrMgr aFrameMgr( true, this, Frmmgr_Type::OLE );
    aFrameMgr.SetHeightSizeType(ATT_FIX_SIZE);
 
    SwRect aBound;
    CalcBoundRect( aBound, aFrameMgr.GetAnchor() );
 
    //The Size should be suggested by the OLE server
    MapMode aMapMode( MapUnit::MapTwip );
    Size aSz = xRef.GetSize( &aMapMode );
 
    //Object size can be limited
    if ( aSz.Width() > aBound.Width() )
    {
        //Always limit proportional.
        aSz.setHeight( aSz.Height() * aBound.Width() / aSz.Width() );
        aSz.setWidth( aBound.Width() );
    }
    aFrameMgr.SetSize( aSz );
    SwFlyFrameFormat *pFormat = SwFEShell::InsertObject( xRef, &aFrameMgr.GetAttrSet() );
 
    // --> #i972#
    if ( bStarMath && mxDoc->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ) )
        AlignFormulaToBaseline( xRef.GetObject() );
 
    if (pFlyFrameFormat)
        *pFlyFrameFormat = pFormat;
 
    if ( SotExchange::IsChart( aCLSID ) )
    {
        uno::Reference< embed::XEmbeddedObject > xEmbeddedObj( xRef.GetObject(), uno::UNO_QUERY );
        if ( xEmbeddedObj.is() )
        {
            bool bDisableDataTableDialog = false;
            svt::EmbeddedObjectRef::TryRunningState( xEmbeddedObj );
            uno::Reference< beans::XPropertySet > xProps( xEmbeddedObj->getComponent(), uno::UNO_QUERY );
            if ( xProps.is() &&
                 ( xProps->getPropertyValue("DisableDataTableDialog") >>= bDisableDataTableDialog ) &&
                 bDisableDataTableDialog )
            {
                xProps->setPropertyValue("DisableDataTableDialog",
                    uno::makeAny( false ) );
                xProps->setPropertyValue("DisableComplexChartTypes",
                    uno::makeAny( false ) );
                uno::Reference< util::XModifiable > xModifiable( xProps, uno::UNO_QUERY );
                if ( xModifiable.is() )
                {
                    xModifiable->setModified( true );
                }
            }
        }
    }
 
    EndAllAction();
    GetView().AutoCaption(OLE_CAP, &aCLSID);
 
    SwRewriter aRewriter;
 
    if ( bStarMath )
        aRewriter.AddRule(UndoArg1, SwResId(STR_MATH_FORMULA));
    else if ( SotExchange::IsChart( aCLSID ) )
        aRewriter.AddRule(UndoArg1, SwResId(STR_CHART));
    else
        aRewriter.AddRule(UndoArg1, SwResId(STR_OLE));
 
    EndUndo(SwUndoId::INSERT, &aRewriter);
 
    return bActivate;
}
 
// The current selected OLE object will be loaded with the
// verb into the server.
 
void SwWrtShell::LaunchOLEObj( long nVerb )
{
    if ( GetCntType() == CNT_OLE &&
         !GetView().GetViewFrame()->GetFrame().IsInPlace() )
    {
        svt::EmbeddedObjectRef& xRef = GetOLEObject();
        OSL_ENSURE( xRef.is(), "OLE not found" );
        SfxInPlaceClient* pCli=nullptr;
 
        pCli = GetView().FindIPClient( xRef.GetObject(), &GetView().GetEditWin() );
        if ( !pCli )
            pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xRef );
 
        static_cast<SwOleClient*>(pCli)->SetInDoVerb( true );
 
        CalcAndSetScale( xRef );
        pCli->DoVerb( nVerb );
 
        static_cast<SwOleClient*>(pCli)->SetInDoVerb( false );
        CalcAndSetScale( xRef );
    }
}
 
void SwWrtShell::MoveObjectIfActive( svt::EmbeddedObjectRef& xObj, const Point& rOffset )
{
    try
    {
        sal_Int32 nState = xObj->getCurrentState();
        if ( nState == css::embed::EmbedStates::INPLACE_ACTIVE
          || nState == css::embed::EmbedStates::UI_ACTIVE )
        {
            SfxInPlaceClient* pCli =
                GetView().FindIPClient( xObj.GetObject(), &(GetView().GetEditWin()) );
            if ( pCli )
            {
                tools::Rectangle aArea = pCli->GetObjArea();
                aArea += rOffset;
                pCli->SetObjArea( aArea );
            }
        }
    }
    catch (const uno::Exception&)
    {
    }
}
 
void SwWrtShell::CalcAndSetScale( svt::EmbeddedObjectRef& xObj,
                                  const SwRect *pFlyPrtRect,
                                  const SwRect *pFlyFrameRect,
                                  const bool bNoTextFramePrtAreaChanged )
{
    // Setting the scale of the client. This arises from the difference
    // between the VisArea of the object and the ObjArea.
    OSL_ENSURE( xObj.is(), "ObjectRef not  valid" );
 
    sal_Int64 nAspect = xObj.GetViewAspect();
    if ( nAspect == embed::Aspects::MSOLE_ICON )
        return; // the replacement image is completely controlled by container in this case
 
    sal_Int64 nMisc = 0;
    bool bLinkingChart = false;
 
    try
    {
        nMisc = xObj->getStatus( nAspect );
 
        // This can surely only be a non-active object, if desired they
        // get the new size set as VisArea (StarChart).
        if( embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE & nMisc )
        {
            // TODO/MBA: testing
            SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
                        : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
            if( !aRect.IsEmpty() )
            {
                // TODO/LEAN: getMapUnit can switch object to running state
                // xObj.TryRunningState();
 
                MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
 
                // TODO/LATER: needs complete VisArea?!
                Size aSize( OutputDevice::LogicToLogic(aRect.SVRect(), MapMode(MapUnit::MapTwip), MapMode(aUnit)).GetSize() );
                awt::Size aSz;
                aSz.Width = aSize.Width();
                aSz.Height = aSize.Height();
 
                // Action 'setVisualAreaSize' doesn't have to turn on the
                // modified state of the document, either.
                bool bModified = false;
                uno::Reference<util::XModifiable> xModifiable(xObj->getComponent(), uno::UNO_QUERY);
                if (xModifiable.is())
                    bModified = xModifiable->isModified();
                xObj->setVisualAreaSize( nAspect, aSz );
                xModifiable.set(xObj->getComponent(), uno::UNO_QUERY);
                if (xModifiable.is() && xModifiable->isModified() && !bModified)
                    xModifiable->setModified(bModified);
 
                // #i48419# - action 'UpdateReplacement' doesn't
                // have to change the modified state of the document.
                // This is only a workaround for the defect, that this action
                // modifies a document after load, because unnecessarily the
                // replacement graphic is updated, in spite of the fact that
                // nothing has been changed.
                // If the replacement graphic changes by this action, the document
                // will be already modified via other mechanisms.
                {
                    bool bResetEnableSetModified(false);
                    if ( GetDoc()->GetDocShell()->IsEnableSetModified() )
                    {
                        GetDoc()->GetDocShell()->EnableSetModified( false );
                        bResetEnableSetModified = true;
                    }
 
                    //#i79576# don't destroy chart replacement images on load
                    //#i79578# don't request a new replacement image for charts to often
                    //a chart sends a modified call to the framework if it was changed
                    //thus the replacement update is already handled elsewhere
                    if ( !SotExchange::IsChart( xObj->getClassID() ) )
                        xObj.UpdateReplacement();
 
                    if ( bResetEnableSetModified )
                    {
                        GetDoc()->GetDocShell()->EnableSetModified();
                    }
                }
            }
 
            // TODO/LATER: this is only a workaround,
            uno::Reference< chart2::XChartDocument > xChartDocument( xObj->getComponent(), uno::UNO_QUERY );
            bLinkingChart = ( xChartDocument.is() && !xChartDocument->hasInternalDataProvider() );
        }
    }
    catch (const uno::Exception&)
    {
        // TODO/LATER: handle the error
        return;
    }
 
    SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin() );
    if ( !pCli )
    {
        if ( (embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY & nMisc)
             || bLinkingChart
             // --> OD #i117189# - refine condition for non-resizable objects
             // non-resizable objects need to be set the size back by this method
             || ( bNoTextFramePrtAreaChanged && nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
        {
            pCli = new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
        }
        else
            return;
    }
 
    // TODO/LEAN: getMapUnit can switch object to running state
    // xObj.TryRunningState();
 
    awt::Size aSize;
    try
    {
        aSize = xObj->getVisualAreaSize( nAspect );
    }
    catch (const embed::NoVisualAreaSizeException&)
    {
        OSL_FAIL("Can't get visual area size!" );
        // the scaling will not be done
    }
    catch (const uno::Exception&)
    {
        // TODO/LATER: handle the error
        OSL_FAIL("Can't get visual area size!" );
        return;
    }
 
    Size _aVisArea( aSize.Width, aSize.Height );
 
    Fraction aScaleWidth( 1, 1 );
    Fraction aScaleHeight( 1, 1 );
 
    bool bUseObjectSize = false;
 
    // As long as there comes no reasonable size from the object,
    // nothing can be scaled.
    if( _aVisArea.Width() && _aVisArea.Height() )
    {
        const MapMode aTmp( MapUnit::MapTwip );
        MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
        _aVisArea = OutputDevice::LogicToLogic(_aVisArea, MapMode(aUnit), aTmp);
        Size aObjArea;
        if ( pFlyPrtRect )
            aObjArea = pFlyPrtRect->SSize();
        else
            aObjArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ).SSize();
 
        // differ the aObjArea and _aVisArea by 1 Pixel then set new VisArea
        long nX, nY;
        SwSelPaintRects::Get1PixelInLogic( *this, &nX, &nY );
        if( !( _aVisArea.Width() - nX <= aObjArea.Width() &&
               _aVisArea.Width() + nX >= aObjArea.Width() &&
               _aVisArea.Height()- nY <= aObjArea.Height()&&
               _aVisArea.Height()+ nY >= aObjArea.Height() ))
        {
            if ( nMisc & embed::EmbedMisc::EMBED_NEVERRESIZE )
            {
                // the object must not be scaled,
                // the size stored in object must be used for restoring
                bUseObjectSize = true;
            }
            else
            {
                aScaleWidth = Fraction( aObjArea.Width(),   _aVisArea.Width() );
                aScaleHeight = Fraction( aObjArea.Height(), _aVisArea.Height());
            }
        }
    }
 
    // Now is the favorable time to set the ObjArea.
    // The Scaling must be considered.
    SwRect aArea;
    if ( pFlyPrtRect )
    {
        aArea = *pFlyPrtRect;
        aArea += pFlyFrameRect->Pos();
    }
    else
    {
        aArea = GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() );
        aArea.Pos() += GetAnyCurRect( CurRectType::FlyEmbedded, nullptr, xObj.GetObject() ).Pos();
    }
 
    if ( bUseObjectSize )
    {
        // --> this moves non-resizable object so that when adding borders the baseline remains the same
        const SwFlyFrameFormat *pFlyFrameFormat = dynamic_cast< const SwFlyFrameFormat * >( GetFlyFrameFormat() );
        OSL_ENSURE( pFlyFrameFormat, "Could not find fly frame." );
        if ( pFlyFrameFormat )
        {
            const Point &rPoint = pFlyFrameFormat->GetLastFlyFramePrtRectPos();
            SwRect aRect( pFlyPrtRect ? *pFlyPrtRect
                        : GetAnyCurRect( CurRectType::FlyEmbeddedPrt, nullptr, xObj.GetObject() ));
            aArea += rPoint - aRect.Pos(); // adjust area by diff of printing area position in order to keep baseline alignment correct.
        }
        aArea.Width ( _aVisArea.Width() );
        aArea.Height( _aVisArea.Height() );
        RequestObjectResize( aArea, xObj.GetObject() );
    }
    else
    {
        aArea.Width ( long( aArea.Width()  / pCli->GetScaleWidth() ) );
        aArea.Height( long( aArea.Height() / pCli->GetScaleHeight() ) );
    }
 
    pCli->SetObjAreaAndScale( aArea.SVRect(), aScaleWidth, aScaleHeight );
}
 
void SwWrtShell::ConnectObj( svt::EmbeddedObjectRef& xObj, const SwRect &rPrt,
                            const SwRect &rFrame )
{
    SfxInPlaceClient* pCli = GetView().FindIPClient( xObj.GetObject(), &GetView().GetEditWin());
    if ( !pCli )
        new SwOleClient( &GetView(), &GetView().GetEditWin(), xObj );
    CalcAndSetScale( xObj, &rPrt, &rFrame );
}
 
// Insert hard page break;
// Selections will be overwritten
void SwWrtShell::InsertPageBreak(const OUString *pPageDesc, const ::boost::optional<sal_uInt16>& oPgNum )
{
    ResetCursorStack();
    if( CanInsert() )
    {
        SwActContext aActContext(this);
        StartUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
 
        if ( !IsCursorInTable() )
        {
            if(HasSelection())
                DelRight();
            SwFEShell::SplitNode();
            // delete the numbered attribute of the last line if the last line is empty
            GetDoc()->ClearLineNumAttrs( *GetCursor()->GetPoint() );
        }
 
        const SwPageDesc *pDesc = pPageDesc
                                ? FindPageDescByName( *pPageDesc, true ) : nullptr;
        if( pDesc )
        {
            SwFormatPageDesc aDesc( pDesc );
            aDesc.SetNumOffset( oPgNum );
            SetAttrItem( aDesc );
        }
        else
            SetAttrItem( SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK) );
        EndUndo(SwUndoId::UI_INSERT_PAGE_BREAK);
    }
}
 
// Insert hard page break;
// Selections will be overwritten
 
void SwWrtShell::InsertLineBreak()
{
    ResetCursorStack();
    if( CanInsert() )
    {
        if(HasSelection())
            DelRight();
 
        const sal_Unicode cIns = 0x0A;
        SvxAutoCorrect* pACorr = lcl_IsAutoCorr();
        if( pACorr )
            AutoCorrect( *pACorr, cIns );
        else
            SwWrtShell::Insert( OUString( cIns ) );
    }
}
 
// Insert hard column break;
// Selections will be overwritten
 
void SwWrtShell::InsertColumnBreak()
{
    SwActContext aActContext(this);
    ResetCursorStack();
    if( CanInsert() )
    {
        StartUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
 
        if ( !IsCursorInTable() )
        {
            if(HasSelection())
                DelRight();
            SwFEShell::SplitNode( false, false );
        }
        SetAttrItem(SvxFormatBreakItem(SvxBreak::ColumnBefore, RES_BREAK));
 
        EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK);
    }
}
 
// Insert footnote
// rStr - optional footnote mark
 
void SwWrtShell::InsertFootnote(const OUString &rStr, bool bEndNote, bool bEdit )
{
    ResetCursorStack();
    if( CanInsert() )
    {
        if(HasSelection())
        {
            //collapse cursor to the end
            if(!IsCursorPtAtEnd())
                SwapPam();
            ClearMark();
        }
        SwPosition aPos = *GetCursor()->GetPoint();
        SwFormatFootnote aFootNote( bEndNote );
        if(!rStr.isEmpty())
            aFootNote.SetNumStr( rStr );
 
        SetAttrItem(aFootNote);
 
        if( bEdit )
        {
            // For editing the footnote text.
            Left(CRSR_SKIP_CHARS, false, 1, false );
            GotoFootnoteText();
        }
        m_aNavigationMgr.addEntry(aPos);
    }
}
 
// SplitNode; also, because
//                  - of deleting selected content;
//                  - of reset of the Cursorstack if necessary.
 
void SwWrtShell::SplitNode( bool bAutoFormat )
{
    ResetCursorStack();
    if( CanInsert() )
    {
        SwActContext aActContext(this);
 
        m_rView.GetEditWin().FlushInBuffer();
        bool bHasSel = HasSelection();
        if( bHasSel )
        {
            StartUndo( SwUndoId::INSERT );
            DelRight();
        }
 
        SwFEShell::SplitNode( bAutoFormat );
        if( bHasSel )
            EndUndo( SwUndoId::INSERT );
    }
}
 
// Turn on numbering
// Parameter:   Optional specification of a name for the named list;
//              this indicates a position if it is possible to convert them
//              into a number and less than nMaxRules.
 
// To test the CharFormats at the numbering
// external void SetNumChrFormat( SwWrtShell*, SwNumRules& );
 
// -> #i40041#
// Preconditions (as far as OD has figured out):
// - <SwEditShell::HasNumber()> is false, if <bNum> is true
// - <SwEditShell::HasBullet()> is false, if <bNum> is false
// Behavior of method is determined by the current situation at the current
// cursor position in the document.
void SwWrtShell::NumOrBulletOn(bool bNum)
{
    // determine numbering rule found at current cursor position in the document.
    const SwNumRule* pCurRule = GetNumRuleAtCurrCursorPos();
 
    StartUndo(SwUndoId::NUMORNONUM);
 
    const SwNumRule * pNumRule = pCurRule;
 
    // - activate outline rule respectively turning on outline rule for
    //   current text node. But, only for turning on a numbering (<bNum> == true).
    // - overwrite found numbering rule at current cursor position, if
    //   no numbering rule can be retrieved from the paragraph style.
    bool bContinueFoundNumRule( false );
    bool bActivateOutlineRule( false );
    int nActivateOutlineLvl( MAXLEVEL );    // only relevant, if <bActivateOutlineRule> == true
    SwTextFormatColl * pColl = GetCurTextFormatColl();
    if ( pColl )
    {
        // retrieve numbering rule at paragraph
        // style, which is found at current cursor position in the document.
        SwNumRule* pCollRule = mxDoc->FindNumRulePtr(pColl->GetNumRule().GetValue());
        // #125993# - The outline numbering rule isn't allowed
        // to be derived from a parent paragraph style to a derived one.
        // Thus check, if the found outline numbering rule is directly
        // set at the paragraph style <pColl>. If not, set <pCollRule> to NULL
        if ( pCollRule && pCollRule == GetDoc()->GetOutlineNumRule() )
        {
            const SwNumRule* pDirectCollRule =
                    mxDoc->FindNumRulePtr(pColl->GetNumRule( false ).GetValue());
            if ( !pDirectCollRule )
            {
                pCollRule = nullptr;
            }
        }
 
        if ( !pCollRule )
        {
            pNumRule = pCollRule;
        }
        // no activation or continuation of outline numbering in Writer/Web document
        else if ( bNum &&
                  !dynamic_cast<SwWebDocShell*>(GetDoc()->GetDocShell()) &&
                  pCollRule == GetDoc()->GetOutlineNumRule() )
        {
            if ( pNumRule == pCollRule )
            {
                // check, if text node at current cursor positioned is counted.
                // If not, let it been counted. Then it has to be checked,
                // of the outline numbering has to be activated or continued.
                SwTextNode* pTextNode =
                            GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
                if ( pTextNode && !pTextNode->IsCountedInList() )
                {
                    // check, if numbering of the outline level of the paragraph
                    // style is active. If not, activate this outline level.
                    nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
                    OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
                            "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
                    if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
                         pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
                            == SVX_NUM_NUMBER_NONE )
                    {
                        // activate outline numbering
                        bActivateOutlineRule = true;
                    }
                    else
                    {
                        // turning on outline numbering at current cursor position
                        bContinueFoundNumRule = true;
                    }
                }
                else
                {
                    // #i101234#
                    // activate outline numbering, because from the precondition
                    // it's known, that <SwEdit::HasNumber()> == false
                    bActivateOutlineRule = true;
                    nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
                }
            }
            else if ( !pNumRule )
            {
                // #i101234#
                // Check, if corresponding list level of the outline numbering
                // has already a numbering format set.
                nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
                if ( pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
                                == SVX_NUM_NUMBER_NONE )
                {
                    // activate outline numbering, because from the precondition
                    // it's known, that <SwEdit::HasNumber()> == false
                    bActivateOutlineRule = true;
                }
                else
                {
                    // turning on outline numbering at current cursor position
                    bContinueFoundNumRule = true;
                }
            }
            else
            {
                // check, if numbering of the outline level of the paragraph
                // style is active. If not, activate this outline level.
                nActivateOutlineLvl = pColl->GetAssignedOutlineStyleLevel();
                OSL_ENSURE( pColl->IsAssignedToListLevelOfOutlineStyle(),
                        "<SwWrtShell::NumOrBulletOn(..)> - paragraph style with outline rule, but no outline level" );
                if ( pColl->IsAssignedToListLevelOfOutlineStyle() &&
                     pCollRule->Get( static_cast<sal_uInt16>(nActivateOutlineLvl) ).GetNumberingType()
                        == SVX_NUM_NUMBER_NONE )
                {
                    // activate outline numbering
                    bActivateOutlineRule = true;
                }
                else
                {
                    // turning on outline numbering at current cursor position
                    bContinueFoundNumRule = true;
                }
            }
            pNumRule = pCollRule;
        }
    }
 
    // Only automatic numbering/bullet rules should be changed.
    // Note: The outline numbering rule is also an automatic one. It's only
    //       changed, if it has to be activated.
    if ( pNumRule )
    {
        if ( !pNumRule->IsAutoRule() )
        {
            pNumRule = nullptr;
        }
        else if ( pNumRule == GetDoc()->GetOutlineNumRule() &&
                  !bActivateOutlineRule && !bContinueFoundNumRule )
        {
            pNumRule = nullptr;
        }
    }
 
    // Search for a previous numbering/bullet rule to continue it.
    OUString sContinuedListId;
    if ( !pNumRule )
    {
        pNumRule = GetDoc()->SearchNumRule( *GetCursor()->GetPoint(),
                                            false, bNum, false, 0,
                                            sContinuedListId );
        bContinueFoundNumRule = pNumRule != nullptr;
    }
 
    if (pNumRule)
    {
        SwNumRule aNumRule(*pNumRule);
 
        // do not change found numbering/bullet rule, if it should only be continued.
        if ( !bContinueFoundNumRule )
        {
            SwTextNode * pTextNode = GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
 
            if (pTextNode)
            {
                // use above retrieve outline level, if outline numbering has to be activated.
                int nLevel = bActivateOutlineRule
                              ? nActivateOutlineLvl
                              : pTextNode->GetActualListLevel();
 
                if (nLevel < 0)
                    nLevel = 0;
 
                if (nLevel >= MAXLEVEL)
                    nLevel = MAXLEVEL - 1;
 
                SwNumFormat aFormat(aNumRule.Get(static_cast<sal_uInt16>(nLevel)));
 
                if (bNum)
                    aFormat.SetNumberingType(SVX_NUM_ARABIC);
                else
                {
                    // #i63395# Only apply user defined default bullet font
                    if ( numfunc::IsDefBulletFontUserDefined() )
                    {
                        const vcl::Font* pFnt = &numfunc::GetDefBulletFont();
                        aFormat.SetBulletFont( pFnt );
                    }
                    aFormat.SetBulletChar( numfunc::GetBulletChar(static_cast<sal_uInt8>(nLevel)));
                    aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
                    // #i93908# clear suffix for bullet lists
                    aFormat.SetPrefix(OUString());
                    aFormat.SetSuffix(OUString());
                }
                aNumRule.Set(static_cast<sal_uInt16>(nLevel), aFormat);
            }
        }
 
        // reset indent attribute on applying list style
        SetCurNumRule( aNumRule, false, sContinuedListId, true );
    }
    else
    {
        // #i95907#
        const SvxNumberFormat::SvxNumPositionAndSpaceMode ePosAndSpaceMode(
                                    numfunc::GetDefaultPositionAndSpaceMode() );
        SwNumRule aNumRule( GetUniqueNumRuleName(), ePosAndSpaceMode );
        // Append the character template at the numbering.
        SwCharFormat* pChrFormat;
        SwDocShell* pDocSh = GetView().GetDocShell();
        // #i63395#
        // Only apply user defined default bullet font
        const vcl::Font* pFnt = numfunc::IsDefBulletFontUserDefined()
                           ? &numfunc::GetDefBulletFont()
                           : nullptr;
 
        if (bNum)
        {
            pChrFormat = GetCharFormatFromPool( RES_POOLCHR_NUM_LEVEL );
        }
        else
        {
            pChrFormat = GetCharFormatFromPool( RES_POOLCHR_BUL_LEVEL );
        }
 
        const SwTextNode* pTextNode = GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
        const SwTwips nWidthOfTabs = pTextNode
                                     ? pTextNode->GetWidthOfLeadingTabs()
                                     : 0;
        GetDoc()->getIDocumentContentOperations().RemoveLeadingWhiteSpace( *GetCursor()->GetPoint() );
 
        const bool bHtml = dynamic_cast<SwWebDocShell*>( pDocSh ) !=  nullptr;
        const bool bRightToLeft = IsInRightToLeftText();
        for( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
        {
            SwNumFormat aFormat( aNumRule.Get( nLvl ) );
            aFormat.SetCharFormat( pChrFormat );
 
            if (! bNum)
            {
                // #i63395#
                // Only apply user defined default bullet font
                if ( pFnt )
                {
                    aFormat.SetBulletFont( pFnt );
                }
                aFormat.SetBulletChar( numfunc::GetBulletChar(nLvl) );
                aFormat.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
                // #i93908# clear suffix for bullet lists
                aFormat.SetPrefix(OUString());
                aFormat.SetSuffix(OUString());
            }
 
            // #i95907#
            if ( ePosAndSpaceMode == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
            {
                if(bHtml && nLvl)
                {
                    // 1/2" for HTML
                    aFormat.SetAbsLSpace(nLvl * 720);
                }
                else if ( nWidthOfTabs > 0 )
                {
                    aFormat.SetAbsLSpace(nWidthOfTabs + nLvl * 720);
                }
            }
 
            // #i38904#  Default alignment for
            // numbering/bullet should be rtl in rtl paragraph:
            if ( bRightToLeft )
            {
                aFormat.SetNumAdjust( SvxAdjust::Right );
            }
 
            aNumRule.Set( nLvl, aFormat );
        }
 
        // #i95907#
        if ( pTextNode &&
             ePosAndSpaceMode == SvxNumberFormat::LABEL_ALIGNMENT )
        {
 
            const SwTwips nTextNodeIndent = pTextNode->GetAdditionalIndentForStartingNewList();
            if ( ( nTextNodeIndent + nWidthOfTabs ) != 0 )
            {
                // #i111172#/fdo#85666
                // If text node is already inside a list, assure that the indents
                // are the same. Thus, adjust the indent change value by subtracting
                // indents of to be applied list style.
                SwTwips nIndentChange = nTextNodeIndent + nWidthOfTabs;
                if ( pTextNode->GetNumRule() )
                {
                    int nLevel = pTextNode->GetActualListLevel();
 
                    if (nLevel < 0)
                        nLevel = 0;
 
                    if (nLevel >= MAXLEVEL)
                        nLevel = MAXLEVEL - 1;
 
                    const SwNumFormat aFormat( aNumRule.Get( nLevel ) );
                    if ( aFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
                    {
                        nIndentChange -= aFormat.GetIndentAt() + aFormat.GetFirstLineIndent();
                    }
                }
                aNumRule.ChangeIndent( nIndentChange );
            }
        }
        // reset indent attribute on applying list style
        // start new list
        SetCurNumRule( aNumRule, true, OUString(), true );
    }
 
    EndUndo(SwUndoId::NUMORNONUM);
}
// <- #i40041#
 
void SwWrtShell::NumOn()
{
    NumOrBulletOn(true);
}
 
void SwWrtShell::NumOrBulletOff()
{
    const SwNumRule * pCurNumRule = GetNumRuleAtCurrCursorPos();
 
    if (pCurNumRule)
    {
        if (pCurNumRule->IsOutlineRule())
        {
            SwNumRule aNumRule(*pCurNumRule);
 
            SwTextNode * pTextNode =
                GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
 
            if (pTextNode)
            {
                int nLevel = pTextNode->GetActualListLevel();
 
                if (nLevel < 0)
                    nLevel = 0;
 
                if (nLevel >= MAXLEVEL)
                    nLevel = MAXLEVEL - 1;
 
                SwNumFormat aFormat(aNumRule.Get(static_cast<sal_uInt16>(nLevel)));
 
                aFormat.SetNumberingType(SVX_NUM_NUMBER_NONE);
                aNumRule.Set(nLevel, aFormat);
 
                // no start or continuation of a list - the outline style is only changed.
                SetCurNumRule( aNumRule, false );
            }
        }
        else
        {
            DelNumRules();
        }
 
        // #126346# - Cursor can not be anymore in front of
        // a label, because numbering/bullet is switched off.
        SetInFrontOfLabel( false );
    }
}
// <- #i29560#
 
// Request Default-Bulletlist
 
void SwWrtShell::BulletOn()
{
    NumOrBulletOn(false);
}
 
SelectionType SwWrtShell::GetSelectionType() const
{
    // ContentType cannot be determined within a Start-/EndAction.
    // Because there is no invalid value TEXT will be returned.
    // The value does not matter, it may be updated in EndAction anyway.
 
    if (ActionPend())
        return IsSelFrameMode() ? SelectionType::Frame : SelectionType::Text;
 
    SwView &_rView = const_cast<SwView&>(GetView());
    if (_rView.GetPostItMgr() && _rView.GetPostItMgr()->HasActiveSidebarWin() )
        return SelectionType::PostIt;
 
    // Inserting a frame is not a DrawMode
    SelectionType nCnt;
    if ( !_rView.GetEditWin().IsFrameAction() &&
        (IsObjSelected() || (_rView.IsDrawMode() && !IsFrameSelected()) ))
    {
        if (GetDrawView()->IsTextEdit())
            nCnt = SelectionType::DrawObjectEditMode;
        else
        {
            if (GetView().IsFormMode()) // Only Form selected
                nCnt = SelectionType::DbForm;
            else
                nCnt = SelectionType::DrawObject;            // Any draw object
 
            if (_rView.IsBezierEditMode())
                nCnt |= SelectionType::Ornament;
            else if( GetDrawView()->GetContext() == SdrViewContext::Media )
                nCnt |= SelectionType::Media;
 
            if (svx::checkForSelectedCustomShapes( GetDrawView(), true /* bOnlyExtruded */ ))
            {
                nCnt |= SelectionType::ExtrudedCustomShape;
            }
            sal_uInt32 nCheckStatus = 0;
            if (svx::checkForSelectedFontWork( GetDrawView(), nCheckStatus ))
            {
                nCnt |= SelectionType::FontWork;
            }
        }
 
        return nCnt;
    }
 
    nCnt = static_cast<SelectionType>(GetCntType());
 
    if ( IsFrameSelected() )
    {
        if (_rView.IsDrawMode())
            _rView.LeaveDrawCreate();   // clean up (Bug #45639)
        if ( !(nCnt & (SelectionType::Graphic | SelectionType::Ole)) )
            return SelectionType::Frame;
    }
 
    if ( IsCursorInTable() )
        nCnt |= SelectionType::Table;
 
    if ( IsTableMode() )
        nCnt |= (SelectionType::Table | SelectionType::TableCell);
 
    // Do not pop up numbering toolbar, if the text node has a numbering of type SVX_NUM_NUMBER_NONE.
    const SwNumRule* pNumRule = GetNumRuleAtCurrCursorPos();
    if ( pNumRule )
    {
        const SwTextNode* pTextNd =
            GetCursor()->GetPoint()->nNode.GetNode().GetTextNode();
 
        if ( pTextNd && pTextNd->IsInList() )
        {
            int nLevel = pTextNd->GetActualListLevel();
 
            if (nLevel < 0)
                nLevel = 0;
 
            if (nLevel >= MAXLEVEL)
                nLevel = MAXLEVEL - 1;
 
            const SwNumFormat& rFormat = pNumRule->Get(nLevel);
            if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
                nCnt |= SelectionType::NumberList;
        }
    }
 
    return nCnt;
}
 
// Find the text collection with the name rCollname
// Returns:   Pointer at the collection or 0, if no
//            text collection with this name exists, or
//            this is a default template.
 
SwTextFormatColl *SwWrtShell::GetParaStyle(const OUString &rCollName, GetStyle eCreate )
{
    SwTextFormatColl* pColl = FindTextFormatCollByName( rCollName );
    if( !pColl && GETSTYLE_NOCREATE != eCreate )
    {
        sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rCollName, SwGetPoolIdFromName::TxtColl );
        if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
            pColl = GetTextCollFromPool( nId );
    }
    return pColl;
}
 
// Find the text collection with the name rCollname
// Returns:   Pointer at the collection or 0, if no
//            character template with this name exists, or
//            this is a default template or template is automatic.
 
SwCharFormat *SwWrtShell::GetCharStyle(const OUString &rFormatName, GetStyle eCreate )
{
    SwCharFormat* pFormat = FindCharFormatByName( rFormatName );
    if( !pFormat && GETSTYLE_NOCREATE != eCreate )
    {
        sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( rFormatName, SwGetPoolIdFromName::ChrFmt );
        if( USHRT_MAX != nId || GETSTYLE_CREATEANY == eCreate )
            pFormat = static_cast<SwCharFormat*>(GetFormatFromPool( nId ));
    }
    return pFormat;
}
 
// Find the table format with the name rFormatname
// Returns:   Pointer at the collection or 0, if no
//            frame format with this name exists or
//            this is a default format or the format is automatic.
 
SwFrameFormat *SwWrtShell::GetTableStyle(const OUString &rFormatName)
{
    for( size_t i = GetTableFrameFormatCount(); i; )
    {
        SwFrameFormat *pFormat = &GetTableFrameFormat( --i );
        if( !pFormat->IsDefault() &&
            pFormat->GetName() == rFormatName && IsUsed( *pFormat ) )
            return pFormat;
    }
    return nullptr;
}
 
void SwWrtShell::addCurrentPosition() {
    SwPaM* pPaM = GetCursor();
    m_aNavigationMgr.addEntry(*pPaM->GetPoint());
}
 
// Applying templates
 
void SwWrtShell::SetPageStyle(const OUString &rCollName)
{
    if( !SwCursorShell::HasSelection() && !IsSelFrameMode() && !IsObjSelected() )
    {
        SwPageDesc* pDesc = FindPageDescByName( rCollName, true );
        if( pDesc )
            ChgCurPageDesc( *pDesc );
    }
}
 
// Access templates
 
OUString const & SwWrtShell::GetCurPageStyle() const
{
    return GetPageDesc(GetCurPageDesc( false/*bCalcFrame*/ )).GetName();
}
 
// Change the current template referring to the existing change.
 
void SwWrtShell::QuickUpdateStyle()
{
    SwTextFormatColl *pColl = GetCurTextFormatColl();
 
    // Default cannot be changed
    if(pColl && !pColl->IsDefault())
    {
        FillByEx(pColl);
            // Also apply the template to remove hard attribute assignment.
        SetTextFormatColl(pColl);
    }
}
 
void SwWrtShell::AutoUpdatePara(SwTextFormatColl* pColl, const SfxItemSet& rStyleSet, SwPaM* pPaM )
{
    SwPaM* pCursor = pPaM ? pPaM : GetCursor( );
    SfxItemSet aCoreSet(
        GetAttrPool(),
        svl::Items<
            RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
            RES_PARATR_BEGIN, RES_PARATR_END - 1,
            RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
            SID_ATTR_TABSTOP_DEFAULTS,SID_ATTR_TABSTOP_OFFSET,
            SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER,
            SID_ATTR_PARA_MODEL, SID_ATTR_PARA_KEEP,
            SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM>{});
    GetPaMAttr( pCursor, aCoreSet );
    bool bReset = false;
    SfxItemIter aParaIter( aCoreSet );
    const SfxPoolItem* pParaItem = aParaIter.FirstItem();
    while( pParaItem )
    {
        if(!IsInvalidItem(pParaItem))
        {
            sal_uInt16 nWhich = pParaItem->Which();
            if(SfxItemState::SET == aCoreSet.GetItemState(nWhich) &&
               SfxItemState::SET == rStyleSet.GetItemState(nWhich))
            {
                aCoreSet.ClearItem(nWhich);
                bReset = true;
            }
        }
        pParaItem = aParaIter.NextItem();
    }
    StartAction();
    if(bReset)
    {
        ResetAttr( std::set<sal_uInt16>(), pCursor );
        SetAttrSet(aCoreSet, SetAttrMode::DEFAULT, pCursor);
    }
    mxDoc->ChgFormat(*pColl, rStyleSet );
    EndAction();
}
 
void SwWrtShell::AutoUpdateFrame( SwFrameFormat* pFormat, const SfxItemSet& rStyleSet )
{
    StartAction();
 
    ResetFlyFrameAttr( &rStyleSet );
    pFormat->SetFormatAttr( rStyleSet );
 
    EndAction();
}
 
void SwWrtShell::AutoCorrect( SvxAutoCorrect& rACorr, sal_Unicode cChar )
{
    ResetCursorStack();
    if(CanInsert())
    {
        bool bStarted = false;
        SwRewriter aRewriter;
 
        if(HasSelection())
        {
                // Only parentheses here, because the regular insert
                // is already clipped to the editshell
            StartAllAction();
 
            OUString aTmpStr1;
            aTmpStr1 += SwResId(STR_START_QUOTE);
            aTmpStr1 += GetSelText();
            aTmpStr1 += SwResId(STR_END_QUOTE);
            OUString aTmpStr3;
            aTmpStr3 += SwResId(STR_START_QUOTE);
            aTmpStr3 += OUStringLiteral1(cChar);
            aTmpStr3 += SwResId(STR_END_QUOTE);
            aRewriter.AddRule( UndoArg1, aTmpStr1 );
            aRewriter.AddRule( UndoArg2, SwResId(STR_YIELDS) );
            aRewriter.AddRule( UndoArg3, aTmpStr3 );
 
            StartUndo( SwUndoId::REPLACE, &aRewriter );
            bStarted = true;
            DelRight();
        }
        SwEditShell::AutoCorrect( rACorr, IsInsMode(), cChar );
 
        if(bStarted)
        {
            EndAllAction();
            EndUndo( SwUndoId::REPLACE, &aRewriter );
        }
    }
}
 
// Some kind of controlled copy ctor
 
SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window *_pWin, SwView &rShell )
    : SwFEShell( rSh, _pWin ),
     COMMON_INI_LIST
{
    BITFLD_INI_LIST
    SET_CURR_SHELL( this );
 
    SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
    SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
 
    // place the cursor on the first field...
    IFieldmark *pBM = nullptr;
    if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
        GotoFieldmark(pBM);
    }
}
 
SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, SwView &rShell,
                        const SwViewOption *pViewOpt )
    : SwFEShell( rDoc, _pWin, pViewOpt),
      COMMON_INI_LIST
{
    BITFLD_INI_LIST
    SET_CURR_SHELL( this );
    SetSfxViewShell( static_cast<SfxViewShell *>(&rShell) );
    SetFlyMacroLnk( LINK(this, SwWrtShell, ExecFlyMac) );
 
    // place the cursor on the first field...
    IFieldmark *pBM = nullptr;
    if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
        GotoFieldmark(pBM);
    }
}
 
SwWrtShell::~SwWrtShell()
{
    SET_CURR_SHELL( this );
    while(IsModePushed())
        PopMode();
    while(PopCursor(false))
        ;
    SwTransferable::ClearSelection( *this );
}
 
bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete)
{
    bool bRet = SwCursorShell::Pop(eDelete);
    if( bRet && IsSelection() )
    {
        m_fnSetCursor = &SwWrtShell::SetCursorKillSel;
        m_fnKillSel = &SwWrtShell::ResetSelect;
    }
    return bRet;
}
 
bool SwWrtShell::CanInsert()
{
    if(IsSelFrameMode())
    {
        return false;
    }
 
    if(IsObjSelected())
    {
        return false;
    }
 
    if(GetView().GetDrawFuncPtr())
    {
        return false;
    }
 
    if(GetView().GetPostItMgr()->GetActiveSidebarWin())
    {
        return false;
    }
 
    return true;
}
 
void SwWrtShell::ChgDBData(const SwDBData& aDBData)
{
    SwEditShell::ChgDBData(aDBData);
    //notify the db-beamer if available
    GetView().NotifyDBChanged();
}
 
OUString SwWrtShell::GetSelDescr() const
{
    OUString aResult;
 
    SelectionType nSelType = GetSelectionType();
    switch (nSelType)
    {
    case SelectionType::Graphic:
        aResult = SwResId(STR_GRAPHIC);
 
        break;
    case SelectionType::Frame:
        {
            const SwFrameFormat * pFrameFormat = GetSelectedFrameFormat();
 
            if (pFrameFormat)
                aResult = pFrameFormat->GetDescription();
        }
        break;
    case SelectionType::DrawObject:
        {
            aResult = SwResId(STR_DRAWING_OBJECTS);
        }
        break;
    default:
        if (mxDoc.get())
            aResult = GetCursorDescr();
    }
 
    return aResult;
}
 
void SwWrtShell::ApplyViewOptions( const SwViewOption &rOpt )
{
    SwFEShell::ApplyViewOptions( rOpt );
    //#i115062# invalidate meta character slot
    GetView().GetViewFrame()->GetBindings().Invalidate( FN_VIEW_META_CHARS );
}
 
void SwWrtShell::SetReadonlyOption(bool bSet)
{
    GetView().GetEditWin().GetFrameControlsManager().SetReadonlyControls( bSet );
    SwViewShell::SetReadonlyOption( bSet );
}
 
// Switch on/off header or footer of a page style - if an empty name is
// given all styles are changed
 
void SwWrtShell::ChangeHeaderOrFooter(
    const OUString& rStyleName, bool bHeader, bool bOn, bool bShowWarning)
{
    SdrView *const pSdrView = GetDrawView();
    if (pSdrView && pSdrView->IsTextEdit())
    {   // tdf#107474 deleting header may delete active drawing object
        pSdrView->SdrEndTextEdit(true);
    }
    addCurrentPosition();
    StartAllAction();
    StartUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
    bool bExecute = true;
    bool bCursorSet = false;
    for( size_t nFrom = 0, nTo = GetPageDescCnt();
            nFrom < nTo; ++nFrom )
    {
        SwPageDesc aDesc( GetPageDesc( nFrom ));
        OUString sTmp(aDesc.GetName());
        if( rStyleName.isEmpty() || rStyleName == sTmp )
        {
            bool bChgd = false;
 
            if( bShowWarning && !bOn && GetActiveView() && GetActiveView() == &GetView() &&
                ( (bHeader && aDesc.GetMaster().GetHeader().IsActive()) ||
                  (!bHeader && aDesc.GetMaster().GetFooter().IsActive()) ) )
            {
                bShowWarning = false;
                //Actions have to be closed while the dialog is showing
                EndAllAction();
 
                weld::Window* pParent = GetView().GetViewFrame()->GetWindow().GetFrameWeld();
                short nResult;
                if (bHeader) {
                    nResult = DeleteHeaderDialog(pParent).run();
                } else {
                    nResult = DeleteFooterDialog(pParent).run();
                }
 
                bExecute = nResult == RET_YES;
                StartAllAction();
            }
            if( bExecute )
            {
                bChgd = true;
                SwFrameFormat &rMaster = aDesc.GetMaster();
                if(bHeader)
                    rMaster.SetFormatAttr( SwFormatHeader( bOn ));
                else
                    rMaster.SetFormatAttr( SwFormatFooter( bOn ));
                if( bOn )
                {
                    SvxULSpaceItem aUL(bHeader ? 0 : MM50, bHeader ? MM50 : 0, RES_UL_SPACE );
                    SwFrameFormat* pFormat = bHeader ?
                        const_cast<SwFrameFormat*>(rMaster.GetHeader().GetHeaderFormat()) :
                        const_cast<SwFrameFormat*>(rMaster.GetFooter().GetFooterFormat());
                    pFormat->SetFormatAttr( aUL );
                }
            }
            if( bChgd )
            {
                ChgPageDesc( nFrom, aDesc );
 
                if( !bCursorSet && bOn )
                {
                    if ( !IsHeaderFooterEdit() )
                        ToggleHeaderFooterEdit();
                    bCursorSet = SetCursorInHdFt(
                            rStyleName.isEmpty() ? SIZE_MAX : nFrom,
                            bHeader );
                }
            }
        }
    }
    EndUndo( SwUndoId::HEADER_FOOTER ); // #i7983#
    EndAllAction();
}
 
void SwWrtShell::SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow )
{
    SwViewShell::SetShowHeaderFooterSeparator( eControl, bShow );
    if ( !bShow )
        GetView().GetEditWin().GetFrameControlsManager().HideControls( eControl );
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

V773 The function was exited without releasing the 'pCli' pointer. A memory leak is possible.

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

V1019 Compound assignment expression is used inside condition.