2000-09-18 23:08:29 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2010-02-12 15:01:35 +01:00
|
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* This file is part of OpenOffice.org.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
* only, as published by the Free Software Foundation.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Lesser General Public License version 3 for more details
|
|
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2008-04-10 15:03:27 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
|
|
* <http://www.openoffice.org/license.html>
|
|
|
|
* for a copy of the LGPLv3 License.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
2006-09-16 20:49:45 +00:00
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
#include "precompiled_sw.hxx"
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
#include <UndoManager.hxx>
|
|
|
|
|
2009-06-04 16:21:29 +00:00
|
|
|
#include <svx/svdmodel.hxx>
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
#include <vcl/wrkwin.hxx>
|
|
|
|
#include <doc.hxx>
|
|
|
|
#include <pam.hxx>
|
|
|
|
#include <ndtxt.hxx>
|
|
|
|
#include <swundo.hxx> // fuer die UndoIds
|
|
|
|
#include <undobj.hxx>
|
|
|
|
#include <rolbck.hxx>
|
|
|
|
#include <docary.hxx>
|
2004-05-18 13:06:14 +00:00
|
|
|
#include <undo.hrc>
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
/// max number of Undo actions
|
|
|
|
static USHORT g_nUndoActions = UNDO_ACTION_COUNT;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2002-06-03 11:35:54 +00:00
|
|
|
// the undo array should never grow beyond this limit:
|
|
|
|
#define UNDO_ACTION_LIMIT (USHRT_MAX - 1000)
|
|
|
|
|
|
|
|
|
2001-04-09 06:23:08 +00:00
|
|
|
SV_IMPL_PTRARR( SwUndoIds, SwUndoIdAndNamePtr )
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
//#define _SHOW_UNDORANGE
|
|
|
|
#ifdef _SHOW_UNDORANGE
|
|
|
|
|
|
|
|
|
|
|
|
class UndoArrStatus : public WorkWindow
|
|
|
|
{
|
|
|
|
USHORT nUndo, nUndoNds;
|
|
|
|
virtual void Paint( const Rectangle& );
|
|
|
|
public:
|
|
|
|
UndoArrStatus();
|
|
|
|
void Set( USHORT, USHORT );
|
|
|
|
};
|
|
|
|
static UndoArrStatus* pUndoMsgWin = 0;
|
|
|
|
|
|
|
|
|
|
|
|
UndoArrStatus::UndoArrStatus()
|
|
|
|
: WorkWindow( APP_GETAPPWINDOW() ), nUndo(0), nUndoNds(0)
|
|
|
|
{
|
|
|
|
SetSizePixel( Size( 200, 100 ));
|
|
|
|
SetFont( Font( "Courier", Size( 0, 10 )) );
|
|
|
|
Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UndoArrStatus::Set( USHORT n1, USHORT n2 )
|
|
|
|
{
|
|
|
|
nUndo = n1; nUndoNds = n2;
|
|
|
|
Invalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UndoArrStatus::Paint( const Rectangle& )
|
|
|
|
{
|
|
|
|
String s;
|
|
|
|
DrawRect( Rectangle( Point(0,0), GetOutputSize() ));
|
|
|
|
( s = "Undos: " ) += nUndo;
|
|
|
|
DrawText( Point( 0, 0 ), s );
|
|
|
|
( s = "UndoNodes: " ) += nUndoNds;
|
|
|
|
DrawText( Point( 0, 15 ), s );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
// SwDoc methods /////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
const SwNodes* SwDoc::GetUndoNds() const
|
|
|
|
{
|
|
|
|
return &aUndoNodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SwDoc::IsNoDrawUndoObj() const
|
|
|
|
{
|
|
|
|
return GetUndoManager().IsNoDrawUndoObj();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwDoc::SetNoDrawUndoObj( bool const bFlag )
|
|
|
|
{
|
|
|
|
GetUndoManager().SetNoDrawUndoObj(bFlag);
|
|
|
|
}
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
sal_uInt16 SwDoc::GetUndoActionCount()
|
|
|
|
{
|
2010-11-25 14:31:07 +01:00
|
|
|
return ::sw::UndoManager::GetUndoActionCount();
|
2006-08-14 15:48:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SwDoc::SetUndoActionCount( sal_uInt16 nNew )
|
|
|
|
{
|
2010-11-25 14:31:07 +01:00
|
|
|
::sw::UndoManager::SetUndoActionCount(nNew);
|
2006-08-14 15:48:33 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
sal_Bool SwDoc::RestoreInvisibleContent()
|
|
|
|
{
|
|
|
|
return GetUndoManager().RestoreInvisibleContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
// UndoManager ///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
namespace sw {
|
|
|
|
|
|
|
|
sal_uInt16 UndoManager::GetUndoActionCount()
|
|
|
|
{
|
|
|
|
return g_nUndoActions;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndoManager::SetUndoActionCount( sal_uInt16 nNew )
|
|
|
|
{
|
|
|
|
g_nUndoActions = nNew;
|
|
|
|
}
|
|
|
|
|
|
|
|
UndoManager::UndoManager(SwDoc & rDoc)
|
|
|
|
: m_rDoc(rDoc)
|
|
|
|
, pUndos( new SwUndos( 0, 20 ) )
|
|
|
|
, nUndoPos(0)
|
|
|
|
, nUndoSavePos(0)
|
|
|
|
, nUndoCnt(0)
|
|
|
|
, nUndoSttEnd(0)
|
|
|
|
, mbUndo(false)
|
|
|
|
, mbGroupUndo(true)
|
|
|
|
, mbNoDrawUndoObj(false)
|
2010-11-25 14:31:10 +01:00
|
|
|
, m_bLockUndoNoModifiedPosition(false)
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const SwNodes* UndoManager::GetUndoNds() const
|
|
|
|
{
|
|
|
|
return m_rDoc.GetUndoNds();
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
void UndoManager::DoUndo(bool const bDoUndo)
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
2010-11-25 14:31:10 +01:00
|
|
|
mbUndo = bDoUndo;
|
2010-11-25 14:31:07 +01:00
|
|
|
|
|
|
|
SdrModel *const pSdrModel = m_rDoc.GetDrawModel();
|
|
|
|
if( pSdrModel )
|
2010-11-25 14:31:10 +01:00
|
|
|
{
|
|
|
|
pSdrModel->EnableUndo(bDoUndo);
|
|
|
|
}
|
2010-11-25 14:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool UndoManager::DoesUndo() const
|
|
|
|
{
|
|
|
|
return mbUndo;
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
void UndoManager::DoGroupUndo(bool const bDoUndo)
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
2010-11-25 14:31:10 +01:00
|
|
|
mbGroupUndo = bDoUndo;
|
2010-11-25 14:31:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool UndoManager::DoesGroupUndo() const
|
|
|
|
{
|
|
|
|
return mbGroupUndo;
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
|
|
|
|
bool UndoManager::IsUndoNoResetModified() const
|
|
|
|
{
|
|
|
|
return USHRT_MAX == nUndoSavePos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndoManager::SetUndoNoResetModified()
|
|
|
|
{
|
|
|
|
nUndoSavePos = USHRT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndoManager::SetUndoNoModifiedPosition()
|
|
|
|
{
|
|
|
|
if (!m_bLockUndoNoModifiedPosition)
|
|
|
|
{
|
|
|
|
nUndoSavePos = (pUndos->Count())
|
|
|
|
? nUndoPos
|
|
|
|
: USHRT_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndoManager::LockUndoNoModifiedPosition()
|
|
|
|
{
|
|
|
|
m_bLockUndoNoModifiedPosition = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UndoManager::UnLockUndoNoModifiedPosition()
|
|
|
|
{
|
|
|
|
m_bLockUndoNoModifiedPosition = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
SwUndo* UndoManager::GetLastUndo()
|
|
|
|
{
|
|
|
|
return (0 == nUndoPos)
|
|
|
|
? 0
|
|
|
|
: (*pUndos)[nUndoPos-1];
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
void UndoManager::AppendUndo(SwUndo *const pUndo)
|
2006-08-14 15:48:33 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
if( nsRedlineMode_t::REDLINE_NONE == pUndo->GetRedlineMode() )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
pUndo->SetRedlineMode( m_rDoc.GetRedlineMode() );
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2002-06-03 11:35:54 +00:00
|
|
|
// Unfortunately, the silly SvPtrArr can only store a little less than
|
|
|
|
// USHRT_MAX elements. Of course it doesn't see any necessity for asserting
|
|
|
|
// or even doing error handling. pUndos should definitely be replaced by an
|
|
|
|
// STL container that doesn't have this problem. cf #95884#
|
|
|
|
DBG_ASSERT( pUndos->Count() < USHRT_MAX - 16,
|
|
|
|
"Writer will crash soon. I apologize for the inconvenience." );
|
|
|
|
|
2001-09-27 12:44:28 +00:00
|
|
|
pUndos->Insert( pUndo, nUndoPos );
|
|
|
|
++nUndoPos;
|
2000-09-18 23:08:29 +00:00
|
|
|
switch( pUndo->GetId() )
|
|
|
|
{
|
|
|
|
case UNDO_START: ++nUndoSttEnd;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case UNDO_END: ASSERT( nUndoSttEnd, "Undo-Ende ohne Start" );
|
|
|
|
--nUndoSttEnd;
|
|
|
|
// kein break !!!
|
2001-09-27 12:44:28 +00:00
|
|
|
default:
|
|
|
|
if( pUndos->Count() != nUndoPos && UNDO_END != pUndo->GetId() )
|
2010-11-25 14:31:09 +01:00
|
|
|
{
|
2001-09-27 12:44:28 +00:00
|
|
|
ClearRedo();
|
2008-04-22 14:01:51 +00:00
|
|
|
}
|
2010-11-25 14:31:09 +01:00
|
|
|
OSL_ENSURE( pUndos->Count() == nUndoPos || UNDO_END == pUndo->GetId(),
|
|
|
|
"Redo history not deleted!" );
|
2001-09-27 12:44:28 +00:00
|
|
|
if( !nUndoSttEnd )
|
|
|
|
++nUndoCnt;
|
|
|
|
break;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _SHOW_UNDORANGE
|
|
|
|
// zur Anzeige der aktuellen Undo-Groessen
|
|
|
|
if( !pUndoMsgWin )
|
|
|
|
pUndoMsgWin = new UndoArrStatus;
|
2010-11-25 14:31:07 +01:00
|
|
|
pUndoMsgWin->Set( pUndos->Count(), m_rDoc.GetUndoNds()->Count() );
|
2000-09-18 23:08:29 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// noch eine offene Klammerung, kann man sich den Rest schenken
|
|
|
|
if( nUndoSttEnd )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// folgende Array-Grenzen muessen ueberwacht werden:
|
|
|
|
// - Undo, Grenze: fester Wert oder USHRT_MAX - 1000
|
|
|
|
// - UndoNodes, Grenze: USHRT_MAX - 1000
|
|
|
|
// - AttrHistory Grenze: USHRT_MAX - 1000
|
2002-06-03 11:35:54 +00:00
|
|
|
// (defined in UNDO_ACTION_LIMIT at the top of this file)
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2002-06-03 11:35:54 +00:00
|
|
|
USHORT nEnde = UNDO_ACTION_LIMIT;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// nur zum Testen der neuen DOC-Member
|
2009-07-10 14:03:42 +02:00
|
|
|
#ifdef DBG_UTIL
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
|
|
|
USHORT nUndosCnt = 0, nSttEndCnt = 0;
|
2000-09-18 23:08:29 +00:00
|
|
|
for( USHORT nCnt = 0; nCnt < nUndoPos; ++nCnt )
|
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
if( UNDO_START == ( nId = (*pUndos)[ nCnt ]->GetId()) )
|
2000-09-18 23:08:29 +00:00
|
|
|
++nSttEndCnt;
|
|
|
|
else if( UNDO_END == nId )
|
|
|
|
--nSttEndCnt;
|
|
|
|
if( !nSttEndCnt )
|
|
|
|
++nUndosCnt;
|
|
|
|
}
|
|
|
|
ASSERT( nSttEndCnt == nUndoSttEnd, "Start-Ende Count ungleich" );
|
|
|
|
ASSERT( nUndosCnt == nUndoCnt, "Undo Count ungleich" );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
if (GetUndoActionCount() < nUndoCnt)
|
|
|
|
{
|
2000-09-18 23:08:29 +00:00
|
|
|
// immer 1/10 loeschen
|
|
|
|
//JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
|
2001-05-29 08:08:52 +00:00
|
|
|
//JP 29.5.2001: Task #83891#: remove only the overlapping actions
|
2010-11-25 14:31:07 +01:00
|
|
|
DelUndoObj( nUndoCnt - GetUndoActionCount() );
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
USHORT nUndosCnt = nUndoCnt;
|
|
|
|
// immer 1/10 loeschen bis der "Ausloeser" behoben ist
|
2010-11-25 14:31:07 +01:00
|
|
|
while (nEnde < m_rDoc.GetUndoNds()->Count())
|
|
|
|
{
|
2000-09-18 23:08:29 +00:00
|
|
|
DelUndoObj( nUndosCnt / 10 );
|
2010-11-25 14:31:07 +01:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
void UndoManager::ClearRedo()
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2010-11-25 14:31:09 +01:00
|
|
|
if (nUndoPos != pUndos->Count())
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2001-09-27 12:44:28 +00:00
|
|
|
//?? why ?? if( !nUndoSttEnd )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
// setze UndoCnt auf den neuen Wert
|
|
|
|
SwUndo* pUndo;
|
|
|
|
for( USHORT nCnt = pUndos->Count(); nUndoPos < nCnt; --nUndoCnt )
|
|
|
|
// Klammerung ueberspringen
|
|
|
|
if( UNDO_END == (pUndo = (*pUndos)[ --nCnt ])->GetId() )
|
2007-09-27 08:29:16 +00:00
|
|
|
nCnt = nCnt - ((SwUndoEnd*)pUndo)->GetSttOffset();
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// loesche die Undo-Aktionen (immer von hinten !)
|
|
|
|
pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// loescht die gesamten UndoObjecte
|
2010-11-25 14:31:07 +01:00
|
|
|
void UndoManager::DelAllUndoObj()
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2010-11-25 14:31:09 +01:00
|
|
|
::sw::UndoGuard const undoGuard(*this);
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2010-11-25 14:31:09 +01:00
|
|
|
ClearRedo();
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// Offene Undo-Klammerungen erhalten !!
|
|
|
|
SwUndo* pUndo;
|
|
|
|
USHORT nSize = pUndos->Count();
|
|
|
|
while( nSize )
|
|
|
|
if( UNDO_START != ( pUndo = (*pUndos)[ --nSize ] )->GetId() ||
|
|
|
|
((SwUndoStart*)pUndo)->GetEndOffset() )
|
|
|
|
// keine offenen Gruppierung ?
|
|
|
|
pUndos->DeleteAndDestroy( nSize, 1 );
|
|
|
|
|
|
|
|
nUndoCnt = 0;
|
|
|
|
nUndoPos = pUndos->Count();
|
|
|
|
|
|
|
|
/*
|
|
|
|
while( nUndoPos )
|
|
|
|
aUndos.DelDtor( --nUndoPos, 1 );
|
|
|
|
nUndoCnt = nUndoSttEnd = nUndoPos = 0;
|
|
|
|
*/
|
|
|
|
nUndoSavePos = USHRT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// loescht alle UndoObjecte vom Anfang bis zum angegebenen Ende
|
2010-11-25 14:31:07 +01:00
|
|
|
bool UndoManager::DelUndoObj( sal_uInt16 nEnd )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2010-11-25 14:31:07 +01:00
|
|
|
if (0 == nEnd) // in case 0 is passed in
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if( !pUndos->Count() )
|
|
|
|
return FALSE;
|
2010-11-25 14:31:07 +01:00
|
|
|
++nEnd; // correct it to 1 // FIXME why ???
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:09 +01:00
|
|
|
::sw::UndoGuard const undoGuard(*this);
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// pruefe erstmal, wo das Ende steht
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
|
|
|
USHORT nSttEndCnt = 0;
|
2003-12-01 16:23:31 +00:00
|
|
|
USHORT nCnt;
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
for (nCnt = 0; nEnd && nCnt < nUndoPos; ++nCnt)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if( UNDO_START == ( nId = (*pUndos)[ nCnt ]->GetId() ))
|
|
|
|
++nSttEndCnt;
|
|
|
|
else if( UNDO_END == nId )
|
|
|
|
--nSttEndCnt;
|
|
|
|
if( !nSttEndCnt )
|
2010-11-25 14:31:07 +01:00
|
|
|
--nEnd, --nUndoCnt;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT( nCnt < nUndoPos || nUndoPos == pUndos->Count(),
|
|
|
|
"Undo-Del-Ende liegt in einer Redo-Aktion" );
|
|
|
|
|
|
|
|
// dann setze ab Ende bis Undo-Ende bei allen Undo-Objecte die Werte um
|
|
|
|
nSttEndCnt = nCnt; // Position merken
|
|
|
|
if( nUndoSavePos < nSttEndCnt ) // SavePos wird aufgegeben
|
|
|
|
nUndoSavePos = USHRT_MAX;
|
|
|
|
else if( nUndoSavePos != USHRT_MAX )
|
2007-09-27 08:29:16 +00:00
|
|
|
nUndoSavePos = nUndoSavePos - nSttEndCnt;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
while( nSttEndCnt )
|
|
|
|
pUndos->DeleteAndDestroy( --nSttEndCnt, 1 );
|
|
|
|
nUndoPos = pUndos->Count();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************** UNDO ******************/
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
bool UndoManager::HasUndoId(SwUndoId const eId) const
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
USHORT nSize = nUndoPos;
|
|
|
|
SwUndo * pUndo;
|
|
|
|
while( nSize-- )
|
2007-09-27 08:29:16 +00:00
|
|
|
if( ( pUndo = (*pUndos)[nSize])->GetId() == eId ||
|
2000-09-18 23:08:29 +00:00
|
|
|
( UNDO_START == pUndo->GetId() &&
|
2007-09-27 08:29:16 +00:00
|
|
|
((SwUndoStart*)pUndo)->GetUserId() == eId )
|
2000-09-18 23:08:29 +00:00
|
|
|
|| ( UNDO_END == pUndo->GetId() &&
|
2007-09-27 08:29:16 +00:00
|
|
|
((SwUndoEnd*)pUndo)->GetUserId() == eId ) )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
bool UndoManager::Undo( SwUndoIter& rUndoIter )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if ( (rUndoIter.GetId()!=0) && (!HasUndoId(rUndoIter.GetId())) )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if( !nUndoPos )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SwUndo *pUndo = (*pUndos)[ --nUndoPos ];
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
RedlineMode_t const eOld = m_rDoc.GetRedlineMode();
|
2007-09-27 08:29:16 +00:00
|
|
|
RedlineMode_t eTmpMode = (RedlineMode_t)pUndo->GetRedlineMode();
|
|
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eTmpMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eOld) &&
|
2000-09-18 23:08:29 +00:00
|
|
|
UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.SetRedlineMode( eTmpMode );
|
|
|
|
}
|
|
|
|
m_rDoc.SetRedlineMode_intern(
|
|
|
|
static_cast<RedlineMode_t>(eTmpMode | nsRedlineMode_t::REDLINE_IGNORE));
|
2000-09-18 23:08:29 +00:00
|
|
|
// Undo ausfuehren
|
|
|
|
|
|
|
|
// zum spaeteren ueberpruefen
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nAktId = pUndo->GetId();
|
2000-09-18 23:08:29 +00:00
|
|
|
//JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
|
|
|
|
// Undo heraus
|
2001-11-13 12:52:46 +00:00
|
|
|
switch( nAktId )
|
|
|
|
{
|
|
|
|
case UNDO_START:
|
|
|
|
case UNDO_END:
|
|
|
|
case UNDO_INSDRAWFMT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2000-09-18 23:08:29 +00:00
|
|
|
rUndoIter.ClearSelections();
|
2001-11-13 12:52:46 +00:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
pUndo->Undo( rUndoIter );
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
m_rDoc.SetRedlineMode( eOld );
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// Besonderheit von Undo-Replace (interne History)
|
|
|
|
if( UNDO_REPLACE == nAktId && ((SwUndoReplace*)pUndo)->nAktPos )
|
|
|
|
{
|
|
|
|
++nUndoPos;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Objekt aus History entfernen und zerstoeren
|
|
|
|
if( nUndoPos && !rUndoIter.bWeiter &&
|
|
|
|
UNDO_START == ( pUndo = (*pUndos)[ nUndoPos-1 ] )->GetId() )
|
|
|
|
--nUndoPos;
|
|
|
|
|
|
|
|
// JP 29.10.96: Start und End setzen kein Modify-Flag.
|
|
|
|
// Sonst gibt es Probleme mit der autom. Aufnahme von Ausnahmen
|
|
|
|
// bei der Autokorrektur
|
|
|
|
if( UNDO_START != nAktId && UNDO_END != nAktId )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.SetModified(); // default: always set, can be reset
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// ist die History leer und wurde nicht wegen Speichermangel
|
|
|
|
// verworfen, so kann das Dokument als unveraendert gelten
|
|
|
|
if( nUndoSavePos == nUndoPos )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.ResetModified();
|
|
|
|
}
|
2006-08-14 15:48:33 +00:00
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setzt Undoklammerung auf, liefert nUndoId der Klammerung
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
SwUndoId
|
2010-11-25 14:31:10 +01:00
|
|
|
UndoManager::StartUndo(SwUndoId const i_eUndoId,
|
|
|
|
SwRewriter const*const pRewriter)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2006-08-14 15:48:33 +00:00
|
|
|
if( !mbUndo )
|
2007-09-27 08:29:16 +00:00
|
|
|
return UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId const eUndoId( (0 == i_eUndoId) ? UNDO_START : i_eUndoId );
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoStart * pUndo = new SwUndoStart( eUndoId );
|
2004-05-18 13:06:14 +00:00
|
|
|
|
|
|
|
if (pRewriter)
|
|
|
|
pUndo->SetRewriter(*pRewriter);
|
|
|
|
|
|
|
|
AppendUndo(pUndo);
|
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
return eUndoId;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
// schliesst Klammerung der nUndoId, nicht vom UI benutzt
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId
|
|
|
|
UndoManager::EndUndo(SwUndoId const i_eUndoId, SwRewriter const*const pRewriter)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2001-09-27 12:44:28 +00:00
|
|
|
USHORT nSize = nUndoPos;
|
2006-08-14 15:48:33 +00:00
|
|
|
if( !mbUndo || !nSize-- )
|
2007-09-27 08:29:16 +00:00
|
|
|
return UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId const eUndoId( ((0 == i_eUndoId) || (UNDO_START == i_eUndoId))
|
|
|
|
? UNDO_END : i_eUndoId );
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
SwUndo* pUndo = (*pUndos)[ nSize ];
|
|
|
|
if( UNDO_START == pUndo->GetId() )
|
|
|
|
{
|
|
|
|
// leere Start/End-Klammerung ??
|
|
|
|
pUndos->DeleteAndDestroy( nSize );
|
2001-09-27 12:44:28 +00:00
|
|
|
--nUndoPos;
|
2000-09-18 23:08:29 +00:00
|
|
|
--nUndoSttEnd;
|
2007-09-27 08:29:16 +00:00
|
|
|
return UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
2001-09-27 12:44:28 +00:00
|
|
|
// exist above any redo objects? If yes, delete them
|
|
|
|
if( nUndoPos != pUndos->Count() )
|
|
|
|
{
|
|
|
|
// setze UndoCnt auf den neuen Wert
|
|
|
|
for( USHORT nCnt = pUndos->Count(); nUndoPos < nCnt; --nUndoCnt )
|
|
|
|
// Klammerung ueberspringen
|
|
|
|
if( UNDO_END == (pUndo = (*pUndos)[ --nCnt ])->GetId() )
|
2007-09-27 08:29:16 +00:00
|
|
|
nCnt = nCnt - ((SwUndoEnd*)pUndo)->GetSttOffset();
|
2001-09-27 12:44:28 +00:00
|
|
|
|
|
|
|
pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
// suche den Anfang dieser Klammerung
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
while( nSize )
|
|
|
|
if( UNDO_START == ( nId = (pUndo = (*pUndos)[ --nSize ] )->GetId()) &&
|
|
|
|
!((SwUndoStart*)pUndo)->GetEndOffset() )
|
|
|
|
break; // Start gefunden
|
|
|
|
|
|
|
|
if( nId != UNDO_START )
|
|
|
|
{
|
|
|
|
// kann eigentlich nur beim Abspielen von Macros passieren, die
|
|
|
|
// Undo/Redo/Repeat benutzen und die eine exitierende Selection
|
|
|
|
// durch Einfuegen loeschen
|
|
|
|
ASSERT( !this, "kein entsprechendes Ende gefunden" );
|
|
|
|
// kein entsprechenden Start gefunden -> Ende nicht einfuegen
|
|
|
|
// und die Member am Doc updaten
|
|
|
|
|
|
|
|
nUndoSttEnd = 0;
|
|
|
|
nUndoCnt = 0;
|
|
|
|
// setze UndoCnt auf den neuen Wert
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndo* pTmpUndo;
|
2000-09-18 23:08:29 +00:00
|
|
|
for( USHORT nCnt = 0; nCnt < pUndos->Count(); ++nCnt, ++nUndoCnt )
|
|
|
|
// Klammerung ueberspringen
|
2007-09-27 08:29:16 +00:00
|
|
|
if( UNDO_START == (pTmpUndo = (*pUndos)[ nCnt ])->GetId() )
|
|
|
|
nCnt = nCnt + ((SwUndoStart*)pTmpUndo)->GetEndOffset();
|
|
|
|
return UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Klammerung um eine einzelne Action muss nicht sein!
|
|
|
|
// Aussnahme: es ist eine eigene ID definiert
|
|
|
|
if( 2 == pUndos->Count() - nSize &&
|
2007-09-27 08:29:16 +00:00
|
|
|
(UNDO_END == eUndoId || eUndoId == (*pUndos)[ nSize+1 ]->GetId() ))
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
pUndos->DeleteAndDestroy( nSize );
|
|
|
|
nUndoPos = pUndos->Count();
|
|
|
|
if( !--nUndoSttEnd )
|
|
|
|
{
|
|
|
|
++nUndoCnt;
|
2010-11-25 14:31:07 +01:00
|
|
|
if (GetUndoActionCount() < nUndoCnt)
|
|
|
|
{
|
2000-09-18 23:08:29 +00:00
|
|
|
// immer 1/10 loeschen
|
|
|
|
//JP 23.09.95: oder wenn neu eingestellt wurde um die Differenz
|
2001-05-29 08:08:52 +00:00
|
|
|
//JP 29.5.2001: Task #83891#: remove only the overlapping actions
|
2010-11-25 14:31:07 +01:00
|
|
|
DelUndoObj( nUndoCnt - GetUndoActionCount() );
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
USHORT nEnde = USHRT_MAX - 1000;
|
|
|
|
USHORT nUndosCnt = nUndoCnt;
|
|
|
|
// immer 1/10 loeschen bis der "Ausloeser" behoben ist
|
2010-11-25 14:31:07 +01:00
|
|
|
while (nEnde < m_rDoc.GetUndoNds()->Count())
|
|
|
|
{
|
2000-09-18 23:08:29 +00:00
|
|
|
DelUndoObj( nUndosCnt / 10 );
|
2010-11-25 14:31:07 +01:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-27 08:29:16 +00:00
|
|
|
return eUndoId;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// setze die Klammerung am Start/End-Undo
|
|
|
|
nSize = pUndos->Count() - nSize;
|
|
|
|
((SwUndoStart*)pUndo)->SetEndOffset( nSize );
|
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoEnd* pUndoEnd = new SwUndoEnd( eUndoId );
|
2000-09-18 23:08:29 +00:00
|
|
|
pUndoEnd->SetSttOffset( nSize );
|
|
|
|
|
|
|
|
// nur zum Testen der Start/End-Verpointerung vom Start/End Undo
|
2009-07-10 14:03:42 +02:00
|
|
|
#ifdef DBG_UTIL
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
USHORT nEndCnt = 1, nCnt = pUndos->Count();
|
|
|
|
SwUndoId nTmpId = UNDO_EMPTY;
|
2004-05-18 13:06:14 +00:00
|
|
|
while( nCnt )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
if( UNDO_START == ( nTmpId = (*pUndos)[ --nCnt ]->GetId()) )
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
|
|
|
if( !nEndCnt ) // falls mal ein Start ohne Ende vorhanden ist
|
|
|
|
continue;
|
|
|
|
--nEndCnt;
|
|
|
|
if( !nEndCnt ) // hier ist der Anfang
|
|
|
|
break;
|
|
|
|
}
|
2007-09-27 08:29:16 +00:00
|
|
|
else if( UNDO_END == nTmpId )
|
2004-05-18 13:06:14 +00:00
|
|
|
++nEndCnt;
|
|
|
|
else if( !nEndCnt )
|
2000-09-18 23:08:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-05-18 13:06:14 +00:00
|
|
|
ASSERT( nCnt == pUndos->Count() - nSize,
|
|
|
|
"Start-Ende falsch geklammert" );
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
if (pRewriter)
|
|
|
|
{
|
|
|
|
((SwUndoStart *) pUndo)->SetRewriter(*pRewriter);
|
|
|
|
pUndoEnd->SetRewriter(*pRewriter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pUndoEnd->SetRewriter(((SwUndoStart *) pUndo)->GetRewriter());
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
AppendUndo( pUndoEnd );
|
2007-09-27 08:29:16 +00:00
|
|
|
return eUndoId;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
2005-01-05 15:09:05 +00:00
|
|
|
/*-- 24.11.2004 16:11:21---------------------------------------------------
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------*/
|
2010-11-25 14:31:07 +01:00
|
|
|
sal_Bool UndoManager::RestoreInvisibleContent()
|
2005-01-05 15:09:05 +00:00
|
|
|
{
|
|
|
|
sal_Bool bRet = sal_False;
|
|
|
|
if(nUndoPos > 0 )
|
|
|
|
{
|
|
|
|
SwUndo * pUndo = (*pUndos)[ nUndoPos - 1 ];
|
|
|
|
if( ( pUndo->GetId() == UNDO_END &&
|
2007-09-27 08:29:16 +00:00
|
|
|
static_cast<SwUndoEnd *>(pUndo)->GetUserId() == UNDO_UI_DELETE_INVISIBLECNTNT) )
|
2005-01-05 15:09:05 +00:00
|
|
|
{
|
2010-11-25 14:31:07 +01:00
|
|
|
SwPaM aPam( m_rDoc.GetNodes().GetEndOfPostIts() );
|
2005-01-05 15:09:05 +00:00
|
|
|
SwUndoIter aUndoIter( &aPam );
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Undo( aUndoIter );
|
|
|
|
}
|
|
|
|
while ( aUndoIter.IsNextUndo() );
|
|
|
|
ClearRedo();
|
|
|
|
bRet = sal_True;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
/**
|
|
|
|
Returns id and comment for a certain undo object in an undo stack.
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
Remark: In the following the object type referred to is always the
|
|
|
|
effective object type. If an UNDO_START or UNDO_END has a user type
|
|
|
|
it is referred to as this type.
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
If the queried object is an UNDO_END and has no user id the result
|
|
|
|
is taken from the first object that is not an UNDO_END nor an
|
|
|
|
UNDO_START preceeding the queried object.
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
If the queried object is an UNDO_START and has no user id the
|
|
|
|
result is taken from the first object that is not an UNDO_END nor
|
|
|
|
an UNDO_START preceeding the UNDO_END object belonging to the
|
|
|
|
queried object.
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
In all other cases the result is taken from the queried object.
|
2001-04-09 06:23:08 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
@param rUndos the undo stack
|
|
|
|
@param nPos position of the undo object to query
|
|
|
|
|
|
|
|
@return SwUndoIdAndName object containing the query result
|
|
|
|
*/
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoIdAndName * lcl_GetUndoIdAndName(const SwUndos & rUndos, sal_uInt16 nPos )
|
2004-10-22 07:14:25 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndo * pUndo = rUndos[ nPos ];
|
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
2004-10-22 07:14:25 +00:00
|
|
|
String sStr("??", RTL_TEXTENCODING_ASCII_US);
|
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
ASSERT( nPos < rUndos.Count(), "nPos out of range");
|
2004-10-22 07:14:25 +00:00
|
|
|
|
|
|
|
switch (pUndo->GetId())
|
|
|
|
{
|
|
|
|
case UNDO_START:
|
2001-04-09 06:23:08 +00:00
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
SwUndoStart * pUndoStart = (SwUndoStart *) pUndo;
|
|
|
|
nId = pUndoStart->GetUserId();
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (nId <= UNDO_END)
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
/**
|
|
|
|
Start at the according UNDO_END. Search backwards
|
|
|
|
for first objects that is not a UNDO_END.
|
|
|
|
*/
|
|
|
|
int nTmpPos = nPos + pUndoStart->GetEndOffset();
|
|
|
|
int nSubstitute = -1;
|
|
|
|
|
2009-10-14 17:33:11 +00:00
|
|
|
// --> OD 2009-09-30 #i105457#
|
|
|
|
if ( nTmpPos > 0 )
|
|
|
|
// <--
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
2009-10-14 17:33:11 +00:00
|
|
|
SwUndo * pTmpUndo;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
nTmpPos--;
|
|
|
|
pTmpUndo = rUndos[ static_cast<USHORT>(nTmpPos) ];
|
|
|
|
|
|
|
|
if (pTmpUndo->GetEffectiveId() > UNDO_END)
|
|
|
|
nSubstitute = nTmpPos;
|
|
|
|
}
|
|
|
|
while (nSubstitute < 0 && nTmpPos > nPos);
|
|
|
|
|
|
|
|
if (nSubstitute >= 0)
|
|
|
|
{
|
|
|
|
SwUndo * pSubUndo = rUndos[ static_cast<USHORT>(nSubstitute) ];
|
|
|
|
nId = pSubUndo->GetEffectiveId();
|
|
|
|
sStr = pSubUndo->GetComment();
|
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sStr = pUndo->GetComment();
|
|
|
|
}
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UNDO_END:
|
|
|
|
{
|
|
|
|
SwUndoEnd * pUndoEnd = (SwUndoEnd *) pUndo;
|
|
|
|
nId = pUndoEnd->GetUserId();
|
|
|
|
|
|
|
|
if (nId <= UNDO_END)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
Start at this UNDO_END. Search backwards
|
|
|
|
for first objects that is not a UNDO_END.
|
|
|
|
*/
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
int nTmpPos = nPos;
|
|
|
|
int nUndoStart = nTmpPos - pUndoEnd->GetSttOffset();
|
|
|
|
int nSubstitute = -1;
|
|
|
|
|
|
|
|
if (nTmpPos > 0)
|
|
|
|
{
|
|
|
|
SwUndo * pTmpUndo;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
nTmpPos--;
|
2007-09-27 08:29:16 +00:00
|
|
|
pTmpUndo = rUndos[ static_cast<USHORT>(nTmpPos) ];
|
2004-10-22 07:14:25 +00:00
|
|
|
|
|
|
|
if (pTmpUndo->GetEffectiveId() > UNDO_END)
|
|
|
|
nSubstitute = nTmpPos;
|
2004-05-18 13:06:14 +00:00
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
while (nSubstitute < 0 && nTmpPos > nUndoStart);
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (nSubstitute >= 0)
|
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndo * pSubUndo = rUndos[ static_cast<USHORT>(nSubstitute) ];
|
2004-10-22 07:14:25 +00:00
|
|
|
nId = pSubUndo->GetEffectiveId();
|
|
|
|
sStr = pSubUndo->GetComment();
|
|
|
|
}
|
2004-05-18 13:06:14 +00:00
|
|
|
}
|
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
else
|
|
|
|
sStr = pUndo->GetComment();
|
2001-04-09 06:23:08 +00:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
break;
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
default:
|
|
|
|
nId = pUndo->GetId();
|
|
|
|
sStr = pUndo->GetComment();
|
|
|
|
}
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
return new SwUndoIdAndName(nId, &sStr);
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId
|
|
|
|
UndoManager::GetUndoIds(String *const o_pStr, SwUndoIds *const o_pUndoIds) const
|
2004-10-22 07:14:25 +00:00
|
|
|
{
|
|
|
|
int nTmpPos = nUndoPos - 1;
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
2004-10-22 07:14:25 +00:00
|
|
|
|
|
|
|
while (nTmpPos >= 0)
|
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndo * pUndo = (*pUndos)[ static_cast<USHORT>(nTmpPos) ];
|
2004-10-22 07:14:25 +00:00
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoIdAndName * pIdAndName = lcl_GetUndoIdAndName( *pUndos, static_cast<sal_uInt16>(nTmpPos) );
|
2004-10-22 07:14:25 +00:00
|
|
|
|
|
|
|
if (nTmpPos == nUndoPos - 1)
|
2001-04-09 06:23:08 +00:00
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
nId = pIdAndName->GetUndoId();
|
2001-05-17 10:49:56 +00:00
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
if (o_pStr)
|
|
|
|
{
|
|
|
|
*o_pStr = *pIdAndName->GetUndoStr();
|
|
|
|
}
|
2001-04-09 06:23:08 +00:00
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
if (o_pUndoIds)
|
|
|
|
{
|
|
|
|
o_pUndoIds->Insert(pIdAndName, o_pUndoIds->Count());
|
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (pUndo->GetId() == UNDO_END)
|
|
|
|
nTmpPos -= ((SwUndoEnd *) pUndo)->GetSttOffset();
|
|
|
|
|
|
|
|
nTmpPos--;
|
|
|
|
}
|
2004-09-08 13:58:12 +00:00
|
|
|
|
2001-04-09 06:23:08 +00:00
|
|
|
return nId;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
bool UndoManager::HasTooManyUndos() const
|
2002-06-03 11:35:54 +00:00
|
|
|
{
|
|
|
|
// AppendUndo checks the UNDO_ACTION_LIMIT, unless there's a nested undo.
|
|
|
|
// So HasTooManyUndos() may only occur when undos are nested; else
|
|
|
|
// AppendUndo has some sort of bug.
|
|
|
|
DBG_ASSERT( (nUndoSttEnd != 0) || (pUndos->Count() < UNDO_ACTION_LIMIT),
|
|
|
|
"non-nested undos should have been handled in AppendUndo" );
|
|
|
|
return (pUndos->Count() >= UNDO_ACTION_LIMIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
/**************** REDO ******************/
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
bool UndoManager::Redo(SwUndoIter & rUndoIter)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if( rUndoIter.GetId() && !HasUndoId( rUndoIter.GetId() ) )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if( nUndoPos == pUndos->Count() )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SwUndo *pUndo = (*pUndos)[ nUndoPos++ ];
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
RedlineMode_t const eOld = m_rDoc.GetRedlineMode();
|
2007-09-27 08:29:16 +00:00
|
|
|
RedlineMode_t eTmpMode = (RedlineMode_t)pUndo->GetRedlineMode();
|
|
|
|
if( (nsRedlineMode_t::REDLINE_SHOW_MASK & eTmpMode) != (nsRedlineMode_t::REDLINE_SHOW_MASK & eOld) &&
|
2000-09-18 23:08:29 +00:00
|
|
|
UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.SetRedlineMode( eTmpMode );
|
|
|
|
}
|
|
|
|
m_rDoc.SetRedlineMode_intern(
|
|
|
|
static_cast<RedlineMode_t>(eTmpMode | nsRedlineMode_t::REDLINE_IGNORE));
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
//JP 11.05.98: FlyFormate ueber die EditShell selektieren, nicht aus dem
|
|
|
|
// Undo heraus
|
|
|
|
if( UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
|
|
|
|
rUndoIter.ClearSelections();
|
|
|
|
|
|
|
|
pUndo->Redo( rUndoIter );
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
m_rDoc.SetRedlineMode( eOld );
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
// Besonderheit von Undo-Replace (interne History)
|
|
|
|
if( UNDO_REPLACE == pUndo->GetId() &&
|
|
|
|
USHRT_MAX != ((SwUndoReplace*)pUndo)->nAktPos )
|
|
|
|
{
|
|
|
|
--nUndoPos;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( rUndoIter.bWeiter && nUndoPos >= pUndos->Count() )
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
|
|
|
|
// ist die History leer und wurde nicht wegen Speichermangel
|
|
|
|
// verworfen, so kann das Dokument als unveraendert gelten
|
|
|
|
if( nUndoSavePos == nUndoPos )
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.ResetModified();
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
else
|
2010-11-25 14:31:07 +01:00
|
|
|
{
|
|
|
|
m_rDoc.SetModified();
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
SwUndoId UndoManager::GetRedoIds( String* pStr, SwUndoIds *pRedoIds ) const
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2007-09-27 08:29:16 +00:00
|
|
|
sal_uInt16 nTmpPos = nUndoPos;
|
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
while (nTmpPos < pUndos->Count())
|
|
|
|
{
|
|
|
|
SwUndo * pUndo = (*pUndos)[nTmpPos];
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
SwUndoIdAndName * pIdAndName = lcl_GetUndoIdAndName(*pUndos, nTmpPos);
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (nTmpPos == nUndoPos)
|
2001-04-09 06:23:08 +00:00
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
nId = pIdAndName->GetUndoId();
|
2001-04-09 06:23:08 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (pStr)
|
|
|
|
*pStr = *pIdAndName->GetUndoStr();
|
2001-04-09 06:23:08 +00:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (pRedoIds)
|
|
|
|
pRedoIds->Insert(pIdAndName, pRedoIds->Count());
|
|
|
|
else
|
|
|
|
break;
|
2001-05-17 10:49:56 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (pUndo->GetId() == UNDO_START)
|
2007-09-27 08:29:16 +00:00
|
|
|
nTmpPos = nTmpPos + ((SwUndoStart *) pUndo)->GetEndOffset();
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
nTmpPos++;
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
return nId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************** REPEAT ******************/
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
bool UndoManager::Repeat(SwUndoIter & rUndoIter, sal_uInt16 const nRepeatCnt)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if( rUndoIter.GetId() && !HasUndoId( rUndoIter.GetId() ) )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
USHORT nSize = nUndoPos;
|
|
|
|
if( !nSize )
|
|
|
|
{
|
|
|
|
rUndoIter.bWeiter = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dann suche jetzt ueber die End/Start-Gruppen die gueltige Repeat-Aktion
|
|
|
|
SwUndo *pUndo = (*pUndos)[ --nSize ];
|
|
|
|
if( UNDO_END == pUndo->GetId() )
|
2007-09-27 08:29:16 +00:00
|
|
|
nSize = nSize - ((SwUndoEnd*)pUndo)->GetSttOffset();
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
USHORT nEndCnt = nUndoPos;
|
|
|
|
BOOL bOneUndo = nSize + 1 == nUndoPos;
|
|
|
|
|
|
|
|
SwPaM* pTmpCrsr = rUndoIter.pAktPam;
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoId nId = UNDO_EMPTY;
|
2005-02-21 15:06:16 +00:00
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
if( pTmpCrsr != pTmpCrsr->GetNext() || !bOneUndo ) // Undo-Klammerung aufbauen
|
2005-02-21 15:06:16 +00:00
|
|
|
{
|
|
|
|
if (pUndo->GetId() == UNDO_END)
|
|
|
|
{
|
|
|
|
SwUndoStart * pStartUndo =
|
|
|
|
(SwUndoStart *) (*pUndos)[nSize];
|
|
|
|
|
|
|
|
nId = pStartUndo->GetUserId();
|
|
|
|
}
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
StartUndo( nId, NULL );
|
2005-02-21 15:06:16 +00:00
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
do { // dann durchlaufe mal den gesamten Ring
|
|
|
|
for( USHORT nRptCnt = nRepeatCnt; nRptCnt > 0; --nRptCnt )
|
|
|
|
{
|
|
|
|
rUndoIter.pLastUndoObj = 0;
|
|
|
|
for( USHORT nCnt = nSize; nCnt < nEndCnt; ++nCnt )
|
|
|
|
(*pUndos)[ nCnt ]->Repeat( rUndoIter ); // Repeat ausfuehren
|
|
|
|
}
|
|
|
|
} while( pTmpCrsr !=
|
|
|
|
( rUndoIter.pAktPam = (SwPaM*)rUndoIter.pAktPam->GetNext() ));
|
|
|
|
if( pTmpCrsr != pTmpCrsr->GetNext() || !bOneUndo )
|
2006-08-14 15:48:33 +00:00
|
|
|
EndUndo( nId, NULL );
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId
|
|
|
|
UndoManager::GetRepeatIds(String *const o_pStr) const
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndoId const nRepeatId = GetUndoIds(o_pStr, 0);
|
|
|
|
if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
2010-11-25 14:31:10 +01:00
|
|
|
return nRepeatId;
|
2004-05-18 13:06:14 +00:00
|
|
|
}
|
2010-11-25 14:31:10 +01:00
|
|
|
if (o_pStr) // not repeatable -> clear comment
|
2010-11-25 14:31:10 +01:00
|
|
|
{
|
2010-11-25 14:31:10 +01:00
|
|
|
*o_pStr = String();
|
2010-11-25 14:31:10 +01:00
|
|
|
}
|
2007-09-27 08:29:16 +00:00
|
|
|
return UNDO_EMPTY;
|
2000-09-18 23:08:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-25 14:31:10 +01:00
|
|
|
SwUndo* UndoManager::RemoveLastUndo(SwUndoId const eUndoId)
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2001-09-27 12:44:28 +00:00
|
|
|
SwUndo* pUndo = (*pUndos)[ nUndoPos - 1 ];
|
2007-09-27 08:29:16 +00:00
|
|
|
if( eUndoId == pUndo->GetId() && nUndoPos == pUndos->Count() )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
if( !nUndoSttEnd )
|
|
|
|
--nUndoCnt;
|
|
|
|
--nUndoPos;
|
|
|
|
pUndos->Remove( nUndoPos, 1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pUndo = 0;
|
|
|
|
ASSERT( !this, "falsches Undo-Object" );
|
|
|
|
}
|
|
|
|
return pUndo;
|
|
|
|
}
|
|
|
|
|
2010-11-25 14:31:07 +01:00
|
|
|
} // namespace sw
|
|
|
|
|
|
|
|
// SwUndoIdAndName ///////////////////////////////////////////////////////
|
|
|
|
|
2007-09-27 08:29:16 +00:00
|
|
|
SwUndoIdAndName::SwUndoIdAndName( SwUndoId nId, const String* pStr )
|
|
|
|
: eUndoId( nId ), pUndoStr( pStr ? new String( *pStr ) : 0 )
|
2001-04-09 06:23:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SwUndoIdAndName::~SwUndoIdAndName()
|
|
|
|
{
|
|
|
|
delete pUndoStr;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
|