Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include "cellvalue.hxx"
11 : #include "document.hxx"
12 : #include "column.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>
21 :
22 : namespace {
23 :
24 232 : CellType adjustCellType( CellType eOrig )
25 : {
26 232 : switch (eOrig)
27 : {
28 : case CELLTYPE_EDIT:
29 0 : return CELLTYPE_STRING;
30 : default:
31 : ;
32 : }
33 232 : return eOrig;
34 : }
35 :
36 : template<typename _T>
37 160 : OUString getString( const _T& rVal )
38 : {
39 160 : if (rVal.meType == CELLTYPE_STRING)
40 160 : return rVal.mpString->getString();
41 :
42 0 : if (rVal.meType == CELLTYPE_EDIT)
43 : {
44 0 : OUStringBuffer aRet;
45 0 : sal_Int32 n = rVal.mpEditText->GetParagraphCount();
46 0 : for (sal_Int32 i = 0; i < n; ++i)
47 : {
48 0 : if (i > 0)
49 0 : aRet.append('\n');
50 0 : aRet.append(rVal.mpEditText->GetText(i));
51 : }
52 0 : return aRet.makeStringAndClear();
53 : }
54 :
55 0 : return EMPTY_OUSTRING;
56 : }
57 :
58 4 : bool equalsFormulaCells( const ScFormulaCell* p1, const ScFormulaCell* p2 )
59 : {
60 4 : const ScTokenArray* pCode1 = p1->GetCode();
61 4 : const ScTokenArray* pCode2 = p2->GetCode();
62 :
63 4 : if (pCode1->GetLen() != pCode2->GetLen())
64 0 : return false;
65 :
66 4 : sal_uInt16 n = pCode1->GetLen();
67 4 : formula::FormulaToken** ppToken1 = pCode1->GetArray();
68 4 : formula::FormulaToken** ppToken2 = pCode2->GetArray();
69 16 : for (sal_uInt16 i = 0; i < n; ++i)
70 : {
71 12 : if (!ppToken1[i]->TextEqual(*(ppToken2[i])))
72 0 : return false;
73 : }
74 :
75 4 : return true;
76 : }
77 :
78 : template<typename _T>
79 116 : bool equalsWithoutFormatImpl( const _T& left, const _T& right )
80 : {
81 116 : CellType eType1 = adjustCellType(left.meType);
82 116 : CellType eType2 = adjustCellType(right.meType);
83 116 : if (eType1 != eType2)
84 14 : return false;
85 :
86 102 : switch (eType1)
87 : {
88 : case CELLTYPE_NONE:
89 0 : return true;
90 : case CELLTYPE_VALUE:
91 18 : return left.mfValue == right.mfValue;
92 : case CELLTYPE_STRING:
93 : {
94 80 : OUString aStr1 = getString(left);
95 160 : OUString aStr2 = getString(right);
96 160 : return aStr1 == aStr2;
97 : }
98 : case CELLTYPE_FORMULA:
99 4 : return equalsFormulaCells(left.mpFormula, right.mpFormula);
100 : default:
101 : ;
102 : }
103 0 : return false;
104 : }
105 :
106 296 : static void commitToColumn( const ScCellValue& rCell, ScColumn& rColumn, SCROW nRow )
107 : {
108 296 : switch (rCell.meType)
109 : {
110 : case CELLTYPE_STRING:
111 108 : rColumn.SetRawString(nRow, *rCell.mpString);
112 108 : break;
113 : case CELLTYPE_EDIT:
114 0 : rColumn.SetEditText(nRow, ScEditUtil::Clone(*rCell.mpEditText, rColumn.GetDoc()));
115 0 : break;
116 : case CELLTYPE_VALUE:
117 188 : rColumn.SetValue(nRow, rCell.mfValue);
118 188 : break;
119 : case CELLTYPE_FORMULA:
120 : {
121 0 : ScAddress aDestPos(rColumn.GetCol(), nRow, rColumn.GetTab());
122 0 : rColumn.SetFormulaCell(nRow, new ScFormulaCell(*rCell.mpFormula, rColumn.GetDoc(), aDestPos));
123 : }
124 0 : break;
125 : default:
126 0 : rColumn.Delete(nRow);
127 : }
128 296 : }
129 :
130 4030 : bool hasStringImpl( CellType eType, ScFormulaCell* pFormula )
131 : {
132 4030 : switch (eType)
133 : {
134 : case CELLTYPE_STRING:
135 : case CELLTYPE_EDIT:
136 670 : return true;
137 : case CELLTYPE_FORMULA:
138 1242 : return !pFormula->IsValue();
139 : default:
140 2118 : return false;
141 : }
142 : }
143 :
144 25794 : bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula )
145 : {
146 25794 : switch (eType)
147 : {
148 : case CELLTYPE_VALUE:
149 15635 : return true;
150 : case CELLTYPE_FORMULA:
151 1045 : return pFormula->IsValue();
152 : default:
153 9114 : return false;
154 : }
155 : }
156 :
157 : template<typename _CellT>
158 4584 : OUString getStringImpl( const _CellT& rCell, const ScDocument* pDoc )
159 : {
160 4584 : switch (rCell.meType)
161 : {
162 : case CELLTYPE_VALUE:
163 14 : return OUString::number(rCell.mfValue);
164 : case CELLTYPE_STRING:
165 4196 : return rCell.mpString->getString();
166 : case CELLTYPE_EDIT:
167 374 : if (rCell.mpEditText)
168 374 : return ScEditUtil::GetString(*rCell.mpEditText, pDoc);
169 0 : break;
170 : case CELLTYPE_FORMULA:
171 0 : return rCell.mpFormula->GetString().getString();
172 : default:
173 : ;
174 : }
175 0 : return EMPTY_OUSTRING;
176 : }
177 :
178 : }
179 :
180 37682 : ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
181 :
182 172 : ScCellValue::ScCellValue( const ScRefCellValue& rCell ) : meType(rCell.meType), mfValue(rCell.mfValue)
183 : {
184 172 : switch (rCell.meType)
185 : {
186 : case CELLTYPE_STRING:
187 40 : mpString = new svl::SharedString(*rCell.mpString);
188 40 : break;
189 : case CELLTYPE_EDIT:
190 0 : mpEditText = rCell.mpEditText->Clone();
191 0 : break;
192 : case CELLTYPE_FORMULA:
193 6 : mpFormula = rCell.mpFormula->Clone();
194 6 : break;
195 : default:
196 : ;
197 : }
198 172 : }
199 :
200 0 : ScCellValue::ScCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
201 :
202 2 : ScCellValue::ScCellValue( const svl::SharedString& rString ) : meType(CELLTYPE_STRING), mpString(new svl::SharedString(rString)) {}
203 :
204 22614 : ScCellValue::ScCellValue( const ScCellValue& r ) : meType(r.meType), mfValue(r.mfValue)
205 : {
206 22614 : switch (r.meType)
207 : {
208 : case CELLTYPE_STRING:
209 3008 : mpString = new svl::SharedString(*r.mpString);
210 3008 : break;
211 : case CELLTYPE_EDIT:
212 666 : mpEditText = r.mpEditText->Clone();
213 666 : break;
214 : case CELLTYPE_FORMULA:
215 282 : mpFormula = r.mpFormula->Clone();
216 282 : break;
217 : default:
218 : ;
219 : }
220 22614 : }
221 :
222 60470 : ScCellValue::~ScCellValue()
223 : {
224 60470 : clear();
225 60470 : }
226 :
227 95456 : void ScCellValue::clear()
228 : {
229 95456 : switch (meType)
230 : {
231 : case CELLTYPE_STRING:
232 6418 : delete mpString;
233 6418 : break;
234 : case CELLTYPE_EDIT:
235 1336 : delete mpEditText;
236 1336 : break;
237 : case CELLTYPE_FORMULA:
238 580 : delete mpFormula;
239 580 : break;
240 : default:
241 : ;
242 : }
243 :
244 : // Reset to empty value.
245 95456 : meType = CELLTYPE_NONE;
246 95456 : mfValue = 0.0;
247 95456 : }
248 :
249 6 : void ScCellValue::set( const ScRefCellValue& rCell )
250 : {
251 6 : clear();
252 :
253 6 : meType = rCell.meType;
254 6 : switch (meType)
255 : {
256 : case CELLTYPE_VALUE:
257 0 : mfValue = rCell.mfValue;
258 0 : break;
259 : case CELLTYPE_STRING:
260 2 : mpString = new svl::SharedString(*rCell.mpString);
261 2 : break;
262 : case CELLTYPE_EDIT:
263 0 : mpEditText = rCell.mpEditText->Clone();
264 0 : break;
265 : case CELLTYPE_FORMULA:
266 2 : mpFormula = rCell.mpFormula->Clone();
267 2 : break;
268 : default:
269 : ;
270 : }
271 6 : }
272 :
273 1870 : void ScCellValue::set( double fValue )
274 : {
275 1870 : clear();
276 1870 : meType = CELLTYPE_VALUE;
277 1870 : mfValue = fValue;
278 1870 : }
279 :
280 8880 : void ScCellValue::set( const svl::SharedString& rStr )
281 : {
282 8880 : clear();
283 8880 : meType = CELLTYPE_STRING;
284 8880 : mpString = new svl::SharedString(rStr);
285 8880 : }
286 :
287 0 : void ScCellValue::set( const EditTextObject& rEditText )
288 : {
289 0 : clear();
290 0 : meType = CELLTYPE_EDIT;
291 0 : mpEditText = rEditText.Clone();
292 0 : }
293 :
294 4 : void ScCellValue::set( EditTextObject* pEditText )
295 : {
296 4 : clear();
297 4 : meType = CELLTYPE_EDIT;
298 4 : mpEditText = pEditText;
299 4 : }
300 :
301 1542 : void ScCellValue::set( ScFormulaCell* pFormula )
302 : {
303 1542 : clear();
304 1542 : meType = CELLTYPE_FORMULA;
305 1542 : mpFormula = pFormula;
306 1542 : }
307 :
308 22478 : void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
309 : {
310 22478 : clear();
311 :
312 22478 : ScRefCellValue aRefVal;
313 22478 : aRefVal.assign(const_cast<ScDocument&>(rDoc), rPos);
314 :
315 22478 : meType = aRefVal.meType;
316 22478 : switch (meType)
317 : {
318 : case CELLTYPE_STRING:
319 3008 : mpString = new svl::SharedString(*aRefVal.mpString);
320 3008 : break;
321 : case CELLTYPE_EDIT:
322 662 : if (aRefVal.mpEditText)
323 662 : mpEditText = aRefVal.mpEditText->Clone();
324 662 : break;
325 : case CELLTYPE_VALUE:
326 11590 : mfValue = aRefVal.mfValue;
327 11590 : break;
328 : case CELLTYPE_FORMULA:
329 274 : mpFormula = aRefVal.mpFormula->Clone();
330 274 : break;
331 : default:
332 6944 : meType = CELLTYPE_NONE; // reset to empty.
333 22478 : }
334 22478 : }
335 :
336 88 : void ScCellValue::assign( const ScCellValue& rOther, ScDocument& rDestDoc, int nCloneFlags )
337 : {
338 88 : clear();
339 :
340 88 : meType = rOther.meType;
341 88 : switch (meType)
342 : {
343 : case CELLTYPE_STRING:
344 8 : mpString = new svl::SharedString(*rOther.mpString);
345 8 : break;
346 : case CELLTYPE_EDIT:
347 : {
348 : // Switch to the pool of the destination document.
349 4 : ScFieldEditEngine& rEngine = rDestDoc.GetEditEngine();
350 4 : if (rOther.mpEditText->HasOnlineSpellErrors())
351 : {
352 0 : sal_uLong nControl = rEngine.GetControlWord();
353 0 : const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
354 0 : bool bNewControl = ((nControl & nSpellControl) != nSpellControl);
355 0 : if (bNewControl)
356 0 : rEngine.SetControlWord(nControl | nSpellControl);
357 0 : rEngine.SetText(*rOther.mpEditText);
358 0 : mpEditText = rEngine.CreateTextObject();
359 0 : if (bNewControl)
360 0 : rEngine.SetControlWord(nControl);
361 : }
362 : else
363 : {
364 4 : rEngine.SetText(*rOther.mpEditText);
365 4 : mpEditText = rEngine.CreateTextObject();
366 : }
367 : }
368 4 : break;
369 : case CELLTYPE_VALUE:
370 40 : mfValue = rOther.mfValue;
371 40 : break;
372 : case CELLTYPE_FORMULA:
373 : // Switch to the destination document.
374 8 : mpFormula = new ScFormulaCell(*rOther.mpFormula, rDestDoc, rOther.mpFormula->aPos, nCloneFlags);
375 8 : break;
376 : default:
377 28 : meType = CELLTYPE_NONE; // reset to empty.
378 : }
379 88 : }
380 :
381 2 : void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
382 : {
383 2 : switch (meType)
384 : {
385 : case CELLTYPE_STRING:
386 : {
387 2 : ScSetStringParam aParam;
388 2 : aParam.setTextInput();
389 2 : rDoc.SetString(rPos, mpString->getString(), &aParam);
390 : }
391 2 : break;
392 : case CELLTYPE_EDIT:
393 0 : rDoc.SetEditText(rPos, mpEditText->Clone());
394 0 : break;
395 : case CELLTYPE_VALUE:
396 0 : rDoc.SetValue(rPos, mfValue);
397 0 : break;
398 : case CELLTYPE_FORMULA:
399 0 : rDoc.SetFormulaCell(rPos, mpFormula->Clone());
400 0 : break;
401 : default:
402 0 : rDoc.SetEmptyCell(rPos);
403 : }
404 2 : }
405 :
406 296 : void ScCellValue::commit( ScColumn& rColumn, SCROW nRow ) const
407 : {
408 296 : commitToColumn(*this, rColumn, nRow);
409 296 : }
410 :
411 0 : void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
412 : {
413 0 : switch (meType)
414 : {
415 : case CELLTYPE_STRING:
416 : {
417 : // Currently, string cannot be placed without copying.
418 0 : ScSetStringParam aParam;
419 0 : aParam.setTextInput();
420 0 : rDoc.SetString(rPos, mpString->getString(), &aParam);
421 0 : delete mpString;
422 : }
423 0 : break;
424 : case CELLTYPE_EDIT:
425 : // Cell takes the ownership of the text object.
426 0 : rDoc.SetEditText(rPos, mpEditText);
427 0 : break;
428 : case CELLTYPE_VALUE:
429 0 : rDoc.SetValue(rPos, mfValue);
430 0 : break;
431 : case CELLTYPE_FORMULA:
432 : // This formula cell instance is directly placed in the document without copying.
433 0 : rDoc.SetFormulaCell(rPos, mpFormula);
434 0 : break;
435 : default:
436 0 : rDoc.SetEmptyCell(rPos);
437 : }
438 :
439 0 : meType = CELLTYPE_NONE;
440 0 : mfValue = 0.0;
441 0 : }
442 :
443 14194 : void ScCellValue::release( ScColumn& rColumn, SCROW nRow )
444 : {
445 14194 : switch (meType)
446 : {
447 : case CELLTYPE_STRING:
448 : {
449 : // Currently, string cannot be placed without copying.
450 8534 : rColumn.SetRawString(nRow, *mpString);
451 8534 : delete mpString;
452 : }
453 8534 : break;
454 : case CELLTYPE_EDIT:
455 : // Cell takes the ownership of the text object.
456 0 : rColumn.SetEditText(nRow, mpEditText);
457 0 : break;
458 : case CELLTYPE_VALUE:
459 1648 : rColumn.SetValue(nRow, mfValue);
460 1648 : break;
461 : case CELLTYPE_FORMULA:
462 : // This formula cell instance is directly placed in the document without copying.
463 1538 : rColumn.SetFormulaCell(nRow, mpFormula);
464 1538 : break;
465 : default:
466 2474 : rColumn.Delete(nRow);
467 : }
468 :
469 14194 : meType = CELLTYPE_NONE;
470 14194 : mfValue = 0.0;
471 14194 : }
472 :
473 0 : OUString ScCellValue::getString( const ScDocument* pDoc )
474 : {
475 0 : return getStringImpl(*this, pDoc);
476 : }
477 :
478 422 : bool ScCellValue::isEmpty() const
479 : {
480 422 : return meType == CELLTYPE_NONE;
481 : }
482 :
483 0 : bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
484 : {
485 0 : return equalsWithoutFormatImpl(*this, r);
486 : }
487 :
488 112 : ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
489 : {
490 112 : ScCellValue aTmp(r);
491 112 : swap(aTmp);
492 112 : return *this;
493 : }
494 :
495 28 : ScCellValue& ScCellValue::operator= ( const ScRefCellValue& r )
496 : {
497 28 : ScCellValue aTmp(r);
498 28 : swap(aTmp);
499 28 : return *this;
500 : }
501 :
502 140 : void ScCellValue::swap( ScCellValue& r )
503 : {
504 140 : std::swap(meType, r.meType);
505 :
506 : // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
507 : // the platform. Swap by double values.
508 140 : std::swap(mfValue, r.mfValue);
509 140 : }
510 :
511 6272222 : ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
512 617230 : ScRefCellValue::ScRefCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
513 189745 : ScRefCellValue::ScRefCellValue( const svl::SharedString* pString ) : meType(CELLTYPE_STRING), mpString(pString) {}
514 1672 : ScRefCellValue::ScRefCellValue( const EditTextObject* pEditText ) : meType(CELLTYPE_EDIT), mpEditText(pEditText) {}
515 12572 : ScRefCellValue::ScRefCellValue( ScFormulaCell* pFormula ) : meType(CELLTYPE_FORMULA), mpFormula(pFormula) {}
516 :
517 : // It should be enough to copy the double value, which is at least as large
518 : // as the pointer values.
519 1037395 : ScRefCellValue::ScRefCellValue( const ScRefCellValue& r ) : meType(r.meType), mfValue(r.mfValue) {}
520 :
521 8130836 : ScRefCellValue::~ScRefCellValue()
522 : {
523 8130836 : clear();
524 8130836 : }
525 :
526 13753991 : void ScRefCellValue::clear()
527 : {
528 : // Reset to empty value.
529 13753991 : meType = CELLTYPE_NONE;
530 13753991 : mfValue = 0.0;
531 13753991 : }
532 :
533 147194 : void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
534 : {
535 147194 : *this = rDoc.GetRefCellValue(rPos);
536 147194 : }
537 :
538 570 : void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
539 : {
540 570 : switch (meType)
541 : {
542 : case CELLTYPE_STRING:
543 : {
544 556 : ScSetStringParam aParam;
545 556 : aParam.setTextInput();
546 556 : rDoc.SetString(rPos, mpString->getString(), &aParam);
547 : }
548 556 : break;
549 : case CELLTYPE_EDIT:
550 0 : rDoc.SetEditText(rPos, ScEditUtil::Clone(*mpEditText, rDoc));
551 0 : break;
552 : case CELLTYPE_VALUE:
553 8 : rDoc.SetValue(rPos, mfValue);
554 8 : break;
555 : case CELLTYPE_FORMULA:
556 6 : rDoc.SetFormulaCell(rPos, new ScFormulaCell(*mpFormula, rDoc, rPos));
557 6 : break;
558 : default:
559 0 : rDoc.SetEmptyCell(rPos);
560 : }
561 570 : }
562 :
563 4030 : bool ScRefCellValue::hasString() const
564 : {
565 4030 : return hasStringImpl(meType, mpFormula);
566 : }
567 :
568 25794 : bool ScRefCellValue::hasNumeric() const
569 : {
570 25794 : return hasNumericImpl(meType, mpFormula);
571 : }
572 :
573 2599 : double ScRefCellValue::getValue()
574 : {
575 2599 : switch (meType)
576 : {
577 : case CELLTYPE_VALUE:
578 2091 : return mfValue;
579 : case CELLTYPE_FORMULA:
580 508 : return mpFormula->GetValue();
581 : default:
582 : ;
583 : }
584 0 : return 0.0;
585 : }
586 :
587 4584 : OUString ScRefCellValue::getString( const ScDocument* pDoc )
588 : {
589 4584 : return getStringImpl(*this, pDoc);
590 : }
591 :
592 115411 : bool ScRefCellValue::isEmpty() const
593 : {
594 115411 : return meType == CELLTYPE_NONE;
595 : }
596 :
597 3440 : bool ScRefCellValue::hasEmptyValue()
598 : {
599 3440 : if (isEmpty())
600 1392 : return true;
601 :
602 2048 : if (meType == CELLTYPE_FORMULA)
603 434 : return mpFormula->IsEmpty();
604 :
605 1614 : return false;
606 : }
607 :
608 116 : bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const
609 : {
610 116 : return equalsWithoutFormatImpl(*this, r);
611 : }
612 :
613 1026179 : ScRefCellValue& ScRefCellValue::operator= ( const ScRefCellValue& r )
614 : {
615 1026179 : ScRefCellValue aTmp(r);
616 1026179 : swap(aTmp);
617 1026179 : return *this;
618 : }
619 :
620 1026179 : void ScRefCellValue::swap( ScRefCellValue& r )
621 : {
622 1026179 : std::swap(meType, r.meType);
623 :
624 : // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
625 : // the platform. Swap by double values.
626 1026179 : std::swap(mfValue, r.mfValue);
627 1026407 : }
628 :
629 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|