xref: /trunk/main/sc/source/core/tool/rangelst.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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