Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #define SC_RANGELST_CXX //fuer ICC
21 :
22 : #include <stdlib.h> // qsort
23 : #include <comphelper/string.hxx>
24 : #include <unotools/collatorwrapper.hxx>
25 :
26 : #include "rangelst.hxx"
27 : #include "document.hxx"
28 : #include "refupdat.hxx"
29 : #include "rechead.hxx"
30 : #include "compiler.hxx"
31 : #include "stlalgorithm.hxx"
32 :
33 : using ::std::vector;
34 : using ::std::advance;
35 : using ::std::find_if;
36 : using ::std::for_each;
37 : using ::formula::FormulaGrammar;
38 :
39 : namespace {
40 :
41 : template<typename T>
42 : class FindEnclosingRange : public ::std::unary_function<ScRange*, bool>
43 : {
44 : public:
45 1611 : FindEnclosingRange(const T& rTest) : mrTest(rTest) {}
46 1611 : FindEnclosingRange(const FindEnclosingRange& r) : mrTest(r.mrTest) {}
47 1923 : bool operator() (const ScRange* pRange) const
48 : {
49 1923 : return pRange->In(mrTest);
50 : }
51 : private:
52 : const T& mrTest;
53 : };
54 :
55 : template<typename T>
56 : class FindRangeIn : public ::std::unary_function<ScRange*, bool>
57 : {
58 : public:
59 21 : FindRangeIn(const T& rTest) : mrTest(rTest) {}
60 : FindRangeIn(const FindRangeIn& r) : mrTest(r.mrTest) {}
61 21 : bool operator() (const ScRange* pRange) const
62 : {
63 21 : return mrTest.In(*pRange);
64 : }
65 : private:
66 : const T& mrTest;
67 : };
68 :
69 : template<typename T>
70 : class FindIntersectingRange : public ::std::unary_function<ScRange*, bool>
71 : {
72 : public:
73 0 : FindIntersectingRange(const T& rTest) : mrTest(rTest) {}
74 0 : FindIntersectingRange(const FindIntersectingRange& r) : mrTest(r.mrTest) {}
75 0 : bool operator() (const ScRange* pRange) const
76 : {
77 0 : return pRange->Intersects(mrTest);
78 : }
79 : private:
80 : const T& mrTest;
81 : };
82 :
83 : class AppendToList : public ::std::unary_function<const ScRange*, void>
84 : {
85 : public:
86 332 : AppendToList(vector<ScRange*>& rRanges) : mrRanges(rRanges) {}
87 332 : AppendToList(const AppendToList& r) : mrRanges(r.mrRanges) {}
88 126 : void operator() (const ScRange* p)
89 : {
90 126 : mrRanges.push_back(new ScRange(*p));
91 126 : }
92 : private:
93 : vector<ScRange*>& mrRanges;
94 : };
95 :
96 : class CountCells : public ::std::unary_function<const ScRange*, void>
97 : {
98 : public:
99 5 : CountCells() : mnCellCount(0) {}
100 10 : CountCells(const CountCells& r) : mnCellCount(r.mnCellCount) {}
101 :
102 8 : void operator() (const ScRange* p)
103 : {
104 : mnCellCount +=
105 16 : size_t(p->aEnd.Col() - p->aStart.Col() + 1)
106 8 : * size_t(p->aEnd.Row() - p->aStart.Row() + 1)
107 24 : * size_t(p->aEnd.Tab() - p->aStart.Tab() + 1);
108 8 : }
109 :
110 5 : size_t getCellCount() const { return mnCellCount; }
111 :
112 : private:
113 : size_t mnCellCount;
114 : };
115 :
116 : class FormatString : public ::std::unary_function<const ScRange*, void>
117 : {
118 : public:
119 105 : FormatString(String& rStr, sal_uInt16 nFlags, ScDocument* pDoc, FormulaGrammar::AddressConvention eConv, sal_Unicode cDelim) :
120 : mrStr(rStr),
121 : mnFlags(nFlags),
122 : mpDoc(pDoc),
123 : meConv(eConv),
124 : mcDelim(cDelim),
125 105 : mbFirst(true) {}
126 :
127 210 : FormatString(const FormatString& r) :
128 : mrStr(r.mrStr),
129 : mnFlags(r.mnFlags),
130 : mpDoc(r.mpDoc),
131 : meConv(r.meConv),
132 : mcDelim(r.mcDelim),
133 210 : mbFirst(r.mbFirst) {}
134 :
135 148 : void operator() (const ScRange* p)
136 : {
137 148 : String aStr;
138 148 : p->Format(aStr, mnFlags, mpDoc, meConv);
139 148 : if (mbFirst)
140 105 : mbFirst = false;
141 : else
142 43 : mrStr += mcDelim;
143 148 : mrStr += aStr;
144 148 : }
145 : private:
146 : String& mrStr;
147 : sal_uInt16 mnFlags;
148 : ScDocument* mpDoc;
149 : FormulaGrammar::AddressConvention meConv;
150 : sal_Unicode mcDelim;
151 : bool mbFirst;
152 : };
153 :
154 : class FindDeletedRange : public ::std::unary_function<const ScRange*, bool>
155 : {
156 : public:
157 : FindDeletedRange( SCsCOL nDx, SCsROW nDy): mnDx(nDx), mnDy(nDy) {}
158 : FindDeletedRange( const FindDeletedRange& r) : mnDx(r.mnDx), mnDy(r.mnDy) {}
159 : bool operator() (const ScRange* p)
160 : {
161 : const ScAddress& rStart = p->aStart;
162 : const ScAddress& rEnd = p->aEnd;
163 :
164 : if( rEnd.Col() +mnDx < rStart.Col() )
165 : return true;
166 : if( rEnd.Row() + mnDy < rStart.Row() )
167 : return true;
168 :
169 : return false;
170 : }
171 :
172 : private:
173 : SCsCOL mnDx;
174 : SCsROW mnDy;
175 : };
176 :
177 : }
178 :
179 : // === ScRangeList ====================================================
180 :
181 16385 : ScRangeList::~ScRangeList()
182 : {
183 8143 : RemoveAll();
184 8242 : }
185 :
186 0 : sal_uInt16 ScRangeList::Parse( const String& rStr, ScDocument* pDoc, sal_uInt16 nMask,
187 : formula::FormulaGrammar::AddressConvention eConv,
188 : SCTAB nDefaultTab )
189 : {
190 0 : if ( rStr.Len() )
191 : {
192 0 : sal_Unicode cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
193 :
194 0 : nMask |= SCA_VALID; // falls das jemand vergessen sollte
195 0 : sal_uInt16 nResult = (sal_uInt16)~0; // alle Bits setzen
196 0 : ScRange aRange;
197 0 : String aOne;
198 0 : SCTAB nTab = 0;
199 0 : if ( pDoc )
200 : {
201 0 : nTab = nDefaultTab;
202 : }
203 : else
204 0 : nTab = 0;
205 0 : sal_uInt16 nTCount = comphelper::string::getTokenCount(rStr, cDelimiter);
206 0 : for ( sal_uInt16 i=0; i<nTCount; i++ )
207 : {
208 0 : aOne = rStr.GetToken( i, cDelimiter );
209 0 : aRange.aStart.SetTab( nTab ); // Default Tab wenn nicht angegeben
210 0 : sal_uInt16 nRes = aRange.ParseAny( aOne, pDoc, eConv );
211 0 : sal_uInt16 nEndRangeBits = SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2;
212 0 : sal_uInt16 nTmp1 = ( nRes & SCA_BITS );
213 0 : sal_uInt16 nTmp2 = ( nRes & nEndRangeBits );
214 : // If we have a valid single range with
215 : // any of the address bits we are interested in
216 : // set - set the equiv end range bits
217 0 : if ( (nRes & SCA_VALID ) && nTmp1 && ( nTmp2 != nEndRangeBits ) )
218 0 : nRes |= ( nTmp1 << 4 );
219 :
220 0 : if ( (nRes & nMask) == nMask )
221 0 : Append( aRange );
222 0 : nResult &= nRes; // alle gemeinsamen Bits bleiben erhalten
223 : }
224 0 : return nResult; // SCA_VALID gesetzt wenn alle ok
225 : }
226 : else
227 0 : return 0;
228 : }
229 :
230 :
231 105 : void ScRangeList::Format( String& rStr, sal_uInt16 nFlags, ScDocument* pDoc,
232 : formula::FormulaGrammar::AddressConvention eConv,
233 : sal_Unicode cDelimiter ) const
234 : {
235 105 : rStr.Erase();
236 :
237 105 : if (!cDelimiter)
238 104 : cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
239 :
240 105 : FormatString func(rStr, nFlags, pDoc, eConv, cDelimiter);
241 105 : for_each(maRanges.begin(), maRanges.end(), func);
242 105 : }
243 :
244 :
245 0 : void ScRangeList::Format( rtl::OUString& rStr, sal_uInt16 nFlags, ScDocument* pDoc,
246 : formula::FormulaGrammar::AddressConvention eConv,
247 : sal_Unicode cDelimiter ) const
248 : {
249 :
250 0 : if (!cDelimiter)
251 0 : cDelimiter = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
252 :
253 0 : String aStr;
254 0 : FormatString func(aStr, nFlags, pDoc, eConv, cDelimiter);
255 0 : for_each(maRanges.begin(), maRanges.end(), func);
256 0 : rStr = aStr;
257 0 : }
258 :
259 :
260 2679 : void ScRangeList::Join( const ScRange& r, bool bIsInList )
261 : {
262 2679 : if ( maRanges.empty() )
263 : {
264 64 : Append( r );
265 2743 : return ;
266 : }
267 2615 : SCCOL nCol1 = r.aStart.Col();
268 2615 : SCROW nRow1 = r.aStart.Row();
269 2615 : SCTAB nTab1 = r.aStart.Tab();
270 2615 : SCCOL nCol2 = r.aEnd.Col();
271 2615 : SCROW nRow2 = r.aEnd.Row();
272 2615 : SCTAB nTab2 = r.aEnd.Tab();
273 :
274 2615 : ScRange* pOver = (ScRange*) &r; // fies aber wahr wenn bInList
275 2615 : size_t nOldPos = 0;
276 2615 : if ( bIsInList )
277 : {
278 : // Find the current position of this range.
279 56 : for ( size_t i = 0, nRanges = maRanges.size(); i < nRanges; ++i )
280 : {
281 56 : if ( maRanges[i] == pOver )
282 : {
283 36 : nOldPos = i;
284 36 : break;
285 : }
286 : }
287 : }
288 2615 : bool bJoinedInput = false;
289 :
290 : // We need to query the size of the container dynamically since its size
291 : // may change during the loop.
292 3123 : for ( size_t i = 0; i < maRanges.size() && pOver; ++i )
293 : {
294 3005 : ScRange* p = maRanges[i];
295 3005 : if ( p == pOver )
296 28 : continue; // derselbe, weiter mit dem naechsten
297 2977 : bool bJoined = false;
298 2977 : if ( p->In( r ) )
299 : { // Range r in Range p enthalten oder identisch
300 2497 : if ( bIsInList )
301 0 : bJoined = true; // weg mit Range r
302 : else
303 : { // das war's dann
304 2497 : bJoinedInput = true; // nicht anhaengen
305 2497 : break; // for
306 : }
307 : }
308 480 : else if ( r.In( *p ) )
309 : { // Range p in Range r enthalten, r zum neuen Range machen
310 1 : *p = r;
311 1 : bJoined = true;
312 : }
313 480 : if ( !bJoined && p->aStart.Tab() == nTab1 && p->aEnd.Tab() == nTab2 )
314 : { // 2D
315 117 : if ( p->aStart.Col() == nCol1 && p->aEnd.Col() == nCol2 )
316 : {
317 23 : if ( p->aStart.Row() == nRow2+1 )
318 : { // oben
319 1 : p->aStart.SetRow( nRow1 );
320 1 : bJoined = true;
321 : }
322 22 : else if ( p->aEnd.Row() == nRow1-1 )
323 : { // unten
324 16 : p->aEnd.SetRow( nRow2 );
325 16 : bJoined = true;
326 : }
327 : }
328 94 : else if ( p->aStart.Row() == nRow1 && p->aEnd.Row() == nRow2 )
329 : {
330 20 : if ( p->aStart.Col() == nCol2+1 )
331 : { // links
332 1 : p->aStart.SetCol( nCol1 );
333 1 : bJoined = true;
334 : }
335 19 : else if ( p->aEnd.Col() == nCol1-1 )
336 : { // rechts
337 14 : p->aEnd.SetCol( nCol2 );
338 14 : bJoined = true;
339 : }
340 : }
341 : }
342 480 : if ( bJoined )
343 : {
344 33 : if ( bIsInList )
345 : { // innerhalb der Liste Range loeschen
346 8 : Remove(nOldPos);
347 8 : i--;
348 8 : delete pOver;
349 8 : pOver = NULL;
350 8 : if ( nOldPos )
351 8 : nOldPos--; // Seek richtig aufsetzen
352 : }
353 33 : bJoinedInput = true;
354 33 : Join( *p, true ); // rekursiv!
355 : }
356 : }
357 2615 : if ( !bIsInList && !bJoinedInput )
358 57 : Append( r );
359 : }
360 :
361 :
362 9 : bool ScRangeList::operator==( const ScRangeList& r ) const
363 : {
364 9 : if ( this == &r )
365 0 : return true;
366 :
367 9 : if (maRanges.size() != r.maRanges.size())
368 0 : return false;
369 :
370 9 : vector<ScRange*>::const_iterator itr1 = maRanges.begin(), itrEnd = maRanges.end();
371 9 : vector<ScRange*>::const_iterator itr2 = r.maRanges.begin();
372 18 : for (; itr1 != itrEnd; ++itr1, ++itr2)
373 : {
374 9 : const ScRange* p1 = *itr1;
375 9 : const ScRange* p2 = *itr2;
376 9 : if (*p1 != *p2)
377 0 : return false;
378 : }
379 9 : return true;
380 : }
381 :
382 0 : bool ScRangeList::operator!=( const ScRangeList& r ) const
383 : {
384 0 : return !operator==( r );
385 : }
386 :
387 3 : bool ScRangeList::UpdateReference(
388 : UpdateRefMode eUpdateRefMode,
389 : ScDocument* pDoc,
390 : const ScRange& rWhere,
391 : SCsCOL nDx,
392 : SCsROW nDy,
393 : SCsTAB nDz
394 : )
395 : {
396 3 : if (maRanges.empty())
397 : // No ranges to update. Bail out.
398 0 : return false;
399 :
400 3 : bool bChanged = false;
401 : SCCOL nCol1;
402 : SCROW nRow1;
403 : SCTAB nTab1;
404 : SCCOL nCol2;
405 : SCROW nRow2;
406 : SCTAB nTab2;
407 3 : rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
408 :
409 3 : if(eUpdateRefMode == URM_INSDEL)
410 : {
411 : // right now this only works for nTab1 == nTab2
412 3 : if(nTab1 == nTab2)
413 : {
414 3 : if(nDx < 0)
415 : {
416 1 : DeleteArea(nCol1+nDx, nRow1, nTab1, nCol1-1, nRow2, nTab2);
417 : }
418 3 : if(nDy < 0)
419 : {
420 2 : DeleteArea(nCol1, nRow1+nDy, nTab1, nCol2, nRow1-1, nTab2);
421 : }
422 : SAL_WARN_IF(nDx < 0 && nDy < 0, "sc", "nDx and nDy are negative, check why");
423 : }
424 : }
425 :
426 3 : if(maRanges.empty())
427 1 : return true;
428 :
429 2 : iterator itr = maRanges.begin(), itrEnd = maRanges.end();
430 6 : for (; itr != itrEnd; ++itr)
431 : {
432 4 : ScRange* pR = *itr;
433 : SCCOL theCol1;
434 : SCROW theRow1;
435 : SCTAB theTab1;
436 : SCCOL theCol2;
437 : SCROW theRow2;
438 : SCTAB theTab2;
439 4 : pR->GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
440 4 : if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
441 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
442 : nDx, nDy, nDz,
443 4 : theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
444 : != UR_NOTHING )
445 : {
446 2 : bChanged = true;
447 2 : pR->aStart.Set( theCol1, theRow1, theTab1 );
448 2 : pR->aEnd.Set( theCol2, theRow2, theTab2 );
449 : }
450 : }
451 :
452 2 : if(eUpdateRefMode == URM_INSDEL)
453 : {
454 2 : if( nDx < 0 || nDy < 0 )
455 : {
456 2 : size_t n = maRanges.size();
457 2 : Join(*maRanges[n-1], true);
458 : }
459 : }
460 :
461 2 : return bChanged;
462 : }
463 :
464 : namespace {
465 :
466 : /**
467 : * Check if the deleting range cuts the test range exactly into a single
468 : * piece.
469 : *
470 : * X = column ; Y = row
471 : * +------+ +------+
472 : * |xxxxxx| | |
473 : * +------+ or +------+
474 : * | | |xxxxxx|
475 : * +------+ +------+
476 : *
477 : * X = row; Y = column
478 : * +--+--+ +--+--+
479 : * |xx| | | |xx|
480 : * |xx| | or | |xx|
481 : * |xx| | | |xx|
482 : * +--+--+ +--+--+
483 : * where xxx is the deleted region.
484 : */
485 : template<typename X, typename Y>
486 36 : bool checkForOneRange(
487 : X nDeleteX1, X nDeleteX2, Y nDeleteY1, Y nDeleteY2, X nX1, X nX2, Y nY1, Y nY2)
488 : {
489 36 : if (nDeleteX1 <= nX1 && nX2 <= nDeleteX2 && (nDeleteY1 <= nY1 || nY2 <= nDeleteY2))
490 1 : return true;
491 :
492 35 : return false;
493 : }
494 :
495 18 : bool handleOneRange( const ScRange& rDeleteRange, ScRange* p )
496 : {
497 18 : const ScAddress& rDelStart = rDeleteRange.aStart;
498 18 : const ScAddress& rDelEnd = rDeleteRange.aEnd;
499 18 : ScAddress aPStart = p->aStart;
500 18 : ScAddress aPEnd = p->aEnd;
501 18 : SCCOL nDeleteCol1 = rDelStart.Col();
502 18 : SCCOL nDeleteCol2 = rDelEnd.Col();
503 18 : SCROW nDeleteRow1 = rDelStart.Row();
504 18 : SCROW nDeleteRow2 = rDelEnd.Row();
505 18 : SCCOL nCol1 = aPStart.Col();
506 18 : SCCOL nCol2 = aPEnd.Col();
507 18 : SCROW nRow1 = aPStart.Row();
508 18 : SCROW nRow2 = aPEnd.Row();
509 :
510 18 : if (checkForOneRange(nDeleteCol1, nDeleteCol2, nDeleteRow1, nDeleteRow2, nCol1, nCol2, nRow1, nRow2))
511 : {
512 : // Deleting range fully overlaps the column range. Adjust the row span.
513 0 : if (nDeleteRow1 <= nRow1)
514 : {
515 : // +------+
516 : // |xxxxxx|
517 : // +------+
518 : // | |
519 : // +------+ (xxx) = deleted region
520 :
521 0 : p->aStart.SetRow(nDeleteRow1+1);
522 0 : return true;
523 : }
524 0 : else if (nRow2 <= nDeleteRow2)
525 : {
526 : // +------+
527 : // | |
528 : // +------+
529 : // |xxxxxx|
530 : // +------+ (xxx) = deleted region
531 :
532 0 : p->aEnd.SetRow(nDeleteRow1-1);
533 0 : return true;
534 : }
535 : }
536 18 : else if (checkForOneRange(nDeleteRow1, nDeleteRow2, nDeleteCol1, nDeleteCol2, nRow1, nRow2, nCol1, nCol2))
537 : {
538 : // Deleting range fully overlaps the row range. Adjust the column span.
539 1 : if (nDeleteCol1 <= nCol1)
540 : {
541 : // +--+--+
542 : // |xx| |
543 : // |xx| |
544 : // |xx| |
545 : // +--+--+ (xxx) = deleted region
546 :
547 1 : p->aStart.SetCol(nDeleteCol2+1);
548 1 : return true;
549 : }
550 0 : else if (nCol2 <= nDeleteCol2)
551 : {
552 : // +--+--+
553 : // | |xx|
554 : // | |xx|
555 : // | |xx|
556 : // +--+--+ (xxx) = deleted region
557 :
558 0 : p->aEnd.SetCol(nDeleteCol1-1);
559 0 : return true;
560 : }
561 : }
562 17 : return false;
563 : }
564 :
565 : /**
566 : * Check if the deleting range cuts the test range in the middle, to
567 : * separate it into exactly two pieces.
568 : *
569 : * Either
570 : * +--------+ +--+-+--+
571 : * | | | |x| |
572 : * +--------+ | |x| |
573 : * |xxxxxxxx| or | |x| |
574 : * +--------+ | |x| |
575 : * | | | |x| |
576 : * +--------+ +--+-+--+
577 : * where xxx is the deleted region.
578 : */
579 : template<typename X, typename Y>
580 : bool checkForTwoRangesCase2(
581 : X nDeleteX1, X nDeleteX2, Y nDeleteY1, Y nDeleteY2, X nX1, X nX2, Y nY1, Y nY2)
582 : {
583 : if (nY1 < nDeleteY1 && nDeleteY2 < nY2 && nDeleteX1 <= nX1 && nX2 <= nDeleteX2)
584 : return true;
585 :
586 : return false;
587 : }
588 :
589 17 : bool handleTwoRanges( const ScRange& rDeleteRange, ScRange* p, std::vector<ScRange>& rNewRanges )
590 : {
591 17 : const ScAddress& rDelStart = rDeleteRange.aStart;
592 17 : const ScAddress& rDelEnd = rDeleteRange.aEnd;
593 17 : ScAddress aPStart = p->aStart;
594 17 : ScAddress aPEnd = p->aEnd;
595 17 : SCCOL nDeleteCol1 = rDelStart.Col();
596 17 : SCCOL nDeleteCol2 = rDelEnd.Col();
597 17 : SCROW nDeleteRow1 = rDelStart.Row();
598 17 : SCROW nDeleteRow2 = rDelEnd.Row();
599 17 : SCCOL nCol1 = aPStart.Col();
600 17 : SCCOL nCol2 = aPEnd.Col();
601 17 : SCROW nRow1 = aPStart.Row();
602 17 : SCROW nRow2 = aPEnd.Row();
603 17 : SCTAB nTab = aPStart.Tab();
604 :
605 17 : if (nCol1 < nDeleteCol1 && nDeleteCol1 <= nCol2 && nCol2 <= nDeleteCol2)
606 : {
607 : // column deleted : |-------|
608 : // column original: |-------|
609 7 : if (nRow1 < nDeleteRow1 && nDeleteRow1 <= nRow2 && nRow2 <= nDeleteRow2)
610 : {
611 : // row deleted: |------|
612 : // row original: |------|
613 : //
614 : // +-------+
615 : // | 1 |
616 : // +---+---+---+
617 : // | 2 |xxxxxxx|
618 : // +---+xxxxxxx|
619 : // |xxxxxxx|
620 : // +-------+ (xxx) deleted region
621 :
622 3 : ScRange aNewRange( nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nRow2, nTab ); // 2
623 3 : rNewRanges.push_back(aNewRange);
624 :
625 3 : p->aEnd.SetRow(nDeleteRow1-1); // 1
626 3 : return true;
627 : }
628 4 : else if (nRow1 <= nDeleteRow2 && nDeleteRow2 < nRow2 && nDeleteRow1 <= nRow1)
629 : {
630 : // row deleted: |------|
631 : // row original: |------|
632 : //
633 : // +-------+
634 : // |xxxxxxx|
635 : // +---+xxxxxxx|
636 : // | 1 |xxxxxxx|
637 : // +---+---+---+
638 : // | 2 | (xxx) deleted region
639 : // +-------+
640 :
641 2 : ScRange aNewRange( aPStart, ScAddress(nDeleteCol1-1, nRow2, nTab) ); // 1
642 2 : rNewRanges.push_back(aNewRange);
643 :
644 2 : p->aStart.SetRow(nDeleteRow2+1); // 2
645 2 : return true;
646 2 : }
647 : }
648 10 : else if (nCol1 <= nDeleteCol2 && nDeleteCol2 < nCol2 && nDeleteCol1 <= nCol1)
649 : {
650 : // column deleted : |-------|
651 : // column original: |-------|
652 4 : if (nRow1 < nDeleteRow1 && nDeleteRow1 <= nRow2 && nRow2 <= nDeleteRow2)
653 : {
654 : // row deleted: |------|
655 : // row original: |------|
656 : //
657 : // +-------+
658 : // | 1 |
659 : // +-------+---+
660 : // |xxxxxxx| 2 |
661 : // |xxxxxxx+---+
662 : // |xxxxxxx|
663 : // +-------+
664 : // (xxx) deleted region
665 :
666 1 : ScRange aNewRange( ScAddress( nDeleteCol2+1, nDeleteRow1, nTab ), aPEnd ); // 2
667 1 : rNewRanges.push_back(aNewRange);
668 :
669 1 : p->aEnd.SetRow(nDeleteRow1-1); // 1
670 1 : return true;
671 : }
672 3 : else if (nRow1 <= nDeleteRow2 && nDeleteRow2 < nRow2 && nDeleteRow1 <= nRow1)
673 : {
674 : // row deleted: |-------|
675 : // row original: |--------|
676 : //
677 : // +-------+
678 : // |xxxxxxx|
679 : // |xxxxxxx+---+
680 : // |xxxxxxx| 1 |
681 : // +-------+---+
682 : // | 2 |
683 : // +-------+ (xxx) deleted region
684 :
685 2 : ScRange aNewRange(nDeleteCol2+1, nRow1, nTab, nCol2, nDeleteRow2, nTab); // 1
686 2 : rNewRanges.push_back(aNewRange);
687 :
688 2 : p->aStart.SetRow(nDeleteRow2+1); // 2
689 2 : return true;
690 1 : }
691 : }
692 6 : else if (nRow1 < nDeleteRow1 && nDeleteRow2 < nRow2 && nDeleteCol1 <= nCol1 && nCol2 <= nDeleteCol2)
693 : {
694 : // +--------+
695 : // | 1 |
696 : // +--------+
697 : // |xxxxxxxx| (xxx) deleted region
698 : // +--------+
699 : // | 2 |
700 : // +--------+
701 :
702 2 : ScRange aNewRange( aPStart, ScAddress(nCol2, nDeleteRow1-1, nTab) ); // 1
703 2 : rNewRanges.push_back(aNewRange);
704 :
705 2 : p->aStart.SetRow(nDeleteRow2+1); // 2
706 2 : return true;
707 : }
708 4 : else if (nCol1 < nDeleteCol1 && nDeleteCol2 < nCol2 && nDeleteRow1 <= nRow1 && nRow2 <= nDeleteRow2)
709 : {
710 : // +---+-+---+
711 : // | |x| |
712 : // | |x| |
713 : // | 1 |x| 2 | (xxx) deleted region
714 : // | |x| |
715 : // | |x| |
716 : // +---+-+---+
717 :
718 1 : ScRange aNewRange( aPStart, ScAddress(nDeleteCol1-1, nRow2, nTab) ); // 1
719 1 : rNewRanges.push_back(aNewRange);
720 :
721 1 : p->aStart.SetCol(nDeleteCol2+1); // 2
722 1 : return true;
723 : }
724 :
725 6 : return false;
726 : }
727 :
728 : /**
729 : * Check if any of the followings applies:
730 : *
731 : * X = column; Y = row
732 : * +----------+ +----------+
733 : * | | | |
734 : * | +-------+---+ +--+-------+ |
735 : * | |xxxxxxxxxxx| or |xxxxxxxxxx| |
736 : * | +-------+---+ +--+-------+ |
737 : * | | | |
738 : * +----------+ +----------+
739 : *
740 : * X = row; Y = column
741 : * +--+
742 : * |xx|
743 : * +---+xx+---+ +----------+
744 : * | |xx| | | |
745 : * | |xx| | or | +--+ |
746 : * | +--+ | | |xx| |
747 : * | | | |xx| |
748 : * +----------+ +---+xx+---+
749 : * |xx|
750 : * +--+ (xxx) deleted region
751 : */
752 : template<typename X, typename Y>
753 9 : bool checkForThreeRanges(
754 : X nDeleteX1, X nDeleteX2, Y nDeleteY1, Y nDeleteY2, X nX1, X nX2, Y nY1, Y nY2)
755 : {
756 9 : if (nX1 <= nDeleteX1 && nX2 <= nDeleteX2 && nY1 < nDeleteY1 && nDeleteY2 < nY2)
757 2 : return true;
758 :
759 7 : if (nDeleteX1 <= nX1 && nDeleteX2 <= nX2 && nY1 < nDeleteY1 && nDeleteY2 < nY2)
760 3 : return true;
761 :
762 4 : return false;
763 : }
764 :
765 6 : bool handleThreeRanges( const ScRange& rDeleteRange, ScRange* p, std::vector<ScRange>& rNewRanges )
766 : {
767 6 : const ScAddress& rDelStart = rDeleteRange.aStart;
768 6 : const ScAddress& rDelEnd = rDeleteRange.aEnd;
769 6 : ScAddress aPStart = p->aStart;
770 6 : ScAddress aPEnd = p->aEnd;
771 6 : SCCOL nDeleteCol1 = rDelStart.Col();
772 6 : SCCOL nDeleteCol2 = rDelEnd.Col();
773 6 : SCROW nDeleteRow1 = rDelStart.Row();
774 6 : SCROW nDeleteRow2 = rDelEnd.Row();
775 6 : SCCOL nCol1 = aPStart.Col();
776 6 : SCCOL nCol2 = aPEnd.Col();
777 6 : SCROW nRow1 = aPStart.Row();
778 6 : SCROW nRow2 = aPEnd.Row();
779 6 : SCTAB nTab = aPStart.Tab();
780 :
781 6 : if (checkForThreeRanges(nDeleteCol1, nDeleteCol2, nDeleteRow1, nDeleteRow2, nCol1, nCol2, nRow1, nRow2))
782 : {
783 3 : if (nCol1 < nDeleteCol1)
784 : {
785 : // +---+------+
786 : // | | 2 |
787 : // | +------+---+
788 : // | 1 |xxxxxxxxxx|
789 : // | +------+---+
790 : // | | 3 |
791 : // +---+------+
792 :
793 2 : ScRange aNewRange(nDeleteCol1, nRow1, nTab, nCol2, nDeleteRow1-1, nTab); // 2
794 2 : rNewRanges.push_back(aNewRange);
795 :
796 2 : aNewRange = ScRange(ScAddress(nDeleteCol1, nDeleteRow2+1, nTab), aPEnd); // 3
797 2 : rNewRanges.push_back(aNewRange);
798 :
799 2 : p->aEnd.SetCol(nDeleteCol1-1); // 1
800 : }
801 : else
802 : {
803 : // +------+---+
804 : // | 1 | |
805 : // +---+------+ |
806 : // |xxxxxxxxxx| 2 |
807 : // +---+------+ |
808 : // | 3 | |
809 : // +------+---+
810 :
811 1 : ScRange aNewRange(aPStart, ScAddress(nDeleteCol2, nDeleteRow1-1, nTab)); // 1
812 1 : rNewRanges.push_back(aNewRange);
813 :
814 1 : aNewRange = ScRange(nCol1, nDeleteRow2+1, nTab, nDeleteCol2, nRow2, nTab); // 3
815 1 : rNewRanges.push_back(aNewRange);
816 :
817 1 : p->aStart.SetCol(nDeleteCol2+1); // 2
818 : }
819 3 : return true;
820 : }
821 3 : else if (checkForThreeRanges(nDeleteRow1, nDeleteRow2, nDeleteCol1, nDeleteCol2, nRow1, nRow2, nCol1, nCol2))
822 : {
823 2 : if (nRow1 < nDeleteRow1)
824 : {
825 : // +----------+
826 : // | 1 |
827 : // +---+--+---+
828 : // | |xx| |
829 : // | 2 |xx| 3 |
830 : // | |xx| |
831 : // +---+xx+---+
832 : // |xx|
833 : // +--+
834 :
835 0 : ScRange aNewRange(nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nRow2, nTab); // 2
836 0 : rNewRanges.push_back( aNewRange );
837 :
838 0 : aNewRange = ScRange(ScAddress(nDeleteCol2+1, nDeleteRow1, nTab), aPEnd); // 3
839 0 : rNewRanges.push_back( aNewRange );
840 :
841 0 : p->aEnd.SetRow(nDeleteRow1-1); // 1
842 : }
843 : else
844 : {
845 : // +--+
846 : // |xx|
847 : // +---+xx+---+
848 : // | 1 |xx| 2 |
849 : // | |xx| |
850 : // +---+--+---+
851 : // | 3 |
852 : // +----------+
853 :
854 2 : ScRange aNewRange(aPStart, ScAddress(nDeleteCol1-1, nDeleteRow2, nTab)); // 1
855 2 : rNewRanges.push_back(aNewRange);
856 :
857 2 : aNewRange = ScRange(nDeleteCol2+1, nRow1, nTab, nCol2, nDeleteRow2, nTab); // 2
858 2 : rNewRanges.push_back( aNewRange );
859 :
860 2 : p->aStart.SetRow(nDeleteRow2+1); // 3
861 : }
862 2 : return true;
863 : }
864 :
865 1 : return false;
866 : }
867 :
868 1 : bool handleFourRanges( const ScRange& rDelRange, ScRange* p, std::vector<ScRange>& rNewRanges )
869 : {
870 1 : const ScAddress& rDelStart = rDelRange.aStart;
871 1 : const ScAddress& rDelEnd = rDelRange.aEnd;
872 1 : ScAddress aPStart = p->aStart;
873 1 : ScAddress aPEnd = p->aEnd;
874 1 : SCCOL nDeleteCol1 = rDelStart.Col();
875 1 : SCCOL nDeleteCol2 = rDelEnd.Col();
876 1 : SCROW nDeleteRow1 = rDelStart.Row();
877 1 : SCROW nDeleteRow2 = rDelEnd.Row();
878 1 : SCCOL nCol1 = aPStart.Col();
879 1 : SCCOL nCol2 = aPEnd.Col();
880 1 : SCROW nRow1 = aPStart.Row();
881 1 : SCROW nRow2 = aPEnd.Row();
882 1 : SCTAB nTab = aPStart.Tab();
883 :
884 1 : if (nCol1 < nDeleteCol1 && nDeleteCol2 < nCol2 && nRow1 < nDeleteRow1 && nDeleteRow2 < nRow2)
885 : {
886 : // +---------------+
887 : // | 1 |
888 : // +---+-------+---+
889 : // | |xxxxxxx| |
890 : // | 2 |xxxxxxx| 3 |
891 : // | |xxxxxxx| |
892 : // +---+-------+---+
893 : // | 4 |
894 : // +---------------+
895 :
896 1 : ScRange aNewRange(ScAddress(nCol1, nDeleteRow2+1, nTab), aPEnd); // 4
897 1 : rNewRanges.push_back( aNewRange );
898 :
899 1 : aNewRange = ScRange(nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nDeleteRow2, nTab); // 2
900 1 : rNewRanges.push_back( aNewRange );
901 :
902 1 : aNewRange = ScRange(nDeleteCol2+1, nDeleteRow1, nTab, nCol2, nDeleteRow2, nTab); // 3
903 1 : rNewRanges.push_back( aNewRange );
904 :
905 1 : p->aEnd.SetRow(nDeleteRow1-1); // 1
906 :
907 1 : return true;
908 : }
909 :
910 0 : return false;
911 : }
912 :
913 : }
914 :
915 21 : void ScRangeList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
916 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
917 : {
918 21 : ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
919 63 : for(size_t i = 0; i < maRanges.size();)
920 : {
921 21 : if(FindRangeIn< ScRange >(aRange)(maRanges[i]))
922 : {
923 3 : ScRange* pRange = Remove(i);
924 3 : delete pRange;
925 : }
926 : else
927 18 : ++i;
928 : }
929 :
930 21 : std::vector<ScRange> aNewRanges;
931 :
932 39 : for(iterator itr = maRanges.begin(); itr != maRanges.end(); ++itr)
933 : {
934 : // we have two basic cases here:
935 : // 1. Delete area and pRange intersect
936 : // 2. Delete area and pRange are not intersecting
937 : // checking for 2 and if true skip this range
938 18 : if(!(*itr)->Intersects(aRange))
939 0 : continue;
940 :
941 : // We get between 1 and 4 ranges from the difference of the first with the second
942 :
943 : // X either Col or Row and Y then the opposite
944 : // r = deleteRange, p = entry from ScRangeList
945 :
946 : // getting exactly one range is the simple case
947 : // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
948 : // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() )
949 18 : if(handleOneRange( aRange, *itr ))
950 1 : continue;
951 :
952 : // getting two ranges
953 : // r.aStart.X()
954 17 : else if(handleTwoRanges( aRange, *itr, aNewRanges ))
955 11 : continue;
956 :
957 : // getting 3 ranges
958 : // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
959 : // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
960 : // or
961 : // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X()
962 : // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
963 6 : else if(handleThreeRanges( aRange, *itr, aNewRanges ))
964 5 : continue;
965 :
966 : // getting 4 ranges
967 : // r.aStart.X() > p.aStart.X() && r.aEnd().X() < p.aEnd.X()
968 : // && r.aStart.Y() > p.aStart.Y() && r.aEnd().Y() < p.aEnd.Y()
969 1 : else if(handleFourRanges( aRange, *itr, aNewRanges ))
970 1 : continue;
971 : }
972 45 : for(vector<ScRange>::iterator itr = aNewRanges.begin(); itr != aNewRanges.end(); ++itr)
973 45 : Join( *itr, false);
974 21 : }
975 :
976 42 : const ScRange* ScRangeList::Find( const ScAddress& rAdr ) const
977 : {
978 : const_iterator itr = find_if(
979 42 : maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr));
980 42 : return itr == maRanges.end() ? NULL : *itr;
981 : }
982 :
983 28 : ScRange* ScRangeList::Find( const ScAddress& rAdr )
984 : {
985 : iterator itr = find_if(
986 28 : maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr));
987 28 : return itr == maRanges.end() ? NULL : *itr;
988 : }
989 :
990 5198 : ScRangeList::ScRangeList() {}
991 :
992 295 : ScRangeList::ScRangeList( const ScRangeList& rList ) :
993 295 : SvRefBase()
994 : {
995 295 : maRanges.reserve(rList.maRanges.size());
996 295 : for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges));
997 295 : }
998 :
999 2678 : ScRangeList::ScRangeList( const ScRange& rRange )
1000 : {
1001 2678 : maRanges.reserve(1);
1002 2678 : Append(rRange);
1003 2678 : }
1004 :
1005 37 : ScRangeList& ScRangeList::operator=(const ScRangeList& rList)
1006 : {
1007 37 : RemoveAll();
1008 37 : maRanges.reserve(rList.maRanges.size());
1009 37 : for_each(rList.maRanges.begin(), rList.maRanges.end(), AppendToList(maRanges));
1010 37 : return *this;
1011 : }
1012 :
1013 6171 : void ScRangeList::Append( const ScRange& rRange )
1014 : {
1015 6171 : ScRange* pR = new ScRange( rRange );
1016 6171 : maRanges.push_back( pR );
1017 6171 : }
1018 :
1019 0 : bool ScRangeList::Intersects( const ScRange& rRange ) const
1020 : {
1021 0 : const_iterator itrEnd = maRanges.end();
1022 : const_iterator itr =
1023 0 : find_if(maRanges.begin(), itrEnd, FindIntersectingRange<ScRange>(rRange));
1024 0 : return itr != itrEnd;
1025 : }
1026 :
1027 1541 : bool ScRangeList::In( const ScRange& rRange ) const
1028 : {
1029 1541 : const_iterator itrEnd = maRanges.end();
1030 : const_iterator itr =
1031 1541 : find_if(maRanges.begin(), itrEnd, FindEnclosingRange<ScRange>(rRange));
1032 1541 : return itr != itrEnd;
1033 : }
1034 :
1035 :
1036 5 : size_t ScRangeList::GetCellCount() const
1037 : {
1038 5 : CountCells func;
1039 5 : return for_each(maRanges.begin(), maRanges.end(), func).getCellCount();
1040 : }
1041 :
1042 11 : ScRange* ScRangeList::Remove(size_t nPos)
1043 : {
1044 11 : if (maRanges.size() <= nPos)
1045 : // Out-of-bound condition. Bail out.
1046 0 : return NULL;
1047 :
1048 11 : iterator itr = maRanges.begin();
1049 11 : advance(itr, nPos);
1050 11 : ScRange* p = *itr;
1051 11 : maRanges.erase(itr);
1052 11 : return p;
1053 : }
1054 :
1055 8387 : void ScRangeList::RemoveAll()
1056 : {
1057 8387 : for_each(maRanges.begin(), maRanges.end(), ScDeleteObjectByPtr<ScRange>());
1058 8387 : maRanges.clear();
1059 8387 : }
1060 :
1061 2655 : ScRange ScRangeList::Combine() const
1062 : {
1063 2655 : if (maRanges.empty())
1064 2236 : return ScRange();
1065 :
1066 419 : const_iterator itr = maRanges.begin(), itrEnd = maRanges.end();
1067 419 : ScRange aRet = **itr;
1068 419 : ++itr;
1069 419 : for (; itr != itrEnd; ++itr)
1070 : {
1071 0 : const ScRange& r = **itr;
1072 0 : SCROW nRow1 = r.aStart.Row(), nRow2 = r.aEnd.Row();
1073 0 : SCCOL nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
1074 0 : SCTAB nTab1 = r.aStart.Tab(), nTab2 = r.aEnd.Tab();
1075 0 : if (aRet.aStart.Row() > nRow1)
1076 0 : aRet.aStart.SetRow(nRow1);
1077 0 : if (aRet.aStart.Col() > nCol1)
1078 0 : aRet.aStart.SetCol(nCol1);
1079 0 : if (aRet.aStart.Tab() > nTab1)
1080 0 : aRet.aStart.SetTab(nTab1);
1081 0 : if (aRet.aEnd.Row() < nRow2)
1082 0 : aRet.aEnd.SetRow(nRow2);
1083 0 : if (aRet.aEnd.Col() < nCol2)
1084 0 : aRet.aEnd.SetCol(nCol2);
1085 0 : if (aRet.aEnd.Tab() < nTab2)
1086 0 : aRet.aEnd.SetTab(nTab2);
1087 : }
1088 419 : return aRet;
1089 : }
1090 :
1091 2517 : bool ScRangeList::empty() const
1092 : {
1093 2517 : return maRanges.empty();
1094 : }
1095 :
1096 3330 : size_t ScRangeList::size() const
1097 : {
1098 3330 : return maRanges.size();
1099 : }
1100 :
1101 548 : ScRange* ScRangeList::operator [](size_t idx)
1102 : {
1103 548 : return maRanges[idx];
1104 : }
1105 :
1106 3887 : const ScRange* ScRangeList::operator [](size_t idx) const
1107 : {
1108 3887 : return maRanges[idx];
1109 : }
1110 :
1111 25 : ScRange* ScRangeList::front()
1112 : {
1113 25 : return maRanges.front();
1114 : }
1115 :
1116 0 : const ScRange* ScRangeList::front() const
1117 : {
1118 0 : return maRanges.front();
1119 : }
1120 :
1121 0 : ScRange* ScRangeList::back()
1122 : {
1123 0 : return maRanges.back();
1124 : }
1125 :
1126 0 : const ScRange* ScRangeList::back() const
1127 : {
1128 0 : return maRanges.back();
1129 : }
1130 :
1131 94 : void ScRangeList::push_back(ScRange* p)
1132 : {
1133 94 : maRanges.push_back(p);
1134 94 : }
1135 :
1136 0 : ScAddress ScRangeList::GetTopLeftCorner() const
1137 : {
1138 0 : if(empty())
1139 0 : return ScAddress();
1140 :
1141 0 : ScAddress aAddr = maRanges[0]->aStart;
1142 0 : for(size_t i = 1, n = size(); i < n; ++i)
1143 : {
1144 0 : if(maRanges[i]->aStart < aAddr)
1145 0 : aAddr = maRanges[i]->aStart;
1146 : }
1147 :
1148 0 : return aAddr;
1149 : }
1150 :
1151 : // === ScRangePairList ========================================================
1152 :
1153 666 : ScRangePairList::~ScRangePairList()
1154 : {
1155 222 : for_each( maPairs.begin(), maPairs.end(), ScDeleteObjectByPtr<ScRangePair>() );
1156 222 : maPairs.clear();
1157 444 : }
1158 :
1159 : //-----------------------------------------------------------------------------
1160 0 : ScRangePair* ScRangePairList::Remove(size_t nPos)
1161 : {
1162 0 : if (maPairs.size() <= nPos)
1163 : // Out-of-bound condition. Bail out.
1164 0 : return NULL;
1165 :
1166 0 : vector<ScRangePair*>::iterator itr = maPairs.begin();
1167 0 : advance(itr, nPos);
1168 0 : ScRangePair* p = *itr;
1169 0 : maPairs.erase(itr);
1170 0 : return p;
1171 : }
1172 :
1173 : //-----------------------------------------------------------------------------
1174 0 : ScRangePair* ScRangePairList::Remove( ScRangePair* Adr)
1175 : {
1176 0 : ScRangePair* p = NULL;
1177 :
1178 0 : if (Adr == NULL) return NULL;
1179 :
1180 0 : for ( vector<ScRangePair*>::iterator itr = maPairs.begin(); itr < maPairs.end(); ++itr )
1181 : {
1182 0 : if ( Adr == (p = *itr) )
1183 : {
1184 0 : maPairs.erase( itr );
1185 0 : break;
1186 : }
1187 : }
1188 0 : return p;
1189 : }
1190 :
1191 0 : bool ScRangePairList::operator==( const ScRangePairList& r ) const
1192 : {
1193 0 : if ( this == &r )
1194 0 : return true; // identische Referenz
1195 0 : if ( maPairs.size() != r.size() )
1196 0 : return false;
1197 0 : for ( size_t nIdx = 0, nCnt = maPairs.size(); nIdx < nCnt; ++nIdx )
1198 : {
1199 0 : if ( *maPairs[ nIdx ] != *r[ nIdx ] )
1200 0 : return false; // auch andere Reihenfolge ist ungleich
1201 : }
1202 0 : return true;
1203 : }
1204 :
1205 0 : ScRangePair* ScRangePairList::operator [](size_t idx)
1206 : {
1207 0 : return maPairs[idx];
1208 : }
1209 :
1210 0 : const ScRangePair* ScRangePairList::operator [](size_t idx) const
1211 : {
1212 0 : return maPairs[idx];
1213 : }
1214 :
1215 34 : size_t ScRangePairList::size() const
1216 : {
1217 34 : return maPairs.size();
1218 : }
1219 :
1220 132 : bool ScRangePairList::UpdateReference( UpdateRefMode eUpdateRefMode,
1221 : ScDocument* pDoc, const ScRange& rWhere,
1222 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
1223 : {
1224 132 : bool bChanged = false;
1225 132 : if ( !maPairs.empty() )
1226 : {
1227 : SCCOL nCol1;
1228 : SCROW nRow1;
1229 : SCTAB nTab1;
1230 : SCCOL nCol2;
1231 : SCROW nRow2;
1232 : SCTAB nTab2;
1233 0 : rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1234 0 : for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i )
1235 : {
1236 0 : ScRangePair* pR = maPairs[ i ];
1237 0 : for ( sal_uInt16 j=0; j<2; j++ )
1238 : {
1239 0 : ScRange& rRange = pR->GetRange(j);
1240 : SCCOL theCol1;
1241 : SCROW theRow1;
1242 : SCTAB theTab1;
1243 : SCCOL theCol2;
1244 : SCROW theRow2;
1245 : SCTAB theTab2;
1246 0 : rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
1247 0 : if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
1248 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
1249 : nDx, nDy, nDz,
1250 0 : theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
1251 : != UR_NOTHING )
1252 : {
1253 0 : bChanged = true;
1254 0 : rRange.aStart.Set( theCol1, theRow1, theTab1 );
1255 0 : rRange.aEnd.Set( theCol2, theRow2, theTab2 );
1256 : }
1257 : }
1258 : }
1259 : }
1260 132 : return bChanged;
1261 : }
1262 :
1263 : //-----------------------------------------------------------------------------
1264 : // Delete entries that have the labels (first range) on nTab
1265 68 : void ScRangePairList::DeleteOnTab( SCTAB nTab )
1266 : {
1267 68 : size_t nListCount = maPairs.size();
1268 68 : size_t nPos = 0;
1269 136 : while ( nPos < nListCount )
1270 : {
1271 0 : ScRangePair* pR = maPairs[ nPos ];
1272 0 : ScRange aRange = pR->GetRange(0);
1273 0 : if ( aRange.aStart.Tab() == nTab && aRange.aEnd.Tab() == nTab )
1274 : {
1275 0 : Remove( nPos );
1276 0 : delete pR;
1277 0 : nListCount = maPairs.size();
1278 : }
1279 : else
1280 0 : ++nPos;
1281 : }
1282 68 : }
1283 :
1284 : //-----------------------------------------------------------------------------
1285 0 : ScRangePair* ScRangePairList::Find( const ScAddress& rAdr ) const
1286 : {
1287 0 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
1288 : {
1289 0 : ScRangePair* pR = maPairs[ j ];
1290 0 : if ( pR->GetRange(0).In( rAdr ) )
1291 0 : return pR;
1292 : }
1293 0 : return NULL;
1294 : }
1295 :
1296 : //-----------------------------------------------------------------------------
1297 0 : ScRangePair* ScRangePairList::Find( const ScRange& rRange ) const
1298 : {
1299 0 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
1300 : {
1301 0 : ScRangePair* pR = maPairs[ j ];
1302 0 : if ( pR->GetRange(0) == rRange )
1303 0 : return pR;
1304 : }
1305 0 : return NULL;
1306 : }
1307 :
1308 :
1309 : //-----------------------------------------------------------------------------
1310 0 : ScRangePairList* ScRangePairList::Clone() const
1311 : {
1312 0 : ScRangePairList* pNew = new ScRangePairList;
1313 0 : for ( size_t j = 0, nListCount = maPairs.size(); j < nListCount; j++ )
1314 : {
1315 0 : pNew->Append( *maPairs[ j ] );
1316 : }
1317 0 : return pNew;
1318 : }
1319 :
1320 : //-----------------------------------------------------------------------------
1321 : struct ScRangePairNameSort
1322 : {
1323 : ScRangePair* pPair;
1324 : ScDocument* pDoc;
1325 : };
1326 :
1327 : //-----------------------------------------------------------------------------
1328 : extern "C"
1329 0 : int SAL_CALL ScRangePairList_QsortNameCompare( const void* p1, const void* p2 )
1330 : {
1331 0 : const ScRangePairNameSort* ps1 = (const ScRangePairNameSort*)p1;
1332 0 : const ScRangePairNameSort* ps2 = (const ScRangePairNameSort*)p2;
1333 0 : const ScAddress& rStartPos1 = ps1->pPair->GetRange(0).aStart;
1334 0 : const ScAddress& rStartPos2 = ps2->pPair->GetRange(0).aStart;
1335 0 : rtl::OUString aStr1, aStr2;
1336 : sal_Int32 nComp;
1337 0 : if ( rStartPos1.Tab() == rStartPos2.Tab() )
1338 0 : nComp = COMPARE_EQUAL;
1339 : else
1340 : {
1341 0 : ps1->pDoc->GetName( rStartPos1.Tab(), aStr1 );
1342 0 : ps2->pDoc->GetName( rStartPos2.Tab(), aStr2 );
1343 0 : nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
1344 : }
1345 0 : switch ( nComp )
1346 : {
1347 : case COMPARE_LESS:
1348 0 : return -1;
1349 : //break;
1350 : case COMPARE_GREATER:
1351 0 : return 1;
1352 : //break;
1353 : default:
1354 : // gleiche Tabs
1355 0 : if ( rStartPos1.Col() < rStartPos2.Col() )
1356 0 : return -1;
1357 0 : if ( rStartPos1.Col() > rStartPos2.Col() )
1358 0 : return 1;
1359 : // gleiche Cols
1360 0 : if ( rStartPos1.Row() < rStartPos2.Row() )
1361 0 : return -1;
1362 0 : if ( rStartPos1.Row() > rStartPos2.Row() )
1363 0 : return 1;
1364 : // erste Ecke gleich, zweite Ecke
1365 : {
1366 0 : const ScAddress& rEndPos1 = ps1->pPair->GetRange(0).aEnd;
1367 0 : const ScAddress& rEndPos2 = ps2->pPair->GetRange(0).aEnd;
1368 0 : if ( rEndPos1.Tab() == rEndPos2.Tab() )
1369 0 : nComp = COMPARE_EQUAL;
1370 : else
1371 : {
1372 0 : ps1->pDoc->GetName( rEndPos1.Tab(), aStr1 );
1373 0 : ps2->pDoc->GetName( rEndPos2.Tab(), aStr2 );
1374 0 : nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
1375 : }
1376 0 : switch ( nComp )
1377 : {
1378 : case COMPARE_LESS:
1379 0 : return -1;
1380 : //break;
1381 : case COMPARE_GREATER:
1382 0 : return 1;
1383 : //break;
1384 : default:
1385 : // gleiche Tabs
1386 0 : if ( rEndPos1.Col() < rEndPos2.Col() )
1387 0 : return -1;
1388 0 : if ( rEndPos1.Col() > rEndPos2.Col() )
1389 0 : return 1;
1390 : // gleiche Cols
1391 0 : if ( rEndPos1.Row() < rEndPos2.Row() )
1392 0 : return -1;
1393 0 : if ( rEndPos1.Row() > rEndPos2.Row() )
1394 0 : return 1;
1395 0 : return 0;
1396 : }
1397 : }
1398 : }
1399 : #ifndef _MSC_VER // MSVC is good enough to warn about unreachable code here.
1400 : // Or stupid enough to bother warning about it, depending
1401 : // on your point of view.
1402 0 : return 0; // just in case
1403 : #endif
1404 : }
1405 :
1406 : //-----------------------------------------------------------------------------
1407 0 : void ScRangePairList::Join( const ScRangePair& r, bool bIsInList )
1408 : {
1409 0 : if ( maPairs.empty() )
1410 : {
1411 0 : Append( r );
1412 0 : return ;
1413 : }
1414 0 : const ScRange& r1 = r.GetRange(0);
1415 0 : const ScRange& r2 = r.GetRange(1);
1416 0 : SCCOL nCol1 = r1.aStart.Col();
1417 0 : SCROW nRow1 = r1.aStart.Row();
1418 0 : SCTAB nTab1 = r1.aStart.Tab();
1419 0 : SCCOL nCol2 = r1.aEnd.Col();
1420 0 : SCROW nRow2 = r1.aEnd.Row();
1421 0 : SCTAB nTab2 = r1.aEnd.Tab();
1422 0 : ScRangePair* pOver = (ScRangePair*) &r; // fies aber wahr wenn bInList
1423 0 : size_t nOldPos = 0;
1424 0 : if ( bIsInList )
1425 : {
1426 : // Find the current position of this range.
1427 0 : for ( size_t i = 0, nPairs = maPairs.size(); i < nPairs; ++i )
1428 : {
1429 0 : if ( maPairs[i] == pOver )
1430 : {
1431 0 : nOldPos = i;
1432 0 : break;
1433 : }
1434 : }
1435 : }
1436 0 : bool bJoinedInput = false;
1437 :
1438 0 : for ( size_t i = 0; i < maPairs.size() && pOver; ++i )
1439 : {
1440 0 : ScRangePair* p = maPairs[ i ];
1441 0 : if ( p == pOver )
1442 0 : continue; // derselbe, weiter mit dem naechsten
1443 0 : bool bJoined = false;
1444 0 : ScRange& rp1 = p->GetRange(0);
1445 0 : ScRange& rp2 = p->GetRange(1);
1446 0 : if ( rp2 == r2 )
1447 : { // nur wenn Range2 gleich ist
1448 0 : if ( rp1.In( r1 ) )
1449 : { // RangePair r in RangePair p enthalten oder identisch
1450 0 : if ( bIsInList )
1451 0 : bJoined = true; // weg mit RangePair r
1452 : else
1453 : { // das war's dann
1454 0 : bJoinedInput = true; // nicht anhaengen
1455 0 : break; // for
1456 : }
1457 : }
1458 0 : else if ( r1.In( rp1 ) )
1459 : { // RangePair p in RangePair r enthalten, r zum neuen RangePair machen
1460 0 : *p = r;
1461 0 : bJoined = true;
1462 : }
1463 : }
1464 0 : if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2
1465 0 : && rp2.aStart.Tab() == r2.aStart.Tab()
1466 0 : && rp2.aEnd.Tab() == r2.aEnd.Tab() )
1467 : { // 2D, Range2 muss genauso nebeneinander liegen wie Range1
1468 0 : if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2
1469 0 : && rp2.aStart.Col() == r2.aStart.Col()
1470 0 : && rp2.aEnd.Col() == r2.aEnd.Col() )
1471 : {
1472 0 : if ( rp1.aStart.Row() == nRow2+1
1473 0 : && rp2.aStart.Row() == r2.aEnd.Row()+1 )
1474 : { // oben
1475 0 : rp1.aStart.SetRow( nRow1 );
1476 0 : rp2.aStart.SetRow( r2.aStart.Row() );
1477 0 : bJoined = true;
1478 : }
1479 0 : else if ( rp1.aEnd.Row() == nRow1-1
1480 0 : && rp2.aEnd.Row() == r2.aStart.Row()-1 )
1481 : { // unten
1482 0 : rp1.aEnd.SetRow( nRow2 );
1483 0 : rp2.aEnd.SetRow( r2.aEnd.Row() );
1484 0 : bJoined = true;
1485 : }
1486 : }
1487 0 : else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2
1488 0 : && rp2.aStart.Row() == r2.aStart.Row()
1489 0 : && rp2.aEnd.Row() == r2.aEnd.Row() )
1490 : {
1491 0 : if ( rp1.aStart.Col() == nCol2+1
1492 0 : && rp2.aStart.Col() == r2.aEnd.Col()+1 )
1493 : { // links
1494 0 : rp1.aStart.SetCol( nCol1 );
1495 0 : rp2.aStart.SetCol( r2.aStart.Col() );
1496 0 : bJoined = true;
1497 : }
1498 0 : else if ( rp1.aEnd.Col() == nCol1-1
1499 0 : && rp2.aEnd.Col() == r2.aEnd.Col()-1 )
1500 : { // rechts
1501 0 : rp1.aEnd.SetCol( nCol2 );
1502 0 : rp2.aEnd.SetCol( r2.aEnd.Col() );
1503 0 : bJoined = true;
1504 : }
1505 : }
1506 : }
1507 0 : if ( bJoined )
1508 : {
1509 0 : if ( bIsInList )
1510 : { // innerhalb der Liste RangePair loeschen
1511 0 : Remove( nOldPos );
1512 0 : i--;
1513 0 : delete pOver;
1514 0 : pOver = NULL;
1515 0 : if ( nOldPos )
1516 0 : nOldPos--; // Seek richtig aufsetzen
1517 : }
1518 0 : bJoinedInput = true;
1519 0 : Join( *p, true ); // rekursiv!
1520 : }
1521 : }
1522 0 : if ( !bIsInList && !bJoinedInput )
1523 0 : Append( r );
1524 : }
1525 :
1526 : //-----------------------------------------------------------------------------
1527 0 : ScRangePair** ScRangePairList::CreateNameSortedArray( size_t& nListCount,
1528 : ScDocument* pDoc ) const
1529 : {
1530 0 : nListCount = maPairs.size();
1531 : OSL_ENSURE( nListCount * sizeof(ScRangePairNameSort) <= (size_t)~0x1F,
1532 : "ScRangePairList::CreateNameSortedArray nListCount * sizeof(ScRangePairNameSort) > (size_t)~0x1F" );
1533 : ScRangePairNameSort* pSortArray = (ScRangePairNameSort*)
1534 0 : new sal_uInt8 [ nListCount * sizeof(ScRangePairNameSort) ];
1535 : sal_uLong j;
1536 0 : for ( j=0; j < nListCount; j++ )
1537 : {
1538 0 : pSortArray[j].pPair = maPairs[ j ];
1539 0 : pSortArray[j].pDoc = pDoc;
1540 : }
1541 0 : qsort( (void*)pSortArray, nListCount, sizeof(ScRangePairNameSort), &ScRangePairList_QsortNameCompare );
1542 : // ScRangePair Pointer aufruecken
1543 0 : ScRangePair** ppSortArray = (ScRangePair**)pSortArray;
1544 0 : for ( j=0; j < nListCount; j++ )
1545 : {
1546 0 : ppSortArray[j] = pSortArray[j].pPair;
1547 : }
1548 0 : return ppSortArray;
1549 : }
1550 :
1551 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|