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

Generated by: LCOV version 1.10