<commit_before>/* -*- 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 <DocumentLayoutManager.hxx>
#include <doc.hxx>
#include <IDocumentState.hxx>
#include <IDocumentUndoRedo.hxx>
#include <DocumentContentOperationsManager.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <undobj.hxx>
#include <viewsh.hxx>
#include <layouter.hxx>
#include <poolfmt.hxx>
#include <frmfmt.hxx>
#include <fmtcntnt.hxx>
#include <fmtcnct.hxx>
#include <ndole.hxx>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <fmtanchr.hxx>
#include <txtflcnt.hxx>
#include <fmtflcnt.hxx>
#include <ndtxt.hxx>
#include <dcontact.hxx>
#include <unoframe.hxx>
#include <docary.hxx>
#include <textboxhelper.hxx>

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

namespace sw
{

DocumentLayoutManager::DocumentLayoutManager( SwDoc& i_rSwdoc ) :
    m_rDoc( i_rSwdoc ),
    mpCurrentView( 0 ),
    mpLayouter( 0 )
{
}

const SwViewShell *DocumentLayoutManager::GetCurrentViewShell() const
{
    return mpCurrentView;
}

SwViewShell *DocumentLayoutManager::GetCurrentViewShell()
{
    return mpCurrentView;
}

void DocumentLayoutManager::SetCurrentViewShell( SwViewShell* pNew )
{
    mpCurrentView = pNew;
}

// It must be able to communicate to a SwViewShell. This is going to be removed later.
const SwRootFrm *DocumentLayoutManager::GetCurrentLayout() const
{
    if(GetCurrentViewShell())
        return GetCurrentViewShell()->GetLayout();
    return 0;
}

SwRootFrm *DocumentLayoutManager::GetCurrentLayout()
{
    if(GetCurrentViewShell())
        return GetCurrentViewShell()->GetLayout();
    return 0;
}

bool DocumentLayoutManager::HasLayout() const
{
    // if there is a view, there is always a layout
    return (mpCurrentView != 0);
}

SwLayouter* DocumentLayoutManager::GetLayouter()
{
    return mpLayouter;
}

const SwLayouter* DocumentLayoutManager::GetLayouter() const
{
    return mpLayouter;
}

void DocumentLayoutManager::SetLayouter( SwLayouter* pNew )
{
    mpLayouter = pNew;
}

/** Create a new format whose settings fit to the Request by default.

    The format is put into the respective format array.
    If there already is a fitting format, it is returned instead. */
SwFrmFmt *DocumentLayoutManager::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
{
    SwFrmFmt *pFmt = 0;
    const bool bMod = m_rDoc.getIDocumentState().IsModified();
    bool bHeader = false;

    switch ( eRequest )
    {
    case RND_STD_HEADER:
    case RND_STD_HEADERL:
    case RND_STD_HEADERR:
        {
            bHeader = true;
            // no break, we continue further down
        }
    case RND_STD_FOOTER:
    case RND_STD_FOOTERL:
    case RND_STD_FOOTERR:
        {
            pFmt = new SwFrmFmt( m_rDoc.GetAttrPool(),
                                 (bHeader ? "Right header" : "Right footer"),
                                 m_rDoc.GetDfltFrmFmt() );

            SwNodeIndex aTmpIdx( m_rDoc.GetNodes().GetEndOfAutotext() );
            SwStartNode* pSttNd =
                m_rDoc.GetNodes().MakeTextSection
                ( aTmpIdx,
                  bHeader ? SwHeaderStartNode : SwFooterStartNode,
                  m_rDoc.getIDocumentStylePoolAccess().GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
                                     ? ( eRequest == RND_STD_HEADERL
                                         ? RES_POOLCOLL_HEADERL
                                         : eRequest == RND_STD_HEADERR
                                         ? RES_POOLCOLL_HEADERR
                                         : RES_POOLCOLL_HEADER )
                                     : ( eRequest == RND_STD_FOOTERL
                                         ? RES_POOLCOLL_FOOTERL
                                         : eRequest == RND_STD_FOOTERR
                                         ? RES_POOLCOLL_FOOTERR
                                         : RES_POOLCOLL_FOOTER )
                                     ) ) );
            pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));

            if( pSet )      // Set a few more attributes
                pFmt->SetFmtAttr( *pSet );

            // Why set it back?  Doc has changed, or not?
            // In any case, wrong for the FlyFrames!
            if ( !bMod )
                m_rDoc.getIDocumentState().ResetModified();
        }
        break;

    case RND_DRAW_OBJECT:
        {
            pFmt = m_rDoc.MakeDrawFrmFmt( OUString(), m_rDoc.GetDfltFrmFmt() );
            if( pSet )      // Set a few more attributes
                pFmt->SetFmtAttr( *pSet );

            if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
            {
                m_rDoc.GetIDocumentUndoRedo().AppendUndo(
                    new SwUndoInsLayFmt(pFmt, 0, 0));
            }
        }
        break;

#if OSL_DEBUG_LEVEL > 0
    case FLY_AT_PAGE:
    case FLY_AT_CHAR:
    case FLY_AT_FLY:
    case FLY_AT_PARA:
    case FLY_AS_CHAR:
        OSL_FAIL( "use new interface instead: SwDoc::MakeFlySection!" );
        break;
#endif

    default:
        OSL_ENSURE( false,
                "LayoutFormat was requested with an invalid Request." );

    }
    return pFmt;
}

/// Deletes the denoted format and its content.
void DocumentLayoutManager::DelLayoutFmt( SwFrmFmt *pFmt )
{
    // A chain of frames needs to be merged, if necessary,
    // so that the Frame's contents are adjusted accordingly before we destroy the Frames.
    const SwFmtChain &rChain = pFmt->GetChain();
    if ( rChain.GetPrev() )
    {
        SwFmtChain aChain( rChain.GetPrev()->GetChain() );
        aChain.SetNext( rChain.GetNext() );
        m_rDoc.SetAttr( aChain, *rChain.GetPrev() );
    }
    if ( rChain.GetNext() )
    {
        SwFmtChain aChain( rChain.GetNext()->GetChain() );
        aChain.SetPrev( rChain.GetPrev() );
        m_rDoc.SetAttr( aChain, *rChain.GetNext() );
    }

    const SwNodeIndex* pCntIdx = 0;
    // The draw format doesn't own its content, it just has a pointer to it.
    if (pFmt->Which() != RES_DRAWFRMFMT)
        pCntIdx = pFmt->GetCntnt().GetCntntIdx();
    if (pCntIdx && !m_rDoc.GetIDocumentUndoRedo().DoesUndo())
    {
        // Disconnect if it's an OLE object
        SwOLENode* pOLENd = m_rDoc.GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
        if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
        {

            // TODO: the old object closed the object and cleared all references to it, but didn't remove it from the container.
            // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
            //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
            //if ( xClose.is() )
            {
                try
                {
                    pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
                }
                catch ( uno::Exception& )
                {
                }
            }

        }
    }

    // Destroy Frames
    pFmt->DelFrms();

    // Only FlyFrames are undoable at first
    const sal_uInt16 nWh = pFmt->Which();
    if (m_rDoc.GetIDocumentUndoRedo().DoesUndo() &&
        (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
    {
        m_rDoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
    }
    else
    {
        // #i32089# - delete at-frame anchored objects
        if ( nWh == RES_FLYFRMFMT )
        {
            // determine frame formats of at-frame anchored objects
            const SwNodeIndex* pCntntIdx = 0;
            if (pFmt->Which() != RES_DRAWFRMFMT)
                pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
            if (pCntntIdx)
            {
                const SwFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
                if ( pTbl )
                {
                    std::vector<SwFrmFmt*> aToDeleteFrmFmts;
                    const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );

                    for ( sal_uInt16 i = 0; i < pTbl->size(); ++i )
                    {
                        SwFrmFmt* pTmpFmt = (*pTbl)[i];
                        const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
                        if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
                             rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
                        {
                            aToDeleteFrmFmts.push_back( pTmpFmt );
                        }
                    }

                    // delete found frame formats
                    while ( !aToDeleteFrmFmts.empty() )
                    {
                        SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
                        pFmt->GetDoc()->getIDocumentLayoutAccess().DelLayoutFmt( pTmpFmt );

                        aToDeleteFrmFmts.pop_back();
                    }
                }
            }
        }

        // Delete content
        if( pCntIdx )
        {
            SwNode *pNode = &pCntIdx->GetNode();
            const_cast<SwFmtCntnt&>(static_cast<const SwFmtCntnt&>(pFmt->GetFmtAttr( RES_CNTNT ))).SetNewCntntIdx( 0 );
            m_rDoc.getIDocumentContentOperations().DeleteSection( pNode );
        }<commit_msg>tdf#89783: fix another potential endless loop<commit_after>/* -*- 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 <DocumentLayoutManager.hxx>
#include <doc.hxx>
#include <IDocumentState.hxx>
#include <IDocumentUndoRedo.hxx>
#include <DocumentContentOperationsManager.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <undobj.hxx>
#include <viewsh.hxx>
#include <layouter.hxx>
#include <poolfmt.hxx>
#include <frmfmt.hxx>
#include <fmtcntnt.hxx>
#include <fmtcnct.hxx>
#include <ndole.hxx>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <fmtanchr.hxx>
#include <txtflcnt.hxx>
#include <fmtflcnt.hxx>
#include <ndtxt.hxx>
#include <dcontact.hxx>
#include <unoframe.hxx>
#include <docary.hxx>
#include <textboxhelper.hxx>

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

namespace sw
{

DocumentLayoutManager::DocumentLayoutManager( SwDoc& i_rSwdoc ) :
    m_rDoc( i_rSwdoc ),
    mpCurrentView( 0 ),
    mpLayouter( 0 )
{
}

const SwViewShell *DocumentLayoutManager::GetCurrentViewShell() const
{
    return mpCurrentView;
}

SwViewShell *DocumentLayoutManager::GetCurrentViewShell()
{
    return mpCurrentView;
}

void DocumentLayoutManager::SetCurrentViewShell( SwViewShell* pNew )
{
    mpCurrentView = pNew;
}

// It must be able to communicate to a SwViewShell. This is going to be removed later.
const SwRootFrm *DocumentLayoutManager::GetCurrentLayout() const
{
    if(GetCurrentViewShell())
        return GetCurrentViewShell()->GetLayout();
    return 0;
}

SwRootFrm *DocumentLayoutManager::GetCurrentLayout()
{
    if(GetCurrentViewShell())
        return GetCurrentViewShell()->GetLayout();
    return 0;
}

bool DocumentLayoutManager::HasLayout() const
{
    // if there is a view, there is always a layout
    return (mpCurrentView != 0);
}

SwLayouter* DocumentLayoutManager::GetLayouter()
{
    return mpLayouter;
}

const SwLayouter* DocumentLayoutManager::GetLayouter() const
{
    return mpLayouter;
}

void DocumentLayoutManager::SetLayouter( SwLayouter* pNew )
{
    mpLayouter = pNew;
}

/** Create a new format whose settings fit to the Request by default.

    The format is put into the respective format array.
    If there already is a fitting format, it is returned instead. */
SwFrmFmt *DocumentLayoutManager::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
{
    SwFrmFmt *pFmt = 0;
    const bool bMod = m_rDoc.getIDocumentState().IsModified();
    bool bHeader = false;

    switch ( eRequest )
    {
    case RND_STD_HEADER:
    case RND_STD_HEADERL:
    case RND_STD_HEADERR:
        {
            bHeader = true;
            // no break, we continue further down
        }
    case RND_STD_FOOTER:
    case RND_STD_FOOTERL:
    case RND_STD_FOOTERR:
        {
            pFmt = new SwFrmFmt( m_rDoc.GetAttrPool(),
                                 (bHeader ? "Right header" : "Right footer"),
                                 m_rDoc.GetDfltFrmFmt() );

            SwNodeIndex aTmpIdx( m_rDoc.GetNodes().GetEndOfAutotext() );
            SwStartNode* pSttNd =
                m_rDoc.GetNodes().MakeTextSection
                ( aTmpIdx,
                  bHeader ? SwHeaderStartNode : SwFooterStartNode,
                  m_rDoc.getIDocumentStylePoolAccess().GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
                                     ? ( eRequest == RND_STD_HEADERL
                                         ? RES_POOLCOLL_HEADERL
                                         : eRequest == RND_STD_HEADERR
                                         ? RES_POOLCOLL_HEADERR
                                         : RES_POOLCOLL_HEADER )
                                     : ( eRequest == RND_STD_FOOTERL
                                         ? RES_POOLCOLL_FOOTERL
                                         : eRequest == RND_STD_FOOTERR
                                         ? RES_POOLCOLL_FOOTERR
                                         : RES_POOLCOLL_FOOTER )
                                     ) ) );
            pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));

            if( pSet )      // Set a few more attributes
                pFmt->SetFmtAttr( *pSet );

            // Why set it back?  Doc has changed, or not?
            // In any case, wrong for the FlyFrames!
            if ( !bMod )
                m_rDoc.getIDocumentState().ResetModified();
        }
        break;

    case RND_DRAW_OBJECT:
        {
            pFmt = m_rDoc.MakeDrawFrmFmt( OUString(), m_rDoc.GetDfltFrmFmt() );
            if( pSet )      // Set a few more attributes
                pFmt->SetFmtAttr( *pSet );

            if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
            {
                m_rDoc.GetIDocumentUndoRedo().AppendUndo(
                    new SwUndoInsLayFmt(pFmt, 0, 0));
            }
        }
        break;

#if OSL_DEBUG_LEVEL > 0
    case FLY_AT_PAGE:
    case FLY_AT_CHAR:
    case FLY_AT_FLY:
    case FLY_AT_PARA:
    case FLY_AS_CHAR:
        OSL_FAIL( "use new interface instead: SwDoc::MakeFlySection!" );
        break;
#endif

    default:
        OSL_ENSURE( false,
                "LayoutFormat was requested with an invalid Request." );

    }
    return pFmt;
}

/// Deletes the denoted format and its content.
void DocumentLayoutManager::DelLayoutFmt( SwFrmFmt *pFmt )
{
    // A chain of frames needs to be merged, if necessary,
    // so that the Frame's contents are adjusted accordingly before we destroy the Frames.
    const SwFmtChain &rChain = pFmt->GetChain();
    if ( rChain.GetPrev() )
    {
        SwFmtChain aChain( rChain.GetPrev()->GetChain() );
        aChain.SetNext( rChain.GetNext() );
        m_rDoc.SetAttr( aChain, *rChain.GetPrev() );
    }
    if ( rChain.GetNext() )
    {
        SwFmtChain aChain( rChain.GetNext()->GetChain() );
        aChain.SetPrev( rChain.GetPrev() );
        m_rDoc.SetAttr( aChain, *rChain.GetNext() );
    }

    const SwNodeIndex* pCntIdx = 0;
    // The draw format doesn't own its content, it just has a pointer to it.
    if (pFmt->Which() != RES_DRAWFRMFMT)
        pCntIdx = pFmt->GetCntnt().GetCntntIdx();
    if (pCntIdx && !m_rDoc.GetIDocumentUndoRedo().DoesUndo())
    {
        // Disconnect if it's an OLE object
        SwOLENode* pOLENd = m_rDoc.GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
        if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
        {

            // TODO: the old object closed the object and cleared all references to it, but didn't remove it from the container.
            // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
            //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
            //if ( xClose.is() )
            {
                try
                {
                    pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
                }
                catch ( uno::Exception& )
                {
                }
            }

        }
    }

    // Destroy Frames
    pFmt->DelFrms();

    // Only FlyFrames are undoable at first
    const sal_uInt16 nWh = pFmt->Which();
    if (m_rDoc.GetIDocumentUndoRedo().DoesUndo() &&
        (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
    {
        m_rDoc.GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
    }
    else
    {
        // #i32089# - delete at-frame anchored objects
        if ( nWh == RES_FLYFRMFMT )
        {
            // determine frame formats of at-frame anchored objects
            const SwNodeIndex* pCntntIdx = 0;
            if (pFmt->Which() != RES_DRAWFRMFMT)
                pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
            if (pCntntIdx)
            {
                const SwFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
                if ( pTbl )
                {
                    std::vector<SwFrmFmt*> aToDeleteFrmFmts;
                    const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );

                    for ( size_t i = 0; i < pTbl->size(); ++i )
                    {
                        SwFrmFmt* pTmpFmt = (*pTbl)[i];
                        const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
                        if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
                             rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
                        {
                            aToDeleteFrmFmts.push_back( pTmpFmt );
                        }
                    }

                    // delete found frame formats
                    while ( !aToDeleteFrmFmts.empty() )
                    {
                        SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
                        pFmt->GetDoc()->getIDocumentLayoutAccess().DelLayoutFmt( pTmpFmt );

                        aToDeleteFrmFmts.pop_back();
                    }
                }
            }
        }

        // Delete content
        if( pCntIdx )
        {
            SwNode *pNode = &pCntIdx->GetNode();
            const_cast<SwFmtCntnt&>(static_cast<const SwFmtCntnt&>(pFmt->GetFmtAttr( RES_CNTNT ))).SetNewCntntIdx( 0 );
            m_rDoc.getIDocumentContentOperations().DeleteSection( pNode );
        }
{'fraction_non_alphanumeric': 0.10083865814696485, 'fraction_numerical': 0.0036441693290734825, 'mean_word_length': 1.929657794676806, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6604185', 'n_tokens_mistral': 6441, 'n_tokens_neox': 6213, 'n_words': 1443}