summaryrefslogtreecommitdiff
path: root/tools/inc/tools/multisel.hxx
blob: 678fc94a998af94dad5ab3cc4e5e6ecd2de11643 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef _SV_MULTISEL_HXX
#define _SV_MULTISEL_HXX

#include "tools/toolsdllapi.h"
#include <tools/gen.hxx>
#include <rtl/ustring.hxx>

#include <vector>
#include <set>

typedef ::std::vector< Range* > ImpSelList;

#define SFX_ENDOFSELECTION      ULONG_MAX

class TOOLS_DLLPUBLIC MultiSelection
{
private:
    ImpSelList      aSels;      // array of SV-selections
    Range           aTotRange;  // total range of indexes
    sal_uIntPtr     nCurSubSel; // index in aSels of current selected index
    long            nCurIndex;  // current selected entry
    sal_uIntPtr     nSelCount;  // number of selected indexes
    sal_Bool        bInverseCur;// inverse cursor
    sal_Bool        bCurValid;  // are nCurIndex and nCurSubSel valid
    sal_Bool        bSelectNew; // auto-select newly inserted indexes

#ifdef _SV_MULTISEL_CXX
    TOOLS_DLLPRIVATE void           ImplClear();
    TOOLS_DLLPRIVATE size_t         ImplFindSubSelection( long nIndex ) const;
    TOOLS_DLLPRIVATE sal_Bool       ImplMergeSubSelections( size_t nPos1, size_t nPos2 );
    TOOLS_DLLPRIVATE long           ImplFwdUnselected();
#endif

public:
                    MultiSelection();
                    MultiSelection( const MultiSelection& rOrig );
                    MultiSelection( const Range& rRange );
                    ~MultiSelection();

    MultiSelection& operator= ( const MultiSelection& rOrig );
    sal_Bool        operator== ( MultiSelection& rOrig );
    sal_Bool        operator!= ( MultiSelection& rOrig )
                        { return !operator==( rOrig ); }
    sal_Bool        operator !() const
                        { return nSelCount == 0; }

    void            SelectAll( sal_Bool bSelect = sal_True );
    sal_Bool        Select( long nIndex, sal_Bool bSelect = sal_True );
    void            Select( const Range& rIndexRange, sal_Bool bSelect = sal_True );
    sal_Bool        IsSelected( long nIndex ) const;
    sal_Bool        IsAllSelected() const
                        { return nSelCount == sal_uIntPtr(aTotRange.Len()); }
    long            GetSelectCount() const { return nSelCount; }

    void            SetTotalRange( const Range& rTotRange );
    void            Insert( long nIndex, long nCount = 1 );
    void            Remove( long nIndex );

    const Range&    GetTotalRange() const { return aTotRange; }
    sal_Bool        IsCurValid() const { return bCurValid; }
    long            GetCurSelected() const { return nCurIndex; }
    long            FirstSelected( sal_Bool bInverse = sal_False );
    long            LastSelected();
    long            NextSelected();

    size_t          GetRangeCount() const { return aSels.size(); }
    const Range&    GetRange( size_t nRange ) const {
                        return *(const Range*)aSels[nRange];
                    }
};

class TOOLS_DLLPUBLIC StringRangeEnumerator
{
    struct Range
    {
        sal_Int32   nFirst;
        sal_Int32   nLast;

        Range() : nFirst( -1 ), nLast( -1 ) {}
        Range( sal_Int32 i_nFirst, sal_Int32 i_nLast ) : nFirst( i_nFirst ), nLast( i_nLast ) {}
    };
    std::vector< StringRangeEnumerator::Range >            maSequence;
    sal_Int32                                              mnCount;
    sal_Int32                                              mnMin;
    sal_Int32                                              mnMax;
    sal_Int32                                              mnOffset;
    bool                                                   mbValidInput;

    bool setRange( const OUString& i_rNewRange, bool i_bStrict = false );
    bool insertRange( sal_Int32 nFirst, sal_Int32 nLast, bool bSequence, bool bMayAdjust );
    bool insertJoinedRanges( const std::vector< sal_Int32 >& rNumbers, bool i_bStrict );
    bool checkValue( sal_Int32, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
public:
    class TOOLS_DLLPUBLIC Iterator
    {
        const StringRangeEnumerator*      pEnumerator;
        const std::set< sal_Int32 >*      pPossibleValues;
        sal_Int32                         nRangeIndex;
        sal_Int32                         nCurrent;

        friend class StringRangeEnumerator;
        Iterator( const StringRangeEnumerator* i_pEnum,
                  const std::set< sal_Int32 >* i_pPossibleValues,
                  sal_Int32 i_nRange,
                  sal_Int32 i_nCurrent )
        : pEnumerator( i_pEnum ), pPossibleValues( i_pPossibleValues )
        , nRangeIndex( i_nRange ), nCurrent( i_nCurrent ) {}

    public:
        Iterator() : pEnumerator( NULL ), pPossibleValues( NULL ), nRangeIndex( -1 ), nCurrent( -1 ) {}
        Iterator& operator++();
        sal_Int32 operator*() const;
        bool operator==(const Iterator&) const;
        bool operator!=(const Iterator& i_rComp) const
        { return ! (*this == i_rComp); }
    };

    friend class StringRangeEnumerator::Iterator;

    StringRangeEnumerator( const OUString& i_rInput,
                           sal_Int32 i_nMinNumber,
                           sal_Int32 i_nMaxNumber,
                           sal_Int32 i_nLogicalOffset = -1
                           );

    sal_Int32 size() const { return mnCount; }
    Iterator begin( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;
    Iterator end( const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;

    bool isValidInput() const { return mbValidInput; }
    bool hasValue( sal_Int32 nValue, const std::set< sal_Int32 >* i_pPossibleValues = NULL ) const;

    /**
    i_rPageRange:     the string to be changed into a sequence of numbers
                      valid format example "5-3,9,9,7-8" ; instead of ',' ';' or ' ' are allowed as well
    o_rPageVector:    the output sequence of numbers
    i_nLogicalOffset: an offset to be applied to each number in the string before inserting it in the resulting sequence
                      example: a user enters page numbers from 1 to n (since that is logical)
                               of course usable page numbers in code would start from 0 and end at n-1
                               so the logical offset would be -1
    i_nMinNumber:     the minimum allowed number
    i_nMaxNumber:     the maximum allowed number

    @returns: true if the input string was valid, o_rPageVector will contain the resulting sequence
              false if the input string was invalid, o_rPageVector will contain
                    the sequence that parser is able to extract

    behavior:
    - only non-negative sequence numbers are allowed
    - only non-negative values in the input string are allowed
    - the string "-3" means the sequence i_nMinNumber to 3
    - the string "3-" means the sequence 3 to i_nMaxNumber
    - the string "-" means the sequence i_nMinNumber to i_nMaxNumber
    - single number that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be ignored
    - range that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be adjusted
    */
    static bool getRangesFromString( const OUString& i_rPageRange,
                                     std::vector< sal_Int32 >& o_rPageVector,
                                     sal_Int32 i_nMinNumber,
                                     sal_Int32 i_nMaxNumber,
                                     sal_Int32 i_nLogicalOffset = -1,
                                     std::set< sal_Int32 >* i_pPossibleValues = NULL
                                    );
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */