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