LibreOffice Module sc (master)  1
rangelst.cxx
Go to the documentation of this file.
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>
22 #include <sal/log.hxx>
23 
24 #include <rangelst.hxx>
25 #include <document.hxx>
26 #include <refupdat.hxx>
27 #include <compiler.hxx>
28 #include <algorithm>
29 #include <memory>
30 
31 using ::std::vector;
32 using ::std::find_if;
33 using ::std::for_each;
34 using ::formula::FormulaGrammar;
35 
36 namespace {
37 
38 template<typename T>
39 class FindEnclosingRange
40 {
41 public:
42  explicit FindEnclosingRange(const T& rTest) : mrTest(rTest) {}
43  bool operator() (const ScRange & rRange) const
44  {
45  return rRange.In(mrTest);
46  }
47 private:
48  const T& mrTest;
49 };
50 
51 template<typename T>
52 class FindRangeIn
53 {
54 public:
55  FindRangeIn(const T& rTest) : mrTest(rTest) {}
56  bool operator() (const ScRange& rRange) const
57  {
58  return mrTest.In(rRange);
59  }
60 private:
61  const T& mrTest;
62 };
63 
64 template<typename T>
65 class FindIntersectingRange
66 {
67 public:
68  explicit FindIntersectingRange(const T& rTest) : mrTest(rTest) {}
69  bool operator() (const ScRange & rRange) const
70  {
71  return rRange.Intersects(mrTest);
72  }
73 private:
74  const T& mrTest;
75 };
76 
77 class CountCells
78 {
79 public:
80  CountCells() : mnCellCount(0) {}
81 
82  void operator() (const ScRange & r)
83  {
84  mnCellCount +=
85  size_t(r.aEnd.Col() - r.aStart.Col() + 1)
86  * size_t(r.aEnd.Row() - r.aStart.Row() + 1)
87  * size_t(r.aEnd.Tab() - r.aStart.Tab() + 1);
88  }
89 
90  size_t getCellCount() const { return mnCellCount; }
91 
92 private:
93  size_t mnCellCount;
94 };
95 
96 
97 }
98 
99 // ScRangeList
101 {
102 }
103 
104 ScRefFlags ScRangeList::Parse( const OUString& rStr, const ScDocument& rDoc,
106  SCTAB nDefaultTab, sal_Unicode cDelimiter )
107 {
108  if ( !rStr.isEmpty() )
109  {
110  if (!cDelimiter)
112 
113  ScRefFlags nResult = ~ScRefFlags::ZERO; // set all bits
114  ScRange aRange;
115  const SCTAB nTab = nDefaultTab;
116 
117  sal_Int32 nPos = 0;
118  do
119  {
120  const OUString aOne = rStr.getToken( 0, cDelimiter, nPos );
121  aRange.aStart.SetTab( nTab ); // default tab if not specified
122  ScRefFlags nRes = aRange.ParseAny( aOne, rDoc, eConv );
124  ScRefFlags nTmp1 = nRes & ScRefFlags::BITS;
125  ScRefFlags nTmp2 = nRes & nEndRangeBits;
126  // If we have a valid single range with
127  // any of the address bits we are interested in
128  // set - set the equiv end range bits
129  if ( (nRes & ScRefFlags::VALID ) && (nTmp1 != ScRefFlags::ZERO) && ( nTmp2 != nEndRangeBits ) )
130  applyStartToEndFlags(nRes, nTmp1);
131 
132  if ( nRes & ScRefFlags::VALID )
133  push_back( aRange );
134  nResult &= nRes; // all common bits are preserved
135  }
136  while (nPos >= 0);
137 
138  return nResult; // ScRefFlags::VALID set when all are OK
139  }
140  else
141  return ScRefFlags::ZERO;
142 }
143 
144 void ScRangeList::Format( OUString& rStr, ScRefFlags nFlags, const ScDocument& rDoc,
146  sal_Unicode cDelimiter, bool bFullAddressNotation ) const
147 {
148  if (!cDelimiter)
150 
151  OUStringBuffer aBuf;
152  bool bFirst = true;
153  for( auto const & r : maRanges)
154  {
155  if (bFirst)
156  bFirst = false;
157  else
158  aBuf.append(OUStringChar(cDelimiter));
159  aBuf.append(r.Format(rDoc, nFlags, eConv, bFullAddressNotation));
160  }
161  rStr = aBuf.makeStringAndClear();
162 }
163 
164 void ScRangeList::Join( const ScRange& rNewRange, bool bIsInList )
165 {
166  if ( maRanges.empty() )
167  {
168  push_back( rNewRange );
169  return ;
170  }
171 
172  // One common usage is to join ranges that actually are top to bottom
173  // appends but the caller doesn't exactly know about it, e.g. when invoked
174  // by ScMarkData::FillRangeListWithMarks(), check for this special case
175  // first and speed up things by not looping over all ranges for each range
176  // to be joined. We don't remember the exact encompassing range that would
177  // have to be updated on refupdates and insertions and deletions, instead
178  // remember just the maximum row used, even independently of the sheet.
179  // This satisfies most use cases.
180 
181  if (!bIsInList)
182  {
183  const SCROW nRow1 = rNewRange.aStart.Row();
184  if (nRow1 > mnMaxRowUsed + 1)
185  {
186  push_back( rNewRange );
187  return;
188  }
189  else if (nRow1 == mnMaxRowUsed + 1)
190  {
191  // Check if we can simply enlarge the last range.
192  ScRange & rLast = maRanges.back();
193  if (rLast.aEnd.Row() + 1 == nRow1 &&
194  rLast.aStart.Col() == rNewRange.aStart.Col() && rLast.aEnd.Col() == rNewRange.aEnd.Col() &&
195  rLast.aStart.Tab() == rNewRange.aStart.Tab() && rLast.aEnd.Tab() == rNewRange.aEnd.Tab())
196  {
197  const SCROW nRow2 = rNewRange.aEnd.Row();
198  rLast.aEnd.SetRow( nRow2 );
199  mnMaxRowUsed = nRow2;
200  return;
201  }
202  }
203  }
204 
205  bool bJoinedInput = false;
206  const ScRange* pOver = &rNewRange;
207 
208 Label_Range_Join:
209 
210  assert(pOver);
211  const SCCOL nCol1 = pOver->aStart.Col();
212  const SCROW nRow1 = pOver->aStart.Row();
213  const SCCOL nTab1 = pOver->aStart.Tab();
214  const SCCOL nCol2 = pOver->aEnd.Col();
215  const SCROW nRow2 = pOver->aEnd.Row();
216  const SCCOL nTab2 = pOver->aEnd.Tab();
217 
218  size_t nOverPos = std::numeric_limits<size_t>::max();
219  for (size_t i = 0; i < maRanges.size(); ++i)
220  {
221  ScRange & rRange = maRanges[i];
222  if ( &rRange == pOver )
223  {
224  nOverPos = i;
225  continue; // the same one, continue with the next
226  }
227  bool bJoined = false;
228  if ( rRange.In( *pOver ) )
229  { // range pOver included in or identical to range p
230  // XXX if we never used Append() before Join() we could remove
231  // pOver and end processing, but it is not guaranteed and there can
232  // be duplicates.
233  if ( bIsInList )
234  bJoined = true; // do away with range pOver
235  else
236  { // that was all then
237  bJoinedInput = true; // don't append
238  break; // for
239  }
240  }
241  else if ( pOver->In( rRange ) )
242  { // range rRange included in range pOver, make pOver the new range
243  rRange = *pOver;
244  bJoined = true;
245  }
246  if ( !bJoined && rRange.aStart.Tab() == nTab1 && rRange.aEnd.Tab() == nTab2 )
247  { // 2D
248  if ( rRange.aStart.Col() == nCol1 && rRange.aEnd.Col() == nCol2 )
249  {
250  if ( rRange.aStart.Row() <= nRow2+1 &&
251  rRange.aStart.Row() >= nRow1 )
252  { // top
253  rRange.aStart.SetRow( nRow1 );
254  bJoined = true;
255  }
256  else if ( rRange.aEnd.Row() >= nRow1-1 &&
257  rRange.aEnd.Row() <= nRow2 )
258  { // bottom
259  rRange.aEnd.SetRow( nRow2 );
260  bJoined = true;
261  }
262  }
263  else if ( rRange.aStart.Row() == nRow1 && rRange.aEnd.Row() == nRow2 )
264  {
265  if ( rRange.aStart.Col() <= nCol2+1 &&
266  rRange.aStart.Col() >= nCol1 )
267  { // left
268  rRange.aStart.SetCol( nCol1 );
269  bJoined = true;
270  }
271  else if ( rRange.aEnd.Col() >= nCol1-1 &&
272  rRange.aEnd.Col() <= nCol2 )
273  { // right
274  rRange.aEnd.SetCol( nCol2 );
275  bJoined = true;
276  }
277  }
278  }
279  if ( bJoined )
280  {
281  if ( bIsInList )
282  { // delete range pOver within the list
283  if (nOverPos != std::numeric_limits<size_t>::max())
284  {
285  Remove(nOverPos);
286  if (nOverPos < i)
287  --i;
288  }
289  else
290  {
291  for (size_t nOver = 0, nRanges = maRanges.size(); nOver < nRanges; ++nOver)
292  {
293  if (&maRanges[nOver] == pOver)
294  {
295  Remove(nOver);
296  break;
297  }
298  }
299  }
300  }
301  bJoinedInput = true;
302  pOver = &maRanges[i];
303  bIsInList = true;
304  goto Label_Range_Join;
305  }
306  }
307  if ( !bIsInList && !bJoinedInput )
308  push_back( rNewRange );
309 }
310 
312 {
313  if ( maRanges.empty() )
314  {
315  push_back( rNewRange );
316  return ;
317  }
318 
319  // One common usage is to join ranges that actually are top to bottom
320  // appends but the caller doesn't exactly know about it, e.g. when invoked
321  // by ScMarkData::FillRangeListWithMarks(), check for this special case
322  // first and speed up things by not looping over all ranges for each range
323  // to be joined. We don't remember the exact encompassing range that would
324  // have to be updated on refupdates and insertions and deletions, instead
325  // remember just the maximum row used, even independently of the sheet.
326  // This satisfies most use cases.
327 
328  const SCROW nRow1 = rNewRange.aStart.Row();
329  if (nRow1 > mnMaxRowUsed + 1)
330  {
331  push_back( rNewRange );
332  return;
333  }
334 
335  // scan backwards 2 rows to see if we can merge with anything
336  auto it = maRanges.rbegin();
337  while (it != maRanges.rend() && it->aStart.Row() >= (rNewRange.aStart.Row() - 2))
338  {
339  // Check if we can simply enlarge this range.
340  ScRange & rLast = *it;
341  if (rLast.aEnd.Row() + 1 == nRow1 &&
342  rLast.aStart.Col() == rNewRange.aStart.Col() && rLast.aEnd.Col() == rNewRange.aEnd.Col() &&
343  rLast.aStart.Tab() == rNewRange.aStart.Tab() && rLast.aEnd.Tab() == rNewRange.aEnd.Tab())
344  {
345  const SCROW nRow2 = rNewRange.aEnd.Row();
346  rLast.aEnd.SetRow( nRow2 );
347  mnMaxRowUsed = std::max(mnMaxRowUsed, nRow2);
348  return;
349  }
350  ++it;
351  }
352 
353  push_back( rNewRange );
354 }
355 
356 bool ScRangeList::operator==( const ScRangeList& r ) const
357 {
358  if ( this == &r )
359  return true;
360 
361  return maRanges == r.maRanges;
362 }
363 
364 bool ScRangeList::operator!=( const ScRangeList& r ) const
365 {
366  return !operator==( r );
367 }
368 
370  UpdateRefMode eUpdateRefMode,
371  const ScDocument* pDoc,
372  const ScRange& rWhere,
373  SCCOL nDx,
374  SCROW nDy,
375  SCTAB nDz
376 )
377 {
378  if (maRanges.empty())
379  // No ranges to update. Bail out.
380  return false;
381 
382  bool bChanged = false;
383  SCCOL nCol1;
384  SCROW nRow1;
385  SCTAB nTab1;
386  SCCOL nCol2;
387  SCROW nRow2;
388  SCTAB nTab2;
389  rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
390 
391  if(eUpdateRefMode == URM_INSDEL)
392  {
393  // right now this only works for nTab1 == nTab2
394  if(nTab1 == nTab2)
395  {
396  if(nDx < 0)
397  {
398  bChanged = DeleteArea(nCol1+nDx, nRow1, nTab1, nCol1-1, nRow2, nTab2);
399  }
400  if(nDy < 0)
401  {
402  bChanged = DeleteArea(nCol1, nRow1+nDy, nTab1, nCol2, nRow1-1, nTab2);
403  }
404  SAL_WARN_IF(nDx < 0 && nDy < 0, "sc", "nDx and nDy are negative, check why");
405  }
406  }
407 
408  if(maRanges.empty())
409  return true;
410 
411  for (auto& rR : maRanges)
412  {
413  SCCOL theCol1;
414  SCROW theRow1;
415  SCTAB theTab1;
416  SCCOL theCol2;
417  SCROW theRow2;
418  SCTAB theTab2;
419  rR.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
420  if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
421  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
422  nDx, nDy, nDz,
423  theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
424  != UR_NOTHING )
425  {
426  bChanged = true;
427  rR.aStart.Set( theCol1, theRow1, theTab1 );
428  rR.aEnd.Set( theCol2, theRow2, theTab2 );
429  if (mnMaxRowUsed < theRow2)
430  mnMaxRowUsed = theRow2;
431  }
432  }
433 
434  if(eUpdateRefMode == URM_INSDEL)
435  {
436  if( nDx < 0 || nDy < 0 )
437  {
438  size_t n = maRanges.size();
439  Join(maRanges[n-1], true);
440  }
441  }
442 
443  return bChanged;
444 }
445 
446 void ScRangeList::InsertRow( SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize )
447 {
448  std::vector<ScRange> aNewRanges;
449  for(const auto & rRange : maRanges)
450  {
451  if(rRange.aStart.Tab() <= nTab && rRange.aEnd.Tab() >= nTab)
452  {
453  if(rRange.aEnd.Row() == nRowPos - 1 && (nColStart <= rRange.aEnd.Col() || nColEnd >= rRange.aStart.Col()))
454  {
455  SCCOL nNewRangeStartCol = std::max<SCCOL>(nColStart, rRange.aStart.Col());
456  SCCOL nNewRangeEndCol = std::min<SCCOL>(nColEnd, rRange.aEnd.Col());
457  SCROW nNewRangeStartRow = rRange.aEnd.Row() + 1;
458  SCROW nNewRangeEndRow = nRowPos + nSize - 1;
459  aNewRanges.emplace_back(nNewRangeStartCol, nNewRangeStartRow, nTab, nNewRangeEndCol,
460  nNewRangeEndRow, nTab);
461  if (mnMaxRowUsed < nNewRangeEndRow)
462  mnMaxRowUsed = nNewRangeEndRow;
463  }
464  }
465  }
466 
467  for(const auto & rRange : aNewRanges)
468  {
469  if(!rRange.IsValid())
470  continue;
471 
472  Join(rRange);
473  }
474 }
475 
476 void ScRangeList::InsertCol( SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize )
477 {
478  std::vector<ScRange> aNewRanges;
479  for(const auto & rRange : maRanges)
480  {
481  if(rRange.aStart.Tab() <= nTab && rRange.aEnd.Tab() >= nTab)
482  {
483  if(rRange.aEnd.Col() == nColPos - 1 && (nRowStart <= rRange.aEnd.Row() || nRowEnd >= rRange.aStart.Row()))
484  {
485  SCROW nNewRangeStartRow = std::max<SCROW>(nRowStart, rRange.aStart.Row());
486  SCROW nNewRangeEndRow = std::min<SCROW>(nRowEnd, rRange.aEnd.Row());
487  SCCOL nNewRangeStartCol = rRange.aEnd.Col() + 1;
488  SCCOL nNewRangeEndCol = nColPos + nSize - 1;
489  aNewRanges.emplace_back(nNewRangeStartCol, nNewRangeStartRow, nTab, nNewRangeEndCol,
490  nNewRangeEndRow, nTab);
491  }
492  }
493  }
494 
495  for(const auto & rRange : aNewRanges)
496  {
497  if(!rRange.IsValid())
498  continue;
499 
500  Join(rRange);
501  }
502 }
503 
505 {
506  std::vector<ScRange> aNewRanges;
507  for(const auto & rRange : maRanges)
508  {
509  if(rRange.aStart.Tab() <= nTab && rRange.aEnd.Tab() >= nTab)
510  {
511  if(rRange.aEnd.Col() == nCol - 1)
512  {
513  SCCOL nNewRangeStartCol = rRange.aEnd.Col() + 1;
514  SCCOL nNewRangeEndCol = nCol;
515  aNewRanges.emplace_back(nNewRangeStartCol, rRange.aStart.Row(), nTab, nNewRangeEndCol,
516  rRange.aEnd.Row(), nTab);
517  }
518  }
519  }
520 
521  for(const auto & rRange : aNewRanges)
522  {
523  if(!rRange.IsValid())
524  continue;
525 
526  Join(rRange);
527  }
528 }
529 
530 namespace {
531 
551 template<typename X, typename Y>
552 bool checkForOneRange(
553  X nDeleteX1, X nDeleteX2, Y nDeleteY1, Y nDeleteY2, X nX1, X nX2, Y nY1, Y nY2)
554 {
555  return nDeleteX1 <= nX1 && nX2 <= nDeleteX2 && (nDeleteY1 <= nY1 || nY2 <= nDeleteY2);
556 }
557 
558 bool handleOneRange( const ScRange& rDeleteRange, ScRange& r )
559 {
560  const ScAddress& rDelStart = rDeleteRange.aStart;
561  const ScAddress& rDelEnd = rDeleteRange.aEnd;
562  ScAddress aPStart = r.aStart;
563  ScAddress aPEnd = r.aEnd;
564  SCCOL nDeleteCol1 = rDelStart.Col();
565  SCCOL nDeleteCol2 = rDelEnd.Col();
566  SCROW nDeleteRow1 = rDelStart.Row();
567  SCROW nDeleteRow2 = rDelEnd.Row();
568  SCCOL nCol1 = aPStart.Col();
569  SCCOL nCol2 = aPEnd.Col();
570  SCROW nRow1 = aPStart.Row();
571  SCROW nRow2 = aPEnd.Row();
572 
573  if (checkForOneRange(nDeleteCol1, nDeleteCol2, nDeleteRow1, nDeleteRow2, nCol1, nCol2, nRow1, nRow2))
574  {
575  // Deleting range fully overlaps the column range. Adjust the row span.
576  if (nDeleteRow1 <= nRow1)
577  {
578  // +------+
579  // |xxxxxx|
580  // +------+
581  // | |
582  // +------+ (xxx) = deleted region
583 
584  r.aStart.SetRow(nDeleteRow1+1);
585  return true;
586  }
587  else if (nRow2 <= nDeleteRow2)
588  {
589  // +------+
590  // | |
591  // +------+
592  // |xxxxxx|
593  // +------+ (xxx) = deleted region
594 
595  r.aEnd.SetRow(nDeleteRow1-1);
596  return true;
597  }
598  }
599  else if (checkForOneRange(nDeleteRow1, nDeleteRow2, nDeleteCol1, nDeleteCol2, nRow1, nRow2, nCol1, nCol2))
600  {
601  // Deleting range fully overlaps the row range. Adjust the column span.
602  if (nDeleteCol1 <= nCol1)
603  {
604  // +--+--+
605  // |xx| |
606  // |xx| |
607  // |xx| |
608  // +--+--+ (xxx) = deleted region
609 
610  r.aStart.SetCol(nDeleteCol2+1);
611  return true;
612  }
613  else if (nCol2 <= nDeleteCol2)
614  {
615  // +--+--+
616  // | |xx|
617  // | |xx|
618  // | |xx|
619  // +--+--+ (xxx) = deleted region
620 
621  r.aEnd.SetCol(nDeleteCol1-1);
622  return true;
623  }
624  }
625  return false;
626 }
627 
628 bool handleTwoRanges( const ScRange& rDeleteRange, ScRange& r, std::vector<ScRange>& rNewRanges )
629 {
630  const ScAddress& rDelStart = rDeleteRange.aStart;
631  const ScAddress& rDelEnd = rDeleteRange.aEnd;
632  ScAddress aPStart = r.aStart;
633  ScAddress aPEnd = r.aEnd;
634  SCCOL nDeleteCol1 = rDelStart.Col();
635  SCCOL nDeleteCol2 = rDelEnd.Col();
636  SCROW nDeleteRow1 = rDelStart.Row();
637  SCROW nDeleteRow2 = rDelEnd.Row();
638  SCCOL nCol1 = aPStart.Col();
639  SCCOL nCol2 = aPEnd.Col();
640  SCROW nRow1 = aPStart.Row();
641  SCROW nRow2 = aPEnd.Row();
642  SCTAB nTab = aPStart.Tab();
643 
644  if (nCol1 < nDeleteCol1 && nDeleteCol1 <= nCol2 && nCol2 <= nDeleteCol2)
645  {
646  // column deleted : |-------|
647  // column original: |-------|
648  if (nRow1 < nDeleteRow1 && nDeleteRow1 <= nRow2 && nRow2 <= nDeleteRow2)
649  {
650  // row deleted: |------|
651  // row original: |------|
652  //
653  // +-------+
654  // | 1 |
655  // +---+---+---+
656  // | 2 |xxxxxxx|
657  // +---+xxxxxxx|
658  // |xxxxxxx|
659  // +-------+ (xxx) deleted region
660 
661  ScRange aNewRange( nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nRow2, nTab ); // 2
662  rNewRanges.push_back(aNewRange);
663 
664  r.aEnd.SetRow(nDeleteRow1-1); // 1
665  return true;
666  }
667  else if (nRow1 <= nDeleteRow2 && nDeleteRow2 < nRow2 && nDeleteRow1 <= nRow1)
668  {
669  // row deleted: |------|
670  // row original: |------|
671  //
672  // +-------+
673  // |xxxxxxx|
674  // +---+xxxxxxx|
675  // | 1 |xxxxxxx|
676  // +---+---+---+
677  // | 2 | (xxx) deleted region
678  // +-------+
679 
680  ScRange aNewRange( aPStart, ScAddress(nDeleteCol1-1, nRow2, nTab) ); // 1
681  rNewRanges.push_back(aNewRange);
682 
683  r.aStart.SetRow(nDeleteRow2+1); // 2
684  return true;
685  }
686  }
687  else if (nCol1 <= nDeleteCol2 && nDeleteCol2 < nCol2 && nDeleteCol1 <= nCol1)
688  {
689  // column deleted : |-------|
690  // column original: |-------|
691  if (nRow1 < nDeleteRow1 && nDeleteRow1 <= nRow2 && nRow2 <= nDeleteRow2)
692  {
693  // row deleted: |------|
694  // row original: |------|
695  //
696  // +-------+
697  // | 1 |
698  // +-------+---+
699  // |xxxxxxx| 2 |
700  // |xxxxxxx+---+
701  // |xxxxxxx|
702  // +-------+
703  // (xxx) deleted region
704 
705  ScRange aNewRange( ScAddress( nDeleteCol2+1, nDeleteRow1, nTab ), aPEnd ); // 2
706  rNewRanges.push_back(aNewRange);
707 
708  r.aEnd.SetRow(nDeleteRow1-1); // 1
709  return true;
710  }
711  else if (nRow1 <= nDeleteRow2 && nDeleteRow2 < nRow2 && nDeleteRow1 <= nRow1)
712  {
713  // row deleted: |-------|
714  // row original: |--------|
715  //
716  // +-------+
717  // |xxxxxxx|
718  // |xxxxxxx+---+
719  // |xxxxxxx| 1 |
720  // +-------+---+
721  // | 2 |
722  // +-------+ (xxx) deleted region
723 
724  ScRange aNewRange(nDeleteCol2+1, nRow1, nTab, nCol2, nDeleteRow2, nTab); // 1
725  rNewRanges.push_back(aNewRange);
726 
727  r.aStart.SetRow(nDeleteRow2+1); // 2
728  return true;
729  }
730  }
731  else if (nRow1 < nDeleteRow1 && nDeleteRow2 < nRow2 && nDeleteCol1 <= nCol1 && nCol2 <= nDeleteCol2)
732  {
733  // +--------+
734  // | 1 |
735  // +--------+
736  // |xxxxxxxx| (xxx) deleted region
737  // +--------+
738  // | 2 |
739  // +--------+
740 
741  ScRange aNewRange( aPStart, ScAddress(nCol2, nDeleteRow1-1, nTab) ); // 1
742  rNewRanges.push_back(aNewRange);
743 
744  r.aStart.SetRow(nDeleteRow2+1); // 2
745  return true;
746  }
747  else if (nCol1 < nDeleteCol1 && nDeleteCol2 < nCol2 && nDeleteRow1 <= nRow1 && nRow2 <= nDeleteRow2)
748  {
749  // +---+-+---+
750  // | |x| |
751  // | |x| |
752  // | 1 |x| 2 | (xxx) deleted region
753  // | |x| |
754  // | |x| |
755  // +---+-+---+
756 
757  ScRange aNewRange( aPStart, ScAddress(nDeleteCol1-1, nRow2, nTab) ); // 1
758  rNewRanges.push_back(aNewRange);
759 
760  r.aStart.SetCol(nDeleteCol2+1); // 2
761  return true;
762  }
763 
764  return false;
765 }
766 
791 template<typename X, typename Y>
792 bool checkForThreeRanges(
793  X nDeleteX1, X nDeleteX2, Y nDeleteY1, Y nDeleteY2, X nX1, X nX2, Y nY1, Y nY2)
794 {
795  if (nX1 <= nDeleteX1 && nX2 <= nDeleteX2 && nY1 < nDeleteY1 && nDeleteY2 < nY2)
796  return true;
797 
798  if (nDeleteX1 <= nX1 && nDeleteX2 <= nX2 && nY1 < nDeleteY1 && nDeleteY2 < nY2)
799  return true;
800 
801  return false;
802 }
803 
804 bool handleThreeRanges( const ScRange& rDeleteRange, ScRange& r, std::vector<ScRange>& rNewRanges )
805 {
806  const ScAddress& rDelStart = rDeleteRange.aStart;
807  const ScAddress& rDelEnd = rDeleteRange.aEnd;
808  ScAddress aPStart = r.aStart;
809  ScAddress aPEnd = r.aEnd;
810  SCCOL nDeleteCol1 = rDelStart.Col();
811  SCCOL nDeleteCol2 = rDelEnd.Col();
812  SCROW nDeleteRow1 = rDelStart.Row();
813  SCROW nDeleteRow2 = rDelEnd.Row();
814  SCCOL nCol1 = aPStart.Col();
815  SCCOL nCol2 = aPEnd.Col();
816  SCROW nRow1 = aPStart.Row();
817  SCROW nRow2 = aPEnd.Row();
818  SCTAB nTab = aPStart.Tab();
819 
820  if (checkForThreeRanges(nDeleteCol1, nDeleteCol2, nDeleteRow1, nDeleteRow2, nCol1, nCol2, nRow1, nRow2))
821  {
822  if (nCol1 < nDeleteCol1)
823  {
824  // +---+------+
825  // | | 2 |
826  // | +------+---+
827  // | 1 |xxxxxxxxxx|
828  // | +------+---+
829  // | | 3 |
830  // +---+------+
831 
832  ScRange aNewRange(nDeleteCol1, nRow1, nTab, nCol2, nDeleteRow1-1, nTab); // 2
833  rNewRanges.push_back(aNewRange);
834 
835  aNewRange = ScRange(ScAddress(nDeleteCol1, nDeleteRow2+1, nTab), aPEnd); // 3
836  rNewRanges.push_back(aNewRange);
837 
838  r.aEnd.SetCol(nDeleteCol1-1); // 1
839  }
840  else
841  {
842  // +------+---+
843  // | 1 | |
844  // +---+------+ |
845  // |xxxxxxxxxx| 2 |
846  // +---+------+ |
847  // | 3 | |
848  // +------+---+
849 
850  ScRange aNewRange(aPStart, ScAddress(nDeleteCol2, nDeleteRow1-1, nTab)); // 1
851  rNewRanges.push_back(aNewRange);
852 
853  aNewRange = ScRange(nCol1, nDeleteRow2+1, nTab, nDeleteCol2, nRow2, nTab); // 3
854  rNewRanges.push_back(aNewRange);
855 
856  r.aStart.SetCol(nDeleteCol2+1); // 2
857  }
858  return true;
859  }
860  else if (checkForThreeRanges(nDeleteRow1, nDeleteRow2, nDeleteCol1, nDeleteCol2, nRow1, nRow2, nCol1, nCol2))
861  {
862  if (nRow1 < nDeleteRow1)
863  {
864  // +----------+
865  // | 1 |
866  // +---+--+---+
867  // | |xx| |
868  // | 2 |xx| 3 |
869  // | |xx| |
870  // +---+xx+---+
871  // |xx|
872  // +--+
873 
874  ScRange aNewRange(nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nRow2, nTab); // 2
875  rNewRanges.push_back( aNewRange );
876 
877  aNewRange = ScRange(ScAddress(nDeleteCol2+1, nDeleteRow1, nTab), aPEnd); // 3
878  rNewRanges.push_back( aNewRange );
879 
880  r.aEnd.SetRow(nDeleteRow1-1); // 1
881  }
882  else
883  {
884  // +--+
885  // |xx|
886  // +---+xx+---+
887  // | 1 |xx| 2 |
888  // | |xx| |
889  // +---+--+---+
890  // | 3 |
891  // +----------+
892 
893  ScRange aNewRange(aPStart, ScAddress(nDeleteCol1-1, nDeleteRow2, nTab)); // 1
894  rNewRanges.push_back(aNewRange);
895 
896  aNewRange = ScRange(nDeleteCol2+1, nRow1, nTab, nCol2, nDeleteRow2, nTab); // 2
897  rNewRanges.push_back( aNewRange );
898 
899  r.aStart.SetRow(nDeleteRow2+1); // 3
900  }
901  return true;
902  }
903 
904  return false;
905 }
906 
907 bool handleFourRanges( const ScRange& rDelRange, ScRange& r, std::vector<ScRange>& rNewRanges )
908 {
909  const ScAddress& rDelStart = rDelRange.aStart;
910  const ScAddress& rDelEnd = rDelRange.aEnd;
911  ScAddress aPStart = r.aStart;
912  ScAddress aPEnd = r.aEnd;
913  SCCOL nDeleteCol1 = rDelStart.Col();
914  SCCOL nDeleteCol2 = rDelEnd.Col();
915  SCROW nDeleteRow1 = rDelStart.Row();
916  SCROW nDeleteRow2 = rDelEnd.Row();
917  SCCOL nCol1 = aPStart.Col();
918  SCCOL nCol2 = aPEnd.Col();
919  SCROW nRow1 = aPStart.Row();
920  SCROW nRow2 = aPEnd.Row();
921  SCTAB nTab = aPStart.Tab();
922 
923  if (nCol1 < nDeleteCol1 && nDeleteCol2 < nCol2 && nRow1 < nDeleteRow1 && nDeleteRow2 < nRow2)
924  {
925 
926  // +---------------+
927  // | 1 |
928  // +---+-------+---+
929  // | |xxxxxxx| |
930  // | 2 |xxxxxxx| 3 |
931  // | |xxxxxxx| |
932  // +---+-------+---+
933  // | 4 |
934  // +---------------+
935 
936  ScRange aNewRange(ScAddress(nCol1, nDeleteRow2+1, nTab), aPEnd); // 4
937  rNewRanges.push_back( aNewRange );
938 
939  aNewRange = ScRange(nCol1, nDeleteRow1, nTab, nDeleteCol1-1, nDeleteRow2, nTab); // 2
940  rNewRanges.push_back( aNewRange );
941 
942  aNewRange = ScRange(nDeleteCol2+1, nDeleteRow1, nTab, nCol2, nDeleteRow2, nTab); // 3
943  rNewRanges.push_back( aNewRange );
944 
945  r.aEnd.SetRow(nDeleteRow1-1); // 1
946 
947  return true;
948  }
949 
950  return false;
951 }
952 
953 }
954 
955 bool ScRangeList::DeleteArea( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
956  SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
957 {
958  bool bChanged = false;
959  ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
960  for(size_t i = 0; i < maRanges.size();)
961  {
962  if(FindRangeIn< ScRange >(aRange)(maRanges[i]))
963  {
964  Remove(i);
965  bChanged = true;
966  }
967  else
968  ++i;
969  }
970 
971  std::vector<ScRange> aNewRanges;
972 
973  for(auto & rRange : maRanges)
974  {
975  // we have two basic cases here:
976  // 1. Delete area and pRange intersect
977  // 2. Delete area and pRange are not intersecting
978  // checking for 2 and if true skip this range
979  if(!rRange.Intersects(aRange))
980  continue;
981 
982  // We get between 1 and 4 ranges from the difference of the first with the second
983 
984  // X either Col or Row and Y then the opposite
985  // r = deleteRange, p = entry from ScRangeList
986 
987  // getting exactly one range is the simple case
988  // r.aStart.X() <= p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
989  // && ( r.aStart.Y() <= p.aStart.Y() || r.aEnd.Y() >= r.aEnd.Y() )
990  if(handleOneRange( aRange, rRange ))
991  {
992  bChanged = true;
993  continue;
994  }
995 
996  // getting two ranges
997  // r.aStart.X()
998  else if(handleTwoRanges( aRange, rRange, aNewRanges ))
999  {
1000  bChanged = true;
1001  continue;
1002  }
1003 
1004  // getting 3 ranges
1005  // r.aStart.X() > p.aStart.X() && r.aEnd.X() >= p.aEnd.X()
1006  // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
1007  // or
1008  // r.aStart.X() <= p.aStart.X() && r.aEnd.X() < p.aEnd.X()
1009  // && r.aStart.Y() > p.aStart.Y() && r.aEnd.Y() < p.aEnd.Y()
1010  else if(handleThreeRanges( aRange, rRange, aNewRanges ))
1011  {
1012  bChanged = true;
1013  continue;
1014  }
1015 
1016  // getting 4 ranges
1017  // r.aStart.X() > p.aStart.X() && r.aEnd().X() < p.aEnd.X()
1018  // && r.aStart.Y() > p.aStart.Y() && r.aEnd().Y() < p.aEnd.Y()
1019  else if(handleFourRanges( aRange, rRange, aNewRanges ))
1020  {
1021  bChanged = true;
1022  continue;
1023  }
1024  }
1025  for(const auto & rRange : aNewRanges)
1026  Join(rRange);
1027 
1028  return bChanged;
1029 }
1030 
1031 const ScRange* ScRangeList::Find( const ScAddress& rAdr ) const
1032 {
1033  auto itr = find_if(
1034  maRanges.cbegin(), maRanges.cend(), FindEnclosingRange<ScAddress>(rAdr));
1035  return itr == maRanges.end() ? nullptr : &*itr;
1036 }
1037 
1039 {
1040  auto itr = find_if(
1041  maRanges.begin(), maRanges.end(), FindEnclosingRange<ScAddress>(rAdr));
1042  return itr == maRanges.end() ? nullptr : &*itr;
1043 }
1044 
1045 ScRangeList::ScRangeList() : mnMaxRowUsed(-1) {}
1046 
1048  SvRefBase(rList),
1049  maRanges(rList.maRanges),
1050  mnMaxRowUsed(rList.mnMaxRowUsed)
1051 {
1052 }
1053 
1055  SvRefBase(),
1056  maRanges(std::move(rList.maRanges)),
1057  mnMaxRowUsed(rList.mnMaxRowUsed)
1058 {
1059 }
1060 
1062  mnMaxRowUsed(-1)
1063 {
1064  maRanges.reserve(1);
1065  push_back(rRange);
1066 }
1067 
1069 {
1070  maRanges = rList.maRanges;
1071  mnMaxRowUsed = rList.mnMaxRowUsed;
1072  return *this;
1073 }
1074 
1076 {
1077  maRanges = std::move(rList.maRanges);
1078  mnMaxRowUsed = rList.mnMaxRowUsed;
1079  return *this;
1080 }
1081 
1082 bool ScRangeList::Intersects( const ScRange& rRange ) const
1083 {
1084  return std::any_of(maRanges.begin(), maRanges.end(), FindIntersectingRange<ScRange>(rRange));
1085 }
1086 
1087 bool ScRangeList::In( const ScRange& rRange ) const
1088 {
1089  return std::any_of(maRanges.begin(), maRanges.end(), FindEnclosingRange<ScRange>(rRange));
1090 }
1091 
1093 {
1094  CountCells func;
1095  return for_each(maRanges.begin(), maRanges.end(), func).getCellCount();
1096 }
1097 
1098 void ScRangeList::Remove(size_t nPos)
1099 {
1100  if (maRanges.size() <= nPos)
1101  // Out-of-bound condition. Bail out.
1102  return;
1103  maRanges.erase(maRanges.begin() + nPos);
1104 }
1105 
1107 {
1108  maRanges.clear();
1109  mnMaxRowUsed = -1;
1110 }
1111 
1113 {
1114  if (maRanges.empty())
1115  return ScRange();
1116 
1117  auto itr = maRanges.cbegin(), itrEnd = maRanges.cend();
1118  ScRange aRet = *itr;
1119  ++itr;
1120  for (; itr != itrEnd; ++itr)
1121  {
1122  const ScRange& r = *itr;
1123  SCROW nRow1 = r.aStart.Row(), nRow2 = r.aEnd.Row();
1124  SCCOL nCol1 = r.aStart.Col(), nCol2 = r.aEnd.Col();
1125  SCTAB nTab1 = r.aStart.Tab(), nTab2 = r.aEnd.Tab();
1126  if (aRet.aStart.Row() > nRow1)
1127  aRet.aStart.SetRow(nRow1);
1128  if (aRet.aStart.Col() > nCol1)
1129  aRet.aStart.SetCol(nCol1);
1130  if (aRet.aStart.Tab() > nTab1)
1131  aRet.aStart.SetTab(nTab1);
1132  if (aRet.aEnd.Row() < nRow2)
1133  aRet.aEnd.SetRow(nRow2);
1134  if (aRet.aEnd.Col() < nCol2)
1135  aRet.aEnd.SetCol(nCol2);
1136  if (aRet.aEnd.Tab() < nTab2)
1137  aRet.aEnd.SetTab(nTab2);
1138  }
1139  return aRet;
1140 }
1141 
1143 {
1144  maRanges.push_back(r);
1145  if (mnMaxRowUsed < r.aEnd.Row())
1146  mnMaxRowUsed = r.aEnd.Row();
1147 }
1148 
1150 {
1151  maRanges.swap(r.maRanges);
1152  std::swap(mnMaxRowUsed, r.mnMaxRowUsed);
1153 }
1154 
1156 {
1157  if(empty())
1158  return ScAddress();
1159 
1160  ScAddress const * pAddr = &maRanges[0].aStart;
1161  for(size_t i = 1, n = size(); i < n; ++i)
1162  {
1163  if(maRanges[i].aStart < *pAddr)
1164  pAddr = &maRanges[i].aStart;
1165  }
1166 
1167  return *pAddr;
1168 }
1169 
1171 {
1172  ScRangeList aReturn;
1173  for(auto& rR : maRanges)
1174  {
1175  if(rR.Intersects(rRange))
1176  {
1177  SCCOL nColStart1, nColEnd1, nColStart2, nColEnd2;
1178  SCROW nRowStart1, nRowEnd1, nRowStart2, nRowEnd2;
1179  SCTAB nTabStart1, nTabEnd1, nTabStart2, nTabEnd2;
1180  rR.GetVars(nColStart1, nRowStart1, nTabStart1,
1181  nColEnd1, nRowEnd1, nTabEnd1);
1182  rRange.GetVars(nColStart2, nRowStart2, nTabStart2,
1183  nColEnd2, nRowEnd2, nTabEnd2);
1184 
1185  ScRange aNewRange(std::max<SCCOL>(nColStart1, nColStart2), std::max<SCROW>(nRowStart1, nRowStart2),
1186  std::max<SCTAB>(nTabStart1, nTabStart2), std::min<SCCOL>(nColEnd1, nColEnd2),
1187  std::min<SCROW>(nRowEnd1, nRowEnd2), std::min<SCTAB>(nTabEnd1, nTabEnd2));
1188  aReturn.Join(aNewRange);
1189  }
1190  }
1191 
1192  return aReturn;
1193 }
1194 
1195 // ScRangePairList
1197 {
1198 }
1199 
1200 void ScRangePairList::Remove(size_t nPos)
1201 {
1202  if (maPairs.size() <= nPos)
1203  // Out-of-bound condition. Bail out.
1204  return;
1205  maPairs.erase(maPairs.begin() + nPos);
1206 }
1207 
1209 {
1210  auto itr = std::find_if(maPairs.begin(), maPairs.end(), [&rAdr](const ScRangePair& rPair) { return &rAdr == &rPair; });
1211  if (itr != maPairs.end())
1212  {
1213  maPairs.erase( itr );
1214  return;
1215  }
1216  assert(false);
1217 }
1218 
1220 {
1221  return maPairs[idx];
1222 }
1223 
1225 {
1226  return maPairs[idx];
1227 }
1228 
1230 {
1231  return maPairs.size();
1232 }
1233 
1235  const ScDocument* pDoc, const ScRange& rWhere,
1236  SCCOL nDx, SCROW nDy, SCTAB nDz )
1237 {
1238  if ( maPairs.empty() )
1239  return;
1240 
1241  SCCOL nCol1;
1242  SCROW nRow1;
1243  SCTAB nTab1;
1244  SCCOL nCol2;
1245  SCROW nRow2;
1246  SCTAB nTab2;
1247  rWhere.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1248  for (ScRangePair & rR : maPairs)
1249  {
1250  for ( sal_uInt16 j=0; j<2; j++ )
1251  {
1252  ScRange& rRange = rR.GetRange(j);
1253  SCCOL theCol1;
1254  SCROW theRow1;
1255  SCTAB theTab1;
1256  SCCOL theCol2;
1257  SCROW theRow2;
1258  SCTAB theTab2;
1259  rRange.GetVars( theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 );
1260  if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
1261  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
1262  nDx, nDy, nDz,
1263  theCol1, theRow1, theTab1, theCol2, theRow2, theTab2 )
1264  != UR_NOTHING )
1265  {
1266  rRange.aStart.Set( theCol1, theRow1, theTab1 );
1267  rRange.aEnd.Set( theCol2, theRow2, theTab2 );
1268  }
1269  }
1270  }
1271 }
1272 
1273 // Delete entries that have the labels (first range) on nTab
1275 {
1276  maPairs.erase(std::remove_if(maPairs.begin(), maPairs.end(),
1277  [&nTab](const ScRangePair& rR) {
1278  const ScRange & rRange = rR.GetRange(0);
1279  return (rRange.aStart.Tab() == nTab) && (rRange.aEnd.Tab() == nTab);
1280  }),
1281  maPairs.end());
1282 }
1283 
1285 {
1286  for (ScRangePair & rR : maPairs)
1287  {
1288  if ( rR.GetRange(0).In( rAdr ) )
1289  return &rR;
1290  }
1291  return nullptr;
1292 }
1293 
1295 {
1296  for (ScRangePair & rR : maPairs)
1297  {
1298  if ( rR.GetRange(0) == rRange )
1299  return &rR;
1300  }
1301  return nullptr;
1302 }
1303 
1305 {
1306  ScRangePairList* pNew = new ScRangePairList;
1307  for (const ScRangePair & rR : maPairs)
1308  {
1309  pNew->Append( rR );
1310  }
1311  return pNew;
1312 }
1313 
1314 namespace {
1315 
1316 class ScRangePairList_sortNameCompare
1317 {
1318 public:
1319  ScRangePairList_sortNameCompare(ScDocument& rDoc) : mrDoc(rDoc) {}
1320 
1321  bool operator()( const ScRangePair *ps1, const ScRangePair* ps2 ) const
1322  {
1323  const ScAddress& rStartPos1 = ps1->GetRange(0).aStart;
1324  const ScAddress& rStartPos2 = ps2->GetRange(0).aStart;
1325  OUString aStr1, aStr2;
1326  sal_Int32 nComp;
1327  if ( rStartPos1.Tab() == rStartPos2.Tab() )
1328  nComp = 0;
1329  else
1330  {
1331  mrDoc.GetName( rStartPos1.Tab(), aStr1 );
1332  mrDoc.GetName( rStartPos2.Tab(), aStr2 );
1333  nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
1334  }
1335  if (nComp < 0)
1336  {
1337  return true; // -1;
1338  }
1339  else if (nComp > 0)
1340  {
1341  return false; // 1;
1342  }
1343 
1344  // equal tabs
1345  if ( rStartPos1.Col() < rStartPos2.Col() )
1346  return true; // -1;
1347  if ( rStartPos1.Col() > rStartPos2.Col() )
1348  return false; // 1;
1349  // equal cols
1350  if ( rStartPos1.Row() < rStartPos2.Row() )
1351  return true; // -1;
1352  if ( rStartPos1.Row() > rStartPos2.Row() )
1353  return false; // 1;
1354 
1355  // first corner equal, second corner
1356  const ScAddress& rEndPos1 = ps1->GetRange(0).aEnd;
1357  const ScAddress& rEndPos2 = ps2->GetRange(0).aEnd;
1358  if ( rEndPos1.Tab() == rEndPos2.Tab() )
1359  nComp = 0;
1360  else
1361  {
1362  mrDoc.GetName( rEndPos1.Tab(), aStr1 );
1363  mrDoc.GetName( rEndPos2.Tab(), aStr2 );
1364  nComp = ScGlobal::GetCollator()->compareString( aStr1, aStr2 );
1365  }
1366  if (nComp < 0)
1367  {
1368  return true; // -1;
1369  }
1370  else if (nComp > 0)
1371  {
1372  return false; // 1;
1373  }
1374 
1375  // equal tabs
1376  if ( rEndPos1.Col() < rEndPos2.Col() )
1377  return true; // -1;
1378  if ( rEndPos1.Col() > rEndPos2.Col() )
1379  return false; // 1;
1380  // equal cols
1381  if ( rEndPos1.Row() < rEndPos2.Row() )
1382  return true; // -1;
1383  if ( rEndPos1.Row() > rEndPos2.Row() )
1384  return false; // 1;
1385 
1386  return false;
1387  }
1388 private:
1389  ScDocument& mrDoc;
1390 };
1391 
1392 }
1393 
1394 void ScRangePairList::Join( const ScRangePair& r, bool bIsInList )
1395 {
1396  if ( maPairs.empty() )
1397  {
1398  Append( r );
1399  return ;
1400  }
1401 
1402  bool bJoinedInput = false;
1403  const ScRangePair* pOver = &r;
1404 
1405 Label_RangePair_Join:
1406 
1407  assert(pOver);
1408  const ScRange& r1 = pOver->GetRange(0);
1409  const ScRange& r2 = pOver->GetRange(1);
1410  const SCCOL nCol1 = r1.aStart.Col();
1411  const SCROW nRow1 = r1.aStart.Row();
1412  const SCTAB nTab1 = r1.aStart.Tab();
1413  const SCCOL nCol2 = r1.aEnd.Col();
1414  const SCROW nRow2 = r1.aEnd.Row();
1415  const SCTAB nTab2 = r1.aEnd.Tab();
1416 
1417  size_t nOverPos = std::numeric_limits<size_t>::max();
1418  for (size_t i = 0; i < maPairs.size(); ++i)
1419  {
1420  ScRangePair & rPair = maPairs[ i ];
1421  if ( &rPair == pOver )
1422  {
1423  nOverPos = i;
1424  continue; // the same one, continue with the next
1425  }
1426  bool bJoined = false;
1427  ScRange& rp1 = rPair.GetRange(0);
1428  ScRange& rp2 = rPair.GetRange(1);
1429  if ( rp2 == r2 )
1430  { // only if Range2 is equal
1431  if ( rp1.In( r1 ) )
1432  { // RangePair pOver included in or identical to RangePair p
1433  if ( bIsInList )
1434  bJoined = true; // do away with RangePair pOver
1435  else
1436  { // that was all then
1437  bJoinedInput = true; // don't append
1438  break; // for
1439  }
1440  }
1441  else if ( r1.In( rp1 ) )
1442  { // RangePair p included in RangePair pOver, make pOver the new RangePair
1443  rPair = *pOver;
1444  bJoined = true;
1445  }
1446  }
1447  if ( !bJoined && rp1.aStart.Tab() == nTab1 && rp1.aEnd.Tab() == nTab2
1448  && rp2.aStart.Tab() == r2.aStart.Tab()
1449  && rp2.aEnd.Tab() == r2.aEnd.Tab() )
1450  { // 2D, Range2 must be located side-by-side just like Range1
1451  if ( rp1.aStart.Col() == nCol1 && rp1.aEnd.Col() == nCol2
1452  && rp2.aStart.Col() == r2.aStart.Col()
1453  && rp2.aEnd.Col() == r2.aEnd.Col() )
1454  {
1455  if ( rp1.aStart.Row() == nRow2+1
1456  && rp2.aStart.Row() == r2.aEnd.Row()+1 )
1457  { // top
1458  rp1.aStart.SetRow( nRow1 );
1459  rp2.aStart.SetRow( r2.aStart.Row() );
1460  bJoined = true;
1461  }
1462  else if ( rp1.aEnd.Row() == nRow1-1
1463  && rp2.aEnd.Row() == r2.aStart.Row()-1 )
1464  { // bottom
1465  rp1.aEnd.SetRow( nRow2 );
1466  rp2.aEnd.SetRow( r2.aEnd.Row() );
1467  bJoined = true;
1468  }
1469  }
1470  else if ( rp1.aStart.Row() == nRow1 && rp1.aEnd.Row() == nRow2
1471  && rp2.aStart.Row() == r2.aStart.Row()
1472  && rp2.aEnd.Row() == r2.aEnd.Row() )
1473  {
1474  if ( rp1.aStart.Col() == nCol2+1
1475  && rp2.aStart.Col() == r2.aEnd.Col()+1 )
1476  { // left
1477  rp1.aStart.SetCol( nCol1 );
1478  rp2.aStart.SetCol( r2.aStart.Col() );
1479  bJoined = true;
1480  }
1481  else if ( rp1.aEnd.Col() == nCol1-1
1482  && rp2.aEnd.Col() == r2.aEnd.Col()-1 )
1483  { // right
1484  rp1.aEnd.SetCol( nCol2 );
1485  rp2.aEnd.SetCol( r2.aEnd.Col() );
1486  bJoined = true;
1487  }
1488  }
1489  }
1490  if ( bJoined )
1491  {
1492  if ( bIsInList )
1493  { // delete RangePair pOver within the list
1494  if (nOverPos != std::numeric_limits<size_t>::max())
1495  {
1496  Remove(nOverPos);
1497  if (nOverPos < i)
1498  --i;
1499  }
1500  else
1501  {
1502  for (size_t nOver = 0, nRangePairs = maPairs.size(); nOver < nRangePairs; ++nOver)
1503  {
1504  if (&maPairs[nOver] == pOver)
1505  {
1506  maPairs.erase(maPairs.begin() + nOver);
1507  break;
1508  }
1509  }
1510  assert(false);
1511  }
1512  }
1513  bJoinedInput = true;
1514  pOver = &maPairs[i];
1515  bIsInList = true;
1516  goto Label_RangePair_Join;
1517  }
1518  }
1519  if ( !bIsInList && !bJoinedInput )
1520  Append( r );
1521 }
1522 
1523 std::vector<const ScRangePair*> ScRangePairList::CreateNameSortedArray( ScDocument& rDoc ) const
1524 {
1525  std::vector<const ScRangePair*> aSortedVec(maPairs.size());
1526  size_t i = 0;
1527  for ( auto const & rPair : maPairs)
1528  {
1529  aSortedVec[i++] = &rPair;
1530  }
1531 
1532  std::sort( aSortedVec.begin(), aSortedVec.end(), ScRangePairList_sortNameCompare(rDoc) );
1533 
1534  return aSortedVec;
1535 }
1536 
1537 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SC_DLLPUBLIC ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1775
bool UpdateReference(UpdateRefMode, const ScDocument *, const ScRange &rWhere, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: rangelst.cxx:369
bool operator!=(const ScRangeList &r) const
Definition: rangelst.cxx:364
bool Intersects(const ScRange &) const
Definition: rangelst.cxx:1082
static ScRefUpdateRes Update(const ScDocument *pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCCOL nDx, SCROW nDy, SCTAB nDz, SCCOL &theCol1, SCROW &theRow1, SCTAB &theTab1, SCCOL &theCol2, SCROW &theRow2, SCTAB &theTab2)
Definition: refupdat.cxx:188
ScAddress aStart
Definition: address.hxx:499
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
SCROW Row() const
Definition: address.hxx:261
void Format(OUString &, ScRefFlags nFlags, const ScDocument &, formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO, sal_Unicode cDelimiter=0, bool bFullAddressNotation=false) const
Definition: rangelst.cxx:144
SC_DLLPUBLIC bool Intersects(const ScRange &rRange) const
Definition: address.cxx:1558
sal_Int64 n
static SC_DLLPUBLIC CollatorWrapper * GetCollator()
Definition: global.cxx:1028
aBuf
ScRange Combine() const
Definition: rangelst.cxx:1112
ScAddress aEnd
Definition: address.hxx:500
const sal_Unicode cDelimiter
Definition: tpusrlst.cxx:45
void DeleteOnTab(SCTAB nTab)
Definition: rangelst.cxx:1274
virtual ~ScRangeList() override
Definition: rangelst.cxx:100
void UpdateReference(UpdateRefMode, const ScDocument *, const ScRange &rWhere, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: rangelst.cxx:1234
void Append(const ScRangePair &rRangePair)
Definition: rangelst.hxx:134
void Remove(size_t nPos)
Definition: rangelst.cxx:1200
size_t GetCellCount() const
Definition: rangelst.cxx:1092
::std::vector< ScRange > maRanges
Definition: rangelst.hxx:105
void InsertRow(SCTAB nTab, SCCOL nColStart, SCCOL nColEnd, SCROW nRowPos, SCSIZE nSize)
Definition: rangelst.cxx:446
sal_uInt16 sal_Unicode
bool DeleteArea(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
For now this method assumes that nTab1 == nTab2 The algorithm will be much more complicated if nTab1 ...
Definition: rangelst.cxx:955
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
ScRangePair & operator[](size_t idx)
Definition: rangelst.cxx:1219
bool In(const ScRange &) const
Definition: rangelst.cxx:1087
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1142
void swap(ScRangeList &r)
Definition: rangelst.cxx:1149
SCTAB Tab() const
Definition: address.hxx:270
void SetRow(SCROW nRowP)
Definition: address.hxx:274
const ScRange * Find(const ScAddress &) const
Definition: rangelst.cxx:1031
static sal_Unicode GetNativeSymbolChar(OpCode eOp)
void SetCol(SCCOL nColP)
Definition: address.hxx:278
ScAddress GetTopLeftCorner() const
Definition: rangelst.cxx:1155
bool empty() const
Definition: rangelst.hxx:88
ocSep
void Remove(size_t nPos)
Definition: rangelst.cxx:1098
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
void Join(const ScRangePair &, bool bIsInList=false)
Definition: rangelst.cxx:1394
ScRangePairList * Clone() const
Definition: rangelst.cxx:1304
void InsertCol(SCTAB nTab, SCROW nRowStart, SCROW nRowEnd, SCCOL nColPos, SCSIZE nSize)
Definition: rangelst.cxx:476
int i
void Set(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: address.hxx:405
sal_Int16 SCCOL
Definition: types.hxx:21
void applyStartToEndFlags(ScRefFlags &target, const ScRefFlags source)
Definition: address.hxx:183
SC_DLLPUBLIC OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2212
ScRefFlags Parse(const OUString &, const ScDocument &, formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO, SCTAB nDefaultTab=0, sal_Unicode cDelimiter=0)
Definition: rangelst.cxx:104
size_t size() const
Definition: rangelst.hxx:89
const ScRange & GetRange(sal_uInt16 n) const
Definition: address.hxx:816
void GetVars(SCCOL &nCol1, SCROW &nRow1, SCTAB &nTab1, SCCOL &nCol2, SCROW &nRow2, SCTAB &nTab2) const
Definition: address.hxx:692
bool In(const ScAddress &) const
is Address& in Range?
Definition: address.hxx:732
Reference not affected, no change at all.
Definition: refupdat.hxx:31
SCCOL Col() const
Definition: address.hxx:266
ScRangeList & operator=(const ScRangeList &rList)
Definition: rangelst.cxx:1068
UpdateRefMode
Definition: global.hxx:309
sal_Int32 SCROW
Definition: types.hxx:17
virtual ~ScRangePairList() override
Definition: rangelst.cxx:1196
#define SAL_WARN_IF(condition, area, stream)
void Join(const ScRange &, bool bIsInList=false)
Definition: rangelst.cxx:164
size_t size() const
Definition: rangelst.cxx:1229
bool operator==(const ScRangeList &) const
Definition: rangelst.cxx:356
ScRangeList GetIntersectedRange(const ScRange &rRange) const
Definition: rangelst.cxx:1170
SCROW mnMaxRowUsed
Definition: rangelst.hxx:106
void AddAndPartialCombine(const ScRange &)
Definition: rangelst.cxx:311
ScRefFlags
Definition: address.hxx:144
std::vector< const ScRangePair * > CreateNameSortedArray(ScDocument &) const
Definition: rangelst.cxx:1523
::std::vector< ScRangePair > maPairs
Definition: rangelst.hxx:156
ScRangePair * Find(const ScAddress &)
Definition: rangelst.cxx:1284
void RemoveAll()
Definition: rangelst.cxx:1106
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22