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>
24 #include "rangelst.hxx"
25 #include "document.hxx"
26 #include "refupdat.hxx"
27 #include "rechead.hxx"
28 #include "compiler.hxx"
29 #include "stlalgorithm.hxx"
34 using ::std::for_each
;
35 using ::formula::FormulaGrammar
;
40 class FindEnclosingRange
: public ::std::unary_function
<ScRange
*, bool>
43 FindEnclosingRange(const T
& rTest
) : mrTest(rTest
) {}
44 FindEnclosingRange(const FindEnclosingRange
& r
) : mrTest(r
.mrTest
) {}
45 bool operator() (const ScRange
* pRange
) const
47 return pRange
->In(mrTest
);
54 class FindRangeIn
: public ::std::unary_function
<ScRange
*, bool>
57 FindRangeIn(const T
& rTest
) : mrTest(rTest
) {}
58 FindRangeIn(const FindRangeIn
& r
) : mrTest(r
.mrTest
) {}
59 bool operator() (const ScRange
* pRange
) const
61 return mrTest
.In(*pRange
);
68 class FindIntersectingRange
: public ::std::unary_function
<ScRange
*, bool>
71 FindIntersectingRange(const T
& rTest
) : mrTest(rTest
) {}
72 FindIntersectingRange(const FindIntersectingRange
& r
) : mrTest(r
.mrTest
) {}
73 bool operator() (const ScRange
* pRange
) const
75 return pRange
->Intersects(mrTest
);
81 class AppendToList
: public ::std::unary_function
<const ScRange
*, void>
84 AppendToList(vector
<ScRange
*>& rRanges
) : mrRanges(rRanges
) {}
85 AppendToList(const AppendToList
& r
) : mrRanges(r
.mrRanges
) {}
86 void operator() (const ScRange
* p
)
88 mrRanges
.push_back(new ScRange(*p
));
91 vector
<ScRange
*>& mrRanges
;
94 class CountCells
: public ::std::unary_function
<const ScRange
*, void>
97 CountCells() : mnCellCount(0) {}
98 CountCells(const CountCells
& r
) : mnCellCount(r
.mnCellCount
) {}
100 void operator() (const ScRange
* p
)
103 size_t(p
->aEnd
.Col() - p
->aStart
.Col() + 1)
104 * size_t(p
->aEnd
.Row() - p
->aStart
.Row() + 1)
105 * size_t(p
->aEnd
.Tab() - p
->aStart
.Tab() + 1);
108 size_t getCellCount() const { return mnCellCount
; }
114 class FormatString
: public ::std::unary_function
<const ScRange
*, void>
117 FormatString(OUString
& rStr
, sal_uInt16 nFlags
, ScDocument
* pDoc
, FormulaGrammar::AddressConvention eConv
, sal_Unicode cDelim
) :
125 FormatString(const FormatString
& r
) :
131 mbFirst(r
.mbFirst
) {}
133 void operator() (const ScRange
* p
)
135 OUString
aStr(p
->Format(mnFlags
, mpDoc
, meConv
));
139 mrStr
+= OUString(mcDelim
);
146 FormulaGrammar::AddressConvention meConv
;
154 ScRangeList::~ScRangeList()
159 sal_uInt16
ScRangeList::Parse( const OUString
& rStr
, ScDocument
* pDoc
, sal_uInt16 nMask
,
160 formula::FormulaGrammar::AddressConvention eConv
,
161 SCTAB nDefaultTab
, sal_Unicode cDelimiter
)
163 if ( !rStr
.isEmpty() )
166 cDelimiter
= ScCompiler::GetNativeSymbolChar(ocSep
);
168 nMask
|= SCA_VALID
; // falls das jemand vergessen sollte
169 sal_uInt16 nResult
= (sal_uInt16
)~0; // alle Bits setzen
179 sal_uInt16 nTCount
= comphelper::string::getTokenCount(rStr
, cDelimiter
);
180 for ( sal_uInt16 i
=0; i
<nTCount
; i
++ )
182 aOne
= rStr
.getToken( i
, cDelimiter
);
183 aRange
.aStart
.SetTab( nTab
); // Default Tab wenn nicht angegeben
184 sal_uInt16 nRes
= aRange
.ParseAny( aOne
, pDoc
, eConv
);
185 sal_uInt16 nEndRangeBits
= SCA_VALID_COL2
| SCA_VALID_ROW2
| SCA_VALID_TAB2
;
186 sal_uInt16 nTmp1
= ( nRes
& SCA_BITS
);
187 sal_uInt16 nTmp2
= ( nRes
& nEndRangeBits
);
188 // If we have a valid single range with
189 // any of the address bits we are interested in
190 // set - set the equiv end range bits
191 if ( (nRes
& SCA_VALID
) && nTmp1
&& ( nTmp2
!= nEndRangeBits
) )
192 nRes
|= ( nTmp1
<< 4 );
194 if ( (nRes
& nMask
) == nMask
)
196 nResult
&= nRes
; // alle gemeinsamen Bits bleiben erhalten
198 return nResult
; // SCA_VALID gesetzt wenn alle ok
204 void ScRangeList::Format( OUString
& rStr
, sal_uInt16 nFlags
, ScDocument
* pDoc
,
205 formula::FormulaGrammar::AddressConvention eConv
,
206 sal_Unicode cDelimiter
) const
210 cDelimiter
= ScCompiler::GetNativeSymbolChar(ocSep
);
213 FormatString
func(aStr
, nFlags
, pDoc
, eConv
, cDelimiter
);
214 for_each(maRanges
.begin(), maRanges
.end(), func
);
218 void ScRangeList::Join( const ScRange
& r
, bool bIsInList
)
220 if ( maRanges
.empty() )
225 SCCOL nCol1
= r
.aStart
.Col();
226 SCROW nRow1
= r
.aStart
.Row();
227 SCTAB nTab1
= r
.aStart
.Tab();
228 SCCOL nCol2
= r
.aEnd
.Col();
229 SCROW nRow2
= r
.aEnd
.Row();
230 SCTAB nTab2
= r
.aEnd
.Tab();
232 ScRange
* pOver
= (ScRange
*) &r
; // fies aber wahr wenn bInList
236 // Find the current position of this range.
237 for ( size_t i
= 0, nRanges
= maRanges
.size(); i
< nRanges
; ++i
)
239 if ( maRanges
[i
] == pOver
)
246 bool bJoinedInput
= false;
248 // We need to query the size of the container dynamically since its size
249 // may change during the loop.
250 for ( size_t i
= 0; i
< maRanges
.size() && pOver
; ++i
)
252 ScRange
* p
= maRanges
[i
];
254 continue; // derselbe, weiter mit dem naechsten
255 bool bJoined
= false;
257 { // Range r in Range p enthalten oder identisch
259 bJoined
= true; // weg mit Range r
262 bJoinedInput
= true; // nicht anhaengen
266 else if ( r
.In( *p
) )
267 { // Range p in Range r enthalten, r zum neuen Range machen
271 if ( !bJoined
&& p
->aStart
.Tab() == nTab1
&& p
->aEnd
.Tab() == nTab2
)
273 if ( p
->aStart
.Col() == nCol1
&& p
->aEnd
.Col() == nCol2
)
275 if ( p
->aStart
.Row() == nRow2
+1 )
277 p
->aStart
.SetRow( nRow1
);
280 else if ( p
->aEnd
.Row() == nRow1
-1 )
282 p
->aEnd
.SetRow( nRow2
);
286 else if ( p
->aStart
.Row() == nRow1
&& p
->aEnd
.Row() == nRow2
)
288 if ( p
->aStart
.Col() == nCol2
+1 )
290 p
->aStart
.SetCol( nCol1
);
293 else if ( p
->aEnd
.Col() == nCol1
-1 )
295 p
->aEnd
.SetCol( nCol2
);
303 { // innerhalb der Liste Range loeschen
309 nOldPos
--; // Seek richtig aufsetzen
312 Join( *p
, true ); // rekursiv!
315 if ( !bIsInList
&& !bJoinedInput
)
319 bool ScRangeList::operator==( const ScRangeList
& r
) const
324 if (maRanges
.size() != r
.maRanges
.size())
327 vector
<ScRange
*>::const_iterator itr1
= maRanges
.begin(), itrEnd
= maRanges
.end();
328 vector
<ScRange
*>::const_iterator itr2
= r
.maRanges
.begin();
329 for (; itr1
!= itrEnd
; ++itr1
, ++itr2
)
331 const ScRange
* p1
= *itr1
;
332 const ScRange
* p2
= *itr2
;
339 bool ScRangeList::operator!=( const ScRangeList
& r
) const
341 return !operator==( r
);
344 bool ScRangeList::UpdateReference(
345 UpdateRefMode eUpdateRefMode
,
347 const ScRange
& rWhere
,
353 if (maRanges
.empty())
354 // No ranges to update. Bail out.
357 bool bChanged
= false;
364 rWhere
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
366 if(eUpdateRefMode
== URM_INSDEL
)
368 // right now this only works for nTab1 == nTab2
373 DeleteArea(nCol1
+nDx
, nRow1
, nTab1
, nCol1
-1, nRow2
, nTab2
);
377 DeleteArea(nCol1
, nRow1
+nDy
, nTab1
, nCol2
, nRow1
-1, nTab2
);
379 SAL_WARN_IF(nDx
< 0 && nDy
< 0, "sc", "nDx and nDy are negative, check why");
386 iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
387 for (; itr
!= itrEnd
; ++itr
)
396 pR
->GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
397 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
398 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
,
400 theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
)
404 pR
->aStart
.Set( theCol1
, theRow1
, theTab1
);
405 pR
->aEnd
.Set( theCol2
, theRow2
, theTab2
);
409 if(eUpdateRefMode
== URM_INSDEL
)
411 if( nDx
< 0 || nDy
< 0 )
413 size_t n
= maRanges
.size();
414 Join(*maRanges
[n
-1], true);
421 void ScRangeList::InsertRow( SCTAB nTab
, SCCOL nColStart
, SCCOL nColEnd
, SCROW nRowPos
, SCSIZE nSize
)
423 std::vector
<ScRange
> aNewRanges
;
424 for(iterator it
= maRanges
.begin(), itEnd
= maRanges
.end(); it
!= itEnd
;
427 ScRange
* pRange
= *it
;
428 if(pRange
->aStart
.Tab() <= nTab
&& pRange
->aEnd
.Tab() >= nTab
)
430 if(pRange
->aEnd
.Row() == nRowPos
- 1 && (nColStart
<= pRange
->aEnd
.Col() || nColEnd
>= pRange
->aStart
.Col()))
432 SCCOL nNewRangeStartCol
= std::max
<SCCOL
>(nColStart
, pRange
->aStart
.Col());
433 SCCOL nNewRangeEndCol
= std::min
<SCCOL
>(nColEnd
, pRange
->aEnd
.Col());
434 SCROW nNewRangeStartRow
= pRange
->aEnd
.Row() + 1;
435 SCROW nNewRangeEndRow
= nRowPos
+ nSize
- 1;
436 aNewRanges
.push_back(ScRange(nNewRangeStartCol
, nNewRangeStartRow
, nTab
, nNewRangeEndCol
,
437 nNewRangeEndRow
, nTab
));
442 for(std::vector
<ScRange
>::const_iterator it
= aNewRanges
.begin(), itEnd
= aNewRanges
.end();
452 void ScRangeList::InsertCol( SCTAB nTab
, SCROW nRowStart
, SCROW nRowEnd
, SCCOL nColPos
, SCSIZE nSize
)
454 std::vector
<ScRange
> aNewRanges
;
455 for(iterator it
= maRanges
.begin(), itEnd
= maRanges
.end(); it
!= itEnd
;
458 ScRange
* pRange
= *it
;
459 if(pRange
->aStart
.Tab() <= nTab
&& pRange
->aEnd
.Tab() >= nTab
)
461 if(pRange
->aEnd
.Col() == nColPos
- 1 && (nRowStart
<= pRange
->aEnd
.Row() || nRowEnd
>= pRange
->aStart
.Row()))
463 SCROW nNewRangeStartRow
= std::max
<SCROW
>(nRowStart
, pRange
->aStart
.Row());
464 SCROW nNewRangeEndRow
= std::min
<SCROW
>(nRowEnd
, pRange
->aEnd
.Row());
465 SCCOL nNewRangeStartCol
= pRange
->aEnd
.Col() + 1;
466 SCCOL nNewRangeEndCol
= nColPos
+ nSize
- 1;
467 aNewRanges
.push_back(ScRange(nNewRangeStartCol
, nNewRangeStartRow
, nTab
, nNewRangeEndCol
,
468 nNewRangeEndRow
, nTab
));
473 for(std::vector
<ScRange
>::const_iterator it
= aNewRanges
.begin(), itEnd
= aNewRanges
.end();
486 * Check if the deleting range cuts the test range exactly into a single
489 * X = column ; Y = row
492 * +------+ or +------+
496 * X = row; Y = column
502 * where xxx is the deleted region.
504 template<typename X
, typename Y
>
505 bool checkForOneRange(
506 X nDeleteX1
, X nDeleteX2
, Y nDeleteY1
, Y nDeleteY2
, X nX1
, X nX2
, Y nY1
, Y nY2
)
508 if (nDeleteX1
<= nX1
&& nX2
<= nDeleteX2
&& (nDeleteY1
<= nY1
|| nY2
<= nDeleteY2
))
514 bool handleOneRange( const ScRange
& rDeleteRange
, ScRange
* p
)
516 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
517 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
518 ScAddress aPStart
= p
->aStart
;
519 ScAddress aPEnd
= p
->aEnd
;
520 SCCOL nDeleteCol1
= rDelStart
.Col();
521 SCCOL nDeleteCol2
= rDelEnd
.Col();
522 SCROW nDeleteRow1
= rDelStart
.Row();
523 SCROW nDeleteRow2
= rDelEnd
.Row();
524 SCCOL nCol1
= aPStart
.Col();
525 SCCOL nCol2
= aPEnd
.Col();
526 SCROW nRow1
= aPStart
.Row();
527 SCROW nRow2
= aPEnd
.Row();
529 if (checkForOneRange(nDeleteCol1
, nDeleteCol2
, nDeleteRow1
, nDeleteRow2
, nCol1
, nCol2
, nRow1
, nRow2
))
531 // Deleting range fully overlaps the column range. Adjust the row span.
532 if (nDeleteRow1
<= nRow1
)
538 // +------+ (xxx) = deleted region
540 p
->aStart
.SetRow(nDeleteRow1
+1);
543 else if (nRow2
<= nDeleteRow2
)
549 // +------+ (xxx) = deleted region
551 p
->aEnd
.SetRow(nDeleteRow1
-1);
555 else if (checkForOneRange(nDeleteRow1
, nDeleteRow2
, nDeleteCol1
, nDeleteCol2
, nRow1
, nRow2
, nCol1
, nCol2
))
557 // Deleting range fully overlaps the row range. Adjust the column span.
558 if (nDeleteCol1
<= nCol1
)
564 // +--+--+ (xxx) = deleted region
566 p
->aStart
.SetCol(nDeleteCol2
+1);
569 else if (nCol2
<= nDeleteCol2
)
575 // +--+--+ (xxx) = deleted region
577 p
->aEnd
.SetCol(nDeleteCol1
-1);
585 * Check if the deleting range cuts the test range in the middle, to
586 * separate it into exactly two pieces.
589 * +--------+ +--+-+--+
592 * |xxxxxxxx| or | |x| |
595 * +--------+ +--+-+--+
596 * where xxx is the deleted region.
598 template<typename X
, typename Y
>
599 bool checkForTwoRangesCase2(
600 X nDeleteX1
, X nDeleteX2
, Y nDeleteY1
, Y nDeleteY2
, X nX1
, X nX2
, Y nY1
, Y nY2
)
602 if (nY1
< nDeleteY1
&& nDeleteY2
< nY2
&& nDeleteX1
<= nX1
&& nX2
<= nDeleteX2
)
608 bool handleTwoRanges( const ScRange
& rDeleteRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
610 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
611 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
612 ScAddress aPStart
= p
->aStart
;
613 ScAddress aPEnd
= p
->aEnd
;
614 SCCOL nDeleteCol1
= rDelStart
.Col();
615 SCCOL nDeleteCol2
= rDelEnd
.Col();
616 SCROW nDeleteRow1
= rDelStart
.Row();
617 SCROW nDeleteRow2
= rDelEnd
.Row();
618 SCCOL nCol1
= aPStart
.Col();
619 SCCOL nCol2
= aPEnd
.Col();
620 SCROW nRow1
= aPStart
.Row();
621 SCROW nRow2
= aPEnd
.Row();
622 SCTAB nTab
= aPStart
.Tab();
624 if (nCol1
< nDeleteCol1
&& nDeleteCol1
<= nCol2
&& nCol2
<= nDeleteCol2
)
626 // column deleted : |-------|
627 // column original: |-------|
628 if (nRow1
< nDeleteRow1
&& nDeleteRow1
<= nRow2
&& nRow2
<= nDeleteRow2
)
630 // row deleted: |------|
631 // row original: |------|
639 // +-------+ (xxx) deleted region
641 ScRange
aNewRange( nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nRow2
, nTab
); // 2
642 rNewRanges
.push_back(aNewRange
);
644 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
647 else if (nRow1
<= nDeleteRow2
&& nDeleteRow2
< nRow2
&& nDeleteRow1
<= nRow1
)
649 // row deleted: |------|
650 // row original: |------|
657 // | 2 | (xxx) deleted region
660 ScRange
aNewRange( aPStart
, ScAddress(nDeleteCol1
-1, nRow2
, nTab
) ); // 1
661 rNewRanges
.push_back(aNewRange
);
663 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
667 else if (nCol1
<= nDeleteCol2
&& nDeleteCol2
< nCol2
&& nDeleteCol1
<= nCol1
)
669 // column deleted : |-------|
670 // column original: |-------|
671 if (nRow1
< nDeleteRow1
&& nDeleteRow1
<= nRow2
&& nRow2
<= nDeleteRow2
)
673 // row deleted: |------|
674 // row original: |------|
683 // (xxx) deleted region
685 ScRange
aNewRange( ScAddress( nDeleteCol2
+1, nDeleteRow1
, nTab
), aPEnd
); // 2
686 rNewRanges
.push_back(aNewRange
);
688 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
691 else if (nRow1
<= nDeleteRow2
&& nDeleteRow2
< nRow2
&& nDeleteRow1
<= nRow1
)
693 // row deleted: |-------|
694 // row original: |--------|
702 // +-------+ (xxx) deleted region
704 ScRange
aNewRange(nDeleteCol2
+1, nRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 1
705 rNewRanges
.push_back(aNewRange
);
707 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
711 else if (nRow1
< nDeleteRow1
&& nDeleteRow2
< nRow2
&& nDeleteCol1
<= nCol1
&& nCol2
<= nDeleteCol2
)
716 // |xxxxxxxx| (xxx) deleted region
721 ScRange
aNewRange( aPStart
, ScAddress(nCol2
, nDeleteRow1
-1, nTab
) ); // 1
722 rNewRanges
.push_back(aNewRange
);
724 p
->aStart
.SetRow(nDeleteRow2
+1); // 2
727 else if (nCol1
< nDeleteCol1
&& nDeleteCol2
< nCol2
&& nDeleteRow1
<= nRow1
&& nRow2
<= nDeleteRow2
)
732 // | 1 |x| 2 | (xxx) deleted region
737 ScRange
aNewRange( aPStart
, ScAddress(nDeleteCol1
-1, nRow2
, nTab
) ); // 1
738 rNewRanges
.push_back(aNewRange
);
740 p
->aStart
.SetCol(nDeleteCol2
+1); // 2
748 * Check if any of the followings applies:
750 * X = column; Y = row
751 * +----------+ +----------+
753 * | +-------+---+ +--+-------+ |
754 * | |xxxxxxxxxxx| or |xxxxxxxxxx| |
755 * | +-------+---+ +--+-------+ |
757 * +----------+ +----------+
759 * X = row; Y = column
762 * +---+xx+---+ +----------+
764 * | |xx| | or | +--+ |
767 * +----------+ +---+xx+---+
769 * +--+ (xxx) deleted region
771 template<typename X
, typename Y
>
772 bool checkForThreeRanges(
773 X nDeleteX1
, X nDeleteX2
, Y nDeleteY1
, Y nDeleteY2
, X nX1
, X nX2
, Y nY1
, Y nY2
)
775 if (nX1
<= nDeleteX1
&& nX2
<= nDeleteX2
&& nY1
< nDeleteY1
&& nDeleteY2
< nY2
)
778 if (nDeleteX1
<= nX1
&& nDeleteX2
<= nX2
&& nY1
< nDeleteY1
&& nDeleteY2
< nY2
)
784 bool handleThreeRanges( const ScRange
& rDeleteRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
786 const ScAddress
& rDelStart
= rDeleteRange
.aStart
;
787 const ScAddress
& rDelEnd
= rDeleteRange
.aEnd
;
788 ScAddress aPStart
= p
->aStart
;
789 ScAddress aPEnd
= p
->aEnd
;
790 SCCOL nDeleteCol1
= rDelStart
.Col();
791 SCCOL nDeleteCol2
= rDelEnd
.Col();
792 SCROW nDeleteRow1
= rDelStart
.Row();
793 SCROW nDeleteRow2
= rDelEnd
.Row();
794 SCCOL nCol1
= aPStart
.Col();
795 SCCOL nCol2
= aPEnd
.Col();
796 SCROW nRow1
= aPStart
.Row();
797 SCROW nRow2
= aPEnd
.Row();
798 SCTAB nTab
= aPStart
.Tab();
800 if (checkForThreeRanges(nDeleteCol1
, nDeleteCol2
, nDeleteRow1
, nDeleteRow2
, nCol1
, nCol2
, nRow1
, nRow2
))
802 if (nCol1
< nDeleteCol1
)
812 ScRange
aNewRange(nDeleteCol1
, nRow1
, nTab
, nCol2
, nDeleteRow1
-1, nTab
); // 2
813 rNewRanges
.push_back(aNewRange
);
815 aNewRange
= ScRange(ScAddress(nDeleteCol1
, nDeleteRow2
+1, nTab
), aPEnd
); // 3
816 rNewRanges
.push_back(aNewRange
);
818 p
->aEnd
.SetCol(nDeleteCol1
-1); // 1
830 ScRange
aNewRange(aPStart
, ScAddress(nDeleteCol2
, nDeleteRow1
-1, nTab
)); // 1
831 rNewRanges
.push_back(aNewRange
);
833 aNewRange
= ScRange(nCol1
, nDeleteRow2
+1, nTab
, nDeleteCol2
, nRow2
, nTab
); // 3
834 rNewRanges
.push_back(aNewRange
);
836 p
->aStart
.SetCol(nDeleteCol2
+1); // 2
840 else if (checkForThreeRanges(nDeleteRow1
, nDeleteRow2
, nDeleteCol1
, nDeleteCol2
, nRow1
, nRow2
, nCol1
, nCol2
))
842 if (nRow1
< nDeleteRow1
)
854 ScRange
aNewRange(nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nRow2
, nTab
); // 2
855 rNewRanges
.push_back( aNewRange
);
857 aNewRange
= ScRange(ScAddress(nDeleteCol2
+1, nDeleteRow1
, nTab
), aPEnd
); // 3
858 rNewRanges
.push_back( aNewRange
);
860 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
873 ScRange
aNewRange(aPStart
, ScAddress(nDeleteCol1
-1, nDeleteRow2
, nTab
)); // 1
874 rNewRanges
.push_back(aNewRange
);
876 aNewRange
= ScRange(nDeleteCol2
+1, nRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 2
877 rNewRanges
.push_back( aNewRange
);
879 p
->aStart
.SetRow(nDeleteRow2
+1); // 3
887 bool handleFourRanges( const ScRange
& rDelRange
, ScRange
* p
, std::vector
<ScRange
>& rNewRanges
)
889 const ScAddress
& rDelStart
= rDelRange
.aStart
;
890 const ScAddress
& rDelEnd
= rDelRange
.aEnd
;
891 ScAddress aPStart
= p
->aStart
;
892 ScAddress aPEnd
= p
->aEnd
;
893 SCCOL nDeleteCol1
= rDelStart
.Col();
894 SCCOL nDeleteCol2
= rDelEnd
.Col();
895 SCROW nDeleteRow1
= rDelStart
.Row();
896 SCROW nDeleteRow2
= rDelEnd
.Row();
897 SCCOL nCol1
= aPStart
.Col();
898 SCCOL nCol2
= aPEnd
.Col();
899 SCROW nRow1
= aPStart
.Row();
900 SCROW nRow2
= aPEnd
.Row();
901 SCTAB nTab
= aPStart
.Tab();
903 if (nCol1
< nDeleteCol1
&& nDeleteCol2
< nCol2
&& nRow1
< nDeleteRow1
&& nDeleteRow2
< nRow2
)
916 ScRange
aNewRange(ScAddress(nCol1
, nDeleteRow2
+1, nTab
), aPEnd
); // 4
917 rNewRanges
.push_back( aNewRange
);
919 aNewRange
= ScRange(nCol1
, nDeleteRow1
, nTab
, nDeleteCol1
-1, nDeleteRow2
, nTab
); // 2
920 rNewRanges
.push_back( aNewRange
);
922 aNewRange
= ScRange(nDeleteCol2
+1, nDeleteRow1
, nTab
, nCol2
, nDeleteRow2
, nTab
); // 3
923 rNewRanges
.push_back( aNewRange
);
925 p
->aEnd
.SetRow(nDeleteRow1
-1); // 1
935 void ScRangeList::DeleteArea( SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
936 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
)
938 ScRange
aRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
939 for(size_t i
= 0; i
< maRanges
.size();)
941 if(FindRangeIn
< ScRange
>(aRange
)(maRanges
[i
]))
943 ScRange
* pRange
= Remove(i
);
950 std::vector
<ScRange
> aNewRanges
;
952 for(iterator itr
= maRanges
.begin(); itr
!= maRanges
.end(); ++itr
)
954 // we have two basic cases here:
955 // 1. Delete area and pRange intersect
956 // 2. Delete area and pRange are not intersecting
957 // checking for 2 and if true skip this range
958 if(!(*itr
)->Intersects(aRange
))
961 // We get between 1 and 4 ranges from the difference of the first with the second
963 // X either Col or Row and Y then the opposite
964 // r = deleteRange, p = entry from ScRangeList
966 // getting exactly one range is the simple case
967 // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
968 // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() )
969 if(handleOneRange( aRange
, *itr
))
972 // getting two ranges
974 else if(handleTwoRanges( aRange
, *itr
, aNewRanges
))
978 // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
979 // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
981 // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X()
982 // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
983 else if(handleThreeRanges( aRange
, *itr
, aNewRanges
))
987 // r.aStart.X() > p.aStart.X() && r.aEnd().X() < p.aEnd.X()
988 // && r.aStart.Y() > p.aStart.Y() && r.aEnd().Y() < p.aEnd.Y()
989 else if(handleFourRanges( aRange
, *itr
, aNewRanges
))
992 for(vector
<ScRange
>::iterator itr
= aNewRanges
.begin(); itr
!= aNewRanges
.end(); ++itr
)
996 const ScRange
* ScRangeList::Find( const ScAddress
& rAdr
) const
998 const_iterator itr
= find_if(
999 maRanges
.begin(), maRanges
.end(), FindEnclosingRange
<ScAddress
>(rAdr
));
1000 return itr
== maRanges
.end() ? NULL
: *itr
;
1003 ScRange
* ScRangeList::Find( const ScAddress
& rAdr
)
1005 iterator itr
= find_if(
1006 maRanges
.begin(), maRanges
.end(), FindEnclosingRange
<ScAddress
>(rAdr
));
1007 return itr
== maRanges
.end() ? NULL
: *itr
;
1010 ScRangeList::ScRangeList() {}
1012 ScRangeList::ScRangeList( const ScRangeList
& rList
) :
1015 maRanges
.reserve(rList
.maRanges
.size());
1016 for_each(rList
.maRanges
.begin(), rList
.maRanges
.end(), AppendToList(maRanges
));
1019 ScRangeList::ScRangeList( const ScRange
& rRange
)
1021 maRanges
.reserve(1);
1025 ScRangeList
& ScRangeList::operator=(const ScRangeList
& rList
)
1028 maRanges
.reserve(rList
.maRanges
.size());
1029 for_each(rList
.maRanges
.begin(), rList
.maRanges
.end(), AppendToList(maRanges
));
1033 void ScRangeList::Append( const ScRange
& rRange
)
1035 ScRange
* pR
= new ScRange( rRange
);
1036 maRanges
.push_back( pR
);
1039 bool ScRangeList::Intersects( const ScRange
& rRange
) const
1041 const_iterator itrEnd
= maRanges
.end();
1042 const_iterator itr
=
1043 find_if(maRanges
.begin(), itrEnd
, FindIntersectingRange
<ScRange
>(rRange
));
1044 return itr
!= itrEnd
;
1047 bool ScRangeList::In( const ScRange
& rRange
) const
1049 const_iterator itrEnd
= maRanges
.end();
1050 const_iterator itr
=
1051 find_if(maRanges
.begin(), itrEnd
, FindEnclosingRange
<ScRange
>(rRange
));
1052 return itr
!= itrEnd
;
1055 size_t ScRangeList::GetCellCount() const
1058 return for_each(maRanges
.begin(), maRanges
.end(), func
).getCellCount();
1061 ScRange
* ScRangeList::Remove(size_t nPos
)
1063 if (maRanges
.size() <= nPos
)
1064 // Out-of-bound condition. Bail out.
1067 iterator itr
= maRanges
.begin();
1070 maRanges
.erase(itr
);
1074 void ScRangeList::RemoveAll()
1076 for_each(maRanges
.begin(), maRanges
.end(), ScDeleteObjectByPtr
<ScRange
>());
1080 ScRange
ScRangeList::Combine() const
1082 if (maRanges
.empty())
1085 const_iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
1086 ScRange aRet
= **itr
;
1088 for (; itr
!= itrEnd
; ++itr
)
1090 const ScRange
& r
= **itr
;
1091 SCROW nRow1
= r
.aStart
.Row(), nRow2
= r
.aEnd
.Row();
1092 SCCOL nCol1
= r
.aStart
.Col(), nCol2
= r
.aEnd
.Col();
1093 SCTAB nTab1
= r
.aStart
.Tab(), nTab2
= r
.aEnd
.Tab();
1094 if (aRet
.aStart
.Row() > nRow1
)
1095 aRet
.aStart
.SetRow(nRow1
);
1096 if (aRet
.aStart
.Col() > nCol1
)
1097 aRet
.aStart
.SetCol(nCol1
);
1098 if (aRet
.aStart
.Tab() > nTab1
)
1099 aRet
.aStart
.SetTab(nTab1
);
1100 if (aRet
.aEnd
.Row() < nRow2
)
1101 aRet
.aEnd
.SetRow(nRow2
);
1102 if (aRet
.aEnd
.Col() < nCol2
)
1103 aRet
.aEnd
.SetCol(nCol2
);
1104 if (aRet
.aEnd
.Tab() < nTab2
)
1105 aRet
.aEnd
.SetTab(nTab2
);
1110 bool ScRangeList::empty() const
1112 return maRanges
.empty();
1115 size_t ScRangeList::size() const
1117 return maRanges
.size();
1120 ScRange
* ScRangeList::operator [](size_t idx
)
1122 return maRanges
[idx
];
1125 const ScRange
* ScRangeList::operator [](size_t idx
) const
1127 return maRanges
[idx
];
1130 ScRange
* ScRangeList::front()
1132 return maRanges
.front();
1135 const ScRange
* ScRangeList::front() const
1137 return maRanges
.front();
1140 ScRange
* ScRangeList::back()
1142 return maRanges
.back();
1145 const ScRange
* ScRangeList::back() const
1147 return maRanges
.back();
1150 void ScRangeList::push_back(ScRange
* p
)
1152 maRanges
.push_back(p
);
1155 ScAddress
ScRangeList::GetTopLeftCorner() const
1160 ScAddress aAddr
= maRanges
[0]->aStart
;
1161 for(size_t i
= 1, n
= size(); i
< n
; ++i
)
1163 if(maRanges
[i
]->aStart
< aAddr
)
1164 aAddr
= maRanges
[i
]->aStart
;
1170 ScRangeList
ScRangeList::GetIntersectedRange(const ScRange
& rRange
) const
1172 ScRangeList aReturn
;
1173 for(const_iterator itr
= maRanges
.begin(), itrEnd
= maRanges
.end();
1174 itr
!= itrEnd
; ++itr
)
1176 if((*itr
)->Intersects(rRange
))
1178 SCCOL nColStart1
, nColEnd1
, nColStart2
, nColEnd2
;
1179 SCROW nRowStart1
, nRowEnd1
, nRowStart2
, nRowEnd2
;
1180 SCTAB nTabStart1
, nTabEnd1
, nTabStart2
, nTabEnd2
;
1181 (*itr
)->GetVars(nColStart1
, nRowStart1
, nTabStart1
,
1182 nColEnd1
, nRowEnd1
, nTabEnd1
);
1183 rRange
.GetVars(nColStart2
, nRowStart2
, nTabStart2
,
1184 nColEnd2
, nRowEnd2
, nTabEnd2
);
1186 ScRange
aNewRange(std::max
<SCCOL
>(nColStart1
, nColStart2
), std::max
<SCROW
>(nRowStart1
, nRowStart2
),
1187 std::max
<SCTAB
>(nTabStart1
, nTabStart2
), std::min
<SCCOL
>(nColEnd1
, nColEnd2
),
1188 std::min
<SCROW
>(nRowEnd1
, nRowEnd2
), std::min
<SCTAB
>(nTabEnd1
, nTabEnd2
));
1189 aReturn
.Join(aNewRange
);
1197 ScRangePairList::~ScRangePairList()
1199 for_each( maPairs
.begin(), maPairs
.end(), ScDeleteObjectByPtr
<ScRangePair
>() );
1203 ScRangePair
* ScRangePairList::Remove(size_t nPos
)
1205 if (maPairs
.size() <= nPos
)
1206 // Out-of-bound condition. Bail out.
1209 vector
<ScRangePair
*>::iterator itr
= maPairs
.begin();
1211 ScRangePair
* p
= *itr
;
1216 ScRangePair
* ScRangePairList::Remove( ScRangePair
* Adr
)
1218 ScRangePair
* p
= NULL
;
1220 if (Adr
== NULL
) return NULL
;
1222 for ( vector
<ScRangePair
*>::iterator itr
= maPairs
.begin(); itr
< maPairs
.end(); ++itr
)
1224 if ( Adr
== (p
= *itr
) )
1226 maPairs
.erase( itr
);
1233 bool ScRangePairList::operator==( const ScRangePairList
& r
) const
1236 return true; // identische Referenz
1237 if ( maPairs
.size() != r
.size() )
1239 for ( size_t nIdx
= 0, nCnt
= maPairs
.size(); nIdx
< nCnt
; ++nIdx
)
1241 if ( *maPairs
[ nIdx
] != *r
[ nIdx
] )
1242 return false; // auch andere Reihenfolge ist ungleich
1247 ScRangePair
* ScRangePairList::operator [](size_t idx
)
1249 return maPairs
[idx
];
1252 const ScRangePair
* ScRangePairList::operator [](size_t idx
) const
1254 return maPairs
[idx
];
1257 size_t ScRangePairList::size() const
1259 return maPairs
.size();
1262 bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode
,
1263 ScDocument
* pDoc
, const ScRange
& rWhere
,
1264 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
1266 bool bChanged
= false;
1267 if ( !maPairs
.empty() )
1275 rWhere
.GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
1276 for ( size_t i
= 0, nPairs
= maPairs
.size(); i
< nPairs
; ++i
)
1278 ScRangePair
* pR
= maPairs
[ i
];
1279 for ( sal_uInt16 j
=0; j
<2; j
++ )
1281 ScRange
& rRange
= pR
->GetRange(j
);
1288 rRange
.GetVars( theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
);
1289 if ( ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
1290 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
,
1292 theCol1
, theRow1
, theTab1
, theCol2
, theRow2
, theTab2
)
1296 rRange
.aStart
.Set( theCol1
, theRow1
, theTab1
);
1297 rRange
.aEnd
.Set( theCol2
, theRow2
, theTab2
);
1305 // Delete entries that have the labels (first range) on nTab
1306 void ScRangePairList::DeleteOnTab( SCTAB nTab
)
1308 size_t nListCount
= maPairs
.size();
1310 while ( nPos
< nListCount
)
1312 ScRangePair
* pR
= maPairs
[ nPos
];
1313 ScRange aRange
= pR
->GetRange(0);
1314 if ( aRange
.aStart
.Tab() == nTab
&& aRange
.aEnd
.Tab() == nTab
)
1318 nListCount
= maPairs
.size();
1325 ScRangePair
* ScRangePairList::Find( const ScAddress
& rAdr
) const
1327 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1329 ScRangePair
* pR
= maPairs
[ j
];
1330 if ( pR
->GetRange(0).In( rAdr
) )
1336 ScRangePair
* ScRangePairList::Find( const ScRange
& rRange
) const
1338 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1340 ScRangePair
* pR
= maPairs
[ j
];
1341 if ( pR
->GetRange(0) == rRange
)
1347 ScRangePairList
* ScRangePairList::Clone() const
1349 ScRangePairList
* pNew
= new ScRangePairList
;
1350 for ( size_t j
= 0, nListCount
= maPairs
.size(); j
< nListCount
; j
++ )
1352 pNew
->Append( *maPairs
[ j
] );
1357 struct ScRangePairNameSort
1364 int SAL_CALL
ScRangePairList_QsortNameCompare( const void* p1
, const void* p2
)
1366 const ScRangePairNameSort
* ps1
= (const ScRangePairNameSort
*)p1
;
1367 const ScRangePairNameSort
* ps2
= (const ScRangePairNameSort
*)p2
;
1368 const ScAddress
& rStartPos1
= ps1
->pPair
->GetRange(0).aStart
;
1369 const ScAddress
& rStartPos2
= ps2
->pPair
->GetRange(0).aStart
;
1370 OUString aStr1
, aStr2
;
1372 if ( rStartPos1
.Tab() == rStartPos2
.Tab() )
1376 ps1
->pDoc
->GetName( rStartPos1
.Tab(), aStr1
);
1377 ps2
->pDoc
->GetName( rStartPos2
.Tab(), aStr2
);
1378 nComp
= ScGlobal::GetCollator()->compareString( aStr1
, aStr2
);
1391 if ( rStartPos1
.Col() < rStartPos2
.Col() )
1393 if ( rStartPos1
.Col() > rStartPos2
.Col() )
1396 if ( rStartPos1
.Row() < rStartPos2
.Row() )
1398 if ( rStartPos1
.Row() > rStartPos2
.Row() )
1400 // erste Ecke gleich, zweite Ecke
1402 const ScAddress
& rEndPos1
= ps1
->pPair
->GetRange(0).aEnd
;
1403 const ScAddress
& rEndPos2
= ps2
->pPair
->GetRange(0).aEnd
;
1404 if ( rEndPos1
.Tab() == rEndPos2
.Tab() )
1408 ps1
->pDoc
->GetName( rEndPos1
.Tab(), aStr1
);
1409 ps2
->pDoc
->GetName( rEndPos2
.Tab(), aStr2
);
1410 nComp
= ScGlobal::GetCollator()->compareString( aStr1
, aStr2
);
1423 if ( rEndPos1
.Col() < rEndPos2
.Col() )
1425 if ( rEndPos1
.Col() > rEndPos2
.Col() )
1428 if ( rEndPos1
.Row() < rEndPos2
.Row() )
1430 if ( rEndPos1
.Row() > rEndPos2
.Row() )
1436 #ifndef _MSC_VER // MSVC is good enough to warn about unreachable code here.
1437 // Or stupid enough to bother warning about it, depending
1438 // on your point of view.
1439 return 0; // just in case
1443 void ScRangePairList::Join( const ScRangePair
& r
, bool bIsInList
)
1445 if ( maPairs
.empty() )
1450 const ScRange
& r1
= r
.GetRange(0);
1451 const ScRange
& r2
= r
.GetRange(1);
1452 SCCOL nCol1
= r1
.aStart
.Col();
1453 SCROW nRow1
= r1
.aStart
.Row();
1454 SCTAB nTab1
= r1
.aStart
.Tab();
1455 SCCOL nCol2
= r1
.aEnd
.Col();
1456 SCROW nRow2
= r1
.aEnd
.Row();
1457 SCTAB nTab2
= r1
.aEnd
.Tab();
1458 ScRangePair
* pOver
= (ScRangePair
*) &r
; // fies aber wahr wenn bInList
1462 // Find the current position of this range.
1463 for ( size_t i
= 0, nPairs
= maPairs
.size(); i
< nPairs
; ++i
)
1465 if ( maPairs
[i
] == pOver
)
1472 bool bJoinedInput
= false;
1474 for ( size_t i
= 0; i
< maPairs
.size() && pOver
; ++i
)
1476 ScRangePair
* p
= maPairs
[ i
];
1478 continue; // derselbe, weiter mit dem naechsten
1479 bool bJoined
= false;
1480 ScRange
& rp1
= p
->GetRange(0);
1481 ScRange
& rp2
= p
->GetRange(1);
1483 { // nur wenn Range2 gleich ist
1485 { // RangePair r in RangePair p enthalten oder identisch
1487 bJoined
= true; // weg mit RangePair r
1490 bJoinedInput
= true; // nicht anhaengen
1494 else if ( r1
.In( rp1
) )
1495 { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen
1500 if ( !bJoined
&& rp1
.aStart
.Tab() == nTab1
&& rp1
.aEnd
.Tab() == nTab2
1501 && rp2
.aStart
.Tab() == r2
.aStart
.Tab()
1502 && rp2
.aEnd
.Tab() == r2
.aEnd
.Tab() )
1503 { // 2D, Range2 muss genauso nebeneinander liegen wie Range1
1504 if ( rp1
.aStart
.Col() == nCol1
&& rp1
.aEnd
.Col() == nCol2
1505 && rp2
.aStart
.Col() == r2
.aStart
.Col()
1506 && rp2
.aEnd
.Col() == r2
.aEnd
.Col() )
1508 if ( rp1
.aStart
.Row() == nRow2
+1
1509 && rp2
.aStart
.Row() == r2
.aEnd
.Row()+1 )
1511 rp1
.aStart
.SetRow( nRow1
);
1512 rp2
.aStart
.SetRow( r2
.aStart
.Row() );
1515 else if ( rp1
.aEnd
.Row() == nRow1
-1
1516 && rp2
.aEnd
.Row() == r2
.aStart
.Row()-1 )
1518 rp1
.aEnd
.SetRow( nRow2
);
1519 rp2
.aEnd
.SetRow( r2
.aEnd
.Row() );
1523 else if ( rp1
.aStart
.Row() == nRow1
&& rp1
.aEnd
.Row() == nRow2
1524 && rp2
.aStart
.Row() == r2
.aStart
.Row()
1525 && rp2
.aEnd
.Row() == r2
.aEnd
.Row() )
1527 if ( rp1
.aStart
.Col() == nCol2
+1
1528 && rp2
.aStart
.Col() == r2
.aEnd
.Col()+1 )
1530 rp1
.aStart
.SetCol( nCol1
);
1531 rp2
.aStart
.SetCol( r2
.aStart
.Col() );
1534 else if ( rp1
.aEnd
.Col() == nCol1
-1
1535 && rp2
.aEnd
.Col() == r2
.aEnd
.Col()-1 )
1537 rp1
.aEnd
.SetCol( nCol2
);
1538 rp2
.aEnd
.SetCol( r2
.aEnd
.Col() );
1546 { // innerhalb der Liste RangePair loeschen
1552 nOldPos
--; // Seek richtig aufsetzen
1554 bJoinedInput
= true;
1555 Join( *p
, true ); // rekursiv!
1558 if ( !bIsInList
&& !bJoinedInput
)
1562 ScRangePair
** ScRangePairList::CreateNameSortedArray( size_t& nListCount
,
1563 ScDocument
* pDoc
) const
1565 nListCount
= maPairs
.size();
1566 OSL_ENSURE( nListCount
* sizeof(ScRangePairNameSort
) <= (size_t)~0x1F,
1567 "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
1568 ScRangePairNameSort
* pSortArray
= (ScRangePairNameSort
*)
1569 new sal_uInt8
[ nListCount
* sizeof(ScRangePairNameSort
) ];
1571 for ( j
=0; j
< nListCount
; j
++ )
1573 pSortArray
[j
].pPair
= maPairs
[ j
];
1574 pSortArray
[j
].pDoc
= pDoc
;
1576 qsort( (void*)pSortArray
, nListCount
, sizeof(ScRangePairNameSort
), &ScRangePairList_QsortNameCompare
);
1577 // ScRangePair Pointer aufruecken
1578 ScRangePair
** ppSortArray
= (ScRangePair
**)pSortArray
;
1579 for ( j
=0; j
< nListCount
; j
++ )
1581 ppSortArray
[j
] = pSortArray
[j
].pPair
;
1586 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */