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