sc/inc/cell.hxx | 1 sc/inc/cellvalue.hxx | 56 ++++++ sc/inc/column.hxx | 1 sc/inc/document.hxx | 11 + sc/inc/table.hxx | 1 sc/source/core/data/cellvalue.cxx | 309 ++++++++++++++++++++++++++++---------- sc/source/core/data/column3.cxx | 12 + sc/source/core/data/document.cxx | 8 sc/source/core/data/table2.cxx | 7 9 files changed, 326 insertions(+), 80 deletions(-)
New commits: commit 0aa3d9c489effcc9ab01946ab9cea846bbab1c39 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Tue Mar 26 12:00:43 2013 -0400 Add ScRefCellValue, which is ScCellValue without copied value. It directly points to the original cell value instance. Change-Id: I638ec8b931873d237871b6d8fa9f0e1277520d0f diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx index 236ad43..0b78f98 100644 --- a/sc/inc/cell.hxx +++ b/sc/inc/cell.hxx @@ -175,6 +175,7 @@ public: inline void SetString( const rtl::OUString& rString ) { maString = rString; } inline const rtl::OUString& GetString() const { return maString; } + const OUString* GetStringPtr() const { return &maString; } private: rtl::OUString maString; diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx index 9dd3a9a..7998898 100644 --- a/sc/inc/cellvalue.hxx +++ b/sc/inc/cellvalue.hxx @@ -19,7 +19,8 @@ class ScBaseCell; /** * Store arbitrary cell value of any kind. It only stores cell value and - * nothing else. + * nothing else. It creates a copy of the original cell value, and manages + * the life cycle of the copied value. */ struct SC_DLLPUBLIC ScCellValue { @@ -78,6 +79,59 @@ struct SC_DLLPUBLIC ScCellValue void swap( ScCellValue& r ); }; +/** + * This is very similar to ScCellValue, except that it points to the + * original value instead of copying it. As such, don't hold an instance of + * this class any longer than necessary. + */ +struct SC_DLLPUBLIC ScRefCellValue +{ + CellType meType; + union { + double mfValue; + const OUString* mpString; + const EditTextObject* mpEditText; + ScFormulaCell* mpFormula; + }; + + ScRefCellValue(); + ScRefCellValue( double fValue ); + ScRefCellValue( const OUString* pString ); + ScRefCellValue( const EditTextObject* pEditText ); + ScRefCellValue( ScFormulaCell* pFormula ); + ScRefCellValue( const ScRefCellValue& r ); + ~ScRefCellValue(); + + void clear(); + + /** + * Take cell value from specified position in specified document. + */ + void assign( ScDocument& rDoc, const ScAddress& rPos ); + + /** + * TODO: Remove this later. + */ + void assign( ScBaseCell& rCell ); + + /** + * Set cell value at specified position in specified document. + */ + void commit( ScDocument& rDoc, const ScAddress& rPos ) const; + + bool hasString() const; + + bool hasNumeric() const; + + bool isEmpty() const; + + bool equalsWithoutFormat( const ScRefCellValue& r ) const; + + ScRefCellValue& operator= ( const ScRefCellValue& r ); + + void swap( ScRefCellValue& r ); +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index f25dc78..ac329b2 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -272,6 +272,7 @@ public: void SetError( SCROW nRow, const sal_uInt16 nError); void GetString( SCROW nRow, rtl::OUString& rString ) const; + const OUString* GetStringCell( SCROW nRow ) const; void GetInputString( SCROW nRow, rtl::OUString& rString ) const; double GetValue( SCROW nRow ) const; const EditTextObject* GetEditText( SCROW nRow ) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 70c5620..892d18f 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -802,6 +802,17 @@ public: SC_DLLPUBLIC OUString GetString( SCCOL nCol, SCROW nRow, SCTAB nTab ) const; OUString GetString( const ScAddress& rPos ) const; + + /** + * Return a pointer to the string object stored in string cell. + * + * @param rPos cell position. + * + * @return pointer to the string object stored in string cell, or NULL if + * the cell at specified position is not a string cell. Note that + * it returns NULL even for a edit cell. + */ + const OUString* GetStringCell( const ScAddress& rPos ) const; SC_DLLPUBLIC void GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString ); SC_DLLPUBLIC void GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, rtl::OUString& rString ); sal_uInt16 GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString ); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 461da522..0a12ead 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -318,6 +318,7 @@ public: void SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError); void GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const; + const OUString* GetStringCell( SCCOL nCol, SCROW nRow ) const; void GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const; double GetValue( const ScAddress& rPos ) const { diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx index 8b0baa4..5b853a3 100644 --- a/sc/source/core/data/cellvalue.cxx +++ b/sc/source/core/data/cellvalue.cxx @@ -16,6 +16,121 @@ #include "editutil.hxx" #include "formula/token.hxx" +namespace { + +CellType adjustCellType( CellType eOrig ) +{ + switch (eOrig) + { + case CELLTYPE_NOTE: + return CELLTYPE_NONE; + case CELLTYPE_EDIT: + return CELLTYPE_STRING; + default: + ; + } + return eOrig; +} + +template<typename _T> +OUString getString( const _T& rVal ) +{ + if (rVal.meType == CELLTYPE_STRING) + return *rVal.mpString; + + if (rVal.meType == CELLTYPE_EDIT) + { + OUStringBuffer aRet; + size_t n = rVal.mpEditText->GetParagraphCount(); + for (size_t i = 0; i < n; ++i) + { + if (i > 0) + aRet.append('\n'); + aRet.append(rVal.mpEditText->GetText(i)); + } + return aRet.makeStringAndClear(); + } + + return EMPTY_OUSTRING; +} + +bool equalsFormulaCells( const ScFormulaCell* p1, const ScFormulaCell* p2 ) +{ + const ScTokenArray* pCode1 = p1->GetCode(); + const ScTokenArray* pCode2 = p2->GetCode(); + + if (pCode1->GetLen() != pCode2->GetLen()) + return false; + + sal_uInt16 n = pCode1->GetLen(); + formula::FormulaToken** ppToken1 = pCode1->GetArray(); + formula::FormulaToken** ppToken2 = pCode2->GetArray(); + for (sal_uInt16 i = 0; i < n; ++i) + { + if (!ppToken1[i]->TextEqual(*(ppToken2[i]))) + return false; + } + + return true; +} + +template<typename _T> +bool equalsWithoutFormatImpl( const _T& left, const _T& right ) +{ + CellType eType1 = adjustCellType(left.meType); + CellType eType2 = adjustCellType(right.meType); + if (eType1 != eType2) + return false; + + switch (eType1) + { + case CELLTYPE_NONE: + return true; + case CELLTYPE_VALUE: + return left.mfValue == right.mfValue; + case CELLTYPE_STRING: + { + OUString aStr1 = getString(left); + OUString aStr2 = getString(right); + return aStr1 == aStr2; + } + case CELLTYPE_FORMULA: + return equalsFormulaCells(left.mpFormula, right.mpFormula); + default: + ; + } + return false; +} + +bool hasStringImpl( CellType eType, ScFormulaCell* pFormula ) +{ + switch (eType) + { + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + return true; + case CELLTYPE_FORMULA: + return !pFormula->IsValue(); + default: + return false; + } +} + +bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula ) +{ + switch (eType) + { + case CELLTYPE_VALUE: + return true; + case CELLTYPE_FORMULA: + return pFormula->IsValue(); + default: + return false; + } +} + +} + ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {} ScCellValue::ScCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {} ScCellValue::ScCellValue( const OUString& rString ) : meType(CELLTYPE_STRING), mpString(new OUString(rString)) {} @@ -223,29 +338,12 @@ void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos ) bool ScCellValue::hasString() const { - switch (meType) - { - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - return true; - case CELLTYPE_FORMULA: - return !mpFormula->IsValue(); - default: - return false; - } + return hasStringImpl(meType, mpFormula); } bool ScCellValue::hasNumeric() const { - switch (meType) - { - case CELLTYPE_VALUE: - return true; - case CELLTYPE_FORMULA: - return mpFormula->IsValue(); - default: - return false; - } + return hasNumericImpl(meType, mpFormula); } bool ScCellValue::isEmpty() const @@ -253,97 +351,150 @@ bool ScCellValue::isEmpty() const return meType == CELLTYPE_NOTE || meType == CELLTYPE_NONE; } -namespace { +bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const +{ + return equalsWithoutFormatImpl(*this, r); +} -CellType adjustCellType( CellType eOrig ) +ScCellValue& ScCellValue::operator= ( const ScCellValue& r ) { - switch (eOrig) + ScCellValue aTmp(r); + swap(aTmp); + return *this; +} + +void ScCellValue::swap( ScCellValue& r ) +{ + std::swap(meType, r.meType); + + // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on + // the platform. Swap by double values. + std::swap(mfValue, r.mfValue); +} + +ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {} +ScRefCellValue::ScRefCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {} +ScRefCellValue::ScRefCellValue( const OUString* pString ) : meType(CELLTYPE_STRING), mpString(pString) {} +ScRefCellValue::ScRefCellValue( const EditTextObject* pEditText ) : meType(CELLTYPE_EDIT), mpEditText(pEditText) {} +ScRefCellValue::ScRefCellValue( ScFormulaCell* pFormula ) : meType(CELLTYPE_FORMULA), mpFormula(pFormula) {} + +// It should be enough to copy the double value, which is at least as large +// as the pointer values. +ScRefCellValue::ScRefCellValue( const ScRefCellValue& r ) : meType(r.meType), mfValue(r.mfValue) {} + +ScRefCellValue::~ScRefCellValue() +{ + clear(); +} + +void ScRefCellValue::clear() +{ + // Reset to empty value. + meType = CELLTYPE_NONE; + mfValue = 0.0; +} + +void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos ) +{ + clear(); + + meType = rDoc.GetCellType(rPos); + switch (meType) { - case CELLTYPE_NOTE: - return CELLTYPE_NONE; + case CELLTYPE_STRING: + mpString = rDoc.GetStringCell(rPos); + break; case CELLTYPE_EDIT: - return CELLTYPE_STRING; + mpEditText = rDoc.GetEditText(rPos); + break; + case CELLTYPE_VALUE: + mfValue = rDoc.GetValue(rPos); + break; + case CELLTYPE_FORMULA: + mpFormula = rDoc.GetFormulaCell(rPos); + break; default: - ; + meType = CELLTYPE_NONE; // reset to empty. } - return eOrig; } -OUString getString( const ScCellValue& rVal ) +void ScRefCellValue::assign( ScBaseCell& rCell ) { - if (rVal.meType == CELLTYPE_STRING) - return *rVal.mpString; + clear(); - if (rVal.meType == CELLTYPE_EDIT) + meType = rCell.GetCellType(); + switch (meType) { - OUStringBuffer aRet; - size_t n = rVal.mpEditText->GetParagraphCount(); - for (size_t i = 0; i < n; ++i) - { - if (i > 0) - aRet.append('\n'); - aRet.append(rVal.mpEditText->GetText(i)); - } - return aRet.makeStringAndClear(); + case CELLTYPE_STRING: + mpString = static_cast<const ScStringCell&>(rCell).GetStringPtr(); + break; + case CELLTYPE_EDIT: + mpEditText = static_cast<const ScEditCell&>(rCell).GetData(); + break; + case CELLTYPE_VALUE: + mfValue = static_cast<const ScValueCell&>(rCell).GetValue(); + break; + case CELLTYPE_FORMULA: + mpFormula = static_cast<ScFormulaCell*>(&rCell); + break; + default: + meType = CELLTYPE_NONE; // reset to empty. } - - return EMPTY_OUSTRING; } -} - -bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const +void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const { - CellType eType1 = adjustCellType(meType); - CellType eType2 = adjustCellType(r.meType); - if (eType1 != eType2) - return false; - switch (meType) { - case CELLTYPE_NONE: - return true; - case CELLTYPE_VALUE: - return mfValue == r.mfValue; case CELLTYPE_STRING: { - OUString aStr1 = getString(*this); - OUString aStr2 = getString(r); - return aStr1 == aStr2; + ScSetStringParam aParam; + aParam.setTextInput(); + rDoc.SetString(rPos, *mpString, &aParam); } + break; + case CELLTYPE_EDIT: + rDoc.SetEditText(rPos, mpEditText->Clone()); + break; + case CELLTYPE_VALUE: + rDoc.SetValue(rPos, mfValue); + break; case CELLTYPE_FORMULA: - { - ScTokenArray* pCode1 = mpFormula->GetCode(); - ScTokenArray* pCode2 = r.mpFormula->GetCode(); + rDoc.SetFormulaCell(rPos, mpFormula->Clone()); + break; + default: + rDoc.SetEmptyCell(rPos); + } +} - if (pCode1->GetLen() != pCode2->GetLen()) - return false; +bool ScRefCellValue::hasString() const +{ + return hasStringImpl(meType, mpFormula); +} - sal_uInt16 n = pCode1->GetLen(); - formula::FormulaToken** ppToken1 = pCode1->GetArray(); - formula::FormulaToken** ppToken2 = pCode2->GetArray(); - for (sal_uInt16 i = 0; i < n; ++i) - { - if (!ppToken1[i]->TextEqual(*(ppToken2[i]))) - return false; - } +bool ScRefCellValue::hasNumeric() const +{ + return hasNumericImpl(meType, mpFormula); +} - return true; - } - default: - ; - } - return false; +bool ScRefCellValue::isEmpty() const +{ + return meType == CELLTYPE_NOTE || meType == CELLTYPE_NONE; } -ScCellValue& ScCellValue::operator= ( const ScCellValue& r ) +bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const { - ScCellValue aTmp(r); + return equalsWithoutFormatImpl(*this, r); +} + +ScRefCellValue& ScRefCellValue::operator= ( const ScRefCellValue& r ) +{ + ScRefCellValue aTmp(r); swap(aTmp); return *this; } -void ScCellValue::swap( ScCellValue& r ) +void ScRefCellValue::swap( ScRefCellValue& r ) { std::swap(meType, r.meType); diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 3297b88..3a591cd 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -1758,6 +1758,18 @@ void ScColumn::GetString( SCROW nRow, rtl::OUString& rString ) const rString = rtl::OUString(); } +const OUString* ScColumn::GetStringCell( SCROW nRow ) const +{ + SCSIZE nIndex; + if (!Search(nRow, nIndex)) + return NULL; + + const ScBaseCell* pCell = maItems[nIndex].pCell; + if (pCell->GetCellType() != CELLTYPE_STRING) + return NULL; + + return static_cast<const ScStringCell*>(pCell)->GetStringPtr(); +} void ScColumn::GetInputString( SCROW nRow, rtl::OUString& rString ) const { diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 6ebbf39..1603d23 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -3053,6 +3053,14 @@ OUString ScDocument::GetString( const ScAddress& rPos ) const return aStr; } +const OUString* ScDocument::GetStringCell( const ScAddress& rPos ) const +{ + if (!TableExists(rPos.Tab())) + return NULL; + + return maTabs[rPos.Tab()]->GetStringCell(rPos.Col(), rPos.Row()); +} + void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString ) { if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] ) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index f6d34c2..319226f 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1404,6 +1404,13 @@ void ScTable::GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const rString = rtl::OUString(); } +const OUString* ScTable::GetStringCell( SCCOL nCol, SCROW nRow ) const +{ + if (!ValidColRow(nCol,nRow)) + return NULL; + + return aCol[nCol].GetStringCell(nRow); +} void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits