1*89b56da7SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*89b56da7SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*89b56da7SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*89b56da7SAndrew Rist * distributed with this work for additional information 6*89b56da7SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*89b56da7SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*89b56da7SAndrew Rist * "License"); you may not use this file except in compliance 9*89b56da7SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*89b56da7SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*89b56da7SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*89b56da7SAndrew Rist * software distributed under the License is distributed on an 15*89b56da7SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*89b56da7SAndrew Rist * KIND, either express or implied. See the License for the 17*89b56da7SAndrew Rist * specific language governing permissions and limitations 18*89b56da7SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*89b56da7SAndrew Rist *************************************************************/ 21*89b56da7SAndrew Rist 22*89b56da7SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_tools.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #define _SV_MULTISEL_CXX 28cdf0e10cSrcweir 29cdf0e10cSrcweir #ifdef MI_DEBUG 30cdf0e10cSrcweir #define private public 31cdf0e10cSrcweir #include <stdio.h> 32cdf0e10cSrcweir #endif 33cdf0e10cSrcweir 34cdf0e10cSrcweir #include <tools/debug.hxx> 35cdf0e10cSrcweir #include <tools/multisel.hxx> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #include "rtl/ustrbuf.hxx" 38cdf0e10cSrcweir 39cdf0e10cSrcweir #ifdef MI_DEBUG 40cdf0e10cSrcweir #define DBG(x) x 41cdf0e10cSrcweir #else 42cdf0e10cSrcweir #define DBG(x) 43cdf0e10cSrcweir #endif 44cdf0e10cSrcweir 45cdf0e10cSrcweir using namespace rtl; 46cdf0e10cSrcweir 47cdf0e10cSrcweir //================================================================== 48cdf0e10cSrcweir 49cdf0e10cSrcweir #ifdef MI_DEBUG 50cdf0e10cSrcweir 51cdf0e10cSrcweir static void Print( const MultiSelection* pSel ) 52cdf0e10cSrcweir { 53cdf0e10cSrcweir DbgOutf( "TotRange: %4ld-%4ld\n", 54cdf0e10cSrcweir pSel->aTotRange.Min(), pSel->aTotRange.Max() ); 55cdf0e10cSrcweir if ( pSel->bCurValid ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir DbgOutf( "CurSubSel: %4ld\n", pSel->nCurSubSel ); 58cdf0e10cSrcweir DbgOutf( "CurIndex: %4ld\n", pSel->nCurIndex ); 59cdf0e10cSrcweir } 60cdf0e10cSrcweir DbgOutf( "SelCount: %4ld\n", pSel->nSelCount ); 61cdf0e10cSrcweir DbgOutf( "SubCount: %4ld\n", pSel->aSels.Count() ); 62cdf0e10cSrcweir for ( sal_uIntPtr nPos = 0; nPos < pSel->aSels.Count(); ++nPos ) 63cdf0e10cSrcweir { 64cdf0e10cSrcweir DbgOutf( "SubSel #%2ld: %4ld-%4ld\n", nPos, 65cdf0e10cSrcweir pSel->aSels.GetObject(nPos)->Min(), 66cdf0e10cSrcweir pSel->aSels.GetObject(nPos)->Max() ); 67cdf0e10cSrcweir } 68cdf0e10cSrcweir DbgOutf( "\n" ); 69cdf0e10cSrcweir fclose( pFile ); 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir #endif 73cdf0e10cSrcweir 74cdf0e10cSrcweir // ----------------------------------------------------------------------- 75cdf0e10cSrcweir 76cdf0e10cSrcweir void MultiSelection::ImplClear() 77cdf0e10cSrcweir { 78cdf0e10cSrcweir // no selected indexes 79cdf0e10cSrcweir nSelCount = 0; 80cdf0e10cSrcweir 81cdf0e10cSrcweir Range* pRange = aSels.First(); 82cdf0e10cSrcweir while ( pRange ) 83cdf0e10cSrcweir { 84cdf0e10cSrcweir delete pRange; 85cdf0e10cSrcweir pRange = aSels.Next(); 86cdf0e10cSrcweir } 87cdf0e10cSrcweir aSels.Clear(); 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir // ----------------------------------------------------------------------- 91cdf0e10cSrcweir 92cdf0e10cSrcweir sal_uIntPtr MultiSelection::ImplFindSubSelection( long nIndex ) const 93cdf0e10cSrcweir { 94cdf0e10cSrcweir // iterate through the sub selections 95cdf0e10cSrcweir sal_uIntPtr n = 0; 96cdf0e10cSrcweir for ( ; 97cdf0e10cSrcweir n < aSels.Count() && nIndex > aSels.GetObject(n)->Max(); 98cdf0e10cSrcweir ++n ) {} /* empty loop */ 99cdf0e10cSrcweir return n; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir // ----------------------------------------------------------------------- 103cdf0e10cSrcweir 104cdf0e10cSrcweir sal_Bool MultiSelection::ImplMergeSubSelections( sal_uIntPtr nPos1, sal_uIntPtr nPos2 ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir // didn't a sub selection at nPos2 exist? 107cdf0e10cSrcweir if ( nPos2 >= aSels.Count() ) 108cdf0e10cSrcweir return sal_False; 109cdf0e10cSrcweir 110cdf0e10cSrcweir // did the sub selections touch each other? 111cdf0e10cSrcweir if ( (aSels.GetObject(nPos1)->Max() + 1) == aSels.GetObject(nPos2)->Min() ) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir // merge them 114cdf0e10cSrcweir aSels.GetObject(nPos1)->Max() = aSels.GetObject(nPos2)->Max(); 115cdf0e10cSrcweir delete aSels.Remove(nPos2); 116cdf0e10cSrcweir return sal_True; 117cdf0e10cSrcweir } 118cdf0e10cSrcweir 119cdf0e10cSrcweir return sal_False; 120cdf0e10cSrcweir } 121cdf0e10cSrcweir 122cdf0e10cSrcweir // ----------------------------------------------------------------------- 123cdf0e10cSrcweir 124cdf0e10cSrcweir MultiSelection::MultiSelection(): 125cdf0e10cSrcweir aTotRange( 0, -1 ), 126cdf0e10cSrcweir nCurSubSel(0), 127cdf0e10cSrcweir nSelCount(0), 128cdf0e10cSrcweir bCurValid(sal_False), 129cdf0e10cSrcweir bSelectNew(sal_False) 130cdf0e10cSrcweir { 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir // ----------------------------------------------------------------------- 134cdf0e10cSrcweir 135cdf0e10cSrcweir MultiSelection::MultiSelection( const UniString& rString, sal_Unicode cRange, sal_Unicode cSep ): 136cdf0e10cSrcweir aTotRange(0,RANGE_MAX), 137cdf0e10cSrcweir nCurSubSel(0), 138cdf0e10cSrcweir nSelCount(0), 139cdf0e10cSrcweir bCurValid(sal_False), 140cdf0e10cSrcweir bSelectNew(sal_False) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir // Dies ist nur ein Schnellschuss und sollte bald optimiert, 143cdf0e10cSrcweir // an die verschiedenen Systeme (UNIX etc.) 144cdf0e10cSrcweir // und die gewuenschte Eingabe-Syntax angepasst werden. 145cdf0e10cSrcweir 146cdf0e10cSrcweir UniString aStr( rString ); 147cdf0e10cSrcweir sal_Unicode* pStr = aStr.GetBufferAccess(); 148cdf0e10cSrcweir sal_Unicode* pOld = pStr; 149cdf0e10cSrcweir sal_Bool bReady = sal_False; 150cdf0e10cSrcweir sal_Bool bUntil = sal_False; 151cdf0e10cSrcweir xub_StrLen nCut = 0; 152cdf0e10cSrcweir 153cdf0e10cSrcweir // Hier normieren wir den String, sodass nur Ziffern, 154cdf0e10cSrcweir // Semikola als Trenn- und Minus als VonBis-Zeichen 155cdf0e10cSrcweir // uebrigbleiben, z.B. "99-117;55;34;-17;37-43" 156cdf0e10cSrcweir while ( *pOld ) 157cdf0e10cSrcweir { 158cdf0e10cSrcweir switch( *pOld ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir case '0': 161cdf0e10cSrcweir case '1': 162cdf0e10cSrcweir case '2': 163cdf0e10cSrcweir case '3': 164cdf0e10cSrcweir case '4': 165cdf0e10cSrcweir case '5': 166cdf0e10cSrcweir case '6': 167cdf0e10cSrcweir case '7': 168cdf0e10cSrcweir case '8': 169cdf0e10cSrcweir case '9': 170cdf0e10cSrcweir DBG_ASSERT( *pOld != cRange, "digit for range char not allowed" ); 171cdf0e10cSrcweir DBG_ASSERT( *pOld != cSep, "digit for separator not allowed" ); 172cdf0e10cSrcweir if( bReady ) 173cdf0e10cSrcweir { 174cdf0e10cSrcweir *pStr++ = ';'; 175cdf0e10cSrcweir nCut++; 176cdf0e10cSrcweir bReady = sal_False; 177cdf0e10cSrcweir } 178cdf0e10cSrcweir *pStr++ = *pOld; 179cdf0e10cSrcweir nCut++; 180cdf0e10cSrcweir bUntil = sal_False; 181cdf0e10cSrcweir break; 182cdf0e10cSrcweir 183cdf0e10cSrcweir case '-': 184cdf0e10cSrcweir case ':': 185cdf0e10cSrcweir case '/': 186cdf0e10cSrcweir if ( *pOld != cSep ) 187cdf0e10cSrcweir { 188cdf0e10cSrcweir if ( !bUntil ) 189cdf0e10cSrcweir { 190cdf0e10cSrcweir *pStr++ = '-'; 191cdf0e10cSrcweir nCut++; 192cdf0e10cSrcweir bUntil = sal_True; 193cdf0e10cSrcweir } 194cdf0e10cSrcweir bReady = sal_False; 195cdf0e10cSrcweir } 196cdf0e10cSrcweir else 197cdf0e10cSrcweir bReady = sal_True; 198cdf0e10cSrcweir break; 199cdf0e10cSrcweir 200cdf0e10cSrcweir case ' ': 201cdf0e10cSrcweir DBG_ASSERT( *pOld != cRange, "SPACE for range char not allowed" ); 202cdf0e10cSrcweir DBG_ASSERT( *pOld != cSep, "SPACE for separator not allowed" ); 203cdf0e10cSrcweir bReady = !bUntil; 204cdf0e10cSrcweir break; 205cdf0e10cSrcweir 206cdf0e10cSrcweir default: 207cdf0e10cSrcweir if ( *pOld == cRange ) 208cdf0e10cSrcweir { 209cdf0e10cSrcweir if ( !bUntil ) 210cdf0e10cSrcweir { 211cdf0e10cSrcweir *pStr++ = '-'; 212cdf0e10cSrcweir nCut++; 213cdf0e10cSrcweir bUntil = sal_True; 214cdf0e10cSrcweir } 215cdf0e10cSrcweir bReady = sal_False; 216cdf0e10cSrcweir } 217cdf0e10cSrcweir else 218cdf0e10cSrcweir bReady = sal_True; 219cdf0e10cSrcweir break; 220cdf0e10cSrcweir } 221cdf0e10cSrcweir 222cdf0e10cSrcweir pOld++; 223cdf0e10cSrcweir } 224cdf0e10cSrcweir aStr.ReleaseBufferAccess( nCut ); 225cdf0e10cSrcweir 226cdf0e10cSrcweir // Jetzt wird der normierte String ausgewertet .. 227cdf0e10cSrcweir UniString aNumStr; 228cdf0e10cSrcweir Range aRg( 1, RANGE_MAX ); 229cdf0e10cSrcweir const sal_Unicode* pCStr = aStr.GetBuffer(); 230cdf0e10cSrcweir long nPage = 1; 231cdf0e10cSrcweir long nNum = 1; 232cdf0e10cSrcweir bUntil = sal_False; 233cdf0e10cSrcweir while ( *pCStr ) 234cdf0e10cSrcweir { 235cdf0e10cSrcweir switch ( *pCStr ) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir case '0': 238cdf0e10cSrcweir case '1': 239cdf0e10cSrcweir case '2': 240cdf0e10cSrcweir case '3': 241cdf0e10cSrcweir case '4': 242cdf0e10cSrcweir case '5': 243cdf0e10cSrcweir case '6': 244cdf0e10cSrcweir case '7': 245cdf0e10cSrcweir case '8': 246cdf0e10cSrcweir case '9': 247cdf0e10cSrcweir aNumStr += *pCStr; 248cdf0e10cSrcweir break; 249cdf0e10cSrcweir case ';': 250cdf0e10cSrcweir nNum = aNumStr.ToInt32(); 251cdf0e10cSrcweir if ( bUntil ) 252cdf0e10cSrcweir { 253cdf0e10cSrcweir if ( !aNumStr.Len() ) 254cdf0e10cSrcweir nNum = RANGE_MAX; 255cdf0e10cSrcweir aRg.Min() = nPage; 256cdf0e10cSrcweir aRg.Max() = nNum; 257cdf0e10cSrcweir aRg.Justify(); 258cdf0e10cSrcweir Select( aRg ); 259cdf0e10cSrcweir } 260cdf0e10cSrcweir else 261cdf0e10cSrcweir Select( nNum ); 262cdf0e10cSrcweir nPage = 0; 263cdf0e10cSrcweir aNumStr.Erase(); 264cdf0e10cSrcweir bUntil = sal_False; 265cdf0e10cSrcweir break; 266cdf0e10cSrcweir 267cdf0e10cSrcweir case '-': 268cdf0e10cSrcweir nPage = aNumStr.ToInt32(); 269cdf0e10cSrcweir aNumStr.Erase(); 270cdf0e10cSrcweir bUntil = sal_True; 271cdf0e10cSrcweir break; 272cdf0e10cSrcweir } 273cdf0e10cSrcweir 274cdf0e10cSrcweir pCStr++; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir 277cdf0e10cSrcweir nNum = aNumStr.ToInt32(); 278cdf0e10cSrcweir if ( bUntil ) 279cdf0e10cSrcweir { 280cdf0e10cSrcweir if ( !aNumStr.Len() ) 281cdf0e10cSrcweir nNum = RANGE_MAX; 282cdf0e10cSrcweir aRg.Min() = nPage; 283cdf0e10cSrcweir aRg.Max() = nNum; 284cdf0e10cSrcweir aRg.Justify(); 285cdf0e10cSrcweir Select( aRg ); 286cdf0e10cSrcweir } 287cdf0e10cSrcweir else 288cdf0e10cSrcweir Select( nNum ); 289cdf0e10cSrcweir } 290cdf0e10cSrcweir 291cdf0e10cSrcweir // ----------------------------------------------------------------------- 292cdf0e10cSrcweir 293cdf0e10cSrcweir MultiSelection::MultiSelection( const MultiSelection& rOrig ) : 294cdf0e10cSrcweir aTotRange(rOrig.aTotRange), 295cdf0e10cSrcweir nSelCount(rOrig.nSelCount), 296cdf0e10cSrcweir bCurValid(rOrig.bCurValid), 297cdf0e10cSrcweir bSelectNew(sal_False) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir if ( bCurValid ) 300cdf0e10cSrcweir { 301cdf0e10cSrcweir nCurSubSel = rOrig.nCurSubSel; 302cdf0e10cSrcweir nCurIndex = rOrig.nCurIndex; 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir // copy the sub selections 306cdf0e10cSrcweir for ( sal_uIntPtr n = 0; n < rOrig.aSels.Count(); ++n ) 307cdf0e10cSrcweir aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND ); 308cdf0e10cSrcweir } 309cdf0e10cSrcweir 310cdf0e10cSrcweir // ----------------------------------------------------------------------- 311cdf0e10cSrcweir 312cdf0e10cSrcweir MultiSelection::MultiSelection( const Range& rRange ): 313cdf0e10cSrcweir aTotRange(rRange), 314cdf0e10cSrcweir nCurSubSel(0), 315cdf0e10cSrcweir nSelCount(0), 316cdf0e10cSrcweir bCurValid(sal_False), 317cdf0e10cSrcweir bSelectNew(sal_False) 318cdf0e10cSrcweir { 319cdf0e10cSrcweir } 320cdf0e10cSrcweir 321cdf0e10cSrcweir // ----------------------------------------------------------------------- 322cdf0e10cSrcweir 323cdf0e10cSrcweir MultiSelection::~MultiSelection() 324cdf0e10cSrcweir { 325cdf0e10cSrcweir Range* pRange = aSels.First(); 326cdf0e10cSrcweir while ( pRange ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir delete pRange; 329cdf0e10cSrcweir pRange = aSels.Next(); 330cdf0e10cSrcweir } 331cdf0e10cSrcweir } 332cdf0e10cSrcweir 333cdf0e10cSrcweir // ----------------------------------------------------------------------- 334cdf0e10cSrcweir 335cdf0e10cSrcweir MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig ) 336cdf0e10cSrcweir { 337cdf0e10cSrcweir aTotRange = rOrig.aTotRange; 338cdf0e10cSrcweir bCurValid = rOrig.bCurValid; 339cdf0e10cSrcweir if ( bCurValid ) 340cdf0e10cSrcweir { 341cdf0e10cSrcweir nCurSubSel = rOrig.nCurSubSel; 342cdf0e10cSrcweir nCurIndex = rOrig.nCurIndex; 343cdf0e10cSrcweir } 344cdf0e10cSrcweir 345cdf0e10cSrcweir // clear the old and copy the sub selections 346cdf0e10cSrcweir ImplClear(); 347cdf0e10cSrcweir for ( sal_uIntPtr n = 0; n < rOrig.aSels.Count(); ++n ) 348cdf0e10cSrcweir aSels.Insert( new Range( *rOrig.aSels.GetObject(n) ), LIST_APPEND ); 349cdf0e10cSrcweir nSelCount = rOrig.nSelCount; 350cdf0e10cSrcweir 351cdf0e10cSrcweir return *this; 352cdf0e10cSrcweir } 353cdf0e10cSrcweir 354cdf0e10cSrcweir // ----------------------------------------------------------------------- 355cdf0e10cSrcweir 356cdf0e10cSrcweir sal_Bool MultiSelection::operator== ( MultiSelection& rWith ) 357cdf0e10cSrcweir { 358cdf0e10cSrcweir if ( aTotRange != rWith.aTotRange || nSelCount != rWith.nSelCount || 359cdf0e10cSrcweir aSels.Count() != rWith.aSels.Count() ) 360cdf0e10cSrcweir return sal_False; 361cdf0e10cSrcweir 362cdf0e10cSrcweir // compare the sub seletions 363cdf0e10cSrcweir for ( sal_uIntPtr n = 0; n < aSels.Count(); ++n ) 364cdf0e10cSrcweir if ( *aSels.GetObject(n) != *rWith.aSels.GetObject(n) ) 365cdf0e10cSrcweir return sal_False; 366cdf0e10cSrcweir return sal_True; 367cdf0e10cSrcweir } 368cdf0e10cSrcweir 369cdf0e10cSrcweir // ----------------------------------------------------------------------- 370cdf0e10cSrcweir 371cdf0e10cSrcweir void MultiSelection::SelectAll( sal_Bool bSelect ) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir DBG(DbgOutf( "::SelectAll(%s)\n", bSelect ? "sal_True" : "sal_False" )); 374cdf0e10cSrcweir 375cdf0e10cSrcweir ImplClear(); 376cdf0e10cSrcweir if ( bSelect ) 377cdf0e10cSrcweir { 378cdf0e10cSrcweir aSels.Insert( new Range(aTotRange), LIST_APPEND ); 379cdf0e10cSrcweir nSelCount = aTotRange.Len(); 380cdf0e10cSrcweir } 381cdf0e10cSrcweir 382cdf0e10cSrcweir DBG(Print( this )); 383cdf0e10cSrcweir } 384cdf0e10cSrcweir 385cdf0e10cSrcweir // ----------------------------------------------------------------------- 386cdf0e10cSrcweir 387cdf0e10cSrcweir sal_Bool MultiSelection::Select( long nIndex, sal_Bool bSelect ) 388cdf0e10cSrcweir { 389cdf0e10cSrcweir DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" ); 390cdf0e10cSrcweir 391cdf0e10cSrcweir // out of range? 392cdf0e10cSrcweir if ( !aTotRange.IsInside(nIndex) ) 393cdf0e10cSrcweir return sal_False; 394cdf0e10cSrcweir 395cdf0e10cSrcweir // find the virtual target position 396cdf0e10cSrcweir sal_uIntPtr nSubSelPos = ImplFindSubSelection( nIndex ); 397cdf0e10cSrcweir 398cdf0e10cSrcweir if ( bSelect ) 399cdf0e10cSrcweir { 400cdf0e10cSrcweir // is it included in the found sub selection? 401cdf0e10cSrcweir if ( nSubSelPos < aSels.Count() && 402cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->IsInside( nIndex ) ) 403cdf0e10cSrcweir // already selected, nothing to do 404cdf0e10cSrcweir return sal_False; 405cdf0e10cSrcweir 406cdf0e10cSrcweir // it will become selected 407cdf0e10cSrcweir ++nSelCount; 408cdf0e10cSrcweir 409cdf0e10cSrcweir // is it at the end of the previous sub selection 410cdf0e10cSrcweir if ( nSubSelPos > 0 && 411cdf0e10cSrcweir aSels.GetObject(nSubSelPos-1)->Max() == (nIndex-1) ) 412cdf0e10cSrcweir { 413cdf0e10cSrcweir // expand the previous sub selection 414cdf0e10cSrcweir aSels.GetObject(nSubSelPos-1)->Max() = nIndex; 415cdf0e10cSrcweir 416cdf0e10cSrcweir // try to merge the previous sub selection 417cdf0e10cSrcweir ImplMergeSubSelections( nSubSelPos-1, nSubSelPos ); 418cdf0e10cSrcweir } 419cdf0e10cSrcweir // is is at the beginning of the found sub selection 420cdf0e10cSrcweir else if ( nSubSelPos < aSels.Count() && 421cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->Min() == (nIndex+1) ) 422cdf0e10cSrcweir // expand the found sub selection 423cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->Min() = nIndex; 424cdf0e10cSrcweir else 425cdf0e10cSrcweir { 426cdf0e10cSrcweir // create a new sub selection 427cdf0e10cSrcweir aSels.Insert( new Range( nIndex, nIndex ), nSubSelPos ); 428cdf0e10cSrcweir if ( bCurValid && nCurSubSel >= nSubSelPos ) 429cdf0e10cSrcweir ++nCurSubSel; 430cdf0e10cSrcweir } 431cdf0e10cSrcweir } 432cdf0e10cSrcweir else 433cdf0e10cSrcweir { 434cdf0e10cSrcweir // is it excluded from the found sub selection? 435cdf0e10cSrcweir if ( nSubSelPos >= aSels.Count() || 436cdf0e10cSrcweir !aSels.GetObject(nSubSelPos)->IsInside( nIndex ) ) 437cdf0e10cSrcweir { 438cdf0e10cSrcweir // not selected, nothing to do 439cdf0e10cSrcweir DBG(Print( this )); 440cdf0e10cSrcweir return sal_False; 441cdf0e10cSrcweir } 442cdf0e10cSrcweir 443cdf0e10cSrcweir // it will become deselected 444cdf0e10cSrcweir --nSelCount; 445cdf0e10cSrcweir 446cdf0e10cSrcweir // is it the only index in the found sub selection? 447cdf0e10cSrcweir if ( aSels.GetObject(nSubSelPos)->Len() == 1 ) 448cdf0e10cSrcweir { 449cdf0e10cSrcweir // remove the complete sub selection 450cdf0e10cSrcweir delete aSels.Remove( nSubSelPos ); 451cdf0e10cSrcweir DBG(Print( this )); 452cdf0e10cSrcweir return sal_True; 453cdf0e10cSrcweir } 454cdf0e10cSrcweir 455cdf0e10cSrcweir // is it at the beginning of the found sub selection? 456cdf0e10cSrcweir if ( aSels.GetObject(nSubSelPos)->Min() == nIndex ) 457cdf0e10cSrcweir ++aSels.GetObject(nSubSelPos)->Min(); 458cdf0e10cSrcweir // is it at the end of the found sub selection? 459cdf0e10cSrcweir else if ( aSels.GetObject(nSubSelPos)->Max() == nIndex ) 460cdf0e10cSrcweir --aSels.GetObject(nSubSelPos)->Max(); 461cdf0e10cSrcweir // it is in the middle of the found sub selection? 462cdf0e10cSrcweir else 463cdf0e10cSrcweir { 464cdf0e10cSrcweir // split the sub selection 465cdf0e10cSrcweir aSels.Insert( 466cdf0e10cSrcweir new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ), 467cdf0e10cSrcweir nSubSelPos ); 468cdf0e10cSrcweir aSels.GetObject(nSubSelPos+1)->Min() = nIndex + 1; 469cdf0e10cSrcweir } 470cdf0e10cSrcweir } 471cdf0e10cSrcweir 472cdf0e10cSrcweir DBG(Print( this )); 473cdf0e10cSrcweir 474cdf0e10cSrcweir return sal_True; 475cdf0e10cSrcweir } 476cdf0e10cSrcweir 477cdf0e10cSrcweir // ----------------------------------------------------------------------- 478cdf0e10cSrcweir 479cdf0e10cSrcweir void MultiSelection::Select( const Range& rIndexRange, sal_Bool bSelect ) 480cdf0e10cSrcweir { 481cdf0e10cSrcweir Range* pRange; 482cdf0e10cSrcweir long nOld; 483cdf0e10cSrcweir 484cdf0e10cSrcweir sal_uIntPtr nTmpMin = rIndexRange.Min(); 485cdf0e10cSrcweir sal_uIntPtr nTmpMax = rIndexRange.Max(); 486cdf0e10cSrcweir sal_uIntPtr nCurMin = FirstSelected(); 487cdf0e10cSrcweir sal_uIntPtr nCurMax = LastSelected(); 488cdf0e10cSrcweir DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" ); 489cdf0e10cSrcweir DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" ); 490cdf0e10cSrcweir 491cdf0e10cSrcweir // gesamte Selektion ersetzen ? 492cdf0e10cSrcweir if( nTmpMin <= nCurMin && nTmpMax >= nCurMax ) 493cdf0e10cSrcweir { 494cdf0e10cSrcweir ImplClear(); 495cdf0e10cSrcweir if ( bSelect ) 496cdf0e10cSrcweir { 497cdf0e10cSrcweir aSels.Insert( new Range(rIndexRange), LIST_APPEND ); 498cdf0e10cSrcweir nSelCount = rIndexRange.Len(); 499cdf0e10cSrcweir } 500cdf0e10cSrcweir return; 501cdf0e10cSrcweir } 502cdf0e10cSrcweir // links erweitern ? 503cdf0e10cSrcweir if( nTmpMax < nCurMin ) 504cdf0e10cSrcweir { 505cdf0e10cSrcweir if( bSelect ) 506cdf0e10cSrcweir { 507cdf0e10cSrcweir // ersten Range erweitern ? 508cdf0e10cSrcweir if( nCurMin > (nTmpMax+1) ) 509cdf0e10cSrcweir { 510cdf0e10cSrcweir pRange = new Range( rIndexRange ); 511cdf0e10cSrcweir aSels.Insert( pRange, (sal_uIntPtr)0 ); 512cdf0e10cSrcweir nSelCount += pRange->Len(); 513cdf0e10cSrcweir } 514cdf0e10cSrcweir else 515cdf0e10cSrcweir { 516cdf0e10cSrcweir pRange = aSels.First(); 517cdf0e10cSrcweir nOld = pRange->Min(); 518cdf0e10cSrcweir pRange->Min() = (long)nTmpMin; 519cdf0e10cSrcweir nSelCount += ( nOld - nTmpMin ); 520cdf0e10cSrcweir } 521cdf0e10cSrcweir bCurValid = sal_False; 522cdf0e10cSrcweir } 523cdf0e10cSrcweir return; 524cdf0e10cSrcweir } 525cdf0e10cSrcweir // rechts erweitern ? 526cdf0e10cSrcweir else if( nTmpMin > nCurMax ) 527cdf0e10cSrcweir { 528cdf0e10cSrcweir if( bSelect ) 529cdf0e10cSrcweir { 530cdf0e10cSrcweir // letzten Range erweitern ? 531cdf0e10cSrcweir if( nTmpMin > (nCurMax+1) ) 532cdf0e10cSrcweir { 533cdf0e10cSrcweir pRange = new Range( rIndexRange ); 534cdf0e10cSrcweir aSels.Insert( pRange, LIST_APPEND ); 535cdf0e10cSrcweir nSelCount += pRange->Len(); 536cdf0e10cSrcweir } 537cdf0e10cSrcweir else 538cdf0e10cSrcweir { 539cdf0e10cSrcweir pRange = aSels.Last(); 540cdf0e10cSrcweir nOld = pRange->Max(); 541cdf0e10cSrcweir pRange->Max() = (long)nTmpMax; 542cdf0e10cSrcweir nSelCount += ( nTmpMax - nOld ); 543cdf0e10cSrcweir } 544cdf0e10cSrcweir bCurValid = sal_False; 545cdf0e10cSrcweir } 546cdf0e10cSrcweir return; 547cdf0e10cSrcweir } 548cdf0e10cSrcweir 549cdf0e10cSrcweir //HACK(Hier muss noch optimiert werden) 550cdf0e10cSrcweir while( nTmpMin <= nTmpMax ) 551cdf0e10cSrcweir { 552cdf0e10cSrcweir Select( nTmpMin, bSelect ); 553cdf0e10cSrcweir nTmpMin++; 554cdf0e10cSrcweir } 555cdf0e10cSrcweir } 556cdf0e10cSrcweir 557cdf0e10cSrcweir // ----------------------------------------------------------------------- 558cdf0e10cSrcweir 559cdf0e10cSrcweir sal_Bool MultiSelection::IsSelected( long nIndex ) const 560cdf0e10cSrcweir { 561cdf0e10cSrcweir // find the virtual target position 562cdf0e10cSrcweir sal_uIntPtr nSubSelPos = ImplFindSubSelection( nIndex ); 563cdf0e10cSrcweir 564cdf0e10cSrcweir return nSubSelPos < aSels.Count() && 565cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->IsInside(nIndex); 566cdf0e10cSrcweir } 567cdf0e10cSrcweir 568cdf0e10cSrcweir // ----------------------------------------------------------------------- 569cdf0e10cSrcweir 570cdf0e10cSrcweir void MultiSelection::Insert( long nIndex, long nCount ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir DBG(DbgOutf( "::Insert(%ld, %ld)\n", nIndex, nCount )); 573cdf0e10cSrcweir 574cdf0e10cSrcweir // find the virtual target position 575cdf0e10cSrcweir sal_uIntPtr nSubSelPos = ImplFindSubSelection( nIndex ); 576cdf0e10cSrcweir 577cdf0e10cSrcweir // did we need to shift the sub selections? 578cdf0e10cSrcweir if ( nSubSelPos < aSels.Count() ) 579cdf0e10cSrcweir { 580cdf0e10cSrcweir // did we insert an unselected into an existing sub selection? 581cdf0e10cSrcweir if ( !bSelectNew && aSels.GetObject(nSubSelPos)->Min() != nIndex && 582cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->IsInside(nIndex) ) 583cdf0e10cSrcweir { 584cdf0e10cSrcweir // split the sub selection 585cdf0e10cSrcweir aSels.Insert( 586cdf0e10cSrcweir new Range( aSels.GetObject(nSubSelPos)->Min(), nIndex-1 ), 587cdf0e10cSrcweir nSubSelPos ); 588cdf0e10cSrcweir ++nSubSelPos; 589cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->Min() = nIndex; 590cdf0e10cSrcweir } 591cdf0e10cSrcweir 592cdf0e10cSrcweir // did we append an selected to an existing sub selection? 593cdf0e10cSrcweir else if ( bSelectNew && nSubSelPos > 0 && 594cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->Max() == nIndex-1 ) 595cdf0e10cSrcweir // expand the previous sub selection 596cdf0e10cSrcweir aSels.GetObject(nSubSelPos-1)->Max() += nCount; 597cdf0e10cSrcweir 598cdf0e10cSrcweir // did we insert an selected into an existing sub selection? 599cdf0e10cSrcweir else if ( bSelectNew && aSels.GetObject(nSubSelPos)->Min() == nIndex ) 600cdf0e10cSrcweir { 601cdf0e10cSrcweir // expand the sub selection 602cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->Max() += nCount; 603cdf0e10cSrcweir ++nSubSelPos; 604cdf0e10cSrcweir } 605cdf0e10cSrcweir 606cdf0e10cSrcweir // shift the sub selections behind the inserting position 607cdf0e10cSrcweir for ( sal_uIntPtr nPos = nSubSelPos; nPos < aSels.Count(); ++nPos ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir aSels.GetObject(nPos)->Min() += nCount; 610cdf0e10cSrcweir aSels.GetObject(nPos)->Max() += nCount; 611cdf0e10cSrcweir } 612cdf0e10cSrcweir } 613cdf0e10cSrcweir 614cdf0e10cSrcweir bCurValid = sal_False; 615cdf0e10cSrcweir aTotRange.Max() += nCount; 616cdf0e10cSrcweir if ( bSelectNew ) 617cdf0e10cSrcweir nSelCount += nCount; 618cdf0e10cSrcweir 619cdf0e10cSrcweir DBG(Print( this )); 620cdf0e10cSrcweir } 621cdf0e10cSrcweir 622cdf0e10cSrcweir // ----------------------------------------------------------------------- 623cdf0e10cSrcweir 624cdf0e10cSrcweir void MultiSelection::Remove( long nIndex ) 625cdf0e10cSrcweir { 626cdf0e10cSrcweir DBG(DbgOutf( "::Remove(%ld)\n", nIndex )); 627cdf0e10cSrcweir 628cdf0e10cSrcweir // find the virtual target position 629cdf0e10cSrcweir sal_uIntPtr nSubSelPos = ImplFindSubSelection( nIndex ); 630cdf0e10cSrcweir 631cdf0e10cSrcweir // did we remove from an existing sub selection? 632cdf0e10cSrcweir if ( nSubSelPos < aSels.Count() && 633cdf0e10cSrcweir aSels.GetObject(nSubSelPos)->IsInside(nIndex) ) 634cdf0e10cSrcweir { 635cdf0e10cSrcweir // does this sub selection only contain the index to be deleted 636cdf0e10cSrcweir if ( aSels.GetObject(nSubSelPos)->Len() == 1 ) 637cdf0e10cSrcweir // completely remove the sub selection 638cdf0e10cSrcweir aSels.Remove(nSubSelPos); 639cdf0e10cSrcweir else 640cdf0e10cSrcweir // shorten this sub selection 641cdf0e10cSrcweir --( aSels.GetObject(nSubSelPos++)->Max() ); 642cdf0e10cSrcweir 643cdf0e10cSrcweir // adjust the selected counter 644cdf0e10cSrcweir --nSelCount; 645cdf0e10cSrcweir } 646cdf0e10cSrcweir 647cdf0e10cSrcweir // shift the sub selections behind the removed index 648cdf0e10cSrcweir for ( sal_uIntPtr nPos = nSubSelPos; nPos < aSels.Count(); ++nPos ) 649cdf0e10cSrcweir { 650cdf0e10cSrcweir --( aSels.GetObject(nPos)->Min() ); 651cdf0e10cSrcweir --( aSels.GetObject(nPos)->Max() ); 652cdf0e10cSrcweir } 653cdf0e10cSrcweir 654cdf0e10cSrcweir bCurValid = sal_False; 655cdf0e10cSrcweir aTotRange.Max() -= 1; 656cdf0e10cSrcweir 657cdf0e10cSrcweir DBG(Print( this )); 658cdf0e10cSrcweir } 659cdf0e10cSrcweir 660cdf0e10cSrcweir // ----------------------------------------------------------------------- 661cdf0e10cSrcweir 662cdf0e10cSrcweir void MultiSelection::Append( long nCount ) 663cdf0e10cSrcweir { 664cdf0e10cSrcweir long nPrevLast = aTotRange.Max(); 665cdf0e10cSrcweir aTotRange.Max() += nCount; 666cdf0e10cSrcweir if ( bSelectNew ) 667cdf0e10cSrcweir { 668cdf0e10cSrcweir nSelCount += nCount; 669cdf0e10cSrcweir aSels.Insert( new Range( nPrevLast+1, nPrevLast + nCount ), 670cdf0e10cSrcweir LIST_APPEND ); 671cdf0e10cSrcweir if ( aSels.Count() > 1 ) 672cdf0e10cSrcweir ImplMergeSubSelections( aSels.Count() - 2, aSels.Count() ); 673cdf0e10cSrcweir } 674cdf0e10cSrcweir } 675cdf0e10cSrcweir 676cdf0e10cSrcweir // ----------------------------------------------------------------------- 677cdf0e10cSrcweir 678cdf0e10cSrcweir long MultiSelection::ImplFwdUnselected() 679cdf0e10cSrcweir { 680cdf0e10cSrcweir if ( !bCurValid ) 681cdf0e10cSrcweir return SFX_ENDOFSELECTION; 682cdf0e10cSrcweir 683cdf0e10cSrcweir if ( ( nCurSubSel < aSels.Count() ) && 684cdf0e10cSrcweir ( aSels.GetObject(nCurSubSel)->Min() <= nCurIndex ) ) 685cdf0e10cSrcweir nCurIndex = aSels.GetObject(nCurSubSel++)->Max() + 1; 686cdf0e10cSrcweir 687cdf0e10cSrcweir if ( nCurIndex <= aTotRange.Max() ) 688cdf0e10cSrcweir return nCurIndex; 689cdf0e10cSrcweir else 690cdf0e10cSrcweir return SFX_ENDOFSELECTION; 691cdf0e10cSrcweir } 692cdf0e10cSrcweir 693cdf0e10cSrcweir // ----------------------------------------------------------------------- 694cdf0e10cSrcweir 695cdf0e10cSrcweir long MultiSelection::ImplBwdUnselected() 696cdf0e10cSrcweir { 697cdf0e10cSrcweir if ( !bCurValid ) 698cdf0e10cSrcweir return SFX_ENDOFSELECTION; 699cdf0e10cSrcweir 700cdf0e10cSrcweir if ( aSels.GetObject(nCurSubSel)->Max() < nCurIndex ) 701cdf0e10cSrcweir return nCurIndex; 702cdf0e10cSrcweir 703cdf0e10cSrcweir nCurIndex = aSels.GetObject(nCurSubSel--)->Min() - 1; 704cdf0e10cSrcweir if ( nCurIndex >= 0 ) 705cdf0e10cSrcweir return nCurIndex; 706cdf0e10cSrcweir else 707cdf0e10cSrcweir return SFX_ENDOFSELECTION; 708cdf0e10cSrcweir } 709cdf0e10cSrcweir 710cdf0e10cSrcweir // ----------------------------------------------------------------------- 711cdf0e10cSrcweir 712cdf0e10cSrcweir long MultiSelection::FirstSelected( sal_Bool bInverse ) 713cdf0e10cSrcweir { 714cdf0e10cSrcweir bInverseCur = bInverse; 715cdf0e10cSrcweir nCurSubSel = 0; 716cdf0e10cSrcweir 717cdf0e10cSrcweir if ( bInverseCur ) 718cdf0e10cSrcweir { 719cdf0e10cSrcweir bCurValid = nSelCount < sal_uIntPtr(aTotRange.Len()); 720cdf0e10cSrcweir if ( bCurValid ) 721cdf0e10cSrcweir { 722cdf0e10cSrcweir nCurIndex = 0; 723cdf0e10cSrcweir return ImplFwdUnselected(); 724cdf0e10cSrcweir } 725cdf0e10cSrcweir } 726cdf0e10cSrcweir else 727cdf0e10cSrcweir { 728cdf0e10cSrcweir bCurValid = aSels.Count() > 0; 729cdf0e10cSrcweir if ( bCurValid ) 730cdf0e10cSrcweir return nCurIndex = aSels.GetObject(0)->Min(); 731cdf0e10cSrcweir } 732cdf0e10cSrcweir 733cdf0e10cSrcweir return SFX_ENDOFSELECTION; 734cdf0e10cSrcweir } 735cdf0e10cSrcweir 736cdf0e10cSrcweir // ----------------------------------------------------------------------- 737cdf0e10cSrcweir 738cdf0e10cSrcweir long MultiSelection::LastSelected() 739cdf0e10cSrcweir { 740cdf0e10cSrcweir nCurSubSel = aSels.Count() - 1; 741cdf0e10cSrcweir bCurValid = aSels.Count() > 0; 742cdf0e10cSrcweir 743cdf0e10cSrcweir if ( bCurValid ) 744cdf0e10cSrcweir return nCurIndex = aSels.GetObject(nCurSubSel)->Max(); 745cdf0e10cSrcweir 746cdf0e10cSrcweir return SFX_ENDOFSELECTION; 747cdf0e10cSrcweir } 748cdf0e10cSrcweir 749cdf0e10cSrcweir // ----------------------------------------------------------------------- 750cdf0e10cSrcweir 751cdf0e10cSrcweir long MultiSelection::NextSelected() 752cdf0e10cSrcweir { 753cdf0e10cSrcweir if ( !bCurValid ) 754cdf0e10cSrcweir return SFX_ENDOFSELECTION; 755cdf0e10cSrcweir 756cdf0e10cSrcweir if ( bInverseCur ) 757cdf0e10cSrcweir { 758cdf0e10cSrcweir ++nCurIndex; 759cdf0e10cSrcweir return ImplFwdUnselected(); 760cdf0e10cSrcweir } 761cdf0e10cSrcweir else 762cdf0e10cSrcweir { 763cdf0e10cSrcweir // is the next index in the current sub selection too? 764cdf0e10cSrcweir if ( nCurIndex < aSels.GetObject(nCurSubSel)->Max() ) 765cdf0e10cSrcweir return ++nCurIndex; 766cdf0e10cSrcweir 767cdf0e10cSrcweir // are there further sub selections? 768cdf0e10cSrcweir if ( ++nCurSubSel < aSels.Count() ) 769cdf0e10cSrcweir return nCurIndex = aSels.GetObject(nCurSubSel)->Min(); 770cdf0e10cSrcweir 771cdf0e10cSrcweir // we are at the end! 772cdf0e10cSrcweir return SFX_ENDOFSELECTION; 773cdf0e10cSrcweir } 774cdf0e10cSrcweir } 775cdf0e10cSrcweir 776cdf0e10cSrcweir // ----------------------------------------------------------------------- 777cdf0e10cSrcweir 778cdf0e10cSrcweir long MultiSelection::PrevSelected() 779cdf0e10cSrcweir { 780cdf0e10cSrcweir if ( !bCurValid ) 781cdf0e10cSrcweir return SFX_ENDOFSELECTION; 782cdf0e10cSrcweir 783cdf0e10cSrcweir if ( bInverseCur ) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir --nCurIndex; 786cdf0e10cSrcweir return ImplBwdUnselected(); 787cdf0e10cSrcweir } 788cdf0e10cSrcweir else 789cdf0e10cSrcweir { 790cdf0e10cSrcweir // is the previous index in the current sub selection too? 791cdf0e10cSrcweir if ( nCurIndex > aSels.GetObject(nCurSubSel)->Min() ) 792cdf0e10cSrcweir return --nCurIndex; 793cdf0e10cSrcweir 794cdf0e10cSrcweir // are there previous sub selections? 795cdf0e10cSrcweir if ( nCurSubSel > 0 ) 796cdf0e10cSrcweir { 797cdf0e10cSrcweir --nCurSubSel; 798cdf0e10cSrcweir return nCurIndex = aSels.GetObject(nCurSubSel)->Max(); 799cdf0e10cSrcweir } 800cdf0e10cSrcweir 801cdf0e10cSrcweir // we are at the beginning! 802cdf0e10cSrcweir return SFX_ENDOFSELECTION; 803cdf0e10cSrcweir } 804cdf0e10cSrcweir } 805cdf0e10cSrcweir 806cdf0e10cSrcweir // ----------------------------------------------------------------------- 807cdf0e10cSrcweir 808cdf0e10cSrcweir void MultiSelection::SetTotalRange( const Range& rTotRange ) 809cdf0e10cSrcweir { 810cdf0e10cSrcweir aTotRange = rTotRange; 811cdf0e10cSrcweir 812cdf0e10cSrcweir // die untere Bereichsgrenze anpassen 813cdf0e10cSrcweir Range* pRange = aSels.GetObject( 0 ); 814cdf0e10cSrcweir while( pRange ) 815cdf0e10cSrcweir { 816cdf0e10cSrcweir if( pRange->Max() < aTotRange.Min() ) 817cdf0e10cSrcweir { 818cdf0e10cSrcweir delete pRange; 819cdf0e10cSrcweir aSels.Remove( (sal_uIntPtr)0 ); 820cdf0e10cSrcweir } 821cdf0e10cSrcweir else if( pRange->Min() < aTotRange.Min() ) 822cdf0e10cSrcweir { 823cdf0e10cSrcweir pRange->Min() = aTotRange.Min(); 824cdf0e10cSrcweir break; 825cdf0e10cSrcweir } 826cdf0e10cSrcweir else 827cdf0e10cSrcweir break; 828cdf0e10cSrcweir 829cdf0e10cSrcweir pRange = aSels.GetObject( 0 ); 830cdf0e10cSrcweir } 831cdf0e10cSrcweir 832cdf0e10cSrcweir // die obere Bereichsgrenze anpassen 833cdf0e10cSrcweir sal_uIntPtr nCount = aSels.Count(); 834cdf0e10cSrcweir while( nCount ) 835cdf0e10cSrcweir { 836cdf0e10cSrcweir pRange = aSels.GetObject( nCount - 1 ); 837cdf0e10cSrcweir if( pRange->Min() > aTotRange.Max() ) 838cdf0e10cSrcweir { 839cdf0e10cSrcweir delete pRange; 840cdf0e10cSrcweir aSels.Remove( (sal_uIntPtr)(nCount - 1) ); 841cdf0e10cSrcweir } 842cdf0e10cSrcweir else if( pRange->Max() > aTotRange.Max() ) 843cdf0e10cSrcweir { 844cdf0e10cSrcweir pRange->Max() = aTotRange.Max(); 845cdf0e10cSrcweir break; 846cdf0e10cSrcweir } 847cdf0e10cSrcweir else 848cdf0e10cSrcweir break; 849cdf0e10cSrcweir 850cdf0e10cSrcweir nCount = aSels.Count(); 851cdf0e10cSrcweir } 852cdf0e10cSrcweir 853cdf0e10cSrcweir // Selection-Count neu berechnen 854cdf0e10cSrcweir nSelCount = 0; 855cdf0e10cSrcweir pRange = aSels.First(); 856cdf0e10cSrcweir while( pRange ) 857cdf0e10cSrcweir { 858cdf0e10cSrcweir nSelCount += pRange->Len(); 859cdf0e10cSrcweir pRange = aSels.Next(); 860cdf0e10cSrcweir } 861cdf0e10cSrcweir 862cdf0e10cSrcweir bCurValid = sal_False; 863cdf0e10cSrcweir nCurIndex = 0; 864cdf0e10cSrcweir } 865cdf0e10cSrcweir 866cdf0e10cSrcweir // ----------------------------------------------------------------------- 867cdf0e10cSrcweir // 868cdf0e10cSrcweir // StringRangeEnumerator 869cdf0e10cSrcweir // 870cdf0e10cSrcweir // ----------------------------------------------------------------------- 871cdf0e10cSrcweir StringRangeEnumerator::StringRangeEnumerator( const rtl::OUString& i_rInput, 872cdf0e10cSrcweir sal_Int32 i_nMinNumber, 873cdf0e10cSrcweir sal_Int32 i_nMaxNumber, 874cdf0e10cSrcweir sal_Int32 i_nLogicalOffset 875cdf0e10cSrcweir ) 876cdf0e10cSrcweir : mnCount( 0 ) 877cdf0e10cSrcweir , mnMin( i_nMinNumber ) 878cdf0e10cSrcweir , mnMax( i_nMaxNumber ) 879cdf0e10cSrcweir , mnOffset( i_nLogicalOffset ) 880cdf0e10cSrcweir { 881cdf0e10cSrcweir setRange( i_rInput ); 882cdf0e10cSrcweir } 883cdf0e10cSrcweir 884cdf0e10cSrcweir bool StringRangeEnumerator::checkValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const 885cdf0e10cSrcweir { 886cdf0e10cSrcweir if( mnMin >= 0 && i_nValue < mnMin ) 887cdf0e10cSrcweir return false; 888cdf0e10cSrcweir if( mnMax >= 0 && i_nValue > mnMax ) 889cdf0e10cSrcweir return false; 890cdf0e10cSrcweir if( i_nValue < 0 ) 891cdf0e10cSrcweir return false; 892cdf0e10cSrcweir if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() ) 893cdf0e10cSrcweir return false; 894cdf0e10cSrcweir return true; 895cdf0e10cSrcweir } 896cdf0e10cSrcweir 897cdf0e10cSrcweir bool StringRangeEnumerator::insertRange( sal_Int32 i_nFirst, sal_Int32 i_nLast, bool bSequence, bool bMayAdjust ) 898cdf0e10cSrcweir { 899cdf0e10cSrcweir bool bSuccess = true; 900cdf0e10cSrcweir if( bSequence ) 901cdf0e10cSrcweir { 902cdf0e10cSrcweir if( i_nFirst == -1 ) 903cdf0e10cSrcweir i_nFirst = mnMin; 904cdf0e10cSrcweir if( i_nLast == -1 ) 905cdf0e10cSrcweir i_nLast = mnMax; 906cdf0e10cSrcweir if( bMayAdjust ) 907cdf0e10cSrcweir { 908cdf0e10cSrcweir if( i_nFirst < mnMin ) 909cdf0e10cSrcweir i_nFirst = mnMin; 910cdf0e10cSrcweir if( i_nFirst > mnMax ) 911cdf0e10cSrcweir i_nFirst = mnMax; 912cdf0e10cSrcweir if( i_nLast < mnMin ) 913cdf0e10cSrcweir i_nLast = mnMin; 914cdf0e10cSrcweir if( i_nLast > mnMax ) 915cdf0e10cSrcweir i_nLast = mnMax; 916cdf0e10cSrcweir } 917cdf0e10cSrcweir if( checkValue( i_nFirst ) && checkValue( i_nLast ) ) 918cdf0e10cSrcweir { 919cdf0e10cSrcweir maSequence.push_back( Range( i_nFirst, i_nLast ) ); 920cdf0e10cSrcweir sal_Int32 nNumber = i_nLast - i_nFirst; 921cdf0e10cSrcweir nNumber = nNumber < 0 ? -nNumber : nNumber; 922cdf0e10cSrcweir mnCount += nNumber + 1; 923cdf0e10cSrcweir } 924cdf0e10cSrcweir else 925cdf0e10cSrcweir bSuccess = false; 926cdf0e10cSrcweir } 927cdf0e10cSrcweir else 928cdf0e10cSrcweir { 929cdf0e10cSrcweir if( i_nFirst >= 0 ) 930cdf0e10cSrcweir { 931cdf0e10cSrcweir if( checkValue( i_nFirst ) ) 932cdf0e10cSrcweir { 933cdf0e10cSrcweir maSequence.push_back( Range( i_nFirst, i_nFirst ) ); 934cdf0e10cSrcweir mnCount++; 935cdf0e10cSrcweir } 936cdf0e10cSrcweir else 937cdf0e10cSrcweir bSuccess = false; 938cdf0e10cSrcweir } 939cdf0e10cSrcweir if( i_nLast >= 0 ) 940cdf0e10cSrcweir { 941cdf0e10cSrcweir if( checkValue( i_nLast ) ) 942cdf0e10cSrcweir { 943cdf0e10cSrcweir maSequence.push_back( Range( i_nLast, i_nLast ) ); 944cdf0e10cSrcweir mnCount++; 945cdf0e10cSrcweir } 946cdf0e10cSrcweir else 947cdf0e10cSrcweir bSuccess = false; 948cdf0e10cSrcweir } 949cdf0e10cSrcweir } 950cdf0e10cSrcweir 951cdf0e10cSrcweir return bSuccess; 952cdf0e10cSrcweir } 953cdf0e10cSrcweir 954cdf0e10cSrcweir bool StringRangeEnumerator::setRange( const rtl::OUString& i_rNewRange, bool i_bStrict ) 955cdf0e10cSrcweir { 956cdf0e10cSrcweir mnCount = 0; 957cdf0e10cSrcweir maSequence.clear(); 958cdf0e10cSrcweir 959cdf0e10cSrcweir // we love special cases 960cdf0e10cSrcweir if( i_rNewRange.getLength() == 0 ) 961cdf0e10cSrcweir { 962cdf0e10cSrcweir if( mnMin >= 0 && mnMax >= 0 ) 963cdf0e10cSrcweir { 964cdf0e10cSrcweir insertRange( mnMin, mnMax, mnMin != mnMax, ! i_bStrict ); 965cdf0e10cSrcweir } 966cdf0e10cSrcweir return true; 967cdf0e10cSrcweir } 968cdf0e10cSrcweir 969cdf0e10cSrcweir const sal_Unicode* pInput = i_rNewRange.getStr(); 970cdf0e10cSrcweir rtl::OUStringBuffer aNumberBuf( 16 ); 971cdf0e10cSrcweir sal_Int32 nLastNumber = -1, nNumber = -1; 972cdf0e10cSrcweir bool bSequence = false; 973cdf0e10cSrcweir bool bSuccess = true; 974cdf0e10cSrcweir while( *pInput ) 975cdf0e10cSrcweir { 976cdf0e10cSrcweir while( *pInput >= sal_Unicode('0') && *pInput <= sal_Unicode('9') ) 977cdf0e10cSrcweir aNumberBuf.append( *pInput++ ); 978cdf0e10cSrcweir if( aNumberBuf.getLength() ) 979cdf0e10cSrcweir { 980cdf0e10cSrcweir if( nNumber != -1 ) 981cdf0e10cSrcweir { 982cdf0e10cSrcweir if( bSequence ) 983cdf0e10cSrcweir { 984cdf0e10cSrcweir if( ! insertRange( nLastNumber, nNumber, true, ! i_bStrict ) && i_bStrict ) 985cdf0e10cSrcweir { 986cdf0e10cSrcweir bSuccess = false; 987cdf0e10cSrcweir break; 988cdf0e10cSrcweir } 989cdf0e10cSrcweir nLastNumber = -1; 990cdf0e10cSrcweir } 991cdf0e10cSrcweir else 992cdf0e10cSrcweir { 993cdf0e10cSrcweir if( ! insertRange( nNumber, nNumber, false, ! i_bStrict ) && i_bStrict ) 994cdf0e10cSrcweir { 995cdf0e10cSrcweir bSuccess = false; 996cdf0e10cSrcweir break; 997cdf0e10cSrcweir } 998cdf0e10cSrcweir } 999cdf0e10cSrcweir } 1000cdf0e10cSrcweir nNumber = aNumberBuf.makeStringAndClear().toInt32(); 1001cdf0e10cSrcweir nNumber += mnOffset; 1002cdf0e10cSrcweir } 1003cdf0e10cSrcweir bool bInsertRange = false; 1004cdf0e10cSrcweir if( *pInput == sal_Unicode('-') ) 1005cdf0e10cSrcweir { 1006cdf0e10cSrcweir nLastNumber = nNumber; 1007cdf0e10cSrcweir nNumber = -1; 1008cdf0e10cSrcweir bSequence = true; 1009cdf0e10cSrcweir } 1010cdf0e10cSrcweir else if( *pInput == ' ' ) 1011cdf0e10cSrcweir { 1012cdf0e10cSrcweir } 1013cdf0e10cSrcweir else if( *pInput == sal_Unicode(',') || *pInput == sal_Unicode(';') ) 1014cdf0e10cSrcweir bInsertRange = true; 1015cdf0e10cSrcweir else if( *pInput ) 1016cdf0e10cSrcweir { 1017cdf0e10cSrcweir 1018cdf0e10cSrcweir bSuccess = false; 1019cdf0e10cSrcweir break; // parse error 1020cdf0e10cSrcweir } 1021cdf0e10cSrcweir 1022cdf0e10cSrcweir if( bInsertRange ) 1023cdf0e10cSrcweir { 1024cdf0e10cSrcweir if( ! insertRange( nLastNumber, nNumber, bSequence, ! i_bStrict ) && i_bStrict ) 1025cdf0e10cSrcweir { 1026cdf0e10cSrcweir bSuccess = false; 1027cdf0e10cSrcweir break; 1028cdf0e10cSrcweir } 1029cdf0e10cSrcweir nNumber = nLastNumber = -1; 1030cdf0e10cSrcweir bSequence = false; 1031cdf0e10cSrcweir } 1032cdf0e10cSrcweir if( *pInput ) 1033cdf0e10cSrcweir pInput++; 1034cdf0e10cSrcweir } 1035cdf0e10cSrcweir // insert last entries 1036cdf0e10cSrcweir insertRange( nLastNumber, nNumber, bSequence, ! i_bStrict ); 1037cdf0e10cSrcweir 1038cdf0e10cSrcweir return bSuccess; 1039cdf0e10cSrcweir } 1040cdf0e10cSrcweir 1041cdf0e10cSrcweir bool StringRangeEnumerator::hasValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const 1042cdf0e10cSrcweir { 1043cdf0e10cSrcweir if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() ) 1044cdf0e10cSrcweir return false; 1045cdf0e10cSrcweir size_t n = maSequence.size(); 1046cdf0e10cSrcweir for( size_t i= 0; i < n; ++i ) 1047cdf0e10cSrcweir { 1048cdf0e10cSrcweir const StringRangeEnumerator::Range rRange( maSequence[i] ); 1049cdf0e10cSrcweir if( rRange.nFirst < rRange.nLast ) 1050cdf0e10cSrcweir { 1051cdf0e10cSrcweir if( i_nValue >= rRange.nFirst && i_nValue <= rRange.nLast ) 1052cdf0e10cSrcweir return true; 1053cdf0e10cSrcweir } 1054cdf0e10cSrcweir else 1055cdf0e10cSrcweir { 1056cdf0e10cSrcweir if( i_nValue >= rRange.nLast && i_nValue <= rRange.nFirst ) 1057cdf0e10cSrcweir return true; 1058cdf0e10cSrcweir } 1059cdf0e10cSrcweir } 1060cdf0e10cSrcweir return false; 1061cdf0e10cSrcweir } 1062cdf0e10cSrcweir 1063cdf0e10cSrcweir StringRangeEnumerator::Iterator& StringRangeEnumerator::Iterator::operator++() 1064cdf0e10cSrcweir { 1065cdf0e10cSrcweir if( nRangeIndex >= 0 && nCurrent >= 0 && pEnumerator ) 1066cdf0e10cSrcweir { 1067cdf0e10cSrcweir const StringRangeEnumerator::Range& rRange( pEnumerator->maSequence[nRangeIndex] ); 1068cdf0e10cSrcweir bool bRangeChange = false; 1069cdf0e10cSrcweir if( rRange.nLast < rRange.nFirst ) 1070cdf0e10cSrcweir { 1071cdf0e10cSrcweir // backward range 1072cdf0e10cSrcweir if( nCurrent > rRange.nLast ) 1073cdf0e10cSrcweir nCurrent--; 1074cdf0e10cSrcweir else 1075cdf0e10cSrcweir bRangeChange = true; 1076cdf0e10cSrcweir } 1077cdf0e10cSrcweir else 1078cdf0e10cSrcweir { 1079cdf0e10cSrcweir // forward range 1080cdf0e10cSrcweir if( nCurrent < rRange.nLast ) 1081cdf0e10cSrcweir nCurrent++; 1082cdf0e10cSrcweir else 1083cdf0e10cSrcweir bRangeChange = true; 1084cdf0e10cSrcweir } 1085cdf0e10cSrcweir if( bRangeChange ) 1086cdf0e10cSrcweir { 1087cdf0e10cSrcweir nRangeIndex++; 1088cdf0e10cSrcweir if( size_t(nRangeIndex) == pEnumerator->maSequence.size() ) 1089cdf0e10cSrcweir { 1090cdf0e10cSrcweir // reached the end 1091cdf0e10cSrcweir nRangeIndex = nCurrent = -1; 1092cdf0e10cSrcweir } 1093cdf0e10cSrcweir else 1094cdf0e10cSrcweir nCurrent = pEnumerator->maSequence[nRangeIndex].nFirst; 1095cdf0e10cSrcweir } 1096cdf0e10cSrcweir if( nRangeIndex != -1 && nCurrent != -1 ) 1097cdf0e10cSrcweir { 1098cdf0e10cSrcweir if( ! pEnumerator->checkValue( nCurrent, pPossibleValues ) ) 1099cdf0e10cSrcweir return ++(*this); 1100cdf0e10cSrcweir } 1101cdf0e10cSrcweir } 1102cdf0e10cSrcweir return *this; 1103cdf0e10cSrcweir } 1104cdf0e10cSrcweir 1105cdf0e10cSrcweir sal_Int32 StringRangeEnumerator::Iterator::operator*() const 1106cdf0e10cSrcweir { 1107cdf0e10cSrcweir return nCurrent; 1108cdf0e10cSrcweir } 1109cdf0e10cSrcweir 1110cdf0e10cSrcweir bool StringRangeEnumerator::Iterator::operator==( const Iterator& i_rCompare ) const 1111cdf0e10cSrcweir { 1112cdf0e10cSrcweir return i_rCompare.pEnumerator == pEnumerator && i_rCompare.nRangeIndex == nRangeIndex && i_rCompare.nCurrent == nCurrent; 1113cdf0e10cSrcweir } 1114cdf0e10cSrcweir 1115cdf0e10cSrcweir StringRangeEnumerator::Iterator StringRangeEnumerator::begin( const std::set< sal_Int32 >* i_pPossibleValues ) const 1116cdf0e10cSrcweir { 1117cdf0e10cSrcweir StringRangeEnumerator::Iterator it( this, 1118cdf0e10cSrcweir i_pPossibleValues, 1119cdf0e10cSrcweir maSequence.empty() ? -1 : 0, 1120cdf0e10cSrcweir maSequence.empty() ? -1 : maSequence[0].nFirst ); 1121cdf0e10cSrcweir if( ! checkValue(*it, i_pPossibleValues ) ) 1122cdf0e10cSrcweir ++it; 1123cdf0e10cSrcweir return it; 1124cdf0e10cSrcweir } 1125cdf0e10cSrcweir 1126cdf0e10cSrcweir StringRangeEnumerator::Iterator StringRangeEnumerator::end( const std::set< sal_Int32 >* i_pPossibleValues ) const 1127cdf0e10cSrcweir { 1128cdf0e10cSrcweir return StringRangeEnumerator::Iterator( this, i_pPossibleValues, -1, -1 ); 1129cdf0e10cSrcweir } 1130cdf0e10cSrcweir 1131cdf0e10cSrcweir bool StringRangeEnumerator::getRangesFromString( const OUString& i_rPageRange, 1132cdf0e10cSrcweir std::vector< sal_Int32 >& o_rPageVector, 1133cdf0e10cSrcweir sal_Int32 i_nMinNumber, 1134cdf0e10cSrcweir sal_Int32 i_nMaxNumber, 1135cdf0e10cSrcweir sal_Int32 i_nLogicalOffset, 1136cdf0e10cSrcweir std::set< sal_Int32 >* i_pPossibleValues 1137cdf0e10cSrcweir ) 1138cdf0e10cSrcweir { 1139cdf0e10cSrcweir StringRangeEnumerator aEnum; 1140cdf0e10cSrcweir aEnum.setMin( i_nMinNumber ); 1141cdf0e10cSrcweir aEnum.setMax( i_nMaxNumber ); 1142cdf0e10cSrcweir aEnum.setLogicalOffset( i_nLogicalOffset ); 1143cdf0e10cSrcweir 1144cdf0e10cSrcweir bool bRes = aEnum.setRange( i_rPageRange ); 1145cdf0e10cSrcweir if( bRes ) 1146cdf0e10cSrcweir { 1147cdf0e10cSrcweir o_rPageVector.clear(); 1148cdf0e10cSrcweir o_rPageVector.reserve( aEnum.size() ); 1149cdf0e10cSrcweir for( StringRangeEnumerator::Iterator it = aEnum.begin( i_pPossibleValues ); 1150cdf0e10cSrcweir it != aEnum.end( i_pPossibleValues ); ++it ) 1151cdf0e10cSrcweir { 1152cdf0e10cSrcweir o_rPageVector.push_back( *it ); 1153cdf0e10cSrcweir } 1154cdf0e10cSrcweir } 1155cdf0e10cSrcweir 1156cdf0e10cSrcweir return bRes; 1157cdf0e10cSrcweir } 1158cdf0e10cSrcweir 1159