fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / formularesult.cxx
blob61b56f5385cded99877522c2be30be47c4ffc4b5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "formularesult.hxx"
11 #include "scmatrix.hxx"
13 namespace sc {
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),
29 mbEmpty( r.mbEmpty),
30 mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
31 meMultiline( r.meMultiline)
33 if (mbToken)
35 mpToken = r.mpToken;
36 if (mpToken)
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();
44 if (pMatFormula)
46 mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
47 mpToken->IncRef();
49 else
50 IncrementTokenRef( mpToken);
53 else
54 mfValue = r.mfValue;
57 ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
58 mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
59 meMultiline(MULTILINE_UNKNOWN)
61 SetToken( p);
64 ScFormulaResult::~ScFormulaResult()
66 if (mbToken && mpToken)
67 mpToken->DecRef();
70 void ScFormulaResult::ResetToDefaults()
72 mnError = 0;
73 mbEmpty = false;
74 mbEmptyDisplayedAsString = false;
75 meMultiline = MULTILINE_UNKNOWN;
78 void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
80 ResetToDefaults();
81 if (!p)
83 mpToken = p;
84 mbToken = true;
86 else
88 switch (p->GetType())
90 case formula::svError:
91 mnError = p->GetError();
92 p->DecRef();
93 mbToken = false;
94 // set in case mnError is 0 now, which shouldn't happen but ...
95 mfValue = 0.0;
96 meMultiline = MULTILINE_FALSE;
97 break;
98 case formula::svEmptyCell:
99 mbEmpty = true;
100 mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
101 p->DecRef();
102 mbToken = false;
103 meMultiline = MULTILINE_FALSE;
104 break;
105 case formula::svDouble:
106 mfValue = p->GetDouble();
107 p->DecRef();
108 mbToken = false;
109 meMultiline = MULTILINE_FALSE;
110 break;
111 default:
112 mpToken = p;
113 mbToken = true;
118 ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
120 Assign( r);
121 return *this;
124 void ScFormulaResult::Assign( const ScFormulaResult & r )
126 if (this == &r)
127 return;
128 if (r.mbEmpty)
130 if (mbToken && mpToken)
131 mpToken->DecRef();
132 mbToken = false;
133 mbEmpty = true;
134 mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
135 meMultiline = r.meMultiline;
137 else if (r.mbToken)
139 // Matrix formula cell token must be cloned, see copy-ctor.
140 const ScMatrixFormulaCellToken* pMatFormula =
141 r.GetMatrixFormulaCellToken();
142 if (pMatFormula)
143 SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
144 else
145 SetToken( r.mpToken);
147 else
148 SetDouble( r.mfValue);
149 // If there was an error there will be an error, no matter what Set...()
150 // methods did.
151 mnError = r.mnError;
154 void ScFormulaResult::SetToken( const formula::FormulaToken* p )
156 ResetToDefaults();
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();
161 if (pMatFormula)
163 const ScMatrixCellResultToken* pMatResult =
164 (p && p->GetType() == formula::svMatrixCell ?
165 dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
166 if (pMatResult)
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);
177 p->DecRef();
179 else if (p)
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);
185 p->DecRef();
187 else
189 // NULL result? Well, if you say so ...
190 pMatFormula->ResetResult();
193 else
195 if (mbToken && mpToken)
196 mpToken->DecRef();
197 ResolveToken( p);
201 void ScFormulaResult::SetDouble( double f )
203 ResetToDefaults();
204 // Handle a result obtained from the interpreter to be assigned to a matrix
205 // formula cell's ScMatrixFormulaCellToken.
206 ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
207 if (pMatFormula)
208 pMatFormula->SetUpperLeftDouble( f);
209 else
211 if (mbToken && mpToken)
212 mpToken->DecRef();
213 mfValue = f;
214 mbToken = false;
215 meMultiline = MULTILINE_FALSE;
219 formula::StackVar ScFormulaResult::GetType() const
221 // Order is significant.
222 if (mnError)
223 return formula::svError;
224 if (mbEmpty)
225 return formula::svEmptyCell;
226 if (!mbToken)
227 return formula::svDouble;
228 if (mpToken)
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();
239 return sv;
242 bool ScFormulaResult::IsEmptyDisplayedAsString() const
244 if (mbEmpty)
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());
252 if (p)
253 return p->IsDisplayedAsString();
255 return false;
258 namespace {
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 )
268 switch (sv)
270 case formula::svString:
271 case formula::svHybridCell:
272 case formula::svHybridValueCell:
273 return true;
274 default:
275 break;
278 return false;
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:
295 return true;
296 default:
297 return false;
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;
308 else
309 const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
311 return meMultiline == MULTILINE_TRUE;
314 bool ScFormulaResult::GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const
316 if (mnError)
318 rErr = mnError;
319 return true;
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();
331 else if (mpToken)
333 rErr = mpToken->GetError();
337 if (rErr)
338 return true;
340 if (!isValue(sv))
341 return false;
343 rVal = GetDouble();
344 return true;
347 sc::FormulaResultValue ScFormulaResult::GetResult() const
349 if (mnError)
350 return sc::FormulaResultValue(mnError);
352 formula::StackVar sv = GetCellResultType();
353 sal_uInt16 nErr = 0;
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();
362 else if (mpToken)
364 nErr = mpToken->GetError();
368 if (nErr)
369 return sc::FormulaResultValue(nErr);
371 if (isValue(sv))
372 return sc::FormulaResultValue(GetDouble());
374 if (!mbToken)
375 // String result type needs token.
376 return sc::FormulaResultValue();
378 if (isString(sv))
379 return sc::FormulaResultValue(GetString());
381 // Invalid
382 return sc::FormulaResultValue();
385 sal_uInt16 ScFormulaResult::GetResultError() const
387 if (mnError)
388 return mnError;
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();
396 if (mpToken)
397 return mpToken->GetError();
399 return 0;
402 void ScFormulaResult::SetResultError( sal_uInt16 nErr )
404 mnError = nErr;
407 formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
409 if (mbToken)
410 return mpToken;
411 return NULL;
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();
419 return GetToken();
422 double ScFormulaResult::GetDouble() const
424 if (mbToken)
426 // Should really not be of type formula::svDouble here.
427 if (mpToken)
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();
441 break;
442 default:
443 ; // nothing
446 return 0.0;
448 if (mbEmpty)
449 return 0.0;
450 return mfValue;
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();
470 break;
471 default:
472 ; // nothing
475 return svl::SharedString::getEmptyString();
478 ScConstMatrixRef ScFormulaResult::GetMatrix() const
480 if (GetType() == formula::svMatrixCell)
481 return mpToken->GetMatrix();
482 return NULL;
485 const OUString& ScFormulaResult::GetHybridFormula() const
487 if (GetType() == formula::svHybridCell)
489 const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
490 if (p)
491 return p->GetFormula();
493 return EMPTY_OUSTRING;
496 void ScFormulaResult::SetHybridDouble( double f )
498 ResetToDefaults();
499 if (mbToken && mpToken)
501 if(GetType() == formula::svMatrixCell)
502 SetDouble(f);
503 else
505 svl::SharedString aString = GetString();
506 OUString aFormula( GetHybridFormula());
507 mpToken->DecRef();
508 mpToken = new ScHybridCellToken( f, aString, aFormula);
509 mpToken->IncRef();
512 else
514 mfValue = f;
515 mbToken = false;
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());
525 ResetToDefaults();
526 if (mbToken && mpToken)
527 mpToken->DecRef();
528 mpToken = new ScHybridCellToken( f, rStr, aFormula);
529 mpToken->IncRef();
530 mbToken = true;
533 void ScFormulaResult::SetHybridFormula( const OUString & rFormula )
535 // Obtain values before changing anything.
536 double f = GetDouble();
537 svl::SharedString aStr = GetString();
538 ResetToDefaults();
539 if (mbToken && mpToken)
540 mpToken->DecRef();
541 mpToken = new ScHybridCellToken( f, aStr, rFormula);
542 mpToken->IncRef();
543 mbToken = true;
546 void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
548 ResetToDefaults();
549 if (mbToken && mpToken)
550 mpToken->DecRef();
551 mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL);
552 mpToken->IncRef();
553 mbToken = true;
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: */