sc/inc/dociter.hxx | 7 +++++++ sc/source/core/data/dociter.cxx | 28 +++++++++++++++++++++++----- sc/source/core/data/documen8.cxx | 2 ++ sc/source/core/data/fillinfo.cxx | 18 ++++++++++-------- 4 files changed, 42 insertions(+), 13 deletions(-)
New commits: commit 38afe6ebddcc54534930941c936437b508a2ca47 Author: Kohei Yoshida <[email protected]> Date: Fri Jun 21 20:11:27 2013 -0400 Prevent crash during on-line spell checking. The new ScHorizontalCellIterator internally uses iterators for each column to track positions. This means that, if a cell value in the iteration range chnages while the iteration is on-going, those internal iterators get invalidated. Allow the client code to rehash the iterators when modifying a cell content during iteration. Having said that, it's best not to modify cells during iteration. Change-Id: Ida453d4f883e1fbcbab4eb0401e37fea8c0b901d diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx index 2452a60..9458aae 100644 --- a/sc/inc/dociter.hxx +++ b/sc/inc/dociter.hxx @@ -441,6 +441,13 @@ public: /// Set a(nother) sheet and (re)init. void SetTab( SCTAB nTab ); + /** + * When modifying a cell while still in iteration, call this to re-fetch + * the column iterators used internally because the old iterators have + * been invalidated. + */ + void RehashCol( SCCOL nCol ); + private: void Advance(); }; diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx index 9c24aae..1cdc52c 100644 --- a/sc/source/core/data/dociter.cxx +++ b/sc/source/core/data/dociter.cxx @@ -1695,7 +1695,7 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nEndRow( nRow2 ), mnCol( nCol1 ), mnRow( nRow1 ), - bMore( true ) + bMore(false) { if (mnTab >= pDoc->GetTableCount()) OSL_FAIL("try to access index out of bounds, FIX IT"); @@ -1714,24 +1714,42 @@ ScHorizontalCellIterator::~ScHorizontalCellIterator() void ScHorizontalCellIterator::SetTab( SCTAB nTabP ) { + bMore = false; mnTab = nTabP; mnRow = nStartRow; mnCol = nStartCol; - bMore = true; // Set the start position in each column. for (SCCOL i = nStartCol; i <= nEndCol; ++i) { ScColumn* pCol = &pDoc->maTabs[mnTab]->aCol[i]; - maColPositions[i-nStartCol].maPos = pCol->maCells.position(nStartRow).first; - maColPositions[i-nStartCol].maEnd = pCol->maCells.end(); + ColParam& rParam = maColPositions[i-nStartCol]; + rParam.maPos = pCol->maCells.position(nStartRow).first; + rParam.maEnd = pCol->maCells.end(); + if (rParam.maPos != rParam.maEnd) + bMore = true; } - if (maColPositions[0].maPos->type == sc::element_type_empty) + if (!bMore) + return; + + ColParam& rParam = maColPositions[0]; + if (rParam.maPos == rParam.maEnd || rParam.maPos->type == sc::element_type_empty) // Skip to the first non-empty cell. Advance(); } +void ScHorizontalCellIterator::RehashCol( SCCOL nCol ) +{ + if (nCol < nStartCol || nEndCol < nCol) + return; + + ColParam& rParam = maColPositions[nCol-nStartCol]; + ScColumn& rCol = pDoc->maTabs[mnTab]->aCol[nCol]; + rParam.maPos = rCol.maCells.position(mnRow).first; + rParam.maEnd = rCol.maCells.end(); +} + ScRefCellValue* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow ) { if (!bMore) diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 570a14c..4c64c45 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -827,12 +827,14 @@ bool ScDocument::OnlineSpellInRange( const ScRange& rSpellRange, ScAddress& rSpe { // The cell will take ownership of pNewData. SetEditText(ScAddress(nCol,nRow,nTab), pEngine->CreateTextObject()); + aIter.RehashCol(nCol); } else { ScSetStringParam aParam; aParam.setTextInput(); SetString(ScAddress(nCol,nRow,nTab), pEngine->GetText(), &aParam); + aIter.RehashCol(nCol); } // Paint commit d873f62d49c61a7943dd6ea2ade9d3549ce5a965 Author: Kohei Yoshida <[email protected]> Date: Fri Jun 21 18:05:46 2013 -0400 Fix my wrong logic in row info iteration. Align the array position of RowInfo by comparing its nRowNo value with the current row number. Change-Id: Idd26636cac0ba4ade1b538dd68580b469611da04 diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 34c2562..5f9b6ce 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -145,8 +145,16 @@ class RowInfoFiller return mbHiddenRow; } - void setInfo(size_t /*nRow*/, const ScRefCellValue& rCell) + void alignArray(size_t nRow) { + while (mpRowInfo[mrArrY].nRowNo < static_cast<SCROW>(nRow)) + ++mrArrY; + } + + void setInfo(size_t nRow, const ScRefCellValue& rCell) + { + alignArray(nRow); + RowInfo* pThisRowInfo = &mpRowInfo[mrArrY]; CellInfo* pInfo = &pThisRowInfo->pCellInfo[mnArrX]; pInfo->maCell = rCell; @@ -183,12 +191,6 @@ public: if (!isHidden(nRow)) setInfo(nRow, ScRefCellValue(const_cast<ScFormulaCell*>(p))); } - - void operator() (mdds::mtv::element_t, size_t, size_t nDataSize) - { - // Skip all empty cells. - mrArrY += nDataSize; - } }; } @@ -430,7 +432,7 @@ void ScDocument::FillInfo( // cells that are not hidden. RowInfoFiller aFunc(*this, nTab, pRowInfo, nArrCol, nArrRow); sc::ParseAllNonEmpty( - pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc, aFunc); + pThisCol->maCells.begin(), pThisCol->maCells, nRow1, nRow2, aFunc); if (nX+1 >= nCol1) // Attribute/Blockmarken ab nX1-1 { _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
