summaryrefslogtreecommitdiff
path: root/sc/source/core/data/table3.cxx
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2014-04-16 22:04:55 -0400
committerEike Rathke <erack@redhat.com>2014-04-25 12:15:19 +0000
commit08b51bfff61870cd573daea914dce429743f4655 (patch)
tree086c1bdf8bc7b602bb3aa874498d4beeaff7e80c /sc/source/core/data/table3.cxx
parent1a33a20fe4ed4078794c07f0b506355999119882 (diff)
fdo#72741, fdo#76607: Backport of Calc sort rework.
This change requires mdds 0.10.3 as the baseline. Conflicts: configure.ac sc/inc/fstalgorithm.hxx sc/source/core/data/column.cxx sc/source/core/data/table3.cxx sc/source/ui/docshell/dbdocfun.cxx Change-Id: Ia6d2bf1ee17e96c30b6d5310f5c49e5a4404e094 Reviewed-on: https://gerrit.libreoffice.org/9144 Reviewed-by: Michael Meeks <michael.meeks@collabora.com> Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Eike Rathke <erack@redhat.com>
Diffstat (limited to 'sc/source/core/data/table3.cxx')
-rw-r--r--sc/source/core/data/table3.cxx529
1 files changed, 436 insertions, 93 deletions
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index 16ed68dd7de6..429cd52ede92 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -56,11 +56,19 @@
#include "tokenarray.hxx"
#include "mtvcellfunc.hxx"
#include "columnspanset.hxx"
+#include <stlalgorithm.hxx>
+#include <fstalgorithm.hxx>
+#include <listenercontext.hxx>
+#include <sharedformula.hxx>
#include "svl/sharedstringpool.hxx"
#include <vector>
+#include <boost/scoped_ptr.hpp>
#include <boost/unordered_set.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <mdds/flat_segment_tree.hpp>
using namespace ::com::sun::star;
@@ -212,78 +220,186 @@ IMPL_FIXEDMEMPOOL_NEWDEL( ScSortInfo )
// END OF STATIC DATA -----------------------------------------------------
-class ScSortInfoArray
+class ScSortInfoArray : boost::noncopyable
{
+public:
+
+ struct Cell
+ {
+ ScRefCellValue maCell;
+ const sc::CellTextAttr* mpAttr;
+ const SvtBroadcaster* mpBroadcaster;
+ const ScPostIt* mpNote;
+ const ScPatternAttr* mpPattern;
+
+ Cell() : mpAttr(NULL), mpBroadcaster(NULL), mpNote(NULL), mpPattern(NULL) {}
+ };
+
+ struct Row
+ {
+ std::vector<Cell> maCells;
+
+ bool mbHidden:1;
+ bool mbFiltered:1;
+
+ Row( size_t nColSize ) : maCells(nColSize, Cell()), mbHidden(false), mbFiltered(false) {}
+ };
+
+ typedef std::vector<Row*> RowsType;
+
private:
+ boost::scoped_ptr<RowsType> mpRows; /// row-wise data table for sort by row operation.
+
ScSortInfo*** pppInfo;
SCSIZE nCount;
SCCOLROW nStart;
+ SCCOLROW mnLastIndex; /// index of last non-empty cell position.
sal_uInt16 nUsedSorts;
+ bool mbKeepQuery;
+
public:
- ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
- pppInfo( new ScSortInfo**[nSorts]),
- nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
- nUsedSorts( nSorts )
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = new ScSortInfo* [nCount];
- for ( SCSIZE j = 0; j < nCount; j++ )
- ppInfo[j] = new ScSortInfo;
- pppInfo[nSort] = ppInfo;
- }
- }
- ~ScSortInfoArray()
- {
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = pppInfo[nSort];
- for ( SCSIZE j = 0; j < nCount; j++ )
- delete ppInfo[j];
- delete [] ppInfo;
- }
- delete[] pppInfo;
- }
+ ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
+ pppInfo( new ScSortInfo**[nSorts]),
+ nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
+ mnLastIndex(nInd2),
+ nUsedSorts(nSorts),
+ mbKeepQuery(false)
+ {
+ for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = new ScSortInfo* [nCount];
+ for ( SCSIZE j = 0; j < nCount; j++ )
+ ppInfo[j] = new ScSortInfo;
+ pppInfo[nSort] = ppInfo;
+ }
+ }
+
+ ~ScSortInfoArray()
+ {
+ for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = pppInfo[nSort];
+ for ( SCSIZE j = 0; j < nCount; j++ )
+ delete ppInfo[j];
+ delete [] ppInfo;
+ }
+ delete[] pppInfo;
+
+ if (mpRows)
+ std::for_each(mpRows->begin(), mpRows->end(), ScDeleteObjectByPtr<Row>());
+ }
+
+ void SetKeepQuery( bool b ) { mbKeepQuery = b; }
+
+ bool IsKeepQuery() const { return mbKeepQuery; }
+
ScSortInfo* Get( sal_uInt16 nSort, SCCOLROW nInd )
{ return (pppInfo[nSort])[ nInd - nStart ]; }
- void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
- {
- SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
- SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
- for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
- {
- ScSortInfo** ppInfo = pppInfo[nSort];
- ScSortInfo* pTmp = ppInfo[n1];
- ppInfo[n1] = ppInfo[n2];
- ppInfo[n2] = pTmp;
- }
- }
+
+ void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
+ {
+ SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
+ SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
+ for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
+ {
+ ScSortInfo** ppInfo = pppInfo[nSort];
+ ScSortInfo* pTmp = ppInfo[n1];
+ ppInfo[n1] = ppInfo[n2];
+ ppInfo[n2] = pTmp;
+ }
+
+ if (mpRows)
+ {
+ // Swap rows in data table.
+ RowsType& rRows = *mpRows;
+ std::swap(rRows[n1], rRows[n2]);
+ }
+ }
+
sal_uInt16 GetUsedSorts() const { return nUsedSorts; }
ScSortInfo** GetFirstArray() const { return pppInfo[0]; }
SCCOLROW GetStart() const { return nStart; }
+ SCCOLROW GetLast() const { return mnLastIndex; }
SCSIZE GetCount() const { return nCount; }
+
+ RowsType& InitDataRows( size_t nRowSize, size_t nColSize )
+ {
+ mpRows.reset(new RowsType);
+ mpRows->reserve(nRowSize);
+ for (size_t i = 0; i < nRowSize; ++i)
+ mpRows->push_back(new Row(nColSize));
+
+ return *mpRows;
+ }
+
+ RowsType* GetDataRows()
+ {
+ return mpRows.get();
+ }
};
-ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
+ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery )
{
sal_uInt16 nUsedSorts = 1;
while ( nUsedSorts < aSortParam.GetSortKeyCount() && aSortParam.maKeyState[nUsedSorts].bDoSort )
nUsedSorts++;
ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
+ pArray->SetKeepQuery(bKeepQuery);
+
if ( aSortParam.bByRow )
{
for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
{
SCCOL nCol = static_cast<SCCOL>(aSortParam.maKeyState[nSort].nField);
ScColumn* pCol = &aCol[nCol];
+ sc::ColumnBlockConstPosition aBlockPos;
+ pCol->InitBlockPosition(aBlockPos);
for ( SCROW nRow = nInd1; nRow <= nInd2; nRow++ )
{
ScSortInfo* pInfo = pArray->Get( nSort, nRow );
- pInfo->maCell = pCol->GetCellValue(nRow);
+ pInfo->maCell = pCol->GetCellValue(aBlockPos, nRow);
pInfo->nOrg = nRow;
}
}
+
+ // Fill row-wise data table.
+ ScSortInfoArray::RowsType& rRows = pArray->InitDataRows(
+ nInd2 - nInd1 + 1, aSortParam.nCol2 - aSortParam.nCol1 + 1);
+
+ for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; ++nCol)
+ {
+ ScColumn& rCol = aCol[nCol];
+
+ // Skip reordering of cell formats if the whole span is on the same pattern entry.
+ bool bUniformPattern = rCol.GetPatternCount(nInd1, nInd2) < 2u;
+
+ sc::ColumnBlockConstPosition aBlockPos;
+ rCol.InitBlockPosition(aBlockPos);
+ for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow)
+ {
+ ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1];
+ ScSortInfoArray::Cell& rCell = rRow.maCells[nCol-aSortParam.nCol1];
+
+ rCell.maCell = rCol.GetCellValue(aBlockPos, nRow);
+ rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow);
+ rCell.mpBroadcaster = rCol.GetBroadcaster(aBlockPos, nRow);
+ rCell.mpNote = rCol.GetCellNote(aBlockPos, nRow);
+
+ if (!bUniformPattern && aSortParam.bIncludePattern)
+ rCell.mpPattern = rCol.GetPattern(nRow);
+ }
+ }
+
+ if (bKeepQuery)
+ {
+ for (SCROW nRow = nInd1; nRow <= nInd2; ++nRow)
+ {
+ ScSortInfoArray::Row& rRow = *rRows[nRow-nInd1];
+ rRow.mbHidden = RowHidden(nRow);
+ rRow.mbFiltered = RowFiltered(nRow);
+ }
+ }
}
else
{
@@ -302,6 +418,71 @@ ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
return pArray;
}
+namespace {
+
+struct SortedColumn : boost::noncopyable
+{
+ typedef mdds::flat_segment_tree<SCROW, const ScPatternAttr*> PatRangeType;
+
+ sc::CellStoreType maCells;
+ sc::CellTextAttrStoreType maCellTextAttrs;
+ sc::BroadcasterStoreType maBroadcasters;
+ sc::CellNoteStoreType maCellNotes;
+
+ PatRangeType maPatterns;
+ PatRangeType::const_iterator miPatternPos;
+
+ SortedColumn( size_t nTopEmptyRows ) :
+ maCells(nTopEmptyRows),
+ maCellTextAttrs(nTopEmptyRows),
+ maBroadcasters(nTopEmptyRows),
+ maCellNotes(nTopEmptyRows),
+ maPatterns(0, MAXROWCOUNT, NULL),
+ miPatternPos(maPatterns.begin()) {}
+
+ void setPattern( SCROW nRow, const ScPatternAttr* pPat )
+ {
+ miPatternPos = maPatterns.insert(miPatternPos, nRow, nRow+1, pPat).first;
+ }
+};
+
+struct SortedRowFlags
+{
+ typedef mdds::flat_segment_tree<SCROW,bool> FlagsType;
+
+ FlagsType maRowsHidden;
+ FlagsType maRowsFiltered;
+ FlagsType::const_iterator miPosHidden;
+ FlagsType::const_iterator miPosFiltered;
+
+ SortedRowFlags() :
+ maRowsHidden(0, MAXROWCOUNT, false),
+ maRowsFiltered(0, MAXROWCOUNT, false),
+ miPosHidden(maRowsHidden.begin()),
+ miPosFiltered(maRowsFiltered.begin()) {}
+
+ void setRowHidden( SCROW nRow, bool b )
+ {
+ miPosHidden = maRowsHidden.insert(miPosHidden, nRow, nRow+1, b).first;
+ }
+
+ void setRowFiltered( SCROW nRow, bool b )
+ {
+ miPosFiltered = maRowsFiltered.insert(miPosFiltered, nRow, nRow+1, b).first;
+ }
+};
+
+struct PatternSpan
+{
+ SCROW mnRow1;
+ SCROW mnRow2;
+ const ScPatternAttr* mpPattern;
+
+ PatternSpan( SCROW nRow1, SCROW nRow2, const ScPatternAttr* pPat ) :
+ mnRow1(nRow1), mnRow2(nRow2), mpPattern(pPat) {}
+};
+
+}
bool ScTable::IsSortCollatorGlobal() const
{
@@ -341,11 +522,17 @@ void ScTable::DestroySortCollator()
void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
{
- bool bByRow = aSortParam.bByRow;
- SCSIZE nCount = pArray->GetCount();
+ if (aSortParam.bByRow)
+ {
+ SortReorderByRow(pArray, pProgress);
+ return;
+ }
+
+ size_t nCount = pArray->GetCount();
SCCOLROW nStart = pArray->GetStart();
ScSortInfo** ppInfo = pArray->GetFirstArray();
- ::std::vector<ScSortInfo*> aTable(nCount);
+
+ std::vector<ScSortInfo*> aTable(nCount);
SCSIZE nPos;
for ( nPos = 0; nPos < nCount; nPos++ )
aTable[ppInfo[nPos]->nOrg - nStart] = ppInfo[nPos];
@@ -356,10 +543,7 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
SCCOLROW nOrg = ppInfo[nPos]->nOrg;
if ( nDest != nOrg )
{
- if ( bByRow )
- SwapRow( nDest, nOrg );
- else
- SwapCol( static_cast<SCCOL>(nDest), static_cast<SCCOL>(nOrg) );
+ SwapCol( static_cast<SCCOL>(nDest), static_cast<SCCOL>(nOrg) );
// neue Position des weggeswapten eintragen
ScSortInfo* p = ppInfo[nPos];
p->nOrg = nDest;
@@ -373,6 +557,195 @@ void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress* pProgress )
}
}
+void ScTable::SortReorderByRow( ScSortInfoArray* pArray, ScProgress* pProgress )
+{
+ SCROW nRow1 = pArray->GetStart();
+ SCROW nRow2 = pArray->GetLast();
+ ScSortInfoArray::RowsType* pRows = pArray->GetDataRows();
+ assert(pRows); // In sort-by-row mode we must have data rows already populated.
+
+ // Detach all formula cells within the sorted range first.
+ sc::EndListeningContext aCxt(*pDocument);
+ DetachFormulaCells(aCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, nRow2);
+
+ // Cells in the data rows only reference values in the document. Make
+ // a copy before updating the document.
+
+ size_t nColCount = aSortParam.nCol2 - aSortParam.nCol1 + 1;
+ boost::ptr_vector<SortedColumn> aSortedCols; // storage for copied cells.
+ SortedRowFlags aRowFlags;
+ aSortedCols.reserve(nColCount);
+ for (size_t i = 0; i < nColCount; ++i)
+ {
+ // In the sorted column container, element positions and row
+ // positions must match, else formula cells may mis-behave during
+ // grouping.
+ aSortedCols.push_back(new SortedColumn(nRow1));
+ }
+
+ for (size_t i = 0; i < pRows->size(); ++i)
+ {
+ ScSortInfoArray::Row* pRow = (*pRows)[i];
+ for (size_t j = 0; j < pRow->maCells.size(); ++j)
+ {
+ ScAddress aCellPos(aSortParam.nCol1 + j, nRow1 + i, nTab);
+
+ ScSortInfoArray::Cell& rCell = pRow->maCells[j];
+
+ sc::CellStoreType& rCellStore = aSortedCols.at(j).maCells;
+ switch (rCell.maCell.meType)
+ {
+ case CELLTYPE_STRING:
+ assert(rCell.mpAttr);
+ rCellStore.push_back(*rCell.maCell.mpString);
+ break;
+ case CELLTYPE_VALUE:
+ assert(rCell.mpAttr);
+ rCellStore.push_back(rCell.maCell.mfValue);
+ break;
+ case CELLTYPE_EDIT:
+ assert(rCell.mpAttr);
+ rCellStore.push_back(rCell.maCell.mpEditText->Clone());
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ assert(rCell.mpAttr);
+ size_t n = rCellStore.size();
+ sc::CellStoreType::iterator itBlk = rCellStore.push_back(rCell.maCell.mpFormula->Clone(aCellPos));
+
+ // Join the formula cells as we fill the container.
+ size_t nOffset = n - itBlk->position;
+ sc::CellStoreType::position_type aPos(itBlk, nOffset);
+ sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
+ }
+ break;
+ default:
+ assert(!rCell.mpAttr);
+ rCellStore.push_back_empty();
+ }
+
+ sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(j).maCellTextAttrs;
+ if (rCell.mpAttr)
+ rAttrStore.push_back(*rCell.mpAttr);
+ else
+ rAttrStore.push_back_empty();
+
+ // At this point each broadcaster instance is managed by 2
+ // containers. We will release those in the original storage
+ // below before transferring them to the document.
+ sc::BroadcasterStoreType& rBCStore = aSortedCols.at(j).maBroadcasters;
+ if (rCell.mpBroadcaster)
+ // A const pointer would be implicitly converted to a bool type.
+ rBCStore.push_back(const_cast<SvtBroadcaster*>(rCell.mpBroadcaster));
+ else
+ rBCStore.push_back_empty();
+
+ // The same with cell note instances ...
+ sc::CellNoteStoreType& rNoteStore = aSortedCols.at(j).maCellNotes;
+ if (rCell.mpNote)
+ rNoteStore.push_back(const_cast<ScPostIt*>(rCell.mpNote));
+ else
+ rNoteStore.push_back_empty();
+
+ if (rCell.mpPattern)
+ aSortedCols.at(j).setPattern(aCellPos.Row(), rCell.mpPattern);
+ }
+
+ if (pArray->IsKeepQuery())
+ {
+ // Hidden and filtered flags are first converted to segments.
+ SCROW nRow = nRow1 + i;
+ aRowFlags.setRowHidden(nRow, pRow->mbHidden);
+ aRowFlags.setRowFiltered(nRow, pRow->mbFiltered);
+ }
+
+ if (pProgress)
+ pProgress->SetStateOnPercent(i);
+ }
+
+ for (size_t i = 0, n = aSortedCols.size(); i < n; ++i)
+ {
+ SCCOL nThisCol = i + aSortParam.nCol1;
+
+ {
+ sc::CellStoreType& rDest = aCol[nThisCol].maCells;
+ sc::CellStoreType& rSrc = aSortedCols[i].maCells;
+ rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+ }
+
+ {
+ sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs;
+ sc::CellTextAttrStoreType& rSrc = aSortedCols[i].maCellTextAttrs;
+ rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+ }
+
+ {
+ sc::BroadcasterStoreType& rSrc = aSortedCols[i].maBroadcasters;
+ sc::BroadcasterStoreType& rDest = aCol[nThisCol].maBroadcasters;
+
+ // Release current broadcasters first, to prevent them from getting deleted.
+ rDest.release_range(nRow1, nRow2);
+
+ // Transfer sorted broadcaster segment to the document.
+ rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+ }
+
+ {
+ sc::CellNoteStoreType& rSrc = aSortedCols[i].maCellNotes;
+ sc::CellNoteStoreType& rDest = aCol[nThisCol].maCellNotes;
+
+ // Do the same as broadcaster storage transfer (to prevent double deletion).
+ rDest.release_range(nRow1, nRow2);
+ rSrc.transfer(nRow1, nRow2, rDest, nRow1);
+ aCol[nThisCol].UpdateNoteCaptions(nRow1, nRow2);
+ }
+
+ {
+ // Get all row spans where the pattern is not NULL.
+ std::vector<PatternSpan> aSpans =
+ sc::toSpanArrayWithValue<SCROW,const ScPatternAttr*,PatternSpan>(
+ aSortedCols[i].maPatterns);
+
+ std::vector<PatternSpan>::iterator it = aSpans.begin(), itEnd = aSpans.end();
+ for (; it != itEnd; ++it)
+ {
+ assert(it->mpPattern); // should never be NULL.
+ aCol[nThisCol].SetPatternArea(it->mnRow1, it->mnRow2, *it->mpPattern, true);
+ }
+ }
+
+ aCol[nThisCol].CellStorageModified();
+ }
+
+ if (pArray->IsKeepQuery())
+ {
+ aRowFlags.maRowsHidden.build_tree();
+ aRowFlags.maRowsFiltered.build_tree();
+
+ // Remove all flags in the range first.
+ SetRowHidden(nRow1, nRow2, false);
+ SetRowFiltered(nRow1, nRow2, false);
+
+ std::vector<sc::RowSpan> aSpans =
+ sc::toSpanArray<SCROW,sc::RowSpan>(aRowFlags.maRowsHidden, nRow1);
+
+ std::vector<sc::RowSpan>::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
+ for (; it != itEnd; ++it)
+ SetRowHidden(it->mnRow1, it->mnRow2, true);
+
+ aSpans = sc::toSpanArray<SCROW,sc::RowSpan>(aRowFlags.maRowsFiltered, nRow1);
+
+ it = aSpans.begin(), itEnd = aSpans.end();
+ for (; it != itEnd; ++it)
+ SetRowFiltered(it->mnRow1, it->mnRow2, true);
+ }
+
+ // Attach all formula cells within sorted range, to have them start listening again.
+ sc::StartListeningContext aStartListenCxt(*pDocument);
+ AttachFormulaCells(
+ aStartListenCxt, aSortParam.nCol1, nRow1, aSortParam.nCol2, nRow2);
+}
+
short ScTable::CompareCell(
sal_uInt16 nSort,
ScRefCellValue& rCell1, SCCOL nCell1Col, SCROW nCell1Row,
@@ -561,40 +934,6 @@ void ScTable::SwapCol(SCCOL nCol1, SCCOL nCol2)
}
}
-void ScTable::SwapRow(SCROW nRow1, SCROW nRow2)
-{
- SCCOL nColStart = aSortParam.nCol1;
- SCCOL nColEnd = aSortParam.nCol2;
- for (SCCOL nCol = nColStart; nCol <= nColEnd; nCol++)
- {
- aCol[nCol].SwapRow(nRow1, nRow2);
- if (aSortParam.bIncludePattern)
- {
- const ScPatternAttr* pPat1 = GetPattern(nCol, nRow1);
- const ScPatternAttr* pPat2 = GetPattern(nCol, nRow2);
- if (pPat1 != pPat2)
- {
- pDocument->GetPool()->Put(*pPat1);
- SetPattern(nCol, nRow1, *pPat2, true);
- SetPattern(nCol, nRow2, *pPat1, true);
- pDocument->GetPool()->Remove(*pPat1);
- }
- }
- }
- if (bGlobalKeepQuery)
- {
- bool bRow1Hidden = RowHidden(nRow1);
- bool bRow2Hidden = RowHidden(nRow2);
- SetRowHidden(nRow1, nRow1, bRow2Hidden);
- SetRowHidden(nRow2, nRow2, bRow1Hidden);
-
- bool bRow1Filtered = RowFiltered(nRow1);
- bool bRow2Filtered = RowFiltered(nRow2);
- SetRowFiltered(nRow1, nRow1, bRow2Filtered);
- SetRowFiltered(nRow2, nRow2, bRow1Filtered);
- }
-}
-
short ScTable::Compare(SCCOLROW nIndex1, SCCOLROW nIndex2) const
{
short nRes;
@@ -662,12 +1001,15 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p
{
if(pProgress)
pProgress->SetState( 0, nLastRow-nRow1 );
- ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, nLastRow );
+
+ boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, nLastRow, bKeepQuery));
+
if ( nLastRow - nRow1 > 255 )
- DecoladeRow( pArray, nRow1, nLastRow );
- QuickSort( pArray, nRow1, nLastRow );
- SortReorder( pArray, pProgress );
- delete pArray;
+ DecoladeRow(pArray.get(), nRow1, nLastRow);
+
+ QuickSort(pArray.get(), nRow1, nLastRow);
+ SortReorder(pArray.get(), pProgress);
+
// #i59745# update position of caption objects of cell notes --> reported at (SortReorder) ScColumn::SwapCellNotes level
}
}
@@ -684,10 +1026,12 @@ void ScTable::Sort(const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* p
{
if(pProgress)
pProgress->SetState( 0, nLastCol-nCol1 );
- ScSortInfoArray* pArray = CreateSortInfoArray( nCol1, nLastCol );
- QuickSort( pArray, nCol1, nLastCol );
- SortReorder( pArray, pProgress );
- delete pArray;
+
+ boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nCol1, nLastCol, bKeepQuery));
+
+ QuickSort(pArray.get(), nCol1, nLastCol);
+ SortReorder(pArray.get(), pProgress);
+
// #i59745# update position of caption objects of cell notes --> reported at (SortReorder) ScColumn::SwapCellNotes level
}
}
@@ -1684,9 +2028,9 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
bSortCollatorInitialized = true;
InitSortCollator( aLocalSortParam );
}
- ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, rParam.nRow2 );
- DecoladeRow( pArray, nRow1, rParam.nRow2 );
- QuickSort( pArray, nRow1, rParam.nRow2 );
+ boost::scoped_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(nRow1, rParam.nRow2, bGlobalKeepQuery));
+ DecoladeRow( pArray.get(), nRow1, rParam.nRow2 );
+ QuickSort( pArray.get(), nRow1, rParam.nRow2 );
ScSortInfo** ppInfo = pArray->GetFirstArray();
SCSIZE nValidCount = nCount;
// keine Note-/Leerzellen zaehlen, sind ans Ende sortiert
@@ -1763,7 +2107,6 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
rItem.meType = ScQueryEntry::ByValue;
rItem.mfVal = 0;
}
- delete pArray;
}
break;
default: