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_sc.hxx" 30 31 32 //------------------------------------------------------------------------ 33 34 #define SC_RANGELST_CXX //fuer ICC 35 36 #include <tools/debug.hxx> 37 #include <stdlib.h> // qsort 38 #include <unotools/collatorwrapper.hxx> 39 40 #include "rangelst.hxx" 41 #include "document.hxx" 42 #include "refupdat.hxx" 43 #include "rechead.hxx" 44 #include "compiler.hxx" 45 46 // === ScRangeList ==================================================== 47 48 ScRangeList::~ScRangeList() 49 { 50 for ( ScRangePtr pR = First(); pR; pR = Next() ) 51 delete pR; 52 } 53 54 void ScRangeList::RemoveAll() 55 { 56 for ( ScRangePtr pR = First(); pR; pR = Next() ) 57 delete pR; 58 Clear(); 59 } 60 61 sal_uInt16 ScRangeList::Parse( const String& rStr, ScDocument* pDoc, sal_uInt16 nMask, 62 formula::FormulaGrammar::AddressConvention eConv, 63 sal_Unicode cDelimiter ) 64 { 65 if ( rStr.Len() ) 66 { 67 if (!cDelimiter) 68 cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); 69 70 nMask |= SCA_VALID; // falls das jemand vergessen sollte 71 sal_uInt16 nResult = (sal_uInt16)~0; // alle Bits setzen 72 ScRange aRange; 73 String aOne; 74 SCTAB nTab = 0; 75 if ( pDoc ) 76 { 77 //! erste markierte Tabelle gibts nicht mehr am Dokument 78 //! -> uebergeben? oder spaeter an den Ranges setzen 79 } 80 else 81 nTab = 0; 82 sal_uInt16 nTCount = rStr.GetTokenCount( cDelimiter ); 83 for ( sal_uInt16 i=0; i<nTCount; i++ ) 84 { 85 aOne = rStr.GetToken( i, cDelimiter ); 86 // FIXME : broken for Lotus 87 if ( aOne.Search( ':' ) == STRING_NOTFOUND ) 88 { // Range muss es sein 89 String aStrTmp( aOne ); 90 aOne += ':'; 91 aOne += aStrTmp; 92 } 93 aRange.aStart.SetTab( nTab ); // Default Tab wenn nicht angegeben 94 sal_uInt16 nRes = aRange.Parse( aOne, pDoc, eConv ); 95 if ( (nRes & nMask) == nMask ) 96 Append( aRange ); 97 nResult &= nRes; // alle gemeinsamen Bits bleiben erhalten 98 } 99 return nResult; // SCA_VALID gesetzt wenn alle ok 100 } 101 else 102 return 0; 103 } 104 105 106 void ScRangeList::Format( String& rStr, sal_uInt16 nFlags, ScDocument* pDoc, 107 formula::FormulaGrammar::AddressConvention eConv, 108 sal_Unicode cDelimiter ) const 109 { 110 rStr.Erase(); 111 112 if (!cDelimiter) 113 cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); 114 115 sal_uLong nCnt = Count(); 116 for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ ) 117 { 118 String aStr; 119 GetObject( nIdx )->Format( aStr, nFlags, pDoc, eConv ); 120 if ( nIdx ) 121 rStr += cDelimiter; 122 rStr += aStr; 123 } 124 } 125 126 127 void ScRangeList::Join( const ScRange& r, sal_Bool bIsInList ) 128 { 129 if ( !Count() ) 130 { 131 Append( r ); 132 return ; 133 } 134 SCCOL nCol1 = r.aStart.Col(); 135 SCROW nRow1 = r.aStart.Row(); 136 SCTAB nTab1 = r.aStart.Tab(); 137 SCCOL nCol2 = r.aEnd.Col(); 138 SCROW nRow2 = r.aEnd.Row(); 139 SCTAB nTab2 = r.aEnd.Tab(); 140 ScRangePtr pOver = (ScRangePtr) &r; // fies aber wahr wenn bInList 141 sal_uLong nOldPos = 0; 142 if ( bIsInList ) 143 { // merken um ggbf. zu loeschen bzw. wiederherzustellen 144 nOldPos = GetPos( pOver ); 145 } 146 sal_Bool bJoinedInput = sal_False; 147 for ( ScRangePtr p = First(); p && pOver; p = Next() ) 148 { 149 if ( p == pOver ) 150 continue; // derselbe, weiter mit dem naechsten 151 sal_Bool bJoined = sal_False; 152 if ( p->In( r ) ) 153 { // Range r in Range p enthalten oder identisch 154 if ( bIsInList ) 155 bJoined = sal_True; // weg mit Range r 156 else 157 { // das war's dann 158 bJoinedInput = sal_True; // nicht anhaengen 159 break; // for 160 } 161 } 162 else if ( r.In( *p ) ) 163 { // Range p in Range r enthalten, r zum neuen Range machen 164 *p = r; 165 bJoined = sal_True; 166 } 167 if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 ) 168 { // 2D 169 if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 ) 170 { 171 if ( p->aStart.Row() == nRow2+1 ) 172 { // oben 173 p->aStart.SetRow( nRow1 ); 174 bJoined = sal_True; 175 } 176 else if ( p->aEnd.Row() == nRow1-1 ) 177 { // unten 178 p->aEnd.SetRow( nRow2 ); 179 bJoined = sal_True; 180 } 181 } 182 else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 ) 183 { 184 if ( p->aStart.Col() == nCol2+1 ) 185 { // links 186 p->aStart.SetCol( nCol1 ); 187 bJoined = sal_True; 188 } 189 else if ( p->aEnd.Col() == nCol1-1 ) 190 { // rechts 191 p->aEnd.SetCol( nCol2 ); 192 bJoined = sal_True; 193 } 194 } 195 } 196 if ( bJoined ) 197 { 198 if ( bIsInList ) 199 { // innerhalb der Liste Range loeschen 200 Remove( nOldPos ); 201 delete pOver; 202 pOver = NULL; 203 if ( nOldPos ) 204 nOldPos--; // Seek richtig aufsetzen 205 } 206 bJoinedInput = sal_True; 207 Join( *p, sal_True ); // rekursiv! 208 } 209 } 210 if ( bIsInList ) 211 Seek( nOldPos ); 212 else if ( !bJoinedInput ) 213 Append( r ); 214 } 215 216 217 sal_Bool ScRangeList::operator==( const ScRangeList& r ) const 218 { 219 if ( this == &r ) 220 return sal_True; // identische Referenz 221 if ( Count() != r.Count() ) 222 return sal_False; 223 sal_uLong nCnt = Count(); 224 for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ ) 225 { 226 if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) ) 227 return sal_False; // auch andere Reihenfolge ist ungleich 228 } 229 return sal_True; 230 } 231 232 sal_Bool ScRangeList::operator!=( const ScRangeList& r ) const 233 { 234 return !operator==( r ); 235 } 236 237 sal_Bool ScRangeList::UpdateReference( UpdateRefMode eUpdateRefMode, 238 ScDocument* pDoc, const ScRange& rWhere, 239 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) 240 { 241 sal_Bool bChanged = sal_False; 242 if ( Count() ) 243 { 244 SCCOL nCol1; 245 SCROW nRow1; 246 SCTAB nTab1; 247 SCCOL nCol2; 248 SCROW nRow2; 249 SCTAB nTab2; 250 rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 251 for ( ScRange* pR = First(); pR; pR = Next() ) 252 { 253 SCCOL theCol1; 254 SCROW theRow1; 255 SCTAB theTab1; 256 SCCOL theCol2; 257 SCROW theRow2; 258 SCTAB theTab2; 259 pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); 260 if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, 261 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, 262 nDx, nDy, nDz, 263 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ) 264 != UR_NOTHING ) 265 { 266 bChanged = sal_True; 267 pR->aStart.Set( theCol1, theRow1, theTab1 ); 268 pR->aEnd.Set( theCol2, theRow2, theTab2 ); 269 } 270 } 271 } 272 return bChanged; 273 } 274 275 276 ScRange* ScRangeList::Find( const ScAddress& rAdr ) const 277 { 278 sal_uLong nListCount = Count(); 279 for ( sal_uLong j = 0; j < nListCount; j++ ) 280 { 281 ScRange* pR = GetObject( j ); 282 if ( pR->In( rAdr ) ) 283 return pR; 284 } 285 return NULL; 286 } 287 288 289 ScRangeList::ScRangeList( const ScRangeList& rList ) : 290 ScRangeListBase(), 291 SvRefBase() 292 { 293 sal_uLong nListCount = rList.Count(); 294 for ( sal_uLong j = 0; j < nListCount; j++ ) 295 Append( *rList.GetObject( j ) ); 296 } 297 298 299 ScRangeList& ScRangeList::operator=(const ScRangeList& rList) 300 { 301 RemoveAll(); 302 303 sal_uLong nListCount = rList.Count(); 304 for ( sal_uLong j = 0; j < nListCount; j++ ) 305 Append( *rList.GetObject( j ) ); 306 307 return *this; 308 } 309 310 311 sal_Bool ScRangeList::Intersects( const ScRange& rRange ) const 312 { 313 sal_uLong nListCount = Count(); 314 for ( sal_uLong j = 0; j < nListCount; j++ ) 315 if ( GetObject(j)->Intersects( rRange ) ) 316 return sal_True; 317 318 return sal_False; 319 } 320 321 322 sal_Bool ScRangeList::In( const ScRange& rRange ) const 323 { 324 sal_uLong nListCount = Count(); 325 for ( sal_uLong j = 0; j < nListCount; j++ ) 326 if ( GetObject(j)->In( rRange ) ) 327 return sal_True; 328 329 return sal_False; 330 } 331 332 333 sal_uLong ScRangeList::GetCellCount() const 334 { 335 sal_uLong nCellCount = 0; 336 sal_uLong nListCount = Count(); 337 for ( sal_uLong j = 0; j < nListCount; j++ ) 338 { 339 ScRange* pR = GetObject( j ); 340 nCellCount += sal_uLong(pR->aEnd.Col() - pR->aStart.Col() + 1) 341 * sal_uLong(pR->aEnd.Row() - pR->aStart.Row() + 1) 342 * sal_uLong(pR->aEnd.Tab() - pR->aStart.Tab() + 1); 343 } 344 return nCellCount; 345 } 346 347 348 // === ScRangePairList ==================================================== 349 350 ScRangePairList::~ScRangePairList() 351 { 352 for ( ScRangePair* pR = First(); pR; pR = Next() ) 353 delete pR; 354 } 355 356 357 void ScRangePairList::Join( const ScRangePair& r, sal_Bool bIsInList ) 358 { 359 if ( !Count() ) 360 { 361 Append( r ); 362 return ; 363 } 364 const ScRange& r1 = r.GetRange(0); 365 const ScRange& r2 = r.GetRange(1); 366 SCCOL nCol1 = r1.aStart.Col(); 367 SCROW nRow1 = r1.aStart.Row(); 368 SCTAB nTab1 = r1.aStart.Tab(); 369 SCCOL nCol2 = r1.aEnd.Col(); 370 SCROW nRow2 = r1.aEnd.Row(); 371 SCTAB nTab2 = r1.aEnd.Tab(); 372 ScRangePair* pOver = (ScRangePair*) &r; // fies aber wahr wenn bInList 373 sal_uLong nOldPos = 0; 374 if ( bIsInList ) 375 { // merken um ggbf. zu loeschen bzw. wiederherzustellen 376 nOldPos = GetPos( pOver ); 377 } 378 sal_Bool bJoinedInput = sal_False; 379 for ( ScRangePair* p = First(); p && pOver; p = Next() ) 380 { 381 if ( p == pOver ) 382 continue; // derselbe, weiter mit dem naechsten 383 sal_Bool bJoined = sal_False; 384 ScRange& rp1 = p->GetRange(0); 385 ScRange& rp2 = p->GetRange(1); 386 if ( rp2 == r2 ) 387 { // nur wenn Range2 gleich ist 388 if ( rp1.In( r1 ) ) 389 { // RangePair r in RangePair p enthalten oder identisch 390 if ( bIsInList ) 391 bJoined = sal_True; // weg mit RangePair r 392 else 393 { // das war's dann 394 bJoinedInput = sal_True; // nicht anhaengen 395 break; // for 396 } 397 } 398 else if ( r1.In( rp1 ) ) 399 { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen 400 *p = r; 401 bJoined = sal_True; 402 } 403 } 404 if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2 405 && rp2.aStart.Tab() == r2.aStart.Tab() 406 && rp2.aEnd.Tab() == r2.aEnd.Tab() ) 407 { // 2D, Range2 muss genauso nebeneinander liegen wie Range1 408 if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2 409 && rp2.aStart.Col() == r2.aStart.Col() 410 && rp2.aEnd.Col() == r2.aEnd.Col() ) 411 { 412 if ( rp1.aStart.Row() == nRow2+1 413 && rp2.aStart.Row() == r2.aEnd.Row()+1 ) 414 { // oben 415 rp1.aStart.SetRow( nRow1 ); 416 rp2.aStart.SetRow( r2.aStart.Row() ); 417 bJoined = sal_True; 418 } 419 else if ( rp1.aEnd.Row() == nRow1-1 420 && rp2.aEnd.Row() == r2.aStart.Row()-1 ) 421 { // unten 422 rp1.aEnd.SetRow( nRow2 ); 423 rp2.aEnd.SetRow( r2.aEnd.Row() ); 424 bJoined = sal_True; 425 } 426 } 427 else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2 428 && rp2.aStart.Row() == r2.aStart.Row() 429 && rp2.aEnd.Row() == r2.aEnd.Row() ) 430 { 431 if ( rp1.aStart.Col() == nCol2+1 432 && rp2.aStart.Col() == r2.aEnd.Col()+1 ) 433 { // links 434 rp1.aStart.SetCol( nCol1 ); 435 rp2.aStart.SetCol( r2.aStart.Col() ); 436 bJoined = sal_True; 437 } 438 else if ( rp1.aEnd.Col() == nCol1-1 439 && rp2.aEnd.Col() == r2.aEnd.Col()-1 ) 440 { // rechts 441 rp1.aEnd.SetCol( nCol2 ); 442 rp2.aEnd.SetCol( r2.aEnd.Col() ); 443 bJoined = sal_True; 444 } 445 } 446 } 447 if ( bJoined ) 448 { 449 if ( bIsInList ) 450 { // innerhalb der Liste RangePair loeschen 451 Remove( nOldPos ); 452 delete pOver; 453 pOver = NULL; 454 if ( nOldPos ) 455 nOldPos--; // Seek richtig aufsetzen 456 } 457 bJoinedInput = sal_True; 458 Join( *p, sal_True ); // rekursiv! 459 } 460 } 461 if ( bIsInList ) 462 Seek( nOldPos ); 463 else if ( !bJoinedInput ) 464 Append( r ); 465 } 466 467 468 sal_Bool ScRangePairList::operator==( const ScRangePairList& r ) const 469 { 470 if ( this == &r ) 471 return sal_True; // identische Referenz 472 if ( Count() != r.Count() ) 473 return sal_False; 474 sal_uLong nCnt = Count(); 475 for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ ) 476 { 477 if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) ) 478 return sal_False; // auch andere Reihenfolge ist ungleich 479 } 480 return sal_True; 481 } 482 483 484 sal_Bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode, 485 ScDocument* pDoc, const ScRange& rWhere, 486 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) 487 { 488 sal_Bool bChanged = sal_False; 489 if ( Count() ) 490 { 491 SCCOL nCol1; 492 SCROW nRow1; 493 SCTAB nTab1; 494 SCCOL nCol2; 495 SCROW nRow2; 496 SCTAB nTab2; 497 rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 498 for ( ScRangePair* pR = First(); pR; pR = Next() ) 499 { 500 for ( sal_uInt16 j=0; j<2; j++ ) 501 { 502 ScRange& rRange = pR->GetRange(j); 503 SCCOL theCol1; 504 SCROW theRow1; 505 SCTAB theTab1; 506 SCCOL theCol2; 507 SCROW theRow2; 508 SCTAB theTab2; 509 rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ); 510 if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, 511 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, 512 nDx, nDy, nDz, 513 theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 ) 514 != UR_NOTHING ) 515 { 516 bChanged = sal_True; 517 rRange.aStart.Set( theCol1, theRow1, theTab1 ); 518 rRange.aEnd.Set( theCol2, theRow2, theTab2 ); 519 } 520 } 521 } 522 } 523 return bChanged; 524 } 525 526 527 void ScRangePairList::DeleteOnTab( SCTAB nTab ) 528 { 529 // Delete entries that have the labels (first range) on nTab 530 531 sal_uLong nListCount = Count(); 532 sal_uLong nPos = 0; 533 while ( nPos < nListCount ) 534 { 535 ScRangePair* pR = GetObject( nPos ); 536 ScRange aRange = pR->GetRange(0); 537 if ( aRange.aStart.Tab() == nTab && aRange.aEnd.Tab() == nTab ) 538 { 539 Remove( nPos ); 540 delete pR; 541 nListCount = Count(); 542 } 543 else 544 ++nPos; 545 } 546 } 547 548 549 ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const 550 { 551 sal_uLong nListCount = Count(); 552 for ( sal_uLong j = 0; j < nListCount; j++ ) 553 { 554 ScRangePair* pR = GetObject( j ); 555 if ( pR->GetRange(0).In( rAdr ) ) 556 return pR; 557 } 558 return NULL; 559 } 560 561 562 ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const 563 { 564 sal_uLong nListCount = Count(); 565 for ( sal_uLong j = 0; j < nListCount; j++ ) 566 { 567 ScRangePair* pR = GetObject( j ); 568 if ( pR->GetRange(0) == rRange ) 569 return pR; 570 } 571 return NULL; 572 } 573 574 575 ScRangePairList* ScRangePairList::Clone() const 576 { 577 ScRangePairList* pNew = new ScRangePairList; 578 sal_uLong nListCount = Count(); 579 for ( sal_uLong j = 0; j < nListCount; j++ ) 580 { 581 pNew->Append( *GetObject( j ) ); 582 } 583 return pNew; 584 } 585 586 587 struct ScRangePairNameSort 588 { 589 ScRangePair* pPair; 590 ScDocument* pDoc; 591 }; 592 593 594 extern "C" int 595 #ifdef WNT 596 __cdecl 597 #endif 598 ScRangePairList_QsortNameCompare( const void* p1, const void* p2 ) 599 { 600 const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1; 601 const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2; 602 const ScAddress& rStartPos1 = ps1->pPair->GetRange(0).aStart; 603 const ScAddress& rStartPos2 = ps2->pPair->GetRange(0).aStart; 604 String aStr1, aStr2; 605 sal_Int32 nComp; 606 if ( rStartPos1.Tab() == rStartPos2.Tab() ) 607 nComp = COMPARE_EQUAL; 608 else 609 { 610 ps1->pDoc->GetName( rStartPos1.Tab(), aStr1 ); 611 ps2->pDoc->GetName( rStartPos2.Tab(), aStr2 ); 612 nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 ); 613 } 614 switch ( nComp ) 615 { 616 case COMPARE_LESS: 617 return -1; 618 //break; 619 case COMPARE_GREATER: 620 return 1; 621 //break; 622 default: 623 // gleiche Tabs 624 if ( rStartPos1.Col() < rStartPos2.Col() ) 625 return -1; 626 if ( rStartPos1.Col() > rStartPos2.Col() ) 627 return 1; 628 // gleiche Cols 629 if ( rStartPos1.Row() < rStartPos2.Row() ) 630 return -1; 631 if ( rStartPos1.Row() > rStartPos2.Row() ) 632 return 1; 633 // erste Ecke gleich, zweite Ecke 634 { 635 const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd; 636 const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd; 637 if ( rEndPos1.Tab() == rEndPos2.Tab() ) 638 nComp = COMPARE_EQUAL; 639 else 640 { 641 ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 ); 642 ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 ); 643 nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 ); 644 } 645 switch ( nComp ) 646 { 647 case COMPARE_LESS: 648 return -1; 649 //break; 650 case COMPARE_GREATER: 651 return 1; 652 //break; 653 default: 654 // gleiche Tabs 655 if ( rEndPos1.Col() < rEndPos2.Col() ) 656 return -1; 657 if ( rEndPos1.Col() > rEndPos2.Col() ) 658 return 1; 659 // gleiche Cols 660 if ( rEndPos1.Row() < rEndPos2.Row() ) 661 return -1; 662 if ( rEndPos1.Row() > rEndPos2.Row() ) 663 return 1; 664 return 0; 665 } 666 } 667 return 0; 668 } 669 return 0; // just in case 670 } 671 672 673 ScRangePair** ScRangePairList::CreateNameSortedArray( sal_uLong& nListCount, 674 ScDocument* pDoc ) const 675 { 676 nListCount = Count(); 677 DBG_ASSERT( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F, 678 "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" ); 679 ScRangePairNameSort* pSortArray = (ScRangePairNameSort*) 680 new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ]; 681 sal_uLong j; 682 for ( j=0; j < nListCount; j++ ) 683 { 684 pSortArray[j].pPair = GetObject( j ); 685 pSortArray[j].pDoc = pDoc; 686 } 687 #if !(defined(ICC ) && defined(OS2)) 688 qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare ); 689 #else 690 qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), ICCQsortRPairCompare ); 691 #endif 692 // ScRangePair Pointer aufruecken 693 ScRangePair** ppSortArray = (ScRangePair**)pSortArray; 694 for ( j=0; j < nListCount; j++ ) 695 { 696 ppSortArray[j] = pSortArray[j].pPair; 697 } 698 return ppSortArray; 699 } 700 701 702 703 704