re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / cellvalue.cxx
blobc82f2904e624c9ac335a584b39effdb04334980d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "cellvalue.hxx"
11 #include "document.hxx"
12 #include "cell.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 "column.hxx"
20 #include "formula/token.hxx"
22 namespace {
24 CellType adjustCellType( CellType eOrig )
26 switch (eOrig)
28 case CELLTYPE_EDIT:
29 return CELLTYPE_STRING;
30 default:
33 return eOrig;
36 template<typename _T>
37 OUString getString( const _T& rVal )
39 if (rVal.meType == CELLTYPE_STRING)
40 return *rVal.mpString;
42 if (rVal.meType == CELLTYPE_EDIT)
44 OUStringBuffer aRet;
45 sal_Int32 n = rVal.mpEditText->GetParagraphCount();
46 for (sal_Int32 i = 0; i < n; ++i)
48 if (i > 0)
49 aRet.append('\n');
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())
64 return false;
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])))
72 return false;
75 return true;
78 template<typename _T>
79 bool equalsWithoutFormatImpl( const _T& left, const _T& right )
81 CellType eType1 = adjustCellType(left.meType);
82 CellType eType2 = adjustCellType(right.meType);
83 if (eType1 != eType2)
84 return false;
86 switch (eType1)
88 case CELLTYPE_NONE:
89 return true;
90 case CELLTYPE_VALUE:
91 return left.mfValue == right.mfValue;
92 case CELLTYPE_STRING:
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);
100 default:
103 return false;
106 bool hasStringImpl( CellType eType, ScFormulaCell* pFormula )
108 switch (eType)
110 case CELLTYPE_STRING:
111 case CELLTYPE_EDIT:
112 return true;
113 case CELLTYPE_FORMULA:
114 return !pFormula->IsValue();
115 default:
116 return false;
120 bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula )
122 switch (eType)
124 case CELLTYPE_VALUE:
125 return true;
126 case CELLTYPE_FORMULA:
127 return pFormula->IsValue();
128 default:
129 return false;
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)
143 switch (r.meType)
145 case CELLTYPE_STRING:
146 mpString = new OUString(*r.mpString);
147 break;
148 case CELLTYPE_EDIT:
149 mpEditText = r.mpEditText->Clone();
150 break;
151 case CELLTYPE_FORMULA:
152 mpFormula = r.mpFormula->Clone();
153 break;
154 default:
159 ScCellValue::~ScCellValue()
161 clear();
164 void ScCellValue::clear()
166 switch (meType)
168 case CELLTYPE_STRING:
169 delete mpString;
170 break;
171 case CELLTYPE_EDIT:
172 delete mpEditText;
173 break;
174 case CELLTYPE_FORMULA:
175 mpFormula->Delete();
176 break;
177 default:
181 // Reset to empty value.
182 meType = CELLTYPE_NONE;
183 mfValue = 0.0;
186 void ScCellValue::set( double fValue )
188 clear();
189 meType = CELLTYPE_VALUE;
190 mfValue = fValue;
193 void ScCellValue::set( const OUString& rStr )
195 clear();
196 meType = CELLTYPE_STRING;
197 mpString = new OUString(rStr);
200 void ScCellValue::set( const EditTextObject& rEditText )
202 clear();
203 meType = CELLTYPE_EDIT;
204 mpEditText = rEditText.Clone();
207 void ScCellValue::set( const ScFormulaCell& rFormula )
209 clear();
210 meType = CELLTYPE_FORMULA;
211 mpFormula = rFormula.Clone();
214 void ScCellValue::set( ScFormulaCell* pFormula )
216 clear();
217 meType = CELLTYPE_FORMULA;
218 mpFormula = pFormula;
221 void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
223 clear();
225 ScRefCellValue aRefVal;
226 aRefVal.assign(const_cast<ScDocument&>(rDoc), rPos);
228 meType = aRefVal.meType;
229 switch (meType)
231 case CELLTYPE_STRING:
232 mpString = new OUString(*aRefVal.mpString);
233 break;
234 case CELLTYPE_EDIT:
235 if (aRefVal.mpEditText)
236 mpEditText = aRefVal.mpEditText->Clone();
237 break;
238 case CELLTYPE_VALUE:
239 mfValue = aRefVal.mfValue;
240 break;
241 case CELLTYPE_FORMULA:
242 mpFormula = aRefVal.mpFormula->Clone();
243 break;
244 default:
245 meType = CELLTYPE_NONE; // reset to empty.
249 void ScCellValue::assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags )
251 clear();
253 meType = rOther.meType;
254 switch (meType)
256 case CELLTYPE_STRING:
257 mpString = new OUString(*rOther.mpString);
258 break;
259 case CELLTYPE_EDIT:
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);
268 if (bNewControl)
269 rEngine.SetControlWord(nControl | nSpellControl);
270 rEngine.SetText(*rOther.mpEditText);
271 mpEditText = rEngine.CreateTextObject();
272 if (bNewControl)
273 rEngine.SetControlWord(nControl);
275 else
277 rEngine.SetText(*rOther.mpEditText);
278 mpEditText = rEngine.CreateTextObject();
281 break;
282 case CELLTYPE_VALUE:
283 mfValue = rOther.mfValue;
284 break;
285 case CELLTYPE_FORMULA:
286 // Switch to the destination document.
287 mpFormula = new ScFormulaCell(*rOther.mpFormula, rDestDoc, rOther.mpFormula->aPos, nCloneFlags);
288 break;
289 default:
290 meType = CELLTYPE_NONE; // reset to empty.
294 void ScCellValue::assign( const ScBaseCell& rCell )
296 clear();
298 meType = rCell.GetCellType();
299 switch (meType)
301 case CELLTYPE_STRING:
302 mpString = new OUString(static_cast<const ScStringCell&>(rCell).GetString());
303 break;
304 case CELLTYPE_EDIT:
306 const EditTextObject* p = static_cast<const ScEditCell&>(rCell).GetData();
307 if (p)
308 mpEditText = p->Clone();
310 break;
311 case CELLTYPE_VALUE:
312 mfValue = static_cast<const ScValueCell&>(rCell).GetValue();
313 break;
314 case CELLTYPE_FORMULA:
315 mpFormula = static_cast<const ScFormulaCell&>(rCell).Clone();
316 break;
317 default:
318 meType = CELLTYPE_NONE; // reset to empty.
322 void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
324 switch (meType)
326 case CELLTYPE_STRING:
328 ScSetStringParam aParam;
329 aParam.setTextInput();
330 rDoc.SetString(rPos, *mpString, &aParam);
332 break;
333 case CELLTYPE_EDIT:
334 rDoc.SetEditText(rPos, mpEditText->Clone());
335 break;
336 case CELLTYPE_VALUE:
337 rDoc.SetValue(rPos, mfValue);
338 break;
339 case CELLTYPE_FORMULA:
340 rDoc.SetFormulaCell(rPos, mpFormula->Clone());
341 break;
342 default:
343 rDoc.SetEmptyCell(rPos);
347 void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
349 switch (meType)
351 case CELLTYPE_STRING:
353 // Currently, string cannot be placed without copying.
354 ScSetStringParam aParam;
355 aParam.setTextInput();
356 rDoc.SetString(rPos, *mpString, &aParam);
357 delete mpString;
359 break;
360 case CELLTYPE_EDIT:
361 // Cell takes the ownership of the text object.
362 rDoc.SetEditText(rPos, mpEditText);
363 break;
364 case CELLTYPE_VALUE:
365 rDoc.SetValue(rPos, mfValue);
366 break;
367 case CELLTYPE_FORMULA:
368 // This formula cell instance is directly placed in the document without copying.
369 rDoc.SetFormulaCell(rPos, mpFormula);
370 break;
371 default:
372 rDoc.SetEmptyCell(rPos);
375 meType = CELLTYPE_NONE;
376 mfValue = 0.0;
379 void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
381 switch (meType)
383 case CELLTYPE_STRING:
385 // Currently, string cannot be placed without copying.
386 rColumn.SetRawString(nRow, *mpString);
387 delete mpString;
389 break;
390 case CELLTYPE_EDIT:
391 // Cell takes the ownership of the text object.
392 rColumn.SetEditText(nRow, mpEditText);
393 break;
394 case CELLTYPE_VALUE:
395 rColumn.SetValue(nRow, mfValue);
396 break;
397 case CELLTYPE_FORMULA:
398 // This formula cell instance is directly placed in the document without copying.
399 rColumn.SetFormulaCell(nRow, mpFormula);
400 break;
401 default:
402 rColumn.Delete(nRow);
405 meType = CELLTYPE_NONE;
406 mfValue = 0.0;
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 )
431 ScCellValue aTmp(r);
432 swap(aTmp);
433 return *this;
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()
457 clear();
460 void ScRefCellValue::clear()
462 // Reset to empty value.
463 meType = CELLTYPE_NONE;
464 mfValue = 0.0;
467 void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
469 *this = rDoc.GetRefCellValue(rPos);
472 void ScRefCellValue::assign( ScBaseCell& rCell )
474 clear();
476 meType = rCell.GetCellType();
477 switch (meType)
479 case CELLTYPE_STRING:
480 mpString = static_cast<const ScStringCell&>(rCell).GetStringPtr();
481 break;
482 case CELLTYPE_EDIT:
483 mpEditText = static_cast<const ScEditCell&>(rCell).GetData();
484 break;
485 case CELLTYPE_VALUE:
486 mfValue = static_cast<const ScValueCell&>(rCell).GetValue();
487 break;
488 case CELLTYPE_FORMULA:
489 mpFormula = static_cast<ScFormulaCell*>(&rCell);
490 break;
491 default:
492 meType = CELLTYPE_NONE; // reset to empty.
496 void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
498 switch (meType)
500 case CELLTYPE_STRING:
502 ScSetStringParam aParam;
503 aParam.setTextInput();
504 rDoc.SetString(rPos, *mpString, &aParam);
506 break;
507 case CELLTYPE_EDIT:
508 rDoc.SetEditText(rPos, mpEditText->Clone());
509 break;
510 case CELLTYPE_VALUE:
511 rDoc.SetValue(rPos, mfValue);
512 break;
513 case CELLTYPE_FORMULA:
514 rDoc.SetFormulaCell(rPos, mpFormula->Clone());
515 break;
516 default:
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()
533 switch (meType)
535 case CELLTYPE_VALUE:
536 return mfValue;
537 case CELLTYPE_FORMULA:
538 return mpFormula->GetValue();
539 default:
542 return 0.0;
545 OUString ScRefCellValue::getString( const ScDocument* pDoc )
547 switch (meType)
549 case CELLTYPE_STRING:
550 return *mpString;
551 case CELLTYPE_EDIT:
552 if (mpEditText)
553 return ScEditUtil::GetString(*mpEditText, pDoc);
554 break;
555 case CELLTYPE_FORMULA:
556 return mpFormula->GetString();
557 default:
560 return EMPTY_OUSTRING;
563 bool ScRefCellValue::isEmpty() const
565 return meType == CELLTYPE_NONE;
568 bool ScRefCellValue::hasEmptyValue()
570 if (isEmpty())
571 return true;
573 if (meType == CELLTYPE_FORMULA)
574 return mpFormula->IsEmpty();
576 return false;
579 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const
581 return equalsWithoutFormatImpl(*this, r);
584 ScRefCellValue& ScRefCellValue::operator= ( const ScRefCellValue& r )
586 ScRefCellValue aTmp(r);
587 swap(aTmp);
588 return *this;
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: */