Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include "cellvalue.hxx"
11 : #include "document.hxx"
12 : #include "column.hxx"
13 : #include "formulacell.hxx"
14 : #include "editeng/editobj.hxx"
15 : #include "editeng/editstat.hxx"
16 : #include "stringutil.hxx"
17 : #include "editutil.hxx"
18 : #include "tokenarray.hxx"
19 : #include "formula/token.hxx"
20 :
21 : namespace {
22 :
23 116 : CellType adjustCellType( CellType eOrig )
24 : {
25 116 : switch (eOrig)
26 : {
27 : case CELLTYPE_EDIT:
28 0 : return CELLTYPE_STRING;
29 : default:
30 : ;
31 : }
32 116 : return eOrig;
33 : }
34 :
35 : template<typename _T>
36 80 : OUString getString( const _T& rVal )
37 : {
38 80 : if (rVal.meType == CELLTYPE_STRING)
39 80 : return *rVal.mpString;
40 :
41 0 : if (rVal.meType == CELLTYPE_EDIT)
42 : {
43 0 : OUStringBuffer aRet;
44 0 : sal_Int32 n = rVal.mpEditText->GetParagraphCount();
45 0 : for (sal_Int32 i = 0; i < n; ++i)
46 : {
47 0 : if (i > 0)
48 0 : aRet.append('\n');
49 0 : aRet.append(rVal.mpEditText->GetText(i));
50 : }
51 0 : return aRet.makeStringAndClear();
52 : }
53 :
54 0 : return EMPTY_OUSTRING;
55 : }
56 :
57 2 : bool equalsFormulaCells( const ScFormulaCell* p1, const ScFormulaCell* p2 )
58 : {
59 2 : const ScTokenArray* pCode1 = p1->GetCode();
60 2 : const ScTokenArray* pCode2 = p2->GetCode();
61 :
62 2 : if (pCode1->GetLen() != pCode2->GetLen())
63 0 : return false;
64 :
65 2 : sal_uInt16 n = pCode1->GetLen();
66 2 : formula::FormulaToken** ppToken1 = pCode1->GetArray();
67 2 : formula::FormulaToken** ppToken2 = pCode2->GetArray();
68 8 : for (sal_uInt16 i = 0; i < n; ++i)
69 : {
70 6 : if (!ppToken1[i]->TextEqual(*(ppToken2[i])))
71 0 : return false;
72 : }
73 :
74 2 : return true;
75 : }
76 :
77 : template<typename _T>
78 58 : bool equalsWithoutFormatImpl( const _T& left, const _T& right )
79 : {
80 58 : CellType eType1 = adjustCellType(left.meType);
81 58 : CellType eType2 = adjustCellType(right.meType);
82 58 : if (eType1 != eType2)
83 7 : return false;
84 :
85 51 : switch (eType1)
86 : {
87 : case CELLTYPE_NONE:
88 0 : return true;
89 : case CELLTYPE_VALUE:
90 9 : return left.mfValue == right.mfValue;
91 : case CELLTYPE_STRING:
92 : {
93 40 : OUString aStr1 = getString(left);
94 80 : OUString aStr2 = getString(right);
95 80 : return aStr1 == aStr2;
96 : }
97 : case CELLTYPE_FORMULA:
98 2 : return equalsFormulaCells(left.mpFormula, right.mpFormula);
99 : default:
100 : ;
101 : }
102 0 : return false;
103 : }
104 :
105 : template<typename _T>
106 148 : void commitToColumn( const _T& rCell, ScColumn& rColumn, SCROW nRow )
107 : {
108 148 : switch (rCell.meType)
109 : {
110 : case CELLTYPE_STRING:
111 54 : rColumn.SetRawString(nRow, *rCell.mpString);
112 54 : break;
113 : case CELLTYPE_EDIT:
114 0 : rColumn.SetEditText(nRow, ScEditUtil::Clone(*rCell.mpEditText, rColumn.GetDoc()));
115 0 : break;
116 : case CELLTYPE_VALUE:
117 94 : rColumn.SetValue(nRow, rCell.mfValue);
118 94 : break;
119 : case CELLTYPE_FORMULA:
120 : {
121 0 : ScAddress aDestPos(rColumn.GetCol(), nRow, rColumn.GetTab());
122 0 : rColumn.SetFormulaCell(nRow, new ScFormulaCell(*rCell.mpFormula, rColumn.GetDoc(), aDestPos));
123 : }
124 0 : break;
125 : default:
126 0 : rColumn.Delete(nRow);
127 : }
128 148 : }
129 :
130 1000 : bool hasStringImpl( CellType eType, ScFormulaCell* pFormula )
131 : {
132 1000 : switch (eType)
133 : {
134 : case CELLTYPE_STRING:
135 : case CELLTYPE_EDIT:
136 93 : return true;
137 : case CELLTYPE_FORMULA:
138 551 : return !pFormula->IsValue();
139 : default:
140 356 : return false;
141 : }
142 : }
143 :
144 13326 : bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula )
145 : {
146 13326 : switch (eType)
147 : {
148 : case CELLTYPE_VALUE:
149 7398 : return true;
150 : case CELLTYPE_FORMULA:
151 463 : return pFormula->IsValue();
152 : default:
153 5465 : return false;
154 : }
155 : }
156 :
157 : }
158 :
159 30649 : ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
160 :
161 83 : ScCellValue::ScCellValue( const ScRefCellValue& rCell ) : meType(rCell.meType), mfValue(rCell.mfValue)
162 : {
163 83 : switch (rCell.meType)
164 : {
165 : case CELLTYPE_STRING:
166 20 : mpString = new OUString(*rCell.mpString);
167 20 : break;
168 : case CELLTYPE_EDIT:
169 0 : mpEditText = rCell.mpEditText->Clone();
170 0 : break;
171 : case CELLTYPE_FORMULA:
172 2 : mpFormula = rCell.mpFormula->Clone();
173 2 : break;
174 : default:
175 : ;
176 : }
177 83 : }
178 :
179 0 : ScCellValue::ScCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
180 0 : ScCellValue::ScCellValue( const OUString& rString ) : meType(CELLTYPE_STRING), mpString(new OUString(rString)) {}
181 0 : ScCellValue::ScCellValue( const EditTextObject& rEditText ) : meType(CELLTYPE_EDIT), mpEditText(rEditText.Clone()) {}
182 0 : ScCellValue::ScCellValue( const ScFormulaCell& rFormula ) : meType(CELLTYPE_FORMULA), mpFormula(rFormula.Clone()) {}
183 :
184 12146 : ScCellValue::ScCellValue( const ScCellValue& r ) : meType(r.meType), mfValue(r.mfValue)
185 : {
186 12146 : switch (r.meType)
187 : {
188 : case CELLTYPE_STRING:
189 2234 : mpString = new OUString(*r.mpString);
190 2234 : break;
191 : case CELLTYPE_EDIT:
192 352 : mpEditText = r.mpEditText->Clone();
193 352 : break;
194 : case CELLTYPE_FORMULA:
195 279 : mpFormula = r.mpFormula->Clone();
196 279 : break;
197 : default:
198 : ;
199 : }
200 12146 : }
201 :
202 42878 : ScCellValue::~ScCellValue()
203 : {
204 42878 : clear();
205 42878 : }
206 :
207 72291 : void ScCellValue::clear()
208 : {
209 72291 : switch (meType)
210 : {
211 : case CELLTYPE_STRING:
212 4488 : delete mpString;
213 4488 : break;
214 : case CELLTYPE_EDIT:
215 704 : delete mpEditText;
216 704 : break;
217 : case CELLTYPE_FORMULA:
218 560 : delete mpFormula;
219 560 : break;
220 : default:
221 : ;
222 : }
223 :
224 : // Reset to empty value.
225 72291 : meType = CELLTYPE_NONE;
226 72291 : mfValue = 0.0;
227 72291 : }
228 :
229 801 : void ScCellValue::set( double fValue )
230 : {
231 801 : clear();
232 801 : meType = CELLTYPE_VALUE;
233 801 : mfValue = fValue;
234 801 : }
235 :
236 15955 : void ScCellValue::set( const OUString& rStr )
237 : {
238 15955 : clear();
239 15955 : meType = CELLTYPE_STRING;
240 15955 : mpString = new OUString(rStr);
241 15955 : }
242 :
243 0 : void ScCellValue::set( const EditTextObject& rEditText )
244 : {
245 0 : clear();
246 0 : meType = CELLTYPE_EDIT;
247 0 : mpEditText = rEditText.Clone();
248 0 : }
249 :
250 0 : void ScCellValue::set( const ScFormulaCell& rFormula )
251 : {
252 0 : clear();
253 0 : meType = CELLTYPE_FORMULA;
254 0 : mpFormula = rFormula.Clone();
255 0 : }
256 :
257 511 : void ScCellValue::set( ScFormulaCell* pFormula )
258 : {
259 511 : clear();
260 511 : meType = CELLTYPE_FORMULA;
261 511 : mpFormula = pFormula;
262 511 : }
263 :
264 12146 : void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
265 : {
266 12146 : clear();
267 :
268 12146 : ScRefCellValue aRefVal;
269 12146 : aRefVal.assign(const_cast<ScDocument&>(rDoc), rPos);
270 :
271 12146 : meType = aRefVal.meType;
272 12146 : switch (meType)
273 : {
274 : case CELLTYPE_STRING:
275 2234 : mpString = new OUString(*aRefVal.mpString);
276 2234 : break;
277 : case CELLTYPE_EDIT:
278 352 : if (aRefVal.mpEditText)
279 352 : mpEditText = aRefVal.mpEditText->Clone();
280 352 : break;
281 : case CELLTYPE_VALUE:
282 5794 : mfValue = aRefVal.mfValue;
283 5794 : break;
284 : case CELLTYPE_FORMULA:
285 279 : mpFormula = aRefVal.mpFormula->Clone();
286 279 : break;
287 : default:
288 3487 : meType = CELLTYPE_NONE; // reset to empty.
289 12146 : }
290 12146 : }
291 :
292 0 : void ScCellValue::assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags )
293 : {
294 0 : clear();
295 :
296 0 : meType = rOther.meType;
297 0 : switch (meType)
298 : {
299 : case CELLTYPE_STRING:
300 0 : mpString = new OUString(*rOther.mpString);
301 0 : break;
302 : case CELLTYPE_EDIT:
303 : {
304 : // Switch to the pool of the destination document.
305 0 : ScFieldEditEngine& rEngine = rDestDoc.GetEditEngine();
306 0 : if (rOther.mpEditText->HasOnlineSpellErrors())
307 : {
308 0 : sal_uLong nControl = rEngine.GetControlWord();
309 0 : const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
310 0 : bool bNewControl = ((nControl & nSpellControl) != nSpellControl);
311 0 : if (bNewControl)
312 0 : rEngine.SetControlWord(nControl | nSpellControl);
313 0 : rEngine.SetText(*rOther.mpEditText);
314 0 : mpEditText = rEngine.CreateTextObject();
315 0 : if (bNewControl)
316 0 : rEngine.SetControlWord(nControl);
317 : }
318 : else
319 : {
320 0 : rEngine.SetText(*rOther.mpEditText);
321 0 : mpEditText = rEngine.CreateTextObject();
322 : }
323 : }
324 0 : break;
325 : case CELLTYPE_VALUE:
326 0 : mfValue = rOther.mfValue;
327 0 : break;
328 : case CELLTYPE_FORMULA:
329 : // Switch to the destination document.
330 0 : mpFormula = new ScFormulaCell(*rOther.mpFormula, rDestDoc, rOther.mpFormula->aPos, nCloneFlags);
331 0 : break;
332 : default:
333 0 : meType = CELLTYPE_NONE; // reset to empty.
334 : }
335 0 : }
336 :
337 0 : void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
338 : {
339 0 : switch (meType)
340 : {
341 : case CELLTYPE_STRING:
342 : {
343 0 : ScSetStringParam aParam;
344 0 : aParam.setTextInput();
345 0 : rDoc.SetString(rPos, *mpString, &aParam);
346 : }
347 0 : break;
348 : case CELLTYPE_EDIT:
349 0 : rDoc.SetEditText(rPos, mpEditText->Clone());
350 0 : break;
351 : case CELLTYPE_VALUE:
352 0 : rDoc.SetValue(rPos, mfValue);
353 0 : break;
354 : case CELLTYPE_FORMULA:
355 0 : rDoc.SetFormulaCell(rPos, mpFormula->Clone());
356 0 : break;
357 : default:
358 0 : rDoc.SetEmptyCell(rPos);
359 : }
360 0 : }
361 :
362 148 : void ScCellValue::commit( ScColumn& rColumn, SCROW nRow ) const
363 : {
364 148 : commitToColumn(*this, rColumn, nRow);
365 148 : }
366 :
367 0 : void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
368 : {
369 0 : switch (meType)
370 : {
371 : case CELLTYPE_STRING:
372 : {
373 : // Currently, string cannot be placed without copying.
374 0 : ScSetStringParam aParam;
375 0 : aParam.setTextInput();
376 0 : rDoc.SetString(rPos, *mpString, &aParam);
377 0 : delete mpString;
378 : }
379 0 : break;
380 : case CELLTYPE_EDIT:
381 : // Cell takes the ownership of the text object.
382 0 : rDoc.SetEditText(rPos, mpEditText);
383 0 : break;
384 : case CELLTYPE_VALUE:
385 0 : rDoc.SetValue(rPos, mfValue);
386 0 : break;
387 : case CELLTYPE_FORMULA:
388 : // This formula cell instance is directly placed in the document without copying.
389 0 : rDoc.SetFormulaCell(rPos, mpFormula);
390 0 : break;
391 : default:
392 0 : rDoc.SetEmptyCell(rPos);
393 : }
394 :
395 0 : meType = CELLTYPE_NONE;
396 0 : mfValue = 0.0;
397 0 : }
398 :
399 18493 : void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
400 : {
401 18493 : switch (meType)
402 : {
403 : case CELLTYPE_STRING:
404 : {
405 : // Currently, string cannot be placed without copying.
406 15955 : rColumn.SetRawString(nRow, *mpString);
407 15955 : delete mpString;
408 : }
409 15955 : break;
410 : case CELLTYPE_EDIT:
411 : // Cell takes the ownership of the text object.
412 0 : rColumn.SetEditText(nRow, mpEditText);
413 0 : break;
414 : case CELLTYPE_VALUE:
415 801 : rColumn.SetValue(nRow, mfValue);
416 801 : break;
417 : case CELLTYPE_FORMULA:
418 : // This formula cell instance is directly placed in the document without copying.
419 511 : rColumn.SetFormulaCell(nRow, mpFormula);
420 511 : break;
421 : default:
422 1226 : rColumn.Delete(nRow);
423 : }
424 :
425 18493 : meType = CELLTYPE_NONE;
426 18493 : mfValue = 0.0;
427 18493 : }
428 :
429 0 : bool ScCellValue::hasString() const
430 : {
431 0 : return hasStringImpl(meType, mpFormula);
432 : }
433 :
434 0 : bool ScCellValue::hasNumeric() const
435 : {
436 0 : return hasNumericImpl(meType, mpFormula);
437 : }
438 :
439 83 : bool ScCellValue::isEmpty() const
440 : {
441 83 : return meType == CELLTYPE_NONE;
442 : }
443 :
444 0 : bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
445 : {
446 0 : return equalsWithoutFormatImpl(*this, r);
447 : }
448 :
449 0 : ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
450 : {
451 0 : ScCellValue aTmp(r);
452 0 : swap(aTmp);
453 0 : return *this;
454 : }
455 :
456 11 : ScCellValue& ScCellValue::operator= ( const ScRefCellValue& r )
457 : {
458 11 : ScCellValue aTmp(r);
459 11 : swap(aTmp);
460 11 : return *this;
461 : }
462 :
463 11 : void ScCellValue::swap( ScCellValue& r )
464 : {
465 11 : std::swap(meType, r.meType);
466 :
467 : // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
468 : // the platform. Swap by double values.
469 11 : std::swap(mfValue, r.mfValue);
470 11 : }
471 :
472 3640153 : ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
473 340045 : ScRefCellValue::ScRefCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
474 107747 : ScRefCellValue::ScRefCellValue( const OUString* pString ) : meType(CELLTYPE_STRING), mpString(pString) {}
475 527 : ScRefCellValue::ScRefCellValue( const EditTextObject* pEditText ) : meType(CELLTYPE_EDIT), mpEditText(pEditText) {}
476 4363 : ScRefCellValue::ScRefCellValue( ScFormulaCell* pFormula ) : meType(CELLTYPE_FORMULA), mpFormula(pFormula) {}
477 :
478 : // It should be enough to copy the double value, which is at least as large
479 : // as the pointer values.
480 543936 : ScRefCellValue::ScRefCellValue( const ScRefCellValue& r ) : meType(r.meType), mfValue(r.mfValue) {}
481 :
482 4636771 : ScRefCellValue::~ScRefCellValue()
483 : {
484 4636771 : clear();
485 4636771 : }
486 :
487 7921436 : void ScRefCellValue::clear()
488 : {
489 : // Reset to empty value.
490 7921436 : meType = CELLTYPE_NONE;
491 7921436 : mfValue = 0.0;
492 7921436 : }
493 :
494 68827 : void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
495 : {
496 68827 : *this = rDoc.GetRefCellValue(rPos);
497 68827 : }
498 :
499 16422 : void ScRefCellValue::assign( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
500 : {
501 16422 : switch (itPos->type)
502 : {
503 : case sc::element_type_numeric:
504 : // Numeric cell
505 9259 : mfValue = sc::numeric_block::at(*itPos->data, nOffset);
506 9259 : meType = CELLTYPE_VALUE;
507 9259 : break;
508 : case sc::element_type_string:
509 : // String cell
510 5380 : mpString = &sc::string_block::at(*itPos->data, nOffset);
511 5380 : meType = CELLTYPE_STRING;
512 5380 : break;
513 : case sc::element_type_edittext:
514 : // Edit cell
515 465 : mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
516 465 : meType = CELLTYPE_EDIT;
517 465 : break;
518 : case sc::element_type_formula:
519 : // Formula cell
520 1318 : mpFormula = sc::formula_block::at(*itPos->data, nOffset);
521 1318 : meType = CELLTYPE_FORMULA;
522 1318 : break;
523 : default:
524 0 : clear();
525 : }
526 16422 : }
527 :
528 285 : void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
529 : {
530 285 : switch (meType)
531 : {
532 : case CELLTYPE_STRING:
533 : {
534 277 : ScSetStringParam aParam;
535 277 : aParam.setTextInput();
536 277 : rDoc.SetString(rPos, *mpString, &aParam);
537 : }
538 277 : break;
539 : case CELLTYPE_EDIT:
540 1 : rDoc.SetEditText(rPos, ScEditUtil::Clone(*mpEditText, rDoc));
541 1 : break;
542 : case CELLTYPE_VALUE:
543 4 : rDoc.SetValue(rPos, mfValue);
544 4 : break;
545 : case CELLTYPE_FORMULA:
546 3 : rDoc.SetFormulaCell(rPos, new ScFormulaCell(*mpFormula, rDoc, rPos));
547 3 : break;
548 : default:
549 0 : rDoc.SetEmptyCell(rPos);
550 : }
551 285 : }
552 :
553 0 : void ScRefCellValue::commit( ScColumn& rColumn, SCROW nRow ) const
554 : {
555 0 : commitToColumn(*this, rColumn, nRow);
556 0 : }
557 :
558 1000 : bool ScRefCellValue::hasString() const
559 : {
560 1000 : return hasStringImpl(meType, mpFormula);
561 : }
562 :
563 13326 : bool ScRefCellValue::hasNumeric() const
564 : {
565 13326 : return hasNumericImpl(meType, mpFormula);
566 : }
567 :
568 376 : double ScRefCellValue::getValue()
569 : {
570 376 : switch (meType)
571 : {
572 : case CELLTYPE_VALUE:
573 326 : return mfValue;
574 : case CELLTYPE_FORMULA:
575 50 : return mpFormula->GetValue();
576 : default:
577 : ;
578 : }
579 0 : return 0.0;
580 : }
581 :
582 1899 : OUString ScRefCellValue::getString()
583 : {
584 1899 : switch (meType)
585 : {
586 : case CELLTYPE_VALUE:
587 3 : return OUString::number(mfValue);
588 : case CELLTYPE_STRING:
589 1647 : return *mpString;
590 : case CELLTYPE_EDIT:
591 249 : if (mpEditText)
592 249 : return ScEditUtil::GetString(*mpEditText);
593 0 : break;
594 : case CELLTYPE_FORMULA:
595 0 : return mpFormula->GetString();
596 : default:
597 : ;
598 : }
599 0 : return EMPTY_OUSTRING;
600 : }
601 :
602 57672 : bool ScRefCellValue::isEmpty() const
603 : {
604 57672 : return meType == CELLTYPE_NONE;
605 : }
606 :
607 1231 : bool ScRefCellValue::hasEmptyValue()
608 : {
609 1231 : if (isEmpty())
610 731 : return true;
611 :
612 500 : if (meType == CELLTYPE_FORMULA)
613 154 : return mpFormula->IsEmpty();
614 :
615 346 : return false;
616 : }
617 :
618 58 : bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const
619 : {
620 58 : return equalsWithoutFormatImpl(*this, r);
621 : }
622 :
623 543936 : ScRefCellValue& ScRefCellValue::operator= ( const ScRefCellValue& r )
624 : {
625 543936 : ScRefCellValue aTmp(r);
626 543936 : swap(aTmp);
627 543936 : return *this;
628 : }
629 :
630 543936 : void ScRefCellValue::swap( ScRefCellValue& r )
631 : {
632 543936 : std::swap(meType, r.meType);
633 :
634 : // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
635 : // the platform. Swap by double values.
636 543936 : std::swap(mfValue, r.mfValue);
637 544029 : }
638 :
639 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|