LCOV - code coverage report
Current view: top level - sc/source/core/data - conditio.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 687 1161 59.2 %
Date: 2014-11-03 Functions: 88 121 72.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10