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