tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / core / data / cellvalue.cxx
blob0f972fc534e3ca71a987af5f5d3ebaf7a8da5d86
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 <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 <formula/errorcodes.hxx>
21 #include <svl/sharedstring.hxx>
22 #include <svl/sharedstringpool.hxx>
24 namespace {
26 CellType adjustCellType( CellType eOrig )
28 switch (eOrig)
30 case CELLTYPE_EDIT:
31 return CELLTYPE_STRING;
32 default:
35 return eOrig;
38 template<typename T>
39 OUString getString( const T& rVal )
41 if (rVal.getType() == CELLTYPE_STRING)
42 return rVal.getSharedString()->getString();
44 if (rVal.getType() == CELLTYPE_EDIT)
46 OUStringBuffer aRet;
47 sal_Int32 n = rVal.getEditText()->GetParagraphCount();
48 for (sal_Int32 i = 0; i < n; ++i)
50 if (i > 0)
51 aRet.append('\n');
52 aRet.append(rVal.getEditText()->GetText(i));
54 return aRet.makeStringAndClear();
57 return OUString();
60 bool equalsFormulaCells( const ScFormulaCell* p1, const ScFormulaCell* p2 )
62 const ScTokenArray* pCode1 = p1->GetCode();
63 const ScTokenArray* pCode2 = p2->GetCode();
65 if (pCode1->GetLen() != pCode2->GetLen())
66 return false;
68 if (pCode1->GetCodeError() != pCode2->GetCodeError())
69 return false;
71 sal_uInt16 n = pCode1->GetLen();
72 formula::FormulaToken** ppToken1 = pCode1->GetArray();
73 formula::FormulaToken** ppToken2 = pCode2->GetArray();
74 for (sal_uInt16 i = 0; i < n; ++i)
76 if (!ppToken1[i]->TextEqual(*(ppToken2[i])))
77 return false;
80 return true;
83 template<typename T>
84 bool equalsWithoutFormatImpl( const T& left, const T& right )
86 CellType eType1 = adjustCellType(left.getType());
87 CellType eType2 = adjustCellType(right.getType());
88 if (eType1 != eType2)
89 return false;
91 switch (eType1)
93 case CELLTYPE_NONE:
94 return true;
95 case CELLTYPE_VALUE:
96 return left.getDouble() == right.getDouble();
97 case CELLTYPE_STRING:
99 OUString aStr1 = getString(left);
100 OUString aStr2 = getString(right);
101 return aStr1 == aStr2;
103 case CELLTYPE_FORMULA:
104 return equalsFormulaCells(left.getFormula(), right.getFormula());
105 default:
108 return false;
111 bool equalsWithoutFormatImpl( const ScCellValue& left, const ScCellValue& right )
113 CellType eType1 = adjustCellType(left.getType());
114 CellType eType2 = adjustCellType(right.getType());
115 if (eType1 != eType2)
116 return false;
118 switch (eType1)
120 case CELLTYPE_NONE:
121 return true;
122 case CELLTYPE_VALUE:
123 return left.getDouble() == right.getDouble();
124 case CELLTYPE_STRING:
126 OUString aStr1 = getString(left);
127 OUString aStr2 = getString(right);
128 return aStr1 == aStr2;
130 case CELLTYPE_FORMULA:
131 return equalsFormulaCells(left.getFormula(), right.getFormula());
132 default:
135 return false;
138 void commitToColumn( const ScCellValue& rCell, ScColumn& rColumn, SCROW nRow )
140 switch (rCell.getType())
142 case CELLTYPE_STRING:
143 rColumn.SetRawString(nRow, *rCell.getSharedString());
144 break;
145 case CELLTYPE_EDIT:
146 rColumn.SetEditText(nRow, ScEditUtil::Clone(*rCell.getEditText(), rColumn.GetDoc()));
147 break;
148 case CELLTYPE_VALUE:
149 rColumn.SetValue(nRow, rCell.getDouble());
150 break;
151 case CELLTYPE_FORMULA:
153 ScAddress aDestPos(rColumn.GetCol(), nRow, rColumn.GetTab());
154 rColumn.SetFormulaCell(nRow, new ScFormulaCell(*rCell.getFormula(), rColumn.GetDoc(), aDestPos));
156 break;
157 default:
158 rColumn.DeleteContent(nRow);
162 bool hasStringImpl( CellType eType, ScFormulaCell* pFormula )
164 switch (eType)
166 case CELLTYPE_STRING:
167 case CELLTYPE_EDIT:
168 return true;
169 case CELLTYPE_FORMULA:
170 return !pFormula->IsValue();
171 default:
172 return false;
176 bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula )
178 switch (eType)
180 case CELLTYPE_VALUE:
181 return true;
182 case CELLTYPE_FORMULA:
183 return pFormula->IsValue();
184 default:
185 return false;
189 template <typename T>
190 OUString getStringImpl( const T& rCell, const ScDocument* pDoc )
192 switch (rCell.getType())
194 case CELLTYPE_VALUE:
195 return OUString::number(rCell.getDouble());
196 case CELLTYPE_STRING:
197 return rCell.getSharedString()->getString();
198 case CELLTYPE_EDIT:
199 if (rCell.getEditText())
200 return ScEditUtil::GetString(*rCell.getEditText(), pDoc);
201 break;
202 case CELLTYPE_FORMULA:
203 return rCell.getFormula()->GetString().getString();
204 default:
207 return OUString();
210 template<typename CellT>
211 OUString getRawStringImpl( const CellT& rCell, const ScDocument& rDoc )
213 switch (rCell.getType())
215 case CELLTYPE_VALUE:
216 return OUString::number(rCell.getDouble());
217 case CELLTYPE_STRING:
218 return rCell.getSharedString()->getString();
219 case CELLTYPE_EDIT:
220 if (rCell.getEditText())
221 return ScEditUtil::GetString(*rCell.getEditText(), &rDoc);
222 break;
223 case CELLTYPE_FORMULA:
224 return rCell.getFormula()->GetRawString().getString();
225 default:
228 return OUString();
233 ScCellValue::ScCellValue() {}
235 ScCellValue::ScCellValue( const ScRefCellValue& rCell )
237 switch (rCell.getType())
239 case CELLTYPE_STRING:
240 maData = *rCell.getSharedString();
241 break;
242 case CELLTYPE_EDIT:
243 maData = rCell.getEditText()->Clone().release();
244 break;
245 case CELLTYPE_FORMULA:
246 maData = rCell.getFormula()->Clone();
247 break;
248 case CELLTYPE_VALUE:
249 maData = rCell.getDouble();
250 break;
251 default: ;
255 ScCellValue::ScCellValue( double fValue ) : maData(fValue) {}
257 ScCellValue::ScCellValue( const svl::SharedString& rString ) : maData(rString) {}
259 ScCellValue::ScCellValue( std::unique_ptr<EditTextObject> xEdit ) : maData(xEdit.release()) {}
261 ScCellValue::ScCellValue( const ScCellValue& r )
263 switch (r.getType())
265 case CELLTYPE_STRING:
266 maData = *r.getSharedString();
267 break;
268 case CELLTYPE_EDIT:
269 maData = r.getEditText()->Clone().release();
270 break;
271 case CELLTYPE_FORMULA:
272 maData = r.getFormula()->Clone();
273 break;
274 case CELLTYPE_VALUE:
275 maData = r.getDouble();
276 break;
277 default: ;
281 void ScCellValue::reset_to_empty()
283 suppress_fun_call_w_exception(maData = std::monostate()); // reset to empty;
286 ScCellValue::ScCellValue(ScCellValue&& r) noexcept
287 : maData(std::move(r.maData))
289 r.reset_to_empty();
292 ScCellValue::~ScCellValue()
294 clear();
297 CellType ScCellValue::getType() const
299 switch (maData.index())
301 case 0: return CELLTYPE_NONE;
302 case 1: return CELLTYPE_VALUE;
303 case 2: return CELLTYPE_STRING;
304 case 3: return CELLTYPE_EDIT;
305 case 4: return CELLTYPE_FORMULA;
306 default:
307 assert(false);
308 return CELLTYPE_NONE;
312 void ScCellValue::clear() noexcept
314 switch (getType())
316 case CELLTYPE_EDIT:
317 suppress_fun_call_w_exception(delete getEditText());
318 break;
319 case CELLTYPE_FORMULA:
320 suppress_fun_call_w_exception(delete getFormula());
321 break;
322 default:
326 // Reset to empty value.
327 reset_to_empty();
330 void ScCellValue::set( double fValue )
332 clear();
333 maData = fValue;
336 void ScCellValue::set( const svl::SharedString& rStr )
338 clear();
339 maData = rStr;
342 void ScCellValue::set( const EditTextObject& rEditText )
344 clear();
345 maData = rEditText.Clone().release();
348 void ScCellValue::set( std::unique_ptr<EditTextObject> xEditText )
350 clear();
351 maData = xEditText.release();
354 void ScCellValue::set( ScFormulaCell* pFormula )
356 clear();
357 maData = pFormula;
360 void ScCellValue::assign( const ScDocument& rDoc, const ScAddress& rPos )
362 clear();
364 ScRefCellValue aRefVal(const_cast<ScDocument&>(rDoc), rPos);
366 switch (aRefVal.getType())
368 case CELLTYPE_STRING:
369 maData = *aRefVal.getSharedString();
370 break;
371 case CELLTYPE_EDIT:
372 maData = aRefVal.getEditText() ? aRefVal.getEditText()->Clone().release() : static_cast<EditTextObject*>(nullptr);
373 break;
374 case CELLTYPE_VALUE:
375 maData = aRefVal.getDouble();
376 break;
377 case CELLTYPE_FORMULA:
378 maData = aRefVal.getFormula()->Clone();
379 break;
380 default: ; // leave empty
384 void ScCellValue::assign(const ScCellValue& rOther, ScDocument& rDestDoc, ScCloneFlags nCloneFlags)
386 clear();
388 switch (rOther.getType())
390 case CELLTYPE_STRING:
391 maData = rOther.maData;
392 break;
393 case CELLTYPE_EDIT:
395 // Switch to the pool of the destination document.
396 ScFieldEditEngine& rEngine = rDestDoc.GetEditEngine();
397 if (rOther.getEditText()->HasOnlineSpellErrors())
399 EEControlBits nControl = rEngine.GetControlWord();
400 const EEControlBits nSpellControl = EEControlBits::ONLINESPELLING | EEControlBits::ALLOWBIGOBJS;
401 bool bNewControl = ((nControl & nSpellControl) != nSpellControl);
402 if (bNewControl)
403 rEngine.SetControlWord(nControl | nSpellControl);
404 rEngine.SetTextCurrentDefaults(*rOther.getEditText());
405 maData = rEngine.CreateTextObject().release();
406 if (bNewControl)
407 rEngine.SetControlWord(nControl);
409 else
411 rEngine.SetTextCurrentDefaults(*rOther.getEditText());
412 maData = rEngine.CreateTextObject().release();
415 break;
416 case CELLTYPE_VALUE:
417 maData = rOther.maData;
418 break;
419 case CELLTYPE_FORMULA:
420 // Switch to the destination document.
421 maData = new ScFormulaCell(*rOther.getFormula(), rDestDoc, rOther.getFormula()->aPos, nCloneFlags);
422 break;
423 default: ; // leave empty
427 void ScCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
429 switch (getType())
431 case CELLTYPE_STRING:
433 ScSetStringParam aParam;
434 aParam.setTextInput();
435 rDoc.SetString(rPos, getSharedString()->getString(), &aParam);
437 break;
438 case CELLTYPE_EDIT:
439 rDoc.SetEditText(rPos, getEditText()->Clone());
440 break;
441 case CELLTYPE_VALUE:
442 rDoc.SetValue(rPos, getDouble());
443 break;
444 case CELLTYPE_FORMULA:
445 rDoc.SetFormulaCell(rPos, getFormula()->Clone());
446 break;
447 default:
448 rDoc.SetEmptyCell(rPos);
452 void ScCellValue::commit( ScColumn& rColumn, SCROW nRow ) const
454 commitToColumn(*this, rColumn, nRow);
457 void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
459 switch (getType())
461 case CELLTYPE_STRING:
463 // Currently, string cannot be placed without copying.
464 ScSetStringParam aParam;
465 aParam.setTextInput();
466 rDoc.SetString(rPos, getSharedString()->getString(), &aParam);
468 break;
469 case CELLTYPE_EDIT:
470 // Cell takes the ownership of the text object.
471 rDoc.SetEditText(rPos, std::unique_ptr<EditTextObject>(getEditText()));
472 break;
473 case CELLTYPE_VALUE:
474 rDoc.SetValue(rPos, getDouble());
475 break;
476 case CELLTYPE_FORMULA:
477 // This formula cell instance is directly placed in the document without copying.
478 rDoc.SetFormulaCell(rPos, getFormula());
479 break;
480 default:
481 rDoc.SetEmptyCell(rPos);
484 reset_to_empty(); // reset to empty
487 void ScCellValue::release( ScColumn& rColumn, SCROW nRow, sc::StartListeningType eListenType )
489 switch (getType())
491 case CELLTYPE_STRING:
493 // Currently, string cannot be placed without copying.
494 rColumn.SetRawString(nRow, *getSharedString());
496 break;
497 case CELLTYPE_EDIT:
498 // Cell takes the ownership of the text object.
499 rColumn.SetEditText(nRow, std::unique_ptr<EditTextObject>(getEditText()));
500 break;
501 case CELLTYPE_VALUE:
502 rColumn.SetValue(nRow, getDouble());
503 break;
504 case CELLTYPE_FORMULA:
505 // This formula cell instance is directly placed in the document without copying.
506 rColumn.SetFormulaCell(nRow, getFormula(), eListenType);
507 break;
508 default:
509 rColumn.DeleteContent(nRow);
512 reset_to_empty(); // reset to empty
515 OUString ScCellValue::getString( const ScDocument& rDoc ) const
517 return getStringImpl(*this, &rDoc);
520 bool ScCellValue::isEmpty() const
522 return getType() == CELLTYPE_NONE;
525 bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
527 return equalsWithoutFormatImpl(*this, r);
530 ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
532 ScCellValue aTmp(r);
533 swap(aTmp);
534 return *this;
537 ScCellValue& ScCellValue::operator=(ScCellValue&& rCell) noexcept
539 clear();
540 maData = std::move(rCell.maData);
541 rCell.reset_to_empty(); // reset to empty;
542 return *this;
545 ScCellValue& ScCellValue::operator= ( const ScRefCellValue& r )
547 ScCellValue aTmp(r);
548 swap(aTmp);
549 return *this;
552 void ScCellValue::swap( ScCellValue& r )
554 std::swap(maData, r.maData);
557 ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
558 ScRefCellValue::ScRefCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
559 ScRefCellValue::ScRefCellValue( const svl::SharedString* pString ) : meType(CELLTYPE_STRING), mpString(pString) {}
560 ScRefCellValue::ScRefCellValue( const EditTextObject* pEditText ) : meType(CELLTYPE_EDIT), mpEditText(pEditText) {}
561 ScRefCellValue::ScRefCellValue( ScFormulaCell* pFormula ) : meType(CELLTYPE_FORMULA), mpFormula(pFormula) {}
563 ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos )
565 assign( rDoc, rPos);
568 ScRefCellValue::ScRefCellValue( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
570 assign( rDoc, rPos, rBlockPos );
573 void ScRefCellValue::clear()
575 // Reset to empty value.
576 meType = CELLTYPE_NONE;
577 mfValue = 0.0;
580 void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
582 *this = rDoc.GetRefCellValue(rPos);
585 void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos, sc::ColumnBlockPosition& rBlockPos )
587 *this = rDoc.GetRefCellValue(rPos, rBlockPos);
590 void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
592 switch (meType)
594 case CELLTYPE_STRING:
596 ScSetStringParam aParam;
597 aParam.setTextInput();
598 rDoc.SetString(rPos, mpString->getString(), &aParam);
600 break;
601 case CELLTYPE_EDIT:
602 rDoc.SetEditText(rPos, ScEditUtil::Clone(*mpEditText, rDoc));
603 break;
604 case CELLTYPE_VALUE:
605 rDoc.SetValue(rPos, mfValue);
606 break;
607 case CELLTYPE_FORMULA:
608 rDoc.SetFormulaCell(rPos, new ScFormulaCell(*mpFormula, rDoc, rPos));
609 break;
610 default:
611 rDoc.SetEmptyCell(rPos);
615 bool ScRefCellValue::hasString() const
617 return hasStringImpl(meType, mpFormula);
620 bool ScRefCellValue::hasNumeric() const
622 return hasNumericImpl(meType, mpFormula);
625 bool ScRefCellValue::hasError() const
627 return meType == CELLTYPE_FORMULA && mpFormula->GetErrCode() != FormulaError::NONE;
630 double ScRefCellValue::getValue()
632 switch (meType)
634 case CELLTYPE_VALUE:
635 return mfValue;
636 case CELLTYPE_FORMULA:
637 return mpFormula->GetValue();
638 default:
641 return 0.0;
644 double ScRefCellValue::getRawValue() const
646 switch (meType)
648 case CELLTYPE_VALUE:
649 return mfValue;
650 case CELLTYPE_FORMULA:
651 return mpFormula->GetRawValue();
652 default:
655 return 0.0;
658 OUString ScRefCellValue::getString( const ScDocument* pDoc ) const
660 return getStringImpl(*this, pDoc);
663 svl::SharedString ScRefCellValue::getSharedString( const ScDocument* pDoc, svl::SharedStringPool& rStrPool ) const
665 switch (getType())
667 case CELLTYPE_VALUE:
668 return rStrPool.intern(OUString::number(getDouble()));
669 case CELLTYPE_STRING:
670 return *getSharedString();
671 case CELLTYPE_EDIT:
672 if (auto pEditText = getEditText())
673 return rStrPool.intern(ScEditUtil::GetString(*pEditText, pDoc));
674 break;
675 case CELLTYPE_FORMULA:
676 return getFormula()->GetString();
677 default:
680 return svl::SharedString::getEmptyString();
683 OUString ScRefCellValue::getRawString( const ScDocument& rDoc ) const
685 return getRawStringImpl(*this, rDoc);
688 bool ScRefCellValue::isEmpty() const
690 return meType == CELLTYPE_NONE;
693 bool ScRefCellValue::hasEmptyValue()
695 if (isEmpty())
696 return true;
698 if (meType == CELLTYPE_FORMULA)
699 return mpFormula->IsEmpty();
701 return false;
704 bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const
706 return equalsWithoutFormatImpl(*this, r);
709 bool ScRefCellValue::operator==( const ScRefCellValue& r ) const
711 if (meType != r.meType)
712 return false;
714 switch (meType)
716 case CELLTYPE_NONE:
717 return true;
718 case CELLTYPE_VALUE:
719 return mfValue == r.mfValue;
720 case CELLTYPE_STRING:
721 return mpString == r.mpString;
722 case CELLTYPE_FORMULA:
723 return equalsFormulaCells(getFormula(), r.getFormula());
724 default:
725 return false;
729 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */