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