diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-03-22 09:47:11 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2014-03-22 09:51:41 -0400 |
commit | 474b2ea601f7fa2f1fbeae0f169ff5b8abc965be (patch) | |
tree | 589ec5ed81f8450057c5d84070e271871d37b879 /sc | |
parent | c78d1bb2cd98aeac64402caf7baa40cbe4cca6f9 (diff) |
fdo#76470: Avoid joining new formula cells individually.
Instead, insert the formula cells in the group first, then only try to join
the top and bottom cells afterward. Otherwise the grouping would get messed
up and a problem would ensue.
Change-Id: I4fdd5326c029032a636d8225b5fb16cbde427c7d
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 3 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/table.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 21 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 69 | ||||
-rw-r--r-- | sc/source/core/data/documen2.cxx | 12 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 8 |
7 files changed, 113 insertions, 4 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index c9e97572de65..a84f83612b47 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -299,6 +299,8 @@ public: ScFormulaCell* SetFormulaCell( SCROW nRow, ScFormulaCell* pCell ); ScFormulaCell* SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, ScFormulaCell* pCell ); + bool SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells ); + void CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges ); svl::SharedString GetSharedString( SCROW nRow ) const; @@ -570,6 +572,7 @@ private: sc::CellStoreType::iterator GetPositionToInsert( const sc::CellStoreType::iterator& it, SCROW nRow ); void ActivateNewFormulaCell( const sc::CellStoreType::iterator& itPos, SCROW nRow, ScFormulaCell& rCell, bool bJoin = true ); void ActivateNewFormulaCell( const sc::CellStoreType::position_type& aPos, ScFormulaCell& rCell, bool bJoin = true ); + void AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ); void BroadcastNewCell( SCROW nRow ); bool UpdateScriptType( sc::CellTextAttr& rAttr, SCROW nRow, sc::CellStoreType::iterator& itr ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 05afc1c87a5d..becca934745a 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -844,6 +844,8 @@ public: */ SC_DLLPUBLIC ScFormulaCell* SetFormulaCell( const ScAddress& rPos, ScFormulaCell* pCell ); + bool SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells ); + SC_DLLPUBLIC void InsertMatrixFormula(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark, diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index ce58c206558c..59a8f58d8b28 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -347,6 +347,8 @@ public: */ ScFormulaCell* SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* pCell ); + bool SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells ); + svl::SharedString GetSharedString( SCCOL nCol, SCROW nRow ) const; void SetValue( SCCOL nCol, SCROW nRow, const double& rVal ); diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 9694790886f7..5c196a01c60b 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -43,6 +43,7 @@ #include "refupdatecontext.hxx" #include <listenercontext.hxx> #include <refhint.hxx> +#include <stlalgorithm.hxx> #include <svl/poolcach.hxx> #include <svl/zforlist.hxx> @@ -2561,21 +2562,33 @@ class UpdateRefOnNonCopy : std::unary_function<FormulaGroup, void> void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode ) { - if (!mpUndoDoc) + if (!mpUndoDoc || nLength <= 0) return; // Insert the old formula group into the undo document. ScAddress aUndoPos = rOldPos; ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, rOldCode.Clone()); - ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false); - mpUndoDoc->SetFormulaCell(aUndoPos, pFC); + if (nLength == 1) + { + mpUndoDoc->SetFormulaCell(aUndoPos, pFC); + return; + } + + std::vector<ScFormulaCell*> aCells; + aCells.reserve(nLength); + ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false); + aCells.push_back(pFC); aUndoPos.IncRow(); for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow()) { pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup); - mpUndoDoc->SetFormulaCell(aUndoPos, pFC); + aCells.push_back(pFC); } + + if (!mpUndoDoc->SetFormulaCells(rOldPos, aCells)) + // Insertion failed. Delete all formula cells. + std::for_each(aCells.begin(), aCells.end(), ScDeleteObjectByPtr<ScFormulaCell>()); } public: diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 40b0729d875d..30168164b776 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -46,6 +46,7 @@ #include "scopetools.hxx" #include "editutil.hxx" #include "sharedformula.hxx" +#include <listenercontext.hxx> #include <com/sun/star/i18n/LocaleDataItem.hpp> @@ -413,6 +414,40 @@ void ScColumn::ActivateNewFormulaCell( } } +void ScColumn::AttachNewFormulaCells( const sc::CellStoreType::position_type& aPos, size_t nLength ) +{ + // Make sure the whole length consists of formula cells. + if (aPos.first->type != sc::element_type_formula) + return; + + if (aPos.first->size < aPos.second + nLength) + // Block is shorter than specified length. + return; + + // Join the top and bottom cells only. + ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second); + JoinNewFormulaCell(aPos, *pCell); + + sc::CellStoreType::position_type aPosLast = aPos; + aPosLast.second += nLength - 1; + pCell = sc::formula_block::at(*aPosLast.first->data, aPosLast.second); + JoinNewFormulaCell(aPosLast, *pCell); + + if (!pDocument->IsClipOrUndo() && !pDocument->IsInsertingFromOtherDoc()) + { + sc::StartListeningContext aCxt(*pDocument); + ScFormulaCell** pp = &sc::formula_block::at(*aPos.first->data, aPos.second); + ScFormulaCell** ppEnd = pp + nLength; + for (; pp != ppEnd; ++pp) + { + pCell = *pp; + pCell->StartListeningTo(aCxt); + if (!pDocument->IsCalcingAfterLoad()) + pCell->SetDirty(); + } + } +} + void ScColumn::BroadcastNewCell( SCROW nRow ) { // When we insert from the Clipboard we still have wrong (old) References! @@ -1797,6 +1832,40 @@ ScFormulaCell* ScColumn::SetFormulaCell( sc::ColumnBlockPosition& rBlockPos, SCR return pCell; } +bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells ) +{ + if (!ValidRow(nRow)) + return false; + + SCROW nEndRow = nRow + rCells.size() - 1; + if (!ValidRow(nEndRow)) + return false; + + sc::CellStoreType::position_type aPos = maCells.position(nRow); + + // Detach all formula cells that will be overwritten. + DetachFormulaCells(aPos, rCells.size()); + + for (size_t i = 0, n = rCells.size(); i < n; ++i) + { + SCROW nThisRow = nRow + i; + sal_uInt32 nFmt = GetNumberFormat(nThisRow); + if ((nFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0) + rCells[i]->SetNeedNumberFormat(true); + } + + std::vector<sc::CellTextAttr> aDefaults(rCells.size(), sc::CellTextAttr()); + maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end()); + + sc::CellStoreType::iterator it = maCells.set(aPos.first, nRow, rCells.begin(), rCells.end()); + + CellStorageModified(); + + AttachNewFormulaCells(aPos, rCells.size()); + + return true; +} + svl::SharedString ScColumn::GetSharedString( SCROW nRow ) const { sc::CellStoreType::const_position_type aPos = maCells.position(nRow); diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 88775f88be5a..745bc24aa9a4 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -1104,6 +1104,18 @@ ScFormulaCell* ScDocument::SetFormulaCell( const ScAddress& rPos, ScFormulaCell* return maTabs[rPos.Tab()]->SetFormulaCell(rPos.Col(), rPos.Row(), pCell); } +bool ScDocument::SetFormulaCells( const ScAddress& rPos, std::vector<ScFormulaCell*>& rCells ) +{ + if (rCells.empty()) + return false; + + ScTable* pTab = FetchTable(rPos.Tab()); + if (!pTab) + return false; + + return pTab->SetFormulaCells(rPos.Col(), rPos.Row(), rCells); +} + void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData ) { delete pConsolidateDlgData; diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index b4d66562c6a8..c4ceabc4258b 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1412,6 +1412,14 @@ ScFormulaCell* ScTable::SetFormulaCell( SCCOL nCol, SCROW nRow, ScFormulaCell* p return aCol[nCol].SetFormulaCell(nRow, pCell); } +bool ScTable::SetFormulaCells( SCCOL nCol, SCROW nRow, std::vector<ScFormulaCell*>& rCells ) +{ + if (!ValidCol(nCol)) + return false; + + return aCol[nCol].SetFormulaCells(nRow, rCells); +} + svl::SharedString ScTable::GetSharedString( SCCOL nCol, SCROW nRow ) const { if (!ValidColRow(nCol, nRow)) |