1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include "formularesult.hxx"
11 #include "scmatrix.hxx"
15 FormulaResultValue::FormulaResultValue() : meType(Invalid
), mfValue(0.0), mnError(0) {}
16 FormulaResultValue::FormulaResultValue( double fValue
) : meType(Value
), mfValue(fValue
), mnError(0) {}
17 FormulaResultValue::FormulaResultValue( const svl::SharedString
& rStr
) : meType(String
), mfValue(0.0), maString(rStr
), mnError(0) {}
18 FormulaResultValue::FormulaResultValue( sal_uInt16 nErr
) : meType(Error
), mfValue(0.0), mnError(nErr
) {}
22 ScFormulaResult::ScFormulaResult() :
23 mpToken(NULL
), mnError(0), mbToken(true),
24 mbEmpty(false), mbEmptyDisplayedAsString(false),
25 meMultiline(MULTILINE_UNKNOWN
) {}
27 ScFormulaResult::ScFormulaResult( const ScFormulaResult
& r
) :
28 mnError( r
.mnError
), mbToken( r
.mbToken
),
30 mbEmptyDisplayedAsString( r
.mbEmptyDisplayedAsString
),
31 meMultiline( r
.meMultiline
)
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 r
.GetMatrixFormulaCellToken();
46 mpToken
= new ScMatrixFormulaCellToken( *pMatFormula
);
50 IncrementTokenRef( mpToken
);
57 ScFormulaResult::ScFormulaResult( const formula::FormulaToken
* p
) :
58 mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
59 meMultiline(MULTILINE_UNKNOWN
)
64 ScFormulaResult::~ScFormulaResult()
66 if (mbToken
&& mpToken
)
70 void ScFormulaResult::ResetToDefaults()
74 mbEmptyDisplayedAsString
= false;
75 meMultiline
= MULTILINE_UNKNOWN
;
78 void ScFormulaResult::ResolveToken( const formula::FormulaToken
* p
)
90 case formula::svError
:
91 mnError
= p
->GetError();
94 // set in case mnError is 0 now, which shouldn't happen but ...
96 meMultiline
= MULTILINE_FALSE
;
98 case formula::svEmptyCell
:
100 mbEmptyDisplayedAsString
= static_cast<const ScEmptyCellToken
*>(p
)->IsDisplayedAsString();
103 meMultiline
= MULTILINE_FALSE
;
105 case formula::svDouble
:
106 mfValue
= p
->GetDouble();
109 meMultiline
= MULTILINE_FALSE
;
118 ScFormulaResult
& ScFormulaResult::operator=( const ScFormulaResult
& r
)
124 void ScFormulaResult::Assign( const ScFormulaResult
& r
)
130 if (mbToken
&& mpToken
)
134 mbEmptyDisplayedAsString
= r
.mbEmptyDisplayedAsString
;
135 meMultiline
= r
.meMultiline
;
139 // Matrix formula cell token must be cloned, see copy-ctor.
140 const ScMatrixFormulaCellToken
* pMatFormula
=
141 r
.GetMatrixFormulaCellToken();
143 SetToken( new ScMatrixFormulaCellToken( *pMatFormula
));
145 SetToken( r
.mpToken
);
148 SetDouble( r
.mfValue
);
149 // If there was an error there will be an error, no matter what Set...()
154 void ScFormulaResult::SetToken( const formula::FormulaToken
* p
)
157 IncrementTokenRef( p
);
158 // Handle a result obtained from the interpreter to be assigned to a matrix
159 // formula cell's ScMatrixFormulaCellToken.
160 ScMatrixFormulaCellToken
* pMatFormula
= GetMatrixFormulaCellTokenNonConst();
163 const ScMatrixCellResultToken
* pMatResult
=
164 (p
&& p
->GetType() == formula::svMatrixCell
?
165 dynamic_cast<const ScMatrixCellResultToken
*>(p
) : NULL
);
168 const ScMatrixFormulaCellToken
* pNewMatFormula
=
169 dynamic_cast<const ScMatrixFormulaCellToken
*>(pMatResult
);
170 if (pNewMatFormula
&& (pMatFormula
->GetMatCols() <= 0 || pMatFormula
->GetMatRows() <= 0))
172 SAL_WARN( "sc", "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
173 pMatFormula
->SetMatColsRows( pNewMatFormula
->GetMatCols(),
174 pNewMatFormula
->GetMatRows());
176 pMatFormula
->Assign( *pMatResult
);
181 // This may be the result of some constant expression like
182 // {="string"} that doesn't result in a matrix but still would
183 // display the result in all cells of this matrix formula.
184 pMatFormula
->Assign( *p
);
189 // NULL result? Well, if you say so ...
190 pMatFormula
->ResetResult();
195 if (mbToken
&& mpToken
)
201 void ScFormulaResult::SetDouble( double f
)
204 // Handle a result obtained from the interpreter to be assigned to a matrix
205 // formula cell's ScMatrixFormulaCellToken.
206 ScMatrixFormulaCellToken
* pMatFormula
= GetMatrixFormulaCellTokenNonConst();
208 pMatFormula
->SetUpperLeftDouble( f
);
211 if (mbToken
&& mpToken
)
215 meMultiline
= MULTILINE_FALSE
;
219 formula::StackVar
ScFormulaResult::GetType() const
221 // Order is significant.
223 return formula::svError
;
225 return formula::svEmptyCell
;
227 return formula::svDouble
;
229 return mpToken
->GetType();
230 return formula::svUnknown
;
233 formula::StackVar
ScFormulaResult::GetCellResultType() const
235 formula::StackVar sv
= GetType();
236 if (sv
== formula::svMatrixCell
)
237 // don't need to test for mpToken here, GetType() already did it
238 sv
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->GetUpperLeftType();
242 bool ScFormulaResult::IsEmptyDisplayedAsString() const
245 return mbEmptyDisplayedAsString
;
246 if (GetType() == formula::svMatrixCell
)
248 // don't need to test for mpToken here, GetType() already did it
249 const ScEmptyCellToken
* p
= dynamic_cast<const ScEmptyCellToken
*>(
250 static_cast<const ScMatrixCellResultToken
*>(
251 mpToken
)->GetUpperLeftToken().get());
253 return p
->IsDisplayedAsString();
260 inline bool isValue( formula::StackVar sv
)
262 return sv
== formula::svDouble
|| sv
== formula::svError
263 || sv
== formula::svEmptyCell
|| sv
== formula::svHybridValueCell
;
266 inline bool isString( formula::StackVar sv
)
270 case formula::svString
:
271 case formula::svHybridCell
:
272 case formula::svHybridValueCell
:
283 bool ScFormulaResult::IsValue() const
285 return isValue(GetCellResultType());
288 bool ScFormulaResult::IsValueNoError() const
290 switch (GetCellResultType())
292 case formula::svDouble
:
293 case formula::svEmptyCell
:
294 case formula::svHybridValueCell
:
301 bool ScFormulaResult::IsMultiline() const
303 if (meMultiline
== MULTILINE_UNKNOWN
)
305 svl::SharedString aStr
= GetString();
306 if (!aStr
.isEmpty() && aStr
.getString().indexOf('\n') != -1)
307 const_cast<ScFormulaResult
*>(this)->meMultiline
= MULTILINE_TRUE
;
309 const_cast<ScFormulaResult
*>(this)->meMultiline
= MULTILINE_FALSE
;
311 return meMultiline
== MULTILINE_TRUE
;
314 bool ScFormulaResult::GetErrorOrDouble( sal_uInt16
& rErr
, double& rVal
) const
322 formula::StackVar sv
= GetCellResultType();
323 if (sv
== formula::svError
)
325 if (GetType() == formula::svMatrixCell
)
327 // don't need to test for mpToken here, GetType() already did it
328 rErr
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
329 GetUpperLeftToken()->GetError();
333 rErr
= mpToken
->GetError();
347 sc::FormulaResultValue
ScFormulaResult::GetResult() const
350 return sc::FormulaResultValue(mnError
);
352 formula::StackVar sv
= GetCellResultType();
354 if (sv
== formula::svError
)
356 if (GetType() == formula::svMatrixCell
)
358 // don't need to test for mpToken here, GetType() already did it
359 nErr
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
360 GetUpperLeftToken()->GetError();
364 nErr
= mpToken
->GetError();
369 return sc::FormulaResultValue(nErr
);
372 return sc::FormulaResultValue(GetDouble());
375 // String result type needs token.
376 return sc::FormulaResultValue();
379 return sc::FormulaResultValue(GetString());
382 return sc::FormulaResultValue();
385 sal_uInt16
ScFormulaResult::GetResultError() const
389 formula::StackVar sv
= GetCellResultType();
390 if (sv
== formula::svError
)
392 if (GetType() == formula::svMatrixCell
)
393 // don't need to test for mpToken here, GetType() already did it
394 return static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
395 GetUpperLeftToken()->GetError();
397 return mpToken
->GetError();
402 void ScFormulaResult::SetResultError( sal_uInt16 nErr
)
407 formula::FormulaConstTokenRef
ScFormulaResult::GetToken() const
414 formula::FormulaConstTokenRef
ScFormulaResult::GetCellResultToken() const
416 if (GetType() == formula::svMatrixCell
)
417 // don't need to test for mpToken here, GetType() already did it
418 return static_cast<const ScMatrixCellResultToken
*>(mpToken
)->GetUpperLeftToken();
422 double ScFormulaResult::GetDouble() const
426 // Should really not be of type formula::svDouble here.
429 switch (mpToken
->GetType())
431 case formula::svHybridCell
:
432 case formula::svHybridValueCell
:
433 return mpToken
->GetDouble();
434 case formula::svMatrixCell
:
436 const ScMatrixCellResultToken
* p
=
437 static_cast<const ScMatrixCellResultToken
*>(mpToken
);
438 if (p
->GetUpperLeftType() == formula::svDouble
)
439 return p
->GetUpperLeftToken()->GetDouble();
453 svl::SharedString
ScFormulaResult::GetString() const
455 if (mbToken
&& mpToken
)
457 switch (mpToken
->GetType())
459 case formula::svString
:
460 case formula::svHybridCell
:
461 case formula::svHybridValueCell
:
462 return mpToken
->GetString();
463 case formula::svMatrixCell
:
465 const ScMatrixCellResultToken
* p
=
466 static_cast<const ScMatrixCellResultToken
*>(mpToken
);
467 if (p
->GetUpperLeftType() == formula::svString
)
468 return p
->GetUpperLeftToken()->GetString();
475 return svl::SharedString::getEmptyString();
478 ScConstMatrixRef
ScFormulaResult::GetMatrix() const
480 if (GetType() == formula::svMatrixCell
)
481 return mpToken
->GetMatrix();
485 const OUString
& ScFormulaResult::GetHybridFormula() const
487 if (GetType() == formula::svHybridCell
)
489 const ScHybridCellToken
* p
= dynamic_cast<const ScHybridCellToken
*>(mpToken
);
491 return p
->GetFormula();
493 return EMPTY_OUSTRING
;
496 void ScFormulaResult::SetHybridDouble( double f
)
499 if (mbToken
&& mpToken
)
501 if(GetType() == formula::svMatrixCell
)
505 svl::SharedString aString
= GetString();
506 OUString
aFormula( GetHybridFormula());
508 mpToken
= new ScHybridCellToken( f
, aString
, aFormula
);
516 meMultiline
= MULTILINE_FALSE
;
520 void ScFormulaResult::SetHybridString( const svl::SharedString
& rStr
)
522 // Obtain values before changing anything.
523 double f
= GetDouble();
524 OUString
aFormula( GetHybridFormula());
526 if (mbToken
&& mpToken
)
528 mpToken
= new ScHybridCellToken( f
, rStr
, aFormula
);
533 void ScFormulaResult::SetHybridFormula( const OUString
& rFormula
)
535 // Obtain values before changing anything.
536 double f
= GetDouble();
537 svl::SharedString aStr
= GetString();
539 if (mbToken
&& mpToken
)
541 mpToken
= new ScHybridCellToken( f
, aStr
, rFormula
);
546 void ScFormulaResult::SetMatrix( SCCOL nCols
, SCROW nRows
, const ScConstMatrixRef
& pMat
, formula::FormulaToken
* pUL
)
549 if (mbToken
&& mpToken
)
551 mpToken
= new ScMatrixFormulaCellToken(nCols
, nRows
, pMat
, pUL
);
556 const ScMatrixFormulaCellToken
* ScFormulaResult::GetMatrixFormulaCellToken() const
558 return (GetType() == formula::svMatrixCell
?
559 dynamic_cast<const ScMatrixFormulaCellToken
*>(mpToken
) : NULL
);
562 ScMatrixFormulaCellToken
* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
564 return const_cast<ScMatrixFormulaCellToken
*>( GetMatrixFormulaCellToken());
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */