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

Quelle  unins.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 <UndoInsert.hxx>

#include <hintids.hxx>
#include <unotools/charclass.hxx>
#include <editeng/keepitem.hxx>
#include <svx/svdobj.hxx>
#include <osl/diagnose.h>

#include <fmtcntnt.hxx>
#include <frmfmt.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IShellCursorSupplier.hxx>
#include <swundo.hxx>
#include <pam.hxx>
#include <ndtxt.hxx>
#include <UndoCore.hxx>
#include <UndoDelete.hxx>
#include <UndoAttribute.hxx>
#include <rolbck.hxx>
#include <ndgrf.hxx>
#include <ndole.hxx>
#include <grfatr.hxx>
#include <cntfrm.hxx>
#include <flyfrm.hxx>
#include <swcrsr.hxx>
#include <swtable.hxx>
#include <redline.hxx>
#include <docary.hxx>
#include <acorrect.hxx>

#include <strings.hrc>
#include <utility>

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

// INSERT

std::optional<OUString> SwUndoInsert::GetTextFromDoc() const
{
    std::optional<OUString> aResult;

    SwNodeIndex aNd( m_rDoc.GetNodes(), m_nNode);
    SwContentNode* pCNd = aNd.GetNode().GetContentNode();

    if( pCNd->IsTextNode() )
    {
        OUString sText = pCNd->GetTextNode()->GetText();

        sal_Int32 nStart = m_nContent-m_nLen;
        sal_Int32 nLength = m_nLen;

        if (nStart < 0)
        {
            nLength += nStart;
            nStart = 0;
        }

        aResult = sText.copy(nStart, nLength);
    }

    return aResult;
}

void SwUndoInsert::Init()
{
    // consider Redline
    if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
    {
        m_pRedlData.reset( new SwRedlineData( RedlineType::Insert,
                                       m_rDoc.getIDocumentRedlineAccess().GetRedlineAuthor() ) );
        SetRedlineFlags( m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
    }

    maUndoText = GetTextFromDoc();

    m_bCacheComment = false;
}

SwUndoInsert::SwUndoInsert( const SwNode& rNd, sal_Int32 nCnt,
            sal_Int32 nL,
            const SwInsertFlags nInsertFlags,
            bool bWDelim )
    : SwUndo(SwUndoId::TYPING, rNd.GetDoc()),
        m_nNode( rNd.GetIndex() ), m_nContent(nCnt), m_nLen(nL),
        m_bIsWordDelim( bWDelim ), m_bIsAppend( false )
    , m_bWithRsid(false)
    , m_nInsertFlags(nInsertFlags)
    , m_rDoc(const_cast<SwDoc&>(rNd.GetDoc()))
{
    Init();
}

SwUndoInsert::SwUndoInsert( const SwNode& rNd )
    : SwUndo(SwUndoId::SPLITNODE, rNd.GetDoc()),
        m_nNode( rNd.GetIndex() ), m_nContent(0), m_nLen(1),
        m_bIsWordDelim( false ), m_bIsAppend( true )
    , m_bWithRsid(false)
    , m_nInsertFlags(SwInsertFlags::EMPTYEXPAND)
    , m_rDoc(const_cast<SwDoc&>(rNd.GetDoc()))
{
    Init();
}

// Check if the next Insert can be combined with the current one. If so
// change the length and InsPos. As a result, SwDoc::Insert will not add a
// new object into the Undo list.

bool SwUndoInsert::CanGrouping( sal_Unicode cIns )
{
    if( !m_bIsAppend && m_bIsWordDelim ==
        !GetAppCharClass().isLetterNumeric( OUString( cIns )) )
    {
        m_nLen++;
        m_nContent++;

        if (maUndoText)
            (*maUndoText) += OUStringChar(cIns);

        return true;
    }
    return false;
}

bool SwUndoInsert::CanGrouping( const SwPosition& rPos )
{
    bool bRet = false;
    if( m_nNode == rPos.GetNodeIndex() &&
        m_nContent == rPos.GetContentIndex() )
    {
        // consider Redline
        SwDoc& rDoc = rPos.GetNode().GetDoc();
        if( ( ~RedlineFlags::ShowMask & rDoc.getIDocumentRedlineAccess().GetRedlineFlags() ) ==
            ( ~RedlineFlags::ShowMask & GetRedlineFlags() ) )
        {
            bRet = true;

            // then there is or was still an active Redline:
            // Check if there is another Redline at the InsPosition. If the
            // same exists only once, it can be combined.
            const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
            if( !rTable.empty() )
            {
                SwRedlineData aRData( RedlineType::Insert, rDoc.getIDocumentRedlineAccess().GetRedlineAuthor() );
                const SwContentNode* pIReg = rPos.GetContentNode();
                for(SwRangeRedline* pRedl : rTable)
                {
                    const SwPosition& rIdx = *pRedl->End();
                    if( pIReg == rIdx.GetContentNode() &&
                        m_nContent == rIdx.GetContentIndex() )
                    {
                        if( !pRedl->HasMark() || !m_pRedlData ||
                            *pRedl != *m_pRedlData || *pRedl != aRData )
                        {
                            bRet = false;
                            break;
                        }
                    }
                }
            }
        }
    }
    return bRet;
}

SwUndoInsert::~SwUndoInsert()
{
    if (m_oUndoNodeIndex) // delete the section from UndoNodes array
    {
        // Insert saves the content in IconSection
        SwNodes& rUNds = m_oUndoNodeIndex->GetNodes();
        rUNds.Delete(*m_oUndoNodeIndex,
            rUNds.GetEndOfExtras().GetIndex() - m_oUndoNodeIndex->GetIndex());
        m_oUndoNodeIndex.reset();
    }
    else     // the inserted text
    {
        maText.reset();
    }
    m_pRedlData.reset();
}

void SwUndoInsert::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pTmpDoc = & rContext.GetDoc();
    SwCursor *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());

    if( m_bIsAppend )
    {
        pPam->GetPoint()->Assign(m_nNode);

        if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
        {
            pPam->SetMark();
            pPam->Move( fnMoveBackward );
            pPam->Exchange();
            pTmpDoc->getIDocumentRedlineAccess().DeleteRedline( *pPam, true, RedlineType::Any );
        }
        pPam->DeleteMark();
        pTmpDoc->getIDocumentContentOperations().DelFullPara( *pPam );
        pPam->GetPoint()->SetContent( 0 );
    }
    else
    {
        SwNodeOffset nNd = m_nNode;
        sal_Int32 nCnt = m_nContent;
        if( m_nLen )
        {
            SwNodeIndex aNd( pTmpDoc->GetNodes(), m_nNode);
            SwContentNode* pCNd = aNd.GetNode().GetContentNode();
            SwPaM aPaM( *pCNd, m_nContent );

            aPaM.SetMark();

            SwTextNode * const pTextNode( pCNd->GetTextNode() );
            if ( pTextNode )
            {
                aPaM.GetPoint()->AdjustContent( - m_nLen );
                if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
                    pTmpDoc->getIDocumentRedlineAccess().DeleteRedline( aPaM, true, RedlineType::Any );
                if (m_bWithRsid)
                {
                    // RSID was added: remove any CHARFMT/AUTOFMT that may be
                    // set on the deleted text; EraseText will leave empty
                    // ones behind otherwise
                    pTextNode->DeleteAttributes(RES_TXTATR_AUTOFMT,
                        aPaM.GetPoint()->GetContentIndex(),
                        aPaM.GetMark()->GetContentIndex());
                    pTextNode->DeleteAttributes(RES_TXTATR_CHARFMT,
                        aPaM.GetPoint()->GetContentIndex(),
                        aPaM.GetMark()->GetContentIndex());
                }
                RemoveIdxFromRange( aPaM, false );
                maText = pTextNode->GetText().copy(m_nContent-m_nLen, m_nLen);
                pTextNode->EraseText( *aPaM.GetPoint(), m_nLen );
            }
            else                // otherwise Graphics/OLE/Text/...
            {
                aPaM.Move(fnMoveBackward);
                if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
                    pTmpDoc->getIDocumentRedlineAccess().DeleteRedline( aPaM, true, RedlineType::Any );
                RemoveIdxFromRange( aPaM, false );
            }

            nNd = aPaM.GetPoint()->GetNodeIndex();
            nCnt = aPaM.GetPoint()->GetContentIndex();

            if (!maText)
            {
                m_oUndoNodeIndex.emplace(m_rDoc.GetNodes().GetEndOfContent());
                MoveToUndoNds(aPaM, &*m_oUndoNodeIndex);
            }
            m_nNode = aPaM.GetPoint()->GetNodeIndex();
            m_nContent = aPaM.GetPoint()->GetContentIndex();
        }

        // set cursor to Undo range
        pPam->DeleteMark();

        pPam->GetPoint()->Assign( nNd, nCnt );
    }

    maUndoText.reset();
}

void SwUndoInsert::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pTmpDoc = & rContext.GetDoc();
    SwCursor *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
    pPam->DeleteMark();

    if( m_bIsAppend )
    {
        pPam->GetPoint()->Assign( m_nNode - 1 );
        pTmpDoc->getIDocumentContentOperations().AppendTextNode( *pPam->GetPoint() );

        pPam->SetMark();
        pPam->Move( fnMoveBackward );
        pPam->Exchange();

        if( m_pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
        {
            RedlineFlags eOld = pTmpDoc->getIDocumentRedlineAccess().GetRedlineFlags();
            pTmpDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld & ~RedlineFlags::Ignore);
            pTmpDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData, *pPam ), true);
            pTmpDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
        }
        else if( !( RedlineFlags::Ignore & GetRedlineFlags() ) &&
                !pTmpDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() )
            pTmpDoc->getIDocumentRedlineAccess().SplitRedline( *pPam );

        pPam->DeleteMark();
    }
    else
    {
        pPam->GetPoint()->Assign( m_nNode );
        SwContentNode *const pCNd =
            pPam->GetPoint()->GetNode().GetContentNode();
        pPam->GetPoint()->SetContent( m_nContent );

        if( m_nLen )
        {
            ::std::optional<SwNodeIndex> oMvBkwrd = MovePtBackward(*pPam);

            if (maText)
            {
                SwTextNode *const pTextNode = pCNd->GetTextNode();
                OSL_ENSURE( pTextNode, "where is my textnode ?" );
                OUString const ins(
                    pTextNode->InsertText( *maText, *pPam->GetMark(),
                    m_nInsertFlags) );
                assert(ins.getLength() == maText->getLength()); // must succeed
                maText.reset();
                if (m_bWithRsid) // re-insert RSID
                {
                    SwPaM pam(*pPam->GetMark(), nullptr); // mark -> point
                    pTmpDoc->UpdateRsid(pam, ins.getLength());
                }
            }
            else
            {
                // re-insert content again (first detach m_oUndoNodeIndex!)
                SwNodeOffset const nMvNd = m_oUndoNodeIndex->GetIndex();
                m_oUndoNodeIndex.reset();
                MoveFromUndoNds(*pTmpDoc, nMvNd, *pPam->GetMark());
            }
            m_nNode = pPam->GetMark()->GetNodeIndex();
            m_nContent = pPam->GetMark()->GetContentIndex();

            MovePtForward(*pPam, ::std::move(oMvBkwrd));
            pPam->Exchange();
            if( m_pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
            {
                RedlineFlags eOld = pTmpDoc->getIDocumentRedlineAccess().GetRedlineFlags();
                pTmpDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld & ~RedlineFlags::Ignore);
                pTmpDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData,
                                            *pPam ), true);
                pTmpDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
            }
            else if( !( RedlineFlags::Ignore & GetRedlineFlags() ) &&
                    !pTmpDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() )
                pTmpDoc->getIDocumentRedlineAccess().SplitRedline(*pPam);
        }
    }

    maUndoText = GetTextFromDoc();
}

void SwUndoInsert::RepeatImpl(::sw::RepeatContext & rContext)
{
    if( !m_nLen )
        return;

    SwDoc & rDoc = rContext.GetDoc();
    SwNodeIndex aNd( rDoc.GetNodes(), m_nNode );
    SwContentNode* pCNd = aNd.GetNode().GetContentNode();

    if( !m_bIsAppend && 1 == m_nLen )       // >1 than always Text, otherwise Graphics/OLE/Text/...
    {
        SwPaM aPaM( *pCNd, m_nContent );
        aPaM.SetMark();
        aPaM.Move(fnMoveBackward);
        pCNd = aPaM.GetPointContentNode();
    }

// What happens with the possible selected range ???

    switch( pCNd->GetNodeType() )
    {
    case SwNodeType::Text:
        if( m_bIsAppend )
        {
            rDoc.getIDocumentContentOperations().AppendTextNode( *rContext.GetRepeatPaM().GetPoint() );
        }
        else
        {
            OUString const aText( pCNd->GetTextNode()->GetText() );
            ::sw::GroupUndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
            rDoc.getIDocumentContentOperations().InsertString( rContext.GetRepeatPaM(),
                aText.copy(m_nContent - m_nLen, m_nLen) );
        }
        break;
    case SwNodeType::Grf:
        {
            SwGrfNode* pGrfNd = static_cast<SwGrfNode*>(pCNd);
            OUString sFile;
            OUString sFilter;
            if( pGrfNd->IsGrfLink() )
                pGrfNd->GetFileFilterNms( &sFile, &sFilter );

            rDoc.getIDocumentContentOperations().InsertGraphic(
                                rContext.GetRepeatPaM(), sFile, sFilter,
                                &pGrfNd->GetGrf(),
                                nullptr/* Graphics collection*/, nullptr, nullptr );
        }
        break;

    case SwNodeType::Ole:
        {
            // StarView does not yet provide an option to copy a StarOBJ
            SwOLEObj& rSwOLE = static_cast<SwOLENode*>(pCNd)->GetOLEObj();

            // temporary storage until object is inserted
            // TODO/MBA: seems that here a physical copy is done - not as in drawing layer! Testing!
            // TODO/LATER: Copying through the container would copy the replacement image as well
            comphelper::EmbeddedObjectContainer aCnt;
            OUString aName = aCnt.CreateUniqueObjectName();
            if (aCnt.StoreEmbeddedObject(rSwOLE.GetOleRef(), aName, true, OUString(), OUString()))
            {
                uno::Reference < embed::XEmbeddedObject > aNew = aCnt.GetEmbeddedObject( aName );
                rDoc.getIDocumentContentOperations().InsertEmbObject(
                    rContext.GetRepeatPaM(),
                    svt::EmbeddedObjectRef( aNew,
                        static_cast<SwOLENode*>(pCNd)->GetAspect() ),
                    nullptr );
            }

            break;
        }

    defaultbreak;
    }
}

SwRewriter SwUndoInsert::GetRewriter() const
{
    SwRewriter aResult;
    std::optional<OUString> aStr;
    bool bDone = false;

    if (maText)
        aStr = maText;
    else if (maUndoText)
        aStr = maUndoText;

    if (aStr)
    {
        OUString aString = ShortenString(DenoteSpecialCharacters(*aStr),
                                       nUndoStringLength,
                                       SwResId(STR_LDOTS));

        aResult.AddRule(UndoArg1, aString);

        bDone = true;
    }

    if ( ! bDone )
    {
        aResult.AddRule(UndoArg1, u"??"_ustr);
    }

    return aResult;
}

bool SwUndoInsert::IsIndependent(const SwUndoInsert& rOther) const
{
    return m_nNode != rOther.m_nNode;
}

class SwUndoReplace::Impl
    : private SwUndoSaveContent
{
    OUString m_sOld;
    OUString m_sIns;
    SwNodeOffset m_nSttNd, m_nEndNd, m_nOffset;
    sal_Int32 m_nSttCnt, m_nEndCnt, m_nSetPos, m_nSelEnd;
    bool m_bSplitNext : 1;
    bool m_bRegExp : 1;
    // metadata references for paragraph and following para (if m_bSplitNext)
    std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
    std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;

public:
    Impl(SwPaM const& rPam, OUString aIns, bool const bRegExp);

    void UndoImpl( ::sw::UndoRedoContext & );
    void RedoImpl( ::sw::UndoRedoContext & );

    void SetEnd(SwPaM const& rPam);

    OUString const& GetOld() const { return m_sOld; }
    OUString const& GetIns() const { return m_sIns; }
};

SwUndoReplace::SwUndoReplace(SwPaM const& rPam,
        OUString const& rIns, bool const bRegExp)
    : SwUndo( SwUndoId::REPLACE, rPam.GetDoc() )
    , m_pImpl(std::make_unique<Impl>(rPam, rIns, bRegExp))
{
}

SwUndoReplace::~SwUndoReplace()
{
}

void SwUndoReplace::UndoImpl(::sw::UndoRedoContext & rContext)
{
    m_pImpl->UndoImpl(rContext);
}

void SwUndoReplace::RedoImpl(::sw::UndoRedoContext & rContext)
{
    m_pImpl->RedoImpl(rContext);
}

SwRewriter
MakeUndoReplaceRewriter(sal_uLong const occurrences,
        OUString const& sOld, OUString const& sNew)
{
    SwRewriter aResult;

    if (1 < occurrences)
    {
        aResult.AddRule(UndoArg1, OUString::number(occurrences));
        aResult.AddRule(UndoArg2, SwResId(STR_OCCURRENCES_OF));

        OUString aTmpStr =
            SwResId(STR_START_QUOTE)
            + ShortenString(sOld, nUndoStringLength, SwResId(STR_LDOTS))
            + SwResId(STR_END_QUOTE);
        aResult.AddRule(UndoArg3, aTmpStr);
    }
    else if (1 == occurrences)
    {
        {
            // #i33488 #
            OUString aTmpStr =
                SwResId(STR_START_QUOTE)
                + ShortenString(sOld, nUndoStringLength, SwResId(STR_LDOTS))
                + SwResId(STR_END_QUOTE);
            aResult.AddRule(UndoArg1, aTmpStr);
        }

        aResult.AddRule(UndoArg2, SwResId(STR_YIELDS));

        {
            // #i33488 #
            OUString aTmpStr =
                SwResId(STR_START_QUOTE)
                + ShortenString(sNew, nUndoStringLength, SwResId(STR_LDOTS))
                + SwResId(STR_END_QUOTE);
            aResult.AddRule(UndoArg3, aTmpStr);
        }
    }

    return aResult;
}

SwRewriter SwUndoReplace::GetRewriter() const
{
    return MakeUndoReplaceRewriter(1, m_pImpl->GetOld(), m_pImpl->GetIns());
}

void SwUndoReplace::SetEnd(SwPaM const& rPam)
{
    m_pImpl->SetEnd(rPam);
}

SwUndoReplace::Impl::Impl(
        SwPaM const& rPam, OUString aIns, bool const bRegExp)
    : m_sIns(std::move( aIns ))
    , m_nOffset( 0 )
    , m_bRegExp(bRegExp)
{

    auto [pStart, pEnd] = rPam.StartEnd(); // SwPosition*

    m_nSttNd = m_nEndNd = pStart->GetNodeIndex();
    m_nSttCnt = pStart->GetContentIndex();
    m_nSelEnd = m_nEndCnt = pEnd->GetContentIndex();

    m_bSplitNext = m_nSttNd != pEnd->GetNodeIndex();

    SwTextNode* pNd = pStart->GetNode().GetTextNode();
    assert(pNd && "Dude, where's my TextNode?");

    m_pHistory.reset( new SwHistory );
    DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(), DelContentType::AllMask | DelContentType::Replace);

    m_nSetPos = m_pHistory->Count();

    SwNodeOffset nNewPos = pStart->GetNodeIndex();
    m_nOffset = m_nSttNd - nNewPos;

    if ( pNd->GetpSwpHints() )
    {
        m_pHistory->CopyAttr( pNd->GetpSwpHints(), nNewPos, 0,
                            pNd->GetText().getLength(), true );
    }

    if ( m_bSplitNext )
    {
        if( pNd->HasSwAttrSet() )
            m_pHistory->CopyFormatAttr( *pNd->GetpSwAttrSet(), nNewPos );
        m_pHistory->AddColl(pNd->GetTextColl(), nNewPos, SwNodeType::Text);

        SwTextNode* pNext = pEnd->GetNode().GetTextNode();
        SwNodeOffset nTmp = pNext->GetIndex();
        m_pHistory->CopyAttr( pNext->GetpSwpHints(), nTmp, 0,
                            pNext->GetText().getLength(), true );
        if( pNext->HasSwAttrSet() )
            m_pHistory->CopyFormatAttr( *pNext->GetpSwAttrSet(), nTmp );
        m_pHistory->AddColl(pNext->GetTextColl(),nTmp, SwNodeType::Text);
        // METADATA: store
        m_pMetadataUndoStart = pNd  ->CreateUndo();
        m_pMetadataUndoEnd   = pNext->CreateUndo();
    }

    if( !m_pHistory->Count() )
    {
        m_pHistory.reset();
    }

    const sal_Int32 nECnt = m_bSplitNext ? pNd->GetText().getLength()
        : pEnd->GetContentIndex();
    m_sOld = pNd->GetText().copy( m_nSttCnt, nECnt - m_nSttCnt );
}

void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc& rDoc = rContext.GetDoc();
    SwCursor & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
    rPam.DeleteMark();

    SwTextNode* pNd = rDoc.GetNodes()[ m_nSttNd - m_nOffset ]->GetTextNode();
    OSL_ENSURE( pNd, "Dude, where's my TextNode?" );

    SwAutoCorrExceptWord* pACEWord = rDoc.GetAutoCorrExceptWord();
    if( pACEWord )
    {
        if ((1 == m_sIns.getLength()) && (1 == m_sOld.getLength()))
        {
            SwPosition aPos( *pNd, m_nSttCnt );
            pACEWord->CheckChar( aPos, m_sOld[ 0 ] );
        }
        rDoc.SetAutoCorrExceptWord( nullptr );
    }

    // don't look at m_sIns for deletion, maybe it was not completely inserted
    {
        rPam.GetPoint()->Assign(*pNd, m_nSttCnt );
        rPam.SetMark();
        rPam.GetPoint()->Assign( m_nSttNd - m_nOffset, m_nSttNd == m_nEndNd ? m_nEndCnt : pNd->Len());

        // replace only in start node, without regex
        bool const ret = rDoc.getIDocumentContentOperations().ReplaceRange(rPam, m_sOld, false);
        assert(ret); (void)ret;
        if (m_nSttNd != m_nEndNd)
        {   // in case of regex inserting paragraph breaks, join nodes...
            assert(rPam.GetMark()->GetContentIndex() == rPam.GetMark()->GetNode().GetTextNode()->Len());
            rPam.GetPoint()->Assign( m_nEndNd - m_nOffset, m_nEndCnt );
            rDoc.getIDocumentContentOperations().DeleteAndJoin(rPam);
        }
        if (*rPam.GetMark() == *rPam.GetPoint())
            rPam.DeleteMark();
        else
            rPam.Normalize(false);
        pNd = rDoc.GetNodes()[ m_nSttNd - m_nOffset ]->GetTextNode();
        OSL_ENSURE( pNd, "Dude, where's my TextNode?" );
    }

    if( m_bSplitNext )
    {
        assert(pNd && m_nSttCnt + m_sOld.getLength() <= pNd->Len());
        SwPosition aPos(*pNd, m_nSttCnt + m_sOld.getLength());
        rDoc.getIDocumentContentOperations().SplitNode( aPos, false );
        pNd->RestoreMetadata(m_pMetadataUndoEnd);
        pNd = rDoc.GetNodes()[ m_nSttNd - m_nOffset ]->GetTextNode();
        // METADATA: restore
        pNd->RestoreMetadata(m_pMetadataUndoStart);
    }

    if( m_pHistory )
    {
        if( pNd->GetpSwpHints() )
            pNd->ClearSwpHintsArr( true );

        m_pHistory->TmpRollback( rDoc, m_nSetPos, false );
        if ( m_nSetPos ) // there were footnotes/FlyFrames
        {
            // are there others than these?
            if( m_nSetPos < m_pHistory->Count() )
            {
                // than save those attributes as well
                SwHistory aHstr;
                aHstr.Move( 0, m_pHistory.get(), m_nSetPos );
                m_pHistory->Rollback( rDoc );
                m_pHistory->Move( 0, &aHstr );
            }
            else
            {
                m_pHistory->Rollback( rDoc );
                m_pHistory.reset();
            }
        }
    }
}

void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc & rDoc = rContext.GetDoc();
    SwCursor & rPam(rContext.GetCursorSupplier().CreateNewShellCursor());
    rPam.DeleteMark();
    rPam.GetPoint()->Assign( m_nSttNd, m_nSttCnt );

    rPam.SetMark();
    if( m_bSplitNext )
        rPam.GetPoint()->Assign( m_nSttNd + 1 );
    rPam.GetPoint()->SetContent( m_nSelEnd );

    if( m_pHistory )
    {
        auto xSave = std::make_unique<SwHistory>();
        std::swap(m_pHistory, xSave);

        DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(), DelContentType::AllMask | DelContentType::Replace);
        m_nSetPos = m_pHistory->Count();

        std::swap(xSave, m_pHistory);
        m_pHistory->Move(0, xSave.get());
    }
    else
    {
        m_pHistory.reset( new SwHistory );
        DelContentIndex(*rPam.GetMark(), *rPam.GetPoint(), DelContentType::AllMask | DelContentType::Replace);
        m_nSetPos = m_pHistory->Count();
        if( !m_nSetPos )
        {
            m_pHistory.reset();
        }
    }

    rDoc.getIDocumentContentOperations().ReplaceRange( rPam, m_sIns, m_bRegExp );
    if (*rPam.GetMark() == *rPam.GetPoint())
        rPam.DeleteMark();
    else
        rPam.Normalize(false);
}

void SwUndoReplace::Impl::SetEnd(SwPaM const& rPam)
{
    const SwPosition* pEnd = rPam.End();
    m_nEndNd = m_nOffset + pEnd->GetNodeIndex();
    m_nEndCnt = pEnd->GetContentIndex();
}

SwUndoReRead::SwUndoReRead( const SwPaM& rPam, const SwGrfNode& rGrfNd )
    : SwUndo( SwUndoId::REREAD, rPam.GetDoc() ), mnPosition( rPam.GetPoint()->GetNodeIndex() )
{
    SaveGraphicData( rGrfNd );
}

SwUndoReRead::~SwUndoReRead()
{
}

void SwUndoReRead::SetAndSave(::sw::UndoRedoContext & rContext)
{
    SwDoc & rDoc = rContext.GetDoc();
    SwGrfNode* pGrfNd = rDoc.GetNodes()[ mnPosition ]->GetGrfNode();

    if( !pGrfNd )
        return ;

    // cache the old values
    std::optional<Graphic> oOldGrf(moGraphic);
    std::optional<OUString> aOldNm = maNm;
    MirrorGraph nOldMirr = mnMirror;
    // since all of them are cleared/modified by SaveGraphicData:
    SaveGraphicData( *pGrfNd );

    if( aOldNm )
    {
        pGrfNd->ReRead( *aOldNm, maFltr ? *maFltr : OUString() );
    }
    else
    {
        pGrfNd->ReRead( OUString(), OUString(), oOldGrf ? &*oOldGrf : nullptr );
    }

    if( MirrorGraph::Dont != nOldMirr )
        pGrfNd->SetAttr( SwMirrorGrf() );

    rContext.SetSelections(pGrfNd->GetFlyFormat(), nullptr);
}

void SwUndoReRead::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SetAndSave(rContext);
}

void SwUndoReRead::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SetAndSave(rContext);
}

void SwUndoReRead::SaveGraphicData( const SwGrfNode& rGrfNd )
{
    if( rGrfNd.IsGrfLink() )
    {
        maNm = OUString();
        maFltr = OUString();
        rGrfNd.GetFileFilterNms(&*maNm, &*maFltr);
        moGraphic.reset();
    }
    else
    {
        moGraphic.emplace( rGrfNd.GetGrf(true) );
        maNm.reset();
        maFltr.reset();
    }
    mnMirror = rGrfNd.GetSwAttrSet().GetMirrorGrf().GetValue();
}

SwUndoInsertLabel::SwUndoInsertLabel( const SwLabelType eTyp,
                                      OUString aText,
                                      OUString aSeparator,
                                      OUString aNumberSeparator,
                                      const bool bBef,
                                      const sal_uInt16 nInitId,
                                      UIName aCharacterStyle,
                                      const bool bCpyBorder,
                                      const SwDoc& rDoc )
    : SwUndo( SwUndoId::INSERTLABEL, rDoc ),
      m_sText(std::move( aText )),
      m_sSeparator(std::move( aSeparator )),
      m_sNumberSeparator(std::move( aNumberSeparator )),//#i61007# order of captions
      m_sCharacterStyle(std::move( aCharacterStyle )),
      m_nFieldId( nInitId ),
      m_eType( eTyp ),
      m_nLayerId( 0 ),
      m_bBefore( bBef ),
      m_bCopyBorder( bCpyBorder )
{
    m_bUndoKeep = false;
    OBJECT.pUndoFly = nullptr;
    OBJECT.pUndoAttr = nullptr;
}

SwUndoInsertLabel::~SwUndoInsertLabel()
{
    if( SwLabelType::Object == m_eType || SwLabelType::Draw == m_eType )
    {
        delete OBJECT.pUndoFly;
        delete OBJECT.pUndoAttr;
    }
    else
        delete NODE.pUndoInsNd;
}

void SwUndoInsertLabel::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc & rDoc = rContext.GetDoc();

    if( SwLabelType::Object == m_eType || SwLabelType::Draw == m_eType )
    {
        OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer not initialized" );
        SwFrameFormat* pFormat;
        SdrObject *pSdrObj = nullptr;
        if( OBJECT.pUndoAttr &&
            nullptr != (pFormat = static_cast<SwFrameFormat*>(OBJECT.pUndoAttr->GetFormat( rDoc ))) &&
            ( SwLabelType::Draw != m_eType ||
              nullptr != (pSdrObj = pFormat->FindSdrObject()) ) )
        {
            OBJECT.pUndoAttr->UndoImpl(rContext);
            OBJECT.pUndoFly->UndoImpl(rContext);
            if( SwLabelType::Draw == m_eType )
            {
                pSdrObj->SetLayer( m_nLayerId );
            }
        }
    }
    else if( NODE.nNode )
    {
        if ( m_eType == SwLabelType::Table && m_bUndoKeep )
        {
            SwTableNode *pNd = rDoc.GetNodes()[
                        rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
            if ( pNd )
                pNd->GetTable().GetFrameFormat()->ResetFormatAttr( RES_KEEP );
        }
        SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
        aPam.GetPoint()->Assign( NODE.nNode );
        aPam.SetMark();
        aPam.GetPoint()->Assign( NODE.nNode + 1 );
        NODE.pUndoInsNd = new SwUndoDelete(aPam, SwDeleteFlags::Defaulttrue);
    }
}

void SwUndoInsertLabel::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc & rDoc = rContext.GetDoc();

    if( SwLabelType::Object == m_eType || SwLabelType::Draw == m_eType )
    {
        OSL_ENSURE( OBJECT.pUndoAttr && OBJECT.pUndoFly, "Pointer not initialized" );
        SwFrameFormat* pFormat;
        SdrObject *pSdrObj = nullptr;
        if( OBJECT.pUndoAttr &&
            nullptr != (pFormat = static_cast<SwFrameFormat*>(OBJECT.pUndoAttr->GetFormat( rDoc ))) &&
            ( SwLabelType::Draw != m_eType ||
              nullptr != (pSdrObj = pFormat->FindSdrObject()) ) )
        {
            OBJECT.pUndoFly->RedoImpl(rContext);
            OBJECT.pUndoAttr->RedoImpl(rContext);
            if( SwLabelType::Draw == m_eType )
            {
                pSdrObj->SetLayer( m_nLayerId );
                if( pSdrObj->GetLayer() == rDoc.getIDocumentDrawModelAccess().GetHellId() )
                    pSdrObj->SetLayer( rDoc.getIDocumentDrawModelAccess().GetHeavenId() );
                // OD 02.07.2003 #108784#
                else if( pSdrObj->GetLayer() == rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId() )
                    pSdrObj->SetLayer( rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId() );
            }
        }
    }
    else if( NODE.pUndoInsNd )
    {
        if ( m_eType == SwLabelType::Table && m_bUndoKeep )
        {
            SwTableNode *pNd = rDoc.GetNodes()[
                        rDoc.GetNodes()[NODE.nNode-1]->StartOfSectionIndex()]->GetTableNode();
            if ( pNd )
                pNd->GetTable().GetFrameFormat()->SetFormatAttr( SvxFormatKeepItem(true, RES_KEEP) );
        }
        NODE.pUndoInsNd->UndoImpl(rContext);
        delete NODE.pUndoInsNd;
        NODE.pUndoInsNd = nullptr;
    }
}

void SwUndoInsertLabel::RepeatImpl(::sw::RepeatContext & rContext)
{
    SwDoc & rDoc = rContext.GetDoc();
    const SwPosition& rPos = *rContext.GetRepeatPaM().GetPoint();

    SwNodeOffset nIdx(0);

    SwContentNode* pCNd = rPos.GetNode().GetContentNode();
    if( pCNd )
        switch( m_eType )
        {
        case SwLabelType::Table:
            {
                const SwTableNode* pTNd = pCNd->FindTableNode();
                if( pTNd )
                    nIdx = pTNd->GetIndex();
            }
            break;

        case SwLabelType::Fly:
        case SwLabelType::Object:
            {
                SwFlyFrame* pFly;
                SwContentFrame *pCnt = pCNd->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() );
                if( pCnt && nullptr != ( pFly = pCnt->FindFlyFrame() ) )
                    nIdx = pFly->GetFormat()->GetContent().GetContentIdx()->GetIndex();
            }
            break;
        case SwLabelType::Draw:
            break;
        }

    if( nIdx )
    {
        rDoc.InsertLabel( m_eType, m_sText, m_sSeparator, m_sNumberSeparator, m_bBefore,
            m_nFieldId, nIdx, m_sCharacterStyle, m_bCopyBorder );
    }
}

SwRewriter SwUndoInsertLabel::GetRewriter() const
{
    return CreateRewriter(m_sText);
}

SwRewriter SwUndoInsertLabel::CreateRewriter(const OUString &rStr)
{
    SwRewriter aRewriter;

    OUString aTmpStr;

    if (!rStr.isEmpty())
    {
        aTmpStr =
            SwResId(STR_START_QUOTE)
            + ShortenString(rStr, nUndoStringLength, SwResId(STR_LDOTS))
            + SwResId(STR_END_QUOTE);
    }

    aRewriter.AddRule(UndoArg1, aTmpStr);

    return aRewriter;
}

void SwUndoInsertLabel::SetFlys( SwFrameFormat& rOldFly, SfxItemSet const & rChgSet,
                                SwFrameFormat& rNewFly )
{
    if( SwLabelType::Object == m_eType || SwLabelType::Draw == m_eType )
    {
        SwUndoFormatAttrHelper aTmp( rOldFly, false );
        rOldFly.SetFormatAttr( rChgSet );
        if ( aTmp.GetUndo() )
        {
            OBJECT.pUndoAttr = aTmp.ReleaseUndo().release();
        }
        OBJECT.pUndoFly = new SwUndoInsLayFormat( &rNewFly, SwNodeOffset(0), 0 );
    }
}

void SwUndoInsertLabel::SetDrawObj( SdrLayerID nLId )
{
    if( SwLabelType::Draw == m_eType )
    {
        m_nLayerId = nLId;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=95 H=98 G=96

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