LCOV - code coverage report
Current view: top level - sc/source/core/tool - chgtrack.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 547 2506 21.8 %
Date: 2015-06-13 12:38:46 Functions: 76 185 41.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11