1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/string.hxx>
22 #include <unotools/collatorwrapper.hxx>
23 #include <osl/diagnose.h>
25 #include "rangelst.hxx"
26 #include "document.hxx"
27 #include "refupdat.hxx"
28 #include "rechead.hxx"
29 #include "compiler.hxx"
30 #include <boost/checked_delete.hpp>
36 using ::std::for_each
;
37 using ::formula::FormulaGrammar
;
42 class FindEnclosingRange
: public ::std::unary_function
<ScRange
*, bool>
45 FindEnclosingRange(const T
& rTest
) : mrTest(rTest
) {}
46 FindEnclosingRange(const FindEnclosingRange
& r
) : mrTest(r
.mrTest
) {}
47 bool operator() (const ScRange
* pRange
) const
49 return pRange
->In(mrTest
);
56 class FindRangeIn
: public ::std::unary_function
<ScRange
*, bool>
59 FindRangeIn(const T
& rTest
) : mrTest(rTest
) {}
60 FindRangeIn(const FindRangeIn
& r
) : mrTest(r
.mrTest
) {}
61 bool operator() (const ScRange
* pRange
) const
63 return mrTest
.In(*pRange
);
70 class FindIntersectingRange
: public ::std::unary_function
<ScRange
*, bool>
73 FindIntersectingRange(const T
& rTest
) : mrTest(rTest
) {}
74 FindIntersectingRange(const FindIntersectingRange
& r
) : mrTest(r
.mrTest
) {}
75 bool operator() (const ScRange
* pRange
) const
77 return pRange
->Intersects(mrTest
);
83 class AppendToList
: public ::std::unary_function
<const ScRange
*, void>
86 AppendToList(vector
<ScRange
*>& rRanges
) : mrRanges(rRanges
) {}
87 AppendToList(const AppendToList
& r
) : mrRanges(r
.mrRanges
) {}
88 void operator() (const ScRange
* p
)
90 mrRanges
.push_back(new ScRange(*p
));
93 vector
<ScRange
*>& mrRanges
;
96 class CountCells
: public ::std::unary_function
<const ScRange
*, void>
99 CountCells() : mnCellCount(0) {}
100 CountCells(const CountCells
& r
) : mnCellCount(r
.mnCellCount
) {}
102 void operator() (const ScRange
* p
)
105 size_t(p
->aEnd
.Col() - p
->aStart
.Col() + 1)
106 * size_t(p
->aEnd
.Row() - p
->aStart
.Row() + 1)
107 * size_t(p
->aEnd
.Tab() - p
->aStart
.Tab() + 1);
110 size_t getCellCount() const { return mnCellCount
; }
116 class FormatString
: public ::std::unary_function
<const ScRange
*, void>
119 FormatString(OUString
& rStr
, sal_uInt16 nFlags
, ScDocument
* pDoc
, FormulaGrammar::AddressConvention eConv
, sal_Unicode cDelim
) :
127 FormatString(const FormatString
& r
) :
133 mbFirst(r
.mbFirst
) {}
135 void operator() (const ScRange
* p
)
137 OUString
aStr(p
->Format(mnFlags
, mpDoc
, meConv
));
141 mrStr
+= OUString(mcDelim
);
148 FormulaGrammar::AddressConvention meConv
;
156 ScRangeList::~ScRangeList()
161 sal_uInt16
ScRangeList::Parse( const OUString
& rStr
, ScDocument
* pDoc
, sal_uInt16 nMask
,
162 formula::FormulaGrammar::AddressConvention eConv
,
163 SCTAB nDefaultTab
, sal_Unicode cDelimiter
)
165 if ( !rStr
.isEmpty() )
168 cDelimiter
= ScCompiler::GetNativeSymbolChar(ocSep
);
170 nMask
|= SCA_VALID
; // falls das jemand vergessen sollte
171 sal_uInt16 nResult
= (sal_uInt16
)~0; // alle Bits setzen
181 sal_uInt16 nTCount
= comphelper::string::getTokenCount(rStr
, cDelimiter
);
182 for ( sal_uInt16 i
=0; i
<nTCount
; i
++ )
184 aOne
= rStr
.getToken( i
, cDelimiter
);
185 aRange
.aStart
.SetTab( nTab
); // Default Tab wenn nicht angegeben
186 sal_uInt16 nRes
= aRange
.ParseAny( aOne
, pDoc
, eConv
);
187 sal_uInt16 nEndRangeBits
= SCA_VALID_COL2
| SCA_VALID_ROW2
| SCA_VALID_TAB2
;
188 sal_uInt16 nTmp1
= ( nRes
& SCA_BITS
);
189 sal_uInt16 nTmp2
= ( nRes
& nEndRangeBits
);
190 // If we have a valid single range with
191 // any of the address bits we are interested in
192 // set - set the equiv end range bits
193 if ( (nRes
& SCA_VALID
) && nTmp1
&& ( nTmp2
!= nEndRangeBits
) )
194 nRes
|= ( nTmp1
<< 4 );
196 if ( (nRes
& nMask
) == nMask
)
198 nResult
&= nRes
; // alle gemeinsamen Bits bleiben erhalten
200 return nResult
; // SCA_VALID gesetzt wenn alle ok
206 void ScRangeList::Format( OUString
& rStr
, sal_uInt16 nFlags
, ScDocument
* pDoc
,
207 formula::FormulaGrammar::AddressConvention eConv
,
208 sal_Unicode cDelimiter
) const
212 cDelimiter
= ScCompiler::GetNativeSymbolChar(ocSep
);
215 FormatString
func(aStr
, nFlags
, pDoc
, eConv
, cDelimiter
);
216 for_each(maRanges
.begin(), maRanges
.end(), func
);
220 void ScRangeList::Join( const ScRange
& r
, bool bIsInList
)
222 if ( maRanges
.empty() )
227 SCCOL nCol1
= r
.aStart
.Col();
228 SCROW nRow1
= r
.aStart
.Row();
229 SCTAB nTab1
= r
.aStart
.Tab();
230 SCCOL nCol2
= r
.aEnd
.Col();
231 SCROW nRow2
= r
.aEnd
.Row();
232 SCTAB nTab2
= r
.aEnd
.Tab();
234 // One common usage is to join ranges that actually are top to bottom
235 // appends but the caller doesn't exactly know about it, e.g. when invoked
236 // by ScMarkData::FillRangeListWithMarks(), check for this special case
237 // first and speed up things by not looping over all ranges for each range
238 // to be joined. We don't remember the exact encompassing range that would
239 // have to be updated on refupdates and insertions and deletions, instead
240 // remember just the maximum row used, even independently of the sheet.
241 // This satisfies most use cases.
245 if (nRow1
> mnMaxRowUsed
+ 1)
250 else if (nRow1
== mnMaxRowUsed
+ 1)
252 // Check if we can simply enlarge the last range.
253 ScRange
* p
= maRanges
.back();
254 if (p
->aEnd
.Row() + 1 == nRow1
&&
255 p
->aStart
.Col() == nCol1
&& p
->aEnd
.Col() == nCol2
&&
256 p
->aStart
.Tab() == nTab1
&& p
->aEnd
.Tab() == nTab2
)
258 p
->aEnd
.SetRow( nRow2
);
259 mnMaxRowUsed
= nRow2
;
265 ScRange
* pOver
= const_cast<ScRange
*>(&r
); // fies aber wahr wenn bInList
269 // Find the current position of this range.
270 for ( size_t i
= 0, nRanges
= maRanges
.size(); i
< nRanges
; ++i
)
272 if ( maRanges
[i
] == pOver
)
279 bool bJoinedInput
= false;
281 // We need to query the size of the container dynamically since its size
282 // may change during the loop.
283 for ( size_t i
= 0; i
< maRanges
.size() && pOver
; ++i
)
285 ScRange
* p
= maRanges
[i
];
287 continue; // derselbe, weiter mit dem naechsten
288 bool bJoined
= false;
290 { // Range r in Range p enthalten oder identisch
292 bJoined
= true; // weg mit Range r
295 bJoinedInput
= true; // nicht anhaengen
299 else if ( r
.In( *p
) )
300 { // Range p in Range r enthalten, r zum neuen Range machen
304 if ( !bJoined
&& p
->aStart
.Tab() == nTab1
&& p
->aEnd
.Tab() == nTab2
)
306 if ( p
->aStart
.Col() == nCol1
&& p
->aEnd
.Col() == nCol2
)
308 if ( p
->aStart
.Row() == nRow2
+1 )
310 p
->aStart
.SetRow( nRow1
);
313 else if ( p
->aEnd
.Row() == nRow1
-1 )
315 p
->aEnd
.SetRow( nRow2
);
319 else if ( p
->aStart
.Row() == nRow1
&& p
->aEnd
.Row() == nRow2
)
321 if ( p
->aStart
.Col() == nCol2
+1 )
323 p
->aStart
.SetCol( nCol1
);
326 else if ( p
->aEnd
.Col() == nCol1
-1 )
328 p
->aEnd
.SetCol( nCol2
);
336 { // innerhalb der Liste Range loeschen
342 nOldPos
--; // Seek richtig aufsetzen
345 Join( *p
, true ); // rekursiv!
348 if ( !bIsInList
&& !bJoinedInput
)
352 bool ScRangeList::operator==( const ScRangeList
& r
) const
357 if (maRanges
.size() != r
.maRanges
.size())
360 vector
<ScRange
*>::const_iterator itr1
= maRanges
.begin(), itrEnd
= maRanges
.end();
361 vector
<ScRange
*>::const_iterator itr2
= r
.maRanges
.begin();
362 for (; itr1
!= itrEnd
; ++itr1
, ++itr2
)
364 const ScRange
* p1
= *itr1
;
365 const ScRange
* p2
= *itr2
;
372 bool ScRangeList::operator!=( const ScRangeList
& r
) const
374 return !operator==( r
);
377 bool ScRangeList::UpdateReference(
378 UpdateRefMode eUpdateRefMode
,
380 const ScRange
& rWhere
,
386 if (maRanges
.empty())
387 // No ranges to update. Bail out.
390 bool bChanged
= false;
397 rWhere
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
399 if(eUpdateRefMode
== URM_INSDEL
)
401 // right now this only works for nTab1 == nTab2
406 DeleteArea(nCol1
+nDx
, nRow1
, nTab1
, nCol1
-1, nRow2
, nTab2
);
410 DeleteArea(nCol1
, nRow1
+nDy
, nTab1
, nCol2
, nRow1
-1, nTab2
);
412 SAL_WARN_IF(nDx
< 0 && nDy
< 0, "sc", "nDx and nDy are negative, check why");
419 iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
420 for (; itr
!= itrEnd
; ++itr
)
429 pR
->GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
430 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
431 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
,
433 theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
)
437 pR
->aStart
.Set( theCol1
, theRow1
, theTab1
);
438 pR
->aEnd
.Set( theCol2
, theRow2
, theTab2
);
439 if (mnMaxRowUsed
< theRow2
)
440 mnMaxRowUsed
= theRow2
;
444 if(eUpdateRefMode
== URM_INSDEL
)
446 if( nDx
< 0 || nDy
< 0 )
448 size_t n
= maRanges
.size();
449 Join(*maRanges
[n
-1], true);
456 void ScRangeList::InsertRow( SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowPos
, SCSIZE nSize
)
458 std::vector
<ScRange
> aNewRanges
;
459 for(iterator it
= maRanges
.begin(), itEnd
= maRanges
.end(); it
!= itEnd
;
462 ScRange
* pRange
= *it
;
463 if(pRange
->aStart
.Tab() <= nTab
&& pRange
->aEnd
.Tab() >= nTab
)
465 if(pRange
->aEnd
.Row() == nRowPos
- 1 && (nColStart
<= pRange
->aEnd
.Col() || nColEnd
>= pRange
->aStart
.Col()))
467 SCCOL nNewRangeStartCol
= std::max
<SCCOL
>(nColStart
, pRange
->aStart
.Col());
468 SCCOL nNewRangeEndCol
= std::min
<SCCOL
>(nColEnd
, pRange
->aEnd
.Col());
469 SCROW nNewRangeStartRow
= pRange
->aEnd
.Row() + 1;
470 SCROW nNewRangeEndRow
= nRowPos
+ nSize
- 1;
471 aNewRanges
.push_back(ScRange(nNewRangeStartCol
, nNewRangeStartRow
, nTab
, nNewRangeEndCol
,
472 nNewRangeEndRow
, nTab
));
473 if (mnMaxRowUsed
< nNewRangeEndRow
)
474 mnMaxRowUsed
= nNewRangeEndRow
;
479 for(std::vector
<ScRange
>::const_iterator it
= aNewRanges
.begin(), itEnd
= aNewRanges
.end();
489 void ScRangeList::InsertCol( SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColPos
, SCSIZE nSize
)
491 std::vector
<ScRange
> aNewRanges
;
492 for(iterator it
= maRanges
.begin(), itEnd
= maRanges
.end(); it
!= itEnd
;
495 ScRange
* pRange
= *it
;
496 if(pRange
->aStart
.Tab() <= nTab
&& pRange
->aEnd
.Tab() >= nTab
)
498 if(pRange
->aEnd
.Col() == nColPos
- 1 && (nRowStart
<= pRange
->aEnd
.Row() || nRowEnd
>= pRange
->aStart
.Row()))
500 SCROW nNewRangeStartRow
= std::max
<SCROW
>(nRowStart
, pRange
->aStart
.Row());
501 SCROW nNewRangeEndRow
= std::min
<SCROW
>(nRowEnd
, pRange
->aEnd
.Row());
502 SCCOL nNewRangeStartCol
= pRange
->aEnd
.Col() + 1;
503 SCCOL nNewRangeEndCol
= nColPos
+ nSize
- 1;
504 aNewRanges
.push_back(ScRange(nNewRangeStartCol
, nNewRangeStartRow
, nTab
, nNewRangeEndCol
,
505 nNewRangeEndRow
, nTab
));
510 for(std::vector
<ScRange
>::const_iterator it
= aNewRanges
.begin(), itEnd
= aNewRanges
.end();
523 * Check if the deleting range cuts the test range exactly into a single
526 * X = column ; Y = row
529 * +------+ or +------+
533 * X = row; Y = column
539 * where xxx is the deleted region.
541 template<typename X
, typename Y
>
542 bool checkForOneRange(
543 X nDeleteX1
, X nDeleteX2
, Y nDeleteY1
, Y nDeleteY2
, X nX1
, X nX2
, Y nY1
, Y nY2
)
545 if (nDeleteX1
<= nX1
&& nX2
<= nDeleteX2
&& (nDeleteY1
<= nY1
|| nY2
<= nDeleteY2
))
551 bool handleOneRange( const ScRange
& rDeleteRange
, ScRange
* p
)
553 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
554 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
555 ScAddress aPStart
= p
->aStart
;
556 ScAddress aPEnd
= p
->aEnd
;
557 SCCOL nDeleteCol1
= rDelStart
.Col();
558 SCCOL nDeleteCol2
= rDelEnd
.Col();
559 SCROW nDeleteRow1
= rDelStart
.Row();
560 SCROW nDeleteRow2
= rDelEnd
.Row();
561 SCCOL nCol1
= aPStart
.Col();
562 SCCOL nCol2
= aPEnd
.Col();
563 SCROW nRow1
= aPStart
.Row();
564 SCROW nRow2
= aPEnd
.Row();
566 if (checkForOneRange(nDeleteCol1
, nDeleteCol2
, nDeleteRow1
, nDeleteRow2
, nCol1
, nCol2
, nRow1
, nRow2
))
568 // Deleting range fully overlaps the column range. Adjust the row span.
569 if (nDeleteRow1
<= nRow1
)
575 // +------+ (xxx) = deleted region
577 p
->aStart
.SetRow(nDeleteRow1
+1);
580 else if (nRow2
<= nDeleteRow2
)
586 // +------+ (xxx) = deleted region
588 p
->aEnd
.SetRow(nDeleteRow1
-1);
592 else if (checkForOneRange(nDeleteRow1
, nDeleteRow2
, nDeleteCol1
, nDeleteCol2
, nRow1
, nRow2
, nCol1
, nCol2
))
594 // Deleting range fully overlaps the row range. Adjust the column span.
595 if (nDeleteCol1
<= nCol1
)
601 // +--+--+ (xxx) = deleted region
603 p
->aStart
.SetCol(nDeleteCol2
+1);
606 else if (nCol2
<= nDeleteCol2
)
612 // +--+--+ (xxx) = deleted region
614 p
->aEnd
.SetCol(nDeleteCol1
-1);
621 bool handleTwoRanges( const ScRange
& rDeleteRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
623 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
624 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
625 ScAddress aPStart
= p
->aStart
;
626 ScAddress aPEnd
= p
->aEnd
;
627 SCCOL nDeleteCol1
= rDelStart
.Col();
628 SCCOL nDeleteCol2
= rDelEnd
.Col();
629 SCROW nDeleteRow1
= rDelStart
.Row();
630 SCROW nDeleteRow2
= rDelEnd
.Row();
631 SCCOL nCol1
= aPStart
.Col();
632 SCCOL nCol2
= aPEnd
.Col();
633 SCROW nRow1
= aPStart
.Row();
634 SCROW nRow2
= aPEnd
.Row();
635 SCTAB nTab
= aPStart
.Tab();
637 if (nCol1
< nDeleteCol1
&& nDeleteCol1
<= nCol2
&& nCol2
<= nDeleteCol2
)
639 // column deleted : |-------|
640 // column original: |-------|
641 if (nRow1
< nDeleteRow1
&& nDeleteRow1
<= nRow2
&& nRow2
<= nDeleteRow2
)
643 // row deleted: |------|
644 // row original: |------|
652 // +-------+ (xxx) deleted region
654 ScRange
aNewRange( nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nRow2
, nTab
); // 2
655 rNewRanges
.push_back(aNewRange
);
657 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
660 else if (nRow1
<= nDeleteRow2
&& nDeleteRow2
< nRow2
&& nDeleteRow1
<= nRow1
)
662 // row deleted: |------|
663 // row original: |------|
670 // | 2 | (xxx) deleted region
673 ScRange
aNewRange( aPStart
, ScAddress(nDeleteCol1
-1, nRow2
, nTab
) ); // 1
674 rNewRanges
.push_back(aNewRange
);
676 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
680 else if (nCol1
<= nDeleteCol2
&& nDeleteCol2
< nCol2
&& nDeleteCol1
<= nCol1
)
682 // column deleted : |-------|
683 // column original: |-------|
684 if (nRow1
< nDeleteRow1
&& nDeleteRow1
<= nRow2
&& nRow2
<= nDeleteRow2
)
686 // row deleted: |------|
687 // row original: |------|
696 // (xxx) deleted region
698 ScRange
aNewRange( ScAddress( nDeleteCol2
+1, nDeleteRow1
, nTab
), aPEnd
); // 2
699 rNewRanges
.push_back(aNewRange
);
701 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
704 else if (nRow1
<= nDeleteRow2
&& nDeleteRow2
< nRow2
&& nDeleteRow1
<= nRow1
)
706 // row deleted: |-------|
707 // row original: |--------|
715 // +-------+ (xxx) deleted region
717 ScRange
aNewRange(nDeleteCol2
+1, nRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 1
718 rNewRanges
.push_back(aNewRange
);
720 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
724 else if (nRow1
< nDeleteRow1
&& nDeleteRow2
< nRow2
&& nDeleteCol1
<= nCol1
&& nCol2
<= nDeleteCol2
)
729 // |xxxxxxxx| (xxx) deleted region
734 ScRange
aNewRange( aPStart
, ScAddress(nCol2
, nDeleteRow1
-1, nTab
) ); // 1
735 rNewRanges
.push_back(aNewRange
);
737 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
740 else if (nCol1
< nDeleteCol1
&& nDeleteCol2
< nCol2
&& nDeleteRow1
<= nRow1
&& nRow2
<= nDeleteRow2
)
745 // | 1 |x| 2 | (xxx) deleted region
750 ScRange
aNewRange( aPStart
, ScAddress(nDeleteCol1
-1, nRow2
, nTab
) ); // 1
751 rNewRanges
.push_back(aNewRange
);
753 p
->aStart
.SetCol(nDeleteCol2
+1); // 2
761 * Check if any of the followings applies:
763 * X = column; Y = row
764 * +----------+ +----------+
766 * | +-------+---+ +--+-------+ |
767 * | |xxxxxxxxxxx| or |xxxxxxxxxx| |
768 * | +-------+---+ +--+-------+ |
770 * +----------+ +----------+
772 * X = row; Y = column
775 * +---+xx+---+ +----------+
777 * | |xx| | or | +--+ |
780 * +----------+ +---+xx+---+
782 * +--+ (xxx) deleted region
784 template<typename X
, typename Y
>
785 bool checkForThreeRanges(
786 X nDeleteX1
, X nDeleteX2
, Y nDeleteY1
, Y nDeleteY2
, X nX1
, X nX2
, Y nY1
, Y nY2
)
788 if (nX1
<= nDeleteX1
&& nX2
<= nDeleteX2
&& nY1
< nDeleteY1
&& nDeleteY2
< nY2
)
791 if (nDeleteX1
<= nX1
&& nDeleteX2
<= nX2
&& nY1
< nDeleteY1
&& nDeleteY2
< nY2
)
797 bool handleThreeRanges( const ScRange
& rDeleteRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
799 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
800 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
801 ScAddress aPStart
= p
->aStart
;
802 ScAddress aPEnd
= p
->aEnd
;
803 SCCOL nDeleteCol1
= rDelStart
.Col();
804 SCCOL nDeleteCol2
= rDelEnd
.Col();
805 SCROW nDeleteRow1
= rDelStart
.Row();
806 SCROW nDeleteRow2
= rDelEnd
.Row();
807 SCCOL nCol1
= aPStart
.Col();
808 SCCOL nCol2
= aPEnd
.Col();
809 SCROW nRow1
= aPStart
.Row();
810 SCROW nRow2
= aPEnd
.Row();
811 SCTAB nTab
= aPStart
.Tab();
813 if (checkForThreeRanges(nDeleteCol1
, nDeleteCol2
, nDeleteRow1
, nDeleteRow2
, nCol1
, nCol2
, nRow1
, nRow2
))
815 if (nCol1
< nDeleteCol1
)
825 ScRange
aNewRange(nDeleteCol1
, nRow1
, nTab
, nCol2
, nDeleteRow1
-1, nTab
); // 2
826 rNewRanges
.push_back(aNewRange
);
828 aNewRange
= ScRange(ScAddress(nDeleteCol1
, nDeleteRow2
+1, nTab
), aPEnd
); // 3
829 rNewRanges
.push_back(aNewRange
);
831 p
->aEnd
.SetCol(nDeleteCol1
-1); // 1
843 ScRange
aNewRange(aPStart
, ScAddress(nDeleteCol2
, nDeleteRow1
-1, nTab
)); // 1
844 rNewRanges
.push_back(aNewRange
);
846 aNewRange
= ScRange(nCol1
, nDeleteRow2
+1, nTab
, nDeleteCol2
, nRow2
, nTab
); // 3
847 rNewRanges
.push_back(aNewRange
);
849 p
->aStart
.SetCol(nDeleteCol2
+1); // 2
853 else if (checkForThreeRanges(nDeleteRow1
, nDeleteRow2
, nDeleteCol1
, nDeleteCol2
, nRow1
, nRow2
, nCol1
, nCol2
))
855 if (nRow1
< nDeleteRow1
)
867 ScRange
aNewRange(nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nRow2
, nTab
); // 2
868 rNewRanges
.push_back( aNewRange
);
870 aNewRange
= ScRange(ScAddress(nDeleteCol2
+1, nDeleteRow1
, nTab
), aPEnd
); // 3
871 rNewRanges
.push_back( aNewRange
);
873 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
886 ScRange
aNewRange(aPStart
, ScAddress(nDeleteCol1
-1, nDeleteRow2
, nTab
)); // 1
887 rNewRanges
.push_back(aNewRange
);
889 aNewRange
= ScRange(nDeleteCol2
+1, nRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 2
890 rNewRanges
.push_back( aNewRange
);
892 p
->aStart
.SetRow(nDeleteRow2
+1); // 3
900 bool handleFourRanges( const ScRange
& rDelRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
902 const ScAddress
& rDelStart
= rDelRange
.aStart
;
903 const ScAddress
& rDelEnd
= rDelRange
.aEnd
;
904 ScAddress aPStart
= p
->aStart
;
905 ScAddress aPEnd
= p
->aEnd
;
906 SCCOL nDeleteCol1
= rDelStart
.Col();
907 SCCOL nDeleteCol2
= rDelEnd
.Col();
908 SCROW nDeleteRow1
= rDelStart
.Row();
909 SCROW nDeleteRow2
= rDelEnd
.Row();
910 SCCOL nCol1
= aPStart
.Col();
911 SCCOL nCol2
= aPEnd
.Col();
912 SCROW nRow1
= aPStart
.Row();
913 SCROW nRow2
= aPEnd
.Row();
914 SCTAB nTab
= aPStart
.Tab();
916 if (nCol1
< nDeleteCol1
&& nDeleteCol2
< nCol2
&& nRow1
< nDeleteRow1
&& nDeleteRow2
< nRow2
)
929 ScRange
aNewRange(ScAddress(nCol1
, nDeleteRow2
+1, nTab
), aPEnd
); // 4
930 rNewRanges
.push_back( aNewRange
);
932 aNewRange
= ScRange(nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nDeleteRow2
, nTab
); // 2
933 rNewRanges
.push_back( aNewRange
);
935 aNewRange
= ScRange(nDeleteCol2
+1, nDeleteRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 3
936 rNewRanges
.push_back( aNewRange
);
938 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
948 void ScRangeList::DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
949 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
951 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
952 for(size_t i
= 0; i
< maRanges
.size();)
954 if(FindRangeIn
< ScRange
>(aRange
)(maRanges
[i
]))
956 ScRange
* pRange
= Remove(i
);
963 std::vector
<ScRange
> aNewRanges
;
965 for(iterator itr
= maRanges
.begin(); itr
!= maRanges
.end(); ++itr
)
967 // we have two basic cases here:
968 // 1. Delete area and pRange intersect
969 // 2. Delete area and pRange are not intersecting
970 // checking for 2 and if true skip this range
971 if(!(*itr
)->Intersects(aRange
))
974 // We get between 1 and 4 ranges from the difference of the first with the second
976 // X either Col or Row and Y then the opposite
977 // r = deleteRange, p = entry from ScRangeList
979 // getting exactly one range is the simple case
980 // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
981 // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() )
982 if(handleOneRange( aRange
, *itr
))
985 // getting two ranges
987 else if(handleTwoRanges( aRange
, *itr
, aNewRanges
))
991 // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
992 // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
994 // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X()
995 // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
996 else if(handleThreeRanges( aRange
, *itr
, aNewRanges
))
1000 // r.aStart.X() > p.aStart.X() && r.aEnd().X() < p.aEnd.X()
1001 // && r.aStart.Y() > p.aStart.Y() && r.aEnd().Y() < p.aEnd.Y()
1002 else if(handleFourRanges( aRange
, *itr
, aNewRanges
))
1005 for(vector
<ScRange
>::iterator itr
= aNewRanges
.begin(); itr
!= aNewRanges
.end(); ++itr
)
1009 const ScRange
* ScRangeList::Find( const ScAddress
& rAdr
) const
1011 const_iterator itr
= find_if(
1012 maRanges
.begin(), maRanges
.end(), FindEnclosingRange
<ScAddress
>(rAdr
));
1013 return itr
== maRanges
.end() ? NULL
: *itr
;
1016 ScRange
* ScRangeList::Find( const ScAddress
& rAdr
)
1018 iterator itr
= find_if(
1019 maRanges
.begin(), maRanges
.end(), FindEnclosingRange
<ScAddress
>(rAdr
));
1020 return itr
== maRanges
.end() ? NULL
: *itr
;
1023 ScRangeList::ScRangeList() : mnMaxRowUsed(-1) {}
1025 ScRangeList::ScRangeList( const ScRangeList
& rList
) :
1029 maRanges
.reserve(rList
.maRanges
.size());
1030 for_each(rList
.maRanges
.begin(), rList
.maRanges
.end(), AppendToList(maRanges
));
1031 mnMaxRowUsed
= rList
.mnMaxRowUsed
;
1034 ScRangeList::ScRangeList( const ScRange
& rRange
) :
1037 maRanges
.reserve(1);
1041 ScRangeList
& ScRangeList::operator=(const ScRangeList
& rList
)
1044 maRanges
.reserve(rList
.maRanges
.size());
1045 for_each(rList
.maRanges
.begin(), rList
.maRanges
.end(), AppendToList(maRanges
));
1046 mnMaxRowUsed
= rList
.mnMaxRowUsed
;
1050 void ScRangeList::Append( const ScRange
& rRange
)
1052 ScRange
* pR
= new ScRange( rRange
);
1056 bool ScRangeList::Intersects( const ScRange
& rRange
) const
1058 return std::any_of(maRanges
.begin(), maRanges
.end(), FindIntersectingRange
<ScRange
>(rRange
));
1061 bool ScRangeList::In( const ScRange
& rRange
) const
1063 return std::any_of(maRanges
.begin(), maRanges
.end(), FindEnclosingRange
<ScRange
>(rRange
));
1066 size_t ScRangeList::GetCellCount() const
1069 return for_each(maRanges
.begin(), maRanges
.end(), func
).getCellCount();
1072 ScRange
* ScRangeList::Remove(size_t nPos
)
1074 if (maRanges
.size() <= nPos
)
1075 // Out-of-bound condition. Bail out.
1078 iterator itr
= maRanges
.begin();
1081 maRanges
.erase(itr
);
1085 void ScRangeList::RemoveAll()
1087 for_each(maRanges
.begin(), maRanges
.end(), boost::checked_deleter
<ScRange
>());
1091 ScRange
ScRangeList::Combine() const
1093 if (maRanges
.empty())
1096 const_iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
1097 ScRange aRet
= **itr
;
1099 for (; itr
!= itrEnd
; ++itr
)
1101 const ScRange
& r
= **itr
;
1102 SCROW nRow1
= r
.aStart
.Row(), nRow2
= r
.aEnd
.Row();
1103 SCCOL nCol1
= r
.aStart
.Col(), nCol2
= r
.aEnd
.Col();
1104 SCTAB nTab1
= r
.aStart
.Tab(), nTab2
= r
.aEnd
.Tab();
1105 if (aRet
.aStart
.Row() > nRow1
)
1106 aRet
.aStart
.SetRow(nRow1
);
1107 if (aRet
.aStart
.Col() > nCol1
)
1108 aRet
.aStart
.SetCol(nCol1
);
1109 if (aRet
.aStart
.Tab() > nTab1
)
1110 aRet
.aStart
.SetTab(nTab1
);
1111 if (aRet
.aEnd
.Row() < nRow2
)
1112 aRet
.aEnd
.SetRow(nRow2
);
1113 if (aRet
.aEnd
.Col() < nCol2
)
1114 aRet
.aEnd
.SetCol(nCol2
);
1115 if (aRet
.aEnd
.Tab() < nTab2
)
1116 aRet
.aEnd
.SetTab(nTab2
);
1121 bool ScRangeList::empty() const
1123 return maRanges
.empty();
1126 size_t ScRangeList::size() const
1128 return maRanges
.size();
1131 ScRange
* ScRangeList::operator [](size_t idx
)
1133 return maRanges
[idx
];
1136 const ScRange
* ScRangeList::operator [](size_t idx
) const
1138 return maRanges
[idx
];
1141 ScRange
* ScRangeList::front()
1143 return maRanges
.front();
1146 const ScRange
* ScRangeList::front() const
1148 return maRanges
.front();
1151 ScRange
* ScRangeList::back()
1153 return maRanges
.back();
1156 const ScRange
* ScRangeList::back() const
1158 return maRanges
.back();
1161 void ScRangeList::push_back(ScRange
* p
)
1163 maRanges
.push_back(p
);
1164 if (mnMaxRowUsed
< p
->aEnd
.Row())
1165 mnMaxRowUsed
= p
->aEnd
.Row();
1168 void ScRangeList::swap( ScRangeList
& r
)
1170 maRanges
.swap(r
.maRanges
);
1171 std::swap(mnMaxRowUsed
, r
.mnMaxRowUsed
);
1174 ScAddress
ScRangeList::GetTopLeftCorner() const
1179 ScAddress aAddr
= maRanges
[0]->aStart
;
1180 for(size_t i
= 1, n
= size(); i
< n
; ++i
)
1182 if(maRanges
[i
]->aStart
< aAddr
)
1183 aAddr
= maRanges
[i
]->aStart
;
1189 ScRangeList
ScRangeList::GetIntersectedRange(const ScRange
& rRange
) const
1191 ScRangeList aReturn
;
1192 for(const_iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
1193 itr
!= itrEnd
; ++itr
)
1195 if((*itr
)->Intersects(rRange
))
1197 SCCOL nColStart1
, nColEnd1
, nColStart2
, nColEnd2
;
1198 SCROW nRowStart1
, nRowEnd1
, nRowStart2
, nRowEnd2
;
1199 SCTAB nTabStart1
, nTabEnd1
, nTabStart2
, nTabEnd2
;
1200 (*itr
)->GetVars(nColStart1
, nRowStart1
, nTabStart1
,
1201 nColEnd1
, nRowEnd1
, nTabEnd1
);
1202 rRange
.GetVars(nColStart2
, nRowStart2
, nTabStart2
,
1203 nColEnd2
, nRowEnd2
, nTabEnd2
);
1205 ScRange
aNewRange(std::max
<SCCOL
>(nColStart1
, nColStart2
), std::max
<SCROW
>(nRowStart1
, nRowStart2
),
1206 std::max
<SCTAB
>(nTabStart1
, nTabStart2
), std::min
<SCCOL
>(nColEnd1
, nColEnd2
),
1207 std::min
<SCROW
>(nRowEnd1
, nRowEnd2
), std::min
<SCTAB
>(nTabEnd1
, nTabEnd2
));
1208 aReturn
.Join(aNewRange
);
1216 ScRangePairList::~ScRangePairList()
1218 for_each( maPairs
.begin(), maPairs
.end(), boost::checked_deleter
<ScRangePair
>() );
1222 ScRangePair
* ScRangePairList::Remove(size_t nPos
)
1224 if (maPairs
.size() <= nPos
)
1225 // Out-of-bound condition. Bail out.
1228 vector
<ScRangePair
*>::iterator itr
= maPairs
.begin();
1230 ScRangePair
* p
= *itr
;
1235 ScRangePair
* ScRangePairList::Remove( ScRangePair
* Adr
)
1237 ScRangePair
* p
= NULL
;
1239 if (Adr
== NULL
) return NULL
;
1241 for ( vector
<ScRangePair
*>::iterator itr
= maPairs
.begin(); itr
< maPairs
.end(); ++itr
)
1243 if ( Adr
== (p
= *itr
) )
1245 maPairs
.erase( itr
);
1252 bool ScRangePairList::operator==( const ScRangePairList
& r
) const
1255 return true; // identical reference
1256 if ( maPairs
.size() != r
.size() )
1258 for ( size_t nIdx
= 0, nCnt
= maPairs
.size(); nIdx
< nCnt
; ++nIdx
)
1260 if ( *maPairs
[ nIdx
] != *r
[ nIdx
] )
1261 return false; // auch andere Reihenfolge ist ungleich
1266 ScRangePair
* ScRangePairList::operator [](size_t idx
)
1268 return maPairs
[idx
];
1271 const ScRangePair
* ScRangePairList::operator [](size_t idx
) const
1273 return maPairs
[idx
];
1276 size_t ScRangePairList::size() const
1278 return maPairs
.size();
1281 bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode
,
1282 ScDocument
* pDoc
, const ScRange
& rWhere
,
1283 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
1285 bool bChanged
= false;
1286 if ( !maPairs
.empty() )
1294 rWhere
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1295 for ( size_t i
= 0, nPairs
= maPairs
.size(); i
< nPairs
; ++i
)
1297 ScRangePair
* pR
= maPairs
[ i
];
1298 for ( sal_uInt16 j
=0; j
<2; j
++ )
1300 ScRange
& rRange
= pR
->GetRange(j
);
1307 rRange
.GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
1308 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
1309 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
,
1311 theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
)
1315 rRange
.aStart
.Set( theCol1
, theRow1
, theTab1
);
1316 rRange
.aEnd
.Set( theCol2
, theRow2
, theTab2
);
1324 // Delete entries that have the labels (first range) on nTab
1325 void ScRangePairList::DeleteOnTab( SCTAB nTab
)
1327 size_t nListCount
= maPairs
.size();
1329 while ( nPos
< nListCount
)
1331 ScRangePair
* pR
= maPairs
[ nPos
];
1332 ScRange aRange
= pR
->GetRange(0);
1333 if ( aRange
.aStart
.Tab() == nTab
&& aRange
.aEnd
.Tab() == nTab
)
1337 nListCount
= maPairs
.size();
1344 ScRangePair
* ScRangePairList::Find( const ScAddress
& rAdr
) const
1346 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1348 ScRangePair
* pR
= maPairs
[ j
];
1349 if ( pR
->GetRange(0).In( rAdr
) )
1355 ScRangePair
* ScRangePairList::Find( const ScRange
& rRange
) const
1357 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1359 ScRangePair
* pR
= maPairs
[ j
];
1360 if ( pR
->GetRange(0) == rRange
)
1366 ScRangePairList
* ScRangePairList::Clone() const
1368 ScRangePairList
* pNew
= new ScRangePairList
;
1369 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1371 pNew
->Append( *maPairs
[ j
] );
1376 struct ScRangePairNameSort
1383 int SAL_CALL
ScRangePairList_QsortNameCompare( const void* p1
, const void* p2
)
1385 const ScRangePairNameSort
* ps1
= static_cast<const ScRangePairNameSort
*>(p1
);
1386 const ScRangePairNameSort
* ps2
= static_cast<const ScRangePairNameSort
*>(p2
);
1387 const ScAddress
& rStartPos1
= ps1
->pPair
->GetRange(0).aStart
;
1388 const ScAddress
& rStartPos2
= ps2
->pPair
->GetRange(0).aStart
;
1389 OUString aStr1
, aStr2
;
1391 if ( rStartPos1
.Tab() == rStartPos2
.Tab() )
1395 ps1
->pDoc
->GetName( rStartPos1
.Tab(), aStr1
);
1396 ps2
->pDoc
->GetName( rStartPos2
.Tab(), aStr2
);
1397 nComp
= ScGlobal::GetCollator()->compareString( aStr1
, aStr2
);
1410 if ( rStartPos1
.Col() < rStartPos2
.Col() )
1412 if ( rStartPos1
.Col() > rStartPos2
.Col() )
1415 if ( rStartPos1
.Row() < rStartPos2
.Row() )
1417 if ( rStartPos1
.Row() > rStartPos2
.Row() )
1419 // erste Ecke gleich, zweite Ecke
1421 const ScAddress
& rEndPos1
= ps1
->pPair
->GetRange(0).aEnd
;
1422 const ScAddress
& rEndPos2
= ps2
->pPair
->GetRange(0).aEnd
;
1423 if ( rEndPos1
.Tab() == rEndPos2
.Tab() )
1427 ps1
->pDoc
->GetName( rEndPos1
.Tab(), aStr1
);
1428 ps2
->pDoc
->GetName( rEndPos2
.Tab(), aStr2
);
1429 nComp
= ScGlobal::GetCollator()->compareString( aStr1
, aStr2
);
1442 if ( rEndPos1
.Col() < rEndPos2
.Col() )
1444 if ( rEndPos1
.Col() > rEndPos2
.Col() )
1447 if ( rEndPos1
.Row() < rEndPos2
.Row() )
1449 if ( rEndPos1
.Row() > rEndPos2
.Row() )
1455 #ifndef _MSC_VER // MSVC is good enough to warn about unreachable code here.
1456 // Or stupid enough to bother warning about it, depending
1457 // on your point of view.
1458 return 0; // just in case
1462 void ScRangePairList::Join( const ScRangePair
& r
, bool bIsInList
)
1464 if ( maPairs
.empty() )
1469 const ScRange
& r1
= r
.GetRange(0);
1470 const ScRange
& r2
= r
.GetRange(1);
1471 SCCOL nCol1
= r1
.aStart
.Col();
1472 SCROW nRow1
= r1
.aStart
.Row();
1473 SCTAB nTab1
= r1
.aStart
.Tab();
1474 SCCOL nCol2
= r1
.aEnd
.Col();
1475 SCROW nRow2
= r1
.aEnd
.Row();
1476 SCTAB nTab2
= r1
.aEnd
.Tab();
1477 ScRangePair
* pOver
= const_cast<ScRangePair
*>(&r
); // fies aber wahr wenn bInList
1481 // Find the current position of this range.
1482 for ( size_t i
= 0, nPairs
= maPairs
.size(); i
< nPairs
; ++i
)
1484 if ( maPairs
[i
] == pOver
)
1491 bool bJoinedInput
= false;
1493 for ( size_t i
= 0; i
< maPairs
.size() && pOver
; ++i
)
1495 ScRangePair
* p
= maPairs
[ i
];
1497 continue; // derselbe, weiter mit dem naechsten
1498 bool bJoined
= false;
1499 ScRange
& rp1
= p
->GetRange(0);
1500 ScRange
& rp2
= p
->GetRange(1);
1502 { // nur wenn Range2 gleich ist
1504 { // RangePair r in RangePair p enthalten oder identisch
1506 bJoined
= true; // weg mit RangePair r
1509 bJoinedInput
= true; // nicht anhaengen
1513 else if ( r1
.In( rp1
) )
1514 { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen
1519 if ( !bJoined
&& rp1
.aStart
.Tab() == nTab1
&& rp1
.aEnd
.Tab() == nTab2
1520 && rp2
.aStart
.Tab() == r2
.aStart
.Tab()
1521 && rp2
.aEnd
.Tab() == r2
.aEnd
.Tab() )
1522 { // 2D, Range2 muss genauso nebeneinander liegen wie Range1
1523 if ( rp1
.aStart
.Col() == nCol1
&& rp1
.aEnd
.Col() == nCol2
1524 && rp2
.aStart
.Col() == r2
.aStart
.Col()
1525 && rp2
.aEnd
.Col() == r2
.aEnd
.Col() )
1527 if ( rp1
.aStart
.Row() == nRow2
+1
1528 && rp2
.aStart
.Row() == r2
.aEnd
.Row()+1 )
1530 rp1
.aStart
.SetRow( nRow1
);
1531 rp2
.aStart
.SetRow( r2
.aStart
.Row() );
1534 else if ( rp1
.aEnd
.Row() == nRow1
-1
1535 && rp2
.aEnd
.Row() == r2
.aStart
.Row()-1 )
1537 rp1
.aEnd
.SetRow( nRow2
);
1538 rp2
.aEnd
.SetRow( r2
.aEnd
.Row() );
1542 else if ( rp1
.aStart
.Row() == nRow1
&& rp1
.aEnd
.Row() == nRow2
1543 && rp2
.aStart
.Row() == r2
.aStart
.Row()
1544 && rp2
.aEnd
.Row() == r2
.aEnd
.Row() )
1546 if ( rp1
.aStart
.Col() == nCol2
+1
1547 && rp2
.aStart
.Col() == r2
.aEnd
.Col()+1 )
1549 rp1
.aStart
.SetCol( nCol1
);
1550 rp2
.aStart
.SetCol( r2
.aStart
.Col() );
1553 else if ( rp1
.aEnd
.Col() == nCol1
-1
1554 && rp2
.aEnd
.Col() == r2
.aEnd
.Col()-1 )
1556 rp1
.aEnd
.SetCol( nCol2
);
1557 rp2
.aEnd
.SetCol( r2
.aEnd
.Col() );
1565 { // innerhalb der Liste RangePair loeschen
1571 nOldPos
--; // Seek richtig aufsetzen
1573 bJoinedInput
= true;
1574 Join( *p
, true ); // rekursiv!
1577 if ( !bIsInList
&& !bJoinedInput
)
1581 ScRangePair
** ScRangePairList::CreateNameSortedArray( size_t& nListCount
,
1582 ScDocument
* pDoc
) const
1584 nListCount
= maPairs
.size();
1585 OSL_ENSURE( nListCount
* sizeof(ScRangePairNameSort
) <= (size_t)~0x1F,
1586 "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
1587 ScRangePairNameSort
* pSortArray
= reinterpret_cast<ScRangePairNameSort
*>(
1588 new sal_uInt8
[ nListCount
* sizeof(ScRangePairNameSort
) ]);
1590 for ( j
=0; j
< nListCount
; j
++ )
1592 pSortArray
[j
].pPair
= maPairs
[ j
];
1593 pSortArray
[j
].pDoc
= pDoc
;
1595 qsort( (void*)pSortArray
, nListCount
, sizeof(ScRangePairNameSort
), &ScRangePairList_QsortNameCompare
);
1596 // ScRangePair Pointer aufruecken
1597 ScRangePair
** ppSortArray
= reinterpret_cast<ScRangePair
**>(pSortArray
);
1598 for ( j
=0; j
< nListCount
; j
++ )
1600 ppSortArray
[j
] = pSortArray
[j
].pPair
;
1605 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */