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