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