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
)
71 void ScFormulaResult::ResetToDefaults()
75 mbEmptyDisplayedAsString
= false;
76 meMultiline
= MULTILINE_UNKNOWN
;
79 void ScFormulaResult::ResolveToken( const formula::FormulaToken
* p
)
91 case formula::svError
:
92 mnError
= p
->GetError();
95 // set in case mnError is 0 now, which shouldn't happen but ...
97 meMultiline
= MULTILINE_FALSE
;
99 case formula::svEmptyCell
:
101 mbEmptyDisplayedAsString
= static_cast<const ScEmptyCellToken
*>(p
)->IsDisplayedAsString();
104 meMultiline
= MULTILINE_FALSE
;
106 case formula::svDouble
:
107 mfValue
= p
->GetDouble();
110 meMultiline
= MULTILINE_FALSE
;
119 ScFormulaResult
& ScFormulaResult::operator=( const ScFormulaResult
& r
)
125 void ScFormulaResult::Assign( const ScFormulaResult
& r
)
131 if (mbToken
&& mpToken
)
135 mbEmptyDisplayedAsString
= r
.mbEmptyDisplayedAsString
;
136 meMultiline
= r
.meMultiline
;
140 // Matrix formula cell token must be cloned, see copy-ctor.
141 const ScMatrixFormulaCellToken
* pMatFormula
=
142 r
.GetMatrixFormulaCellToken();
144 SetToken( new ScMatrixFormulaCellToken( *pMatFormula
));
146 SetToken( r
.mpToken
);
149 SetDouble( r
.mfValue
);
150 // If there was an error there will be an error, no matter what Set...()
155 void ScFormulaResult::SetToken( const formula::FormulaToken
* p
)
158 IncrementTokenRef( p
);
159 // Handle a result obtained from the interpreter to be assigned to a matrix
160 // formula cell's ScMatrixFormulaCellToken.
161 ScMatrixFormulaCellToken
* pMatFormula
= GetMatrixFormulaCellTokenNonConst();
164 const ScMatrixCellResultToken
* pMatResult
=
165 (p
&& p
->GetType() == formula::svMatrixCell
?
166 dynamic_cast<const ScMatrixCellResultToken
*>(p
) : NULL
);
169 const ScMatrixFormulaCellToken
* pNewMatFormula
=
170 dynamic_cast<const ScMatrixFormulaCellToken
*>(pMatResult
);
173 SAL_WARN( "sc", "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
174 pMatFormula
->SetMatColsRows( pNewMatFormula
->GetMatCols(),
175 pNewMatFormula
->GetMatRows());
177 pMatFormula
->Assign( *pMatResult
);
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 pMatFormula
->Assign( *p
);
190 // NULL result? Well, if you say so ...
191 pMatFormula
->ResetResult();
196 if (mbToken
&& mpToken
)
202 void ScFormulaResult::SetDouble( double f
)
205 // Handle a result obtained from the interpreter to be assigned to a matrix
206 // formula cell's ScMatrixFormulaCellToken.
207 ScMatrixFormulaCellToken
* pMatFormula
= GetMatrixFormulaCellTokenNonConst();
209 pMatFormula
->SetUpperLeftDouble( f
);
212 if (mbToken
&& mpToken
)
216 meMultiline
= MULTILINE_FALSE
;
220 formula::StackVar
ScFormulaResult::GetType() const
222 // Order is significant.
224 return formula::svError
;
226 return formula::svEmptyCell
;
228 return formula::svDouble
;
230 return mpToken
->GetType();
231 return formula::svUnknown
;
234 formula::StackVar
ScFormulaResult::GetCellResultType() const
236 formula::StackVar sv
= GetType();
237 if (sv
== formula::svMatrixCell
)
238 // don't need to test for mpToken here, GetType() already did it
239 sv
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->GetUpperLeftType();
243 bool ScFormulaResult::IsEmptyDisplayedAsString() const
246 return mbEmptyDisplayedAsString
;
247 if (GetType() == formula::svMatrixCell
)
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 mpToken
)->GetUpperLeftToken().get());
254 return p
->IsDisplayedAsString();
261 inline bool isValue( formula::StackVar sv
)
263 return sv
== formula::svDouble
|| sv
== formula::svError
264 || sv
== formula::svEmptyCell
|| sv
== formula::svHybridValueCell
;
267 inline bool isString( formula::StackVar sv
)
271 case formula::svString
:
272 case formula::svHybridCell
:
273 case formula::svHybridValueCell
:
284 bool ScFormulaResult::IsValue() const
286 return isValue(GetCellResultType());
289 bool ScFormulaResult::IsValueNoError() const
291 switch (GetCellResultType())
293 case formula::svDouble
:
294 case formula::svEmptyCell
:
295 case formula::svHybridValueCell
:
302 bool ScFormulaResult::IsMultiline() const
304 if (meMultiline
== MULTILINE_UNKNOWN
)
306 svl::SharedString aStr
= GetString();
307 if (!aStr
.isEmpty() && aStr
.getString().indexOf('\n') != -1)
308 const_cast<ScFormulaResult
*>(this)->meMultiline
= MULTILINE_TRUE
;
310 const_cast<ScFormulaResult
*>(this)->meMultiline
= MULTILINE_FALSE
;
312 return meMultiline
== MULTILINE_TRUE
;
315 bool ScFormulaResult::GetErrorOrDouble( sal_uInt16
& rErr
, double& rVal
) const
323 formula::StackVar sv
= GetCellResultType();
324 if (sv
== formula::svError
)
326 if (GetType() == formula::svMatrixCell
)
328 // don't need to test for mpToken here, GetType() already did it
329 rErr
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
330 GetUpperLeftToken()->GetError();
334 rErr
= mpToken
->GetError();
348 bool ScFormulaResult::GetErrorOrString( sal_uInt16
& rErr
, svl::SharedString
& rStr
) const
356 formula::StackVar sv
= GetCellResultType();
357 if (sv
== formula::svError
)
359 if (GetType() == formula::svMatrixCell
)
361 // don't need to test for mpToken here, GetType() already did it
362 rErr
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
363 GetUpperLeftToken()->GetError();
367 rErr
= mpToken
->GetError();
384 sc::FormulaResultValue
ScFormulaResult::GetResult() const
387 return sc::FormulaResultValue(mnError
);
389 formula::StackVar sv
= GetCellResultType();
391 if (sv
== formula::svError
)
393 if (GetType() == formula::svMatrixCell
)
395 // don't need to test for mpToken here, GetType() already did it
396 nErr
= static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
397 GetUpperLeftToken()->GetError();
401 nErr
= mpToken
->GetError();
406 return sc::FormulaResultValue(nErr
);
409 return sc::FormulaResultValue(GetDouble());
412 // String result type needs token.
413 return sc::FormulaResultValue();
416 return sc::FormulaResultValue(GetString());
419 return sc::FormulaResultValue();
422 sal_uInt16
ScFormulaResult::GetResultError() const
426 formula::StackVar sv
= GetCellResultType();
427 if (sv
== formula::svError
)
429 if (GetType() == formula::svMatrixCell
)
430 // don't need to test for mpToken here, GetType() already did it
431 return static_cast<const ScMatrixCellResultToken
*>(mpToken
)->
432 GetUpperLeftToken()->GetError();
434 return mpToken
->GetError();
439 void ScFormulaResult::SetResultError( sal_uInt16 nErr
)
444 formula::FormulaConstTokenRef
ScFormulaResult::GetToken() const
451 formula::FormulaConstTokenRef
ScFormulaResult::GetCellResultToken() const
453 if (GetType() == formula::svMatrixCell
)
454 // don't need to test for mpToken here, GetType() already did it
455 return static_cast<const ScMatrixCellResultToken
*>(mpToken
)->GetUpperLeftToken();
459 double ScFormulaResult::GetDouble() const
463 // Should really not be of type formula::svDouble here.
466 switch (mpToken
->GetType())
468 case formula::svHybridCell
:
469 case formula::svHybridValueCell
:
470 return mpToken
->GetDouble();
471 case formula::svMatrixCell
:
473 const ScMatrixCellResultToken
* p
=
474 static_cast<const ScMatrixCellResultToken
*>(mpToken
);
475 if (p
->GetUpperLeftType() == formula::svDouble
)
476 return p
->GetUpperLeftToken()->GetDouble();
490 svl::SharedString
ScFormulaResult::GetString() const
492 if (mbToken
&& mpToken
)
494 switch (mpToken
->GetType())
496 case formula::svString
:
497 case formula::svHybridCell
:
498 case formula::svHybridValueCell
:
499 return mpToken
->GetString();
500 case formula::svMatrixCell
:
502 const ScMatrixCellResultToken
* p
=
503 static_cast<const ScMatrixCellResultToken
*>(mpToken
);
504 if (p
->GetUpperLeftType() == formula::svString
)
505 return p
->GetUpperLeftToken()->GetString();
512 return svl::SharedString::getEmptyString();
515 ScConstMatrixRef
ScFormulaResult::GetMatrix() const
517 if (GetType() == formula::svMatrixCell
)
518 return static_cast<const ScToken
*>(mpToken
)->GetMatrix();
522 const OUString
& ScFormulaResult::GetHybridFormula() const
524 if (GetType() == formula::svHybridCell
)
526 const ScHybridCellToken
* p
= dynamic_cast<const ScHybridCellToken
*>(mpToken
);
528 return p
->GetFormula();
530 return EMPTY_OUSTRING
;
533 void ScFormulaResult::SetHybridDouble( double f
)
536 if (mbToken
&& mpToken
)
538 if(GetType() == formula::svMatrixCell
)
542 svl::SharedString aString
= GetString();
543 OUString
aFormula( GetHybridFormula());
545 mpToken
= new ScHybridCellToken( f
, aString
, aFormula
);
553 meMultiline
= MULTILINE_FALSE
;
557 void ScFormulaResult::SetHybridString( const OUString
& rStr
)
559 // Obtain values before changing anything.
560 double f
= GetDouble();
561 OUString
aFormula( GetHybridFormula());
563 if (mbToken
&& mpToken
)
565 mpToken
= new ScHybridCellToken( f
, rStr
, aFormula
);
570 void ScFormulaResult::SetHybridFormula( const OUString
& rFormula
)
572 // Obtain values before changing anything.
573 double f
= GetDouble();
574 svl::SharedString aStr
= GetString();
576 if (mbToken
&& mpToken
)
578 mpToken
= new ScHybridCellToken( f
, aStr
, rFormula
);
583 void ScFormulaResult::SetMatrix( SCCOL nCols
, SCROW nRows
, const ScConstMatrixRef
& pMat
, formula::FormulaToken
* pUL
)
586 if (mbToken
&& mpToken
)
588 mpToken
= new ScMatrixFormulaCellToken(nCols
, nRows
, pMat
, pUL
);
593 const ScMatrixFormulaCellToken
* ScFormulaResult::GetMatrixFormulaCellToken() const
595 return (GetType() == formula::svMatrixCell
?
596 dynamic_cast<const ScMatrixFormulaCellToken
*>(mpToken
) : NULL
);
599 ScMatrixFormulaCellToken
* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
601 return const_cast<ScMatrixFormulaCellToken
*>( GetMatrixFormulaCellToken());
604 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */