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