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