xref: /trunk/main/sc/source/core/tool/rangelst.cxx (revision e8e74e65)
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 		case COMPARE_GREATER:
615 			return 1;
616 		default:
617 			// gleiche Tabs
618 			if ( rStartPos1.Col() < rStartPos2.Col() )
619 				return -1;
620 			if ( rStartPos1.Col() > rStartPos2.Col() )
621 				return 1;
622 			// gleiche Cols
623 			if ( rStartPos1.Row() < rStartPos2.Row() )
624 				return -1;
625 			if ( rStartPos1.Row() > rStartPos2.Row() )
626 				return 1;
627 			// erste Ecke gleich, zweite Ecke
628 			{
629 				const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd;
630 				const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd;
631 				if ( rEndPos1.Tab() == rEndPos2.Tab() )
632 					nComp = COMPARE_EQUAL;
633 				else
634 				{
635 					ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 );
636 					ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 );
637 					nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
638 				}
639 				switch ( nComp )
640 				{
641 					case COMPARE_LESS:
642 						return -1;
643 					case COMPARE_GREATER:
644 						return 1;
645 					default:
646 						// gleiche Tabs
647 						if ( rEndPos1.Col() < rEndPos2.Col() )
648 							return -1;
649 						if ( rEndPos1.Col() > rEndPos2.Col() )
650 							return 1;
651 						// gleiche Cols
652 						if ( rEndPos1.Row() < rEndPos2.Row() )
653 							return -1;
654 						if ( rEndPos1.Row() > rEndPos2.Row() )
655 							return 1;
656 						return 0;
657 				}
658 			}
659 	}
660 }
661 
662 
CreateNameSortedArray(sal_uLong & nListCount,ScDocument * pDoc) const663 ScRangePair** ScRangePairList::CreateNameSortedArray( sal_uLong& nListCount,
664 		ScDocument* pDoc ) const
665 {
666 	nListCount = Count();
667 	DBG_ASSERT( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F,
668 		"ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
669 	ScRangePairNameSort* pSortArray = (ScRangePairNameSort*)
670 		new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ];
671 	sal_uLong j;
672 	for ( j=0; j < nListCount; j++ )
673 	{
674 		pSortArray[j].pPair = GetObject( j );
675 		pSortArray[j].pDoc = pDoc;
676 	}
677 #if !(defined(ICC ) && defined(OS2))
678 	qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare );
679 #else
680 	qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), ICCQsortRPairCompare );
681 #endif
682 	// ScRangePair Pointer aufruecken
683 	ScRangePair** ppSortArray = (ScRangePair**)pSortArray;
684 	for ( j=0; j < nListCount; j++ )
685 	{
686 		ppSortArray[j] = pSortArray[j].pPair;
687 	}
688 	return ppSortArray;
689 }
690 
691 
692 
693 
694