1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svl.hxx" 30 31 // compiled via include from itemset.cxx only! 32 33 //======================================================================== 34 35 #ifdef DBG_UTIL 36 37 #define DBG_CHECK_RANGES(NUMTYPE, pArr) \ 38 for ( const NUMTYPE *pRange = pArr; *pRange; pRange += 2 ) \ 39 { \ 40 DBG_ASSERT( pRange[0] <= pRange[1], "ranges must be sorted" ); \ 41 DBG_ASSERT( !pRange[2] || ( pRange[2] - pRange[1] ) > 1, \ 42 "ranges must be sorted and discrete" ); \ 43 } 44 45 #else 46 47 #define DBG_CHECK_RANGES(NUMTYPE,pArr) 48 49 #endif 50 51 //============================================================================ 52 inline void Swap_Impl(const NUMTYPE *& rp1, const NUMTYPE *& rp2) 53 { 54 const NUMTYPE * pTemp = rp1; 55 rp1 = rp2; 56 rp2 = pTemp; 57 } 58 59 //======================================================================== 60 61 NUMTYPE InitializeRanges_Impl( NUMTYPE *&rpRanges, va_list pArgs, 62 NUMTYPE nWh1, NUMTYPE nWh2, NUMTYPE nNull ) 63 64 /** <H3>Description</H3> 65 66 Creates an sal_uInt16-ranges-array in 'rpRanges' using 'nWh1' and 'nWh2' as 67 first range, 'nNull' as terminator or start of 2nd range and 'pArgs' as 68 remaider. 69 70 It returns the number of NUMTYPEs which are contained in the described 71 set of NUMTYPEs. 72 */ 73 74 { 75 NUMTYPE nSize = 0, nIns = 0; 76 sal_uInt16 nCnt = 0; 77 SvNums aNumArr( 11, 8 ); 78 aNumArr.Insert( nWh1, nCnt++ ); 79 aNumArr.Insert( nWh2, nCnt++ ); 80 DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" ); 81 nSize += nWh2 - nWh1 + 1; 82 aNumArr.Insert( nNull, nCnt++ ); 83 while ( 0 != 84 ( nIns = 85 sal::static_int_cast< NUMTYPE >( 86 va_arg( pArgs, NUMTYPE_ARG ) ) ) ) 87 { 88 aNumArr.Insert( nIns, nCnt++ ); 89 if ( 0 == (nCnt & 1) ) // 4,6,8, usw. 90 { 91 DBG_ASSERT( aNumArr[ nCnt-2 ] <= nIns, "Ungueltiger Bereich" ); 92 nSize += nIns - aNumArr[ nCnt-2 ] + 1; 93 } 94 } 95 va_end( pArgs ); 96 97 DBG_ASSERT( 0 == (nCnt & 1), "ungerade Anzahl von Which-Paaren!" ); 98 99 // so, jetzt sind alle Bereiche vorhanden und 100 rpRanges = new NUMTYPE[ nCnt+1 ]; 101 memcpy( rpRanges, aNumArr.GetData(), sizeof(NUMTYPE) * nCnt ); 102 *(rpRanges+nCnt) = 0; 103 104 return nSize; 105 } 106 107 //------------------------------------------------------------------------ 108 109 NUMTYPE Count_Impl( const NUMTYPE *pRanges ) 110 111 /** <H3>Description</H3> 112 113 Determines the number of NUMTYPEs in an 0-terminated array of pairs of 114 NUMTYPEs. The terminating 0 is not included in the count. 115 */ 116 117 { 118 NUMTYPE nCount = 0; 119 while ( *pRanges ) 120 { 121 nCount += 2; 122 pRanges += 2; 123 } 124 return nCount; 125 } 126 127 //------------------------------------------------------------------------ 128 129 NUMTYPE Capacity_Impl( const NUMTYPE *pRanges ) 130 131 /** <H3>Description</H3> 132 133 Determines the total number of NUMTYPEs described in an 0-terminated 134 array of pairs of NUMTYPEs, each representing an range of NUMTYPEs. 135 */ 136 137 { 138 NUMTYPE nCount = 0; 139 140 if ( pRanges ) 141 { 142 while ( *pRanges ) 143 { 144 nCount += pRanges[1] - pRanges[0] + 1; 145 pRanges += 2; 146 } 147 } 148 return nCount; 149 } 150 151 //------------------------------------------------------------------------ 152 153 SfxNumRanges::SfxNumRanges( const SfxNumRanges &rOrig ) 154 155 /** <H3>Description</H3> 156 157 Copy-Ctor. 158 */ 159 160 { 161 if ( rOrig._pRanges ) 162 { 163 NUMTYPE nCount = Count_Impl( rOrig._pRanges ) + 1; 164 _pRanges = new NUMTYPE[nCount]; 165 memcpy( _pRanges, rOrig._pRanges, sizeof(NUMTYPE) * nCount ); 166 } 167 else 168 _pRanges = 0; 169 } 170 171 //------------------------------------------------------------------------ 172 173 SfxNumRanges::SfxNumRanges( NUMTYPE nWhich1, NUMTYPE nWhich2 ) 174 175 /** <H3>Description</H3> 176 177 Constructs an SfxNumRanges-instance from one range of NUMTYPEs. 178 179 precondition: 180 nWhich1 <= nWhich2 181 */ 182 183 : _pRanges( new NUMTYPE[3] ) 184 { 185 _pRanges[0] = nWhich1; 186 _pRanges[1] = nWhich2; 187 _pRanges[2] = 0; 188 } 189 190 //------------------------------------------------------------------------ 191 192 SfxNumRanges::SfxNumRanges( NUMTYPE_ARG nWh0, NUMTYPE_ARG nWh1, NUMTYPE_ARG nNull, ... ) 193 194 /** <H3>Description</H3> 195 196 Constructs an SfxNumRanges-instance from more than one sorted ranges of 197 NUMTYPEs terminated with one 0. 198 199 precondition: for each n >= 0 && n < nArgs 200 nWh(2n) <= nWh(2n+1) && ( nWh(2n+2)-nWh(2n+1) ) > 1 201 */ 202 203 { 204 va_list pArgs; 205 va_start( pArgs, nNull ); 206 InitializeRanges_Impl( 207 _pRanges, pArgs, sal::static_int_cast< NUMTYPE >(nWh0), 208 sal::static_int_cast< NUMTYPE >(nWh1), 209 sal::static_int_cast< NUMTYPE >(nNull)); 210 DBG_CHECK_RANGES(NUMTYPE, _pRanges); 211 } 212 213 //------------------------------------------------------------------------ 214 215 SfxNumRanges::SfxNumRanges( const NUMTYPE* pArr ) 216 217 /** <H3>Description</H3> 218 219 Constcurts an SfxNumRanges-instance from an sorted ranges of NUMTYPEs, 220 terminates with on 0. 221 222 precondition: for each n >= 0 && n < (sizeof(pArr)-1) 223 pArr[2n] <= pArr[2n+1] && ( pArr[2n+2]-pArr[2n+1] ) > 1 224 */ 225 226 { 227 DBG_CHECK_RANGES(NUMTYPE, pArr); 228 NUMTYPE nCount = Count_Impl(pArr) + 1; 229 _pRanges = new NUMTYPE[ nCount ]; 230 memcpy( _pRanges, pArr, sizeof(NUMTYPE) * nCount ); 231 } 232 233 //------------------------------------------------------------------------ 234 235 sal_Bool SfxNumRanges::operator==( const SfxNumRanges &rOther ) const 236 { 237 // Object pointers equal? 238 if ( this == &rOther ) 239 return sal_True; 240 241 // Ranges pointers equal? 242 if ( _pRanges == rOther._pRanges ) 243 return sal_True; 244 245 // Counts equal? 246 NUMTYPE nCount = Count(); 247 if ( nCount != rOther.Count() ) 248 return sal_False; 249 250 // Check arrays. 251 NUMTYPE n = 0; 252 while( _pRanges[ n ] != 0 ) 253 { 254 // Elements at current position equal? 255 if ( _pRanges[ n ] != rOther._pRanges[ n ] ) 256 return sal_False; 257 258 ++n; 259 } 260 261 return sal_True; 262 } 263 264 //------------------------------------------------------------------------ 265 266 SfxNumRanges& SfxNumRanges::operator = 267 ( 268 const SfxNumRanges &rRanges 269 ) 270 271 /** <H3>Description</H3> 272 273 Assigns ranges from 'rRanges' to '*this'. 274 */ 275 276 { 277 // special case: assign itself 278 if ( &rRanges == this ) 279 return *this; 280 281 delete[] _pRanges; 282 283 // special case: 'rRanges' is empty 284 if ( rRanges.IsEmpty() ) 285 _pRanges = 0; 286 else 287 { 288 // copy ranges 289 NUMTYPE nCount = Count_Impl( rRanges._pRanges ) + 1; 290 _pRanges = new NUMTYPE[ nCount ]; 291 memcpy( _pRanges, rRanges._pRanges, sizeof(NUMTYPE) * nCount ); 292 } 293 return *this; 294 } 295 296 //------------------------------------------------------------------------ 297 298 SfxNumRanges& SfxNumRanges::operator += 299 ( 300 const SfxNumRanges &rRanges 301 ) 302 303 /** <H3>Description</H3> 304 305 Merges *this with 'rRanges'. 306 307 for each NUMTYPE n: 308 this->Contains( n ) || rRanges.Contains( n ) => this'->Contains( n ) 309 !this->Contains( n ) && !rRanges.Contains( n ) => !this'->Contains( n ) 310 */ 311 312 { 313 // special cases: one is empty 314 if ( rRanges.IsEmpty() ) 315 return *this; 316 if ( IsEmpty() ) 317 return *this = rRanges; 318 319 // First, run thru _pRanges and rRanges._pRanges and determine the size of 320 // the new, merged ranges: 321 NUMTYPE nCount = 0; 322 const NUMTYPE * pRA = _pRanges; 323 const NUMTYPE * pRB = rRanges._pRanges; 324 325 for (;;) 326 { 327 // The first pair of pRA has a lower lower bound than the first pair 328 // of pRB: 329 if (pRA[0] > pRB[0]) 330 Swap_Impl(pRA, pRB); 331 332 // We are done with the merging if at least pRA is exhausted: 333 if (!pRA[0]) 334 break; 335 336 for (;;) 337 { 338 // Skip those pairs in pRB that completely lie in the first pair 339 // of pRA: 340 while (pRB[1] <= pRA[1]) 341 { 342 pRB += 2; 343 344 // Watch out for exhaustion of pRB: 345 if (!pRB[0]) 346 { 347 Swap_Impl(pRA, pRB); 348 goto count_rest; 349 } 350 } 351 352 // If the next pair of pRA does not at least touch the current new 353 // pair, we are done with the current new pair: 354 if (pRB[0] > pRA[1] + 1) 355 break; 356 357 // The next pair of pRB extends the current new pair; first, 358 // extend the current new pair (we are done if pRB is then 359 // exhausted); second, switch the roles of pRA and pRB in order to 360 // merge in those following pairs of the original pRA that will 361 // lie in the (now larger) current new pair or will even extend it 362 // further: 363 pRA += 2; 364 if (!pRA[0]) 365 goto count_rest; 366 Swap_Impl(pRA, pRB); 367 } 368 369 // Done with the current new pair: 370 pRA += 2; 371 nCount += 2; 372 } 373 374 // Only pRB has more pairs available, pRA is already exhausted: 375 count_rest: 376 for (; pRB[0]; pRB += 2) 377 nCount += 2; 378 379 // Now, create new ranges of the correct size and, on a second run thru 380 // _pRanges and rRanges._pRanges, copy the merged pairs into the new 381 // ranges: 382 NUMTYPE * pNew = new NUMTYPE[nCount + 1]; 383 pRA = _pRanges; 384 pRB = rRanges._pRanges; 385 NUMTYPE * pRN = pNew; 386 387 for (;;) 388 { 389 // The first pair of pRA has a lower lower bound than the first pair 390 // of pRB: 391 if (pRA[0] > pRB[0]) 392 Swap_Impl(pRA, pRB); 393 394 // We are done with the merging if at least pRA is exhausted: 395 if (!pRA[0]) 396 break; 397 398 // Lower bound of current new pair is already known: 399 *pRN++ = pRA[0]; 400 401 for (;;) 402 { 403 // Skip those pairs in pRB that completely lie in the first pair 404 // of pRA: 405 while (pRB[1] <= pRA[1]) 406 { 407 pRB += 2; 408 409 // Watch out for exhaustion of pRB: 410 if (!pRB[0]) 411 { 412 Swap_Impl(pRA, pRB); 413 ++pRB; 414 goto copy_rest; 415 } 416 } 417 418 // If the next pair of pRA does not at least touch the current new 419 // pair, we are done with the current new pair: 420 if (pRB[0] > pRA[1] + 1) 421 break; 422 423 // The next pair of pRB extends the current new pair; first, 424 // extend the current new pair (we are done if pRB is then 425 // exhausted); second, switch the roles of pRA and pRB in order to 426 // merge in those following pairs of the original pRA that will 427 // lie in the (now larger) current new pair or will even extend it 428 // further: 429 pRA += 2; 430 if (!pRA[0]) 431 { 432 ++pRB; 433 goto copy_rest; 434 } 435 Swap_Impl(pRA, pRB); 436 } 437 438 // Done with the current new pair, now upper bound is also known: 439 *pRN++ = pRA[1]; 440 pRA += 2; 441 } 442 443 // Only pRB has more pairs available (which are copied to the new ranges 444 // unchanged), pRA is already exhausted: 445 copy_rest: 446 for (; *pRB;) 447 *pRN++ = *pRB++; 448 *pRN = 0; 449 450 delete[] _pRanges; 451 _pRanges = pNew; 452 453 return *this; 454 } 455 456 //------------------------------------------------------------------------ 457 458 SfxNumRanges& SfxNumRanges::operator -= 459 ( 460 const SfxNumRanges &rRanges 461 ) 462 463 /** <H3>Description</H3> 464 465 Removes 'rRanges' from '*this'. 466 467 for each NUMTYPE n: 468 this->Contains( n ) && rRanges.Contains( n ) => !this'->Contains( n ) 469 this->Contains( n ) && !rRanges.Contains( n ) => this'->Contains( n ) 470 !this->Contains( n ) => !this'->Contains( n ) 471 */ 472 473 { 474 // special cases: one is empty 475 if ( rRanges.IsEmpty() || IsEmpty() ) 476 return *this; 477 478 // differentiate 'rRanges' in a temporary copy of '*this' 479 // (size is computed for maximal possibly split-count plus terminating 0) 480 NUMTYPE nThisSize = Count_Impl(_pRanges); 481 NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) ); 482 NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ]; 483 memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize ); 484 memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize ); 485 486 NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0; 487 while( _pRanges[ nPos1 ] ) 488 { 489 NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1 490 NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1 491 NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2 492 NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2 493 494 // boundary cases 495 // * subtrahend is empty -> copy the minuend 496 if( !l2 ) 497 { 498 pTarget[ nTargetPos ] = l1; 499 pTarget[ nTargetPos+1 ] = u1; 500 nTargetPos += 2; 501 nPos1 += 2; 502 continue; 503 } 504 // * next subtrahend interval is completely higher -> copy the minuend 505 if( u1 < l2 ) 506 { 507 pTarget[ nTargetPos ] = l1; 508 pTarget[ nTargetPos+1 ] = u1; 509 nTargetPos += 2; 510 nPos1 += 2; 511 continue; 512 } 513 514 // * next subtrahend interval is completely lower -> try next 515 if( u2 < l1 ) 516 { 517 nPos2 += 2; 518 continue; 519 } 520 521 // intersecting cases 522 // * subtrahend cuts out from the beginning of the minuend 523 if( l2 <= l1 && u2 <= u1 ) 524 { 525 // reduce minuend interval, try again (minuend might be affected by other subtrahend intervals) 526 _pRanges[ nPos1 ] = u2 + 1; 527 nPos2 += 2; // this cannot hurt any longer 528 continue; 529 } 530 531 // * subtrahend cuts out from the end of the minuend 532 if( l1 <= l2 && u1 <= u2 ) 533 { 534 // copy remaining part of minuend (cannot be affected by other intervals) 535 if( l1 < l2 ) // anything left at all? 536 { 537 pTarget[ nTargetPos ] = l1; 538 pTarget[ nTargetPos+1 ] = l2 - 1; 539 nTargetPos += 2; 540 // do not increment nPos2, might affect next minuend interval, too 541 } 542 nPos1 += 2; // nothing left at all 543 continue; 544 } 545 546 // * subtrahend completely deletes minuend (larger or same at both ends) 547 if( l1 >= l2 && u1 <= u2 ) 548 { 549 nPos1 += 2; // minuend deleted 550 // do not increment nPos2, might affect next minuend interval, too 551 continue; 552 } 553 554 // * subtrahend divides minuend into two pieces 555 if( l1 <= l2 && u1 >= u2 ) // >= and <= since they may be something left only at one side 556 { 557 // left side 558 if( l1 < l2 ) // anything left at all 559 { 560 pTarget[ nTargetPos ] = l1; 561 pTarget[ nTargetPos+1 ] = l2 - 1; 562 nTargetPos += 2; 563 } 564 565 // right side 566 if( u1 > u2 ) // anything left at all 567 { 568 // reduce minuend interval, try again (minuend might be affected by other subtrahend itnervals ) 569 _pRanges[ nPos1 ] = u2 + 1; 570 } 571 572 // subtrahend is completely used 573 nPos2 += 2; 574 continue; 575 } 576 577 // we should never be here 578 DBG_ERROR( "SfxNumRanges::operator-=: internal error" ); 579 } // while 580 581 pTarget[ nTargetPos ] = 0; 582 583 // assign the differentiated ranges 584 delete[] _pRanges; 585 586 NUMTYPE nUShorts = Count_Impl(pTarget) + 1; 587 if ( 1 != nUShorts ) 588 { 589 _pRanges = new NUMTYPE[ nUShorts ]; 590 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) ); 591 } 592 else 593 _pRanges = 0; 594 595 delete [] pTarget; 596 return *this; 597 598 /* untested code from MI commented out (MDA, 28.01.97) 599 do 600 { 601 // 1st range is smaller than 2nd range? 602 if ( pRange1[1] < pRange2[0] ) 603 // => keep 1st range 604 pRange1 += 2; 605 606 // 2nd range is smaller than 1st range? 607 else if ( pRange2[1] < pRange1[0] ) 608 // => skip 2nd range 609 pRange2 += 2; 610 611 // 2nd range totally overlaps the 1st range? 612 else if ( pRange2[0] <= pRange1[0] && pRange2[1] >= pRange1[1] ) 613 // => remove 1st range 614 memmove( pRange1, pRange1+2, sizeof(NUMTYPE) * (pEndOfTarget-pRange1+2) ); 615 616 // 2nd range overlaps only the beginning of 1st range? 617 else if ( pRange2[0] <= pRange1[0] && pRange2[1] < pRange1[1] ) 618 { 619 // => cut the beginning of 1st range and goto next 2nd range 620 pRange1[0] = pRange2[1] + 1; 621 pRange2 += 2; 622 } 623 624 // 2nd range overlaps only the end of 1st range? 625 else if ( pRange2[0] > pRange1[0] && pRange2[1] >= pRange1[0] ) 626 // => cut the beginning of 1st range 627 pRange1[0] = pRange2[1]+1; 628 629 // 2nd range is a real subset of 1st range 630 else 631 { 632 // => split 1st range and goto next 2nd range 633 memmove( pRange1+3, pRange1+1, sizeof(NUMTYPE) * (pEndOfTarget-pRange1-1) ); 634 pRange1[1] = pRange2[0] - 1; 635 pRange1[2] = pRange2[1] + 1; 636 pRange1 += 2; 637 pRange2 += 2; 638 } 639 } 640 while ( *pRange1 && *pRange2 ); 641 642 // assign the differentiated ranges 643 delete[] _pRanges; 644 NUMTYPE nUShorts = Count_Impl(pTarget) + 1; 645 if ( 1 != nUShorts ) 646 { 647 _pRanges = new NUMTYPE[ nUShorts ]; 648 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) ); 649 _pRanges[ nUShorts-1 ] = 0; 650 } 651 else 652 _pRanges = 0; 653 return *this; 654 */ 655 } 656 657 //------------------------------------------------------------------------ 658 659 SfxNumRanges& SfxNumRanges::operator /= 660 ( 661 const SfxNumRanges &rRanges 662 ) 663 664 /** <H3>Description</H3> 665 666 Determines intersection of '*this' with 'rRanges'. 667 668 for each NUMTYPE n: 669 this->Contains( n ) && rRanges.Contains( n ) => this'->Contains( n ) 670 !this->Contains( n ) => !this'->Contains( n ) 671 !rRanges.Contains( n ) => !this'->Contains( n ) 672 */ 673 674 { 675 // boundary cases 676 // * first set is empty -> nothing to be done 677 // * second set is empty -> delete first set 678 if( rRanges.IsEmpty() ) 679 { 680 delete[] _pRanges; 681 682 _pRanges = new NUMTYPE[1]; 683 _pRanges[0] = 0; 684 685 return *this; 686 } 687 688 // intersect 'rRanges' in a temporary copy of '*this' 689 // (size is computed for maximal possibly split-count plus terminating 0) 690 NUMTYPE nThisSize = Count_Impl(_pRanges); 691 NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) ); 692 NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ]; 693 memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize ); 694 memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize ); 695 696 NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0; 697 while( _pRanges[ nPos1 ] != 0 && rRanges._pRanges[ nPos2 ] != 0 ) 698 { 699 NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1 700 NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1 701 NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2 702 NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2 703 704 if( u1 < l2 ) 705 { 706 // current interval in s1 is completely before ci in s2 707 nPos1 += 2; 708 continue; 709 } 710 if( u2 < l1 ) 711 { 712 // ci in s2 is completely before ci in s1 713 nPos2 += 2; 714 continue; 715 } 716 717 // assert: there exists an intersection between ci1 and ci2 718 719 if( l1 <= l2 ) 720 { 721 // c1 "is more to the left" than c2 722 723 if( u1 <= u2 ) 724 { 725 pTarget[ nTargetPos ] = l2; 726 pTarget[ nTargetPos+1 ] = u1; 727 nTargetPos += 2; 728 nPos1 += 2; 729 continue; 730 } 731 else 732 { 733 pTarget[ nTargetPos ] = l2; 734 pTarget[ nTargetPos+1 ] = u2; 735 nTargetPos += 2; 736 nPos2 += 2; 737 } 738 } 739 else 740 { 741 // c2 "is more to the left" than c1" 742 743 if( u1 > u2 ) 744 { 745 pTarget[ nTargetPos ] = l1; 746 pTarget[ nTargetPos+1 ] = u2; 747 nTargetPos += 2; 748 nPos2 += 2; 749 } 750 else 751 { 752 pTarget[ nTargetPos ] = l1; 753 pTarget[ nTargetPos+1 ] = u1; 754 nTargetPos += 2; 755 nPos1 += 2; 756 } 757 } 758 }; // while 759 pTarget[ nTargetPos ] = 0; 760 761 // assign the intersected ranges 762 delete[] _pRanges; 763 764 NUMTYPE nUShorts = Count_Impl(pTarget) + 1; 765 if ( 1 != nUShorts ) 766 { 767 _pRanges = new NUMTYPE[ nUShorts ]; 768 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) ); 769 } 770 else 771 _pRanges = 0; 772 773 delete [] pTarget; 774 return *this; 775 } 776 777 //------------------------------------------------------------------------ 778 779 sal_Bool SfxNumRanges::Intersects( const SfxNumRanges &rRanges ) const 780 781 /** <H3>Description</H3> 782 783 Determines if at least one range in 'rRanges' intersects with one 784 range in '*this'. 785 786 sal_True, if there is at least one with: 787 this->Contains( n ) && rRanges.Contains( n ) 788 */ 789 790 { 791 // special cases: one is empty 792 if ( rRanges.IsEmpty() || IsEmpty() ) 793 return sal_False; 794 795 // find at least one intersecting range 796 const NUMTYPE *pRange1 = _pRanges; 797 const NUMTYPE *pRange2 = rRanges._pRanges; 798 799 do 800 { 801 // 1st range is smaller than 2nd range? 802 if ( pRange1[1] < pRange2[0] ) 803 // => keep 1st range 804 pRange1 += 2; 805 806 // 2nd range is smaller than 1st range? 807 else if ( pRange2[1] < pRange1[0] ) 808 // => skip 2nd range 809 pRange2 += 2; 810 811 // the ranges are overlappung 812 else 813 return sal_True; 814 } 815 while ( *pRange2 ); 816 817 // no intersection found 818 return sal_False; 819 } 820 821 //------------------------------------------------------------------------ 822 823 NUMTYPE SfxNumRanges::Count() const 824 825 /** <H3>Description</H3> 826 827 Determines the number of USHORTs in the set described by the ranges 828 of USHORTs in '*this'. 829 */ 830 831 { 832 return Capacity_Impl( _pRanges ); 833 } 834 835 //------------------------------------------------------------------------ 836 837 sal_Bool SfxNumRanges::Contains( NUMTYPE n ) const 838 839 /** <H3>Description</H3> 840 841 Determines if '*this' contains 'n'. 842 */ 843 844 { 845 for ( NUMTYPE *pRange = _pRanges; *pRange && *pRange <= n; pRange += 2 ) 846 if ( pRange[0] <= n && n <= pRange[1] ) 847 return sal_True; 848 return sal_False; 849 850 } 851