sc/inc/column.hxx | 8 + sc/source/core/data/column.cxx | 25 ++- sc/source/core/data/column2.cxx | 21 ++ sc/source/core/data/column3.cxx | 292 +++++++++++++++++++--------------------- 4 files changed, 189 insertions(+), 157 deletions(-)
New commits: commit 5b1d9145acd9dcb4d364f0bdc865c0464b3cdc80 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Mar 15 02:55:09 2013 -0400 Delete cell segments using reverse iterator (as TODO comment said). This makes it much simpler, and less error-prone. Change-Id: I21dbe0d2bb4a71fc2ac738a5ffb03e4d959d91a5 diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index f09367b..6116780 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -165,12 +165,12 @@ void ScColumn::Delete( SCROW nRow ) { pNoteCell->Delete(); maItems.erase( maItems.begin() + nIndex); + maTextWidths.set_empty(nRow, nRow); // Should we free memory here (delta)? It'll be slower! } pCell->EndListeningTo( pDocument ); pCell->Delete(); - maTextWidths.set_empty(nRow, nRow); CellStorageModified(); } } @@ -360,9 +360,6 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ScHint aHint( SC_HINT_DYING, ScAddress( nCol, 0, nTab ), 0 ); - SCROW nStartRow = maItems[nStartIndex].nRow; - SCROW nEndRow = maItems[nEndIndex].nRow; - // cache all formula cells, they will be deleted at end of this function typedef ::std::vector< ScFormulaCell* > FormulaCellVector; FormulaCellVector aDelCells; @@ -471,50 +468,40 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe if (nFirst <= nEndIndex) aRemovedSegments.insert_back(nFirst, nEndIndex + 1, true); - // Remove segments from the column array, containing pDummyCell and formula - // cell pointers to be deleted. - { // own scope for variables - RemovedSegments_t::const_iterator aIt(aRemovedSegments.begin()); - RemovedSegments_t::const_iterator aEnd(aRemovedSegments.end()); - // The indexes in aRemovedSegments denote cell positions in the - // original array. But as we are shifting it from the left, we have - // to compensate for already performed shifts for latter segments. - // TODO: use reverse iterators instead - SCSIZE nShift(0); - SCSIZE nStartSegment(nStartIndex); - bool bRemoved = false; - for (;aIt != aEnd; ++aIt) + { + // Remove segments from the column array, containing pDummyCell and + // formula cell pointers to be deleted. + + RemovedSegments_t::const_reverse_iterator it = aRemovedSegments.rbegin(); + RemovedSegments_t::const_reverse_iterator itEnd = aRemovedSegments.rend(); + + std::vector<ColEntry>::iterator itErase, itEraseEnd; + SCSIZE nEndSegment = it->first; // should equal maItems.size(). Non-inclusive. + // Skip the first node. + for (++it; it != itEnd; ++it) { - if (aIt->second) + if (!it->second) { - // this segment removed - if (!bRemoved) - nStartSegment = aIt->first; - // The first of removes in a row sets start (they should be - // alternating removed/notremoved anyway). - bRemoved = true; + // Don't remove this segment. + nEndSegment = it->first; continue; } - if (bRemoved) - { - // this segment not removed, but previous segment(s) removed, move tail. - SCSIZE const nEndSegment(aIt->first); - memmove( - &maItems[nStartSegment - nShift], - &maItems[nEndSegment - nShift], - (maItems.size() - nEndSegment) * sizeof(ColEntry)); - nShift += nEndSegment - nStartSegment; - bRemoved = false; - } + // Remove this segment. + SCSIZE nStartSegment = it->first; + SCROW nStartRow = maItems[nStartSegment].nRow; + SCROW nEndRow = maItems[nEndSegment-1].nRow; + + itErase = maItems.begin(); + std::advance(itErase, nStartSegment); + itEraseEnd = maItems.begin(); + std::advance(itEraseEnd, nEndSegment); + maItems.erase(itErase, itEraseEnd); + + maTextWidths.set_empty(nStartRow, nEndRow); + + nEndSegment = nStartSegment; } - // The last removed segment up to aItems.size() is discarded, there's - // nothing following to be moved. - if (bRemoved) - nShift += maItems.size() - nStartSegment; - maItems.erase(maItems.end() - nShift, maItems.end()); - maTextWidths.set_empty(nStartRow, nEndRow); - CellStorageModified(); } // *** delete all formula cells *** @@ -1666,8 +1653,8 @@ void ScColumn::RemoveProtected( SCROW nStartRow, SCROW nEndRow ) } delete pFormula; - CellStorageModified(); SetTextWidth(maItems[nIndex].nRow, TEXTWIDTH_DIRTY); + CellStorageModified(); } ++nIndex; } commit da91c606cb9de7ffb998ae46a0ba60cba855e3ac Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Mar 15 02:03:19 2013 -0400 Don't forget to set text widths here too. Change-Id: Ieaa9bd0e4f8117e3bc7ceccc68d6f37daac61440 diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index e778f96..a53c8a8 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -879,12 +879,12 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) { // remove ColEntry at old position maItems.erase( maItems.begin() + nIndex1 ); + maTextWidths.set_empty(nRow1, nRow1); } // Empty text width at the cell 1 position. For now, we don't // transfer the old value to the cell 2 position since Insert() is // quite complicated. - maTextWidths.set_empty(nRow1, nRow1); CellStorageModified(); // insert ColEntry at new position. @@ -1284,6 +1284,7 @@ void ScColumn::CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol itEnd = std::find_if(it, rDestCol.maItems.end(), FindAboveRow(nRow2)); std::for_each(it, itEnd, DeleteCell()); rDestCol.maItems.erase(it, itEnd); + rDestCol.maTextWidths.set_empty(nRow1, nRow2); } // Determine the range of cells in the original column that need to be copied. @@ -1351,6 +1352,10 @@ void ScColumn::CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol // destination column shouldn't have any cells within the specified range. it = std::find_if(rDestCol.maItems.begin(), rDestCol.maItems.end(), FindAboveRow(nRow2)); rDestCol.maItems.insert(it, aCopied.begin(), aCopied.end()); + it = aCopied.begin(); + itEnd = aCopied.end(); + for (; it != itEnd; ++it) + rDestCol.maTextWidths.set<unsigned short>(it->nRow, TEXTWIDTH_DIRTY); } void ScColumn::CopyToColumn( commit 8d0e982a80aabcd10e02a4cce20cc603e8c33ad8 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Mar 15 00:54:12 2013 -0400 Move some of the code to local functions to make it easier to read. Change-Id: Ib7ca5c04ec057dbce958d580ad3b7d52d19ed21f diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index baaaacd..f09367b 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -303,6 +303,53 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize ) pDocument->SetAutoCalc( bOldAutoCalc ); } +namespace { + +bool isDate(const ScDocument& rDoc, const ScColumn& rCol, SCROW nRow) +{ + sal_uLong nIndex = (sal_uLong)((SfxUInt32Item*)rCol.GetAttr(nRow, ATTR_VALUE_FORMAT))->GetValue(); + short nType = rDoc.GetFormatTable()->GetType(nIndex); + return (nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME); +} + +bool checkDeleteCellByFlag( + CellType eCellType, sal_uInt16 nDelFlag, const ScDocument& rDoc, const ScColumn& rCol, const ColEntry& rEntry) +{ + bool bDelete = false; + + switch (eCellType) + { + case CELLTYPE_VALUE: + { + sal_uInt16 nValFlags = nDelFlag & (IDF_DATETIME|IDF_VALUE); + // delete values and dates? + bDelete = nValFlags == (IDF_DATETIME|IDF_VALUE); + // if not, decide according to cell number format + if (!bDelete && (nValFlags != 0)) + { + bool bIsDate = isDate(rDoc, rCol, rEntry.nRow); + bDelete = nValFlags == (bIsDate ? IDF_DATETIME : IDF_VALUE); + } + } + break; + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + bDelete = (nDelFlag & IDF_STRING) != 0; + break; + case CELLTYPE_FORMULA: + bDelete = (nDelFlag & IDF_FORMULA) != 0; + break; + case CELLTYPE_NOTE: + // do note delete note cell with broadcaster + bDelete = !rEntry.pCell->GetBroadcaster(); + break; + default:; // added to avoid warnings + } + + return bDelete; +} + +} void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDelFlag ) { @@ -323,7 +370,7 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe typedef mdds::flat_segment_tree<SCSIZE, bool> RemovedSegments_t; RemovedSegments_t aRemovedSegments(nStartIndex, maItems.size(), false); - SCSIZE nFirst(nStartIndex); + SCSIZE nFirst = nStartIndex; // dummy replacement for old cells, to prevent that interpreter uses old cell boost::scoped_ptr<ScNoteCell> pDummyCell(new ScNoteCell); @@ -357,57 +404,27 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe ScBaseCell* pOldCell = maItems[nIdx].pCell; CellType eCellType = pOldCell->GetCellType(); if ((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS) + // All cell types to be deleted. bDelete = true; else { - // decide whether to delete the cell object according to passed - // flags - switch ( eCellType ) - { - case CELLTYPE_VALUE: - { - sal_uInt16 nValFlags = nDelFlag & (IDF_DATETIME|IDF_VALUE); - // delete values and dates? - bDelete = nValFlags == (IDF_DATETIME|IDF_VALUE); - // if not, decide according to cell number format - if (!bDelete && (nValFlags != 0)) - { - sal_uLong nIndex = (sal_uLong)((SfxUInt32Item*)GetAttr( - maItems[nIdx].nRow, ATTR_VALUE_FORMAT))->GetValue(); - short nType = pDocument->GetFormatTable()->GetType(nIndex); - bool bIsDate = (nType == NUMBERFORMAT_DATE) || - (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME); - bDelete = nValFlags == (bIsDate ? IDF_DATETIME : IDF_VALUE); - } - } - break; - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - bDelete = (nDelFlag & IDF_STRING) != 0; - break; - case CELLTYPE_FORMULA: - bDelete = (nDelFlag & IDF_FORMULA) != 0; - break; - case CELLTYPE_NOTE: - // do note delete note cell with broadcaster - bDelete = !pOldCell->GetBroadcaster(); - break; - default:; // added to avoid warnings - } + // Decide whether to delete the cell object according to passed + // flags. + bDelete = checkDeleteCellByFlag(eCellType, nDelFlag, *pDocument, *this, maItems[nIdx]); } if (bDelete) { - // try to create a replacement note cell, if note or broadcaster exists + // Try to create a replacement "note" cell if broadcaster exists. ScNoteCell* pNoteCell = NULL; SvtBroadcaster* pBC = pOldCell->GetBroadcaster(); if (pBC && pBC->HasListeners()) { - pNoteCell = new ScNoteCell( pBC ); - // NOTE: the broadcaster here is transferred and released - // only if it has listeners! If it does not, it will simply - // be deleted when the cell is deleted and no replacement - // cell is created. + // NOTE: the broadcaster here is transferred and released only + // if it has listeners! If it does not, it will simply be + // deleted when the cell is deleted and no replacement cell is + // created. + pNoteCell = new ScNoteCell(pBC); pOldCell->ReleaseBroadcaster(); } @@ -423,16 +440,16 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe else maItems[nIdx].pCell = pDummyCell.get(); - // cache formula cells (will be deleted later), delete cell of other type if (eCellType == CELLTYPE_FORMULA) { - aDelCells.push_back( static_cast< ScFormulaCell* >( pOldCell ) ); + // Cache formula cells (will be deleted later), delete cell of other type. + aDelCells.push_back(static_cast<ScFormulaCell*>(pOldCell)); } else { - aHint.GetAddress().SetRow( nOldRow ); - aHint.SetCell( pNoteCell ? pNoteCell : pOldCell ); - pDocument->Broadcast( aHint ); + aHint.GetAddress().SetRow(nOldRow); + aHint.SetCell(pNoteCell ? pNoteCell : pOldCell); + pDocument->Broadcast(aHint); if (pNoteCell != pOldCell) { pOldCell->Delete(); commit ed75f60db067ccfe87e077b3bc6b2cb76f3a0c7b Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Fri Mar 15 00:11:37 2013 -0400 Reduce indentation level. Change-Id: Ia70d1dfde53e13e7d40e7cb8fa09dc401570aa93 diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index cc25641..baaaacd 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -330,9 +330,10 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe for ( SCSIZE nIdx = nStartIndex; nIdx <= nEndIndex; ++nIdx ) { - // all content is deleted and cell does not contain broadcaster if (((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS) && !maItems[ nIdx ].pCell->GetBroadcaster()) { + // all content is deleted and cell does not contain broadcaster + ScBaseCell* pOldCell = maItems[ nIdx ].pCell; if (pOldCell->GetCellType() == CELLTYPE_FORMULA) { @@ -348,110 +349,105 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe pDocument->Broadcast( aHint ); pOldCell->Delete(); } + continue; } + // delete some contents of the cells, or cells with broadcaster + bool bDelete = false; + ScBaseCell* pOldCell = maItems[nIdx].pCell; + CellType eCellType = pOldCell->GetCellType(); + if ((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS) + bDelete = true; else { - bool bDelete = false; - ScBaseCell* pOldCell = maItems[nIdx].pCell; - CellType eCellType = pOldCell->GetCellType(); - if ((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS) - bDelete = true; - else + // decide whether to delete the cell object according to passed + // flags + switch ( eCellType ) { - // decide whether to delete the cell object according to passed - // flags - switch ( eCellType ) + case CELLTYPE_VALUE: { - case CELLTYPE_VALUE: - { - sal_uInt16 nValFlags = nDelFlag & (IDF_DATETIME|IDF_VALUE); - // delete values and dates? - bDelete = nValFlags == (IDF_DATETIME|IDF_VALUE); - // if not, decide according to cell number format - if( !bDelete && (nValFlags != 0) ) - { - sal_uLong nIndex = (sal_uLong)((SfxUInt32Item*)GetAttr( - maItems[nIdx].nRow, ATTR_VALUE_FORMAT ))->GetValue(); - short nType = pDocument->GetFormatTable()->GetType(nIndex); - bool bIsDate = (nType == NUMBERFORMAT_DATE) || - (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME); - bDelete = nValFlags == (bIsDate ? IDF_DATETIME : IDF_VALUE); - } - } - break; - - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - bDelete = (nDelFlag & IDF_STRING) != 0; - break; - - case CELLTYPE_FORMULA: - bDelete = (nDelFlag & IDF_FORMULA) != 0; - break; - - case CELLTYPE_NOTE: - // do note delete note cell with broadcaster - bDelete = !pOldCell->GetBroadcaster(); - break; - - default:; // added to avoid warnings + sal_uInt16 nValFlags = nDelFlag & (IDF_DATETIME|IDF_VALUE); + // delete values and dates? + bDelete = nValFlags == (IDF_DATETIME|IDF_VALUE); + // if not, decide according to cell number format + if (!bDelete && (nValFlags != 0)) + { + sal_uLong nIndex = (sal_uLong)((SfxUInt32Item*)GetAttr( + maItems[nIdx].nRow, ATTR_VALUE_FORMAT))->GetValue(); + short nType = pDocument->GetFormatTable()->GetType(nIndex); + bool bIsDate = (nType == NUMBERFORMAT_DATE) || + (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME); + bDelete = nValFlags == (bIsDate ? IDF_DATETIME : IDF_VALUE); + } } + break; + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + bDelete = (nDelFlag & IDF_STRING) != 0; + break; + case CELLTYPE_FORMULA: + bDelete = (nDelFlag & IDF_FORMULA) != 0; + break; + case CELLTYPE_NOTE: + // do note delete note cell with broadcaster + bDelete = !pOldCell->GetBroadcaster(); + break; + default:; // added to avoid warnings } + } - if (bDelete) + if (bDelete) + { + // try to create a replacement note cell, if note or broadcaster exists + ScNoteCell* pNoteCell = NULL; + SvtBroadcaster* pBC = pOldCell->GetBroadcaster(); + if (pBC && pBC->HasListeners()) { - // try to create a replacement note cell, if note or broadcaster exists - ScNoteCell* pNoteCell = NULL; - SvtBroadcaster* pBC = pOldCell->GetBroadcaster(); - if (pBC && pBC->HasListeners()) - { - pNoteCell = new ScNoteCell( pBC ); - // NOTE: the broadcaster here is transferred and released - // only if it has listeners! If it does not, it will simply - // be deleted when the cell is deleted and no replacement - // cell is created. - pOldCell->ReleaseBroadcaster(); - } + pNoteCell = new ScNoteCell( pBC ); + // NOTE: the broadcaster here is transferred and released + // only if it has listeners! If it does not, it will simply + // be deleted when the cell is deleted and no replacement + // cell is created. + pOldCell->ReleaseBroadcaster(); + } - // remove cell entry in cell item list - SCROW nOldRow = maItems[nIdx].nRow; - if (pNoteCell) - { - // replace old cell with the replacement note cell - maItems[nIdx].pCell = pNoteCell; - // ... so it's not really deleted - bDelete = false; - } - else - maItems[nIdx].pCell = pDummyCell.get(); + // remove cell entry in cell item list + SCROW nOldRow = maItems[nIdx].nRow; + if (pNoteCell) + { + // replace old cell with the replacement note cell + maItems[nIdx].pCell = pNoteCell; + // ... so it's not really deleted + bDelete = false; + } + else + maItems[nIdx].pCell = pDummyCell.get(); - // cache formula cells (will be deleted later), delete cell of other type - if (eCellType == CELLTYPE_FORMULA) - { - aDelCells.push_back( static_cast< ScFormulaCell* >( pOldCell ) ); - } - else + // cache formula cells (will be deleted later), delete cell of other type + if (eCellType == CELLTYPE_FORMULA) + { + aDelCells.push_back( static_cast< ScFormulaCell* >( pOldCell ) ); + } + else + { + aHint.GetAddress().SetRow( nOldRow ); + aHint.SetCell( pNoteCell ? pNoteCell : pOldCell ); + pDocument->Broadcast( aHint ); + if (pNoteCell != pOldCell) { - aHint.GetAddress().SetRow( nOldRow ); - aHint.SetCell( pNoteCell ? pNoteCell : pOldCell ); - pDocument->Broadcast( aHint ); - if (pNoteCell != pOldCell) - { - pOldCell->Delete(); - } + pOldCell->Delete(); } } + } - if (!bDelete) - { - // We just came to a non-deleted cell after a segment of - // deleted ones. So we need to remember the segment - // before moving on. - if (nFirst < nIdx) - aRemovedSegments.insert_back(nFirst, nIdx, true); - nFirst = nIdx + 1; - } + if (!bDelete) + { + // We just came to a non-deleted cell after a segment of + // deleted ones. So we need to remember the segment + // before moving on. + if (nFirst < nIdx) + aRemovedSegments.insert_back(nFirst, nIdx, true); + nFirst = nIdx + 1; } } // there is a segment of deleted cells at the end @@ -470,30 +466,30 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe SCSIZE nShift(0); SCSIZE nStartSegment(nStartIndex); bool bRemoved = false; - while (aIt != aEnd) + for (;aIt != aEnd; ++aIt) { if (aIt->second) - { // this segment removed + { + // this segment removed if (!bRemoved) nStartSegment = aIt->first; // The first of removes in a row sets start (they should be // alternating removed/notremoved anyway). bRemoved = true; + continue; } - else - { // this segment not removed - if (bRemoved) - { // previous segment(s) removed, move tail - SCSIZE const nEndSegment(aIt->first); - memmove( - &maItems[nStartSegment - nShift], - &maItems[nEndSegment - nShift], - (maItems.size() - nEndSegment) * sizeof(ColEntry)); - nShift += nEndSegment - nStartSegment; - bRemoved = false; - } + + if (bRemoved) + { + // this segment not removed, but previous segment(s) removed, move tail. + SCSIZE const nEndSegment(aIt->first); + memmove( + &maItems[nStartSegment - nShift], + &maItems[nEndSegment - nShift], + (maItems.size() - nEndSegment) * sizeof(ColEntry)); + nShift += nEndSegment - nStartSegment; + bRemoved = false; } - ++aIt; } // The last removed segment up to aItems.size() is discarded, there's // nothing following to be moved. commit ce81e00c0e4dcd4929bbaa9244f38e205e0d170d Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Thu Mar 14 22:57:56 2013 -0400 Add integrity check after column cell storage is modified. Change-Id: I8d2bd7616e0428e4e881ef0dc1012c4973e636a9 diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index ca68e7f..666d067 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -28,6 +28,14 @@ #include <set> #include <vector> +#define DEBUG_COLUMN_STORAGE 1 + +#if DEBUG_COLUMN_STORAGE +#ifdef NDEBUG +#undef NDEBUG +#endif +#endif + #include <mdds/multi_type_vector.hpp> #include <mdds/multi_type_vector_trait.hpp> diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 9190b31..19e5e9c 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -56,6 +56,13 @@ #include <math.h> +#if DEBUG_COLUMN_STORAGE +#include "columniterator.hxx" +#include <iostream> +using std::cout; +using std::endl; +#endif + // ----------------------------------------------------------------------- // factor from font size to optimal cell height (text width) @@ -1384,6 +1391,20 @@ SCROW ScColumn::FindNextVisibleRowWithContent(SCROW nRow, bool bForward) const void ScColumn::CellStorageModified() { +#if DEBUG_COLUMN_STORAGE + ScColumnTextWidthIterator aIter(*this, 0, MAXROW); + for (; aIter.hasCell(); aIter.next()) + { + SCROW nRow = aIter.getPos(); + ScBaseCell* pCell = GetCell(nRow); + if (!pCell) + { + cout << "Cell and text width storages are out of sync!" << endl; + cout.flush(); + abort(); + } + } +#endif } unsigned short ScColumn::GetTextWidth(SCROW nRow) const commit c5ca9a66c36cc30aea81be4e99f73d14777d27f9 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Thu Mar 14 22:35:43 2013 -0400 Call CellStorageModified() *after* the text widths get modified. So that I can put some integrity check code in there to test the integrity of cell storage. Change-Id: I0cc141ea74c27db1a014390b7abf807220e7be9f diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 682afc6..e778f96 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -852,7 +852,6 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) be performed (but keep broadcasters and notes at old position). */ maItems[nIndex1].pCell = pCell2; maItems[nIndex2].pCell = pCell1; - CellStorageModified(); SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster(); pCell1->TakeBroadcaster( pBC2 ); @@ -863,6 +862,7 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) unsigned short nVal2 = maTextWidths.get<unsigned short>(nRow2); maTextWidths.set<unsigned short>(nRow1, nVal2); maTextWidths.set<unsigned short>(nRow2, nVal1); + CellStorageModified(); } else { @@ -874,19 +874,18 @@ void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2) { // insert dummy note cell (without note) containing old broadcaster maItems[nIndex1].pCell = pDummyCell; - CellStorageModified(); } else { // remove ColEntry at old position maItems.erase( maItems.begin() + nIndex1 ); - CellStorageModified(); } // Empty text width at the cell 1 position. For now, we don't // transfer the old value to the cell 2 position since Insert() is // quite complicated. maTextWidths.set_empty(nRow1, nRow1); + CellStorageModified(); // insert ColEntry at new position. Insert( nRow2, pCell1 ); @@ -1013,14 +1012,14 @@ void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol) pFmlaCell2->UpdateReference(URM_MOVE, aRange, -dx, 0, 0); } - CellStorageModified(); - rCol.CellStorageModified(); - // Swap the text widths. unsigned short nVal1 = maTextWidths.get<unsigned short>(nRow); unsigned short nVal2 = rCol.maTextWidths.get<unsigned short>(nRow); maTextWidths.set<unsigned short>(nRow, nVal2); rCol.maTextWidths.set<unsigned short>(nRow, nVal1); + + CellStorageModified(); + rCol.CellStorageModified(); } else { @@ -1037,8 +1036,9 @@ void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol) pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0); } - CellStorageModified(); maTextWidths.set_empty(nRow, nRow); + CellStorageModified(); + // We don't transfer the text width to the destination column because // of Insert()'s complexity. @@ -1189,8 +1189,8 @@ void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize ) pDocument->SetAutoCalc( bOldAutoCalc ); - CellStorageModified(); maTextWidths.insert_empty(nStartRow, nSize); + CellStorageModified(); } @@ -1691,8 +1691,8 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol) if (bErased) { - CellStorageModified(); maTextWidths.set_empty(nStartRow, nEndRow); + CellStorageModified(); } } } diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 57b5370..cc25641 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -88,17 +88,16 @@ void ScColumn::Insert( SCROW nRow, ScBaseCell* pNewCell ) } pOldCell->Delete(); maItems[nIndex].pCell = pNewCell; - CellStorageModified(); } else { maItems.insert(maItems.begin() + nIndex, ColEntry()); maItems[nIndex].pCell = pNewCell; maItems[nIndex].nRow = nRow; - CellStorageModified(); } maTextWidths.set<unsigned short>(nRow, TEXTWIDTH_DIRTY); + CellStorageModified(); } // When we insert from the Clipboard we still have wrong (old) References! // First they are rewired in CopyBlockFromClip via UpdateReference and the @@ -142,8 +141,8 @@ void ScColumn::Append( SCROW nRow, ScBaseCell* pCell ) maItems.back().pCell = pCell; maItems.back().nRow = nRow; - CellStorageModified(); maTextWidths.set<unsigned short>(nRow, TEXTWIDTH_DIRTY); + CellStorageModified(); } @@ -156,7 +155,6 @@ void ScColumn::Delete( SCROW nRow ) ScBaseCell* pCell = maItems[nIndex].pCell; ScNoteCell* pNoteCell = new ScNoteCell; maItems[nIndex].pCell = pNoteCell; // Dummy for Interpret - CellStorageModified(); pDocument->Broadcast( ScHint( SC_HINT_DYING, ScAddress( nCol, nRow, nTab ), pCell ) ); if ( SvtBroadcaster* pBC = pCell->ReleaseBroadcaster() ) @@ -167,13 +165,13 @@ void ScColumn::Delete( SCROW nRow ) { pNoteCell->Delete(); maItems.erase( maItems.begin() + nIndex); - CellStorageModified(); // Should we free memory here (delta)? It'll be slower! } pCell->EndListeningTo( pDocument ); pCell->Delete(); maTextWidths.set_empty(nRow, nRow); + CellStorageModified(); } } @@ -191,8 +189,8 @@ void ScColumn::DeleteAtIndex( SCSIZE nIndex ) pCell->EndListeningTo( pDocument ); pCell->Delete(); - CellStorageModified(); maTextWidths.set_empty(nRow, nRow); + CellStorageModified(); } @@ -202,8 +200,8 @@ void ScColumn::FreeAll() maItems[i].pCell->Delete(); maItems.clear(); - CellStorageModified(); maTextWidths.clear(); + CellStorageModified(); } @@ -502,8 +500,8 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDe if (bRemoved) nShift += maItems.size() - nStartSegment; maItems.erase(maItems.end() - nShift, maItems.end()); - CellStorageModified(); maTextWidths.set_empty(nStartRow, nEndRow); + CellStorageModified(); } // *** delete all formula cells *** @@ -1430,8 +1428,8 @@ bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString, pOldCell->Delete(); maItems[i].pCell = pNewCell; // Replace + maTextWidths.set<unsigned short>(nRow, TEXTWIDTH_DIRTY); CellStorageModified(); - SetTextWidth(nRow, TEXTWIDTH_DIRTY); if ( pNewCell->GetCellType() == CELLTYPE_FORMULA ) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits