Branch data 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 : 3769 : ScFormulaResult::ScFormulaResult() :
32 : : mpToken(NULL), mnError(0), mbToken(true),
33 : : mbEmpty(false), mbEmptyDisplayedAsString(false),
34 : 3769 : meMultiline(MULTILINE_UNKNOWN) {}
35 : :
36 : 334 : ScFormulaResult::ScFormulaResult( const ScFormulaResult & r ) :
37 : : mnError( r.mnError), mbToken( r.mbToken),
38 : : mbEmpty( r.mbEmpty),
39 : : mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
40 : 334 : meMultiline( r.meMultiline)
41 : : {
42 [ + + ]: 334 : if (mbToken)
43 : : {
44 : 206 : mpToken = r.mpToken;
45 [ + + ]: 206 : 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 : 36 : r.GetMatrixFormulaCellToken();
53 [ + + ]: 36 : if (pMatFormula)
54 : : {
55 [ + - ]: 1 : mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
56 : 1 : mpToken->IncRef();
57 : : }
58 : : else
59 : 35 : IncrementTokenRef( mpToken);
60 : : }
61 : : }
62 : : else
63 : 128 : mfValue = r.mfValue;
64 : 334 : }
65 : :
66 : 686 : ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
67 : : mnError(0), mbToken(false), mbEmpty(false), mbEmptyDisplayedAsString(false),
68 : 686 : meMultiline(MULTILINE_UNKNOWN)
69 : : {
70 : 686 : SetToken( p);
71 : 686 : }
72 : :
73 : 4533 : ScFormulaResult::~ScFormulaResult()
74 : : {
75 [ + + ][ + + ]: 4533 : if (mbToken && mpToken)
76 : 333 : mpToken->DecRef();
77 : 4533 : }
78 : :
79 : :
80 : 10498 : void ScFormulaResult::ResetToDefaults()
81 : : {
82 : 10498 : mnError = 0;
83 : 10498 : mbEmpty = false;
84 : 10498 : mbEmptyDisplayedAsString = false;
85 : 10498 : meMultiline = MULTILINE_UNKNOWN;
86 : 10498 : }
87 : :
88 : 3417 : void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
89 : : {
90 : 3417 : ResetToDefaults();
91 [ + + ]: 3417 : if (!p)
92 : : {
93 : 563 : mpToken = p;
94 : 563 : mbToken = true;
95 : : }
96 : : else
97 : : {
98 [ + + + + ]: 2854 : switch (p->GetType())
99 : : {
100 : : case formula::svError:
101 : 312 : mnError = p->GetError();
102 : 312 : p->DecRef();
103 : 312 : mbToken = false;
104 : : // set in case mnError is 0 now, which shouldn't happen but ...
105 : 312 : mfValue = 0.0;
106 : 312 : meMultiline = MULTILINE_FALSE;
107 : 312 : break;
108 : : case formula::svEmptyCell:
109 : 39 : mbEmpty = true;
110 : 39 : mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
111 : 39 : p->DecRef();
112 : 39 : mbToken = false;
113 : 39 : meMultiline = MULTILINE_FALSE;
114 : 39 : break;
115 : : case formula::svDouble:
116 : 2092 : mfValue = p->GetDouble();
117 : 2092 : p->DecRef();
118 : 2092 : mbToken = false;
119 : 2092 : meMultiline = MULTILINE_FALSE;
120 : 2092 : break;
121 : : default:
122 : 411 : mpToken = p;
123 : 411 : mbToken = true;
124 : : }
125 : : }
126 : 3417 : }
127 : :
128 : 0 : ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
129 : : {
130 : 0 : Assign( r);
131 : 0 : return *this;
132 : : }
133 : :
134 : 470 : void ScFormulaResult::Assign( const ScFormulaResult & r )
135 : : {
136 [ - + ]: 470 : if (this == &r)
137 : 470 : return;
138 [ + + ]: 470 : if (r.mbEmpty)
139 : : {
140 [ + - ][ - + ]: 3 : if (mbToken && mpToken)
141 : 0 : mpToken->DecRef();
142 : 3 : mbToken = false;
143 : 3 : mbEmpty = true;
144 : 3 : mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
145 : 3 : meMultiline = r.meMultiline;
146 : : }
147 [ + + ]: 467 : else if (r.mbToken)
148 : : {
149 : : // Matrix formula cell token must be cloned, see copy-ctor.
150 : : const ScMatrixFormulaCellToken* pMatFormula =
151 : 34 : r.GetMatrixFormulaCellToken();
152 [ - + ]: 34 : if (pMatFormula)
153 [ # # ]: 0 : SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
154 : : else
155 : 34 : SetToken( r.mpToken);
156 : : }
157 : : else
158 : 433 : SetDouble( r.mfValue);
159 : : // If there was an error there will be an error, no matter what Set...()
160 : : // methods did.
161 : 470 : mnError = r.mnError;
162 : : }
163 : :
164 : 3539 : void ScFormulaResult::SetToken( const formula::FormulaToken* p )
165 : : {
166 : 3539 : ResetToDefaults();
167 : 3539 : IncrementTokenRef( p);
168 : : // Handle a result obtained from the interpreter to be assigned to a matrix
169 : : // formula cell's ScMatrixFormulaCellToken.
170 : 3539 : ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
171 [ + + ]: 3539 : if (pMatFormula)
172 : : {
173 : : const ScMatrixCellResultToken* pMatResult =
174 : 122 : (p && p->GetType() == formula::svMatrixCell ?
175 [ + - + + ]: 244 : dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
[ - + ]
176 [ + + ]: 122 : if (pMatResult)
177 : : {
178 : : const ScMatrixFormulaCellToken* pNewMatFormula =
179 [ - + ]: 58 : dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
180 [ - + ]: 58 : 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 : 58 : pMatFormula->Assign( *pMatResult);
187 : 58 : p->DecRef();
188 : : }
189 [ + - ]: 64 : 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 : 64 : pMatFormula->Assign( *p);
195 : 64 : p->DecRef();
196 : : }
197 : : else
198 : : {
199 : : // NULL result? Well, if you say so ...
200 : 0 : pMatFormula->ResetResult();
201 : : }
202 : : }
203 : : else
204 : : {
205 [ + + ][ + + ]: 3417 : if (mbToken && mpToken)
206 : 208 : mpToken->DecRef();
207 : 3417 : ResolveToken( p);
208 : : }
209 : 3539 : }
210 : :
211 : 2253 : void ScFormulaResult::SetDouble( double f )
212 : : {
213 : 2253 : ResetToDefaults();
214 : : // Handle a result obtained from the interpreter to be assigned to a matrix
215 : : // formula cell's ScMatrixFormulaCellToken.
216 : 2253 : ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
217 [ + + ]: 2253 : if (pMatFormula)
218 : 53 : pMatFormula->SetUpperLeftDouble( f);
219 : : else
220 : : {
221 [ + + ][ - + ]: 2200 : if (mbToken && mpToken)
222 : 0 : mpToken->DecRef();
223 : 2200 : mfValue = f;
224 : 2200 : mbToken = false;
225 : 2200 : meMultiline = MULTILINE_FALSE;
226 : : }
227 : 2253 : }
228 : :
229 : 40539 : formula::StackVar ScFormulaResult::GetType() const
230 : : {
231 : : // Order is significant.
232 [ + + ]: 40539 : if (mnError)
233 : 1312 : return formula::svError;
234 [ + + ]: 39227 : if (mbEmpty)
235 : 201 : return formula::svEmptyCell;
236 [ + + ]: 39026 : if (!mbToken)
237 : 29012 : return formula::svDouble;
238 [ + + ]: 10014 : if (mpToken)
239 : 5071 : return mpToken->GetType();
240 : 40539 : return formula::svUnknown;
241 : : }
242 : :
243 : 29602 : formula::StackVar ScFormulaResult::GetCellResultType() const
244 : : {
245 : 29602 : formula::StackVar sv = GetType();
246 [ + + ]: 29602 : if (sv == formula::svMatrixCell)
247 : : // don't need to test for mpToken here, GetType() already did it
248 : 845 : sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
249 : 29602 : return sv;
250 : : }
251 : :
252 : 1808 : bool ScFormulaResult::IsEmptyDisplayedAsString() const
253 : : {
254 [ + + ]: 1808 : if (mbEmpty)
255 : 12 : return mbEmptyDisplayedAsString;
256 [ + + ]: 1796 : 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 [ - + ]: 10 : mpToken)->GetUpperLeftToken().get());
262 [ - + ]: 10 : if (p)
263 : 0 : return p->IsDisplayedAsString();
264 : : }
265 : 1808 : return false;
266 : : }
267 : :
268 : 15275 : bool ScFormulaResult::IsValue() const
269 : : {
270 : 15275 : formula::StackVar sv = GetCellResultType();
271 [ + + ][ + + ]: 15275 : return sv == formula::svDouble || sv == formula::svError || sv == formula::svEmptyCell;
[ + + ]
272 : : }
273 : :
274 : 40 : bool ScFormulaResult::IsMultiline() const
275 : : {
276 [ + + ]: 40 : if (meMultiline == MULTILINE_UNKNOWN)
277 : : {
278 : 32 : const String& rStr = GetString();
279 [ # # ][ - + ]: 32 : if (rStr.Len() && rStr.Search( _LF ) != STRING_NOTFOUND)
[ - + ]
280 : 0 : const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
281 : : else
282 : 32 : const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
283 : : }
284 : 40 : return meMultiline == MULTILINE_TRUE;
285 : : }
286 : :
287 : 13283 : sal_uInt16 ScFormulaResult::GetResultError() const
288 : : {
289 [ + + ]: 13283 : if (mnError)
290 : 550 : return mnError;
291 : 12733 : formula::StackVar sv = GetCellResultType();
292 [ + + ]: 12733 : if (sv == formula::svError)
293 : : {
294 [ + - ]: 3 : 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 [ + - ]: 3 : GetUpperLeftToken()->GetError();
298 [ # # ]: 0 : if (mpToken)
299 : 0 : return mpToken->GetError();
300 : : }
301 : 13283 : return 0;
302 : : }
303 : :
304 : 2668 : void ScFormulaResult::SetResultError( sal_uInt16 nErr )
305 : : {
306 : 2668 : mnError = nErr;
307 : 2668 : }
308 : :
309 : 0 : formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
310 : : {
311 [ # # ]: 0 : if (mbToken)
312 : 0 : return mpToken;
313 : 0 : return NULL;
314 : : }
315 : :
316 : 23 : formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
317 : : {
318 [ + - ]: 23 : if (GetType() == formula::svMatrixCell)
319 : : // don't need to test for mpToken here, GetType() already did it
320 : 23 : return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
321 : 23 : return GetToken();
322 : : }
323 : :
324 : 11646 : double ScFormulaResult::GetDouble() const
325 : : {
326 [ + + ]: 11646 : if (mbToken)
327 : : {
328 : : // Should really not be of type formula::svDouble here.
329 [ + + ]: 687 : if (mpToken)
330 : : {
331 [ - + + ]: 464 : switch (mpToken->GetType())
332 : : {
333 : : case formula::svHybridCell:
334 : 0 : return mpToken->GetDouble();
335 : : case formula::svMatrixCell:
336 : : {
337 : : const ScMatrixCellResultToken* p =
338 : 307 : static_cast<const ScMatrixCellResultToken*>(mpToken);
339 [ + + ]: 307 : if (p->GetUpperLeftType() == formula::svDouble)
340 [ + - ]: 274 : return p->GetUpperLeftToken()->GetDouble();
341 : : }
342 : 190 : break;
343 : : default:
344 : : ; // nothing
345 : : }
346 : : }
347 : 413 : return 0.0;
348 : : }
349 [ + + ]: 10959 : if (mbEmpty)
350 : 66 : return 0.0;
351 : 11646 : return mfValue;
352 : : }
353 : :
354 : 499 : const String & ScFormulaResult::GetString() const
355 : : {
356 [ + - ][ + - ]: 499 : if (mbToken && mpToken)
357 : : {
358 [ + - - ]: 499 : switch (mpToken->GetType())
359 : : {
360 : : case formula::svString:
361 : : case formula::svHybridCell:
362 : 499 : return mpToken->GetString();
363 : : case formula::svMatrixCell:
364 : : {
365 : : const ScMatrixCellResultToken* p =
366 : 0 : static_cast<const ScMatrixCellResultToken*>(mpToken);
367 [ # # ]: 0 : if (p->GetUpperLeftType() == formula::svString)
368 [ # # ]: 0 : return p->GetUpperLeftToken()->GetString();
369 : : }
370 : 0 : break;
371 : : default:
372 : : ; // nothing
373 : : }
374 : : }
375 : 499 : return EMPTY_STRING;
376 : : }
377 : :
378 : 2924 : ScConstMatrixRef ScFormulaResult::GetMatrix() const
379 : : {
380 [ + + ]: 2924 : if (GetType() == formula::svMatrixCell)
381 : 425 : return static_cast<const ScToken*>(mpToken)->GetMatrix();
382 : 2924 : return NULL;
383 : : }
384 : :
385 : 172 : const String & ScFormulaResult::GetHybridFormula() const
386 : : {
387 [ - + ]: 172 : 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 : 172 : return EMPTY_STRING;
394 : : }
395 : :
396 : 1117 : void ScFormulaResult::SetHybridDouble( double f )
397 : : {
398 : 1117 : ResetToDefaults();
399 [ + + ][ + - ]: 1117 : if (mbToken && mpToken)
400 : : {
401 [ + - ]: 45 : if(GetType() == formula::svMatrixCell)
402 : 45 : 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 : 45 : }
411 : : }
412 : : else
413 : : {
414 : 1072 : mfValue = f;
415 : 1072 : mbToken = false;
416 : 1072 : meMultiline = MULTILINE_FALSE;
417 : : }
418 : 1117 : }
419 : :
420 : 172 : void ScFormulaResult::SetHybridString( const rtl::OUString & rStr )
421 : : {
422 : : // Obtain values before changing anything.
423 [ + - ]: 172 : double f = GetDouble();
424 [ + - ][ + - ]: 172 : String aFormula( GetHybridFormula());
425 : 172 : ResetToDefaults();
426 [ + + ][ + - ]: 172 : if (mbToken && mpToken)
427 [ + - ]: 30 : mpToken->DecRef();
428 [ + - ][ + - ]: 172 : mpToken = new ScHybridCellToken( f, rStr, aFormula);
[ + - ][ + - ]
429 : 172 : mpToken->IncRef();
430 [ + - ]: 172 : mbToken = true;
431 : 172 : }
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 : 5974 : const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
447 : : {
448 : 5974 : return (GetType() == formula::svMatrixCell ?
449 [ + - ][ + + ]: 5974 : dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
450 : : }
451 : :
452 : 5876 : ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
453 : : {
454 : 5876 : return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
455 : : }
456 : :
457 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|