LCOV - code coverage report
Current view: top level - sc/source/core/data - conditio.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 729 1166 62.5 %
Date: 2015-06-13 12:38:46 Functions: 93 123 75.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "scitems.hxx"
      21             : #include <sfx2/objsh.hxx>
      22             : #include <svl/itemset.hxx>
      23             : #include <svl/zforlist.hxx>
      24             : #include <rtl/math.hxx>
      25             : #include <unotools/collatorwrapper.hxx>
      26             : 
      27             : #include <com/sun/star/sheet/ConditionOperator2.hpp>
      28             : 
      29             : #include "conditio.hxx"
      30             : #include "formulacell.hxx"
      31             : #include "document.hxx"
      32             : #include "hints.hxx"
      33             : #include "compiler.hxx"
      34             : #include "rechead.hxx"
      35             : #include "rangelst.hxx"
      36             : #include "stlpool.hxx"
      37             : #include "rangenam.hxx"
      38             : #include "colorscale.hxx"
      39             : #include "cellvalue.hxx"
      40             : #include "editutil.hxx"
      41             : #include "tokenarray.hxx"
      42             : #include "refupdatecontext.hxx"
      43             : #include <svl/sharedstring.hxx>
      44             : #include <svl/sharedstringpool.hxx>
      45             : #include <boost/scoped_ptr.hpp>
      46             : 
      47             : using namespace formula;
      48             : 
      49         425 : ScFormatEntry::ScFormatEntry(ScDocument* pDoc):
      50         425 :     mpDoc(pDoc)
      51             : {
      52         425 : }
      53             : 
      54           0 : bool ScFormatEntry::operator==( const ScFormatEntry& r ) const
      55             : {
      56           0 :     if(GetType() != r.GetType())
      57           0 :         return false;
      58             : 
      59           0 :     switch(GetType())
      60             :     {
      61             :         case condformat::CONDITION:
      62           0 :             return static_cast<const ScCondFormatEntry&>(*this) == static_cast<const ScCondFormatEntry&>(r);
      63             :         default:
      64             :             // TODO: implement also this case
      65             :             // actually return false for these cases is not that bad
      66             :             // as soon as databar and color scale are tested we need
      67             :             // to think about the range
      68           0 :             return false;
      69             :     }
      70             : }
      71             : 
      72           0 : void ScFormatEntry::startRendering()
      73             : {
      74           0 : }
      75             : 
      76           0 : void ScFormatEntry::endRendering()
      77             : {
      78           0 : }
      79             : 
      80         213 : static bool lcl_HasRelRef( ScDocument* pDoc, ScTokenArray* pFormula, sal_uInt16 nRecursion = 0 )
      81             : {
      82         213 :     if (pFormula)
      83             :     {
      84          36 :         pFormula->Reset();
      85             :         FormulaToken* t;
      86          66 :         for( t = pFormula->Next(); t; t = pFormula->Next() )
      87             :         {
      88          54 :             switch( t->GetType() )
      89             :             {
      90             :                 case svDoubleRef:
      91             :                 {
      92           8 :                     ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
      93           8 :                     if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() )
      94           7 :                         return true;
      95             :                 }
      96             :                 // fall through
      97             : 
      98             :                 case svSingleRef:
      99             :                 {
     100          22 :                     ScSingleRefData& rRef1 = *t->GetSingleRef();
     101          22 :                     if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() )
     102          17 :                         return true;
     103             :                 }
     104           5 :                 break;
     105             : 
     106             :                 case svIndex:
     107             :                 {
     108           1 :                     if( t->GetOpCode() == ocName )      // DB areas always absolute
     109           1 :                         if( ScRangeData* pRangeData = pDoc->GetRangeName()->findByIndex( t->GetIndex() ) )
     110           1 :                             if( (nRecursion < 42) && lcl_HasRelRef( pDoc, pRangeData->GetCode(), nRecursion + 1 ) )
     111           0 :                                 return true;
     112             :                 }
     113           1 :                 break;
     114             : 
     115             :                 // #i34474# function result dependent on cell position
     116             :                 case svByte:
     117             :                 {
     118          12 :                     switch( t->GetOpCode() )
     119             :                     {
     120             :                         case ocRow:     // ROW() returns own row index
     121             :                         case ocColumn:  // COLUMN() returns own column index
     122             :                         case ocSheet:   // SHEET() returns own sheet index
     123             :                         case ocCell:    // CELL() may return own cell address
     124           0 :                             return true;
     125             :                         default:
     126             :                         {
     127             :                             // added to avoid warnings
     128             :                         }
     129             :                     }
     130             :                 }
     131          12 :                 break;
     132             : 
     133             :                 default:
     134             :                 {
     135             :                     // added to avoid warnings
     136             :                 }
     137             :             }
     138             :         }
     139             :     }
     140         189 :     return false;
     141             : }
     142             : 
     143           3 : ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) :
     144             :     ScFormatEntry(r.mpDoc),
     145             :     eOp(r.eOp),
     146             :     nOptions(r.nOptions),
     147             :     nVal1(r.nVal1),
     148             :     nVal2(r.nVal2),
     149             :     aStrVal1(r.aStrVal1),
     150             :     aStrVal2(r.aStrVal2),
     151             :     aStrNmsp1(r.aStrNmsp1),
     152             :     aStrNmsp2(r.aStrNmsp2),
     153             :     eTempGrammar1(r.eTempGrammar1),
     154             :     eTempGrammar2(r.eTempGrammar2),
     155             :     bIsStr1(r.bIsStr1),
     156             :     bIsStr2(r.bIsStr2),
     157             :     pFormula1(NULL),
     158             :     pFormula2(NULL),
     159             :     aSrcPos(r.aSrcPos),
     160             :     aSrcString(r.aSrcString),
     161             :     pFCell1(NULL),
     162             :     pFCell2(NULL),
     163             :     bRelRef1(r.bRelRef1),
     164             :     bRelRef2(r.bRelRef2),
     165             :     bFirstRun(true),
     166           3 :     pCondFormat(r.pCondFormat)
     167             : {
     168             :     // ScTokenArray copy ctor creates a flat copy
     169           3 :     if (r.pFormula1)
     170           1 :         pFormula1 = new ScTokenArray( *r.pFormula1 );
     171           3 :     if (r.pFormula2)
     172           0 :         pFormula2 = new ScTokenArray( *r.pFormula2 );
     173             : 
     174             :     // Formula cells are created at IsValid
     175           3 : }
     176             : 
     177          86 : ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntry& r ) :
     178             :     ScFormatEntry(pDocument),
     179             :     eOp(r.eOp),
     180             :     nOptions(r.nOptions),
     181             :     nVal1(r.nVal1),
     182             :     nVal2(r.nVal2),
     183             :     aStrVal1(r.aStrVal1),
     184             :     aStrVal2(r.aStrVal2),
     185             :     aStrNmsp1(r.aStrNmsp1),
     186             :     aStrNmsp2(r.aStrNmsp2),
     187             :     eTempGrammar1(r.eTempGrammar1),
     188             :     eTempGrammar2(r.eTempGrammar2),
     189             :     bIsStr1(r.bIsStr1),
     190             :     bIsStr2(r.bIsStr2),
     191             :     pFormula1(NULL),
     192             :     pFormula2(NULL),
     193             :     aSrcPos(r.aSrcPos),
     194             :     aSrcString(r.aSrcString),
     195             :     pFCell1(NULL),
     196             :     pFCell2(NULL),
     197             :     bRelRef1(r.bRelRef1),
     198             :     bRelRef2(r.bRelRef2),
     199             :     bFirstRun(true),
     200          86 :     pCondFormat(r.pCondFormat)
     201             : {
     202             :     // Real copy of the formulas (for Ref Undo)
     203          86 :     if (r.pFormula1)
     204          47 :         pFormula1 = r.pFormula1->Clone();
     205          86 :     if (r.pFormula2)
     206          15 :         pFormula2 = r.pFormula2->Clone();
     207             : 
     208             :     // Formula cells are created at IsValid
     209             :     // TODO: But not in the Clipboard! So interpret beforehand!
     210          86 : }
     211             : 
     212         186 : ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
     213             :         const OUString& rExpr1, const OUString& rExpr2, ScDocument* pDocument, const ScAddress& rPos,
     214             :         const OUString& rExprNmsp1, const OUString& rExprNmsp2,
     215             :         FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) :
     216             :     ScFormatEntry(pDocument),
     217             :     eOp(eOper),
     218             :     nOptions(0),
     219             :     nVal1(0.0),
     220             :     nVal2(0.0),
     221             :     aStrNmsp1(rExprNmsp1),
     222             :     aStrNmsp2(rExprNmsp2),
     223             :     eTempGrammar1(eGrammar1),
     224             :     eTempGrammar2(eGrammar2),
     225             :     bIsStr1(false),
     226             :     bIsStr2(false),
     227             :     pFormula1(NULL),
     228             :     pFormula2(NULL),
     229             :     aSrcPos(rPos),
     230             :     pFCell1(NULL),
     231             :     pFCell2(NULL),
     232             :     bRelRef1(false),
     233             :     bRelRef2(false),
     234             :     bFirstRun(true),
     235         186 :     pCondFormat(NULL)
     236             : {
     237         186 :     Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, false );
     238             : 
     239             :     // Formula cells are created at IsValid
     240         186 : }
     241             : 
     242          36 : ScConditionEntry::ScConditionEntry( ScConditionMode eOper,
     243             :                                 const ScTokenArray* pArr1, const ScTokenArray* pArr2,
     244             :                                 ScDocument* pDocument, const ScAddress& rPos ) :
     245             :     ScFormatEntry(pDocument),
     246             :     eOp(eOper),
     247             :     nOptions(0),
     248             :     nVal1(0.0),
     249             :     nVal2(0.0),
     250             :     eTempGrammar1(FormulaGrammar::GRAM_DEFAULT),
     251             :     eTempGrammar2(FormulaGrammar::GRAM_DEFAULT),
     252             :     bIsStr1(false),
     253             :     bIsStr2(false),
     254             :     pFormula1(NULL),
     255             :     pFormula2(NULL),
     256             :     aSrcPos(rPos),
     257             :     pFCell1(NULL),
     258             :     pFCell2(NULL),
     259             :     bRelRef1(false),
     260             :     bRelRef2(false),
     261             :     bFirstRun(true),
     262          36 :     pCondFormat(NULL)
     263             : {
     264          36 :     if ( pArr1 )
     265             :     {
     266          34 :         pFormula1 = new ScTokenArray( *pArr1 );
     267          34 :         if ( pFormula1->GetLen() == 1 )
     268             :         {
     269             :             // Single (constant number)?
     270          28 :             FormulaToken* pToken = pFormula1->First();
     271          28 :             if ( pToken->GetOpCode() == ocPush )
     272             :             {
     273          27 :                 if ( pToken->GetType() == svDouble )
     274             :                 {
     275          24 :                     nVal1 = pToken->GetDouble();
     276          24 :                     DELETEZ(pFormula1);             // Do not remember as formula
     277             :                 }
     278           3 :                 else if ( pToken->GetType() == svString )
     279             :                 {
     280           1 :                     bIsStr1 = true;
     281           1 :                     aStrVal1 = pToken->GetString().getString();
     282           1 :                     DELETEZ(pFormula1);             // Do not remember as formula
     283             :                 }
     284             :             }
     285             :         }
     286          34 :         bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
     287             :     }
     288          36 :     if ( pArr2 )
     289             :     {
     290           1 :         pFormula2 = new ScTokenArray( *pArr2 );
     291           1 :         if ( pFormula2->GetLen() == 1 )
     292             :         {
     293             :             // Single (constant number)?
     294           1 :             FormulaToken* pToken = pFormula2->First();
     295           1 :             if ( pToken->GetOpCode() == ocPush )
     296             :             {
     297           1 :                 if ( pToken->GetType() == svDouble )
     298             :                 {
     299           0 :                     nVal2 = pToken->GetDouble();
     300           0 :                     DELETEZ(pFormula2);             // Do not remember as formula
     301             :                 }
     302           1 :                 else if ( pToken->GetType() == svString )
     303             :                 {
     304           0 :                     bIsStr2 = true;
     305           0 :                     aStrVal2 = pToken->GetString().getString();
     306           0 :                     DELETEZ(pFormula2);             // Do not remember as formula
     307             :                 }
     308             :             }
     309             :         }
     310           1 :         bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
     311             :     }
     312             : 
     313             :     // Formula cells are created at IsValid
     314          36 : }
     315             : 
     316         616 : ScConditionEntry::~ScConditionEntry()
     317             : {
     318         308 :     delete pFCell1;
     319         308 :     delete pFCell2;
     320             : 
     321         308 :     delete pFormula1;
     322         308 :     delete pFormula2;
     323         308 : }
     324             : 
     325           0 : void ScConditionEntry::SetOperation(ScConditionMode eMode)
     326             : {
     327           0 :     eOp = eMode;
     328           0 : }
     329             : 
     330         257 : void ScConditionEntry::Compile( const OUString& rExpr1, const OUString& rExpr2,
     331             :         const OUString& rExprNmsp1, const OUString& rExprNmsp2,
     332             :         FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, bool bTextToReal )
     333             : {
     334         257 :     if ( !rExpr1.isEmpty() || !rExpr2.isEmpty() )
     335             :     {
     336         199 :         ScCompiler aComp( mpDoc, aSrcPos );
     337             : 
     338         199 :         if ( !rExpr1.isEmpty() )
     339             :         {
     340         199 :             delete pFormula1;
     341         199 :             aComp.SetGrammar( eGrammar1 );
     342         199 :             if ( mpDoc->IsImportingXML() && !bTextToReal )
     343             :             {
     344             :                 //  temporary formula string as string tokens
     345             :                 //TODO: merge with lcl_ScDocFunc_CreateTokenArrayXML
     346         104 :                 pFormula1 = new ScTokenArray;
     347         104 :                 pFormula1->AddStringXML( rExpr1 );
     348             :                 // bRelRef1 is set when the formula is compiled again (CompileXML)
     349             :             }
     350             :             else
     351             :             {
     352          95 :                 pFormula1 = aComp.CompileString( rExpr1, rExprNmsp1 );
     353          95 :                 if ( pFormula1->GetLen() == 1 )
     354             :                 {
     355             :                     // Single (constant number)?
     356          83 :                     FormulaToken* pToken = pFormula1->First();
     357          83 :                     if ( pToken->GetOpCode() == ocPush )
     358             :                     {
     359          83 :                         if ( pToken->GetType() == svDouble )
     360             :                         {
     361          71 :                             nVal1 = pToken->GetDouble();
     362          71 :                             DELETEZ(pFormula1);             // Do not remember as formula
     363             :                         }
     364          12 :                         else if ( pToken->GetType() == svString )
     365             :                         {
     366           0 :                             bIsStr1 = true;
     367           0 :                             aStrVal1 = pToken->GetString().getString();
     368           0 :                             DELETEZ(pFormula1);             // Do not remember as formula
     369             :                         }
     370             :                     }
     371             :                 }
     372          95 :                 bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
     373             :             }
     374             :         }
     375             : 
     376         199 :         if ( !rExpr2.isEmpty() )
     377             :         {
     378         110 :             delete pFormula2;
     379         110 :             aComp.SetGrammar( eGrammar2 );
     380         110 :             if ( mpDoc->IsImportingXML() && !bTextToReal )
     381             :             {
     382             :                 //  temporary formula string as string tokens
     383             :                 //TODO: merge with lcl_ScDocFunc_CreateTokenArrayXML
     384          28 :                 pFormula2 = new ScTokenArray;
     385          28 :                 pFormula2->AddStringXML( rExpr2 );
     386             :                 // bRelRef2 is set when the formula is compiled again (CompileXML)
     387             :             }
     388             :             else
     389             :             {
     390          82 :                 pFormula2 = aComp.CompileString( rExpr2, rExprNmsp2 );
     391          82 :                 if ( pFormula2->GetLen() == 1 )
     392             :                 {
     393             :                     // Sigle (constant number)?
     394          82 :                     FormulaToken* pToken = pFormula2->First();
     395          82 :                     if ( pToken->GetOpCode() == ocPush )
     396             :                     {
     397          82 :                         if ( pToken->GetType() == svDouble )
     398             :                         {
     399          81 :                             nVal2 = pToken->GetDouble();
     400          81 :                             DELETEZ(pFormula2);             // Do not remember as formula
     401             :                         }
     402           1 :                         else if ( pToken->GetType() == svString )
     403             :                         {
     404           0 :                             bIsStr2 = true;
     405           0 :                             aStrVal2 = pToken->GetString().getString();
     406           0 :                             DELETEZ(pFormula2);             // Do not remember as formula
     407             :                         }
     408             :                     }
     409             :                 }
     410          82 :                 bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
     411             :             }
     412         199 :         }
     413             :     }
     414         257 : }
     415             : 
     416             : /**
     417             :  * Create formula cells
     418             :  */
     419         825 : void ScConditionEntry::MakeCells( const ScAddress& rPos )
     420             : {
     421         825 :     if ( !mpDoc->IsClipOrUndo() ) // Never calculate in the Clipboard!
     422             :     {
     423         825 :         if ( pFormula1 && !pFCell1 && !bRelRef1 )
     424             :         {
     425           5 :             pFCell1 = new ScFormulaCell(mpDoc, rPos, *pFormula1);
     426           5 :             pFCell1->StartListeningTo( mpDoc );
     427             :         }
     428             : 
     429         825 :         if ( pFormula2 && !pFCell2 && !bRelRef2 )
     430             :         {
     431           1 :             pFCell2 = new ScFormulaCell(mpDoc, rPos, *pFormula2);
     432           1 :             pFCell2->StartListeningTo( mpDoc );
     433             :         }
     434             :     }
     435         825 : }
     436             : 
     437          35 : void ScConditionEntry::SetIgnoreBlank(bool bSet)
     438             : {
     439             :     // The bit SC_COND_NOBLANKS is set if blanks are not ignored
     440             :     // (only of valid)
     441          35 :     if (bSet)
     442          34 :         nOptions &= ~SC_COND_NOBLANKS;
     443             :     else
     444           1 :         nOptions |= SC_COND_NOBLANKS;
     445          35 : }
     446             : 
     447             : /**
     448             :  * Delete formula cells, so we re-complile at the next IsValid
     449             :  */
     450           1 : void ScConditionEntry::CompileAll()
     451             : {
     452           1 :     DELETEZ(pFCell1);
     453           1 :     DELETEZ(pFCell2);
     454           1 : }
     455             : 
     456          71 : void ScConditionEntry::CompileXML()
     457             : {
     458             :     //  First parse the formula source position if it was stored as text
     459          71 :     if ( !aSrcString.isEmpty() )
     460             :     {
     461          71 :         ScAddress aNew;
     462             :         /* XML is always in OOo:A1 format, although R1C1 would be more amenable
     463             :          * to compression */
     464          71 :         if ( aNew.Parse( aSrcString, mpDoc ) & SCA_VALID )
     465          71 :             aSrcPos = aNew;
     466             :         // if the position is invalid, there isn't much we can do at this time
     467          71 :         aSrcString.clear();
     468             :     }
     469             : 
     470             :     //  Convert the text tokens that were created during XML import into real tokens.
     471             :     Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1),
     472             :              GetExpression(aSrcPos, 1, 0, eTempGrammar2),
     473          71 :              aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, true );
     474          71 : }
     475             : 
     476         122 : void ScConditionEntry::SetSrcString( const OUString& rNew )
     477             : {
     478             :     // aSrcString is only evaluated in CompileXML
     479             :     SAL_WARN_IF( !mpDoc->IsImportingXML(), "sc", "SetSrcString is only valid for XML import" );
     480             : 
     481         122 :     aSrcString = rNew;
     482         122 : }
     483             : 
     484           0 : void ScConditionEntry::SetFormula1( const ScTokenArray& rArray )
     485             : {
     486           0 :     DELETEZ( pFormula1 );
     487           0 :     if( rArray.GetLen() > 0 )
     488             :     {
     489           0 :         pFormula1 = new ScTokenArray( rArray );
     490           0 :         bRelRef1 = lcl_HasRelRef( mpDoc, pFormula1 );
     491             :     }
     492           0 : }
     493             : 
     494           0 : void ScConditionEntry::SetFormula2( const ScTokenArray& rArray )
     495             : {
     496           0 :     DELETEZ( pFormula2 );
     497           0 :     if( rArray.GetLen() > 0 )
     498             :     {
     499           0 :         pFormula2 = new ScTokenArray( rArray );
     500           0 :         bRelRef2 = lcl_HasRelRef( mpDoc, pFormula2 );
     501             :     }
     502           0 : }
     503             : 
     504          36 : void ScConditionEntry::UpdateReference( sc::RefUpdateContext& rCxt )
     505             : {
     506          36 :     if(pCondFormat)
     507          20 :         aSrcPos = pCondFormat->GetRange().Combine().aStart;
     508          36 :     ScAddress aOldSrcPos = aSrcPos;
     509          36 :     bool bChangedPos = false;
     510          36 :     if (rCxt.meMode == URM_INSDEL && rCxt.maRange.In(aSrcPos))
     511             :     {
     512           1 :         aSrcPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
     513           1 :         bChangedPos = aSrcPos != aOldSrcPos;
     514             :     }
     515             : 
     516          36 :     if (pFormula1)
     517             :     {
     518          21 :         sc::RefUpdateResult aRes;
     519          21 :         switch (rCxt.meMode)
     520             :         {
     521             :             case URM_INSDEL:
     522           5 :                 aRes = pFormula1->AdjustReferenceOnShift(rCxt, aOldSrcPos);
     523           5 :             break;
     524             :             case URM_MOVE:
     525           0 :                 aRes = pFormula1->AdjustReferenceOnMove(rCxt, aOldSrcPos, aSrcPos);
     526           0 :             break;
     527             :             default:
     528             :                 ;
     529             :         }
     530             : 
     531          21 :         if (aRes.mbReferenceModified || bChangedPos)
     532           3 :             DELETEZ(pFCell1);       // is created again in IsValid
     533             :     }
     534             : 
     535          36 :     if (pFormula2)
     536             :     {
     537           1 :         sc::RefUpdateResult aRes;
     538           1 :         switch (rCxt.meMode)
     539             :         {
     540             :             case URM_INSDEL:
     541           0 :                 aRes = pFormula2->AdjustReferenceOnShift(rCxt, aOldSrcPos);
     542           0 :             break;
     543             :             case URM_MOVE:
     544           0 :                 aRes = pFormula2->AdjustReferenceOnMove(rCxt, aOldSrcPos, aSrcPos);
     545           0 :             break;
     546             :             default:
     547             :                 ;
     548             :         }
     549             : 
     550           1 :         if (aRes.mbReferenceModified || bChangedPos)
     551           0 :             DELETEZ(pFCell2);       // is created again in IsValid
     552             :     }
     553          36 : }
     554             : 
     555           3 : void ScConditionEntry::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
     556             : {
     557           3 :     if (pFormula1)
     558             :     {
     559           1 :         pFormula1->AdjustReferenceOnInsertedTab(rCxt, aSrcPos);
     560           1 :         DELETEZ(pFCell1);
     561             :     }
     562             : 
     563           3 :     if (pFormula2)
     564             :     {
     565           0 :         pFormula2->AdjustReferenceOnInsertedTab(rCxt, aSrcPos);
     566           0 :         DELETEZ(pFCell2);
     567             :     }
     568           3 : }
     569             : 
     570           4 : void ScConditionEntry::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
     571             : {
     572           4 :     if (pFormula1)
     573             :     {
     574           2 :         pFormula1->AdjustReferenceOnDeletedTab(rCxt, aSrcPos);
     575           2 :         DELETEZ(pFCell1);
     576             :     }
     577             : 
     578           4 :     if (pFormula2)
     579             :     {
     580           0 :         pFormula2->AdjustReferenceOnDeletedTab(rCxt, aSrcPos);
     581           0 :         DELETEZ(pFCell2);
     582             :     }
     583           4 : }
     584             : 
     585           0 : void ScConditionEntry::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
     586             : {
     587           0 :     if (pFormula1)
     588             :     {
     589           0 :         pFormula1->AdjustReferenceOnMovedTab(rCxt, aSrcPos);
     590           0 :         DELETEZ(pFCell1);
     591             :     }
     592             : 
     593           0 :     if (pFormula2)
     594             :     {
     595           0 :         pFormula2->AdjustReferenceOnMovedTab(rCxt, aSrcPos);
     596           0 :         DELETEZ(pFCell2);
     597             :     }
     598           0 : }
     599             : 
     600             : //FIXME: Make this a comparison operator at the TokenArray?
     601          95 : static bool lcl_IsEqual( const ScTokenArray* pArr1, const ScTokenArray* pArr2 )
     602             : {
     603             :     // We only compare the non-RPN array
     604          95 :     if ( pArr1 && pArr2 )
     605             :     {
     606          21 :         sal_uInt16 nLen = pArr1->GetLen();
     607          21 :         if ( pArr2->GetLen() != nLen )
     608           0 :             return false;
     609             : 
     610          21 :         FormulaToken** ppToken1 = pArr1->GetArray();
     611          21 :         FormulaToken** ppToken2 = pArr2->GetArray();
     612          42 :         for (sal_uInt16 i=0; i<nLen; i++)
     613             :         {
     614          42 :             if ( ppToken1[i] != ppToken2[i] &&
     615          21 :                  !(*ppToken1[i] == *ppToken2[i]) )
     616           0 :                 return false; // Difference
     617             :         }
     618          21 :         return true; // All entries are the same
     619             :     }
     620             :     else
     621          74 :         return !pArr1 && !pArr2; // Both 0? -> the same
     622             : }
     623             : 
     624         115 : bool ScConditionEntry::operator== ( const ScConditionEntry& r ) const
     625             : {
     626         218 :     bool bEq = (eOp == r.eOp && nOptions == r.nOptions &&
     627         210 :                 lcl_IsEqual( pFormula1, r.pFormula1 ) &&
     628         162 :                 lcl_IsEqual( pFormula2, r.pFormula2 ));
     629         115 :     if (bEq)
     630             :     {
     631             :         // for formulas, the reference positions must be compared, too
     632             :         // (including aSrcString, for inserting the entries during XML import)
     633          47 :         if ( ( pFormula1 || pFormula2 ) && ( aSrcPos != r.aSrcPos || aSrcString != r.aSrcString ) )
     634           0 :             bEq = false;
     635             : 
     636             :         // If not formulas, compare values
     637          47 :         if ( !pFormula1 && ( nVal1 != r.nVal1 || aStrVal1 != r.aStrVal1 || bIsStr1 != r.bIsStr1 ) )
     638           7 :             bEq = false;
     639          47 :         if ( !pFormula2 && ( nVal2 != r.nVal2 || aStrVal2 != r.aStrVal2 || bIsStr2 != r.bIsStr2 ) )
     640           7 :             bEq = false;
     641             :     }
     642             : 
     643         115 :     return bEq;
     644             : }
     645             : 
     646        3500 : void ScConditionEntry::Interpret( const ScAddress& rPos )
     647             : {
     648             :     // Create formula cells
     649             :     // Note: New Broadcaster (Note cells) may be inserted into the document!
     650        3500 :     if ( ( pFormula1 && !pFCell1 ) || ( pFormula2 && !pFCell2 ) )
     651         825 :         MakeCells( rPos );
     652             : 
     653             :     // Evaluate formulas
     654        3500 :     bool bDirty = false; // 1 and 2 separate?
     655             : 
     656        3500 :     boost::scoped_ptr<ScFormulaCell> pTemp1;
     657        3500 :     ScFormulaCell* pEff1 = pFCell1;
     658        3500 :     if ( bRelRef1 )
     659             :     {
     660         820 :         pTemp1.reset(pFormula1 ? new ScFormulaCell(mpDoc, rPos, *pFormula1) : new ScFormulaCell(mpDoc, rPos));
     661         820 :         pEff1 = pTemp1.get();
     662             :     }
     663        3500 :     if ( pEff1 )
     664             :     {
     665        2491 :         if (!pEff1->IsRunning()) // Don't create 522
     666             :         {
     667             :             //TODO: Query Changed instead of Dirty!
     668        2491 :             if (pEff1->GetDirty() && !bRelRef1 && mpDoc->GetAutoCalc())
     669           5 :                 bDirty = true;
     670        2491 :             if (pEff1->IsValue())
     671             :             {
     672        2491 :                 bIsStr1 = false;
     673        2491 :                 nVal1 = pEff1->GetValue();
     674        2491 :                 aStrVal1.clear();
     675             :             }
     676             :             else
     677             :             {
     678           0 :                 bIsStr1 = true;
     679           0 :                 aStrVal1 = pEff1->GetString().getString();
     680           0 :                 nVal1 = 0.0;
     681             :             }
     682             :         }
     683             :     }
     684        3500 :     pTemp1.reset();
     685             : 
     686        7000 :     boost::scoped_ptr<ScFormulaCell> pTemp2;
     687        3500 :     ScFormulaCell* pEff2 = pFCell2; //@ 1!=2
     688        3500 :     if ( bRelRef2 )
     689             :     {
     690          94 :         pTemp2.reset(pFormula2 ? new ScFormulaCell(mpDoc, rPos, *pFormula2) : new ScFormulaCell(mpDoc, rPos));
     691          94 :         pEff2 = pTemp2.get();
     692             :     }
     693        3500 :     if ( pEff2 )
     694             :     {
     695         141 :         if (!pEff2->IsRunning()) // Don't create 522
     696             :         {
     697         141 :             if (pEff2->GetDirty() && !bRelRef2 && mpDoc->GetAutoCalc())
     698           1 :                 bDirty = true;
     699         141 :             if (pEff2->IsValue())
     700             :             {
     701         141 :                 bIsStr2 = false;
     702         141 :                 nVal2 = pEff2->GetValue();
     703         141 :                 aStrVal2.clear();
     704             :             }
     705             :             else
     706             :             {
     707           0 :                 bIsStr2 = true;
     708           0 :                 aStrVal2 = pEff2->GetString().getString();
     709           0 :                 nVal2 = 0.0;
     710             :             }
     711             :         }
     712             :     }
     713        3500 :     pTemp2.reset();
     714             : 
     715             :     // If IsRunning, the last values remain
     716        3500 :     if (bDirty && !bFirstRun)
     717             :     {
     718             :         // Repaint everything for dependent formats
     719           0 :         DataChanged( NULL );
     720             :     }
     721             : 
     722        7000 :     bFirstRun = false;
     723        3500 : }
     724             : 
     725        4486 : static bool lcl_GetCellContent( ScRefCellValue& rCell, bool bIsStr1, double& rArg, OUString& rArgStr,
     726             :         const ScDocument* pDoc )
     727             : {
     728             : 
     729        4486 :     if (rCell.isEmpty())
     730        2408 :         return !bIsStr1;
     731             : 
     732        2078 :     bool bVal = true;
     733             : 
     734        2078 :     switch (rCell.meType)
     735             :     {
     736             :         case CELLTYPE_VALUE:
     737        2077 :             rArg = rCell.mfValue;
     738        2077 :         break;
     739             :         case CELLTYPE_FORMULA:
     740             :         {
     741           0 :             bVal = rCell.mpFormula->IsValue();
     742           0 :             if (bVal)
     743           0 :                 rArg = rCell.mpFormula->GetValue();
     744             :             else
     745           0 :                 rArgStr = rCell.mpFormula->GetString().getString();
     746             :         }
     747           0 :         break;
     748             :         case CELLTYPE_STRING:
     749             :         case CELLTYPE_EDIT:
     750           1 :             bVal = false;
     751           1 :             if (rCell.meType == CELLTYPE_STRING)
     752           1 :                 rArgStr = rCell.mpString->getString();
     753           0 :             else if (rCell.mpEditText)
     754           0 :                 rArgStr = ScEditUtil::GetString(*rCell.mpEditText, pDoc);
     755           1 :         break;
     756             :         default:
     757             :             ;
     758             :     }
     759             : 
     760        2078 :     return bVal;
     761             : }
     762             : 
     763         986 : void ScConditionEntry::FillCache() const
     764             : {
     765         986 :     if(!mpCache)
     766             :     {
     767          47 :         const ScRangeList& rRanges = pCondFormat->GetRange();
     768          47 :         mpCache.reset(new ScConditionEntryCache);
     769          47 :         size_t nListCount = rRanges.size();
     770          95 :         for( size_t i = 0; i < nListCount; i++ )
     771             :         {
     772          48 :             const ScRange *aRange = rRanges[i];
     773          48 :             SCROW nRow = aRange->aEnd.Row();
     774          48 :             SCCOL nCol = aRange->aEnd.Col();
     775          48 :             SCCOL nColStart = aRange->aStart.Col();
     776          48 :             SCROW nRowStart = aRange->aStart.Row();
     777          48 :             SCTAB nTab = aRange->aStart.Tab();
     778             : 
     779             :             // temporary fix to workaorund slow duplicate entry
     780             :             // conditions, prevent to use a whole row
     781          48 :             if(nRow == MAXROW)
     782             :             {
     783           0 :                 bool bShrunk = false;
     784             :                 mpDoc->ShrinkToUsedDataArea(bShrunk, nTab, nColStart, nRowStart,
     785           0 :                         nCol, nRow, false);
     786             :             }
     787             : 
     788        1034 :             for( SCROW r = nRowStart; r <= nRow; r++ )
     789        1972 :                 for( SCCOL c = nColStart; c <= nCol; c++ )
     790             :                 {
     791         986 :                     ScRefCellValue aCell;
     792         986 :                     aCell.assign(*mpDoc, ScAddress(c, r, nTab));
     793         986 :                     if (aCell.isEmpty())
     794           0 :                         continue;
     795             : 
     796         986 :                     double nVal = 0.0;
     797        1972 :                     OUString aStr;
     798         986 :                     if (!lcl_GetCellContent(aCell, false, nVal, aStr, mpDoc))
     799             :                     {
     800             :                         std::pair<ScConditionEntryCache::StringCacheType::iterator, bool> aResult =
     801           0 :                             mpCache->maStrings.insert(
     802           0 :                                 ScConditionEntryCache::StringCacheType::value_type(aStr, 1));
     803             : 
     804           0 :                         if(!aResult.second)
     805           0 :                             aResult.first->second++;
     806             :                     }
     807             :                     else
     808             :                     {
     809             :                         std::pair<ScConditionEntryCache::ValueCacheType::iterator, bool> aResult =
     810         986 :                             mpCache->maValues.insert(
     811        1972 :                                 ScConditionEntryCache::ValueCacheType::value_type(nVal, 1));
     812             : 
     813         986 :                         if(!aResult.second)
     814         149 :                             aResult.first->second++;
     815             : 
     816         986 :                         ++(mpCache->nValueItems);
     817             :                     }
     818         986 :                 }
     819             :         }
     820             :     }
     821         986 : }
     822             : 
     823           0 : bool ScConditionEntry::IsDuplicate( double nArg, const OUString& rStr ) const
     824             : {
     825           0 :     FillCache();
     826             : 
     827           0 :     if(rStr.isEmpty())
     828             :     {
     829           0 :         ScConditionEntryCache::ValueCacheType::iterator itr = mpCache->maValues.find(nArg);
     830           0 :         if(itr == mpCache->maValues.end())
     831           0 :             return false;
     832             :         else
     833             :         {
     834           0 :             if(itr->second > 1)
     835           0 :                 return true;
     836             :             else
     837           0 :                 return false;
     838             :         }
     839             :     }
     840             :     else
     841             :     {
     842           0 :         ScConditionEntryCache::StringCacheType::iterator itr = mpCache->maStrings.find(rStr);
     843           0 :         if(itr == mpCache->maStrings.end())
     844           0 :             return false;
     845             :         else
     846             :         {
     847           0 :             if(itr->second > 1)
     848           0 :                 return true;
     849             :             else
     850           0 :                 return false;
     851             :         }
     852             :     }
     853             : }
     854             : 
     855         146 : bool ScConditionEntry::IsTopNElement( double nArg ) const
     856             : {
     857         146 :     FillCache();
     858             : 
     859         146 :     if(mpCache->nValueItems <= nVal1)
     860           0 :         return true;
     861             : 
     862         146 :     size_t nCells = 0;
     863         917 :     for(ScConditionEntryCache::ValueCacheType::const_reverse_iterator itr = mpCache->maValues.rbegin(),
     864         146 :             itrEnd = mpCache->maValues.rend(); itr != itrEnd; ++itr)
     865             :     {
     866         771 :         if(nCells >= nVal1)
     867         257 :             return false;
     868         660 :         if(itr->first <= nArg)
     869          35 :             return true;
     870         625 :         nCells += itr->second;
     871             :     }
     872             : 
     873           0 :     return true;
     874             : }
     875             : 
     876         147 : bool ScConditionEntry::IsBottomNElement( double nArg ) const
     877             : {
     878         147 :     FillCache();
     879             : 
     880         147 :     if(mpCache->nValueItems <= nVal1)
     881           0 :         return true;
     882             : 
     883         147 :     size_t nCells = 0;
     884         651 :     for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
     885         147 :             itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
     886             :     {
     887         504 :         if(nCells >= nVal1)
     888         252 :             return false;
     889         399 :         if(itr->first >= nArg)
     890          42 :             return true;
     891         357 :         nCells += itr->second;
     892             :     }
     893             : 
     894           0 :     return true;
     895             : }
     896             : 
     897         147 : bool ScConditionEntry::IsTopNPercent( double nArg ) const
     898             : {
     899         147 :     FillCache();
     900             : 
     901         147 :     size_t nCells = 0;
     902         147 :     size_t nLimitCells = static_cast<size_t>(mpCache->nValueItems*nVal1/100);
     903         567 :     for(ScConditionEntryCache::ValueCacheType::const_reverse_iterator itr = mpCache->maValues.rbegin(),
     904         147 :             itrEnd = mpCache->maValues.rend(); itr != itrEnd; ++itr)
     905             :     {
     906         420 :         if(nCells >= nLimitCells)
     907         280 :             return false;
     908         287 :         if(itr->first <= nArg)
     909          14 :             return true;
     910         273 :         nCells += itr->second;
     911             :     }
     912             : 
     913           0 :     return true;
     914             : }
     915             : 
     916         147 : bool ScConditionEntry::IsBottomNPercent( double nArg ) const
     917             : {
     918         147 :     FillCache();
     919             : 
     920         147 :     size_t nCells = 0;
     921         147 :     size_t nLimitCells = static_cast<size_t>(mpCache->nValueItems*nVal1/100);
     922         546 :     for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
     923         147 :             itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
     924             :     {
     925         399 :         if(nCells >= nLimitCells)
     926         266 :             return false;
     927         280 :         if(itr->first >= nArg)
     928          28 :             return true;
     929         252 :         nCells += itr->second;
     930             :     }
     931             : 
     932           0 :     return true;
     933             : }
     934             : 
     935         168 : bool ScConditionEntry::IsBelowAverage( double nArg, bool bEqual ) const
     936             : {
     937         168 :     FillCache();
     938             : 
     939         168 :     double nSum = 0;
     940        3276 :     for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
     941         168 :             itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
     942             :     {
     943        2940 :         nSum += itr->first * itr->second;
     944             :     }
     945             : 
     946         168 :     if(bEqual)
     947          84 :         return (nArg <= nSum/mpCache->nValueItems);
     948             :     else
     949          84 :         return (nArg < nSum/mpCache->nValueItems);
     950             : }
     951             : 
     952         231 : bool ScConditionEntry::IsAboveAverage( double nArg, bool bEqual ) const
     953             : {
     954         231 :     FillCache();
     955             : 
     956         231 :     double nSum = 0;
     957        4536 :     for(ScConditionEntryCache::ValueCacheType::const_iterator itr = mpCache->maValues.begin(),
     958         231 :             itrEnd = mpCache->maValues.end(); itr != itrEnd; ++itr)
     959             :     {
     960        4074 :         nSum += itr->first * itr->second;
     961             :     }
     962             : 
     963         231 :     if(bEqual)
     964          84 :         return (nArg >= nSum/mpCache->nValueItems);
     965             :     else
     966         147 :         return (nArg > nSum/mpCache->nValueItems);
     967             : }
     968             : 
     969           0 : bool ScConditionEntry::IsError( const ScAddress& rPos ) const
     970             : {
     971           0 :     switch (mpDoc->GetCellType(rPos))
     972             :     {
     973             :         case CELLTYPE_VALUE:
     974           0 :             return false;
     975             :         case CELLTYPE_FORMULA:
     976             :         {
     977           0 :             ScFormulaCell* pFormulaCell = mpDoc->GetFormulaCell(rPos);
     978           0 :             if (pFormulaCell && pFormulaCell->GetErrCode())
     979           0 :                 return true;
     980             :         }
     981             :         case CELLTYPE_STRING:
     982             :         case CELLTYPE_EDIT:
     983           0 :             return false;
     984             :         default:
     985           0 :             break;
     986             :     }
     987           0 :     return false;
     988             : }
     989             : 
     990        3499 : bool ScConditionEntry::IsValid( double nArg, const ScAddress& rPos ) const
     991             : {
     992             :     // Interpret must already have been called
     993        3499 :     if ( bIsStr1 )
     994             :     {
     995           0 :         switch( eOp )
     996             :         {
     997             :             case SC_COND_BEGINS_WITH:
     998             :             case SC_COND_ENDS_WITH:
     999             :             case SC_COND_CONTAINS_TEXT:
    1000             :             case SC_COND_NOT_CONTAINS_TEXT:
    1001           0 :                 break;
    1002             :             case SC_COND_NOTEQUAL:
    1003           0 :                 return true;
    1004             :             default:
    1005           0 :                 return false;
    1006             :         }
    1007             :     }
    1008             : 
    1009        3499 :     if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
    1010         102 :         if ( bIsStr2 )
    1011           0 :             return false;
    1012             : 
    1013        3499 :     double nComp1 = nVal1; // Copy, so that it can be changed
    1014        3499 :     double nComp2 = nVal2;
    1015             : 
    1016        3499 :     if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
    1017         102 :         if ( nComp1 > nComp2 )
    1018             :         {
    1019             :             // Right order for value range
    1020           0 :             double nTemp = nComp1; nComp1 = nComp2; nComp2 = nTemp;
    1021             :         }
    1022             : 
    1023             :     // All corner cases need to be tested with ::rtl::math::approxEqual!
    1024        3499 :     bool bValid = false;
    1025        3499 :     switch (eOp)
    1026             :     {
    1027             :         case SC_COND_NONE:
    1028           0 :             break;                  // Always sal_False
    1029             :         case SC_COND_EQUAL:
    1030        1673 :             bValid = ::rtl::math::approxEqual( nArg, nComp1 );
    1031        1673 :             break;
    1032             :         case SC_COND_NOTEQUAL:
    1033           0 :             bValid = !::rtl::math::approxEqual( nArg, nComp1 );
    1034           0 :             break;
    1035             :         case SC_COND_GREATER:
    1036         714 :             bValid = ( nArg > nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
    1037         714 :             break;
    1038             :         case SC_COND_EQGREATER:
    1039           2 :             bValid = ( nArg >= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
    1040           2 :             break;
    1041             :         case SC_COND_LESS:
    1042           8 :             bValid = ( nArg < nComp1 ) && !::rtl::math::approxEqual( nArg, nComp1 );
    1043           8 :             break;
    1044             :         case SC_COND_EQLESS:
    1045           0 :             bValid = ( nArg <= nComp1 ) || ::rtl::math::approxEqual( nArg, nComp1 );
    1046           0 :             break;
    1047             :         case SC_COND_BETWEEN:
    1048         100 :             bValid = ( nArg >= nComp1 && nArg <= nComp2 ) ||
    1049         130 :                      ::rtl::math::approxEqual( nArg, nComp1 ) || ::rtl::math::approxEqual( nArg, nComp2 );
    1050          98 :             break;
    1051             :         case SC_COND_NOTBETWEEN:
    1052           6 :             bValid = ( nArg < nComp1 || nArg > nComp2 ) &&
    1053           8 :                      !::rtl::math::approxEqual( nArg, nComp1 ) && !::rtl::math::approxEqual( nArg, nComp2 );
    1054           4 :             break;
    1055             :         case SC_COND_DUPLICATE:
    1056             :         case SC_COND_NOTDUPLICATE:
    1057           0 :             if( pCondFormat )
    1058             :             {
    1059           0 :                 bValid = IsDuplicate( nArg, OUString() );
    1060           0 :                 if( eOp == SC_COND_NOTDUPLICATE )
    1061           0 :                     bValid = !bValid;
    1062             :             }
    1063           0 :             break;
    1064             :         case SC_COND_DIRECT:
    1065          14 :             bValid = !::rtl::math::approxEqual( nComp1, 0.0 );
    1066          14 :             break;
    1067             :         case SC_COND_TOP10:
    1068         146 :             bValid = IsTopNElement( nArg );
    1069         146 :             break;
    1070             :         case SC_COND_BOTTOM10:
    1071         147 :             bValid = IsBottomNElement( nArg );
    1072         147 :             break;
    1073             :         case SC_COND_TOP_PERCENT:
    1074         147 :             bValid = IsTopNPercent( nArg );
    1075         147 :             break;
    1076             :         case SC_COND_BOTTOM_PERCENT:
    1077         147 :             bValid = IsBottomNPercent( nArg );
    1078         147 :             break;
    1079             :         case SC_COND_ABOVE_AVERAGE:
    1080             :         case SC_COND_ABOVE_EQUAL_AVERAGE:
    1081         231 :             bValid = IsAboveAverage( nArg, eOp == SC_COND_ABOVE_EQUAL_AVERAGE );
    1082         231 :             break;
    1083             :         case SC_COND_BELOW_AVERAGE:
    1084             :         case SC_COND_BELOW_EQUAL_AVERAGE:
    1085         168 :             bValid = IsBelowAverage( nArg, eOp == SC_COND_BELOW_EQUAL_AVERAGE );
    1086         168 :             break;
    1087             :         case SC_COND_ERROR:
    1088             :         case SC_COND_NOERROR:
    1089           0 :             bValid = IsError( rPos );
    1090           0 :             if( eOp == SC_COND_NOERROR )
    1091           0 :                 bValid = !bValid;
    1092           0 :             break;
    1093             :         case SC_COND_BEGINS_WITH:
    1094           0 :             if(aStrVal1.isEmpty())
    1095             :             {
    1096           0 :                 OUString aStr = OUString::number(nVal1);
    1097           0 :                 OUString aStr2 = OUString::number(nArg);
    1098           0 :                 bValid = aStr2.startsWith(aStr);
    1099             :             }
    1100             :             else
    1101             :             {
    1102           0 :                 OUString aStr2 = OUString::number(nArg);
    1103           0 :                 bValid = aStr2.startsWith(aStrVal1);
    1104             :             }
    1105           0 :             break;
    1106             :         case SC_COND_ENDS_WITH:
    1107           0 :             if(aStrVal1.isEmpty())
    1108             :             {
    1109           0 :                 OUString aStr = OUString::number(nVal1);
    1110           0 :                 OUString aStr2 = OUString::number(nArg);
    1111           0 :                 bValid = !aStr2.endsWith(aStr);
    1112             :             }
    1113             :             else
    1114             :             {
    1115           0 :                 OUString aStr2 = OUString::number(nArg);
    1116           0 :                 bValid = !aStr2.endsWith(aStrVal1);
    1117             :             }
    1118           0 :             break;
    1119             :         case SC_COND_CONTAINS_TEXT:
    1120             :         case SC_COND_NOT_CONTAINS_TEXT:
    1121           0 :             if(aStrVal1.isEmpty())
    1122             :             {
    1123           0 :                 OUString aStr = OUString::number(nVal1);
    1124           0 :                 OUString aStr2 = OUString::number(nArg);
    1125           0 :                 bValid = aStr2.indexOf(aStr) != -1;
    1126             :             }
    1127             :             else
    1128             :             {
    1129           0 :                 OUString aStr2 = OUString::number(nArg);
    1130           0 :                 bValid = aStr2.indexOf(aStrVal1) != -1;
    1131             :             }
    1132             : 
    1133           0 :             if( eOp == SC_COND_NOT_CONTAINS_TEXT )
    1134           0 :                 bValid = !bValid;
    1135           0 :             break;
    1136             :         default:
    1137             :             SAL_WARN("sc", "unknown operation at ScConditionEntry");
    1138           0 :             break;
    1139             :     }
    1140        3499 :     return bValid;
    1141             : }
    1142             : 
    1143           1 : bool ScConditionEntry::IsValidStr( const OUString& rArg, const ScAddress& rPos ) const
    1144             : {
    1145           1 :     bool bValid = false;
    1146             :     // Interpret must already have been called
    1147           1 :     if ( eOp == SC_COND_DIRECT ) // Formula is independent from the content
    1148           0 :         return !::rtl::math::approxEqual( nVal1, 0.0 );
    1149             : 
    1150           1 :     if ( eOp == SC_COND_DUPLICATE || eOp == SC_COND_NOTDUPLICATE )
    1151             :     {
    1152           0 :         if( pCondFormat && !rArg.isEmpty() )
    1153             :         {
    1154           0 :             bValid = IsDuplicate( 0.0, rArg );
    1155           0 :             if( eOp == SC_COND_NOTDUPLICATE )
    1156           0 :                 bValid = !bValid;
    1157           0 :             return bValid;
    1158             :         }
    1159             :     }
    1160             : 
    1161             :     // If number contains condition, always false, except for "not equal".
    1162           1 :     if ( !bIsStr1 && (eOp != SC_COND_ERROR && eOp != SC_COND_NOERROR) )
    1163           0 :         return ( eOp == SC_COND_NOTEQUAL );
    1164           1 :     if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
    1165           0 :         if ( !bIsStr2 )
    1166           0 :             return false;
    1167             : 
    1168           1 :     OUString aUpVal1( aStrVal1 ); //TODO: As a member? (Also set in Interpret)
    1169           2 :     OUString aUpVal2( aStrVal2 );
    1170             : 
    1171           1 :     if ( eOp == SC_COND_BETWEEN || eOp == SC_COND_NOTBETWEEN )
    1172           0 :         if (ScGlobal::GetCollator()->compareString( aUpVal1, aUpVal2 ) > 0)
    1173             :         {
    1174             :             // Right order for value range
    1175           0 :             OUString aTemp( aUpVal1 ); aUpVal1 = aUpVal2; aUpVal2 = aTemp;
    1176             :         }
    1177             : 
    1178           1 :     switch ( eOp )
    1179             :     {
    1180             :         case SC_COND_EQUAL:
    1181             :             bValid = (ScGlobal::GetCollator()->compareString(
    1182           0 :                 rArg, aUpVal1 ) == 0);
    1183           0 :         break;
    1184             :         case SC_COND_NOTEQUAL:
    1185             :             bValid = (ScGlobal::GetCollator()->compareString(
    1186           0 :                 rArg, aUpVal1 ) != 0);
    1187           0 :         break;
    1188             :         case SC_COND_TOP_PERCENT:
    1189             :         case SC_COND_BOTTOM_PERCENT:
    1190             :         case SC_COND_TOP10:
    1191             :         case SC_COND_BOTTOM10:
    1192             :         case SC_COND_ABOVE_AVERAGE:
    1193             :         case SC_COND_BELOW_AVERAGE:
    1194           0 :             return false;
    1195             :         case SC_COND_ERROR:
    1196             :         case SC_COND_NOERROR:
    1197           0 :             bValid = IsError( rPos );
    1198           0 :             if(eOp == SC_COND_NOERROR)
    1199           0 :                 bValid = !bValid;
    1200           0 :         break;
    1201             :         case SC_COND_BEGINS_WITH:
    1202           0 :             bValid = rArg.startsWith(aUpVal1);
    1203           0 :         break;
    1204             :         case SC_COND_ENDS_WITH:
    1205           0 :             bValid = rArg.endsWith(aUpVal1);
    1206           0 :         break;
    1207             :         case SC_COND_CONTAINS_TEXT:
    1208             :         case SC_COND_NOT_CONTAINS_TEXT:
    1209           1 :             bValid = rArg.indexOf(aUpVal1) != -1;
    1210           1 :             if(eOp == SC_COND_NOT_CONTAINS_TEXT)
    1211           0 :                 bValid = !bValid;
    1212           1 :         break;
    1213             :         default:
    1214             :         {
    1215             :             sal_Int32 nCompare = ScGlobal::GetCollator()->compareString(
    1216           0 :                 rArg, aUpVal1 );
    1217           0 :             switch ( eOp )
    1218             :             {
    1219             :                 case SC_COND_GREATER:
    1220           0 :                     bValid = ( nCompare > 0 );
    1221           0 :                     break;
    1222             :                 case SC_COND_EQGREATER:
    1223           0 :                     bValid = ( nCompare >= 0 );
    1224           0 :                     break;
    1225             :                 case SC_COND_LESS:
    1226           0 :                     bValid = ( nCompare < 0 );
    1227           0 :                     break;
    1228             :                 case SC_COND_EQLESS:
    1229           0 :                     bValid = ( nCompare <= 0 );
    1230           0 :                     break;
    1231             :                 case SC_COND_BETWEEN:
    1232             :                 case SC_COND_NOTBETWEEN:
    1233             :                     //  Test for NOTBETWEEN:
    1234           0 :                     bValid = ( nCompare < 0 ||
    1235             :                         ScGlobal::GetCollator()->compareString( rArg,
    1236           0 :                         aUpVal2 ) > 0 );
    1237           0 :                     if ( eOp == SC_COND_BETWEEN )
    1238           0 :                         bValid = !bValid;
    1239           0 :                     break;
    1240             :                 //  SC_COND_DIRECT already handled above
    1241             :                 default:
    1242             :                     SAL_WARN("sc", "unknown operation in ScConditionEntry");
    1243           0 :                     bValid = false;
    1244           0 :                     break;
    1245             :             }
    1246             :         }
    1247             :     }
    1248           2 :     return bValid;
    1249             : }
    1250             : 
    1251        3500 : bool ScConditionEntry::IsCellValid( ScRefCellValue& rCell, const ScAddress& rPos ) const
    1252             : {
    1253        3500 :     const_cast<ScConditionEntry*>(this)->Interpret(rPos); // Evaluate formula
    1254             : 
    1255        3500 :     double nArg = 0.0;
    1256        3500 :     OUString aArgStr;
    1257        3500 :     bool bVal = lcl_GetCellContent( rCell, bIsStr1, nArg, aArgStr, mpDoc );
    1258        3500 :     if (bVal)
    1259        3499 :         return IsValid( nArg, rPos );
    1260             :     else
    1261           1 :         return IsValidStr( aArgStr, rPos );
    1262             : }
    1263             : 
    1264         305 : OUString ScConditionEntry::GetExpression( const ScAddress& rCursor, sal_uInt16 nIndex,
    1265             :                                         sal_uLong nNumFmt,
    1266             :                                         const FormulaGrammar::Grammar eGrammar ) const
    1267             : {
    1268             :     assert( nIndex <= 1);
    1269         305 :     OUString aRet;
    1270             : 
    1271         305 :     if ( FormulaGrammar::isEnglish( eGrammar) && nNumFmt == 0 )
    1272         280 :         nNumFmt = mpDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US );
    1273             : 
    1274         305 :     if ( nIndex==0 )
    1275             :     {
    1276         161 :         if ( pFormula1 )
    1277             :         {
    1278          65 :             ScCompiler aComp(mpDoc, rCursor, *pFormula1);
    1279          65 :             aComp.SetGrammar(eGrammar);
    1280         130 :             OUStringBuffer aBuffer;
    1281          65 :             aComp.CreateStringFromTokenArray( aBuffer );
    1282         130 :             aRet = aBuffer.makeStringAndClear();
    1283             :         }
    1284          96 :         else if (bIsStr1)
    1285             :         {
    1286           0 :             aRet = "\"";
    1287           0 :             aRet += aStrVal1;
    1288           0 :             aRet += "\"";
    1289             :         }
    1290             :         else
    1291          96 :             mpDoc->GetFormatTable()->GetInputLineString(nVal1, nNumFmt, aRet);
    1292             :     }
    1293         144 :     else if ( nIndex==1 )
    1294             :     {
    1295         144 :         if ( pFormula2 )
    1296             :         {
    1297          11 :             ScCompiler aComp(mpDoc, rCursor, *pFormula2);
    1298          11 :             aComp.SetGrammar(eGrammar);
    1299          22 :             OUStringBuffer aBuffer;
    1300          11 :             aComp.CreateStringFromTokenArray( aBuffer );
    1301          22 :             aRet = aBuffer.makeStringAndClear();
    1302             :         }
    1303         133 :         else if (bIsStr2)
    1304             :         {
    1305           0 :             aRet = "\"";
    1306           0 :             aRet += aStrVal2;
    1307           0 :             aRet += "\"";
    1308             :         }
    1309             :         else
    1310         133 :             mpDoc->GetFormatTable()->GetInputLineString(nVal2, nNumFmt, aRet);
    1311             :     }
    1312             : 
    1313         305 :     return aRet;
    1314             : }
    1315             : 
    1316          21 : ScTokenArray* ScConditionEntry::CreateTokenArry( sal_uInt16 nIndex ) const
    1317             : {
    1318             :     assert(nIndex <= 1);
    1319          21 :     ScTokenArray* pRet = NULL;
    1320          21 :     ScAddress aAddr;
    1321             : 
    1322          21 :     if ( nIndex==0 )
    1323             :     {
    1324          21 :         if ( pFormula1 )
    1325           9 :             pRet = new ScTokenArray( *pFormula1 );
    1326             :         else
    1327             :         {
    1328          12 :             pRet = new ScTokenArray();
    1329          12 :             if (bIsStr1)
    1330             :             {
    1331           0 :                 svl::SharedStringPool& rSPool = mpDoc->GetSharedStringPool();
    1332           0 :                 pRet->AddString(rSPool.intern(aStrVal1));
    1333             :             }
    1334             :             else
    1335          12 :                 pRet->AddDouble( nVal1 );
    1336             :         }
    1337             :     }
    1338           0 :     else if ( nIndex==1 )
    1339             :     {
    1340           0 :         if ( pFormula2 )
    1341           0 :             pRet = new ScTokenArray( *pFormula2 );
    1342             :         else
    1343             :         {
    1344           0 :             pRet = new ScTokenArray();
    1345           0 :             if (bIsStr2)
    1346             :             {
    1347           0 :                 svl::SharedStringPool& rSPool = mpDoc->GetSharedStringPool();
    1348           0 :                 pRet->AddString(rSPool.intern(aStrVal2));
    1349             :             }
    1350             :             else
    1351           0 :                 pRet->AddDouble( nVal2 );
    1352             :         }
    1353             :     }
    1354             : 
    1355          21 :     return pRet;
    1356             : }
    1357             : 
    1358          94 : void ScConditionEntry::SourceChanged( const ScAddress& rChanged )
    1359             : {
    1360         282 :     for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
    1361             :     {
    1362         188 :         ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
    1363         188 :         if (pFormula)
    1364             :         {
    1365         141 :             pFormula->Reset();
    1366             :             formula::FormulaToken* t;
    1367         423 :             while ( ( t = pFormula->GetNextReference() ) != NULL )
    1368             :             {
    1369         141 :                 SingleDoubleRefProvider aProv( *t );
    1370         423 :                 if ( aProv.Ref1.IsColRel() || aProv.Ref1.IsRowRel() || aProv.Ref1.IsTabRel() ||
    1371         141 :                      aProv.Ref2.IsColRel() || aProv.Ref2.IsRowRel() || aProv.Ref2.IsTabRel() )
    1372             :                 {
    1373             :                     // Absolute must be reached, relative determines range
    1374         141 :                     bool bHit = true;
    1375             :                     SCsCOL nCol1;
    1376             :                     SCsROW nRow1;
    1377             :                     SCsTAB nTab1;
    1378             :                     SCsCOL nCol2;
    1379             :                     SCsROW nRow2;
    1380             :                     SCsTAB nTab2;
    1381             : 
    1382         141 :                     if ( aProv.Ref1.IsColRel() )
    1383           0 :                         nCol2 = rChanged.Col() - aProv.Ref1.Col();
    1384             :                     else
    1385             :                     {
    1386         141 :                         bHit &= (rChanged.Col() >= aProv.Ref1.Col());
    1387         141 :                         nCol2 = MAXCOL;
    1388             :                     }
    1389         141 :                     if ( aProv.Ref1.IsRowRel() )
    1390           0 :                         nRow2 = rChanged.Row() - aProv.Ref1.Row();
    1391             :                     else
    1392             :                     {
    1393         141 :                         bHit &= ( rChanged.Row() >= aProv.Ref1.Row() );
    1394         141 :                         nRow2 = MAXROW;
    1395             :                     }
    1396         141 :                     if ( aProv.Ref1.IsTabRel() )
    1397         141 :                         nTab2 = rChanged.Tab() - aProv.Ref1.Tab();
    1398             :                     else
    1399             :                     {
    1400           0 :                         bHit &= (rChanged.Tab() >= aProv.Ref1.Tab());
    1401           0 :                         nTab2 = MAXTAB;
    1402             :                     }
    1403             : 
    1404         141 :                     if ( aProv.Ref2.IsColRel() )
    1405           0 :                         nCol1 = rChanged.Col() - aProv.Ref2.Col();
    1406             :                     else
    1407             :                     {
    1408         141 :                         bHit &= ( rChanged.Col() <= aProv.Ref2.Col() );
    1409         141 :                         nCol1 = 0;
    1410             :                     }
    1411         141 :                     if ( aProv.Ref2.IsRowRel() )
    1412           0 :                         nRow1 = rChanged.Row() - aProv.Ref2.Row();
    1413             :                     else
    1414             :                     {
    1415         141 :                         bHit &= (rChanged.Row() <= aProv.Ref2.Row());
    1416         141 :                         nRow1 = 0;
    1417             :                     }
    1418         141 :                     if ( aProv.Ref2.IsTabRel() )
    1419         141 :                         nTab1 = rChanged.Tab() - aProv.Ref2.Tab();
    1420             :                     else
    1421             :                     {
    1422           0 :                         bHit &= (rChanged.Tab() <= aProv.Ref2.Tab());
    1423           0 :                         nTab1 = 0;
    1424             :                     }
    1425             : 
    1426         141 :                     if ( bHit )
    1427             :                     {
    1428             :                         // Limit paint!
    1429          11 :                         ScRange aPaint( nCol1,nRow1,nTab1, nCol2,nRow2,nTab2 );
    1430             : 
    1431             :                         // No paint if it's the cell itself
    1432          11 :                         if ( aPaint.IsValid() && (aPaint.aStart != rChanged || aPaint.aEnd != rChanged ))
    1433          11 :                             DataChanged( &aPaint );
    1434             :                     }
    1435             :                 }
    1436         141 :             }
    1437             :         }
    1438             :     }
    1439          94 : }
    1440             : 
    1441             : /**
    1442             :  * Return a position that's adjusted to allow textual representation
    1443             :  * of expressions if possible
    1444             :  */
    1445          76 : ScAddress ScConditionEntry::GetValidSrcPos() const
    1446             : {
    1447          76 :     SCTAB nMinTab = aSrcPos.Tab();
    1448          76 :     SCTAB nMaxTab = nMinTab;
    1449             : 
    1450         228 :     for (sal_uInt16 nPass = 0; nPass < 2; nPass++)
    1451             :     {
    1452         152 :         ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
    1453         152 :         if (pFormula)
    1454             :         {
    1455           8 :             pFormula->Reset();
    1456             :             formula::FormulaToken* t;
    1457          22 :             while ( ( t = pFormula->GetNextReference() ) != NULL )
    1458             :             {
    1459           6 :                 ScSingleRefData& rRef1 = *t->GetSingleRef();
    1460           6 :                 ScAddress aAbs = rRef1.toAbs(aSrcPos);
    1461           6 :                 if (!rRef1.IsTabDeleted())
    1462             :                 {
    1463           6 :                     if (aAbs.Tab() < nMinTab)
    1464           0 :                         nMinTab = aAbs.Tab();
    1465           6 :                     if (aAbs.Tab() > nMaxTab)
    1466           0 :                         nMaxTab = aAbs.Tab();
    1467             :                 }
    1468           6 :                 if ( t->GetType() == svDoubleRef )
    1469             :                 {
    1470           2 :                     ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
    1471           2 :                     aAbs = rRef2.toAbs(aSrcPos);
    1472           2 :                     if (!rRef2.IsTabDeleted())
    1473             :                     {
    1474           2 :                         if (aAbs.Tab() < nMinTab)
    1475           0 :                             nMinTab = aAbs.Tab();
    1476           2 :                         if (aAbs.Tab() > nMaxTab)
    1477           0 :                             nMaxTab = aAbs.Tab();
    1478             :                     }
    1479             :                 }
    1480             :             }
    1481             :         }
    1482             :     }
    1483             : 
    1484          76 :     ScAddress aValidPos = aSrcPos;
    1485          76 :     SCTAB nTabCount = mpDoc->GetTableCount();
    1486          76 :     if ( nMaxTab >= nTabCount && nMinTab > 0 )
    1487           0 :         aValidPos.SetTab( aSrcPos.Tab() - nMinTab ); // so the lowest tab ref will be on 0
    1488             : 
    1489          76 :     if ( aValidPos.Tab() >= nTabCount )
    1490           0 :         aValidPos.SetTab( nTabCount - 1 );  // ensure a valid position even if some references will be invalid
    1491             : 
    1492          76 :     return aValidPos;
    1493             : }
    1494             : 
    1495           0 : void ScConditionEntry::DataChanged( const ScRange* /* pModified */ ) const
    1496             : {
    1497             :     //FIXME: Nothing so far
    1498           0 : }
    1499             : 
    1500           0 : bool ScConditionEntry::MarkUsedExternalReferences() const
    1501             : {
    1502           0 :     bool bAllMarked = false;
    1503           0 :     for (sal_uInt16 nPass = 0; !bAllMarked && nPass < 2; nPass++)
    1504             :     {
    1505           0 :         ScTokenArray* pFormula = nPass ? pFormula2 : pFormula1;
    1506           0 :         if (pFormula)
    1507           0 :             bAllMarked = mpDoc->MarkUsedExternalReferences(*pFormula, aSrcPos);
    1508             :     }
    1509           0 :     return bAllMarked;
    1510             : }
    1511             : 
    1512           0 : ScFormatEntry* ScConditionEntry::Clone(ScDocument* pDoc) const
    1513             : {
    1514           0 :     return new ScConditionEntry(pDoc, *this);
    1515             : }
    1516             : 
    1517          59 : ScConditionMode ScConditionEntry::GetModeFromApi(sal_Int32 nOperation)
    1518             : {
    1519          59 :     ScConditionMode eMode = SC_COND_NONE;
    1520          59 :     switch (nOperation)
    1521             :     {
    1522             :         case com::sun::star::sheet::ConditionOperator2::EQUAL:
    1523          18 :             eMode = SC_COND_EQUAL;
    1524          18 :             break;
    1525             :         case com::sun::star::sheet::ConditionOperator2::LESS:
    1526           3 :             eMode = SC_COND_LESS;
    1527           3 :             break;
    1528             :         case com::sun::star::sheet::ConditionOperator2::GREATER:
    1529           7 :             eMode = SC_COND_GREATER;
    1530           7 :             break;
    1531             :         case com::sun::star::sheet::ConditionOperator2::LESS_EQUAL:
    1532           0 :             eMode = SC_COND_EQLESS;
    1533           0 :             break;
    1534             :         case com::sun::star::sheet::ConditionOperator2::GREATER_EQUAL:
    1535           6 :             eMode = SC_COND_EQGREATER;
    1536           6 :             break;
    1537             :         case com::sun::star::sheet::ConditionOperator2::NOT_EQUAL:
    1538           0 :             eMode = SC_COND_NOTEQUAL;
    1539           0 :             break;
    1540             :         case com::sun::star::sheet::ConditionOperator2::BETWEEN:
    1541          13 :             eMode = SC_COND_BETWEEN;
    1542          13 :             break;
    1543             :         case com::sun::star::sheet::ConditionOperator2::NOT_BETWEEN:
    1544           6 :             eMode = SC_COND_NOTBETWEEN;
    1545           6 :             break;
    1546             :         case com::sun::star::sheet::ConditionOperator2::FORMULA:
    1547           6 :             eMode = SC_COND_DIRECT;
    1548           6 :             break;
    1549             :         case com::sun::star::sheet::ConditionOperator2::DUPLICATE:
    1550           0 :             eMode = SC_COND_DUPLICATE;
    1551           0 :             break;
    1552             :         case com::sun::star::sheet::ConditionOperator2::NOT_DUPLICATE:
    1553           0 :             eMode = SC_COND_NOTDUPLICATE;
    1554           0 :             break;
    1555             :         default:
    1556           0 :             break;
    1557             :     }
    1558          59 :     return eMode;
    1559             : }
    1560             : 
    1561         169 : void ScConditionEntry::startRendering()
    1562             : {
    1563         169 :     mpCache.reset();
    1564         169 : }
    1565             : 
    1566         169 : void ScConditionEntry::endRendering()
    1567             : {
    1568         169 :     mpCache.reset();
    1569         169 : }
    1570             : 
    1571         119 : ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
    1572             :                                         const OUString& rExpr1, const OUString& rExpr2,
    1573             :                                         ScDocument* pDocument, const ScAddress& rPos,
    1574             :                                         const OUString& rStyle,
    1575             :                                         const OUString& rExprNmsp1, const OUString& rExprNmsp2,
    1576             :                                         FormulaGrammar::Grammar eGrammar1,
    1577             :                                         FormulaGrammar::Grammar eGrammar2 ) :
    1578             :     ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ),
    1579         119 :     aStyleName( rStyle )
    1580             : {
    1581         119 : }
    1582             : 
    1583          33 : ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper,
    1584             :                                         const ScTokenArray* pArr1, const ScTokenArray* pArr2,
    1585             :                                         ScDocument* pDocument, const ScAddress& rPos,
    1586             :                                         const OUString& rStyle ) :
    1587             :     ScConditionEntry( eOper, pArr1, pArr2, pDocument, rPos ),
    1588          33 :     aStyleName( rStyle )
    1589             : {
    1590          33 : }
    1591             : 
    1592           0 : ScCondFormatEntry::ScCondFormatEntry( const ScCondFormatEntry& r ) :
    1593             :     ScConditionEntry( r ),
    1594           0 :     aStyleName( r.aStyleName )
    1595             : {
    1596           0 : }
    1597             : 
    1598          58 : ScCondFormatEntry::ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r ) :
    1599             :     ScConditionEntry( pDocument, r ),
    1600          58 :     aStyleName( r.aStyleName )
    1601             : {
    1602          58 : }
    1603             : 
    1604           0 : bool ScCondFormatEntry::operator== ( const ScCondFormatEntry& r ) const
    1605             : {
    1606           0 :     return ScConditionEntry::operator==( r ) &&
    1607           0 :             aStyleName == r.aStyleName;
    1608             : }
    1609             : 
    1610         414 : ScCondFormatEntry::~ScCondFormatEntry()
    1611             : {
    1612         414 : }
    1613             : 
    1614          11 : void ScCondFormatEntry::DataChanged( const ScRange* pModified ) const
    1615             : {
    1616          11 :     if ( pCondFormat )
    1617          11 :         pCondFormat->DoRepaint( pModified );
    1618          11 : }
    1619             : 
    1620          58 : ScFormatEntry* ScCondFormatEntry::Clone( ScDocument* pDoc ) const
    1621             : {
    1622          58 :     return new ScCondFormatEntry( pDoc, *this );
    1623             : }
    1624             : 
    1625           4 : ScCondDateFormatEntry::ScCondDateFormatEntry( ScDocument* pDoc )
    1626             :     : ScFormatEntry( pDoc )
    1627           4 :     , meType(condformat::TODAY)
    1628             : {
    1629           4 : }
    1630             : 
    1631           0 : ScCondDateFormatEntry::ScCondDateFormatEntry( ScDocument* pDoc, const ScCondDateFormatEntry& rFormat ):
    1632             :     ScFormatEntry( pDoc ),
    1633             :     meType( rFormat.meType ),
    1634           0 :     maStyleName( rFormat.maStyleName )
    1635             : {
    1636           0 : }
    1637             : 
    1638           0 : bool ScCondDateFormatEntry::IsValid( const ScAddress& rPos ) const
    1639             : {
    1640           0 :     CellType eCellType = mpDoc->GetCellType(rPos);
    1641             : 
    1642           0 :     if (eCellType == CELLTYPE_NONE)
    1643             :         // empty cell.
    1644           0 :         return false;
    1645             : 
    1646           0 :     if (eCellType != CELLTYPE_VALUE && eCellType != CELLTYPE_FORMULA)
    1647             :         // non-numerical cell.
    1648           0 :         return false;
    1649             : 
    1650           0 :     if( !mpCache )
    1651           0 :         mpCache.reset( new Date( Date::SYSTEM ) );
    1652             : 
    1653           0 :     const Date& rActDate = *mpCache;
    1654           0 :     SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
    1655           0 :     long nCurrentDate = rActDate - *(pFormatter->GetNullDate());
    1656             : 
    1657           0 :     double nVal = mpDoc->GetValue(rPos);
    1658           0 :     long nCellDate = (long) ::rtl::math::approxFloor(nVal);
    1659           0 :     Date aCellDate = *(pFormatter->GetNullDate());
    1660           0 :     aCellDate += (long) ::rtl::math::approxFloor(nVal);
    1661             : 
    1662           0 :     switch(meType)
    1663             :     {
    1664             :         case condformat::TODAY:
    1665           0 :             if( nCurrentDate == nCellDate )
    1666           0 :                 return true;
    1667           0 :             break;
    1668             :         case condformat::TOMORROW:
    1669           0 :             if( nCurrentDate == nCellDate -1 )
    1670           0 :                 return true;
    1671           0 :             break;
    1672             :         case condformat::YESTERDAY:
    1673           0 :             if( nCurrentDate == nCellDate + 1)
    1674           0 :                 return true;
    1675           0 :             break;
    1676             :         case condformat::LAST7DAYS:
    1677           0 :             if( nCurrentDate >= nCellDate && nCurrentDate - 7 < nCellDate )
    1678           0 :                 return true;
    1679           0 :             break;
    1680             :         case condformat::LASTWEEK:
    1681           0 :             if( rActDate.GetDayOfWeek() != SUNDAY )
    1682             :             {
    1683           0 :                 Date aBegin(rActDate - 8 - static_cast<long>(rActDate.GetDayOfWeek()));
    1684           0 :                 Date aEnd(rActDate - 2 -static_cast<long>(rActDate.GetDayOfWeek()));
    1685           0 :                 return aCellDate.IsBetween( aBegin, aEnd );
    1686             :             }
    1687             :             else
    1688             :             {
    1689           0 :                 Date aBegin(rActDate - 8);
    1690           0 :                 Date aEnd(rActDate - 1);
    1691           0 :                 return aCellDate.IsBetween( aBegin, aEnd );
    1692             :             }
    1693             :             break;
    1694             :         case condformat::THISWEEK:
    1695           0 :             if( rActDate.GetDayOfWeek() != SUNDAY )
    1696             :             {
    1697           0 :                 Date aBegin(rActDate - 1 - static_cast<long>(rActDate.GetDayOfWeek()));
    1698           0 :                 Date aEnd(rActDate + 5 - static_cast<long>(rActDate.GetDayOfWeek()));
    1699           0 :                 return aCellDate.IsBetween( aBegin, aEnd );
    1700             :             }
    1701             :             else
    1702             :             {
    1703           0 :                 Date aEnd( rActDate + 6);
    1704           0 :                 return aCellDate.IsBetween( rActDate, aEnd );
    1705             :             }
    1706             :             break;
    1707             :         case condformat::NEXTWEEK:
    1708           0 :             if( rActDate.GetDayOfWeek() != SUNDAY )
    1709             :             {
    1710           0 :                 return aCellDate.IsBetween( rActDate + 6 - static_cast<long>(rActDate.GetDayOfWeek()), rActDate + 12 - static_cast<long>(rActDate.GetDayOfWeek()) );
    1711             :             }
    1712             :             else
    1713             :             {
    1714           0 :                 return aCellDate.IsBetween( rActDate + 7, rActDate + 13 );
    1715             :             }
    1716             :             break;
    1717             :         case condformat::LASTMONTH:
    1718           0 :             if( rActDate.GetMonth() == 1 )
    1719             :             {
    1720           0 :                 if( aCellDate.GetMonth() == 12 && rActDate.GetYear() == aCellDate.GetYear() + 1 )
    1721           0 :                     return true;
    1722             :             }
    1723           0 :             else if( rActDate.GetYear() == aCellDate.GetYear() )
    1724             :             {
    1725           0 :                 if( rActDate.GetMonth() == aCellDate.GetMonth() + 1)
    1726           0 :                     return true;
    1727             :             }
    1728           0 :             break;
    1729             :         case condformat::THISMONTH:
    1730           0 :             if( rActDate.GetYear() == aCellDate.GetYear() )
    1731             :             {
    1732           0 :                 if( rActDate.GetMonth() == aCellDate.GetMonth() )
    1733           0 :                     return true;
    1734             :             }
    1735           0 :             break;
    1736             :         case condformat::NEXTMONTH:
    1737           0 :             if( rActDate.GetMonth() == 12 )
    1738             :             {
    1739           0 :                 if( aCellDate.GetMonth() == 1 && rActDate.GetYear() == aCellDate.GetYear() - 1 )
    1740           0 :                     return true;
    1741             :             }
    1742           0 :             else if( rActDate.GetYear() == aCellDate.GetYear() )
    1743             :             {
    1744           0 :                 if( rActDate.GetMonth() == aCellDate.GetMonth() - 1)
    1745           0 :                     return true;
    1746             :             }
    1747           0 :             break;
    1748             :         case condformat::LASTYEAR:
    1749           0 :             if( rActDate.GetYear() == aCellDate.GetYear() + 1 )
    1750           0 :                 return true;
    1751           0 :             break;
    1752             :         case condformat::THISYEAR:
    1753           0 :             if( rActDate.GetYear() == aCellDate.GetYear() )
    1754           0 :                 return true;
    1755           0 :             break;
    1756             :         case condformat::NEXTYEAR:
    1757           0 :             if( rActDate.GetYear() == aCellDate.GetYear() - 1 )
    1758           0 :                 return true;
    1759           0 :             break;
    1760             :     }
    1761             : 
    1762           0 :     return false;
    1763             : }
    1764             : 
    1765           4 : void ScCondDateFormatEntry::SetDateType( condformat::ScCondFormatDateType eType )
    1766             : {
    1767           4 :     meType = eType;
    1768           4 : }
    1769             : 
    1770           4 : void ScCondDateFormatEntry::SetStyleName( const OUString& rStyleName )
    1771             : {
    1772           4 :     maStyleName = rStyleName;
    1773           4 : }
    1774             : 
    1775           0 : ScFormatEntry* ScCondDateFormatEntry::Clone( ScDocument* pDoc ) const
    1776             : {
    1777           0 :     return new ScCondDateFormatEntry( pDoc, *this );
    1778             : }
    1779             : 
    1780           0 : bool ScCondDateFormatEntry::operator==( const ScFormatEntry& r ) const
    1781             : {
    1782           0 :     if(r.GetType() != condformat::DATE)
    1783           0 :         return false;
    1784             : 
    1785           0 :     const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(r);
    1786             : 
    1787           0 :     if(rEntry.meType != meType)
    1788           0 :         return false;
    1789             : 
    1790           0 :     return rEntry.maStyleName == maStyleName;
    1791             : }
    1792             : 
    1793           0 : void ScCondDateFormatEntry::startRendering()
    1794             : {
    1795           0 :     mpCache.reset();
    1796           0 : }
    1797             : 
    1798           0 : void ScCondDateFormatEntry::endRendering()
    1799             : {
    1800           0 :     mpCache.reset();
    1801           0 : }
    1802             : 
    1803         250 : ScConditionalFormat::ScConditionalFormat(sal_uInt32 nNewKey, ScDocument* pDocument) :
    1804             :     pDoc( pDocument ),
    1805         250 :     nKey( nNewKey )
    1806             : {
    1807         250 : }
    1808             : 
    1809          56 : ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const
    1810             : {
    1811             :     // Real copy of the formula (for Ref Undo/between documents)
    1812          56 :     if (!pNewDoc)
    1813           2 :         pNewDoc = pDoc;
    1814             : 
    1815          56 :     ScConditionalFormat* pNew = new ScConditionalFormat(nKey, pNewDoc);
    1816             : 
    1817         114 :     for (CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1818             :     {
    1819          58 :         ScFormatEntry* pNewEntry = itr->Clone(pNewDoc);
    1820          58 :         pNew->maEntries.push_back( pNewEntry );
    1821          58 :         pNewEntry->SetParent(pNew);
    1822             :     }
    1823          56 :     pNew->SetRange( maRanges );
    1824             : 
    1825          56 :     return pNew;
    1826             : }
    1827             : 
    1828           0 : bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const
    1829             : {
    1830           0 :     if( size() != r.size())
    1831           0 :         return false;
    1832             : 
    1833             :     //TODO: Test for same entries in reverse order?
    1834           0 :     for (size_t i=0; i<size(); i++)
    1835           0 :         if ( ! (maEntries == r.maEntries ) )
    1836           0 :             return false;
    1837             : 
    1838             :     // right now don't check for same range
    1839             :     // we only use this method to merge same conditional formats from
    1840             :     // old ODF data structure
    1841           0 :     return true;
    1842             : }
    1843             : 
    1844         249 : void ScConditionalFormat::SetRange( const ScRangeList& rRanges )
    1845             : {
    1846         249 :     maRanges = rRanges;
    1847             :     SAL_WARN_IF(maRanges.empty(), "sc", "the conditional format range is empty! will result in a crash later!");
    1848         249 : }
    1849             : 
    1850         260 : void ScConditionalFormat::AddEntry( ScFormatEntry* pNew )
    1851             : {
    1852         260 :     maEntries.push_back(pNew);
    1853         260 :     pNew->SetParent(this);
    1854         260 : }
    1855             : 
    1856           0 : void ScConditionalFormat::RemoveEntry(size_t n)
    1857             : {
    1858           0 :     if (n < maEntries.size())
    1859             :     {
    1860           0 :         maEntries.erase(maEntries.begin() + n);
    1861           0 :         DoRepaint(NULL);
    1862             :     }
    1863           0 : }
    1864             : 
    1865           3 : bool ScConditionalFormat::IsEmpty() const
    1866             : {
    1867           3 :     return maEntries.empty();
    1868             : }
    1869             : 
    1870       13512 : size_t ScConditionalFormat::size() const
    1871             : {
    1872       13512 :     return maEntries.size();
    1873             : }
    1874             : 
    1875         234 : ScConditionalFormat::~ScConditionalFormat()
    1876             : {
    1877         234 : }
    1878             : 
    1879        6832 : const ScFormatEntry* ScConditionalFormat::GetEntry( sal_uInt16 nPos ) const
    1880             : {
    1881        6832 :     if ( nPos < size() )
    1882        6832 :         return &maEntries[nPos];
    1883             :     else
    1884           0 :         return NULL;
    1885             : }
    1886             : 
    1887         695 : const OUString& ScConditionalFormat::GetCellStyle( ScRefCellValue& rCell, const ScAddress& rPos ) const
    1888             : {
    1889        1148 :     for (CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1890             :     {
    1891         713 :         if(itr->GetType() == condformat::CONDITION)
    1892             :         {
    1893         713 :             const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*itr);
    1894         713 :             if (rEntry.IsCellValid(rCell, rPos))
    1895         520 :                 return rEntry.GetStyle();
    1896             :         }
    1897           0 :         else if(itr->GetType() == condformat::DATE)
    1898             :         {
    1899           0 :             const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(*itr);
    1900           0 :             if (rEntry.IsValid( rPos ))
    1901           0 :                 return rEntry.GetStyleName();
    1902             :         }
    1903             :     }
    1904             : 
    1905         435 :     return EMPTY_OUSTRING;
    1906             : }
    1907             : 
    1908        2740 : ScCondFormatData ScConditionalFormat::GetData( ScRefCellValue& rCell, const ScAddress& rPos ) const
    1909             : {
    1910        2740 :     ScCondFormatData aData;
    1911        5542 :     for(CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1912             :     {
    1913        2802 :         if(itr->GetType() == condformat::CONDITION && aData.aStyleName.isEmpty())
    1914             :         {
    1915        2787 :             const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*itr);
    1916        2787 :             if (rEntry.IsCellValid(rCell, rPos))
    1917         176 :                 aData.aStyleName = rEntry.GetStyle();
    1918             :         }
    1919          15 :         else if(itr->GetType() == condformat::COLORSCALE && !aData.pColorScale)
    1920             :         {
    1921           0 :             const ScColorScaleFormat& rEntry = static_cast<const ScColorScaleFormat&>(*itr);
    1922           0 :             aData.pColorScale = rEntry.GetColor(rPos);
    1923             :         }
    1924          15 :         else if(itr->GetType() == condformat::DATABAR && !aData.pDataBar)
    1925             :         {
    1926           0 :             const ScDataBarFormat& rEntry = static_cast<const ScDataBarFormat&>(*itr);
    1927           0 :             aData.pDataBar = rEntry.GetDataBarInfo(rPos);
    1928             :         }
    1929          15 :         else if(itr->GetType() == condformat::ICONSET && !aData.pIconSet)
    1930             :         {
    1931           0 :             const ScIconSetFormat& rEntry = static_cast<const ScIconSetFormat&>(*itr);
    1932           0 :             aData.pIconSet = rEntry.GetIconSetInfo(rPos);
    1933             :         }
    1934          15 :         else if(itr->GetType() == condformat::DATE && aData.aStyleName.isEmpty())
    1935             :         {
    1936           0 :             const ScCondDateFormatEntry& rEntry = static_cast<const ScCondDateFormatEntry&>(*itr);
    1937           0 :             if ( rEntry.IsValid( rPos ) )
    1938           0 :                 aData.aStyleName = rEntry.GetStyleName();
    1939             :         }
    1940             :     }
    1941        2740 :     return aData;
    1942             : }
    1943             : 
    1944          11 : void ScConditionalFormat::DoRepaint( const ScRange* pModified )
    1945             : {
    1946          11 :     if(pModified)
    1947             :     {
    1948          11 :         if(maRanges.Intersects(*pModified))
    1949          11 :             pDoc->RepaintRange(*pModified);
    1950             :     }
    1951             :     else
    1952             :     {
    1953             :         // all conditional format cells
    1954           0 :         pDoc->RepaintRange( maRanges );
    1955             :     }
    1956          11 : }
    1957             : 
    1958           1 : void ScConditionalFormat::CompileAll()
    1959             : {
    1960           2 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1961           1 :         if(itr->GetType() == condformat::CONDITION)
    1962           1 :             static_cast<ScCondFormatEntry&>(*itr).CompileAll();
    1963           1 : }
    1964             : 
    1965          88 : void ScConditionalFormat::CompileXML()
    1966             : {
    1967         218 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1968         130 :         if(itr->GetType() == condformat::CONDITION)
    1969          69 :             static_cast<ScCondFormatEntry&>(*itr).CompileXML();
    1970          88 : }
    1971             : 
    1972          19 : void ScConditionalFormat::UpdateReference( sc::RefUpdateContext& rCxt, bool bCopyAsMove )
    1973             : {
    1974          39 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    1975          20 :         itr->UpdateReference(rCxt);
    1976             : 
    1977          19 :     if (rCxt.meMode == URM_COPY && bCopyAsMove)
    1978          12 :         maRanges.UpdateReference(URM_MOVE, pDoc, rCxt.maRange, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    1979             :     else
    1980           7 :         maRanges.UpdateReference(rCxt.meMode, pDoc, rCxt.maRange, rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    1981          19 : }
    1982             : 
    1983           1 : void ScConditionalFormat::InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize)
    1984             : {
    1985           1 :     maRanges.InsertRow(nTab, nColStart, nColEnd, nRowPos, nSize);
    1986           1 : }
    1987             : 
    1988           2 : void ScConditionalFormat::InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize)
    1989             : {
    1990           2 :     maRanges.InsertCol(nTab, nRowStart, nRowEnd, nColPos, nSize);
    1991           2 : }
    1992             : 
    1993           3 : void ScConditionalFormat::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
    1994             : {
    1995           6 :     for (size_t i = 0, n = maRanges.size(); i < n; ++i)
    1996             :     {
    1997             :         // We assume that the start and end sheet indices are equal.
    1998           3 :         ScRange* pRange = maRanges[i];
    1999           3 :         SCTAB nTab = pRange->aStart.Tab();
    2000             : 
    2001           3 :         if (nTab < rCxt.mnInsertPos)
    2002             :             // Unaffected.
    2003           1 :             continue;
    2004             : 
    2005           2 :         pRange->aStart.IncTab(rCxt.mnSheets);
    2006           2 :         pRange->aEnd.IncTab(rCxt.mnSheets);
    2007             :     }
    2008             : 
    2009           6 :     for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
    2010           3 :         it->UpdateInsertTab(rCxt);
    2011           3 : }
    2012             : 
    2013           4 : void ScConditionalFormat::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
    2014             : {
    2015           8 :     for (size_t i = 0, n = maRanges.size(); i < n; ++i)
    2016             :     {
    2017             :         // We assume that the start and end sheet indices are equal.
    2018           4 :         ScRange* pRange = maRanges[i];
    2019           4 :         SCTAB nTab = pRange->aStart.Tab();
    2020             : 
    2021           4 :         if (nTab < rCxt.mnDeletePos)
    2022             :             // Left of the deleted sheet(s).  Unaffected.
    2023           1 :             continue;
    2024             : 
    2025           3 :         if (nTab <= rCxt.mnDeletePos+rCxt.mnSheets-1)
    2026             :         {
    2027             :             // On the deleted sheet(s).
    2028           2 :             pRange->aStart.SetTab(-1);
    2029           2 :             pRange->aEnd.SetTab(-1);
    2030           2 :             continue;
    2031             :         }
    2032             : 
    2033             :         // Right of the deleted sheet(s).  Adjust the sheet indices.
    2034           1 :         pRange->aStart.IncTab(-1*rCxt.mnSheets);
    2035           1 :         pRange->aEnd.IncTab(-1*rCxt.mnSheets);
    2036             :     }
    2037             : 
    2038           8 :     for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
    2039           4 :         it->UpdateDeleteTab(rCxt);
    2040           4 : }
    2041             : 
    2042           0 : void ScConditionalFormat::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
    2043             : {
    2044           0 :     size_t n = maRanges.size();
    2045           0 :     SCTAB nMinTab = std::min<SCTAB>(rCxt.mnOldPos, rCxt.mnNewPos);
    2046           0 :     SCTAB nMaxTab = std::max<SCTAB>(rCxt.mnOldPos, rCxt.mnNewPos);
    2047           0 :     for(size_t i = 0; i < n; ++i)
    2048             :     {
    2049           0 :         ScRange* pRange = maRanges[i];
    2050           0 :         SCTAB nTab = pRange->aStart.Tab();
    2051           0 :         if(nTab < nMinTab || nTab > nMaxTab)
    2052             :         {
    2053           0 :             continue;
    2054             :         }
    2055             : 
    2056           0 :         if (nTab == rCxt.mnOldPos)
    2057             :         {
    2058           0 :             pRange->aStart.SetTab(rCxt.mnNewPos);
    2059           0 :             pRange->aEnd.SetTab(rCxt.mnNewPos);
    2060           0 :             continue;
    2061             :         }
    2062             : 
    2063           0 :         if (rCxt.mnNewPos < rCxt.mnOldPos)
    2064             :         {
    2065           0 :             pRange->aStart.IncTab();
    2066           0 :             pRange->aEnd.IncTab();
    2067             :         }
    2068             :         else
    2069             :         {
    2070           0 :             pRange->aStart.IncTab(-1);
    2071           0 :             pRange->aEnd.IncTab(-1);
    2072             :         }
    2073             :     }
    2074             : 
    2075           0 :     for (CondFormatContainer::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
    2076           0 :         it->UpdateMoveTab(rCxt);
    2077           0 : }
    2078             : 
    2079          74 : void ScConditionalFormat::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
    2080             : {
    2081          74 :     if (maRanges.empty())
    2082          74 :         return;
    2083             : 
    2084          74 :     SCTAB nTab = maRanges[0]->aStart.Tab();
    2085          74 :     maRanges.DeleteArea( nCol1, nRow1, nTab, nCol2, nRow2, nTab );
    2086             : }
    2087             : 
    2088           0 : void ScConditionalFormat::RenameCellStyle(const OUString& rOld, const OUString& rNew)
    2089             : {
    2090           0 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    2091           0 :         if(itr->GetType() == condformat::CONDITION)
    2092             :         {
    2093           0 :             ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*itr);
    2094           0 :             if(rFormat.GetStyle() == rOld)
    2095           0 :                 rFormat.UpdateStyleName( rNew );
    2096             :         }
    2097           0 : }
    2098             : 
    2099          99 : void ScConditionalFormat::SourceChanged( const ScAddress& rAddr )
    2100             : {
    2101         193 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    2102             :     {
    2103          94 :         condformat::ScFormatEntryType eEntryType = itr->GetType();
    2104          94 :         if( eEntryType == condformat::CONDITION)
    2105             :         {
    2106          94 :             ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*itr);
    2107          94 :             rFormat.SourceChanged( rAddr );
    2108             :         }
    2109           0 :         else if( eEntryType == condformat::COLORSCALE ||
    2110           0 :                 eEntryType == condformat::DATABAR ||
    2111             :                 eEntryType == condformat::ICONSET )
    2112             :         {
    2113           0 :             ScColorFormat& rFormat = static_cast<ScColorFormat&>(*itr);
    2114           0 :             if(rFormat.NeedsRepaint())
    2115             :             {
    2116             :                 // we need to repaint the whole range anyway
    2117           0 :                 DoRepaint(NULL);
    2118           0 :                 return;
    2119             :             }
    2120             :         }
    2121             :     }
    2122             : }
    2123             : 
    2124           0 : bool ScConditionalFormat::MarkUsedExternalReferences() const
    2125             : {
    2126           0 :     bool bAllMarked = false;
    2127           0 :     for(CondFormatContainer::const_iterator itr = maEntries.begin(); itr != maEntries.end() && !bAllMarked; ++itr)
    2128           0 :         if(itr->GetType() == condformat::CONDITION)
    2129             :         {
    2130           0 :             const ScCondFormatEntry& rFormat = static_cast<const ScCondFormatEntry&>(*itr);
    2131           0 :             bAllMarked = rFormat.MarkUsedExternalReferences();
    2132             :         }
    2133             : 
    2134           0 :     return bAllMarked;
    2135             : }
    2136             : 
    2137         166 : void ScConditionalFormat::startRendering()
    2138             : {
    2139         335 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    2140             :     {
    2141         169 :         itr->startRendering();
    2142             :     }
    2143         166 : }
    2144             : 
    2145         166 : void ScConditionalFormat::endRendering()
    2146             : {
    2147         335 :     for(CondFormatContainer::iterator itr = maEntries.begin(); itr != maEntries.end(); ++itr)
    2148             :     {
    2149         169 :         itr->endRendering();
    2150             :     }
    2151         166 : }
    2152             : 
    2153           0 : ScConditionalFormatList::ScConditionalFormatList(const ScConditionalFormatList& rList)
    2154             : {
    2155           0 :     for(const_iterator itr = rList.begin(); itr != rList.end(); ++itr)
    2156           0 :         InsertNew( itr->Clone() );
    2157           0 : }
    2158             : 
    2159         824 : ScConditionalFormatList::ScConditionalFormatList(ScDocument* pDoc, const ScConditionalFormatList& rList)
    2160             : {
    2161         866 :     for(const_iterator itr = rList.begin(); itr != rList.end(); ++itr)
    2162          42 :         InsertNew( itr->Clone(pDoc) );
    2163         824 : }
    2164             : 
    2165         229 : void ScConditionalFormatList::InsertNew( ScConditionalFormat* pNew )
    2166             : {
    2167         229 :     maConditionalFormats.insert(pNew);
    2168         229 : }
    2169             : 
    2170           0 : bool ScConditionalFormatList::operator==( const ScConditionalFormatList& r ) const
    2171             : {
    2172             :     // For Ref Undo - internal variables are not compared
    2173           0 :     sal_uInt16 nCount = size();
    2174           0 :     bool bEqual = ( nCount == r.size() );
    2175           0 :     const_iterator locIterator = begin();
    2176           0 :     for(const_iterator itr = r.begin(); itr != r.end() && bEqual; ++itr, ++locIterator)
    2177           0 :         if ( !locIterator->EqualEntries(*itr) ) // Entries differ?
    2178           0 :             bEqual = false;
    2179             : 
    2180           0 :     return bEqual;
    2181             : }
    2182             : 
    2183        9333 : ScConditionalFormat* ScConditionalFormatList::GetFormat( sal_uInt32 nKey )
    2184             : {
    2185             :     //FIXME: Binary search
    2186       11195 :     for( iterator itr = begin(); itr != end(); ++itr)
    2187       11195 :         if (itr->GetKey() == nKey)
    2188        9333 :             return &(*itr);
    2189             : 
    2190             :     SAL_WARN("sc", "ScConditionalFormatList: Entry not found");
    2191           0 :     return NULL;
    2192             : }
    2193             : 
    2194         695 : const ScConditionalFormat* ScConditionalFormatList::GetFormat( sal_uInt32 nKey ) const
    2195             : {
    2196             :     //FIXME: Binary search
    2197        3064 :     for ( const_iterator itr = begin(); itr != end(); ++itr)
    2198        3064 :         if (itr->GetKey() == nKey)
    2199         695 :             return &(*itr);
    2200             : 
    2201             :     SAL_WARN("sc", "ScConditionalFormatList: Entry not found");
    2202           0 :     return NULL;
    2203             : }
    2204             : 
    2205          14 : void ScConditionalFormatList::CompileAll()
    2206             : {
    2207          15 :     for( iterator itr = begin(); itr != end(); ++itr)
    2208           1 :         itr->CompileAll();
    2209          14 : }
    2210             : 
    2211         331 : void ScConditionalFormatList::CompileXML()
    2212             : {
    2213         419 :     for( iterator itr = begin(); itr != end(); ++itr)
    2214          88 :         itr->CompileXML();
    2215         331 : }
    2216             : 
    2217         258 : void ScConditionalFormatList::UpdateReference( sc::RefUpdateContext& rCxt )
    2218             : {
    2219         265 :     for( iterator itr = begin(); itr != end(); ++itr)
    2220           7 :         itr->UpdateReference(rCxt);
    2221             : 
    2222         258 :     if (rCxt.meMode == URM_INSDEL)
    2223             :     {
    2224             :         // need to check which must be deleted
    2225         184 :         CheckAllEntries();
    2226             :     }
    2227         258 : }
    2228             : 
    2229          54 : void ScConditionalFormatList::InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize)
    2230             : {
    2231          55 :     for(iterator it = begin(), itEnd = end(); it != itEnd; ++it)
    2232           1 :         it->InsertRow(nTab, nColStart, nColEnd, nRowPos, nSize);
    2233          54 : }
    2234             : 
    2235          37 : void ScConditionalFormatList::InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize)
    2236             : {
    2237          39 :     for(iterator it = begin(), itEnd = end(); it != itEnd; ++it)
    2238           2 :         it->InsertCol(nTab, nRowStart, nRowEnd, nColPos, nSize);
    2239          37 : }
    2240             : 
    2241         148 : void ScConditionalFormatList::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
    2242             : {
    2243         151 :     for (iterator it = begin(); it != end(); ++it)
    2244           3 :         it->UpdateInsertTab(rCxt);
    2245         148 : }
    2246             : 
    2247         249 : void ScConditionalFormatList::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
    2248             : {
    2249         253 :     for (iterator it = begin(); it != end(); ++it)
    2250           4 :         it->UpdateDeleteTab(rCxt);
    2251         249 : }
    2252             : 
    2253          39 : void ScConditionalFormatList::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt )
    2254             : {
    2255          39 :     for (iterator it = begin(); it != end(); ++it)
    2256           0 :         it->UpdateMoveTab(rCxt);
    2257          39 : }
    2258             : 
    2259           0 : void ScConditionalFormatList::RenameCellStyle( const OUString& rOld, const OUString& rNew )
    2260             : {
    2261           0 :     for( iterator itr = begin(); itr != end(); ++itr)
    2262           0 :         itr->RenameCellStyle(rOld,rNew);
    2263           0 : }
    2264             : 
    2265        1460 : bool ScConditionalFormatList::CheckAllEntries()
    2266             : {
    2267        1460 :     bool bValid = true;
    2268             : 
    2269             :     // need to check which must be deleted
    2270        1460 :     iterator itr = begin();
    2271        3085 :     while(itr != end())
    2272             :     {
    2273         165 :         if(itr->GetRange().empty())
    2274             :         {
    2275           4 :             bValid = false;
    2276           4 :             maConditionalFormats.erase(itr++);
    2277             :         }
    2278             :         else
    2279         161 :             ++itr;
    2280             :     }
    2281             : 
    2282        1460 :     return bValid;
    2283             : }
    2284             : 
    2285        1252 : void ScConditionalFormatList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
    2286             : {
    2287        1326 :     for( iterator itr = begin(); itr != end(); ++itr)
    2288          74 :         itr->DeleteArea( nCol1, nRow1, nCol2, nRow2 );
    2289             : 
    2290        1252 :     CheckAllEntries();
    2291        1252 : }
    2292             : 
    2293       78979 : void ScConditionalFormatList::SourceChanged( const ScAddress& rAddr )
    2294             : {
    2295       79078 :     for( iterator itr = begin(); itr != end(); ++itr)
    2296          99 :         itr->SourceChanged( rAddr );
    2297       78979 : }
    2298             : 
    2299      114413 : ScConditionalFormatList::iterator ScConditionalFormatList::begin()
    2300             : {
    2301      114413 :     return maConditionalFormats.begin();
    2302             : }
    2303             : 
    2304        1660 : ScConditionalFormatList::const_iterator ScConditionalFormatList::begin() const
    2305             : {
    2306        1660 :     return maConditionalFormats.begin();
    2307             : }
    2308             : 
    2309      117516 : ScConditionalFormatList::iterator ScConditionalFormatList::end()
    2310             : {
    2311      117516 :     return maConditionalFormats.end();
    2312             : }
    2313             : 
    2314        4104 : ScConditionalFormatList::const_iterator ScConditionalFormatList::end() const
    2315             : {
    2316        4104 :     return maConditionalFormats.end();
    2317             : }
    2318             : 
    2319          44 : size_t ScConditionalFormatList::size() const
    2320             : {
    2321          44 :     return maConditionalFormats.size();
    2322             : }
    2323             : 
    2324           0 : void ScConditionalFormatList::erase( sal_uLong nIndex )
    2325             : {
    2326           0 :     for( iterator itr = begin(); itr != end(); ++itr )
    2327             :     {
    2328           0 :         if( itr->GetKey() == nIndex )
    2329             :         {
    2330           0 :             maConditionalFormats.erase(itr);
    2331           0 :             break;
    2332             :         }
    2333             :     }
    2334           0 : }
    2335             : 
    2336       10483 : void ScConditionalFormatList::startRendering()
    2337             : {
    2338       10649 :     for(iterator itr = begin(); itr != end(); ++itr)
    2339             :     {
    2340         166 :         itr->startRendering();
    2341             :     }
    2342       10483 : }
    2343             : 
    2344       10483 : void ScConditionalFormatList::endRendering()
    2345             : {
    2346       10649 :     for(iterator itr = begin(); itr != end(); ++itr)
    2347             :     {
    2348         166 :         itr->endRendering();
    2349             :     }
    2350       10639 : }
    2351             : 
    2352             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11