[Libreoffice-commits] core.git: 11 commits - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Fri Mar 15 08:35:53 PDT 2013
sc/inc/column.hxx | 11 +
sc/inc/document.hxx | 3
sc/inc/table.hxx | 3
sc/source/core/data/column.cxx | 25 +--
sc/source/core/data/column2.cxx | 61 +++++++
sc/source/core/data/column3.cxx | 301 +++++++++++++++++++--------------------
sc/source/core/data/document.cxx | 9 +
sc/source/core/data/table1.cxx | 16 ++
sc/source/ui/view/viewfunc.cxx | 2
sc/source/ui/view/viewutil.cxx | 2
10 files changed, 273 insertions(+), 160 deletions(-)
New commits:
commit 5874231b8a7fc790299e9129684271b5ca70410b
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Fri Mar 15 11:20:19 2013 -0400
Turn off debugging and silence compiler warning.
Change-Id: If2bfc9f346d7f2eee20caa30e1eb1f60d266ef90
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 666d067..dd14b6a 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -28,7 +28,7 @@
#include <set>
#include <vector>
-#define DEBUG_COLUMN_STORAGE 1
+#define DEBUG_COLUMN_STORAGE 0
#if DEBUG_COLUMN_STORAGE
#ifdef NDEBUG
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index f96515a..a1a84bb 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1449,10 +1449,12 @@ sal_uInt8 ScColumn::GetScriptType( SCROW nRow ) const
return SC_SCRIPTTYPE_UNKNOWN;
}
-void ScColumn::SetScriptType( SCROW nRow, sal_uInt8 nType )
+void ScColumn::SetScriptType( SCROW nRow, sal_uInt8 /*nType*/ )
{
if (!ValidRow(nRow))
return;
+
+ // TODO: Implement this.
}
void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
commit 3a78c5b9898f70ca0163501ae2b583a7cb76d51f
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Fri Mar 15 11:10:39 2013 -0400
Oops the erase() method takes start and end positions.
The second parameter has to be the absolute end position, not the size
from the start position.
Change-Id: I310ec52697d0521a82810889f6fe861471279645
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 62f0135..0ba6f01 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -262,7 +262,7 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
// There are cells below the deletion point. Shift their row positions.
// Shift the text width array too (before the broadcast).
- maTextWidths.erase(nStartRow, nSize);
+ maTextWidths.erase(nStartRow, nEndRow);
maTextWidths.resize(MAXROW);
ScAddress aAdr( nCol, 0, nTab );
commit 431c4536ce58410d6dd3e199185bd128bac624ef
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Fri Mar 15 10:57:42 2013 -0400
Better consistency checking.
Change-Id: I096282ebb9a10d212affbab32aaa49ca1815b1a7
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 19e5e9c..f96515a 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1392,18 +1392,42 @@ SCROW ScColumn::FindNextVisibleRowWithContent(SCROW nRow, bool bForward) const
void ScColumn::CellStorageModified()
{
#if DEBUG_COLUMN_STORAGE
+ if (maItems.empty())
+ {
+ if (maTextWidths.empty())
+ {
+ cout << "ScColumn::CellStorageModified: Text width array is empty, but shouldn't." << endl;
+ abort();
+ }
+
+ if (maTextWidths.block_size() != 1 || maTextWidths.begin()->type != mdds::mtv::element_type_empty)
+ {
+ cout << "ScColumn::CellStorageModified: When the cell array is empty, the text with array should consist of one empty block." << endl;
+ abort();
+ }
+
+ return;
+ }
+
+ cout << "-- begin" << endl;
+ std::vector<ColEntry>::const_iterator it = maItems.begin(), itEnd = maItems.end();
+ for (; it != itEnd; ++it)
+ cout << "ScColumn::CellStorageModified: entry: row = " << it->nRow << "; cell = " << it->pCell << endl;
+
ScColumnTextWidthIterator aIter(*this, 0, MAXROW);
for (; aIter.hasCell(); aIter.next())
{
SCROW nRow = aIter.getPos();
ScBaseCell* pCell = GetCell(nRow);
+ cout << "ScColumn::CellStorageModified: row = " << nRow << "; cell = " << pCell << endl;
if (!pCell)
{
- cout << "Cell and text width storages are out of sync!" << endl;
+ cout << "ScColumn::CellStorageModified: Cell and text width storages are out of sync!" << endl;
cout.flush();
abort();
}
}
+ cout << "-- end" << endl;
#endif
}
commit 17be36299fd59babe10de164ef2c885c21ae3a54
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Fri Mar 15 10:55:40 2013 -0400
Fix the text width array going out of sync when shifting row positions.
Change-Id: I7b9c5554e38a25dd4ff6980e6ae0d1eff241a746
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 6116780..62f0135 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -200,7 +200,9 @@ void ScColumn::FreeAll()
maItems[i].pCell->Delete();
maItems.clear();
+ // Text width should keep a logical empty range of 0-MAXROW when the cell array is empty.
maTextWidths.clear();
+ maTextWidths.resize(MAXROW);
CellStorageModified();
}
@@ -257,6 +259,12 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
else
i = nFirstIndex;
+ // There are cells below the deletion point. Shift their row positions.
+
+ // Shift the text width array too (before the broadcast).
+ maTextWidths.erase(nStartRow, nSize);
+ maTextWidths.resize(MAXROW);
+
ScAddress aAdr( nCol, 0, nTab );
ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL ); // only areas (ScBaseCell* == NULL)
ScAddress& rAddress = aHint.GetAddress();
@@ -300,6 +308,7 @@ void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
pDocument->AreaBroadcastInRange( aRange, aHint );
}
+ CellStorageModified();
pDocument->SetAutoCalc( bOldAutoCalc );
}
commit 41afb3ecfa80e3afc907dcf77b8efd17e048309e
Author: Kohei Yoshida <kohei.yoshida at 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 feb5b164f6a371ee934049c89b3d02ca5308f68e
Author: Kohei Yoshida <kohei.yoshida at 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 d71e44e78333111a02818b903699188bc372b382
Author: Kohei Yoshida <kohei.yoshida at 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 7b6d3e8f0cc1cc72d6b3f958957c4747b4839bcf
Author: Kohei Yoshida <kohei.yoshida at 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 927da98a2a4860f926968b4704e02d58d7cf0eea
Author: Kohei Yoshida <kohei.yoshida at 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 632290663a9d2bc722ddfb96aec049d7362204d6
Author: Kohei Yoshida <kohei.yoshida at 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 )
{
commit 7ac77e31a54d0b0545ed039426405f2b0c96a6e3
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Thu Mar 14 17:56:51 2013 -0400
Create skeleton accessors for cell text script types.
Change-Id: I5408cdd87f06423a6bb287c855237878859da880
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 114a39b..ca68e7f 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -387,6 +387,9 @@ public:
sal_uInt16 GetTextWidth(SCROW nRow) const;
void SetTextWidth(SCROW nRow, sal_uInt16 nWidth);
+ sal_uInt8 GetScriptType( SCROW nRow ) const;
+ void SetScriptType( SCROW nRow, sal_uInt8 nType );
+
private:
ScBaseCell* CloneCell(SCSIZE nIndex, sal_uInt16 nFlags, ScDocument& rDestDoc, const ScAddress& rDestPos) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 541ec05..cb8aac7 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1177,7 +1177,8 @@ public:
bool HasStringWeakCharacters( const rtl::OUString& rString );
SC_DLLPUBLIC sal_uInt8 GetStringScriptType( const rtl::OUString& rString );
SC_DLLPUBLIC sal_uInt8 GetCellScriptType( ScBaseCell* pCell, sal_uLong nNumberFormat );
- SC_DLLPUBLIC sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell = NULL );
+ SC_DLLPUBLIC sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* pCell );
+ sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab ) const;
bool HasDetectiveOperations() const;
void AddDetectiveOperation( const ScDetOpData& rData );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 3e4d1eb..25f4f7a 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -793,6 +793,9 @@ public:
sal_uLong AddCondFormat( ScConditionalFormat* pNew );
+ sal_uInt8 GetScriptType( SCCOL nCol, SCROW nRow ) const;
+ void SetScriptType( SCCOL nCol, SCROW nRow, sal_uInt8 nType );
+
private:
void FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd,
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index c586b34..9190b31 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1396,6 +1396,20 @@ void ScColumn::SetTextWidth(SCROW nRow, unsigned short nWidth)
maTextWidths.set(nRow, nWidth);
}
+sal_uInt8 ScColumn::GetScriptType( SCROW nRow ) const
+{
+ if (!ValidRow(nRow))
+ return SC_SCRIPTTYPE_UNKNOWN;
+
+ return SC_SCRIPTTYPE_UNKNOWN;
+}
+
+void ScColumn::SetScriptType( SCROW nRow, sal_uInt8 nType )
+{
+ if (!ValidRow(nRow))
+ return;
+}
+
void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
{
// check if we are in a data area
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index a73cd60..ec9c7c6 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -5767,4 +5767,13 @@ void ScDocument::SetAutoNameCache( ScAutoNameCache* pCache )
delete pAutoNameCache;
pAutoNameCache = pCache;
}
+
+sal_uInt8 ScDocument::GetScriptType( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
+{
+ if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
+ return SC_SCRIPTTYPE_UNKNOWN;
+
+ return maTabs[nTab]->GetScriptType(nCol, nRow);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index b50380a..cfe0e57 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2080,6 +2080,22 @@ sal_uLong ScTable::AddCondFormat( ScConditionalFormat* pNew )
return nMax + 1;
}
+sal_uInt8 ScTable::GetScriptType( SCCOL nCol, SCROW nRow ) const
+{
+ if (!ValidCol(nCol))
+ return SC_SCRIPTTYPE_UNKNOWN;
+
+ return aCol[nCol].GetScriptType(nRow);
+}
+
+void ScTable::SetScriptType( SCCOL nCol, SCROW nRow, sal_uInt8 nType )
+{
+ if (!ValidCol(nCol))
+ return;
+
+ aCol[nCol].SetScriptType(nRow, nType);
+}
+
void ScTable::DeleteConditionalFormat( sal_uLong nIndex )
{
mpCondFormatList->erase(nIndex);
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index 4b7c02a..fcd76aa 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -823,7 +823,7 @@ sal_uInt8 ScViewFunc::GetSelectionScriptType()
// no selection -> cursor
nScript = pDoc->GetScriptType( GetViewData()->GetCurX(),
- GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+ GetViewData()->GetCurY(), GetViewData()->GetTabNo(), NULL );
}
else
{
diff --git a/sc/source/ui/view/viewutil.cxx b/sc/source/ui/view/viewutil.cxx
index e740079..d24d080 100644
--- a/sc/source/ui/view/viewutil.cxx
+++ b/sc/source/ui/view/viewutil.cxx
@@ -71,7 +71,7 @@ sal_uInt16 ScViewUtil::GetEffLanguage( ScDocument* pDoc, const ScAddress& rPos )
{
// used for thesaurus
- sal_uInt8 nScript = pDoc->GetScriptType( rPos.Col(), rPos.Row(), rPos.Tab() );
+ sal_uInt8 nScript = pDoc->GetScriptType( rPos.Col(), rPos.Row(), rPos.Tab(), NULL );
sal_uInt16 nWhich = ( nScript == SCRIPTTYPE_ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
( ( nScript == SCRIPTTYPE_COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE : ATTR_FONT_LANGUAGE );
const SfxPoolItem* pItem = pDoc->GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), nWhich);
More information about the Libreoffice-commits
mailing list