LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/tool - formularesult.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 180 233 77.3 %
Date: 2012-12-27 Functions: 24 28 85.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             :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4             :  *
       5             :  * The contents of this file are subject to the Mozilla Public License Version
       6             :  * 1.1 (the "License"); you may not use this file except in compliance with
       7             :  * the License or as specified alternatively below. You may obtain a copy of
       8             :  * the License at http://www.mozilla.org/MPL/
       9             :  *
      10             :  * Software distributed under the License is distributed on an "AS IS" basis,
      11             :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12             :  * for the specific language governing rights and limitations under the
      13             :  * License.
      14             :  *
      15             :  * Major Contributor(s):
      16             :  *   Copyright (C) 2012 Kohei Yoshida <kohei.yoshida@suse.com>
      17             :  *
      18             :  * All Rights Reserved.
      19             :  *
      20             :  * For minor contributions see the git repository.
      21             :  *
      22             :  * Alternatively, the contents of this file may be used under the terms of
      23             :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      24             :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      25             :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      26             :  * instead of those above.
      27             :  */
      28             : 
      29             : #include "formularesult.hxx"
      30             : 
      31        3109 : ScFormulaResult::ScFormulaResult() :
      32             :     mpToken(NULL), mnError(0), mbToken(true),
      33             :     mbEmpty(false), mbEmptyDisplayedAsString(false),
      34        3109 :     meMultiline(MULTILINE_UNKNOWN) {}
      35             : 
      36          26 : ScFormulaResult::ScFormulaResult( const ScFormulaResult & r ) :
      37             :     mnError( r.mnError), mbToken( r.mbToken),
      38             :     mbEmpty( r.mbEmpty),
      39             :     mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
      40          26 :     meMultiline( r.meMultiline)
      41             : {
      42          26 :     if (mbToken)
      43             :     {
      44           0 :         mpToken = r.mpToken;
      45           0 :         if (mpToken)
      46             :         {
      47             :             // Since matrix dimension and
      48             :             // results are assigned to a matrix
      49             :             // cell formula token we have to
      50             :             // clone that instead of sharing it.
      51             :             const ScMatrixFormulaCellToken* pMatFormula =
      52           0 :                 r.GetMatrixFormulaCellToken();
      53           0 :             if (pMatFormula)
      54             :             {
      55           0 :                 mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
      56           0 :                 mpToken->IncRef();
      57             :             }
      58             :             else
      59           0 :                 IncrementTokenRef( mpToken);
      60             :         }
      61             :     }
      62             :     else
      63          26 :         mfValue = r.mfValue;
      64          26 : }
      65             : 
      66        2432 : ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
      67             :     mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
      68        2432 :     meMultiline(MULTILINE_UNKNOWN)
      69             : {
      70        2432 :     SetToken( p);
      71        2432 : }
      72             : 
      73        5431 : ScFormulaResult::~ScFormulaResult()
      74             : {
      75        5431 :     if (mbToken && mpToken)
      76          91 :         mpToken->DecRef();
      77        5431 : }
      78             : 
      79             : 
      80       11941 : void ScFormulaResult::ResetToDefaults()
      81             : {
      82       11941 :     mnError = 0;
      83       11941 :     mbEmpty = false;
      84       11941 :     mbEmptyDisplayedAsString = false;
      85       11941 :     meMultiline = MULTILINE_UNKNOWN;
      86       11941 : }
      87             : 
      88        3374 : void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
      89             : {
      90        3374 :     ResetToDefaults();
      91        3374 :     if (!p)
      92             :     {
      93         230 :         mpToken = p;
      94         230 :         mbToken = true;
      95             :     }
      96             :     else
      97             :     {
      98        3144 :         switch (p->GetType())
      99             :         {
     100             :             case formula::svError:
     101          62 :                 mnError = p->GetError();
     102          62 :                 p->DecRef();
     103          62 :                 mbToken = false;
     104             :                 // set in case mnError is 0 now, which shouldn't happen but ...
     105          62 :                 mfValue = 0.0;
     106          62 :                 meMultiline = MULTILINE_FALSE;
     107          62 :                 break;
     108             :             case formula::svEmptyCell:
     109          14 :                 mbEmpty = true;
     110          14 :                 mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
     111          14 :                 p->DecRef();
     112          14 :                 mbToken = false;
     113          14 :                 meMultiline = MULTILINE_FALSE;
     114          14 :                 break;
     115             :             case formula::svDouble:
     116        2961 :                 mfValue = p->GetDouble();
     117        2961 :                 p->DecRef();
     118        2961 :                 mbToken = false;
     119        2961 :                 meMultiline = MULTILINE_FALSE;
     120        2961 :                 break;
     121             :             default:
     122         107 :                 mpToken = p;
     123         107 :                 mbToken = true;
     124             :         }
     125             :     }
     126        3374 : }
     127             : 
     128           0 : ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
     129             : {
     130           0 :     Assign( r);
     131           0 :     return *this;
     132             : }
     133             : 
     134        2321 : void ScFormulaResult::Assign( const ScFormulaResult & r )
     135             : {
     136        2321 :     if (this == &r)
     137        2321 :         return;
     138        2321 :     if (r.mbEmpty)
     139             :     {
     140           1 :         if (mbToken && mpToken)
     141           0 :             mpToken->DecRef();
     142           1 :         mbToken = false;
     143           1 :         mbEmpty = true;
     144           1 :         mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
     145           1 :         meMultiline = r.meMultiline;
     146             :     }
     147        2320 :     else if (r.mbToken)
     148             :     {
     149             :         // Matrix formula cell token must be cloned, see copy-ctor.
     150             :         const ScMatrixFormulaCellToken* pMatFormula =
     151           3 :             r.GetMatrixFormulaCellToken();
     152           3 :         if (pMatFormula)
     153           0 :             SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
     154             :         else
     155           3 :             SetToken( r.mpToken);
     156             :     }
     157             :     else
     158        2317 :         SetDouble( r.mfValue);
     159             :     // If there was an error there will be an error, no matter what Set...()
     160             :     // methods did.
     161        2321 :     mnError = r.mnError;
     162             : }
     163             : 
     164        3385 : void ScFormulaResult::SetToken( const formula::FormulaToken* p )
     165             : {
     166        3385 :     ResetToDefaults();
     167        3385 :     IncrementTokenRef( p);
     168             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     169             :     // formula cell's ScMatrixFormulaCellToken.
     170        3385 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     171        3385 :     if (pMatFormula)
     172             :     {
     173             :         const ScMatrixCellResultToken* pMatResult =
     174          11 :             (p && p->GetType() == formula::svMatrixCell ?
     175          22 :              dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
     176          11 :         if (pMatResult)
     177             :         {
     178             :             const ScMatrixFormulaCellToken* pNewMatFormula =
     179           9 :                 dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
     180           9 :             if (pNewMatFormula)
     181             :             {
     182             :                 SAL_WARN( "sc", "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
     183           0 :                 pMatFormula->SetMatColsRows( pNewMatFormula->GetMatCols(),
     184           0 :                         pNewMatFormula->GetMatRows());
     185             :             }
     186           9 :             pMatFormula->Assign( *pMatResult);
     187           9 :             p->DecRef();
     188             :         }
     189           2 :         else if (p)
     190             :         {
     191             :             // This may be the result of some constant expression like
     192             :             // {="string"} that doesn't result in a matrix but still would
     193             :             // display the result in all cells of this matrix formula.
     194           2 :             pMatFormula->Assign( *p);
     195           2 :             p->DecRef();
     196             :         }
     197             :         else
     198             :         {
     199             :             // NULL result? Well, if you say so ...
     200           0 :             pMatFormula->ResetResult();
     201             :         }
     202             :     }
     203             :     else
     204             :     {
     205        3374 :         if (mbToken && mpToken)
     206          44 :             mpToken->DecRef();
     207        3374 :         ResolveToken( p);
     208             :     }
     209        3385 : }
     210             : 
     211        4757 : void ScFormulaResult::SetDouble( double f )
     212             : {
     213        4757 :     ResetToDefaults();
     214             :     // Handle a result obtained from the interpreter to be assigned to a matrix
     215             :     // formula cell's ScMatrixFormulaCellToken.
     216        4757 :     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
     217        4757 :     if (pMatFormula)
     218          17 :         pMatFormula->SetUpperLeftDouble( f);
     219             :     else
     220             :     {
     221        4740 :         if (mbToken && mpToken)
     222           0 :             mpToken->DecRef();
     223        4740 :         mfValue = f;
     224        4740 :         mbToken = false;
     225        4740 :         meMultiline = MULTILINE_FALSE;
     226             :     }
     227        4757 : }
     228             : 
     229       42046 : formula::StackVar ScFormulaResult::GetType() const
     230             : {
     231             :     // Order is significant.
     232       42046 :     if (mnError)
     233         218 :         return formula::svError;
     234       41828 :     if (mbEmpty)
     235          74 :         return formula::svEmptyCell;
     236       41754 :     if (!mbToken)
     237       37102 :         return formula::svDouble;
     238        4652 :     if (mpToken)
     239        1099 :         return mpToken->GetType();
     240        3553 :     return formula::svUnknown;
     241             : }
     242             : 
     243       30193 : formula::StackVar ScFormulaResult::GetCellResultType() const
     244             : {
     245       30193 :     formula::StackVar sv = GetType();
     246       30193 :     if (sv == formula::svMatrixCell)
     247             :         // don't need to test for mpToken here, GetType() already did it
     248         108 :         sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
     249       30193 :     return sv;
     250             : }
     251             : 
     252         514 : bool ScFormulaResult::IsEmptyDisplayedAsString() const
     253             : {
     254         514 :     if (mbEmpty)
     255           4 :         return mbEmptyDisplayedAsString;
     256         510 :     if (GetType() == formula::svMatrixCell)
     257             :     {
     258             :         // don't need to test for mpToken here, GetType() already did it
     259             :         const ScEmptyCellToken* p = dynamic_cast<const ScEmptyCellToken*>(
     260             :                 static_cast<const ScMatrixCellResultToken*>(
     261           3 :                     mpToken)->GetUpperLeftToken().get());
     262           3 :         if (p)
     263           0 :             return p->IsDisplayedAsString();
     264             :     }
     265         510 :     return false;
     266             : }
     267             : 
     268       12721 : bool ScFormulaResult::IsValue() const
     269             : {
     270       12721 :     formula::StackVar sv = GetCellResultType();
     271       12721 :     return sv == formula::svDouble || sv == formula::svError || sv == formula::svEmptyCell;
     272             : }
     273             : 
     274           0 : bool ScFormulaResult::IsMultiline() const
     275             : {
     276           0 :     if (meMultiline == MULTILINE_UNKNOWN)
     277             :     {
     278           0 :         const String& rStr = GetString();
     279           0 :         if (rStr.Len() && rStr.Search( _LF ) != STRING_NOTFOUND)
     280           0 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
     281             :         else
     282           0 :             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
     283             :     }
     284           0 :     return meMultiline == MULTILINE_TRUE;
     285             : }
     286             : 
     287       12587 : sal_uInt16 ScFormulaResult::GetResultError() const
     288             : {
     289       12587 :     if (mnError)
     290          75 :         return mnError;
     291       12512 :     formula::StackVar sv = GetCellResultType();
     292       12512 :     if (sv == formula::svError)
     293             :     {
     294           0 :         if (GetType() == formula::svMatrixCell)
     295             :             // don't need to test for mpToken here, GetType() already did it
     296             :             return static_cast<const ScMatrixCellResultToken*>(mpToken)->
     297           0 :                 GetUpperLeftToken()->GetError();
     298           0 :         if (mpToken)
     299           0 :             return mpToken->GetError();
     300             :     }
     301       12512 :     return 0;
     302             : }
     303             : 
     304        3011 : void ScFormulaResult::SetResultError( sal_uInt16 nErr )
     305             : {
     306        3011 :     mnError = nErr;
     307        3011 : }
     308             : 
     309           0 : formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
     310             : {
     311           0 :     if (mbToken)
     312           0 :         return mpToken;
     313           0 :     return NULL;
     314             : }
     315             : 
     316           3 : formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
     317             : {
     318           3 :     if (GetType() == formula::svMatrixCell)
     319             :         // don't need to test for mpToken here, GetType() already did it
     320           3 :         return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
     321           0 :     return GetToken();
     322             : }
     323             : 
     324       13793 : double ScFormulaResult::GetDouble() const
     325             : {
     326       13793 :     if (mbToken)
     327             :     {
     328             :         // Should really not be of type formula::svDouble here.
     329          99 :         if (mpToken)
     330             :         {
     331          53 :             switch (mpToken->GetType())
     332             :             {
     333             :                 case formula::svHybridCell:
     334           0 :                     return mpToken->GetDouble();
     335             :                 case formula::svMatrixCell:
     336             :                     {
     337             :                         const ScMatrixCellResultToken* p =
     338          53 :                             static_cast<const ScMatrixCellResultToken*>(mpToken);
     339          53 :                         if (p->GetUpperLeftType() == formula::svDouble)
     340          43 :                             return p->GetUpperLeftToken()->GetDouble();
     341             :                     }
     342          10 :                     break;
     343             :                 default:
     344             :                     ;   // nothing
     345             :             }
     346             :         }
     347          56 :         return 0.0;
     348             :     }
     349       13694 :     if (mbEmpty)
     350          24 :         return 0.0;
     351       13670 :     return mfValue;
     352             : }
     353             : 
     354         136 : const String & ScFormulaResult::GetString() const
     355             : {
     356         136 :     if (mbToken && mpToken)
     357             :     {
     358         135 :         switch (mpToken->GetType())
     359             :         {
     360             :             case formula::svString:
     361             :             case formula::svHybridCell:
     362         134 :                 return mpToken->GetString();
     363             :             case formula::svMatrixCell:
     364             :                 {
     365             :                     const ScMatrixCellResultToken* p =
     366           1 :                         static_cast<const ScMatrixCellResultToken*>(mpToken);
     367           1 :                     if (p->GetUpperLeftType() == formula::svString)
     368           1 :                         return p->GetUpperLeftToken()->GetString();
     369             :                 }
     370           0 :                 break;
     371             :             default:
     372             :                 ;   // nothing
     373             :         }
     374             :     }
     375           1 :     return EMPTY_STRING;
     376             : }
     377             : 
     378        3094 : ScConstMatrixRef ScFormulaResult::GetMatrix() const
     379             : {
     380        3094 :     if (GetType() == formula::svMatrixCell)
     381          90 :         return static_cast<const ScToken*>(mpToken)->GetMatrix();
     382        3004 :     return NULL;
     383             : }
     384             : 
     385          56 : const String & ScFormulaResult::GetHybridFormula() const
     386             : {
     387          56 :     if (GetType() == formula::svHybridCell)
     388             :     {
     389           0 :         const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
     390           0 :         if (p)
     391           0 :             return p->GetFormula();
     392             :     }
     393          56 :     return EMPTY_STRING;
     394             : }
     395             : 
     396         369 : void ScFormulaResult::SetHybridDouble( double f )
     397             : {
     398         369 :     ResetToDefaults();
     399         369 :     if (mbToken && mpToken)
     400             :     {
     401          15 :         if(GetType() == formula::svMatrixCell)
     402          15 :             SetDouble(f);
     403             :         else
     404             :         {
     405           0 :             String aString( GetString());
     406           0 :             String aFormula( GetHybridFormula());
     407           0 :             mpToken->DecRef();
     408           0 :             mpToken = new ScHybridCellToken( f, aString, aFormula);
     409           0 :             mpToken->IncRef();
     410          15 :         }
     411             :     }
     412             :     else
     413             :     {
     414         354 :         mfValue = f;
     415         354 :         mbToken = false;
     416         354 :         meMultiline = MULTILINE_FALSE;
     417             :     }
     418         369 : }
     419             : 
     420          56 : void ScFormulaResult::SetHybridString( const rtl::OUString & rStr )
     421             : {
     422             :     // Obtain values before changing anything.
     423          56 :     double f = GetDouble();
     424          56 :     String aFormula( GetHybridFormula());
     425          56 :     ResetToDefaults();
     426          56 :     if (mbToken && mpToken)
     427          10 :         mpToken->DecRef();
     428          56 :     mpToken = new ScHybridCellToken( f, rStr, aFormula);
     429          56 :     mpToken->IncRef();
     430          56 :     mbToken = true;
     431          56 : }
     432             : 
     433           0 : void ScFormulaResult::SetHybridFormula( const String & rFormula )
     434             : {
     435             :     // Obtain values before changing anything.
     436           0 :     double f = GetDouble();
     437           0 :     String aStr( GetString());
     438           0 :     ResetToDefaults();
     439           0 :     if (mbToken && mpToken)
     440           0 :         mpToken->DecRef();
     441           0 :     mpToken = new ScHybridCellToken( f, aStr, rFormula);
     442           0 :     mpToken->IncRef();
     443           0 :     mbToken = true;
     444           0 : }
     445             : 
     446        8175 : const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
     447             : {
     448        8175 :     return (GetType() == formula::svMatrixCell ?
     449        8175 :             dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
     450             : }
     451             : 
     452        8170 : ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
     453             : {
     454        8170 :     return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
     455             : }
     456             : 
     457             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10