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