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