LCOV - code coverage report
Current view: top level - sc/source/core/data - documen7.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 271 333 81.4 %
Date: 2014-11-03 Functions: 28 29 96.6 %
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       19764 : void ScDocument::StartListeningArea( const ScRange& rRange,
      49             :         SvtListener* pListener
      50             :     )
      51             : {
      52       19764 :     if ( pBASM )
      53       19764 :         pBASM->StartListeningArea( rRange, pListener );
      54       19764 : }
      55             : 
      56       21147 : void ScDocument::EndListeningArea( const ScRange& rRange,
      57             :         SvtListener* pListener
      58             :     )
      59             : {
      60       21147 :     if ( pBASM )
      61       21147 :         pBASM->EndListeningArea( rRange, pListener );
      62       21147 : }
      63             : 
      64      101708 : void ScDocument::Broadcast( const ScHint& rHint )
      65             : {
      66      101708 :     if ( !pBASM )
      67      103146 :         return ;    // Clipboard or Undo
      68      100270 :     if ( !bHardRecalcState )
      69             :     {
      70      100002 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
      71      100002 :         bool bIsBroadcasted = false;
      72      100002 :         SvtBroadcaster* pBC = GetBroadcaster(rHint.GetAddress());
      73      100002 :         if ( pBC )
      74             :         {
      75         970 :             pBC->Broadcast( rHint );
      76         970 :             bIsBroadcasted = true;
      77             :         }
      78      100002 :         if ( pBASM->AreaBroadcast( rHint ) || bIsBroadcasted )
      79        1278 :             TrackFormulas( rHint.GetId() );
      80             :     }
      81             : 
      82             :     //  Repaint fuer bedingte Formate mit relativen Referenzen:
      83      264366 :     for(SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabs.size()); ++nTab)
      84             :     {
      85      164096 :         if(!maTabs[nTab])
      86           0 :             continue;
      87             : 
      88      164096 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
      89      164096 :         if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
      90       98912 :             pCondFormList->SourceChanged( rHint.GetAddress() );
      91             : 
      92             :     }
      93             : 
      94      100270 :     if ( rHint.GetAddress() != BCA_BRDCST_ALWAYS )
      95             :     {
      96       66026 :         SCTAB nTab = rHint.GetAddress().Tab();
      97       66026 :         if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsStreamValid())
      98          30 :             maTabs[nTab]->SetStreamValid(false);
      99             :     }
     100             : }
     101             : 
     102          48 : void ScDocument::BroadcastCells( const ScRange& rRange, sal_uLong nHint )
     103             : {
     104          48 :     ClearFormulaContext();
     105             : 
     106          48 :     ScBulkBroadcast aBulkBroadcast(pBASM);
     107             : 
     108          96 :     ScHint aHint(nHint, ScAddress());
     109          48 :     ScAddress& rPos = aHint.GetAddress();
     110          96 :     for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
     111             :     {
     112          48 :         rPos.SetTab(nTab);
     113         132 :         for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
     114             :         {
     115          84 :             rPos.SetCol(nCol);
     116         280 :             for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
     117             :             {
     118         196 :                 rPos.SetRow(nRow);
     119         196 :                 Broadcast(aHint);
     120             :             }
     121             :         }
     122             :     }
     123             : 
     124          96 :     BroadcastUno(SfxSimpleHint(SC_HINT_DATACHANGED));
     125          48 : }
     126             : 
     127             : namespace {
     128             : 
     129             : class RefMovedNotifier : std::unary_function<SvtListener*, void>
     130             : {
     131             :     const sc::RefMovedHint& mrHint;
     132             : public:
     133          12 :     RefMovedNotifier( const sc::RefMovedHint& rHint ) : mrHint(rHint) {}
     134             : 
     135          20 :     void operator() ( SvtListener* p )
     136             :     {
     137          20 :         p->Notify(mrHint);
     138          20 :     }
     139             : };
     140             : 
     141             : }
     142             : 
     143          12 : void ScDocument::BroadcastRefMoved( const sc::RefMovedHint& rHint )
     144             : {
     145          12 :     if (!pBASM)
     146             :         // clipboard or undo document.
     147          12 :         return;
     148             : 
     149          12 :     const ScRange& rSrcRange = rHint.getRange(); // old range
     150          12 :     const ScAddress& rDelta = rHint.getDelta();
     151             : 
     152             :     // Get all area listeners that listens on the old range, and end their listening.
     153          12 :     std::vector<sc::AreaListener> aAreaListeners = pBASM->GetAllListeners(rSrcRange, sc::AreaInside);
     154             :     {
     155          12 :         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
     156          20 :         for (; it != itEnd; ++it)
     157             :         {
     158           8 :             pBASM->EndListeningArea(it->maArea, it->mpListener);
     159           8 :             it->mpListener->Notify(rHint); // Adjust the references.
     160             :         }
     161             :     }
     162             : 
     163             :     // Collect all listeners listening into the range.
     164          24 :     std::vector<SvtListener*> aListeners;
     165          24 :     for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
     166             :     {
     167          12 :         ScTable* pTab = FetchTable(nTab);
     168          12 :         if (!pTab)
     169           0 :             continue;
     170             : 
     171             :         pTab->CollectListeners(
     172             :             aListeners,
     173          12 :             rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
     174          24 :             rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row());
     175             :     }
     176             : 
     177             :     // Remove any duplicate listener entries.  We must ensure that we notify
     178             :     // each unique listener only once.
     179          12 :     std::sort(aListeners.begin(), aListeners.end());
     180          12 :     aListeners.erase(std::unique(aListeners.begin(), aListeners.end()), aListeners.end());
     181             : 
     182             :     // Notify the listeners.
     183          12 :     std::for_each(aListeners.begin(), aListeners.end(), RefMovedNotifier(rHint));
     184             : 
     185          24 :     for (SCTAB nTab = rSrcRange.aStart.Tab(); nTab <= rSrcRange.aEnd.Tab(); ++nTab)
     186             :     {
     187          12 :         ScTable* pTab = FetchTable(nTab);
     188          12 :         if (!pTab)
     189           0 :             continue;
     190             : 
     191          12 :         SCTAB nDestTab = nTab + rDelta.Tab();
     192          12 :         ScTable* pDestTab = FetchTable(nDestTab);
     193          12 :         if (!pDestTab)
     194           0 :             continue;
     195             : 
     196             :         // Move the listeners from the old location to the new.
     197             :         pTab->TransferListeners(
     198          12 :             *pDestTab, rSrcRange.aStart.Col(), rSrcRange.aStart.Row(),
     199          24 :             rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), rDelta.Col(), rDelta.Row());
     200             :     }
     201             : 
     202             :     // Re-start area listeners on the new range.
     203             :     {
     204          12 :         std::vector<sc::AreaListener>::iterator it = aAreaListeners.begin(), itEnd = aAreaListeners.end();
     205          20 :         for (; it != itEnd; ++it)
     206             :         {
     207           8 :             ScRange aNewRange = it->maArea;
     208           8 :             aNewRange.Move(rDelta.Col(), rDelta.Row(), rDelta.Tab());
     209           8 :             pBASM->StartListeningArea(aNewRange, it->mpListener);
     210             :         }
     211          12 :     }
     212             : }
     213             : 
     214          26 : void ScDocument::AreaBroadcast( const ScHint& rHint )
     215             : {
     216          26 :     if ( !pBASM )
     217          26 :         return ;    // Clipboard or Undo
     218          26 :     if ( !bHardRecalcState )
     219             :     {
     220          26 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
     221          26 :         if ( pBASM->AreaBroadcast( rHint ) )
     222           0 :             TrackFormulas( rHint.GetId() );
     223             :     }
     224             : 
     225          58 :     for(SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabs.size()); ++nTab)
     226             :     {
     227          32 :         if(!maTabs[nTab])
     228           0 :             continue;
     229             : 
     230          32 :         ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
     231          32 :         if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
     232          32 :             pCondFormList->SourceChanged( rHint.GetAddress() );
     233             :     }
     234             : }
     235             : 
     236           0 : void ScDocument::AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint )
     237             : {
     238           0 :     if ( !pBASM )
     239           0 :         return ;    // Clipboard or Undo
     240           0 :     if ( !bHardRecalcState )
     241             :     {
     242           0 :         ScBulkBroadcast aBulkBroadcast( pBASM);     // scoped bulk broadcast
     243           0 :         if ( pBASM->AreaBroadcastInRange( rRange, rHint ) )
     244           0 :             TrackFormulas( rHint.GetId() );
     245             :     }
     246             : 
     247             :     // Repaint for conditional formats containing relative references.
     248             :     //! This is _THE_ bottle neck!
     249           0 :     TableContainer::iterator itr = maTabs.begin();
     250           0 :     for(; itr != maTabs.end(); ++itr)
     251             :     {
     252           0 :         if(!*itr)
     253           0 :             continue;
     254             : 
     255           0 :         ScConditionalFormatList* pCondFormList = (*itr)->GetCondFormList();
     256           0 :         if ( pCondFormList )
     257             :         {
     258             :             SCCOL nCol1;
     259             :             SCROW nRow1;
     260             :             SCTAB nTab1;
     261             :             SCCOL nCol2;
     262             :             SCROW nRow2;
     263             :             SCTAB nTab2;
     264           0 :             rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
     265           0 :             ScAddress aAddress( rRange.aStart );
     266           0 :             for ( SCTAB nTab = nTab1; nTab <= nTab2; ++nTab )
     267             :             {
     268           0 :                 aAddress.SetTab( nTab );
     269           0 :                 for ( SCCOL nCol = nCol1; nCol <= nCol2; ++nCol )
     270             :                 {
     271           0 :                     aAddress.SetCol( nCol );
     272           0 :                     for ( SCROW nRow = nRow1; nRow <= nRow2; ++nRow )
     273             :                     {
     274           0 :                         aAddress.SetRow( nRow );
     275           0 :                         pCondFormList->SourceChanged( aAddress );
     276             :                     }
     277             :                 }
     278             :             }
     279             :         }
     280             : 
     281             :     }
     282             : }
     283             : 
     284         322 : void ScDocument::DelBroadcastAreasInRange( const ScRange& rRange )
     285             : {
     286         322 :     if ( pBASM )
     287         322 :         pBASM->DelBroadcastAreasInRange( rRange );
     288         322 : }
     289             : 
     290       17572 : void ScDocument::StartListeningCell( const ScAddress& rAddress,
     291             :                                             SvtListener* pListener )
     292             : {
     293             :     OSL_ENSURE(pListener, "StartListeningCell: pListener Null");
     294       17572 :     SCTAB nTab = rAddress.Tab();
     295       17572 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     296       17478 :         maTabs[nTab]->StartListening( rAddress, pListener );
     297       17572 : }
     298             : 
     299        1870 : void ScDocument::EndListeningCell( const ScAddress& rAddress,
     300             :                                             SvtListener* pListener )
     301             : {
     302             :     OSL_ENSURE(pListener, "EndListeningCell: pListener Null");
     303        1870 :     SCTAB nTab = rAddress.Tab();
     304        1870 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     305        1828 :         maTabs[nTab]->EndListening( rAddress, pListener );
     306        1870 : }
     307             : 
     308       22946 : void ScDocument::StartListeningCell(
     309             :     sc::StartListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener )
     310             : {
     311       22946 :     ScTable* pTab = FetchTable(rPos.Tab());
     312       22946 :     if (!pTab)
     313       22946 :         return;
     314             : 
     315       22946 :     pTab->StartListening(rCxt, rPos.Col(), rPos.Row(), rListener);
     316             : }
     317             : 
     318         528 : void ScDocument::EndListeningCell(
     319             :     sc::EndListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener )
     320             : {
     321         528 :     ScTable* pTab = FetchTable(rPos.Tab());
     322         528 :     if (!pTab)
     323         528 :         return;
     324             : 
     325         528 :     pTab->EndListening(rCxt, rPos.Col(), rPos.Row(), rListener);
     326             : }
     327             : 
     328        8944 : void ScDocument::EndListeningFormulaCells( std::vector<ScFormulaCell*>& rCells )
     329             : {
     330        8944 :     if (rCells.empty())
     331       17656 :         return;
     332             : 
     333         232 :     sc::EndListeningContext aCxt(*this);
     334         232 :     std::vector<ScFormulaCell*>::iterator it = rCells.begin(), itEnd = rCells.end();
     335         858 :     for (; it != itEnd; ++it)
     336         626 :         (*it)->EndListeningTo(aCxt);
     337             : 
     338         232 :     aCxt.purgeEmptyBroadcasters();
     339             : }
     340             : 
     341       56520 : void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
     342             : {
     343             :     OSL_ENSURE( pCell, "PutInFormulaTree: pCell Null" );
     344       56520 :     RemoveFromFormulaTree( pCell );
     345             :     // anhaengen
     346       56520 :     if ( pEOFormulaTree )
     347       54884 :         pEOFormulaTree->SetNext( pCell );
     348             :     else
     349        1636 :         pFormulaTree = pCell;               // kein Ende, kein Anfang..
     350       56520 :     pCell->SetPrevious( pEOFormulaTree );
     351       56520 :     pCell->SetNext( 0 );
     352       56520 :     pEOFormulaTree = pCell;
     353       56520 :     nFormulaCodeInTree += pCell->GetCode()->GetCodeLen();
     354       56520 : }
     355             : 
     356      165266 : void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
     357             : {
     358             :     OSL_ENSURE( pCell, "RemoveFromFormulaTree: pCell Null" );
     359      165266 :     ScFormulaCell* pPrev = pCell->GetPrevious();
     360             :     // wenn die Zelle die erste oder sonstwo ist
     361      165266 :     if ( pPrev || pFormulaTree == pCell )
     362             :     {
     363       56504 :         ScFormulaCell* pNext = pCell->GetNext();
     364       56504 :         if ( pPrev )
     365        7913 :             pPrev->SetNext( pNext );        // gibt Vorlaeufer
     366             :         else
     367       48591 :             pFormulaTree = pNext;           // ist erste Zelle
     368       56504 :         if ( pNext )
     369       54223 :             pNext->SetPrevious( pPrev );    // gibt Nachfolger
     370             :         else
     371        2281 :             pEOFormulaTree = pPrev;         // ist letzte Zelle
     372       56504 :         pCell->SetPrevious( 0 );
     373       56504 :         pCell->SetNext( 0 );
     374       56504 :         sal_uInt16 nRPN = pCell->GetCode()->GetCodeLen();
     375       56504 :         if ( nFormulaCodeInTree >= nRPN )
     376       56504 :             nFormulaCodeInTree -= nRPN;
     377             :         else
     378             :         {
     379             :             OSL_FAIL( "RemoveFromFormulaTree: nFormulaCodeInTree < nRPN" );
     380           0 :             nFormulaCodeInTree = 0;
     381       56504 :         }
     382             :     }
     383      108762 :     else if ( !pFormulaTree && nFormulaCodeInTree )
     384             :     {
     385             :         OSL_FAIL( "!pFormulaTree && nFormulaCodeInTree != 0" );
     386           0 :         nFormulaCodeInTree = 0;
     387             :     }
     388      165266 : }
     389             : 
     390      137512 : bool ScDocument::IsInFormulaTree( ScFormulaCell* pCell ) const
     391             : {
     392      137512 :     return pCell->GetPrevious() || pFormulaTree == pCell;
     393             : }
     394             : 
     395         148 : void ScDocument::CalcFormulaTree( bool bOnlyForced, bool bProgressBar, bool bSetAllDirty )
     396             : {
     397             :     OSL_ENSURE( !IsCalculatingFormulaTree(), "CalcFormulaTree recursion" );
     398             :     // never ever recurse into this, might end up lost in infinity
     399         148 :     if ( IsCalculatingFormulaTree() )
     400         148 :         return ;
     401             : 
     402         148 :     mpFormulaGroupCxt.reset();
     403         148 :     bCalculatingFormulaTree = true;
     404             : 
     405         148 :     SetForcedFormulaPending( false );
     406         148 :     bool bOldIdleEnabled = IsIdleEnabled();
     407         148 :     EnableIdle(false);
     408         148 :     bool bOldAutoCalc = GetAutoCalc();
     409             :     //! _nicht_ SetAutoCalc( true ) weil das evtl. CalcFormulaTree( true )
     410             :     //! aufruft, wenn vorher disabled war und bHasForcedFormulas gesetzt ist
     411         148 :     bAutoCalc = true;
     412         148 :     if ( bHardRecalcState )
     413           0 :         CalcAll();
     414             :     else
     415             :     {
     416         148 :         ScFormulaCell* pCell = pFormulaTree;
     417        1836 :         while ( pCell )
     418             :         {
     419        1540 :             if ( pCell->GetDirty() )
     420        1540 :                 pCell = pCell->GetNext();       // alles klar
     421             :             else
     422             :             {
     423           0 :                 if ( pCell->GetCode()->IsRecalcModeAlways() )
     424             :                 {
     425             :                     // pCell wird im SetDirty neu angehaengt!
     426           0 :                     ScFormulaCell* pNext = pCell->GetNext();
     427           0 :                     pCell->SetDirty();
     428             :                     // falls pNext==0 und neue abhaengige hinten angehaengt
     429             :                     // wurden, so macht das nichts, da die alle bDirty sind
     430           0 :                     pCell = pNext;
     431             :                 }
     432             :                 else
     433             :                 {   // andere simpel berechnen
     434           0 :                     if( bSetAllDirty )
     435           0 :                         pCell->SetDirtyVar();
     436           0 :                     pCell = pCell->GetNext();
     437             :                 }
     438             :             }
     439             :         }
     440         148 :         bool bProgress = !bOnlyForced && nFormulaCodeInTree && bProgressBar;
     441         148 :         if ( bProgress )
     442          16 :             ScProgress::CreateInterpretProgress( this, true );
     443             : 
     444         148 :         pCell = pFormulaTree;
     445         148 :         ScFormulaCell* pLastNoGood = 0;
     446         810 :         while ( pCell )
     447             :         {
     448             :             // Interpret setzt bDirty zurueck und callt Remove, auch der referierten!
     449             :             // bei RECALCMODE_ALWAYS bleibt die Zelle
     450         514 :             if ( bOnlyForced )
     451             :             {
     452           0 :                 if ( pCell->GetCode()->IsRecalcModeForced() )
     453           0 :                     pCell->Interpret();
     454             :             }
     455             :             else
     456             :             {
     457         514 :                 pCell->Interpret();
     458             :             }
     459         514 :             if ( pCell->GetPrevious() || pCell == pFormulaTree )
     460             :             {   // (IsInFormulaTree(pCell)) kein Remove gewesen => next
     461           4 :                 pLastNoGood = pCell;
     462           4 :                 pCell = pCell->GetNext();
     463             :             }
     464             :             else
     465             :             {
     466         510 :                 if ( pFormulaTree )
     467             :                 {
     468         488 :                     if ( pFormulaTree->GetDirty() && !bOnlyForced )
     469             :                     {
     470         488 :                         pCell = pFormulaTree;
     471         488 :                         pLastNoGood = 0;
     472             :                     }
     473             :                     else
     474             :                     {
     475             :                         // IsInFormulaTree(pLastNoGood)
     476           0 :                         if ( pLastNoGood && (pLastNoGood->GetPrevious() ||
     477           0 :                                 pLastNoGood == pFormulaTree) )
     478           0 :                             pCell = pLastNoGood->GetNext();
     479             :                         else
     480             :                         {
     481           0 :                             pCell = pFormulaTree;
     482           0 :                             while ( pCell && !pCell->GetDirty() )
     483           0 :                                 pCell = pCell->GetNext();
     484           0 :                             if ( pCell )
     485           0 :                                 pLastNoGood = pCell->GetPrevious();
     486             :                         }
     487             :                     }
     488             :                 }
     489             :                 else
     490          22 :                     pCell = 0;
     491             :             }
     492         514 :             if ( ScProgress::IsUserBreak() )
     493           0 :                 pCell = 0;
     494             :         }
     495         148 :         if ( bProgress )
     496          16 :             ScProgress::DeleteInterpretProgress();
     497             :     }
     498         148 :     bAutoCalc = bOldAutoCalc;
     499         148 :     EnableIdle(bOldIdleEnabled);
     500         148 :     bCalculatingFormulaTree = false;
     501             : 
     502         148 :     mpFormulaGroupCxt.reset();
     503             : }
     504             : 
     505         478 : void ScDocument::ClearFormulaTree()
     506             : {
     507             :     ScFormulaCell* pCell;
     508         478 :     ScFormulaCell* pTree = pFormulaTree;
     509        1340 :     while ( pTree )
     510             :     {
     511         384 :         pCell = pTree;
     512         384 :         pTree = pCell->GetNext();
     513         384 :         if ( !pCell->GetCode()->IsRecalcModeAlways() )
     514         312 :             RemoveFromFormulaTree( pCell );
     515             :     }
     516         478 : }
     517             : 
     518       48006 : void ScDocument::AppendToFormulaTrack( ScFormulaCell* pCell )
     519             : {
     520             :     OSL_ENSURE( pCell, "AppendToFormulaTrack: pCell Null" );
     521             :     // Zelle kann nicht in beiden Listen gleichzeitig sein
     522       48006 :     RemoveFromFormulaTrack( pCell );
     523       48006 :     RemoveFromFormulaTree( pCell );
     524       48006 :     if ( pEOFormulaTrack )
     525       42334 :         pEOFormulaTrack->SetNextTrack( pCell );
     526             :     else
     527        5672 :         pFormulaTrack = pCell;              // kein Ende, kein Anfang..
     528       48006 :     pCell->SetPreviousTrack( pEOFormulaTrack );
     529       48006 :     pCell->SetNextTrack( 0 );
     530       48006 :     pEOFormulaTrack = pCell;
     531       48006 :     ++nFormulaTrackCount;
     532       48006 : }
     533             : 
     534       96012 : void ScDocument::RemoveFromFormulaTrack( ScFormulaCell* pCell )
     535             : {
     536             :     OSL_ENSURE( pCell, "RemoveFromFormulaTrack: pCell Null" );
     537       96012 :     ScFormulaCell* pPrev = pCell->GetPreviousTrack();
     538             :     // wenn die Zelle die erste oder sonstwo ist
     539       96012 :     if ( pPrev || pFormulaTrack == pCell )
     540             :     {
     541       48006 :         ScFormulaCell* pNext = pCell->GetNextTrack();
     542       48006 :         if ( pPrev )
     543           0 :             pPrev->SetNextTrack( pNext );       // gibt Vorlaeufer
     544             :         else
     545       48006 :             pFormulaTrack = pNext;              // ist erste Zelle
     546       48006 :         if ( pNext )
     547       42334 :             pNext->SetPreviousTrack( pPrev );   // gibt Nachfolger
     548             :         else
     549        5672 :             pEOFormulaTrack = pPrev;            // ist letzte Zelle
     550       48006 :         pCell->SetPreviousTrack( 0 );
     551       48006 :         pCell->SetNextTrack( 0 );
     552       48006 :         --nFormulaTrackCount;
     553             :     }
     554       96012 : }
     555             : 
     556       43386 : bool ScDocument::IsInFormulaTrack( ScFormulaCell* pCell ) const
     557             : {
     558       43386 :     return pCell->GetPreviousTrack() || pFormulaTrack == pCell;
     559             : }
     560             : 
     561             : /*
     562             :     Der erste wird gebroadcastet,
     563             :     die dadurch entstehenden werden durch das Notify an den Track gehaengt.
     564             :     Der nachfolgende broadcastet wieder usw.
     565             :     View stoesst Interpret an.
     566             :  */
     567        6232 : void ScDocument::TrackFormulas( sal_uLong nHintId )
     568             : {
     569             : 
     570        6232 :     if ( pFormulaTrack )
     571             :     {
     572             :         // outside the loop, check if any sheet has a "calculate" event script
     573        5672 :         bool bCalcEvent = HasAnySheetEventScript( SC_SHEETEVENT_CALCULATE, true );
     574             :         SvtBroadcaster* pBC;
     575             :         ScFormulaCell* pTrack;
     576             :         ScFormulaCell* pNext;
     577        5672 :         pTrack = pFormulaTrack;
     578       48006 :         do
     579             :         {
     580       48006 :             pBC = GetBroadcaster(pTrack->aPos);
     581       48006 :             ScHint aHint(nHintId, pTrack->aPos);
     582       48006 :             if (pBC)
     583         878 :                 pBC->Broadcast( aHint );
     584       48006 :             pBASM->AreaBroadcast( aHint );
     585             :             //  Repaint fuer bedingte Formate mit relativen Referenzen:
     586       48006 :             TableContainer::iterator itr = maTabs.begin();
     587      100348 :             for(; itr != maTabs.end(); ++itr)
     588             :             {
     589       52342 :                 if(!*itr)
     590           0 :                     continue;
     591       52342 :                 ScConditionalFormatList* pCondFormList = (*itr)->GetCondFormList();
     592       52342 :                 if ( pCondFormList )
     593       52342 :                     pCondFormList->SourceChanged( pTrack->aPos );
     594             :             }
     595             :             // for "calculate" event, keep track of which sheets are affected by tracked formulas
     596       48006 :             if ( bCalcEvent )
     597           0 :                 SetCalcNotification( pTrack->aPos.Tab() );
     598       48006 :             pTrack = pTrack->GetNextTrack();
     599             :         } while ( pTrack );
     600        5672 :         pTrack = pFormulaTrack;
     601        5672 :         bool bHaveForced = false;
     602       48006 :         do
     603             :         {
     604       48006 :             pNext = pTrack->GetNextTrack();
     605       48006 :             RemoveFromFormulaTrack( pTrack );
     606       48006 :             PutInFormulaTree( pTrack );
     607       48006 :             if ( pTrack->GetCode()->IsRecalcModeForced() )
     608           0 :                 bHaveForced = true;
     609       48006 :             pTrack = pNext;
     610             :         } while ( pTrack );
     611        5672 :         if ( bHaveForced )
     612             :         {
     613           0 :             SetForcedFormulas( true );
     614           0 :             if ( bAutoCalc && !IsAutoCalcShellDisabled() && !IsInInterpreter()
     615           0 :                     && !IsCalculatingFormulaTree() )
     616           0 :                 CalcFormulaTree( true );
     617             :             else
     618           0 :                 SetForcedFormulaPending( true );
     619             :         }
     620             :     }
     621             :     OSL_ENSURE( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" );
     622        6232 : }
     623             : 
     624          14 : void ScDocument::StartAllListeners()
     625             : {
     626          28 :     for ( SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i )
     627          14 :         if ( maTabs[i] )
     628          14 :             maTabs[i]->StartAllListeners();
     629          14 : }
     630             : 
     631         604 : void ScDocument::UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
     632             :         const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz
     633             :     )
     634             : {
     635         604 :     bool bExpandRefsOld = IsExpandRefs();
     636         604 :     if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
     637         284 :         SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
     638         604 :     if ( pBASM )
     639         604 :         pBASM->UpdateBroadcastAreas( eUpdateRefMode, rRange, nDx, nDy, nDz );
     640         604 :     SetExpandRefs( bExpandRefsOld );
     641         604 : }
     642             : 
     643     6101858 : void ScDocument::SetAutoCalc( bool bNewAutoCalc )
     644             : {
     645     6101858 :     bool bOld = bAutoCalc;
     646     6101858 :     bAutoCalc = bNewAutoCalc;
     647     6101858 :     if ( !bOld && bNewAutoCalc && bHasForcedFormulas )
     648             :     {
     649           0 :         if ( IsAutoCalcShellDisabled() )
     650           0 :             SetForcedFormulaPending( true );
     651           0 :         else if ( !IsInInterpreter() )
     652           0 :             CalcFormulaTree( true );
     653             :     }
     654     6102086 : }
     655             : 
     656             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10