xref: /trunk/main/sc/source/core/tool/chgtrack.cxx (revision 5cd1c82638b65a86a575c9871d07bec79d4064b8)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew 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,
93786e1cf34SPedro Giffuni                                     const ScChangeActionType eTypeP, const SCsCOLROW nD, ScChangeTrack* pTrackP) // which 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                 {
1147*5cd1c826Smseidel // TODO: 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,
126586e1cf34SPedro Giffuni                                     const ScBigRange& aFromBigRange, ScChangeTrack* pTrackP) // which 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
2163*5cd1c826Smseidel // TODO: 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
2595*5cd1c826Smseidel // TODO: 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