Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #define SC_RANGELST_CXX //fuer ICC
30 : :
31 : : #include <stdlib.h> // qsort
32 : : #include <comphelper/string.hxx>
33 : : #include <unotools/collatorwrapper.hxx>
34 : :
35 : : #include "rangelst.hxx"
36 : : #include "document.hxx"
37 : : #include "refupdat.hxx"
38 : : #include "rechead.hxx"
39 : : #include "compiler.hxx"
40 : : #include "stlalgorithm.hxx"
41 : :
42 : : using ::std::vector;
43 : : using ::std::advance;
44 : : using ::std::find_if;
45 : : using ::std::for_each;
46 : : using ::formula::FormulaGrammar;
47 : :
48 : : namespace {
49 : :
50 : : template<typename T>
51 : : class FindEnclosingRange : public ::std::unary_function<bool, ScRange*>
52 : : {
53 : : public:
54 : 3578 : FindEnclosingRange(const T& rTest) : mrTest(rTest) {}
55 : 3578 : FindEnclosingRange(const FindEnclosingRange& r) : mrTest(r.mrTest) {}
56 : 3779 : bool operator() (const ScRange* pRange) const
57 : : {
58 : 3779 : return pRange->In(mrTest);
59 : : }
60 : : private:
61 : : const T& mrTest;
62 : : };
63 : :
64 : : template<typename T>
65 : : class FindIntersectingRange : public ::std::unary_function<bool, ScRange*>
66 : : {
67 : : public:
68 : 0 : FindIntersectingRange(const T& rTest) : mrTest(rTest) {}
69 : 0 : FindIntersectingRange(const FindIntersectingRange& r) : mrTest(r.mrTest) {}
70 : 0 : bool operator() (const ScRange* pRange) const
71 : : {
72 : 0 : return pRange->Intersects(mrTest);
73 : : }
74 : : private:
75 : : const T& mrTest;
76 : : };
77 : :
78 : : class AppendToList : public ::std::unary_function<void, const ScRange*>
79 : : {
80 : : public:
81 : 5888 : AppendToList(vector<ScRange*>& rRanges) : mrRanges(rRanges) {}
82 : 5888 : AppendToList(const AppendToList& r) : mrRanges(r.mrRanges) {}
83 : 5210 : void operator() (const ScRange* p)
84 : : {
85 [ + - ]: 5210 : mrRanges.push_back(new ScRange(*p));
86 : 5210 : }
87 : : private:
88 : : vector<ScRange*>& mrRanges;
89 : : };
90 : :
91 : : class CountCells : public ::std::unary_function<void, const ScRange*>
92 : : {
93 : : public:
94 : 0 : CountCells() : mnCellCount(0) {}
95 : 0 : CountCells(const CountCells& r) : mnCellCount(r.mnCellCount) {}
96 : :
97 : 0 : void operator() (const ScRange* p)
98 : : {
99 : : mnCellCount +=
100 : 0 : size_t(p->aEnd.Col() - p->aStart.Col() + 1)
101 : 0 : * size_t(p->aEnd.Row() - p->aStart.Row() + 1)
102 : 0 : * size_t(p->aEnd.Tab() - p->aStart.Tab() + 1);
103 : 0 : }
104 : :
105 : 0 : size_t getCellCount() const { return mnCellCount; }
106 : :
107 : : private:
108 : : size_t mnCellCount;
109 : : };
110 : :
111 : : class FormatString : public ::std::unary_function<void, const ScRange*>
112 : : {
113 : : public:
114 : 356 : FormatString(String& rStr, sal_uInt16 nFlags, ScDocument* pDoc, FormulaGrammar::AddressConvention eConv, sal_Unicode cDelim) :
115 : : mrStr(rStr),
116 : : mnFlags(nFlags),
117 : : mpDoc(pDoc),
118 : : meConv(eConv),
119 : : mcDelim(cDelim),
120 : 356 : mbFirst(true) {}
121 : :
122 : 712 : FormatString(const FormatString& r) :
123 : : mrStr(r.mrStr),
124 : : mnFlags(r.mnFlags),
125 : : mpDoc(r.mpDoc),
126 : : meConv(r.meConv),
127 : : mcDelim(r.mcDelim),
128 : 712 : mbFirst(r.mbFirst) {}
129 : :
130 : 500 : void operator() (const ScRange* p)
131 : : {
132 [ + - ]: 500 : String aStr;
133 [ + - ]: 500 : p->Format(aStr, mnFlags, mpDoc, meConv);
134 [ + + ]: 500 : if (mbFirst)
135 : 352 : mbFirst = false;
136 : : else
137 [ + - ]: 148 : mrStr += mcDelim;
138 [ + - ][ + - ]: 500 : mrStr += aStr;
139 : 500 : }
140 : : private:
141 : : String& mrStr;
142 : : sal_uInt16 mnFlags;
143 : : ScDocument* mpDoc;
144 : : FormulaGrammar::AddressConvention meConv;
145 : : sal_Unicode mcDelim;
146 : : bool mbFirst;
147 : : };
148 : :
149 : : class FindDeletedRange : public ::std::unary_function<bool, const ScRange*>
150 : : {
151 : : public:
152 : 124 : FindDeletedRange( SCsCOL nDx, SCsROW nDy): mnDx(nDx), mnDy(nDy) {}
153 : 248 : FindDeletedRange( const FindDeletedRange& r) : mnDx(r.mnDx), mnDy(r.mnDy) {}
154 : 124 : bool operator() (const ScRange* p)
155 : : {
156 : 124 : ScAddress rStart = p->aStart;
157 : 124 : ScAddress rEnd = p->aEnd;
158 : :
159 [ + + ]: 124 : if( rEnd.Col() +mnDx < rStart.Col() )
160 : 86 : return true;
161 [ + + ]: 38 : if( rEnd.Row() + mnDy < rStart.Row() )
162 : 27 : return true;
163 : :
164 : 124 : return false;
165 : : }
166 : :
167 : : private:
168 : : SCsCOL mnDx;
169 : : SCsROW mnDy;
170 : : };
171 : :
172 : : }
173 : :
174 : : // === ScRangeList ====================================================
175 : :
176 : 53532 : ScRangeList::~ScRangeList()
177 : : {
178 [ + - ]: 53532 : RemoveAll();
179 [ - + ]: 55530 : }
180 : :
181 : 95 : sal_uInt16 ScRangeList::Parse( const String& rStr, ScDocument* pDoc, sal_uInt16 nMask,
182 : : formula::FormulaGrammar::AddressConvention eConv,
183 : : sal_Unicode cDelimiter )
184 : : {
185 [ + - ]: 95 : if ( rStr.Len() )
186 : : {
187 [ + - ]: 95 : if (!cDelimiter)
188 [ + - ]: 95 : cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
189 : :
190 : 95 : nMask |= SCA_VALID; // falls das jemand vergessen sollte
191 : 95 : sal_uInt16 nResult = (sal_uInt16)~0; // alle Bits setzen
192 : 95 : ScRange aRange;
193 [ + - ]: 95 : String aOne;
194 : 95 : SCTAB nTab = 0;
195 [ - + ]: 95 : if ( pDoc )
196 : : {
197 : : //! erste markierte Tabelle gibts nicht mehr am Dokument
198 : : //! -> uebergeben? oder spaeter an den Ranges setzen
199 : : }
200 : : else
201 : 0 : nTab = 0;
202 [ + - ][ + - ]: 95 : sal_uInt16 nTCount = comphelper::string::getTokenCount(rStr, cDelimiter);
203 [ + + ]: 190 : for ( sal_uInt16 i=0; i<nTCount; i++ )
204 : : {
205 [ + - ][ + - ]: 95 : aOne = rStr.GetToken( i, cDelimiter );
[ + - ]
206 : 95 : aRange.aStart.SetTab( nTab ); // Default Tab wenn nicht angegeben
207 [ + - ]: 95 : sal_uInt16 nRes = aRange.ParseAny( aOne, pDoc, eConv );
208 : 95 : sal_uInt16 nEndRangeBits = SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2;
209 : 95 : sal_uInt16 nTmp1 = ( nRes & SCA_BITS );
210 : 95 : sal_uInt16 nTmp2 = ( nRes & nEndRangeBits );
211 : : // If we have a valid single range with
212 : : // any of the address bits we are interested in
213 : : // set - set the equiv end range bits
214 [ + + ][ + - ]: 95 : if ( (nRes & SCA_VALID ) && nTmp1 && ( nTmp2 != nEndRangeBits ) )
[ + + ]
215 : 22 : nRes |= ( nTmp1 << 4 );
216 : :
217 [ + + ]: 95 : if ( (nRes & nMask) == nMask )
218 [ + - ]: 87 : Append( aRange );
219 : 95 : nResult &= nRes; // alle gemeinsamen Bits bleiben erhalten
220 : : }
221 [ + - ]: 95 : return nResult; // SCA_VALID gesetzt wenn alle ok
222 : : }
223 : : else
224 : 95 : return 0;
225 : : }
226 : :
227 : :
228 : 350 : void ScRangeList::Format( String& rStr, sal_uInt16 nFlags, ScDocument* pDoc,
229 : : formula::FormulaGrammar::AddressConvention eConv,
230 : : sal_Unicode cDelimiter ) const
231 : : {
232 [ + - ]: 350 : rStr.Erase();
233 : :
234 [ + - ]: 350 : if (!cDelimiter)
235 [ + - ]: 350 : cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
236 : :
237 : 350 : FormatString func(rStr, nFlags, pDoc, eConv, cDelimiter);
238 [ + - ]: 350 : for_each(maRanges.begin(), maRanges.end(), func);
239 : 350 : }
240 : :
241 : :
242 : 6 : void ScRangeList::Format( rtl::OUString& rStr, sal_uInt16 nFlags, ScDocument* pDoc,
243 : : formula::FormulaGrammar::AddressConvention eConv,
244 : : sal_Unicode cDelimiter ) const
245 : : {
246 : :
247 [ + - ]: 6 : if (!cDelimiter)
248 [ + - ]: 6 : cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
249 : :
250 [ + - ]: 6 : String aStr;
251 : 6 : FormatString func(aStr, nFlags, pDoc, eConv, cDelimiter);
252 [ + - ]: 6 : for_each(maRanges.begin(), maRanges.end(), func);
253 [ + - ][ + - ]: 6 : rStr = aStr;
254 : 6 : }
255 : :
256 : :
257 : 10233 : void ScRangeList::Join( const ScRange& r, bool bIsInList )
258 : : {
259 [ + + ]: 10233 : if ( maRanges.empty() )
260 : : {
261 : 321 : Append( r );
262 : 10233 : return ;
263 : : }
264 : 9912 : SCCOL nCol1 = r.aStart.Col();
265 : 9912 : SCROW nRow1 = r.aStart.Row();
266 : 9912 : SCTAB nTab1 = r.aStart.Tab();
267 : 9912 : SCCOL nCol2 = r.aEnd.Col();
268 : 9912 : SCROW nRow2 = r.aEnd.Row();
269 : 9912 : SCTAB nTab2 = r.aEnd.Tab();
270 : :
271 : 9912 : ScRange* pOver = (ScRange*) &r; // fies aber wahr wenn bInList
272 : 9912 : size_t nOldPos = 0;
273 [ + + ]: 9912 : if ( bIsInList )
274 : : {
275 : : // Find the current position of this range.
276 [ + - ]: 2529 : for ( size_t i = 0, nRanges = maRanges.size(); i < nRanges; ++i )
277 : : {
278 [ + + ]: 1310 : if ( maRanges[i] == pOver )
279 : : {
280 : 1219 : nOldPos = i;
281 : 1219 : break;
282 : : }
283 : : }
284 : : }
285 : 9912 : bool bJoinedInput = false;
286 : :
287 : : // We need to query the size of the container dynamically since its size
288 : : // may change during the loop.
289 [ + + ][ + + ]: 14061 : for ( size_t i = 0; i < maRanges.size() && pOver; ++i )
[ + + ]
290 : : {
291 : 11400 : ScRange* p = maRanges[i];
292 [ + + ]: 11400 : if ( p == pOver )
293 : 1207 : continue; // derselbe, weiter mit dem naechsten
294 : 10193 : bool bJoined = false;
295 [ + + ]: 10193 : if ( p->In( r ) )
296 : : { // Range r in Range p enthalten oder identisch
297 [ - + ]: 7251 : if ( bIsInList )
298 : 0 : bJoined = true; // weg mit Range r
299 : : else
300 : : { // das war's dann
301 : 7251 : bJoinedInput = true; // nicht anhaengen
302 : 7251 : break; // for
303 : : }
304 : : }
305 [ + + ]: 2942 : else if ( r.In( *p ) )
306 : : { // Range p in Range r enthalten, r zum neuen Range machen
307 : 3 : *p = r;
308 : 3 : bJoined = true;
309 : : }
310 [ + + ][ + + ]: 2942 : if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 )
[ + - ][ + + ]
311 : : { // 2D
312 [ + + ][ + + ]: 1663 : if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 )
[ + + ]
313 : : {
314 [ - + ]: 63 : if ( p->aStart.Row() == nRow2+1 )
315 : : { // oben
316 : 0 : p->aStart.SetRow( nRow1 );
317 : 0 : bJoined = true;
318 : : }
319 [ + + ]: 63 : else if ( p->aEnd.Row() == nRow1-1 )
320 : : { // unten
321 : 51 : p->aEnd.SetRow( nRow2 );
322 : 51 : bJoined = true;
323 : : }
324 : : }
325 [ + + ][ + + ]: 1600 : else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 )
[ + + ]
326 : : {
327 [ - + ]: 1175 : if ( p->aStart.Col() == nCol2+1 )
328 : : { // links
329 : 0 : p->aStart.SetCol( nCol1 );
330 : 0 : bJoined = true;
331 : : }
332 [ + + ]: 1175 : else if ( p->aEnd.Col() == nCol1-1 )
333 : : { // rechts
334 : 1165 : p->aEnd.SetCol( nCol2 );
335 : 1165 : bJoined = true;
336 : : }
337 : : }
338 : : }
339 [ + + ]: 2942 : if ( bJoined )
340 : : {
341 [ + + ]: 1219 : if ( bIsInList )
342 : : { // innerhalb der Liste Range loeschen
343 : 12 : Remove(nOldPos);
344 : 12 : i--;
345 : 12 : delete pOver;
346 : 12 : pOver = NULL;
347 [ + - ]: 12 : if ( nOldPos )
348 : 12 : nOldPos--; // Seek richtig aufsetzen
349 : : }
350 : 1219 : bJoinedInput = true;
351 : 1219 : Join( *p, true ); // rekursiv!
352 : : }
353 : : }
354 [ + + ][ + + ]: 9912 : if ( !bIsInList && !bJoinedInput )
355 : 235 : Append( r );
356 : : }
357 : :
358 : :
359 : 2 : bool ScRangeList::operator==( const ScRangeList& r ) const
360 : : {
361 [ - + ]: 2 : if ( this == &r )
362 : 0 : return true;
363 : :
364 [ - + ]: 2 : if (maRanges.size() != r.maRanges.size())
365 : 0 : return false;
366 : :
367 : 2 : vector<ScRange*>::const_iterator itr1 = maRanges.begin(), itrEnd = maRanges.end();
368 : 2 : vector<ScRange*>::const_iterator itr2 = r.maRanges.begin();
369 [ + - ][ + - ]: 2 : for (; itr1 != itrEnd; ++itr1, ++itr2)
370 : : {
371 : 2 : const ScRange* p1 = *itr1;
372 : 2 : const ScRange* p2 = *itr2;
373 [ + - ]: 2 : if (*p1 != *p2)
374 : 2 : return false;
375 : : }
376 : 2 : return true;
377 : : }
378 : :
379 : 2 : bool ScRangeList::operator!=( const ScRangeList& r ) const
380 : : {
381 : 2 : return !operator==( r );
382 : : }
383 : :
384 : 3043 : bool ScRangeList::UpdateReference(
385 : : UpdateRefMode eUpdateRefMode,
386 : : ScDocument* pDoc,
387 : : const ScRange& rWhere,
388 : : SCsCOL nDx,
389 : : SCsROW nDy,
390 : : SCsTAB nDz
391 : : )
392 : : {
393 [ + + ]: 3043 : if (maRanges.empty())
394 : : // No ranges to update. Bail out.
395 : 155 : return false;
396 : :
397 : 2888 : bool bChanged = false;
398 : : SCCOL nCol1;
399 : : SCROW nRow1;
400 : : SCTAB nTab1;
401 : : SCCOL nCol2;
402 : : SCROW nRow2;
403 : : SCTAB nTab2;
404 : 2888 : rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
405 : :
406 : : // delete all entries that are fully deleted
407 [ + + ][ + + ]: 2888 : if( eUpdateRefMode == URM_INSDEL && (nDx < 0 || nDy < 0) )
[ + - ]
408 : : {
409 [ + - ]: 124 : vector<ScRange*>::iterator itr = std::remove_if(maRanges.begin(), maRanges.end(), FindDeletedRange(nDx, nDy));
410 [ + - ]: 124 : for_each(itr, maRanges.end(), ScDeleteObjectByPtr<ScRange>());
411 [ + - ]: 124 : maRanges.erase(itr, maRanges.end());
412 : : }
413 : :
414 : 2888 : vector<ScRange*>::iterator itr = maRanges.begin(), itrEnd = maRanges.end();
415 [ + - ][ + + ]: 5663 : for (; itr != itrEnd; ++itr)
416 : : {
417 : 2775 : ScRange* pR = *itr;
418 : : SCCOL theCol1;
419 : : SCROW theRow1;
420 : : SCTAB theTab1;
421 : : SCCOL theCol2;
422 : : SCROW theRow2;
423 : : SCTAB theTab2;
424 : 2775 : pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
425 [ + + ]: 2775 : if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
426 : : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
427 : : nDx, nDy, nDz,
428 [ + - ]: 2775 : theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
429 : : != UR_NOTHING )
430 : : {
431 : 2723 : bChanged = true;
432 : 2723 : pR->aStart.Set( theCol1, theRow1, theTab1 );
433 : 2723 : pR->aEnd.Set( theCol2, theRow2, theTab2 );
434 : : }
435 : : }
436 : 3043 : return bChanged;
437 : : }
438 : :
439 : 126 : const ScRange* ScRangeList::Find( const ScAddress& rAdr ) const
440 : : {
441 : : vector<ScRange*>::const_iterator itr = find_if(
442 [ + - ]: 126 : maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr));
443 [ + - ][ + - ]: 126 : return itr == maRanges.end() ? NULL : *itr;
444 : : }
445 : :
446 : 84 : ScRange* ScRangeList::Find( const ScAddress& rAdr )
447 : : {
448 : : vector<ScRange*>::iterator itr = find_if(
449 [ + - ]: 84 : maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr));
450 [ + - ][ + + ]: 84 : return itr == maRanges.end() ? NULL : *itr;
451 : : }
452 : :
453 [ + - ]: 35896 : ScRangeList::ScRangeList() {}
454 : :
455 : 5783 : ScRangeList::ScRangeList( const ScRangeList& rList ) :
456 [ + - ]: 5783 : SvRefBase()
457 : : {
458 [ + - ]: 5783 : maRanges.reserve(rList.maRanges.size());
459 [ + - ]: 5783 : for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges));
460 : 5783 : }
461 : :
462 [ + - ]: 11917 : ScRangeList::ScRangeList( const ScRange& rRange )
463 : : {
464 [ + - ]: 11917 : maRanges.reserve(1);
465 [ + - ]: 11917 : Append(rRange);
466 : 11917 : }
467 : :
468 : 105 : ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
469 : : {
470 : 105 : RemoveAll();
471 : 105 : maRanges.reserve(rList.maRanges.size());
472 [ + - ]: 105 : for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges));
473 : 105 : return *this;
474 : : }
475 : :
476 : 41853 : void ScRangeList::Append( const ScRange& rRange )
477 : : {
478 [ + - ]: 41853 : ScRange* pR = new ScRange( rRange );
479 [ + - ]: 41853 : maRanges.push_back( pR );
480 : 41853 : }
481 : :
482 : 0 : bool ScRangeList::Intersects( const ScRange& rRange ) const
483 : : {
484 : 0 : vector<ScRange*>::const_iterator itrEnd = maRanges.end();
485 : : vector<ScRange*>::const_iterator itr =
486 [ # # ]: 0 : find_if(maRanges.begin(), itrEnd, FindIntersectingRange<ScRange>(rRange));
487 [ # # ]: 0 : return itr != itrEnd;
488 : : }
489 : :
490 : 3368 : bool ScRangeList::In( const ScRange& rRange ) const
491 : : {
492 : 3368 : vector<ScRange*>::const_iterator itrEnd = maRanges.end();
493 : : vector<ScRange*>::const_iterator itr =
494 [ + - ]: 3368 : find_if(maRanges.begin(), itrEnd, FindEnclosingRange<ScRange>(rRange));
495 [ + - ]: 3368 : return itr != itrEnd;
496 : : }
497 : :
498 : :
499 : 0 : size_t ScRangeList::GetCellCount() const
500 : : {
501 : 0 : CountCells func;
502 [ # # ]: 0 : return for_each(maRanges.begin(), maRanges.end(), func).getCellCount();
503 : : }
504 : :
505 : 12 : ScRange* ScRangeList::Remove(size_t nPos)
506 : : {
507 [ - + ]: 12 : if (maRanges.size() <= nPos)
508 : : // Out-of-bound condition. Bail out.
509 : 0 : return NULL;
510 : :
511 : 12 : vector<ScRange*>::iterator itr = maRanges.begin();
512 [ + - ]: 12 : advance(itr, nPos);
513 : 12 : ScRange* p = *itr;
514 [ + - ]: 12 : maRanges.erase(itr);
515 : 12 : return p;
516 : : }
517 : :
518 : 54272 : void ScRangeList::RemoveAll()
519 : : {
520 [ + - ]: 54272 : for_each(maRanges.begin(), maRanges.end(), ScDeleteObjectByPtr<ScRange>());
521 : 54272 : maRanges.clear();
522 : 54272 : }
523 : :
524 : 11869 : ScRange ScRangeList::Combine() const
525 : : {
526 [ + + ]: 11869 : if (maRanges.empty())
527 : 6438 : return ScRange();
528 : :
529 : 5431 : vector<ScRange*>::const_iterator itr = maRanges.begin(), itrEnd = maRanges.end();
530 : 5431 : ScRange aRet = **itr;
531 : 5431 : ++itr;
532 [ + - ][ - + ]: 5431 : for (; itr != itrEnd; ++itr)
533 : : {
534 : 0 : const ScRange& r = **itr;
535 : 0 : SCROW nRow1 = r.aStart.Row(), nRow2 = r.aEnd.Row();
536 : 0 : SCCOL nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
537 : 0 : SCTAB nTab1 = r.aStart.Tab(), nTab2 = r.aEnd.Tab();
538 [ # # ]: 0 : if (aRet.aStart.Row() > nRow1)
539 : 0 : aRet.aStart.SetRow(nRow1);
540 [ # # ]: 0 : if (aRet.aStart.Col() > nCol1)
541 : 0 : aRet.aStart.SetCol(nCol1);
542 [ # # ]: 0 : if (aRet.aStart.Tab() > nTab1)
543 : 0 : aRet.aStart.SetTab(nTab1);
544 [ # # ]: 0 : if (aRet.aEnd.Row() < nRow2)
545 : 0 : aRet.aEnd.SetRow(nRow2);
546 [ # # ]: 0 : if (aRet.aEnd.Col() < nCol2)
547 : 0 : aRet.aEnd.SetCol(nCol2);
548 [ # # ]: 0 : if (aRet.aEnd.Tab() < nTab2)
549 : 0 : aRet.aEnd.SetTab(nTab2);
550 : : }
551 : 11869 : return aRet;
552 : : }
553 : :
554 : 16055 : bool ScRangeList::empty() const
555 : : {
556 : 16055 : return maRanges.empty();
557 : : }
558 : :
559 : 23630 : size_t ScRangeList::size() const
560 : : {
561 : 23630 : return maRanges.size();
562 : : }
563 : :
564 : 7260 : ScRange* ScRangeList::operator [](size_t idx)
565 : : {
566 : 7260 : return maRanges[idx];
567 : : }
568 : :
569 : 21028 : const ScRange* ScRangeList::operator [](size_t idx) const
570 : : {
571 : 21028 : return maRanges[idx];
572 : : }
573 : :
574 : 894 : ScRange* ScRangeList::front()
575 : : {
576 : 894 : return maRanges.front();
577 : : }
578 : :
579 : 0 : const ScRange* ScRangeList::front() const
580 : : {
581 : 0 : return maRanges.front();
582 : : }
583 : :
584 : 0 : ScRange* ScRangeList::back()
585 : : {
586 : 0 : return maRanges.back();
587 : : }
588 : :
589 : 0 : const ScRange* ScRangeList::back() const
590 : : {
591 : 0 : return maRanges.back();
592 : : }
593 : :
594 : 219 : void ScRangeList::push_back(ScRange* p)
595 : : {
596 : 219 : maRanges.push_back(p);
597 : 219 : }
598 : :
599 : : // === ScRangePairList ========================================================
600 : :
601 : 3229 : ScRangePairList::~ScRangePairList()
602 : : {
603 [ + - ]: 3229 : for_each( maPairs.begin(), maPairs.end(), ScDeleteObjectByPtr<ScRangePair>() );
604 : 3229 : maPairs.clear();
605 [ - + ]: 6458 : }
606 : :
607 : : //-----------------------------------------------------------------------------
608 : 0 : ScRangePair* ScRangePairList::Remove(size_t nPos)
609 : : {
610 [ # # ]: 0 : if (maPairs.size() <= nPos)
611 : : // Out-of-bound condition. Bail out.
612 : 0 : return NULL;
613 : :
614 : 0 : vector<ScRangePair*>::iterator itr = maPairs.begin();
615 [ # # ]: 0 : advance(itr, nPos);
616 : 0 : ScRangePair* p = *itr;
617 [ # # ]: 0 : maPairs.erase(itr);
618 : 0 : return p;
619 : : }
620 : :
621 : : //-----------------------------------------------------------------------------
622 : 3 : ScRangePair* ScRangePairList::Remove( ScRangePair* Adr)
623 : : {
624 : 3 : ScRangePair* p = NULL;
625 : :
626 [ - + ]: 3 : if (Adr == NULL) return NULL;
627 : :
628 [ + - ][ + - ]: 4 : for ( vector<ScRangePair*>::iterator itr = maPairs.begin(); itr < maPairs.end(); ++itr )
629 : : {
630 [ + + ]: 4 : if ( Adr == (p = *itr) )
631 : : {
632 [ + - ]: 3 : maPairs.erase( itr );
633 : 3 : break;
634 : : }
635 : : }
636 : 3 : return p;
637 : : }
638 : :
639 : 0 : bool ScRangePairList::operator==( const ScRangePairList& r ) const
640 : : {
641 [ # # ]: 0 : if ( this == &r )
642 : 0 : return true; // identische Referenz
643 [ # # ]: 0 : if ( maPairs.size() != r.size() )
644 : 0 : return false;
645 [ # # ]: 0 : for ( size_t nIdx = 0, nCnt = maPairs.size(); nIdx < nCnt; ++nIdx )
646 : : {
647 [ # # ]: 0 : if ( *maPairs[ nIdx ] != *r[ nIdx ] )
648 : 0 : return false; // auch andere Reihenfolge ist ungleich
649 : : }
650 : 0 : return true;
651 : : }
652 : :
653 : 6 : ScRangePair* ScRangePairList::operator [](size_t idx)
654 : : {
655 : 6 : return maPairs[idx];
656 : : }
657 : :
658 : 0 : const ScRangePair* ScRangePairList::operator [](size_t idx) const
659 : : {
660 : 0 : return maPairs[idx];
661 : : }
662 : :
663 : 133 : size_t ScRangePairList::size() const
664 : : {
665 : 133 : return maPairs.size();
666 : : }
667 : :
668 : 472 : bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode,
669 : : ScDocument* pDoc, const ScRange& rWhere,
670 : : SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
671 : : {
672 : 472 : bool bChanged = false;
673 [ - + ]: 472 : if ( !maPairs.empty() )
674 : : {
675 : : SCCOL nCol1;
676 : : SCROW nRow1;
677 : : SCTAB nTab1;
678 : : SCCOL nCol2;
679 : : SCROW nRow2;
680 : : SCTAB nTab2;
681 : 0 : rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
682 [ # # ]: 0 : for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i )
683 : : {
684 : 0 : ScRangePair* pR = maPairs[ i ];
685 [ # # ]: 0 : for ( sal_uInt16 j=0; j<2; j++ )
686 : : {
687 : 0 : ScRange& rRange = pR->GetRange(j);
688 : : SCCOL theCol1;
689 : : SCROW theRow1;
690 : : SCTAB theTab1;
691 : : SCCOL theCol2;
692 : : SCROW theRow2;
693 : : SCTAB theTab2;
694 : 0 : rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
695 [ # # ]: 0 : if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
696 : : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
697 : : nDx, nDy, nDz,
698 [ # # ]: 0 : theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
699 : : != UR_NOTHING )
700 : : {
701 : 0 : bChanged = true;
702 : 0 : rRange.aStart.Set( theCol1, theRow1, theTab1 );
703 : 0 : rRange.aEnd.Set( theCol2, theRow2, theTab2 );
704 : : }
705 : : }
706 : : }
707 : : }
708 : 472 : return bChanged;
709 : : }
710 : :
711 : : //-----------------------------------------------------------------------------
712 : : // Delete entries that have the labels (first range) on nTab
713 : 230 : void ScRangePairList::DeleteOnTab( SCTAB nTab )
714 : : {
715 : 230 : size_t nListCount = maPairs.size();
716 : 230 : size_t nPos = 0;
717 [ - + ]: 230 : while ( nPos < nListCount )
718 : : {
719 : 0 : ScRangePair* pR = maPairs[ nPos ];
720 : 0 : ScRange aRange = pR->GetRange(0);
721 [ # # ][ # # ]: 0 : if ( aRange.aStart.Tab() == nTab && aRange.aEnd.Tab() == nTab )
[ # # ]
722 : : {
723 [ # # ]: 0 : Remove( nPos );
724 : 0 : delete pR;
725 : 0 : nListCount = maPairs.size();
726 : : }
727 : : else
728 : 0 : ++nPos;
729 : : }
730 : 230 : }
731 : :
732 : : //-----------------------------------------------------------------------------
733 : 0 : ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const
734 : : {
735 [ # # ]: 0 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
736 : : {
737 : 0 : ScRangePair* pR = maPairs[ j ];
738 [ # # ]: 0 : if ( pR->GetRange(0).In( rAdr ) )
739 : 0 : return pR;
740 : : }
741 : 0 : return NULL;
742 : : }
743 : :
744 : : //-----------------------------------------------------------------------------
745 : 4 : ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const
746 : : {
747 [ + - ]: 4 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
748 : : {
749 : 4 : ScRangePair* pR = maPairs[ j ];
750 [ + - ]: 4 : if ( pR->GetRange(0) == rRange )
751 : 4 : return pR;
752 : : }
753 : 4 : return NULL;
754 : : }
755 : :
756 : :
757 : : //-----------------------------------------------------------------------------
758 : 7 : ScRangePairList* ScRangePairList::Clone() const
759 : : {
760 [ + - ]: 7 : ScRangePairList* pNew = new ScRangePairList;
761 [ + + ]: 12 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
762 : : {
763 : 5 : pNew->Append( *maPairs[ j ] );
764 : : }
765 : 7 : return pNew;
766 : : }
767 : :
768 : : //-----------------------------------------------------------------------------
769 : : struct ScRangePairNameSort
770 : : {
771 : : ScRangePair* pPair;
772 : : ScDocument* pDoc;
773 : : };
774 : :
775 : : //-----------------------------------------------------------------------------
776 : : extern "C"
777 : 0 : int SAL_CALL ScRangePairList_QsortNameCompare( const void* p1, const void* p2 )
778 : : {
779 : 0 : const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1;
780 : 0 : const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2;
781 : 0 : const ScAddress& rStartPos1 = ps1->pPair->GetRange(0).aStart;
782 : 0 : const ScAddress& rStartPos2 = ps2->pPair->GetRange(0).aStart;
783 : 0 : rtl::OUString aStr1, aStr2;
784 : : sal_Int32 nComp;
785 [ # # ]: 0 : if ( rStartPos1.Tab() == rStartPos2.Tab() )
786 : 0 : nComp = COMPARE_EQUAL;
787 : : else
788 : : {
789 [ # # ]: 0 : ps1->pDoc->GetName( rStartPos1.Tab(), aStr1 );
790 [ # # ]: 0 : ps2->pDoc->GetName( rStartPos2.Tab(), aStr2 );
791 [ # # ][ # # ]: 0 : nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
792 : : }
793 [ # # # ]: 0 : switch ( nComp )
794 : : {
795 : : case COMPARE_LESS:
796 : 0 : return -1;
797 : : //break;
798 : : case COMPARE_GREATER:
799 : 0 : return 1;
800 : : //break;
801 : : default:
802 : : // gleiche Tabs
803 [ # # ]: 0 : if ( rStartPos1.Col() < rStartPos2.Col() )
804 : 0 : return -1;
805 [ # # ]: 0 : if ( rStartPos1.Col() > rStartPos2.Col() )
806 : 0 : return 1;
807 : : // gleiche Cols
808 [ # # ]: 0 : if ( rStartPos1.Row() < rStartPos2.Row() )
809 : 0 : return -1;
810 [ # # ]: 0 : if ( rStartPos1.Row() > rStartPos2.Row() )
811 : 0 : return 1;
812 : : // erste Ecke gleich, zweite Ecke
813 : : {
814 : 0 : const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd;
815 : 0 : const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd;
816 [ # # ]: 0 : if ( rEndPos1.Tab() == rEndPos2.Tab() )
817 : 0 : nComp = COMPARE_EQUAL;
818 : : else
819 : : {
820 [ # # ]: 0 : ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 );
821 [ # # ]: 0 : ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 );
822 [ # # ][ # # ]: 0 : nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
823 : : }
824 [ # # # ]: 0 : switch ( nComp )
825 : : {
826 : : case COMPARE_LESS:
827 : 0 : return -1;
828 : : //break;
829 : : case COMPARE_GREATER:
830 : 0 : return 1;
831 : : //break;
832 : : default:
833 : : // gleiche Tabs
834 [ # # ]: 0 : if ( rEndPos1.Col() < rEndPos2.Col() )
835 : 0 : return -1;
836 [ # # ]: 0 : if ( rEndPos1.Col() > rEndPos2.Col() )
837 : 0 : return 1;
838 : : // gleiche Cols
839 [ # # ]: 0 : if ( rEndPos1.Row() < rEndPos2.Row() )
840 : 0 : return -1;
841 [ # # ]: 0 : if ( rEndPos1.Row() > rEndPos2.Row() )
842 : 0 : return 1;
843 : 0 : return 0;
844 : : }
845 : : }
846 : : }
847 : : #ifndef _MSC_VER // MSVC is good enough to warn about unreachable code here.
848 : : // Or stupid enough to bother warning about it, depending
849 : : // on your point of view.
850 : 0 : return 0; // just in case
851 : : #endif
852 : : }
853 : :
854 : : //-----------------------------------------------------------------------------
855 : 6 : void ScRangePairList::Join( const ScRangePair& r, bool bIsInList )
856 : : {
857 [ + + ]: 6 : if ( maPairs.empty() )
858 : : {
859 : 5 : Append( r );
860 : 6 : return ;
861 : : }
862 : 1 : const ScRange& r1 = r.GetRange(0);
863 : 1 : const ScRange& r2 = r.GetRange(1);
864 : 1 : SCCOL nCol1 = r1.aStart.Col();
865 : 1 : SCROW nRow1 = r1.aStart.Row();
866 : 1 : SCTAB nTab1 = r1.aStart.Tab();
867 : 1 : SCCOL nCol2 = r1.aEnd.Col();
868 : 1 : SCROW nRow2 = r1.aEnd.Row();
869 : 1 : SCTAB nTab2 = r1.aEnd.Tab();
870 : 1 : ScRangePair* pOver = (ScRangePair*) &r; // fies aber wahr wenn bInList
871 : 1 : size_t nOldPos = 0;
872 [ - + ]: 1 : if ( bIsInList )
873 : : {
874 : : // Find the current position of this range.
875 [ # # ]: 0 : for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i )
876 : : {
877 [ # # ]: 0 : if ( maPairs[i] == pOver )
878 : : {
879 : 0 : nOldPos = i;
880 : 0 : break;
881 : : }
882 : : }
883 : : }
884 : 1 : bool bJoinedInput = false;
885 : :
886 [ + + ][ + - ]: 2 : for ( size_t i = 0; i < maPairs.size() && pOver; ++i )
[ + + ]
887 : : {
888 : 1 : ScRangePair* p = maPairs[ i ];
889 [ - + ]: 1 : if ( p == pOver )
890 : 0 : continue; // derselbe, weiter mit dem naechsten
891 : 1 : bool bJoined = false;
892 : 1 : ScRange& rp1 = p->GetRange(0);
893 : 1 : ScRange& rp2 = p->GetRange(1);
894 [ - + ]: 1 : if ( rp2 == r2 )
895 : : { // nur wenn Range2 gleich ist
896 [ # # ]: 0 : if ( rp1.In( r1 ) )
897 : : { // RangePair r in RangePair p enthalten oder identisch
898 [ # # ]: 0 : if ( bIsInList )
899 : 0 : bJoined = true; // weg mit RangePair r
900 : : else
901 : : { // das war's dann
902 : 0 : bJoinedInput = true; // nicht anhaengen
903 : 0 : break; // for
904 : : }
905 : : }
906 [ # # ]: 0 : else if ( r1.In( rp1 ) )
907 : : { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen
908 : 0 : *p = r;
909 : 0 : bJoined = true;
910 : : }
911 : : }
912 [ + - ][ + - ]: 3 : if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2
[ + - + -
+ - ][ + - ]
913 : 1 : && rp2.aStart.Tab() == r2.aStart.Tab()
914 : 1 : && rp2.aEnd.Tab() == r2.aEnd.Tab() )
915 : : { // 2D, Range2 muss genauso nebeneinander liegen wie Range1
916 [ - + ][ # # : 1 : if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2
# # # # ]
[ - + ]
917 : 0 : && rp2.aStart.Col() == r2.aStart.Col()
918 : 0 : && rp2.aEnd.Col() == r2.aEnd.Col() )
919 : : {
920 [ # # # # ]: 0 : if ( rp1.aStart.Row() == nRow2+1
[ # # ]
921 : 0 : && rp2.aStart.Row() == r2.aEnd.Row()+1 )
922 : : { // oben
923 : 0 : rp1.aStart.SetRow( nRow1 );
924 : 0 : rp2.aStart.SetRow( r2.aStart.Row() );
925 : 0 : bJoined = true;
926 : : }
927 [ # # # # ]: 0 : else if ( rp1.aEnd.Row() == nRow1-1
[ # # ]
928 : 0 : && rp2.aEnd.Row() == r2.aStart.Row()-1 )
929 : : { // unten
930 : 0 : rp1.aEnd.SetRow( nRow2 );
931 : 0 : rp2.aEnd.SetRow( r2.aEnd.Row() );
932 : 0 : bJoined = true;
933 : : }
934 : : }
935 [ + - ][ - + : 1 : else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2
# # # # ]
[ - + ]
936 : 0 : && rp2.aStart.Row() == r2.aStart.Row()
937 : 0 : && rp2.aEnd.Row() == r2.aEnd.Row() )
938 : : {
939 [ # # # # ]: 0 : if ( rp1.aStart.Col() == nCol2+1
[ # # ]
940 : 0 : && rp2.aStart.Col() == r2.aEnd.Col()+1 )
941 : : { // links
942 : 0 : rp1.aStart.SetCol( nCol1 );
943 : 0 : rp2.aStart.SetCol( r2.aStart.Col() );
944 : 0 : bJoined = true;
945 : : }
946 [ # # # # ]: 0 : else if ( rp1.aEnd.Col() == nCol1-1
[ # # ]
947 : 0 : && rp2.aEnd.Col() == r2.aEnd.Col()-1 )
948 : : { // rechts
949 : 0 : rp1.aEnd.SetCol( nCol2 );
950 : 0 : rp2.aEnd.SetCol( r2.aEnd.Col() );
951 : 0 : bJoined = true;
952 : : }
953 : : }
954 : : }
955 [ - + ]: 1 : if ( bJoined )
956 : : {
957 [ # # ]: 0 : if ( bIsInList )
958 : : { // innerhalb der Liste RangePair loeschen
959 : 0 : Remove( nOldPos );
960 : 0 : i--;
961 : 0 : delete pOver;
962 : 0 : pOver = NULL;
963 [ # # ]: 0 : if ( nOldPos )
964 : 0 : nOldPos--; // Seek richtig aufsetzen
965 : : }
966 : 0 : bJoinedInput = true;
967 : 0 : Join( *p, true ); // rekursiv!
968 : : }
969 : : }
970 [ + - ][ + - ]: 1 : if ( !bIsInList && !bJoinedInput )
971 : 1 : Append( r );
972 : : }
973 : :
974 : : //-----------------------------------------------------------------------------
975 : 0 : ScRangePair** ScRangePairList::CreateNameSortedArray( size_t& nListCount,
976 : : ScDocument* pDoc ) const
977 : : {
978 : 0 : nListCount = maPairs.size();
979 : : OSL_ENSURE( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F,
980 : : "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
981 : : ScRangePairNameSort* pSortArray = (ScRangePairNameSort*)
982 : 0 : new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ];
983 : : sal_uLong j;
984 [ # # ]: 0 : for ( j=0; j < nListCount; j++ )
985 : : {
986 : 0 : pSortArray[j].pPair = maPairs[ j ];
987 : 0 : pSortArray[j].pDoc = pDoc;
988 : : }
989 : 0 : qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare );
990 : : // ScRangePair Pointer aufruecken
991 : 0 : ScRangePair** ppSortArray = (ScRangePair**)pSortArray;
992 [ # # ]: 0 : for ( j=0; j < nListCount; j++ )
993 : : {
994 : 0 : ppSortArray[j] = pSortArray[j].pPair;
995 : : }
996 : 0 : return ppSortArray;
997 : : }
998 : :
999 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|