xref: /AOO41X/main/sc/source/core/tool/chgtrack.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <tools/debug.hxx>
29cdf0e10cSrcweir #include <tools/shl.hxx>		// SHL_CALC
30cdf0e10cSrcweir #include <tools/stack.hxx>
31cdf0e10cSrcweir #include <tools/rtti.hxx>
32cdf0e10cSrcweir #include <svl/zforlist.hxx>
33cdf0e10cSrcweir #include <svl/itemset.hxx>
34cdf0e10cSrcweir #include <svl/isethint.hxx>
35cdf0e10cSrcweir #include <svl/itempool.hxx>
36cdf0e10cSrcweir #include <sfx2/app.hxx>
37cdf0e10cSrcweir #include <unotools/useroptions.hxx>
38cdf0e10cSrcweir #include <sfx2/sfxsids.hrc>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "cell.hxx"
41cdf0e10cSrcweir #include "document.hxx"
42cdf0e10cSrcweir #include "dociter.hxx"
43cdf0e10cSrcweir #include "global.hxx"
44cdf0e10cSrcweir #include "rechead.hxx"
45cdf0e10cSrcweir #include "scerrors.hxx"
46cdf0e10cSrcweir #include "scmod.hxx"   		// SC_MOD
47cdf0e10cSrcweir #include "inputopt.hxx" 	// GetExpandRefs
48cdf0e10cSrcweir #include "patattr.hxx"
49cdf0e10cSrcweir #include "hints.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir #include "globstr.hrc"
52cdf0e10cSrcweir 
53cdf0e10cSrcweir #include <stack>
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #define SC_CHGTRACK_CXX
56cdf0e10cSrcweir #include "chgtrack.hxx"
57cdf0e10cSrcweir 
58cdf0e10cSrcweir DECLARE_STACK( ScChangeActionStack, ScChangeAction* )
59cdf0e10cSrcweir 
60cdf0e10cSrcweir const sal_uInt16 nMemPoolChangeActionCellListEntry = (0x2000 - 64) / sizeof(ScChangeActionCellListEntry);
61cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionCellListEntry, nMemPoolChangeActionCellListEntry, nMemPoolChangeActionCellListEntry )
62cdf0e10cSrcweir 
63cdf0e10cSrcweir const sal_uInt16 nMemPoolChangeActionLinkEntry = (0x8000 - 64) / sizeof(ScChangeActionLinkEntry);
IMPL_FIXEDMEMPOOL_NEWDEL(ScChangeActionLinkEntry,nMemPoolChangeActionLinkEntry,nMemPoolChangeActionLinkEntry)64cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionLinkEntry, nMemPoolChangeActionLinkEntry, nMemPoolChangeActionLinkEntry )
65cdf0e10cSrcweir 
66cdf0e10cSrcweir // loaded MSB > eigenes => inkompatibel
67cdf0e10cSrcweir #define SC_CHGTRACK_FILEFORMAT_FIRST	0x0001
68cdf0e10cSrcweir #define SC_CHGTRACK_FILEFORMAT	0x0001
69cdf0e10cSrcweir 
70cdf0e10cSrcweir // --- ScChangeActionLinkEntry ---------------------------------------------
71cdf0e10cSrcweir 
72cdf0e10cSrcweir #if DEBUG_CHANGETRACK
73cdf0e10cSrcweir String ScChangeActionLinkEntry::ToString() const
74cdf0e10cSrcweir {
75cdf0e10cSrcweir     String aReturn;
76cdf0e10cSrcweir     if ( pAction )
77cdf0e10cSrcweir     {
78cdf0e10cSrcweir         aReturn = String::CreateFromInt64( static_cast< sal_Int64 >( pAction->GetActionNumber() ) );
79cdf0e10cSrcweir     }
80cdf0e10cSrcweir     else if ( pLink && pLink->pAction )
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         aReturn = String::CreateFromAscii( "*" );
83cdf0e10cSrcweir         aReturn += String::CreateFromInt64( static_cast< sal_Int64 >( pLink->pAction->GetActionNumber() ) );
84cdf0e10cSrcweir     }
85cdf0e10cSrcweir     else
86cdf0e10cSrcweir     {
87cdf0e10cSrcweir         aReturn = String::CreateFromAscii( "-" );
88cdf0e10cSrcweir     }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir     return aReturn;
91cdf0e10cSrcweir }
92cdf0e10cSrcweir #endif // DEBUG_CHANGETRACK
93cdf0e10cSrcweir 
94cdf0e10cSrcweir // --- ScChangeAction ------------------------------------------------------
95cdf0e10cSrcweir 
ScChangeAction(ScChangeActionType eTypeP,const ScRange & rRange)96cdf0e10cSrcweir ScChangeAction::ScChangeAction( ScChangeActionType eTypeP, const ScRange& rRange )
97cdf0e10cSrcweir 		:
98cdf0e10cSrcweir 		aBigRange( rRange ),
99cdf0e10cSrcweir 		pNext( NULL ),
100cdf0e10cSrcweir 		pPrev( NULL ),
101cdf0e10cSrcweir 		pLinkAny( NULL ),
102cdf0e10cSrcweir 		pLinkDeletedIn( NULL ),
103cdf0e10cSrcweir 		pLinkDeleted( NULL ),
104cdf0e10cSrcweir 		pLinkDependent( NULL ),
105cdf0e10cSrcweir 		nAction( 0 ),
106cdf0e10cSrcweir 		nRejectAction( 0 ),
107cdf0e10cSrcweir 		eType( eTypeP ),
108cdf0e10cSrcweir 		eState( SC_CAS_VIRGIN )
109cdf0e10cSrcweir {
110cdf0e10cSrcweir 	aDateTime.ConvertToUTC();
111cdf0e10cSrcweir }
112cdf0e10cSrcweir 
ScChangeAction(ScChangeActionType eTypeP,const ScBigRange & rRange,const sal_uLong nTempAction,const sal_uLong nTempRejectAction,const ScChangeActionState eTempState,const DateTime & aTempDateTime,const String & aTempUser,const String & aTempComment)113cdf0e10cSrcweir ScChangeAction::ScChangeAction( ScChangeActionType eTypeP, const ScBigRange& rRange,
114cdf0e10cSrcweir 						const sal_uLong nTempAction, const sal_uLong nTempRejectAction,
115cdf0e10cSrcweir 						const ScChangeActionState eTempState, const DateTime& aTempDateTime,
116cdf0e10cSrcweir 						const String& aTempUser,  const String& aTempComment)
117cdf0e10cSrcweir 		:
118cdf0e10cSrcweir 		aBigRange( rRange ),
119cdf0e10cSrcweir 		aDateTime( aTempDateTime ),
120cdf0e10cSrcweir 		aUser( aTempUser ),
121cdf0e10cSrcweir 		aComment( aTempComment ),
122cdf0e10cSrcweir 		pNext( NULL ),
123cdf0e10cSrcweir 		pPrev( NULL ),
124cdf0e10cSrcweir 		pLinkAny( NULL ),
125cdf0e10cSrcweir 		pLinkDeletedIn( NULL ),
126cdf0e10cSrcweir 		pLinkDeleted( NULL ),
127cdf0e10cSrcweir 		pLinkDependent( NULL ),
128cdf0e10cSrcweir 		nAction( nTempAction ),
129cdf0e10cSrcweir 		nRejectAction( nTempRejectAction ),
130cdf0e10cSrcweir 		eType( eTypeP ),
131cdf0e10cSrcweir 		eState( eTempState )
132cdf0e10cSrcweir {
133cdf0e10cSrcweir }
134cdf0e10cSrcweir 
ScChangeAction(ScChangeActionType eTypeP,const ScBigRange & rRange,const sal_uLong nTempAction)135cdf0e10cSrcweir ScChangeAction::ScChangeAction( ScChangeActionType eTypeP, const ScBigRange& rRange,
136cdf0e10cSrcweir 						const sal_uLong nTempAction)
137cdf0e10cSrcweir 		:
138cdf0e10cSrcweir 		aBigRange( rRange ),
139cdf0e10cSrcweir 		pNext( NULL ),
140cdf0e10cSrcweir 		pPrev( NULL ),
141cdf0e10cSrcweir 		pLinkAny( NULL ),
142cdf0e10cSrcweir 		pLinkDeletedIn( NULL ),
143cdf0e10cSrcweir 		pLinkDeleted( NULL ),
144cdf0e10cSrcweir 		pLinkDependent( NULL ),
145cdf0e10cSrcweir 		nAction( nTempAction ),
146cdf0e10cSrcweir 		nRejectAction( 0 ),
147cdf0e10cSrcweir 		eType( eTypeP ),
148cdf0e10cSrcweir 		eState( SC_CAS_VIRGIN )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir 	aDateTime.ConvertToUTC();
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir 
~ScChangeAction()154cdf0e10cSrcweir ScChangeAction::~ScChangeAction()
155cdf0e10cSrcweir {
156cdf0e10cSrcweir 	RemoveAllLinks();
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir 
IsVisible() const160cdf0e10cSrcweir sal_Bool ScChangeAction::IsVisible() const
161cdf0e10cSrcweir {
162cdf0e10cSrcweir 	//! sequence order of execution is significant
163cdf0e10cSrcweir 	if ( IsRejected() || GetType() == SC_CAT_DELETE_TABS || IsDeletedIn() )
164cdf0e10cSrcweir 		return sal_False;
165cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
166cdf0e10cSrcweir 		return ((ScChangeActionContent*)this)->IsTopContent();
167cdf0e10cSrcweir 	return sal_True;
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
170cdf0e10cSrcweir 
IsTouchable() const171cdf0e10cSrcweir sal_Bool ScChangeAction::IsTouchable() const
172cdf0e10cSrcweir {
173cdf0e10cSrcweir 	//! sequence order of execution is significant
174cdf0e10cSrcweir 	if ( IsRejected() || GetType() == SC_CAT_REJECT || IsDeletedIn() )
175cdf0e10cSrcweir 		return sal_False;
176cdf0e10cSrcweir 	// content may reject and be touchable if on top
177cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
178cdf0e10cSrcweir 		return ((ScChangeActionContent*)this)->IsTopContent();
179cdf0e10cSrcweir 	if ( IsRejecting() )
180cdf0e10cSrcweir 		return sal_False;
181cdf0e10cSrcweir 	return sal_True;
182cdf0e10cSrcweir }
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 
IsClickable() const185cdf0e10cSrcweir sal_Bool ScChangeAction::IsClickable() const
186cdf0e10cSrcweir {
187cdf0e10cSrcweir 	//! sequence order of execution is significant
188cdf0e10cSrcweir 	if ( !IsVirgin() )
189cdf0e10cSrcweir 		return sal_False;
190cdf0e10cSrcweir 	if ( IsDeletedIn() )
191cdf0e10cSrcweir 		return sal_False;
192cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
193cdf0e10cSrcweir 	{
194cdf0e10cSrcweir 		ScChangeActionContentCellType eCCT =
195cdf0e10cSrcweir 			ScChangeActionContent::GetContentCellType(
196cdf0e10cSrcweir 			((ScChangeActionContent*)this)->GetNewCell() );
197cdf0e10cSrcweir 		if ( eCCT == SC_CACCT_MATREF )
198cdf0e10cSrcweir 			return sal_False;
199cdf0e10cSrcweir 		if ( eCCT == SC_CACCT_MATORG )
200cdf0e10cSrcweir 		{	// no Accept-Select if one of the references is in a deleted col/row
201cdf0e10cSrcweir 			const ScChangeActionLinkEntry* pL =
202cdf0e10cSrcweir 				((ScChangeActionContent*)this)->GetFirstDependentEntry();
203cdf0e10cSrcweir 			while ( pL )
204cdf0e10cSrcweir 			{
205cdf0e10cSrcweir 				ScChangeAction* p = (ScChangeAction*) pL->GetAction();
206cdf0e10cSrcweir 				if ( p && p->IsDeletedIn() )
207cdf0e10cSrcweir 					return sal_False;
208cdf0e10cSrcweir 				pL = pL->GetNext();
209cdf0e10cSrcweir 			}
210cdf0e10cSrcweir 		}
211cdf0e10cSrcweir 		return sal_True;	// for Select() a content doesn't have to be touchable
212cdf0e10cSrcweir 	}
213cdf0e10cSrcweir 	return IsTouchable();	// Accept()/Reject() only on touchables
214cdf0e10cSrcweir }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 
IsRejectable() const217cdf0e10cSrcweir sal_Bool ScChangeAction::IsRejectable() const
218cdf0e10cSrcweir {
219cdf0e10cSrcweir 	//! sequence order of execution is significant
220cdf0e10cSrcweir 	if ( !IsClickable() )
221cdf0e10cSrcweir 		return sal_False;
222cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
223cdf0e10cSrcweir 	{
224cdf0e10cSrcweir 		if ( ((ScChangeActionContent*)this)->IsOldMatrixReference() )
225cdf0e10cSrcweir 			return sal_False;
226cdf0e10cSrcweir 		ScChangeActionContent* pNextContent =
227cdf0e10cSrcweir 			((ScChangeActionContent*)this)->GetNextContent();
228cdf0e10cSrcweir 		if ( pNextContent == NULL )
229cdf0e10cSrcweir 			return sal_True;		// *this is TopContent
230cdf0e10cSrcweir 		return pNextContent->IsRejected();		// *this is next rejectable
231cdf0e10cSrcweir 	}
232cdf0e10cSrcweir 	return IsTouchable();
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 
IsInternalRejectable() const236cdf0e10cSrcweir sal_Bool ScChangeAction::IsInternalRejectable() const
237cdf0e10cSrcweir {
238cdf0e10cSrcweir 	//! sequence order of execution is significant
239cdf0e10cSrcweir 	if ( !IsVirgin() )
240cdf0e10cSrcweir 		return sal_False;
241cdf0e10cSrcweir 	if ( IsDeletedIn() )
242cdf0e10cSrcweir 		return sal_False;
243cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
244cdf0e10cSrcweir 	{
245cdf0e10cSrcweir 		ScChangeActionContent* pNextContent =
246cdf0e10cSrcweir 			((ScChangeActionContent*)this)->GetNextContent();
247cdf0e10cSrcweir 		if ( pNextContent == NULL )
248cdf0e10cSrcweir 			return sal_True;		// *this is TopContent
249cdf0e10cSrcweir 		return pNextContent->IsRejected();		// *this is next rejectable
250cdf0e10cSrcweir 	}
251cdf0e10cSrcweir 	return IsTouchable();
252cdf0e10cSrcweir }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 
IsDialogRoot() const255cdf0e10cSrcweir sal_Bool ScChangeAction::IsDialogRoot() const
256cdf0e10cSrcweir {
257cdf0e10cSrcweir 	return IsInternalRejectable();		// only rejectables in root
258cdf0e10cSrcweir }
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 
IsDialogParent() const261cdf0e10cSrcweir sal_Bool ScChangeAction::IsDialogParent() const
262cdf0e10cSrcweir {
263cdf0e10cSrcweir 	//! sequence order of execution is significant
264cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
265cdf0e10cSrcweir 	{
266cdf0e10cSrcweir 		if ( !IsDialogRoot() )
267cdf0e10cSrcweir 			return sal_False;
268cdf0e10cSrcweir 		if ( ((ScChangeActionContent*)this)->IsMatrixOrigin() && HasDependent() )
269cdf0e10cSrcweir 			return sal_True;
270cdf0e10cSrcweir 		ScChangeActionContent* pPrevContent =
271cdf0e10cSrcweir 			((ScChangeActionContent*)this)->GetPrevContent();
272cdf0e10cSrcweir 		return pPrevContent && pPrevContent->IsVirgin();
273cdf0e10cSrcweir 	}
274cdf0e10cSrcweir 	if ( HasDependent() )
275cdf0e10cSrcweir 		return IsDeleteType() ? sal_True : !IsDeletedIn();
276cdf0e10cSrcweir 	if ( HasDeleted() )
277cdf0e10cSrcweir 	{
278cdf0e10cSrcweir 		if ( IsDeleteType() )
279cdf0e10cSrcweir 		{
280cdf0e10cSrcweir 			if ( IsDialogRoot() )
281cdf0e10cSrcweir 				return sal_True;
282cdf0e10cSrcweir 			ScChangeActionLinkEntry* pL = pLinkDeleted;
283cdf0e10cSrcweir 			while ( pL )
284cdf0e10cSrcweir 			{
285cdf0e10cSrcweir 				ScChangeAction* p = pL->GetAction();
286cdf0e10cSrcweir 				if ( p && p->GetType() != eType )
287cdf0e10cSrcweir 					return sal_True;
288cdf0e10cSrcweir 				pL = pL->GetNext();
289cdf0e10cSrcweir 			}
290cdf0e10cSrcweir 		}
291cdf0e10cSrcweir 		else
292cdf0e10cSrcweir 			return sal_True;
293cdf0e10cSrcweir 	}
294cdf0e10cSrcweir 	return sal_False;
295cdf0e10cSrcweir }
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 
IsMasterDelete() const298cdf0e10cSrcweir sal_Bool ScChangeAction::IsMasterDelete() const
299cdf0e10cSrcweir {
300cdf0e10cSrcweir 	if ( !IsDeleteType() )
301cdf0e10cSrcweir 		return sal_False;
302cdf0e10cSrcweir 	ScChangeActionDel* pDel = (ScChangeActionDel*) this;
303cdf0e10cSrcweir 	return pDel->IsMultiDelete() && (pDel->IsTopDelete() || pDel->IsRejectable());
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 
RemoveAllLinks()307cdf0e10cSrcweir void ScChangeAction::RemoveAllLinks()
308cdf0e10cSrcweir {
309cdf0e10cSrcweir 	RemoveAllAnyLinks();
310cdf0e10cSrcweir 	RemoveAllDeletedIn();
311cdf0e10cSrcweir 	RemoveAllDeleted();
312cdf0e10cSrcweir 	RemoveAllDependent();
313cdf0e10cSrcweir }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir 
RemoveAllAnyLinks()316cdf0e10cSrcweir void ScChangeAction::RemoveAllAnyLinks()
317cdf0e10cSrcweir {
318cdf0e10cSrcweir 	while ( pLinkAny )
319cdf0e10cSrcweir 		delete pLinkAny;		// rueckt sich selbst hoch
320cdf0e10cSrcweir }
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 
RemoveDeletedIn(const ScChangeAction * p)323cdf0e10cSrcweir sal_Bool ScChangeAction::RemoveDeletedIn( const ScChangeAction* p )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir 	sal_Bool bRemoved = sal_False;
326cdf0e10cSrcweir 	ScChangeActionLinkEntry* pL = GetDeletedIn();
327cdf0e10cSrcweir 	while ( pL )
328cdf0e10cSrcweir 	{
329cdf0e10cSrcweir 		ScChangeActionLinkEntry* pNextLink = pL->GetNext();
330cdf0e10cSrcweir 		if ( pL->GetAction() == p )
331cdf0e10cSrcweir 		{
332cdf0e10cSrcweir 			delete pL;
333cdf0e10cSrcweir 			bRemoved = sal_True;
334cdf0e10cSrcweir 		}
335cdf0e10cSrcweir 		pL = pNextLink;
336cdf0e10cSrcweir 	}
337cdf0e10cSrcweir 	return bRemoved;
338cdf0e10cSrcweir }
339cdf0e10cSrcweir 
340cdf0e10cSrcweir 
IsDeletedIn(const ScChangeAction * p) const341cdf0e10cSrcweir sal_Bool ScChangeAction::IsDeletedIn( const ScChangeAction* p ) const
342cdf0e10cSrcweir {
343cdf0e10cSrcweir 	ScChangeActionLinkEntry* pL = GetDeletedIn();
344cdf0e10cSrcweir 	while ( pL )
345cdf0e10cSrcweir 	{
346cdf0e10cSrcweir 		if ( pL->GetAction() == p )
347cdf0e10cSrcweir 			return sal_True;
348cdf0e10cSrcweir 		pL = pL->GetNext();
349cdf0e10cSrcweir 	}
350cdf0e10cSrcweir 	return sal_False;
351cdf0e10cSrcweir }
352cdf0e10cSrcweir 
353cdf0e10cSrcweir 
RemoveAllDeletedIn()354cdf0e10cSrcweir void ScChangeAction::RemoveAllDeletedIn()
355cdf0e10cSrcweir {
356cdf0e10cSrcweir 	//! nicht vom evtl. TopContent sondern wirklich dieser
357cdf0e10cSrcweir 	while ( pLinkDeletedIn )
358cdf0e10cSrcweir 		delete pLinkDeletedIn;		// rueckt sich selbst hoch
359cdf0e10cSrcweir }
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 
IsDeletedInDelType(ScChangeActionType eDelType) const362cdf0e10cSrcweir sal_Bool ScChangeAction::IsDeletedInDelType( ScChangeActionType eDelType ) const
363cdf0e10cSrcweir {
364cdf0e10cSrcweir 	ScChangeAction* p;
365cdf0e10cSrcweir 	ScChangeActionLinkEntry* pL = GetDeletedIn();
366cdf0e10cSrcweir 	if ( pL )
367cdf0e10cSrcweir 	{
368cdf0e10cSrcweir 		// InsertType fuer MergePrepare/MergeOwn
369cdf0e10cSrcweir 		ScChangeActionType eInsType;
370cdf0e10cSrcweir 		switch ( eDelType )
371cdf0e10cSrcweir 		{
372cdf0e10cSrcweir 			case SC_CAT_DELETE_COLS :
373cdf0e10cSrcweir 				eInsType = SC_CAT_INSERT_COLS;
374cdf0e10cSrcweir 			break;
375cdf0e10cSrcweir 			case SC_CAT_DELETE_ROWS :
376cdf0e10cSrcweir 				eInsType = SC_CAT_INSERT_ROWS;
377cdf0e10cSrcweir 			break;
378cdf0e10cSrcweir 			case SC_CAT_DELETE_TABS :
379cdf0e10cSrcweir 				eInsType = SC_CAT_INSERT_TABS;
380cdf0e10cSrcweir 			break;
381cdf0e10cSrcweir 			default:
382cdf0e10cSrcweir 				eInsType = SC_CAT_NONE;
383cdf0e10cSrcweir 		}
384cdf0e10cSrcweir 		while ( pL )
385cdf0e10cSrcweir 		{
386cdf0e10cSrcweir             if ( (p = pL->GetAction()) != NULL &&
387cdf0e10cSrcweir 					(p->GetType() == eDelType || p->GetType() == eInsType) )
388cdf0e10cSrcweir 				return sal_True;
389cdf0e10cSrcweir 			pL = pL->GetNext();
390cdf0e10cSrcweir 		}
391cdf0e10cSrcweir 	}
392cdf0e10cSrcweir 	return sal_False;
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
395cdf0e10cSrcweir 
SetDeletedIn(ScChangeAction * p)396cdf0e10cSrcweir void ScChangeAction::SetDeletedIn( ScChangeAction* p )
397cdf0e10cSrcweir {
398cdf0e10cSrcweir 	ScChangeActionLinkEntry* pLink1 = AddDeletedIn( p );
399cdf0e10cSrcweir 	ScChangeActionLinkEntry* pLink2;
400cdf0e10cSrcweir 	if ( GetType() == SC_CAT_CONTENT )
401cdf0e10cSrcweir 		pLink2 = p->AddDeleted( ((ScChangeActionContent*)this)->GetTopContent() );
402cdf0e10cSrcweir 	else
403cdf0e10cSrcweir 		pLink2 = p->AddDeleted( this );
404cdf0e10cSrcweir 	pLink1->SetLink( pLink2 );
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 
RemoveAllDeleted()408cdf0e10cSrcweir void ScChangeAction::RemoveAllDeleted()
409cdf0e10cSrcweir {
410cdf0e10cSrcweir 	while ( pLinkDeleted )
411cdf0e10cSrcweir 		delete pLinkDeleted;		// rueckt sich selbst hoch
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir 
RemoveAllDependent()415cdf0e10cSrcweir void ScChangeAction::RemoveAllDependent()
416cdf0e10cSrcweir {
417cdf0e10cSrcweir 	while ( pLinkDependent )
418cdf0e10cSrcweir 		delete pLinkDependent;		// rueckt sich selbst hoch
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir 
GetDateTime() const422cdf0e10cSrcweir DateTime ScChangeAction::GetDateTime() const
423cdf0e10cSrcweir {
424cdf0e10cSrcweir 	DateTime aDT( aDateTime );
425cdf0e10cSrcweir 	aDT.ConvertToLocalTime();
426cdf0e10cSrcweir 	return aDT;
427cdf0e10cSrcweir }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 
UpdateReference(const ScChangeTrack *,UpdateRefMode eMode,const ScBigRange & rRange,sal_Int32 nDx,sal_Int32 nDy,sal_Int32 nDz)430cdf0e10cSrcweir void ScChangeAction::UpdateReference( const ScChangeTrack* /* pTrack */,
431cdf0e10cSrcweir 		UpdateRefMode eMode, const ScBigRange& rRange,
432cdf0e10cSrcweir 		sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz )
433cdf0e10cSrcweir {
434cdf0e10cSrcweir 	ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, GetBigRange() );
435cdf0e10cSrcweir }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir 
GetDescription(String & rStr,ScDocument *,sal_Bool,bool bWarning) const438cdf0e10cSrcweir void ScChangeAction::GetDescription( String& rStr, ScDocument* /* pDoc */,
439cdf0e10cSrcweir         sal_Bool /* bSplitRange */, bool bWarning ) const
440cdf0e10cSrcweir {
441cdf0e10cSrcweir     if ( IsRejecting() && bWarning )
442cdf0e10cSrcweir     {
443cdf0e10cSrcweir         // #112261# Add comment if rejection may have resulted in references
444cdf0e10cSrcweir         // not properly restored in formulas. See specification at
445cdf0e10cSrcweir         // http://specs.openoffice.org/calc/ease-of-use/redlining_comment.sxw
446cdf0e10cSrcweir         if (GetType() == SC_CAT_MOVE)
447cdf0e10cSrcweir         {
448cdf0e10cSrcweir             rStr += ScGlobal::GetRscString(
449cdf0e10cSrcweir                     STR_CHANGED_MOVE_REJECTION_WARNING);
450cdf0e10cSrcweir             rStr += ' ';
451cdf0e10cSrcweir         }
452cdf0e10cSrcweir         else if (IsInsertType())
453cdf0e10cSrcweir         {
454cdf0e10cSrcweir             rStr += ScGlobal::GetRscString(
455cdf0e10cSrcweir                     STR_CHANGED_DELETE_REJECTION_WARNING);
456cdf0e10cSrcweir             rStr += ' ';
457cdf0e10cSrcweir         }
458cdf0e10cSrcweir         else
459cdf0e10cSrcweir         {
460cdf0e10cSrcweir             const ScChangeTrack* pCT = GetChangeTrack();
461cdf0e10cSrcweir             if (pCT)
462cdf0e10cSrcweir             {
463cdf0e10cSrcweir                 ScChangeAction* pReject = pCT->GetActionOrGenerated(
464cdf0e10cSrcweir                         GetRejectAction());
465cdf0e10cSrcweir                 if (pReject)
466cdf0e10cSrcweir                 {
467cdf0e10cSrcweir                     if (pReject->GetType() == SC_CAT_MOVE)
468cdf0e10cSrcweir                     {
469cdf0e10cSrcweir                         rStr += ScGlobal::GetRscString(
470cdf0e10cSrcweir                                 STR_CHANGED_MOVE_REJECTION_WARNING);
471cdf0e10cSrcweir                         rStr += ' ';
472cdf0e10cSrcweir                     }
473cdf0e10cSrcweir                     else if (pReject->IsDeleteType())
474cdf0e10cSrcweir                     {
475cdf0e10cSrcweir                         rStr += ScGlobal::GetRscString(
476cdf0e10cSrcweir                                 STR_CHANGED_DELETE_REJECTION_WARNING);
477cdf0e10cSrcweir                         rStr += ' ';
478cdf0e10cSrcweir                     }
479cdf0e10cSrcweir                     else if (pReject->HasDependent())
480cdf0e10cSrcweir                     {
481cdf0e10cSrcweir                         ScChangeActionTable aTable;
482cdf0e10cSrcweir                         pCT->GetDependents( pReject, aTable, sal_False, sal_True );
483cdf0e10cSrcweir                         for ( const ScChangeAction* p = aTable.First(); p;
484cdf0e10cSrcweir                                 p = aTable.Next() )
485cdf0e10cSrcweir                         {
486cdf0e10cSrcweir                             if (p->GetType() == SC_CAT_MOVE)
487cdf0e10cSrcweir                             {
488cdf0e10cSrcweir                                 rStr += ScGlobal::GetRscString(
489cdf0e10cSrcweir                                         STR_CHANGED_MOVE_REJECTION_WARNING);
490cdf0e10cSrcweir                                 rStr += ' ';
491cdf0e10cSrcweir                                 break;  // for
492cdf0e10cSrcweir                             }
493cdf0e10cSrcweir                             else if (pReject->IsDeleteType())
494cdf0e10cSrcweir                             {
495cdf0e10cSrcweir                                 rStr += ScGlobal::GetRscString(
496cdf0e10cSrcweir                                         STR_CHANGED_DELETE_REJECTION_WARNING);
497cdf0e10cSrcweir                                 rStr += ' ';
498cdf0e10cSrcweir                                 break;  // for
499cdf0e10cSrcweir                             }
500cdf0e10cSrcweir                         }
501cdf0e10cSrcweir                     }
502cdf0e10cSrcweir                 }
503cdf0e10cSrcweir             }
504cdf0e10cSrcweir         }
505cdf0e10cSrcweir     }
506cdf0e10cSrcweir }
507cdf0e10cSrcweir 
508cdf0e10cSrcweir 
GetRefString(const ScBigRange & rRange,ScDocument * pDoc,sal_Bool bFlag3D) const509cdf0e10cSrcweir String ScChangeAction::GetRefString( const ScBigRange& rRange,
510cdf0e10cSrcweir 		ScDocument* pDoc, sal_Bool bFlag3D ) const
511cdf0e10cSrcweir {
512cdf0e10cSrcweir 	String aStr;
513cdf0e10cSrcweir 	sal_uInt16 nFlags = ( rRange.IsValid( pDoc ) ? SCA_VALID : 0 );
514cdf0e10cSrcweir 	if ( !nFlags )
515cdf0e10cSrcweir 		aStr = ScGlobal::GetRscString( STR_NOREF_STR );
516cdf0e10cSrcweir 	else
517cdf0e10cSrcweir 	{
518cdf0e10cSrcweir 		ScRange aTmpRange( rRange.MakeRange() );
519cdf0e10cSrcweir 		switch ( GetType() )
520cdf0e10cSrcweir 		{
521cdf0e10cSrcweir 			case SC_CAT_INSERT_COLS :
522cdf0e10cSrcweir 			case SC_CAT_DELETE_COLS :
523cdf0e10cSrcweir 				if ( bFlag3D )
524cdf0e10cSrcweir 				{
525cdf0e10cSrcweir 					pDoc->GetName( aTmpRange.aStart.Tab(), aStr );
526cdf0e10cSrcweir 					aStr += '.';
527cdf0e10cSrcweir 				}
528cdf0e10cSrcweir 				aStr += ::ScColToAlpha( aTmpRange.aStart.Col() );
529cdf0e10cSrcweir 				aStr += ':';
530cdf0e10cSrcweir 				aStr += ::ScColToAlpha( aTmpRange.aEnd.Col() );
531cdf0e10cSrcweir 			break;
532cdf0e10cSrcweir 			case SC_CAT_INSERT_ROWS :
533cdf0e10cSrcweir 			case SC_CAT_DELETE_ROWS :
534cdf0e10cSrcweir 				if ( bFlag3D )
535cdf0e10cSrcweir 				{
536cdf0e10cSrcweir 					pDoc->GetName( aTmpRange.aStart.Tab(), aStr );
537cdf0e10cSrcweir 					aStr += '.';
538cdf0e10cSrcweir 				}
539cdf0e10cSrcweir 				aStr += String::CreateFromInt32( aTmpRange.aStart.Row() + 1 );
540cdf0e10cSrcweir 				aStr += ':';
541cdf0e10cSrcweir 				aStr += String::CreateFromInt32( aTmpRange.aEnd.Row() + 1 );
542cdf0e10cSrcweir 			break;
543cdf0e10cSrcweir 			default:
544cdf0e10cSrcweir 				if ( bFlag3D || GetType() == SC_CAT_INSERT_TABS )
545cdf0e10cSrcweir 					nFlags |= SCA_TAB_3D;
546cdf0e10cSrcweir 				aTmpRange.Format( aStr, nFlags, pDoc, pDoc->GetAddressConvention() );
547cdf0e10cSrcweir 		}
548cdf0e10cSrcweir 		if ( (bFlag3D && IsDeleteType()) || IsDeletedIn() )
549cdf0e10cSrcweir 		{
550cdf0e10cSrcweir 			aStr.Insert( '(', 0 );
551cdf0e10cSrcweir 			aStr += ')';
552cdf0e10cSrcweir 		}
553cdf0e10cSrcweir 	}
554cdf0e10cSrcweir 	return aStr;
555cdf0e10cSrcweir }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir 
GetRefString(String & rStr,ScDocument * pDoc,sal_Bool bFlag3D) const558cdf0e10cSrcweir void ScChangeAction::GetRefString( String& rStr, ScDocument* pDoc,
559cdf0e10cSrcweir 		sal_Bool bFlag3D ) const
560cdf0e10cSrcweir {
561cdf0e10cSrcweir 	rStr = GetRefString( GetBigRange(), pDoc, bFlag3D );
562cdf0e10cSrcweir }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir 
Accept()565cdf0e10cSrcweir void ScChangeAction::Accept()
566cdf0e10cSrcweir {
567cdf0e10cSrcweir 	if ( IsVirgin() )
568cdf0e10cSrcweir 	{
569cdf0e10cSrcweir 		SetState( SC_CAS_ACCEPTED );
570cdf0e10cSrcweir 		DeleteCellEntries();
571cdf0e10cSrcweir 	}
572cdf0e10cSrcweir }
573cdf0e10cSrcweir 
574cdf0e10cSrcweir 
SetRejected()575cdf0e10cSrcweir void ScChangeAction::SetRejected()
576cdf0e10cSrcweir {
577cdf0e10cSrcweir 	if ( IsVirgin() )
578cdf0e10cSrcweir 	{
579cdf0e10cSrcweir 		SetState( SC_CAS_REJECTED );
580cdf0e10cSrcweir 		RemoveAllLinks();
581cdf0e10cSrcweir 		DeleteCellEntries();
582cdf0e10cSrcweir 	}
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
585cdf0e10cSrcweir 
RejectRestoreContents(ScChangeTrack * pTrack,SCsCOL nDx,SCsROW nDy)586cdf0e10cSrcweir void ScChangeAction::RejectRestoreContents( ScChangeTrack* pTrack,
587cdf0e10cSrcweir 		SCsCOL nDx, SCsROW nDy )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir 	// Liste der Contents aufbauen
590cdf0e10cSrcweir 	ScChangeActionCellListEntry* pListContents = NULL;
591cdf0e10cSrcweir 	for ( ScChangeActionLinkEntry* pL = pLinkDeleted; pL; pL = pL->GetNext() )
592cdf0e10cSrcweir 	{
593cdf0e10cSrcweir 		ScChangeAction* p = pL->GetAction();
594cdf0e10cSrcweir 		if ( p && p->GetType() == SC_CAT_CONTENT )
595cdf0e10cSrcweir 		{
596cdf0e10cSrcweir 			ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
597cdf0e10cSrcweir 				(ScChangeActionContent*) p, pListContents );
598cdf0e10cSrcweir 			pListContents = pE;
599cdf0e10cSrcweir 		}
600cdf0e10cSrcweir 	}
601cdf0e10cSrcweir 	SetState( SC_CAS_REJECTED );		// vor UpdateReference fuer Move
602cdf0e10cSrcweir 	pTrack->UpdateReference( this, sal_True );		// LinkDeleted freigeben
603cdf0e10cSrcweir 	DBG_ASSERT( !pLinkDeleted, "ScChangeAction::RejectRestoreContents: pLinkDeleted != NULL" );
604cdf0e10cSrcweir 	// Liste der Contents abarbeiten und loeschen
605cdf0e10cSrcweir 	ScDocument* pDoc = pTrack->GetDocument();
606cdf0e10cSrcweir 	ScChangeActionCellListEntry* pE = pListContents;
607cdf0e10cSrcweir 	while ( pE )
608cdf0e10cSrcweir 	{
609cdf0e10cSrcweir 		if ( !pE->pContent->IsDeletedIn() &&
610cdf0e10cSrcweir 				pE->pContent->GetBigRange().aStart.IsValid( pDoc ) )
611cdf0e10cSrcweir 			pE->pContent->PutNewValueToDoc( pDoc, nDx, nDy );
612cdf0e10cSrcweir         ScChangeActionCellListEntry* pNextEntry;
613cdf0e10cSrcweir         pNextEntry = pE->pNext;
614cdf0e10cSrcweir 		delete pE;
615cdf0e10cSrcweir         pE = pNextEntry;
616cdf0e10cSrcweir 	}
617cdf0e10cSrcweir 	DeleteCellEntries();		// weg mit den generierten
618cdf0e10cSrcweir }
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 
SetDeletedInThis(sal_uLong nActionNumber,const ScChangeTrack * pTrack)621cdf0e10cSrcweir void ScChangeAction::SetDeletedInThis( sal_uLong nActionNumber,
622cdf0e10cSrcweir 		const ScChangeTrack* pTrack )
623cdf0e10cSrcweir {
624cdf0e10cSrcweir 	if ( nActionNumber )
625cdf0e10cSrcweir 	{
626cdf0e10cSrcweir 		ScChangeAction* pAct = pTrack->GetActionOrGenerated( nActionNumber );
627cdf0e10cSrcweir 		DBG_ASSERT( pAct, "ScChangeAction::SetDeletedInThis: missing Action" );
628cdf0e10cSrcweir 		if ( pAct )
629cdf0e10cSrcweir 			pAct->SetDeletedIn( this );
630cdf0e10cSrcweir 	}
631cdf0e10cSrcweir }
632cdf0e10cSrcweir 
633cdf0e10cSrcweir 
AddDependent(sal_uLong nActionNumber,const ScChangeTrack * pTrack)634cdf0e10cSrcweir void ScChangeAction::AddDependent( sal_uLong nActionNumber,
635cdf0e10cSrcweir 		const ScChangeTrack* pTrack )
636cdf0e10cSrcweir {
637cdf0e10cSrcweir 	if ( nActionNumber )
638cdf0e10cSrcweir 	{
639cdf0e10cSrcweir 		ScChangeAction* pAct = pTrack->GetActionOrGenerated( nActionNumber );
640cdf0e10cSrcweir 		DBG_ASSERT( pAct, "ScChangeAction::AddDependent: missing Action" );
641cdf0e10cSrcweir 		if ( pAct )
642cdf0e10cSrcweir 		{
643cdf0e10cSrcweir 			ScChangeActionLinkEntry* pLink = AddDependent( pAct );
644cdf0e10cSrcweir 			pAct->AddLink( this, pLink );
645cdf0e10cSrcweir 		}
646cdf0e10cSrcweir 	}
647cdf0e10cSrcweir }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir 
650cdf0e10cSrcweir #if DEBUG_CHANGETRACK
ToString(ScDocument * pDoc) const651cdf0e10cSrcweir String ScChangeAction::ToString( ScDocument* pDoc ) const
652cdf0e10cSrcweir {
653cdf0e10cSrcweir     String aReturn;
654cdf0e10cSrcweir 
655cdf0e10cSrcweir     String aNumber = String::CreateFromInt64( static_cast< sal_Int64 >( GetActionNumber() ) );
656cdf0e10cSrcweir 
657cdf0e10cSrcweir     String aActionState;
658cdf0e10cSrcweir     ScChangeActionState eActionState = GetState();
659cdf0e10cSrcweir     switch ( eActionState )
660cdf0e10cSrcweir     {
661cdf0e10cSrcweir         case SC_CAS_VIRGIN:
662cdf0e10cSrcweir             {
663cdf0e10cSrcweir                 aActionState = String::CreateFromAscii( " " );
664cdf0e10cSrcweir             }
665cdf0e10cSrcweir             break;
666cdf0e10cSrcweir         case SC_CAS_ACCEPTED:
667cdf0e10cSrcweir             {
668cdf0e10cSrcweir                 aActionState = String::CreateFromAscii( "+" );
669cdf0e10cSrcweir             }
670cdf0e10cSrcweir             break;
671cdf0e10cSrcweir         case SC_CAS_REJECTED:
672cdf0e10cSrcweir             {
673cdf0e10cSrcweir                 aActionState = String::CreateFromAscii( "-" );
674cdf0e10cSrcweir             }
675cdf0e10cSrcweir             break;
676cdf0e10cSrcweir     }
677cdf0e10cSrcweir 
678cdf0e10cSrcweir     String aRejectAction;
679cdf0e10cSrcweir     if ( IsRejecting() )
680cdf0e10cSrcweir     {
681cdf0e10cSrcweir         aRejectAction += 'r';
682cdf0e10cSrcweir         aRejectAction += String::CreateFromInt64( static_cast< sal_Int64 >( GetRejectAction() ) );
683cdf0e10cSrcweir     }
684cdf0e10cSrcweir 
685cdf0e10cSrcweir     String aReference;
686cdf0e10cSrcweir     GetRefString( aReference, pDoc, sal_True );
687cdf0e10cSrcweir 
688cdf0e10cSrcweir     String aAuthor = GetUser();
689cdf0e10cSrcweir 
690cdf0e10cSrcweir     DateTime aDT = GetDateTime();
691cdf0e10cSrcweir     String aDate = ScGlobal::pLocaleData->getDate( aDT );
692cdf0e10cSrcweir     aDate += ' ';
693cdf0e10cSrcweir     aDate += ScGlobal::pLocaleData->getTime( aDT, sal_False, sal_False );
694cdf0e10cSrcweir 
695cdf0e10cSrcweir     String aDescription;
696cdf0e10cSrcweir     GetDescription( aDescription, pDoc );
697cdf0e10cSrcweir 
698cdf0e10cSrcweir     String aLinkAny;
699cdf0e10cSrcweir     const ScChangeActionLinkEntry* pLinkA = pLinkAny;
700cdf0e10cSrcweir     while ( pLinkA )
701cdf0e10cSrcweir     {
702cdf0e10cSrcweir         if ( !aLinkAny.Len() )
703cdf0e10cSrcweir         {
704cdf0e10cSrcweir             aLinkAny = String::CreateFromAscii( "(Any:" );
705cdf0e10cSrcweir         }
706cdf0e10cSrcweir         aLinkAny += String::CreateFromAscii( " ->" );
707cdf0e10cSrcweir         aLinkAny += pLinkA->ToString();
708cdf0e10cSrcweir         pLinkA = pLinkA->GetNext();
709cdf0e10cSrcweir     }
710cdf0e10cSrcweir     if ( aLinkAny.Len() )
711cdf0e10cSrcweir     {
712cdf0e10cSrcweir         aLinkAny += ')';
713cdf0e10cSrcweir     }
714cdf0e10cSrcweir 
715cdf0e10cSrcweir     String aLinkDeletedIn;
716cdf0e10cSrcweir     const ScChangeActionLinkEntry* pLinkDI = pLinkDeletedIn;
717cdf0e10cSrcweir     while ( pLinkDI )
718cdf0e10cSrcweir     {
719cdf0e10cSrcweir         if ( !aLinkDeletedIn.Len() )
720cdf0e10cSrcweir         {
721cdf0e10cSrcweir             aLinkDeletedIn = String::CreateFromAscii( "(DeletedIn:" );
722cdf0e10cSrcweir         }
723cdf0e10cSrcweir         aLinkDeletedIn += String::CreateFromAscii( " ->" );
724cdf0e10cSrcweir         aLinkDeletedIn += pLinkDI->ToString();
725cdf0e10cSrcweir         pLinkDI = pLinkDI->GetNext();
726cdf0e10cSrcweir     }
727cdf0e10cSrcweir     if ( aLinkDeletedIn.Len() )
728cdf0e10cSrcweir     {
729cdf0e10cSrcweir         aLinkDeletedIn += ')';
730cdf0e10cSrcweir     }
731cdf0e10cSrcweir 
732cdf0e10cSrcweir     String aLinkDeleted;
733cdf0e10cSrcweir     const ScChangeActionLinkEntry* pLinkD = pLinkDeleted;
734cdf0e10cSrcweir     while ( pLinkD )
735cdf0e10cSrcweir     {
736cdf0e10cSrcweir         if ( !aLinkDeleted.Len() )
737cdf0e10cSrcweir         {
738cdf0e10cSrcweir             aLinkDeleted = String::CreateFromAscii( "(Deleted:" );
739cdf0e10cSrcweir         }
740cdf0e10cSrcweir         aLinkDeleted += String::CreateFromAscii( " ->" );
741cdf0e10cSrcweir         aLinkDeleted += pLinkD->ToString();
742cdf0e10cSrcweir         pLinkD = pLinkD->GetNext();
743cdf0e10cSrcweir     }
744cdf0e10cSrcweir     if ( aLinkDeleted.Len() )
745cdf0e10cSrcweir     {
746cdf0e10cSrcweir         aLinkDeleted += ')';
747cdf0e10cSrcweir     }
748cdf0e10cSrcweir 
749cdf0e10cSrcweir     String aLinkDependent;
750cdf0e10cSrcweir     const ScChangeActionLinkEntry* pLinkDp = pLinkDependent;
751cdf0e10cSrcweir     while ( pLinkDp )
752cdf0e10cSrcweir     {
753cdf0e10cSrcweir         if ( !aLinkDependent.Len() )
754cdf0e10cSrcweir         {
755cdf0e10cSrcweir             aLinkDependent = String::CreateFromAscii( "(Dependent:" );
756cdf0e10cSrcweir         }
757cdf0e10cSrcweir         aLinkDependent += String::CreateFromAscii( " ->" );
758cdf0e10cSrcweir         aLinkDependent += pLinkDp->ToString();
759cdf0e10cSrcweir         pLinkDp = pLinkDp->GetNext();
760cdf0e10cSrcweir     }
761cdf0e10cSrcweir     if ( aLinkDependent.Len() )
762cdf0e10cSrcweir     {
763cdf0e10cSrcweir         aLinkDependent += ')';
764cdf0e10cSrcweir     }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir     aReturn += aNumber;
767cdf0e10cSrcweir     aReturn += aActionState;
768cdf0e10cSrcweir     aReturn += aRejectAction;
769cdf0e10cSrcweir     aReturn += String::CreateFromAscii( ": " );
770cdf0e10cSrcweir     aReturn += aReference;
771cdf0e10cSrcweir     aReturn += ' ';
772cdf0e10cSrcweir     aReturn += aAuthor;
773cdf0e10cSrcweir     aReturn += ' ';
774cdf0e10cSrcweir     aReturn += aDate;
775cdf0e10cSrcweir     aReturn += ' ';
776cdf0e10cSrcweir     aReturn += aDescription;
777cdf0e10cSrcweir     aReturn += ' ';
778cdf0e10cSrcweir     aReturn += aLinkAny;
779cdf0e10cSrcweir     aReturn += ' ';
780cdf0e10cSrcweir     aReturn += aLinkDeletedIn;
781cdf0e10cSrcweir     aReturn += ' ';
782cdf0e10cSrcweir     aReturn += aLinkDeleted;
783cdf0e10cSrcweir     aReturn += ' ';
784cdf0e10cSrcweir     aReturn += aLinkDependent;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir     return aReturn;
787cdf0e10cSrcweir }
788cdf0e10cSrcweir #endif // DEBUG_CHANGETRACK
789cdf0e10cSrcweir 
790cdf0e10cSrcweir 
791cdf0e10cSrcweir // --- ScChangeActionIns ---------------------------------------------------
792cdf0e10cSrcweir 
ScChangeActionIns(const ScRange & rRange)793cdf0e10cSrcweir ScChangeActionIns::ScChangeActionIns( const ScRange& rRange )
794cdf0e10cSrcweir 		: ScChangeAction( SC_CAT_NONE, rRange )
795cdf0e10cSrcweir {
796cdf0e10cSrcweir 	if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
797cdf0e10cSrcweir 	{
798cdf0e10cSrcweir 		aBigRange.aStart.SetCol( nInt32Min );
799cdf0e10cSrcweir 		aBigRange.aEnd.SetCol( nInt32Max );
800cdf0e10cSrcweir 		if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
801cdf0e10cSrcweir 		{
802cdf0e10cSrcweir 			SetType( SC_CAT_INSERT_TABS );
803cdf0e10cSrcweir 			aBigRange.aStart.SetRow( nInt32Min );
804cdf0e10cSrcweir 			aBigRange.aEnd.SetRow( nInt32Max );
805cdf0e10cSrcweir 		}
806cdf0e10cSrcweir 		else
807cdf0e10cSrcweir 			SetType( SC_CAT_INSERT_ROWS );
808cdf0e10cSrcweir 	}
809cdf0e10cSrcweir 	else if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
810cdf0e10cSrcweir 	{
811cdf0e10cSrcweir 		SetType( SC_CAT_INSERT_COLS );
812cdf0e10cSrcweir 		aBigRange.aStart.SetRow( nInt32Min );
813cdf0e10cSrcweir 		aBigRange.aEnd.SetRow( nInt32Max );
814cdf0e10cSrcweir 	}
815cdf0e10cSrcweir 	else
816cdf0e10cSrcweir 	{
817cdf0e10cSrcweir 		DBG_ERROR( "ScChangeActionIns: Block not supported!" );
818cdf0e10cSrcweir 	}
819cdf0e10cSrcweir }
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 
ScChangeActionIns(const sal_uLong nActionNumber,const ScChangeActionState eStateP,const sal_uLong nRejectingNumber,const ScBigRange & aBigRangeP,const String & aUserP,const DateTime & aDateTimeP,const String & sComment,const ScChangeActionType eTypeP)822cdf0e10cSrcweir ScChangeActionIns::ScChangeActionIns(const sal_uLong nActionNumber, const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
823cdf0e10cSrcweir                                                 const ScBigRange& aBigRangeP, const String& aUserP, const DateTime& aDateTimeP, const String& sComment,
824cdf0e10cSrcweir                                                 const ScChangeActionType eTypeP)
825cdf0e10cSrcweir 		:
826cdf0e10cSrcweir         ScChangeAction(eTypeP, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment)
827cdf0e10cSrcweir {
828cdf0e10cSrcweir }
829cdf0e10cSrcweir 
~ScChangeActionIns()830cdf0e10cSrcweir ScChangeActionIns::~ScChangeActionIns()
831cdf0e10cSrcweir {
832cdf0e10cSrcweir }
833cdf0e10cSrcweir 
834cdf0e10cSrcweir 
GetDescription(String & rStr,ScDocument * pDoc,sal_Bool bSplitRange,bool bWarning) const835cdf0e10cSrcweir void ScChangeActionIns::GetDescription( String& rStr, ScDocument* pDoc,
836cdf0e10cSrcweir 		sal_Bool bSplitRange, bool bWarning ) const
837cdf0e10cSrcweir {
838cdf0e10cSrcweir     ScChangeAction::GetDescription( rStr, pDoc, bSplitRange, bWarning );
839cdf0e10cSrcweir 
840cdf0e10cSrcweir 	sal_uInt16 nWhatId;
841cdf0e10cSrcweir 	switch ( GetType() )
842cdf0e10cSrcweir 	{
843cdf0e10cSrcweir 		case SC_CAT_INSERT_COLS :
844cdf0e10cSrcweir 			nWhatId = STR_COLUMN;
845cdf0e10cSrcweir 		break;
846cdf0e10cSrcweir 		case SC_CAT_INSERT_ROWS :
847cdf0e10cSrcweir 			nWhatId = STR_ROW;
848cdf0e10cSrcweir 		break;
849cdf0e10cSrcweir 		default:
850cdf0e10cSrcweir 			nWhatId = STR_AREA;
851cdf0e10cSrcweir 	}
852cdf0e10cSrcweir 
853cdf0e10cSrcweir 	String aRsc( ScGlobal::GetRscString( STR_CHANGED_INSERT ) );
854cdf0e10cSrcweir 	xub_StrLen nPos = aRsc.SearchAscii( "#1" );
855cdf0e10cSrcweir 	rStr += aRsc.Copy( 0, nPos );
856cdf0e10cSrcweir 	rStr += ScGlobal::GetRscString( nWhatId );
857cdf0e10cSrcweir 	rStr += ' ';
858cdf0e10cSrcweir 	rStr += GetRefString( GetBigRange(), pDoc );
859cdf0e10cSrcweir 	rStr += aRsc.Copy( nPos+2 );
860cdf0e10cSrcweir }
861cdf0e10cSrcweir 
862cdf0e10cSrcweir 
Reject(ScDocument * pDoc)863cdf0e10cSrcweir sal_Bool ScChangeActionIns::Reject( ScDocument* pDoc )
864cdf0e10cSrcweir {
865cdf0e10cSrcweir 	if ( !aBigRange.IsValid( pDoc ) )
866cdf0e10cSrcweir 		return sal_False;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir 	ScRange aRange( aBigRange.MakeRange() );
869cdf0e10cSrcweir 	if ( !pDoc->IsBlockEditable( aRange.aStart.Tab(), aRange.aStart.Col(),
870cdf0e10cSrcweir 			aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() ) )
871cdf0e10cSrcweir 		return sal_False;
872cdf0e10cSrcweir 
873cdf0e10cSrcweir 	switch ( GetType() )
874cdf0e10cSrcweir 	{
875cdf0e10cSrcweir 		case SC_CAT_INSERT_COLS :
876cdf0e10cSrcweir 			pDoc->DeleteCol( aRange );
877cdf0e10cSrcweir 		break;
878cdf0e10cSrcweir 		case SC_CAT_INSERT_ROWS :
879cdf0e10cSrcweir 			pDoc->DeleteRow( aRange );
880cdf0e10cSrcweir 		break;
881cdf0e10cSrcweir 		case SC_CAT_INSERT_TABS :
882cdf0e10cSrcweir 			pDoc->DeleteTab( aRange.aStart.Tab() );
883cdf0e10cSrcweir 		break;
884cdf0e10cSrcweir         default:
885cdf0e10cSrcweir         {
886cdf0e10cSrcweir             // added to avoid warnings
887cdf0e10cSrcweir         }
888cdf0e10cSrcweir 	}
889cdf0e10cSrcweir 	SetState( SC_CAS_REJECTED );
890cdf0e10cSrcweir 	RemoveAllLinks();
891cdf0e10cSrcweir 	return sal_True;
892cdf0e10cSrcweir }
893cdf0e10cSrcweir 
894cdf0e10cSrcweir 
895cdf0e10cSrcweir // --- ScChangeActionDel ---------------------------------------------------
896cdf0e10cSrcweir 
ScChangeActionDel(const ScRange & rRange,SCsCOL nDxP,SCsROW nDyP,ScChangeTrack * pTrackP)897cdf0e10cSrcweir ScChangeActionDel::ScChangeActionDel( const ScRange& rRange,
898cdf0e10cSrcweir 			SCsCOL nDxP, SCsROW nDyP, ScChangeTrack* pTrackP )
899cdf0e10cSrcweir 		:
900cdf0e10cSrcweir 		ScChangeAction( SC_CAT_NONE, rRange ),
901cdf0e10cSrcweir 		pTrack( pTrackP ),
902cdf0e10cSrcweir 		pFirstCell( NULL ),
903cdf0e10cSrcweir 		pCutOff( NULL ),
904cdf0e10cSrcweir 		nCutOff( 0 ),
905cdf0e10cSrcweir 		pLinkMove( NULL ),
906cdf0e10cSrcweir 		nDx( nDxP ),
907cdf0e10cSrcweir 		nDy( nDyP )
908cdf0e10cSrcweir {
909cdf0e10cSrcweir 	if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL )
910cdf0e10cSrcweir 	{
911cdf0e10cSrcweir 		aBigRange.aStart.SetCol( nInt32Min );
912cdf0e10cSrcweir 		aBigRange.aEnd.SetCol( nInt32Max );
913cdf0e10cSrcweir 		if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
914cdf0e10cSrcweir 		{
915cdf0e10cSrcweir 			SetType( SC_CAT_DELETE_TABS );
916cdf0e10cSrcweir 			aBigRange.aStart.SetRow( nInt32Min );
917cdf0e10cSrcweir 			aBigRange.aEnd.SetRow( nInt32Max );
918cdf0e10cSrcweir 		}
919cdf0e10cSrcweir 		else
920cdf0e10cSrcweir 			SetType( SC_CAT_DELETE_ROWS );
921cdf0e10cSrcweir 	}
922cdf0e10cSrcweir 	else if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW )
923cdf0e10cSrcweir 	{
924cdf0e10cSrcweir 		SetType( SC_CAT_DELETE_COLS );
925cdf0e10cSrcweir 		aBigRange.aStart.SetRow( nInt32Min );
926cdf0e10cSrcweir 		aBigRange.aEnd.SetRow( nInt32Max );
927cdf0e10cSrcweir 	}
928cdf0e10cSrcweir 	else
929cdf0e10cSrcweir 	{
930cdf0e10cSrcweir 		DBG_ERROR( "ScChangeActionDel: Block not supported!" );
931cdf0e10cSrcweir 	}
932cdf0e10cSrcweir }
933cdf0e10cSrcweir 
934cdf0e10cSrcweir 
ScChangeActionDel(const sal_uLong nActionNumber,const ScChangeActionState eStateP,const sal_uLong nRejectingNumber,const ScBigRange & aBigRangeP,const String & aUserP,const DateTime & aDateTimeP,const String & sComment,const ScChangeActionType eTypeP,const SCsCOLROW nD,ScChangeTrack * pTrackP)935cdf0e10cSrcweir ScChangeActionDel::ScChangeActionDel(const sal_uLong nActionNumber, const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
936cdf0e10cSrcweir                                     const ScBigRange& aBigRangeP, const String& aUserP, const DateTime& aDateTimeP, const String &sComment,
937cdf0e10cSrcweir                                     const ScChangeActionType eTypeP, const SCsCOLROW nD, ScChangeTrack* pTrackP) // wich of nDx and nDy is set is depend on the type
938cdf0e10cSrcweir 		:
939cdf0e10cSrcweir         ScChangeAction(eTypeP, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
940cdf0e10cSrcweir 		pTrack( pTrackP ),
941cdf0e10cSrcweir 		pFirstCell( NULL ),
942cdf0e10cSrcweir 		pCutOff( NULL ),
943cdf0e10cSrcweir 		nCutOff( 0 ),
944cdf0e10cSrcweir 		pLinkMove( NULL ),
945cdf0e10cSrcweir 		nDx( 0 ),
946cdf0e10cSrcweir 		nDy( 0 )
947cdf0e10cSrcweir {
948cdf0e10cSrcweir 	if (eType == SC_CAT_DELETE_COLS)
949cdf0e10cSrcweir 		nDx = static_cast<SCsCOL>(nD);
950cdf0e10cSrcweir 	else if (eType == SC_CAT_DELETE_ROWS)
951cdf0e10cSrcweir 		nDy = static_cast<SCsROW>(nD);
952cdf0e10cSrcweir }
953cdf0e10cSrcweir 
~ScChangeActionDel()954cdf0e10cSrcweir ScChangeActionDel::~ScChangeActionDel()
955cdf0e10cSrcweir {
956cdf0e10cSrcweir 	DeleteCellEntries();
957cdf0e10cSrcweir 	while ( pLinkMove )
958cdf0e10cSrcweir 		delete pLinkMove;
959cdf0e10cSrcweir }
960cdf0e10cSrcweir 
AddContent(ScChangeActionContent * pContent)961cdf0e10cSrcweir void ScChangeActionDel::AddContent( ScChangeActionContent* pContent )
962cdf0e10cSrcweir {
963cdf0e10cSrcweir 	ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
964cdf0e10cSrcweir 		pContent, pFirstCell );
965cdf0e10cSrcweir 	pFirstCell = pE;
966cdf0e10cSrcweir }
967cdf0e10cSrcweir 
968cdf0e10cSrcweir 
DeleteCellEntries()969cdf0e10cSrcweir void ScChangeActionDel::DeleteCellEntries()
970cdf0e10cSrcweir {
971cdf0e10cSrcweir 	pTrack->DeleteCellEntries( pFirstCell, this );
972cdf0e10cSrcweir }
973cdf0e10cSrcweir 
974cdf0e10cSrcweir 
IsBaseDelete() const975cdf0e10cSrcweir sal_Bool ScChangeActionDel::IsBaseDelete() const
976cdf0e10cSrcweir {
977cdf0e10cSrcweir 	return !GetDx() && !GetDy();
978cdf0e10cSrcweir }
979cdf0e10cSrcweir 
980cdf0e10cSrcweir 
IsTopDelete() const981cdf0e10cSrcweir sal_Bool ScChangeActionDel::IsTopDelete() const
982cdf0e10cSrcweir {
983cdf0e10cSrcweir 	const ScChangeAction* p = GetNext();
984cdf0e10cSrcweir 	if ( !p || p->GetType() != GetType() )
985cdf0e10cSrcweir 		return sal_True;
986cdf0e10cSrcweir 	return ((ScChangeActionDel*)p)->IsBaseDelete();
987cdf0e10cSrcweir }
988cdf0e10cSrcweir 
989cdf0e10cSrcweir 
IsMultiDelete() const990cdf0e10cSrcweir sal_Bool ScChangeActionDel::IsMultiDelete() const
991cdf0e10cSrcweir {
992cdf0e10cSrcweir 	if ( GetDx() || GetDy() )
993cdf0e10cSrcweir 		return sal_True;
994cdf0e10cSrcweir 	const ScChangeAction* p = GetNext();
995cdf0e10cSrcweir 	if ( !p || p->GetType() != GetType() )
996cdf0e10cSrcweir 		return sal_False;
997cdf0e10cSrcweir 	const ScChangeActionDel* pDel = (const ScChangeActionDel*) p;
998cdf0e10cSrcweir 	if ( (pDel->GetDx() > GetDx() || pDel->GetDy() > GetDy()) &&
999cdf0e10cSrcweir 			pDel->GetBigRange() == aBigRange )
1000cdf0e10cSrcweir 		return sal_True;
1001cdf0e10cSrcweir 	return sal_False;
1002cdf0e10cSrcweir }
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir 
IsTabDeleteCol() const1005cdf0e10cSrcweir sal_Bool ScChangeActionDel::IsTabDeleteCol() const
1006cdf0e10cSrcweir {
1007cdf0e10cSrcweir 	if ( GetType() != SC_CAT_DELETE_COLS )
1008cdf0e10cSrcweir 		return sal_False;
1009cdf0e10cSrcweir 	const ScChangeAction* p = this;
1010cdf0e10cSrcweir 	while ( p && p->GetType() == SC_CAT_DELETE_COLS &&
1011cdf0e10cSrcweir 			!((const ScChangeActionDel*)p)->IsTopDelete() )
1012cdf0e10cSrcweir 		p = p->GetNext();
1013cdf0e10cSrcweir 	return p && p->GetType() == SC_CAT_DELETE_TABS;
1014cdf0e10cSrcweir }
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir 
UpdateReference(const ScChangeTrack *,UpdateRefMode eMode,const ScBigRange & rRange,sal_Int32 nDxP,sal_Int32 nDyP,sal_Int32 nDz)1017cdf0e10cSrcweir void ScChangeActionDel::UpdateReference( const ScChangeTrack* /* pTrack */,
1018cdf0e10cSrcweir 		UpdateRefMode eMode, const ScBigRange& rRange,
1019cdf0e10cSrcweir         sal_Int32 nDxP, sal_Int32 nDyP, sal_Int32 nDz )
1020cdf0e10cSrcweir {
1021cdf0e10cSrcweir     ScRefUpdate::Update( eMode, rRange, nDxP, nDyP, nDz, GetBigRange() );
1022cdf0e10cSrcweir 	if ( !IsDeletedIn() )
1023cdf0e10cSrcweir 		return ;
1024cdf0e10cSrcweir 	// evtl. in "druntergerutschten" anpassen
1025cdf0e10cSrcweir 	for ( ScChangeActionLinkEntry* pL = pLinkDeleted; pL; pL = pL->GetNext() )
1026cdf0e10cSrcweir 	{
1027cdf0e10cSrcweir 		ScChangeAction* p = pL->GetAction();
1028cdf0e10cSrcweir 		if ( p && p->GetType() == SC_CAT_CONTENT &&
1029cdf0e10cSrcweir 				!GetBigRange().In( p->GetBigRange() ) )
1030cdf0e10cSrcweir 		{
1031cdf0e10cSrcweir 			switch ( GetType() )
1032cdf0e10cSrcweir 			{
1033cdf0e10cSrcweir 				case SC_CAT_DELETE_COLS :
1034cdf0e10cSrcweir 					p->GetBigRange().aStart.SetCol( GetBigRange().aStart.Col() );
1035cdf0e10cSrcweir 					p->GetBigRange().aEnd.SetCol( GetBigRange().aStart.Col() );
1036cdf0e10cSrcweir 				break;
1037cdf0e10cSrcweir 				case SC_CAT_DELETE_ROWS :
1038cdf0e10cSrcweir 					p->GetBigRange().aStart.SetRow( GetBigRange().aStart.Row() );
1039cdf0e10cSrcweir 					p->GetBigRange().aEnd.SetRow( GetBigRange().aStart.Row() );
1040cdf0e10cSrcweir 				break;
1041cdf0e10cSrcweir 				case SC_CAT_DELETE_TABS :
1042cdf0e10cSrcweir 					p->GetBigRange().aStart.SetTab( GetBigRange().aStart.Tab() );
1043cdf0e10cSrcweir 					p->GetBigRange().aEnd.SetTab( GetBigRange().aStart.Tab() );
1044cdf0e10cSrcweir 				break;
1045cdf0e10cSrcweir                 default:
1046cdf0e10cSrcweir                 {
1047cdf0e10cSrcweir                     // added to avoid warnings
1048cdf0e10cSrcweir                 }
1049cdf0e10cSrcweir 			}
1050cdf0e10cSrcweir 		}
1051cdf0e10cSrcweir 	}
1052cdf0e10cSrcweir }
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir 
GetOverAllRange() const1055cdf0e10cSrcweir ScBigRange ScChangeActionDel::GetOverAllRange() const
1056cdf0e10cSrcweir {
1057cdf0e10cSrcweir 	ScBigRange aTmpRange( GetBigRange() );
1058cdf0e10cSrcweir 	aTmpRange.aEnd.SetCol( aTmpRange.aEnd.Col() + GetDx() );
1059cdf0e10cSrcweir 	aTmpRange.aEnd.SetRow( aTmpRange.aEnd.Row() + GetDy() );
1060cdf0e10cSrcweir 	return aTmpRange;
1061cdf0e10cSrcweir }
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 
GetDescription(String & rStr,ScDocument * pDoc,sal_Bool bSplitRange,bool bWarning) const1064cdf0e10cSrcweir void ScChangeActionDel::GetDescription( String& rStr, ScDocument* pDoc,
1065cdf0e10cSrcweir 		sal_Bool bSplitRange, bool bWarning ) const
1066cdf0e10cSrcweir {
1067cdf0e10cSrcweir     ScChangeAction::GetDescription( rStr, pDoc, bSplitRange, bWarning );
1068cdf0e10cSrcweir 
1069cdf0e10cSrcweir 	sal_uInt16 nWhatId;
1070cdf0e10cSrcweir 	switch ( GetType() )
1071cdf0e10cSrcweir 	{
1072cdf0e10cSrcweir 		case SC_CAT_DELETE_COLS :
1073cdf0e10cSrcweir 			nWhatId = STR_COLUMN;
1074cdf0e10cSrcweir 		break;
1075cdf0e10cSrcweir 		case SC_CAT_DELETE_ROWS :
1076cdf0e10cSrcweir 			nWhatId = STR_ROW;
1077cdf0e10cSrcweir 		break;
1078cdf0e10cSrcweir 		default:
1079cdf0e10cSrcweir 			nWhatId = STR_AREA;
1080cdf0e10cSrcweir 	}
1081cdf0e10cSrcweir 
1082cdf0e10cSrcweir 	ScBigRange aTmpRange( GetBigRange() );
1083cdf0e10cSrcweir 	if ( !IsRejected() )
1084cdf0e10cSrcweir 	{
1085cdf0e10cSrcweir 		if ( bSplitRange )
1086cdf0e10cSrcweir 		{
1087cdf0e10cSrcweir 			aTmpRange.aStart.SetCol( aTmpRange.aStart.Col() + GetDx() );
1088cdf0e10cSrcweir 			aTmpRange.aStart.SetRow( aTmpRange.aStart.Row() + GetDy() );
1089cdf0e10cSrcweir 		}
1090cdf0e10cSrcweir 		aTmpRange.aEnd.SetCol( aTmpRange.aEnd.Col() + GetDx() );
1091cdf0e10cSrcweir 		aTmpRange.aEnd.SetRow( aTmpRange.aEnd.Row() + GetDy() );
1092cdf0e10cSrcweir 	}
1093cdf0e10cSrcweir 
1094cdf0e10cSrcweir 	String aRsc( ScGlobal::GetRscString( STR_CHANGED_DELETE ) );
1095cdf0e10cSrcweir 	xub_StrLen nPos = aRsc.SearchAscii( "#1" );
1096cdf0e10cSrcweir 	rStr += aRsc.Copy( 0, nPos );
1097cdf0e10cSrcweir 	rStr += ScGlobal::GetRscString( nWhatId );
1098cdf0e10cSrcweir 	rStr += ' ';
1099cdf0e10cSrcweir 	rStr += GetRefString( aTmpRange, pDoc );
1100cdf0e10cSrcweir 	rStr += aRsc.Copy( nPos+2 );
1101cdf0e10cSrcweir }
1102cdf0e10cSrcweir 
1103cdf0e10cSrcweir 
Reject(ScDocument * pDoc)1104cdf0e10cSrcweir sal_Bool ScChangeActionDel::Reject( ScDocument* pDoc )
1105cdf0e10cSrcweir {
1106cdf0e10cSrcweir 	if ( !aBigRange.IsValid( pDoc ) && GetType() != SC_CAT_DELETE_TABS )
1107cdf0e10cSrcweir 		return sal_False;
1108cdf0e10cSrcweir 
1109cdf0e10cSrcweir 	sal_Bool bOk = sal_True;
1110cdf0e10cSrcweir 
1111cdf0e10cSrcweir 	if ( IsTopDelete() )
1112cdf0e10cSrcweir 	{	// den kompletten Bereich in einem Rutsch restaurieren
1113cdf0e10cSrcweir 		ScBigRange aTmpRange( GetOverAllRange() );
1114cdf0e10cSrcweir 		if ( !aTmpRange.IsValid( pDoc ) )
1115cdf0e10cSrcweir 		{
1116cdf0e10cSrcweir 			if ( GetType() == SC_CAT_DELETE_TABS )
1117cdf0e10cSrcweir 			{	// wird Tab angehaengt?
1118cdf0e10cSrcweir 				if ( aTmpRange.aStart.Tab() > pDoc->GetMaxTableNumber() )
1119cdf0e10cSrcweir 					bOk = sal_False;
1120cdf0e10cSrcweir 			}
1121cdf0e10cSrcweir 			else
1122cdf0e10cSrcweir 				bOk = sal_False;
1123cdf0e10cSrcweir 		}
1124cdf0e10cSrcweir 		if ( bOk )
1125cdf0e10cSrcweir 		{
1126cdf0e10cSrcweir 			ScRange aRange( aTmpRange.MakeRange() );
1127cdf0e10cSrcweir 			// InDelete... fuer Formel UpdateReference in Document
1128cdf0e10cSrcweir 			pTrack->SetInDeleteRange( aRange );
1129cdf0e10cSrcweir 			pTrack->SetInDeleteTop( sal_True );
1130cdf0e10cSrcweir 			pTrack->SetInDeleteUndo( sal_True );
1131cdf0e10cSrcweir 			pTrack->SetInDelete( sal_True );
1132cdf0e10cSrcweir 			switch ( GetType() )
1133cdf0e10cSrcweir 			{
1134cdf0e10cSrcweir 				case SC_CAT_DELETE_COLS :
1135cdf0e10cSrcweir 					if ( !(aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL) )
1136cdf0e10cSrcweir 					{	// nur wenn nicht TabDelete
1137cdf0e10cSrcweir                         if ( ( bOk = pDoc->CanInsertCol( aRange ) ) != sal_False )
1138cdf0e10cSrcweir 							bOk = pDoc->InsertCol( aRange );
1139cdf0e10cSrcweir 					}
1140cdf0e10cSrcweir 				break;
1141cdf0e10cSrcweir 				case SC_CAT_DELETE_ROWS :
1142cdf0e10cSrcweir                     if ( ( bOk = pDoc->CanInsertRow( aRange ) ) != sal_False )
1143cdf0e10cSrcweir 						bOk = pDoc->InsertRow( aRange );
1144cdf0e10cSrcweir 				break;
1145cdf0e10cSrcweir 				case SC_CAT_DELETE_TABS :
1146cdf0e10cSrcweir 				{
1147cdf0e10cSrcweir //2do: Tabellennamen merken?
1148cdf0e10cSrcweir 					String aName;
1149cdf0e10cSrcweir 					pDoc->CreateValidTabName( aName );
1150cdf0e10cSrcweir                     if ( ( bOk = pDoc->ValidNewTabName( aName ) ) != sal_False )
1151cdf0e10cSrcweir 						bOk = pDoc->InsertTab( aRange.aStart.Tab(), aName );
1152cdf0e10cSrcweir 				}
1153cdf0e10cSrcweir 				break;
1154cdf0e10cSrcweir                 default:
1155cdf0e10cSrcweir                 {
1156cdf0e10cSrcweir                     // added to avoid warnings
1157cdf0e10cSrcweir                 }
1158cdf0e10cSrcweir 			}
1159cdf0e10cSrcweir 			pTrack->SetInDelete( sal_False );
1160cdf0e10cSrcweir 			pTrack->SetInDeleteUndo( sal_False );
1161cdf0e10cSrcweir 		}
1162cdf0e10cSrcweir 		if ( !bOk )
1163cdf0e10cSrcweir 		{
1164cdf0e10cSrcweir 			pTrack->SetInDeleteTop( sal_False );
1165cdf0e10cSrcweir 			return sal_False;
1166cdf0e10cSrcweir 		}
1167cdf0e10cSrcweir 		// InDeleteTop fuer UpdateReference-Undo behalten
1168cdf0e10cSrcweir 	}
1169cdf0e10cSrcweir 
1170cdf0e10cSrcweir 	// setzt rejected und ruft UpdateReference-Undo und DeleteCellEntries
1171cdf0e10cSrcweir 	RejectRestoreContents( pTrack, GetDx(), GetDy() );
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir 	pTrack->SetInDeleteTop( sal_False );
1174cdf0e10cSrcweir 	RemoveAllLinks();
1175cdf0e10cSrcweir 	return sal_True;
1176cdf0e10cSrcweir }
1177cdf0e10cSrcweir 
1178cdf0e10cSrcweir 
UndoCutOffMoves()1179cdf0e10cSrcweir void ScChangeActionDel::UndoCutOffMoves()
1180cdf0e10cSrcweir {	// abgeschnittene Moves wiederherstellen, Entries/Links deleten
1181cdf0e10cSrcweir 	while ( pLinkMove )
1182cdf0e10cSrcweir 	{
1183cdf0e10cSrcweir 		ScChangeActionMove* pMove = pLinkMove->GetMove();
1184cdf0e10cSrcweir 		short nFrom = pLinkMove->GetCutOffFrom();
1185cdf0e10cSrcweir 		short nTo = pLinkMove->GetCutOffTo();
1186cdf0e10cSrcweir 		switch ( GetType() )
1187cdf0e10cSrcweir 		{
1188cdf0e10cSrcweir 			case SC_CAT_DELETE_COLS :
1189cdf0e10cSrcweir 				if ( nFrom > 0 )
1190cdf0e10cSrcweir 					pMove->GetFromRange().aStart.IncCol( -nFrom );
1191cdf0e10cSrcweir 				else if ( nFrom < 0 )
1192cdf0e10cSrcweir 					pMove->GetFromRange().aEnd.IncCol( -nFrom );
1193cdf0e10cSrcweir 				if ( nTo > 0 )
1194cdf0e10cSrcweir 					pMove->GetBigRange().aStart.IncCol( -nTo );
1195cdf0e10cSrcweir 				else if ( nTo < 0 )
1196cdf0e10cSrcweir 					pMove->GetBigRange().aEnd.IncCol( -nTo );
1197cdf0e10cSrcweir 			break;
1198cdf0e10cSrcweir 			case SC_CAT_DELETE_ROWS :
1199cdf0e10cSrcweir 				if ( nFrom > 0 )
1200cdf0e10cSrcweir 					pMove->GetFromRange().aStart.IncRow( -nFrom );
1201cdf0e10cSrcweir 				else if ( nFrom < 0 )
1202cdf0e10cSrcweir 					pMove->GetFromRange().aEnd.IncRow( -nFrom );
1203cdf0e10cSrcweir 				if ( nTo > 0 )
1204cdf0e10cSrcweir 					pMove->GetBigRange().aStart.IncRow( -nTo );
1205cdf0e10cSrcweir 				else if ( nTo < 0 )
1206cdf0e10cSrcweir 					pMove->GetBigRange().aEnd.IncRow( -nTo );
1207cdf0e10cSrcweir 			break;
1208cdf0e10cSrcweir 			case SC_CAT_DELETE_TABS :
1209cdf0e10cSrcweir 				if ( nFrom > 0 )
1210cdf0e10cSrcweir 					pMove->GetFromRange().aStart.IncTab( -nFrom );
1211cdf0e10cSrcweir 				else if ( nFrom < 0 )
1212cdf0e10cSrcweir 					pMove->GetFromRange().aEnd.IncTab( -nFrom );
1213cdf0e10cSrcweir 				if ( nTo > 0 )
1214cdf0e10cSrcweir 					pMove->GetBigRange().aStart.IncTab( -nTo );
1215cdf0e10cSrcweir 				else if ( nTo < 0 )
1216cdf0e10cSrcweir 					pMove->GetBigRange().aEnd.IncTab( -nTo );
1217cdf0e10cSrcweir 			break;
1218cdf0e10cSrcweir             default:
1219cdf0e10cSrcweir             {
1220cdf0e10cSrcweir                 // added to avoid warnings
1221cdf0e10cSrcweir             }
1222cdf0e10cSrcweir 		}
1223cdf0e10cSrcweir 		delete pLinkMove;		// rueckt sich selbst hoch
1224cdf0e10cSrcweir 	}
1225cdf0e10cSrcweir }
1226cdf0e10cSrcweir 
UndoCutOffInsert()1227cdf0e10cSrcweir void ScChangeActionDel::UndoCutOffInsert()
1228cdf0e10cSrcweir {	// abgeschnittenes Insert wiederherstellen
1229cdf0e10cSrcweir 	if ( pCutOff )
1230cdf0e10cSrcweir 	{
1231cdf0e10cSrcweir 		switch ( pCutOff->GetType() )
1232cdf0e10cSrcweir 		{
1233cdf0e10cSrcweir 			case SC_CAT_INSERT_COLS :
1234cdf0e10cSrcweir 				if ( nCutOff < 0 )
1235cdf0e10cSrcweir 					pCutOff->GetBigRange().aEnd.IncCol( -nCutOff );
1236cdf0e10cSrcweir 				else
1237cdf0e10cSrcweir 					pCutOff->GetBigRange().aStart.IncCol( -nCutOff );
1238cdf0e10cSrcweir 			break;
1239cdf0e10cSrcweir 			case SC_CAT_INSERT_ROWS :
1240cdf0e10cSrcweir 				if ( nCutOff < 0 )
1241cdf0e10cSrcweir 					pCutOff->GetBigRange().aEnd.IncRow( -nCutOff );
1242cdf0e10cSrcweir 				else
1243cdf0e10cSrcweir 					pCutOff->GetBigRange().aStart.IncRow( -nCutOff );
1244cdf0e10cSrcweir 			break;
1245cdf0e10cSrcweir 			case SC_CAT_INSERT_TABS :
1246cdf0e10cSrcweir 				if ( nCutOff < 0 )
1247cdf0e10cSrcweir 					pCutOff->GetBigRange().aEnd.IncTab( -nCutOff );
1248cdf0e10cSrcweir 				else
1249cdf0e10cSrcweir 					pCutOff->GetBigRange().aStart.IncTab( -nCutOff );
1250cdf0e10cSrcweir 			break;
1251cdf0e10cSrcweir             default:
1252cdf0e10cSrcweir             {
1253cdf0e10cSrcweir                 // added to avoid warnings
1254cdf0e10cSrcweir             }
1255cdf0e10cSrcweir 		}
1256cdf0e10cSrcweir 		SetCutOffInsert( NULL, 0 );
1257cdf0e10cSrcweir 	}
1258cdf0e10cSrcweir }
1259cdf0e10cSrcweir 
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir // --- ScChangeActionMove --------------------------------------------------
1262cdf0e10cSrcweir 
ScChangeActionMove(const sal_uLong nActionNumber,const ScChangeActionState eStateP,const sal_uLong nRejectingNumber,const ScBigRange & aToBigRange,const String & aUserP,const DateTime & aDateTimeP,const String & sComment,const ScBigRange & aFromBigRange,ScChangeTrack * pTrackP)1263cdf0e10cSrcweir ScChangeActionMove::ScChangeActionMove(const sal_uLong nActionNumber, const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
1264cdf0e10cSrcweir                                     const ScBigRange& aToBigRange, const String& aUserP, const DateTime& aDateTimeP, const String &sComment,
1265cdf0e10cSrcweir 									const ScBigRange& aFromBigRange, ScChangeTrack* pTrackP) // wich of nDx and nDy is set is depend on the type
1266cdf0e10cSrcweir 		:
1267cdf0e10cSrcweir         ScChangeAction(SC_CAT_MOVE, aToBigRange, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
1268cdf0e10cSrcweir 		aFromRange(aFromBigRange),
1269cdf0e10cSrcweir 		pTrack( pTrackP ),
1270cdf0e10cSrcweir 		pFirstCell( NULL ),
1271cdf0e10cSrcweir 		nStartLastCut(0),
1272cdf0e10cSrcweir 		nEndLastCut(0)
1273cdf0e10cSrcweir {
1274cdf0e10cSrcweir }
1275cdf0e10cSrcweir 
~ScChangeActionMove()1276cdf0e10cSrcweir ScChangeActionMove::~ScChangeActionMove()
1277cdf0e10cSrcweir {
1278cdf0e10cSrcweir 	DeleteCellEntries();
1279cdf0e10cSrcweir }
1280cdf0e10cSrcweir 
1281cdf0e10cSrcweir 
AddContent(ScChangeActionContent * pContent)1282cdf0e10cSrcweir void ScChangeActionMove::AddContent( ScChangeActionContent* pContent )
1283cdf0e10cSrcweir {
1284cdf0e10cSrcweir 	ScChangeActionCellListEntry* pE = new ScChangeActionCellListEntry(
1285cdf0e10cSrcweir 		pContent, pFirstCell );
1286cdf0e10cSrcweir 	pFirstCell = pE;
1287cdf0e10cSrcweir }
1288cdf0e10cSrcweir 
1289cdf0e10cSrcweir 
DeleteCellEntries()1290cdf0e10cSrcweir void ScChangeActionMove::DeleteCellEntries()
1291cdf0e10cSrcweir {
1292cdf0e10cSrcweir 	pTrack->DeleteCellEntries( pFirstCell, this );
1293cdf0e10cSrcweir }
1294cdf0e10cSrcweir 
1295cdf0e10cSrcweir 
UpdateReference(const ScChangeTrack *,UpdateRefMode eMode,const ScBigRange & rRange,sal_Int32 nDx,sal_Int32 nDy,sal_Int32 nDz)1296cdf0e10cSrcweir void ScChangeActionMove::UpdateReference( const ScChangeTrack* /* pTrack */,
1297cdf0e10cSrcweir 		UpdateRefMode eMode, const ScBigRange& rRange,
1298cdf0e10cSrcweir 		sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz )
1299cdf0e10cSrcweir {
1300cdf0e10cSrcweir 	ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, aFromRange );
1301cdf0e10cSrcweir 	ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, GetBigRange() );
1302cdf0e10cSrcweir }
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir 
GetDelta(sal_Int32 & nDx,sal_Int32 & nDy,sal_Int32 & nDz) const1305cdf0e10cSrcweir void ScChangeActionMove::GetDelta( sal_Int32& nDx, sal_Int32& nDy, sal_Int32& nDz ) const
1306cdf0e10cSrcweir {
1307cdf0e10cSrcweir 	const ScBigAddress& rToPos = GetBigRange().aStart;
1308cdf0e10cSrcweir 	const ScBigAddress& rFromPos = GetFromRange().aStart;
1309cdf0e10cSrcweir 	nDx = rToPos.Col() - rFromPos.Col();
1310cdf0e10cSrcweir 	nDy = rToPos.Row() - rFromPos.Row();
1311cdf0e10cSrcweir 	nDz = rToPos.Tab() - rFromPos.Tab();
1312cdf0e10cSrcweir }
1313cdf0e10cSrcweir 
1314cdf0e10cSrcweir 
GetDescription(String & rStr,ScDocument * pDoc,sal_Bool bSplitRange,bool bWarning) const1315cdf0e10cSrcweir void ScChangeActionMove::GetDescription( String& rStr, ScDocument* pDoc,
1316cdf0e10cSrcweir 		sal_Bool bSplitRange, bool bWarning ) const
1317cdf0e10cSrcweir {
1318cdf0e10cSrcweir     ScChangeAction::GetDescription( rStr, pDoc, bSplitRange, bWarning );
1319cdf0e10cSrcweir 
1320cdf0e10cSrcweir 	sal_Bool bFlag3D = ( GetFromRange().aStart.Tab() != GetBigRange().aStart.Tab() );
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir 	String aRsc( ScGlobal::GetRscString( STR_CHANGED_MOVE ) );
1323cdf0e10cSrcweir 
1324cdf0e10cSrcweir 	xub_StrLen nPos = 0;
1325cdf0e10cSrcweir 	String aTmpStr = ScChangeAction::GetRefString( GetFromRange(), pDoc, bFlag3D );
1326cdf0e10cSrcweir 	nPos = aRsc.SearchAscii( "#1", nPos );
1327cdf0e10cSrcweir 	aRsc.Erase( nPos, 2 );
1328cdf0e10cSrcweir 	aRsc.Insert( aTmpStr, nPos );
1329cdf0e10cSrcweir     nPos = sal::static_int_cast<xub_StrLen>( nPos + aTmpStr.Len() );
1330cdf0e10cSrcweir 
1331cdf0e10cSrcweir 	aTmpStr = ScChangeAction::GetRefString( GetBigRange(), pDoc, bFlag3D );
1332cdf0e10cSrcweir 	nPos = aRsc.SearchAscii( "#2", nPos );
1333cdf0e10cSrcweir 	aRsc.Erase( nPos, 2 );
1334cdf0e10cSrcweir 	aRsc.Insert( aTmpStr, nPos );
1335cdf0e10cSrcweir 	nPos = sal::static_int_cast<xub_StrLen>( nPos + aTmpStr.Len() );
1336cdf0e10cSrcweir 
1337cdf0e10cSrcweir 	rStr += aRsc;
1338cdf0e10cSrcweir }
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir 
GetRefString(String & rStr,ScDocument * pDoc,sal_Bool bFlag3D) const1341cdf0e10cSrcweir void ScChangeActionMove::GetRefString( String& rStr, ScDocument* pDoc,
1342cdf0e10cSrcweir 		sal_Bool bFlag3D ) const
1343cdf0e10cSrcweir {
1344cdf0e10cSrcweir 	if ( !bFlag3D )
1345cdf0e10cSrcweir 		bFlag3D = ( GetFromRange().aStart.Tab() != GetBigRange().aStart.Tab() );
1346cdf0e10cSrcweir 	rStr = ScChangeAction::GetRefString( GetFromRange(), pDoc, bFlag3D );
1347cdf0e10cSrcweir 	rStr += ',';
1348cdf0e10cSrcweir 	rStr += ' ';
1349cdf0e10cSrcweir 	rStr += ScChangeAction::GetRefString( GetBigRange(), pDoc, bFlag3D );
1350cdf0e10cSrcweir }
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir 
Reject(ScDocument * pDoc)1353cdf0e10cSrcweir sal_Bool ScChangeActionMove::Reject( ScDocument* pDoc )
1354cdf0e10cSrcweir {
1355cdf0e10cSrcweir 	if ( !(aBigRange.IsValid( pDoc ) && aFromRange.IsValid( pDoc )) )
1356cdf0e10cSrcweir 		return sal_False;
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir 	ScRange aToRange( aBigRange.MakeRange() );
1359cdf0e10cSrcweir 	ScRange aFrmRange( aFromRange.MakeRange() );
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir 	sal_Bool bOk = pDoc->IsBlockEditable( aToRange.aStart.Tab(),
1362cdf0e10cSrcweir 		aToRange.aStart.Col(), aToRange.aStart.Row(),
1363cdf0e10cSrcweir 		aToRange.aEnd.Col(), aToRange.aEnd.Row() );
1364cdf0e10cSrcweir 	if ( bOk )
1365cdf0e10cSrcweir 		bOk = pDoc->IsBlockEditable( aFrmRange.aStart.Tab(),
1366cdf0e10cSrcweir 			aFrmRange.aStart.Col(), aFrmRange.aStart.Row(),
1367cdf0e10cSrcweir 			aFrmRange.aEnd.Col(), aFrmRange.aEnd.Row() );
1368cdf0e10cSrcweir 	if ( !bOk )
1369cdf0e10cSrcweir 		return sal_False;
1370cdf0e10cSrcweir 
1371cdf0e10cSrcweir 	pTrack->LookUpContents( aToRange, pDoc, 0, 0, 0 );	// zu movende Contents
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir 	pDoc->DeleteAreaTab( aToRange, IDF_ALL );
1374cdf0e10cSrcweir 	pDoc->DeleteAreaTab( aFrmRange, IDF_ALL );
1375cdf0e10cSrcweir 	// Formeln im Dokument anpassen
1376cdf0e10cSrcweir 	pDoc->UpdateReference( URM_MOVE,
1377cdf0e10cSrcweir 		aFrmRange.aStart.Col(), aFrmRange.aStart.Row(), aFrmRange.aStart.Tab(),
1378cdf0e10cSrcweir 		aFrmRange.aEnd.Col(), aFrmRange.aEnd.Row(), aFrmRange.aEnd.Tab(),
1379cdf0e10cSrcweir 		(SCsCOL) aFrmRange.aStart.Col() - aToRange.aStart.Col(),
1380cdf0e10cSrcweir 		(SCsROW) aFrmRange.aStart.Row() - aToRange.aStart.Row(),
1381cdf0e10cSrcweir 		(SCsTAB) aFrmRange.aStart.Tab() - aToRange.aStart.Tab(), NULL );
1382cdf0e10cSrcweir 
1383cdf0e10cSrcweir 	// LinkDependent freigeben, nachfolgendes UpdateReference-Undo setzt
1384cdf0e10cSrcweir 	// ToRange->FromRange Dependents
1385cdf0e10cSrcweir 	RemoveAllDependent();
1386cdf0e10cSrcweir 
1387cdf0e10cSrcweir 	// setzt rejected und ruft UpdateReference-Undo und DeleteCellEntries
1388cdf0e10cSrcweir 	RejectRestoreContents( pTrack, 0, 0 );
1389cdf0e10cSrcweir 
1390cdf0e10cSrcweir 	while ( pLinkDependent )
1391cdf0e10cSrcweir 	{
1392cdf0e10cSrcweir 		ScChangeAction* p = pLinkDependent->GetAction();
1393cdf0e10cSrcweir 		if ( p && p->GetType() == SC_CAT_CONTENT )
1394cdf0e10cSrcweir 		{
1395cdf0e10cSrcweir 			ScChangeActionContent* pContent = (ScChangeActionContent*) p;
1396cdf0e10cSrcweir 			if ( !pContent->IsDeletedIn() &&
1397cdf0e10cSrcweir 					pContent->GetBigRange().aStart.IsValid( pDoc ) )
1398cdf0e10cSrcweir 				pContent->PutNewValueToDoc( pDoc, 0, 0 );
1399cdf0e10cSrcweir 			// in LookUpContents generierte loeschen
1400cdf0e10cSrcweir 			if ( pTrack->IsGenerated( pContent->GetActionNumber() ) &&
1401cdf0e10cSrcweir 					!pContent->IsDeletedIn() )
1402cdf0e10cSrcweir 			{
1403cdf0e10cSrcweir 				pLinkDependent->UnLink();		//! sonst wird der mitgeloescht
1404cdf0e10cSrcweir 				pTrack->DeleteGeneratedDelContent( pContent );
1405cdf0e10cSrcweir 			}
1406cdf0e10cSrcweir 		}
1407cdf0e10cSrcweir 		delete pLinkDependent;
1408cdf0e10cSrcweir 	}
1409cdf0e10cSrcweir 
1410cdf0e10cSrcweir 	RemoveAllLinks();
1411cdf0e10cSrcweir 	return sal_True;
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir 
1415cdf0e10cSrcweir // --- ScChangeActionContent -----------------------------------------------
1416cdf0e10cSrcweir 
1417cdf0e10cSrcweir const sal_uInt16 nMemPoolChangeActionContent = (0x8000 - 64) / sizeof(ScChangeActionContent);
IMPL_FIXEDMEMPOOL_NEWDEL(ScChangeActionContent,nMemPoolChangeActionContent,nMemPoolChangeActionContent)1418cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeActionContent, nMemPoolChangeActionContent, nMemPoolChangeActionContent )
1419cdf0e10cSrcweir 
1420cdf0e10cSrcweir ScChangeActionContent::ScChangeActionContent( const sal_uLong nActionNumber,
1421cdf0e10cSrcweir             const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
1422cdf0e10cSrcweir             const ScBigRange& aBigRangeP, const String& aUserP,
1423cdf0e10cSrcweir             const DateTime& aDateTimeP, const String& sComment,
1424cdf0e10cSrcweir 			ScBaseCell* pTempOldCell, ScDocument* pDoc, const String& sOldValue )
1425cdf0e10cSrcweir 		:
1426cdf0e10cSrcweir         ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment),
1427cdf0e10cSrcweir 		aOldValue(sOldValue),
1428cdf0e10cSrcweir 		pOldCell(pTempOldCell),
1429cdf0e10cSrcweir 		pNewCell(NULL),
1430cdf0e10cSrcweir 		pNextContent(NULL),
1431cdf0e10cSrcweir 		pPrevContent(NULL),
1432cdf0e10cSrcweir 		pNextInSlot(NULL),
1433cdf0e10cSrcweir 		ppPrevInSlot(NULL)
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir {
1436cdf0e10cSrcweir 	if (pOldCell)
1437cdf0e10cSrcweir 		ScChangeActionContent::SetCell( aOldValue, pOldCell, 0, pDoc );
1438cdf0e10cSrcweir     if ( sOldValue.Len() )     // #i40704# don't overwrite SetCell result with empty string
1439cdf0e10cSrcweir         aOldValue = sOldValue; // set again, because SetCell removes it
1440cdf0e10cSrcweir }
1441cdf0e10cSrcweir 
ScChangeActionContent(const sal_uLong nActionNumber,ScBaseCell * pTempNewCell,const ScBigRange & aBigRangeP,ScDocument * pDoc,const String & sNewValue)1442cdf0e10cSrcweir ScChangeActionContent::ScChangeActionContent( const sal_uLong nActionNumber,
1443cdf0e10cSrcweir             ScBaseCell* pTempNewCell, const ScBigRange& aBigRangeP,
1444cdf0e10cSrcweir 			ScDocument* pDoc, const String& sNewValue )
1445cdf0e10cSrcweir 		:
1446cdf0e10cSrcweir         ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber),
1447cdf0e10cSrcweir         aNewValue(sNewValue),
1448cdf0e10cSrcweir 		pOldCell(NULL),
1449cdf0e10cSrcweir 		pNewCell(pTempNewCell),
1450cdf0e10cSrcweir 		pNextContent(NULL),
1451cdf0e10cSrcweir 		pPrevContent(NULL),
1452cdf0e10cSrcweir 		pNextInSlot(NULL),
1453cdf0e10cSrcweir 		ppPrevInSlot(NULL)
1454cdf0e10cSrcweir {
1455cdf0e10cSrcweir 	if (pNewCell)
1456cdf0e10cSrcweir 		ScChangeActionContent::SetCell( aNewValue, pNewCell, 0, pDoc );
1457cdf0e10cSrcweir     if ( sNewValue.Len() )     // #i40704# don't overwrite SetCell result with empty string
1458cdf0e10cSrcweir         aNewValue = sNewValue; // set again, because SetCell removes it
1459cdf0e10cSrcweir }
1460cdf0e10cSrcweir 
~ScChangeActionContent()1461cdf0e10cSrcweir ScChangeActionContent::~ScChangeActionContent()
1462cdf0e10cSrcweir {
1463cdf0e10cSrcweir 	ClearTrack();
1464cdf0e10cSrcweir }
1465cdf0e10cSrcweir 
1466cdf0e10cSrcweir 
ClearTrack()1467cdf0e10cSrcweir void ScChangeActionContent::ClearTrack()
1468cdf0e10cSrcweir {
1469cdf0e10cSrcweir 	RemoveFromSlot();
1470cdf0e10cSrcweir 	if ( pPrevContent )
1471cdf0e10cSrcweir 		pPrevContent->pNextContent = pNextContent;
1472cdf0e10cSrcweir 	if ( pNextContent )
1473cdf0e10cSrcweir 		pNextContent->pPrevContent = pPrevContent;
1474cdf0e10cSrcweir }
1475cdf0e10cSrcweir 
1476cdf0e10cSrcweir 
GetTopContent() const1477cdf0e10cSrcweir ScChangeActionContent* ScChangeActionContent::GetTopContent() const
1478cdf0e10cSrcweir {
1479cdf0e10cSrcweir 	if ( pNextContent )
1480cdf0e10cSrcweir 	{
1481cdf0e10cSrcweir 		ScChangeActionContent* pContent = pNextContent;
1482cdf0e10cSrcweir 		while ( pContent->pNextContent && pContent != pContent->pNextContent )
1483cdf0e10cSrcweir 			pContent = pContent->pNextContent;
1484cdf0e10cSrcweir 		return pContent;
1485cdf0e10cSrcweir 	}
1486cdf0e10cSrcweir 	return (ScChangeActionContent*) this;
1487cdf0e10cSrcweir }
1488cdf0e10cSrcweir 
1489cdf0e10cSrcweir 
GetDeletedIn() const1490cdf0e10cSrcweir ScChangeActionLinkEntry* ScChangeActionContent::GetDeletedIn() const
1491cdf0e10cSrcweir {
1492cdf0e10cSrcweir 	if ( pNextContent )
1493cdf0e10cSrcweir 		return GetTopContent()->pLinkDeletedIn;
1494cdf0e10cSrcweir 	return pLinkDeletedIn;
1495cdf0e10cSrcweir }
1496cdf0e10cSrcweir 
1497cdf0e10cSrcweir 
GetDeletedInAddress()1498cdf0e10cSrcweir ScChangeActionLinkEntry** ScChangeActionContent::GetDeletedInAddress()
1499cdf0e10cSrcweir {
1500cdf0e10cSrcweir 	if ( pNextContent )
1501cdf0e10cSrcweir 		return GetTopContent()->GetDeletedInAddress();
1502cdf0e10cSrcweir 	return &pLinkDeletedIn;
1503cdf0e10cSrcweir }
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir 
SetOldValue(const ScBaseCell * pCell,const ScDocument * pFromDoc,ScDocument * pToDoc,sal_uLong nFormat)1506cdf0e10cSrcweir void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
1507cdf0e10cSrcweir 		const ScDocument* pFromDoc, ScDocument* pToDoc, sal_uLong nFormat )
1508cdf0e10cSrcweir {
1509cdf0e10cSrcweir 	ScChangeActionContent::SetValue( aOldValue, pOldCell,
1510cdf0e10cSrcweir 		nFormat, pCell, pFromDoc, pToDoc );
1511cdf0e10cSrcweir }
1512cdf0e10cSrcweir 
1513cdf0e10cSrcweir 
SetOldValue(const ScBaseCell * pCell,const ScDocument * pFromDoc,ScDocument * pToDoc)1514cdf0e10cSrcweir void ScChangeActionContent::SetOldValue( const ScBaseCell* pCell,
1515cdf0e10cSrcweir 		const ScDocument* pFromDoc, ScDocument* pToDoc )
1516cdf0e10cSrcweir {
1517cdf0e10cSrcweir 	ScChangeActionContent::SetValue( aOldValue, pOldCell,
1518cdf0e10cSrcweir 		aBigRange.aStart.MakeAddress(), pCell, pFromDoc, pToDoc );
1519cdf0e10cSrcweir }
1520cdf0e10cSrcweir 
1521cdf0e10cSrcweir 
SetNewValue(const ScBaseCell * pCell,ScDocument * pDoc)1522cdf0e10cSrcweir void ScChangeActionContent::SetNewValue( const ScBaseCell* pCell,
1523cdf0e10cSrcweir 		ScDocument* pDoc )
1524cdf0e10cSrcweir {
1525cdf0e10cSrcweir 	ScChangeActionContent::SetValue( aNewValue, pNewCell,
1526cdf0e10cSrcweir 		aBigRange.aStart.MakeAddress(), pCell, pDoc, pDoc );
1527cdf0e10cSrcweir }
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir 
SetOldNewCells(ScBaseCell * pOldCellP,sal_uLong nOldFormat,ScBaseCell * pNewCellP,sal_uLong nNewFormat,ScDocument * pDoc)1530cdf0e10cSrcweir void ScChangeActionContent::SetOldNewCells( ScBaseCell* pOldCellP,
1531cdf0e10cSrcweir 						sal_uLong nOldFormat, ScBaseCell* pNewCellP,
1532cdf0e10cSrcweir 						sal_uLong nNewFormat, ScDocument* pDoc )
1533cdf0e10cSrcweir {
1534cdf0e10cSrcweir 	pOldCell = pOldCellP;
1535cdf0e10cSrcweir 	pNewCell = pNewCellP;
1536cdf0e10cSrcweir 	ScChangeActionContent::SetCell( aOldValue, pOldCell, nOldFormat, pDoc );
1537cdf0e10cSrcweir 	ScChangeActionContent::SetCell( aNewValue, pNewCell, nNewFormat, pDoc );
1538cdf0e10cSrcweir }
1539cdf0e10cSrcweir 
SetNewCell(ScBaseCell * pCell,ScDocument * pDoc,const String & rFormatted)1540cdf0e10cSrcweir void ScChangeActionContent::SetNewCell( ScBaseCell* pCell, ScDocument* pDoc, const String& rFormatted )
1541cdf0e10cSrcweir {
1542cdf0e10cSrcweir 	DBG_ASSERT( !pNewCell, "ScChangeActionContent::SetNewCell: overwriting existing cell" );
1543cdf0e10cSrcweir 	pNewCell = pCell;
1544cdf0e10cSrcweir 	ScChangeActionContent::SetCell( aNewValue, pNewCell, 0, pDoc );
1545cdf0e10cSrcweir 
1546cdf0e10cSrcweir     // #i40704# allow to set formatted text here - don't call SetNewValue with String from XML filter
1547cdf0e10cSrcweir     if ( rFormatted.Len() )
1548cdf0e10cSrcweir         aNewValue = rFormatted;
1549cdf0e10cSrcweir }
1550cdf0e10cSrcweir 
SetValueString(String & rValue,ScBaseCell * & pCell,const String & rStr,ScDocument * pDoc)1551cdf0e10cSrcweir void ScChangeActionContent::SetValueString( String& rValue, ScBaseCell*& pCell,
1552cdf0e10cSrcweir 		const String& rStr, ScDocument* pDoc )
1553cdf0e10cSrcweir {
1554cdf0e10cSrcweir 	if ( pCell )
1555cdf0e10cSrcweir 	{
1556cdf0e10cSrcweir 		pCell->Delete();
1557cdf0e10cSrcweir 		pCell = NULL;
1558cdf0e10cSrcweir 	}
1559cdf0e10cSrcweir 	if ( rStr.Len() > 1 && rStr.GetChar(0) == '=' )
1560cdf0e10cSrcweir 	{
1561cdf0e10cSrcweir 		rValue.Erase();
1562cdf0e10cSrcweir 		pCell = new ScFormulaCell(
1563cdf0e10cSrcweir             pDoc, aBigRange.aStart.MakeAddress(), rStr, formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::CONV_OOO );
1564cdf0e10cSrcweir 		((ScFormulaCell*)pCell)->SetInChangeTrack( sal_True );
1565cdf0e10cSrcweir 	}
1566cdf0e10cSrcweir 	else
1567cdf0e10cSrcweir 		rValue = rStr;
1568cdf0e10cSrcweir }
1569cdf0e10cSrcweir 
1570cdf0e10cSrcweir 
SetOldValue(const String & rOld,ScDocument * pDoc)1571cdf0e10cSrcweir void ScChangeActionContent::SetOldValue( const String& rOld, ScDocument* pDoc )
1572cdf0e10cSrcweir {
1573cdf0e10cSrcweir 	SetValueString( aOldValue, pOldCell, rOld, pDoc );
1574cdf0e10cSrcweir }
1575cdf0e10cSrcweir 
1576cdf0e10cSrcweir 
SetNewValue(const String & rNew,ScDocument * pDoc)1577cdf0e10cSrcweir void ScChangeActionContent::SetNewValue( const String& rNew, ScDocument* pDoc )
1578cdf0e10cSrcweir {
1579cdf0e10cSrcweir 	SetValueString( aNewValue, pNewCell, rNew, pDoc );
1580cdf0e10cSrcweir }
1581cdf0e10cSrcweir 
1582cdf0e10cSrcweir 
GetOldString(String & rStr) const1583cdf0e10cSrcweir void ScChangeActionContent::GetOldString( String& rStr ) const
1584cdf0e10cSrcweir {
1585cdf0e10cSrcweir 	GetValueString( rStr, aOldValue, pOldCell );
1586cdf0e10cSrcweir }
1587cdf0e10cSrcweir 
1588cdf0e10cSrcweir 
GetNewString(String & rStr) const1589cdf0e10cSrcweir void ScChangeActionContent::GetNewString( String& rStr ) const
1590cdf0e10cSrcweir {
1591cdf0e10cSrcweir 	GetValueString( rStr, aNewValue, pNewCell );
1592cdf0e10cSrcweir }
1593cdf0e10cSrcweir 
1594cdf0e10cSrcweir 
GetDescription(String & rStr,ScDocument * pDoc,sal_Bool bSplitRange,bool bWarning) const1595cdf0e10cSrcweir void ScChangeActionContent::GetDescription( String& rStr, ScDocument* pDoc,
1596cdf0e10cSrcweir 		sal_Bool bSplitRange, bool bWarning ) const
1597cdf0e10cSrcweir {
1598cdf0e10cSrcweir     ScChangeAction::GetDescription( rStr, pDoc, bSplitRange, bWarning );
1599cdf0e10cSrcweir 
1600cdf0e10cSrcweir 	String aRsc( ScGlobal::GetRscString( STR_CHANGED_CELL ) );
1601cdf0e10cSrcweir 
1602cdf0e10cSrcweir 	String aTmpStr;
1603cdf0e10cSrcweir 	GetRefString( aTmpStr, pDoc );
1604cdf0e10cSrcweir 
1605cdf0e10cSrcweir 	xub_StrLen nPos = 0;
1606cdf0e10cSrcweir 	nPos = aRsc.SearchAscii( "#1", nPos );
1607cdf0e10cSrcweir 	aRsc.Erase( nPos, 2 );
1608cdf0e10cSrcweir 	aRsc.Insert( aTmpStr, nPos );
1609cdf0e10cSrcweir     nPos = sal::static_int_cast<xub_StrLen>( nPos + aTmpStr.Len() );
1610cdf0e10cSrcweir 
1611cdf0e10cSrcweir 	GetOldString( aTmpStr );
1612cdf0e10cSrcweir 	if ( !aTmpStr.Len() )
1613cdf0e10cSrcweir 		aTmpStr = ScGlobal::GetRscString( STR_CHANGED_BLANK );
1614cdf0e10cSrcweir 	nPos = aRsc.SearchAscii( "#2", nPos );
1615cdf0e10cSrcweir 	aRsc.Erase( nPos, 2 );
1616cdf0e10cSrcweir 	aRsc.Insert( aTmpStr, nPos );
1617cdf0e10cSrcweir 	nPos = sal::static_int_cast<xub_StrLen>( nPos + aTmpStr.Len() );
1618cdf0e10cSrcweir 
1619cdf0e10cSrcweir 	GetNewString( aTmpStr );
1620cdf0e10cSrcweir 	if ( !aTmpStr.Len() )
1621cdf0e10cSrcweir 		aTmpStr = ScGlobal::GetRscString( STR_CHANGED_BLANK );
1622cdf0e10cSrcweir 	nPos = aRsc.SearchAscii( "#3", nPos );
1623cdf0e10cSrcweir 	aRsc.Erase( nPos, 2 );
1624cdf0e10cSrcweir 	aRsc.Insert( aTmpStr, nPos );
1625cdf0e10cSrcweir 
1626cdf0e10cSrcweir 	rStr += aRsc;
1627cdf0e10cSrcweir }
1628cdf0e10cSrcweir 
1629cdf0e10cSrcweir 
GetRefString(String & rStr,ScDocument * pDoc,sal_Bool bFlag3D) const1630cdf0e10cSrcweir void ScChangeActionContent::GetRefString( String& rStr, ScDocument* pDoc,
1631cdf0e10cSrcweir 		sal_Bool bFlag3D ) const
1632cdf0e10cSrcweir {
1633cdf0e10cSrcweir 	sal_uInt16 nFlags = ( GetBigRange().IsValid( pDoc ) ? SCA_VALID : 0 );
1634cdf0e10cSrcweir 	if ( nFlags )
1635cdf0e10cSrcweir 	{
1636cdf0e10cSrcweir 		const ScBaseCell* pCell = GetNewCell();
1637cdf0e10cSrcweir 		if ( ScChangeActionContent::GetContentCellType( pCell ) == SC_CACCT_MATORG )
1638cdf0e10cSrcweir 		{
1639cdf0e10cSrcweir             ScBigRange aLocalBigRange( GetBigRange() );
1640cdf0e10cSrcweir             SCCOL nC;
1641cdf0e10cSrcweir             SCROW nR;
1642cdf0e10cSrcweir             ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
1643cdf0e10cSrcweir             aLocalBigRange.aEnd.IncCol( nC-1 );
1644cdf0e10cSrcweir             aLocalBigRange.aEnd.IncRow( nR-1 );
1645cdf0e10cSrcweir             rStr = ScChangeAction::GetRefString( aLocalBigRange, pDoc, bFlag3D );
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir 			return ;
1648cdf0e10cSrcweir 		}
1649cdf0e10cSrcweir 
1650cdf0e10cSrcweir 		ScAddress aTmpAddress( GetBigRange().aStart.MakeAddress() );
1651cdf0e10cSrcweir 		if ( bFlag3D )
1652cdf0e10cSrcweir 			nFlags |= SCA_TAB_3D;
1653cdf0e10cSrcweir 		aTmpAddress.Format( rStr, nFlags, pDoc, pDoc->GetAddressConvention() );
1654cdf0e10cSrcweir 		if ( IsDeletedIn() )
1655cdf0e10cSrcweir 		{
1656cdf0e10cSrcweir 			rStr.Insert( '(', 0 );
1657cdf0e10cSrcweir 			rStr += ')';
1658cdf0e10cSrcweir 		}
1659cdf0e10cSrcweir 	}
1660cdf0e10cSrcweir 	else
1661cdf0e10cSrcweir 		rStr = ScGlobal::GetRscString( STR_NOREF_STR );
1662cdf0e10cSrcweir }
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir 
Reject(ScDocument * pDoc)1665cdf0e10cSrcweir sal_Bool ScChangeActionContent::Reject( ScDocument* pDoc )
1666cdf0e10cSrcweir {
1667cdf0e10cSrcweir 	if ( !aBigRange.IsValid( pDoc ) )
1668cdf0e10cSrcweir 		return sal_False;
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir 	PutOldValueToDoc( pDoc, 0, 0 );
1671cdf0e10cSrcweir 
1672cdf0e10cSrcweir 	SetState( SC_CAS_REJECTED );
1673cdf0e10cSrcweir 	RemoveAllLinks();
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir 	return sal_True;
1676cdf0e10cSrcweir }
1677cdf0e10cSrcweir 
1678cdf0e10cSrcweir 
Select(ScDocument * pDoc,ScChangeTrack * pTrack,sal_Bool bOldest,Stack * pRejectActions)1679cdf0e10cSrcweir sal_Bool ScChangeActionContent::Select( ScDocument* pDoc, ScChangeTrack* pTrack,
1680cdf0e10cSrcweir 		sal_Bool bOldest, Stack* pRejectActions )
1681cdf0e10cSrcweir {
1682cdf0e10cSrcweir 	if ( !aBigRange.IsValid( pDoc ) )
1683cdf0e10cSrcweir 		return sal_False;
1684cdf0e10cSrcweir 
1685cdf0e10cSrcweir 	ScChangeActionContent* pContent = this;
1686cdf0e10cSrcweir 	// accept previous contents
1687cdf0e10cSrcweir     while ( ( pContent = pContent->pPrevContent ) != NULL )
1688cdf0e10cSrcweir 	{
1689cdf0e10cSrcweir 		if ( pContent->IsVirgin() )
1690cdf0e10cSrcweir 			pContent->SetState( SC_CAS_ACCEPTED );
1691cdf0e10cSrcweir 	}
1692cdf0e10cSrcweir 	ScChangeActionContent* pEnd = pContent = this;
1693cdf0e10cSrcweir 	// reject subsequent contents
1694cdf0e10cSrcweir     while ( ( pContent = pContent->pNextContent ) != NULL )
1695cdf0e10cSrcweir 	{
1696cdf0e10cSrcweir 		// MatrixOrigin may have dependents, no dependency recursion needed
1697cdf0e10cSrcweir 		const ScChangeActionLinkEntry* pL = pContent->GetFirstDependentEntry();
1698cdf0e10cSrcweir 		while ( pL )
1699cdf0e10cSrcweir 		{
1700cdf0e10cSrcweir 			ScChangeAction* p = (ScChangeAction*) pL->GetAction();
1701cdf0e10cSrcweir 			if ( p )
1702cdf0e10cSrcweir 				p->SetRejected();
1703cdf0e10cSrcweir 			pL = pL->GetNext();
1704cdf0e10cSrcweir 		}
1705cdf0e10cSrcweir 		pContent->SetRejected();
1706cdf0e10cSrcweir 		pEnd = pContent;
1707cdf0e10cSrcweir 	}
1708cdf0e10cSrcweir 
1709cdf0e10cSrcweir 	if ( bOldest || pEnd != this )
1710cdf0e10cSrcweir 	{	// wenn nicht aeltester: ist es ueberhaupt ein anderer als der letzte?
1711cdf0e10cSrcweir 		ScRange aRange( aBigRange.aStart.MakeAddress() );
1712cdf0e10cSrcweir 		const ScAddress& rPos = aRange.aStart;
1713cdf0e10cSrcweir 
1714cdf0e10cSrcweir 		ScChangeActionContent* pNew = new ScChangeActionContent( aRange );
1715cdf0e10cSrcweir 		pNew->SetOldValue( pDoc->GetCell( rPos ), pDoc, pDoc );
1716cdf0e10cSrcweir 
1717cdf0e10cSrcweir 		if ( bOldest )
1718cdf0e10cSrcweir 			PutOldValueToDoc( pDoc, 0, 0 );
1719cdf0e10cSrcweir 		else
1720cdf0e10cSrcweir 			PutNewValueToDoc( pDoc, 0, 0 );
1721cdf0e10cSrcweir 
1722cdf0e10cSrcweir 		pNew->SetRejectAction( bOldest ? GetActionNumber() : pEnd->GetActionNumber() );
1723cdf0e10cSrcweir 		pNew->SetState( SC_CAS_ACCEPTED );
1724cdf0e10cSrcweir 		if ( pRejectActions )
1725cdf0e10cSrcweir 			pRejectActions->Push( pNew );
1726cdf0e10cSrcweir 		else
1727cdf0e10cSrcweir 		{
1728cdf0e10cSrcweir 			pNew->SetNewValue( pDoc->GetCell( rPos ), pDoc );
1729cdf0e10cSrcweir 			pTrack->Append( pNew );
1730cdf0e10cSrcweir 		}
1731cdf0e10cSrcweir 	}
1732cdf0e10cSrcweir 
1733cdf0e10cSrcweir 	if ( bOldest )
1734cdf0e10cSrcweir 		SetRejected();
1735cdf0e10cSrcweir 	else
1736cdf0e10cSrcweir 		SetState( SC_CAS_ACCEPTED );
1737cdf0e10cSrcweir 
1738cdf0e10cSrcweir 	return sal_True;
1739cdf0e10cSrcweir }
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir 
1742cdf0e10cSrcweir // static
GetStringOfCell(String & rStr,const ScBaseCell * pCell,const ScDocument * pDoc,const ScAddress & rPos)1743cdf0e10cSrcweir void ScChangeActionContent::GetStringOfCell( String& rStr,
1744cdf0e10cSrcweir 		const ScBaseCell* pCell, const ScDocument* pDoc, const ScAddress& rPos )
1745cdf0e10cSrcweir {
1746cdf0e10cSrcweir 	if ( pCell )
1747cdf0e10cSrcweir 	{
1748cdf0e10cSrcweir 		if ( ScChangeActionContent::NeedsNumberFormat( pCell ) )
1749cdf0e10cSrcweir 			GetStringOfCell( rStr, pCell, pDoc, pDoc->GetNumberFormat( rPos ) );
1750cdf0e10cSrcweir 		else
1751cdf0e10cSrcweir 			GetStringOfCell( rStr, pCell, pDoc, 0 );
1752cdf0e10cSrcweir 	}
1753cdf0e10cSrcweir 	else
1754cdf0e10cSrcweir 		rStr.Erase();
1755cdf0e10cSrcweir }
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir 
1758cdf0e10cSrcweir // static
GetStringOfCell(String & rStr,const ScBaseCell * pCell,const ScDocument * pDoc,sal_uLong nFormat)1759cdf0e10cSrcweir void ScChangeActionContent::GetStringOfCell( String& rStr,
1760cdf0e10cSrcweir 		const ScBaseCell* pCell, const ScDocument* pDoc, sal_uLong nFormat )
1761cdf0e10cSrcweir {
1762cdf0e10cSrcweir 	if ( ScChangeActionContent::GetContentCellType( pCell ) )
1763cdf0e10cSrcweir 	{
1764cdf0e10cSrcweir 		switch ( pCell->GetCellType() )
1765cdf0e10cSrcweir 		{
1766cdf0e10cSrcweir 			case CELLTYPE_VALUE :
1767cdf0e10cSrcweir 			{
1768cdf0e10cSrcweir 				double nValue = ((ScValueCell*)pCell)->GetValue();
1769cdf0e10cSrcweir 				pDoc->GetFormatTable()->GetInputLineString( nValue,	nFormat,
1770cdf0e10cSrcweir 					rStr );
1771cdf0e10cSrcweir 			}
1772cdf0e10cSrcweir 			break;
1773cdf0e10cSrcweir 			case CELLTYPE_STRING :
1774cdf0e10cSrcweir 				((ScStringCell*)pCell)->GetString( rStr );
1775cdf0e10cSrcweir 			break;
1776cdf0e10cSrcweir 			case CELLTYPE_EDIT :
1777cdf0e10cSrcweir 				((ScEditCell*)pCell)->GetString( rStr );
1778cdf0e10cSrcweir 			break;
1779cdf0e10cSrcweir 			case CELLTYPE_FORMULA :
1780cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->GetFormula( rStr );
1781cdf0e10cSrcweir 			break;
1782cdf0e10cSrcweir 			default:
1783cdf0e10cSrcweir 				rStr.Erase();
1784cdf0e10cSrcweir 		}
1785cdf0e10cSrcweir 	}
1786cdf0e10cSrcweir 	else
1787cdf0e10cSrcweir 		rStr.Erase();
1788cdf0e10cSrcweir }
1789cdf0e10cSrcweir 
1790cdf0e10cSrcweir 
1791cdf0e10cSrcweir // static
GetContentCellType(const ScBaseCell * pCell)1792cdf0e10cSrcweir ScChangeActionContentCellType ScChangeActionContent::GetContentCellType( const ScBaseCell* pCell )
1793cdf0e10cSrcweir {
1794cdf0e10cSrcweir 	if ( pCell )
1795cdf0e10cSrcweir 	{
1796cdf0e10cSrcweir 		switch ( pCell->GetCellType() )
1797cdf0e10cSrcweir 		{
1798cdf0e10cSrcweir 			case CELLTYPE_VALUE :
1799cdf0e10cSrcweir 			case CELLTYPE_STRING :
1800cdf0e10cSrcweir 			case CELLTYPE_EDIT :
1801cdf0e10cSrcweir 				return SC_CACCT_NORMAL;
1802cdf0e10cSrcweir             //break;
1803cdf0e10cSrcweir 			case CELLTYPE_FORMULA :
1804cdf0e10cSrcweir 				switch ( ((const ScFormulaCell*)pCell)->GetMatrixFlag() )
1805cdf0e10cSrcweir 				{
1806cdf0e10cSrcweir 					case MM_NONE :
1807cdf0e10cSrcweir 						return SC_CACCT_NORMAL;
1808cdf0e10cSrcweir                     //break;
1809cdf0e10cSrcweir 					case MM_FORMULA :
1810cdf0e10cSrcweir 					case MM_FAKE :
1811cdf0e10cSrcweir 						return SC_CACCT_MATORG;
1812cdf0e10cSrcweir                     //break;
1813cdf0e10cSrcweir 					case MM_REFERENCE :
1814cdf0e10cSrcweir 						return SC_CACCT_MATREF;
1815cdf0e10cSrcweir                     //break;
1816cdf0e10cSrcweir 				}
1817cdf0e10cSrcweir 				return SC_CACCT_NORMAL;
1818cdf0e10cSrcweir             //break;
1819cdf0e10cSrcweir 			default:
1820cdf0e10cSrcweir 				return SC_CACCT_NONE;
1821cdf0e10cSrcweir 		}
1822cdf0e10cSrcweir 	}
1823cdf0e10cSrcweir 	return SC_CACCT_NONE;
1824cdf0e10cSrcweir }
1825cdf0e10cSrcweir 
1826cdf0e10cSrcweir 
1827cdf0e10cSrcweir // static
NeedsNumberFormat(const ScBaseCell * pCell)1828cdf0e10cSrcweir sal_Bool ScChangeActionContent::NeedsNumberFormat( const ScBaseCell* pCell )
1829cdf0e10cSrcweir {
1830cdf0e10cSrcweir 	return pCell && pCell->GetCellType() == CELLTYPE_VALUE;
1831cdf0e10cSrcweir }
1832cdf0e10cSrcweir 
1833cdf0e10cSrcweir 
1834cdf0e10cSrcweir // static
SetValue(String & rStr,ScBaseCell * & pCell,const ScAddress & rPos,const ScBaseCell * pOrgCell,const ScDocument * pFromDoc,ScDocument * pToDoc)1835cdf0e10cSrcweir void ScChangeActionContent::SetValue( String& rStr, ScBaseCell*& pCell,
1836cdf0e10cSrcweir 		const ScAddress& rPos, const ScBaseCell* pOrgCell,
1837cdf0e10cSrcweir 		const ScDocument* pFromDoc, ScDocument* pToDoc )
1838cdf0e10cSrcweir {
1839cdf0e10cSrcweir 	sal_uLong nFormat = NeedsNumberFormat( pOrgCell ) ? pFromDoc->GetNumberFormat( rPos ) : 0;
1840cdf0e10cSrcweir     SetValue( rStr, pCell, nFormat, pOrgCell, pFromDoc, pToDoc );
1841cdf0e10cSrcweir }
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir 
1844cdf0e10cSrcweir // static
SetValue(String & rStr,ScBaseCell * & pCell,sal_uLong nFormat,const ScBaseCell * pOrgCell,const ScDocument * pFromDoc,ScDocument * pToDoc)1845cdf0e10cSrcweir void ScChangeActionContent::SetValue( String& rStr, ScBaseCell*& pCell,
1846cdf0e10cSrcweir 		sal_uLong nFormat, const ScBaseCell* pOrgCell,
1847cdf0e10cSrcweir 		const ScDocument* pFromDoc, ScDocument* pToDoc )
1848cdf0e10cSrcweir {
1849cdf0e10cSrcweir 	rStr.Erase();
1850cdf0e10cSrcweir 	if ( pCell )
1851cdf0e10cSrcweir 		pCell->Delete();
1852cdf0e10cSrcweir 	if ( ScChangeActionContent::GetContentCellType( pOrgCell ) )
1853cdf0e10cSrcweir 	{
1854cdf0e10cSrcweir         pCell = pOrgCell->CloneWithoutNote( *pToDoc );
1855cdf0e10cSrcweir 		switch ( pOrgCell->GetCellType() )
1856cdf0e10cSrcweir 		{
1857cdf0e10cSrcweir 			case CELLTYPE_VALUE :
1858cdf0e10cSrcweir 			{	// z.B. Datum auch als solches merken
1859cdf0e10cSrcweir 				double nValue = ((ScValueCell*)pOrgCell)->GetValue();
1860cdf0e10cSrcweir 				pFromDoc->GetFormatTable()->GetInputLineString( nValue,
1861cdf0e10cSrcweir 					nFormat, rStr );
1862cdf0e10cSrcweir 			}
1863cdf0e10cSrcweir 			break;
1864cdf0e10cSrcweir 			case CELLTYPE_FORMULA :
1865cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->SetInChangeTrack( sal_True );
1866cdf0e10cSrcweir 			break;
1867cdf0e10cSrcweir             default:
1868cdf0e10cSrcweir             {
1869cdf0e10cSrcweir                 // added to avoid warnings
1870cdf0e10cSrcweir             }
1871cdf0e10cSrcweir 		}
1872cdf0e10cSrcweir 	}
1873cdf0e10cSrcweir 	else
1874cdf0e10cSrcweir 		pCell = NULL;
1875cdf0e10cSrcweir }
1876cdf0e10cSrcweir 
1877cdf0e10cSrcweir 
1878cdf0e10cSrcweir // static
SetCell(String & rStr,ScBaseCell * pCell,sal_uLong nFormat,const ScDocument * pDoc)1879cdf0e10cSrcweir void ScChangeActionContent::SetCell( String& rStr, ScBaseCell* pCell,
1880cdf0e10cSrcweir 		sal_uLong nFormat, const ScDocument* pDoc )
1881cdf0e10cSrcweir {
1882cdf0e10cSrcweir 	rStr.Erase();
1883cdf0e10cSrcweir 	if ( pCell )
1884cdf0e10cSrcweir 	{
1885cdf0e10cSrcweir 		switch ( pCell->GetCellType() )
1886cdf0e10cSrcweir 		{
1887cdf0e10cSrcweir 			case CELLTYPE_VALUE :
1888cdf0e10cSrcweir 			{	// e.g. remember date as date string
1889cdf0e10cSrcweir 				double nValue = ((ScValueCell*)pCell)->GetValue();
1890cdf0e10cSrcweir 				pDoc->GetFormatTable()->GetInputLineString( nValue,
1891cdf0e10cSrcweir 					nFormat, rStr );
1892cdf0e10cSrcweir 			}
1893cdf0e10cSrcweir 			break;
1894cdf0e10cSrcweir 			case CELLTYPE_FORMULA :
1895cdf0e10cSrcweir 				((ScFormulaCell*)pCell)->SetInChangeTrack( sal_True );
1896cdf0e10cSrcweir 			break;
1897cdf0e10cSrcweir             default:
1898cdf0e10cSrcweir             {
1899cdf0e10cSrcweir                 // added to avoid warnings
1900cdf0e10cSrcweir             }
1901cdf0e10cSrcweir 		}
1902cdf0e10cSrcweir 	}
1903cdf0e10cSrcweir }
1904cdf0e10cSrcweir 
1905cdf0e10cSrcweir 
GetValueString(String & rStr,const String & rValue,const ScBaseCell * pCell) const1906cdf0e10cSrcweir void ScChangeActionContent::GetValueString( String& rStr,
1907cdf0e10cSrcweir 		const String& rValue, const ScBaseCell* pCell ) const
1908cdf0e10cSrcweir {
1909cdf0e10cSrcweir 	if ( !rValue.Len() )
1910cdf0e10cSrcweir 	{
1911cdf0e10cSrcweir 		if ( pCell )
1912cdf0e10cSrcweir 		{
1913cdf0e10cSrcweir 			switch ( pCell->GetCellType() )
1914cdf0e10cSrcweir 			{
1915cdf0e10cSrcweir 				case CELLTYPE_STRING :
1916cdf0e10cSrcweir 					((ScStringCell*)pCell)->GetString( rStr );
1917cdf0e10cSrcweir 				break;
1918cdf0e10cSrcweir 				case CELLTYPE_EDIT :
1919cdf0e10cSrcweir 					((ScEditCell*)pCell)->GetString( rStr );
1920cdf0e10cSrcweir 				break;
1921cdf0e10cSrcweir 				case CELLTYPE_VALUE :	// ist immer in rValue
1922cdf0e10cSrcweir 					rStr = rValue;
1923cdf0e10cSrcweir 				break;
1924cdf0e10cSrcweir 				case CELLTYPE_FORMULA :
1925cdf0e10cSrcweir 					GetFormulaString( rStr, (ScFormulaCell*) pCell );
1926cdf0e10cSrcweir 				break;
1927cdf0e10cSrcweir                 default:
1928cdf0e10cSrcweir                 {
1929cdf0e10cSrcweir                     // added to avoid warnings
1930cdf0e10cSrcweir                 }
1931cdf0e10cSrcweir 			}
1932cdf0e10cSrcweir 		}
1933cdf0e10cSrcweir 		else
1934cdf0e10cSrcweir 			rStr.Erase();
1935cdf0e10cSrcweir 	}
1936cdf0e10cSrcweir 	else
1937cdf0e10cSrcweir 		rStr = rValue;
1938cdf0e10cSrcweir }
1939cdf0e10cSrcweir 
1940cdf0e10cSrcweir 
GetFormulaString(String & rStr,const ScFormulaCell * pCell) const1941cdf0e10cSrcweir void ScChangeActionContent::GetFormulaString( String& rStr,
1942cdf0e10cSrcweir 		const ScFormulaCell* pCell ) const
1943cdf0e10cSrcweir {
1944cdf0e10cSrcweir 	ScAddress aPos( aBigRange.aStart.MakeAddress() );
1945cdf0e10cSrcweir 	if ( aPos == pCell->aPos || IsDeletedIn() )
1946cdf0e10cSrcweir 		pCell->GetFormula( rStr );
1947cdf0e10cSrcweir 	else
1948cdf0e10cSrcweir 	{
1949cdf0e10cSrcweir 		DBG_ERROR( "ScChangeActionContent::GetFormulaString: aPos != pCell->aPos" );
1950cdf0e10cSrcweir         ScFormulaCell* pNew = new ScFormulaCell( *pCell, *pCell->GetDocument(), aPos );
1951cdf0e10cSrcweir 		pNew->GetFormula( rStr );
1952cdf0e10cSrcweir 		delete pNew;
1953cdf0e10cSrcweir 	}
1954cdf0e10cSrcweir }
1955cdf0e10cSrcweir 
1956cdf0e10cSrcweir 
PutOldValueToDoc(ScDocument * pDoc,SCsCOL nDx,SCsROW nDy) const1957cdf0e10cSrcweir void ScChangeActionContent::PutOldValueToDoc( ScDocument* pDoc,
1958cdf0e10cSrcweir 		SCsCOL nDx, SCsROW nDy ) const
1959cdf0e10cSrcweir {
1960cdf0e10cSrcweir 	PutValueToDoc( pOldCell, aOldValue, pDoc, nDx, nDy );
1961cdf0e10cSrcweir }
1962cdf0e10cSrcweir 
1963cdf0e10cSrcweir 
PutNewValueToDoc(ScDocument * pDoc,SCsCOL nDx,SCsROW nDy) const1964cdf0e10cSrcweir void ScChangeActionContent::PutNewValueToDoc( ScDocument* pDoc,
1965cdf0e10cSrcweir 		SCsCOL nDx, SCsROW nDy ) const
1966cdf0e10cSrcweir {
1967cdf0e10cSrcweir 	PutValueToDoc( pNewCell, aNewValue, pDoc, nDx, nDy );
1968cdf0e10cSrcweir }
1969cdf0e10cSrcweir 
1970cdf0e10cSrcweir 
PutValueToDoc(ScBaseCell * pCell,const String & rValue,ScDocument * pDoc,SCsCOL nDx,SCsROW nDy) const1971cdf0e10cSrcweir void ScChangeActionContent::PutValueToDoc( ScBaseCell* pCell,
1972cdf0e10cSrcweir 		const String& rValue, ScDocument* pDoc, SCsCOL nDx, SCsROW nDy ) const
1973cdf0e10cSrcweir {
1974cdf0e10cSrcweir 	ScAddress aPos( aBigRange.aStart.MakeAddress() );
1975cdf0e10cSrcweir 	if ( nDx )
1976cdf0e10cSrcweir 		aPos.IncCol( nDx );
1977cdf0e10cSrcweir 	if ( nDy )
1978cdf0e10cSrcweir 		aPos.IncRow( nDy );
1979cdf0e10cSrcweir 	if ( !rValue.Len() )
1980cdf0e10cSrcweir 	{
1981cdf0e10cSrcweir 		if ( pCell )
1982cdf0e10cSrcweir 		{
1983cdf0e10cSrcweir 			switch ( pCell->GetCellType() )
1984cdf0e10cSrcweir 			{
1985cdf0e10cSrcweir 				case CELLTYPE_VALUE :	// ist immer in rValue
1986cdf0e10cSrcweir 					pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
1987cdf0e10cSrcweir 				break;
1988cdf0e10cSrcweir 				default:
1989cdf0e10cSrcweir 					switch ( ScChangeActionContent::GetContentCellType( pCell ) )
1990cdf0e10cSrcweir 					{
1991cdf0e10cSrcweir 						case SC_CACCT_MATORG :
1992cdf0e10cSrcweir 						{
1993cdf0e10cSrcweir                             SCCOL nC;
1994cdf0e10cSrcweir                             SCROW nR;
1995cdf0e10cSrcweir                             ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
1996cdf0e10cSrcweir 							DBG_ASSERT( nC>0 && nR>0, "ScChangeActionContent::PutValueToDoc: MatColsRows?" );
1997cdf0e10cSrcweir 							ScRange aRange( aPos );
1998cdf0e10cSrcweir 							if ( nC > 1 )
1999cdf0e10cSrcweir 								aRange.aEnd.IncCol( nC-1 );
2000cdf0e10cSrcweir 							if ( nR > 1 )
2001cdf0e10cSrcweir 								aRange.aEnd.IncRow( nR-1 );
2002cdf0e10cSrcweir 							ScMarkData aDestMark;
2003cdf0e10cSrcweir 							aDestMark.SelectOneTable( aPos.Tab() );
2004cdf0e10cSrcweir 							aDestMark.SetMarkArea( aRange );
2005cdf0e10cSrcweir 							pDoc->InsertMatrixFormula( aPos.Col(), aPos.Row(),
2006cdf0e10cSrcweir 								aRange.aEnd.Col(), aRange.aEnd.Row(),
2007cdf0e10cSrcweir 								aDestMark, EMPTY_STRING,
2008cdf0e10cSrcweir 								((const ScFormulaCell*)pCell)->GetCode() );
2009cdf0e10cSrcweir 						}
2010cdf0e10cSrcweir 						break;
2011cdf0e10cSrcweir 						case SC_CACCT_MATREF :
2012cdf0e10cSrcweir 							// nothing
2013cdf0e10cSrcweir 						break;
2014cdf0e10cSrcweir 						default:
2015cdf0e10cSrcweir                             pDoc->PutCell( aPos, pCell->CloneWithoutNote( *pDoc ) );
2016cdf0e10cSrcweir 					}
2017cdf0e10cSrcweir 			}
2018cdf0e10cSrcweir 		}
2019cdf0e10cSrcweir 		else
2020cdf0e10cSrcweir 			pDoc->PutCell( aPos, NULL );
2021cdf0e10cSrcweir 	}
2022cdf0e10cSrcweir 	else
2023cdf0e10cSrcweir 		pDoc->SetString( aPos.Col(), aPos.Row(), aPos.Tab(), rValue );
2024cdf0e10cSrcweir }
2025cdf0e10cSrcweir 
2026cdf0e10cSrcweir 
lcl_InvalidateReference(ScToken & rTok,const ScBigAddress & rPos)2027cdf0e10cSrcweir void lcl_InvalidateReference( ScToken& rTok, const ScBigAddress& rPos )
2028cdf0e10cSrcweir {
2029cdf0e10cSrcweir 	ScSingleRefData& rRef1 = rTok.GetSingleRef();
2030cdf0e10cSrcweir 	if ( rPos.Col() < 0 || MAXCOL < rPos.Col() )
2031cdf0e10cSrcweir 	{
2032cdf0e10cSrcweir 		rRef1.nCol = SCCOL_MAX;
2033cdf0e10cSrcweir 		rRef1.nRelCol = SCCOL_MAX;
2034cdf0e10cSrcweir 		rRef1.SetColDeleted( sal_True );
2035cdf0e10cSrcweir 	}
2036cdf0e10cSrcweir 	if ( rPos.Row() < 0 || MAXROW < rPos.Row() )
2037cdf0e10cSrcweir 	{
2038cdf0e10cSrcweir 		rRef1.nRow = SCROW_MAX;
2039cdf0e10cSrcweir 		rRef1.nRelRow = SCROW_MAX;
2040cdf0e10cSrcweir 		rRef1.SetRowDeleted( sal_True );
2041cdf0e10cSrcweir 	}
2042cdf0e10cSrcweir 	if ( rPos.Tab() < 0 || MAXTAB < rPos.Tab() )
2043cdf0e10cSrcweir 	{
2044cdf0e10cSrcweir 		rRef1.nTab = SCTAB_MAX;
2045cdf0e10cSrcweir 		rRef1.nRelTab = SCTAB_MAX;
2046cdf0e10cSrcweir 		rRef1.SetTabDeleted( sal_True );
2047cdf0e10cSrcweir 	}
2048cdf0e10cSrcweir 	if ( rTok.GetType() == formula::svDoubleRef )
2049cdf0e10cSrcweir 	{
2050cdf0e10cSrcweir 		ScSingleRefData& rRef2 = rTok.GetDoubleRef().Ref2;
2051cdf0e10cSrcweir 		if ( rPos.Col() < 0 || MAXCOL < rPos.Col() )
2052cdf0e10cSrcweir 		{
2053cdf0e10cSrcweir 			rRef2.nCol = SCCOL_MAX;
2054cdf0e10cSrcweir 			rRef2.nRelCol = SCCOL_MAX;
2055cdf0e10cSrcweir 			rRef2.SetColDeleted( sal_True );
2056cdf0e10cSrcweir 		}
2057cdf0e10cSrcweir 		if ( rPos.Row() < 0 || MAXROW < rPos.Row() )
2058cdf0e10cSrcweir 		{
2059cdf0e10cSrcweir 			rRef2.nRow = SCROW_MAX;
2060cdf0e10cSrcweir 			rRef2.nRelRow = SCROW_MAX;
2061cdf0e10cSrcweir 			rRef2.SetRowDeleted( sal_True );
2062cdf0e10cSrcweir 		}
2063cdf0e10cSrcweir 		if ( rPos.Tab() < 0 || MAXTAB < rPos.Tab() )
2064cdf0e10cSrcweir 		{
2065cdf0e10cSrcweir 			rRef2.nTab = SCTAB_MAX;
2066cdf0e10cSrcweir 			rRef2.nRelTab = SCTAB_MAX;
2067cdf0e10cSrcweir 			rRef2.SetTabDeleted( sal_True );
2068cdf0e10cSrcweir 		}
2069cdf0e10cSrcweir 	}
2070cdf0e10cSrcweir }
2071cdf0e10cSrcweir 
2072cdf0e10cSrcweir 
UpdateReference(const ScChangeTrack * pTrack,UpdateRefMode eMode,const ScBigRange & rRange,sal_Int32 nDx,sal_Int32 nDy,sal_Int32 nDz)2073cdf0e10cSrcweir void ScChangeActionContent::UpdateReference( const ScChangeTrack* pTrack,
2074cdf0e10cSrcweir 		UpdateRefMode eMode, const ScBigRange& rRange,
2075cdf0e10cSrcweir 		sal_Int32 nDx, sal_Int32 nDy, sal_Int32 nDz )
2076cdf0e10cSrcweir {
2077cdf0e10cSrcweir 	SCSIZE nOldSlot = ScChangeTrack::ComputeContentSlot( aBigRange.aStart.Row() );
2078cdf0e10cSrcweir 	ScRefUpdate::Update( eMode, rRange, nDx, nDy, nDz, aBigRange );
2079cdf0e10cSrcweir 	SCSIZE nNewSlot = ScChangeTrack::ComputeContentSlot( aBigRange.aStart.Row() );
2080cdf0e10cSrcweir 	if ( nNewSlot != nOldSlot )
2081cdf0e10cSrcweir 	{
2082cdf0e10cSrcweir 		RemoveFromSlot();
2083cdf0e10cSrcweir 		InsertInSlot( &(pTrack->GetContentSlots()[nNewSlot]) );
2084cdf0e10cSrcweir 	}
2085cdf0e10cSrcweir 
2086cdf0e10cSrcweir 	if ( pTrack->IsInDelete() && !pTrack->IsInDeleteTop() )
2087cdf0e10cSrcweir 		return ;		// Formeln nur kompletten Bereich updaten
2088cdf0e10cSrcweir 
2089cdf0e10cSrcweir 	sal_Bool bOldFormula = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_FORMULA );
2090cdf0e10cSrcweir 	sal_Bool bNewFormula = ( pNewCell && pNewCell->GetCellType() == CELLTYPE_FORMULA );
2091cdf0e10cSrcweir 	if ( bOldFormula || bNewFormula )
2092cdf0e10cSrcweir 	{	// via ScFormulaCell UpdateReference anpassen (dort)
2093cdf0e10cSrcweir 		if ( pTrack->IsInDelete() )
2094cdf0e10cSrcweir 		{
2095cdf0e10cSrcweir 			const ScRange& rDelRange = pTrack->GetInDeleteRange();
2096cdf0e10cSrcweir 			if ( nDx > 0 )
2097cdf0e10cSrcweir 				nDx = rDelRange.aEnd.Col() - rDelRange.aStart.Col() + 1;
2098cdf0e10cSrcweir 			else if ( nDx < 0 )
2099cdf0e10cSrcweir 				nDx = -(rDelRange.aEnd.Col() - rDelRange.aStart.Col() + 1);
2100cdf0e10cSrcweir 			if ( nDy > 0 )
2101cdf0e10cSrcweir 				nDy = rDelRange.aEnd.Row() - rDelRange.aStart.Row() + 1;
2102cdf0e10cSrcweir 			else if ( nDy < 0 )
2103cdf0e10cSrcweir 				nDy = -(rDelRange.aEnd.Row() - rDelRange.aStart.Row() + 1);
2104cdf0e10cSrcweir 			if ( nDz > 0 )
2105cdf0e10cSrcweir 				nDz = rDelRange.aEnd.Tab() - rDelRange.aStart.Tab() + 1;
2106cdf0e10cSrcweir 			else if ( nDz < 0 )
2107cdf0e10cSrcweir 				nDz = -(rDelRange.aEnd.Tab() - rDelRange.aStart.Tab() + 1);
2108cdf0e10cSrcweir 		}
2109cdf0e10cSrcweir 		ScBigRange aTmpRange( rRange );
2110cdf0e10cSrcweir 		switch ( eMode )
2111cdf0e10cSrcweir 		{
2112cdf0e10cSrcweir 			case URM_INSDEL :
2113cdf0e10cSrcweir 				if ( nDx < 0 || nDy < 0 || nDz < 0 )
2114cdf0e10cSrcweir 				{	// Delete startet dort hinter geloeschtem Bereich,
2115cdf0e10cSrcweir 					// Position wird dort angepasst.
2116cdf0e10cSrcweir 					if ( nDx )
2117cdf0e10cSrcweir 						aTmpRange.aStart.IncCol( -nDx );
2118cdf0e10cSrcweir 					if ( nDy )
2119cdf0e10cSrcweir 						aTmpRange.aStart.IncRow( -nDy );
2120cdf0e10cSrcweir 					if ( nDz )
2121cdf0e10cSrcweir 						aTmpRange.aStart.IncTab( -nDz );
2122cdf0e10cSrcweir 				}
2123cdf0e10cSrcweir 			break;
2124cdf0e10cSrcweir 			case URM_MOVE :
2125cdf0e10cSrcweir 				// Move ist hier Quelle, dort Ziel,
2126cdf0e10cSrcweir 				// Position muss vorher angepasst sein.
2127cdf0e10cSrcweir 				if ( bOldFormula )
2128cdf0e10cSrcweir 					((ScFormulaCell*)pOldCell)->aPos = aBigRange.aStart.MakeAddress();
2129cdf0e10cSrcweir 				if ( bNewFormula )
2130cdf0e10cSrcweir 					((ScFormulaCell*)pNewCell)->aPos = aBigRange.aStart.MakeAddress();
2131cdf0e10cSrcweir 				if ( nDx )
2132cdf0e10cSrcweir 				{
2133cdf0e10cSrcweir 					aTmpRange.aStart.IncCol( nDx );
2134cdf0e10cSrcweir 					aTmpRange.aEnd.IncCol( nDx );
2135cdf0e10cSrcweir 				}
2136cdf0e10cSrcweir 				if ( nDy )
2137cdf0e10cSrcweir 				{
2138cdf0e10cSrcweir 					aTmpRange.aStart.IncRow( nDy );
2139cdf0e10cSrcweir 					aTmpRange.aEnd.IncRow( nDy );
2140cdf0e10cSrcweir 				}
2141cdf0e10cSrcweir 				if ( nDz )
2142cdf0e10cSrcweir 				{
2143cdf0e10cSrcweir 					aTmpRange.aStart.IncTab( nDz );
2144cdf0e10cSrcweir 					aTmpRange.aEnd.IncTab( nDz );
2145cdf0e10cSrcweir 				}
2146cdf0e10cSrcweir 			break;
2147cdf0e10cSrcweir             default:
2148cdf0e10cSrcweir             {
2149cdf0e10cSrcweir                 // added to avoid warnings
2150cdf0e10cSrcweir             }
2151cdf0e10cSrcweir 		}
2152cdf0e10cSrcweir 		ScRange aRange( aTmpRange.MakeRange() );
2153cdf0e10cSrcweir 		if ( bOldFormula )
2154cdf0e10cSrcweir 			((ScFormulaCell*)pOldCell)->UpdateReference( eMode, aRange,
2155cdf0e10cSrcweir 				(SCsCOL) nDx, (SCsROW) nDy, (SCsTAB) nDz, NULL );
2156cdf0e10cSrcweir 		if ( bNewFormula )
2157cdf0e10cSrcweir 			((ScFormulaCell*)pNewCell)->UpdateReference( eMode, aRange,
2158cdf0e10cSrcweir 				(SCsCOL) nDx, (SCsROW) nDy, (SCsTAB) nDz, NULL );
2159cdf0e10cSrcweir 		if ( !aBigRange.aStart.IsValid( pTrack->GetDocument() ) )
2160cdf0e10cSrcweir 		{	//! HACK!
2161cdf0e10cSrcweir 			//! UpdateReference kann nicht mit Positionen ausserhalb des
2162cdf0e10cSrcweir 			//! Dokuments umgehen, deswegen alles auf #REF! setzen
2163cdf0e10cSrcweir //2do: make it possible! das bedeutet grossen Umbau von ScAddress etc.!
2164cdf0e10cSrcweir 			const ScBigAddress& rPos = aBigRange.aStart;
2165cdf0e10cSrcweir 			if ( bOldFormula )
2166cdf0e10cSrcweir 			{
2167cdf0e10cSrcweir 				ScToken* t;
2168cdf0e10cSrcweir 				ScTokenArray* pArr = ((ScFormulaCell*)pOldCell)->GetCode();
2169cdf0e10cSrcweir 				pArr->Reset();
2170cdf0e10cSrcweir                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReference()) ) != NULL )
2171cdf0e10cSrcweir 					lcl_InvalidateReference( *t, rPos );
2172cdf0e10cSrcweir 				pArr->Reset();
2173cdf0e10cSrcweir                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
2174cdf0e10cSrcweir 					lcl_InvalidateReference( *t, rPos );
2175cdf0e10cSrcweir 			}
2176cdf0e10cSrcweir 			if ( bNewFormula )
2177cdf0e10cSrcweir 			{
2178cdf0e10cSrcweir 				ScToken* t;
2179cdf0e10cSrcweir 				ScTokenArray* pArr = ((ScFormulaCell*)pNewCell)->GetCode();
2180cdf0e10cSrcweir 				pArr->Reset();
2181cdf0e10cSrcweir                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReference()) ) != NULL )
2182cdf0e10cSrcweir 					lcl_InvalidateReference( *t, rPos );
2183cdf0e10cSrcweir 				pArr->Reset();
2184cdf0e10cSrcweir                 while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
2185cdf0e10cSrcweir 					lcl_InvalidateReference( *t, rPos );
2186cdf0e10cSrcweir 			}
2187cdf0e10cSrcweir 		}
2188cdf0e10cSrcweir 	}
2189cdf0e10cSrcweir }
2190cdf0e10cSrcweir 
2191cdf0e10cSrcweir 
2192cdf0e10cSrcweir // --- ScChangeActionReject ------------------------------------------------
2193cdf0e10cSrcweir 
ScChangeActionReject(const sal_uLong nActionNumber,const ScChangeActionState eStateP,const sal_uLong nRejectingNumber,const ScBigRange & aBigRangeP,const String & aUserP,const DateTime & aDateTimeP,const String & sComment)2194cdf0e10cSrcweir ScChangeActionReject::ScChangeActionReject(const sal_uLong nActionNumber, const ScChangeActionState eStateP, const sal_uLong nRejectingNumber,
2195cdf0e10cSrcweir                                                 const ScBigRange& aBigRangeP, const String& aUserP, const DateTime& aDateTimeP, const String& sComment)
2196cdf0e10cSrcweir 		:
2197cdf0e10cSrcweir         ScChangeAction(SC_CAT_CONTENT, aBigRangeP, nActionNumber, nRejectingNumber, eStateP, aDateTimeP, aUserP, sComment)
2198cdf0e10cSrcweir {
2199cdf0e10cSrcweir }
2200cdf0e10cSrcweir 
2201cdf0e10cSrcweir 
2202cdf0e10cSrcweir // --- ScChangeTrack -------------------------------------------------------
2203cdf0e10cSrcweir 
2204cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScChangeTrackMsgInfo, 16, 16 )
2205cdf0e10cSrcweir 
2206cdf0e10cSrcweir const SCROW ScChangeTrack::nContentRowsPerSlot = InitContentRowsPerSlot();
2207cdf0e10cSrcweir const SCSIZE ScChangeTrack::nContentSlots =
2208cdf0e10cSrcweir 	(MAXROWCOUNT) / InitContentRowsPerSlot() + 2;
2209cdf0e10cSrcweir 
2210cdf0e10cSrcweir // static
InitContentRowsPerSlot()2211cdf0e10cSrcweir SCROW ScChangeTrack::InitContentRowsPerSlot()
2212cdf0e10cSrcweir {
2213cdf0e10cSrcweir 	const SCSIZE nMaxSlots = 0xffe0 / sizeof( ScChangeActionContent* ) - 2;
2214cdf0e10cSrcweir 	SCROW nRowsPerSlot = (MAXROWCOUNT) / nMaxSlots;
2215cdf0e10cSrcweir     if ( nRowsPerSlot * nMaxSlots < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
2216cdf0e10cSrcweir 		++nRowsPerSlot;
2217cdf0e10cSrcweir 	return nRowsPerSlot;
2218cdf0e10cSrcweir }
2219cdf0e10cSrcweir 
2220cdf0e10cSrcweir 
ScChangeTrack(ScDocument * pDocP)2221cdf0e10cSrcweir ScChangeTrack::ScChangeTrack( ScDocument* pDocP ) :
2222cdf0e10cSrcweir 		pDoc( pDocP )
2223cdf0e10cSrcweir {
2224cdf0e10cSrcweir 	Init();
2225cdf0e10cSrcweir     SC_MOD()->GetUserOptions().AddListener(this);
2226cdf0e10cSrcweir 
2227cdf0e10cSrcweir 	ppContentSlots = new ScChangeActionContent* [ nContentSlots ];
2228cdf0e10cSrcweir 	memset( ppContentSlots, 0, nContentSlots * sizeof( ScChangeActionContent* ) );
2229cdf0e10cSrcweir }
2230cdf0e10cSrcweir 
ScChangeTrack(ScDocument * pDocP,const ScStrCollection & aTempUserCollection)2231cdf0e10cSrcweir ScChangeTrack::ScChangeTrack( ScDocument* pDocP, const ScStrCollection& aTempUserCollection) :
2232cdf0e10cSrcweir 		aUserCollection(aTempUserCollection),
2233cdf0e10cSrcweir 		pDoc( pDocP )
2234cdf0e10cSrcweir {
2235cdf0e10cSrcweir 	Init();
2236cdf0e10cSrcweir     SC_MOD()->GetUserOptions().AddListener(this);
2237cdf0e10cSrcweir     ppContentSlots = new ScChangeActionContent* [ nContentSlots ];
2238cdf0e10cSrcweir 	memset( ppContentSlots, 0, nContentSlots * sizeof( ScChangeActionContent* ) );
2239cdf0e10cSrcweir }
2240cdf0e10cSrcweir 
~ScChangeTrack()2241cdf0e10cSrcweir ScChangeTrack::~ScChangeTrack()
2242cdf0e10cSrcweir {
2243cdf0e10cSrcweir     SC_MOD()->GetUserOptions().RemoveListener(this);
2244cdf0e10cSrcweir 	DtorClear();
2245cdf0e10cSrcweir 	delete [] ppContentSlots;
2246cdf0e10cSrcweir }
2247cdf0e10cSrcweir 
2248cdf0e10cSrcweir 
Init()2249cdf0e10cSrcweir void ScChangeTrack::Init()
2250cdf0e10cSrcweir {
2251cdf0e10cSrcweir 	pFirst = NULL;
2252cdf0e10cSrcweir 	pLast = NULL;
2253cdf0e10cSrcweir 	pFirstGeneratedDelContent = NULL;
2254cdf0e10cSrcweir 	pLastCutMove = NULL;
2255cdf0e10cSrcweir 	pLinkInsertCol = NULL;
2256cdf0e10cSrcweir 	pLinkInsertRow = NULL;
2257cdf0e10cSrcweir 	pLinkInsertTab = NULL;
2258cdf0e10cSrcweir 	pLinkMove = NULL;
2259cdf0e10cSrcweir 	pBlockModifyMsg = NULL;
2260cdf0e10cSrcweir 	nActionMax = 0;
2261cdf0e10cSrcweir 	nGeneratedMin = SC_CHGTRACK_GENERATED_START;
2262cdf0e10cSrcweir 	nMarkLastSaved = 0;
2263cdf0e10cSrcweir 	nStartLastCut = 0;
2264cdf0e10cSrcweir 	nEndLastCut = 0;
2265cdf0e10cSrcweir 	nLastMerge = 0;
2266cdf0e10cSrcweir 	eMergeState = SC_CTMS_NONE;
2267cdf0e10cSrcweir 	nLoadedFileFormatVersion = SC_CHGTRACK_FILEFORMAT;
2268cdf0e10cSrcweir 	bLoadSave = sal_False;
2269cdf0e10cSrcweir 	bInDelete = sal_False;
2270cdf0e10cSrcweir 	bInDeleteTop = sal_False;
2271cdf0e10cSrcweir 	bInDeleteUndo = sal_False;
2272cdf0e10cSrcweir 	bInPasteCut = sal_False;
2273cdf0e10cSrcweir 	bUseFixDateTime = sal_False;
2274cdf0e10cSrcweir     bTime100thSeconds = sal_True;
2275cdf0e10cSrcweir 
2276cdf0e10cSrcweir     const SvtUserOptions& rUserOpt = SC_MOD()->GetUserOptions();
2277cdf0e10cSrcweir     aUser = rUserOpt.GetFirstName();
2278cdf0e10cSrcweir 	aUser += ' ';
2279cdf0e10cSrcweir     aUser += (String)rUserOpt.GetLastName();
2280cdf0e10cSrcweir 	aUserCollection.Insert( new StrData( aUser ) );
2281cdf0e10cSrcweir }
2282cdf0e10cSrcweir 
2283cdf0e10cSrcweir 
DtorClear()2284cdf0e10cSrcweir void ScChangeTrack::DtorClear()
2285cdf0e10cSrcweir {
2286cdf0e10cSrcweir 	ScChangeAction* p;
2287cdf0e10cSrcweir 	ScChangeAction* pNext;
2288cdf0e10cSrcweir 	for ( p = GetFirst(); p; p = pNext )
2289cdf0e10cSrcweir 	{
2290cdf0e10cSrcweir 		pNext = p->GetNext();
2291cdf0e10cSrcweir 		delete p;
2292cdf0e10cSrcweir 	}
2293cdf0e10cSrcweir 	for ( p = pFirstGeneratedDelContent; p; p = pNext )
2294cdf0e10cSrcweir 	{
2295cdf0e10cSrcweir 		pNext = p->GetNext();
2296cdf0e10cSrcweir 		delete p;
2297cdf0e10cSrcweir 	}
2298cdf0e10cSrcweir 	for ( p = aPasteCutTable.First(); p; p = aPasteCutTable.Next() )
2299cdf0e10cSrcweir 	{
2300cdf0e10cSrcweir 		delete p;
2301cdf0e10cSrcweir 	}
2302cdf0e10cSrcweir 	delete pLastCutMove;
2303cdf0e10cSrcweir 	ClearMsgQueue();
2304cdf0e10cSrcweir }
2305cdf0e10cSrcweir 
2306cdf0e10cSrcweir 
ClearMsgQueue()2307cdf0e10cSrcweir void ScChangeTrack::ClearMsgQueue()
2308cdf0e10cSrcweir {
2309cdf0e10cSrcweir 	if ( pBlockModifyMsg )
2310cdf0e10cSrcweir 	{
2311cdf0e10cSrcweir 		delete pBlockModifyMsg;
2312cdf0e10cSrcweir 		pBlockModifyMsg = NULL;
2313cdf0e10cSrcweir 	}
2314cdf0e10cSrcweir 	ScChangeTrackMsgInfo* pMsgInfo;
2315cdf0e10cSrcweir     while ( ( pMsgInfo = aMsgStackTmp.Pop() ) != NULL )
2316cdf0e10cSrcweir 		delete pMsgInfo;
2317cdf0e10cSrcweir     while ( ( pMsgInfo = aMsgStackFinal.Pop() ) != NULL )
2318cdf0e10cSrcweir 		delete pMsgInfo;
2319cdf0e10cSrcweir     while ( ( pMsgInfo = aMsgQueue.Get() ) != NULL )
2320cdf0e10cSrcweir 		delete pMsgInfo;
2321cdf0e10cSrcweir }
2322cdf0e10cSrcweir 
2323cdf0e10cSrcweir 
Clear()2324cdf0e10cSrcweir void ScChangeTrack::Clear()
2325cdf0e10cSrcweir {
2326cdf0e10cSrcweir 	DtorClear();
2327cdf0e10cSrcweir 	aTable.Clear();
2328cdf0e10cSrcweir 	aGeneratedTable.Clear();
2329cdf0e10cSrcweir 	aPasteCutTable.Clear();
2330cdf0e10cSrcweir 	aUserCollection.FreeAll();
2331cdf0e10cSrcweir 	aUser.Erase();
2332cdf0e10cSrcweir 	Init();
2333cdf0e10cSrcweir }
2334cdf0e10cSrcweir 
2335cdf0e10cSrcweir 
ConfigurationChanged(utl::ConfigurationBroadcaster *,sal_uInt32)2336cdf0e10cSrcweir void __EXPORT ScChangeTrack::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 )
2337cdf0e10cSrcweir {
2338cdf0e10cSrcweir     if ( !pDoc->IsInDtorClear() )
2339cdf0e10cSrcweir 	{
2340cdf0e10cSrcweir         const SvtUserOptions& rUserOptions = SC_MOD()->GetUserOptions();
2341cdf0e10cSrcweir         sal_uInt16 nOldCount = aUserCollection.GetCount();
2342cdf0e10cSrcweir 
2343cdf0e10cSrcweir         String aStr( rUserOptions.GetFirstName() );
2344cdf0e10cSrcweir         aStr += ' ';
2345cdf0e10cSrcweir         aStr += (String)rUserOptions.GetLastName();
2346cdf0e10cSrcweir         SetUser( aStr );
2347cdf0e10cSrcweir 
2348cdf0e10cSrcweir         if ( aUserCollection.GetCount() != nOldCount )
2349cdf0e10cSrcweir         {
2350cdf0e10cSrcweir             //  New user in collection -> have to repaint because
2351cdf0e10cSrcweir             //  colors may be different now (#106697#).
2352cdf0e10cSrcweir             //  (Has to be done in the Notify handler, to be sure
2353cdf0e10cSrcweir             //  the user collection has already been updated)
2354cdf0e10cSrcweir 
2355cdf0e10cSrcweir             SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
2356cdf0e10cSrcweir             if (pDocSh)
2357cdf0e10cSrcweir                 pDocSh->Broadcast( ScPaintHint( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB), PAINT_GRID ) );
2358cdf0e10cSrcweir         }
2359cdf0e10cSrcweir 	}
2360cdf0e10cSrcweir }
2361cdf0e10cSrcweir 
2362cdf0e10cSrcweir 
SetUser(const String & rUser)2363cdf0e10cSrcweir void ScChangeTrack::SetUser( const String& rUser )
2364cdf0e10cSrcweir {
2365cdf0e10cSrcweir 	if ( IsLoadSave() )
2366cdf0e10cSrcweir 		return ;		// nicht die Collection zerschiessen
2367cdf0e10cSrcweir 
2368cdf0e10cSrcweir 	aUser = rUser;
2369cdf0e10cSrcweir 	StrData* pStrData = new StrData( aUser );
2370cdf0e10cSrcweir 	if ( !aUserCollection.Insert( pStrData ) )
2371cdf0e10cSrcweir 		delete pStrData;
2372cdf0e10cSrcweir }
2373cdf0e10cSrcweir 
2374cdf0e10cSrcweir 
StartBlockModify(ScChangeTrackMsgType eMsgType,sal_uLong nStartAction)2375cdf0e10cSrcweir void ScChangeTrack::StartBlockModify( ScChangeTrackMsgType eMsgType,
2376cdf0e10cSrcweir 		sal_uLong nStartAction )
2377cdf0e10cSrcweir {
2378cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
2379cdf0e10cSrcweir 	{
2380cdf0e10cSrcweir 		if ( pBlockModifyMsg )
2381cdf0e10cSrcweir 			aMsgStackTmp.Push( pBlockModifyMsg );	// Block im Block
2382cdf0e10cSrcweir 		pBlockModifyMsg = new ScChangeTrackMsgInfo;
2383cdf0e10cSrcweir 		pBlockModifyMsg->eMsgType = eMsgType;
2384cdf0e10cSrcweir 		pBlockModifyMsg->nStartAction = nStartAction;
2385cdf0e10cSrcweir 	}
2386cdf0e10cSrcweir }
2387cdf0e10cSrcweir 
2388cdf0e10cSrcweir 
EndBlockModify(sal_uLong nEndAction)2389cdf0e10cSrcweir void ScChangeTrack::EndBlockModify( sal_uLong nEndAction )
2390cdf0e10cSrcweir {
2391cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
2392cdf0e10cSrcweir 	{
2393cdf0e10cSrcweir 		if ( pBlockModifyMsg )
2394cdf0e10cSrcweir 		{
2395cdf0e10cSrcweir 			if ( pBlockModifyMsg->nStartAction <= nEndAction )
2396cdf0e10cSrcweir 			{
2397cdf0e10cSrcweir 				pBlockModifyMsg->nEndAction = nEndAction;
2398cdf0e10cSrcweir 				// Blocks in Blocks aufgeloest
2399cdf0e10cSrcweir 				aMsgStackFinal.Push( pBlockModifyMsg );
2400cdf0e10cSrcweir 			}
2401cdf0e10cSrcweir 			else
2402cdf0e10cSrcweir 				delete pBlockModifyMsg;
2403cdf0e10cSrcweir 			pBlockModifyMsg = aMsgStackTmp.Pop();	// evtl. Block im Block
2404cdf0e10cSrcweir 		}
2405cdf0e10cSrcweir 		if ( !pBlockModifyMsg )
2406cdf0e10cSrcweir 		{
2407cdf0e10cSrcweir 			sal_Bool bNew = sal_False;
2408cdf0e10cSrcweir 			ScChangeTrackMsgInfo* pMsg;
2409cdf0e10cSrcweir             while ( ( pMsg = aMsgStackFinal.Pop() ) != NULL )
2410cdf0e10cSrcweir 			{
2411cdf0e10cSrcweir 				aMsgQueue.Put( pMsg );
2412cdf0e10cSrcweir 				bNew = sal_True;
2413cdf0e10cSrcweir 			}
2414cdf0e10cSrcweir 			if ( bNew )
2415cdf0e10cSrcweir 				aModifiedLink.Call( this );
2416cdf0e10cSrcweir 		}
2417cdf0e10cSrcweir 	}
2418cdf0e10cSrcweir }
2419cdf0e10cSrcweir 
2420cdf0e10cSrcweir 
NotifyModified(ScChangeTrackMsgType eMsgType,sal_uLong nStartAction,sal_uLong nEndAction)2421cdf0e10cSrcweir void ScChangeTrack::NotifyModified( ScChangeTrackMsgType eMsgType,
2422cdf0e10cSrcweir 		sal_uLong nStartAction, sal_uLong nEndAction )
2423cdf0e10cSrcweir {
2424cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
2425cdf0e10cSrcweir 	{
2426cdf0e10cSrcweir 		if ( !pBlockModifyMsg || pBlockModifyMsg->eMsgType != eMsgType ||
2427cdf0e10cSrcweir 				(IsGenerated( nStartAction ) &&
2428cdf0e10cSrcweir 				(eMsgType == SC_CTM_APPEND || eMsgType == SC_CTM_REMOVE)) )
2429cdf0e10cSrcweir 		{	// Append innerhalb von Append z.B. nicht
2430cdf0e10cSrcweir 			StartBlockModify( eMsgType, nStartAction );
2431cdf0e10cSrcweir 			EndBlockModify( nEndAction );
2432cdf0e10cSrcweir 		}
2433cdf0e10cSrcweir 	}
2434cdf0e10cSrcweir }
2435cdf0e10cSrcweir 
2436cdf0e10cSrcweir 
MasterLinks(ScChangeAction * pAppend)2437cdf0e10cSrcweir void ScChangeTrack::MasterLinks( ScChangeAction* pAppend )
2438cdf0e10cSrcweir {
2439cdf0e10cSrcweir 	ScChangeActionType eType = pAppend->GetType();
2440cdf0e10cSrcweir 
2441cdf0e10cSrcweir 	if ( eType == SC_CAT_CONTENT )
2442cdf0e10cSrcweir 	{
2443cdf0e10cSrcweir 		if ( !IsGenerated( pAppend->GetActionNumber() ) )
2444cdf0e10cSrcweir 		{
2445cdf0e10cSrcweir 			SCSIZE nSlot = ComputeContentSlot(
2446cdf0e10cSrcweir 				pAppend->GetBigRange().aStart.Row() );
2447cdf0e10cSrcweir 			((ScChangeActionContent*)pAppend)->InsertInSlot(
2448cdf0e10cSrcweir 				&ppContentSlots[nSlot] );
2449cdf0e10cSrcweir 		}
2450cdf0e10cSrcweir 		return ;
2451cdf0e10cSrcweir 	}
2452cdf0e10cSrcweir 
2453cdf0e10cSrcweir 	if ( pAppend->IsRejecting() )
2454cdf0e10cSrcweir 		return ;		// Rejects haben keine Abhaengigkeiten
2455cdf0e10cSrcweir 
2456cdf0e10cSrcweir 	switch ( eType )
2457cdf0e10cSrcweir 	{
2458cdf0e10cSrcweir 		case SC_CAT_INSERT_COLS :
2459cdf0e10cSrcweir 		{
2460cdf0e10cSrcweir 			ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
2461cdf0e10cSrcweir 				&pLinkInsertCol, pAppend );
2462cdf0e10cSrcweir 			pAppend->AddLink( NULL, pLink );
2463cdf0e10cSrcweir 		}
2464cdf0e10cSrcweir 		break;
2465cdf0e10cSrcweir 		case SC_CAT_INSERT_ROWS :
2466cdf0e10cSrcweir 		{
2467cdf0e10cSrcweir 			ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
2468cdf0e10cSrcweir 				&pLinkInsertRow, pAppend );
2469cdf0e10cSrcweir 			pAppend->AddLink( NULL, pLink );
2470cdf0e10cSrcweir 		}
2471cdf0e10cSrcweir 		break;
2472cdf0e10cSrcweir 		case SC_CAT_INSERT_TABS :
2473cdf0e10cSrcweir 		{
2474cdf0e10cSrcweir 			ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
2475cdf0e10cSrcweir 				&pLinkInsertTab, pAppend );
2476cdf0e10cSrcweir 			pAppend->AddLink( NULL, pLink );
2477cdf0e10cSrcweir 		}
2478cdf0e10cSrcweir 		break;
2479cdf0e10cSrcweir 		case SC_CAT_MOVE :
2480cdf0e10cSrcweir 		{
2481cdf0e10cSrcweir 			ScChangeActionLinkEntry* pLink = new ScChangeActionLinkEntry(
2482cdf0e10cSrcweir 				&pLinkMove, pAppend );
2483cdf0e10cSrcweir 			pAppend->AddLink( NULL, pLink );
2484cdf0e10cSrcweir 		}
2485cdf0e10cSrcweir 		break;
2486cdf0e10cSrcweir         default:
2487cdf0e10cSrcweir         {
2488cdf0e10cSrcweir             // added to avoid warnings
2489cdf0e10cSrcweir         }
2490cdf0e10cSrcweir 	}
2491cdf0e10cSrcweir }
2492cdf0e10cSrcweir 
2493cdf0e10cSrcweir 
AppendLoaded(ScChangeAction * pAppend)2494cdf0e10cSrcweir void ScChangeTrack::AppendLoaded( ScChangeAction* pAppend )
2495cdf0e10cSrcweir {
2496cdf0e10cSrcweir 	aTable.Insert( pAppend->GetActionNumber(), pAppend );
2497cdf0e10cSrcweir 	if ( !pLast )
2498cdf0e10cSrcweir 		pFirst = pLast = pAppend;
2499cdf0e10cSrcweir 	else
2500cdf0e10cSrcweir 	{
2501cdf0e10cSrcweir 		pLast->pNext = pAppend;
2502cdf0e10cSrcweir 		pAppend->pPrev = pLast;
2503cdf0e10cSrcweir 		pLast = pAppend;
2504cdf0e10cSrcweir 	}
2505cdf0e10cSrcweir 	MasterLinks( pAppend );
2506cdf0e10cSrcweir }
2507cdf0e10cSrcweir 
2508cdf0e10cSrcweir 
Append(ScChangeAction * pAppend,sal_uLong nAction)2509cdf0e10cSrcweir void ScChangeTrack::Append( ScChangeAction* pAppend, sal_uLong nAction )
2510cdf0e10cSrcweir {
2511cdf0e10cSrcweir 	if ( nActionMax < nAction )
2512cdf0e10cSrcweir 		nActionMax = nAction;
2513cdf0e10cSrcweir 	pAppend->SetUser( aUser );
2514cdf0e10cSrcweir 	if ( bUseFixDateTime )
2515cdf0e10cSrcweir 		pAppend->SetDateTimeUTC( aFixDateTime );
2516cdf0e10cSrcweir 	pAppend->SetActionNumber( nAction );
2517cdf0e10cSrcweir 	aTable.Insert( nAction, pAppend );
2518cdf0e10cSrcweir 	// UpdateReference Inserts vor Dependencies.
2519cdf0e10cSrcweir 	// Delete rejectendes Insert hatte UpdateReference mit Delete-Undo.
2520cdf0e10cSrcweir 	// UpdateReference auch wenn pLast==NULL, weil pAppend ein Delete sein
2521cdf0e10cSrcweir 	// kann, dass DelContents generiert haben kann
2522cdf0e10cSrcweir 	if ( pAppend->IsInsertType() && !pAppend->IsRejecting() )
2523cdf0e10cSrcweir 		UpdateReference( pAppend, sal_False );
2524cdf0e10cSrcweir 	if ( !pLast )
2525cdf0e10cSrcweir 		pFirst = pLast = pAppend;
2526cdf0e10cSrcweir 	else
2527cdf0e10cSrcweir 	{
2528cdf0e10cSrcweir 		pLast->pNext = pAppend;
2529cdf0e10cSrcweir 		pAppend->pPrev = pLast;
2530cdf0e10cSrcweir 		pLast = pAppend;
2531cdf0e10cSrcweir 		Dependencies( pAppend );
2532cdf0e10cSrcweir 	}
2533cdf0e10cSrcweir 	// UpdateReference Inserts nicht nach Dependencies.
2534cdf0e10cSrcweir 	// Move rejectendes Move hatte UpdateReference mit Move-Undo, Inhalt in
2535cdf0e10cSrcweir 	// ToRange nicht deleten.
2536cdf0e10cSrcweir 	if ( !pAppend->IsInsertType() &&
2537cdf0e10cSrcweir 			!(pAppend->GetType() == SC_CAT_MOVE && pAppend->IsRejecting()) )
2538cdf0e10cSrcweir 		UpdateReference( pAppend, sal_False );
2539cdf0e10cSrcweir 	MasterLinks( pAppend );
2540cdf0e10cSrcweir 
2541cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
2542cdf0e10cSrcweir 	{
2543cdf0e10cSrcweir 		NotifyModified( SC_CTM_APPEND, nAction, nAction );
2544cdf0e10cSrcweir 		if ( pAppend->GetType() == SC_CAT_CONTENT )
2545cdf0e10cSrcweir 		{
2546cdf0e10cSrcweir 			ScChangeActionContent* pContent = (ScChangeActionContent*) pAppend;
2547cdf0e10cSrcweir             if ( ( pContent = pContent->GetPrevContent() ) != NULL )
2548cdf0e10cSrcweir 			{
2549cdf0e10cSrcweir 				sal_uLong nMod = pContent->GetActionNumber();
2550cdf0e10cSrcweir 				NotifyModified( SC_CTM_CHANGE, nMod, nMod );
2551cdf0e10cSrcweir 			}
2552cdf0e10cSrcweir 		}
2553cdf0e10cSrcweir 		else
2554cdf0e10cSrcweir 			NotifyModified( SC_CTM_CHANGE, pFirst->GetActionNumber(),
2555cdf0e10cSrcweir 				pLast->GetActionNumber() );
2556cdf0e10cSrcweir 	}
2557cdf0e10cSrcweir }
2558cdf0e10cSrcweir 
2559cdf0e10cSrcweir 
Append(ScChangeAction * pAppend)2560cdf0e10cSrcweir void ScChangeTrack::Append( ScChangeAction* pAppend )
2561cdf0e10cSrcweir {
2562cdf0e10cSrcweir 	Append( pAppend, ++nActionMax );
2563cdf0e10cSrcweir }
2564cdf0e10cSrcweir 
2565cdf0e10cSrcweir 
AppendDeleteRange(const ScRange & rRange,ScDocument * pRefDoc,sal_uLong & nStartAction,sal_uLong & nEndAction,SCsTAB nDz)2566cdf0e10cSrcweir void ScChangeTrack::AppendDeleteRange( const ScRange& rRange,
2567cdf0e10cSrcweir 		ScDocument* pRefDoc, sal_uLong& nStartAction, sal_uLong& nEndAction, SCsTAB nDz )
2568cdf0e10cSrcweir {
2569cdf0e10cSrcweir 	nStartAction = GetActionMax() + 1;
2570cdf0e10cSrcweir 	AppendDeleteRange( rRange, pRefDoc, nDz, 0 );
2571cdf0e10cSrcweir 	nEndAction = GetActionMax();
2572cdf0e10cSrcweir }
2573cdf0e10cSrcweir 
2574cdf0e10cSrcweir 
AppendDeleteRange(const ScRange & rRange,ScDocument * pRefDoc,SCsTAB nDz,sal_uLong nRejectingInsert)2575cdf0e10cSrcweir void ScChangeTrack::AppendDeleteRange( const ScRange& rRange,
2576cdf0e10cSrcweir 		ScDocument* pRefDoc, SCsTAB nDz, sal_uLong nRejectingInsert )
2577cdf0e10cSrcweir {
2578cdf0e10cSrcweir 	SetInDeleteRange( rRange );
2579cdf0e10cSrcweir 	StartBlockModify( SC_CTM_APPEND, GetActionMax() + 1 );
2580cdf0e10cSrcweir 	SCCOL nCol1;
2581cdf0e10cSrcweir 	SCROW nRow1;
2582cdf0e10cSrcweir 	SCTAB nTab1;
2583cdf0e10cSrcweir 	SCCOL nCol2;
2584cdf0e10cSrcweir 	SCROW nRow2;
2585cdf0e10cSrcweir 	SCTAB nTab2;
2586cdf0e10cSrcweir 	rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
2587cdf0e10cSrcweir 	for ( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
2588cdf0e10cSrcweir 	{
2589cdf0e10cSrcweir 		if ( !pRefDoc || nTab < pRefDoc->GetTableCount() )
2590cdf0e10cSrcweir 		{
2591cdf0e10cSrcweir 			if ( nCol1 == 0 && nCol2 == MAXCOL )
2592cdf0e10cSrcweir 			{	// ganze Zeilen und/oder Tabellen
2593cdf0e10cSrcweir 				if ( nRow1 == 0 && nRow2 == MAXROW )
2594cdf0e10cSrcweir 				{	// ganze Tabellen
2595cdf0e10cSrcweir //2do: geht nicht auch komplette Tabelle als ganzes?
2596cdf0e10cSrcweir 					ScRange aRange( 0, 0, nTab, 0, MAXROW, nTab );
2597cdf0e10cSrcweir 					for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
2598cdf0e10cSrcweir 					{	// spaltenweise ist weniger als zeilenweise
2599cdf0e10cSrcweir 						aRange.aStart.SetCol( nCol );
2600cdf0e10cSrcweir 						aRange.aEnd.SetCol( nCol );
2601cdf0e10cSrcweir 						if ( nCol == nCol2 )
2602cdf0e10cSrcweir 							SetInDeleteTop( sal_True );
2603cdf0e10cSrcweir 						AppendOneDeleteRange( aRange, pRefDoc, nCol-nCol1, 0,
2604cdf0e10cSrcweir 							nTab-nTab1 + nDz, nRejectingInsert );
2605cdf0e10cSrcweir 					}
2606cdf0e10cSrcweir 					//! immer noch InDeleteTop
2607cdf0e10cSrcweir 					AppendOneDeleteRange( rRange, pRefDoc, 0, 0,
2608cdf0e10cSrcweir 						nTab-nTab1 + nDz, nRejectingInsert );
2609cdf0e10cSrcweir 				}
2610cdf0e10cSrcweir 				else
2611cdf0e10cSrcweir 				{	// ganze Zeilen
2612cdf0e10cSrcweir 					ScRange aRange( 0, 0, nTab, MAXCOL, 0, nTab );
2613cdf0e10cSrcweir 					for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
2614cdf0e10cSrcweir 					{
2615cdf0e10cSrcweir 						aRange.aStart.SetRow( nRow );
2616cdf0e10cSrcweir 						aRange.aEnd.SetRow( nRow );
2617cdf0e10cSrcweir 						if ( nRow == nRow2 )
2618cdf0e10cSrcweir 							SetInDeleteTop( sal_True );
2619cdf0e10cSrcweir 						AppendOneDeleteRange( aRange, pRefDoc, 0, nRow-nRow1,
2620cdf0e10cSrcweir 							0, nRejectingInsert );
2621cdf0e10cSrcweir 					}
2622cdf0e10cSrcweir 				}
2623cdf0e10cSrcweir 			}
2624cdf0e10cSrcweir 			else if ( nRow1 == 0 && nRow2 == MAXROW )
2625cdf0e10cSrcweir 			{	// ganze Spalten
2626cdf0e10cSrcweir 				ScRange aRange( 0, 0, nTab, 0, MAXROW, nTab );
2627cdf0e10cSrcweir 				for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
2628cdf0e10cSrcweir 				{
2629cdf0e10cSrcweir 					aRange.aStart.SetCol( nCol );
2630cdf0e10cSrcweir 					aRange.aEnd.SetCol( nCol );
2631cdf0e10cSrcweir 					if ( nCol == nCol2 )
2632cdf0e10cSrcweir 						SetInDeleteTop( sal_True );
2633cdf0e10cSrcweir 					AppendOneDeleteRange( aRange, pRefDoc, nCol-nCol1, 0,
2634cdf0e10cSrcweir 						0, nRejectingInsert );
2635cdf0e10cSrcweir 				}
2636cdf0e10cSrcweir 			}
2637cdf0e10cSrcweir 			else
2638cdf0e10cSrcweir 			{
2639cdf0e10cSrcweir 				DBG_ERROR( "ScChangeTrack::AppendDeleteRange: Block not supported!" );
2640cdf0e10cSrcweir 			}
2641cdf0e10cSrcweir 			SetInDeleteTop( sal_False );
2642cdf0e10cSrcweir 		}
2643cdf0e10cSrcweir 	}
2644cdf0e10cSrcweir 	EndBlockModify( GetActionMax() );
2645cdf0e10cSrcweir }
2646cdf0e10cSrcweir 
2647cdf0e10cSrcweir 
AppendOneDeleteRange(const ScRange & rOrgRange,ScDocument * pRefDoc,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,sal_uLong nRejectingInsert)2648cdf0e10cSrcweir void ScChangeTrack::AppendOneDeleteRange( const ScRange& rOrgRange,
2649cdf0e10cSrcweir 		ScDocument* pRefDoc, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
2650cdf0e10cSrcweir 		sal_uLong nRejectingInsert )
2651cdf0e10cSrcweir {
2652cdf0e10cSrcweir 	ScRange aTrackRange( rOrgRange );
2653cdf0e10cSrcweir 	if ( nDx )
2654cdf0e10cSrcweir 	{
2655cdf0e10cSrcweir 		aTrackRange.aStart.IncCol( -nDx );
2656cdf0e10cSrcweir 		aTrackRange.aEnd.IncCol( -nDx );
2657cdf0e10cSrcweir 	}
2658cdf0e10cSrcweir 	if ( nDy )
2659cdf0e10cSrcweir 	{
2660cdf0e10cSrcweir 		aTrackRange.aStart.IncRow( -nDy );
2661cdf0e10cSrcweir 		aTrackRange.aEnd.IncRow( -nDy );
2662cdf0e10cSrcweir 	}
2663cdf0e10cSrcweir 	if ( nDz )
2664cdf0e10cSrcweir 	{
2665cdf0e10cSrcweir 		aTrackRange.aStart.IncTab( -nDz );
2666cdf0e10cSrcweir 		aTrackRange.aEnd.IncTab( -nDz );
2667cdf0e10cSrcweir 	}
2668cdf0e10cSrcweir 	ScChangeActionDel* pAct = new ScChangeActionDel( aTrackRange, nDx, nDy,
2669cdf0e10cSrcweir 		this );
2670cdf0e10cSrcweir 	// TabDelete keine Contents, sind in einzelnen Spalten
2671cdf0e10cSrcweir 	if ( !(rOrgRange.aStart.Col() == 0 && rOrgRange.aStart.Row() == 0 &&
2672cdf0e10cSrcweir 			rOrgRange.aEnd.Col() == MAXCOL && rOrgRange.aEnd.Row() == MAXROW) )
2673cdf0e10cSrcweir 		LookUpContents( rOrgRange, pRefDoc, -nDx, -nDy, -nDz );
2674cdf0e10cSrcweir 	if ( nRejectingInsert )
2675cdf0e10cSrcweir 	{
2676cdf0e10cSrcweir 		pAct->SetRejectAction( nRejectingInsert );
2677cdf0e10cSrcweir 		pAct->SetState( SC_CAS_ACCEPTED );
2678cdf0e10cSrcweir 	}
2679cdf0e10cSrcweir 	Append( pAct );
2680cdf0e10cSrcweir }
2681cdf0e10cSrcweir 
2682cdf0e10cSrcweir 
LookUpContents(const ScRange & rOrgRange,ScDocument * pRefDoc,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)2683cdf0e10cSrcweir void ScChangeTrack::LookUpContents( const ScRange& rOrgRange,
2684cdf0e10cSrcweir 		ScDocument* pRefDoc, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
2685cdf0e10cSrcweir {
2686cdf0e10cSrcweir 	if ( pRefDoc )
2687cdf0e10cSrcweir 	{
2688cdf0e10cSrcweir 		ScAddress aPos;
2689cdf0e10cSrcweir 		ScBigAddress aBigPos;
2690cdf0e10cSrcweir 		ScCellIterator aIter( pRefDoc, rOrgRange );
2691cdf0e10cSrcweir 		ScBaseCell* pCell = aIter.GetFirst();
2692cdf0e10cSrcweir 		while ( pCell )
2693cdf0e10cSrcweir 		{
2694cdf0e10cSrcweir 			if ( ScChangeActionContent::GetContentCellType( pCell ) )
2695cdf0e10cSrcweir 			{
2696cdf0e10cSrcweir 				aBigPos.Set( aIter.GetCol() + nDx, aIter.GetRow() + nDy,
2697cdf0e10cSrcweir 					aIter.GetTab() + nDz );
2698cdf0e10cSrcweir 				ScChangeActionContent* pContent = SearchContentAt( aBigPos, NULL );
2699cdf0e10cSrcweir 				if ( !pContent )
2700cdf0e10cSrcweir 				{	// nicht getrackte Contents
2701cdf0e10cSrcweir 					aPos.Set( aIter.GetCol() + nDx, aIter.GetRow() + nDy,
2702cdf0e10cSrcweir 						aIter.GetTab() + nDz );
2703cdf0e10cSrcweir 					GenerateDelContent( aPos, pCell, pRefDoc );
2704cdf0e10cSrcweir 					//! der Content wird hier _nicht_ per AddContent hinzugefuegt,
2705cdf0e10cSrcweir 					//! sondern in UpdateReference, um z.B. auch kreuzende Deletes
2706cdf0e10cSrcweir 					//! korrekt zu erfassen
2707cdf0e10cSrcweir 				}
2708cdf0e10cSrcweir 			}
2709cdf0e10cSrcweir 			pCell = aIter.GetNext();
2710cdf0e10cSrcweir 		}
2711cdf0e10cSrcweir 	}
2712cdf0e10cSrcweir }
2713cdf0e10cSrcweir 
2714cdf0e10cSrcweir 
AppendMove(const ScRange & rFromRange,const ScRange & rToRange,ScDocument * pRefDoc)2715cdf0e10cSrcweir void ScChangeTrack::AppendMove( const ScRange& rFromRange,
2716cdf0e10cSrcweir 		const ScRange& rToRange, ScDocument* pRefDoc )
2717cdf0e10cSrcweir {
2718cdf0e10cSrcweir 	ScChangeActionMove* pAct = new ScChangeActionMove( rFromRange, rToRange, this );
2719cdf0e10cSrcweir 	LookUpContents( rToRange, pRefDoc, 0, 0, 0 );	// ueberschriebene Contents
2720cdf0e10cSrcweir 	Append( pAct );
2721cdf0e10cSrcweir }
2722cdf0e10cSrcweir 
2723cdf0e10cSrcweir 
2724cdf0e10cSrcweir // static
IsMatrixFormulaRangeDifferent(const ScBaseCell * pOldCell,const ScBaseCell * pNewCell)2725cdf0e10cSrcweir sal_Bool ScChangeTrack::IsMatrixFormulaRangeDifferent( const ScBaseCell* pOldCell,
2726cdf0e10cSrcweir 		const ScBaseCell* pNewCell )
2727cdf0e10cSrcweir {
2728cdf0e10cSrcweir 	SCCOL nC1, nC2;
2729cdf0e10cSrcweir 	SCROW nR1, nR2;
2730cdf0e10cSrcweir 	nC1 = nC2 = 0;
2731cdf0e10cSrcweir     nR1 = nR2 = 0;
2732cdf0e10cSrcweir 	if ( pOldCell && (pOldCell->GetCellType() == CELLTYPE_FORMULA) &&
2733cdf0e10cSrcweir 			((const ScFormulaCell*)pOldCell)->GetMatrixFlag() == MM_FORMULA )
2734cdf0e10cSrcweir 		((const ScFormulaCell*)pOldCell)->GetMatColsRows( nC1, nR1 );
2735cdf0e10cSrcweir 	if ( pNewCell && (pNewCell->GetCellType() == CELLTYPE_FORMULA) &&
2736cdf0e10cSrcweir 			((const ScFormulaCell*)pNewCell)->GetMatrixFlag() == MM_FORMULA )
2737cdf0e10cSrcweir 		((const ScFormulaCell*)pNewCell)->GetMatColsRows( nC1, nR1 );
2738cdf0e10cSrcweir 	return nC1 != nC2 || nR1 != nR2;
2739cdf0e10cSrcweir }
2740cdf0e10cSrcweir 
2741cdf0e10cSrcweir 
AppendContent(const ScAddress & rPos,const String & rNewValue,ScBaseCell * pOldCell)2742cdf0e10cSrcweir void ScChangeTrack::AppendContent( const ScAddress& rPos,
2743cdf0e10cSrcweir 		const String& rNewValue, ScBaseCell* pOldCell )
2744cdf0e10cSrcweir {
2745cdf0e10cSrcweir 	String aOldValue;
2746cdf0e10cSrcweir 	ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pDoc, rPos );
2747cdf0e10cSrcweir 	if ( aOldValue != rNewValue ||
2748cdf0e10cSrcweir 			IsMatrixFormulaRangeDifferent( pOldCell, NULL ) )
2749cdf0e10cSrcweir 	{	// nur wirkliche Aenderung tracken
2750cdf0e10cSrcweir 		ScRange aRange( rPos );
2751cdf0e10cSrcweir 		ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
2752cdf0e10cSrcweir 		pAct->SetOldValue( pOldCell, pDoc, pDoc );
2753cdf0e10cSrcweir 		pAct->SetNewValue( rNewValue, pDoc );
2754cdf0e10cSrcweir 		Append( pAct );
2755cdf0e10cSrcweir 	}
2756cdf0e10cSrcweir }
2757cdf0e10cSrcweir 
2758cdf0e10cSrcweir 
AppendContent(const ScAddress & rPos,const ScBaseCell * pOldCell,sal_uLong nOldFormat,ScDocument * pRefDoc)2759cdf0e10cSrcweir void ScChangeTrack::AppendContent( const ScAddress& rPos,
2760cdf0e10cSrcweir 		const ScBaseCell* pOldCell, sal_uLong nOldFormat, ScDocument* pRefDoc )
2761cdf0e10cSrcweir {
2762cdf0e10cSrcweir 	if ( !pRefDoc )
2763cdf0e10cSrcweir 		pRefDoc = pDoc;
2764cdf0e10cSrcweir 	String aOldValue;
2765cdf0e10cSrcweir 	ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, nOldFormat );
2766cdf0e10cSrcweir 	String aNewValue;
2767cdf0e10cSrcweir 	ScBaseCell* pNewCell = pDoc->GetCell( rPos );
2768cdf0e10cSrcweir 	ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
2769cdf0e10cSrcweir 	if ( aOldValue != aNewValue ||
2770cdf0e10cSrcweir 			IsMatrixFormulaRangeDifferent( pOldCell, pNewCell ) )
2771cdf0e10cSrcweir 	{	// nur wirkliche Aenderung tracken
2772cdf0e10cSrcweir 		ScRange aRange( rPos );
2773cdf0e10cSrcweir 		ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
2774cdf0e10cSrcweir 		pAct->SetOldValue( pOldCell, pRefDoc, pDoc, nOldFormat );
2775cdf0e10cSrcweir 		pAct->SetNewValue( pNewCell, pDoc );
2776cdf0e10cSrcweir 		Append( pAct );
2777cdf0e10cSrcweir 	}
2778cdf0e10cSrcweir }
2779cdf0e10cSrcweir 
2780cdf0e10cSrcweir 
AppendContent(const ScAddress & rPos,ScDocument * pRefDoc)2781cdf0e10cSrcweir void ScChangeTrack::AppendContent( const ScAddress& rPos,
2782cdf0e10cSrcweir 		ScDocument* pRefDoc )
2783cdf0e10cSrcweir {
2784cdf0e10cSrcweir 	String aOldValue;
2785cdf0e10cSrcweir 	ScBaseCell* pOldCell = pRefDoc->GetCell( rPos );
2786cdf0e10cSrcweir 	ScChangeActionContent::GetStringOfCell( aOldValue, pOldCell, pRefDoc, rPos );
2787cdf0e10cSrcweir 	String aNewValue;
2788cdf0e10cSrcweir 	ScBaseCell* pNewCell = pDoc->GetCell( rPos );
2789cdf0e10cSrcweir 	ScChangeActionContent::GetStringOfCell( aNewValue, pNewCell, pDoc, rPos );
2790cdf0e10cSrcweir 	if ( aOldValue != aNewValue ||
2791cdf0e10cSrcweir 			IsMatrixFormulaRangeDifferent( pOldCell, pNewCell ) )
2792cdf0e10cSrcweir 	{	// nur wirkliche Aenderung tracken
2793cdf0e10cSrcweir 		ScRange aRange( rPos );
2794cdf0e10cSrcweir 		ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
2795cdf0e10cSrcweir 		pAct->SetOldValue( pOldCell, pRefDoc, pDoc );
2796cdf0e10cSrcweir 		pAct->SetNewValue( pNewCell, pDoc );
2797cdf0e10cSrcweir 		Append( pAct );
2798cdf0e10cSrcweir 	}
2799cdf0e10cSrcweir }
2800cdf0e10cSrcweir 
2801cdf0e10cSrcweir 
AppendContent(const ScAddress & rPos,const ScBaseCell * pOldCell)2802cdf0e10cSrcweir void ScChangeTrack::AppendContent( const ScAddress& rPos,
2803cdf0e10cSrcweir 		const ScBaseCell* pOldCell )
2804cdf0e10cSrcweir {
2805cdf0e10cSrcweir 	if ( ScChangeActionContent::NeedsNumberFormat( pOldCell ) )
2806cdf0e10cSrcweir 		AppendContent( rPos, pOldCell, pDoc->GetNumberFormat( rPos ), pDoc );
2807cdf0e10cSrcweir 	else
2808cdf0e10cSrcweir 		AppendContent( rPos, pOldCell, 0, pDoc );
2809cdf0e10cSrcweir }
2810cdf0e10cSrcweir 
2811cdf0e10cSrcweir 
SetLastCutMoveRange(const ScRange & rRange,ScDocument * pRefDoc)2812cdf0e10cSrcweir void ScChangeTrack::SetLastCutMoveRange( const ScRange& rRange,
2813cdf0e10cSrcweir 		ScDocument* pRefDoc )
2814cdf0e10cSrcweir {
2815cdf0e10cSrcweir 	if ( pLastCutMove )
2816cdf0e10cSrcweir 	{
2817cdf0e10cSrcweir 		// ToRange nicht mit Deletes linken und nicht in der Groesse aendern,
2818cdf0e10cSrcweir 		// eigentlich unnoetig, da ein Delete vorher in
2819cdf0e10cSrcweir 		// ScViewFunc::PasteFromClip ein ResetLastCut ausloest
2820cdf0e10cSrcweir 		ScBigRange& r = pLastCutMove->GetBigRange();
2821cdf0e10cSrcweir 		r.aEnd.SetCol( -1 );
2822cdf0e10cSrcweir 		r.aEnd.SetRow( -1 );
2823cdf0e10cSrcweir 		r.aEnd.SetTab( -1 );
2824cdf0e10cSrcweir 		r.aStart.SetCol( -1 - (rRange.aEnd.Col() - rRange.aStart.Col()) );
2825cdf0e10cSrcweir 		r.aStart.SetRow( -1 - (rRange.aEnd.Row() - rRange.aStart.Row()) );
2826cdf0e10cSrcweir 		r.aStart.SetTab( -1 - (rRange.aEnd.Tab() - rRange.aStart.Tab()) );
2827cdf0e10cSrcweir 		// zu ueberschreibende Contents im FromRange
2828cdf0e10cSrcweir 		LookUpContents( rRange, pRefDoc, 0, 0, 0 );
2829cdf0e10cSrcweir 	}
2830cdf0e10cSrcweir }
2831cdf0e10cSrcweir 
2832cdf0e10cSrcweir 
AppendContentRange(const ScRange & rRange,ScDocument * pRefDoc,sal_uLong & nStartAction,sal_uLong & nEndAction,ScChangeActionClipMode eClipMode)2833cdf0e10cSrcweir void ScChangeTrack::AppendContentRange( const ScRange& rRange,
2834cdf0e10cSrcweir 		ScDocument* pRefDoc, sal_uLong& nStartAction, sal_uLong& nEndAction,
2835cdf0e10cSrcweir 		ScChangeActionClipMode eClipMode )
2836cdf0e10cSrcweir {
2837cdf0e10cSrcweir 	if ( eClipMode == SC_CACM_CUT )
2838cdf0e10cSrcweir 	{
2839cdf0e10cSrcweir 		ResetLastCut();
2840cdf0e10cSrcweir 		pLastCutMove = new ScChangeActionMove( rRange, rRange, this );
2841cdf0e10cSrcweir 		SetLastCutMoveRange( rRange, pRefDoc );
2842cdf0e10cSrcweir 	}
2843cdf0e10cSrcweir 	SCCOL nCol1;
2844cdf0e10cSrcweir 	SCROW nRow1;
2845cdf0e10cSrcweir 	SCTAB nTab1;
2846cdf0e10cSrcweir 	SCCOL nCol2;
2847cdf0e10cSrcweir 	SCROW nRow2;
2848cdf0e10cSrcweir 	SCTAB nTab2;
2849cdf0e10cSrcweir 	rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
2850cdf0e10cSrcweir 	sal_Bool bDoContents;
2851cdf0e10cSrcweir 	if ( eClipMode == SC_CACM_PASTE && HasLastCut() )
2852cdf0e10cSrcweir 	{
2853cdf0e10cSrcweir 		bDoContents = sal_False;
2854cdf0e10cSrcweir 		SetInPasteCut( sal_True );
2855cdf0e10cSrcweir 		// Paste und Cut abstimmen, Paste kann groesserer Range sein
2856cdf0e10cSrcweir 		ScRange aRange( rRange );
2857cdf0e10cSrcweir 		ScBigRange& r = pLastCutMove->GetBigRange();
2858cdf0e10cSrcweir         SCCOL nTmpCol;
2859cdf0e10cSrcweir 		if ( (nTmpCol = (SCCOL) (r.aEnd.Col() - r.aStart.Col())) != (nCol2 - nCol1) )
2860cdf0e10cSrcweir 		{
2861cdf0e10cSrcweir 			aRange.aEnd.SetCol( aRange.aStart.Col() + nTmpCol );
2862cdf0e10cSrcweir 			nCol1 += nTmpCol + 1;
2863cdf0e10cSrcweir 			bDoContents = sal_True;
2864cdf0e10cSrcweir 		}
2865cdf0e10cSrcweir         SCROW nTmpRow;
2866cdf0e10cSrcweir 		if ( (nTmpRow = (SCROW) (r.aEnd.Row() - r.aStart.Row())) != (nRow2 - nRow1) )
2867cdf0e10cSrcweir 		{
2868cdf0e10cSrcweir 			aRange.aEnd.SetRow( aRange.aStart.Row() + nTmpRow );
2869cdf0e10cSrcweir 			nRow1 += nTmpRow + 1;
2870cdf0e10cSrcweir 			bDoContents = sal_True;
2871cdf0e10cSrcweir 		}
2872cdf0e10cSrcweir         SCTAB nTmpTab;
2873cdf0e10cSrcweir 		if ( (nTmpTab = (SCTAB) (r.aEnd.Tab() - r.aStart.Tab())) != (nTab2 - nTab1) )
2874cdf0e10cSrcweir 		{
2875cdf0e10cSrcweir 			aRange.aEnd.SetTab( aRange.aStart.Tab() + nTmpTab );
2876cdf0e10cSrcweir 			nTab1 += nTmpTab + 1;
2877cdf0e10cSrcweir 			bDoContents = sal_True;
2878cdf0e10cSrcweir 		}
2879cdf0e10cSrcweir 		r = aRange;
2880cdf0e10cSrcweir 		Undo( nStartLastCut, nEndLastCut );	// hier werden sich die Cuts gemerkt
2881cdf0e10cSrcweir 		//! StartAction erst nach Undo
2882cdf0e10cSrcweir 		nStartAction = GetActionMax() + 1;
2883cdf0e10cSrcweir 		StartBlockModify( SC_CTM_APPEND, nStartAction );
2884cdf0e10cSrcweir 		// zu ueberschreibende Contents im ToRange
2885cdf0e10cSrcweir 		LookUpContents( aRange, pRefDoc, 0, 0, 0 );
2886cdf0e10cSrcweir 		pLastCutMove->SetStartLastCut( nStartLastCut );
2887cdf0e10cSrcweir 		pLastCutMove->SetEndLastCut( nEndLastCut );
2888cdf0e10cSrcweir 		Append( pLastCutMove );
2889cdf0e10cSrcweir 		pLastCutMove = NULL;
2890cdf0e10cSrcweir 		ResetLastCut();
2891cdf0e10cSrcweir 		SetInPasteCut( sal_False );
2892cdf0e10cSrcweir 	}
2893cdf0e10cSrcweir 	else
2894cdf0e10cSrcweir 	{
2895cdf0e10cSrcweir 		bDoContents = sal_True;
2896cdf0e10cSrcweir 		nStartAction = GetActionMax() + 1;
2897cdf0e10cSrcweir 		StartBlockModify( SC_CTM_APPEND, nStartAction );
2898cdf0e10cSrcweir 	}
2899cdf0e10cSrcweir 	if ( bDoContents )
2900cdf0e10cSrcweir 	{
2901cdf0e10cSrcweir 		ScAddress aPos;
2902cdf0e10cSrcweir 		for ( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
2903cdf0e10cSrcweir 		{
2904cdf0e10cSrcweir 			aPos.SetTab( nTab );
2905cdf0e10cSrcweir 			for ( SCCOL nCol = nCol1; nCol <= nCol2; nCol++ )
2906cdf0e10cSrcweir 			{
2907cdf0e10cSrcweir 				aPos.SetCol( nCol );
2908cdf0e10cSrcweir 				for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
2909cdf0e10cSrcweir 				{
2910cdf0e10cSrcweir 					aPos.SetRow( nRow );
2911cdf0e10cSrcweir 					AppendContent( aPos, pRefDoc );
2912cdf0e10cSrcweir 				}
2913cdf0e10cSrcweir 			}
2914cdf0e10cSrcweir 		}
2915cdf0e10cSrcweir 	}
2916cdf0e10cSrcweir 	nEndAction = GetActionMax();
2917cdf0e10cSrcweir 	EndBlockModify( nEndAction );
2918cdf0e10cSrcweir 	if ( eClipMode == SC_CACM_CUT )
2919cdf0e10cSrcweir 	{
2920cdf0e10cSrcweir 		nStartLastCut = nStartAction;
2921cdf0e10cSrcweir 		nEndLastCut = nEndAction;
2922cdf0e10cSrcweir 	}
2923cdf0e10cSrcweir }
2924cdf0e10cSrcweir 
2925cdf0e10cSrcweir 
AppendContentsIfInRefDoc(ScDocument * pRefDoc,sal_uLong & nStartAction,sal_uLong & nEndAction)2926cdf0e10cSrcweir void ScChangeTrack::AppendContentsIfInRefDoc( ScDocument* pRefDoc,
2927cdf0e10cSrcweir 			sal_uLong& nStartAction, sal_uLong& nEndAction )
2928cdf0e10cSrcweir {
2929cdf0e10cSrcweir 	ScDocumentIterator aIter( pRefDoc, 0, MAXTAB );
2930cdf0e10cSrcweir 	if ( aIter.GetFirst() )
2931cdf0e10cSrcweir 	{
2932cdf0e10cSrcweir 		nStartAction = GetActionMax() + 1;
2933cdf0e10cSrcweir 		StartBlockModify( SC_CTM_APPEND, nStartAction );
2934cdf0e10cSrcweir 		SvNumberFormatter* pFormatter = pRefDoc->GetFormatTable();
2935cdf0e10cSrcweir 		do
2936cdf0e10cSrcweir 		{
2937cdf0e10cSrcweir             SCCOL nCol;
2938cdf0e10cSrcweir             SCROW nRow;
2939cdf0e10cSrcweir             SCTAB nTab;
2940cdf0e10cSrcweir 			aIter.GetPos( nCol, nRow, nTab );
2941cdf0e10cSrcweir 			ScAddress aPos( nCol, nRow, nTab );
2942cdf0e10cSrcweir 			AppendContent( aPos, aIter.GetCell(),
2943cdf0e10cSrcweir 				aIter.GetPattern()->GetNumberFormat( pFormatter ), pRefDoc );
2944cdf0e10cSrcweir 		} while ( aIter.GetNext() );
2945cdf0e10cSrcweir 		nEndAction = GetActionMax();
2946cdf0e10cSrcweir 		EndBlockModify( nEndAction );
2947cdf0e10cSrcweir 	}
2948cdf0e10cSrcweir 	else
2949cdf0e10cSrcweir 		nStartAction = nEndAction = 0;
2950cdf0e10cSrcweir }
2951cdf0e10cSrcweir 
2952cdf0e10cSrcweir 
AppendContentOnTheFly(const ScAddress & rPos,ScBaseCell * pOldCell,ScBaseCell * pNewCell,sal_uLong nOldFormat,sal_uLong nNewFormat)2953cdf0e10cSrcweir ScChangeActionContent* ScChangeTrack::AppendContentOnTheFly(
2954cdf0e10cSrcweir 		const ScAddress& rPos, ScBaseCell* pOldCell, ScBaseCell* pNewCell,
2955cdf0e10cSrcweir 		sal_uLong nOldFormat, sal_uLong nNewFormat )
2956cdf0e10cSrcweir {
2957cdf0e10cSrcweir 	ScRange aRange( rPos );
2958cdf0e10cSrcweir 	ScChangeActionContent* pAct = new ScChangeActionContent( aRange );
2959cdf0e10cSrcweir 	pAct->SetOldNewCells( pOldCell, nOldFormat, pNewCell, nNewFormat, pDoc );
2960cdf0e10cSrcweir 	Append( pAct );
2961cdf0e10cSrcweir 	return pAct;
2962cdf0e10cSrcweir }
2963cdf0e10cSrcweir 
2964cdf0e10cSrcweir 
AppendInsert(const ScRange & rRange)2965cdf0e10cSrcweir void ScChangeTrack::AppendInsert( const ScRange& rRange )
2966cdf0e10cSrcweir {
2967cdf0e10cSrcweir 	ScChangeActionIns* pAct = new ScChangeActionIns( rRange );
2968cdf0e10cSrcweir 	Append( pAct );
2969cdf0e10cSrcweir }
2970cdf0e10cSrcweir 
2971cdf0e10cSrcweir 
DeleteCellEntries(ScChangeActionCellListEntry * & pCellList,ScChangeAction * pDeletor)2972cdf0e10cSrcweir void ScChangeTrack::DeleteCellEntries( ScChangeActionCellListEntry*& pCellList,
2973cdf0e10cSrcweir 		ScChangeAction* pDeletor )
2974cdf0e10cSrcweir {
2975cdf0e10cSrcweir 	ScChangeActionCellListEntry* pE = pCellList;
2976cdf0e10cSrcweir 	while ( pE )
2977cdf0e10cSrcweir 	{
2978cdf0e10cSrcweir 		ScChangeActionCellListEntry* pNext = pE->pNext;
2979cdf0e10cSrcweir 		pE->pContent->RemoveDeletedIn( pDeletor );
2980cdf0e10cSrcweir 		if ( IsGenerated( pE->pContent->GetActionNumber() ) &&
2981cdf0e10cSrcweir 				!pE->pContent->IsDeletedIn() )
2982cdf0e10cSrcweir 			DeleteGeneratedDelContent( pE->pContent );
2983cdf0e10cSrcweir 		delete pE;
2984cdf0e10cSrcweir 		pE = pNext;
2985cdf0e10cSrcweir 	}
2986cdf0e10cSrcweir 	pCellList = NULL;
2987cdf0e10cSrcweir }
2988cdf0e10cSrcweir 
2989cdf0e10cSrcweir 
GenerateDelContent(const ScAddress & rPos,const ScBaseCell * pCell,const ScDocument * pFromDoc)2990cdf0e10cSrcweir ScChangeActionContent* ScChangeTrack::GenerateDelContent(
2991cdf0e10cSrcweir 		const ScAddress& rPos, const ScBaseCell* pCell,
2992cdf0e10cSrcweir 		const ScDocument* pFromDoc )
2993cdf0e10cSrcweir {
2994cdf0e10cSrcweir 	ScChangeActionContent* pContent = new ScChangeActionContent(
2995cdf0e10cSrcweir 		ScRange( rPos ) );
2996cdf0e10cSrcweir 	pContent->SetActionNumber( --nGeneratedMin );
2997cdf0e10cSrcweir 	// nur NewValue
2998cdf0e10cSrcweir 	ScChangeActionContent::SetValue( pContent->aNewValue, pContent->pNewCell,
2999cdf0e10cSrcweir 		rPos, pCell, pFromDoc, pDoc );
3000cdf0e10cSrcweir 	// pNextContent und pPrevContent werden nicht gesetzt
3001cdf0e10cSrcweir 	if ( pFirstGeneratedDelContent )
3002cdf0e10cSrcweir 	{	// vorne reinhaengen
3003cdf0e10cSrcweir 		pFirstGeneratedDelContent->pPrev = pContent;
3004cdf0e10cSrcweir 		pContent->pNext = pFirstGeneratedDelContent;
3005cdf0e10cSrcweir 	}
3006cdf0e10cSrcweir 	pFirstGeneratedDelContent = pContent;
3007cdf0e10cSrcweir 	aGeneratedTable.Insert( nGeneratedMin, pContent );
3008cdf0e10cSrcweir 	NotifyModified( SC_CTM_APPEND, nGeneratedMin, nGeneratedMin );
3009cdf0e10cSrcweir 	return pContent;
3010cdf0e10cSrcweir }
3011cdf0e10cSrcweir 
3012cdf0e10cSrcweir 
DeleteGeneratedDelContent(ScChangeActionContent * pContent)3013cdf0e10cSrcweir void ScChangeTrack::DeleteGeneratedDelContent( ScChangeActionContent* pContent )
3014cdf0e10cSrcweir {
3015cdf0e10cSrcweir 	sal_uLong nAct = pContent->GetActionNumber();
3016cdf0e10cSrcweir 	aGeneratedTable.Remove( nAct );
3017cdf0e10cSrcweir 	if ( pFirstGeneratedDelContent == pContent )
3018cdf0e10cSrcweir 		pFirstGeneratedDelContent = (ScChangeActionContent*) pContent->pNext;
3019cdf0e10cSrcweir 	if ( pContent->pNext )
3020cdf0e10cSrcweir 		pContent->pNext->pPrev = pContent->pPrev;
3021cdf0e10cSrcweir 	if ( pContent->pPrev )
3022cdf0e10cSrcweir 		pContent->pPrev->pNext = pContent->pNext;
3023cdf0e10cSrcweir 	delete pContent;
3024cdf0e10cSrcweir 	NotifyModified( SC_CTM_REMOVE, nAct, nAct );
3025cdf0e10cSrcweir 	if ( nAct == nGeneratedMin )
3026cdf0e10cSrcweir 		++nGeneratedMin;		//! erst nach NotifyModified wg. IsGenerated
3027cdf0e10cSrcweir }
3028cdf0e10cSrcweir 
3029cdf0e10cSrcweir 
SearchContentAt(const ScBigAddress & rPos,ScChangeAction * pButNotThis) const3030cdf0e10cSrcweir ScChangeActionContent* ScChangeTrack::SearchContentAt(
3031cdf0e10cSrcweir 		const ScBigAddress& rPos, ScChangeAction* pButNotThis ) const
3032cdf0e10cSrcweir {
3033cdf0e10cSrcweir 	SCSIZE nSlot = ComputeContentSlot( rPos.Row() );
3034cdf0e10cSrcweir 	for ( ScChangeActionContent* p = ppContentSlots[nSlot]; p;
3035cdf0e10cSrcweir 			p = p->GetNextInSlot() )
3036cdf0e10cSrcweir 	{
3037cdf0e10cSrcweir 		if ( p != pButNotThis && !p->IsDeletedIn() &&
3038cdf0e10cSrcweir 				p->GetBigRange().aStart == rPos )
3039cdf0e10cSrcweir 		{
3040cdf0e10cSrcweir 			ScChangeActionContent* pContent = p->GetTopContent();
3041cdf0e10cSrcweir 			if ( !pContent->IsDeletedIn() )
3042cdf0e10cSrcweir 				return pContent;
3043cdf0e10cSrcweir 		}
3044cdf0e10cSrcweir 	}
3045cdf0e10cSrcweir 	return NULL;
3046cdf0e10cSrcweir }
3047cdf0e10cSrcweir 
3048cdf0e10cSrcweir 
AddDependentWithNotify(ScChangeAction * pParent,ScChangeAction * pDependent)3049cdf0e10cSrcweir void ScChangeTrack::AddDependentWithNotify( ScChangeAction* pParent,
3050cdf0e10cSrcweir 		ScChangeAction* pDependent )
3051cdf0e10cSrcweir {
3052cdf0e10cSrcweir 	ScChangeActionLinkEntry* pLink = pParent->AddDependent( pDependent );
3053cdf0e10cSrcweir 	pDependent->AddLink( pParent, pLink );
3054cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
3055cdf0e10cSrcweir 	{
3056cdf0e10cSrcweir 		sal_uLong nMod = pParent->GetActionNumber();
3057cdf0e10cSrcweir 		NotifyModified( SC_CTM_PARENT, nMod, nMod );
3058cdf0e10cSrcweir 	}
3059cdf0e10cSrcweir }
3060cdf0e10cSrcweir 
3061cdf0e10cSrcweir 
Dependencies(ScChangeAction * pAct)3062cdf0e10cSrcweir void ScChangeTrack::Dependencies( ScChangeAction* pAct )
3063cdf0e10cSrcweir {
3064cdf0e10cSrcweir 	// Finde die letzte Abhaengigkeit fuer jeweils Col/Row/Tab.
3065cdf0e10cSrcweir 	// Content an gleicher Position verketten.
3066cdf0e10cSrcweir 	// Move Abhaengigkeiten.
3067cdf0e10cSrcweir 	ScChangeActionType eActType = pAct->GetType();
3068cdf0e10cSrcweir 	if ( eActType == SC_CAT_REJECT ||
3069cdf0e10cSrcweir 			(eActType == SC_CAT_MOVE && pAct->IsRejecting()) )
3070cdf0e10cSrcweir 		return ;		// diese Rejects sind nicht abhaengig
3071cdf0e10cSrcweir 
3072cdf0e10cSrcweir 	if ( eActType == SC_CAT_CONTENT )
3073cdf0e10cSrcweir 	{
3074cdf0e10cSrcweir 		if ( !(((ScChangeActionContent*)pAct)->GetNextContent() ||
3075cdf0e10cSrcweir 			((ScChangeActionContent*)pAct)->GetPrevContent()) )
3076cdf0e10cSrcweir 		{	// Contents an gleicher Position verketten
3077cdf0e10cSrcweir 			ScChangeActionContent* pContent = SearchContentAt(
3078cdf0e10cSrcweir 				pAct->GetBigRange().aStart, pAct );
3079cdf0e10cSrcweir 			if ( pContent )
3080cdf0e10cSrcweir 			{
3081cdf0e10cSrcweir 				pContent->SetNextContent( (ScChangeActionContent*) pAct );
3082cdf0e10cSrcweir 				((ScChangeActionContent*)pAct)->SetPrevContent( pContent );
3083cdf0e10cSrcweir 			}
3084cdf0e10cSrcweir 		}
3085cdf0e10cSrcweir 		const ScBaseCell* pCell = ((ScChangeActionContent*)pAct)->GetNewCell();
3086cdf0e10cSrcweir 		if ( ScChangeActionContent::GetContentCellType( pCell ) == SC_CACCT_MATREF )
3087cdf0e10cSrcweir 		{
3088cdf0e10cSrcweir 			ScAddress aOrg;
3089cdf0e10cSrcweir 			((const ScFormulaCell*)pCell)->GetMatrixOrigin( aOrg );
3090cdf0e10cSrcweir 			ScChangeActionContent* pContent = SearchContentAt( aOrg, pAct );
3091cdf0e10cSrcweir 			if ( pContent && pContent->IsMatrixOrigin() )
3092cdf0e10cSrcweir 			{
3093cdf0e10cSrcweir 				AddDependentWithNotify( pContent, pAct );
3094cdf0e10cSrcweir 			}
3095cdf0e10cSrcweir 			else
3096cdf0e10cSrcweir 			{
3097cdf0e10cSrcweir 				DBG_ERRORFILE( "ScChangeTrack::Dependencies: MatOrg not found" );
3098cdf0e10cSrcweir 			}
3099cdf0e10cSrcweir 		}
3100cdf0e10cSrcweir 	}
3101cdf0e10cSrcweir 
3102cdf0e10cSrcweir 	if ( !(pLinkInsertCol || pLinkInsertRow || pLinkInsertTab || pLinkMove) )
3103cdf0e10cSrcweir 		return ;		// keine Dependencies
3104cdf0e10cSrcweir 	if ( pAct->IsRejecting() )
3105cdf0e10cSrcweir 		return ;		// ausser Content keine Dependencies
3106cdf0e10cSrcweir 
3107cdf0e10cSrcweir 	// Insert in einem entsprechenden Insert haengt davon ab, sonst muesste
3108cdf0e10cSrcweir 	// der vorherige Insert gesplittet werden.
3109cdf0e10cSrcweir 	// Sich kreuzende Inserts und Deletes sind nicht abhaengig.
3110cdf0e10cSrcweir 	// Alles andere ist abhaengig.
3111cdf0e10cSrcweir 
3112cdf0e10cSrcweir 	// Der zuletzt eingelinkte Insert steht am Anfang einer Kette,
3113cdf0e10cSrcweir 	// also genau richtig
3114cdf0e10cSrcweir 
3115cdf0e10cSrcweir 	const ScBigRange& rRange = pAct->GetBigRange();
3116cdf0e10cSrcweir 	sal_Bool bActNoInsert = !pAct->IsInsertType();
3117cdf0e10cSrcweir 	sal_Bool bActColDel = ( eActType == SC_CAT_DELETE_COLS );
3118cdf0e10cSrcweir 	sal_Bool bActRowDel = ( eActType == SC_CAT_DELETE_ROWS );
3119cdf0e10cSrcweir 	sal_Bool bActTabDel = ( eActType == SC_CAT_DELETE_TABS );
3120cdf0e10cSrcweir 
3121cdf0e10cSrcweir 	if ( pLinkInsertCol && (eActType == SC_CAT_INSERT_COLS ||
3122cdf0e10cSrcweir 			(bActNoInsert && !bActRowDel && !bActTabDel)) )
3123cdf0e10cSrcweir 	{
3124cdf0e10cSrcweir 		for ( ScChangeActionLinkEntry* pL = pLinkInsertCol; pL; pL = pL->GetNext() )
3125cdf0e10cSrcweir 		{
3126cdf0e10cSrcweir 			ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
3127cdf0e10cSrcweir 			if ( !pTest->IsRejected() &&
3128cdf0e10cSrcweir 					pTest->GetBigRange().Intersects( rRange ) )
3129cdf0e10cSrcweir 			{
3130cdf0e10cSrcweir 				AddDependentWithNotify( pTest, pAct );
3131cdf0e10cSrcweir 				break;	// for
3132cdf0e10cSrcweir 			}
3133cdf0e10cSrcweir 		}
3134cdf0e10cSrcweir 	}
3135cdf0e10cSrcweir 	if ( pLinkInsertRow && (eActType == SC_CAT_INSERT_ROWS ||
3136cdf0e10cSrcweir 			(bActNoInsert && !bActColDel && !bActTabDel)) )
3137cdf0e10cSrcweir 	{
3138cdf0e10cSrcweir 		for ( ScChangeActionLinkEntry* pL = pLinkInsertRow; pL; pL = pL->GetNext() )
3139cdf0e10cSrcweir 		{
3140cdf0e10cSrcweir 			ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
3141cdf0e10cSrcweir 			if ( !pTest->IsRejected() &&
3142cdf0e10cSrcweir 					pTest->GetBigRange().Intersects( rRange ) )
3143cdf0e10cSrcweir 			{
3144cdf0e10cSrcweir 				AddDependentWithNotify( pTest, pAct );
3145cdf0e10cSrcweir 				break;	// for
3146cdf0e10cSrcweir 			}
3147cdf0e10cSrcweir 		}
3148cdf0e10cSrcweir 	}
3149cdf0e10cSrcweir 	if ( pLinkInsertTab && (eActType == SC_CAT_INSERT_TABS ||
3150cdf0e10cSrcweir 			(bActNoInsert && !bActColDel &&  !bActRowDel)) )
3151cdf0e10cSrcweir 	{
3152cdf0e10cSrcweir 		for ( ScChangeActionLinkEntry* pL = pLinkInsertTab; pL; pL = pL->GetNext() )
3153cdf0e10cSrcweir 		{
3154cdf0e10cSrcweir 			ScChangeActionIns* pTest = (ScChangeActionIns*) pL->GetAction();
3155cdf0e10cSrcweir 			if ( !pTest->IsRejected() &&
3156cdf0e10cSrcweir 					pTest->GetBigRange().Intersects( rRange ) )
3157cdf0e10cSrcweir 			{
3158cdf0e10cSrcweir 				AddDependentWithNotify( pTest, pAct );
3159cdf0e10cSrcweir 				break;	// for
3160cdf0e10cSrcweir 			}
3161cdf0e10cSrcweir 		}
3162cdf0e10cSrcweir 	}
3163cdf0e10cSrcweir 
3164cdf0e10cSrcweir 	if ( pLinkMove )
3165cdf0e10cSrcweir 	{
3166cdf0e10cSrcweir 		if ( eActType == SC_CAT_CONTENT )
3167cdf0e10cSrcweir 		{	// Content ist von FromRange abhaengig
3168cdf0e10cSrcweir 			const ScBigAddress& rPos = rRange.aStart;
3169cdf0e10cSrcweir 			for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
3170cdf0e10cSrcweir 			{
3171cdf0e10cSrcweir 				ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
3172cdf0e10cSrcweir 				if ( !pTest->IsRejected() &&
3173cdf0e10cSrcweir 						pTest->GetFromRange().In( rPos ) )
3174cdf0e10cSrcweir 				{
3175cdf0e10cSrcweir 					AddDependentWithNotify( pTest, pAct );
3176cdf0e10cSrcweir 				}
3177cdf0e10cSrcweir 			}
3178cdf0e10cSrcweir 		}
3179cdf0e10cSrcweir 		else if ( eActType == SC_CAT_MOVE )
3180cdf0e10cSrcweir 		{	// Move FromRange ist von ToRange abhaengig
3181cdf0e10cSrcweir 			const ScBigRange& rFromRange = ((ScChangeActionMove*)pAct)->GetFromRange();
3182cdf0e10cSrcweir 			for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
3183cdf0e10cSrcweir 			{
3184cdf0e10cSrcweir 				ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
3185cdf0e10cSrcweir 				if ( !pTest->IsRejected() &&
3186cdf0e10cSrcweir 						pTest->GetBigRange().Intersects( rFromRange ) )
3187cdf0e10cSrcweir 				{
3188cdf0e10cSrcweir 					AddDependentWithNotify( pTest, pAct );
3189cdf0e10cSrcweir 				}
3190cdf0e10cSrcweir 			}
3191cdf0e10cSrcweir 		}
3192cdf0e10cSrcweir 		else
3193cdf0e10cSrcweir 		{	// Inserts und Deletes sind abhaengig, sobald sie FromRange oder
3194cdf0e10cSrcweir 			// ToRange kreuzen
3195cdf0e10cSrcweir 			for ( ScChangeActionLinkEntry* pL = pLinkMove; pL; pL = pL->GetNext() )
3196cdf0e10cSrcweir 			{
3197cdf0e10cSrcweir 				ScChangeActionMove* pTest = (ScChangeActionMove*) pL->GetAction();
3198cdf0e10cSrcweir 				if ( !pTest->IsRejected() &&
3199cdf0e10cSrcweir 						(pTest->GetFromRange().Intersects( rRange ) ||
3200cdf0e10cSrcweir 						pTest->GetBigRange().Intersects( rRange )) )
3201cdf0e10cSrcweir 				{
3202cdf0e10cSrcweir 					AddDependentWithNotify( pTest, pAct );
3203cdf0e10cSrcweir 				}
3204cdf0e10cSrcweir 			}
3205cdf0e10cSrcweir 		}
3206cdf0e10cSrcweir 	}
3207cdf0e10cSrcweir }
3208cdf0e10cSrcweir 
3209cdf0e10cSrcweir 
Remove(ScChangeAction * pRemove)3210cdf0e10cSrcweir void ScChangeTrack::Remove( ScChangeAction* pRemove )
3211cdf0e10cSrcweir {
3212cdf0e10cSrcweir 	// aus Track ausklinken
3213cdf0e10cSrcweir 	sal_uLong nAct = pRemove->GetActionNumber();
3214cdf0e10cSrcweir 	aTable.Remove( nAct );
3215cdf0e10cSrcweir 	if ( nAct == nActionMax )
3216cdf0e10cSrcweir 		--nActionMax;
3217cdf0e10cSrcweir 	if ( pRemove == pLast )
3218cdf0e10cSrcweir 		pLast = pRemove->pPrev;
3219cdf0e10cSrcweir 	if ( pRemove == pFirst )
3220cdf0e10cSrcweir 		pFirst = pRemove->pNext;
3221cdf0e10cSrcweir 	if ( nAct == nMarkLastSaved )
3222cdf0e10cSrcweir 		nMarkLastSaved =
3223cdf0e10cSrcweir 			( pRemove->pPrev ? pRemove->pPrev->GetActionNumber() : 0 );
3224cdf0e10cSrcweir 
3225cdf0e10cSrcweir 	// aus der globalen Kette ausklinken
3226cdf0e10cSrcweir 	if ( pRemove->pNext )
3227cdf0e10cSrcweir 		pRemove->pNext->pPrev = pRemove->pPrev;
3228cdf0e10cSrcweir 	if ( pRemove->pPrev )
3229cdf0e10cSrcweir 		pRemove->pPrev->pNext = pRemove->pNext;
3230cdf0e10cSrcweir 
3231cdf0e10cSrcweir 	// Dependencies nicht loeschen, passiert on delete automatisch durch
3232cdf0e10cSrcweir 	// LinkEntry, ohne Listen abzuklappern
3233cdf0e10cSrcweir 
3234cdf0e10cSrcweir 	if ( aModifiedLink.IsSet() )
3235cdf0e10cSrcweir 	{
3236cdf0e10cSrcweir 		NotifyModified( SC_CTM_REMOVE, nAct, nAct );
3237cdf0e10cSrcweir 		if ( pRemove->GetType() == SC_CAT_CONTENT )
3238cdf0e10cSrcweir 		{
3239cdf0e10cSrcweir 			ScChangeActionContent* pContent = (ScChangeActionContent*) pRemove;
3240cdf0e10cSrcweir             if ( ( pContent = pContent->GetPrevContent() ) != NULL )
3241cdf0e10cSrcweir 			{
3242cdf0e10cSrcweir 				sal_uLong nMod = pContent->GetActionNumber();
3243cdf0e10cSrcweir 				NotifyModified( SC_CTM_CHANGE, nMod, nMod );
3244cdf0e10cSrcweir 			}
3245cdf0e10cSrcweir 		}
3246cdf0e10cSrcweir 		else if ( pLast )
3247cdf0e10cSrcweir 			NotifyModified( SC_CTM_CHANGE, pFirst->GetActionNumber(),
3248cdf0e10cSrcweir 				pLast->GetActionNumber() );
3249cdf0e10cSrcweir 	}
3250cdf0e10cSrcweir 
3251cdf0e10cSrcweir 	if ( IsInPasteCut() && pRemove->GetType() == SC_CAT_CONTENT )
3252cdf0e10cSrcweir 	{	//! Content wird wiederverwertet
3253cdf0e10cSrcweir 		ScChangeActionContent* pContent = (ScChangeActionContent*) pRemove;
3254cdf0e10cSrcweir 		pContent->RemoveAllLinks();
3255cdf0e10cSrcweir 		pContent->ClearTrack();
3256cdf0e10cSrcweir 		pContent->pNext = pContent->pPrev = NULL;
3257cdf0e10cSrcweir 		pContent->pNextContent = pContent->pPrevContent = NULL;
3258cdf0e10cSrcweir 	}
3259cdf0e10cSrcweir }
3260cdf0e10cSrcweir 
3261cdf0e10cSrcweir 
Undo(sal_uLong nStartAction,sal_uLong nEndAction,bool bMerge)3262cdf0e10cSrcweir void ScChangeTrack::Undo( sal_uLong nStartAction, sal_uLong nEndAction, bool bMerge )
3263cdf0e10cSrcweir {
3264cdf0e10cSrcweir     // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3265cdf0e10cSrcweir     if ( bMerge )
3266cdf0e10cSrcweir     {
3267cdf0e10cSrcweir         SetMergeState( SC_CTMS_UNDO );
3268cdf0e10cSrcweir     }
3269cdf0e10cSrcweir 
3270cdf0e10cSrcweir 	if ( nStartAction == 0 )
3271cdf0e10cSrcweir 		++nStartAction;
3272cdf0e10cSrcweir 	if ( nEndAction > nActionMax )
3273cdf0e10cSrcweir 		nEndAction = nActionMax;
3274cdf0e10cSrcweir 	if ( nEndAction && nStartAction <= nEndAction )
3275cdf0e10cSrcweir 	{
3276cdf0e10cSrcweir 		if ( nStartAction == nStartLastCut && nEndAction == nEndLastCut &&
3277cdf0e10cSrcweir 				!IsInPasteCut() )
3278cdf0e10cSrcweir 			ResetLastCut();
3279cdf0e10cSrcweir 		StartBlockModify( SC_CTM_REMOVE, nStartAction );
3280cdf0e10cSrcweir 		for ( sal_uLong j = nEndAction; j >= nStartAction; --j )
3281cdf0e10cSrcweir 		{	// rueckwaerts um evtl. nActionMax zu recyclen und schnelleren
3282cdf0e10cSrcweir 			// Zugriff via pLast, Deletes in richtiger Reihenfolge
3283cdf0e10cSrcweir 			ScChangeAction* pAct = ( (j == nActionMax && pLast &&
3284cdf0e10cSrcweir 				pLast->GetActionNumber() == j) ? pLast : GetAction( j ) );
3285cdf0e10cSrcweir 			if ( pAct )
3286cdf0e10cSrcweir 			{
3287cdf0e10cSrcweir 				if ( pAct->IsDeleteType() )
3288cdf0e10cSrcweir 				{
3289cdf0e10cSrcweir 					if ( j == nEndAction || (pAct != pLast &&
3290cdf0e10cSrcweir 							((ScChangeActionDel*)pAct)->IsTopDelete()) )
3291cdf0e10cSrcweir 					{
3292cdf0e10cSrcweir 						SetInDeleteTop( sal_True );
3293cdf0e10cSrcweir 						SetInDeleteRange( ((ScChangeActionDel*)pAct)->
3294cdf0e10cSrcweir 							GetOverAllRange().MakeRange() );
3295cdf0e10cSrcweir 					}
3296cdf0e10cSrcweir 				}
3297cdf0e10cSrcweir 				UpdateReference( pAct, sal_True );
3298cdf0e10cSrcweir 				SetInDeleteTop( sal_False );
3299cdf0e10cSrcweir 				Remove( pAct );
3300cdf0e10cSrcweir 				if ( IsInPasteCut() )
3301cdf0e10cSrcweir 					aPasteCutTable.Insert( pAct->GetActionNumber(), pAct );
3302cdf0e10cSrcweir 				else
3303cdf0e10cSrcweir 				{
3304cdf0e10cSrcweir 					if ( j == nStartAction && pAct->GetType() == SC_CAT_MOVE )
3305cdf0e10cSrcweir 					{
3306cdf0e10cSrcweir 						ScChangeActionMove* pMove = (ScChangeActionMove*) pAct;
3307cdf0e10cSrcweir 						sal_uLong nStart = pMove->GetStartLastCut();
3308cdf0e10cSrcweir 						sal_uLong nEnd = pMove->GetEndLastCut();
3309cdf0e10cSrcweir 						if ( nStart && nStart <= nEnd )
3310cdf0e10cSrcweir 						{	// LastCut wiederherstellen
3311cdf0e10cSrcweir 							//! Links vor Cut-Append aufloesen
3312cdf0e10cSrcweir 							pMove->RemoveAllLinks();
3313cdf0e10cSrcweir 							StartBlockModify( SC_CTM_APPEND, nStart );
3314cdf0e10cSrcweir 							for ( sal_uLong nCut = nStart; nCut <= nEnd; nCut++ )
3315cdf0e10cSrcweir 							{
3316cdf0e10cSrcweir 								ScChangeAction* pCut = aPasteCutTable.Remove( nCut );
3317cdf0e10cSrcweir 								if ( pCut )
3318cdf0e10cSrcweir 								{
3319cdf0e10cSrcweir 									DBG_ASSERT( !aTable.Get( nCut ), "ScChangeTrack::Undo: nCut dup" );
3320cdf0e10cSrcweir 									Append( pCut, nCut );
3321cdf0e10cSrcweir 								}
3322cdf0e10cSrcweir 								else
3323cdf0e10cSrcweir 								{
3324cdf0e10cSrcweir 									DBG_ERROR( "ScChangeTrack::Undo: nCut not found" );
3325cdf0e10cSrcweir 								}
3326cdf0e10cSrcweir 							}
3327cdf0e10cSrcweir 							EndBlockModify( nEnd );
3328cdf0e10cSrcweir 							ResetLastCut();
3329cdf0e10cSrcweir 							nStartLastCut = nStart;
3330cdf0e10cSrcweir 							nEndLastCut = nEnd;
3331cdf0e10cSrcweir 							pLastCutMove = pMove;
3332cdf0e10cSrcweir 							SetLastCutMoveRange(
3333cdf0e10cSrcweir 								pMove->GetFromRange().MakeRange(), pDoc );
3334cdf0e10cSrcweir 						}
3335cdf0e10cSrcweir 						else
3336cdf0e10cSrcweir 							delete pMove;
3337cdf0e10cSrcweir 					}
3338cdf0e10cSrcweir 					else
3339cdf0e10cSrcweir 						delete pAct;
3340cdf0e10cSrcweir 				}
3341cdf0e10cSrcweir 			}
3342cdf0e10cSrcweir 		}
3343cdf0e10cSrcweir 		EndBlockModify( nEndAction );
3344cdf0e10cSrcweir 	}
3345cdf0e10cSrcweir 
3346cdf0e10cSrcweir     // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3347cdf0e10cSrcweir     if ( bMerge )
3348cdf0e10cSrcweir     {
3349cdf0e10cSrcweir         SetMergeState( SC_CTMS_OTHER );
3350cdf0e10cSrcweir     }
3351cdf0e10cSrcweir }
3352cdf0e10cSrcweir 
3353cdf0e10cSrcweir 
3354cdf0e10cSrcweir // static
MergeIgnore(const ScChangeAction & rAction,sal_uLong nFirstMerge)3355cdf0e10cSrcweir sal_Bool ScChangeTrack::MergeIgnore( const ScChangeAction& rAction, sal_uLong nFirstMerge )
3356cdf0e10cSrcweir {
3357cdf0e10cSrcweir 	if ( rAction.IsRejected() )
3358cdf0e10cSrcweir 		return sal_True;				// da kommt noch eine passende Reject-Action
3359cdf0e10cSrcweir 
3360cdf0e10cSrcweir 	if ( rAction.IsRejecting() && rAction.GetRejectAction() >= nFirstMerge )
3361cdf0e10cSrcweir 		return sal_True;				// da ist sie
3362cdf0e10cSrcweir 
3363cdf0e10cSrcweir 	return sal_False;					// alles andere
3364cdf0e10cSrcweir }
3365cdf0e10cSrcweir 
3366cdf0e10cSrcweir 
MergePrepare(ScChangeAction * pFirstMerge,bool bShared)3367cdf0e10cSrcweir void ScChangeTrack::MergePrepare( ScChangeAction* pFirstMerge, bool bShared )
3368cdf0e10cSrcweir {
3369cdf0e10cSrcweir 	SetMergeState( SC_CTMS_PREPARE );
3370cdf0e10cSrcweir 	sal_uLong nFirstMerge = pFirstMerge->GetActionNumber();
3371cdf0e10cSrcweir 	ScChangeAction* pAct = GetLast();
3372cdf0e10cSrcweir 	if ( pAct )
3373cdf0e10cSrcweir 	{
3374cdf0e10cSrcweir 		SetLastMerge( pAct->GetActionNumber() );
3375cdf0e10cSrcweir 		while ( pAct )
3376cdf0e10cSrcweir 		{	// rueckwaerts, Deletes in richtiger Reihenfolge
3377cdf0e10cSrcweir             // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3378cdf0e10cSrcweir             if ( bShared || !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) )
3379cdf0e10cSrcweir 			{
3380cdf0e10cSrcweir 				if ( pAct->IsDeleteType() )
3381cdf0e10cSrcweir 				{
3382cdf0e10cSrcweir 					if ( ((ScChangeActionDel*)pAct)->IsTopDelete() )
3383cdf0e10cSrcweir 					{
3384cdf0e10cSrcweir 						SetInDeleteTop( sal_True );
3385cdf0e10cSrcweir 						SetInDeleteRange( ((ScChangeActionDel*)pAct)->
3386cdf0e10cSrcweir 							GetOverAllRange().MakeRange() );
3387cdf0e10cSrcweir 					}
3388cdf0e10cSrcweir 				}
3389cdf0e10cSrcweir 				UpdateReference( pAct, sal_True );
3390cdf0e10cSrcweir 				SetInDeleteTop( sal_False );
3391cdf0e10cSrcweir 				pAct->DeleteCellEntries();		// sonst GPF bei Track Clear()
3392cdf0e10cSrcweir 			}
3393cdf0e10cSrcweir 			pAct = ( pAct == pFirstMerge ? NULL : pAct->GetPrev() );
3394cdf0e10cSrcweir 		}
3395cdf0e10cSrcweir 	}
3396cdf0e10cSrcweir 	SetMergeState( SC_CTMS_OTHER );		//! nachfolgende per default MergeOther
3397cdf0e10cSrcweir }
3398cdf0e10cSrcweir 
3399cdf0e10cSrcweir 
MergeOwn(ScChangeAction * pAct,sal_uLong nFirstMerge,bool bShared)3400cdf0e10cSrcweir void ScChangeTrack::MergeOwn( ScChangeAction* pAct, sal_uLong nFirstMerge, bool bShared )
3401cdf0e10cSrcweir {
3402cdf0e10cSrcweir     // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3403cdf0e10cSrcweir     if ( bShared || !ScChangeTrack::MergeIgnore( *pAct, nFirstMerge ) )
3404cdf0e10cSrcweir 	{
3405cdf0e10cSrcweir 		SetMergeState( SC_CTMS_OWN );
3406cdf0e10cSrcweir 		if ( pAct->IsDeleteType() )
3407cdf0e10cSrcweir 		{
3408cdf0e10cSrcweir 			if ( ((ScChangeActionDel*)pAct)->IsTopDelete() )
3409cdf0e10cSrcweir 			{
3410cdf0e10cSrcweir 				SetInDeleteTop( sal_True );
3411cdf0e10cSrcweir 				SetInDeleteRange( ((ScChangeActionDel*)pAct)->
3412cdf0e10cSrcweir 					GetOverAllRange().MakeRange() );
3413cdf0e10cSrcweir 			}
3414cdf0e10cSrcweir 		}
3415cdf0e10cSrcweir 		UpdateReference( pAct, sal_False );
3416cdf0e10cSrcweir 		SetInDeleteTop( sal_False );
3417cdf0e10cSrcweir 		SetMergeState( SC_CTMS_OTHER );		//! nachfolgende per default MergeOther
3418cdf0e10cSrcweir 	}
3419cdf0e10cSrcweir }
3420cdf0e10cSrcweir 
3421cdf0e10cSrcweir 
UpdateReference(ScChangeAction * pAct,sal_Bool bUndo)3422cdf0e10cSrcweir void ScChangeTrack::UpdateReference( ScChangeAction* pAct, sal_Bool bUndo )
3423cdf0e10cSrcweir {
3424cdf0e10cSrcweir 	ScChangeActionType eActType = pAct->GetType();
3425cdf0e10cSrcweir 	if ( eActType == SC_CAT_CONTENT || eActType == SC_CAT_REJECT )
3426cdf0e10cSrcweir 		return ;
3427cdf0e10cSrcweir 
3428cdf0e10cSrcweir 	//! Formelzellen haengen nicht im Dokument
3429cdf0e10cSrcweir 	sal_Bool bOldAutoCalc = pDoc->GetAutoCalc();
3430cdf0e10cSrcweir 	pDoc->SetAutoCalc( sal_False );
3431cdf0e10cSrcweir 	sal_Bool bOldNoListening = pDoc->GetNoListening();
3432cdf0e10cSrcweir 	pDoc->SetNoListening( sal_True );
3433cdf0e10cSrcweir 	//! Formelzellen ExpandRefs synchronisiert zu denen im Dokument
3434cdf0e10cSrcweir 	sal_Bool bOldExpandRefs = pDoc->IsExpandRefs();
3435cdf0e10cSrcweir 	if ( (!bUndo && pAct->IsInsertType()) || (bUndo && pAct->IsDeleteType()) )
3436cdf0e10cSrcweir 		pDoc->SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
3437cdf0e10cSrcweir 
3438cdf0e10cSrcweir 	if ( pAct->IsDeleteType() )
3439cdf0e10cSrcweir 	{
3440cdf0e10cSrcweir 		SetInDeleteUndo( bUndo );
3441cdf0e10cSrcweir 		SetInDelete( sal_True );
3442cdf0e10cSrcweir 	}
3443cdf0e10cSrcweir 	else if ( GetMergeState() == SC_CTMS_OWN )
3444cdf0e10cSrcweir 	{
3445cdf0e10cSrcweir 		// Referenzen von Formelzellen wiederherstellen,
3446cdf0e10cSrcweir 		// vorheriges MergePrepare war bei einem Insert wie ein Delete
3447cdf0e10cSrcweir 		if ( pAct->IsInsertType() )
3448cdf0e10cSrcweir 			SetInDeleteUndo( sal_True );
3449cdf0e10cSrcweir 	}
3450cdf0e10cSrcweir 
3451cdf0e10cSrcweir 	//! erst die generated, als waeren sie vorher getrackt worden
3452cdf0e10cSrcweir 	if ( pFirstGeneratedDelContent )
3453cdf0e10cSrcweir 		UpdateReference( (ScChangeAction**)&pFirstGeneratedDelContent, pAct,
3454cdf0e10cSrcweir 			bUndo );
3455cdf0e10cSrcweir 	UpdateReference( &pFirst, pAct, bUndo );
3456cdf0e10cSrcweir 
3457cdf0e10cSrcweir 	SetInDelete( sal_False );
3458cdf0e10cSrcweir 	SetInDeleteUndo( sal_False );
3459cdf0e10cSrcweir 
3460cdf0e10cSrcweir 	pDoc->SetExpandRefs( bOldExpandRefs );
3461cdf0e10cSrcweir 	pDoc->SetNoListening( bOldNoListening );
3462cdf0e10cSrcweir 	pDoc->SetAutoCalc( bOldAutoCalc );
3463cdf0e10cSrcweir }
3464cdf0e10cSrcweir 
3465cdf0e10cSrcweir 
UpdateReference(ScChangeAction ** ppFirstAction,ScChangeAction * pAct,sal_Bool bUndo)3466cdf0e10cSrcweir void ScChangeTrack::UpdateReference( ScChangeAction** ppFirstAction,
3467cdf0e10cSrcweir 		ScChangeAction* pAct, sal_Bool bUndo )
3468cdf0e10cSrcweir {
3469cdf0e10cSrcweir 	ScChangeActionType eActType = pAct->GetType();
3470cdf0e10cSrcweir 	sal_Bool bGeneratedDelContents =
3471cdf0e10cSrcweir 		( ppFirstAction == (ScChangeAction**)&pFirstGeneratedDelContent );
3472cdf0e10cSrcweir 	const ScBigRange& rOrgRange = pAct->GetBigRange();
3473cdf0e10cSrcweir 	ScBigRange aRange( rOrgRange );
3474cdf0e10cSrcweir 	ScBigRange aDelRange( rOrgRange );
3475cdf0e10cSrcweir 	sal_Int32 nDx, nDy, nDz;
3476cdf0e10cSrcweir 	nDx = nDy = nDz = 0;
3477cdf0e10cSrcweir 	UpdateRefMode eMode = URM_INSDEL;
3478cdf0e10cSrcweir 	sal_Bool bDel = sal_False;
3479cdf0e10cSrcweir 	switch ( eActType )
3480cdf0e10cSrcweir 	{
3481cdf0e10cSrcweir 		case SC_CAT_INSERT_COLS :
3482cdf0e10cSrcweir 			aRange.aEnd.SetCol( nInt32Max );
3483cdf0e10cSrcweir 			nDx = rOrgRange.aEnd.Col() - rOrgRange.aStart.Col() + 1;
3484cdf0e10cSrcweir 		break;
3485cdf0e10cSrcweir 		case SC_CAT_INSERT_ROWS :
3486cdf0e10cSrcweir 			aRange.aEnd.SetRow( nInt32Max );
3487cdf0e10cSrcweir 			nDy = rOrgRange.aEnd.Row() - rOrgRange.aStart.Row() + 1;
3488cdf0e10cSrcweir 		break;
3489cdf0e10cSrcweir 		case SC_CAT_INSERT_TABS :
3490cdf0e10cSrcweir 			aRange.aEnd.SetTab( nInt32Max );
3491cdf0e10cSrcweir 			nDz = rOrgRange.aEnd.Tab() - rOrgRange.aStart.Tab() + 1;
3492cdf0e10cSrcweir 		break;
3493cdf0e10cSrcweir 		case SC_CAT_DELETE_COLS :
3494cdf0e10cSrcweir 			aRange.aEnd.SetCol( nInt32Max );
3495cdf0e10cSrcweir 			nDx = -(rOrgRange.aEnd.Col() - rOrgRange.aStart.Col() + 1);
3496cdf0e10cSrcweir 			aDelRange.aEnd.SetCol( aDelRange.aStart.Col() - nDx - 1 );
3497cdf0e10cSrcweir 			bDel = sal_True;
3498cdf0e10cSrcweir 		break;
3499cdf0e10cSrcweir 		case SC_CAT_DELETE_ROWS :
3500cdf0e10cSrcweir 			aRange.aEnd.SetRow( nInt32Max );
3501cdf0e10cSrcweir 			nDy = -(rOrgRange.aEnd.Row() - rOrgRange.aStart.Row() + 1);
3502cdf0e10cSrcweir 			aDelRange.aEnd.SetRow( aDelRange.aStart.Row() - nDy - 1 );
3503cdf0e10cSrcweir 			bDel = sal_True;
3504cdf0e10cSrcweir 		break;
3505cdf0e10cSrcweir 		case SC_CAT_DELETE_TABS :
3506cdf0e10cSrcweir 			aRange.aEnd.SetTab( nInt32Max );
3507cdf0e10cSrcweir 			nDz = -(rOrgRange.aEnd.Tab() - rOrgRange.aStart.Tab() + 1);
3508cdf0e10cSrcweir 			aDelRange.aEnd.SetTab( aDelRange.aStart.Tab() - nDz - 1 );
3509cdf0e10cSrcweir 			bDel = sal_True;
3510cdf0e10cSrcweir 		break;
3511cdf0e10cSrcweir 		case SC_CAT_MOVE :
3512cdf0e10cSrcweir 			eMode = URM_MOVE;
3513cdf0e10cSrcweir 			((ScChangeActionMove*)pAct)->GetDelta( nDx, nDy, nDz );
3514cdf0e10cSrcweir 		break;
3515cdf0e10cSrcweir 		default:
3516cdf0e10cSrcweir 			DBG_ERROR( "ScChangeTrack::UpdateReference: unknown Type" );
3517cdf0e10cSrcweir 	}
3518cdf0e10cSrcweir 	if ( bUndo )
3519cdf0e10cSrcweir 	{
3520cdf0e10cSrcweir 		nDx = -nDx;
3521cdf0e10cSrcweir 		nDy = -nDy;
3522cdf0e10cSrcweir 		nDz = -nDz;
3523cdf0e10cSrcweir 	}
3524cdf0e10cSrcweir 	if ( bDel )
3525cdf0e10cSrcweir 	{	//! fuer diesen Mechanismus gilt:
3526cdf0e10cSrcweir 		//! es gibt nur ganze, einfache geloeschte Spalten/Zeilen
3527cdf0e10cSrcweir 		ScChangeActionDel* pActDel = (ScChangeActionDel*) pAct;
3528cdf0e10cSrcweir 		if ( !bUndo )
3529cdf0e10cSrcweir 		{	// Delete
3530cdf0e10cSrcweir             ScChangeActionType eInsType = SC_CAT_NONE;      // for Insert-Undo-"Deletes"
3531cdf0e10cSrcweir 			switch ( eActType )
3532cdf0e10cSrcweir 			{
3533cdf0e10cSrcweir 				case SC_CAT_DELETE_COLS :
3534cdf0e10cSrcweir 					eInsType = SC_CAT_INSERT_COLS;
3535cdf0e10cSrcweir 				break;
3536cdf0e10cSrcweir 				case SC_CAT_DELETE_ROWS :
3537cdf0e10cSrcweir 					eInsType = SC_CAT_INSERT_ROWS;
3538cdf0e10cSrcweir 				break;
3539cdf0e10cSrcweir 				case SC_CAT_DELETE_TABS :
3540cdf0e10cSrcweir 					eInsType = SC_CAT_INSERT_TABS;
3541cdf0e10cSrcweir 				break;
3542cdf0e10cSrcweir                 default:
3543cdf0e10cSrcweir                 {
3544cdf0e10cSrcweir                     // added to avoid warnings
3545cdf0e10cSrcweir                 }
3546cdf0e10cSrcweir 			}
3547cdf0e10cSrcweir 			for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3548cdf0e10cSrcweir 			{
3549cdf0e10cSrcweir 				if ( p == pAct )
3550cdf0e10cSrcweir 					continue;	// for
3551cdf0e10cSrcweir 				sal_Bool bUpdate = sal_True;
3552cdf0e10cSrcweir 				if ( GetMergeState() == SC_CTMS_OTHER &&
3553cdf0e10cSrcweir 						p->GetActionNumber() <= GetLastMerge() )
3554cdf0e10cSrcweir 				{	// Delete in mergendem Dokument, Action im zu mergenden
3555cdf0e10cSrcweir 					if ( p->IsInsertType() )
3556cdf0e10cSrcweir 					{
3557cdf0e10cSrcweir 						// Bei Insert Referenzen nur anpassen, wenn das Delete
3558cdf0e10cSrcweir 						// das Insert nicht schneidet.
3559cdf0e10cSrcweir 						if ( !aDelRange.Intersects( p->GetBigRange() ) )
3560cdf0e10cSrcweir 							p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3561cdf0e10cSrcweir 						bUpdate = sal_False;
3562cdf0e10cSrcweir 					}
3563cdf0e10cSrcweir 					else if ( p->GetType() == SC_CAT_CONTENT &&
3564cdf0e10cSrcweir 							p->IsDeletedInDelType( eInsType ) )
3565cdf0e10cSrcweir 					{	// Content in Insert-Undo-"Delete"
3566cdf0e10cSrcweir 						// Nicht anpassen, wenn dieses Delete in dem
3567cdf0e10cSrcweir 						// Insert-"Delete" sein wuerde (ist nur verschoben).
3568cdf0e10cSrcweir 						if ( aDelRange.In( p->GetBigRange().aStart ) )
3569cdf0e10cSrcweir 							bUpdate = sal_False;
3570cdf0e10cSrcweir 						else
3571cdf0e10cSrcweir 						{
3572cdf0e10cSrcweir 							const ScChangeActionLinkEntry* pLink = p->GetDeletedIn();
3573cdf0e10cSrcweir 							while ( pLink && bUpdate )
3574cdf0e10cSrcweir 							{
3575cdf0e10cSrcweir 								const ScChangeAction* pDel = pLink->GetAction();
3576cdf0e10cSrcweir 								if ( pDel && pDel->GetType() == eInsType &&
3577cdf0e10cSrcweir 										pDel->GetBigRange().In( aDelRange ) )
3578cdf0e10cSrcweir 									bUpdate = sal_False;
3579cdf0e10cSrcweir 								pLink = pLink->GetNext();
3580cdf0e10cSrcweir 							}
3581cdf0e10cSrcweir 						}
3582cdf0e10cSrcweir 					}
3583cdf0e10cSrcweir 					if ( !bUpdate )
3584cdf0e10cSrcweir 						continue;	// for
3585cdf0e10cSrcweir 				}
3586cdf0e10cSrcweir 				if ( aDelRange.In( p->GetBigRange() ) )
3587cdf0e10cSrcweir 				{
3588cdf0e10cSrcweir 					// Innerhalb eines gerade geloeschten Bereiches nicht
3589cdf0e10cSrcweir 					// anpassen, stattdessen dem Bereich zuordnen.
3590cdf0e10cSrcweir 					// Mehrfache geloeschte Bereiche "stapeln".
3591cdf0e10cSrcweir 					// Kreuzende Deletes setzen mehrfach geloescht.
3592cdf0e10cSrcweir 					if ( !p->IsDeletedInDelType( eActType ) )
3593cdf0e10cSrcweir 					{
3594cdf0e10cSrcweir 						p->SetDeletedIn( pActDel );
3595cdf0e10cSrcweir 						// GeneratedDelContent in zu loeschende Liste aufnehmen
3596cdf0e10cSrcweir 						if ( bGeneratedDelContents )
3597cdf0e10cSrcweir 							pActDel->AddContent( (ScChangeActionContent*) p );
3598cdf0e10cSrcweir 					}
3599cdf0e10cSrcweir 					bUpdate = sal_False;
3600cdf0e10cSrcweir 				}
3601cdf0e10cSrcweir 				else
3602cdf0e10cSrcweir 				{
3603cdf0e10cSrcweir 					// Eingefuegte Bereiche abschneiden, wenn Start/End im
3604cdf0e10cSrcweir 					// Delete liegt, aber das Insert nicht komplett innerhalb
3605cdf0e10cSrcweir 					// des Delete liegt bzw. das Delete nicht komplett im
3606cdf0e10cSrcweir 					// Insert. Das Delete merkt sich, welchem Insert es was
3607cdf0e10cSrcweir 					// abgeschnitten hat, es kann auch nur ein einziges Insert
3608cdf0e10cSrcweir 					// sein (weil Delete einspaltig/einzeilig ist).
3609cdf0e10cSrcweir 					// Abgeschnittene Moves kann es viele geben.
3610cdf0e10cSrcweir 					//! Ein Delete ist immer einspaltig/einzeilig, deswegen 1
3611cdf0e10cSrcweir 					//! ohne die Ueberlappung auszurechnen.
3612cdf0e10cSrcweir 					switch ( p->GetType() )
3613cdf0e10cSrcweir 					{
3614cdf0e10cSrcweir 						case SC_CAT_INSERT_COLS :
3615cdf0e10cSrcweir 							if ( eActType == SC_CAT_DELETE_COLS )
3616cdf0e10cSrcweir 							{
3617cdf0e10cSrcweir 								if ( aDelRange.In( p->GetBigRange().aStart ) )
3618cdf0e10cSrcweir 								{
3619cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3620cdf0e10cSrcweir 										(ScChangeActionIns*) p, 1 );
3621cdf0e10cSrcweir 									p->GetBigRange().aStart.IncCol( 1 );
3622cdf0e10cSrcweir 								}
3623cdf0e10cSrcweir 								else if ( aDelRange.In( p->GetBigRange().aEnd ) )
3624cdf0e10cSrcweir 								{
3625cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3626cdf0e10cSrcweir 										(ScChangeActionIns*) p, -1 );
3627cdf0e10cSrcweir 									p->GetBigRange().aEnd.IncCol( -1 );
3628cdf0e10cSrcweir 								}
3629cdf0e10cSrcweir 							}
3630cdf0e10cSrcweir 						break;
3631cdf0e10cSrcweir 						case SC_CAT_INSERT_ROWS :
3632cdf0e10cSrcweir 							if ( eActType == SC_CAT_DELETE_ROWS )
3633cdf0e10cSrcweir 							{
3634cdf0e10cSrcweir 								if ( aDelRange.In( p->GetBigRange().aStart ) )
3635cdf0e10cSrcweir 								{
3636cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3637cdf0e10cSrcweir 										(ScChangeActionIns*) p, 1 );
3638cdf0e10cSrcweir 									p->GetBigRange().aStart.IncRow( 1 );
3639cdf0e10cSrcweir 								}
3640cdf0e10cSrcweir 								else if ( aDelRange.In( p->GetBigRange().aEnd ) )
3641cdf0e10cSrcweir 								{
3642cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3643cdf0e10cSrcweir 										(ScChangeActionIns*) p, -1 );
3644cdf0e10cSrcweir 									p->GetBigRange().aEnd.IncRow( -1 );
3645cdf0e10cSrcweir 								}
3646cdf0e10cSrcweir 							}
3647cdf0e10cSrcweir 						break;
3648cdf0e10cSrcweir 						case SC_CAT_INSERT_TABS :
3649cdf0e10cSrcweir 							if ( eActType == SC_CAT_DELETE_TABS )
3650cdf0e10cSrcweir 							{
3651cdf0e10cSrcweir 								if ( aDelRange.In( p->GetBigRange().aStart ) )
3652cdf0e10cSrcweir 								{
3653cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3654cdf0e10cSrcweir 										(ScChangeActionIns*) p, 1 );
3655cdf0e10cSrcweir 									p->GetBigRange().aStart.IncTab( 1 );
3656cdf0e10cSrcweir 								}
3657cdf0e10cSrcweir 								else if ( aDelRange.In( p->GetBigRange().aEnd ) )
3658cdf0e10cSrcweir 								{
3659cdf0e10cSrcweir 									pActDel->SetCutOffInsert(
3660cdf0e10cSrcweir 										(ScChangeActionIns*) p, -1 );
3661cdf0e10cSrcweir 									p->GetBigRange().aEnd.IncTab( -1 );
3662cdf0e10cSrcweir 								}
3663cdf0e10cSrcweir 							}
3664cdf0e10cSrcweir 						break;
3665cdf0e10cSrcweir 						case SC_CAT_MOVE :
3666cdf0e10cSrcweir 						{
3667cdf0e10cSrcweir 							ScChangeActionMove* pMove = (ScChangeActionMove*) p;
3668cdf0e10cSrcweir 							short nFrom = 0;
3669cdf0e10cSrcweir 							short nTo = 0;
3670cdf0e10cSrcweir 							if ( aDelRange.In( pMove->GetBigRange().aStart ) )
3671cdf0e10cSrcweir 								nTo = 1;
3672cdf0e10cSrcweir 							else if ( aDelRange.In( pMove->GetBigRange().aEnd ) )
3673cdf0e10cSrcweir 								nTo = -1;
3674cdf0e10cSrcweir 							if ( aDelRange.In( pMove->GetFromRange().aStart ) )
3675cdf0e10cSrcweir 								nFrom = 1;
3676cdf0e10cSrcweir 							else if ( aDelRange.In( pMove->GetFromRange().aEnd ) )
3677cdf0e10cSrcweir 								nFrom = -1;
3678cdf0e10cSrcweir 							if ( nFrom )
3679cdf0e10cSrcweir 							{
3680cdf0e10cSrcweir 								switch ( eActType )
3681cdf0e10cSrcweir 								{
3682cdf0e10cSrcweir 									case SC_CAT_DELETE_COLS :
3683cdf0e10cSrcweir 										if ( nFrom > 0 )
3684cdf0e10cSrcweir 											pMove->GetFromRange().aStart.IncCol( nFrom );
3685cdf0e10cSrcweir 										else
3686cdf0e10cSrcweir 											pMove->GetFromRange().aEnd.IncCol( nFrom );
3687cdf0e10cSrcweir 									break;
3688cdf0e10cSrcweir 									case SC_CAT_DELETE_ROWS :
3689cdf0e10cSrcweir 										if ( nFrom > 0 )
3690cdf0e10cSrcweir 											pMove->GetFromRange().aStart.IncRow( nFrom );
3691cdf0e10cSrcweir 										else
3692cdf0e10cSrcweir 											pMove->GetFromRange().aEnd.IncRow( nFrom );
3693cdf0e10cSrcweir 									break;
3694cdf0e10cSrcweir 									case SC_CAT_DELETE_TABS :
3695cdf0e10cSrcweir 										if ( nFrom > 0 )
3696cdf0e10cSrcweir 											pMove->GetFromRange().aStart.IncTab( nFrom );
3697cdf0e10cSrcweir 										else
3698cdf0e10cSrcweir 											pMove->GetFromRange().aEnd.IncTab( nFrom );
3699cdf0e10cSrcweir 									break;
3700cdf0e10cSrcweir                                     default:
3701cdf0e10cSrcweir                                     {
3702cdf0e10cSrcweir                                         // added to avoid warnings
3703cdf0e10cSrcweir                                     }
3704cdf0e10cSrcweir 								}
3705cdf0e10cSrcweir 							}
3706cdf0e10cSrcweir 							if ( nTo )
3707cdf0e10cSrcweir 							{
3708cdf0e10cSrcweir 								switch ( eActType )
3709cdf0e10cSrcweir 								{
3710cdf0e10cSrcweir 									case SC_CAT_DELETE_COLS :
3711cdf0e10cSrcweir 										if ( nTo > 0 )
3712cdf0e10cSrcweir 											pMove->GetBigRange().aStart.IncCol( nTo );
3713cdf0e10cSrcweir 										else
3714cdf0e10cSrcweir 											pMove->GetBigRange().aEnd.IncCol( nTo );
3715cdf0e10cSrcweir 									break;
3716cdf0e10cSrcweir 									case SC_CAT_DELETE_ROWS :
3717cdf0e10cSrcweir 										if ( nTo > 0 )
3718cdf0e10cSrcweir 											pMove->GetBigRange().aStart.IncRow( nTo );
3719cdf0e10cSrcweir 										else
3720cdf0e10cSrcweir 											pMove->GetBigRange().aEnd.IncRow( nTo );
3721cdf0e10cSrcweir 									break;
3722cdf0e10cSrcweir 									case SC_CAT_DELETE_TABS :
3723cdf0e10cSrcweir 										if ( nTo > 0 )
3724cdf0e10cSrcweir 											pMove->GetBigRange().aStart.IncTab( nTo );
3725cdf0e10cSrcweir 										else
3726cdf0e10cSrcweir 											pMove->GetBigRange().aEnd.IncTab( nTo );
3727cdf0e10cSrcweir 									break;
3728cdf0e10cSrcweir                                     default:
3729cdf0e10cSrcweir                                     {
3730cdf0e10cSrcweir                                         // added to avoid warnings
3731cdf0e10cSrcweir                                     }
3732cdf0e10cSrcweir 								}
3733cdf0e10cSrcweir 							}
3734cdf0e10cSrcweir 							if ( nFrom || nTo )
3735cdf0e10cSrcweir 							{
3736cdf0e10cSrcweir 								ScChangeActionDelMoveEntry* pLink =
3737cdf0e10cSrcweir 									pActDel->AddCutOffMove( pMove, nFrom, nTo );
3738cdf0e10cSrcweir 								pMove->AddLink( pActDel, pLink );
3739cdf0e10cSrcweir 							}
3740cdf0e10cSrcweir 						}
3741cdf0e10cSrcweir 						break;
3742cdf0e10cSrcweir                         default:
3743cdf0e10cSrcweir                         {
3744cdf0e10cSrcweir                             // added to avoid warnings
3745cdf0e10cSrcweir                         }
3746cdf0e10cSrcweir 					}
3747cdf0e10cSrcweir 				}
3748cdf0e10cSrcweir 				if ( bUpdate )
3749cdf0e10cSrcweir 				{
3750cdf0e10cSrcweir 					p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3751cdf0e10cSrcweir 					if ( p->GetType() == eActType && !p->IsRejected() &&
3752cdf0e10cSrcweir 							!pActDel->IsDeletedIn() &&
3753cdf0e10cSrcweir 							p->GetBigRange().In( aDelRange ) )
3754cdf0e10cSrcweir 						pActDel->SetDeletedIn( p );		// "druntergerutscht"
3755cdf0e10cSrcweir 				}
3756cdf0e10cSrcweir 			}
3757cdf0e10cSrcweir 		}
3758cdf0e10cSrcweir 		else
3759cdf0e10cSrcweir 		{	// Undo Delete
3760cdf0e10cSrcweir 			for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3761cdf0e10cSrcweir 			{
3762cdf0e10cSrcweir 				if ( p == pAct )
3763cdf0e10cSrcweir 					continue;	// for
3764cdf0e10cSrcweir 				sal_Bool bUpdate = sal_True;
3765cdf0e10cSrcweir 				if ( aDelRange.In( p->GetBigRange() ) )
3766cdf0e10cSrcweir 				{
3767cdf0e10cSrcweir                     // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3768cdf0e10cSrcweir                     if ( GetMergeState() == SC_CTMS_UNDO && !p->IsDeletedIn( pAct ) && pAct->IsDeleteType() &&
3769cdf0e10cSrcweir                          ( p->GetType() == SC_CAT_CONTENT ||
3770cdf0e10cSrcweir                            p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS ||
3771cdf0e10cSrcweir                            p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) )
3772cdf0e10cSrcweir                     {
3773cdf0e10cSrcweir                         p->SetDeletedIn( pAct );
3774cdf0e10cSrcweir                     }
3775cdf0e10cSrcweir 
3776cdf0e10cSrcweir 					if ( p->IsDeletedInDelType( eActType ) )
3777cdf0e10cSrcweir 					{
3778cdf0e10cSrcweir 						if ( p->IsDeletedIn( pActDel ) )
3779cdf0e10cSrcweir 						{
3780cdf0e10cSrcweir 							if ( p->GetType() != SC_CAT_CONTENT ||
3781cdf0e10cSrcweir 									((ScChangeActionContent*)p)->IsTopContent() )
3782cdf0e10cSrcweir 							{	// erst der TopContent wird wirklich entfernt
3783cdf0e10cSrcweir 								p->RemoveDeletedIn( pActDel );
3784cdf0e10cSrcweir 								// GeneratedDelContent _nicht_ aus Liste loeschen,
3785cdf0e10cSrcweir 								// wir brauchen ihn evtl. noch fuer Reject,
3786cdf0e10cSrcweir 								// geloescht wird in DeleteCellEntries
3787cdf0e10cSrcweir 							}
3788cdf0e10cSrcweir 						}
3789cdf0e10cSrcweir 						bUpdate = sal_False;
3790cdf0e10cSrcweir 					}
3791cdf0e10cSrcweir 					else if ( eActType != SC_CAT_DELETE_TABS &&
3792cdf0e10cSrcweir 							p->IsDeletedInDelType( SC_CAT_DELETE_TABS ) )
3793cdf0e10cSrcweir 					{	// in geloeschten Tabellen nicht updaten,
3794cdf0e10cSrcweir 						// ausser wenn Tabelle verschoben wird
3795cdf0e10cSrcweir 						bUpdate = sal_False;
3796cdf0e10cSrcweir 					}
3797cdf0e10cSrcweir 					if ( p->GetType() == eActType && pActDel->IsDeletedIn( p ) )
3798cdf0e10cSrcweir 					{
3799cdf0e10cSrcweir 						pActDel->RemoveDeletedIn( p );	// "druntergerutscht"
3800cdf0e10cSrcweir 						bUpdate = sal_True;
3801cdf0e10cSrcweir 					}
3802cdf0e10cSrcweir 				}
3803cdf0e10cSrcweir 				if ( bUpdate )
3804cdf0e10cSrcweir 					p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3805cdf0e10cSrcweir 			}
3806cdf0e10cSrcweir 			if ( !bGeneratedDelContents )
3807cdf0e10cSrcweir 			{	// die werden sonst noch fuer das echte Undo gebraucht
3808cdf0e10cSrcweir 				pActDel->UndoCutOffInsert();
3809cdf0e10cSrcweir 				pActDel->UndoCutOffMoves();
3810cdf0e10cSrcweir 			}
3811cdf0e10cSrcweir 		}
3812cdf0e10cSrcweir 	}
3813cdf0e10cSrcweir 	else if ( eActType == SC_CAT_MOVE )
3814cdf0e10cSrcweir 	{
3815cdf0e10cSrcweir 		ScChangeActionMove* pActMove = (ScChangeActionMove*) pAct;
3816cdf0e10cSrcweir 		sal_Bool bLastCutMove = ( pActMove == pLastCutMove );
3817cdf0e10cSrcweir 		const ScBigRange& rTo = pActMove->GetBigRange();
3818cdf0e10cSrcweir 		const ScBigRange& rFrom = pActMove->GetFromRange();
3819cdf0e10cSrcweir 		if ( !bUndo )
3820cdf0e10cSrcweir 		{	// Move
3821cdf0e10cSrcweir 			for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3822cdf0e10cSrcweir 			{
3823cdf0e10cSrcweir 				if ( p == pAct )
3824cdf0e10cSrcweir 					continue;	// for
3825cdf0e10cSrcweir 				if ( p->GetType() == SC_CAT_CONTENT )
3826cdf0e10cSrcweir 				{
3827cdf0e10cSrcweir 					// Inhalt in Ziel deleten (Inhalt in Quelle moven)
3828cdf0e10cSrcweir 					if ( rTo.In( p->GetBigRange() ) )
3829cdf0e10cSrcweir 					{
3830cdf0e10cSrcweir 						if ( !p->IsDeletedIn( pActMove ) )
3831cdf0e10cSrcweir 						{
3832cdf0e10cSrcweir 							p->SetDeletedIn( pActMove );
3833cdf0e10cSrcweir 							// GeneratedDelContent in zu loeschende Liste aufnehmen
3834cdf0e10cSrcweir 							if ( bGeneratedDelContents )
3835cdf0e10cSrcweir 								pActMove->AddContent( (ScChangeActionContent*) p );
3836cdf0e10cSrcweir 						}
3837cdf0e10cSrcweir 					}
3838cdf0e10cSrcweir 					else if ( bLastCutMove &&
3839cdf0e10cSrcweir 							p->GetActionNumber() > nEndLastCut &&
3840cdf0e10cSrcweir 							rFrom.In( p->GetBigRange() ) )
3841cdf0e10cSrcweir 					{	// Paste Cut: neuer Content nach Cut eingefuegt, bleibt.
3842cdf0e10cSrcweir 						// Aufsplitten der ContentChain
3843cdf0e10cSrcweir 						ScChangeActionContent *pHere, *pTmp;
3844cdf0e10cSrcweir 						pHere = (ScChangeActionContent*) p;
3845cdf0e10cSrcweir                         while ( (pTmp = pHere->GetPrevContent()) != NULL &&
3846cdf0e10cSrcweir 								pTmp->GetActionNumber() > nEndLastCut )
3847cdf0e10cSrcweir 							pHere = pTmp;
3848cdf0e10cSrcweir 						if ( pTmp )
3849cdf0e10cSrcweir 						{	// wird TopContent des Move
3850cdf0e10cSrcweir 							pTmp->SetNextContent( NULL );
3851cdf0e10cSrcweir 							pHere->SetPrevContent( NULL );
3852cdf0e10cSrcweir 						}
3853cdf0e10cSrcweir 						do
3854cdf0e10cSrcweir 						{	// Abhaengigkeit vom FromRange herstellen
3855cdf0e10cSrcweir 							AddDependentWithNotify( pActMove, pHere );
3856cdf0e10cSrcweir                         } while ( ( pHere = pHere->GetNextContent() ) != NULL );
3857cdf0e10cSrcweir 					}
3858cdf0e10cSrcweir                     // #i87003# [Collaboration] Move range and insert content in FromRange is not merged correctly
3859cdf0e10cSrcweir                     else if ( ( GetMergeState() != SC_CTMS_PREPARE && GetMergeState() != SC_CTMS_OWN ) || p->GetActionNumber() <= pAct->GetActionNumber() )
3860cdf0e10cSrcweir 						p->UpdateReference( this, eMode, rFrom, nDx, nDy, nDz );
3861cdf0e10cSrcweir 				}
3862cdf0e10cSrcweir 			}
3863cdf0e10cSrcweir 		}
3864cdf0e10cSrcweir 		else
3865cdf0e10cSrcweir 		{	// Undo Move
3866cdf0e10cSrcweir 			sal_Bool bActRejected = pActMove->IsRejected();
3867cdf0e10cSrcweir 			for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3868cdf0e10cSrcweir 			{
3869cdf0e10cSrcweir 				if ( p == pAct )
3870cdf0e10cSrcweir 					continue;	// for
3871cdf0e10cSrcweir 				if ( p->GetType() == SC_CAT_CONTENT )
3872cdf0e10cSrcweir 				{
3873cdf0e10cSrcweir 					// Inhalt in Ziel moven, wenn nicht deleted, sonst undelete
3874cdf0e10cSrcweir 					if ( p->IsDeletedIn( pActMove ) )
3875cdf0e10cSrcweir 					{
3876cdf0e10cSrcweir 						if ( ((ScChangeActionContent*)p)->IsTopContent() )
3877cdf0e10cSrcweir 						{	// erst der TopContent wird wirklich entfernt
3878cdf0e10cSrcweir 							p->RemoveDeletedIn( pActMove );
3879cdf0e10cSrcweir 							// GeneratedDelContent _nicht_ aus Liste loeschen,
3880cdf0e10cSrcweir 							// wir brauchen ihn evtl. noch fuer Reject,
3881cdf0e10cSrcweir 							// geloescht wird in DeleteCellEntries
3882cdf0e10cSrcweir 						}
3883cdf0e10cSrcweir 					}
3884cdf0e10cSrcweir                     // #i87003# [Collaboration] Move range and insert content in FromRange is not merged correctly
3885cdf0e10cSrcweir                     else if ( ( GetMergeState() != SC_CTMS_PREPARE && GetMergeState() != SC_CTMS_OWN ) || p->GetActionNumber() <= pAct->GetActionNumber() )
3886cdf0e10cSrcweir 						p->UpdateReference( this, eMode, rTo, nDx, nDy, nDz );
3887cdf0e10cSrcweir 					if ( bActRejected &&
3888cdf0e10cSrcweir 							((ScChangeActionContent*)p)->IsTopContent() &&
3889cdf0e10cSrcweir 							rFrom.In( p->GetBigRange() ) )
3890cdf0e10cSrcweir 					{	// Abhaengigkeit herstellen, um Content zu schreiben
3891cdf0e10cSrcweir 						ScChangeActionLinkEntry* pLink =
3892cdf0e10cSrcweir 							pActMove->AddDependent( p );
3893cdf0e10cSrcweir 						p->AddLink( pActMove, pLink );
3894cdf0e10cSrcweir 					}
3895cdf0e10cSrcweir 				}
3896cdf0e10cSrcweir 			}
3897cdf0e10cSrcweir 		}
3898cdf0e10cSrcweir 	}
3899cdf0e10cSrcweir 	else
3900cdf0e10cSrcweir 	{	// Insert / Undo Insert
3901cdf0e10cSrcweir 		switch ( GetMergeState() )
3902cdf0e10cSrcweir 		{
3903cdf0e10cSrcweir 			case SC_CTMS_NONE :
3904cdf0e10cSrcweir 			case SC_CTMS_OTHER :
3905cdf0e10cSrcweir 			{
3906cdf0e10cSrcweir 				for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3907cdf0e10cSrcweir 				{
3908cdf0e10cSrcweir 					if ( p == pAct )
3909cdf0e10cSrcweir 						continue;	// for
3910cdf0e10cSrcweir 					p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3911cdf0e10cSrcweir 				}
3912cdf0e10cSrcweir 			}
3913cdf0e10cSrcweir 			break;
3914cdf0e10cSrcweir 			case SC_CTMS_PREPARE :
3915cdf0e10cSrcweir 			{
3916cdf0e10cSrcweir 				// in Insert-Undo "Deleten"
3917cdf0e10cSrcweir 				const ScChangeActionLinkEntry* pLink = pAct->GetFirstDependentEntry();
3918cdf0e10cSrcweir 				while ( pLink )
3919cdf0e10cSrcweir 				{
3920cdf0e10cSrcweir 					ScChangeAction* p = (ScChangeAction*) pLink->GetAction();
3921cdf0e10cSrcweir 					if ( p )
3922cdf0e10cSrcweir 						p->SetDeletedIn( pAct );
3923cdf0e10cSrcweir 					pLink = pLink->GetNext();
3924cdf0e10cSrcweir 				}
3925cdf0e10cSrcweir 
3926cdf0e10cSrcweir                 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
3927cdf0e10cSrcweir                 for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3928cdf0e10cSrcweir                 {
3929cdf0e10cSrcweir                     if ( !p->IsDeletedIn( pAct ) && pAct->IsInsertType() &&
3930cdf0e10cSrcweir                          // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3931cdf0e10cSrcweir                          ( p->GetType() == SC_CAT_CONTENT ||
3932cdf0e10cSrcweir                            p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS ||
3933cdf0e10cSrcweir                            p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) &&
3934cdf0e10cSrcweir                          pAct->GetBigRange().Intersects( p->GetBigRange() ) )
3935cdf0e10cSrcweir                     {
3936cdf0e10cSrcweir                         p->SetDeletedIn( pAct );
3937cdf0e10cSrcweir                     }
3938cdf0e10cSrcweir                 }
3939cdf0e10cSrcweir 
3940cdf0e10cSrcweir                 for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3941cdf0e10cSrcweir 				{
3942cdf0e10cSrcweir 					if ( p == pAct )
3943cdf0e10cSrcweir 						continue;	// for
3944cdf0e10cSrcweir                     if ( !p->IsDeletedIn( pAct )
3945cdf0e10cSrcweir                          // #i95212# [Collaboration] Bad handling of row insertion in shared spreadsheet
3946cdf0e10cSrcweir                          && p->GetActionNumber() <= pAct->GetActionNumber() )
3947cdf0e10cSrcweir                     {
3948cdf0e10cSrcweir 						p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3949cdf0e10cSrcweir                     }
3950cdf0e10cSrcweir 				}
3951cdf0e10cSrcweir 			}
3952cdf0e10cSrcweir 			break;
3953cdf0e10cSrcweir 			case SC_CTMS_OWN :
3954cdf0e10cSrcweir 			{
3955cdf0e10cSrcweir 				for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3956cdf0e10cSrcweir 				{
3957cdf0e10cSrcweir 					if ( p == pAct )
3958cdf0e10cSrcweir 						continue;	// for
3959cdf0e10cSrcweir                     if ( !p->IsDeletedIn( pAct )
3960cdf0e10cSrcweir                          // #i95212# [Collaboration] Bad handling of row insertion in shared spreadsheet
3961cdf0e10cSrcweir                          && p->GetActionNumber() <= pAct->GetActionNumber() )
3962cdf0e10cSrcweir                     {
3963cdf0e10cSrcweir 						p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
3964cdf0e10cSrcweir                     }
3965cdf0e10cSrcweir 				}
3966cdf0e10cSrcweir 				// in Insert-Undo "Delete" rueckgaengig
3967cdf0e10cSrcweir 				const ScChangeActionLinkEntry* pLink = pAct->GetFirstDependentEntry();
3968cdf0e10cSrcweir 				while ( pLink )
3969cdf0e10cSrcweir 				{
3970cdf0e10cSrcweir 					ScChangeAction* p = (ScChangeAction*) pLink->GetAction();
3971cdf0e10cSrcweir 					if ( p )
3972cdf0e10cSrcweir 						p->RemoveDeletedIn( pAct );
3973cdf0e10cSrcweir 					pLink = pLink->GetNext();
3974cdf0e10cSrcweir 				}
3975cdf0e10cSrcweir 
3976cdf0e10cSrcweir                 // #i87049# [Collaboration] Conflict between delete row and insert content is not merged correctly
3977cdf0e10cSrcweir                 for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3978cdf0e10cSrcweir                 {
3979cdf0e10cSrcweir                     if ( p->IsDeletedIn( pAct ) && pAct->IsInsertType() &&
3980cdf0e10cSrcweir                          // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3981cdf0e10cSrcweir                          ( p->GetType() == SC_CAT_CONTENT ||
3982cdf0e10cSrcweir                            p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS ||
3983cdf0e10cSrcweir                            p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) &&
3984cdf0e10cSrcweir                          pAct->GetBigRange().Intersects( p->GetBigRange() ) )
3985cdf0e10cSrcweir                     {
3986cdf0e10cSrcweir                         p->RemoveDeletedIn( pAct );
3987cdf0e10cSrcweir                     }
3988cdf0e10cSrcweir                 }
3989cdf0e10cSrcweir 			}
3990cdf0e10cSrcweir 			break;
3991cdf0e10cSrcweir             // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
3992cdf0e10cSrcweir             case SC_CTMS_UNDO :
3993cdf0e10cSrcweir             {
3994cdf0e10cSrcweir                 for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
3995cdf0e10cSrcweir                 {
3996cdf0e10cSrcweir                     if ( !p->IsDeletedIn( pAct ) && pAct->IsInsertType() &&
3997cdf0e10cSrcweir                          ( p->GetType() == SC_CAT_CONTENT ||
3998cdf0e10cSrcweir                            p->GetType() == SC_CAT_DELETE_ROWS || p->GetType() == SC_CAT_DELETE_COLS ||
3999cdf0e10cSrcweir                            p->GetType() == SC_CAT_INSERT_ROWS || p->GetType() == SC_CAT_INSERT_COLS ) &&
4000cdf0e10cSrcweir                          pAct->GetBigRange().Intersects( p->GetBigRange() ) )
4001cdf0e10cSrcweir                     {
4002cdf0e10cSrcweir                         p->SetDeletedIn( pAct );
4003cdf0e10cSrcweir                     }
4004cdf0e10cSrcweir                 }
4005cdf0e10cSrcweir 
4006cdf0e10cSrcweir                 for ( ScChangeAction* p = *ppFirstAction; p; p = p->GetNext() )
4007cdf0e10cSrcweir                 {
4008cdf0e10cSrcweir                     if ( p == pAct )
4009cdf0e10cSrcweir                     {
4010cdf0e10cSrcweir                         continue;
4011cdf0e10cSrcweir                     }
4012cdf0e10cSrcweir                     if ( !p->IsDeletedIn( pAct ) && p->GetActionNumber() <= pAct->GetActionNumber() )
4013cdf0e10cSrcweir                     {
4014cdf0e10cSrcweir                         p->UpdateReference( this, eMode, aRange, nDx, nDy, nDz );
4015cdf0e10cSrcweir                     }
4016cdf0e10cSrcweir                 }
4017cdf0e10cSrcweir             }
4018cdf0e10cSrcweir             break;
4019cdf0e10cSrcweir 		}
4020cdf0e10cSrcweir 	}
4021cdf0e10cSrcweir }
4022cdf0e10cSrcweir 
4023cdf0e10cSrcweir 
GetDependents(ScChangeAction * pAct,ScChangeActionTable & rTable,sal_Bool bListMasterDelete,sal_Bool bAllFlat) const4024cdf0e10cSrcweir void ScChangeTrack::GetDependents( ScChangeAction* pAct,
4025cdf0e10cSrcweir 		ScChangeActionTable& rTable, sal_Bool bListMasterDelete, sal_Bool bAllFlat ) const
4026cdf0e10cSrcweir {
4027cdf0e10cSrcweir 	//! bAllFlat==TRUE: intern aus Accept oder Reject gerufen,
4028cdf0e10cSrcweir 	//! => Generated werden nicht aufgenommen
4029cdf0e10cSrcweir 
4030cdf0e10cSrcweir 	sal_Bool bIsDelete = pAct->IsDeleteType();
4031cdf0e10cSrcweir 	sal_Bool bIsMasterDelete = ( bListMasterDelete && pAct->IsMasterDelete() );
4032cdf0e10cSrcweir 
4033cdf0e10cSrcweir 	const ScChangeAction* pCur = pAct;
4034cdf0e10cSrcweir 	ScChangeActionStack* pStack = new ScChangeActionStack;
4035cdf0e10cSrcweir 	do
4036cdf0e10cSrcweir 	{
4037cdf0e10cSrcweir 		if ( pCur->IsInsertType() )
4038cdf0e10cSrcweir 		{
4039cdf0e10cSrcweir 			const ScChangeActionLinkEntry* pL = pCur->GetFirstDependentEntry();
4040cdf0e10cSrcweir 			while ( pL )
4041cdf0e10cSrcweir 			{
4042cdf0e10cSrcweir 				ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4043cdf0e10cSrcweir 				if ( p != pAct )
4044cdf0e10cSrcweir 				{
4045cdf0e10cSrcweir 					if ( bAllFlat )
4046cdf0e10cSrcweir 					{
4047cdf0e10cSrcweir 						sal_uLong n = p->GetActionNumber();
4048cdf0e10cSrcweir 						if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
4049cdf0e10cSrcweir 							if ( p->HasDependent() )
4050cdf0e10cSrcweir 								pStack->Push( p );
4051cdf0e10cSrcweir 					}
4052cdf0e10cSrcweir 					else
4053cdf0e10cSrcweir 					{
4054cdf0e10cSrcweir 						if ( p->GetType() == SC_CAT_CONTENT )
4055cdf0e10cSrcweir 						{
4056cdf0e10cSrcweir 							if ( ((ScChangeActionContent*)p)->IsTopContent() )
4057cdf0e10cSrcweir 								rTable.Insert( p->GetActionNumber(), p );
4058cdf0e10cSrcweir 						}
4059cdf0e10cSrcweir 						else
4060cdf0e10cSrcweir 							rTable.Insert( p->GetActionNumber(), p );
4061cdf0e10cSrcweir 					}
4062cdf0e10cSrcweir 				}
4063cdf0e10cSrcweir 				pL = pL->GetNext();
4064cdf0e10cSrcweir 			}
4065cdf0e10cSrcweir 		}
4066cdf0e10cSrcweir 		else if ( pCur->IsDeleteType() )
4067cdf0e10cSrcweir 		{
4068cdf0e10cSrcweir 			if ( bIsDelete )
4069cdf0e10cSrcweir 			{	// Inhalte geloeschter Bereiche interessieren nur bei Delete
4070cdf0e10cSrcweir 				ScChangeActionDel* pDel = (ScChangeActionDel*) pCur;
4071cdf0e10cSrcweir 				if ( !bAllFlat && bIsMasterDelete && pCur == pAct )
4072cdf0e10cSrcweir 				{
4073cdf0e10cSrcweir 					// zu diesem Delete gehoerende Deletes in gleiche Ebene,
4074cdf0e10cSrcweir 					// wenn dieses Delete das momentan oberste einer Reihe ist,
4075cdf0e10cSrcweir 					ScChangeActionType eType = pDel->GetType();
4076cdf0e10cSrcweir 					ScChangeAction* p = pDel;
4077cdf0e10cSrcweir                     while ( (p = p->GetPrev()) != NULL && p->GetType() == eType &&
4078cdf0e10cSrcweir 							!((ScChangeActionDel*)p)->IsTopDelete() )
4079cdf0e10cSrcweir 						rTable.Insert( p->GetActionNumber(), p );
4080cdf0e10cSrcweir 					// dieses Delete auch in Table!
4081cdf0e10cSrcweir 					rTable.Insert( pAct->GetActionNumber(), pAct );
4082cdf0e10cSrcweir 				}
4083cdf0e10cSrcweir 				else
4084cdf0e10cSrcweir 				{
4085cdf0e10cSrcweir 					const ScChangeActionLinkEntry* pL = pCur->GetFirstDeletedEntry();
4086cdf0e10cSrcweir 					while ( pL )
4087cdf0e10cSrcweir 					{
4088cdf0e10cSrcweir 						ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4089cdf0e10cSrcweir 						if ( p != pAct )
4090cdf0e10cSrcweir 						{
4091cdf0e10cSrcweir 							if ( bAllFlat )
4092cdf0e10cSrcweir 							{
4093cdf0e10cSrcweir 								// nur ein TopContent einer Kette ist in LinkDeleted
4094cdf0e10cSrcweir 								sal_uLong n = p->GetActionNumber();
4095cdf0e10cSrcweir 								if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
4096cdf0e10cSrcweir 									if ( p->HasDeleted() ||
4097cdf0e10cSrcweir 											p->GetType() == SC_CAT_CONTENT )
4098cdf0e10cSrcweir 										pStack->Push( p );
4099cdf0e10cSrcweir 							}
4100cdf0e10cSrcweir 							else
4101cdf0e10cSrcweir 							{
4102cdf0e10cSrcweir 								if ( p->IsDeleteType() )
4103cdf0e10cSrcweir 								{	// weiteres TopDelete in gleiche Ebene,
4104cdf0e10cSrcweir 									// es ist nicht rejectable
4105cdf0e10cSrcweir 									if ( ((ScChangeActionDel*)p)->IsTopDelete() )
4106cdf0e10cSrcweir 										rTable.Insert( p->GetActionNumber(), p );
4107cdf0e10cSrcweir 								}
4108cdf0e10cSrcweir 								else
4109cdf0e10cSrcweir 									rTable.Insert( p->GetActionNumber(), p );
4110cdf0e10cSrcweir 							}
4111cdf0e10cSrcweir 						}
4112cdf0e10cSrcweir 						pL = pL->GetNext();
4113cdf0e10cSrcweir 					}
4114cdf0e10cSrcweir 				}
4115cdf0e10cSrcweir 			}
4116cdf0e10cSrcweir 		}
4117cdf0e10cSrcweir 		else if ( pCur->GetType() == SC_CAT_MOVE )
4118cdf0e10cSrcweir 		{
4119cdf0e10cSrcweir 			// geloeschte Contents im ToRange
4120cdf0e10cSrcweir 			const ScChangeActionLinkEntry* pL = pCur->GetFirstDeletedEntry();
4121cdf0e10cSrcweir 			while ( pL )
4122cdf0e10cSrcweir 			{
4123cdf0e10cSrcweir 				ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4124cdf0e10cSrcweir 				if ( p != pAct && rTable.Insert( p->GetActionNumber(), p ) )
4125cdf0e10cSrcweir 				{
4126cdf0e10cSrcweir 					// nur ein TopContent einer Kette ist in LinkDeleted
4127cdf0e10cSrcweir 					if ( bAllFlat && (p->HasDeleted() ||
4128cdf0e10cSrcweir 							p->GetType() == SC_CAT_CONTENT) )
4129cdf0e10cSrcweir 						pStack->Push( p );
4130cdf0e10cSrcweir 				}
4131cdf0e10cSrcweir 				pL = pL->GetNext();
4132cdf0e10cSrcweir 			}
4133cdf0e10cSrcweir 			// neue Contents im FromRange oder neuer FromRange im ToRange
4134cdf0e10cSrcweir 			// oder Inserts/Deletes in FromRange/ToRange
4135cdf0e10cSrcweir 			pL = pCur->GetFirstDependentEntry();
4136cdf0e10cSrcweir 			while ( pL )
4137cdf0e10cSrcweir 			{
4138cdf0e10cSrcweir 				ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4139cdf0e10cSrcweir 				if ( p != pAct )
4140cdf0e10cSrcweir 				{
4141cdf0e10cSrcweir 					if ( bAllFlat )
4142cdf0e10cSrcweir 					{
4143cdf0e10cSrcweir 						sal_uLong n = p->GetActionNumber();
4144cdf0e10cSrcweir 						if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
4145cdf0e10cSrcweir 							if ( p->HasDependent() || p->HasDeleted() )
4146cdf0e10cSrcweir 								pStack->Push( p );
4147cdf0e10cSrcweir 					}
4148cdf0e10cSrcweir 					else
4149cdf0e10cSrcweir 					{
4150cdf0e10cSrcweir 						if ( p->GetType() == SC_CAT_CONTENT )
4151cdf0e10cSrcweir 						{
4152cdf0e10cSrcweir 							if ( ((ScChangeActionContent*)p)->IsTopContent() )
4153cdf0e10cSrcweir 								rTable.Insert( p->GetActionNumber(), p );
4154cdf0e10cSrcweir 						}
4155cdf0e10cSrcweir 						else
4156cdf0e10cSrcweir 							rTable.Insert( p->GetActionNumber(), p );
4157cdf0e10cSrcweir 					}
4158cdf0e10cSrcweir 				}
4159cdf0e10cSrcweir 				pL = pL->GetNext();
4160cdf0e10cSrcweir 			}
4161cdf0e10cSrcweir 		}
4162cdf0e10cSrcweir 		else if ( pCur->GetType() == SC_CAT_CONTENT )
4163cdf0e10cSrcweir 		{	// alle Aenderungen an gleicher Position
4164cdf0e10cSrcweir 			ScChangeActionContent* pContent = (ScChangeActionContent*) pCur;
4165cdf0e10cSrcweir 			// alle vorherigen
4166cdf0e10cSrcweir             while ( ( pContent = pContent->GetPrevContent() ) != NULL )
4167cdf0e10cSrcweir 			{
4168cdf0e10cSrcweir 				if ( !pContent->IsRejected() )
4169cdf0e10cSrcweir 					rTable.Insert( pContent->GetActionNumber(), pContent );
4170cdf0e10cSrcweir 			}
4171cdf0e10cSrcweir 			pContent = (ScChangeActionContent*) pCur;
4172cdf0e10cSrcweir 			// alle nachfolgenden
4173cdf0e10cSrcweir             while ( ( pContent = pContent->GetNextContent() ) != NULL )
4174cdf0e10cSrcweir 			{
4175cdf0e10cSrcweir 				if ( !pContent->IsRejected() )
4176cdf0e10cSrcweir 					rTable.Insert( pContent->GetActionNumber(), pContent );
4177cdf0e10cSrcweir 			}
4178cdf0e10cSrcweir 			// all MatrixReferences of a MatrixOrigin
4179cdf0e10cSrcweir 			const ScChangeActionLinkEntry* pL = pCur->GetFirstDependentEntry();
4180cdf0e10cSrcweir 			while ( pL )
4181cdf0e10cSrcweir 			{
4182cdf0e10cSrcweir 				ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4183cdf0e10cSrcweir 				if ( p != pAct )
4184cdf0e10cSrcweir 				{
4185cdf0e10cSrcweir 					if ( bAllFlat )
4186cdf0e10cSrcweir 					{
4187cdf0e10cSrcweir 						sal_uLong n = p->GetActionNumber();
4188cdf0e10cSrcweir 						if ( !IsGenerated( n ) && rTable.Insert( n, p ) )
4189cdf0e10cSrcweir 							if ( p->HasDependent() )
4190cdf0e10cSrcweir 								pStack->Push( p );
4191cdf0e10cSrcweir 					}
4192cdf0e10cSrcweir 					else
4193cdf0e10cSrcweir 						rTable.Insert( p->GetActionNumber(), p );
4194cdf0e10cSrcweir 				}
4195cdf0e10cSrcweir 				pL = pL->GetNext();
4196cdf0e10cSrcweir 			}
4197cdf0e10cSrcweir 		}
4198cdf0e10cSrcweir 		else if ( pCur->GetType() == SC_CAT_REJECT )
4199cdf0e10cSrcweir 		{
4200cdf0e10cSrcweir 			if ( bAllFlat )
4201cdf0e10cSrcweir 			{
4202cdf0e10cSrcweir 				ScChangeAction* p = GetAction(
4203cdf0e10cSrcweir 						((ScChangeActionReject*)pCur)->GetRejectAction() );
4204cdf0e10cSrcweir 				if ( p != pAct && !rTable.Get( p->GetActionNumber() ) )
4205cdf0e10cSrcweir 					pStack->Push( p );
4206cdf0e10cSrcweir 			}
4207cdf0e10cSrcweir 		}
4208cdf0e10cSrcweir     } while ( ( pCur = pStack->Pop() ) != NULL );
4209cdf0e10cSrcweir 	delete pStack;
4210cdf0e10cSrcweir }
4211cdf0e10cSrcweir 
4212cdf0e10cSrcweir 
SelectContent(ScChangeAction * pAct,sal_Bool bOldest)4213cdf0e10cSrcweir sal_Bool ScChangeTrack::SelectContent( ScChangeAction* pAct, sal_Bool bOldest )
4214cdf0e10cSrcweir {
4215cdf0e10cSrcweir 	if ( pAct->GetType() != SC_CAT_CONTENT )
4216cdf0e10cSrcweir 		return sal_False;
4217cdf0e10cSrcweir 
4218cdf0e10cSrcweir 	ScChangeActionContent* pContent = (ScChangeActionContent*) pAct;
4219cdf0e10cSrcweir 	if ( bOldest )
4220cdf0e10cSrcweir 	{
4221cdf0e10cSrcweir 		pContent = pContent->GetTopContent();
4222cdf0e10cSrcweir 		ScChangeActionContent* pPrevContent;
4223cdf0e10cSrcweir         while ( (pPrevContent = pContent->GetPrevContent()) != NULL &&
4224cdf0e10cSrcweir 				pPrevContent->IsVirgin() )
4225cdf0e10cSrcweir 			pContent = pPrevContent;
4226cdf0e10cSrcweir 	}
4227cdf0e10cSrcweir 
4228cdf0e10cSrcweir 	if ( !pContent->IsClickable() )
4229cdf0e10cSrcweir 		return sal_False;
4230cdf0e10cSrcweir 
4231cdf0e10cSrcweir 	ScBigRange aBigRange( pContent->GetBigRange() );
4232cdf0e10cSrcweir 	const ScBaseCell* pCell = (bOldest ? pContent->GetOldCell() :
4233cdf0e10cSrcweir 		pContent->GetNewCell());
4234cdf0e10cSrcweir 	if ( ScChangeActionContent::GetContentCellType( pCell ) == SC_CACCT_MATORG )
4235cdf0e10cSrcweir 	{
4236cdf0e10cSrcweir         SCCOL nC;
4237cdf0e10cSrcweir         SCROW nR;
4238cdf0e10cSrcweir         ((const ScFormulaCell*)pCell)->GetMatColsRows( nC, nR );
4239cdf0e10cSrcweir 		aBigRange.aEnd.IncCol( nC-1 );
4240cdf0e10cSrcweir 		aBigRange.aEnd.IncRow( nR-1 );
4241cdf0e10cSrcweir 	}
4242cdf0e10cSrcweir 
4243cdf0e10cSrcweir 	if ( !aBigRange.IsValid( pDoc ) )
4244cdf0e10cSrcweir 		return sal_False;
4245cdf0e10cSrcweir 
4246cdf0e10cSrcweir 	ScRange aRange( aBigRange.MakeRange() );
4247cdf0e10cSrcweir 	if ( !pDoc->IsBlockEditable( aRange.aStart.Tab(), aRange.aStart.Col(),
4248cdf0e10cSrcweir 			aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row() ) )
4249cdf0e10cSrcweir 		return sal_False;
4250cdf0e10cSrcweir 
4251cdf0e10cSrcweir 	if ( pContent->HasDependent() )
4252cdf0e10cSrcweir 	{
4253cdf0e10cSrcweir 		sal_Bool bOk = sal_True;
4254cdf0e10cSrcweir 		Stack aRejectActions;
4255cdf0e10cSrcweir 		const ScChangeActionLinkEntry* pL = pContent->GetFirstDependentEntry();
4256cdf0e10cSrcweir 		while ( pL )
4257cdf0e10cSrcweir 		{
4258cdf0e10cSrcweir 			ScChangeAction* p = (ScChangeAction*) pL->GetAction();
4259cdf0e10cSrcweir 			if ( p != pContent )
4260cdf0e10cSrcweir 			{
4261cdf0e10cSrcweir 				if ( p->GetType() == SC_CAT_CONTENT )
4262cdf0e10cSrcweir 				{
4263cdf0e10cSrcweir 					// we don't need no recursion here, do we?
4264cdf0e10cSrcweir 					bOk &= ((ScChangeActionContent*)p)->Select( pDoc, this,
4265cdf0e10cSrcweir 						bOldest, &aRejectActions );
4266cdf0e10cSrcweir 				}
4267cdf0e10cSrcweir 				else
4268cdf0e10cSrcweir 				{
4269cdf0e10cSrcweir 					DBG_ERRORFILE( "ScChangeTrack::SelectContent: content dependent no content" );
4270cdf0e10cSrcweir 				}
4271cdf0e10cSrcweir 			}
4272cdf0e10cSrcweir 			pL = pL->GetNext();
4273cdf0e10cSrcweir 		}
4274cdf0e10cSrcweir 
4275cdf0e10cSrcweir 		bOk &= pContent->Select( pDoc, this, bOldest, NULL );
4276cdf0e10cSrcweir 		// now the matrix is inserted and new content values are ready
4277cdf0e10cSrcweir 
4278cdf0e10cSrcweir 		ScChangeActionContent* pNew;
4279cdf0e10cSrcweir         while ( ( pNew = (ScChangeActionContent*) aRejectActions.Pop() ) != NULL )
4280cdf0e10cSrcweir 		{
4281cdf0e10cSrcweir 			ScAddress aPos( pNew->GetBigRange().aStart.MakeAddress() );
4282cdf0e10cSrcweir 			pNew->SetNewValue( pDoc->GetCell( aPos ), pDoc );
4283cdf0e10cSrcweir 			Append( pNew );
4284cdf0e10cSrcweir 		}
4285cdf0e10cSrcweir 		return bOk;
4286cdf0e10cSrcweir 	}
4287cdf0e10cSrcweir 	else
4288cdf0e10cSrcweir 		return pContent->Select( pDoc, this, bOldest, NULL );
4289cdf0e10cSrcweir }
4290cdf0e10cSrcweir 
4291cdf0e10cSrcweir 
AcceptAll()4292cdf0e10cSrcweir void ScChangeTrack::AcceptAll()
4293cdf0e10cSrcweir {
4294cdf0e10cSrcweir 	for ( ScChangeAction* p = GetFirst(); p; p = p->GetNext() )
4295cdf0e10cSrcweir 	{
4296cdf0e10cSrcweir 		p->Accept();
4297cdf0e10cSrcweir 	}
4298cdf0e10cSrcweir }
4299cdf0e10cSrcweir 
4300cdf0e10cSrcweir 
Accept(ScChangeAction * pAct)4301cdf0e10cSrcweir sal_Bool ScChangeTrack::Accept( ScChangeAction* pAct )
4302cdf0e10cSrcweir {
4303cdf0e10cSrcweir 	if ( !pAct->IsClickable() )
4304cdf0e10cSrcweir 		return sal_False;
4305cdf0e10cSrcweir 
4306cdf0e10cSrcweir 	if ( pAct->IsDeleteType() || pAct->GetType() == SC_CAT_CONTENT )
4307cdf0e10cSrcweir 	{
4308cdf0e10cSrcweir         ScChangeActionTable aActionTable;
4309cdf0e10cSrcweir         GetDependents( pAct, aActionTable, sal_False, sal_True );
4310cdf0e10cSrcweir         for ( ScChangeAction* p = aActionTable.First(); p; p = aActionTable.Next() )
4311cdf0e10cSrcweir 		{
4312cdf0e10cSrcweir 			p->Accept();
4313cdf0e10cSrcweir 		}
4314cdf0e10cSrcweir 	}
4315cdf0e10cSrcweir 	pAct->Accept();
4316cdf0e10cSrcweir 	return sal_True;
4317cdf0e10cSrcweir }
4318cdf0e10cSrcweir 
4319cdf0e10cSrcweir 
RejectAll()4320cdf0e10cSrcweir sal_Bool ScChangeTrack::RejectAll()
4321cdf0e10cSrcweir {
4322cdf0e10cSrcweir 	sal_Bool bOk = sal_True;
4323cdf0e10cSrcweir 	for ( ScChangeAction* p = GetLast(); p && bOk; p = p->GetPrev() )
4324cdf0e10cSrcweir 	{	//! rueckwaerts, weil abhaengige hinten und RejectActions angehaengt
4325cdf0e10cSrcweir 		if ( p->IsInternalRejectable() )
4326cdf0e10cSrcweir 			bOk = Reject( p );
4327cdf0e10cSrcweir 	}
4328cdf0e10cSrcweir 	return bOk;
4329cdf0e10cSrcweir }
4330cdf0e10cSrcweir 
4331cdf0e10cSrcweir 
Reject(ScChangeAction * pAct,bool bShared)4332cdf0e10cSrcweir sal_Bool ScChangeTrack::Reject( ScChangeAction* pAct, bool bShared )
4333cdf0e10cSrcweir {
4334cdf0e10cSrcweir     // #i100895# When collaboration changes are reversed, it must be possible
4335cdf0e10cSrcweir     // to reject a deleted row above another deleted row.
4336cdf0e10cSrcweir     if ( bShared && pAct->IsDeletedIn() )
4337cdf0e10cSrcweir         pAct->RemoveAllDeletedIn();
4338cdf0e10cSrcweir 
4339cdf0e10cSrcweir 	if ( !pAct->IsRejectable() )
4340cdf0e10cSrcweir 		return sal_False;
4341cdf0e10cSrcweir 
4342cdf0e10cSrcweir 	ScChangeActionTable* pTable = NULL;
4343cdf0e10cSrcweir 	if ( pAct->HasDependent() )
4344cdf0e10cSrcweir 	{
4345cdf0e10cSrcweir 		pTable = new ScChangeActionTable;
4346cdf0e10cSrcweir 		GetDependents( pAct, *pTable, sal_False, sal_True );
4347cdf0e10cSrcweir 	}
4348cdf0e10cSrcweir 	sal_Bool bRejected = Reject( pAct, pTable, sal_False );
4349cdf0e10cSrcweir 	if ( pTable )
4350cdf0e10cSrcweir 		delete pTable;
4351cdf0e10cSrcweir 	return bRejected;
4352cdf0e10cSrcweir }
4353cdf0e10cSrcweir 
4354cdf0e10cSrcweir 
Reject(ScChangeAction * pAct,ScChangeActionTable * pTable,sal_Bool bRecursion)4355cdf0e10cSrcweir sal_Bool ScChangeTrack::Reject( ScChangeAction* pAct, ScChangeActionTable* pTable,
4356cdf0e10cSrcweir 		sal_Bool bRecursion )
4357cdf0e10cSrcweir {
4358cdf0e10cSrcweir 	if ( !pAct->IsInternalRejectable() )
4359cdf0e10cSrcweir 		return sal_False;
4360cdf0e10cSrcweir 
4361cdf0e10cSrcweir 	sal_Bool bOk = sal_True;
4362cdf0e10cSrcweir 	sal_Bool bRejected = sal_False;
4363cdf0e10cSrcweir 	if ( pAct->IsInsertType() )
4364cdf0e10cSrcweir 	{
4365cdf0e10cSrcweir 		if ( pAct->HasDependent() && !bRecursion )
4366cdf0e10cSrcweir 		{
4367cdf0e10cSrcweir 			DBG_ASSERT( pTable, "ScChangeTrack::Reject: Insert ohne Table" );
4368cdf0e10cSrcweir 			for ( ScChangeAction* p = pTable->Last(); p && bOk; p = pTable->Prev() )
4369cdf0e10cSrcweir 			{
4370cdf0e10cSrcweir 				// keine Contents restoren, die eh geloescht werden wuerden
4371cdf0e10cSrcweir 				if ( p->GetType() == SC_CAT_CONTENT )
4372cdf0e10cSrcweir 					p->SetRejected();
4373cdf0e10cSrcweir 				else if ( p->IsDeleteType() )
4374cdf0e10cSrcweir 					p->Accept();		// geloeschtes ins Nirvana
4375cdf0e10cSrcweir 				else
4376cdf0e10cSrcweir 					bOk = Reject( p, NULL, sal_True );		//! rekursiv
4377cdf0e10cSrcweir 			}
4378cdf0e10cSrcweir 		}
4379cdf0e10cSrcweir         if ( bOk && (bRejected = pAct->Reject( pDoc )) != sal_False )
4380cdf0e10cSrcweir 		{
4381cdf0e10cSrcweir 			// pRefDoc NULL := geloeschte Zellen nicht speichern
4382cdf0e10cSrcweir 			AppendDeleteRange( pAct->GetBigRange().MakeRange(), NULL, (short) 0,
4383cdf0e10cSrcweir 				pAct->GetActionNumber() );
4384cdf0e10cSrcweir 		}
4385cdf0e10cSrcweir 	}
4386cdf0e10cSrcweir 	else if ( pAct->IsDeleteType() )
4387cdf0e10cSrcweir 	{
4388cdf0e10cSrcweir 		DBG_ASSERT( !pTable, "ScChangeTrack::Reject: Delete mit Table" );
4389cdf0e10cSrcweir 		ScBigRange aDelRange;
4390cdf0e10cSrcweir 		sal_uLong nRejectAction = pAct->GetActionNumber();
4391cdf0e10cSrcweir 		sal_Bool bTabDel, bTabDelOk;
4392cdf0e10cSrcweir 		if ( pAct->GetType() == SC_CAT_DELETE_TABS )
4393cdf0e10cSrcweir 		{
4394cdf0e10cSrcweir 			bTabDel = sal_True;
4395cdf0e10cSrcweir 			aDelRange = pAct->GetBigRange();
4396cdf0e10cSrcweir 			bOk = bTabDelOk = pAct->Reject( pDoc );
4397cdf0e10cSrcweir 			if ( bOk )
4398cdf0e10cSrcweir 			{
4399cdf0e10cSrcweir 				pAct = pAct->GetPrev();
4400cdf0e10cSrcweir 				bOk = ( pAct && pAct->GetType() == SC_CAT_DELETE_COLS );
4401cdf0e10cSrcweir 			}
4402cdf0e10cSrcweir 		}
4403cdf0e10cSrcweir 		else
4404cdf0e10cSrcweir 			bTabDel = bTabDelOk = sal_False;
4405cdf0e10cSrcweir 		ScChangeActionDel* pDel = (ScChangeActionDel*) pAct;
4406cdf0e10cSrcweir 		if ( bOk )
4407cdf0e10cSrcweir 		{
4408cdf0e10cSrcweir 			aDelRange = pDel->GetOverAllRange();
4409cdf0e10cSrcweir 			bOk = aDelRange.IsValid( pDoc );
4410cdf0e10cSrcweir 		}
4411cdf0e10cSrcweir 		sal_Bool bOneOk = sal_False;
4412cdf0e10cSrcweir 		if ( bOk )
4413cdf0e10cSrcweir 		{
4414cdf0e10cSrcweir 			ScChangeActionType eActType = pAct->GetType();
4415cdf0e10cSrcweir 			switch ( eActType )
4416cdf0e10cSrcweir 			{
4417cdf0e10cSrcweir 				case SC_CAT_DELETE_COLS :
4418cdf0e10cSrcweir 					aDelRange.aStart.SetCol( aDelRange.aEnd.Col() );
4419cdf0e10cSrcweir 				break;
4420cdf0e10cSrcweir 				case SC_CAT_DELETE_ROWS :
4421cdf0e10cSrcweir 					aDelRange.aStart.SetRow( aDelRange.aEnd.Row() );
4422cdf0e10cSrcweir 				break;
4423cdf0e10cSrcweir 				case SC_CAT_DELETE_TABS :
4424cdf0e10cSrcweir 					aDelRange.aStart.SetTab( aDelRange.aEnd.Tab() );
4425cdf0e10cSrcweir 				break;
4426cdf0e10cSrcweir                 default:
4427cdf0e10cSrcweir                 {
4428cdf0e10cSrcweir                     // added to avoid warnings
4429cdf0e10cSrcweir                 }
4430cdf0e10cSrcweir 			}
4431cdf0e10cSrcweir 			ScChangeAction* p = pAct;
4432cdf0e10cSrcweir 			sal_Bool bLoop = sal_True;
4433cdf0e10cSrcweir 			do
4434cdf0e10cSrcweir 			{
4435cdf0e10cSrcweir 				pDel = (ScChangeActionDel*) p;
4436cdf0e10cSrcweir 				bOk = pDel->Reject( pDoc );
4437cdf0e10cSrcweir 				if ( bOk )
4438cdf0e10cSrcweir 				{
4439cdf0e10cSrcweir 					if ( bOneOk )
4440cdf0e10cSrcweir 					{
4441cdf0e10cSrcweir 						switch ( pDel->GetType() )
4442cdf0e10cSrcweir 						{
4443cdf0e10cSrcweir 							case SC_CAT_DELETE_COLS :
4444cdf0e10cSrcweir 								aDelRange.aStart.IncCol( -1 );
4445cdf0e10cSrcweir 							break;
4446cdf0e10cSrcweir 							case SC_CAT_DELETE_ROWS :
4447cdf0e10cSrcweir 								aDelRange.aStart.IncRow( -1 );
4448cdf0e10cSrcweir 							break;
4449cdf0e10cSrcweir 							case SC_CAT_DELETE_TABS :
4450cdf0e10cSrcweir 								aDelRange.aStart.IncTab( -1 );
4451cdf0e10cSrcweir 							break;
4452cdf0e10cSrcweir                             default:
4453cdf0e10cSrcweir                             {
4454cdf0e10cSrcweir                                 // added to avoid warnings
4455cdf0e10cSrcweir                             }
4456cdf0e10cSrcweir 						}
4457cdf0e10cSrcweir 					}
4458cdf0e10cSrcweir 					else
4459cdf0e10cSrcweir 						bOneOk = sal_True;
4460cdf0e10cSrcweir 				}
4461cdf0e10cSrcweir 				if ( pDel->IsBaseDelete() )
4462cdf0e10cSrcweir 					bLoop = sal_False;
4463cdf0e10cSrcweir 				else
4464cdf0e10cSrcweir 					p = p->GetPrev();
4465cdf0e10cSrcweir 			} while ( bOk && bLoop && p && p->GetType() == eActType &&
4466cdf0e10cSrcweir 				!((ScChangeActionDel*)p)->IsTopDelete() );
4467cdf0e10cSrcweir 		}
4468cdf0e10cSrcweir 		bRejected = bOk;
4469cdf0e10cSrcweir 		if ( bOneOk || (bTabDel && bTabDelOk) )
4470cdf0e10cSrcweir 		{
4471cdf0e10cSrcweir 			// Delete-Reject machte UpdateReference Undo
4472cdf0e10cSrcweir 			ScChangeActionIns* pReject = new ScChangeActionIns(
4473cdf0e10cSrcweir 				aDelRange.MakeRange() );
4474cdf0e10cSrcweir 			pReject->SetRejectAction( nRejectAction );
4475cdf0e10cSrcweir 			pReject->SetState( SC_CAS_ACCEPTED );
4476cdf0e10cSrcweir 			Append( pReject );
4477cdf0e10cSrcweir 		}
4478cdf0e10cSrcweir 	}
4479cdf0e10cSrcweir 	else if ( pAct->GetType() == SC_CAT_MOVE )
4480cdf0e10cSrcweir 	{
4481cdf0e10cSrcweir 		if ( pAct->HasDependent() && !bRecursion )
4482cdf0e10cSrcweir 		{
4483cdf0e10cSrcweir 			DBG_ASSERT( pTable, "ScChangeTrack::Reject: Move ohne Table" );
4484cdf0e10cSrcweir 			for ( ScChangeAction* p = pTable->Last(); p && bOk; p = pTable->Prev() )
4485cdf0e10cSrcweir 			{
4486cdf0e10cSrcweir 				bOk = Reject( p, NULL, sal_True );		//! rekursiv
4487cdf0e10cSrcweir 			}
4488cdf0e10cSrcweir 		}
4489cdf0e10cSrcweir         if ( bOk && (bRejected = pAct->Reject( pDoc )) != sal_False )
4490cdf0e10cSrcweir 		{
4491cdf0e10cSrcweir 			ScChangeActionMove* pReject = new ScChangeActionMove(
4492cdf0e10cSrcweir 				pAct->GetBigRange().MakeRange(),
4493cdf0e10cSrcweir 				((ScChangeActionMove*)pAct)->GetFromRange().MakeRange(), this );
4494cdf0e10cSrcweir 			pReject->SetRejectAction( pAct->GetActionNumber() );
4495cdf0e10cSrcweir 			pReject->SetState( SC_CAS_ACCEPTED );
4496cdf0e10cSrcweir 			Append( pReject );
4497cdf0e10cSrcweir 		}
4498cdf0e10cSrcweir 	}
4499cdf0e10cSrcweir 	else if ( pAct->GetType() == SC_CAT_CONTENT )
4500cdf0e10cSrcweir 	{
4501cdf0e10cSrcweir 		ScRange aRange;
4502cdf0e10cSrcweir 		ScChangeActionContent* pReject;
4503cdf0e10cSrcweir 		if ( bRecursion )
4504cdf0e10cSrcweir 			pReject = NULL;
4505cdf0e10cSrcweir 		else
4506cdf0e10cSrcweir 		{
4507cdf0e10cSrcweir 			aRange = pAct->GetBigRange().aStart.MakeAddress();
4508cdf0e10cSrcweir 			pReject = new ScChangeActionContent( aRange );
4509cdf0e10cSrcweir 			pReject->SetOldValue( pDoc->GetCell( aRange.aStart ), pDoc, pDoc );
4510cdf0e10cSrcweir 		}
4511cdf0e10cSrcweir         if ( (bRejected = pAct->Reject( pDoc )) != sal_False && !bRecursion )
4512cdf0e10cSrcweir 		{
4513cdf0e10cSrcweir 			pReject->SetNewValue( pDoc->GetCell( aRange.aStart ), pDoc );
4514cdf0e10cSrcweir 			pReject->SetRejectAction( pAct->GetActionNumber() );
4515cdf0e10cSrcweir 			pReject->SetState( SC_CAS_ACCEPTED );
4516cdf0e10cSrcweir 			Append( pReject );
4517cdf0e10cSrcweir 		}
4518cdf0e10cSrcweir 		else if ( pReject )
4519cdf0e10cSrcweir 			delete pReject;
4520cdf0e10cSrcweir 	}
4521cdf0e10cSrcweir 	else
4522cdf0e10cSrcweir 	{
4523cdf0e10cSrcweir 		DBG_ERROR( "ScChangeTrack::Reject: say what?" );
4524cdf0e10cSrcweir 	}
4525cdf0e10cSrcweir 
4526cdf0e10cSrcweir 	return bRejected;
4527cdf0e10cSrcweir }
4528cdf0e10cSrcweir 
4529cdf0e10cSrcweir 
AddLoadedGenerated(ScBaseCell * pNewCell,const ScBigRange & aBigRange,const String & sNewValue)4530cdf0e10cSrcweir sal_uLong ScChangeTrack::AddLoadedGenerated(ScBaseCell* pNewCell, const ScBigRange& aBigRange, const String& sNewValue )
4531cdf0e10cSrcweir {
4532cdf0e10cSrcweir 	ScChangeActionContent* pAct = new ScChangeActionContent( --nGeneratedMin, pNewCell, aBigRange, pDoc, sNewValue );
4533cdf0e10cSrcweir 	if ( pAct )
4534cdf0e10cSrcweir 	{
4535cdf0e10cSrcweir 		if ( pFirstGeneratedDelContent )
4536cdf0e10cSrcweir 			pFirstGeneratedDelContent->pPrev = pAct;
4537cdf0e10cSrcweir 		pAct->pNext = pFirstGeneratedDelContent;
4538cdf0e10cSrcweir 		pFirstGeneratedDelContent = pAct;
4539cdf0e10cSrcweir 		aGeneratedTable.Insert( pAct->GetActionNumber(), pAct );
4540cdf0e10cSrcweir 		return pAct->GetActionNumber();
4541cdf0e10cSrcweir 	}
4542cdf0e10cSrcweir 	return 0;
4543cdf0e10cSrcweir }
4544cdf0e10cSrcweir 
AppendCloned(ScChangeAction * pAppend)4545cdf0e10cSrcweir void ScChangeTrack::AppendCloned( ScChangeAction* pAppend )
4546cdf0e10cSrcweir {
4547cdf0e10cSrcweir     aTable.Insert( pAppend->GetActionNumber(), pAppend );
4548cdf0e10cSrcweir     if ( !pLast )
4549cdf0e10cSrcweir         pFirst = pLast = pAppend;
4550cdf0e10cSrcweir     else
4551cdf0e10cSrcweir     {
4552cdf0e10cSrcweir         pLast->pNext = pAppend;
4553cdf0e10cSrcweir         pAppend->pPrev = pLast;
4554cdf0e10cSrcweir         pLast = pAppend;
4555cdf0e10cSrcweir     }
4556cdf0e10cSrcweir }
4557cdf0e10cSrcweir 
Clone(ScDocument * pDocument) const4558cdf0e10cSrcweir ScChangeTrack* ScChangeTrack::Clone( ScDocument* pDocument ) const
4559cdf0e10cSrcweir {
4560cdf0e10cSrcweir     if ( !pDocument )
4561cdf0e10cSrcweir     {
4562cdf0e10cSrcweir         return NULL;
4563cdf0e10cSrcweir     }
4564cdf0e10cSrcweir 
4565cdf0e10cSrcweir     ScChangeTrack* pClonedTrack = new ScChangeTrack( pDocument );
4566cdf0e10cSrcweir     pClonedTrack->SetTime100thSeconds( IsTime100thSeconds() );
4567cdf0e10cSrcweir 
4568cdf0e10cSrcweir     // clone generated actions
4569cdf0e10cSrcweir     ::std::stack< const ScChangeAction* > aGeneratedStack;
4570cdf0e10cSrcweir     const ScChangeAction* pGenerated = GetFirstGenerated();
4571cdf0e10cSrcweir     while ( pGenerated )
4572cdf0e10cSrcweir     {
4573cdf0e10cSrcweir         aGeneratedStack.push( pGenerated );
4574cdf0e10cSrcweir         pGenerated = pGenerated->GetNext();
4575cdf0e10cSrcweir     }
4576cdf0e10cSrcweir     while ( !aGeneratedStack.empty() )
4577cdf0e10cSrcweir     {
4578cdf0e10cSrcweir         pGenerated = aGeneratedStack.top();
4579cdf0e10cSrcweir         aGeneratedStack.pop();
4580cdf0e10cSrcweir         const ScChangeActionContent* pContent = dynamic_cast< const ScChangeActionContent* >( pGenerated );
4581cdf0e10cSrcweir         DBG_ASSERT( pContent, "ScChangeTrack::Clone: pContent is null!" );
4582cdf0e10cSrcweir         const ScBaseCell* pNewCell = pContent->GetNewCell();
4583cdf0e10cSrcweir         if ( pNewCell )
4584cdf0e10cSrcweir         {
4585cdf0e10cSrcweir             ScBaseCell* pClonedNewCell = pNewCell->CloneWithoutNote( *pDocument );
4586cdf0e10cSrcweir             String aNewValue;
4587cdf0e10cSrcweir             pContent->GetNewString( aNewValue );
4588cdf0e10cSrcweir             pClonedTrack->nGeneratedMin = pGenerated->GetActionNumber() + 1;
4589cdf0e10cSrcweir             pClonedTrack->AddLoadedGenerated( pClonedNewCell, pGenerated->GetBigRange(), aNewValue );
4590cdf0e10cSrcweir         }
4591cdf0e10cSrcweir     }
4592cdf0e10cSrcweir 
4593cdf0e10cSrcweir     // clone actions
4594cdf0e10cSrcweir     const ScChangeAction* pAction = GetFirst();
4595cdf0e10cSrcweir     while ( pAction )
4596cdf0e10cSrcweir     {
4597cdf0e10cSrcweir         ScChangeAction* pClonedAction = NULL;
4598cdf0e10cSrcweir 
4599cdf0e10cSrcweir         switch ( pAction->GetType() )
4600cdf0e10cSrcweir         {
4601cdf0e10cSrcweir             case SC_CAT_INSERT_COLS:
4602cdf0e10cSrcweir             case SC_CAT_INSERT_ROWS:
4603cdf0e10cSrcweir             case SC_CAT_INSERT_TABS:
4604cdf0e10cSrcweir                 {
4605cdf0e10cSrcweir                     pClonedAction = new ScChangeActionIns(
4606cdf0e10cSrcweir                         pAction->GetActionNumber(),
4607cdf0e10cSrcweir                         pAction->GetState(),
4608cdf0e10cSrcweir                         pAction->GetRejectAction(),
4609cdf0e10cSrcweir 		                pAction->GetBigRange(),
4610cdf0e10cSrcweir                         pAction->GetUser(),
4611cdf0e10cSrcweir                         pAction->GetDateTimeUTC(),
4612cdf0e10cSrcweir                         pAction->GetComment(),
4613cdf0e10cSrcweir                         pAction->GetType() );
4614cdf0e10cSrcweir                 }
4615cdf0e10cSrcweir                 break;
4616cdf0e10cSrcweir             case SC_CAT_DELETE_COLS:
4617cdf0e10cSrcweir             case SC_CAT_DELETE_ROWS:
4618cdf0e10cSrcweir             case SC_CAT_DELETE_TABS:
4619cdf0e10cSrcweir                 {
4620cdf0e10cSrcweir                     const ScChangeActionDel* pDelete = dynamic_cast< const ScChangeActionDel* >( pAction );
4621cdf0e10cSrcweir                     DBG_ASSERT( pDelete, "ScChangeTrack::Clone: pDelete is null!" );
4622cdf0e10cSrcweir 
4623cdf0e10cSrcweir                     SCsCOLROW nD = 0;
4624cdf0e10cSrcweir                     ScChangeActionType eType = pAction->GetType();
4625cdf0e10cSrcweir                     if ( eType == SC_CAT_DELETE_COLS )
4626cdf0e10cSrcweir                     {
4627cdf0e10cSrcweir                         nD = static_cast< SCsCOLROW >( pDelete->GetDx() );
4628cdf0e10cSrcweir                     }
4629cdf0e10cSrcweir                     else if ( eType == SC_CAT_DELETE_ROWS )
4630cdf0e10cSrcweir                     {
4631cdf0e10cSrcweir                         nD = static_cast< SCsCOLROW >( pDelete->GetDy() );
4632cdf0e10cSrcweir                     }
4633cdf0e10cSrcweir 
4634cdf0e10cSrcweir                     pClonedAction = new ScChangeActionDel(
4635cdf0e10cSrcweir                         pAction->GetActionNumber(),
4636cdf0e10cSrcweir                         pAction->GetState(),
4637cdf0e10cSrcweir                         pAction->GetRejectAction(),
4638cdf0e10cSrcweir 		                pAction->GetBigRange(),
4639cdf0e10cSrcweir                         pAction->GetUser(),
4640cdf0e10cSrcweir                         pAction->GetDateTimeUTC(),
4641cdf0e10cSrcweir                         pAction->GetComment(),
4642cdf0e10cSrcweir                         eType,
4643cdf0e10cSrcweir                         nD,
4644cdf0e10cSrcweir                         pClonedTrack );
4645cdf0e10cSrcweir                 }
4646cdf0e10cSrcweir                 break;
4647cdf0e10cSrcweir             case SC_CAT_MOVE:
4648cdf0e10cSrcweir                 {
4649cdf0e10cSrcweir                     const ScChangeActionMove* pMove = dynamic_cast< const ScChangeActionMove* >( pAction );
4650cdf0e10cSrcweir                     DBG_ASSERT( pMove, "ScChangeTrack::Clone: pMove is null!" );
4651cdf0e10cSrcweir 
4652cdf0e10cSrcweir                     pClonedAction = new ScChangeActionMove(
4653cdf0e10cSrcweir                         pAction->GetActionNumber(),
4654cdf0e10cSrcweir                         pAction->GetState(),
4655cdf0e10cSrcweir                         pAction->GetRejectAction(),
4656cdf0e10cSrcweir 		                pAction->GetBigRange(),
4657cdf0e10cSrcweir                         pAction->GetUser(),
4658cdf0e10cSrcweir                         pAction->GetDateTimeUTC(),
4659cdf0e10cSrcweir                         pAction->GetComment(),
4660cdf0e10cSrcweir                         pMove->GetFromRange(),
4661cdf0e10cSrcweir                         pClonedTrack );
4662cdf0e10cSrcweir                 }
4663cdf0e10cSrcweir                 break;
4664cdf0e10cSrcweir             case SC_CAT_CONTENT:
4665cdf0e10cSrcweir                 {
4666cdf0e10cSrcweir                     const ScChangeActionContent* pContent = dynamic_cast< const ScChangeActionContent* >( pAction );
4667cdf0e10cSrcweir                     DBG_ASSERT( pContent, "ScChangeTrack::Clone: pContent is null!" );
4668cdf0e10cSrcweir                     const ScBaseCell* pOldCell = pContent->GetOldCell();
4669cdf0e10cSrcweir                     ScBaseCell* pClonedOldCell = pOldCell ? pOldCell->CloneWithoutNote( *pDocument ) : 0;
4670cdf0e10cSrcweir                     String aOldValue;
4671cdf0e10cSrcweir                     pContent->GetOldString( aOldValue );
4672cdf0e10cSrcweir 
4673cdf0e10cSrcweir                     ScChangeActionContent* pClonedContent = new ScChangeActionContent(
4674cdf0e10cSrcweir                         pAction->GetActionNumber(),
4675cdf0e10cSrcweir                         pAction->GetState(),
4676cdf0e10cSrcweir                         pAction->GetRejectAction(),
4677cdf0e10cSrcweir 		                pAction->GetBigRange(),
4678cdf0e10cSrcweir                         pAction->GetUser(),
4679cdf0e10cSrcweir                         pAction->GetDateTimeUTC(),
4680cdf0e10cSrcweir                         pAction->GetComment(),
4681cdf0e10cSrcweir                         pClonedOldCell,
4682cdf0e10cSrcweir                         pDocument,
4683cdf0e10cSrcweir                         aOldValue );
4684cdf0e10cSrcweir 
4685cdf0e10cSrcweir                     const ScBaseCell* pNewCell = pContent->GetNewCell();
4686cdf0e10cSrcweir                     if ( pNewCell )
4687cdf0e10cSrcweir                     {
4688cdf0e10cSrcweir                         ScBaseCell* pClonedNewCell = pNewCell->CloneWithoutNote( *pDocument );
4689cdf0e10cSrcweir                         pClonedContent->SetNewValue( pClonedNewCell, pDocument );
4690cdf0e10cSrcweir                     }
4691cdf0e10cSrcweir 
4692cdf0e10cSrcweir                     pClonedAction = pClonedContent;
4693cdf0e10cSrcweir                 }
4694cdf0e10cSrcweir                 break;
4695cdf0e10cSrcweir             case SC_CAT_REJECT:
4696cdf0e10cSrcweir                 {
4697cdf0e10cSrcweir                     pClonedAction = new ScChangeActionReject(
4698cdf0e10cSrcweir                         pAction->GetActionNumber(),
4699cdf0e10cSrcweir                         pAction->GetState(),
4700cdf0e10cSrcweir                         pAction->GetRejectAction(),
4701cdf0e10cSrcweir 		                pAction->GetBigRange(),
4702cdf0e10cSrcweir                         pAction->GetUser(),
4703cdf0e10cSrcweir                         pAction->GetDateTimeUTC(),
4704cdf0e10cSrcweir                         pAction->GetComment() );
4705cdf0e10cSrcweir                 }
4706cdf0e10cSrcweir                 break;
4707cdf0e10cSrcweir             default:
4708cdf0e10cSrcweir                 {
4709cdf0e10cSrcweir                 }
4710cdf0e10cSrcweir                 break;
4711cdf0e10cSrcweir         }
4712cdf0e10cSrcweir 
4713cdf0e10cSrcweir         if ( pClonedAction )
4714cdf0e10cSrcweir         {
4715cdf0e10cSrcweir             pClonedTrack->AppendCloned( pClonedAction );
4716cdf0e10cSrcweir         }
4717cdf0e10cSrcweir 
4718cdf0e10cSrcweir         pAction = pAction->GetNext();
4719cdf0e10cSrcweir     }
4720cdf0e10cSrcweir 
4721cdf0e10cSrcweir     if ( pClonedTrack->GetLast() )
4722cdf0e10cSrcweir     {
4723cdf0e10cSrcweir         pClonedTrack->SetActionMax( pClonedTrack->GetLast()->GetActionNumber() );
4724cdf0e10cSrcweir     }
4725cdf0e10cSrcweir 
4726cdf0e10cSrcweir     // set dependencies for Deleted/DeletedIn
4727cdf0e10cSrcweir     pAction = GetFirst();
4728cdf0e10cSrcweir     while ( pAction )
4729cdf0e10cSrcweir     {
4730cdf0e10cSrcweir         if ( pAction->HasDeleted() )
4731cdf0e10cSrcweir         {
4732cdf0e10cSrcweir             ::std::stack< sal_uLong > aStack;
4733cdf0e10cSrcweir             const ScChangeActionLinkEntry* pL = pAction->GetFirstDeletedEntry();
4734cdf0e10cSrcweir             while ( pL )
4735cdf0e10cSrcweir             {
4736cdf0e10cSrcweir                 const ScChangeAction* pDeleted = pL->GetAction();
4737cdf0e10cSrcweir                 if ( pDeleted )
4738cdf0e10cSrcweir                 {
4739cdf0e10cSrcweir                     aStack.push( pDeleted->GetActionNumber() );
4740cdf0e10cSrcweir                 }
4741cdf0e10cSrcweir                 pL = pL->GetNext();
4742cdf0e10cSrcweir             }
4743cdf0e10cSrcweir             ScChangeAction* pClonedAction = pClonedTrack->GetAction( pAction->GetActionNumber() );
4744cdf0e10cSrcweir             if ( pClonedAction )
4745cdf0e10cSrcweir             {
4746cdf0e10cSrcweir                 while ( !aStack.empty() )
4747cdf0e10cSrcweir                 {
4748cdf0e10cSrcweir                     ScChangeAction* pClonedDeleted = pClonedTrack->GetActionOrGenerated( aStack.top() );
4749cdf0e10cSrcweir                     aStack.pop();
4750cdf0e10cSrcweir                     if ( pClonedDeleted )
4751cdf0e10cSrcweir                     {
4752cdf0e10cSrcweir                         pClonedDeleted->SetDeletedIn( pClonedAction );
4753cdf0e10cSrcweir                     }
4754cdf0e10cSrcweir                 }
4755cdf0e10cSrcweir             }
4756cdf0e10cSrcweir         }
4757cdf0e10cSrcweir         pAction = pAction->GetNext();
4758cdf0e10cSrcweir     }
4759cdf0e10cSrcweir 
4760cdf0e10cSrcweir     // set dependencies for Dependent/Any
4761cdf0e10cSrcweir     pAction = GetLast();
4762cdf0e10cSrcweir     while ( pAction )
4763cdf0e10cSrcweir     {
4764cdf0e10cSrcweir         if ( pAction->HasDependent() )
4765cdf0e10cSrcweir         {
4766cdf0e10cSrcweir             ::std::stack< sal_uLong > aStack;
4767cdf0e10cSrcweir             const ScChangeActionLinkEntry* pL = pAction->GetFirstDependentEntry();
4768cdf0e10cSrcweir             while ( pL )
4769cdf0e10cSrcweir             {
4770cdf0e10cSrcweir                 const ScChangeAction* pDependent = pL->GetAction();
4771cdf0e10cSrcweir                 if ( pDependent )
4772cdf0e10cSrcweir                 {
4773cdf0e10cSrcweir                     aStack.push( pDependent->GetActionNumber() );
4774cdf0e10cSrcweir                 }
4775cdf0e10cSrcweir                 pL = pL->GetNext();
4776cdf0e10cSrcweir             }
4777cdf0e10cSrcweir             ScChangeAction* pClonedAction = pClonedTrack->GetAction( pAction->GetActionNumber() );
4778cdf0e10cSrcweir             if ( pClonedAction )
4779cdf0e10cSrcweir             {
4780cdf0e10cSrcweir                 while ( !aStack.empty() )
4781cdf0e10cSrcweir                 {
4782cdf0e10cSrcweir                     ScChangeAction* pClonedDependent = pClonedTrack->GetActionOrGenerated( aStack.top() );
4783cdf0e10cSrcweir                     aStack.pop();
4784cdf0e10cSrcweir                     if ( pClonedDependent )
4785cdf0e10cSrcweir                     {
4786cdf0e10cSrcweir                         ScChangeActionLinkEntry* pLink = pClonedAction->AddDependent( pClonedDependent );
4787cdf0e10cSrcweir                         pClonedDependent->AddLink( pClonedAction, pLink );
4788cdf0e10cSrcweir                     }
4789cdf0e10cSrcweir                 }
4790cdf0e10cSrcweir             }
4791cdf0e10cSrcweir         }
4792cdf0e10cSrcweir         pAction = pAction->GetPrev();
4793cdf0e10cSrcweir     }
4794cdf0e10cSrcweir 
4795cdf0e10cSrcweir     // masterlinks
4796cdf0e10cSrcweir     ScChangeAction* pClonedAction = pClonedTrack->GetFirst();
4797cdf0e10cSrcweir     while ( pClonedAction )
4798cdf0e10cSrcweir     {
4799cdf0e10cSrcweir         pClonedTrack->MasterLinks( pClonedAction );
4800cdf0e10cSrcweir         pClonedAction = pClonedAction->GetNext();
4801cdf0e10cSrcweir     }
4802cdf0e10cSrcweir 
4803cdf0e10cSrcweir     if ( IsProtected() )
4804cdf0e10cSrcweir     {
4805cdf0e10cSrcweir         pClonedTrack->SetProtection( GetProtection() );
4806cdf0e10cSrcweir     }
4807cdf0e10cSrcweir 
4808cdf0e10cSrcweir     if ( pClonedTrack->GetLast() )
4809cdf0e10cSrcweir     {
4810cdf0e10cSrcweir         pClonedTrack->SetLastSavedActionNumber( pClonedTrack->GetLast()->GetActionNumber() );
4811cdf0e10cSrcweir     }
4812cdf0e10cSrcweir 
4813cdf0e10cSrcweir     pDocument->SetChangeTrack( pClonedTrack );
4814cdf0e10cSrcweir 
4815cdf0e10cSrcweir     return pClonedTrack;
4816cdf0e10cSrcweir }
4817cdf0e10cSrcweir 
MergeActionState(ScChangeAction * pAct,const ScChangeAction * pOtherAct)4818cdf0e10cSrcweir void ScChangeTrack::MergeActionState( ScChangeAction* pAct, const ScChangeAction* pOtherAct )
4819cdf0e10cSrcweir {
4820cdf0e10cSrcweir     if ( pAct->IsVirgin() )
4821cdf0e10cSrcweir     {
4822cdf0e10cSrcweir         if ( pOtherAct->IsAccepted() )
4823cdf0e10cSrcweir         {
4824cdf0e10cSrcweir             pAct->Accept();
4825cdf0e10cSrcweir             if ( pOtherAct->IsRejecting() )
4826cdf0e10cSrcweir             {
4827cdf0e10cSrcweir                 pAct->SetRejectAction( pOtherAct->GetRejectAction() );
4828cdf0e10cSrcweir             }
4829cdf0e10cSrcweir         }
4830cdf0e10cSrcweir         else if ( pOtherAct->IsRejected() )
4831cdf0e10cSrcweir         {
4832cdf0e10cSrcweir             pAct->SetRejected();
4833cdf0e10cSrcweir         }
4834cdf0e10cSrcweir     }
4835cdf0e10cSrcweir }
4836cdf0e10cSrcweir 
4837cdf0e10cSrcweir #if DEBUG_CHANGETRACK
ToString() const4838cdf0e10cSrcweir String ScChangeTrack::ToString() const
4839cdf0e10cSrcweir {
4840cdf0e10cSrcweir     String aReturn;
4841cdf0e10cSrcweir 
4842cdf0e10cSrcweir     aReturn += String::CreateFromAscii( "============================================================\n" );
4843cdf0e10cSrcweir 
4844cdf0e10cSrcweir     const ScChangeAction* pGenerated = GetFirstGenerated();
4845cdf0e10cSrcweir     while ( pGenerated )
4846cdf0e10cSrcweir     {
4847cdf0e10cSrcweir         aReturn += pGenerated->ToString( pDoc );
4848cdf0e10cSrcweir         aReturn += '\n';
4849cdf0e10cSrcweir         pGenerated = pGenerated->GetNext();
4850cdf0e10cSrcweir     }
4851cdf0e10cSrcweir 
4852cdf0e10cSrcweir     aReturn += String::CreateFromAscii( "------------------------------------------------------------\n" );
4853cdf0e10cSrcweir 
4854cdf0e10cSrcweir     const ScChangeAction* pAction = GetFirst();
4855cdf0e10cSrcweir     while ( pAction )
4856cdf0e10cSrcweir     {
4857cdf0e10cSrcweir         aReturn += pAction->ToString( pDoc );
4858cdf0e10cSrcweir         aReturn += '\n';
4859cdf0e10cSrcweir         pAction = pAction->GetNext();
4860cdf0e10cSrcweir     }
4861cdf0e10cSrcweir     aReturn += String::CreateFromAscii( "============================================================\n" );
4862cdf0e10cSrcweir 
4863cdf0e10cSrcweir     return aReturn;
4864cdf0e10cSrcweir }
4865cdf0e10cSrcweir #endif // DEBUG_CHANGETRACK
4866