Avoid potential negative array index access to cached text.
[LibreOffice.git] / sc / inc / sortparam.hxx
blobb2bda019a91df98031a0877c24751152fe0ddb41
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #pragma once
22 #define DEFSORT 3
24 #include <vector>
26 #include "address.hxx"
27 #include <editeng/colritem.hxx>
28 #include <com/sun/star/lang/Locale.hpp>
29 #include "scdllapi.h"
30 #include "celltextattr.hxx"
31 #include "cellvalue.hxx"
32 #include "patattr.hxx"
34 struct ScSubTotalParam;
35 struct ScQueryParam;
36 class SdrObject;
37 class ScPostIt;
39 enum class ScColorSortMode {
40 None,
41 TextColor,
42 BackgroundColor
45 struct ScSortKeyState
47 SCCOLROW nField;
48 bool bDoSort;
49 bool bAscending;
50 ScColorSortMode aColorSortMode;
51 Color aColorSortColor;
54 /** Struct to hold non-data extended area, used with
55 ScDocument::ShrinkToUsedDataArea().
57 struct ScDataAreaExtras
59 /// If TRUE, consider the presence of cell notes besides data.
60 bool mbCellNotes = false;
61 /// If TRUE, consider the presence of draw objects anchored to the cell.
62 bool mbCellDrawObjects = false;
63 /// If TRUE, consider the presence of cell formats.
64 bool mbCellFormats = false;
65 SCCOL mnStartCol = SCCOL_MAX;
66 SCROW mnStartRow = SCROW_MAX;
67 SCCOL mnEndCol = -1;
68 SCROW mnEndRow = -1;
70 bool anyExtrasWanted() const { return mbCellNotes || mbCellDrawObjects || mbCellFormats; }
71 void resetArea() { mnStartCol = SCCOL_MAX; mnStartRow = SCROW_MAX; mnEndCol = -1; mnEndRow = -1; }
73 bool operator==( const ScDataAreaExtras& rOther ) const
75 // Ignore area range, this is used in ScSortParam::operator==().
76 return mbCellNotes == rOther.mbCellNotes
77 && mbCellDrawObjects == rOther.mbCellDrawObjects
78 && mbCellFormats == rOther.mbCellFormats;
81 enum class Clip
83 None,
84 Col,
85 Row
88 /// Obtain the overall range if area extras are larger.
89 void GetOverallRange( SCCOL& nCol1, SCROW& nRow1, SCCOL& nCol2, SCROW& nRow2, Clip eClip = Clip::None ) const
91 if (eClip != Clip::Col)
93 if (nCol1 > mnStartCol)
94 nCol1 = mnStartCol;
95 if (nCol2 < mnEndCol)
96 nCol2 = mnEndCol;
98 if (eClip != Clip::Row)
100 if (nRow1 > mnStartRow)
101 nRow1 = mnStartRow;
102 if (nRow2 < mnEndRow)
103 nRow2 = mnEndRow;
107 /// Set the overall range.
108 void SetOverallRange( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
110 mnStartCol = nCol1;
111 mnStartRow = nRow1;
112 mnEndCol = nCol2;
113 mnEndRow = nRow2;
117 struct SC_DLLPUBLIC ScSortParam
119 SCCOL nCol1;
120 SCROW nRow1;
121 SCCOL nCol2;
122 SCROW nRow2;
123 SCTAB nSourceTab;
124 ScDataAreaExtras aDataAreaExtras;
125 sal_uInt16 nUserIndex;
126 bool bHasHeader;
127 bool bByRow;
128 bool bCaseSens;
129 bool bNaturalSort;
130 bool bUserDef;
131 bool bInplace;
132 SCTAB nDestTab;
133 SCCOL nDestCol;
134 SCROW nDestRow;
135 ::std::vector<ScSortKeyState>
136 maKeyState;
137 css::lang::Locale aCollatorLocale;
138 OUString aCollatorAlgorithm;
139 sal_uInt16 nCompatHeader;
141 ScSortParam();
142 ScSortParam( const ScSortParam& r );
143 /// SubTotals sort
144 ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld );
145 /// TopTen sort
146 ScSortParam( const ScQueryParam&, SCCOL nCol );
147 ~ScSortParam();
149 ScSortParam& operator= ( const ScSortParam& r );
150 bool operator== ( const ScSortParam& rOther ) const;
151 void Clear ();
152 void MoveToDest();
154 sal_uInt16 GetSortKeyCount() const { return maKeyState.size(); }
157 struct ScSortInfo final
159 ScRefCellValue maCell;
160 SCCOLROW nOrg;
163 class ScSortInfoArray
165 public:
167 struct Cell
169 ScRefCellValue maCell;
170 const sc::CellTextAttr* mpAttr;
171 const ScPostIt* mpNote;
172 std::vector<SdrObject*> maDrawObjects;
173 const ScPatternAttr* mpPattern;
175 Cell() : mpAttr(nullptr), mpNote(nullptr), mpPattern(nullptr) {}
178 struct Row
180 std::vector<Cell> maCells;
182 bool mbHidden:1;
183 bool mbFiltered:1;
185 explicit Row( size_t nColSize ) : maCells(nColSize, Cell()), mbHidden(false), mbFiltered(false) {}
188 typedef std::vector<Row> RowsType;
190 private:
191 std::unique_ptr<RowsType> mpRows; /// row-wise data table for sort by row operation.
193 std::vector<std::unique_ptr<ScSortInfo[]>> mvppInfo;
194 SCCOLROW nStart;
195 SCCOLROW mnLastIndex; /// index of last non-empty cell position.
197 std::vector<SCCOLROW> maOrderIndices;
198 bool mbKeepQuery;
199 bool mbUpdateRefs;
201 public:
202 ScSortInfoArray(const ScSortInfoArray&) = delete;
203 const ScSortInfoArray& operator=(const ScSortInfoArray&) = delete;
205 ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
206 mvppInfo(nSorts),
207 nStart( nInd1 ),
208 mnLastIndex(nInd2),
209 mbKeepQuery(false),
210 mbUpdateRefs(false)
212 SCSIZE nCount( nInd2 - nInd1 + 1 );
213 if (nSorts)
215 for ( sal_uInt16 nSort = 0; nSort < nSorts; nSort++ )
217 mvppInfo[nSort].reset(new ScSortInfo[nCount]);
221 for (size_t i = 0; i < nCount; ++i)
222 maOrderIndices.push_back(i+nStart);
225 void SetKeepQuery( bool b ) { mbKeepQuery = b; }
227 bool IsKeepQuery() const { return mbKeepQuery; }
229 void SetUpdateRefs( bool b ) { mbUpdateRefs = b; }
231 bool IsUpdateRefs() const { return mbUpdateRefs; }
234 * Call this only during normal sorting, not from reordering.
236 std::unique_ptr<ScSortInfo[]> const & GetFirstArray() const
238 return mvppInfo[0];
242 * Call this only during normal sorting, not from reordering.
244 ScSortInfo & Get( sal_uInt16 nSort, SCCOLROW nInd )
246 return mvppInfo[nSort][ nInd - nStart ];
250 * Call this only during normal sorting, not from reordering.
252 void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
254 if (nInd1 == nInd2) // avoid self-move-assign
255 return;
256 SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
257 SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
258 for ( sal_uInt16 nSort = 0; nSort < static_cast<sal_uInt16>(mvppInfo.size()); nSort++ )
260 auto & ppInfo = mvppInfo[nSort];
261 std::swap(ppInfo[n1], ppInfo[n2]);
264 std::swap(maOrderIndices[n1], maOrderIndices[n2]);
266 if (mpRows)
268 // Swap rows in data table.
269 RowsType& rRows = *mpRows;
270 std::swap(rRows[n1], rRows[n2]);
274 void SetOrderIndices( std::vector<SCCOLROW>&& rIndices )
276 maOrderIndices = std::move(rIndices);
280 * @param rIndices indices are actual row positions on the sheet, not an
281 * offset from the top row.
283 void ReorderByRow( const std::vector<SCCOLROW>& rIndices )
285 if (!mpRows)
286 return;
288 RowsType& rRows = *mpRows;
290 std::vector<SCCOLROW> aOrderIndices2;
291 aOrderIndices2.reserve(rIndices.size());
293 RowsType aRows2;
294 aRows2.reserve(rRows.size());
296 for (const auto& rIndex : rIndices)
298 size_t nPos = rIndex - nStart; // switch to an offset to top row.
299 aRows2.push_back(rRows[nPos]);
300 aOrderIndices2.push_back(maOrderIndices[nPos]);
303 rRows.swap(aRows2);
304 maOrderIndices.swap(aOrderIndices2);
307 sal_uInt16 GetUsedSorts() const { return mvppInfo.size(); }
309 SCCOLROW GetStart() const { return nStart; }
310 SCCOLROW GetLast() const { return mnLastIndex; }
312 const std::vector<SCCOLROW>& GetOrderIndices() const { return maOrderIndices; }
314 RowsType& InitDataRows( size_t nRowSize, size_t nColSize )
316 mpRows.reset(new RowsType);
317 mpRows->resize(nRowSize, Row(nColSize));
318 return *mpRows;
321 RowsType* GetDataRows()
323 return mpRows.get();
327 namespace sc {
329 struct ReorderParam
332 * This sort range already takes into account the presence or absence of
333 * header row / column i.e. if a header row / column is present, it
334 * excludes that row / column.
336 ScRange maSortRange;
337 ScDataAreaExtras maDataAreaExtras;
340 * List of original column / row positions after reordering.
342 std::vector<SCCOLROW> maOrderIndices;
343 bool mbByRow;
344 bool mbHiddenFiltered;
345 bool mbUpdateRefs;
346 bool mbHasHeaders;
349 * Reorder the position indices such that it can be used to undo the
350 * original reordering.
352 void reverse();
354 ReorderParam()
355 : mbByRow(false)
356 , mbHiddenFiltered(false)
357 , mbUpdateRefs(false)
358 , mbHasHeaders(false)
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */