LCOV - code coverage report
Current view: top level - sc/source/core/data - cell.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 616 930 66.2 %
Date: 2012-08-25 Functions: 60 65 92.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 665 1648 40.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <svl/zforlist.hxx>
      30                 :            : 
      31                 :            : #include "scitems.hxx"
      32                 :            : #include "attrib.hxx"
      33                 :            : #include "cell.hxx"
      34                 :            : #include "compiler.hxx"
      35                 :            : #include "interpre.hxx"
      36                 :            : #include "document.hxx"
      37                 :            : #include "scmatrix.hxx"
      38                 :            : #include "dociter.hxx"
      39                 :            : #include "docoptio.hxx"
      40                 :            : #include "rechead.hxx"
      41                 :            : #include "rangenam.hxx"
      42                 :            : #include "brdcst.hxx"
      43                 :            : #include "ddelink.hxx"
      44                 :            : #include "validat.hxx"
      45                 :            : #include "progress.hxx"
      46                 :            : #include "editutil.hxx"
      47                 :            : #include "recursionhelper.hxx"
      48                 :            : #include "postit.hxx"
      49                 :            : #include "externalrefmgr.hxx"
      50                 :            : #include "macromgr.hxx"
      51                 :            : #include "dbdata.hxx"
      52                 :            : 
      53                 :            : #include <editeng/editobj.hxx>
      54                 :            : #include <svl/intitem.hxx>
      55                 :            : #include <editeng/flditem.hxx>
      56                 :            : #include <svl/broadcast.hxx>
      57                 :            : 
      58                 :            : using namespace formula;
      59                 :            : // More or less arbitrary, of course all recursions must fit into available
      60                 :            : // stack space (which is what on all systems we don't know yet?). Choosing a
      61                 :            : // lower value may be better than trying a much higher value that also isn't
      62                 :            : // sufficient but temporarily leads to high memory consumption. On the other
      63                 :            : // hand, if the value fits all recursions, execution is quicker as no resumes
      64                 :            : // are necessary. Could be made a configurable option.
      65                 :            : // Allow for a year's calendar (366).
      66                 :            : const sal_uInt16 MAXRECURSION = 400;
      67                 :            : 
      68                 :            : // STATIC DATA -----------------------------------------------------------
      69                 :            : 
      70                 :            : #ifdef USE_MEMPOOL
      71                 :         51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScValueCell )
      72                 :         51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
      73                 :         51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScStringCell )
      74                 :         51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScNoteCell )
      75                 :            : #endif
      76                 :            : 
      77                 :            : // ============================================================================
      78                 :            : 
      79                 :      51923 : ScBaseCell::ScBaseCell( CellType eNewType ) :
      80                 :            :     mpBroadcaster( 0 ),
      81                 :            :     nTextWidth( TEXTWIDTH_DIRTY ),
      82                 :      51923 :     eCellType( sal::static_int_cast<sal_uInt8>(eNewType) ),
      83                 :     103846 :     nScriptType( SC_SCRIPTTYPE_UNKNOWN )
      84                 :            : {
      85                 :      51923 : }
      86                 :            : 
      87                 :       6595 : ScBaseCell::ScBaseCell( const ScBaseCell& rCell ) :
      88                 :            :     mpBroadcaster( 0 ),
      89                 :            :     nTextWidth( rCell.nTextWidth ),
      90                 :            :     eCellType( rCell.eCellType ),
      91                 :       6595 :     nScriptType( SC_SCRIPTTYPE_UNKNOWN )
      92                 :            : {
      93                 :       6595 : }
      94                 :            : 
      95                 :      56727 : ScBaseCell::~ScBaseCell()
      96                 :            : {
      97         [ +  + ]:      56727 :     delete mpBroadcaster;
      98                 :            :     OSL_ENSURE( eCellType == CELLTYPE_DESTROYED, "BaseCell Destructor" );
      99                 :      56727 : }
     100                 :            : 
     101                 :            : namespace {
     102                 :            : 
     103                 :       6593 : ScBaseCell* lclCloneCell( const ScBaseCell& rSrcCell, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags )
     104                 :            : {
     105   [ +  +  +  +  :       6593 :     switch( rSrcCell.GetCellType() )
                   +  - ]
     106                 :            :     {
     107                 :            :         case CELLTYPE_VALUE:
     108         [ +  - ]:       3544 :             return new ScValueCell( static_cast< const ScValueCell& >( rSrcCell ) );
     109                 :            :         case CELLTYPE_STRING:
     110         [ +  - ]:       2328 :             return new ScStringCell( static_cast< const ScStringCell& >( rSrcCell ) );
     111                 :            :         case CELLTYPE_EDIT:
     112         [ +  - ]:        389 :             return new ScEditCell(static_cast<const ScEditCell&>(rSrcCell), rDestDoc, rDestPos);
     113                 :            :         case CELLTYPE_FORMULA:
     114 [ +  - ][ +  - ]:        331 :             return new ScFormulaCell( static_cast< const ScFormulaCell& >( rSrcCell ), rDestDoc, rDestPos, nCloneFlags );
     115                 :            :         case CELLTYPE_NOTE:
     116         [ +  - ]:          1 :             return new ScNoteCell;
     117                 :            :         default:;
     118                 :            :     }
     119                 :            :     OSL_FAIL( "lclCloneCell - unknown cell type" );
     120                 :       6593 :     return 0;
     121                 :            : }
     122                 :            : 
     123                 :         34 : void adjustRangeName(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc, const ScAddress& aNewPos, const ScAddress& aOldPos)
     124                 :            : {
     125         [ +  - ]:         34 :     bool bOldGlobal = pToken->IsGlobal();
     126                 :         34 :     SCTAB aOldTab = aOldPos.Tab();
     127                 :         34 :     rtl::OUString aRangeName;
     128         [ +  - ]:         34 :     int nOldIndex = pToken->GetIndex();
     129                 :         34 :     ScRangeData* pOldRangeData = NULL;
     130                 :            : 
     131                 :            :     //search the name of the RangeName
     132         [ +  + ]:         34 :     if (!bOldGlobal)
     133                 :            :     {
     134 [ +  - ][ +  - ]:          9 :         pOldRangeData = pOldDoc->GetRangeName(aOldTab)->findByIndex(nOldIndex);
     135         [ -  + ]:          9 :         if (!pOldRangeData)
     136                 :            :             return;     //might be an error in the formula array
     137                 :          9 :         aRangeName = pOldRangeData->GetUpperName();
     138                 :            :     }
     139                 :            :     else
     140                 :            :     {
     141 [ +  - ][ +  - ]:         25 :         pOldRangeData = pOldDoc->GetRangeName()->findByIndex(nOldIndex);
     142         [ -  + ]:         25 :         if (!pOldRangeData)
     143                 :            :             return;     //might be an error in the formula array
     144                 :         25 :         aRangeName = pOldRangeData->GetUpperName();
     145                 :            :     }
     146                 :            : 
     147                 :            :     //find corresponding range name in new document
     148                 :            :     //first search for local range name then global range names
     149                 :         34 :     SCTAB aNewTab = aNewPos.Tab();
     150         [ +  - ]:         34 :     ScRangeName* pRangeName = rNewDoc.GetRangeName(aNewTab);
     151                 :         34 :     ScRangeData* pRangeData = NULL;
     152                 :         34 :     bool bNewGlobal = false;
     153                 :            :     //search local range names
     154         [ +  - ]:         34 :     if (pRangeName)
     155                 :            :     {
     156         [ +  - ]:         34 :         pRangeData = pRangeName->findByUpperName(aRangeName);
     157                 :            :     }
     158                 :            :     //search global range names
     159         [ +  + ]:         34 :     if (!pRangeData)
     160                 :            :     {
     161                 :         31 :         bNewGlobal = true;
     162         [ +  - ]:         31 :         pRangeName = rNewDoc.GetRangeName();
     163         [ +  - ]:         31 :         if (pRangeName)
     164         [ +  - ]:         31 :             pRangeData = pRangeName->findByUpperName(aRangeName);
     165                 :            :     }
     166                 :            :     //if no range name was found copy it
     167         [ +  + ]:         34 :     if (!pRangeData)
     168                 :            :     {
     169                 :         13 :         bNewGlobal = bOldGlobal;
     170 [ +  - ][ +  - ]:         13 :         pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc);
     171                 :         13 :         ScTokenArray* pRangeNameToken = pRangeData->GetCode();
     172 [ +  - ][ +  + ]:         13 :         if (rNewDoc.GetPool() != const_cast<ScDocument*>(pOldDoc)->GetPool())
                 [ +  - ]
     173                 :            :         {
     174         [ +  - ]:          4 :             pRangeNameToken->ReadjustAbsolute3DReferences(pOldDoc, &rNewDoc, pRangeData->GetPos(), true);
     175         [ +  - ]:          4 :             pRangeNameToken->AdjustAbsoluteRefs(pOldDoc, aOldPos, aNewPos, false, true);
     176                 :            :         }
     177                 :            : 
     178                 :            :         bool bInserted;
     179         [ +  + ]:         13 :         if (bNewGlobal)
     180 [ +  - ][ +  - ]:          7 :             bInserted = rNewDoc.GetRangeName()->insert(pRangeData);
     181                 :            :         else
     182 [ +  - ][ +  - ]:          6 :             bInserted = rNewDoc.GetRangeName(aNewTab)->insert(pRangeData);
     183         [ -  + ]:         13 :         if (!bInserted)
     184                 :            :         {
     185                 :            :             //if this happened we have a real problem
     186                 :          0 :             pRangeData = NULL;
     187         [ #  # ]:          0 :             pToken->SetIndex(0);
     188                 :            :             OSL_FAIL("inserting the range name should not fail");
     189                 :            :             return;
     190                 :            :         }
     191                 :            :     }
     192                 :         34 :     sal_Int32 nIndex = pRangeData->GetIndex();
     193         [ +  - ]:         34 :     pToken->SetIndex(nIndex);
     194 [ +  - ][ +  - ]:         34 :     pToken->SetGlobal(bNewGlobal);
     195                 :            : }
     196                 :            : 
     197                 :          0 : void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldDoc)
     198                 :            : {
     199         [ #  # ]:          0 :     ScDBCollection* pOldDBCollection = pOldDoc->GetDBCollection();
     200         [ #  # ]:          0 :     if (!pOldDBCollection)
     201                 :            :         return;//strange error case, don't do anything
     202         [ #  # ]:          0 :     ScDBCollection::NamedDBs& aOldNamedDBs = pOldDBCollection->getNamedDBs();
     203 [ #  # ][ #  # ]:          0 :     ScDBData* pDBData = aOldNamedDBs.findByIndex(pToken->GetIndex());
     204         [ #  # ]:          0 :     if (!pDBData)
     205                 :            :         return; //invalid index
     206                 :          0 :     rtl::OUString aDBName = pDBData->GetName();
     207                 :            : 
     208                 :            :     //search in new document
     209         [ #  # ]:          0 :     ScDBCollection* pNewDBCollection = rNewDoc.GetDBCollection();
     210         [ #  # ]:          0 :     if (!pNewDBCollection)
     211                 :            :     {
     212 [ #  # ][ #  # ]:          0 :         pNewDBCollection = new ScDBCollection(&rNewDoc);
     213                 :            :     }
     214         [ #  # ]:          0 :     ScDBCollection::NamedDBs& aNewNamedDBs = pNewDBCollection->getNamedDBs();
     215         [ #  # ]:          0 :     ScDBData* pNewDBData = aNewNamedDBs.findByName(aDBName);
     216         [ #  # ]:          0 :     if (!pNewDBData)
     217                 :            :     {
     218 [ #  # ][ #  # ]:          0 :         pNewDBData = new ScDBData(*pDBData);
     219         [ #  # ]:          0 :         aNewNamedDBs.insert(pNewDBData);
     220                 :            :     }
     221         [ #  # ]:          0 :     pToken->SetIndex(pNewDBData->GetIndex());
     222                 :            : }
     223                 :            : 
     224                 :            : } // namespace
     225                 :            : 
     226                 :         51 : ScBaseCell* ScBaseCell::Clone( ScDocument& rDestDoc, int nCloneFlags ) const
     227                 :            : {
     228                 :            :     // notes will not be cloned -> cell address only needed for formula cells
     229                 :         51 :     ScAddress aDestPos;
     230         [ +  + ]:         51 :     if( eCellType == CELLTYPE_FORMULA )
     231                 :         10 :         aDestPos = static_cast< const ScFormulaCell* >( this )->aPos;
     232         [ +  - ]:         51 :     return lclCloneCell( *this, rDestDoc, aDestPos, nCloneFlags );
     233                 :            : }
     234                 :            : 
     235                 :       6542 : ScBaseCell* ScBaseCell::Clone( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags ) const
     236                 :            : {
     237                 :       6542 :     return lclCloneCell( *this, rDestDoc, rDestPos, nCloneFlags );
     238                 :            : }
     239                 :            : 
     240                 :      56064 : void ScBaseCell::Delete()
     241                 :            : {
     242   [ +  +  +  +  :      56064 :     switch (eCellType)
                   +  - ]
     243                 :            :     {
     244                 :            :         case CELLTYPE_VALUE:
     245         [ +  - ]:      39815 :             delete (ScValueCell*) this;
     246                 :      39815 :             break;
     247                 :            :         case CELLTYPE_STRING:
     248         [ +  - ]:      11349 :             delete (ScStringCell*) this;
     249                 :      11349 :             break;
     250                 :            :         case CELLTYPE_EDIT:
     251         [ +  - ]:        845 :             delete (ScEditCell*) this;
     252                 :        845 :             break;
     253                 :            :         case CELLTYPE_FORMULA:
     254         [ +  - ]:       3818 :             delete (ScFormulaCell*) this;
     255                 :       3818 :             break;
     256                 :            :         case CELLTYPE_NOTE:
     257         [ +  - ]:        237 :             delete (ScNoteCell*) this;
     258                 :        237 :             break;
     259                 :            :         default:
     260                 :            :             OSL_FAIL("Attempt to Delete() an unknown CELLTYPE");
     261                 :          0 :             break;
     262                 :            :     }
     263                 :      56064 : }
     264                 :            : 
     265                 :       1776 : bool ScBaseCell::IsBlank() const
     266                 :            : {
     267                 :       1776 :     return false;
     268                 :            : }
     269                 :            : 
     270                 :       3713 : void ScBaseCell::TakeBroadcaster( SvtBroadcaster* pBroadcaster )
     271                 :            : {
     272         [ -  + ]:       3713 :     delete mpBroadcaster;
     273                 :       3713 :     mpBroadcaster = pBroadcaster;
     274                 :       3713 : }
     275                 :            : 
     276                 :       1251 : SvtBroadcaster* ScBaseCell::ReleaseBroadcaster()
     277                 :            : {
     278                 :       1251 :     SvtBroadcaster* pBroadcaster = mpBroadcaster;
     279                 :       1251 :     mpBroadcaster = 0;
     280                 :       1251 :     return pBroadcaster;
     281                 :            : }
     282                 :            : 
     283                 :        311 : void ScBaseCell::DeleteBroadcaster()
     284                 :            : {
     285         [ +  - ]:        311 :     DELETEZ( mpBroadcaster );
     286                 :        311 : }
     287                 :            : 
     288                 :       6874 : ScBaseCell* ScBaseCell::CreateTextCell( const rtl::OUString& rString, ScDocument* pDoc )
     289                 :            : {
     290 [ +  + ][ -  + ]:       6874 :     if ( rString.indexOf('\n') != -1 || rString.indexOf(CHAR_CR) != -1 )
                 [ +  + ]
     291         [ +  - ]:          5 :         return new ScEditCell( rString, pDoc );
     292                 :            :     else
     293         [ +  - ]:       6874 :         return new ScStringCell( rString );
     294                 :            : }
     295                 :            : 
     296                 :      31913 : void ScBaseCell::StartListeningTo( ScDocument* pDoc )
     297                 :            : {
     298 [ +  + ][ +  -  :      39708 :     if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
             +  +  +  - ]
                 [ +  + ]
     299                 :       3909 :             && !pDoc->GetNoListening()
     300                 :       3886 :             && !((ScFormulaCell*)this)->IsInChangeTrack()
     301                 :            :         )
     302                 :            :     {
     303                 :       3886 :         pDoc->SetDetectiveDirty(true);  // es hat sich was geaendert...
     304                 :            : 
     305                 :       3886 :         ScFormulaCell* pFormCell = (ScFormulaCell*)this;
     306                 :       3886 :         ScTokenArray* pArr = pFormCell->GetCode();
     307         [ +  + ]:       3886 :         if( pArr->IsRecalcModeAlways() )
     308         [ +  - ]:         66 :             pDoc->StartListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
     309                 :            :         else
     310                 :            :         {
     311                 :       3820 :             pArr->Reset();
     312                 :            :             ScToken* t;
     313         [ +  + ]:      14531 :             while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
     314                 :            :             {
     315                 :      10711 :                 StackVar eType = t->GetType();
     316                 :      10711 :                 ScSingleRefData& rRef1 = t->GetSingleRef();
     317                 :            :                 ScSingleRefData& rRef2 = (eType == svDoubleRef ?
     318         [ +  + ]:      10711 :                     t->GetDoubleRef().Ref2 : rRef1);
     319      [ +  +  + ]:      10711 :                 switch( eType )
     320                 :            :                 {
     321                 :            :                     case svSingleRef:
     322                 :       5110 :                         rRef1.CalcAbsIfRel( pFormCell->aPos );
     323         [ +  + ]:       5110 :                         if ( rRef1.Valid() )
     324                 :            :                         {
     325                 :            :                             pDoc->StartListeningCell(
     326                 :            :                                 ScAddress( rRef1.nCol,
     327                 :            :                                            rRef1.nRow,
     328         [ +  - ]:       5107 :                                            rRef1.nTab ), pFormCell );
     329                 :            :                         }
     330                 :       5110 :                     break;
     331                 :            :                     case svDoubleRef:
     332                 :       5503 :                         t->CalcAbsIfRel( pFormCell->aPos );
     333 [ +  - ][ +  - ]:       5503 :                         if ( rRef1.Valid() && rRef2.Valid() )
                 [ +  - ]
     334                 :            :                         {
     335         [ -  + ]:       5503 :                             if ( t->GetOpCode() == ocColRowNameAuto )
     336                 :            :                             {   // automagically
     337         [ #  # ]:          0 :                                 if ( rRef1.IsColRel() )
     338                 :            :                                 {   // ColName
     339                 :            :                                     pDoc->StartListeningArea( ScRange (
     340                 :            :                                         rRef1.nCol,
     341                 :            :                                         rRef1.nRow,
     342                 :            :                                         rRef1.nTab,
     343                 :            :                                         rRef2.nCol,
     344                 :            :                                         MAXROW,
     345         [ #  # ]:          0 :                                         rRef2.nTab ), pFormCell );
     346                 :            :                                 }
     347                 :            :                                 else
     348                 :            :                                 {   // RowName
     349                 :            :                                     pDoc->StartListeningArea( ScRange (
     350                 :            :                                         rRef1.nCol,
     351                 :            :                                         rRef1.nRow,
     352                 :            :                                         rRef1.nTab,
     353                 :            :                                         MAXCOL,
     354                 :            :                                         rRef2.nRow,
     355         [ #  # ]:          0 :                                         rRef2.nTab ), pFormCell );
     356                 :            :                                 }
     357                 :            :                             }
     358                 :            :                             else
     359                 :            :                             {
     360                 :            :                                 pDoc->StartListeningArea( ScRange (
     361                 :            :                                     rRef1.nCol,
     362                 :            :                                     rRef1.nRow,
     363                 :            :                                     rRef1.nTab,
     364                 :            :                                     rRef2.nCol,
     365                 :            :                                     rRef2.nRow,
     366         [ +  - ]:       5503 :                                     rRef2.nTab ), pFormCell );
     367                 :            :                             }
     368                 :            :                         }
     369                 :       5503 :                     break;
     370                 :            :                     default:
     371                 :            :                         ;   // nothing
     372                 :            :                 }
     373                 :            :             }
     374                 :            :         }
     375                 :       3886 :         pFormCell->SetNeedsListening( false);
     376                 :            :     }
     377                 :      31913 : }
     378                 :            : 
     379                 :            : //  pArr gesetzt -> Referenzen von anderer Zelle nehmen
     380                 :            : // dann muss auch aPos uebergeben werden!
     381                 :            : 
     382                 :        535 : void ScBaseCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
     383                 :            :         ScAddress aPos )
     384                 :            : {
     385         [ +  + ]:       1046 :     if ( eCellType == CELLTYPE_FORMULA && !pDoc->IsClipOrUndo()
           [ +  -  +  - ]
                 [ +  + ]
     386                 :        511 :             && !((ScFormulaCell*)this)->IsInChangeTrack()
     387                 :            :         )
     388                 :            :     {
     389                 :        511 :         pDoc->SetDetectiveDirty(true);  // es hat sich was geaendert...
     390                 :            : 
     391                 :        511 :         ScFormulaCell* pFormCell = (ScFormulaCell*)this;
     392         [ -  + ]:        511 :         if( pFormCell->GetCode()->IsRecalcModeAlways() )
     393         [ #  # ]:          0 :             pDoc->EndListeningArea( BCA_LISTEN_ALWAYS, pFormCell );
     394                 :            :         else
     395                 :            :         {
     396         [ +  - ]:        511 :             if (!pArr)
     397                 :            :             {
     398                 :        511 :                 pArr = pFormCell->GetCode();
     399                 :        511 :                 aPos = pFormCell->aPos;
     400                 :            :             }
     401                 :        511 :             pArr->Reset();
     402                 :            :             ScToken* t;
     403         [ +  + ]:       1234 :             while ( ( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) ) != NULL )
     404                 :            :             {
     405                 :        723 :                 StackVar eType = t->GetType();
     406                 :        723 :                 ScSingleRefData& rRef1 = t->GetSingleRef();
     407                 :            :                 ScSingleRefData& rRef2 = (eType == svDoubleRef ?
     408         [ +  + ]:        723 :                     t->GetDoubleRef().Ref2 : rRef1);
     409      [ +  +  + ]:        723 :                 switch( eType )
     410                 :            :                 {
     411                 :            :                     case svSingleRef:
     412                 :        477 :                         rRef1.CalcAbsIfRel( aPos );
     413         [ +  + ]:        477 :                         if ( rRef1.Valid() )
     414                 :            :                         {
     415                 :            :                             pDoc->EndListeningCell(
     416                 :            :                                 ScAddress( rRef1.nCol,
     417                 :            :                                            rRef1.nRow,
     418         [ +  - ]:        474 :                                            rRef1.nTab ), pFormCell );
     419                 :            :                         }
     420                 :        477 :                     break;
     421                 :            :                     case svDoubleRef:
     422                 :        226 :                         t->CalcAbsIfRel( aPos );
     423 [ +  - ][ +  - ]:        226 :                         if ( rRef1.Valid() && rRef2.Valid() )
                 [ +  - ]
     424                 :            :                         {
     425         [ -  + ]:        226 :                             if ( t->GetOpCode() == ocColRowNameAuto )
     426                 :            :                             {   // automagically
     427         [ #  # ]:          0 :                                 if ( rRef1.IsColRel() )
     428                 :            :                                 {   // ColName
     429                 :            :                                     pDoc->EndListeningArea( ScRange (
     430                 :            :                                         rRef1.nCol,
     431                 :            :                                         rRef1.nRow,
     432                 :            :                                         rRef1.nTab,
     433                 :            :                                         rRef2.nCol,
     434                 :            :                                         MAXROW,
     435         [ #  # ]:          0 :                                         rRef2.nTab ), pFormCell );
     436                 :            :                                 }
     437                 :            :                                 else
     438                 :            :                                 {   // RowName
     439                 :            :                                     pDoc->EndListeningArea( ScRange (
     440                 :            :                                         rRef1.nCol,
     441                 :            :                                         rRef1.nRow,
     442                 :            :                                         rRef1.nTab,
     443                 :            :                                         MAXCOL,
     444                 :            :                                         rRef2.nRow,
     445         [ #  # ]:          0 :                                         rRef2.nTab ), pFormCell );
     446                 :            :                                 }
     447                 :            :                             }
     448                 :            :                             else
     449                 :            :                             {
     450                 :            :                                 pDoc->EndListeningArea( ScRange (
     451                 :            :                                     rRef1.nCol,
     452                 :            :                                     rRef1.nRow,
     453                 :            :                                     rRef1.nTab,
     454                 :            :                                     rRef2.nCol,
     455                 :            :                                     rRef2.nRow,
     456         [ +  - ]:        226 :                                     rRef2.nTab ), pFormCell );
     457                 :            :                             }
     458                 :            :                         }
     459                 :        226 :                     break;
     460                 :            :                     default:
     461                 :            :                         ;   // nothing
     462                 :            :                 }
     463                 :            :             }
     464                 :            :         }
     465                 :            :     }
     466                 :        535 : }
     467                 :            : 
     468                 :            : 
     469                 :       1306 : sal_uInt16 ScBaseCell::GetErrorCode() const
     470                 :            : {
     471         [ +  + ]:       1306 :     switch ( eCellType )
     472                 :            :     {
     473                 :            :         case CELLTYPE_FORMULA :
     474                 :        186 :             return ((ScFormulaCell*)this)->GetErrCode();
     475                 :            :         default:
     476                 :       1306 :             return 0;
     477                 :            :     }
     478                 :            : }
     479                 :            : 
     480                 :            : 
     481                 :        752 : bool ScBaseCell::HasEmptyData() const
     482                 :            : {
     483      [ +  +  + ]:        752 :     switch ( eCellType )
     484                 :            :     {
     485                 :            :         case CELLTYPE_NOTE :
     486                 :         30 :             return true;
     487                 :            :         case CELLTYPE_FORMULA :
     488                 :         31 :             return ((ScFormulaCell*)this)->IsEmpty();
     489                 :            :         default:
     490                 :        752 :             return false;
     491                 :            :     }
     492                 :            : }
     493                 :            : 
     494                 :            : 
     495                 :      26074 : bool ScBaseCell::HasValueData() const
     496                 :            : {
     497      [ +  +  + ]:      26074 :     switch ( eCellType )
     498                 :            :     {
     499                 :            :         case CELLTYPE_VALUE :
     500                 :      17936 :             return true;
     501                 :            :         case CELLTYPE_FORMULA :
     502                 :        604 :             return ((ScFormulaCell*)this)->IsValue();
     503                 :            :         default:
     504                 :      26074 :             return false;
     505                 :            :     }
     506                 :            : }
     507                 :            : 
     508                 :            : 
     509                 :      10870 : bool ScBaseCell::HasStringData() const
     510                 :            : {
     511      [ +  +  + ]:      10870 :     switch ( eCellType )
     512                 :            :     {
     513                 :            :         case CELLTYPE_STRING :
     514                 :            :         case CELLTYPE_EDIT :
     515                 :       6054 :             return true;
     516                 :            :         case CELLTYPE_FORMULA :
     517                 :       1079 :             return !((ScFormulaCell*)this)->IsValue();
     518                 :            :         default:
     519                 :      10870 :             return false;
     520                 :            :     }
     521                 :            : }
     522                 :            : 
     523                 :       5375 : rtl::OUString ScBaseCell::GetStringData() const
     524                 :            : {
     525                 :       5375 :     rtl::OUString aStr;
     526   [ +  +  -  - ]:       5375 :     switch ( eCellType )
     527                 :            :     {
     528                 :            :         case CELLTYPE_STRING:
     529                 :       5374 :             aStr = ((const ScStringCell*)this)->GetString();
     530                 :       5374 :             break;
     531                 :            :         case CELLTYPE_EDIT:
     532         [ +  - ]:          1 :             aStr = ((const ScEditCell*)this)->GetString();
     533                 :          1 :             break;
     534                 :            :         case CELLTYPE_FORMULA:
     535         [ #  # ]:          0 :             aStr = ((ScFormulaCell*)this)->GetString();      // an der Formelzelle nicht-const
     536                 :          0 :             break;
     537                 :            :     }
     538                 :       5375 :     return aStr;
     539                 :            : }
     540                 :            : 
     541                 :         68 : bool ScBaseCell::CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 )
     542                 :            : {
     543                 :         68 :     CellType eType1 = CELLTYPE_NONE;
     544                 :         68 :     CellType eType2 = CELLTYPE_NONE;
     545         [ +  - ]:         68 :     if ( pCell1 )
     546                 :            :     {
     547                 :         68 :         eType1 = pCell1->GetCellType();
     548         [ -  + ]:         68 :         if (eType1 == CELLTYPE_EDIT)
     549                 :          0 :             eType1 = CELLTYPE_STRING;
     550         [ -  + ]:         68 :         else if (eType1 == CELLTYPE_NOTE)
     551                 :          0 :             eType1 = CELLTYPE_NONE;
     552                 :            :     }
     553         [ +  - ]:         68 :     if ( pCell2 )
     554                 :            :     {
     555                 :         68 :         eType2 = pCell2->GetCellType();
     556         [ -  + ]:         68 :         if (eType2 == CELLTYPE_EDIT)
     557                 :          0 :             eType2 = CELLTYPE_STRING;
     558         [ -  + ]:         68 :         else if (eType2 == CELLTYPE_NOTE)
     559                 :          0 :             eType2 = CELLTYPE_NONE;
     560                 :            :     }
     561         [ +  + ]:         68 :     if ( eType1 != eType2 )
     562                 :         10 :         return false;
     563                 :            : 
     564   [ -  +  +  +  :         58 :     switch ( eType1 )               // beide Typen gleich
                      - ]
     565                 :            :     {
     566                 :            :         case CELLTYPE_NONE:         // beide leer
     567                 :          0 :             return true;
     568                 :            :         case CELLTYPE_VALUE:        // wirklich Value-Zellen
     569                 :         14 :             return ( ((const ScValueCell*)pCell1)->GetValue() ==
     570                 :         14 :                      ((const ScValueCell*)pCell2)->GetValue() );
     571                 :            :         case CELLTYPE_STRING:       // String oder Edit
     572                 :            :             {
     573                 :         40 :                 rtl::OUString aText1;
     574         [ +  - ]:         40 :                 if ( pCell1->GetCellType() == CELLTYPE_STRING )
     575                 :         40 :                     aText1 = ((const ScStringCell*)pCell1)->GetString();
     576                 :            :                 else
     577         [ #  # ]:          0 :                     aText1 = ((const ScEditCell*)pCell1)->GetString();
     578                 :         40 :                 rtl::OUString aText2;
     579         [ +  - ]:         40 :                 if ( pCell2->GetCellType() == CELLTYPE_STRING )
     580                 :         40 :                     aText2 = ((const ScStringCell*)pCell2)->GetString();
     581                 :            :                 else
     582         [ #  # ]:          0 :                     aText2 = ((const ScEditCell*)pCell2)->GetString();
     583                 :         40 :                 return ( aText1 == aText2 );
     584                 :            :             }
     585                 :            :         case CELLTYPE_FORMULA:
     586                 :            :             {
     587                 :            :                 //! eingefuegte Zeilen / Spalten beruecksichtigen !!!!!
     588                 :            :                 //! Vergleichsfunktion an der Formelzelle ???
     589                 :            :                 //! Abfrage mit ScColumn::SwapRow zusammenfassen!
     590                 :            : 
     591         [ +  - ]:          4 :                 ScTokenArray* pCode1 = ((ScFormulaCell*)pCell1)->GetCode();
     592         [ +  - ]:          4 :                 ScTokenArray* pCode2 = ((ScFormulaCell*)pCell2)->GetCode();
     593                 :            : 
     594         [ +  - ]:          4 :                 if (pCode1->GetLen() == pCode2->GetLen())       // nicht-UPN
     595                 :            :                 {
     596                 :          4 :                     bool bEqual = true;
     597                 :          4 :                     sal_uInt16 nLen = pCode1->GetLen();
     598                 :          4 :                     FormulaToken** ppToken1 = pCode1->GetArray();
     599                 :          4 :                     FormulaToken** ppToken2 = pCode2->GetArray();
     600         [ +  + ]:         16 :                     for (sal_uInt16 i=0; i<nLen; i++)
     601         [ -  + ]:         12 :                         if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) )
     602                 :            :                         {
     603                 :          0 :                             bEqual = false;
     604                 :          0 :                             break;
     605                 :            :                         }
     606                 :            : 
     607         [ +  - ]:          4 :                     if (bEqual)
     608                 :          4 :                         return true;
     609                 :            :                 }
     610                 :            : 
     611                 :          0 :                 return false;       // unterschiedlich lang oder unterschiedliche Tokens
     612                 :            :             }
     613                 :            :         default:
     614                 :            :             OSL_FAIL("huch, was fuer Zellen???");
     615                 :            :     }
     616                 :         68 :     return false;
     617                 :            : }
     618                 :            : 
     619                 :            : // ============================================================================
     620                 :            : 
     621                 :        928 : ScNoteCell::ScNoteCell( SvtBroadcaster* pBC ) :
     622                 :        928 :     ScBaseCell( CELLTYPE_NOTE )
     623                 :            : {
     624         [ +  - ]:        928 :     TakeBroadcaster( pBC );
     625                 :        928 : }
     626                 :            : 
     627                 :            : #if OSL_DEBUG_LEVEL > 0
     628                 :            : ScNoteCell::~ScNoteCell()
     629                 :            : {
     630                 :            :     eCellType = CELLTYPE_DESTROYED;
     631                 :            : }
     632                 :            : #endif
     633                 :            : 
     634                 :            : // ============================================================================
     635                 :            : 
     636                 :      37150 : ScValueCell::ScValueCell( double fValue ) :
     637                 :            :     ScBaseCell( CELLTYPE_VALUE ),
     638                 :      37150 :     mfValue( fValue )
     639                 :            : {
     640                 :      37150 : }
     641                 :            : 
     642                 :            : #if OSL_DEBUG_LEVEL > 0
     643                 :            : ScValueCell::~ScValueCell()
     644                 :            : {
     645                 :            :     eCellType = CELLTYPE_DESTROYED;
     646                 :            : }
     647                 :            : #endif
     648                 :            : 
     649                 :            : // ============================================================================
     650                 :            : 
     651                 :       9620 : ScStringCell::ScStringCell( const rtl::OUString& rString ) :
     652                 :            :     ScBaseCell( CELLTYPE_STRING ),
     653         [ +  - ]:       9620 :     maString( rString.intern() )
     654                 :            : {
     655                 :       9620 : }
     656                 :            : 
     657                 :            : #if OSL_DEBUG_LEVEL > 0
     658                 :            : ScStringCell::~ScStringCell()
     659                 :            : {
     660                 :            :     eCellType = CELLTYPE_DESTROYED;
     661                 :            : }
     662                 :            : #endif
     663                 :            : 
     664                 :            : // ============================================================================
     665                 :            : 
     666                 :            : //
     667                 :            : //      ScFormulaCell
     668                 :            : //
     669                 :            : 
     670                 :        519 : ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
     671                 :            :                               const rtl::OUString& rFormula,
     672                 :            :                               const FormulaGrammar::Grammar eGrammar,
     673                 :            :                               sal_uInt8 cMatInd ) :
     674                 :            :     ScBaseCell( CELLTYPE_FORMULA ),
     675                 :            :     eTempGrammar( eGrammar),
     676                 :            :     pCode( NULL ),
     677                 :            :     pDocument( pDoc ),
     678                 :            :     pPrevious(0),
     679                 :            :     pNext(0),
     680                 :            :     pPreviousTrack(0),
     681                 :            :     pNextTrack(0),
     682                 :            :     nFormatIndex(0),
     683                 :            :     nFormatType( NUMBERFORMAT_NUMBER ),
     684                 :            :     nSeenInIteration(0),
     685                 :            :     cMatrixFlag ( cMatInd ),
     686                 :            :     bDirty( true ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cMatInd != 0
     687                 :            :     bChanged( false ),
     688                 :            :     bRunning( false ),
     689                 :            :     bCompile( false ),
     690                 :            :     bSubTotal( false ),
     691                 :            :     bIsIterCell( false ),
     692                 :            :     bInChangeTrack( false ),
     693                 :            :     bTableOpDirty( false ),
     694                 :            :     bNeedListening( false ),
     695 [ +  - ][ +  - ]:        519 :     aPos( rPos )
     696                 :            : {
     697         [ +  - ]:        519 :     Compile( rFormula, true, eGrammar );    // bNoListening, Insert does that
     698         [ -  + ]:        519 :     if (!pCode)
     699                 :            :         // We need to have a non-NULL token array instance at all times.
     700 [ #  # ][ #  # ]:          0 :         pCode = new ScTokenArray;
     701                 :        519 : }
     702                 :            : 
     703                 :            : // Wird von den Importfiltern verwendet
     704                 :            : 
     705                 :       3250 : ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
     706                 :            :                               const ScTokenArray* pArr,
     707                 :            :                               const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) :
     708                 :            :     ScBaseCell( CELLTYPE_FORMULA ),
     709                 :            :     eTempGrammar( eGrammar),
     710 [ +  - ][ +  - ]:       3250 :     pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
     711                 :            :     pDocument( pDoc ),
     712                 :            :     pPrevious(0),
     713                 :            :     pNext(0),
     714                 :            :     pPreviousTrack(0),
     715                 :            :     pNextTrack(0),
     716                 :            :     nFormatIndex(0),
     717                 :            :     nFormatType( NUMBERFORMAT_NUMBER ),
     718                 :            :     nSeenInIteration(0),
     719                 :            :     cMatrixFlag ( cInd ),
     720                 :            :     bDirty( NULL != pArr ), // -> wg. Benutzung im Fkt.AutoPiloten, war: cInd != 0
     721                 :            :     bChanged( false ),
     722                 :            :     bRunning( false ),
     723                 :            :     bCompile( false ),
     724                 :            :     bSubTotal( false ),
     725                 :            :     bIsIterCell( false ),
     726                 :            :     bInChangeTrack( false ),
     727                 :            :     bTableOpDirty( false ),
     728                 :            :     bNeedListening( false ),
     729 [ +  - ][ +  - ]:       6500 :     aPos( rPos )
         [ +  + ][ +  - ]
                 [ +  - ]
     730                 :            : {
     731                 :            :     // UPN-Array erzeugen
     732 [ +  - ][ +  - ]:       3250 :     if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() )
         [ +  + ][ +  + ]
     733                 :            :     {
     734         [ +  - ]:       3213 :         ScCompiler aComp( pDocument, aPos, *pCode);
     735         [ +  - ]:       3213 :         aComp.SetGrammar(eTempGrammar);
     736         [ +  - ]:       3213 :         bSubTotal = aComp.CompileTokenArray();
     737         [ +  - ]:       3213 :         nFormatType = aComp.GetNumFormatType();
     738                 :            :     }
     739                 :            :     else
     740                 :            :     {
     741                 :         37 :         pCode->Reset();
     742 [ -  + ][ +  - ]:         37 :         if ( pCode->GetNextOpCodeRPN( ocSubTotal ) )
     743                 :          0 :             bSubTotal = true;
     744                 :            :     }
     745                 :            : 
     746         [ +  + ]:       3250 :     if (bSubTotal)
     747         [ +  - ]:          5 :         pDocument->AddSubTotalCell(this);
     748                 :       3250 : }
     749                 :            : 
     750                 :        334 : ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) :
     751                 :            :     ScBaseCell( rCell ),
     752                 :            :     SvtListener(),
     753                 :            :     aResult( rCell.aResult ),
     754                 :            :     eTempGrammar( rCell.eTempGrammar),
     755                 :            :     pDocument( &rDoc ),
     756                 :            :     pPrevious(0),
     757                 :            :     pNext(0),
     758                 :            :     pPreviousTrack(0),
     759                 :            :     pNextTrack(0),
     760                 :            :     nFormatIndex( &rDoc == rCell.pDocument ? rCell.nFormatIndex : 0 ),
     761                 :            :     nFormatType( rCell.nFormatType ),
     762                 :            :     nSeenInIteration(0),
     763                 :            :     cMatrixFlag ( rCell.cMatrixFlag ),
     764                 :            :     bDirty( rCell.bDirty ),
     765                 :            :     bChanged( rCell.bChanged ),
     766                 :            :     bRunning( false ),
     767                 :            :     bCompile( rCell.bCompile ),
     768                 :            :     bSubTotal( rCell.bSubTotal ),
     769                 :            :     bIsIterCell( false ),
     770                 :            :     bInChangeTrack( false ),
     771                 :            :     bTableOpDirty( false ),
     772                 :            :     bNeedListening( false ),
     773 [ +  - ][ +  - ]:        334 :     aPos( rPos )
                 [ +  + ]
     774                 :            : {
     775         [ +  - ]:        334 :     pCode = rCell.pCode->Clone();
     776                 :            : 
     777                 :            :     // evtl. Fehler zuruecksetzen und neu kompilieren
     778                 :            :     //  nicht im Clipboard - da muss das Fehlerflag erhalten bleiben
     779                 :            :     //  Spezialfall Laenge=0: als Fehlerzelle erzeugt, dann auch Fehler behalten
     780 [ +  + ][ +  - ]:        334 :     if ( pCode->GetCodeError() && !pDocument->IsClipboard() && pCode->GetLen() )
         [ -  + ][ -  + ]
     781                 :            :     {
     782                 :          0 :         pCode->SetCodeError( 0 );
     783                 :          0 :         bCompile = true;
     784                 :            :     }
     785                 :            :     //! Compile ColRowNames on URM_MOVE/URM_COPY _after_ UpdateReference
     786                 :        334 :     bool bCompileLater = false;
     787                 :        334 :     bool bClipMode = rCell.pDocument->IsClipboard();
     788                 :            : 
     789                 :            :     //update ScNameTokens
     790 [ +  + ][ +  + ]:        334 :     if (!pDocument->IsClipOrUndo() || rDoc.IsUndo())
                 [ +  + ]
     791                 :            :     {
     792 [ +  - ][ -  + ]:        298 :         if (!pDocument->IsClipboardSource() || aPos.Tab() != rCell.aPos.Tab())
         [ #  # ][ +  - ]
     793                 :            :         {
     794                 :        298 :             ScToken* pToken = NULL;
     795 [ +  - ][ +  + ]:        332 :             while((pToken = static_cast<ScToken*>(pCode->GetNextName()))!= NULL)
     796                 :            :             {
     797                 :         34 :                 OpCode eOpCode = pToken->GetOpCode();
     798         [ +  - ]:         34 :                 if (eOpCode == ocName)
     799         [ +  - ]:         34 :                     adjustRangeName(pToken, rDoc, rCell.pDocument, aPos, rCell.aPos);
     800         [ #  # ]:          0 :                 else if (eOpCode == ocDBArea)
     801         [ #  # ]:          0 :                     adjustDBRange(pToken, rDoc, rCell.pDocument);
     802                 :            :             }
     803                 :            :         }
     804                 :            : 
     805 [ +  - ][ +  - ]:        298 :         bool bCopyBetweenDocs = pDocument->GetPool() != rCell.pDocument->GetPool();
     806 [ +  + ][ +  - ]:        298 :         if (bCopyBetweenDocs && !(nCloneFlags & SC_CLONECELL_NOMAKEABS_EXTERNAL))
     807                 :            :         {
     808         [ +  - ]:         28 :             pCode->ReadjustAbsolute3DReferences( rCell.pDocument, &rDoc, rCell.aPos);
     809                 :            :         }
     810                 :            : 
     811         [ +  - ]:        298 :         pCode->AdjustAbsoluteRefs( rCell.pDocument, rCell.aPos, aPos, false, bCopyBetweenDocs );
     812                 :            :     }
     813                 :            : 
     814         [ -  + ]:        334 :     if ( nCloneFlags & SC_CLONECELL_ADJUST3DREL )
     815         [ #  # ]:          0 :         pCode->ReadjustRelative3DReferences( rCell.aPos, aPos );
     816                 :            : 
     817         [ +  + ]:        334 :     if( !bCompile )
     818                 :            :     {   // Name references with references and ColRowNames
     819                 :        328 :         pCode->Reset();
     820                 :            :         ScToken* t;
     821 [ +  - ][ +  + ]:        851 :         while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceOrName()) ) != NULL && !bCompile )
         [ +  + ][ +  + ]
     822                 :            :         {
     823 [ +  - ][ +  + ]:        523 :             if ( t->IsExternalRef() )
     824                 :            :             {
     825                 :            :                 // External name, cell, and area references.
     826                 :          9 :                 bCompile = true;
     827                 :            :             }
     828         [ +  + ]:        514 :             else if ( t->GetType() == svIndex )
     829                 :            :             {
     830 [ +  - ][ +  - ]:         22 :                 ScRangeData* pRangeData = rDoc.GetRangeName()->findByIndex( t->GetIndex() );
                 [ +  - ]
     831         [ +  - ]:         22 :                 if( pRangeData )
     832                 :            :                 {
     833 [ +  - ][ +  - ]:         22 :                     if( pRangeData->HasReferences() )
     834                 :         22 :                         bCompile = true;
     835                 :            :                 }
     836                 :            :                 else
     837                 :          0 :                     bCompile = true;    // invalid reference!
     838                 :            :             }
     839         [ -  + ]:        492 :             else if ( t->GetOpCode() == ocColRowName )
     840                 :            :             {
     841                 :          0 :                 bCompile = true;        // new lookup needed
     842                 :          0 :                 bCompileLater = bClipMode;
     843                 :            :             }
     844                 :            :         }
     845                 :            :     }
     846         [ +  + ]:        334 :     if( bCompile )
     847                 :            :     {
     848 [ +  - ][ +  + ]:         37 :         if ( !bCompileLater && bClipMode )
     849                 :            :         {
     850                 :            :             // Merging ranges needs the actual positions after UpdateReference.
     851                 :            :             // ColRowNames need new lookup after positions are adjusted.
     852 [ +  - ][ +  - ]:         12 :             bCompileLater = pCode->HasOpCode( ocRange) || pCode->HasOpCode( ocColRowName);
         [ +  - ][ -  + ]
     853                 :            :         }
     854         [ +  - ]:         37 :         if ( !bCompileLater )
     855                 :            :         {
     856                 :            :             // bNoListening, not at all if in Clipboard/Undo,
     857                 :            :             // and not from Clipboard either, instead after Insert(Clone) and UpdateReference.
     858         [ +  - ]:         37 :             CompileTokenArray( true );
     859                 :            :         }
     860                 :            :     }
     861                 :            : 
     862         [ +  + ]:        334 :     if( nCloneFlags & SC_CLONECELL_STARTLISTENING )
     863         [ +  - ]:         55 :         StartListeningTo( &rDoc );
     864                 :            : 
     865         [ +  + ]:        334 :     if (bSubTotal)
     866         [ +  - ]:          8 :         pDocument->AddSubTotalCell(this);
     867                 :        334 : }
     868                 :            : 
     869 [ +  - ][ +  - ]:       3847 : ScFormulaCell::~ScFormulaCell()
     870                 :            : {
     871         [ +  - ]:       3847 :     pDocument->RemoveFromFormulaTree( this );
     872         [ +  - ]:       3847 :     pDocument->RemoveSubTotalCell(this);
     873 [ +  - ][ +  + ]:       3847 :     if (pCode->HasOpCode(ocMacro))
     874 [ +  - ][ +  - ]:          3 :         pDocument->GetMacroManager()->RemoveDependentCell(this);
     875                 :            : 
     876         [ +  + ]:       3847 :     if (pDocument->HasExternalRefManager())
     877 [ +  - ][ +  - ]:        229 :         pDocument->GetExternalRefManager()->removeRefCell(this);
     878                 :            : 
     879 [ +  - ][ +  - ]:       3847 :     delete pCode;
     880                 :            : #if OSL_DEBUG_LEVEL > 0
     881                 :            :     eCellType = CELLTYPE_DESTROYED;
     882                 :            : #endif
     883         [ -  + ]:       7688 : }
     884                 :            : 
     885                 :         98 : void ScFormulaCell::GetFormula( rtl::OUStringBuffer& rBuffer,
     886                 :            :                                 const FormulaGrammar::Grammar eGrammar ) const
     887                 :            : {
     888 [ -  + ][ #  # ]:         98 :     if( pCode->GetCodeError() && !pCode->GetLen() )
                 [ -  + ]
     889                 :            :     {
     890 [ #  # ][ #  # ]:          0 :         rBuffer = rtl::OUStringBuffer( ScGlobal::GetErrorString( pCode->GetCodeError()));
         [ #  # ][ #  # ]
                 [ #  # ]
     891                 :            :         return;
     892                 :            :     }
     893         [ -  + ]:         98 :     else if( cMatrixFlag == MM_REFERENCE )
     894                 :            :     {
     895                 :            :         // Reference to another cell that contains a matrix formula.
     896                 :          0 :         pCode->Reset();
     897         [ #  # ]:          0 :         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
     898         [ #  # ]:          0 :         if( p )
     899                 :            :         {
     900                 :            :             /* FIXME: original GetFormula() code obtained
     901                 :            :              * pCell only if (!this->IsInChangeTrack()),
     902                 :            :              * GetEnglishFormula() omitted that test.
     903                 :            :              * Can we live without in all cases? */
     904                 :            :             ScBaseCell* pCell;
     905         [ #  # ]:          0 :             ScSingleRefData& rRef = p->GetSingleRef();
     906         [ #  # ]:          0 :             rRef.CalcAbsIfRel( aPos );
     907         [ #  # ]:          0 :             if ( rRef.Valid() )
     908                 :            :                 pCell = pDocument->GetCell( ScAddress( rRef.nCol,
     909         [ #  # ]:          0 :                             rRef.nRow, rRef.nTab ) );
     910                 :            :             else
     911                 :          0 :                 pCell = NULL;
     912 [ #  # ][ #  # ]:          0 :             if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA)
                 [ #  # ]
     913                 :            :             {
     914 [ #  # ][ #  # ]:          0 :                 ((ScFormulaCell*)pCell)->GetFormula( rBuffer, eGrammar);
     915                 :            :                 return;
     916                 :            :             }
     917                 :            :             else
     918                 :            :             {
     919         [ #  # ]:          0 :                 ScCompiler aComp( pDocument, aPos, *pCode);
     920         [ #  # ]:          0 :                 aComp.SetGrammar(eGrammar);
     921 [ #  # ][ #  # ]:          0 :                 aComp.CreateStringFromTokenArray( rBuffer );
     922                 :            :             }
     923                 :            :         }
     924                 :            :         else
     925                 :            :         {
     926                 :            :             OSL_FAIL("ScFormulaCell::GetFormula: not a matrix");
     927                 :            :         }
     928                 :            :     }
     929                 :            :     else
     930                 :            :     {
     931         [ +  - ]:         98 :         ScCompiler aComp( pDocument, aPos, *pCode);
     932         [ +  - ]:         98 :         aComp.SetGrammar(eGrammar);
     933 [ +  - ][ +  - ]:         98 :         aComp.CreateStringFromTokenArray( rBuffer );
     934                 :            :     }
     935                 :            : 
     936                 :         98 :     sal_Unicode ch('=');
     937         [ +  - ]:         98 :     rBuffer.insert( 0, &ch, 1 );
     938         [ +  + ]:         98 :     if( cMatrixFlag )
     939                 :            :     {
     940                 :          2 :         sal_Unicode ch2('{');
     941         [ +  - ]:          2 :         rBuffer.insert( 0, &ch2, 1);
     942         [ +  - ]:         98 :         rBuffer.append( sal_Unicode('}'));
     943                 :            :     }
     944                 :            : }
     945                 :            : 
     946                 :         98 : void ScFormulaCell::GetFormula( rtl::OUString& rFormula, const FormulaGrammar::Grammar eGrammar ) const
     947                 :            : {
     948         [ +  - ]:         98 :     rtl::OUStringBuffer rBuffer( rFormula );
     949         [ +  - ]:         98 :     GetFormula( rBuffer, eGrammar );
     950         [ +  - ]:         98 :     rFormula = rBuffer.makeStringAndClear();
     951                 :         98 : }
     952                 :            : 
     953                 :          0 : void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows )
     954                 :            : {
     955                 :          0 :     MaybeInterpret();
     956                 :            : 
     957                 :          0 :     const ScMatrix* pMat = NULL;
     958         [ #  # ]:          0 :     if (!pCode->GetCodeError() && aResult.GetType() == svMatrixCell &&
           [ #  #  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     959 [ #  # ][ #  # ]:          0 :             ((pMat = static_cast<const ScToken*>(aResult.GetToken().get())->GetMatrix()) != 0))
                 [ #  # ]
     960                 :          0 :         pMat->GetDimensions( rCols, rRows );
     961                 :            :     else
     962                 :            :     {
     963                 :          0 :         rCols = 0;
     964                 :          0 :         rRows = 0;
     965                 :            :     }
     966                 :          0 : }
     967                 :            : 
     968                 :        519 : void ScFormulaCell::Compile( const rtl::OUString& rFormula, bool bNoListening,
     969                 :            :                             const FormulaGrammar::Grammar eGrammar )
     970                 :            : {
     971         [ +  - ]:        519 :     if ( pDocument->IsClipOrUndo() )
     972                 :        519 :         return;
     973         [ +  - ]:        519 :     bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
     974         [ -  + ]:        519 :     if ( bWasInFormulaTree )
     975         [ #  # ]:          0 :         pDocument->RemoveFromFormulaTree( this );
     976                 :            :     // pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
     977         [ -  + ]:        519 :     if ( pCode )
     978         [ #  # ]:          0 :         pCode->Clear();
     979                 :        519 :     ScTokenArray* pCodeOld = pCode;
     980         [ +  - ]:        519 :     ScCompiler aComp( pDocument, aPos);
     981         [ +  - ]:        519 :     aComp.SetGrammar(eGrammar);
     982 [ +  - ][ +  - ]:        519 :     pCode = aComp.CompileString( rFormula );
                 [ +  - ]
     983         [ -  + ]:        519 :     if ( pCodeOld )
     984 [ #  # ][ #  # ]:          0 :         delete pCodeOld;
     985         [ +  - ]:        519 :     if( !pCode->GetCodeError() )
     986                 :            :     {
     987 [ -  + ][ #  # ]:        519 :         if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() && rFormula == rtl::OUString(aResult.GetHybridFormula()) )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ -  + ]
           [ -  +  #  # ]
     988                 :            :         {   // nicht rekursiv CompileTokenArray/Compile/CompileTokenArray
     989         [ #  # ]:          0 :             if ( rFormula[0] == '=' )
     990 [ #  # ][ #  # ]:          0 :                 pCode->AddBad( rFormula.copy(1) );
                 [ #  # ]
     991                 :            :             else
     992 [ #  # ][ #  # ]:          0 :                 pCode->AddBad( rFormula );
                 [ #  # ]
     993                 :            :         }
     994                 :        519 :         bCompile = true;
     995         [ +  - ]:        519 :         CompileTokenArray( bNoListening );
     996                 :            :     }
     997                 :            :     else
     998                 :            :     {
     999                 :          0 :         bChanged = true;
    1000                 :          0 :         SetTextWidth( TEXTWIDTH_DIRTY );
    1001                 :          0 :         SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
    1002                 :            :     }
    1003         [ -  + ]:        519 :     if ( bWasInFormulaTree )
    1004 [ #  # ][ +  - ]:        519 :         pDocument->PutInFormulaTree( this );
    1005                 :            : }
    1006                 :            : 
    1007                 :            : 
    1008                 :        642 : void ScFormulaCell::CompileTokenArray( bool bNoListening )
    1009                 :            : {
    1010                 :            :     // Not already compiled?
    1011 [ -  + ][ #  # ]:        642 :     if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
                 [ -  + ]
    1012         [ #  # ]:          0 :         Compile( aResult.GetHybridFormula(), bNoListening, eTempGrammar);
    1013 [ +  + ][ +  + ]:        642 :     else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() )
         [ +  - ][ +  + ]
    1014                 :            :     {
    1015                 :            :         // RPN length may get changed
    1016         [ +  - ]:        563 :         bool bWasInFormulaTree = pDocument->IsInFormulaTree( this );
    1017         [ +  + ]:        563 :         if ( bWasInFormulaTree )
    1018         [ +  - ]:         10 :             pDocument->RemoveFromFormulaTree( this );
    1019                 :            : 
    1020                 :            :         // Loading from within filter? No listening yet!
    1021         [ +  + ]:        563 :         if( pDocument->IsInsertingFromOtherDoc() )
    1022                 :         15 :             bNoListening = true;
    1023                 :            : 
    1024 [ +  + ][ +  - ]:        563 :         if( !bNoListening && pCode->GetCodeLen() )
                 [ +  + ]
    1025         [ +  - ]:         13 :             EndListeningTo( pDocument );
    1026         [ +  - ]:        563 :         ScCompiler aComp(pDocument, aPos, *pCode);
    1027 [ +  - ][ +  - ]:        563 :         aComp.SetGrammar(pDocument->GetGrammar());
    1028         [ +  - ]:        563 :         bSubTotal = aComp.CompileTokenArray();
    1029         [ +  - ]:        563 :         if( !pCode->GetCodeError() )
    1030                 :            :         {
    1031                 :        563 :             nFormatType = aComp.GetNumFormatType();
    1032                 :        563 :             nFormatIndex = 0;
    1033                 :        563 :             bChanged = true;
    1034         [ +  - ]:        563 :             aResult.SetToken( NULL);
    1035                 :        563 :             bCompile = false;
    1036         [ +  + ]:        563 :             if ( !bNoListening )
    1037         [ +  - ]:         13 :                 StartListeningTo( pDocument );
    1038                 :            :         }
    1039         [ +  + ]:        563 :         if ( bWasInFormulaTree )
    1040         [ +  - ]:         10 :             pDocument->PutInFormulaTree( this );
    1041                 :            : 
    1042         [ -  + ]:        563 :         if (bSubTotal)
    1043 [ #  # ][ +  - ]:        563 :             pDocument->AddSubTotalCell(this);
    1044                 :            :     }
    1045                 :        642 : }
    1046                 :            : 
    1047                 :            : 
    1048                 :       1202 : void ScFormulaCell::CompileXML( ScProgress& rProgress )
    1049                 :            : {
    1050         [ +  + ]:       1202 :     if ( cMatrixFlag == MM_REFERENCE )
    1051                 :            :     {   // is already token code via ScDocFunc::EnterMatrix, ScDocument::InsertMatrixFormula
    1052                 :            :         // just establish listeners
    1053         [ +  - ]:        135 :         StartListeningTo( pDocument );
    1054                 :       1202 :         return ;
    1055                 :            :     }
    1056                 :            : 
    1057         [ +  - ]:       1067 :     ScCompiler aComp( pDocument, aPos, *pCode);
    1058         [ +  - ]:       1067 :     aComp.SetGrammar(eTempGrammar);
    1059                 :       1067 :     rtl::OUString aFormula, aFormulaNmsp;
    1060         [ +  - ]:       1067 :     aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp );
    1061                 :       1067 :     pDocument->DecXMLImportedFormulaCount( aFormula.getLength() );
    1062         [ +  - ]:       1067 :     rProgress.SetStateCountDownOnPercent( pDocument->GetXMLImportedFormulaCount() );
    1063                 :            :     // pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein
    1064         [ +  - ]:       1067 :     if ( pCode )
    1065         [ +  - ]:       1067 :         pCode->Clear();
    1066                 :       1067 :     ScTokenArray* pCodeOld = pCode;
    1067 [ +  - ][ +  - ]:       1067 :     pCode = aComp.CompileString( aFormula, aFormulaNmsp );
         [ +  - ][ +  - ]
                 [ +  - ]
    1068 [ +  - ][ +  - ]:       1067 :     delete pCodeOld;
    1069         [ +  - ]:       1067 :     if( !pCode->GetCodeError() )
    1070                 :            :     {
    1071         [ -  + ]:       1067 :         if ( !pCode->GetLen() )
    1072                 :            :         {
    1073         [ #  # ]:          0 :             if ( aFormula[0] == '=' )
    1074 [ #  # ][ #  # ]:          0 :                 pCode->AddBad( aFormula.copy( 1 ) );
                 [ #  # ]
    1075                 :            :             else
    1076 [ #  # ][ #  # ]:          0 :                 pCode->AddBad( aFormula );
                 [ #  # ]
    1077                 :            :         }
    1078         [ +  - ]:       1067 :         bSubTotal = aComp.CompileTokenArray();
    1079         [ +  - ]:       1067 :         if( !pCode->GetCodeError() )
    1080                 :            :         {
    1081                 :       1067 :             nFormatType = aComp.GetNumFormatType();
    1082                 :       1067 :             nFormatIndex = 0;
    1083                 :       1067 :             bChanged = true;
    1084                 :       1067 :             bCompile = false;
    1085         [ +  - ]:       1067 :             StartListeningTo( pDocument );
    1086                 :            :         }
    1087                 :            : 
    1088         [ -  + ]:       1067 :         if (bSubTotal)
    1089         [ #  # ]:          0 :             pDocument->AddSubTotalCell(this);
    1090                 :            :     }
    1091                 :            :     else
    1092                 :            :     {
    1093                 :          0 :         bChanged = true;
    1094                 :          0 :         SetTextWidth( TEXTWIDTH_DIRTY );
    1095                 :          0 :         SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
    1096                 :            :     }
    1097                 :            : 
    1098                 :            :     //  Same as in Load: after loading, it must be known if ocMacro is in any formula
    1099                 :            :     //  (for macro warning, CompileXML is called at the end of loading XML file)
    1100 [ +  - ][ +  - ]:       1067 :     if ( !pDocument->GetHasMacroFunc() && pCode->HasOpCodeRPN( ocMacro ) )
         [ -  + ][ -  + ]
    1101                 :          0 :         pDocument->SetHasMacroFunc( true );
    1102                 :            : 
    1103                 :            :     //volatile cells must be added here for import
    1104 [ +  + ][ +  -  :       3099 :     if( pCode->IsRecalcModeAlways() || pCode->IsRecalcModeForced() ||
             +  -  -  + ]
                 [ +  + ]
    1105                 :       2032 :         pCode->IsRecalcModeOnLoad() || pCode->IsRecalcModeOnLoadOnce() )
    1106 [ +  - ][ +  - ]:       1202 :         pDocument->PutInFormulaTree(this);
    1107                 :            : }
    1108                 :            : 
    1109                 :            : 
    1110                 :       1773 : void ScFormulaCell::CalcAfterLoad()
    1111                 :            : {
    1112                 :       1773 :     bool bNewCompiled = false;
    1113                 :            :     // Falls ein Calc 1.0-Doc eingelesen wird, haben wir ein Ergebnis,
    1114                 :            :     // aber kein TokenArray
    1115 [ -  + ][ #  # ]:       1773 :     if( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
                 [ -  + ]
    1116                 :            :     {
    1117         [ #  # ]:          0 :         Compile( aResult.GetHybridFormula(), true, eTempGrammar);
    1118                 :          0 :         aResult.SetToken( NULL);
    1119                 :          0 :         bDirty = true;
    1120                 :          0 :         bNewCompiled = true;
    1121                 :            :     }
    1122                 :            :     // Das UPN-Array wird nicht erzeugt, wenn ein Calc 3.0-Doc eingelesen
    1123                 :            :     // wurde, da die RangeNames erst jetzt existieren.
    1124 [ +  - ][ -  + ]:       1773 :     if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetCodeError() )
         [ #  # ][ -  + ]
    1125                 :            :     {
    1126         [ #  # ]:          0 :         ScCompiler aComp(pDocument, aPos, *pCode);
    1127 [ #  # ][ #  # ]:          0 :         aComp.SetGrammar(pDocument->GetGrammar());
    1128         [ #  # ]:          0 :         bSubTotal = aComp.CompileTokenArray();
    1129                 :          0 :         nFormatType = aComp.GetNumFormatType();
    1130                 :          0 :         nFormatIndex = 0;
    1131                 :          0 :         bDirty = true;
    1132                 :          0 :         bCompile = false;
    1133                 :          0 :         bNewCompiled = true;
    1134                 :            : 
    1135         [ #  # ]:          0 :         if (bSubTotal)
    1136 [ #  # ][ #  # ]:          0 :             pDocument->AddSubTotalCell(this);
    1137                 :            :     }
    1138                 :            :     // irgendwie koennen unter os/2 mit rotter FPU-Exception /0 ohne Err503
    1139                 :            :     // gespeichert werden, woraufhin spaeter im NumberFormatter die BLC Lib
    1140                 :            :     // bei einem fabs(-NAN) abstuerzt (#32739#)
    1141                 :            :     // hier fuer alle Systeme ausbuegeln, damit da auch Err503 steht
    1142 [ +  + ][ -  + ]:       1773 :     if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
                 [ -  + ]
    1143                 :            :     {
    1144                 :            :         OSL_FAIL("Formelzelle INFINITY !!! Woher kommt das Dokument?");
    1145                 :          0 :         aResult.SetResultError( errIllegalFPOperation );
    1146                 :          0 :         bDirty = true;
    1147                 :            :     }
    1148                 :            :     // DoubleRefs bei binaeren Operatoren waren vor v5.0 immer Matrix,
    1149                 :            :     // jetzt nur noch wenn in Matrixformel, sonst implizite Schnittmenge
    1150   [ -  +  #  #  :       1773 :     if ( pDocument->GetSrcVersion() < SC_MATRIX_DOUBLEREF &&
           #  # ][ -  + ]
    1151                 :          0 :             GetMatrixFlag() == MM_NONE && pCode->HasMatrixDoubleRefOps() )
    1152                 :            :     {
    1153                 :          0 :         cMatrixFlag = MM_FORMULA;
    1154                 :          0 :         SetMatColsRows( 1, 1);
    1155                 :            :     }
    1156                 :            :     // Muss die Zelle berechnet werden?
    1157                 :            :     // Nach Load koennen Zellen einen Fehlercode enthalten, auch dann
    1158                 :            :     // Listener starten und ggbf. neu berechnen wenn nicht RECALCMODE_NORMAL
    1159 [ -  + ][ #  # ]:       1773 :     if( !bNewCompiled || !pCode->GetCodeError() )
                 [ +  - ]
    1160                 :            :     {
    1161                 :       1773 :         StartListeningTo( pDocument );
    1162         [ -  + ]:       1773 :         if( !pCode->IsRecalcModeNormal() )
    1163                 :          0 :             bDirty = true;
    1164                 :            :     }
    1165         [ -  + ]:       1773 :     if ( pCode->IsRecalcModeAlways() )
    1166                 :            :     {   // zufall(), heute(), jetzt() bleiben immer im FormulaTree, damit sie
    1167                 :            :         // auch bei jedem F9 berechnet werden.
    1168                 :          0 :         bDirty = true;
    1169                 :            :     }
    1170                 :            :     // Noch kein SetDirty weil noch nicht alle Listener bekannt, erst in
    1171                 :            :     // SetDirtyAfterLoad.
    1172                 :       1773 : }
    1173                 :            : 
    1174                 :            : 
    1175                 :          0 : bool ScFormulaCell::MarkUsedExternalReferences()
    1176                 :            : {
    1177 [ #  # ][ #  # ]:          0 :     return pCode && pDocument->MarkUsedExternalReferences( *pCode);
    1178                 :            : }
    1179                 :            : 
    1180                 :            : 
    1181                 :       2702 : void ScFormulaCell::Interpret()
    1182                 :            : {
    1183 [ +  + ][ -  + ]:       2702 :     if (!IsDirtyOrInTableOpDirty() || pDocument->GetRecursionHelper().IsInReturn())
                 [ +  + ]
    1184                 :         34 :         return;     // no double/triple processing
    1185                 :            : 
    1186                 :            :     //! HACK:
    1187                 :            :     //  Wenn der Aufruf aus einem Reschedule im DdeLink-Update kommt, dirty stehenlassen
    1188                 :            :     //  Besser: Dde-Link Update ohne Reschedule oder ganz asynchron !!!
    1189                 :            : 
    1190         [ -  + ]:       2668 :     if ( pDocument->IsInDdeLinkUpdate() )
    1191                 :          0 :         return;
    1192                 :            : 
    1193         [ +  + ]:       2668 :     if (bRunning)
    1194                 :            :     {
    1195         [ +  - ]:          9 :         if (!pDocument->GetDocOptions().IsIter())
    1196                 :            :         {
    1197                 :          9 :             aResult.SetResultError( errCircularReference );
    1198                 :          9 :             return;
    1199                 :            :         }
    1200                 :            : 
    1201         [ #  # ]:          0 :         if (aResult.GetResultError() == errCircularReference)
    1202                 :          0 :             aResult.SetResultError( 0 );
    1203                 :            : 
    1204                 :            :         // Start or add to iteration list.
    1205   [ #  #  #  # ]:          0 :         if (!pDocument->GetRecursionHelper().IsDoingIteration() ||
                 [ #  # ]
    1206                 :          0 :                 !pDocument->GetRecursionHelper().GetRecursionInIterationStack().top()->bIsIterCell)
    1207                 :          0 :             pDocument->GetRecursionHelper().SetInIterationReturn( true);
    1208                 :            : 
    1209                 :          0 :         return;
    1210                 :            :     }
    1211                 :            :     // no multiple interprets for GetErrCode, IsValue, GetValue and
    1212                 :            :     // different entry point recursions. Would also lead to premature
    1213                 :            :     // convergence in iterations.
    1214   [ -  +  #  # ]:       2659 :     if (pDocument->GetRecursionHelper().GetIteration() && nSeenInIteration ==
                 [ -  + ]
    1215                 :          0 :             pDocument->GetRecursionHelper().GetIteration())
    1216                 :          0 :         return ;
    1217                 :            : 
    1218                 :       2659 :     ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper();
    1219                 :       2659 :     bool bOldRunning = bRunning;
    1220         [ -  + ]:       2659 :     if (rRecursionHelper.GetRecursionCount() > MAXRECURSION)
    1221                 :            :     {
    1222                 :          0 :         bRunning = true;
    1223                 :          0 :         rRecursionHelper.SetInRecursionReturn( true);
    1224                 :            :     }
    1225                 :            :     else
    1226                 :            :     {
    1227                 :       2659 :         InterpretTail( SCITP_NORMAL);
    1228                 :            :     }
    1229                 :            : 
    1230                 :            :     // While leaving a recursion or iteration stack, insert its cells to the
    1231                 :            :     // recursion list in reverse order.
    1232         [ -  + ]:       2659 :     if (rRecursionHelper.IsInReturn())
    1233                 :            :     {
    1234   [ #  #  #  # ]:          0 :         if (rRecursionHelper.GetRecursionCount() > 0 ||
                 [ #  # ]
    1235                 :          0 :                 !rRecursionHelper.IsDoingRecursion())
    1236                 :          0 :             rRecursionHelper.Insert( this, bOldRunning, aResult);
    1237                 :          0 :         bool bIterationFromRecursion = false;
    1238                 :          0 :         bool bResumeIteration = false;
    1239 [ #  # ][ #  # ]:       2702 :         do
                 [ #  # ]
    1240                 :            :         {
    1241   [ #  #  #  #  :          0 :             if ((rRecursionHelper.IsInIterationReturn() &&
           #  # ][ #  # ]
         [ #  # ][ #  # ]
    1242                 :          0 :                         rRecursionHelper.GetRecursionCount() == 0 &&
    1243                 :          0 :                         !rRecursionHelper.IsDoingIteration()) ||
    1244                 :            :                     bIterationFromRecursion || bResumeIteration)
    1245                 :            :             {
    1246                 :          0 :                 ScFormulaCell* pIterCell = this; // scope for debug convenience
    1247                 :          0 :                 bool & rDone = rRecursionHelper.GetConvergingReference();
    1248                 :          0 :                 rDone = false;
    1249 [ #  # ][ #  # ]:          0 :                 if (!bIterationFromRecursion && bResumeIteration)
    1250                 :            :                 {
    1251                 :          0 :                     bResumeIteration = false;
    1252                 :            :                     // Resuming iteration expands the range.
    1253                 :            :                     ScFormulaRecursionList::const_iterator aOldStart(
    1254                 :          0 :                             rRecursionHelper.GetLastIterationStart());
    1255         [ #  # ]:          0 :                     rRecursionHelper.ResumeIteration();
    1256                 :            :                     // Mark new cells being in iteration.
    1257         [ #  # ]:          0 :                     for (ScFormulaRecursionList::const_iterator aIter(
    1258         [ #  # ]:          0 :                                 rRecursionHelper.GetIterationStart()); aIter !=
    1259                 :            :                             aOldStart; ++aIter)
    1260                 :            :                     {
    1261                 :          0 :                         pIterCell = (*aIter).pCell;
    1262                 :          0 :                         pIterCell->bIsIterCell = true;
    1263                 :            :                     }
    1264                 :            :                     // Mark older cells dirty again, in case they converted
    1265                 :            :                     // without accounting for all remaining cells in the circle
    1266                 :            :                     // that weren't touched so far, e.g. conditional. Restore
    1267                 :            :                     // backuped result.
    1268                 :          0 :                     sal_uInt16 nIteration = rRecursionHelper.GetIteration();
    1269         [ #  # ]:          0 :                     for (ScFormulaRecursionList::const_iterator aIter(
    1270                 :          0 :                                 aOldStart); aIter !=
    1271         [ #  # ]:          0 :                             rRecursionHelper.GetIterationEnd(); ++aIter)
    1272                 :            :                     {
    1273                 :          0 :                         pIterCell = (*aIter).pCell;
    1274         [ #  # ]:          0 :                         if (pIterCell->nSeenInIteration == nIteration)
    1275                 :            :                         {
    1276 [ #  # ][ #  # ]:          0 :                             if (!pIterCell->bDirty || aIter == aOldStart)
                 [ #  # ]
    1277                 :            :                             {
    1278         [ #  # ]:          0 :                                 pIterCell->aResult = (*aIter).aPreviousResult;
    1279                 :            :                             }
    1280                 :          0 :                             --pIterCell->nSeenInIteration;
    1281                 :            :                         }
    1282                 :          0 :                         pIterCell->bDirty = true;
    1283                 :          0 :                     }
    1284                 :            :                 }
    1285                 :            :                 else
    1286                 :            :                 {
    1287                 :          0 :                     bResumeIteration = false;
    1288                 :            :                     // Close circle once.
    1289                 :          0 :                     rRecursionHelper.GetList().back().pCell->InterpretTail(
    1290                 :          0 :                             SCITP_CLOSE_ITERATION_CIRCLE);
    1291                 :            :                     // Start at 1, init things.
    1292                 :          0 :                     rRecursionHelper.StartIteration();
    1293                 :            :                     // Mark all cells being in iteration.
    1294         [ #  # ]:          0 :                     for (ScFormulaRecursionList::const_iterator aIter(
    1295         [ #  # ]:          0 :                                 rRecursionHelper.GetIterationStart()); aIter !=
    1296         [ #  # ]:          0 :                             rRecursionHelper.GetIterationEnd(); ++aIter)
    1297                 :            :                     {
    1298                 :          0 :                         pIterCell = (*aIter).pCell;
    1299                 :          0 :                         pIterCell->bIsIterCell = true;
    1300                 :            :                     }
    1301                 :            :                 }
    1302                 :          0 :                 bIterationFromRecursion = false;
    1303                 :          0 :                 sal_uInt16 nIterMax = pDocument->GetDocOptions().GetIterCount();
    1304 [ #  # ][ #  # ]:          0 :                 for ( ; rRecursionHelper.GetIteration() <= nIterMax && !rDone;
                 [ #  # ]
    1305                 :          0 :                         rRecursionHelper.IncIteration())
    1306                 :            :                 {
    1307                 :          0 :                     rDone = true;
    1308   [ #  #  #  # ]:          0 :                     for ( ScFormulaRecursionList::iterator aIter(
                 [ #  # ]
    1309         [ #  # ]:          0 :                                 rRecursionHelper.GetIterationStart()); aIter !=
    1310 [ #  # ][ #  # ]:          0 :                             rRecursionHelper.GetIterationEnd() &&
                 [ #  # ]
    1311                 :          0 :                             !rRecursionHelper.IsInReturn(); ++aIter)
    1312                 :            :                     {
    1313                 :          0 :                         pIterCell = (*aIter).pCell;
    1314   [ #  #  #  # ]:          0 :                         if (pIterCell->IsDirtyOrInTableOpDirty() &&
         [ #  # ][ #  # ]
    1315                 :          0 :                                 rRecursionHelper.GetIteration() !=
    1316                 :          0 :                                 pIterCell->GetSeenInIteration())
    1317                 :            :                         {
    1318         [ #  # ]:          0 :                             (*aIter).aPreviousResult = pIterCell->aResult;
    1319         [ #  # ]:          0 :                             pIterCell->InterpretTail( SCITP_FROM_ITERATION);
    1320                 :            :                         }
    1321 [ #  # ][ #  # ]:          0 :                         rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty();
                 [ #  # ]
    1322                 :            :                     }
    1323         [ #  # ]:          0 :                     if (rRecursionHelper.IsInReturn())
    1324                 :            :                     {
    1325                 :          0 :                         bResumeIteration = true;
    1326                 :          0 :                         break;  // for
    1327                 :            :                         // Don't increment iteration.
    1328                 :            :                     }
    1329                 :            :                 }
    1330         [ #  # ]:          0 :                 if (!bResumeIteration)
    1331                 :            :                 {
    1332         [ #  # ]:          0 :                     if (rDone)
    1333                 :            :                     {
    1334         [ #  # ]:          0 :                         for (ScFormulaRecursionList::const_iterator aIter(
    1335         [ #  # ]:          0 :                                     rRecursionHelper.GetIterationStart());
    1336         [ #  # ]:          0 :                                 aIter != rRecursionHelper.GetIterationEnd();
    1337                 :            :                                 ++aIter)
    1338                 :            :                         {
    1339                 :          0 :                             pIterCell = (*aIter).pCell;
    1340                 :          0 :                             pIterCell->bIsIterCell = false;
    1341                 :          0 :                             pIterCell->nSeenInIteration = 0;
    1342                 :          0 :                             pIterCell->bRunning = (*aIter).bOldRunning;
    1343                 :            :                         }
    1344                 :            :                     }
    1345                 :            :                     else
    1346                 :            :                     {
    1347         [ #  # ]:          0 :                         for (ScFormulaRecursionList::const_iterator aIter(
    1348         [ #  # ]:          0 :                                     rRecursionHelper.GetIterationStart());
    1349         [ #  # ]:          0 :                                 aIter != rRecursionHelper.GetIterationEnd();
    1350                 :            :                                 ++aIter)
    1351                 :            :                         {
    1352                 :          0 :                             pIterCell = (*aIter).pCell;
    1353                 :          0 :                             pIterCell->bIsIterCell = false;
    1354                 :          0 :                             pIterCell->nSeenInIteration = 0;
    1355                 :          0 :                             pIterCell->bRunning = (*aIter).bOldRunning;
    1356                 :            :                             // If one cell didn't converge, all cells of this
    1357                 :            :                             // circular dependency don't, no matter whether
    1358                 :            :                             // single cells did.
    1359                 :          0 :                             pIterCell->bDirty = false;
    1360                 :          0 :                             pIterCell->bTableOpDirty = false;
    1361         [ #  # ]:          0 :                             pIterCell->aResult.SetResultError( errNoConvergence);
    1362                 :          0 :                             pIterCell->bChanged = true;
    1363                 :          0 :                             pIterCell->SetTextWidth( TEXTWIDTH_DIRTY);
    1364                 :          0 :                             pIterCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN);
    1365                 :            :                         }
    1366                 :            :                     }
    1367                 :            :                     // End this iteration and remove entries.
    1368                 :          0 :                     rRecursionHelper.EndIteration();
    1369                 :          0 :                     bResumeIteration = rRecursionHelper.IsDoingIteration();
    1370                 :            :                 }
    1371                 :            :             }
    1372   [ #  #  #  #  :          0 :             if (rRecursionHelper.IsInRecursionReturn() &&
           #  # ][ #  # ]
    1373                 :          0 :                     rRecursionHelper.GetRecursionCount() == 0 &&
    1374                 :          0 :                     !rRecursionHelper.IsDoingRecursion())
    1375                 :            :             {
    1376                 :          0 :                 bIterationFromRecursion = false;
    1377                 :            :                 // Iterate over cells known so far, start with the last cell
    1378                 :            :                 // encountered, inserting new cells if another recursion limit
    1379                 :            :                 // is reached. Repeat until solved.
    1380                 :          0 :                 rRecursionHelper.SetDoingRecursion( true);
    1381         [ #  # ]:          0 :                 do
    1382                 :            :                 {
    1383                 :          0 :                     rRecursionHelper.SetInRecursionReturn( false);
    1384   [ #  #  #  # ]:          0 :                     for (ScFormulaRecursionList::const_iterator aIter(
                 [ #  # ]
    1385         [ #  # ]:          0 :                                 rRecursionHelper.GetIterationStart());
    1386                 :          0 :                             !rRecursionHelper.IsInReturn() && aIter !=
    1387 [ #  # ][ #  # ]:          0 :                             rRecursionHelper.GetIterationEnd(); ++aIter)
                 [ #  # ]
           [ #  #  #  # ]
    1388                 :            :                     {
    1389                 :          0 :                         ScFormulaCell* pCell = (*aIter).pCell;
    1390 [ #  # ][ #  # ]:          0 :                         if (pCell->IsDirtyOrInTableOpDirty())
    1391                 :            :                         {
    1392         [ #  # ]:          0 :                             pCell->InterpretTail( SCITP_NORMAL);
    1393 [ #  # ][ #  # ]:          0 :                             if (!pCell->IsDirtyOrInTableOpDirty() && !pCell->IsIterCell())
         [ #  # ][ #  # ]
    1394                 :          0 :                                 pCell->bRunning = (*aIter).bOldRunning;
    1395                 :            :                         }
    1396                 :            :                     }
    1397                 :            :                 } while (rRecursionHelper.IsInRecursionReturn());
    1398                 :          0 :                 rRecursionHelper.SetDoingRecursion( false);
    1399         [ #  # ]:          0 :                 if (rRecursionHelper.IsInIterationReturn())
    1400                 :            :                 {
    1401         [ #  # ]:          0 :                     if (!bResumeIteration)
    1402                 :          0 :                         bIterationFromRecursion = true;
    1403                 :            :                 }
    1404   [ #  #  #  # ]:          0 :                 else if (bResumeIteration ||
                 [ #  # ]
    1405                 :          0 :                         rRecursionHelper.IsDoingIteration())
    1406                 :          0 :                     rRecursionHelper.GetList().erase(
    1407                 :            :                             rRecursionHelper.GetIterationStart(),
    1408                 :          0 :                             rRecursionHelper.GetLastIterationStart());
    1409                 :            :                 else
    1410                 :          0 :                     rRecursionHelper.Clear();
    1411                 :            :             }
    1412                 :            :         } while (bIterationFromRecursion || bResumeIteration);
    1413                 :            :     }
    1414                 :            : }
    1415                 :            : 
    1416                 :       2659 : void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
    1417                 :            : {
    1418                 :            :     class RecursionCounter
    1419                 :            :     {
    1420                 :            :         ScRecursionHelper&  rRec;
    1421                 :            :         bool                bStackedInIteration;
    1422                 :            :         public:
    1423                 :       2659 :         RecursionCounter( ScRecursionHelper& r, ScFormulaCell* p ) : rRec(r)
    1424                 :            :         {
    1425                 :       2659 :             bStackedInIteration = rRec.IsDoingIteration();
    1426         [ -  + ]:       2659 :             if (bStackedInIteration)
    1427                 :          0 :                 rRec.GetRecursionInIterationStack().push( p);
    1428                 :       2659 :             rRec.IncRecursionCount();
    1429                 :       2659 :         }
    1430                 :       2659 :         ~RecursionCounter()
    1431                 :            :         {
    1432                 :       2659 :             rRec.DecRecursionCount();
    1433         [ -  + ]:       2659 :             if (bStackedInIteration)
    1434                 :          0 :                 rRec.GetRecursionInIterationStack().pop();
    1435                 :       2659 :         }
    1436 [ +  - ][ +  - ]:       2659 :     } aRecursionCounter( pDocument->GetRecursionHelper(), this);
    1437         [ +  - ]:       2659 :     nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
    1438 [ -  + ][ -  + ]:       2659 :     if( !pCode->GetCodeLen() && !pCode->GetCodeError() )
                 [ +  + ]
    1439                 :            :     {
    1440                 :            :         // #i11719# no UPN and no error and no token code but result string present
    1441                 :            :         // => interpretation of this cell during name-compilation and unknown names
    1442                 :            :         // => can't exchange underlying code array in CompileTokenArray() /
    1443                 :            :         // Compile() because interpreter's token iterator would crash or pCode
    1444                 :            :         // would be deleted twice if this cell was interpreted during
    1445                 :            :         // compilation.
    1446                 :            :         // This should only be a temporary condition and, since we set an
    1447                 :            :         // error, if ran into it again we'd bump into the dirty-clearing
    1448                 :            :         // condition further down.
    1449 [ #  # ][ #  # ]:          0 :         if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
         [ #  # ][ #  # ]
    1450                 :            :         {
    1451                 :          0 :             pCode->SetCodeError( errNoCode );
    1452                 :            :             // This is worth an assertion; if encountered in daily work
    1453                 :            :             // documents we might need another solution. Or just confirm correctness.
    1454                 :            :             OSL_FAIL( "ScFormulaCell::Interpret: no UPN, no error, no token, but hybrid formula string" );
    1455                 :            :             return;
    1456                 :            :         }
    1457         [ #  # ]:          0 :         CompileTokenArray();
    1458                 :            :     }
    1459                 :            : 
    1460 [ +  + ][ +  - ]:       2659 :     if( pCode->GetCodeLen() && pDocument )
                 [ +  + ]
    1461                 :            :     {
    1462                 :            :         class StackCleaner
    1463                 :            :         {
    1464                 :            :             ScDocument*     pDoc;
    1465                 :            :             ScInterpreter*  pInt;
    1466                 :            :             public:
    1467                 :       2619 :             StackCleaner( ScDocument* pD, ScInterpreter* pI )
    1468                 :       2619 :                 : pDoc(pD), pInt(pI)
    1469                 :       2619 :                 {}
    1470                 :       2619 :             ~StackCleaner()
    1471                 :            :             {
    1472         [ +  - ]:       2619 :                 delete pInt;
    1473                 :       2619 :                 pDoc->DecInterpretLevel();
    1474                 :       2619 :             }
    1475                 :            :         };
    1476                 :       2619 :         pDocument->IncInterpretLevel();
    1477 [ +  - ][ +  - ]:       2619 :         ScInterpreter* p = new ScInterpreter( this, pDocument, aPos, *pCode );
    1478                 :       2619 :         StackCleaner aStackCleaner( pDocument, p);
    1479         [ +  - ]:       2619 :         sal_uInt16 nOldErrCode = aResult.GetResultError();
    1480         [ +  - ]:       2619 :         if ( nSeenInIteration == 0 )
    1481                 :            :         {   // Only the first time
    1482                 :            :             // With bChanged=false, if a newly compiled cell has a result of
    1483                 :            :             // 0.0, no change is detected and the cell will not be repainted.
    1484                 :            :             // bChanged = false;
    1485         [ +  - ]:       2619 :             aResult.SetResultError( 0 );
    1486                 :            :         }
    1487                 :            : 
    1488 [ +  - ][ -  + ]:       2619 :         switch ( aResult.GetResultError() )
    1489                 :            :         {
    1490                 :            :             case errCircularReference :     // will be determined again if so
    1491         [ #  # ]:          0 :                 aResult.SetResultError( 0 );
    1492                 :          0 :             break;
    1493                 :            :         }
    1494                 :            : 
    1495                 :       2619 :         bool bOldRunning = bRunning;
    1496                 :       2619 :         bRunning = true;
    1497         [ +  - ]:       2619 :         p->Interpret();
    1498 [ +  - ][ -  + ]:       2619 :         if (pDocument->GetRecursionHelper().IsInReturn() && eTailParam != SCITP_CLOSE_ITERATION_CIRCLE)
         [ #  # ][ -  + ]
    1499                 :            :         {
    1500         [ #  # ]:          0 :             if (nSeenInIteration > 0)
    1501                 :          0 :                 --nSeenInIteration;     // retry when iteration is resumed
    1502                 :            :             return;
    1503                 :            :         }
    1504                 :       2619 :         bRunning = bOldRunning;
    1505                 :            : 
    1506                 :            :         // #i102616# For single-sheet saving consider only content changes, not format type,
    1507                 :            :         // because format type isn't set on loading (might be changed later)
    1508                 :       2619 :         bool bContentChanged = false;
    1509                 :            : 
    1510                 :            :         // Do not create a HyperLink() cell if the formula results in an error.
    1511 [ +  + ][ -  + ]:       2619 :         if( p->GetError() && pCode->IsHyperLink())
                 [ -  + ]
    1512                 :          0 :             pCode->SetHyperLink(false);
    1513                 :            : 
    1514 [ +  + ][ +  + ]:       2619 :         if( p->GetError() && p->GetError() != errCircularReference)
                 [ +  + ]
    1515                 :            :         {
    1516                 :        309 :             bDirty = false;
    1517                 :        309 :             bTableOpDirty = false;
    1518                 :        309 :             bChanged = true;
    1519                 :            :         }
    1520 [ -  + ][ #  # ]:       2619 :         if (eTailParam == SCITP_FROM_ITERATION && IsDirtyOrInTableOpDirty())
         [ #  # ][ -  + ]
    1521                 :            :         {
    1522         [ #  # ]:          0 :             bool bIsValue = aResult.IsValue();  // the previous type
    1523                 :            :             // Did it converge?
    1524 [ #  # ][ #  # ]:          0 :             if ((bIsValue && p->GetResultType() == svDouble && fabs(
           [ #  #  #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1525 [ #  # ][ #  # ]:          0 :                             p->GetNumResult() - aResult.GetDouble()) <=
    1526         [ #  # ]:          0 :                         pDocument->GetDocOptions().GetIterEps()) ||
    1527         [ #  # ]:          0 :                     (!bIsValue && p->GetResultType() == svString &&
    1528 [ #  # ][ #  # ]:          0 :                      p->GetStringResult() == aResult.GetString()))
                 [ #  # ]
    1529                 :            :             {
    1530                 :            :                 // A convergence in the first iteration doesn't necessarily
    1531                 :            :                 // mean that it's done, it may be because not all related cells
    1532                 :            :                 // of a circle changed their values yet. If the set really
    1533                 :            :                 // converges it will do so also during the next iteration. This
    1534                 :            :                 // fixes situations like of #i44115#. If this wasn't wanted an
    1535                 :            :                 // initial "uncalculated" value would be needed for all cells
    1536                 :            :                 // of a circular dependency => graph needed before calculation.
    1537   [ #  #  #  # ]:          0 :                 if (nSeenInIteration > 1 ||
                 [ #  # ]
    1538         [ #  # ]:          0 :                         pDocument->GetDocOptions().GetIterCount() == 1)
    1539                 :            :                 {
    1540                 :          0 :                     bDirty = false;
    1541                 :          0 :                     bTableOpDirty = false;
    1542                 :            :                 }
    1543                 :            :             }
    1544                 :            :         }
    1545                 :            : 
    1546                 :            :         // New error code?
    1547         [ +  + ]:       2619 :         if( p->GetError() != nOldErrCode )
    1548                 :            :         {
    1549                 :        173 :             bChanged = true;
    1550                 :            :             // bContentChanged only has to be set if the file content would be changed
    1551 [ +  - ][ +  + ]:        173 :             if ( aResult.GetCellResultType() != svUnknown )
    1552                 :        138 :                 bContentChanged = true;
    1553                 :            :         }
    1554                 :            :         // Different number format?
    1555         [ +  + ]:       2619 :         if( nFormatType != p->GetRetFormatType() )
    1556                 :            :         {
    1557                 :        187 :             nFormatType = p->GetRetFormatType();
    1558                 :        187 :             bChanged = true;
    1559                 :            :         }
    1560         [ -  + ]:       2619 :         if( nFormatIndex != p->GetRetFormatIndex() )
    1561                 :            :         {
    1562                 :          0 :             nFormatIndex = p->GetRetFormatIndex();
    1563                 :          0 :             bChanged = true;
    1564                 :            :         }
    1565                 :            : 
    1566                 :            :         // In case of changes just obtain the result, no temporary and
    1567                 :            :         // comparison needed anymore.
    1568         [ +  + ]:       2619 :         if (bChanged)
    1569                 :            :         {
    1570                 :            :             // #i102616# Compare anyway if the sheet is still marked unchanged for single-sheet saving
    1571                 :            :             // Also handle special cases of initial results after loading.
    1572                 :            : 
    1573 [ +  + ][ +  - ]:       2149 :             if ( !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
         [ +  + ][ +  + ]
    1574                 :            :             {
    1575 [ +  - ][ +  - ]:        216 :                 ScFormulaResult aNewResult( p->GetResultToken().get());
                 [ +  - ]
    1576         [ +  - ]:        216 :                 StackVar eOld = aResult.GetCellResultType();
    1577         [ +  - ]:        216 :                 StackVar eNew = aNewResult.GetCellResultType();
    1578 [ -  + ][ #  # ]:        216 :                 if ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) )
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
    1579                 :            :                 {
    1580                 :            :                     // ScXMLTableRowCellContext::EndElement doesn't call SetFormulaResultDouble for 0
    1581                 :            :                     // -> no change
    1582                 :            :                 }
    1583                 :            :                 else
    1584                 :            :                 {
    1585         [ +  + ]:        216 :                     if ( eOld == svHybridCell )     // string result from SetFormulaResultString?
    1586                 :         18 :                         eOld = svString;            // ScHybridCellToken has a valid GetString method
    1587                 :            : 
    1588                 :            :                     // #i106045# use approxEqual to compare with stored value
    1589                 :            :                     bContentChanged = (eOld != eNew ||
    1590 [ +  - ][ +  - ]:        180 :                             (eNew == svDouble && !rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() )) ||
    1591         [ +  - ]:        396 :                             (eNew == svString && aResult.GetString() != aNewResult.GetString()));
           [ +  +  +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    1592         [ +  - ]:        216 :                 }
    1593                 :            :             }
    1594                 :            : 
    1595 [ +  - ][ +  - ]:       2149 :             aResult.SetToken( p->GetResultToken().get() );
                 [ +  - ]
    1596                 :            :         }
    1597                 :            :         else
    1598                 :            :         {
    1599 [ +  - ][ +  - ]:        470 :             ScFormulaResult aNewResult( p->GetResultToken().get());
                 [ +  - ]
    1600         [ +  - ]:        470 :             StackVar eOld = aResult.GetCellResultType();
    1601         [ +  - ]:        470 :             StackVar eNew = aNewResult.GetCellResultType();
    1602                 :            :             bChanged = (eOld != eNew ||
    1603 [ +  - ][ +  - ]:        314 :                     (eNew == svDouble && aResult.GetDouble() != aNewResult.GetDouble()) ||
    1604 [ +  + ][ +  + ]:        784 :                     (eNew == svString && aResult.GetString() != aNewResult.GetString()));
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
    1605                 :            : 
    1606                 :            :             // #i102616# handle special cases of initial results after loading (only if the sheet is still marked unchanged)
    1607 [ +  + ][ +  - ]:        470 :             if ( bChanged && !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) )
         [ +  - ][ -  + ]
                 [ -  + ]
    1608                 :            :             {
    1609 [ #  # ][ #  # ]:          0 :                 if ( ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) ) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
    1610 [ #  # ][ #  # ]:          0 :                      ( eOld == svHybridCell && eNew == svString && aResult.GetString() == aNewResult.GetString() ) ||
                 [ #  # ]
    1611 [ #  # ][ #  # ]:          0 :                      ( eOld == svDouble && eNew == svDouble && rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() ) ) )
    1612                 :            :                 {
    1613                 :            :                     // no change, see above
    1614                 :            :                 }
    1615                 :            :                 else
    1616                 :          0 :                     bContentChanged = true;
    1617                 :            :             }
    1618                 :            : 
    1619 [ +  - ][ +  - ]:        470 :             aResult.Assign( aNewResult);
    1620                 :            :         }
    1621                 :            : 
    1622                 :            :         // Precision as shown?
    1623 [ +  - ][ +  + ]:       4707 :         if ( aResult.IsValue() && !p->GetError()
           [ +  +  +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
    1624         [ +  - ]:       2088 :           && pDocument->GetDocOptions().IsCalcAsShown()
    1625                 :            :           && nFormatType != NUMBERFORMAT_DATE
    1626                 :            :           && nFormatType != NUMBERFORMAT_TIME
    1627                 :            :           && nFormatType != NUMBERFORMAT_DATETIME )
    1628                 :            :         {
    1629         [ +  - ]:         14 :             sal_uLong nFormat = pDocument->GetNumberFormat( aPos );
    1630 [ -  + ][ #  # ]:         14 :             if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
    1631                 :          0 :                 nFormat = nFormatIndex;
    1632         [ +  - ]:         14 :             if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
    1633                 :            :                 nFormat = ScGlobal::GetStandardFormat(
    1634 [ +  - ][ +  - ]:         14 :                     *pDocument->GetFormatTable(), nFormat, nFormatType );
    1635                 :            :             aResult.SetDouble( pDocument->RoundValueAsShown(
    1636 [ +  - ][ +  - ]:         14 :                         aResult.GetDouble(), nFormat));
                 [ +  - ]
    1637                 :            :         }
    1638         [ +  - ]:       2619 :         if (eTailParam == SCITP_NORMAL)
    1639                 :            :         {
    1640                 :       2619 :             bDirty = false;
    1641                 :       2619 :             bTableOpDirty = false;
    1642                 :            :         }
    1643 [ +  - ][ +  - ]:       2619 :         if( aResult.GetMatrix() )
                 [ +  + ]
    1644                 :            :         {
    1645                 :            :             // If the formula wasn't entered as a matrix formula, live on with
    1646                 :            :             // the upper left corner and let reference counting delete the matrix.
    1647 [ +  + ][ +  - ]:         81 :             if( cMatrixFlag != MM_FORMULA && !pCode->IsHyperLink() )
                 [ +  + ]
    1648 [ +  - ][ +  - ]:         23 :                 aResult.SetToken( aResult.GetCellResultToken().get());
                 [ +  - ]
    1649                 :            :         }
    1650 [ +  - ][ +  + ]:       2619 :         if ( aResult.IsValue() && !::rtl::math::isFinite( aResult.GetDouble() ) )
         [ +  - ][ -  + ]
                 [ -  + ]
    1651                 :            :         {
    1652                 :            :             // Coded double error may occur via filter import.
    1653         [ #  # ]:          0 :             sal_uInt16 nErr = GetDoubleErrorValue( aResult.GetDouble());
    1654         [ #  # ]:          0 :             aResult.SetResultError( nErr);
    1655                 :          0 :             bChanged = bContentChanged = true;
    1656                 :            :         }
    1657         [ +  + ]:       2619 :         if( bChanged )
    1658                 :            :         {
    1659                 :       2325 :             SetTextWidth( TEXTWIDTH_DIRTY );
    1660                 :       2325 :             SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
    1661                 :            :         }
    1662 [ +  + ][ +  - ]:       2619 :         if (bContentChanged && pDocument->IsStreamValid(aPos.Tab()))
         [ +  + ][ +  + ]
    1663                 :            :         {
    1664                 :            :             // pass bIgnoreLock=true, because even if called from pending row height update,
    1665                 :            :             // a changed result must still reset the stream flag
    1666         [ +  - ]:         12 :             pDocument->SetStreamValid(aPos.Tab(), false, true);
    1667                 :            :         }
    1668         [ +  + ]:       2619 :         if ( !pCode->IsRecalcModeAlways() )
    1669         [ +  - ]:       2487 :             pDocument->RemoveFromFormulaTree( this );
    1670                 :            : 
    1671                 :            :         //  FORCED Zellen auch sofort auf Gueltigkeit testen (evtl. Makro starten)
    1672                 :            : 
    1673         [ -  + ]:       2619 :         if ( pCode->IsRecalcModeForced() )
    1674                 :            :         {
    1675                 :            :             sal_uLong nValidation = ((const SfxUInt32Item*) pDocument->GetAttr(
    1676         [ #  # ]:          0 :                     aPos.Col(), aPos.Row(), aPos.Tab(), ATTR_VALIDDATA ))->GetValue();
    1677         [ #  # ]:          0 :             if ( nValidation )
    1678                 :            :             {
    1679         [ #  # ]:          0 :                 const ScValidationData* pData = pDocument->GetValidationEntry( nValidation );
    1680 [ #  # ][ #  # ]:          0 :                 if ( pData && !pData->IsDataValid( this, aPos ) )
         [ #  # ][ #  # ]
    1681         [ #  # ]:          0 :                     pData->DoCalcError( this );
    1682                 :            :             }
    1683                 :            :         }
    1684                 :            : 
    1685                 :            :         // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
    1686                 :            :         ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
    1687         [ +  - ]:       2619 :             pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
    1688                 :            : 
    1689         [ +  - ]:       2619 :         switch (p->GetVolatileType())
           [ +  -  +  - ]
    1690                 :            :         {
    1691                 :            :             case ScInterpreter::VOLATILE:
    1692                 :            :                 // Volatile via built-in volatile functions.  No actions needed.
    1693                 :        132 :             break;
    1694                 :            :             case ScInterpreter::VOLATILE_MACRO:
    1695                 :            :                 // The formula contains a volatile macro.
    1696                 :          0 :                 pCode->SetRecalcModeAlways();
    1697         [ #  # ]:          0 :                 pDocument->PutInFormulaTree(this);
    1698         [ #  # ]:          0 :                 StartListeningTo(pDocument);
    1699                 :          0 :             break;
    1700                 :            :             case ScInterpreter::NOT_VOLATILE:
    1701         [ -  + ]:       2487 :                 if (pCode->IsRecalcModeAlways())
    1702                 :            :                 {
    1703                 :            :                     // The formula was previously volatile, but no more.
    1704         [ #  # ]:          0 :                     EndListeningTo(pDocument);
    1705                 :          0 :                     pCode->SetRecalcModeNormal();
    1706                 :            :                 }
    1707                 :            :                 else
    1708                 :            :                 {
    1709                 :            :                     // non-volatile formula.  End listening to the area in case
    1710                 :            :                     // it's listening due to macro module change.
    1711         [ +  - ]:       2487 :                     pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, this);
    1712                 :            :                 }
    1713         [ +  - ]:       2487 :                 pDocument->RemoveFromFormulaTree(this);
    1714                 :       2619 :             break;
    1715                 :            :             default:
    1716                 :            :                 ;
    1717 [ +  - ][ +  - ]:       2619 :         }
    1718                 :            :     }
    1719                 :            :     else
    1720                 :            :     {
    1721                 :            :         //  Zelle bei Compiler-Fehlern nicht ewig auf dirty stehenlassen
    1722                 :            :         OSL_ENSURE( pCode->GetCodeError(), "kein UPN-Code und kein Fehler ?!?!" );
    1723                 :         40 :         bDirty = false;
    1724                 :       2659 :         bTableOpDirty = false;
    1725 [ +  - ][ +  - ]:       2659 :     }
    1726                 :            : }
    1727                 :            : 
    1728                 :            : 
    1729                 :         84 : void ScFormulaCell::SetMatColsRows( SCCOL nCols, SCROW nRows )
    1730                 :            : {
    1731                 :         84 :     ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellTokenNonConst();
    1732         [ -  + ]:         84 :     if (pMat)
    1733                 :          0 :         pMat->SetMatColsRows( nCols, nRows);
    1734 [ -  + ][ #  # ]:         84 :     else if (nCols || nRows)
    1735                 :            :     {
    1736         [ +  - ]:         84 :         aResult.SetToken( new ScMatrixFormulaCellToken( nCols, nRows));
    1737                 :            :         // Setting the new token actually forces an empty result at this top
    1738                 :            :         // left cell, so have that recalculated.
    1739                 :         84 :         SetDirty();
    1740                 :            :     }
    1741                 :         84 : }
    1742                 :            : 
    1743                 :            : 
    1744                 :         28 : void ScFormulaCell::GetMatColsRows( SCCOL & nCols, SCROW & nRows ) const
    1745                 :            : {
    1746                 :         28 :     const ScMatrixFormulaCellToken* pMat = aResult.GetMatrixFormulaCellToken();
    1747         [ +  - ]:         28 :     if (pMat)
    1748                 :         28 :         pMat->GetMatColsRows( nCols, nRows);
    1749                 :            :     else
    1750                 :            :     {
    1751                 :          0 :         nCols = 0;
    1752                 :          0 :         nRows = 0;
    1753                 :            :     }
    1754                 :         28 : }
    1755                 :            : 
    1756                 :            : 
    1757                 :       1755 : sal_uLong ScFormulaCell::GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const
    1758                 :            : {
    1759 [ -  + ][ #  # ]:       1755 :     if ( nFormatIndex && (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
    1760                 :          0 :         return nFormatIndex;
    1761                 :            :     //! not ScFormulaCell::IsValue(), that could reinterpret the formula again.
    1762         [ +  + ]:       1755 :     if ( aResult.IsValue() )
    1763                 :       1512 :         return ScGlobal::GetStandardFormat( aResult.GetDouble(), rFormatter, nFormat, nFormatType );
    1764                 :            :     else
    1765                 :       1755 :         return ScGlobal::GetStandardFormat( rFormatter, nFormat, nFormatType );
    1766                 :            : }
    1767                 :            : 
    1768                 :            : 
    1769                 :      10237 : void ScFormulaCell::Notify( SvtBroadcaster&, const SfxHint& rHint)
    1770                 :            : {
    1771 [ +  + ][ +  - ]:      10237 :     if ( !pDocument->IsInDtorClear() && !pDocument->GetHardRecalcState() )
                 [ +  + ]
    1772                 :            :     {
    1773 [ +  - ][ +  + ]:       3025 :         const ScHint* p = PTR_CAST( ScHint, &rHint );
    1774         [ +  + ]:       3025 :         sal_uLong nHint = (p ? p->GetId() : 0);
    1775         [ +  + ]:       3025 :         if (nHint & (SC_HINT_DATACHANGED | SC_HINT_DYING | SC_HINT_TABLEOPDIRTY))
    1776                 :            :         {
    1777                 :       3018 :             bool bForceTrack = false;
    1778         [ +  + ]:       3018 :             if ( nHint & SC_HINT_TABLEOPDIRTY )
    1779                 :            :             {
    1780                 :       1414 :                 bForceTrack = !bTableOpDirty;
    1781         [ +  + ]:       1414 :                 if ( !bTableOpDirty )
    1782                 :            :                 {
    1783                 :        795 :                     pDocument->AddTableOpFormulaCell( this );
    1784                 :        795 :                     bTableOpDirty = true;
    1785                 :            :                 }
    1786                 :            :             }
    1787                 :            :             else
    1788                 :            :             {
    1789                 :       1604 :                 bForceTrack = !bDirty;
    1790                 :       1604 :                 SetDirtyVar();
    1791                 :            :             }
    1792                 :            :             // Don't remove from FormulaTree to put in FormulaTrack to
    1793                 :            :             // put in FormulaTree again and again, only if necessary.
    1794                 :            :             // Any other means except RECALCMODE_ALWAYS by which a cell could
    1795                 :            :             // be in FormulaTree if it would notify other cells through
    1796                 :            :             // FormulaTrack which weren't in FormulaTrack/FormulaTree before?!?
    1797                 :            :             // Yes. The new TableOpDirty made it necessary to have a
    1798                 :            :             // forced mode where formulas may still be in FormulaTree from
    1799                 :            :             // TableOpDirty but have to notify dependents for normal dirty.
    1800 [ +  + ][ +  +  :       6036 :             if ( (bForceTrack || !pDocument->IsInFormulaTree( this )
             -  +  +  + ]
                 [ +  + ]
    1801                 :       1392 :                     || pCode->IsRecalcModeAlways())
    1802                 :       1626 :                     && !pDocument->IsInFormulaTrack( this ) )
    1803                 :       1403 :                 pDocument->AppendToFormulaTrack( this );
    1804                 :            :         }
    1805                 :            :     }
    1806                 :      10237 : }
    1807                 :            : 
    1808                 :        962 : void ScFormulaCell::SetDirty()
    1809                 :            : {
    1810         [ +  - ]:        962 :     if ( !IsInChangeTrack() )
    1811                 :            :     {
    1812         [ -  + ]:        962 :         if ( pDocument->GetHardRecalcState() )
    1813                 :          0 :             SetDirtyVar();
    1814                 :            :         else
    1815                 :            :         {
    1816                 :            :             // Mehrfach-FormulaTracking in Load und in CompileAll
    1817                 :            :             // nach CopyScenario und CopyBlockFromClip vermeiden.
    1818                 :            :             // Wenn unbedingtes FormulaTracking noetig, vor SetDirty bDirty=false
    1819                 :            :             // setzen, z.B. in CompileTokenArray
    1820 [ +  + ][ +  + ]:        962 :             if ( !bDirty || !pDocument->IsInFormulaTree( this ) )
                 [ +  + ]
    1821                 :            :             {
    1822                 :        907 :                 SetDirtyVar();
    1823                 :        907 :                 pDocument->AppendToFormulaTrack( this );
    1824                 :        907 :                 pDocument->TrackFormulas();
    1825                 :            :             }
    1826                 :            :         }
    1827                 :            : 
    1828         [ +  + ]:        962 :         if (pDocument->IsStreamValid(aPos.Tab()))
    1829                 :         15 :             pDocument->SetStreamValid(aPos.Tab(), false);
    1830                 :            :     }
    1831                 :        962 : }
    1832                 :            : 
    1833                 :       4421 : void ScFormulaCell::SetDirtyVar()
    1834                 :            : {
    1835                 :       4421 :     bDirty = true;
    1836                 :            :     // mark the sheet of this cell to be calculated
    1837                 :            :     //#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() );
    1838                 :       4421 : }
    1839                 :            : 
    1840                 :       1773 : void ScFormulaCell::SetDirtyAfterLoad()
    1841                 :            : {
    1842                 :       1773 :     bDirty = true;
    1843         [ +  - ]:       1773 :     if ( !pDocument->GetHardRecalcState() )
    1844                 :       1773 :         pDocument->PutInFormulaTree( this );
    1845                 :       1773 : }
    1846                 :            : 
    1847                 :       1205 : void ScFormulaCell::SetTableOpDirty()
    1848                 :            : {
    1849         [ +  - ]:       1205 :     if ( !IsInChangeTrack() )
    1850                 :            :     {
    1851         [ -  + ]:       1205 :         if ( pDocument->GetHardRecalcState() )
    1852                 :          0 :             bTableOpDirty = true;
    1853                 :            :         else
    1854                 :            :         {
    1855 [ +  + ][ -  + ]:       1205 :             if ( !bTableOpDirty || !pDocument->IsInFormulaTree( this ) )
                 [ +  + ]
    1856                 :            :             {
    1857         [ +  - ]:        134 :                 if ( !bTableOpDirty )
    1858                 :            :                 {
    1859                 :        134 :                     pDocument->AddTableOpFormulaCell( this );
    1860                 :        134 :                     bTableOpDirty = true;
    1861                 :            :                 }
    1862                 :        134 :                 pDocument->AppendToFormulaTrack( this );
    1863                 :        134 :                 pDocument->TrackFormulas( SC_HINT_TABLEOPDIRTY );
    1864                 :            :             }
    1865                 :            :         }
    1866                 :            :     }
    1867                 :       1205 : }
    1868                 :            : 
    1869                 :            : 
    1870                 :      19480 : bool ScFormulaCell::IsDirtyOrInTableOpDirty() const
    1871                 :            : {
    1872 [ +  + ][ -  + ]:      19480 :     return bDirty || (bTableOpDirty && pDocument->IsInInterpreterTableOp());
                 [ #  # ]
    1873                 :            : }
    1874                 :            : 
    1875                 :            : 
    1876                 :         40 : void ScFormulaCell::SetErrCode( sal_uInt16 n )
    1877                 :            : {
    1878                 :            :     /* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
    1879                 :            :      * used whether it is solely for transport of a simple result error and get
    1880                 :            :      * rid of that abuse. */
    1881                 :         40 :     pCode->SetCodeError( n );
    1882                 :            :     // Hard set errors are transported as result type value per convention,
    1883                 :            :     // e.g. via clipboard. ScFormulaResult::IsValue() and
    1884                 :            :     // ScFormulaResult::GetDouble() handle that.
    1885                 :         40 :     aResult.SetResultError( n );
    1886                 :         40 : }
    1887                 :            : 
    1888                 :         48 : void ScFormulaCell::AddRecalcMode( ScRecalcMode nBits )
    1889                 :            : {
    1890         [ +  - ]:         48 :     if ( (nBits & RECALCMODE_EMASK) != RECALCMODE_NORMAL )
    1891                 :         48 :         bDirty = true;
    1892         [ +  - ]:         48 :     if ( nBits & RECALCMODE_ONLOAD_ONCE )
    1893                 :            :     {   // OnLoadOnce nur zum Dirty setzen nach Filter-Import
    1894                 :         48 :         nBits = (nBits & ~RECALCMODE_EMASK) | RECALCMODE_NORMAL;
    1895                 :            :     }
    1896                 :         48 :     pCode->AddRecalcMode( nBits );
    1897                 :         48 : }
    1898                 :            : 
    1899                 :            : // Dynamically create the URLField on a mouse-over action on a hyperlink() cell.
    1900                 :          0 : void ScFormulaCell::GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText )
    1901                 :            : {
    1902                 :          0 :     rtl::OUString aCellString;
    1903                 :            : 
    1904                 :            :     Color* pColor;
    1905                 :            : 
    1906                 :            :     // Cell Text uses the Cell format while the URL uses
    1907                 :            :     // the default format for the type.
    1908         [ #  # ]:          0 :     sal_uLong nCellFormat = pDocument->GetNumberFormat( aPos );
    1909         [ #  # ]:          0 :     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
    1910                 :            : 
    1911         [ #  # ]:          0 :     if ( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
    1912         [ #  # ]:          0 :         nCellFormat = GetStandardFormat( *pFormatter,nCellFormat );
    1913                 :            : 
    1914         [ #  # ]:          0 :    sal_uLong nURLFormat = ScGlobal::GetStandardFormat( *pFormatter,nCellFormat, NUMBERFORMAT_NUMBER);
    1915                 :            : 
    1916 [ #  # ][ #  # ]:          0 :     if ( IsValue() )
    1917                 :            :     {
    1918         [ #  # ]:          0 :         double fValue = GetValue();
    1919         [ #  # ]:          0 :         pFormatter->GetOutputString( fValue, nCellFormat, rCellText, &pColor );
    1920                 :            :     }
    1921                 :            :     else
    1922                 :            :     {
    1923         [ #  # ]:          0 :         aCellString = GetString();
    1924         [ #  # ]:          0 :         pFormatter->GetOutputString( aCellString, nCellFormat, rCellText, &pColor );
    1925                 :            :     }
    1926         [ #  # ]:          0 :     ScConstMatrixRef xMat( aResult.GetMatrix());
    1927         [ #  # ]:          0 :     if (xMat)
    1928                 :            :     {
    1929                 :            :         // determine if the matrix result is a string or value.
    1930 [ #  # ][ #  # ]:          0 :         if (!xMat->IsValue(0, 1))
    1931         [ #  # ]:          0 :             rURL = xMat->GetString(0, 1);
    1932                 :            :         else
    1933                 :            :             pFormatter->GetOutputString(
    1934 [ #  # ][ #  # ]:          0 :                 xMat->GetDouble(0, 1), nURLFormat, rURL, &pColor);
    1935                 :            :     }
    1936                 :            : 
    1937         [ #  # ]:          0 :     if(rURL.isEmpty())
    1938                 :            :     {
    1939 [ #  # ][ #  # ]:          0 :         if(IsValue())
    1940 [ #  # ][ #  # ]:          0 :             pFormatter->GetOutputString( GetValue(), nURLFormat, rURL, &pColor );
    1941                 :            :         else
    1942         [ #  # ]:          0 :             pFormatter->GetOutputString( aCellString, nURLFormat, rURL, &pColor );
    1943         [ #  # ]:          0 :     }
    1944                 :          0 : }
    1945                 :            : 
    1946                 :        334 : bool ScFormulaCell::IsMultilineResult()
    1947                 :            : {
    1948         [ +  + ]:        334 :     if (!IsValue())
    1949                 :         40 :         return aResult.IsMultiline();
    1950                 :        334 :     return false;
    1951                 :            : }
    1952                 :            : 
    1953                 :      16624 : void ScFormulaCell::MaybeInterpret()
    1954                 :            : {
    1955         [ +  + ]:      16624 :     if (!IsDirtyOrInTableOpDirty())
    1956                 :      16624 :         return;
    1957                 :            : 
    1958 [ +  + ][ -  + ]:        630 :     if (pDocument->GetAutoCalc() || (cMatrixFlag != MM_NONE))
                 [ +  + ]
    1959                 :        624 :         Interpret();
    1960                 :            : }
    1961                 :            : 
    1962                 :          0 : EditTextObject* ScFormulaCell::CreateURLObject()
    1963                 :            : {
    1964                 :          0 :     rtl::OUString aCellText;
    1965                 :          0 :     rtl::OUString aURL;
    1966         [ #  # ]:          0 :     GetURLResult( aURL, aCellText );
    1967                 :            : 
    1968         [ #  # ]:          0 :     SvxURLField aUrlField( aURL, aCellText, SVXURLFORMAT_APPDEFAULT);
    1969         [ #  # ]:          0 :     EditEngine& rEE = pDocument->GetEditEngine();
    1970 [ #  # ][ #  # ]:          0 :     rEE.SetText( EMPTY_STRING );
    1971 [ #  # ][ #  # ]:          0 :     rEE.QuickInsertField( SvxFieldItem( aUrlField, EE_FEATURE_FIELD ), ESelection( 0xFFFF, 0xFFFF ) );
                 [ #  # ]
    1972                 :            : 
    1973 [ #  # ][ #  # ]:          0 :     return rEE.CreateTextObject();
    1974                 :            : }
    1975                 :            : 
    1976                 :            : // ============================================================================
    1977                 :            : 
    1978                 :         32 : ScDetectiveRefIter::ScDetectiveRefIter( ScFormulaCell* pCell )
    1979                 :            : {
    1980                 :         32 :     pCode = pCell->GetCode();
    1981                 :         32 :     pCode->Reset();
    1982                 :         32 :     aPos = pCell->aPos;
    1983                 :         32 : }
    1984                 :            : 
    1985                 :         44 : bool lcl_ScDetectiveRefIter_SkipRef( ScToken* p )
    1986                 :            : {
    1987                 :         44 :     ScSingleRefData& rRef1 = p->GetSingleRef();
    1988         [ +  - ]:         88 :     if ( rRef1.IsColDeleted() || rRef1.IsRowDeleted() || rRef1.IsTabDeleted()
           [ +  -  -  + ]
         [ -  + ][ +  - ]
    1989                 :         44 :             || !rRef1.Valid() )
    1990                 :          0 :         return true;
    1991 [ +  + ][ -  + ]:         44 :     if ( p->GetType() == svDoubleRef || p->GetType() == svExternalDoubleRef )
                 [ +  + ]
    1992                 :            :     {
    1993                 :          5 :         ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
    1994         [ +  - ]:         10 :         if ( rRef2.IsColDeleted() || rRef2.IsRowDeleted() || rRef2.IsTabDeleted()
           [ +  -  -  + ]
         [ -  + ][ +  - ]
    1995                 :          5 :                 || !rRef2.Valid() )
    1996                 :          0 :             return true;
    1997                 :            :     }
    1998                 :         44 :     return false;
    1999                 :            : }
    2000                 :            : 
    2001                 :         40 : bool ScDetectiveRefIter::GetNextRef( ScRange& rRange )
    2002                 :            : {
    2003                 :         40 :     bool bRet = false;
    2004                 :         40 :     ScToken* p = GetNextRefToken();
    2005         [ +  + ]:         40 :     if( p )
    2006                 :            :     {
    2007         [ +  - ]:         20 :         SingleDoubleRefProvider aProv( *p );
    2008                 :         20 :         rRange.aStart.Set( aProv.Ref1.nCol, aProv.Ref1.nRow, aProv.Ref1.nTab );
    2009                 :         20 :         rRange.aEnd.Set( aProv.Ref2.nCol, aProv.Ref2.nRow, aProv.Ref2.nTab );
    2010                 :         20 :         bRet = true;
    2011                 :            :     }
    2012                 :            : 
    2013                 :         40 :     return bRet;
    2014                 :            : }
    2015                 :            : 
    2016                 :         76 : ScToken* ScDetectiveRefIter::GetNextRefToken()
    2017                 :            : {
    2018                 :         76 :     ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    2019         [ +  + ]:         76 :     if (p)
    2020                 :         44 :         p->CalcAbsIfRel( aPos );
    2021                 :            : 
    2022 [ +  + ][ -  + ]:         76 :     while ( p && lcl_ScDetectiveRefIter_SkipRef( p ) )
                 [ -  + ]
    2023                 :            :     {
    2024                 :          0 :         p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    2025         [ #  # ]:          0 :         if (p)
    2026                 :          0 :             p->CalcAbsIfRel( aPos );
    2027                 :            :     }
    2028                 :         76 :     return p;
    2029 [ +  - ][ +  - ]:        153 : }
    2030                 :            : 
    2031                 :            : // ============================================================================
    2032                 :            : 
    2033                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10