LCOV - code coverage report
Current view: top level - libreoffice/tools/source/memtools - multisel.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 86 397 21.7 %
Date: 2012-12-27 Functions: 10 32 31.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10