/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <memory>
#include "impedit.hxx"
#include "editundo.hxx"
#include <editeng/editview.hxx>
#include <editeng/editeng.hxx>
#include <utility>
#include <osl/diagnose.h>
static void lcl_DoSetSelection( EditView
const * pView, sal_uInt16 nPara )
{
EPaM aEPaM( nPara, 0 );
EditPaM aPaM = pView->getImpEditEngine().CreateEditPaM(aEPaM);
aPaM.SetIndex( aPaM.GetNode()->Len() );
EditSelection aSel( aPaM, aPaM );
pView->getImpl().SetEditSelection( aSel );
}
EditUndoManager::EditUndoManager(sal_uInt16 nMaxUndoActionCount )
: SfxUndoManager(nMaxUndoActionCount),
mpEditEngine(nullptr)
{
}
void EditUndoManager::SetEditEngine(EditEngine* pNew)
{
mpEditEngine = pNew;
}
bool EditUndoManager::Undo()
{
if ( !mpEditEngine || GetUndoActionCount() == 0 )
return false ;
DBG_ASSERT( mpEditEngine->GetActiveView(),
"Active View?" );
if ( !mpEditEngine->GetActiveView() )
{
if (!mpEditEngine->GetEditViews().empty())
mpEditEngine->SetActiveView(mpEditEngine->GetEditViews()[0]);
else
{
OSL_FAIL(
"Undo in engine is not possible without a View! " );
return false ;
}
}
mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR();
// Remove the old selection
mpEditEngine->SetUndoMode(
true );
bool bDone = SfxUndoManager::Undo();
mpEditEngine->SetUndoMode(
false );
EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() );
DBG_ASSERT( !aNewSel.IsInvalid(),
"Invalid selection after Undo () " );
DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ),
"Broken selection after Undo () " );
aNewSel.Min() = aNewSel.Max();
mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel );
if (mpEditEngine->IsUpdateLayout())
mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView(),
true );
return bDone;
}
bool EditUndoManager::Redo()
{
if ( !mpEditEngine || GetRedoActionCount() == 0 )
return false ;
DBG_ASSERT( mpEditEngine->GetActiveView(),
"Active View?" );
if ( !mpEditEngine->GetActiveView() )
{
if (!mpEditEngine->GetEditViews().empty())
mpEditEngine->SetActiveView(mpEditEngine->GetEditViews()[0]);
else
{
OSL_FAIL(
"Redo in Engine without View not possible!" );
return false ;
}
}
mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR();
// Remove the old selection
mpEditEngine->SetUndoMode(
true );
bool bDone = SfxUndoManager::Redo();
mpEditEngine->SetUndoMode(
false );
EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() );
DBG_ASSERT( !aNewSel.IsInvalid(),
"Invalid selection after Undo () " );
DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ),
"Broken selection after Undo () " );
aNewSel.Min() = aNewSel.Max();
mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel );
if (mpEditEngine->IsUpdateLayout())
mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView() );
return bDone;
}
EditUndo::EditUndo(sal_uInt16 nI, EditEngine* pEE) :
nId(nI), mnViewShellId(-1), mpEditEngine(pEE)
{
const EditView* pEditView = mpEditEngine ? mpEditEngine->GetActiveView() : nullptr;
const OutlinerViewShell* pViewShell = pEditView ? pEditView->getImpl().GetViewShell() : n
ullptr;
if (pViewShell)
mnViewShellId = pViewShell->GetViewShellId();
}
EditUndo::~EditUndo()
{
}
sal_uInt16 EditUndo::GetId() const
{
return nId;
}
bool EditUndo::CanRepeat(SfxRepeatTarget&) const
{
return false ;
}
OUString EditUndo::GetComment() const
{
OUString aComment;
if (mpEditEngine)
aComment = mpEditEngine->GetUndoComment( GetId() );
return aComment;
}
ViewShellId EditUndo::GetViewShellId() const
{
return mnViewShellId;
}
EditUndoDelContent::EditUndoDelContent(EditEngine* pEE, std::unique_ptr<ContentNode> pNode, sal_Int32 nPortion)
: EditUndo(EDITUNDO_DELCONTENT, pEE)
, nNode(nPortion)
, mpContentNode(std::move(pNode))
{}
EditUndoDelContent::~EditUndoDelContent()
{
}
void EditUndoDelContent::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
ContentNode* pNode = mpContentNode.get();
GetEditEngine()->InsertContent(std::move(mpContentNode), nNode);
EditSelection aSel(EditPaM(pNode, 0), EditPaM(pNode, pNode->Len()));
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel);
}
void EditUndoDelContent::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditEngine* pEE = GetEditEngine();
// pNode is no longer correct, if the paragraphs where merged
// in between Undos
ContentNode* pNode = pEE->GetEditDoc().GetObject(nNode);
DBG_ASSERT(pNode, "EditUndoDelContent::Redo(): Node?!" );
pEE->RemoveParaPortion(nNode);
// Do not delete node, depends on the undo!
mpContentNode = pEE->GetEditDoc().Release(nNode);
assert(mpContentNode.get() == pNode);
if (pEE->IsCallParaInsertedOrDeleted())
pEE->ParagraphDeleted(nNode);
DeletedNodeInfo* pDeletedNodeInfo = new DeletedNodeInfo(pNode, nNode);
pEE->AppendDeletedNodeInfo(pDeletedNodeInfo);
pEE->UpdateSelections();
ContentNode* pCheckNode = (nNode < pEE->GetEditDoc().Count())
? pEE->GetEditDoc().GetObject(nNode)
: pEE->GetEditDoc().GetObject(nNode - 1);
assert(pCheckNode);
DBG_ASSERT(pCheckNode != mpContentNode.get(), "?! RemoveContent !? " );
EditPaM aPaM(pCheckNode, pCheckNode->Len());
pEE->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) );
}
EditUndoConnectParas::EditUndoConnectParas(
EditEngine* pEE, sal_Int32 nN, sal_uInt16 nSP,
SfxItemSet _aLeftParaAttribs, SfxItemSet _aRightParaAttribs,
const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, bool bBkwrd) :
EditUndo(EDITUNDO_CONNECTPARAS, pEE),
nNode(nN),
nSepPos(nSP),
aLeftParaAttribs(std::move(_aLeftParaAttribs)),
aRightParaAttribs(std::move(_aRightParaAttribs)),
eLeftStyleFamily(SfxStyleFamily::All),
eRightStyleFamily(SfxStyleFamily::All),
bBackward(bBkwrd)
{
if ( pLeftStyle )
{
aLeftStyleName = pLeftStyle->GetName();
eLeftStyleFamily = pLeftStyle->GetFamily();
}
if ( pRightStyle )
{
aRightStyleName = pRightStyle->GetName();
eRightStyleFamily = pRightStyle->GetFamily();
}
}
EditUndoConnectParas::~EditUndoConnectParas()
{
}
void EditUndoConnectParas::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
// For SplitContent ParagraphInserted can not be called yet because the
// Outliner relies on the attributes to initialize the depth
bool bCall = GetEditEngine()->IsCallParaInsertedOrDeleted();
GetEditEngine()->SetCallParaInsertedOrDeleted(false );
EditPaM aPaM = GetEditEngine()->SplitContent(nNode, nSepPos);
GetEditEngine()->SetCallParaInsertedOrDeleted( bCall );
if (GetEditEngine()->IsCallParaInsertedOrDeleted())
{
GetEditEngine()->ParagraphInserted( nNode+1 );
GetEditEngine()->SetParaAttribs( nNode+1, aRightParaAttribs );
}
// Calling SetParaAttribs is effective only after ParagraphInserted
GetEditEngine()->SetParaAttribs( nNode, aLeftParaAttribs );
if (GetEditEngine()->GetStyleSheetPool())
{
if ( !aLeftStyleName.isEmpty() )
GetEditEngine()->SetStyleSheet( nNode, static_cast <SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aLeftStyleName, eLeftStyleFamily )) );
if ( !aRightStyleName.isEmpty() )
GetEditEngine()->SetStyleSheet( nNode+1, static_cast <SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aRightStyleName, eRightStyleFamily )) );
}
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) );
}
void EditUndoConnectParas::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: Np Active View!" );
EditPaM aPaM = GetEditEngine()->ConnectContents( nNode, bBackward );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) );
}
EditUndoSplitPara::EditUndoSplitPara(
EditEngine* pEE, sal_Int32 nN, sal_uInt16 nSP) :
EditUndo(EDITUNDO_SPLITPARA, pEE),
nNode(nN), nSepPos(nSP) {}
EditUndoSplitPara::~EditUndoSplitPara() {}
void EditUndoSplitPara::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->ConnectContents(nNode, false );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) );
}
void EditUndoSplitPara::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->SplitContent(nNode, nSepPos);
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) );
}
EditUndoInsertChars::EditUndoInsertChars(
EditEngine* pEE, const EPaM& rEPaM, OUString aStr) :
EditUndo(EDITUNDO_INSERTCHARS, pEE),
aEPaM(rEPaM),
aText(std::move(aStr)) {}
void EditUndoInsertChars::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
EditSelection aSel( aPaM, aPaM );
aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() );
EditPaM aNewPaM( GetEditEngine()->DeleteSelection(aSel) );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aNewPaM, aNewPaM ) );
}
void EditUndoInsertChars::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
GetEditEngine()->InsertText(EditSelection(aPaM, aPaM), aText);
EditPaM aNewPaM( aPaM );
aNewPaM.SetIndex( aNewPaM.GetIndex() + aText.getLength() );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aNewPaM ) );
}
bool EditUndoInsertChars::Merge( SfxUndoAction* pNextAction )
{
EditUndoInsertChars* pNext = dynamic_cast <EditUndoInsertChars*>(pNextAction);
if (!pNext)
return false ;
if ( aEPaM.nPara != pNext->aEPaM.nPara )
return false ;
if ( ( aEPaM.nIndex + aText.getLength() ) == pNext->aEPaM.nIndex )
{
aText += pNext->aText;
return true ;
}
return false ;
}
EditUndoRemoveChars::EditUndoRemoveChars(
EditEngine* pEE, const EPaM& rEPaM, OUString aStr) :
EditUndo(EDITUNDO_REMOVECHARS, pEE),
aEPaM(rEPaM), aText(std::move(aStr)) {}
void EditUndoRemoveChars::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
EditSelection aSel( aPaM, aPaM );
GetEditEngine()->InsertText(aSel, aText);
aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel);
}
void EditUndoRemoveChars::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
EditSelection aSel( aPaM, aPaM );
aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() );
EditPaM aNewPaM = GetEditEngine()->DeleteSelection(aSel);
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aNewPaM);
}
EditUndoInsertFeature::EditUndoInsertFeature(
EditEngine* pEE, const EPaM& rEPaM, const SfxPoolItem& rFeature) :
EditUndo(EDITUNDO_INSERTFEATURE, pEE),
aEPaM(rEPaM),
pFeature(rFeature.Clone())
{
DBG_ASSERT( pFeature, "Feature could not be duplicated: EditUndoInsertFeature" );
}
EditUndoInsertFeature::~EditUndoInsertFeature()
{
}
void EditUndoInsertFeature::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
EditSelection aSel( aPaM, aPaM );
// Attributes are then corrected implicitly by the document ...
aSel.Max().SetIndex( aSel.Max().GetIndex()+1 );
GetEditEngine()->DeleteSelection(aSel);
aSel.Max().SetIndex( aSel.Max().GetIndex()-1 ); // For Selection
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel);
}
void EditUndoInsertFeature::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditPaM aPaM = GetEditEngine()->CreateEditPaM(aEPaM);
EditSelection aSel( aPaM, aPaM );
GetEditEngine()->InsertFeature(aSel, *pFeature);
if ( pFeature->Which() == EE_FEATURE_FIELD )
GetEditEngine()->UpdateFieldsOnly();
aSel.Max().SetIndex( aSel.Max().GetIndex()+1 );
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel);
}
EditUndoMoveParagraphs::EditUndoMoveParagraphs(
EditEngine* pEE, const Range& rParas, sal_Int32 n) :
EditUndo(EDITUNDO_MOVEPARAGRAPHS, pEE), nParagraphs(rParas), nDest(n) {}
EditUndoMoveParagraphs::~EditUndoMoveParagraphs() {}
void EditUndoMoveParagraphs::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
Range aTmpRange( nParagraphs );
tools::Long nTmpDest = aTmpRange.Min();
tools::Long nDiff = nDest - aTmpRange.Min();
aTmpRange.Min() += nDiff;
aTmpRange.Max() += nDiff;
if ( nParagraphs.Min() < static_cast <tools::Long >(nDest) )
{
tools::Long nLen = aTmpRange.Len();
aTmpRange.Min() -= nLen;
aTmpRange.Max() -= nLen;
}
else
nTmpDest += aTmpRange.Len();
EditSelection aNewSel = GetEditEngine()->MoveParagraphs(aTmpRange, nTmpDest);
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel );
}
void EditUndoMoveParagraphs::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditSelection aNewSel = GetEditEngine()->MoveParagraphs(nParagraphs, nDest);
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel );
}
EditUndoSetStyleSheet::EditUndoSetStyleSheet(
EditEngine* pEE, sal_Int32 nP, OUString _aPrevName, SfxStyleFamily ePrevFam,
OUString _aNewName, SfxStyleFamily eNewFam, SfxItemSet _aPrevParaAttribs) :
EditUndo(EDITUNDO_STYLESHEET, pEE),
nPara(nP),
aPrevName(std::move(_aPrevName)),
aNewName(std::move(_aNewName)),
ePrevFamily(ePrevFam),
eNewFamily(eNewFam),
aPrevParaAttribs(std::move(_aPrevParaAttribs))
{
}
EditUndoSetStyleSheet::~EditUndoSetStyleSheet()
{
}
void EditUndoSetStyleSheet::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
GetEditEngine()->SetStyleSheet( nPara, static_cast <SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aPrevName, ePrevFamily )) );
GetEditEngine()->SetParaAttribsOnly( nPara, aPrevParaAttribs );
lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara );
}
void EditUndoSetStyleSheet::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
GetEditEngine()->SetStyleSheet( nPara, static_cast <SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aNewName, eNewFamily )) );
lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara );
}
EditUndoSetParaAttribs::EditUndoSetParaAttribs(
EditEngine* pEE, sal_Int32 nP, SfxItemSet _aPrevItems, SfxItemSet _aNewItems) :
EditUndo(EDITUNDO_PARAATTRIBS, pEE),
nPara(nP),
aPrevItems(std::move(_aPrevItems)),
aNewItems(std::move(_aNewItems)) {}
EditUndoSetParaAttribs::~EditUndoSetParaAttribs() {}
void EditUndoSetParaAttribs::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
GetEditEngine()->SetParaAttribsOnly( nPara, aPrevItems );
lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara );
}
void EditUndoSetParaAttribs::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
GetEditEngine()->SetParaAttribsOnly( nPara, aNewItems );
lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara );
}
EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, SfxItemSet aNewItems) :
EditUndo(EDITUNDO_ATTRIBS, pEE),
aESel(rESel),
aNewAttribs(std::move(aNewItems)),
nSpecial(SetAttribsMode::NONE),
m_bSetSelection(true ),
// When EditUndoSetAttribs actually is a RemoveAttribs this could be
// recognize by the empty itemset, but then it would have to be caught in
// its own place, which possible a setAttribs does with an empty itemset.
bSetIsRemove(false ),
bRemoveParaAttribs(false ),
nRemoveWhich(0)
{
}
EditUndoSetAttribs::~EditUndoSetAttribs()
{
}
void EditUndoSetAttribs::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditEngine* pEE = GetEditEngine();
bool bFields = false ;
for ( sal_Int32 nPara = aESel.start.nPara; nPara <= aESel.end.nPara; nPara++ )
{
const ContentAttribsInfo& rInf = *aPrevAttribs[nPara-aESel.start.nPara];
// first the paragraph attributes ...
pEE->SetParaAttribsOnly(nPara, rInf.GetPrevParaAttribs());
// Then the character attributes ...
// Remove all attributes including features, are later re-established.
pEE->RemoveCharAttribs(nPara, 0, true );
DBG_ASSERT( pEE->GetEditDoc().GetObject( nPara ), "Undo (SetAttribs): pNode = NULL!" );
ContentNode* pNode = pEE->GetEditDoc().GetObject( nPara );
for (const auto & nAttr : rInf.GetPrevCharAttribs())
{
const EditCharAttrib& rX = *nAttr;
// is automatically "poolsized"
pEE->GetEditDoc().InsertAttrib(pNode, rX.GetStart(), rX.GetEnd(), *rX.GetItem());
if (rX.Which() == EE_FEATURE_FIELD)
bFields = true ;
}
}
if ( bFields )
pEE->UpdateFieldsOnly();
if (m_bSetSelection)
{
ImpSetSelection();
}
}
void EditUndoSetAttribs::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditEngine* pEE = GetEditEngine();
EditSelection aSel = pEE->CreateSelection(aESel);
if ( !bSetIsRemove )
pEE->SetAttribs( aSel, aNewAttribs, nSpecial );
else
pEE->RemoveCharAttribs( aSel, bRemoveParaAttribs, nRemoveWhich );
if (m_bSetSelection)
{
ImpSetSelection();
}
}
void EditUndoSetAttribs::AppendContentInfo(ContentAttribsInfo* pNew)
{
aPrevAttribs.push_back(std::unique_ptr<ContentAttribsInfo>(pNew));
}
void EditUndoSetAttribs::ImpSetSelection()
{
EditEngine* pEE = GetEditEngine();
EditSelection aSel = pEE->CreateSelection(aESel);
pEE->GetActiveView()->getImpl().SetEditSelection(aSel);
}
EditUndoTransliteration::EditUndoTransliteration(EditEngine* pEE, const ESelection& rESel, TransliterationFlags nM) :
EditUndo(EDITUNDO_TRANSLITERATE, pEE),
aOldESel(rESel), nMode(nM) {}
EditUndoTransliteration::~EditUndoTransliteration()
{
}
void EditUndoTransliteration::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditEngine* pEE = GetEditEngine();
EditSelection aSel = pEE->CreateSelection(aNewESel);
// Insert text, but don't expand Attribs at the current position:
aSel = pEE->DeleteSelected( aSel );
EditSelection aDelSel( aSel );
aSel = pEE->InsertParaBreak( aSel );
aDelSel.Max() = aSel.Min();
aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs();
EditSelection aNewSel;
if ( pTxtObj )
{
aNewSel = pEE->InsertText( *pTxtObj, aSel );
}
else
{
aNewSel = pEE->InsertText( aSel, aText );
}
if ( aNewSel.Min().GetNode() == aDelSel.Max().GetNode() )
{
aNewSel.Min().SetNode( aDelSel.Min().GetNode() );
aNewSel.Min().SetIndex( aNewSel.Min().GetIndex() + aDelSel.Min().GetIndex() );
}
if ( aNewSel.Max().GetNode() == aDelSel.Max().GetNode() )
{
aNewSel.Max().SetNode( aDelSel.Min().GetNode() );
aNewSel.Max().SetIndex( aNewSel.Max().GetIndex() + aDelSel.Min().GetIndex() );
}
pEE->DeleteSelected( aDelSel );
pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel );
}
void EditUndoTransliteration::Redo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
EditEngine* pEE = GetEditEngine();
EditSelection aSel = pEE->CreateSelection(aOldESel);
EditSelection aNewSel = pEE->TransliterateText( aSel, nMode );
pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel );
}
EditUndoMarkSelection::EditUndoMarkSelection(EditEngine* pEE, const ESelection& rSel) :
EditUndo(EDITUNDO_MARKSELECTION, pEE), aSelection(rSel) {}
EditUndoMarkSelection::~EditUndoMarkSelection() {}
void EditUndoMarkSelection::Undo()
{
DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" );
if ( GetEditEngine()->GetActiveView() )
{
if ( GetEditEngine()->IsFormatted() )
GetEditEngine()->GetActiveView()->SetSelection( aSelection );
else
GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(GetEditEngine()->CreateSelection(aSelection));
}
}
void EditUndoMarkSelection::Redo()
{
// For redo unimportant, because at the beginning of the undo parentheses
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 C=97 H=98 G=97
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland