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