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

Generated by: LCOV version 1.10