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"
20 #include "formula/token.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
;
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 bool hasStringImpl( CellType eType
, ScFormulaCell
* pFormula
)
110 case CELLTYPE_STRING
:
113 case CELLTYPE_FORMULA
:
114 return !pFormula
->IsValue();
120 bool hasNumericImpl( CellType eType
, ScFormulaCell
* pFormula
)
126 case CELLTYPE_FORMULA
:
127 return pFormula
->IsValue();
135 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
136 ScCellValue::ScCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
137 ScCellValue::ScCellValue( const OUString
& rString
) : meType(CELLTYPE_STRING
), mpString(new OUString(rString
)) {}
138 ScCellValue::ScCellValue( const EditTextObject
& rEditText
) : meType(CELLTYPE_EDIT
), mpEditText(rEditText
.Clone()) {}
139 ScCellValue::ScCellValue( const ScFormulaCell
& rFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(rFormula
.Clone()) {}
141 ScCellValue::ScCellValue( const ScCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
)
145 case CELLTYPE_STRING
:
146 mpString
= new OUString(*r
.mpString
);
149 mpEditText
= r
.mpEditText
->Clone();
151 case CELLTYPE_FORMULA
:
152 mpFormula
= r
.mpFormula
->Clone();
159 ScCellValue::~ScCellValue()
164 void ScCellValue::clear()
168 case CELLTYPE_STRING
:
174 case CELLTYPE_FORMULA
:
181 // Reset to empty value.
182 meType
= CELLTYPE_NONE
;
186 void ScCellValue::set( double fValue
)
189 meType
= CELLTYPE_VALUE
;
193 void ScCellValue::set( const OUString
& rStr
)
196 meType
= CELLTYPE_STRING
;
197 mpString
= new OUString(rStr
);
200 void ScCellValue::set( const EditTextObject
& rEditText
)
203 meType
= CELLTYPE_EDIT
;
204 mpEditText
= rEditText
.Clone();
207 void ScCellValue::set( const ScFormulaCell
& rFormula
)
210 meType
= CELLTYPE_FORMULA
;
211 mpFormula
= rFormula
.Clone();
214 void ScCellValue::set( ScFormulaCell
* pFormula
)
217 meType
= CELLTYPE_FORMULA
;
218 mpFormula
= pFormula
;
221 void ScCellValue::assign( const ScDocument
& rDoc
, const ScAddress
& rPos
)
225 ScRefCellValue aRefVal
;
226 aRefVal
.assign(const_cast<ScDocument
&>(rDoc
), rPos
);
228 meType
= aRefVal
.meType
;
231 case CELLTYPE_STRING
:
232 mpString
= new OUString(*aRefVal
.mpString
);
235 if (aRefVal
.mpEditText
)
236 mpEditText
= aRefVal
.mpEditText
->Clone();
239 mfValue
= aRefVal
.mfValue
;
241 case CELLTYPE_FORMULA
:
242 mpFormula
= aRefVal
.mpFormula
->Clone();
245 meType
= CELLTYPE_NONE
; // reset to empty.
249 void ScCellValue::assign( const ScCellValue
& rOther
, ScDocument
& rDestDoc
, int nCloneFlags
)
253 meType
= rOther
.meType
;
256 case CELLTYPE_STRING
:
257 mpString
= new OUString(*rOther
.mpString
);
261 // Switch to the pool of the destination document.
262 ScFieldEditEngine
& rEngine
= rDestDoc
.GetEditEngine();
263 if (rOther
.mpEditText
->HasOnlineSpellErrors())
265 sal_uLong nControl
= rEngine
.GetControlWord();
266 const sal_uLong nSpellControl
= EE_CNTRL_ONLINESPELLING
| EE_CNTRL_ALLOWBIGOBJS
;
267 bool bNewControl
= ((nControl
& nSpellControl
) != nSpellControl
);
269 rEngine
.SetControlWord(nControl
| nSpellControl
);
270 rEngine
.SetText(*rOther
.mpEditText
);
271 mpEditText
= rEngine
.CreateTextObject();
273 rEngine
.SetControlWord(nControl
);
277 rEngine
.SetText(*rOther
.mpEditText
);
278 mpEditText
= rEngine
.CreateTextObject();
283 mfValue
= rOther
.mfValue
;
285 case CELLTYPE_FORMULA
:
286 // Switch to the destination document.
287 mpFormula
= new ScFormulaCell(*rOther
.mpFormula
, rDestDoc
, rOther
.mpFormula
->aPos
, nCloneFlags
);
290 meType
= CELLTYPE_NONE
; // reset to empty.
294 void ScCellValue::assign( const ScBaseCell
& rCell
)
298 meType
= rCell
.GetCellType();
301 case CELLTYPE_STRING
:
302 mpString
= new OUString(static_cast<const ScStringCell
&>(rCell
).GetString());
306 const EditTextObject
* p
= static_cast<const ScEditCell
&>(rCell
).GetData();
308 mpEditText
= p
->Clone();
312 mfValue
= static_cast<const ScValueCell
&>(rCell
).GetValue();
314 case CELLTYPE_FORMULA
:
315 mpFormula
= static_cast<const ScFormulaCell
&>(rCell
).Clone();
318 meType
= CELLTYPE_NONE
; // reset to empty.
322 void ScCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
326 case CELLTYPE_STRING
:
328 ScSetStringParam aParam
;
329 aParam
.setTextInput();
330 rDoc
.SetString(rPos
, *mpString
, &aParam
);
334 rDoc
.SetEditText(rPos
, mpEditText
->Clone());
337 rDoc
.SetValue(rPos
, mfValue
);
339 case CELLTYPE_FORMULA
:
340 rDoc
.SetFormulaCell(rPos
, mpFormula
->Clone());
343 rDoc
.SetEmptyCell(rPos
);
347 void ScCellValue::release( ScDocument
& rDoc
, const ScAddress
& rPos
)
351 case CELLTYPE_STRING
:
353 // Currently, string cannot be placed without copying.
354 ScSetStringParam aParam
;
355 aParam
.setTextInput();
356 rDoc
.SetString(rPos
, *mpString
, &aParam
);
361 // Cell takes the ownership of the text object.
362 rDoc
.SetEditText(rPos
, mpEditText
);
365 rDoc
.SetValue(rPos
, mfValue
);
367 case CELLTYPE_FORMULA
:
368 // This formula cell instance is directly placed in the document without copying.
369 rDoc
.SetFormulaCell(rPos
, mpFormula
);
372 rDoc
.SetEmptyCell(rPos
);
375 meType
= CELLTYPE_NONE
;
379 void ScCellValue::release( ScColumn
& rColumn
, SCROW nRow
)
383 case CELLTYPE_STRING
:
385 // Currently, string cannot be placed without copying.
386 rColumn
.SetRawString(nRow
, *mpString
);
391 // Cell takes the ownership of the text object.
392 rColumn
.SetEditText(nRow
, mpEditText
);
395 rColumn
.SetValue(nRow
, mfValue
);
397 case CELLTYPE_FORMULA
:
398 // This formula cell instance is directly placed in the document without copying.
399 rColumn
.SetFormulaCell(nRow
, mpFormula
);
402 rColumn
.Delete(nRow
);
405 meType
= CELLTYPE_NONE
;
409 bool ScCellValue::hasString() const
411 return hasStringImpl(meType
, mpFormula
);
414 bool ScCellValue::hasNumeric() const
416 return hasNumericImpl(meType
, mpFormula
);
419 bool ScCellValue::isEmpty() const
421 return meType
== CELLTYPE_NONE
;
424 bool ScCellValue::equalsWithoutFormat( const ScCellValue
& r
) const
426 return equalsWithoutFormatImpl(*this, r
);
429 ScCellValue
& ScCellValue::operator= ( const ScCellValue
& r
)
436 void ScCellValue::swap( ScCellValue
& r
)
438 std::swap(meType
, r
.meType
);
440 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
441 // the platform. Swap by double values.
442 std::swap(mfValue
, r
.mfValue
);
445 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE
), mfValue(0.0) {}
446 ScRefCellValue::ScRefCellValue( double fValue
) : meType(CELLTYPE_VALUE
), mfValue(fValue
) {}
447 ScRefCellValue::ScRefCellValue( const OUString
* pString
) : meType(CELLTYPE_STRING
), mpString(pString
) {}
448 ScRefCellValue::ScRefCellValue( const EditTextObject
* pEditText
) : meType(CELLTYPE_EDIT
), mpEditText(pEditText
) {}
449 ScRefCellValue::ScRefCellValue( ScFormulaCell
* pFormula
) : meType(CELLTYPE_FORMULA
), mpFormula(pFormula
) {}
451 // It should be enough to copy the double value, which is at least as large
452 // as the pointer values.
453 ScRefCellValue::ScRefCellValue( const ScRefCellValue
& r
) : meType(r
.meType
), mfValue(r
.mfValue
) {}
455 ScRefCellValue::~ScRefCellValue()
460 void ScRefCellValue::clear()
462 // Reset to empty value.
463 meType
= CELLTYPE_NONE
;
467 void ScRefCellValue::assign( ScDocument
& rDoc
, const ScAddress
& rPos
)
469 *this = rDoc
.GetRefCellValue(rPos
);
472 void ScRefCellValue::assign( ScBaseCell
& rCell
)
476 meType
= rCell
.GetCellType();
479 case CELLTYPE_STRING
:
480 mpString
= static_cast<const ScStringCell
&>(rCell
).GetStringPtr();
483 mpEditText
= static_cast<const ScEditCell
&>(rCell
).GetData();
486 mfValue
= static_cast<const ScValueCell
&>(rCell
).GetValue();
488 case CELLTYPE_FORMULA
:
489 mpFormula
= static_cast<ScFormulaCell
*>(&rCell
);
492 meType
= CELLTYPE_NONE
; // reset to empty.
496 void ScRefCellValue::commit( ScDocument
& rDoc
, const ScAddress
& rPos
) const
500 case CELLTYPE_STRING
:
502 ScSetStringParam aParam
;
503 aParam
.setTextInput();
504 rDoc
.SetString(rPos
, *mpString
, &aParam
);
508 rDoc
.SetEditText(rPos
, mpEditText
->Clone());
511 rDoc
.SetValue(rPos
, mfValue
);
513 case CELLTYPE_FORMULA
:
514 rDoc
.SetFormulaCell(rPos
, mpFormula
->Clone());
517 rDoc
.SetEmptyCell(rPos
);
521 bool ScRefCellValue::hasString() const
523 return hasStringImpl(meType
, mpFormula
);
526 bool ScRefCellValue::hasNumeric() const
528 return hasNumericImpl(meType
, mpFormula
);
531 double ScRefCellValue::getValue()
537 case CELLTYPE_FORMULA
:
538 return mpFormula
->GetValue();
545 OUString
ScRefCellValue::getString( const ScDocument
* pDoc
)
549 case CELLTYPE_STRING
:
553 return ScEditUtil::GetString(*mpEditText
, pDoc
);
555 case CELLTYPE_FORMULA
:
556 return mpFormula
->GetString();
560 return EMPTY_OUSTRING
;
563 bool ScRefCellValue::isEmpty() const
565 return meType
== CELLTYPE_NONE
;
568 bool ScRefCellValue::hasEmptyValue()
573 if (meType
== CELLTYPE_FORMULA
)
574 return mpFormula
->IsEmpty();
579 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue
& r
) const
581 return equalsWithoutFormatImpl(*this, r
);
584 ScRefCellValue
& ScRefCellValue::operator= ( const ScRefCellValue
& r
)
586 ScRefCellValue
aTmp(r
);
591 void ScRefCellValue::swap( ScRefCellValue
& r
)
593 std::swap(meType
, r
.meType
);
595 // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
596 // the platform. Swap by double values.
597 std::swap(mfValue
, r
.mfValue
);
600 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */