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