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 <svl/sharedstring.hxx>
24 CellType
adjustCellType( CellType eOrig
)
29 return CELLTYPE_STRING
;
37 OUString
getString( const _T
& rVal
)
39 if (rVal
.meType
== CELLTYPE_STRING
)
40 return rVal
.mpString
->getString();
42 if (rVal
.meType
== CELLTYPE_EDIT
)
45 sal_Int32 n
= rVal
.mpEditText
->GetParagraphCount();
46 for (sal_Int32 i
= 0; i
< n
; ++i
)
50 aRet
.append(rVal
.mpEditText
->GetText(i
));
52 return aRet
.makeStringAndClear();
55 return EMPTY_OUSTRING
;
58 bool equalsFormulaCells( const ScFormulaCell
* p1
, const ScFormulaCell
* p2
)
60 const ScTokenArray
* pCode1
= p1
->GetCode();
61 const ScTokenArray
* pCode2
= p2
->GetCode();
63 if (pCode1
->GetLen() != pCode2
->GetLen())
66 sal_uInt16 n
= pCode1
->GetLen();
67 formula::FormulaToken
** ppToken1
= pCode1
->GetArray();
68 formula::FormulaToken
** ppToken2
= pCode2
->GetArray();
69 for (sal_uInt16 i
= 0; i
< n
; ++i
)
71 if (!ppToken1
[i
]->TextEqual(*(ppToken2
[i
])))
79 bool equalsWithoutFormatImpl( const _T
& left
, const _T
& right
)
81 CellType eType1
= adjustCellType(left
.meType
);
82 CellType eType2
= adjustCellType(right
.meType
);
91 return left
.mfValue
== right
.mfValue
;
94 OUString aStr1
= getString(left
);
95 OUString aStr2
= getString(right
);
96 return aStr1
== aStr2
;
98 case CELLTYPE_FORMULA
:
99 return equalsFormulaCells(left
.mpFormula
, right
.mpFormula
);
106 static void commitToColumn( const ScCellValue
& rCell
, ScColumn
& rColumn
, SCROW nRow
)
108 switch (rCell
.meType
)
110 case CELLTYPE_STRING
:
111 rColumn
.SetRawString(nRow
, *rCell
.mpString
);
114 rColumn
.SetEditText(nRow
, ScEditUtil::Clone(*rCell
.mpEditText
, rColumn
.GetDoc()));
117 rColumn
.SetValue(nRow
, rCell
.mfValue
);
119 case CELLTYPE_FORMULA
:
121 ScAddress
aDestPos(rColumn
.GetCol(), nRow
, rColumn
.GetTab());
122 rColumn
.SetFormulaCell(nRow
, new ScFormulaCell(*rCell
.mpFormula
, rColumn
.GetDoc(), aDestPos
));
126 rColumn
.DeleteContent(nRow
);
130 bool hasStringImpl( CellType eType
, ScFormulaCell
* pFormula
)
134 case CELLTYPE_STRING
:
137 case CELLTYPE_FORMULA
:
138 return !pFormula
->IsValue();
144 bool hasNumericImpl( CellType eType
, ScFormulaCell
* pFormula
)
150 case CELLTYPE_FORMULA
:
151 return pFormula
->IsValue();
157 template<typename _CellT
>
158 OUString
getStringImpl( const _CellT
& rCell
, const ScDocument
* pDoc
)
160 switch (rCell
.meType
)
163 return OUString::number(rCell
.mfValue
);
164 case CELLTYPE_STRING
:
165 return rCell
.mpString
->getString();
167 if (rCell
.mpEditText
)
168 return ScEditUtil::GetString(*rCell
.mpEditText
, pDoc
);
170 case CELLTYPE_FORMULA
:
171 return rCell
.mpFormula
->GetString().getString();
175 return EMPTY_OUSTRING
;
180 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
182 ScCellValue::ScCellValue( const ScRefCellValue
& rCell
) : meType(rCell
.meType
), mfValue(rCell
.mfValue
)
184 switch (rCell
.meType
)
186 case CELLTYPE_STRING
:
187 mpString
= new svl::SharedString(*rCell
.mpString
);
190 mpEditText
= rCell
.mpEditText
->Clone();
192 case CELLTYPE_FORMULA
:
193 mpFormula
= rCell
.mpFormula
->Clone();
200 ScCellValue::ScCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
202 ScCellValue::ScCellValue( const svl::SharedString
& rString
) : meType(CELLTYPE_STRING
), mpString(new svl::SharedString(rString
)) {}
204 ScCellValue::ScCellValue( const ScCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
)
208 case CELLTYPE_STRING
:
209 mpString
= new svl::SharedString(*r
.mpString
);
212 mpEditText
= r
.mpEditText
->Clone();
214 case CELLTYPE_FORMULA
:
215 mpFormula
= r
.mpFormula
->Clone();
222 ScCellValue::~ScCellValue()
227 void ScCellValue::clear()
231 case CELLTYPE_STRING
:
237 case CELLTYPE_FORMULA
:
244 // Reset to empty value.
245 meType
= CELLTYPE_NONE
;
249 void ScCellValue::set( const ScRefCellValue
& rCell
)
253 meType
= rCell
.meType
;
257 mfValue
= rCell
.mfValue
;
259 case CELLTYPE_STRING
:
260 mpString
= new svl::SharedString(*rCell
.mpString
);
263 mpEditText
= rCell
.mpEditText
->Clone();
265 case CELLTYPE_FORMULA
:
266 mpFormula
= rCell
.mpFormula
->Clone();
273 void ScCellValue::set( double fValue
)
276 meType
= CELLTYPE_VALUE
;
280 void ScCellValue::set( const svl::SharedString
& rStr
)
283 meType
= CELLTYPE_STRING
;
284 mpString
= new svl::SharedString(rStr
);
287 void ScCellValue::set( const EditTextObject
& rEditText
)
290 meType
= CELLTYPE_EDIT
;
291 mpEditText
= rEditText
.Clone();
294 void ScCellValue::set( EditTextObject
* pEditText
)
297 meType
= CELLTYPE_EDIT
;
298 mpEditText
= pEditText
;
301 void ScCellValue::set( ScFormulaCell
* pFormula
)
304 meType
= CELLTYPE_FORMULA
;
305 mpFormula
= pFormula
;
308 void ScCellValue::assign( const ScDocument
& rDoc
, const ScAddress
& rPos
)
312 ScRefCellValue aRefVal
;
313 aRefVal
.assign(const_cast<ScDocument
&>(rDoc
), rPos
);
315 meType
= aRefVal
.meType
;
318 case CELLTYPE_STRING
:
319 mpString
= new svl::SharedString(*aRefVal
.mpString
);
322 if (aRefVal
.mpEditText
)
323 mpEditText
= aRefVal
.mpEditText
->Clone();
326 mfValue
= aRefVal
.mfValue
;
328 case CELLTYPE_FORMULA
:
329 mpFormula
= aRefVal
.mpFormula
->Clone();
332 meType
= CELLTYPE_NONE
; // reset to empty.
336 void ScCellValue::assign( const ScCellValue
& rOther
, ScDocument
& rDestDoc
, int nCloneFlags
)
340 meType
= rOther
.meType
;
343 case CELLTYPE_STRING
:
344 mpString
= new svl::SharedString(*rOther
.mpString
);
348 // Switch to the pool of the destination document.
349 ScFieldEditEngine
& rEngine
= rDestDoc
.GetEditEngine();
350 if (rOther
.mpEditText
->HasOnlineSpellErrors())
352 EEControlBits nControl
= rEngine
.GetControlWord();
353 const EEControlBits nSpellControl
= EEControlBits::ONLINESPELLING
| EEControlBits::ALLOWBIGOBJS
;
354 bool bNewControl
= ((nControl
& nSpellControl
) != nSpellControl
);
356 rEngine
.SetControlWord(nControl
| nSpellControl
);
357 rEngine
.SetText(*rOther
.mpEditText
);
358 mpEditText
= rEngine
.CreateTextObject();
360 rEngine
.SetControlWord(nControl
);
364 rEngine
.SetText(*rOther
.mpEditText
);
365 mpEditText
= rEngine
.CreateTextObject();
370 mfValue
= rOther
.mfValue
;
372 case CELLTYPE_FORMULA
:
373 // Switch to the destination document.
374 mpFormula
= new ScFormulaCell(*rOther
.mpFormula
, rDestDoc
, rOther
.mpFormula
->aPos
, nCloneFlags
);
377 meType
= CELLTYPE_NONE
; // reset to empty.
381 void ScCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
385 case CELLTYPE_STRING
:
387 ScSetStringParam aParam
;
388 aParam
.setTextInput();
389 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
393 rDoc
.SetEditText(rPos
, mpEditText
->Clone());
396 rDoc
.SetValue(rPos
, mfValue
);
398 case CELLTYPE_FORMULA
:
399 rDoc
.SetFormulaCell(rPos
, mpFormula
->Clone());
402 rDoc
.SetEmptyCell(rPos
);
406 void ScCellValue::commit( ScColumn
& rColumn
, SCROW nRow
) const
408 commitToColumn(*this, rColumn
, nRow
);
411 void ScCellValue::release( ScDocument
& rDoc
, const ScAddress
& rPos
)
415 case CELLTYPE_STRING
:
417 // Currently, string cannot be placed without copying.
418 ScSetStringParam aParam
;
419 aParam
.setTextInput();
420 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
425 // Cell takes the ownership of the text object.
426 rDoc
.SetEditText(rPos
, mpEditText
);
429 rDoc
.SetValue(rPos
, mfValue
);
431 case CELLTYPE_FORMULA
:
432 // This formula cell instance is directly placed in the document without copying.
433 rDoc
.SetFormulaCell(rPos
, mpFormula
);
436 rDoc
.SetEmptyCell(rPos
);
439 meType
= CELLTYPE_NONE
;
443 void ScCellValue::release( ScColumn
& rColumn
, SCROW nRow
, sc::StartListeningType eListenType
)
447 case CELLTYPE_STRING
:
449 // Currently, string cannot be placed without copying.
450 rColumn
.SetRawString(nRow
, *mpString
);
455 // Cell takes the ownership of the text object.
456 rColumn
.SetEditText(nRow
, mpEditText
);
459 rColumn
.SetValue(nRow
, mfValue
);
461 case CELLTYPE_FORMULA
:
462 // This formula cell instance is directly placed in the document without copying.
463 rColumn
.SetFormulaCell(nRow
, mpFormula
, eListenType
);
466 rColumn
.DeleteContent(nRow
);
469 meType
= CELLTYPE_NONE
;
473 OUString
ScCellValue::getString( const ScDocument
* pDoc
)
475 return getStringImpl(*this, pDoc
);
478 bool ScCellValue::isEmpty() const
480 return meType
== CELLTYPE_NONE
;
483 bool ScCellValue::equalsWithoutFormat( const ScCellValue
& r
) const
485 return equalsWithoutFormatImpl(*this, r
);
488 ScCellValue
& ScCellValue::operator= ( const ScCellValue
& r
)
495 ScCellValue
& ScCellValue::operator= ( const ScRefCellValue
& r
)
502 void ScCellValue::swap( ScCellValue
& r
)
504 std::swap(meType
, r
.meType
);
506 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
507 // the platform. Swap by double values.
508 std::swap(mfValue
, r
.mfValue
);
511 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
512 ScRefCellValue::ScRefCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
513 ScRefCellValue::ScRefCellValue( const svl::SharedString
* pString
) : meType(CELLTYPE_STRING
), mpString(pString
) {}
514 ScRefCellValue::ScRefCellValue( const EditTextObject
* pEditText
) : meType(CELLTYPE_EDIT
), mpEditText(pEditText
) {}
515 ScRefCellValue::ScRefCellValue( ScFormulaCell
* pFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(pFormula
) {}
517 // It should be enough to copy the double value, which is at least as large
518 // as the pointer values.
519 ScRefCellValue::ScRefCellValue( const ScRefCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
) {}
521 ScRefCellValue::~ScRefCellValue()
526 void ScRefCellValue::clear()
528 // Reset to empty value.
529 meType
= CELLTYPE_NONE
;
533 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
)
535 *this = rDoc
.GetRefCellValue(rPos
);
538 void ScRefCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
542 case CELLTYPE_STRING
:
544 ScSetStringParam aParam
;
545 aParam
.setTextInput();
546 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
550 rDoc
.SetEditText(rPos
, ScEditUtil::Clone(*mpEditText
, rDoc
));
553 rDoc
.SetValue(rPos
, mfValue
);
555 case CELLTYPE_FORMULA
:
556 rDoc
.SetFormulaCell(rPos
, new ScFormulaCell(*mpFormula
, rDoc
, rPos
));
559 rDoc
.SetEmptyCell(rPos
);
563 bool ScRefCellValue::hasString() const
565 return hasStringImpl(meType
, mpFormula
);
568 bool ScRefCellValue::hasNumeric() const
570 return hasNumericImpl(meType
, mpFormula
);
573 double ScRefCellValue::getValue()
579 case CELLTYPE_FORMULA
:
580 return mpFormula
->GetValue();
587 OUString
ScRefCellValue::getString( const ScDocument
* pDoc
)
589 return getStringImpl(*this, pDoc
);
592 bool ScRefCellValue::isEmpty() const
594 return meType
== CELLTYPE_NONE
;
597 bool ScRefCellValue::hasEmptyValue()
602 if (meType
== CELLTYPE_FORMULA
)
603 return mpFormula
->IsEmpty();
608 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue
& r
) const
610 return equalsWithoutFormatImpl(*this, r
);
613 ScRefCellValue
& ScRefCellValue::operator= ( const ScRefCellValue
& r
)
615 ScRefCellValue
aTmp(r
);
620 void ScRefCellValue::swap( ScRefCellValue
& r
)
622 std::swap(meType
, r
.meType
);
624 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
625 // the platform. Swap by double values.
626 std::swap(mfValue
, r
.mfValue
);
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */