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>
25 CellType
adjustCellType( CellType eOrig
)
30 return CELLTYPE_STRING
;
38 OUString
getString( const T
& rVal
)
40 if (rVal
.getType() == CELLTYPE_STRING
)
41 return rVal
.getSharedString()->getString();
43 if (rVal
.getType() == CELLTYPE_EDIT
)
46 sal_Int32 n
= rVal
.getEditText()->GetParagraphCount();
47 for (sal_Int32 i
= 0; i
< n
; ++i
)
51 aRet
.append(rVal
.getEditText()->GetText(i
));
53 return aRet
.makeStringAndClear();
59 bool equalsFormulaCells( const ScFormulaCell
* p1
, const ScFormulaCell
* p2
)
61 const ScTokenArray
* pCode1
= p1
->GetCode();
62 const ScTokenArray
* pCode2
= p2
->GetCode();
64 if (pCode1
->GetLen() != pCode2
->GetLen())
67 if (pCode1
->GetCodeError() != pCode2
->GetCodeError())
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
)
75 if (!ppToken1
[i
]->TextEqual(*(ppToken2
[i
])))
83 bool equalsWithoutFormatImpl( const T
& left
, const T
& right
)
85 CellType eType1
= adjustCellType(left
.getType());
86 CellType eType2
= adjustCellType(right
.getType());
95 return left
.getDouble() == right
.getDouble();
98 OUString aStr1
= getString(left
);
99 OUString aStr2
= getString(right
);
100 return aStr1
== aStr2
;
102 case CELLTYPE_FORMULA
:
103 return equalsFormulaCells(left
.getFormula(), right
.getFormula());
110 bool equalsWithoutFormatImpl( const ScCellValue
& left
, const ScCellValue
& right
)
112 CellType eType1
= adjustCellType(left
.getType());
113 CellType eType2
= adjustCellType(right
.getType());
114 if (eType1
!= eType2
)
122 return left
.getDouble() == right
.getDouble();
123 case CELLTYPE_STRING
:
125 OUString aStr1
= getString(left
);
126 OUString aStr2
= getString(right
);
127 return aStr1
== aStr2
;
129 case CELLTYPE_FORMULA
:
130 return equalsFormulaCells(left
.getFormula(), right
.getFormula());
137 void commitToColumn( const ScCellValue
& rCell
, ScColumn
& rColumn
, SCROW nRow
)
139 switch (rCell
.getType())
141 case CELLTYPE_STRING
:
142 rColumn
.SetRawString(nRow
, *rCell
.getSharedString());
145 rColumn
.SetEditText(nRow
, ScEditUtil::Clone(*rCell
.getEditText(), rColumn
.GetDoc()));
148 rColumn
.SetValue(nRow
, rCell
.getDouble());
150 case CELLTYPE_FORMULA
:
152 ScAddress
aDestPos(rColumn
.GetCol(), nRow
, rColumn
.GetTab());
153 rColumn
.SetFormulaCell(nRow
, new ScFormulaCell(*rCell
.getFormula(), rColumn
.GetDoc(), aDestPos
));
157 rColumn
.DeleteContent(nRow
);
161 bool hasStringImpl( CellType eType
, ScFormulaCell
* pFormula
)
165 case CELLTYPE_STRING
:
168 case CELLTYPE_FORMULA
:
169 return !pFormula
->IsValue();
175 bool hasNumericImpl( CellType eType
, ScFormulaCell
* pFormula
)
181 case CELLTYPE_FORMULA
:
182 return pFormula
->IsValue();
188 template <typename T
>
189 OUString
getStringImpl( const T
& rCell
, const ScDocument
* pDoc
)
191 switch (rCell
.getType())
194 return OUString::number(rCell
.getDouble());
195 case CELLTYPE_STRING
:
196 return rCell
.getSharedString()->getString();
198 if (rCell
.getEditText())
199 return ScEditUtil::GetString(*rCell
.getEditText(), pDoc
);
201 case CELLTYPE_FORMULA
:
202 return rCell
.getFormula()->GetString().getString();
209 template<typename CellT
>
210 OUString
getRawStringImpl( const CellT
& rCell
, const ScDocument
& rDoc
)
212 switch (rCell
.getType())
215 return OUString::number(rCell
.getDouble());
216 case CELLTYPE_STRING
:
217 return rCell
.getSharedString()->getString();
219 if (rCell
.getEditText())
220 return ScEditUtil::GetString(*rCell
.getEditText(), &rDoc
);
222 case CELLTYPE_FORMULA
:
223 return rCell
.getFormula()->GetRawString().getString();
232 ScCellValue::ScCellValue() {}
234 ScCellValue::ScCellValue( const ScRefCellValue
& rCell
)
236 switch (rCell
.getType())
238 case CELLTYPE_STRING
:
239 maData
= *rCell
.getSharedString();
242 maData
= rCell
.getEditText()->Clone().release();
244 case CELLTYPE_FORMULA
:
245 maData
= rCell
.getFormula()->Clone();
248 maData
= rCell
.getDouble();
254 ScCellValue::ScCellValue( double fValue
) : maData(fValue
) {}
256 ScCellValue::ScCellValue( const svl::SharedString
& rString
) : maData(rString
) {}
258 ScCellValue::ScCellValue( std::unique_ptr
<EditTextObject
> xEdit
) : maData(xEdit
.release()) {}
260 ScCellValue::ScCellValue( const ScCellValue
& r
)
264 case CELLTYPE_STRING
:
265 maData
= *r
.getSharedString();
268 maData
= r
.getEditText()->Clone().release();
270 case CELLTYPE_FORMULA
:
271 maData
= r
.getFormula()->Clone();
274 maData
= r
.getDouble();
280 void ScCellValue::reset_to_empty()
282 suppress_fun_call_w_exception(maData
= std::monostate()); // reset to empty;
285 ScCellValue::ScCellValue(ScCellValue
&& r
) noexcept
286 : maData(std::move(r
.maData
))
291 ScCellValue::~ScCellValue()
296 CellType
ScCellValue::getType() const
298 switch (maData
.index())
300 case 0: return CELLTYPE_NONE
;
301 case 1: return CELLTYPE_VALUE
;
302 case 2: return CELLTYPE_STRING
;
303 case 3: return CELLTYPE_EDIT
;
304 case 4: return CELLTYPE_FORMULA
;
307 return CELLTYPE_NONE
;
311 void ScCellValue::clear() noexcept
316 suppress_fun_call_w_exception(delete getEditText());
318 case CELLTYPE_FORMULA
:
319 suppress_fun_call_w_exception(delete getFormula());
325 // Reset to empty value.
329 void ScCellValue::set( double fValue
)
335 void ScCellValue::set( const svl::SharedString
& rStr
)
341 void ScCellValue::set( const EditTextObject
& rEditText
)
344 maData
= rEditText
.Clone().release();
347 void ScCellValue::set( std::unique_ptr
<EditTextObject
> xEditText
)
350 maData
= xEditText
.release();
353 void ScCellValue::set( ScFormulaCell
* pFormula
)
359 void ScCellValue::assign( const ScDocument
& rDoc
, const ScAddress
& rPos
)
363 ScRefCellValue
aRefVal(const_cast<ScDocument
&>(rDoc
), rPos
);
365 switch (aRefVal
.getType())
367 case CELLTYPE_STRING
:
368 maData
= *aRefVal
.getSharedString();
371 maData
= aRefVal
.getEditText() ? aRefVal
.getEditText()->Clone().release() : static_cast<EditTextObject
*>(nullptr);
374 maData
= aRefVal
.getDouble();
376 case CELLTYPE_FORMULA
:
377 maData
= aRefVal
.getFormula()->Clone();
379 default: ; // leave empty
383 void ScCellValue::assign(const ScCellValue
& rOther
, ScDocument
& rDestDoc
, ScCloneFlags nCloneFlags
)
387 switch (rOther
.getType())
389 case CELLTYPE_STRING
:
390 maData
= rOther
.maData
;
394 // Switch to the pool of the destination document.
395 ScFieldEditEngine
& rEngine
= rDestDoc
.GetEditEngine();
396 if (rOther
.getEditText()->HasOnlineSpellErrors())
398 EEControlBits nControl
= rEngine
.GetControlWord();
399 const EEControlBits nSpellControl
= EEControlBits::ONLINESPELLING
| EEControlBits::ALLOWBIGOBJS
;
400 bool bNewControl
= ((nControl
& nSpellControl
) != nSpellControl
);
402 rEngine
.SetControlWord(nControl
| nSpellControl
);
403 rEngine
.SetTextCurrentDefaults(*rOther
.getEditText());
404 maData
= rEngine
.CreateTextObject().release();
406 rEngine
.SetControlWord(nControl
);
410 rEngine
.SetTextCurrentDefaults(*rOther
.getEditText());
411 maData
= rEngine
.CreateTextObject().release();
416 maData
= rOther
.maData
;
418 case CELLTYPE_FORMULA
:
419 // Switch to the destination document.
420 maData
= new ScFormulaCell(*rOther
.getFormula(), rDestDoc
, rOther
.getFormula()->aPos
, nCloneFlags
);
422 default: ; // leave empty
426 void ScCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
430 case CELLTYPE_STRING
:
432 ScSetStringParam aParam
;
433 aParam
.setTextInput();
434 rDoc
.SetString(rPos
, getSharedString()->getString(), &aParam
);
438 rDoc
.SetEditText(rPos
, getEditText()->Clone());
441 rDoc
.SetValue(rPos
, getDouble());
443 case CELLTYPE_FORMULA
:
444 rDoc
.SetFormulaCell(rPos
, getFormula()->Clone());
447 rDoc
.SetEmptyCell(rPos
);
451 void ScCellValue::commit( ScColumn
& rColumn
, SCROW nRow
) const
453 commitToColumn(*this, rColumn
, nRow
);
456 void ScCellValue::release( ScDocument
& rDoc
, const ScAddress
& rPos
)
460 case CELLTYPE_STRING
:
462 // Currently, string cannot be placed without copying.
463 ScSetStringParam aParam
;
464 aParam
.setTextInput();
465 rDoc
.SetString(rPos
, getSharedString()->getString(), &aParam
);
469 // Cell takes the ownership of the text object.
470 rDoc
.SetEditText(rPos
, std::unique_ptr
<EditTextObject
>(getEditText()));
473 rDoc
.SetValue(rPos
, getDouble());
475 case CELLTYPE_FORMULA
:
476 // This formula cell instance is directly placed in the document without copying.
477 rDoc
.SetFormulaCell(rPos
, getFormula());
480 rDoc
.SetEmptyCell(rPos
);
483 reset_to_empty(); // reset to empty
486 void ScCellValue::release( ScColumn
& rColumn
, SCROW nRow
, sc::StartListeningType eListenType
)
490 case CELLTYPE_STRING
:
492 // Currently, string cannot be placed without copying.
493 rColumn
.SetRawString(nRow
, *getSharedString());
497 // Cell takes the ownership of the text object.
498 rColumn
.SetEditText(nRow
, std::unique_ptr
<EditTextObject
>(getEditText()));
501 rColumn
.SetValue(nRow
, getDouble());
503 case CELLTYPE_FORMULA
:
504 // This formula cell instance is directly placed in the document without copying.
505 rColumn
.SetFormulaCell(nRow
, getFormula(), eListenType
);
508 rColumn
.DeleteContent(nRow
);
511 reset_to_empty(); // reset to empty
514 OUString
ScCellValue::getString( const ScDocument
& rDoc
) const
516 return getStringImpl(*this, &rDoc
);
519 bool ScCellValue::isEmpty() const
521 return getType() == CELLTYPE_NONE
;
524 bool ScCellValue::equalsWithoutFormat( const ScCellValue
& r
) const
526 return equalsWithoutFormatImpl(*this, r
);
529 ScCellValue
& ScCellValue::operator= ( const ScCellValue
& r
)
536 ScCellValue
& ScCellValue::operator=(ScCellValue
&& rCell
) noexcept
539 maData
= std::move(rCell
.maData
);
540 rCell
.reset_to_empty(); // reset to empty;
544 ScCellValue
& ScCellValue::operator= ( const ScRefCellValue
& r
)
551 void ScCellValue::swap( ScCellValue
& r
)
553 std::swap(maData
, r
.maData
);
556 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
557 ScRefCellValue::ScRefCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
558 ScRefCellValue::ScRefCellValue( const svl::SharedString
* pString
) : meType(CELLTYPE_STRING
), mpString(pString
) {}
559 ScRefCellValue::ScRefCellValue( const EditTextObject
* pEditText
) : meType(CELLTYPE_EDIT
), mpEditText(pEditText
) {}
560 ScRefCellValue::ScRefCellValue( ScFormulaCell
* pFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(pFormula
) {}
562 ScRefCellValue::ScRefCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
)
567 ScRefCellValue::ScRefCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
, sc::ColumnBlockPosition
& rBlockPos
)
569 assign( rDoc
, rPos
, rBlockPos
);
572 void ScRefCellValue::clear()
574 // Reset to empty value.
575 meType
= CELLTYPE_NONE
;
579 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
)
581 *this = rDoc
.GetRefCellValue(rPos
);
584 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
, sc::ColumnBlockPosition
& rBlockPos
)
586 *this = rDoc
.GetRefCellValue(rPos
, rBlockPos
);
589 void ScRefCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
593 case CELLTYPE_STRING
:
595 ScSetStringParam aParam
;
596 aParam
.setTextInput();
597 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
601 rDoc
.SetEditText(rPos
, ScEditUtil::Clone(*mpEditText
, rDoc
));
604 rDoc
.SetValue(rPos
, mfValue
);
606 case CELLTYPE_FORMULA
:
607 rDoc
.SetFormulaCell(rPos
, new ScFormulaCell(*mpFormula
, rDoc
, rPos
));
610 rDoc
.SetEmptyCell(rPos
);
614 bool ScRefCellValue::hasString() const
616 return hasStringImpl(meType
, mpFormula
);
619 bool ScRefCellValue::hasNumeric() const
621 return hasNumericImpl(meType
, mpFormula
);
624 bool ScRefCellValue::hasError() const
626 return meType
== CELLTYPE_FORMULA
&& mpFormula
->GetErrCode() != FormulaError::NONE
;
629 double ScRefCellValue::getValue()
635 case CELLTYPE_FORMULA
:
636 return mpFormula
->GetValue();
643 double ScRefCellValue::getRawValue() const
649 case CELLTYPE_FORMULA
:
650 return mpFormula
->GetRawValue();
657 OUString
ScRefCellValue::getString( const ScDocument
* pDoc
) const
659 return getStringImpl(*this, pDoc
);
662 OUString
ScRefCellValue::getRawString( const ScDocument
& rDoc
) const
664 return getRawStringImpl(*this, rDoc
);
667 bool ScRefCellValue::isEmpty() const
669 return meType
== CELLTYPE_NONE
;
672 bool ScRefCellValue::hasEmptyValue()
677 if (meType
== CELLTYPE_FORMULA
)
678 return mpFormula
->IsEmpty();
683 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue
& r
) const
685 return equalsWithoutFormatImpl(*this, r
);
688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */