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 template<typename _T
>
107 void commitToColumn( const _T
& rCell
, ScColumn
& rColumn
, SCROW nRow
)
109 switch (rCell
.meType
)
111 case CELLTYPE_STRING
:
112 rColumn
.SetRawString(nRow
, *rCell
.mpString
);
115 rColumn
.SetEditText(nRow
, ScEditUtil::Clone(*rCell
.mpEditText
, rColumn
.GetDoc()));
118 rColumn
.SetValue(nRow
, rCell
.mfValue
);
120 case CELLTYPE_FORMULA
:
122 ScAddress
aDestPos(rColumn
.GetCol(), nRow
, rColumn
.GetTab());
123 rColumn
.SetFormulaCell(nRow
, new ScFormulaCell(*rCell
.mpFormula
, rColumn
.GetDoc(), aDestPos
));
127 rColumn
.Delete(nRow
);
131 bool hasStringImpl( CellType eType
, ScFormulaCell
* pFormula
)
135 case CELLTYPE_STRING
:
138 case CELLTYPE_FORMULA
:
139 return !pFormula
->IsValue();
145 bool hasNumericImpl( CellType eType
, ScFormulaCell
* pFormula
)
151 case CELLTYPE_FORMULA
:
152 return pFormula
->IsValue();
160 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
162 ScCellValue::ScCellValue( const ScRefCellValue
& rCell
) : meType(rCell
.meType
), mfValue(rCell
.mfValue
)
164 switch (rCell
.meType
)
166 case CELLTYPE_STRING
:
167 mpString
= new svl::SharedString(*rCell
.mpString
);
170 mpEditText
= rCell
.mpEditText
->Clone();
172 case CELLTYPE_FORMULA
:
173 mpFormula
= rCell
.mpFormula
->Clone();
180 ScCellValue::ScCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
181 ScCellValue::ScCellValue( const svl::SharedString
& rString
) : meType(CELLTYPE_STRING
), mpString(new svl::SharedString(rString
)) {}
182 ScCellValue::ScCellValue( const EditTextObject
& rEditText
) : meType(CELLTYPE_EDIT
), mpEditText(rEditText
.Clone()) {}
183 ScCellValue::ScCellValue( const ScFormulaCell
& rFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(rFormula
.Clone()) {}
185 ScCellValue::ScCellValue( const ScCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
)
189 case CELLTYPE_STRING
:
190 mpString
= new svl::SharedString(*r
.mpString
);
193 mpEditText
= r
.mpEditText
->Clone();
195 case CELLTYPE_FORMULA
:
196 mpFormula
= r
.mpFormula
->Clone();
203 ScCellValue::~ScCellValue()
208 void ScCellValue::clear()
212 case CELLTYPE_STRING
:
218 case CELLTYPE_FORMULA
:
225 // Reset to empty value.
226 meType
= CELLTYPE_NONE
;
230 void ScCellValue::set( double fValue
)
233 meType
= CELLTYPE_VALUE
;
237 void ScCellValue::set( const svl::SharedString
& rStr
)
240 meType
= CELLTYPE_STRING
;
241 mpString
= new svl::SharedString(rStr
);
244 void ScCellValue::set( const EditTextObject
& rEditText
)
247 meType
= CELLTYPE_EDIT
;
248 mpEditText
= rEditText
.Clone();
251 void ScCellValue::set( const ScFormulaCell
& rFormula
)
254 meType
= CELLTYPE_FORMULA
;
255 mpFormula
= rFormula
.Clone();
258 void ScCellValue::set( ScFormulaCell
* pFormula
)
261 meType
= CELLTYPE_FORMULA
;
262 mpFormula
= pFormula
;
265 void ScCellValue::assign( const ScDocument
& rDoc
, const ScAddress
& rPos
)
269 ScRefCellValue aRefVal
;
270 aRefVal
.assign(const_cast<ScDocument
&>(rDoc
), rPos
);
272 meType
= aRefVal
.meType
;
275 case CELLTYPE_STRING
:
276 mpString
= new svl::SharedString(*aRefVal
.mpString
);
279 if (aRefVal
.mpEditText
)
280 mpEditText
= aRefVal
.mpEditText
->Clone();
283 mfValue
= aRefVal
.mfValue
;
285 case CELLTYPE_FORMULA
:
286 mpFormula
= aRefVal
.mpFormula
->Clone();
289 meType
= CELLTYPE_NONE
; // reset to empty.
293 void ScCellValue::assign( const ScCellValue
& rOther
, ScDocument
& rDestDoc
, int nCloneFlags
)
297 meType
= rOther
.meType
;
300 case CELLTYPE_STRING
:
301 mpString
= new svl::SharedString(*rOther
.mpString
);
305 // Switch to the pool of the destination document.
306 ScFieldEditEngine
& rEngine
= rDestDoc
.GetEditEngine();
307 if (rOther
.mpEditText
->HasOnlineSpellErrors())
309 sal_uLong nControl
= rEngine
.GetControlWord();
310 const sal_uLong nSpellControl
= EE_CNTRL_ONLINESPELLING
| EE_CNTRL_ALLOWBIGOBJS
;
311 bool bNewControl
= ((nControl
& nSpellControl
) != nSpellControl
);
313 rEngine
.SetControlWord(nControl
| nSpellControl
);
314 rEngine
.SetText(*rOther
.mpEditText
);
315 mpEditText
= rEngine
.CreateTextObject();
317 rEngine
.SetControlWord(nControl
);
321 rEngine
.SetText(*rOther
.mpEditText
);
322 mpEditText
= rEngine
.CreateTextObject();
327 mfValue
= rOther
.mfValue
;
329 case CELLTYPE_FORMULA
:
330 // Switch to the destination document.
331 mpFormula
= new ScFormulaCell(*rOther
.mpFormula
, rDestDoc
, rOther
.mpFormula
->aPos
, nCloneFlags
);
334 meType
= CELLTYPE_NONE
; // reset to empty.
338 void ScCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
342 case CELLTYPE_STRING
:
344 ScSetStringParam aParam
;
345 aParam
.setTextInput();
346 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
350 rDoc
.SetEditText(rPos
, mpEditText
->Clone());
353 rDoc
.SetValue(rPos
, mfValue
);
355 case CELLTYPE_FORMULA
:
356 rDoc
.SetFormulaCell(rPos
, mpFormula
->Clone());
359 rDoc
.SetEmptyCell(rPos
);
363 void ScCellValue::commit( ScColumn
& rColumn
, SCROW nRow
) const
365 commitToColumn(*this, rColumn
, nRow
);
368 void ScCellValue::release( ScDocument
& rDoc
, const ScAddress
& rPos
)
372 case CELLTYPE_STRING
:
374 // Currently, string cannot be placed without copying.
375 ScSetStringParam aParam
;
376 aParam
.setTextInput();
377 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
382 // Cell takes the ownership of the text object.
383 rDoc
.SetEditText(rPos
, mpEditText
);
386 rDoc
.SetValue(rPos
, mfValue
);
388 case CELLTYPE_FORMULA
:
389 // This formula cell instance is directly placed in the document without copying.
390 rDoc
.SetFormulaCell(rPos
, mpFormula
);
393 rDoc
.SetEmptyCell(rPos
);
396 meType
= CELLTYPE_NONE
;
400 void ScCellValue::release( ScColumn
& rColumn
, SCROW nRow
)
404 case CELLTYPE_STRING
:
406 // Currently, string cannot be placed without copying.
407 rColumn
.SetRawString(nRow
, *mpString
);
412 // Cell takes the ownership of the text object.
413 rColumn
.SetEditText(nRow
, mpEditText
);
416 rColumn
.SetValue(nRow
, mfValue
);
418 case CELLTYPE_FORMULA
:
419 // This formula cell instance is directly placed in the document without copying.
420 rColumn
.SetFormulaCell(nRow
, mpFormula
);
423 rColumn
.Delete(nRow
);
426 meType
= CELLTYPE_NONE
;
430 bool ScCellValue::hasString() const
432 return hasStringImpl(meType
, mpFormula
);
435 bool ScCellValue::hasNumeric() const
437 return hasNumericImpl(meType
, mpFormula
);
440 bool ScCellValue::isEmpty() const
442 return meType
== CELLTYPE_NONE
;
445 bool ScCellValue::equalsWithoutFormat( const ScCellValue
& r
) const
447 return equalsWithoutFormatImpl(*this, r
);
450 ScCellValue
& ScCellValue::operator= ( const ScCellValue
& r
)
457 ScCellValue
& ScCellValue::operator= ( const ScRefCellValue
& r
)
464 void ScCellValue::swap( ScCellValue
& r
)
466 std::swap(meType
, r
.meType
);
468 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
469 // the platform. Swap by double values.
470 std::swap(mfValue
, r
.mfValue
);
473 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
474 ScRefCellValue::ScRefCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
475 ScRefCellValue::ScRefCellValue( const svl::SharedString
* pString
) : meType(CELLTYPE_STRING
), mpString(pString
) {}
476 ScRefCellValue::ScRefCellValue( const EditTextObject
* pEditText
) : meType(CELLTYPE_EDIT
), mpEditText(pEditText
) {}
477 ScRefCellValue::ScRefCellValue( ScFormulaCell
* pFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(pFormula
) {}
479 // It should be enough to copy the double value, which is at least as large
480 // as the pointer values.
481 ScRefCellValue::ScRefCellValue( const ScRefCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
) {}
483 ScRefCellValue::~ScRefCellValue()
488 void ScRefCellValue::clear()
490 // Reset to empty value.
491 meType
= CELLTYPE_NONE
;
495 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
)
497 *this = rDoc
.GetRefCellValue(rPos
);
500 void ScRefCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
504 case CELLTYPE_STRING
:
506 ScSetStringParam aParam
;
507 aParam
.setTextInput();
508 rDoc
.SetString(rPos
, mpString
->getString(), &aParam
);
512 rDoc
.SetEditText(rPos
, ScEditUtil::Clone(*mpEditText
, rDoc
));
515 rDoc
.SetValue(rPos
, mfValue
);
517 case CELLTYPE_FORMULA
:
518 rDoc
.SetFormulaCell(rPos
, new ScFormulaCell(*mpFormula
, rDoc
, rPos
));
521 rDoc
.SetEmptyCell(rPos
);
525 void ScRefCellValue::commit( ScColumn
& rColumn
, SCROW nRow
) const
527 commitToColumn(*this, rColumn
, nRow
);
530 bool ScRefCellValue::hasString() const
532 return hasStringImpl(meType
, mpFormula
);
535 bool ScRefCellValue::hasNumeric() const
537 return hasNumericImpl(meType
, mpFormula
);
540 double ScRefCellValue::getValue()
546 case CELLTYPE_FORMULA
:
547 return mpFormula
->GetValue();
554 OUString
ScRefCellValue::getString( const ScDocument
* pDoc
)
559 return OUString::number(mfValue
);
560 case CELLTYPE_STRING
:
561 return mpString
->getString();
564 return ScEditUtil::GetString(*mpEditText
, pDoc
);
566 case CELLTYPE_FORMULA
:
567 return mpFormula
->GetString().getString();
571 return EMPTY_OUSTRING
;
574 bool ScRefCellValue::isEmpty() const
576 return meType
== CELLTYPE_NONE
;
579 bool ScRefCellValue::hasEmptyValue()
584 if (meType
== CELLTYPE_FORMULA
)
585 return mpFormula
->IsEmpty();
590 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue
& r
) const
592 return equalsWithoutFormatImpl(*this, r
);
595 ScRefCellValue
& ScRefCellValue::operator= ( const ScRefCellValue
& r
)
597 ScRefCellValue
aTmp(r
);
602 void ScRefCellValue::swap( ScRefCellValue
& r
)
604 std::swap(meType
, r
.meType
);
606 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
607 // the platform. Swap by double values.
608 std::swap(mfValue
, r
.mfValue
);
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */