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