2000-09-18 23:08:29 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* $RCSfile: docundo.cxx,v $
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2007-05-25 12:01:29 +00:00
|
|
|
* $Revision: 1.22 $
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2007-05-25 12:01:29 +00:00
|
|
|
* last change: $Author: vg $ $Date: 2007-05-25 13:01:29 $
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* The Contents of this file are made available subject to
|
|
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* This library 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 for more details.
|
2000-09-18 23:08:29 +00:00
|
|
|
*
|
2005-09-09 04:17:05 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
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"
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
#ifndef _SV_WRKWIN_HXX //autogen
|
|
|
|
#include <vcl/wrkwin.hxx>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _DOC_HXX
|
|
|
|
#include <doc.hxx>
|
|
|
|
#endif
|
|
|
|
#ifndef _PAM_HXX
|
|
|
|
#include <pam.hxx>
|
|
|
|
#endif
|
|
|
|
#ifndef _NDTXT_HXX
|
|
|
|
#include <ndtxt.hxx>
|
|
|
|
#endif
|
|
|
|
#ifndef _SWUNDO_HXX
|
|
|
|
#include <swundo.hxx> // fuer die UndoIds
|
|
|
|
#endif
|
|
|
|
#ifndef _UNDOBJ_HXX
|
|
|
|
#include <undobj.hxx>
|
|
|
|
#endif
|
|
|
|
#ifndef _ROLBCK_HXX
|
|
|
|
#include <rolbck.hxx>
|
|
|
|
#endif
|
|
|
|
#ifndef _DOCARY_HXX
|
|
|
|
#include <docary.hxx>
|
|
|
|
#endif
|
2004-05-18 13:06:14 +00:00
|
|
|
#ifndef _UNDO_HRC
|
|
|
|
#include <undo.hrc>
|
|
|
|
#endif
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
USHORT SwDoc::nUndoActions = UNDO_ACTION_COUNT; // anzahl von Undo-Action
|
|
|
|
|
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
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
void SwDoc::SetUndoNoResetModified()
|
|
|
|
{
|
|
|
|
nUndoSavePos = USHRT_MAX;
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::IsUndoNoResetModified() const
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2006-08-14 15:48:33 +00:00
|
|
|
return USHRT_MAX == nUndoSavePos;
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
void SwDoc::DoUndo(bool bUn)
|
|
|
|
{
|
|
|
|
mbUndo = bUn;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SwDoc::DoesUndo() const
|
|
|
|
{
|
|
|
|
return mbUndo;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwDoc::DoGroupUndo(bool bUn)
|
|
|
|
{
|
|
|
|
mbGroupUndo = bUn;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SwDoc::DoesGroupUndo() const
|
|
|
|
{
|
|
|
|
return mbGroupUndo;
|
|
|
|
}
|
|
|
|
|
|
|
|
sal_uInt16 SwDoc::GetUndoActionCount()
|
|
|
|
{
|
|
|
|
return nUndoActions;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwDoc::SetUndoActionCount( sal_uInt16 nNew )
|
|
|
|
{
|
|
|
|
nUndoActions = nNew;
|
|
|
|
}
|
|
|
|
|
|
|
|
const SwNodes* SwDoc::GetUndoNds() const
|
|
|
|
{
|
|
|
|
return &aUndoNodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SwDoc::AppendUndo( SwUndo* pUndo )
|
|
|
|
{
|
|
|
|
if( IDocumentRedlineAccess::REDLINE_NONE == pUndo->GetRedlineMode() )
|
2000-09-18 23:08:29 +00:00
|
|
|
pUndo->SetRedlineMode( GetRedlineMode() );
|
|
|
|
|
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() )
|
|
|
|
ClearRedo();
|
|
|
|
else
|
|
|
|
ASSERT( pUndos->Count() == nUndoPos || UNDO_END == pUndo->GetId(),
|
|
|
|
"Redo history not deleted!" );
|
|
|
|
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;
|
|
|
|
pUndoMsgWin->Set( pUndos->Count(), aUndoNodes.Count() );
|
|
|
|
#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
|
|
|
|
#ifndef PRODUCT
|
|
|
|
{
|
|
|
|
USHORT nId, nUndosCnt = 0, nSttEndCnt = 0;
|
|
|
|
for( USHORT nCnt = 0; nCnt < nUndoPos; ++nCnt )
|
|
|
|
{
|
|
|
|
if( UNDO_START == ( nId = (*pUndos)[ nCnt ]->GetId() ))
|
|
|
|
++nSttEndCnt;
|
|
|
|
else if( UNDO_END == nId )
|
|
|
|
--nSttEndCnt;
|
|
|
|
if( !nSttEndCnt )
|
|
|
|
++nUndosCnt;
|
|
|
|
}
|
|
|
|
ASSERT( nSttEndCnt == nUndoSttEnd, "Start-Ende Count ungleich" );
|
|
|
|
ASSERT( nUndosCnt == nUndoCnt, "Undo Count ungleich" );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if( SwDoc::nUndoActions < nUndoCnt )
|
|
|
|
// 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
|
|
|
|
DelUndoObj( nUndoCnt - SwDoc::nUndoActions );
|
2000-09-18 23:08:29 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
USHORT nUndosCnt = nUndoCnt;
|
|
|
|
// immer 1/10 loeschen bis der "Ausloeser" behoben ist
|
|
|
|
while( aUndoNodes.Count() && nEnde < aUndoNodes.Count() )
|
|
|
|
DelUndoObj( nUndosCnt / 10 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SwDoc::ClearRedo()
|
|
|
|
{
|
|
|
|
if( DoesUndo() && nUndoPos != pUndos->Count() )
|
|
|
|
{
|
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() )
|
|
|
|
nCnt -= ((SwUndoEnd*)pUndo)->GetSttOffset();
|
|
|
|
}
|
|
|
|
|
|
|
|
// loesche die Undo-Aktionen (immer von hinten !)
|
|
|
|
pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// loescht die gesamten UndoObjecte
|
|
|
|
void SwDoc::DelAllUndoObj()
|
|
|
|
{
|
|
|
|
ClearRedo();
|
|
|
|
|
|
|
|
DoUndo( FALSE );
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
DoUndo( TRUE );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// loescht alle UndoObjecte vom Anfang bis zum angegebenen Ende
|
|
|
|
BOOL SwDoc::DelUndoObj( USHORT nEnde )
|
|
|
|
{
|
|
|
|
if( !nEnde ) // sollte mal 0 uebergeben werden,
|
|
|
|
{
|
|
|
|
if( !pUndos->Count() )
|
|
|
|
return FALSE;
|
|
|
|
++nEnde; // dann korrigiere es auf 1
|
|
|
|
}
|
|
|
|
|
|
|
|
DoUndo( FALSE );
|
|
|
|
|
|
|
|
// pruefe erstmal, wo das Ende steht
|
|
|
|
USHORT nId = 0, nSttEndCnt = 0;
|
2003-12-01 16:23:31 +00:00
|
|
|
USHORT nCnt;
|
|
|
|
|
|
|
|
for( nCnt = 0; nEnde && 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 )
|
|
|
|
--nEnde, --nUndoCnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 )
|
|
|
|
nUndoSavePos -= nSttEndCnt;
|
|
|
|
|
|
|
|
while( nSttEndCnt )
|
|
|
|
pUndos->DeleteAndDestroy( --nSttEndCnt, 1 );
|
|
|
|
nUndoPos = pUndos->Count();
|
|
|
|
|
|
|
|
DoUndo( TRUE );
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************** UNDO ******************/
|
|
|
|
|
2007-05-25 12:01:29 +00:00
|
|
|
void SwDoc::setUndoNoModifiedPosition( SwUndoNoModifiedPosition nNew )
|
|
|
|
{
|
|
|
|
nUndoSavePos = nNew;
|
|
|
|
if( !pUndos->Count() || nUndoSavePos > pUndos->Count() - 1 )
|
|
|
|
nUndoSavePos = USHRT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
SwUndoNoModifiedPosition SwDoc::getUndoNoModifiedPosition() const
|
|
|
|
{
|
|
|
|
return nUndoSavePos;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::HasUndoId(sal_uInt16 nId) const
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
|
|
|
USHORT nSize = nUndoPos;
|
|
|
|
SwUndo * pUndo;
|
|
|
|
while( nSize-- )
|
|
|
|
if( ( pUndo = (*pUndos)[nSize])->GetId() == nId ||
|
|
|
|
( UNDO_START == pUndo->GetId() &&
|
|
|
|
((SwUndoStart*)pUndo)->GetUserId() == nId )
|
|
|
|
|| ( UNDO_END == pUndo->GetId() &&
|
|
|
|
((SwUndoEnd*)pUndo)->GetUserId() == nId ) )
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::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 ];
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
IDocumentRedlineAccess::RedlineMode_t eOld = GetRedlineMode();
|
2006-09-25 08:28:05 +00:00
|
|
|
IDocumentRedlineAccess::RedlineMode_t eTmpMode = (IDocumentRedlineAccess::RedlineMode_t)pUndo->GetRedlineMode();
|
2006-08-14 15:48:33 +00:00
|
|
|
if( (IDocumentRedlineAccess::REDLINE_SHOW_MASK & eTmpMode) != (IDocumentRedlineAccess::REDLINE_SHOW_MASK & eOld) &&
|
2000-09-18 23:08:29 +00:00
|
|
|
UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
|
|
|
|
SetRedlineMode( eTmpMode );
|
|
|
|
|
2006-09-25 08:28:05 +00:00
|
|
|
SetRedlineMode_intern((IDocumentRedlineAccess::RedlineMode_t)(eTmpMode | IDocumentRedlineAccess::REDLINE_IGNORE));
|
2000-09-18 23:08:29 +00:00
|
|
|
// Undo ausfuehren
|
|
|
|
|
|
|
|
// zum spaeteren ueberpruefen
|
|
|
|
USHORT nAktId = pUndo->GetId();
|
|
|
|
//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 );
|
|
|
|
|
|
|
|
SetRedlineMode( eOld );
|
|
|
|
|
|
|
|
// 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 )
|
|
|
|
SetModified(); // default: immer setzen, kann zurueck gesetzt werden
|
|
|
|
|
|
|
|
// ist die History leer und wurde nicht wegen Speichermangel
|
|
|
|
// verworfen, so kann das Dokument als unveraendert gelten
|
|
|
|
if( nUndoSavePos == nUndoPos )
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
USHORT SwDoc::StartUndo( USHORT nUndoId, const SwRewriter * pRewriter )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2006-08-14 15:48:33 +00:00
|
|
|
if( !mbUndo )
|
2000-09-18 23:08:29 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( !nUndoId )
|
|
|
|
nUndoId = UNDO_START;
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
SwUndoStart * pUndo = new SwUndoStart( nUndoId );
|
|
|
|
|
|
|
|
if (pRewriter)
|
|
|
|
pUndo->SetRewriter(*pRewriter);
|
|
|
|
|
|
|
|
AppendUndo(pUndo);
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
return nUndoId;
|
|
|
|
}
|
|
|
|
// schliesst Klammerung der nUndoId, nicht vom UI benutzt
|
|
|
|
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
USHORT SwDoc::EndUndo(USHORT nUndoId, const SwRewriter * 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-- )
|
2000-09-18 23:08:29 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( UNDO_START == nUndoId || !nUndoId )
|
|
|
|
nUndoId = UNDO_END;
|
|
|
|
|
|
|
|
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;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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() )
|
|
|
|
nCnt -= ((SwUndoEnd*)pUndo)->GetSttOffset();
|
|
|
|
|
|
|
|
pUndos->DeleteAndDestroy( nUndoPos, pUndos->Count() - nUndoPos );
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
// suche den Anfang dieser Klammerung
|
|
|
|
USHORT nId;
|
|
|
|
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
|
|
|
|
SwUndo* pUndo;
|
|
|
|
for( USHORT nCnt = 0; nCnt < pUndos->Count(); ++nCnt, ++nUndoCnt )
|
|
|
|
// Klammerung ueberspringen
|
|
|
|
if( UNDO_START == (pUndo = (*pUndos)[ nCnt ])->GetId() )
|
|
|
|
nCnt += ((SwUndoStart*)pUndo)->GetEndOffset();
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Klammerung um eine einzelne Action muss nicht sein!
|
|
|
|
// Aussnahme: es ist eine eigene ID definiert
|
|
|
|
if( 2 == pUndos->Count() - nSize &&
|
|
|
|
(UNDO_END == nUndoId || nUndoId == (*pUndos)[ nSize+1 ]->GetId() ))
|
|
|
|
{
|
|
|
|
pUndos->DeleteAndDestroy( nSize );
|
|
|
|
nUndoPos = pUndos->Count();
|
|
|
|
if( !--nUndoSttEnd )
|
|
|
|
{
|
|
|
|
++nUndoCnt;
|
|
|
|
if( SwDoc::nUndoActions < nUndoCnt )
|
|
|
|
// 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
|
|
|
|
DelUndoObj( nUndoCnt - SwDoc::nUndoActions );
|
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
|
|
|
|
while( aUndoNodes.Count() && nEnde < aUndoNodes.Count() )
|
|
|
|
DelUndoObj( nUndosCnt / 10 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nUndoId;
|
|
|
|
}
|
|
|
|
|
|
|
|
// setze die Klammerung am Start/End-Undo
|
|
|
|
nSize = pUndos->Count() - nSize;
|
|
|
|
((SwUndoStart*)pUndo)->SetEndOffset( nSize );
|
|
|
|
|
|
|
|
SwUndoEnd* pUndoEnd = new SwUndoEnd( nUndoId );
|
|
|
|
pUndoEnd->SetSttOffset( nSize );
|
|
|
|
|
|
|
|
// nur zum Testen der Start/End-Verpointerung vom Start/End Undo
|
|
|
|
#ifndef PRODUCT
|
|
|
|
{
|
2004-05-18 13:06:14 +00:00
|
|
|
USHORT nEndCnt = 1, nCnt = pUndos->Count(), nId;
|
|
|
|
while( nCnt )
|
2000-09-18 23:08:29 +00:00
|
|
|
{
|
2004-05-18 13:06:14 +00:00
|
|
|
if( UNDO_START == ( nId = (*pUndos)[ --nCnt ]->GetId()) )
|
|
|
|
{
|
|
|
|
if( !nEndCnt ) // falls mal ein Start ohne Ende vorhanden ist
|
|
|
|
continue;
|
|
|
|
--nEndCnt;
|
|
|
|
if( !nEndCnt ) // hier ist der Anfang
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( UNDO_END == nId )
|
|
|
|
++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 );
|
|
|
|
return nUndoId;
|
|
|
|
}
|
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
// liefert die Id der letzten Undofaehigen Aktion zurueck oder 0
|
|
|
|
// fuellt ggf. VARARR mit User-UndoIds
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
String SwDoc::GetUndoIdsStr( String* pStr, SwUndoIds *pUndoIds) const
|
|
|
|
{
|
|
|
|
String aTmpStr;
|
|
|
|
|
|
|
|
if (pStr != NULL)
|
|
|
|
{
|
|
|
|
GetUndoIds( pStr, pUndoIds);
|
|
|
|
aTmpStr = *pStr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
GetUndoIds( &aTmpStr, pUndoIds);
|
|
|
|
|
|
|
|
return aTmpStr;
|
|
|
|
}
|
|
|
|
|
2005-01-05 15:09:05 +00:00
|
|
|
/*-- 24.11.2004 16:11:21---------------------------------------------------
|
|
|
|
|
|
|
|
-----------------------------------------------------------------------*/
|
|
|
|
sal_Bool SwDoc::RestoreInvisibleContent()
|
|
|
|
{
|
|
|
|
sal_Bool bRet = sal_False;
|
|
|
|
if(nUndoPos > 0 )
|
|
|
|
{
|
|
|
|
SwUndo * pUndo = (*pUndos)[ nUndoPos - 1 ];
|
|
|
|
if( ( pUndo->GetId() == UNDO_END &&
|
|
|
|
static_cast<SwUndoEnd *>(pUndo)->GetUserId() == UIUNDO_DELETE_INVISIBLECNTNT) )
|
|
|
|
{
|
|
|
|
SwPaM aPam( GetNodes().GetEndOfPostIts() );
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
SwUndoIdAndName * lcl_GetUndoIdAndName(const SwUndos & rUndos, int nPos)
|
|
|
|
{
|
|
|
|
SwUndo * pUndo = rUndos[nPos];
|
|
|
|
USHORT nId = 0;
|
|
|
|
String sStr("??", RTL_TEXTENCODING_ASCII_US);
|
|
|
|
|
|
|
|
ASSERT(nPos >= 0 && nPos < rUndos.Count(), "nPos out of range");
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
SwUndo * pTmpUndo;
|
|
|
|
do
|
2004-05-18 13:06:14 +00:00
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
nTmpPos--;
|
|
|
|
pTmpUndo = rUndos[nTmpPos];
|
|
|
|
|
|
|
|
if (pTmpUndo->GetEffectiveId() > UNDO_END)
|
|
|
|
nSubstitute = nTmpPos;
|
|
|
|
}
|
|
|
|
while (nSubstitute < 0 && nTmpPos > nPos);
|
2004-05-18 13:06:14 +00:00
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (nSubstitute >= 0)
|
|
|
|
{
|
|
|
|
SwUndo * pSubUndo = rUndos[nSubstitute];
|
|
|
|
nId = pSubUndo->GetEffectiveId();
|
|
|
|
sStr = pSubUndo->GetComment();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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--;
|
|
|
|
pTmpUndo = rUndos[nTmpPos];
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
SwUndo * pSubUndo = rUndos[nSubstitute];
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
USHORT SwDoc::GetUndoIds( String* pStr, SwUndoIds *pUndoIds) const
|
|
|
|
{
|
|
|
|
int nTmpPos = nUndoPos - 1;
|
|
|
|
USHORT nId = 0;
|
|
|
|
|
|
|
|
while (nTmpPos >= 0)
|
|
|
|
{
|
|
|
|
SwUndo * pUndo = (*pUndos)[nTmpPos];
|
|
|
|
|
|
|
|
SwUndoIdAndName * pIdAndName = lcl_GetUndoIdAndName(*pUndos, nTmpPos);
|
|
|
|
|
|
|
|
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
|
|
|
|
2004-10-22 07:14:25 +00:00
|
|
|
if (pStr)
|
|
|
|
*pStr = *pIdAndName->GetUndoStr();
|
2001-04-09 06:23:08 +00:00
|
|
|
}
|
2004-10-22 07:14:25 +00:00
|
|
|
|
|
|
|
if (pUndoIds)
|
|
|
|
pUndoIds->Insert(pIdAndName, pUndoIds->Count());
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::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 ******************/
|
|
|
|
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::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++ ];
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
IDocumentRedlineAccess::RedlineMode_t eOld = GetRedlineMode();
|
2006-09-25 08:28:05 +00:00
|
|
|
IDocumentRedlineAccess::RedlineMode_t eTmpMode = (IDocumentRedlineAccess::RedlineMode_t)pUndo->GetRedlineMode();
|
2006-08-14 15:48:33 +00:00
|
|
|
if( (IDocumentRedlineAccess::REDLINE_SHOW_MASK & eTmpMode) != (IDocumentRedlineAccess::REDLINE_SHOW_MASK & eOld) &&
|
2000-09-18 23:08:29 +00:00
|
|
|
UNDO_START != pUndo->GetId() && UNDO_END != pUndo->GetId() )
|
|
|
|
SetRedlineMode( eTmpMode );
|
2006-09-25 08:28:05 +00:00
|
|
|
SetRedlineMode_intern( (IDocumentRedlineAccess::RedlineMode_t)(eTmpMode | IDocumentRedlineAccess::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 );
|
|
|
|
|
|
|
|
SetRedlineMode( eOld );
|
|
|
|
|
|
|
|
// 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 )
|
|
|
|
ResetModified();
|
|
|
|
else
|
|
|
|
SetModified();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// liefert die Id der letzten Redofaehigen Aktion zurueck oder 0
|
|
|
|
// fuellt ggf. VARARR mit User-RedoIds
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
String SwDoc::GetRedoIdsStr( String* pStr, SwUndoIds *pRedoIds ) const
|
|
|
|
{
|
|
|
|
String aTmpStr;
|
|
|
|
|
|
|
|
if (pStr != NULL)
|
|
|
|
{
|
2005-02-22 09:03:09 +00:00
|
|
|
GetRedoIds( pStr, pRedoIds );
|
2004-05-18 13:06:14 +00:00
|
|
|
aTmpStr = *pStr;
|
|
|
|
}
|
|
|
|
else
|
2005-02-22 09:03:09 +00:00
|
|
|
GetRedoIds( &aTmpStr, pRedoIds );
|
2004-05-18 13:06:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
return aTmpStr;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
USHORT SwDoc::GetRedoIds( String* pStr, SwUndoIds *pRedoIds ) const
|
|
|
|
{
|
2004-10-22 07:14:25 +00:00
|
|
|
int nTmpPos = nUndoPos;
|
|
|
|
USHORT nId = 0;
|
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)
|
|
|
|
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 ******************/
|
|
|
|
|
|
|
|
|
2006-08-14 15:48:33 +00:00
|
|
|
bool SwDoc::Repeat( SwUndoIter& rUndoIter, sal_uInt16 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() )
|
|
|
|
nSize -= ((SwUndoEnd*)pUndo)->GetSttOffset();
|
|
|
|
|
|
|
|
USHORT nEndCnt = nUndoPos;
|
|
|
|
BOOL bOneUndo = nSize + 1 == nUndoPos;
|
|
|
|
|
|
|
|
SwPaM* pTmpCrsr = rUndoIter.pAktPam;
|
2005-02-21 15:06:16 +00:00
|
|
|
USHORT nId = 0;
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// liefert die Id der letzten Repeatfaehigen Aktion zurueck oder 0
|
|
|
|
// fuellt ggf. VARARR mit User-RedoIds
|
|
|
|
|
2004-05-18 13:06:14 +00:00
|
|
|
String SwDoc::GetRepeatIdsStr(String* pStr, SwUndoIds *pRepeatIds) const
|
|
|
|
{
|
|
|
|
String aTmpStr;
|
|
|
|
USHORT nId;
|
|
|
|
|
|
|
|
if ( pStr != NULL)
|
|
|
|
{
|
|
|
|
nId = GetRepeatIds(pStr, pRepeatIds);
|
|
|
|
aTmpStr = *pStr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
nId = GetRepeatIds(&aTmpStr, pRepeatIds);
|
|
|
|
|
|
|
|
if (nId <= UNDO_END)
|
|
|
|
return String();
|
|
|
|
|
|
|
|
return aTmpStr;
|
|
|
|
}
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
USHORT SwDoc::GetRepeatIds(String* pStr, SwUndoIds *pRepeatIds) const
|
|
|
|
{
|
|
|
|
USHORT nRepeatId = GetUndoIds( pStr, pRepeatIds );
|
|
|
|
if( REPEAT_START <= nRepeatId && REPEAT_END > nRepeatId )
|
|
|
|
return nRepeatId;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SwUndo* SwDoc::RemoveLastUndo( USHORT nUndoId )
|
|
|
|
{
|
2001-09-27 12:44:28 +00:00
|
|
|
SwUndo* pUndo = (*pUndos)[ nUndoPos - 1 ];
|
2000-09-18 23:08:29 +00:00
|
|
|
if( nUndoId == pUndo->GetId() && nUndoPos == pUndos->Count() )
|
|
|
|
{
|
|
|
|
if( !nUndoSttEnd )
|
|
|
|
--nUndoCnt;
|
|
|
|
--nUndoPos;
|
|
|
|
pUndos->Remove( nUndoPos, 1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pUndo = 0;
|
|
|
|
ASSERT( !this, "falsches Undo-Object" );
|
|
|
|
}
|
|
|
|
return pUndo;
|
|
|
|
}
|
|
|
|
|
2001-04-09 06:23:08 +00:00
|
|
|
SwUndoIdAndName::SwUndoIdAndName( USHORT nId, const String* pStr )
|
|
|
|
: nUndoId( nId ), pUndoStr( pStr ? new String( *pStr ) : 0 )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SwUndoIdAndName::~SwUndoIdAndName()
|
|
|
|
{
|
|
|
|
delete pUndoStr;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:08:29 +00:00
|
|
|
|
|
|
|
|