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

Generated by: LCOV version 1.10