xref: /trunk/main/sc/source/core/tool/rangelst.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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
10cdf0e10cSrcweir  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
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.
19cdf0e10cSrcweir  *
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 }
690