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