summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-06-21 20:11:27 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-06-24 16:51:41 -0400
commit2c92a92e2fa2503f0381b89f316f982eda580b6e (patch)
treebf0345cbbad0edc93134b94135d05c78a323f755 /sc
parentcf02151987b19b12ca0be463732765bd35f54028 (diff)
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
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/dociter.hxx7
-rw-r--r--sc/source/core/data/dociter.cxx28
-rw-r--r--sc/source/core/data/documen8.cxx2
3 files changed, 32 insertions, 5 deletions
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index 2452a6083d93..9458aaef50ef 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 fb1becda12c2..3fa15cface43 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -1681,7 +1681,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");
@@ -1700,24 +1700,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 ec797f176215..4cbaf8d1be51 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