xref: /aoo42x/main/sc/source/core/tool/rangelst.cxx (revision e8e74e65)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b3f79822SAndrew Rist  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19*b3f79822SAndrew Rist  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir //------------------------------------------------------------------------
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #define SC_RANGELST_CXX			//fuer ICC
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <tools/debug.hxx>
33cdf0e10cSrcweir #include <stdlib.h>				// qsort
34cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include "rangelst.hxx"
37cdf0e10cSrcweir #include "document.hxx"
38cdf0e10cSrcweir #include "refupdat.hxx"
39cdf0e10cSrcweir #include "rechead.hxx"
40cdf0e10cSrcweir #include "compiler.hxx"
41cdf0e10cSrcweir 
42cdf0e10cSrcweir // === ScRangeList ====================================================
43cdf0e10cSrcweir 
~ScRangeList()44cdf0e10cSrcweir ScRangeList::~ScRangeList()
45cdf0e10cSrcweir {
46cdf0e10cSrcweir 	for ( ScRangePtr pR = First(); pR; pR = Next() )
47cdf0e10cSrcweir 		delete pR;
48cdf0e10cSrcweir }
49cdf0e10cSrcweir 
RemoveAll()50cdf0e10cSrcweir void ScRangeList::RemoveAll()
51cdf0e10cSrcweir {
52cdf0e10cSrcweir 	for ( ScRangePtr pR = First(); pR; pR = Next() )
53cdf0e10cSrcweir 		delete pR;
54cdf0e10cSrcweir 	Clear();
55cdf0e10cSrcweir }
56cdf0e10cSrcweir 
Parse(const String & rStr,ScDocument * pDoc,sal_uInt16 nMask,formula::FormulaGrammar::AddressConvention eConv,sal_Unicode cDelimiter)57cdf0e10cSrcweir sal_uInt16 ScRangeList::Parse( const String& rStr, ScDocument* pDoc, sal_uInt16 nMask,
58cdf0e10cSrcweir 						   formula::FormulaGrammar::AddressConvention eConv,
59cdf0e10cSrcweir                            sal_Unicode cDelimiter )
60cdf0e10cSrcweir {
61cdf0e10cSrcweir 	if ( rStr.Len() )
62cdf0e10cSrcweir 	{
63cdf0e10cSrcweir         if (!cDelimiter)
64cdf0e10cSrcweir             cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
65cdf0e10cSrcweir 
66cdf0e10cSrcweir 		nMask |= SCA_VALID;				// falls das jemand vergessen sollte
67cdf0e10cSrcweir 		sal_uInt16 nResult = (sal_uInt16)~0;	// alle Bits setzen
68cdf0e10cSrcweir 		ScRange	aRange;
69cdf0e10cSrcweir 		String aOne;
70cdf0e10cSrcweir 		SCTAB nTab = 0;
71cdf0e10cSrcweir 		if ( pDoc )
72cdf0e10cSrcweir 		{
73cdf0e10cSrcweir 			//!	erste markierte Tabelle gibts nicht mehr am Dokument
74cdf0e10cSrcweir 			//!	-> uebergeben? oder spaeter an den Ranges setzen
75cdf0e10cSrcweir 		}
76cdf0e10cSrcweir 		else
77cdf0e10cSrcweir 			nTab = 0;
78cdf0e10cSrcweir 		sal_uInt16 nTCount = rStr.GetTokenCount( cDelimiter );
79cdf0e10cSrcweir 		for ( sal_uInt16 i=0; i<nTCount; i++ )
80cdf0e10cSrcweir 		{
81cdf0e10cSrcweir 			aOne = rStr.GetToken( i, cDelimiter );
82cdf0e10cSrcweir 			// FIXME : broken for Lotus
83cdf0e10cSrcweir 			if ( aOne.Search( ':' ) == STRING_NOTFOUND )
84cdf0e10cSrcweir 			{	// Range muss es sein
85cdf0e10cSrcweir 				String aStrTmp( aOne );
86cdf0e10cSrcweir 				aOne += ':';
87cdf0e10cSrcweir 				aOne += aStrTmp;
88cdf0e10cSrcweir 			}
89cdf0e10cSrcweir 			aRange.aStart.SetTab( nTab );	// Default Tab wenn nicht angegeben
90cdf0e10cSrcweir 			sal_uInt16 nRes = aRange.Parse( aOne, pDoc, eConv );
91cdf0e10cSrcweir 			if ( (nRes & nMask) == nMask )
92cdf0e10cSrcweir 				Append( aRange );
93cdf0e10cSrcweir 			nResult &= nRes;		// alle gemeinsamen Bits bleiben erhalten
94cdf0e10cSrcweir 		}
95cdf0e10cSrcweir 		return nResult;				// SCA_VALID gesetzt wenn alle ok
96cdf0e10cSrcweir 	}
97cdf0e10cSrcweir 	else
98cdf0e10cSrcweir 		return 0;
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 
Format(String & rStr,sal_uInt16 nFlags,ScDocument * pDoc,formula::FormulaGrammar::AddressConvention eConv,sal_Unicode cDelimiter) const102cdf0e10cSrcweir void ScRangeList::Format( String& rStr, sal_uInt16 nFlags, ScDocument* pDoc,
103cdf0e10cSrcweir 						  formula::FormulaGrammar::AddressConvention eConv,
104cdf0e10cSrcweir                           sal_Unicode cDelimiter ) const
105cdf0e10cSrcweir {
106cdf0e10cSrcweir 	rStr.Erase();
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     if (!cDelimiter)
109cdf0e10cSrcweir         cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
110cdf0e10cSrcweir 
111cdf0e10cSrcweir 	sal_uLong nCnt = Count();
112cdf0e10cSrcweir 	for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ )
113cdf0e10cSrcweir 	{
114cdf0e10cSrcweir 		String aStr;
115cdf0e10cSrcweir 		GetObject( nIdx )->Format( aStr, nFlags, pDoc, eConv );
116cdf0e10cSrcweir 		if ( nIdx )
117cdf0e10cSrcweir 			rStr += cDelimiter;
118cdf0e10cSrcweir 		rStr += aStr;
119cdf0e10cSrcweir 	}
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 
Join(const ScRange & r,sal_Bool bIsInList)123cdf0e10cSrcweir void ScRangeList::Join( const ScRange& r, sal_Bool bIsInList )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir 	if ( !Count() )
126cdf0e10cSrcweir 	{
127cdf0e10cSrcweir 		Append( r );
128cdf0e10cSrcweir 		return ;
129cdf0e10cSrcweir 	}
130cdf0e10cSrcweir 	SCCOL nCol1 = r.aStart.Col();
131cdf0e10cSrcweir 	SCROW nRow1 = r.aStart.Row();
132cdf0e10cSrcweir 	SCTAB nTab1 = r.aStart.Tab();
133cdf0e10cSrcweir 	SCCOL nCol2 = r.aEnd.Col();
134cdf0e10cSrcweir 	SCROW nRow2 = r.aEnd.Row();
135cdf0e10cSrcweir 	SCTAB nTab2 = r.aEnd.Tab();
136cdf0e10cSrcweir 	ScRangePtr pOver = (ScRangePtr) &r;		// fies aber wahr wenn bInList
137cdf0e10cSrcweir     sal_uLong nOldPos = 0;
138cdf0e10cSrcweir 	if ( bIsInList )
139cdf0e10cSrcweir 	{	// merken um ggbf. zu loeschen bzw. wiederherzustellen
140cdf0e10cSrcweir 		nOldPos = GetPos( pOver );
141cdf0e10cSrcweir 	}
142cdf0e10cSrcweir 	sal_Bool bJoinedInput = sal_False;
143cdf0e10cSrcweir 	for ( ScRangePtr p = First(); p && pOver; p = Next() )
144cdf0e10cSrcweir 	{
145cdf0e10cSrcweir 		if ( p == pOver )
146cdf0e10cSrcweir 			continue;			// derselbe, weiter mit dem naechsten
147cdf0e10cSrcweir 		sal_Bool bJoined = sal_False;
148cdf0e10cSrcweir 		if ( p->In( r ) )
149cdf0e10cSrcweir 		{	// Range r in Range p enthalten oder identisch
150cdf0e10cSrcweir 			if ( bIsInList )
151cdf0e10cSrcweir 				bJoined = sal_True;		// weg mit Range r
152cdf0e10cSrcweir 			else
153cdf0e10cSrcweir 			{	// das war's dann
154cdf0e10cSrcweir 				bJoinedInput = sal_True;	// nicht anhaengen
155cdf0e10cSrcweir 				break;	// for
156cdf0e10cSrcweir 			}
157cdf0e10cSrcweir 		}
158cdf0e10cSrcweir 		else if ( r.In( *p ) )
159cdf0e10cSrcweir 		{	// Range p in Range r enthalten, r zum neuen Range machen
160cdf0e10cSrcweir 			*p = r;
161cdf0e10cSrcweir 			bJoined = sal_True;
162cdf0e10cSrcweir 		}
163cdf0e10cSrcweir 		if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 )
164cdf0e10cSrcweir 		{	// 2D
165cdf0e10cSrcweir 			if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 )
166cdf0e10cSrcweir 			{
167cdf0e10cSrcweir 				if ( p->aStart.Row() == nRow2+1 )
168cdf0e10cSrcweir 				{	// oben
169cdf0e10cSrcweir 					p->aStart.SetRow( nRow1 );
170cdf0e10cSrcweir 					bJoined = sal_True;
171cdf0e10cSrcweir 				}
172cdf0e10cSrcweir 				else if ( p->aEnd.Row() == nRow1-1 )
173cdf0e10cSrcweir 				{	// unten
174cdf0e10cSrcweir 					p->aEnd.SetRow( nRow2 );
175cdf0e10cSrcweir 					bJoined = sal_True;
176cdf0e10cSrcweir 				}
177cdf0e10cSrcweir 			}
178cdf0e10cSrcweir 			else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 )
179cdf0e10cSrcweir 			{
180cdf0e10cSrcweir 				if ( p->aStart.Col() == nCol2+1 )
181cdf0e10cSrcweir 				{	// links
182cdf0e10cSrcweir 					p->aStart.SetCol( nCol1 );
183cdf0e10cSrcweir 					bJoined = sal_True;
184cdf0e10cSrcweir 				}
185cdf0e10cSrcweir 				else if ( p->aEnd.Col() == nCol1-1 )
186cdf0e10cSrcweir 				{	// rechts
187cdf0e10cSrcweir 					p->aEnd.SetCol( nCol2 );
188cdf0e10cSrcweir 					bJoined = sal_True;
189cdf0e10cSrcweir 				}
190cdf0e10cSrcweir 			}
191cdf0e10cSrcweir 		}
192cdf0e10cSrcweir 		if ( bJoined )
193cdf0e10cSrcweir 		{
194cdf0e10cSrcweir 			if ( bIsInList )
195cdf0e10cSrcweir 			{	// innerhalb der Liste Range loeschen
196cdf0e10cSrcweir 				Remove( nOldPos );
197cdf0e10cSrcweir 				delete pOver;
198cdf0e10cSrcweir 				pOver = NULL;
199cdf0e10cSrcweir 				if ( nOldPos )
200cdf0e10cSrcweir 					nOldPos--;			// Seek richtig aufsetzen
201cdf0e10cSrcweir 			}
202cdf0e10cSrcweir 			bJoinedInput = sal_True;
203cdf0e10cSrcweir 			Join( *p, sal_True );			// rekursiv!
204cdf0e10cSrcweir 		}
205cdf0e10cSrcweir 	}
206cdf0e10cSrcweir 	if ( bIsInList )
207cdf0e10cSrcweir 		Seek( nOldPos );
208cdf0e10cSrcweir 	else if ( !bJoinedInput )
209cdf0e10cSrcweir 		Append( r );
210cdf0e10cSrcweir }
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 
operator ==(const ScRangeList & r) const213cdf0e10cSrcweir sal_Bool ScRangeList::operator==( const ScRangeList& r ) const
214cdf0e10cSrcweir {
215cdf0e10cSrcweir 	if ( this == &r )
216cdf0e10cSrcweir 		return sal_True;				// identische Referenz
217cdf0e10cSrcweir 	if ( Count() != r.Count() )
218cdf0e10cSrcweir 		return sal_False;
219cdf0e10cSrcweir 	sal_uLong nCnt = Count();
220cdf0e10cSrcweir 	for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ )
221cdf0e10cSrcweir 	{
222cdf0e10cSrcweir 		if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) )
223cdf0e10cSrcweir 			return sal_False;			// auch andere Reihenfolge ist ungleich
224cdf0e10cSrcweir 	}
225cdf0e10cSrcweir 	return sal_True;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
operator !=(const ScRangeList & r) const228cdf0e10cSrcweir sal_Bool ScRangeList::operator!=( const ScRangeList& r ) const
229cdf0e10cSrcweir {
230cdf0e10cSrcweir     return !operator==( r );
231cdf0e10cSrcweir }
232cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,ScDocument * pDoc,const ScRange & rWhere,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)233cdf0e10cSrcweir sal_Bool ScRangeList::UpdateReference( UpdateRefMode eUpdateRefMode,
234cdf0e10cSrcweir 									ScDocument* pDoc, const ScRange& rWhere,
235cdf0e10cSrcweir 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir 	sal_Bool bChanged = sal_False;
238cdf0e10cSrcweir 	if ( Count() )
239cdf0e10cSrcweir 	{
240cdf0e10cSrcweir         SCCOL nCol1;
241cdf0e10cSrcweir         SCROW nRow1;
242cdf0e10cSrcweir         SCTAB nTab1;
243cdf0e10cSrcweir         SCCOL nCol2;
244cdf0e10cSrcweir         SCROW nRow2;
245cdf0e10cSrcweir         SCTAB nTab2;
246cdf0e10cSrcweir 		rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
247cdf0e10cSrcweir 		for ( ScRange* pR = First(); pR; pR = Next() )
248cdf0e10cSrcweir 		{
249cdf0e10cSrcweir             SCCOL theCol1;
250cdf0e10cSrcweir             SCROW theRow1;
251cdf0e10cSrcweir             SCTAB theTab1;
252cdf0e10cSrcweir             SCCOL theCol2;
253cdf0e10cSrcweir             SCROW theRow2;
254cdf0e10cSrcweir             SCTAB theTab2;
255cdf0e10cSrcweir 			pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
256cdf0e10cSrcweir 			if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
257cdf0e10cSrcweir 					nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
258cdf0e10cSrcweir 					nDx, nDy, nDz,
259cdf0e10cSrcweir 					theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
260cdf0e10cSrcweir 					!= UR_NOTHING )
261cdf0e10cSrcweir 			{
262cdf0e10cSrcweir 				bChanged = sal_True;
263cdf0e10cSrcweir 				pR->aStart.Set( theCol1, theRow1, theTab1 );
264cdf0e10cSrcweir 				pR->aEnd.Set( theCol2, theRow2, theTab2 );
265cdf0e10cSrcweir 			}
266cdf0e10cSrcweir 		}
267cdf0e10cSrcweir 	}
268cdf0e10cSrcweir 	return bChanged;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 
Find(const ScAddress & rAdr) const272cdf0e10cSrcweir ScRange* ScRangeList::Find( const ScAddress& rAdr ) const
273cdf0e10cSrcweir {
274cdf0e10cSrcweir 	sal_uLong nListCount = Count();
275cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
276cdf0e10cSrcweir 	{
277cdf0e10cSrcweir 		ScRange* pR = GetObject( j );
278cdf0e10cSrcweir 		if ( pR->In( rAdr ) )
279cdf0e10cSrcweir 			return pR;
280cdf0e10cSrcweir 	}
281cdf0e10cSrcweir 	return NULL;
282cdf0e10cSrcweir }
283cdf0e10cSrcweir 
284cdf0e10cSrcweir 
ScRangeList(const ScRangeList & rList)285cdf0e10cSrcweir ScRangeList::ScRangeList( const ScRangeList& rList ) :
286cdf0e10cSrcweir     ScRangeListBase(),
287cdf0e10cSrcweir     SvRefBase()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir 	sal_uLong nListCount = rList.Count();
290cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
291cdf0e10cSrcweir 		Append( *rList.GetObject( j ) );
292cdf0e10cSrcweir }
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 
operator =(const ScRangeList & rList)295cdf0e10cSrcweir ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
296cdf0e10cSrcweir {
297cdf0e10cSrcweir 	RemoveAll();
298cdf0e10cSrcweir 
299cdf0e10cSrcweir 	sal_uLong nListCount = rList.Count();
300cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
301cdf0e10cSrcweir 		Append( *rList.GetObject( j ) );
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 	return *this;
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 
Intersects(const ScRange & rRange) const307cdf0e10cSrcweir sal_Bool ScRangeList::Intersects( const ScRange& rRange ) const
308cdf0e10cSrcweir {
309cdf0e10cSrcweir 	sal_uLong nListCount = Count();
310cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
311cdf0e10cSrcweir 		if ( GetObject(j)->Intersects( rRange ) )
312cdf0e10cSrcweir 			return sal_True;
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 	return sal_False;
315cdf0e10cSrcweir }
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 
In(const ScRange & rRange) const318cdf0e10cSrcweir sal_Bool ScRangeList::In( const ScRange& rRange ) const
319cdf0e10cSrcweir {
320cdf0e10cSrcweir 	sal_uLong nListCount = Count();
321cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
322cdf0e10cSrcweir 		if ( GetObject(j)->In( rRange ) )
323cdf0e10cSrcweir 			return sal_True;
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 	return sal_False;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 
GetCellCount() const329cdf0e10cSrcweir sal_uLong ScRangeList::GetCellCount() const
330cdf0e10cSrcweir {
331cdf0e10cSrcweir 	sal_uLong nCellCount = 0;
332cdf0e10cSrcweir 	sal_uLong nListCount = Count();
333cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
334cdf0e10cSrcweir 	{
335cdf0e10cSrcweir 		ScRange* pR = GetObject( j );
336cdf0e10cSrcweir 		nCellCount += sal_uLong(pR->aEnd.Col() - pR->aStart.Col() + 1)
337cdf0e10cSrcweir 			* sal_uLong(pR->aEnd.Row() - pR->aStart.Row() + 1)
338cdf0e10cSrcweir 			* sal_uLong(pR->aEnd.Tab() - pR->aStart.Tab() + 1);
339cdf0e10cSrcweir 	}
340cdf0e10cSrcweir 	return nCellCount;
341cdf0e10cSrcweir }
342cdf0e10cSrcweir 
343cdf0e10cSrcweir 
344cdf0e10cSrcweir // === ScRangePairList ====================================================
345cdf0e10cSrcweir 
~ScRangePairList()346cdf0e10cSrcweir ScRangePairList::~ScRangePairList()
347cdf0e10cSrcweir {
348cdf0e10cSrcweir 	for ( ScRangePair* pR = First(); pR; pR = Next() )
349cdf0e10cSrcweir 		delete pR;
350cdf0e10cSrcweir }
351cdf0e10cSrcweir 
352cdf0e10cSrcweir 
Join(const ScRangePair & r,sal_Bool bIsInList)353cdf0e10cSrcweir void ScRangePairList::Join( const ScRangePair& r, sal_Bool bIsInList )
354cdf0e10cSrcweir {
355cdf0e10cSrcweir 	if ( !Count() )
356cdf0e10cSrcweir 	{
357cdf0e10cSrcweir 		Append( r );
358cdf0e10cSrcweir 		return ;
359cdf0e10cSrcweir 	}
360cdf0e10cSrcweir 	const ScRange& r1 = r.GetRange(0);
361cdf0e10cSrcweir 	const ScRange& r2 = r.GetRange(1);
362cdf0e10cSrcweir 	SCCOL nCol1 = r1.aStart.Col();
363cdf0e10cSrcweir 	SCROW nRow1 = r1.aStart.Row();
364cdf0e10cSrcweir 	SCTAB nTab1 = r1.aStart.Tab();
365cdf0e10cSrcweir 	SCCOL nCol2 = r1.aEnd.Col();
366cdf0e10cSrcweir 	SCROW nRow2 = r1.aEnd.Row();
367cdf0e10cSrcweir 	SCTAB nTab2 = r1.aEnd.Tab();
368cdf0e10cSrcweir 	ScRangePair* pOver = (ScRangePair*) &r;		// fies aber wahr wenn bInList
369cdf0e10cSrcweir     sal_uLong nOldPos = 0;
370cdf0e10cSrcweir 	if ( bIsInList )
371cdf0e10cSrcweir 	{	// merken um ggbf. zu loeschen bzw. wiederherzustellen
372cdf0e10cSrcweir 		nOldPos = GetPos( pOver );
373cdf0e10cSrcweir 	}
374cdf0e10cSrcweir 	sal_Bool bJoinedInput = sal_False;
375cdf0e10cSrcweir 	for ( ScRangePair* p = First(); p && pOver; p = Next() )
376cdf0e10cSrcweir 	{
377cdf0e10cSrcweir 		if ( p == pOver )
378cdf0e10cSrcweir 			continue;			// derselbe, weiter mit dem naechsten
379cdf0e10cSrcweir 		sal_Bool bJoined = sal_False;
380cdf0e10cSrcweir 		ScRange& rp1 = p->GetRange(0);
381cdf0e10cSrcweir 		ScRange& rp2 = p->GetRange(1);
382cdf0e10cSrcweir 		if ( rp2 == r2 )
383cdf0e10cSrcweir 		{	// nur wenn Range2 gleich ist
384cdf0e10cSrcweir 			if ( rp1.In( r1 ) )
385cdf0e10cSrcweir 			{	// RangePair r in RangePair p enthalten oder identisch
386cdf0e10cSrcweir 				if ( bIsInList )
387cdf0e10cSrcweir 					bJoined = sal_True;		// weg mit RangePair r
388cdf0e10cSrcweir 				else
389cdf0e10cSrcweir 				{	// das war's dann
390cdf0e10cSrcweir 					bJoinedInput = sal_True;	// nicht anhaengen
391cdf0e10cSrcweir 					break;	// for
392cdf0e10cSrcweir 				}
393cdf0e10cSrcweir 			}
394cdf0e10cSrcweir 			else if ( r1.In( rp1 ) )
395cdf0e10cSrcweir 			{	// RangePair p in RangePair r enthalten, r zum neuen RangePair machen
396cdf0e10cSrcweir 				*p = r;
397cdf0e10cSrcweir 				bJoined = sal_True;
398cdf0e10cSrcweir 			}
399cdf0e10cSrcweir 		}
400cdf0e10cSrcweir 		if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2
401cdf0e10cSrcweir 		  && rp2.aStart.Tab() == r2.aStart.Tab()
402cdf0e10cSrcweir 		  && rp2.aEnd.Tab() == r2.aEnd.Tab() )
403cdf0e10cSrcweir 		{	// 2D, Range2 muss genauso nebeneinander liegen wie Range1
404cdf0e10cSrcweir 			if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2
405cdf0e10cSrcweir 			  && rp2.aStart.Col() == r2.aStart.Col()
406cdf0e10cSrcweir 			  && rp2.aEnd.Col() == r2.aEnd.Col() )
407cdf0e10cSrcweir 			{
408cdf0e10cSrcweir 				if ( rp1.aStart.Row() == nRow2+1
409cdf0e10cSrcweir 				  && rp2.aStart.Row() == r2.aEnd.Row()+1 )
410cdf0e10cSrcweir 				{	// oben
411cdf0e10cSrcweir 					rp1.aStart.SetRow( nRow1 );
412cdf0e10cSrcweir 					rp2.aStart.SetRow( r2.aStart.Row() );
413cdf0e10cSrcweir 					bJoined = sal_True;
414cdf0e10cSrcweir 				}
415cdf0e10cSrcweir 				else if ( rp1.aEnd.Row() == nRow1-1
416cdf0e10cSrcweir 				  && rp2.aEnd.Row() == r2.aStart.Row()-1 )
417cdf0e10cSrcweir 				{	// unten
418cdf0e10cSrcweir 					rp1.aEnd.SetRow( nRow2 );
419cdf0e10cSrcweir 					rp2.aEnd.SetRow( r2.aEnd.Row() );
420cdf0e10cSrcweir 					bJoined = sal_True;
421cdf0e10cSrcweir 				}
422cdf0e10cSrcweir 			}
423cdf0e10cSrcweir 			else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2
424cdf0e10cSrcweir 			  && rp2.aStart.Row() == r2.aStart.Row()
425cdf0e10cSrcweir 			  && rp2.aEnd.Row() == r2.aEnd.Row() )
426cdf0e10cSrcweir 			{
427cdf0e10cSrcweir 				if ( rp1.aStart.Col() == nCol2+1
428cdf0e10cSrcweir 				  && rp2.aStart.Col() == r2.aEnd.Col()+1 )
429cdf0e10cSrcweir 				{	// links
430cdf0e10cSrcweir 					rp1.aStart.SetCol( nCol1 );
431cdf0e10cSrcweir 					rp2.aStart.SetCol( r2.aStart.Col() );
432cdf0e10cSrcweir 					bJoined = sal_True;
433cdf0e10cSrcweir 				}
434cdf0e10cSrcweir 				else if ( rp1.aEnd.Col() == nCol1-1
435cdf0e10cSrcweir 				  && rp2.aEnd.Col() == r2.aEnd.Col()-1 )
436cdf0e10cSrcweir 				{	// rechts
437cdf0e10cSrcweir 					rp1.aEnd.SetCol( nCol2 );
438cdf0e10cSrcweir 					rp2.aEnd.SetCol( r2.aEnd.Col() );
439cdf0e10cSrcweir 					bJoined = sal_True;
440cdf0e10cSrcweir 				}
441cdf0e10cSrcweir 			}
442cdf0e10cSrcweir 		}
443cdf0e10cSrcweir 		if ( bJoined )
444cdf0e10cSrcweir 		{
445cdf0e10cSrcweir 			if ( bIsInList )
446cdf0e10cSrcweir 			{	// innerhalb der Liste RangePair loeschen
447cdf0e10cSrcweir 				Remove( nOldPos );
448cdf0e10cSrcweir 				delete pOver;
449cdf0e10cSrcweir 				pOver = NULL;
450cdf0e10cSrcweir 				if ( nOldPos )
451cdf0e10cSrcweir 					nOldPos--;			// Seek richtig aufsetzen
452cdf0e10cSrcweir 			}
453cdf0e10cSrcweir 			bJoinedInput = sal_True;
454cdf0e10cSrcweir 			Join( *p, sal_True );			// rekursiv!
455cdf0e10cSrcweir 		}
456cdf0e10cSrcweir 	}
457cdf0e10cSrcweir 	if ( bIsInList )
458cdf0e10cSrcweir 		Seek( nOldPos );
459cdf0e10cSrcweir 	else if ( !bJoinedInput )
460cdf0e10cSrcweir 		Append( r );
461cdf0e10cSrcweir }
462cdf0e10cSrcweir 
463cdf0e10cSrcweir 
operator ==(const ScRangePairList & r) const464cdf0e10cSrcweir sal_Bool ScRangePairList::operator==( const ScRangePairList& r ) const
465cdf0e10cSrcweir {
466cdf0e10cSrcweir 	if ( this == &r )
467cdf0e10cSrcweir 		return sal_True;				// identische Referenz
468cdf0e10cSrcweir 	if ( Count() != r.Count() )
469cdf0e10cSrcweir 		return sal_False;
470cdf0e10cSrcweir 	sal_uLong nCnt = Count();
471cdf0e10cSrcweir 	for ( sal_uLong nIdx = 0; nIdx < nCnt; nIdx++ )
472cdf0e10cSrcweir 	{
473cdf0e10cSrcweir 		if ( *GetObject( nIdx ) != *r.GetObject( nIdx ) )
474cdf0e10cSrcweir 			return sal_False;			// auch andere Reihenfolge ist ungleich
475cdf0e10cSrcweir 	}
476cdf0e10cSrcweir 	return sal_True;
477cdf0e10cSrcweir }
478cdf0e10cSrcweir 
479cdf0e10cSrcweir 
UpdateReference(UpdateRefMode eUpdateRefMode,ScDocument * pDoc,const ScRange & rWhere,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)480cdf0e10cSrcweir sal_Bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode,
481cdf0e10cSrcweir 									ScDocument* pDoc, const ScRange& rWhere,
482cdf0e10cSrcweir 									SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
483cdf0e10cSrcweir {
484cdf0e10cSrcweir 	sal_Bool bChanged = sal_False;
485cdf0e10cSrcweir 	if ( Count() )
486cdf0e10cSrcweir 	{
487cdf0e10cSrcweir         SCCOL nCol1;
488cdf0e10cSrcweir         SCROW nRow1;
489cdf0e10cSrcweir         SCTAB nTab1;
490cdf0e10cSrcweir         SCCOL nCol2;
491cdf0e10cSrcweir         SCROW nRow2;
492cdf0e10cSrcweir         SCTAB nTab2;
493cdf0e10cSrcweir 		rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
494cdf0e10cSrcweir 		for ( ScRangePair* pR = First(); pR; pR = Next() )
495cdf0e10cSrcweir 		{
496cdf0e10cSrcweir 			for ( sal_uInt16 j=0; j<2; j++ )
497cdf0e10cSrcweir 			{
498cdf0e10cSrcweir 				ScRange& rRange = pR->GetRange(j);
499cdf0e10cSrcweir                 SCCOL theCol1;
500cdf0e10cSrcweir                 SCROW theRow1;
501cdf0e10cSrcweir                 SCTAB theTab1;
502cdf0e10cSrcweir                 SCCOL theCol2;
503cdf0e10cSrcweir                 SCROW theRow2;
504cdf0e10cSrcweir                 SCTAB theTab2;
505cdf0e10cSrcweir 				rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
506cdf0e10cSrcweir 				if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
507cdf0e10cSrcweir 						nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
508cdf0e10cSrcweir 						nDx, nDy, nDz,
509cdf0e10cSrcweir 						theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
510cdf0e10cSrcweir 						!= UR_NOTHING )
511cdf0e10cSrcweir 				{
512cdf0e10cSrcweir 					bChanged = sal_True;
513cdf0e10cSrcweir 					rRange.aStart.Set( theCol1, theRow1, theTab1 );
514cdf0e10cSrcweir 					rRange.aEnd.Set( theCol2, theRow2, theTab2 );
515cdf0e10cSrcweir 				}
516cdf0e10cSrcweir 			}
517cdf0e10cSrcweir 		}
518cdf0e10cSrcweir 	}
519cdf0e10cSrcweir 	return bChanged;
520cdf0e10cSrcweir }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir 
DeleteOnTab(SCTAB nTab)523cdf0e10cSrcweir void ScRangePairList::DeleteOnTab( SCTAB nTab )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir     // Delete entries that have the labels (first range) on nTab
526cdf0e10cSrcweir 
527cdf0e10cSrcweir     sal_uLong nListCount = Count();
528cdf0e10cSrcweir     sal_uLong nPos = 0;
529cdf0e10cSrcweir     while ( nPos < nListCount )
530cdf0e10cSrcweir     {
531cdf0e10cSrcweir         ScRangePair* pR = GetObject( nPos );
532cdf0e10cSrcweir         ScRange aRange = pR->GetRange(0);
533cdf0e10cSrcweir         if ( aRange.aStart.Tab() == nTab && aRange.aEnd.Tab() == nTab )
534cdf0e10cSrcweir         {
535cdf0e10cSrcweir             Remove( nPos );
536cdf0e10cSrcweir             delete pR;
537cdf0e10cSrcweir             nListCount = Count();
538cdf0e10cSrcweir         }
539cdf0e10cSrcweir         else
540cdf0e10cSrcweir             ++nPos;
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir }
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 
Find(const ScAddress & rAdr) const545cdf0e10cSrcweir ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const
546cdf0e10cSrcweir {
547cdf0e10cSrcweir 	sal_uLong nListCount = Count();
548cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
549cdf0e10cSrcweir 	{
550cdf0e10cSrcweir 		ScRangePair* pR = GetObject( j );
551cdf0e10cSrcweir 		if ( pR->GetRange(0).In( rAdr ) )
552cdf0e10cSrcweir 			return pR;
553cdf0e10cSrcweir 	}
554cdf0e10cSrcweir 	return NULL;
555cdf0e10cSrcweir }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir 
Find(const ScRange & rRange) const558cdf0e10cSrcweir ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const
559cdf0e10cSrcweir {
560cdf0e10cSrcweir 	sal_uLong nListCount = Count();
561cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
562cdf0e10cSrcweir 	{
563cdf0e10cSrcweir 		ScRangePair* pR = GetObject( j );
564cdf0e10cSrcweir 		if ( pR->GetRange(0) == rRange )
565cdf0e10cSrcweir 			return pR;
566cdf0e10cSrcweir 	}
567cdf0e10cSrcweir 	return NULL;
568cdf0e10cSrcweir }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 
Clone() const571cdf0e10cSrcweir ScRangePairList* ScRangePairList::Clone() const
572cdf0e10cSrcweir {
573cdf0e10cSrcweir 	ScRangePairList* pNew = new ScRangePairList;
574cdf0e10cSrcweir 	sal_uLong nListCount = Count();
575cdf0e10cSrcweir 	for ( sal_uLong j = 0; j < nListCount; j++ )
576cdf0e10cSrcweir 	{
577cdf0e10cSrcweir 		pNew->Append( *GetObject( j ) );
578cdf0e10cSrcweir 	}
579cdf0e10cSrcweir 	return pNew;
580cdf0e10cSrcweir }
581cdf0e10cSrcweir 
582cdf0e10cSrcweir 
583cdf0e10cSrcweir struct ScRangePairNameSort
584cdf0e10cSrcweir {
585cdf0e10cSrcweir 	ScRangePair*	pPair;
586cdf0e10cSrcweir 	ScDocument*		pDoc;
587cdf0e10cSrcweir };
588cdf0e10cSrcweir 
589cdf0e10cSrcweir 
590cdf0e10cSrcweir extern "C" int
591cdf0e10cSrcweir #ifdef WNT
592cdf0e10cSrcweir __cdecl
593cdf0e10cSrcweir #endif
ScRangePairList_QsortNameCompare(const void * p1,const void * p2)594cdf0e10cSrcweir ScRangePairList_QsortNameCompare( const void* p1, const void* p2 )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir 	const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1;
597cdf0e10cSrcweir 	const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2;
598cdf0e10cSrcweir 	const ScAddress& rStartPos1 = ps1->pPair->GetRange(0).aStart;
599cdf0e10cSrcweir 	const ScAddress& rStartPos2 = ps2->pPair->GetRange(0).aStart;
600cdf0e10cSrcweir 	String aStr1, aStr2;
601cdf0e10cSrcweir 	sal_Int32 nComp;
602cdf0e10cSrcweir 	if ( rStartPos1.Tab() == rStartPos2.Tab() )
603cdf0e10cSrcweir 		nComp = COMPARE_EQUAL;
604cdf0e10cSrcweir 	else
605cdf0e10cSrcweir 	{
606cdf0e10cSrcweir 		ps1->pDoc->GetName( rStartPos1.Tab(), aStr1 );
607cdf0e10cSrcweir 		ps2->pDoc->GetName( rStartPos2.Tab(), aStr2 );
608cdf0e10cSrcweir 		nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
609cdf0e10cSrcweir 	}
610cdf0e10cSrcweir 	switch ( nComp )
611cdf0e10cSrcweir 	{
612cdf0e10cSrcweir 		case COMPARE_LESS:
613cdf0e10cSrcweir 			return -1;
614cdf0e10cSrcweir 		case COMPARE_GREATER:
615cdf0e10cSrcweir 			return 1;
616cdf0e10cSrcweir 		default:
617cdf0e10cSrcweir 			// gleiche Tabs
618cdf0e10cSrcweir 			if ( rStartPos1.Col() < rStartPos2.Col() )
619cdf0e10cSrcweir 				return -1;
620cdf0e10cSrcweir 			if ( rStartPos1.Col() > rStartPos2.Col() )
621cdf0e10cSrcweir 				return 1;
622cdf0e10cSrcweir 			// gleiche Cols
623cdf0e10cSrcweir 			if ( rStartPos1.Row() < rStartPos2.Row() )
624cdf0e10cSrcweir 				return -1;
625cdf0e10cSrcweir 			if ( rStartPos1.Row() > rStartPos2.Row() )
626cdf0e10cSrcweir 				return 1;
627cdf0e10cSrcweir 			// erste Ecke gleich, zweite Ecke
628cdf0e10cSrcweir 			{
629cdf0e10cSrcweir 				const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd;
630cdf0e10cSrcweir 				const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd;
631cdf0e10cSrcweir 				if ( rEndPos1.Tab() == rEndPos2.Tab() )
632cdf0e10cSrcweir 					nComp = COMPARE_EQUAL;
633cdf0e10cSrcweir 				else
634cdf0e10cSrcweir 				{
635cdf0e10cSrcweir 					ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 );
636cdf0e10cSrcweir 					ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 );
637cdf0e10cSrcweir 					nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
638cdf0e10cSrcweir 				}
639cdf0e10cSrcweir 				switch ( nComp )
640cdf0e10cSrcweir 				{
641cdf0e10cSrcweir 					case COMPARE_LESS:
642cdf0e10cSrcweir 						return -1;
643cdf0e10cSrcweir 					case COMPARE_GREATER:
644cdf0e10cSrcweir 						return 1;
645cdf0e10cSrcweir 					default:
646cdf0e10cSrcweir 						// gleiche Tabs
647cdf0e10cSrcweir 						if ( rEndPos1.Col() < rEndPos2.Col() )
648cdf0e10cSrcweir 							return -1;
649cdf0e10cSrcweir 						if ( rEndPos1.Col() > rEndPos2.Col() )
650cdf0e10cSrcweir 							return 1;
651cdf0e10cSrcweir 						// gleiche Cols
652cdf0e10cSrcweir 						if ( rEndPos1.Row() < rEndPos2.Row() )
653cdf0e10cSrcweir 							return -1;
654cdf0e10cSrcweir 						if ( rEndPos1.Row() > rEndPos2.Row() )
655cdf0e10cSrcweir 							return 1;
656cdf0e10cSrcweir 						return 0;
657cdf0e10cSrcweir 				}
658cdf0e10cSrcweir 			}
659cdf0e10cSrcweir 	}
660cdf0e10cSrcweir }
661cdf0e10cSrcweir 
662cdf0e10cSrcweir 
CreateNameSortedArray(sal_uLong & nListCount,ScDocument * pDoc) const663cdf0e10cSrcweir ScRangePair** ScRangePairList::CreateNameSortedArray( sal_uLong& nListCount,
664cdf0e10cSrcweir 		ScDocument* pDoc ) const
665cdf0e10cSrcweir {
666cdf0e10cSrcweir 	nListCount = Count();
667cdf0e10cSrcweir 	DBG_ASSERT( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F,
668cdf0e10cSrcweir 		"ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
669cdf0e10cSrcweir 	ScRangePairNameSort* pSortArray = (ScRangePairNameSort*)
670cdf0e10cSrcweir 		new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ];
671cdf0e10cSrcweir 	sal_uLong j;
672cdf0e10cSrcweir 	for ( j=0; j < nListCount; j++ )
673cdf0e10cSrcweir 	{
674cdf0e10cSrcweir 		pSortArray[j].pPair = GetObject( j );
675cdf0e10cSrcweir 		pSortArray[j].pDoc = pDoc;
676cdf0e10cSrcweir 	}
677cdf0e10cSrcweir #if !(defined(ICC ) && defined(OS2))
678cdf0e10cSrcweir 	qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare );
679cdf0e10cSrcweir #else
680cdf0e10cSrcweir 	qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), ICCQsortRPairCompare );
681cdf0e10cSrcweir #endif
682cdf0e10cSrcweir 	// ScRangePair Pointer aufruecken
683cdf0e10cSrcweir 	ScRangePair** ppSortArray = (ScRangePair**)pSortArray;
684cdf0e10cSrcweir 	for ( j=0; j < nListCount; j++ )
685cdf0e10cSrcweir 	{
686cdf0e10cSrcweir 		ppSortArray[j] = pSortArray[j].pPair;
687cdf0e10cSrcweir 	}
688cdf0e10cSrcweir 	return ppSortArray;
689cdf0e10cSrcweir }
690cdf0e10cSrcweir 
691cdf0e10cSrcweir 
692cdf0e10cSrcweir 
693cdf0e10cSrcweir 
694