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