LCOV - code coverage report
Current view: top level - sc/source/core/tool - formularesult.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 291 0.0 %
Date: 2014-04-14 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "formularesult.hxx"
      11             : #include "scmatrix.hxx"
      12             : 
      13             : namespace sc {
      14             : 
      15           0 : FormulaResultValue::FormulaResultValue() : meType(Invalid), mfValue(0.0), mnError(0) {}
      16           0 : FormulaResultValue::FormulaResultValue( double fValue ) : meType(Value), mfValue(fValue), mnError(0) {}
      17           0 : FormulaResultValue::FormulaResultValue( const svl::SharedString& rStr ) : meType(String), mfValue(0.0), maString(rStr), mnError(0) {}
      18           0 : FormulaResultValue::FormulaResultValue( sal_uInt16 nErr ) : meType(Error), mfValue(0.0), mnError(nErr) {}
      19             : 
      20             : }
      21             : 
      22           0 : ScFormulaResult::ScFormulaResult() :
      23             :     mpToken(NULL), mnError(0), mbToken(true),
      24             :     mbEmpty(false), mbEmptyDisplayedAsString(false),
      25           0 :     meMultiline(MULTILINE_UNKNOWN) {}
      26             : 
      27           0 : ScFormulaResult::ScFormulaResult( const ScFormulaResult & r ) :
      28             :     mnError( r.mnError), mbToken( r.mbToken),
      29             :     mbEmpty( r.mbEmpty),
      30             :     mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
      31           0 :     meMultiline( r.meMultiline)
      32             : {
      33           0 :     if (mbToken)
      34             :     {
      35           0 :         mpToken = r.mpToken;
      36           0 :         if (mpToken)
      37             :         {
      38             :             // Since matrix dimension and
      39             :             // results are assigned to a matrix
      40             :             // cell formula token we have to
      41             :             // clone that instead of sharing it.
      42             :             const ScMatrixFormulaCellToken* pMatFormula =
      43           0 :                 r.GetMatrixFormulaCellToken();
      44           0 :             if (pMatFormula)
      45             :             {
      46           0 :                 mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
      47           0 :                 mpToken->IncRef();
      48             :             }
      49             :             else
      50           0 :                 IncrementTokenRef( mpToken);
      51             :         }
      52             :     }
      53             :     else
      54           0 :         mfValue = r.mfValue;
      55           0 : }
      56             : 
      57           0 : ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
      58             :     mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
      59           0 :     meMultiline(MULTILINE_UNKNOWN)
      60             : {
      61           0 :     SetToken( p);
      62           0 : }
      63             : 
      64           0 : ScFormulaResult::~ScFormulaResult()
      65             : {
      66           0 :     if (mbToken && mpToken)
      67           0 :         mpToken->DecRef();
      68           0 : }
      69             : 
      70             : 
      71           0 : void ScFormulaResult::ResetToDefaults()
      72             : {
      73           0 :     mnError = 0;
      74           0 :     mbEmpty = false;
      75           0 :     mbEmptyDisplayedAsString = false;
      76           0 :     meMultiline = MULTILINE_UNKNOWN;
      77           0 : }
      78             : 
      79           0 : void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
      80             : {
      81           0 :     ResetToDefaults();
      82           0 :     if (!p)
      83             :     {
      84           0 :         mpToken = p;
      85           0 :         mbToken = true;
      86             :     }
      87             :     else
      88             :     {
      89           0 :         switch (p->GetType())
      90             :         {
      91             :             case formula::svError:
      92           0 :                 mnError = p->GetError();
      93           0 :                 p->DecRef();
      94           0 :                 mbToken = false;
      95             :                 // set in case mnError is 0 now, which shouldn't happen but ...
      96           0 :                 mfValue = 0.0;
      97           0 :                 meMultiline = MULTILINE_FALSE;
      98           0 :                 break;
      99             :             case formula::svEmptyCell:
     100           0 :                 mbEmpty = true;
     101           0 :                 mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
     102           0 :                 p->DecRef();
     103           0 :                 mbToken = false;
     104           0 :                 meMultiline = MULTILINE_FALSE;
     105           0 :                 break;
     106             :             case formula::svDouble:
     107           0 :                 mfValue = p->GetDouble();
     108           0 :                 p->DecRef();
     109           0 :                 mbToken = false;
     110           0 :                 meMultiline = MULTILINE_FALSE;
     111           0 :                 break;
     112             :             default:
     113           0 :                 mpToken = p;
     114           0 :                 mbToken = true;
     115             :         }
     116             :     }
     117           0 : }
     118             : 
     119           0 : ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
     120             : {
     121           0 :     Assign( r);
     122           0 :     return *this;
     123             : }
     124             : 
     125           0 : void ScFormulaResult::Assign( const ScFormulaResult & r )
     126             : {
     127           0 :     if (this == &r)
     128           0 :         return;
     129           0 :     if (r.mbEmpty)
     130             :     {
     131           0 :         if (mbToken && mpToken)
     132           0 :             mpToken->DecRef();
     133           0 :         mbToken = false;
     134           0 :         mbEmpty = true;
     135           0 :         mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
     136           0 :         meMultiline = r.meMultiline;
     137             :     }
     138           0 :     else if (r.mbToken)
     139             :     {
     140             :         // Matrix formula cell token must be cloned, see copy-ctor.
     141             :         const ScMatrixFormulaCellToken* pMatFormula =
     142           0 :             r.GetMatrixFormulaCellToken();
     143           0 :         if (pMatFormula)
     144           0 :             SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
     145             :         else
     146           0 :             SetToken( r.mpToken);
     147             :     }
     148             :     else
     149           0 :         SetDouble( r.mfValue);
     150             :     // If there was an error there will be an error, no matter what Set...()
     151             :     // methods did.
     152           0 :     mnError = r.mnError;
     153             : }
     154             : 
     155           0 : void ScFormulaResult::SetToken( const formula::FormulaToken* p )
     156             : {
     157           0 :     ResetToDefaults();
     158           0 :     IncrementTokenRef( p);
     159             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     160             :     // formula cell's ScMatrixFormulaCellToken.
     161           0 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     162           0 :     if (pMatFormula)
     163             :     {
     164             :         const ScMatrixCellResultToken* pMatResult =
     165           0 :             (p && p->GetType() == formula::svMatrixCell ?
     166           0 :              dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
     167           0 :         if (pMatResult)
     168             :         {
     169             :             const ScMatrixFormulaCellToken* pNewMatFormula =
     170           0 :                 dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
     171           0 :             if (pNewMatFormula)
     172             :             {
     173             :                 SAL_WARN( "sc", "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
     174           0 :                 pMatFormula->SetMatColsRows( pNewMatFormula->GetMatCols(),
     175           0 :                         pNewMatFormula->GetMatRows());
     176             :             }
     177           0 :             pMatFormula->Assign( *pMatResult);
     178           0 :             p->DecRef();
     179             :         }
     180           0 :         else if (p)
     181             :         {
     182             :             // This may be the result of some constant expression like
     183             :             // {="string"} that doesn't result in a matrix but still would
     184             :             // display the result in all cells of this matrix formula.
     185           0 :             pMatFormula->Assign( *p);
     186           0 :             p->DecRef();
     187             :         }
     188             :         else
     189             :         {
     190             :             // NULL result? Well, if you say so ...
     191           0 :             pMatFormula->ResetResult();
     192             :         }
     193             :     }
     194             :     else
     195             :     {
     196           0 :         if (mbToken && mpToken)
     197           0 :             mpToken->DecRef();
     198           0 :         ResolveToken( p);
     199             :     }
     200           0 : }
     201             : 
     202           0 : void ScFormulaResult::SetDouble( double f )
     203             : {
     204           0 :     ResetToDefaults();
     205             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     206             :     // formula cell's ScMatrixFormulaCellToken.
     207           0 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     208           0 :     if (pMatFormula)
     209           0 :         pMatFormula->SetUpperLeftDouble( f);
     210             :     else
     211             :     {
     212           0 :         if (mbToken && mpToken)
     213           0 :             mpToken->DecRef();
     214           0 :         mfValue = f;
     215           0 :         mbToken = false;
     216           0 :         meMultiline = MULTILINE_FALSE;
     217             :     }
     218           0 : }
     219             : 
     220           0 : formula::StackVar ScFormulaResult::GetType() const
     221             : {
     222             :     // Order is significant.
     223           0 :     if (mnError)
     224           0 :         return formula::svError;
     225           0 :     if (mbEmpty)
     226           0 :         return formula::svEmptyCell;
     227           0 :     if (!mbToken)
     228           0 :         return formula::svDouble;
     229           0 :     if (mpToken)
     230           0 :         return mpToken->GetType();
     231           0 :     return formula::svUnknown;
     232             : }
     233             : 
     234           0 : formula::StackVar ScFormulaResult::GetCellResultType() const
     235             : {
     236           0 :     formula::StackVar sv = GetType();
     237           0 :     if (sv == formula::svMatrixCell)
     238             :         // don't need to test for mpToken here, GetType() already did it
     239           0 :         sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
     240           0 :     return sv;
     241             : }
     242             : 
     243           0 : bool ScFormulaResult::IsEmptyDisplayedAsString() const
     244             : {
     245           0 :     if (mbEmpty)
     246           0 :         return mbEmptyDisplayedAsString;
     247           0 :     if (GetType() == formula::svMatrixCell)
     248             :     {
     249             :         // don't need to test for mpToken here, GetType() already did it
     250             :         const ScEmptyCellToken* p = dynamic_cast<const ScEmptyCellToken*>(
     251             :                 static_cast<const ScMatrixCellResultToken*>(
     252           0 :                     mpToken)->GetUpperLeftToken().get());
     253           0 :         if (p)
     254           0 :             return p->IsDisplayedAsString();
     255             :     }
     256           0 :     return false;
     257             : }
     258             : 
     259             : namespace {
     260             : 
     261           0 : inline bool isValue( formula::StackVar sv )
     262             : {
     263           0 :     return sv == formula::svDouble || sv == formula::svError
     264           0 :         || sv == formula::svEmptyCell || sv == formula::svHybridValueCell;
     265             : }
     266             : 
     267           0 : inline bool isString( formula::StackVar sv )
     268             : {
     269           0 :     switch (sv)
     270             :     {
     271             :         case formula::svString:
     272             :         case formula::svHybridCell:
     273             :         case formula::svHybridValueCell:
     274           0 :             return true;
     275             :         default:
     276           0 :             break;
     277             :     }
     278             : 
     279           0 :     return false;
     280             : }
     281             : 
     282             : }
     283             : 
     284           0 : bool ScFormulaResult::IsValue() const
     285             : {
     286           0 :     return isValue(GetCellResultType());
     287             : }
     288             : 
     289           0 : bool ScFormulaResult::IsValueNoError() const
     290             : {
     291           0 :     switch (GetCellResultType())
     292             :     {
     293             :         case formula::svDouble:
     294             :         case formula::svEmptyCell:
     295             :         case formula::svHybridValueCell:
     296           0 :             return true;
     297             :         default:
     298           0 :             return false;
     299             :     }
     300             : }
     301             : 
     302           0 : bool ScFormulaResult::IsMultiline() const
     303             : {
     304           0 :     if (meMultiline == MULTILINE_UNKNOWN)
     305             :     {
     306           0 :         svl::SharedString aStr = GetString();
     307           0 :         if (!aStr.isEmpty() && aStr.getString().indexOf('\n') != -1)
     308           0 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
     309             :         else
     310           0 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
     311             :     }
     312           0 :     return meMultiline == MULTILINE_TRUE;
     313             : }
     314             : 
     315           0 : bool ScFormulaResult::GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const
     316             : {
     317           0 :     if (mnError)
     318             :     {
     319           0 :         rErr = mnError;
     320           0 :         return true;
     321             :     }
     322             : 
     323           0 :     formula::StackVar sv = GetCellResultType();
     324           0 :     if (sv == formula::svError)
     325             :     {
     326           0 :         if (GetType() == formula::svMatrixCell)
     327             :         {
     328             :             // don't need to test for mpToken here, GetType() already did it
     329             :             rErr = static_cast<const ScMatrixCellResultToken*>(mpToken)->
     330           0 :                 GetUpperLeftToken()->GetError();
     331             :         }
     332           0 :         else if (mpToken)
     333             :         {
     334           0 :             rErr = mpToken->GetError();
     335             :         }
     336             :     }
     337             : 
     338           0 :     if (rErr)
     339           0 :         return true;
     340             : 
     341           0 :     if (!isValue(sv))
     342           0 :         return false;
     343             : 
     344           0 :     rVal = GetDouble();
     345           0 :     return true;
     346             : }
     347             : 
     348           0 : sc::FormulaResultValue ScFormulaResult::GetResult() const
     349             : {
     350           0 :     if (mnError)
     351           0 :         return sc::FormulaResultValue(mnError);
     352             : 
     353           0 :     formula::StackVar sv = GetCellResultType();
     354           0 :     sal_uInt16 nErr = 0;
     355           0 :     if (sv == formula::svError)
     356             :     {
     357           0 :         if (GetType() == formula::svMatrixCell)
     358             :         {
     359             :             // don't need to test for mpToken here, GetType() already did it
     360             :             nErr = static_cast<const ScMatrixCellResultToken*>(mpToken)->
     361           0 :                 GetUpperLeftToken()->GetError();
     362             :         }
     363           0 :         else if (mpToken)
     364             :         {
     365           0 :             nErr = mpToken->GetError();
     366             :         }
     367             :     }
     368             : 
     369           0 :     if (nErr)
     370           0 :         return sc::FormulaResultValue(nErr);
     371             : 
     372           0 :     if (isValue(sv))
     373           0 :         return sc::FormulaResultValue(GetDouble());
     374             : 
     375           0 :     if (!mbToken)
     376             :         // String result type needs token.
     377           0 :         return sc::FormulaResultValue();
     378             : 
     379           0 :     if (isString(sv))
     380           0 :         return sc::FormulaResultValue(GetString());
     381             : 
     382             :     // Invalid
     383           0 :     return sc::FormulaResultValue();
     384             : }
     385             : 
     386           0 : sal_uInt16 ScFormulaResult::GetResultError() const
     387             : {
     388           0 :     if (mnError)
     389           0 :         return mnError;
     390           0 :     formula::StackVar sv = GetCellResultType();
     391           0 :     if (sv == formula::svError)
     392             :     {
     393           0 :         if (GetType() == formula::svMatrixCell)
     394             :             // don't need to test for mpToken here, GetType() already did it
     395             :             return static_cast<const ScMatrixCellResultToken*>(mpToken)->
     396           0 :                 GetUpperLeftToken()->GetError();
     397           0 :         if (mpToken)
     398           0 :             return mpToken->GetError();
     399             :     }
     400           0 :     return 0;
     401             : }
     402             : 
     403           0 : void ScFormulaResult::SetResultError( sal_uInt16 nErr )
     404             : {
     405           0 :     mnError = nErr;
     406           0 : }
     407             : 
     408           0 : formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
     409             : {
     410           0 :     if (mbToken)
     411           0 :         return mpToken;
     412           0 :     return NULL;
     413             : }
     414             : 
     415           0 : formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
     416             : {
     417           0 :     if (GetType() == formula::svMatrixCell)
     418             :         // don't need to test for mpToken here, GetType() already did it
     419           0 :         return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
     420           0 :     return GetToken();
     421             : }
     422             : 
     423           0 : double ScFormulaResult::GetDouble() const
     424             : {
     425           0 :     if (mbToken)
     426             :     {
     427             :         // Should really not be of type formula::svDouble here.
     428           0 :         if (mpToken)
     429             :         {
     430           0 :             switch (mpToken->GetType())
     431             :             {
     432             :                 case formula::svHybridCell:
     433             :                 case formula::svHybridValueCell:
     434           0 :                     return mpToken->GetDouble();
     435             :                 case formula::svMatrixCell:
     436             :                     {
     437             :                         const ScMatrixCellResultToken* p =
     438           0 :                             static_cast<const ScMatrixCellResultToken*>(mpToken);
     439           0 :                         if (p->GetUpperLeftType() == formula::svDouble)
     440           0 :                             return p->GetUpperLeftToken()->GetDouble();
     441             :                     }
     442           0 :                     break;
     443             :                 default:
     444             :                     ;   // nothing
     445             :             }
     446             :         }
     447           0 :         return 0.0;
     448             :     }
     449           0 :     if (mbEmpty)
     450           0 :         return 0.0;
     451           0 :     return mfValue;
     452             : }
     453             : 
     454           0 : svl::SharedString ScFormulaResult::GetString() const
     455             : {
     456           0 :     if (mbToken && mpToken)
     457             :     {
     458           0 :         switch (mpToken->GetType())
     459             :         {
     460             :             case formula::svString:
     461             :             case formula::svHybridCell:
     462             :             case formula::svHybridValueCell:
     463           0 :                 return mpToken->GetString();
     464             :             case formula::svMatrixCell:
     465             :                 {
     466             :                     const ScMatrixCellResultToken* p =
     467           0 :                         static_cast<const ScMatrixCellResultToken*>(mpToken);
     468           0 :                     if (p->GetUpperLeftType() == formula::svString)
     469           0 :                         return p->GetUpperLeftToken()->GetString();
     470             :                 }
     471           0 :                 break;
     472             :             default:
     473             :                 ;   // nothing
     474             :         }
     475             :     }
     476           0 :     return svl::SharedString::getEmptyString();
     477             : }
     478             : 
     479           0 : ScConstMatrixRef ScFormulaResult::GetMatrix() const
     480             : {
     481           0 :     if (GetType() == formula::svMatrixCell)
     482           0 :         return static_cast<const ScToken*>(mpToken)->GetMatrix();
     483           0 :     return NULL;
     484             : }
     485             : 
     486           0 : const OUString& ScFormulaResult::GetHybridFormula() const
     487             : {
     488           0 :     if (GetType() == formula::svHybridCell)
     489             :     {
     490           0 :         const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
     491           0 :         if (p)
     492           0 :             return p->GetFormula();
     493             :     }
     494           0 :     return EMPTY_OUSTRING;
     495             : }
     496             : 
     497           0 : void ScFormulaResult::SetHybridDouble( double f )
     498             : {
     499           0 :     ResetToDefaults();
     500           0 :     if (mbToken && mpToken)
     501             :     {
     502           0 :         if(GetType() == formula::svMatrixCell)
     503           0 :             SetDouble(f);
     504             :         else
     505             :         {
     506           0 :             svl::SharedString aString = GetString();
     507           0 :             OUString aFormula( GetHybridFormula());
     508           0 :             mpToken->DecRef();
     509           0 :             mpToken = new ScHybridCellToken( f, aString, aFormula);
     510           0 :             mpToken->IncRef();
     511           0 :         }
     512             :     }
     513             :     else
     514             :     {
     515           0 :         mfValue = f;
     516           0 :         mbToken = false;
     517           0 :         meMultiline = MULTILINE_FALSE;
     518             :     }
     519           0 : }
     520             : 
     521           0 : void ScFormulaResult::SetHybridString( const OUString & rStr )
     522             : {
     523             :     // Obtain values before changing anything.
     524           0 :     double f = GetDouble();
     525           0 :     OUString aFormula( GetHybridFormula());
     526           0 :     ResetToDefaults();
     527           0 :     if (mbToken && mpToken)
     528           0 :         mpToken->DecRef();
     529           0 :     mpToken = new ScHybridCellToken( f, rStr, aFormula);
     530           0 :     mpToken->IncRef();
     531           0 :     mbToken = true;
     532           0 : }
     533             : 
     534           0 : void ScFormulaResult::SetHybridFormula( const OUString & rFormula )
     535             : {
     536             :     // Obtain values before changing anything.
     537           0 :     double f = GetDouble();
     538           0 :     svl::SharedString aStr = GetString();
     539           0 :     ResetToDefaults();
     540           0 :     if (mbToken && mpToken)
     541           0 :         mpToken->DecRef();
     542           0 :     mpToken = new ScHybridCellToken( f, aStr, rFormula);
     543           0 :     mpToken->IncRef();
     544           0 :     mbToken = true;
     545           0 : }
     546             : 
     547           0 : void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
     548             : {
     549           0 :     ResetToDefaults();
     550           0 :     if (mbToken && mpToken)
     551           0 :         mpToken->DecRef();
     552           0 :     mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL);
     553           0 :     mpToken->IncRef();
     554           0 :     mbToken = true;
     555           0 : }
     556             : 
     557           0 : const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
     558             : {
     559           0 :     return (GetType() == formula::svMatrixCell ?
     560           0 :             dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
     561             : }
     562             : 
     563           0 : ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
     564             : {
     565           0 :     return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
     566             : }
     567             : 
     568             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10