1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <cellvalue.hxx>
11 #include <document.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 #include <svl/sharedstringpool.hxx>
26 CellType
adjustCellType( CellType eOrig
)
31 return CELLTYPE_STRING
;
39 OUString
getString( const T
& rVal
)
41 if (rVal
.getType() == CELLTYPE_STRING
)
42 return rVal
.getSharedString()->getString();
44 if (rVal
.getType() == CELLTYPE_EDIT
)
47 sal_Int32 n
= rVal
.getEditText()->GetParagraphCount();
48 for (sal_Int32 i
= 0; i
< n
; ++i
)
52 aRet
.append(rVal
.getEditText()->GetText(i
));
54 return aRet
.makeStringAndClear();
60 bool equalsFormulaCells( const ScFormulaCell
* p1
, const ScFormulaCell
* p2
)
62 const ScTokenArray
* pCode1
= p1
->GetCode();
63 const ScTokenArray
* pCode2
= p2
->GetCode();
65 if (pCode1
->GetLen() != pCode2
->GetLen())
68 if (pCode1
->GetCodeError() != pCode2
->GetCodeError())
71 sal_uInt16 n
= pCode1
->GetLen();
72 formula::FormulaToken
** ppToken1
= pCode1
->GetArray();
73 formula::FormulaToken
** ppToken2
= pCode2
->GetArray();
74 for (sal_uInt16 i
= 0; i
< n
; ++i
)
76 if (!ppToken1
[i
]->TextEqual(*(ppToken2
[i
])))
84 bool equalsWithoutFormatImpl( const T
& left
, const T
& right
)
86 CellType eType1
= adjustCellType(left
.getType());
87 CellType eType2
= adjustCellType(right
.getType());
96 return left
.getDouble() == right
.getDouble();
99 OUString aStr1
= getString(left
);
100 OUString aStr2
= getString(right
);
101 return aStr1
== aStr2
;
103 case CELLTYPE_FORMULA
:
104 return equalsFormulaCells(left
.getFormula(), right
.getFormula());
111 bool equalsWithoutFormatImpl( const ScCellValue
& left
, const ScCellValue
& right
)
113 CellType eType1
= adjustCellType(left
.getType());
114 CellType eType2
= adjustCellType(right
.getType());
115 if (eType1
!= eType2
)
123 return left
.getDouble() == right
.getDouble();
124 case CELLTYPE_STRING
:
126 OUString aStr1
= getString(left
);
127 OUString aStr2
= getString(right
);
128 return aStr1
== aStr2
;
130 case CELLTYPE_FORMULA
:
131 return equalsFormulaCells(left
.getFormula(), right
.getFormula());
138 void commitToColumn( const ScCellValue
& rCell
, ScColumn
& rColumn
, SCROW nRow
)
140 switch (rCell
.getType())
142 case CELLTYPE_STRING
:
143 rColumn
.SetRawString(nRow
, *rCell
.getSharedString());
146 rColumn
.SetEditText(nRow
, ScEditUtil::Clone(*rCell
.getEditText(), rColumn
.GetDoc()));
149 rColumn
.SetValue(nRow
, rCell
.getDouble());
151 case CELLTYPE_FORMULA
:
153 ScAddress
aDestPos(rColumn
.GetCol(), nRow
, rColumn
.GetTab());
154 rColumn
.SetFormulaCell(nRow
, new ScFormulaCell(*rCell
.getFormula(), rColumn
.GetDoc(), aDestPos
));
158 rColumn
.DeleteContent(nRow
);
162 bool hasStringImpl( CellType eType
, ScFormulaCell
* pFormula
)
166 case CELLTYPE_STRING
:
169 case CELLTYPE_FORMULA
:
170 return !pFormula
->IsValue();
176 bool hasNumericImpl( CellType eType
, ScFormulaCell
* pFormula
)
182 case CELLTYPE_FORMULA
:
183 return pFormula
->IsValue();
189 template <typename T
>
190 OUString
getStringImpl( const T
& rCell
, const ScDocument
* pDoc
)
192 switch (rCell
.getType())
195 return OUString::number(rCell
.getDouble());
196 case CELLTYPE_STRING
:
197 return rCell
.getSharedString()->getString();
199 if (rCell
.getEditText())
200 return ScEditUtil::GetString(*rCell
.getEditText(), pDoc
);
202 case CELLTYPE_FORMULA
:
203 return rCell
.getFormula()->GetString().getString();
210 template<typename CellT
>
211 OUString
getRawStringImpl( const CellT
& rCell
, const ScDocument
& rDoc
)
213 switch (rCell
.getType())
216 return OUString::number(rCell
.getDouble());
217 case CELLTYPE_STRING
:
218 return rCell
.getSharedString()->getString();
220 if (rCell
.getEditText())
221 return ScEditUtil::GetString(*rCell
.getEditText(), &rDoc
);
223 case CELLTYPE_FORMULA
:
224 return rCell
.getFormula()->GetRawString().getString();
233 ScCellValue::ScCellValue() {}
235 ScCellValue::ScCellValue( const ScRefCellValue
& rCell
)
237 switch (rCell
.getType())
239 case CELLTYPE_STRING
:
240 maData
= *rCell
.getSharedString();
243 maData
= rCell
.getEditText()->Clone().release();
245 case CELLTYPE_FORMULA
:
246 maData
= rCell
.getFormula()->Clone();
249 maData
= rCell
.getDouble();
255 ScCellValue::ScCellValue( double fValue
) : maData(fValue
) {}
257 ScCellValue::ScCellValue( const svl::SharedString
& rString
) : maData(rString
) {}
259 ScCellValue::ScCellValue( std::unique_ptr
<EditTextObject
> xEdit
) : maData(xEdit
.release()) {}
261 ScCellValue::ScCellValue( const ScCellValue
& r
)
265 case CELLTYPE_STRING
:
266 maData
= *r
.getSharedString();
269 maData
= r
.getEditText()->Clone().release();
271 case CELLTYPE_FORMULA
:
272 maData
= r
.getFormula()->Clone();
275 maData
= r
.getDouble();
281 void ScCellValue::reset_to_empty()
283 suppress_fun_call_w_exception(maData
= std::monostate()); // reset to empty;
286 ScCellValue::ScCellValue(ScCellValue
&& r
) noexcept
287 : maData(std::move(r
.maData
))
292 ScCellValue::~ScCellValue()
297 CellType
ScCellValue::getType() const
299 switch (maData
.index())
301 case 0: return CELLTYPE_NONE
;
302 case 1: return CELLTYPE_VALUE
;
303 case 2: return CELLTYPE_STRING
;
304 case 3: return CELLTYPE_EDIT
;
305 case 4: return CELLTYPE_FORMULA
;
308 return CELLTYPE_NONE
;
312 void ScCellValue::clear() noexcept
317 suppress_fun_call_w_exception(delete getEditText());
319 case CELLTYPE_FORMULA
:
320 suppress_fun_call_w_exception(delete getFormula());
326 // Reset to empty value.
330 void ScCellValue::set( double fValue
)
336 void ScCellValue::set( const svl::SharedString
& rStr
)
342 void ScCellValue::set( const EditTextObject
& rEditText
)
345 maData
= rEditText
.Clone().release();
348 void ScCellValue::set( std::unique_ptr
<EditTextObject
> xEditText
)
351 maData
= xEditText
.release();
354 void ScCellValue::set( ScFormulaCell
* pFormula
)
360 void ScCellValue::assign( const ScDocument
& rDoc
, const ScAddress
& rPos
)
364 ScRefCellValue
aRefVal(const_cast<ScDocument
&>(rDoc
), rPos
);
366 switch (aRefVal
.getType())
368 case CELLTYPE_STRING
:
369 maData
= *aRefVal
.getSharedString();
372 maData
= aRefVal
.getEditText() ? aRefVal
.getEditText()->Clone().release() : static_cast<EditTextObject
*>(nullptr);
375 maData
= aRefVal
.getDouble();
377 case CELLTYPE_FORMULA
:
378 maData
= aRefVal
.getFormula()->Clone();
380 default: ; // leave empty
384 void ScCellValue::assign(const ScCellValue
& rOther
, ScDocument
& rDestDoc
, ScCloneFlags nCloneFlags
)
388 switch (rOther
.getType())
390 case CELLTYPE_STRING
:
391 maData
= rOther
.maData
;
395 // Switch to the pool of the destination document.
396 ScFieldEditEngine
& rEngine
= rDestDoc
.GetEditEngine();
397 if (rOther
.getEditText()->HasOnlineSpellErrors())
399 EEControlBits nControl
= rEngine
.GetControlWord();
400 const EEControlBits nSpellControl
= EEControlBits::ONLINESPELLING
| EEControlBits::ALLOWBIGOBJS
;
401 bool bNewControl
= ((nControl
& nSpellControl
) != nSpellControl
);
403 rEngine
.SetControlWord(nControl
| nSpellControl
);
404 rEngine
.SetTextCurrentDefaults(*rOther
.getEditText());
405 maData
= rEngine
.CreateTextObject().release();
407 rEngine
.SetControlWord(nControl
);
411 rEngine
.SetTextCurrentDefaults(*rOther
.getEditText());
412 maData
= rEngine
.CreateTextObject().release();
417 maData
= rOther
.maData
;
419 case CELLTYPE_FORMULA
:
420 // Switch to the destination document.
421 maData
= new ScFormulaCell(*rOther
.getFormula(), rDestDoc
, rOther
.getFormula()->aPos
, nCloneFlags
);
423 default: ; // leave empty
427 void ScCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
431 case CELLTYPE_STRING
:
433 ScSetStringParam aParam
;
434 aParam
.setTextInput();
435 rDoc
.SetString(rPos
, getSharedString()->getString(), &aParam
);
439 rDoc
.SetEditText(rPos
, getEditText()->Clone());
442 rDoc
.SetValue(rPos
, getDouble());
444 case CELLTYPE_FORMULA
:
445 rDoc
.SetFormulaCell(rPos
, getFormula()->Clone());
448 rDoc
.SetEmptyCell(rPos
);
452 void ScCellValue::commit( ScColumn
& rColumn
, SCROW nRow
) const
454 commitToColumn(*this, rColumn
, nRow
);
457 void ScCellValue::release( ScDocument
& rDoc
, const ScAddress
& rPos
)
461 case CELLTYPE_STRING
:
463 // Currently, string cannot be placed without copying.
464 ScSetStringParam aParam
;
465 aParam
.setTextInput();
466 rDoc
.SetString(rPos
, getSharedString()->getString(), &aParam
);
470 // Cell takes the ownership of the text object.
471 rDoc
.SetEditText(rPos
, std::unique_ptr
<EditTextObject
>(getEditText()));
474 rDoc
.SetValue(rPos
, getDouble());
476 case CELLTYPE_FORMULA
:
477 // This formula cell instance is directly placed in the document without copying.
478 rDoc
.SetFormulaCell(rPos
, getFormula());
481 rDoc
.SetEmptyCell(rPos
);
484 reset_to_empty(); // reset to empty
487 void ScCellValue::release( ScColumn
& rColumn
, SCROW nRow
, sc::StartListeningType eListenType
)
491 case CELLTYPE_STRING
:
493 // Currently, string cannot be placed without copying.
494 rColumn
.SetRawString(nRow
, *getSharedString());
498 // Cell takes the ownership of the text object.
499 rColumn
.SetEditText(nRow
, std::unique_ptr
<EditTextObject
>(getEditText()));
502 rColumn
.SetValue(nRow
, getDouble());
504 case CELLTYPE_FORMULA
:
505 // This formula cell instance is directly placed in the document without copying.
506 rColumn
.SetFormulaCell(nRow
, getFormula(), eListenType
);
509 rColumn
.DeleteContent(nRow
);
512 reset_to_empty(); // reset to empty
515 OUString
ScCellValue::getString( const ScDocument
& rDoc
) const
517 return getStringImpl(*this, &rDoc
);
520 bool ScCellValue::isEmpty() const
522 return getType() == CELLTYPE_NONE
;
525 bool ScCellValue::equalsWithoutFormat( const ScCellValue
& r
) const
527 return equalsWithoutFormatImpl(*this, r
);
530 ScCellValue
& ScCellValue::operator= ( const ScCellValue
& r
)
537 ScCellValue
& ScCellValue::operator=(ScCellValue
&& rCell
) noexcept
540 maData
= std::move(rCell
.maData
);
541 rCell
.reset_to_empty(); // reset to empty;
545 ScCellValue
& ScCellValue::operator= ( const ScRefCellValue
& r
)
552 void ScCellValue::swap( ScCellValue
& r
)
554 std::swap(maData
, r
.maData
);
557 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
558 ScRefCellValue::ScRefCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
559 ScRefCellValue::ScRefCellValue( const svl::SharedString
* pString
) : meType(CELLTYPE_STRING
), mpString(pString
) {}
560 ScRefCellValue::ScRefCellValue( const EditTextObject
* pEditText
) : meType(CELLTYPE_EDIT
), mpEditText(pEditText
) {}
561 ScRefCellValue::ScRefCellValue( ScFormulaCell
* pFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(pFormula
) {}
563 ScRefCellValue::ScRefCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
)
568 ScRefCellValue::ScRefCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
, sc::ColumnBlockPosition
& rBlockPos
)
570 assign( rDoc
, rPos
, rBlockPos
);
573 void ScRefCellValue::clear()
575 // Reset to empty value.
576 meType
= CELLTYPE_NONE
;
580 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
)
582 *this = rDoc
.GetRefCellValue(rPos
);
585 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
, sc::ColumnBlockPosition
& rBlockPos
)
587 *this = rDoc
.GetRefCellValue(rPos
, rBlockPos
);
590 void ScRefCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
594 case CELLTYPE_STRING
:
596 ScSetStringParam aParam
;
597 aParam
.setTextInput();
598 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
602 rDoc
.SetEditText(rPos
, ScEditUtil::Clone(*mpEditText
, rDoc
));
605 rDoc
.SetValue(rPos
, mfValue
);
607 case CELLTYPE_FORMULA
:
608 rDoc
.SetFormulaCell(rPos
, new ScFormulaCell(*mpFormula
, rDoc
, rPos
));
611 rDoc
.SetEmptyCell(rPos
);
615 bool ScRefCellValue::hasString() const
617 return hasStringImpl(meType
, mpFormula
);
620 bool ScRefCellValue::hasNumeric() const
622 return hasNumericImpl(meType
, mpFormula
);
625 bool ScRefCellValue::hasError() const
627 return meType
== CELLTYPE_FORMULA
&& mpFormula
->GetErrCode() != FormulaError::NONE
;
630 double ScRefCellValue::getValue()
636 case CELLTYPE_FORMULA
:
637 return mpFormula
->GetValue();
644 double ScRefCellValue::getRawValue() const
650 case CELLTYPE_FORMULA
:
651 return mpFormula
->GetRawValue();
658 OUString
ScRefCellValue::getString( const ScDocument
* pDoc
) const
660 return getStringImpl(*this, pDoc
);
663 svl::SharedString
ScRefCellValue::getSharedString( const ScDocument
* pDoc
, svl::SharedStringPool
& rStrPool
) const
668 return rStrPool
.intern(OUString::number(getDouble()));
669 case CELLTYPE_STRING
:
670 return *getSharedString();
672 if (auto pEditText
= getEditText())
673 return rStrPool
.intern(ScEditUtil::GetString(*pEditText
, pDoc
));
675 case CELLTYPE_FORMULA
:
676 return getFormula()->GetString();
680 return svl::SharedString::getEmptyString();
683 OUString
ScRefCellValue::getRawString( const ScDocument
& rDoc
) const
685 return getRawStringImpl(*this, rDoc
);
688 bool ScRefCellValue::isEmpty() const
690 return meType
== CELLTYPE_NONE
;
693 bool ScRefCellValue::hasEmptyValue()
698 if (meType
== CELLTYPE_FORMULA
)
699 return mpFormula
->IsEmpty();
704 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue
& r
) const
706 return equalsWithoutFormatImpl(*this, r
);
709 bool ScRefCellValue::operator==( const ScRefCellValue
& r
) const
711 if (meType
!= r
.meType
)
719 return mfValue
== r
.mfValue
;
720 case CELLTYPE_STRING
:
721 return mpString
== r
.mpString
;
722 case CELLTYPE_FORMULA
:
723 return equalsFormulaCells(getFormula(), r
.getFormula());
729 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */