Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/inc/sortparam.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#pragma once
21
22
535k
#define DEFSORT 3
23
24
#include <vector>
25
26
#include "address.hxx"
27
#include <com/sun/star/lang/Locale.hpp>
28
#include <com/sun/star/sheet/SortNumberBehavior.hpp>
29
#include "scdllapi.h"
30
#include "celltextattr.hxx"
31
#include "cellvalue.hxx"
32
#include "patattr.hxx"
33
#include <tools/color.hxx>
34
35
struct ScSubTotalParam;
36
struct ScQueryParam;
37
class SdrObject;
38
class ScPostIt;
39
40
enum class SortOrderType
41
{
42
    Ordered,
43
    Random
44
};
45
46
/** Sort by which color */
47
enum class ScColorSortMode {
48
    None,
49
    TextColor,
50
    BackgroundColor
51
};
52
53
/** Sort key state defines one way how to sort the range.
54
 *
55
 * A range of values can be sorted in multiple way, each column a different way.
56
 *
57
 * For example: sort column A ascending and if the column when there are same values, define that those should be
58
 * sorted descending usign the column C.
59
 **/
60
struct ScSortKeyState
61
{
62
    SCCOLROW nField = 0;
63
    bool bDoSort = false;
64
    bool bAscending = true;
65
    ScColorSortMode aColorSortMode = ScColorSortMode::None;
66
    Color aColorSortColor;
67
68
    bool operator==(const ScSortKeyState& rOther) const
69
0
    {
70
0
        return nField == rOther.nField
71
0
            && bDoSort == rOther.bDoSort
72
0
            && bAscending == rOther.bAscending
73
0
            && aColorSortMode == rOther.aColorSortMode
74
0
            && aColorSortColor == rOther.aColorSortColor;
75
0
    }
76
};
77
78
/** Struct to hold non-data extended area, used with
79
    ScDocument::ShrinkToUsedDataArea().
80
*/
81
struct ScDataAreaExtras
82
{
83
    /// If TRUE, consider the presence of cell notes besides data.
84
    bool    mbCellNotes = false;
85
    /// If TRUE, consider the presence of draw objects anchored to the cell.
86
    bool    mbCellDrawObjects = false;
87
    /// If TRUE, consider the presence of cell formats.
88
    bool    mbCellFormats = false;
89
    SCCOL   mnStartCol = SCCOL_MAX;
90
    SCROW   mnStartRow = SCROW_MAX;
91
    SCCOL   mnEndCol = -1;
92
    SCROW   mnEndRow = -1;
93
94
0
    bool anyExtrasWanted() const { return mbCellNotes || mbCellDrawObjects || mbCellFormats; }
95
0
    void resetArea() { mnStartCol = SCCOL_MAX; mnStartRow = SCROW_MAX; mnEndCol = -1; mnEndRow = -1; }
96
97
    bool operator==( const ScDataAreaExtras& rOther ) const
98
0
    {
99
        // Ignore area range, this is used in ScSortParam::operator==().
100
0
        return mbCellNotes       == rOther.mbCellNotes
101
0
            && mbCellDrawObjects == rOther.mbCellDrawObjects
102
0
            && mbCellFormats     == rOther.mbCellFormats;
103
0
    }
104
105
    enum class Clip
106
    {
107
        None,
108
        Col,
109
        Row
110
    };
111
112
    /// Obtain the overall range if area extras are larger.
113
    void GetOverallRange( SCCOL& nCol1, SCROW& nRow1, SCCOL& nCol2, SCROW& nRow2, Clip eClip = Clip::None ) const
114
0
    {
115
0
        if (eClip != Clip::Col)
116
0
        {
117
0
            if (nCol1 > mnStartCol)
118
0
                nCol1 = mnStartCol;
119
0
            if (nCol2 < mnEndCol)
120
0
                nCol2 = mnEndCol;
121
0
        }
122
0
        if (eClip != Clip::Row)
123
0
        {
124
0
            if (nRow1 > mnStartRow)
125
0
                nRow1 = mnStartRow;
126
0
            if (nRow2 < mnEndRow)
127
0
                nRow2 = mnEndRow;
128
0
        }
129
0
    }
130
131
    /// Set the overall range.
132
    void SetOverallRange( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
133
0
    {
134
0
        mnStartCol = nCol1;
135
0
        mnStartRow = nRow1;
136
0
        mnEndCol   = nCol2;
137
0
        mnEndRow   = nRow2;
138
0
    }
139
};
140
141
/** Specifies how numbers embedded in text are treated in text
142
    comparisons. The values correspond to the ODF attribute
143
    table:embedded-number-behavior (19.628, part 3 ODF 1.4).
144
*/
145
enum class ScSortNumberBehavior : sal_Int32
146
{
147
    ALPHA_NUMERIC = css::sheet::SortNumberBehavior::ALPHA_NUMERIC, // 0
148
    DOUBLE = css::sheet::SortNumberBehavior::DOUBLE, // 1
149
    INTEGER  = css::sheet::SortNumberBehavior::INTEGER, // 2
150
};
151
152
struct SC_DLLPUBLIC ScSortParam
153
{
154
    SCCOL       nCol1;
155
    SCROW       nRow1;
156
    SCCOL       nCol2;
157
    SCROW       nRow2;
158
    SCTAB       nSourceTab;
159
    ScDataAreaExtras aDataAreaExtras;
160
    sal_uInt16  nUserIndex;
161
    bool        bHasHeader;
162
    bool        bByRow;
163
    bool        bCaseSens;
164
    ScSortNumberBehavior eSortNumberBehavior;
165
    bool        bUserDef;
166
    bool        bInplace;
167
    SCTAB       nDestTab;
168
    SCCOL       nDestCol;
169
    SCROW       nDestRow;
170
    std::vector<ScSortKeyState> maKeyState;
171
    css::lang::Locale aCollatorLocale;
172
    OUString    aCollatorAlgorithm;
173
    sal_uInt16  nCompatHeader;
174
    SortOrderType meSortOrderType = SortOrderType::Ordered;
175
176
    ScSortParam();
177
    ScSortParam( const ScSortParam& r );
178
    /// SubTotals sort
179
    ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld );
180
    /// TopTen sort
181
    ScSortParam( const ScQueryParam&, SCCOL nCol );
182
    ~ScSortParam();
183
184
    ScSortParam&    operator=  ( const ScSortParam& r );
185
    bool            operator== ( const ScSortParam& rOther ) const;
186
    void            Clear       ();
187
    void            MoveToDest();
188
189
0
    sal_uInt16 GetSortKeyCount() const { return maKeyState.size(); }
190
};
191
192
struct ScSortInfo final
193
{
194
    ScRefCellValue maCell;
195
    SCCOLROW       nOrg;
196
};
197
198
class ScSortInfoArray
199
{
200
public:
201
202
    struct Cell
203
    {
204
        ScRefCellValue maCell;
205
        const sc::CellTextAttr* mpAttr;
206
        const ScPostIt* mpNote;
207
        std::vector<SdrObject*> maDrawObjects;
208
        CellAttributeHolder maPattern;
209
210
0
        Cell() : mpAttr(nullptr), mpNote(nullptr),  maPattern() {}
211
    };
212
213
    struct Row
214
    {
215
        std::vector<Cell> maCells;
216
217
        bool mbHidden:1;
218
        bool mbFiltered:1;
219
220
0
        explicit Row( size_t nColSize ) : maCells(nColSize, Cell()), mbHidden(false), mbFiltered(false) {}
221
    };
222
223
    typedef std::vector<Row> RowsType;
224
225
private:
226
    std::unique_ptr<RowsType> mpRows; /// row-wise data table for sort by row operation.
227
228
    std::vector<std::unique_ptr<ScSortInfo[]>> mvppInfo;
229
    SCCOLROW        nStart;
230
    SCCOLROW        mnLastIndex; /// index of last non-empty cell position.
231
232
    std::vector<SCCOLROW> maOrderIndices;
233
    bool mbKeepQuery;
234
    bool mbUpdateRefs;
235
236
public:
237
    ScSortInfoArray(const ScSortInfoArray&) = delete;
238
    const ScSortInfoArray& operator=(const ScSortInfoArray&) = delete;
239
240
    ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
241
0
        mvppInfo(nSorts),
242
0
        nStart( nInd1 ),
243
0
        mnLastIndex(nInd2),
244
0
        mbKeepQuery(false),
245
0
        mbUpdateRefs(false)
246
0
    {
247
0
        SCSIZE nCount( nInd2 - nInd1 + 1 );
248
0
        if (nSorts)
249
0
        {
250
0
            for ( sal_uInt16 nSort = 0; nSort < nSorts; nSort++ )
251
0
            {
252
0
                mvppInfo[nSort].reset(new ScSortInfo[nCount]);
253
0
            }
254
0
        }
255
256
0
        for (size_t i = 0; i < nCount; ++i)
257
0
            maOrderIndices.push_back(i+nStart);
258
0
    }
259
260
0
    void SetKeepQuery( bool b ) { mbKeepQuery = b; }
261
262
0
    bool IsKeepQuery() const { return mbKeepQuery; }
263
264
0
    void SetUpdateRefs( bool b ) { mbUpdateRefs = b; }
265
266
0
    bool IsUpdateRefs() const { return mbUpdateRefs; }
267
268
    /**
269
     * Call this only during normal sorting, not from reordering.
270
     */
271
    std::unique_ptr<ScSortInfo[]> const & GetFirstArray() const
272
0
    {
273
0
        return mvppInfo[0];
274
0
    }
275
276
    /**
277
     * Call this only during normal sorting, not from reordering.
278
     */
279
    ScSortInfo & Get( sal_uInt16 nSort, SCCOLROW nInd )
280
0
    {
281
0
        return mvppInfo[nSort][ nInd - nStart ];
282
0
    }
283
284
    /**
285
     * Call this only during normal sorting, not from reordering.
286
     */
287
    void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
288
0
    {
289
0
        if (nInd1 == nInd2) // avoid self-move-assign
290
0
            return;
291
0
        SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
292
0
        SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
293
0
        for ( sal_uInt16 nSort = 0; nSort < static_cast<sal_uInt16>(mvppInfo.size()); nSort++ )
294
0
        {
295
0
            auto & ppInfo = mvppInfo[nSort];
296
0
            std::swap(ppInfo[n1], ppInfo[n2]);
297
0
        }
298
299
0
        std::swap(maOrderIndices[n1], maOrderIndices[n2]);
300
301
0
        if (mpRows)
302
0
        {
303
            // Swap rows in data table.
304
0
            RowsType& rRows = *mpRows;
305
0
            std::swap(rRows[n1], rRows[n2]);
306
0
        }
307
0
    }
308
309
    void SetOrderIndices( std::vector<SCCOLROW>&& rIndices )
310
0
    {
311
0
        maOrderIndices = std::move(rIndices);
312
0
    }
313
314
    /**
315
     * @param rIndices indices are actual row positions on the sheet, not an
316
     *                 offset from the top row.
317
     */
318
    void ReorderByRow( const std::vector<SCCOLROW>& rIndices )
319
0
    {
320
0
        if (!mpRows)
321
0
            return;
322
323
0
        RowsType& rRows = *mpRows;
324
325
0
        std::vector<SCCOLROW> aOrderIndices2;
326
0
        aOrderIndices2.reserve(rIndices.size());
327
328
0
        RowsType aRows2;
329
0
        aRows2.reserve(rRows.size());
330
331
0
        for (const auto& rIndex : rIndices)
332
0
        {
333
0
            size_t nPos = rIndex - nStart; // switch to an offset to top row.
334
0
            aRows2.push_back(rRows[nPos]);
335
0
            aOrderIndices2.push_back(maOrderIndices[nPos]);
336
0
        }
337
338
0
        rRows.swap(aRows2);
339
0
        maOrderIndices.swap(aOrderIndices2);
340
0
    }
341
342
0
    sal_uInt16      GetUsedSorts() const { return mvppInfo.size(); }
343
344
0
    SCCOLROW    GetStart() const { return nStart; }
345
0
    SCCOLROW GetLast() const { return mnLastIndex; }
346
347
0
    const std::vector<SCCOLROW>& GetOrderIndices() const { return maOrderIndices; }
348
349
    RowsType& InitDataRows( size_t nRowSize, size_t nColSize )
350
0
    {
351
0
        mpRows.reset(new RowsType);
352
0
        mpRows->resize(nRowSize, Row(nColSize));
353
0
        return *mpRows;
354
0
    }
355
356
    RowsType* GetDataRows()
357
0
    {
358
0
        return mpRows.get();
359
0
    }
360
};
361
362
namespace sc {
363
364
struct ReorderParam
365
{
366
    /**
367
     * This sort range already takes into account the presence or absence of
368
     * header row / column i.e. if a header row / column is present, it
369
     * excludes that row / column.
370
     */
371
    ScRange maSortRange;
372
    ScDataAreaExtras maDataAreaExtras;
373
374
    /**
375
     * List of original column / row positions after reordering.
376
     */
377
    std::vector<SCCOLROW> maOrderIndices;
378
    bool mbByRow;
379
    bool mbHiddenFiltered;
380
    bool mbUpdateRefs;
381
    bool mbHasHeaders;
382
    bool mbShuffle;
383
384
    /**
385
     * Reorder the position indices such that it can be used to undo the
386
     * original reordering.
387
     */
388
    void reverse();
389
390
    ReorderParam()
391
0
        : mbByRow(false)
392
0
        , mbHiddenFiltered(false)
393
0
        , mbUpdateRefs(false)
394
0
        , mbHasHeaders(false)
395
0
        , mbShuffle(false)
396
0
    {
397
0
    }
398
};
399
400
}
401
402
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */