LCOV - code coverage report
Current view: top level - sc/source/core/data - documen7.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 297 338 87.9 %
Date: 2015-06-13 12:38:46 Functions: 28 28 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <vcl/svapp.hxx>
      21             : 
      22             : #include "document.hxx"
      23             : #include "brdcst.hxx"
      24             : #include "bcaslot.hxx"
      25             : #include "formulacell.hxx"
      26             : #include <formula/errorcodes.hxx>
      27             : #include "scerrors.hxx"
      28             : #include "docoptio.hxx"
      29             : #include "refupdat.hxx"
      30             : #include "table.hxx"
      31             : #include "progress.hxx"
      32             : #include "scmod.hxx"
      33             : #include "inputopt.hxx"
      34             : #include "conditio.hxx"
      35             : #include "colorscale.hxx"
      36             : #include "sheetevents.hxx"
      37             : #include "tokenarray.hxx"
      38             : #include "listenercontext.hxx"
      39             : #include "formulagroup.hxx"
      40             : #include <refhint.hxx>
      41             : 
      42             : #include "globstr.hrc"
      43             : 
      44             : extern const ScFormulaCell* pLastFormulaTreeTop;    // cellform.cxx Err527 WorkAround
      45             : 
      46             : // STATIC DATA -----------------------------------------------------------
      47             : 
      48        6835 : void ScDocument::StartListeningArea(
      49             :     const ScRange& rRange, bool bGroupListening, SvtListener* pListener )
      50             : {
      51        6835 :     if ( pBASM )
      52        6835 :         pBASM->StartListeningArea(rRange, bGroupListening, pListener);
      53        6835 : }
      54             : 
      55       12289 : void ScDocument::EndListeningArea( const ScRange& rRange, bool bGroupListening, SvtListener* pListener )
      56             : {
      57       12289 :     if ( pBASM )
      58       12289 :         pBASM->EndListeningArea(rRange, bGroupListening, pListener);
      59       12289 : }
      60             : 
      61       49354 : void ScDocument::Broadcast( const ScHint& rHint )
      62             : {
      63       49354 :     if ( !pBASM )
      64       50073 :         return ;    // Clipboard or Undo
      65       48635 :     if ( !bHardRecalcState )
      66             :     {
      67       48471 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
      68       48471 :         bool bIsBroadcasted = false;
      69       48471 :         SvtBroadcaster* pBC = GetBroadcaster(rHint.GetAddress());
      70       48471 :         if ( pBC )
      71             :         {
      72         324 :             pBC->Broadcast( rHint );
      73         324 :             bIsBroadcasted = true;
      74             :         }
      75       48471 :         if ( pBASM->AreaBroadcast( rHint ) || bIsBroadcasted )
      76         466 :             TrackFormulas( rHint.GetId() );
      77             :     }
      78             : 
      79             :     // Repaint for conditional formats with relative references:
      80      134069 :     for(SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabs.size()); ++nTab)
      81             :     {
      82       85434 :         if(!maTabs[nTab])
      83           0 :             continue;
      84             : 
      85       85434 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
      86       85434 :         if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
      87       49183 :             pCondFormList->SourceChanged( rHint.GetAddress() );
      88             : 
      89             :     }
      90             : 
      91       48635 :     if ( rHint.GetAddress() != BCA_BRDCST_ALWAYS )
      92             :     {
      93       32742 :         SCTAB nTab = rHint.GetAddress().Tab();
      94       32742 :         if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsStreamValid())
      95          13 :             maTabs[nTab]->SetStreamValid(false);
      96             :     }
      97             : }
      98             : 
      99         197 : void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint, bool bBroadcastSingleBroadcasters )
     100             : {
     101         197 :     ClearFormulaContext();
     102             : 
     103         197 :     if (!pBASM)
     104         197 :         return;    // Clipboard or Undo
     105             : 
     106         197 :     SCTAB nTab1 = rRange.aStart.Tab();
     107         197 :     SCTAB nTab2 = rRange.aEnd.Tab();
     108         197 :     SCROW nRow1 = rRange.aStart.Row();
     109         197 :     SCROW nRow2 = rRange.aEnd.Row();
     110         197 :     SCCOL nCol1 = rRange.aStart.Col();
     111         197 :     SCCOL nCol2 = rRange.aEnd.Col();
     112             : 
     113         197 :     if (!bHardRecalcState)
     114             :     {
     115         197 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
     116         197 :         bool bIsBroadcasted = false;
     117             : 
     118         197 :         if (bBroadcastSingleBroadcasters)
     119             :         {
     120         144 :             ScHint aHint(nHint, ScAddress());
     121             : 
     122         288 :             for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
     123             :             {
     124         144 :                 ScTable* pTab = FetchTable(nTab);
     125         144 :                 if (!pTab)
     126           0 :                     continue;
     127             : 
     128         144 :                 bIsBroadcasted |= pTab->BroadcastBroadcasters( nCol1, nRow1, nCol2, nRow2, aHint);
     129         144 :             }
     130             :         }
     131             : 
     132         197 :         if (pBASM->AreaBroadcast(rRange, nHint) || bIsBroadcasted)
     133          41 :             TrackFormulas(nHint);
     134             :     }
     135             : 
     136             :     // Repaint for conditional formats with relative references:
     137         394 :     for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
     138             :     {
     139         197 :         ScTable* pTab = FetchTable(nTab);
     140         197 :         if (!pTab)
     141           0 :             continue;
     142             : 
     143         197 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
     144         197 :         if (pCondFormList)
     145             :         {
     146         197 :             ScAddress aAddress( 0, 0, nTab);
     147         773 :             for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
     148             :             {
     149         576 :                 aAddress.SetRow(nRow);
     150        1665 :                 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     151             :                 {
     152        1089 :                     aAddress.SetCol(nCol);
     153        1089 :                     pCondFormList->SourceChanged(aAddress);
     154             :                 }
     155             :             }
     156             :         }
     157             :     }
     158             : 
     159         394 :     for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
     160             :     {
     161         197 :         ScTable* pTab = FetchTable(nTab);
     162         197 :         if (pTab)
     163         197 :             pTab->SetStreamValid(false);
     164             :     }
     165             : 
     166         197 :     BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
     167             : }
     168             : 
     169             : namespace {
     170             : 
     171             : class RefMovedNotifier : std::unary_function<SvtListener*, void>
     172             : {
     173             :     const sc::RefMovedHint& mrHint;
     174             : public:
     175           6 :     RefMovedNotifier( const sc::RefMovedHint& rHint ) : mrHint(rHint) {}
     176             : 
     177          10 :     void operator() ( SvtListener* p )
     178             :     {
     179          10 :         p->Notify(mrHint);
     180          10 :     }
     181             : };
     182             : 
     183             : }
     184             : 
     185           6 : void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
     186             : {
     187           6 :     if (!pBASM)
     188             :         // clipboard or undo document.
     189           6 :         return;
     190             : 
     191           6 :     const ScRange& rSrcRange = rHint.getRange(); // old range
     192           6 :     const ScAddress& rDelta = rHint.getDelta();
     193             : 
     194             :     // Get all area listeners that listens on the old range, and end their listening.
     195           6 :     std::vector<sc::AreaListener> aAreaListeners = pBASM->GetAllListeners(rSrcRange, sc::AreaInside);
     196             :     {
     197           6 :         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
     198          10 :         for (; it != itEnd; ++it)
     199             :         {
     200           4 :             pBASM->EndListeningArea(it->maArea, it->mbGroupListening, it->mpListener);
     201           4 :             it->mpListener->Notify(rHint); // Adjust the references.
     202             :         }
     203             :     }
     204             : 
     205             :     // Collect all listeners listening into the range.
     206          12 :     std::vector<SvtListener*> aListeners;
     207          12 :     for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
     208             :     {
     209           6 :         ScTable* pTab = FetchTable(nTab);
     210           6 :         if (!pTab)
     211           0 :             continue;
     212             : 
     213             :         pTab->CollectListeners(
     214             :             aListeners,
     215           6 :             rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
     216          12 :             rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row());
     217             :     }
     218             : 
     219             :     // Remove any duplicate listener entries.  We must ensure that we notify
     220             :     // each unique listener only once.
     221           6 :     std::sort(aListeners.begin(), aListeners.end());
     222           6 :     aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
     223             : 
     224             :     // Notify the listeners.
     225           6 :     std::for_each(aListeners.begin(), aListeners.end(), RefMovedNotifier(rHint));
     226             : 
     227          12 :     for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
     228             :     {
     229           6 :         ScTable* pTab = FetchTable(nTab);
     230           6 :         if (!pTab)
     231           0 :             continue;
     232             : 
     233           6 :         SCTAB nDestTab = nTab + rDelta.Tab();
     234           6 :         ScTable* pDestTab = FetchTable(nDestTab);
     235           6 :         if (!pDestTab)
     236           0 :             continue;
     237             : 
     238             :         // Move the listeners from the old location to the new.
     239             :         pTab->TransferListeners(
     240           6 :             *pDestTab, rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
     241          12 :             rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), rDelta.Col(), rDelta.Row());
     242             :     }
     243             : 
     244             :     // Re-start area listeners on the new range.
     245             :     {
     246           6 :         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
     247          10 :         for (; it != itEnd; ++it)
     248             :         {
     249           4 :             ScRange aNewRange = it->maArea;
     250           4 :             aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
     251           4 :             pBASM->StartListeningArea(aNewRange, it->mbGroupListening, it->mpListener);
     252             :         }
     253           6 :     }
     254             : }
     255             : 
     256          13 : void ScDocument::AreaBroadcast( const ScHint& rHint )
     257             : {
     258          13 :     if ( !pBASM )
     259          13 :         return ;    // Clipboard or Undo
     260          13 :     if ( !bHardRecalcState )
     261             :     {
     262          13 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
     263          13 :         if ( pBASM->AreaBroadcast( rHint ) )
     264           0 :             TrackFormulas( rHint.GetId() );
     265             :     }
     266             : 
     267          29 :     for(SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabs.size()); ++nTab)
     268             :     {
     269          16 :         if(!maTabs[nTab])
     270           0 :             continue;
     271             : 
     272          16 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
     273          16 :         if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
     274          16 :             pCondFormList->SourceChanged( rHint.GetAddress() );
     275             :     }
     276             : }
     277             : 
     278         180 : void ScDocument::DelBroadcastAreasInRange( const ScRange& rRange )
     279             : {
     280         180 :     if ( pBASM )
     281         180 :         pBASM->DelBroadcastAreasInRange( rRange );
     282         180 : }
     283             : 
     284        1059 : void ScDocument::StartListeningCell( const ScAddress& rAddress,
     285             :                                             SvtListener* pListener )
     286             : {
     287             :     OSL_ENSURE(pListener, "StartListeningCell: pListener Null");
     288        1059 :     SCTAB nTab = rAddress.Tab();
     289        1059 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     290        1059 :         maTabs[nTab]->StartListening( rAddress, pListener );
     291        1059 : }
     292             : 
     293         783 : void ScDocument::EndListeningCell( const ScAddress& rAddress,
     294             :                                             SvtListener* pListener )
     295             : {
     296             :     OSL_ENSURE(pListener, "EndListeningCell: pListener Null");
     297         783 :     SCTAB nTab = rAddress.Tab();
     298         783 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     299         775 :         maTabs[nTab]->EndListening( rAddress, pListener );
     300         783 : }
     301             : 
     302       13711 : void ScDocument::StartListeningCell(
     303             :     sc::StartListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener )
     304             : {
     305       13711 :     ScTable* pTab = FetchTable(rPos.Tab());
     306       13711 :     if (!pTab)
     307       13778 :         return;
     308             : 
     309       13644 :     pTab->StartListening(rCxt, rPos.Col(), rPos.Row(), rListener);
     310             : }
     311             : 
     312         595 : void ScDocument::EndListeningCell(
     313             :     sc::EndListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener )
     314             : {
     315         595 :     ScTable* pTab = FetchTable(rPos.Tab());
     316         595 :     if (!pTab)
     317         595 :         return;
     318             : 
     319         595 :     pTab->EndListening(rCxt, rPos.Col(), rPos.Row(), rListener);
     320             : }
     321             : 
     322        4495 : void ScDocument::EndListeningFormulaCells( std::vector<ScFormulaCell*>& rCells )
     323             : {
     324        4495 :     if (rCells.empty())
     325        8869 :         return;
     326             : 
     327         121 :     sc::EndListeningContext aCxt(*this);
     328         121 :     std::vector<ScFormulaCell*>::iterator it = rCells.begin(), itEnd = rCells.end();
     329         457 :     for (; it != itEnd; ++it)
     330         336 :         (*it)->EndListeningTo(aCxt);
     331             : 
     332         121 :     aCxt.purgeEmptyBroadcasters();
     333             : }
     334             : 
     335       28764 : void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
     336             : {
     337             :     OSL_ENSURE( pCell, "PutInFormulaTree: pCell Null" );
     338       28764 :     RemoveFromFormulaTree( pCell );
     339             :     // append
     340       28764 :     if ( pEOFormulaTree )
     341       28038 :         pEOFormulaTree->SetNext( pCell );
     342             :     else
     343         726 :         pFormulaTree = pCell;               // No end, no beginning..
     344       28764 :     pCell->SetPrevious( pEOFormulaTree );
     345       28764 :     pCell->SetNext( 0 );
     346       28764 :     pEOFormulaTree = pCell;
     347       28764 :     nFormulaCodeInTree += pCell->GetCode()->GetCodeLen();
     348       28764 : }
     349             : 
     350       87497 : void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
     351             : {
     352             :     OSL_ENSURE( pCell, "RemoveFromFormulaTree: pCell Null" );
     353       87497 :     ScFormulaCell* pPrev = pCell->GetPrevious();
     354             :     assert(pPrev != pCell);                 // pointing to itself?!?
     355             :     // if the cell is first or somewhere in chain
     356       87497 :     if ( pPrev || pFormulaTree == pCell )
     357             :     {
     358       28754 :         ScFormulaCell* pNext = pCell->GetNext();
     359             :         assert(pNext != pCell);             // pointing to itself?!?
     360       28754 :         if ( pPrev )
     361             :         {
     362             :             assert(pFormulaTree != pCell);  // if this cell is also head something's wrong
     363        4268 :             pPrev->SetNext( pNext );        // predecessor exists, set successor
     364             :         }
     365             :         else
     366             :         {
     367       24486 :             pFormulaTree = pNext;           // this cell was first cell
     368             :         }
     369       28754 :         if ( pNext )
     370             :         {
     371             :             assert(pEOFormulaTree != pCell); // if this cell is also tail something's wrong
     372       27712 :             pNext->SetPrevious( pPrev );    // successor exists, set predecessor
     373             :         }
     374             :         else
     375             :         {
     376        1042 :             pEOFormulaTree = pPrev;         // this cell was last cell
     377             :         }
     378       28754 :         pCell->SetPrevious( 0 );
     379       28754 :         pCell->SetNext( 0 );
     380       28754 :         sal_uInt16 nRPN = pCell->GetCode()->GetCodeLen();
     381       28754 :         if ( nFormulaCodeInTree >= nRPN )
     382       28754 :             nFormulaCodeInTree -= nRPN;
     383             :         else
     384             :         {
     385             :             OSL_FAIL( "RemoveFromFormulaTree: nFormulaCodeInTree < nRPN" );
     386           0 :             nFormulaCodeInTree = 0;
     387       28754 :         }
     388             :     }
     389       58743 :     else if ( !pFormulaTree && nFormulaCodeInTree )
     390             :     {
     391             :         OSL_FAIL( "!pFormulaTree && nFormulaCodeInTree != 0" );
     392           0 :         nFormulaCodeInTree = 0;
     393             :     }
     394       87497 : }
     395             : 
     396       70254 : bool ScDocument::IsInFormulaTree( ScFormulaCell* pCell ) const
     397             : {
     398       70254 :     return pCell->GetPrevious() || pFormulaTree == pCell;
     399             : }
     400             : 
     401         155 : void ScDocument::CalcFormulaTree( bool bOnlyForced, bool bProgressBar, bool bSetAllDirty )
     402             : {
     403             :     OSL_ENSURE( !IsCalculatingFormulaTree(), "CalcFormulaTree recursion" );
     404             :     // never ever recurse into this, might end up lost in infinity
     405         155 :     if ( IsCalculatingFormulaTree() )
     406         155 :         return ;
     407             : 
     408         155 :     mpFormulaGroupCxt.reset();
     409         155 :     bCalculatingFormulaTree = true;
     410             : 
     411         155 :     SetForcedFormulaPending( false );
     412         155 :     bool bOldIdleEnabled = IsIdleEnabled();
     413         155 :     EnableIdle(false);
     414         155 :     bool bOldAutoCalc = GetAutoCalc();
     415             :     //ATTENTION: _not_ SetAutoCalc( true ) because this might call CalcFormulaTree( true )
     416             :     //ATTENTION: if it was disabled before and bHasForcedFormulas is set
     417         155 :     bAutoCalc = true;
     418         155 :     if ( bHardRecalcState )
     419           0 :         CalcAll();
     420             :     else
     421             :     {
     422         155 :         ScFormulaCell* pCell = pFormulaTree;
     423        1080 :         while ( pCell )
     424             :         {
     425         770 :             if ( pCell->GetDirty() )
     426         770 :                 pCell = pCell->GetNext();       // all clear
     427             :             else
     428             :             {
     429           0 :                 if ( pCell->GetCode()->IsRecalcModeAlways() )
     430             :                 {
     431             :                     // pCell is set to Dirty again!
     432           0 :                     ScFormulaCell* pNext = pCell->GetNext();
     433           0 :                     pCell->SetDirty();
     434             :                     // if pNext==0 and new dependencies were appended at the end,
     435             :                     // this does not matter since they all are bDirty
     436           0 :                     pCell = pNext;
     437             :                 }
     438             :                 else
     439             :                 {   // calculate the other single
     440           0 :                     if( bSetAllDirty )
     441           0 :                         pCell->SetDirtyVar();
     442           0 :                     pCell = pCell->GetNext();
     443             :                 }
     444             :             }
     445             :         }
     446         155 :         bool bProgress = !bOnlyForced && nFormulaCodeInTree && bProgressBar;
     447         155 :         if ( bProgress )
     448           8 :             ScProgress::CreateInterpretProgress( this, true );
     449             : 
     450         155 :         pCell = pFormulaTree;
     451         155 :         ScFormulaCell* pLastNoGood = 0;
     452         567 :         while ( pCell )
     453             :         {
     454             :             // Interpret resets bDirty and calls Remove, also the referenced!
     455             :             // the Cell remains when ScRecalcMode::ALWAYS.
     456         257 :             if ( bOnlyForced )
     457             :             {
     458           0 :                 if ( pCell->GetCode()->IsRecalcModeForced() )
     459           0 :                     pCell->Interpret();
     460             :             }
     461             :             else
     462             :             {
     463         257 :                 pCell->Interpret();
     464             :             }
     465         257 :             if ( pCell->GetPrevious() || pCell == pFormulaTree )
     466             :             {   // (IsInFormulaTree(pCell)) no Remove was called => next
     467           2 :                 pLastNoGood = pCell;
     468           2 :                 pCell = pCell->GetNext();
     469             :             }
     470             :             else
     471             :             {
     472         255 :                 if ( pFormulaTree )
     473             :                 {
     474         244 :                     if ( pFormulaTree->GetDirty() && !bOnlyForced )
     475             :                     {
     476         244 :                         pCell = pFormulaTree;
     477         244 :                         pLastNoGood = 0;
     478             :                     }
     479             :                     else
     480             :                     {
     481             :                         // IsInFormulaTree(pLastNoGood)
     482           0 :                         if ( pLastNoGood && (pLastNoGood->GetPrevious() ||
     483           0 :                                 pLastNoGood == pFormulaTree) )
     484           0 :                             pCell = pLastNoGood->GetNext();
     485             :                         else
     486             :                         {
     487           0 :                             pCell = pFormulaTree;
     488           0 :                             while ( pCell && !pCell->GetDirty() )
     489           0 :                                 pCell = pCell->GetNext();
     490           0 :                             if ( pCell )
     491           0 :                                 pLastNoGood = pCell->GetPrevious();
     492             :                         }
     493             :                     }
     494             :                 }
     495             :                 else
     496          11 :                     pCell = 0;
     497             :             }
     498         257 :             if ( ScProgress::IsUserBreak() )
     499           0 :                 pCell = 0;
     500             :         }
     501         155 :         if ( bProgress )
     502           8 :             ScProgress::DeleteInterpretProgress();
     503             :     }
     504         155 :     bAutoCalc = bOldAutoCalc;
     505         155 :     EnableIdle(bOldIdleEnabled);
     506         155 :     bCalculatingFormulaTree = false;
     507             : 
     508         155 :     mpFormulaGroupCxt.reset();
     509             : }
     510             : 
     511         349 : void ScDocument::ClearFormulaTree()
     512             : {
     513             :     ScFormulaCell* pCell;
     514         349 :     ScFormulaCell* pTree = pFormulaTree;
     515         891 :     while ( pTree )
     516             :     {
     517         193 :         pCell = pTree;
     518         193 :         pTree = pCell->GetNext();
     519         193 :         if ( !pCell->GetCode()->IsRecalcModeAlways() )
     520         155 :             RemoveFromFormulaTree( pCell );
     521             :     }
     522         349 : }
     523             : 
     524       24613 : void ScDocument::AppendToFormulaTrack( ScFormulaCell* pCell )
     525             : {
     526             :     OSL_ENSURE( pCell, "AppendToFormulaTrack: pCell Null" );
     527             :     // The cell can not be in both lists at the same time
     528       24613 :     RemoveFromFormulaTrack( pCell );
     529       24613 :     RemoveFromFormulaTree( pCell );
     530       24613 :     if ( pEOFormulaTrack )
     531        6087 :         pEOFormulaTrack->SetNextTrack( pCell );
     532             :     else
     533       18526 :         pFormulaTrack = pCell;              // No end, no beginning..
     534       24613 :     pCell->SetPreviousTrack( pEOFormulaTrack );
     535       24613 :     pCell->SetNextTrack( 0 );
     536       24613 :     pEOFormulaTrack = pCell;
     537       24613 :     ++nFormulaTrackCount;
     538       24613 : }
     539             : 
     540       59446 : void ScDocument::RemoveFromFormulaTrack( ScFormulaCell* pCell )
     541             : {
     542             :     OSL_ENSURE( pCell, "RemoveFromFormulaTrack: pCell Null" );
     543       59446 :     ScFormulaCell* pPrev = pCell->GetPreviousTrack();
     544             :     assert(pPrev != pCell);                     // pointing to itself?!?
     545             :     // if the cell is first or somewhere in chain
     546       59446 :     if ( pPrev || pFormulaTrack == pCell )
     547             :     {
     548       24613 :         ScFormulaCell* pNext = pCell->GetNextTrack();
     549             :         assert(pNext != pCell);                 // pointing to itself?!?
     550       24613 :         if ( pPrev )
     551             :         {
     552             :             assert(pFormulaTrack != pCell);     // if this cell is also head something's wrong
     553          12 :             pPrev->SetNextTrack( pNext );       // predecessor exists, set successor
     554             :         }
     555             :         else
     556             :         {
     557       24601 :             pFormulaTrack = pNext;              // this cell was first cell
     558             :         }
     559       24613 :         if ( pNext )
     560             :         {
     561             :             assert(pEOFormulaTrack != pCell);   // if this cell is also tail something's wrong
     562        6076 :             pNext->SetPreviousTrack( pPrev );   // successor exists, set predecessor
     563             :         }
     564             :         else
     565             :         {
     566       18537 :             pEOFormulaTrack = pPrev;            // this cell was last cell
     567             :         }
     568       24613 :         pCell->SetPreviousTrack( 0 );
     569       24613 :         pCell->SetNextTrack( 0 );
     570       24613 :         --nFormulaTrackCount;
     571             :     }
     572       59446 : }
     573             : 
     574        6579 : bool ScDocument::IsInFormulaTrack( ScFormulaCell* pCell ) const
     575             : {
     576        6579 :     return pCell->GetPreviousTrack() || pFormulaTrack == pCell;
     577             : }
     578             : 
     579             : /*
     580             :     The first is broadcasted,
     581             :     the ones that are created through this are appended to the Track by Notify.
     582             :     The next is broadcasted again, and so on.
     583             :     View initiates Interpret.
     584             :  */
     585       18945 : void ScDocument::TrackFormulas( sal_uLong nHintId )
     586             : {
     587             : 
     588       18945 :     if ( pFormulaTrack )
     589             :     {
     590             :         // outside the loop, check if any sheet has a "calculate" event script
     591       18525 :         bool bCalcEvent = HasAnySheetEventScript( SC_SHEETEVENT_CALCULATE, true );
     592             :         ScFormulaCell* pTrack;
     593             :         ScFormulaCell* pNext;
     594       18525 :         pTrack = pFormulaTrack;
     595       24590 :         do
     596             :         {
     597       24590 :             SvtBroadcaster* pBC = GetBroadcaster(pTrack->aPos);
     598       24590 :             ScHint aHint(nHintId, pTrack->aPos);
     599       24590 :             if (pBC)
     600         488 :                 pBC->Broadcast( aHint );
     601       24590 :             pBASM->AreaBroadcast( aHint );
     602             :             // Repaint for conditional formats with relative references:
     603       24590 :             TableContainer::iterator itr = maTabs.begin();
     604       53281 :             for(; itr != maTabs.end(); ++itr)
     605             :             {
     606       28691 :                 if(!*itr)
     607           0 :                     continue;
     608       28691 :                 ScConditionalFormatList* pCondFormList = (*itr)->GetCondFormList();
     609       28691 :                 if ( pCondFormList )
     610       28691 :                     pCondFormList->SourceChanged( pTrack->aPos );
     611             :             }
     612             :             // for "calculate" event, keep track of which sheets are affected by tracked formulas
     613       24590 :             if ( bCalcEvent )
     614           0 :                 SetCalcNotification( pTrack->aPos.Tab() );
     615       24590 :             pTrack = pTrack->GetNextTrack();
     616             :         } while ( pTrack );
     617       18525 :         pTrack = pFormulaTrack;
     618       18525 :         bool bHaveForced = false;
     619       24590 :         do
     620             :         {
     621       24590 :             pNext = pTrack->GetNextTrack();
     622       24590 :             RemoveFromFormulaTrack( pTrack );
     623       24590 :             PutInFormulaTree( pTrack );
     624       24590 :             if ( pTrack->GetCode()->IsRecalcModeForced() )
     625           0 :                 bHaveForced = true;
     626       24590 :             pTrack = pNext;
     627             :         } while ( pTrack );
     628       18525 :         if ( bHaveForced )
     629             :         {
     630           0 :             SetForcedFormulas( true );
     631           0 :             if ( bAutoCalc && !IsAutoCalcShellDisabled() && !IsInInterpreter()
     632           0 :                     && !IsCalculatingFormulaTree() )
     633           0 :                 CalcFormulaTree( true );
     634             :             else
     635           0 :                 SetForcedFormulaPending( true );
     636             :         }
     637             :     }
     638             :     OSL_ENSURE( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" );
     639       18945 : }
     640             : 
     641         380 : void ScDocument::StartAllListeners()
     642             : {
     643         380 :     sc::StartListeningContext aCxt(*this);
     644        1105 :     for ( SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i )
     645         725 :         if ( maTabs[i] )
     646        1105 :             maTabs[i]->StartListeners(aCxt, true);
     647         380 : }
     648             : 
     649         330 : void ScDocument::UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
     650             :         const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz
     651             :     )
     652             : {
     653         330 :     bool bExpandRefsOld = IsExpandRefs();
     654         330 :     if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
     655         153 :         SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
     656         330 :     if ( pBASM )
     657         330 :         pBASM->UpdateBroadcastAreas( eUpdateRefMode, rRange, nDx, nDy, nDz );
     658         330 :     SetExpandRefs( bExpandRefsOld );
     659         330 : }
     660             : 
     661     3529523 : void ScDocument::SetAutoCalc( bool bNewAutoCalc )
     662             : {
     663     3529523 :     bool bOld = bAutoCalc;
     664     3529523 :     bAutoCalc = bNewAutoCalc;
     665     3529523 :     if ( !bOld && bNewAutoCalc && bHasForcedFormulas )
     666             :     {
     667           0 :         if ( IsAutoCalcShellDisabled() )
     668           0 :             SetForcedFormulaPending( true );
     669           0 :         else if ( !IsInInterpreter() )
     670           0 :             CalcFormulaTree( true );
     671             :     }
     672     3529679 : }
     673             : 
     674             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11