LCOV - code coverage report
Current view: top level - sc/source/core/tool - rangelst.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 546 725 75.3 %
Date: 2014-11-03 Functions: 73 82 89.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10