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