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 #include <tools/debug.hxx>
21 #include <tools/multisel.hxx>
22 
23 #include <rtl/ustrbuf.hxx>
24 
ImplClear()25 void MultiSelection::ImplClear()
26 {
27     // no selected indexes
28     nSelCount = 0;
29     aSels.clear();
30 }
31 
ImplFindSubSelection(sal_Int32 nIndex) const32 sal_Int32 MultiSelection::ImplFindSubSelection( sal_Int32 nIndex ) const
33 {
34     // iterate through the sub selections
35     sal_Int32 n = 0;
36     for ( ;
37           n < sal_Int32(aSels.size()) && nIndex > aSels[ n ].Max();
38           ++n ) {} /* empty loop */
39     return n;
40 }
41 
ImplMergeSubSelections(sal_Int32 nPos1,sal_Int32 nPos2)42 void MultiSelection::ImplMergeSubSelections( sal_Int32 nPos1, sal_Int32 nPos2 )
43 {
44     // didn't a sub selection at nPos2 exist?
45     if ( nPos2 >= sal_Int32(aSels.size()) )
46         return;
47 
48     // did the sub selections touch each other?
49     if ( (aSels[ nPos1 ].Max() + 1) == aSels[ nPos2 ].Min() )
50     {
51         // merge them
52         aSels[ nPos1 ].Max() = aSels[ nPos2 ].Max();
53         aSels.erase( aSels.begin() + nPos2 );
54     }
55 }
56 
MultiSelection()57 MultiSelection::MultiSelection():
58     aTotRange( 0, -1 ),
59     nCurSubSel(0),
60     nCurIndex(0),
61     nSelCount(0),
62     bCurValid(false)
63 {
64 }
65 
Reset()66 void MultiSelection::Reset()
67 {
68     aTotRange = Range(0, -1);
69     bCurValid = false;
70     // clear the old sub selections
71     ImplClear();
72 }
73 
MultiSelection(const MultiSelection & rOrig)74 MultiSelection::MultiSelection( const MultiSelection& rOrig ) :
75     aTotRange(rOrig.aTotRange),
76     nSelCount(rOrig.nSelCount),
77     bCurValid(rOrig.bCurValid)
78 {
79     if ( bCurValid )
80     {
81         nCurSubSel = rOrig.nCurSubSel;
82         nCurIndex = rOrig.nCurIndex;
83     }
84     else
85     {
86         nCurSubSel = 0;
87         nCurIndex = 0;
88     }
89 
90     // copy the sub selections
91     for (const Range & rSel : rOrig.aSels)
92         aSels.push_back( rSel );
93 }
94 
MultiSelection(const Range & rRange)95 MultiSelection::MultiSelection( const Range& rRange ):
96     aTotRange(rRange),
97     nCurSubSel(0),
98     nCurIndex(0),
99     nSelCount(0),
100     bCurValid(false)
101 {
102 }
103 
~MultiSelection()104 MultiSelection::~MultiSelection()
105 {
106 }
107 
operator =(const MultiSelection & rOrig)108 MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig )
109 {
110     aTotRange = rOrig.aTotRange;
111     bCurValid = rOrig.bCurValid;
112     if ( bCurValid )
113     {
114         nCurSubSel = rOrig.nCurSubSel;
115         nCurIndex = rOrig.nCurIndex;
116     }
117 
118     // clear the old and copy the sub selections
119     ImplClear();
120     for (const Range& rSel : rOrig.aSels)
121         aSels.push_back( rSel );
122     nSelCount = rOrig.nSelCount;
123 
124     return *this;
125 }
126 
SelectAll(bool bSelect)127 void MultiSelection::SelectAll( bool bSelect )
128 {
129     ImplClear();
130     if ( bSelect )
131     {
132         aSels.push_back( aTotRange );
133         nSelCount = aTotRange.Len();
134     }
135 }
136 
Select(sal_Int32 nIndex,bool bSelect)137 bool MultiSelection::Select( sal_Int32 nIndex, bool bSelect )
138 {
139     DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" );
140 
141     // out of range?
142     if ( !aTotRange.IsInside(nIndex) )
143         return false;
144 
145     // find the virtual target position
146     sal_Int32 nSubSelPos = ImplFindSubSelection( nIndex );
147 
148     if ( bSelect )
149     {
150         // is it included in the found sub selection?
151         if ( nSubSelPos < sal_Int32(aSels.size()) && aSels[ nSubSelPos ].IsInside( nIndex ) )
152             // already selected, nothing to do
153             return false;
154 
155         // it will become selected
156         ++nSelCount;
157 
158         // is it at the end of the previous sub selection
159         if ( nSubSelPos > 0 &&
160              aSels[ nSubSelPos-1 ].Max() == (nIndex-1) )
161         {
162             // expand the previous sub selection
163             aSels[ nSubSelPos-1 ].Max() = nIndex;
164 
165             // try to merge the previous sub selection
166             ImplMergeSubSelections( nSubSelPos-1, nSubSelPos );
167         }
168         // is it at the beginning of the found sub selection
169         else if (  nSubSelPos < sal_Int32(aSels.size())
170                 && aSels[ nSubSelPos ].Min() == (nIndex+1)
171         )
172             // expand the found sub selection
173             aSels[ nSubSelPos ].Min() = nIndex;
174         else
175         {
176             // create a new sub selection
177             if ( nSubSelPos < sal_Int32(aSels.size()) ) {
178                 aSels.insert( aSels.begin() + nSubSelPos, Range( nIndex, nIndex ) );
179             } else {
180                 aSels.push_back( Range( nIndex, nIndex ) );
181             }
182             if ( bCurValid && nCurSubSel >= nSubSelPos )
183                 ++nCurSubSel;
184         }
185     }
186     else
187     {
188         // is it excluded from the found sub selection?
189         if (  nSubSelPos >= sal_Int32(aSels.size())
190            || !aSels[ nSubSelPos ].IsInside( nIndex )
191         ) {
192             // not selected, nothing to do
193             return false;
194         }
195 
196         // it will become deselected
197         --nSelCount;
198 
199         // is it the only index in the found sub selection?
200         if ( aSels[ nSubSelPos ].Len() == 1 )
201         {
202             // remove the complete sub selection
203             aSels.erase( aSels.begin() + nSubSelPos );
204             return true;
205         }
206 
207         // is it at the beginning of the found sub selection?
208         if ( aSels[ nSubSelPos ].Min() == nIndex )
209             ++aSels[ nSubSelPos ].Min();
210         // is it at the end of the found sub selection?
211         else if ( aSels[ nSubSelPos ].Max() == nIndex )
212             --aSels[ nSubSelPos ].Max();
213         // it is in the middle of the found sub selection?
214         else
215         {
216             // split the sub selection
217             if ( nSubSelPos < sal_Int32(aSels.size()) ) {
218                 aSels.insert( aSels.begin() + nSubSelPos, Range( aSels[ nSubSelPos ].Min(), nIndex-1 ) );
219             } else {
220                 aSels.push_back( Range( aSels[ nSubSelPos ].Min(), nIndex-1 ) );
221             }
222             aSels[ nSubSelPos+1 ].Min() = nIndex + 1;
223         }
224     }
225 
226     return true;
227 }
228 
Select(const Range & rIndexRange,bool bSelect)229 void MultiSelection::Select( const Range& rIndexRange, bool bSelect )
230 {
231     sal_Int32 nOld;
232 
233     sal_Int32 nTmpMin = rIndexRange.Min();
234     sal_Int32 nTmpMax = rIndexRange.Max();
235     sal_Int32 nCurMin = FirstSelected();
236     sal_Int32 nCurMax = LastSelected();
237     DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" );
238     DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" );
239 
240     // replace whole selection?
241     if( aSels.empty() || (nTmpMin <= nCurMin && nTmpMax >= nCurMax ) )
242     {
243         ImplClear();
244         if ( bSelect )
245         {
246             aSels.push_back( rIndexRange );
247             nSelCount = rIndexRange.Len();
248         }
249         return;
250     }
251     // expand on left side?
252     if( nTmpMax < nCurMin )
253     {
254         if( bSelect )
255         {
256             // extend first range?
257             if( nCurMin > (nTmpMax+1)  )
258             {
259                 aSels.insert( aSels.begin(), rIndexRange );
260                 nSelCount += rIndexRange.Len();
261             }
262             else
263             {
264                 auto & rRange = aSels.front();
265                 nOld = rRange.Min();
266                 rRange.Min() = nTmpMin;
267                 nSelCount += ( nOld - nTmpMin );
268             }
269             bCurValid = false;
270         }
271         return;
272     }
273     // expand on right side?
274     else if( nTmpMin > nCurMax )
275     {
276         if( bSelect )
277         {
278             // extend last range?
279             if( nTmpMin > (nCurMax+1) )
280             {
281                 aSels.push_back( rIndexRange );
282                 nSelCount += rIndexRange.Len();
283             }
284             else
285             {
286                 auto & rRange = aSels.back();
287                 nOld = rRange.Max();
288                 rRange.Max() = nTmpMax;
289                 nSelCount += ( nTmpMax - nOld );
290             }
291             bCurValid = false;
292         }
293         return;
294     }
295 
296     // TODO here is potential for optimization
297     while( nTmpMin <= nTmpMax )
298     {
299         Select( nTmpMin, bSelect );
300         nTmpMin++;
301     }
302 }
303 
IsSelected(sal_Int32 nIndex) const304 bool MultiSelection::IsSelected( sal_Int32 nIndex ) const
305 {
306     // find the virtual target position
307     sal_Int32 nSubSelPos = ImplFindSubSelection( nIndex );
308 
309     return nSubSelPos < sal_Int32(aSels.size()) && aSels[ nSubSelPos ].IsInside(nIndex);
310 }
311 
Insert(sal_Int32 nIndex,sal_Int32 nCount)312 void MultiSelection::Insert( sal_Int32 nIndex, sal_Int32 nCount )
313 {
314     // find the virtual target position
315     sal_Int32 nSubSelPos = ImplFindSubSelection( nIndex );
316 
317     // did we need to shift the sub selections?
318     if ( nSubSelPos < sal_Int32(aSels.size()) )
319     {   // did we insert an unselected into an existing sub selection?
320         if (  aSels[ nSubSelPos ].Min() != nIndex
321            && aSels[ nSubSelPos ].IsInside(nIndex)
322         ) { // split the sub selection
323             if ( nSubSelPos < sal_Int32(aSels.size()) ) {
324                 aSels.insert( aSels.begin() + nSubSelPos, Range( aSels[ nSubSelPos ].Min(), nIndex-1 ) );
325             } else {
326                 aSels.push_back( Range( aSels[ nSubSelPos ].Min(), nIndex-1 ) );
327             }
328             ++nSubSelPos;
329             aSels[ nSubSelPos ].Min() = nIndex;
330         }
331 
332         // shift the sub selections behind the inserting position
333         for ( sal_Int32 nPos = nSubSelPos; nPos < sal_Int32(aSels.size()); ++nPos )
334         {
335             aSels[ nPos ].Min() += nCount;
336             aSels[ nPos ].Max() += nCount;
337         }
338     }
339 
340     bCurValid = false;
341     aTotRange.Max() += nCount;
342 }
343 
Remove(sal_Int32 nIndex)344 void MultiSelection::Remove( sal_Int32 nIndex )
345 {
346     // find the virtual target position
347     sal_Int32 nSubSelPos = ImplFindSubSelection( nIndex );
348 
349     // did we remove from an existing sub selection?
350     if (  nSubSelPos < sal_Int32(aSels.size())
351        && aSels[ nSubSelPos ].IsInside(nIndex)
352     ) {
353         // does this sub selection only contain the index to be deleted
354         if ( aSels[ nSubSelPos ].Len() == 1 ) {
355             // completely remove the sub selection
356             aSels.erase( aSels.begin() + nSubSelPos );
357         } else {
358             // shorten this sub selection
359             --( aSels[ nSubSelPos++ ].Max() );
360         }
361 
362         // adjust the selected counter
363         --nSelCount;
364     }
365 
366     // shift the sub selections behind the removed index
367     for ( sal_Int32 nPos = nSubSelPos; nPos < sal_Int32(aSels.size()); ++nPos )
368     {
369         --( aSels[ nPos ].Min() );
370         --( aSels[ nPos ].Max() );
371     }
372 
373     bCurValid = false;
374     aTotRange.Max() -= 1;
375 }
376 
FirstSelected()377 sal_Int32 MultiSelection::FirstSelected()
378 {
379     nCurSubSel = 0;
380 
381     bCurValid = !aSels.empty();
382     if ( bCurValid )
383         return nCurIndex = aSels[ 0 ].Min();
384 
385     return SFX_ENDOFSELECTION;
386 }
387 
LastSelected()388 sal_Int32 MultiSelection::LastSelected()
389 {
390     nCurSubSel = aSels.size() - 1;
391     bCurValid = !aSels.empty();
392 
393     if ( bCurValid )
394         return nCurIndex = aSels[ nCurSubSel ].Max();
395 
396     return SFX_ENDOFSELECTION;
397 }
398 
NextSelected()399 sal_Int32 MultiSelection::NextSelected()
400 {
401     if ( !bCurValid )
402         return SFX_ENDOFSELECTION;
403 
404     // is the next index in the current sub selection too?
405     if ( nCurIndex < aSels[ nCurSubSel ].Max() )
406         return ++nCurIndex;
407 
408     // are there further sub selections?
409     if ( ++nCurSubSel < sal_Int32(aSels.size()) )
410         return nCurIndex = aSels[ nCurSubSel ].Min();
411 
412     // we are at the end!
413     return SFX_ENDOFSELECTION;
414 }
415 
SetTotalRange(const Range & rTotRange)416 void MultiSelection::SetTotalRange( const Range& rTotRange )
417 {
418     aTotRange = rTotRange;
419 
420     // adjust lower boundary
421     Range* pRange = aSels.empty() ? nullptr : &aSels.front();
422     while( pRange )
423     {
424         if( pRange->Max() < aTotRange.Min() )
425         {
426             aSels.erase( aSels.begin() );
427         }
428         else if( pRange->Min() < aTotRange.Min() )
429         {
430             pRange->Min() = aTotRange.Min();
431             break;
432         }
433         else
434             break;
435 
436         pRange = aSels.empty() ? nullptr : &aSels.front();
437     }
438 
439     // adjust upper boundary
440     sal_Int32 nCount = aSels.size();
441     while( nCount )
442     {
443         pRange = &aSels[ nCount - 1 ];
444         if( pRange->Min() > aTotRange.Max() )
445         {
446             aSels.pop_back();
447         }
448         else if( pRange->Max() > aTotRange.Max() )
449         {
450             pRange->Max() = aTotRange.Max();
451             break;
452         }
453         else
454             break;
455 
456         nCount = aSels.size();
457     }
458 
459     // re-calculate selection count
460     nSelCount = 0;
461     for (Range const & rSel : aSels)
462         nSelCount += rSel.Len();
463 
464     bCurValid = false;
465     nCurIndex = 0;
466 }
467 
468 // StringRangeEnumerator
469 
StringRangeEnumerator(const OUString & i_rInput,sal_Int32 i_nMinNumber,sal_Int32 i_nMaxNumber,sal_Int32 i_nLogicalOffset)470 StringRangeEnumerator::StringRangeEnumerator( const OUString& i_rInput,
471                                               sal_Int32 i_nMinNumber,
472                                               sal_Int32 i_nMaxNumber,
473                                               sal_Int32 i_nLogicalOffset
474                                               )
475     : mnCount( 0 )
476     , mnMin( i_nMinNumber )
477     , mnMax( i_nMaxNumber )
478     , mnOffset( i_nLogicalOffset )
479     , mbValidInput( false )
480 {
481     // Parse string only if boundaries are valid.
482     if( mnMin >= 0 && mnMax >= 0 && mnMin <= mnMax )
483         mbValidInput = setRange( i_rInput );
484 }
485 
checkValue(sal_Int32 i_nValue,const std::set<sal_Int32> * i_pPossibleValues) const486 bool StringRangeEnumerator::checkValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const
487 {
488     if( i_nValue < 0 || i_nValue < mnMin || i_nValue > mnMax )
489         return false;
490     if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() )
491         return false;
492     return true;
493 }
494 
insertRange(sal_Int32 i_nFirst,sal_Int32 i_nLast,bool bSequence)495 bool StringRangeEnumerator::insertRange( sal_Int32 i_nFirst, sal_Int32 i_nLast, bool bSequence )
496 {
497     bool bSuccess = true;
498     if( bSequence )
499     {
500         // Check if the range is completely outside of possible pages range
501         if ((i_nFirst < mnMin && i_nLast < mnMin) ||
502             (i_nFirst > mnMax && i_nLast > mnMax))
503             return false;
504         if( i_nFirst < mnMin )
505             i_nFirst = mnMin;
506         if( i_nFirst > mnMax )
507             i_nFirst = mnMax;
508         if( i_nLast < mnMin )
509             i_nLast = mnMin;
510         if( i_nLast > mnMax )
511             i_nLast = mnMax;
512         if( checkValue( i_nFirst ) && checkValue( i_nLast ) )
513         {
514             maSequence.push_back( Range( i_nFirst, i_nLast ) );
515             sal_Int32 nNumber = i_nLast - i_nFirst;
516             nNumber = nNumber < 0 ? -nNumber : nNumber;
517             mnCount += nNumber + 1;
518         }
519         else
520             bSuccess = false;
521     }
522     else
523     {
524         if( checkValue( i_nFirst ) )
525         {
526             maSequence.push_back( Range( i_nFirst, i_nFirst ) );
527             mnCount++;
528         }
529         else if( checkValue( i_nLast ) )
530         {
531             maSequence.push_back( Range( i_nLast, i_nLast ) );
532             mnCount++;
533         }
534         else
535             bSuccess = false;
536     }
537 
538     return bSuccess;
539 }
540 
insertJoinedRanges(const std::vector<sal_Int32> & rNumbers)541 void StringRangeEnumerator::insertJoinedRanges(
542     const std::vector< sal_Int32 >& rNumbers )
543 {
544     size_t nCount = rNumbers.size();
545     if( nCount == 0 )
546         return;
547 
548     if( nCount == 1 )
549     {
550         insertRange( rNumbers[0], -1, false );
551         return;
552     }
553 
554     for( size_t i = 0; i < nCount - 1; i++ )
555     {
556         sal_Int32 nFirst = rNumbers[i];
557         sal_Int32 nLast  = rNumbers[i + 1];
558         if( i > 0 )
559         {
560             if     ( nFirst > nLast ) nFirst--;
561             else if( nFirst < nLast ) nFirst++;
562         }
563 
564         insertRange( nFirst, nLast, nFirst != nLast );
565     }
566 }
567 
setRange(const OUString & i_rNewRange)568 bool StringRangeEnumerator::setRange( const OUString& i_rNewRange )
569 {
570     mnCount = 0;
571     maSequence.clear();
572 
573     const sal_Unicode* pInput = i_rNewRange.getStr();
574     OUStringBuffer aNumberBuf( 16 );
575     std::vector< sal_Int32 > aNumbers;
576     bool bSequence = false;
577     while( *pInput )
578     {
579         while( *pInput >= '0' && *pInput <= '9' )
580             aNumberBuf.append( *pInput++ );
581         if( !aNumberBuf.isEmpty() )
582         {
583             sal_Int32 nNumber = aNumberBuf.makeStringAndClear().toInt32() + mnOffset;
584             aNumbers.push_back( nNumber );
585             bSequence = false;
586         }
587 
588         if( *pInput == '-' )
589         {
590             bSequence = true;
591             if( aNumbers.empty() )
592             {
593                 // push out-of-range small value, to exclude ranges totally outside of possible range
594                 aNumbers.push_back( mnMin-1 );
595             }
596         }
597         else if( *pInput == ',' || *pInput == ';' )
598         {
599             if( bSequence && !aNumbers.empty() )
600             {
601                 // push out-of-range large value, to exclude ranges totally outside of possible range
602                 aNumbers.push_back( mnMax+1 );
603             }
604             insertJoinedRanges( aNumbers );
605 
606             aNumbers.clear();
607             bSequence = false;
608         }
609         else if( *pInput && *pInput != ' ' )
610             return false; // parse error
611 
612         if( *pInput )
613             pInput++;
614     }
615     // insert last entries
616     if( bSequence && !aNumbers.empty() )
617     {
618         // push out-of-range large value, to exclude ranges totally outside of possible range
619         aNumbers.push_back( mnMax+1 );
620     }
621     insertJoinedRanges( aNumbers );
622 
623     return true;
624 }
625 
hasValue(sal_Int32 i_nValue,const std::set<sal_Int32> * i_pPossibleValues) const626 bool StringRangeEnumerator::hasValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const
627 {
628     if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() )
629         return false;
630     size_t n = maSequence.size();
631     for( size_t i= 0; i < n; ++i )
632     {
633         const StringRangeEnumerator::Range rRange( maSequence[i] );
634         if( rRange.nFirst < rRange.nLast )
635         {
636             if( i_nValue >= rRange.nFirst && i_nValue <= rRange.nLast )
637                 return true;
638         }
639         else
640         {
641             if( i_nValue >= rRange.nLast && i_nValue <= rRange.nFirst )
642                 return true;
643         }
644     }
645     return false;
646 }
647 
operator ++()648 StringRangeEnumerator::Iterator& StringRangeEnumerator::Iterator::operator++()
649 {
650     if( nRangeIndex >= 0 && nCurrent >= 0 && pEnumerator )
651     {
652         const StringRangeEnumerator::Range& rRange( pEnumerator->maSequence[nRangeIndex] );
653         bool bRangeChange = false;
654         if( rRange.nLast < rRange.nFirst )
655         {
656             // backward range
657             if( nCurrent > rRange.nLast )
658                 nCurrent--;
659             else
660                 bRangeChange = true;
661         }
662         else
663         {
664             // forward range
665             if( nCurrent < rRange.nLast )
666                 nCurrent++;
667             else
668                 bRangeChange = true;
669         }
670         if( bRangeChange )
671         {
672             nRangeIndex++;
673             if( size_t(nRangeIndex) == pEnumerator->maSequence.size() )
674             {
675                 // reached the end
676                 nRangeIndex = nCurrent = -1;
677             }
678             else
679                 nCurrent = pEnumerator->maSequence[nRangeIndex].nFirst;
680         }
681         if( nRangeIndex != -1 && nCurrent != -1 )
682         {
683             if( ! pEnumerator->checkValue( nCurrent, pPossibleValues ) )
684                 return ++(*this);
685         }
686     }
687     return *this;
688 }
689 
690 
operator ==(const Iterator & i_rCompare) const691 bool StringRangeEnumerator::Iterator::operator==( const Iterator& i_rCompare ) const
692 {
693     return i_rCompare.pEnumerator == pEnumerator && i_rCompare.nRangeIndex == nRangeIndex && i_rCompare.nCurrent == nCurrent;
694 }
695 
begin(const std::set<sal_Int32> * i_pPossibleValues) const696 StringRangeEnumerator::Iterator StringRangeEnumerator::begin( const std::set< sal_Int32 >* i_pPossibleValues ) const
697 {
698     StringRangeEnumerator::Iterator it( this,
699                                         i_pPossibleValues,
700                                         maSequence.empty() ? -1 : 0,
701                                         maSequence.empty() ? -1 : maSequence[0].nFirst );
702     if( ! checkValue(*it, i_pPossibleValues ) )
703         ++it;
704     return it;
705 }
706 
end(const std::set<sal_Int32> * i_pPossibleValues) const707 StringRangeEnumerator::Iterator StringRangeEnumerator::end( const std::set< sal_Int32 >* i_pPossibleValues ) const
708 {
709     return StringRangeEnumerator::Iterator( this, i_pPossibleValues, -1, -1 );
710 }
711 
getRangesFromString(const OUString & i_rPageRange,std::vector<sal_Int32> & o_rPageVector,sal_Int32 i_nMinNumber,sal_Int32 i_nMaxNumber,sal_Int32 i_nLogicalOffset,std::set<sal_Int32> const * i_pPossibleValues)712 bool StringRangeEnumerator::getRangesFromString( const OUString& i_rPageRange,
713                                                  std::vector< sal_Int32 >& o_rPageVector,
714                                                  sal_Int32 i_nMinNumber,
715                                                  sal_Int32 i_nMaxNumber,
716                                                  sal_Int32 i_nLogicalOffset,
717                                                  std::set< sal_Int32 > const * i_pPossibleValues
718                                                )
719 {
720     o_rPageVector.clear();
721 
722     StringRangeEnumerator aEnum( i_rPageRange, i_nMinNumber, i_nMaxNumber, i_nLogicalOffset ) ;
723 
724     //Even if the input range wasn't completely valid, return what ranges could
725     //be extracted from the input.
726     o_rPageVector.reserve( static_cast< size_t >( aEnum.size() ) );
727     for( StringRangeEnumerator::Iterator it = aEnum.begin( i_pPossibleValues );
728          it != aEnum.end( i_pPossibleValues ); ++it )
729     {
730         o_rPageVector.push_back( *it );
731     }
732 
733     return aEnum.mbValidInput;
734 }
735 
736 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
737