xref: /AOO41X/main/sc/source/core/tool/rangelst.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 
~ScRangeList()44 ScRangeList::~ScRangeList()
45 {
46     for ( ScRangePtr pR = First(); pR; pR = Next() )
47         delete pR;
48 }
49 
RemoveAll()50 void ScRangeList::RemoveAll()
51 {
52     for ( ScRangePtr pR = First(); pR; pR = Next() )
53         delete pR;
54     Clear();
55 }
56 
Parse(const String & rStr,ScDocument * pDoc,sal_uInt16 nMask,formula::FormulaGrammar::AddressConvention eConv,sal_Unicode cDelimiter)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 
Format(String & rStr,sal_uInt16 nFlags,ScDocument * pDoc,formula::FormulaGrammar::AddressConvention eConv,sal_Unicode cDelimiter) const102 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 
Join(const ScRange & r,sal_Bool bIsInList)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 
operator ==(const ScRangeList & r) const213 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 
operator !=(const ScRangeList & r) const228 sal_Bool ScRangeList::operator!=( const ScRangeList& r ) const
229 {
230     return !operator==( r );
231 }
232 
UpdateReference(UpdateRefMode eUpdateRefMode,ScDocument * pDoc,const ScRange & rWhere,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)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 
Find(const ScAddress & rAdr) const272 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 
ScRangeList(const ScRangeList & rList)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 
operator =(const ScRangeList & rList)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 
Intersects(const ScRange & rRange) const307 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 
In(const ScRange & rRange) const318 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 
GetCellCount() const329 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 
~ScRangePairList()346 ScRangePairList::~ScRangePairList()
347 {
348     for ( ScRangePair* pR = First(); pR; pR = Next() )
349         delete pR;
350 }
351 
352 
Join(const ScRangePair & r,sal_Bool bIsInList)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 
operator ==(const ScRangePairList & r) const464 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 
UpdateReference(UpdateRefMode eUpdateRefMode,ScDocument * pDoc,const ScRange & rWhere,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)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 
DeleteOnTab(SCTAB nTab)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 
Find(const ScAddress & rAdr) const545 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 
Find(const ScRange & rRange) const558 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 
Clone() const571 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
ScRangePairList_QsortNameCompare(const void * p1,const void * p2)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 
CreateNameSortedArray(sal_uLong & nListCount,ScDocument * pDoc) const669 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