LCOV - code coverage report
Current view: top level - sc/source/core/data - document.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 2520 3321 75.9 %
Date: 2014-04-11 Functions: 305 356 85.7 %
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 "scitems.hxx"
      21             : #include <editeng/eeitem.hxx>
      22             : 
      23             : #include <editeng/boxitem.hxx>
      24             : #include <editeng/frmdiritem.hxx>
      25             : #include "editeng/editobj.hxx"
      26             : #include <svx/pageitem.hxx>
      27             : #include <editeng/editeng.hxx>
      28             : #include <svx/sdrundomanager.hxx>
      29             : #include <svx/svditer.hxx>
      30             : #include <svx/svdpage.hxx>
      31             : #include <svx/svdocapt.hxx>
      32             : #include <sfx2/app.hxx>
      33             : #include <sfx2/objsh.hxx>
      34             : #include <sfx2/docfile.hxx>
      35             : #include <svl/poolcach.hxx>
      36             : #include <unotools/saveopt.hxx>
      37             : #include <svl/zforlist.hxx>
      38             : #include <unotools/charclass.hxx>
      39             : #include <unotools/transliterationwrapper.hxx>
      40             : #include <tools/tenccvt.hxx>
      41             : #include <tools/urlobj.hxx>
      42             : 
      43             : #include <com/sun/star/text/WritingMode2.hpp>
      44             : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
      45             : #include <com/sun/star/sheet/TablePageBreakData.hpp>
      46             : #include <com/sun/star/lang/NotInitializedException.hpp>
      47             : 
      48             : #include "document.hxx"
      49             : #include "table.hxx"
      50             : #include "attrib.hxx"
      51             : #include "attarray.hxx"
      52             : #include "markarr.hxx"
      53             : #include "patattr.hxx"
      54             : #include "rangenam.hxx"
      55             : #include "poolhelp.hxx"
      56             : #include "docpool.hxx"
      57             : #include "stlpool.hxx"
      58             : #include "stlsheet.hxx"
      59             : #include "globstr.hrc"
      60             : #include "rechead.hxx"
      61             : #include "dbdata.hxx"
      62             : #include "pivot.hxx"
      63             : #include "chartlis.hxx"
      64             : #include "rangelst.hxx"
      65             : #include "markdata.hxx"
      66             : #include "drwlayer.hxx"
      67             : #include "conditio.hxx"
      68             : #include "colorscale.hxx"
      69             : #include "validat.hxx"
      70             : #include "prnsave.hxx"
      71             : #include "chgtrack.hxx"
      72             : #include "sc.hrc"
      73             : #include "scresid.hxx"
      74             : #include "hints.hxx"
      75             : #include "detdata.hxx"
      76             : #include "dpobject.hxx"
      77             : #include "detfunc.hxx"
      78             : #include "scmod.hxx"
      79             : #include "dociter.hxx"
      80             : #include "progress.hxx"
      81             : #include "autonamecache.hxx"
      82             : #include "bcaslot.hxx"
      83             : #include "postit.hxx"
      84             : #include "externalrefmgr.hxx"
      85             : #include "tabprotection.hxx"
      86             : #include "clipparam.hxx"
      87             : #include "stlalgorithm.hxx"
      88             : #include "defaultsoptions.hxx"
      89             : #include "editutil.hxx"
      90             : #include "stringutil.hxx"
      91             : #include "formulaiter.hxx"
      92             : #include "formulacell.hxx"
      93             : #include "clipcontext.hxx"
      94             : #include "listenercontext.hxx"
      95             : #include "scopetools.hxx"
      96             : #include "refupdatecontext.hxx"
      97             : #include "formulagroup.hxx"
      98             : #include <tokenarray.hxx>
      99             : #include <tokenstringcontext.hxx>
     100             : 
     101             : #include "formula/vectortoken.hxx"
     102             : 
     103             : #include <map>
     104             : #include <limits>
     105             : #include <boost/scoped_ptr.hpp>
     106             : 
     107             : #include "mtvelements.hxx"
     108             : 
     109             : using ::editeng::SvxBorderLine;
     110             : using namespace ::com::sun::star;
     111             : 
     112             : namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
     113             : using ::com::sun::star::uno::Sequence;
     114             : using ::com::sun::star::sheet::TablePageBreakData;
     115             : using ::std::set;
     116             : 
     117             : namespace {
     118             : 
     119          57 : std::pair<SCTAB,SCTAB> getMarkedTableRange(const std::vector<ScTable*>& rTables, const ScMarkData& rMark)
     120             : {
     121          57 :     SCTAB nTabStart = MAXTAB;
     122          57 :     SCTAB nTabEnd = 0;
     123          57 :     SCTAB nMax = static_cast<SCTAB>(rTables.size());
     124          57 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
     125         111 :     for (; itr != itrEnd && *itr < nMax; ++itr)
     126             :     {
     127          54 :         if (!rTables[*itr])
     128           0 :             continue;
     129             : 
     130          54 :         if (*itr < nTabStart)
     131          54 :             nTabStart = *itr;
     132          54 :         nTabEnd = *itr;
     133             :     }
     134             : 
     135          57 :     return std::pair<SCTAB,SCTAB>(nTabStart,nTabEnd);
     136             : }
     137             : 
     138             : }
     139             : 
     140             : struct ScDefaultAttr
     141             : {
     142             :     const ScPatternAttr*    pAttr;
     143             :     SCROW                   nFirst;
     144             :     SCSIZE                  nCount;
     145          80 :     ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {}
     146             : };
     147             : 
     148             : struct ScLessDefaultAttr
     149             : {
     150         309 :     bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const
     151             :     {
     152         309 :         return rValue1.pAttr < rValue2.pAttr;
     153             :     }
     154             : };
     155             : 
     156             : typedef std::set<ScDefaultAttr, ScLessDefaultAttr>  ScDefaultAttrSet;
     157             : 
     158         830 : void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck )
     159             : {
     160         830 :     if ( ValidTab(nTab) && ( nTab >= static_cast<SCTAB>(maTabs.size()) ||!maTabs[nTab]) )
     161             :     {
     162             :         // Get Custom prefix
     163         514 :         const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
     164         514 :         OUString aString = rOpt.GetInitTabPrefix();
     165             : 
     166         514 :         aString += OUString::number(nTab+1);
     167         514 :         if ( _bNeedsNameCheck )
     168         514 :             CreateValidTabName( aString );  // no doubles
     169         514 :         if (nTab < static_cast<SCTAB>(maTabs.size()))
     170             :         {
     171           0 :             maTabs[nTab] = new ScTable(this, nTab, aString);
     172             :         }
     173             :         else
     174             :         {
     175        1028 :             while(nTab > static_cast<SCTAB>(maTabs.size()))
     176           0 :                 maTabs.push_back(NULL);
     177         514 :             maTabs.push_back( new ScTable(this, nTab, aString) );
     178             :         }
     179         514 :         maTabs[nTab]->SetLoadingMedium(bLoadingMedium);
     180             :     }
     181         830 : }
     182             : 
     183       10234 : bool ScDocument::HasTable( SCTAB nTab ) const
     184             : {
     185       10234 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
     186       10234 :         if (maTabs[nTab])
     187       10234 :             return true;
     188             : 
     189           0 :     return false;
     190             : }
     191             : 
     192        3729 : bool ScDocument::GetName( SCTAB nTab, OUString& rName ) const
     193             : {
     194        3729 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
     195        3728 :         if (maTabs[nTab])
     196             :         {
     197        3728 :             maTabs[nTab]->GetName( rName );
     198        3728 :             return true;
     199             :         }
     200           1 :     rName = OUString();
     201           1 :     return false;
     202             : }
     203             : 
     204           4 : OUString ScDocument::GetCopyTabName( SCTAB nTab ) const
     205             : {
     206           4 :     if (nTab < static_cast<SCTAB>(maTabNames.size()))
     207           3 :         return maTabNames[nTab];
     208             :     else
     209           1 :         return OUString();
     210             : }
     211             : 
     212         456 : bool ScDocument::SetCodeName( SCTAB nTab, const OUString& rName )
     213             : {
     214         456 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
     215             :     {
     216         456 :         if (maTabs[nTab])
     217             :         {
     218         456 :             maTabs[nTab]->SetCodeName( rName );
     219         456 :             return true;
     220             :         }
     221             :     }
     222             :     OSL_TRACE( "**** can't set code name %s", OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
     223           0 :     return false;
     224             : }
     225             : 
     226        2945 : bool ScDocument::GetCodeName( SCTAB nTab, OUString& rName ) const
     227             : {
     228        2945 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
     229        2945 :         if (maTabs[nTab])
     230             :         {
     231        2945 :             maTabs[nTab]->GetCodeName( rName );
     232        2945 :             return true;
     233             :         }
     234           0 :     rName = OUString();
     235           0 :     return false;
     236             : }
     237             : 
     238        5958 : bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const
     239             : {
     240        5958 :     OUString aUpperName = ScGlobal::pCharClass->uppercase(rName);
     241             : 
     242        8586 :     for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
     243        8535 :         if (maTabs[i])
     244             :         {
     245        8535 :             if (aUpperName.equals(maTabs[i]->GetUpperName()))
     246             :             {
     247        5907 :                 rTab = i;
     248        5907 :                 return true;
     249             :             }
     250             :         }
     251          51 :     rTab = 0;
     252          51 :     return false;
     253             : }
     254             : 
     255       35390 : std::vector<OUString> ScDocument::GetAllTableNames() const
     256             : {
     257       35390 :     std::vector<OUString> aNames;
     258       35390 :     aNames.reserve(maTabs.size());
     259       35390 :     TableContainer::const_iterator it = maTabs.begin(), itEnd = maTabs.end();
     260      104340 :     for (; it != itEnd; ++it)
     261             :     {
     262       68950 :         OUString aName;
     263       68950 :         const ScTable& rTab = **it;
     264       68950 :         rTab.GetName(aName);
     265       68950 :         aNames.push_back(aName);
     266       68950 :     }
     267             : 
     268       35390 :     return aNames;
     269             : }
     270             : 
     271         530 : ScDBData* ScDocument::GetAnonymousDBData(SCTAB nTab)
     272             : {
     273         530 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     274         530 :         return maTabs[nTab]->GetAnonymousDBData();
     275           0 :     return NULL;
     276             : }
     277             : 
     278      442699 : SCTAB ScDocument::GetTableCount() const
     279             : {
     280      442699 :     return static_cast<SCTAB>(maTabs.size());
     281             : }
     282             : 
     283          20 : void ScDocument::SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData)
     284             : {
     285          20 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
     286          20 :         maTabs[nTab]->SetAnonymousDBData(pDBData);
     287          20 : }
     288             : 
     289             : 
     290        1969 : bool ScDocument::ValidTabName( const OUString& rName )
     291             : {
     292        1969 :     if (rName.isEmpty())
     293          23 :         return false;
     294        1946 :     sal_Int32 nLen = rName.getLength();
     295             : 
     296             : #if 1
     297             :     // Restrict sheet names to what Excel accepts.
     298             :     /* TODO: We may want to remove this restriction for full ODFF compliance.
     299             :      * Merely loading and calculating ODF documents using these characters in
     300             :      * sheet names is not affected by this, but all sheet name editing and
     301             :      * copying functionality is, maybe falling back to "Sheet4" or similar. */
     302       14144 :     for (sal_Int32 i = 0; i < nLen; ++i)
     303             :     {
     304       12198 :         const sal_Unicode c = rName[i];
     305       12198 :         switch (c)
     306             :         {
     307             :             case ':':
     308             :             case '\\':
     309             :             case '/':
     310             :             case '?':
     311             :             case '*':
     312             :             case '[':
     313             :             case ']':
     314             :                 // these characters are not allowed to match XL's convention.
     315           0 :                 return false;
     316             :             case '\'':
     317           8 :                 if (i == 0 || i == nLen - 1)
     318             :                     // single quote is not allowed at the first or last
     319             :                     // character position.
     320           0 :                     return false;
     321           8 :             break;
     322             :         }
     323             :     }
     324             : #endif
     325             : 
     326        1946 :     return true;
     327             : }
     328             : 
     329             : 
     330         951 : bool ScDocument::ValidNewTabName( const OUString& rName ) const
     331             : {
     332         951 :     bool bValid = ValidTabName(rName);
     333         951 :     TableContainer::const_iterator it = maTabs.begin();
     334        1856 :     for (; it != maTabs.end() && bValid; ++it)
     335         905 :         if ( *it )
     336             :         {
     337         905 :             OUString aOldName;
     338         905 :             (*it)->GetName(aOldName);
     339         905 :             bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
     340             :         }
     341         951 :     return bValid;
     342             : }
     343             : 
     344             : 
     345         657 : void ScDocument::CreateValidTabName(OUString& rName) const
     346             : {
     347         657 :     if ( !ValidTabName(rName) )
     348             :     {
     349             :         // Find new one
     350             : 
     351             :         // Get Custom prefix
     352          23 :         const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
     353          23 :         OUString aStrTable = rOpt.GetInitTabPrefix();
     354             : 
     355          23 :         bool         bOk   = false;
     356             : 
     357             :         // First test if the prefix is valid, if so only avoid doubles
     358          23 :         bool bPrefix = ValidTabName( aStrTable );
     359             :         OSL_ENSURE(bPrefix, "Invalid Table Name");
     360             :         SCTAB nDummy;
     361             : 
     362          46 :         for ( SCTAB i = static_cast<SCTAB>(maTabs.size())+1; !bOk ; i++ )
     363             :         {
     364          23 :             OUStringBuffer aBuf;
     365          23 :             aBuf.append(aStrTable);
     366          23 :             aBuf.append(static_cast<sal_Int32>(i));
     367          23 :             rName = aBuf.makeStringAndClear();
     368          23 :             if (bPrefix)
     369          23 :                 bOk = ValidNewTabName( rName );
     370             :             else
     371           0 :                 bOk = !GetTable( rName, nDummy );
     372          46 :         }
     373             :     }
     374             :     else
     375             :     {
     376             :         // testing the supplied Name
     377             : 
     378         634 :         if ( !ValidNewTabName(rName) )
     379             :         {
     380          10 :             SCTAB i = 1;
     381          10 :             OUStringBuffer aName;
     382          20 :             do
     383             :             {
     384          10 :                 i++;
     385          10 :                 aName = rName;
     386          10 :                 aName.append('_');
     387          10 :                 aName.append(static_cast<sal_Int32>(i));
     388             :             }
     389          30 :             while (!ValidNewTabName(aName.toString()) && (i < MAXTAB+1));
     390          10 :             rName = aName.makeStringAndClear();
     391             :         }
     392             :     }
     393         657 : }
     394             : 
     395           0 : void ScDocument::CreateValidTabNames(std::vector<OUString>& aNames, SCTAB nCount) const
     396             : {
     397           0 :     aNames.clear();//ensure that the vector is empty
     398             : 
     399             :     // Get Custom prefix
     400           0 :     const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
     401           0 :     OUString aStrTable = rOpt.GetInitTabPrefix();
     402             : 
     403           0 :     OUStringBuffer rName;
     404           0 :     bool         bOk   = false;
     405             : 
     406             :     // First test if the prefix is valid, if so only avoid doubles
     407           0 :     bool bPrefix = ValidTabName( aStrTable );
     408             :     OSL_ENSURE(bPrefix, "Invalid Table Name");
     409             :     SCTAB nDummy;
     410           0 :     SCTAB i = static_cast<SCTAB>(maTabs.size())+1;
     411             : 
     412           0 :     for (SCTAB j = 0; j < nCount; ++j)
     413             :     {
     414           0 :         bOk = false;
     415           0 :         while(!bOk)
     416             :         {
     417           0 :             rName = aStrTable;
     418           0 :             rName.append(static_cast<sal_Int32>(i));
     419           0 :             if (bPrefix)
     420           0 :                 bOk = ValidNewTabName( rName.toString() );
     421             :             else
     422           0 :                 bOk = !GetTable( rName.toString(), nDummy );
     423           0 :             i++;
     424             :         }
     425           0 :         aNames.push_back(rName.makeStringAndClear());
     426           0 :     }
     427           0 : }
     428             : 
     429         114 : void ScDocument::AppendTabOnLoad(const OUString& rName)
     430             : {
     431         114 :     SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
     432         114 :     if (!ValidTab(nTabCount))
     433             :         // max table count reached.  No more tables.
     434         114 :         return;
     435             : 
     436         114 :     OUString aName = rName;
     437         114 :     CreateValidTabName(aName);
     438         114 :     maTabs.push_back( new ScTable(this, nTabCount, aName) );
     439             : }
     440             : 
     441         107 : void ScDocument::SetTabNameOnLoad(SCTAB nTab, const OUString& rName)
     442             : {
     443         107 :     if (!ValidTab(nTab) || static_cast<SCTAB>(maTabs.size()) <= nTab)
     444           0 :         return;
     445             : 
     446         107 :     if (!ValidTabName(rName))
     447           0 :         return;
     448             : 
     449         107 :     maTabs[nTab]->SetName(rName);
     450             : }
     451             : 
     452          13 : void ScDocument::InvalidateStreamOnSave()
     453             : {
     454          13 :     TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
     455          30 :     for (; it != itEnd; ++it)
     456             :     {
     457          17 :         ScTable* pTab = *it;
     458          17 :         if (pTab)
     459          17 :             pTab->SetStreamValid(false);
     460             :     }
     461          13 : }
     462             : 
     463         279 : bool ScDocument::InsertTab(
     464             :     SCTAB nPos, const OUString& rName, bool bExternalDocument, bool bUndoDeleteTab )
     465             : {
     466         279 :     SCTAB   nTabCount = static_cast<SCTAB>(maTabs.size());
     467         279 :     bool    bValid = ValidTab(nTabCount);
     468         279 :     if ( !bExternalDocument )   // else test rName == "'Doc'!Tab" first
     469         279 :         bValid = (bValid && ValidNewTabName(rName));
     470         279 :     if (bValid)
     471             :     {
     472         276 :         if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
     473             :         {
     474         231 :             nPos = maTabs.size();
     475         231 :             maTabs.push_back( new ScTable(this, nTabCount, rName) );
     476         462 :             if ( bExternalDocument )
     477           0 :                 maTabs[nTabCount]->SetVisible( false );
     478             :         }
     479             :         else
     480             :         {
     481          45 :             if (ValidTab(nPos) && (nPos < nTabCount))
     482             :             {
     483          45 :                 sc::RefUpdateInsertTabContext aCxt(nPos, 1);
     484             : 
     485          45 :                 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
     486          45 :                 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
     487          45 :                 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
     488          45 :                 if (pRangeName)
     489          30 :                     pRangeName->UpdateInsertTab(aCxt);
     490             :                 pDBCollection->UpdateReference(
     491          45 :                                     URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
     492          45 :                 if (pDPCollection)
     493          17 :                     pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
     494          45 :                 if (pDetOpList)
     495           0 :                     pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
     496          45 :                 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
     497          45 :                 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
     498          45 :                 if ( pUnoBroadcaster )
     499          45 :                     pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
     500             : 
     501             :                 SCTAB i;
     502          45 :                 TableContainer::iterator it = maTabs.begin();
     503         105 :                 for (; it != maTabs.end(); ++it)
     504          60 :                     if ( *it )
     505          60 :                         (*it)->UpdateInsertTab(aCxt);
     506          45 :                 maTabs.push_back(NULL);
     507         100 :                 for (i = nTabCount; i > nPos; i--)
     508             :                 {
     509          55 :                     maTabs[i] = maTabs[i - 1];
     510             :                 }
     511             : 
     512          45 :                 maTabs[nPos] = new ScTable(this, nPos, rName);
     513             : 
     514             :                 // UpdateBroadcastAreas must be called between UpdateInsertTab,
     515             :                 // which ends listening, and StartAllListeners, to not modify
     516             :                 // areas that are to be inserted by starting listeners.
     517          45 :                 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1);
     518          45 :                 it = maTabs.begin();
     519         150 :                 for (; it != maTabs.end(); ++it)
     520         105 :                     if ( *it )
     521         105 :                         (*it)->UpdateCompile();
     522          45 :                 it = maTabs.begin();
     523         150 :                 for (; it != maTabs.end(); ++it)
     524         105 :                     if ( *it )
     525         105 :                         (*it)->StartAllListeners();
     526             : 
     527          45 :                 if (pValidationList)
     528           0 :                     pValidationList->UpdateInsertTab(aCxt);
     529             : 
     530             :                 // sheet names of references are not valid until sheet is inserted
     531          45 :                 if ( pChartListenerCollection )
     532          45 :                     pChartListenerCollection->UpdateScheduledSeriesRanges();
     533             : 
     534          45 :                 bValid = true;
     535             :             }
     536             :             else
     537           0 :                 bValid = false;
     538             :         }
     539             :     }
     540             : 
     541         279 :     if (bValid)
     542             :     {
     543         276 :         sc::SetFormulaDirtyContext aCxt;
     544         276 :         aCxt.mbClearTabDeletedFlag = bUndoDeleteTab;
     545         276 :         aCxt.mnTabDeletedStart = nPos;
     546         276 :         aCxt.mnTabDeletedEnd = nPos;
     547         276 :         SetAllFormulasDirty(aCxt);
     548             :     }
     549             : 
     550         279 :     return bValid;
     551             : }
     552             : 
     553             : 
     554           1 : bool ScDocument::InsertTabs( SCTAB nPos, const std::vector<OUString>& rNames,
     555             :             bool bExternalDocument, bool bNamesValid )
     556             : {
     557           1 :     SCTAB   nNewSheets = static_cast<SCTAB>(rNames.size());
     558           1 :     SCTAB    nTabCount = static_cast<SCTAB>(maTabs.size());
     559           1 :     bool    bValid = bNamesValid || ValidTab(nTabCount+nNewSheets);
     560             : //    if ( !bExternalDocument )    // else test rName == "'Doc'!Tab" first
     561             : //        bValid = (bValid && ValidNewTabName(rNames));
     562           1 :     if (bValid)
     563             :     {
     564           1 :         if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
     565             :         {
     566           0 :             for ( SCTAB i = 0; i < nNewSheets; ++i )
     567             :             {
     568           0 :                 maTabs.push_back( new ScTable(this, nTabCount + i, rNames.at(i)) );
     569           0 :                 if ( bExternalDocument )
     570           0 :                     maTabs[nTabCount+i]->SetVisible( false );
     571           0 :             }
     572             :         }
     573             :         else
     574             :         {
     575           1 :             if (ValidTab(nPos) && (nPos < nTabCount))
     576             :             {
     577           1 :                 sc::RefUpdateInsertTabContext aCxt(nPos, nNewSheets);
     578           1 :                 ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
     579           1 :                 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
     580           1 :                 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
     581           1 :                 if (pRangeName)
     582           0 :                     pRangeName->UpdateInsertTab(aCxt);
     583             :                 pDBCollection->UpdateReference(
     584           1 :                                     URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
     585           1 :                 if (pDPCollection)
     586           0 :                     pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,nNewSheets );
     587           1 :                 if (pDetOpList)
     588           0 :                     pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,nNewSheets );
     589           1 :                 UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
     590           1 :                 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0, nNewSheets );
     591           1 :                 if ( pUnoBroadcaster )
     592           1 :                     pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,nNewSheets ) );
     593             : 
     594           1 :                 TableContainer::iterator it = maTabs.begin();
     595           3 :                 for (; it != maTabs.end(); ++it)
     596           2 :                     if ( *it )
     597           2 :                         (*it)->UpdateInsertTab(aCxt);
     598           1 :                 it = maTabs.begin();
     599           1 :                 maTabs.insert(it+nPos,nNewSheets, NULL);
     600           3 :                 for (SCTAB i = 0; i < nNewSheets; ++i)
     601             :                 {
     602           2 :                     maTabs[nPos + i] = new ScTable(this, nPos + i, rNames.at(i));
     603             :                 }
     604             : 
     605             :                 // UpdateBroadcastAreas must be called between UpdateInsertTab,
     606             :                 // which ends listening, and StartAllListeners, to not modify
     607             :                 // areas that are to be inserted by starting listeners.
     608           1 :                 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,nNewSheets);
     609           1 :                 it = maTabs.begin();
     610           5 :                 for (; it != maTabs.end(); ++it)
     611             :                 {
     612           4 :                     if ( *it )
     613           4 :                         (*it)->UpdateCompile();
     614             :                 }
     615           1 :                 it = maTabs.begin();
     616           5 :                 for (; it != maTabs.end(); ++it)
     617           4 :                     if ( *it )
     618           4 :                         (*it)->StartAllListeners();
     619             : 
     620           1 :                 if (pValidationList)
     621           0 :                     pValidationList->UpdateInsertTab(aCxt);
     622             : 
     623             :                 // sheet names of references are not valid until sheet is inserted
     624           1 :                 if ( pChartListenerCollection )
     625           1 :                     pChartListenerCollection->UpdateScheduledSeriesRanges();
     626             : 
     627           1 :                 bValid = true;
     628             :             }
     629             :             else
     630           0 :                 bValid = false;
     631             :         }
     632             :     }
     633             : 
     634           1 :     if (bValid)
     635             :     {
     636           1 :         sc::SetFormulaDirtyContext aCxt;
     637           1 :         SetAllFormulasDirty(aCxt);
     638             :     }
     639             : 
     640           1 :     return bValid;
     641             : }
     642             : 
     643             : 
     644         209 : bool ScDocument::DeleteTab( SCTAB nTab )
     645             : {
     646         209 :     bool bValid = false;
     647         209 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
     648             :     {
     649         206 :         if (maTabs[nTab])
     650             :         {
     651         206 :             SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
     652         206 :             if (nTabCount > 1)
     653             :             {
     654          79 :                 sc::AutoCalcSwitch aACSwitch(*this, false);
     655         158 :                 sc::RefUpdateDeleteTabContext aCxt(nTab, 1);
     656             : 
     657          79 :                 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
     658          79 :                 DelBroadcastAreasInRange( aRange );
     659             : 
     660             :                 // #i8180# remove database ranges etc. that are on the deleted tab
     661             :                 // (restored in undo with ScRefUndoData)
     662             : 
     663          79 :                 xColNameRanges->DeleteOnTab( nTab );
     664          79 :                 xRowNameRanges->DeleteOnTab( nTab );
     665          79 :                 pDBCollection->DeleteOnTab( nTab );
     666          79 :                 if (pDPCollection)
     667          39 :                     pDPCollection->DeleteOnTab( nTab );
     668          79 :                 if (pDetOpList)
     669           0 :                     pDetOpList->DeleteOnTab( nTab );
     670          79 :                 DeleteAreaLinksOnTab( nTab );
     671             : 
     672             :                 // normal reference update
     673             : 
     674          79 :                 aRange.aEnd.SetTab( static_cast<SCTAB>(maTabs.size())-1 );
     675          79 :                 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
     676          79 :                 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
     677          79 :                 if (pRangeName)
     678          27 :                     pRangeName->UpdateDeleteTab(aCxt);
     679             :                 pDBCollection->UpdateReference(
     680          79 :                                     URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
     681          79 :                 if (pDPCollection)
     682          39 :                     pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
     683          79 :                 if (pDetOpList)
     684           0 :                     pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 );
     685          79 :                 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
     686          79 :                 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 );
     687          79 :                 if (pValidationList)
     688           0 :                     pValidationList->UpdateDeleteTab(aCxt);
     689          79 :                 if ( pUnoBroadcaster )
     690          79 :                     pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) );
     691             : 
     692         272 :                 for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
     693         193 :                     if (maTabs[i])
     694         193 :                         maTabs[i]->UpdateDeleteTab(aCxt);
     695             : 
     696          79 :                 TableContainer::iterator it = maTabs.begin() + nTab;
     697          79 :                 delete *it;
     698          79 :                 maTabs.erase(it);
     699             :                 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
     700             :                 // which ends listening, and StartAllListeners, to not modify
     701             :                 // areas that are to be inserted by starting listeners.
     702          79 :                 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1);
     703          79 :                 it = maTabs.begin();
     704         193 :                 for (; it != maTabs.end(); ++it)
     705         114 :                     if ( *it )
     706         114 :                         (*it)->UpdateCompile();
     707             :                 // Excel-Filter deletes some Tables while loading, Listeners will
     708             :                 // only be triggered after the loading is done.
     709          79 :                 if ( !bInsertingFromOtherDoc )
     710             :                 {
     711          79 :                     it = maTabs.begin();
     712         193 :                     for (; it != maTabs.end(); ++it)
     713         114 :                         if ( *it )
     714         114 :                             (*it)->StartAllListeners();
     715             : 
     716          79 :                     sc::SetFormulaDirtyContext aFormulaDirtyCxt;
     717          79 :                     SetAllFormulasDirty(aFormulaDirtyCxt);
     718             :                 }
     719             :                 // sheet names of references are not valid until sheet is deleted
     720          79 :                 pChartListenerCollection->UpdateScheduledSeriesRanges();
     721             : 
     722         158 :                 bValid = true;
     723             :             }
     724             :         }
     725             :     }
     726         209 :     return bValid;
     727             : }
     728             : 
     729             : 
     730           1 : bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets )
     731             : {
     732           1 :     bool bValid = false;
     733           1 :     if (ValidTab(nTab) && (nTab + nSheets) < static_cast<SCTAB>(maTabs.size()))
     734             :     {
     735           1 :         if (maTabs[nTab])
     736             :         {
     737           1 :             SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
     738           1 :             if (nTabCount > nSheets)
     739             :             {
     740           1 :                 sc::AutoCalcSwitch aACSwitch(*this, false);
     741           2 :                 sc::RefUpdateDeleteTabContext aCxt(nTab, nSheets);
     742             : 
     743           3 :                 for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
     744             :                 {
     745           2 :                     ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab + aTab );
     746           2 :                     DelBroadcastAreasInRange( aRange );
     747             : 
     748             :                     // #i8180# remove database ranges etc. that are on the deleted tab
     749             :                     // (restored in undo with ScRefUndoData)
     750             : 
     751           2 :                     xColNameRanges->DeleteOnTab( nTab + aTab );
     752           2 :                     xRowNameRanges->DeleteOnTab( nTab + aTab );
     753           2 :                     pDBCollection->DeleteOnTab( nTab + aTab );
     754           2 :                     if (pDPCollection)
     755           0 :                         pDPCollection->DeleteOnTab( nTab + aTab );
     756           2 :                     if (pDetOpList)
     757           0 :                         pDetOpList->DeleteOnTab( nTab + aTab );
     758           2 :                     DeleteAreaLinksOnTab( nTab + aTab );
     759             :                 }
     760             : 
     761           1 :                 if (pRangeName)
     762           0 :                     pRangeName->UpdateDeleteTab(aCxt);
     763             : 
     764             :                 // normal reference update
     765             : 
     766           1 :                 ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTabCount - 1 );
     767           1 :                 xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
     768           1 :                 xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
     769             :                 pDBCollection->UpdateReference(
     770           1 :                                     URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
     771           1 :                 if (pDPCollection)
     772           0 :                     pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1*nSheets );
     773           1 :                 if (pDetOpList)
     774           0 :                     pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1*nSheets );
     775           1 :                 UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
     776           1 :                 UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1*nSheets );
     777           1 :                 if (pValidationList)
     778           0 :                     pValidationList->UpdateDeleteTab(aCxt);
     779           1 :                 if ( pUnoBroadcaster )
     780           1 :                     pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1*nSheets ) );
     781             : 
     782           5 :                 for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
     783           4 :                     if (maTabs[i])
     784           4 :                         maTabs[i]->UpdateDeleteTab(aCxt);
     785             : 
     786           1 :                 TableContainer::iterator it = maTabs.begin() + nTab;
     787           1 :                 TableContainer::iterator itEnd = it + nSheets;
     788           1 :                 std::for_each(it, itEnd, ScDeleteObjectByPtr<ScTable>());
     789           1 :                 maTabs.erase(it, itEnd);
     790             :                 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
     791             :                 // which ends listening, and StartAllListeners, to not modify
     792             :                 // areas that are to be inserted by starting listeners.
     793           1 :                 UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1*nSheets);
     794           1 :                 it = maTabs.begin();
     795           3 :                 for (; it != maTabs.end(); ++it)
     796           2 :                     if ( *it )
     797           2 :                         (*it)->UpdateCompile();
     798             :                 // Excel-Filter deletes some Tables while loading, Listeners will
     799             :                 // only be triggered after the loading is done.
     800           1 :                 if ( !bInsertingFromOtherDoc )
     801             :                 {
     802           1 :                     it = maTabs.begin();
     803           3 :                     for (; it != maTabs.end(); ++it)
     804           2 :                         if ( *it )
     805           2 :                             (*it)->StartAllListeners();
     806             : 
     807           1 :                     sc::SetFormulaDirtyContext aFormulaDirtyCxt;
     808           1 :                     SetAllFormulasDirty(aFormulaDirtyCxt);
     809             :                 }
     810             :                 // sheet names of references are not valid until sheet is deleted
     811           1 :                 pChartListenerCollection->UpdateScheduledSeriesRanges();
     812             : 
     813           2 :                 bValid = true;
     814             :             }
     815             :         }
     816             :     }
     817           1 :     return bValid;
     818             : }
     819             : 
     820             : 
     821         226 : bool ScDocument::RenameTab( SCTAB nTab, const OUString& rName, bool /* bUpdateRef */,
     822             :         bool bExternalDocument )
     823             : {
     824         226 :     bool bValid = false;
     825             :     SCTAB i;
     826         226 :     if (ValidTab(nTab))
     827             :     {
     828         226 :         if (maTabs[nTab])
     829             :         {
     830         226 :             if ( bExternalDocument )
     831           0 :                 bValid = true;      // composed name
     832             :             else
     833         226 :                 bValid = ValidTabName(rName);
     834         856 :             for (i=0; (i< static_cast<SCTAB>(maTabs.size())) && bValid; i++)
     835         630 :                 if (maTabs[i] && (i != nTab))
     836             :                 {
     837         405 :                     OUString aOldName;
     838         405 :                     maTabs[i]->GetName(aOldName);
     839         405 :                     bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
     840             :                 }
     841         226 :             if (bValid)
     842             :             {
     843             :                 // #i75258# update charts before renaming, so they can get their live data objects.
     844             :                 // Once the charts are live, the sheet can be renamed without problems.
     845         225 :                 if ( pChartListenerCollection )
     846         206 :                     pChartListenerCollection->UpdateChartsContainingTab( nTab );
     847         225 :                 maTabs[nTab]->SetName(rName);
     848             : 
     849             :                 // If formulas refer to the renamed sheet, the TokenArray remains valid,
     850             :                 // but the XML stream must be re-generated.
     851         225 :                 TableContainer::iterator it = maTabs.begin();
     852         854 :                 for (; it != maTabs.end(); ++it)
     853         629 :                     if ( *it && (*it)->IsStreamValid())
     854           0 :                         (*it)->SetStreamValid( false );
     855             :             }
     856             :         }
     857             :     }
     858         226 :     return bValid;
     859             : }
     860             : 
     861             : 
     862          32 : void ScDocument::SetVisible( SCTAB nTab, bool bVisible )
     863             : {
     864          32 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
     865          32 :         if (maTabs[nTab])
     866          32 :             maTabs[nTab]->SetVisible(bVisible);
     867          32 : }
     868             : 
     869             : 
     870        3617 : bool ScDocument::IsVisible( SCTAB nTab ) const
     871             : {
     872        3617 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
     873        3617 :         if (maTabs[nTab])
     874        3617 :             return maTabs[nTab]->IsVisible();
     875             : 
     876           0 :     return false;
     877             : }
     878             : 
     879             : 
     880      330161 : bool ScDocument::IsStreamValid( SCTAB nTab ) const
     881             : {
     882      330161 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     883      330158 :         return maTabs[nTab]->IsStreamValid();
     884             : 
     885           3 :     return false;
     886             : }
     887             : 
     888             : 
     889         237 : void ScDocument::SetStreamValid( SCTAB nTab, bool bSet, bool bIgnoreLock )
     890             : {
     891         237 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     892         237 :         maTabs[nTab]->SetStreamValid( bSet, bIgnoreLock );
     893         237 : }
     894             : 
     895             : 
     896       16456 : void ScDocument::LockStreamValid( bool bLock )
     897             : {
     898       16456 :     mbStreamValidLocked = bLock;
     899       16456 : }
     900             : 
     901             : 
     902        8228 : bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const
     903             : {
     904        8228 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     905        8228 :         return maTabs[nTab]->IsPendingRowHeights();
     906             : 
     907           0 :     return false;
     908             : }
     909             : 
     910             : 
     911           0 : void ScDocument::SetPendingRowHeights( SCTAB nTab, bool bSet )
     912             : {
     913           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     914           0 :         maTabs[nTab]->SetPendingRowHeights( bSet );
     915           0 : }
     916             : 
     917             : 
     918         158 : void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
     919             : {
     920         158 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     921             :     {
     922         158 :         if ( bImportingXML )
     923             :         {
     924             :             // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
     925             :             // is applied in SetImportingXML(false). This is so the shapes can be loaded in
     926             :             // normal LTR mode.
     927             : 
     928           0 :             maTabs[nTab]->SetLoadingRTL( bRTL );
     929         158 :             return;
     930             :         }
     931             : 
     932         158 :         maTabs[nTab]->SetLayoutRTL( bRTL );     // only sets the flag
     933         158 :         maTabs[nTab]->SetDrawPageSize();
     934             : 
     935             :         //  mirror existing objects:
     936             : 
     937         158 :         if (pDrawLayer)
     938             :         {
     939           4 :             SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
     940             :             OSL_ENSURE(pPage,"Page ?");
     941           4 :             if (pPage)
     942             :             {
     943           4 :                 SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
     944           4 :                 SdrObject* pObject = aIter.Next();
     945          10 :                 while (pObject)
     946             :                 {
     947             :                     //  objects with ScDrawObjData are re-positioned in SetPageSize,
     948             :                     //  don't mirror again
     949           2 :                     ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
     950           2 :                     if ( !pData )
     951           2 :                         pDrawLayer->MirrorRTL( pObject );
     952             : 
     953           2 :                     pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB );
     954             : 
     955           2 :                     pObject = aIter.Next();
     956           4 :                 }
     957             :             }
     958             :         }
     959             :     }
     960             : }
     961             : 
     962             : 
     963      110297 : bool ScDocument::IsLayoutRTL( SCTAB nTab ) const
     964             : {
     965      110297 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
     966      110113 :         return maTabs[nTab]->IsLayoutRTL();
     967             : 
     968         184 :     return false;
     969             : }
     970             : 
     971             : 
     972       24057 : bool ScDocument::IsNegativePage( SCTAB nTab ) const
     973             : {
     974             :     //  Negative page area is always used for RTL layout.
     975             :     //  The separate method is used to find all RTL handling of drawing objects.
     976       24057 :     return IsLayoutRTL( nTab );
     977             : }
     978             : 
     979             : 
     980             : /* ----------------------------------------------------------------------------
     981             :     used search area:
     982             : 
     983             :     GetCellArea  - Only Data
     984             :     GetTableArea - Data / Attributes
     985             :     GetPrintArea - intended for character objects,
     986             :                     sweeps attributes all the way to bottom / right
     987             : ---------------------------------------------------------------------------- */
     988             : 
     989             : 
     990          28 : bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
     991             : {
     992          28 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
     993          28 :         if (maTabs[nTab])
     994          28 :             return maTabs[nTab]->GetCellArea( rEndCol, rEndRow );
     995             : 
     996           0 :     rEndCol = 0;
     997           0 :     rEndRow = 0;
     998           0 :     return false;
     999             : }
    1000             : 
    1001             : 
    1002        2825 : bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
    1003             : {
    1004        2825 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
    1005        2825 :         if (maTabs[nTab])
    1006        2825 :             return maTabs[nTab]->GetTableArea( rEndCol, rEndRow );
    1007             : 
    1008           0 :     rEndCol = 0;
    1009           0 :     rEndRow = 0;
    1010           0 :     return false;
    1011             : }
    1012             : 
    1013         558 : bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const
    1014             : {
    1015         558 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
    1016           0 :         return false;
    1017             : 
    1018             :     SCCOL nCol1, nCol2;
    1019             :     SCROW nRow1, nRow2;
    1020         558 :     maTabs[nTab]->GetFirstDataPos(nCol1, nRow1);
    1021         558 :     maTabs[nTab]->GetLastDataPos(nCol2, nRow2);
    1022             : 
    1023         558 :     if (nCol1 > nCol2 || nRow1 > nRow2)
    1024             :         // invalid range.
    1025           1 :         return false;
    1026             : 
    1027             :     // Make sure the area only shrinks, and doesn't grow.
    1028         557 :     if (rStartCol < nCol1)
    1029          67 :         rStartCol = nCol1;
    1030         557 :     if (nCol2 < rEndCol)
    1031         509 :         rEndCol = nCol2;
    1032         557 :     if (rStartRow < nRow1)
    1033          71 :         rStartRow = nRow1;
    1034         557 :     if (nRow2 < rEndRow)
    1035         513 :         rEndRow = nRow2;
    1036             : 
    1037         557 :     if (rStartCol > rEndCol || rStartRow > rEndRow)
    1038             :         // invalid range.
    1039           0 :         return false;
    1040             : 
    1041         557 :     return true;  // success!
    1042             : }
    1043             : 
    1044          11 : bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol,
    1045             :         SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
    1046             : {
    1047          11 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
    1048             :     {
    1049           0 :         o_bShrunk = false;
    1050           0 :         return false;
    1051             :     }
    1052          11 :     return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly);
    1053             : }
    1054             : 
    1055           0 : SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const
    1056             : {
    1057           0 :     const ScTable* pTab = FetchTable(nTab);
    1058           0 :     if (!pTab)
    1059           0 :         return -1;
    1060             : 
    1061           0 :     return pTab->GetLastDataRow(nCol1, nCol2, nLastRow);
    1062             : }
    1063             : 
    1064             : // connected area
    1065             : 
    1066          35 : void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
    1067             :                               SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const
    1068             : {
    1069          35 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
    1070          35 :         maTabs[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
    1071          35 : }
    1072             : 
    1073             : 
    1074           0 : void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
    1075             :                                     SCCOL& rEndCol, SCROW& rEndRow )
    1076             : {
    1077           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
    1078           0 :         if (maTabs[nTab])
    1079           0 :             maTabs[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow );
    1080           0 : }
    1081             : 
    1082             : 
    1083           0 : void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList )
    1084             : {
    1085           0 :     ScRangeListRef aNew = new ScRangeList;
    1086           0 :     if (rRangeList.Is())
    1087             :     {
    1088           0 :         for ( size_t i = 0, nCount = rRangeList->size(); i < nCount; i++ )
    1089             :         {
    1090           0 :             ScRange aRange( *(*rRangeList)[i] );
    1091           0 :             if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) ||
    1092           0 :                  ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) )
    1093             :             {
    1094           0 :                 SCCOL nStartCol = aRange.aStart.Col();
    1095           0 :                 SCROW nStartRow = aRange.aStart.Row();
    1096           0 :                 SCCOL nEndCol = aRange.aEnd.Col();
    1097           0 :                 SCROW nEndRow = aRange.aEnd.Row();
    1098           0 :                 SCTAB nTab = aRange.aStart.Tab();
    1099           0 :                 if ( nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
    1100           0 :                     maTabs[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow);
    1101           0 :                 aRange.aStart.SetCol( nStartCol );
    1102           0 :                 aRange.aStart.SetRow( nStartRow );
    1103           0 :                 aRange.aEnd.SetCol( nEndCol );
    1104           0 :                 aRange.aEnd.SetRow( nEndRow );
    1105             :             }
    1106           0 :             aNew->Append(aRange);
    1107             :         }
    1108             :     }
    1109             :     else
    1110             :     {
    1111             :         OSL_FAIL("LimitChartIfAll: Ref==0");
    1112             :     }
    1113           0 :     rRangeList = aNew;
    1114           0 : }
    1115             : 
    1116             : 
    1117         238 : static void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
    1118             : {
    1119             :     // without ScMarkData, leave start/end unchanged
    1120         238 :     if ( pTabMark )
    1121             :     {
    1122          42 :         for (SCTAB nTab=0; nTab< aMaxTab; ++nTab)
    1123          42 :             if (pTabMark->GetTableSelect(nTab))
    1124             :             {
    1125             :                 // find first range of consecutive selected sheets
    1126          42 :                 rTabRangeStart = pTabMark->GetFirstSelected();
    1127          84 :                 while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
    1128           0 :                     ++nTab;
    1129          42 :                 rTabRangeEnd = nTab;
    1130         280 :                 return;
    1131             :             }
    1132             :     }
    1133             : }
    1134             : 
    1135         238 : static bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
    1136             : {
    1137         238 :     if ( pTabMark )
    1138             :     {
    1139             :         // find next range of consecutive selected sheets after rTabRangeEnd
    1140          66 :         for (SCTAB nTab=rTabRangeEnd+1; nTab< aMaxTab; ++nTab)
    1141          24 :             if (pTabMark->GetTableSelect(nTab))
    1142             :             {
    1143           0 :                 rTabRangeStart = nTab;
    1144           0 :                 while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
    1145           0 :                     ++nTab;
    1146           0 :                 rTabRangeEnd = nTab;
    1147           0 :                 return true;
    1148             :             }
    1149             :     }
    1150         238 :     return false;
    1151             : }
    1152             : 
    1153             : 
    1154           3 : bool ScDocument::CanInsertRow( const ScRange& rRange ) const
    1155             : {
    1156           3 :     SCCOL nStartCol = rRange.aStart.Col();
    1157           3 :     SCROW nStartRow = rRange.aStart.Row();
    1158           3 :     SCTAB nStartTab = rRange.aStart.Tab();
    1159           3 :     SCCOL nEndCol = rRange.aEnd.Col();
    1160           3 :     SCROW nEndRow = rRange.aEnd.Row();
    1161           3 :     SCTAB nEndTab = rRange.aEnd.Tab();
    1162           3 :     PutInOrder( nStartCol, nEndCol );
    1163           3 :     PutInOrder( nStartRow, nEndRow );
    1164           3 :     PutInOrder( nStartTab, nEndTab );
    1165           3 :     SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
    1166             : 
    1167           3 :     bool bTest = true;
    1168           3 :     for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
    1169           0 :         if (maTabs[i])
    1170           0 :             bTest &= maTabs[i]->TestInsertRow( nStartCol, nEndCol, nStartRow, nSize );
    1171             : 
    1172           3 :     return bTest;
    1173             : }
    1174             : 
    1175             : namespace {
    1176             : 
    1177             : struct StartNeededListenersHandler : std::unary_function<ScTable*, void>
    1178             : {
    1179          30 :     void operator() (ScTable* p)
    1180             :     {
    1181          30 :         if (p)
    1182          30 :             p->StartNeededListeners();
    1183          30 :     }
    1184             : };
    1185             : 
    1186             : struct SetDirtyIfPostponedHandler : std::unary_function<ScTable*, void>
    1187             : {
    1188          30 :     void operator() (ScTable* p)
    1189             :     {
    1190          30 :         if (p)
    1191          30 :             p->SetDirtyIfPostponed();
    1192          30 :     }
    1193             : };
    1194             : 
    1195             : struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void>
    1196             : {
    1197         134 :     void operator() (ScTable* p)
    1198             :     {
    1199         134 :         if (p)
    1200         134 :             p->BroadcastRecalcOnRefMove();
    1201         134 :     }
    1202             : };
    1203             : 
    1204             : }
    1205             : 
    1206          37 : bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
    1207             :                             SCCOL nEndCol,   SCTAB nEndTab,
    1208             :                             SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc,
    1209             :                             const ScMarkData* pTabMark )
    1210             : {
    1211             :     SCTAB i;
    1212             : 
    1213          37 :     PutInOrder( nStartCol, nEndCol );
    1214          37 :     PutInOrder( nStartTab, nEndTab );
    1215          37 :     if ( pTabMark )
    1216             :     {
    1217           5 :         nStartTab = 0;
    1218           5 :         nEndTab = static_cast<SCTAB>(maTabs.size()) -1;
    1219             :     }
    1220             : 
    1221          37 :     bool bTest = true;
    1222          37 :     bool bRet = false;
    1223          37 :     bool bOldAutoCalc = GetAutoCalc();
    1224          37 :     SetAutoCalc( false );   // avoid mulitple calculations
    1225          74 :     for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
    1226          37 :         if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1227          37 :             bTest &= maTabs[i]->TestInsertRow(nStartCol, nEndCol, nStartRow, nSize);
    1228          37 :     if (bTest)
    1229             :     {
    1230             :         // UpdateBroadcastAreas have to be called before UpdateReference, so that entries
    1231             :         // aren't shifted that would be rebuild at UpdateReference
    1232             : 
    1233             :         // handle chunks of consecutive selected sheets together
    1234          37 :         SCTAB nTabRangeStart = nStartTab;
    1235          37 :         SCTAB nTabRangeEnd = nEndTab;
    1236          37 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1237          37 :         do
    1238             :         {
    1239             :             UpdateBroadcastAreas( URM_INSDEL, ScRange(
    1240             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1241          37 :                 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 );
    1242             :         }
    1243          37 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1244             : 
    1245          37 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1246             : 
    1247          37 :         sc::RefUpdateContext aCxt(*this);
    1248          37 :         aCxt.meMode = URM_INSDEL;
    1249          37 :         aCxt.maRange = ScRange(nStartCol, nStartRow, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
    1250          37 :         aCxt.mnRowDelta = nSize;
    1251          37 :         do
    1252             :         {
    1253          37 :             UpdateReference(aCxt, pRefUndoDoc, false);        // without drawing objects
    1254             :         }
    1255          37 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1256             : 
    1257          74 :         for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
    1258          37 :             if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1259          37 :                 maTabs[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
    1260             : 
    1261             :         //  UpdateRef for drawing layer must be after inserting,
    1262             :         //  when the new row heights are known.
    1263          74 :         for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
    1264          37 :             if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1265          37 :                 maTabs[i]->UpdateDrawRef( URM_INSDEL,
    1266             :                             nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab,
    1267          74 :                             0, static_cast<SCsROW>(nSize), 0 );
    1268             : 
    1269          37 :         if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
    1270             :         {   // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
    1271             :             // ein neues Listening faellig, bisherige Listener wurden in
    1272             :             // FormulaCell UpdateReference abgehaengt
    1273           0 :             StartAllListeners();
    1274             :         }
    1275             :         else
    1276             :         {   // Listeners have been removed in UpdateReference
    1277          37 :             TableContainer::iterator it = maTabs.begin();
    1278          77 :             for (; it != maTabs.end(); ++it)
    1279          40 :                 if (*it)
    1280          40 :                     (*it)->StartNeededListeners();
    1281             :             // At least all cells using range names pointing relative to the
    1282             :             // moved range must be recalculated, and all cells marked postponed
    1283             :             // dirty.
    1284          37 :             it = maTabs.begin();
    1285          77 :             for (; it != maTabs.end(); ++it)
    1286          40 :                 if (*it)
    1287          40 :                     (*it)->SetDirtyIfPostponed();
    1288             : 
    1289          37 :             std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
    1290             :         }
    1291          37 :         bRet = true;
    1292             :     }
    1293          37 :     SetAutoCalc( bOldAutoCalc );
    1294          37 :     if ( bRet )
    1295          37 :         pChartListenerCollection->UpdateDirtyCharts();
    1296          37 :     return bRet;
    1297             : }
    1298             : 
    1299             : 
    1300          16 : bool ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc )
    1301             : {
    1302          32 :     return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(),
    1303          32 :                       rRange.aEnd.Col(),   rRange.aEnd.Tab(),
    1304          16 :                       rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
    1305          80 :                       pRefUndoDoc );
    1306             : }
    1307             : 
    1308             : 
    1309          37 : void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
    1310             :                             SCCOL nEndCol,   SCTAB nEndTab,
    1311             :                             SCROW nStartRow, SCSIZE nSize,
    1312             :                             ScDocument* pRefUndoDoc, bool* pUndoOutline,
    1313             :                             const ScMarkData* pTabMark )
    1314             : {
    1315             :     SCTAB i;
    1316             : 
    1317          37 :     PutInOrder( nStartCol, nEndCol );
    1318          37 :     PutInOrder( nStartTab, nEndTab );
    1319          37 :     if ( pTabMark )
    1320             :     {
    1321           5 :         nStartTab = 0;
    1322           5 :         nEndTab = static_cast<SCTAB>(maTabs.size())-1;
    1323             :     }
    1324             : 
    1325          37 :     bool bOldAutoCalc = GetAutoCalc();
    1326          37 :     SetAutoCalc( false );   // avoid multiple calculations
    1327             : 
    1328             :     // handle chunks of consecutive selected sheets together
    1329          37 :     SCTAB nTabRangeStart = nStartTab;
    1330          37 :     SCTAB nTabRangeEnd = nEndTab;
    1331          37 :     lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1332          37 :     do
    1333             :     {
    1334          37 :         if ( ValidRow(nStartRow+nSize) )
    1335             :         {
    1336             :             DelBroadcastAreasInRange( ScRange(
    1337             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1338          37 :                 ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) );
    1339             :             UpdateBroadcastAreas( URM_INSDEL, ScRange(
    1340          37 :                 ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ),
    1341          74 :                 ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 );
    1342             :         }
    1343             :         else
    1344             :             DelBroadcastAreasInRange( ScRange(
    1345             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1346           0 :                 ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) );
    1347             :     }
    1348          37 :     while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1349             : 
    1350          37 :     sc::RefUpdateContext aCxt(*this);
    1351          37 :     if ( ValidRow(nStartRow+nSize) )
    1352             :     {
    1353          37 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1354          37 :         aCxt.meMode = URM_INSDEL;
    1355          37 :         aCxt.maRange = ScRange(nStartCol, nStartRow+nSize, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
    1356          37 :         aCxt.mnRowDelta = -(static_cast<SCROW>(nSize));
    1357          37 :         do
    1358             :         {
    1359          37 :             UpdateReference(aCxt, pRefUndoDoc, true, false);
    1360             :         }
    1361          37 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1362             :     }
    1363             : 
    1364          37 :     if (pUndoOutline)
    1365           1 :         *pUndoOutline = false;
    1366             : 
    1367          77 :     for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
    1368          40 :         if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1369          37 :             maTabs[i]->DeleteRow(aCxt.maRegroupCols, nStartCol, nEndCol, nStartRow, nSize, pUndoOutline);
    1370             : 
    1371          37 :     if ( ValidRow(nStartRow+nSize) )
    1372             :     {   // Listeners have been removed in UpdateReference
    1373          37 :         TableContainer::iterator it = maTabs.begin();
    1374          77 :         for (; it != maTabs.end(); ++it)
    1375          40 :             if (*it)
    1376          40 :                 (*it)->StartNeededListeners();
    1377             :         // At least all cells using range names pointing relative to the moved
    1378             :         // range must be recalculated, and all cells marked postponed dirty.
    1379          37 :         it = maTabs.begin();
    1380          77 :         for (; it != maTabs.end(); ++it)
    1381          40 :             if (*it)
    1382          40 :                 (*it)->SetDirtyIfPostponed();
    1383             : 
    1384          37 :         std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
    1385             :     }
    1386             : 
    1387          37 :     SetAutoCalc( bOldAutoCalc );
    1388          37 :     pChartListenerCollection->UpdateDirtyCharts();
    1389          37 : }
    1390             : 
    1391             : 
    1392          18 : void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
    1393             : {
    1394          36 :     DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(),
    1395          36 :                rRange.aEnd.Col(),   rRange.aEnd.Tab(),
    1396          18 :                rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
    1397          90 :                pRefUndoDoc, pUndoOutline );
    1398          18 : }
    1399             : 
    1400             : 
    1401           3 : bool ScDocument::CanInsertCol( const ScRange& rRange ) const
    1402             : {
    1403           3 :     SCCOL nStartCol = rRange.aStart.Col();
    1404           3 :     SCROW nStartRow = rRange.aStart.Row();
    1405           3 :     SCTAB nStartTab = rRange.aStart.Tab();
    1406           3 :     SCCOL nEndCol = rRange.aEnd.Col();
    1407           3 :     SCROW nEndRow = rRange.aEnd.Row();
    1408           3 :     SCTAB nEndTab = rRange.aEnd.Tab();
    1409           3 :     PutInOrder( nStartCol, nEndCol );
    1410           3 :     PutInOrder( nStartRow, nEndRow );
    1411           3 :     PutInOrder( nStartTab, nEndTab );
    1412           3 :     SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1);
    1413             : 
    1414           3 :     bool bTest = true;
    1415           3 :     for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
    1416           0 :         if (maTabs[i])
    1417           0 :             bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
    1418             : 
    1419           3 :     return bTest;
    1420             : }
    1421             : 
    1422          27 : bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
    1423             :                             SCROW nEndRow,   SCTAB nEndTab,
    1424             :                             SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
    1425             :                             const ScMarkData* pTabMark )
    1426             : {
    1427             :     SCTAB i;
    1428             : 
    1429          27 :     PutInOrder( nStartRow, nEndRow );
    1430          27 :     PutInOrder( nStartTab, nEndTab );
    1431          27 :     if ( pTabMark )
    1432             :     {
    1433           4 :         nStartTab = 0;
    1434           4 :         nEndTab = static_cast<SCTAB>(maTabs.size())-1;
    1435             :     }
    1436             : 
    1437          27 :     bool bTest = true;
    1438          27 :     bool bRet = false;
    1439          27 :     bool bOldAutoCalc = GetAutoCalc();
    1440          27 :     SetAutoCalc( false );   // avoid multiple calculations
    1441          57 :     for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
    1442          30 :         if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1443          27 :             bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
    1444          27 :     if (bTest)
    1445             :     {
    1446             :         // handle chunks of consecutive selected sheets together
    1447          27 :         SCTAB nTabRangeStart = nStartTab;
    1448          27 :         SCTAB nTabRangeEnd = nEndTab;
    1449          27 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1450          27 :         do
    1451             :         {
    1452             :             UpdateBroadcastAreas( URM_INSDEL, ScRange(
    1453             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1454          27 :                 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 );
    1455             :         }
    1456          27 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1457             : 
    1458          27 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1459             : 
    1460          27 :         sc::RefUpdateContext aCxt(*this);
    1461          27 :         aCxt.meMode = URM_INSDEL;
    1462          27 :         aCxt.maRange = ScRange(nStartCol, nStartRow, nTabRangeStart, MAXCOL, nEndRow, nTabRangeEnd);
    1463          27 :         aCxt.mnColDelta = nSize;
    1464          27 :         do
    1465             :         {
    1466          27 :             UpdateReference(aCxt, pRefUndoDoc, true, false);
    1467             :         }
    1468          27 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1469             : 
    1470          57 :         for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
    1471          30 :             if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1472          27 :                 maTabs[i]->InsertCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize);
    1473             : 
    1474          27 :         if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
    1475             :         {   // durch Restaurierung von Referenzen auf geloeschte Bereiche ist
    1476             :             // ein neues Listening faellig, bisherige Listener wurden in
    1477             :             // FormulaCell UpdateReference abgehaengt
    1478           0 :             StartAllListeners();
    1479             :         }
    1480             :         else
    1481             :         {
    1482             :             // Listeners have been removed in UpdateReference
    1483          27 :             std::for_each(maTabs.begin(), maTabs.end(), StartNeededListenersHandler());
    1484             :             // At least all cells using range names pointing relative to the
    1485             :             // moved range must be recalculated, and all cells marked postponed
    1486             :             // dirty.
    1487          27 :             std::for_each(maTabs.begin(), maTabs.end(), SetDirtyIfPostponedHandler());
    1488             :             // Cells containing functions such as CELL, COLUMN or ROW may have
    1489             :             // changed their values on relocation. Broadcast them.
    1490          27 :             std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
    1491             :         }
    1492          27 :         bRet = true;
    1493             :     }
    1494          27 :     SetAutoCalc( bOldAutoCalc );
    1495          27 :     if ( bRet )
    1496          27 :         pChartListenerCollection->UpdateDirtyCharts();
    1497          27 :     return bRet;
    1498             : }
    1499             : 
    1500             : 
    1501          17 : bool ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc )
    1502             : {
    1503          17 :     return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(),
    1504          17 :                       rRange.aEnd.Row(),   rRange.aEnd.Tab(),
    1505          34 :                       rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
    1506          68 :                       pRefUndoDoc );
    1507             : }
    1508             : 
    1509             : 
    1510          18 : void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab,
    1511             :                                 SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
    1512             :                                 bool* pUndoOutline, const ScMarkData* pTabMark )
    1513             : {
    1514             :     SCTAB i;
    1515             : 
    1516          18 :     PutInOrder( nStartRow, nEndRow );
    1517          18 :     PutInOrder( nStartTab, nEndTab );
    1518          18 :     if ( pTabMark )
    1519             :     {
    1520           7 :         nStartTab = 0;
    1521           7 :         nEndTab = static_cast<SCTAB>(maTabs.size())-1;
    1522             :     }
    1523             : 
    1524          18 :     sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations
    1525             : 
    1526             :     // handle chunks of consecutive selected sheets together
    1527          18 :     SCTAB nTabRangeStart = nStartTab;
    1528          18 :     SCTAB nTabRangeEnd = nEndTab;
    1529          18 :     lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1530          18 :     do
    1531             :     {
    1532          18 :         if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
    1533             :         {
    1534             :             DelBroadcastAreasInRange( ScRange(
    1535             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1536          18 :                 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) );
    1537             :             UpdateBroadcastAreas( URM_INSDEL, ScRange(
    1538          18 :                 ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ),
    1539          36 :                 ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 );
    1540             :         }
    1541             :         else
    1542             :             DelBroadcastAreasInRange( ScRange(
    1543             :                 ScAddress( nStartCol, nStartRow, nTabRangeStart ),
    1544           0 :                 ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) );
    1545             :     }
    1546          18 :     while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1547             : 
    1548          36 :     sc::RefUpdateContext aCxt(*this);
    1549          18 :     if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
    1550             :     {
    1551          18 :         lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
    1552          18 :         aCxt.meMode = URM_INSDEL;
    1553          18 :         aCxt.maRange = ScRange(sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, MAXCOL, nEndRow, nTabRangeEnd);
    1554          18 :         aCxt.mnColDelta = -(static_cast<SCCOL>(nSize));
    1555          18 :         do
    1556             :         {
    1557          18 :             UpdateReference(aCxt, pRefUndoDoc, true, false);
    1558             :         }
    1559          18 :         while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
    1560             :     }
    1561             : 
    1562          18 :     if (pUndoOutline)
    1563           3 :         *pUndoOutline = false;
    1564             : 
    1565          42 :     for (i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); ++i)
    1566             :     {
    1567          24 :         if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
    1568          18 :             maTabs[i]->DeleteCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize, pUndoOutline);
    1569             :     }
    1570             : 
    1571          18 :     if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
    1572             :     {// Listeners have been removed in UpdateReference
    1573          18 :         TableContainer::iterator it = maTabs.begin();
    1574          42 :         for (; it != maTabs.end(); ++it)
    1575          24 :             if (*it)
    1576          24 :                 (*it)->StartNeededListeners();
    1577             :         // At least all cells using range names pointing relative to the moved
    1578             :         // range must be recalculated, and all cells marked postponed dirty.
    1579          18 :         it = maTabs.begin();
    1580          42 :         for (; it != maTabs.end(); ++it)
    1581          24 :             if (*it)
    1582          24 :                 (*it)->SetDirtyIfPostponed();
    1583             : 
    1584          18 :         std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
    1585             :     }
    1586             : 
    1587          36 :     pChartListenerCollection->UpdateDirtyCharts();
    1588          18 : }
    1589             : 
    1590             : 
    1591           8 : void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
    1592             : {
    1593           8 :     DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(),
    1594           8 :                rRange.aEnd.Row(),   rRange.aEnd.Tab(),
    1595          16 :                rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
    1596          32 :                pRefUndoDoc, pUndoOutline );
    1597           8 : }
    1598             : 
    1599             : 
    1600             : //  fuer Area-Links: Zellen einuegen/loeschen, wenn sich der Bereich veraendert
    1601             : //  (ohne Paint)
    1602             : 
    1603             : 
    1604           4 : static void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew,
    1605             :                             ScRange& rColRange, bool& rInsCol, bool& rDelCol,
    1606             :                             ScRange& rRowRange, bool& rInsRow, bool& rDelRow )
    1607             : {
    1608             :     OSL_ENSURE( rOld.aStart == rNew.aStart, "FitBlock: Beginning is different" );
    1609             : 
    1610           4 :     rInsCol = rDelCol = rInsRow = rDelRow = false;
    1611             : 
    1612           4 :     SCCOL nStartX = rOld.aStart.Col();
    1613           4 :     SCROW nStartY = rOld.aStart.Row();
    1614           4 :     SCCOL nOldEndX = rOld.aEnd.Col();
    1615           4 :     SCROW nOldEndY = rOld.aEnd.Row();
    1616           4 :     SCCOL nNewEndX = rNew.aEnd.Col();
    1617           4 :     SCROW nNewEndY = rNew.aEnd.Row();
    1618           4 :     SCTAB nTab = rOld.aStart.Tab();
    1619             : 
    1620             :     //  wenn es mehr Zeilen werden, werden Spalten auf der alten Hoehe eingefuegt/geloescht
    1621           4 :     bool bGrowY = ( nNewEndY > nOldEndY );
    1622           4 :     SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY;
    1623           4 :     SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX;
    1624             : 
    1625             :     //  Spalten
    1626             : 
    1627           4 :     if ( nNewEndX > nOldEndX )          // Spalten einfuegen
    1628             :     {
    1629           3 :         rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab );
    1630           3 :         rInsCol = true;
    1631             :     }
    1632           1 :     else if ( nNewEndX < nOldEndX )     // Spalten loeschen
    1633             :     {
    1634           0 :         rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab );
    1635           0 :         rDelCol = true;
    1636             :     }
    1637             : 
    1638             :     //  Zeilen
    1639             : 
    1640           4 :     if ( nNewEndY > nOldEndY )          // Zeilen einfuegen
    1641             :     {
    1642           3 :         rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab );
    1643           3 :         rInsRow = true;
    1644             :     }
    1645           1 :     else if ( nNewEndY < nOldEndY )     // Zeilen loeschen
    1646             :     {
    1647           0 :         rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab );
    1648           0 :         rDelRow = true;
    1649             :     }
    1650           4 : }
    1651             : 
    1652             : 
    1653           6 : bool ScDocument::HasPartOfMerged( const ScRange& rRange )
    1654             : {
    1655           6 :     bool bPart = false;
    1656           6 :     SCTAB nTab = rRange.aStart.Tab();
    1657             : 
    1658           6 :     SCCOL nStartX = rRange.aStart.Col();
    1659           6 :     SCROW nStartY = rRange.aStart.Row();
    1660           6 :     SCCOL nEndX = rRange.aEnd.Col();
    1661           6 :     SCROW nEndY = rRange.aEnd.Row();
    1662             : 
    1663           6 :     if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
    1664           6 :                         HASATTR_MERGED | HASATTR_OVERLAPPED ))
    1665             :     {
    1666           0 :         ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
    1667           0 :         ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab );
    1668             : 
    1669           0 :         bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() ||
    1670           0 :                   nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() );
    1671             :     }
    1672           6 :     return bPart;
    1673             : }
    1674             : 
    1675          38 : size_t ScDocument::GetFormulaHash( const ScAddress& rPos ) const
    1676             : {
    1677          38 :     SCTAB nTab = rPos.Tab();
    1678          38 :     if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
    1679           0 :         return 0;
    1680             : 
    1681          38 :     return maTabs[nTab]->GetFormulaHash(rPos.Col(), rPos.Row());
    1682             : }
    1683             : 
    1684           6 : ScFormulaVectorState ScDocument::GetFormulaVectorState( const ScAddress& rPos ) const
    1685             : {
    1686           6 :     SCTAB nTab = rPos.Tab();
    1687           6 :     if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
    1688           0 :         return FormulaVectorUnknown;
    1689             : 
    1690           6 :     return maTabs[nTab]->GetFormulaVectorState(rPos.Col(), rPos.Row());
    1691             : }
    1692             : 
    1693           0 : formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScAddress& rPos )
    1694             : {
    1695           0 :     SCTAB nTab = rPos.Tab();
    1696           0 :     if (!TableExists(nTab))
    1697           0 :         return formula::FormulaTokenRef();
    1698             : 
    1699           0 :     return maTabs[nTab]->ResolveStaticReference(rPos.Col(), rPos.Row());
    1700             : }
    1701             : 
    1702           0 : formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRange )
    1703             : {
    1704           0 :     SCTAB nTab = rRange.aStart.Tab();
    1705           0 :     if (nTab != rRange.aEnd.Tab() || !TableExists(nTab))
    1706           0 :         return formula::FormulaTokenRef();
    1707             : 
    1708           0 :     return maTabs[nTab]->ResolveStaticReference(
    1709           0 :         rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
    1710             : }
    1711             : 
    1712          20 : formula::VectorRefArray ScDocument::FetchVectorRefArray( const ScAddress& rPos, SCROW nLength )
    1713             : {
    1714          20 :     SCTAB nTab = rPos.Tab();
    1715          20 :     if (!TableExists(nTab))
    1716           0 :         return formula::VectorRefArray();
    1717             : 
    1718          20 :     return maTabs[nTab]->FetchVectorRefArray(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
    1719             : }
    1720             : 
    1721           4 : bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
    1722             : {
    1723           4 :     if ( rOld == rNew )
    1724           1 :         return true;
    1725             : 
    1726           3 :     bool bOk = true;
    1727             :     bool bInsCol,bDelCol,bInsRow,bDelRow;
    1728           3 :     ScRange aColRange,aRowRange;
    1729           3 :     lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
    1730             : 
    1731           3 :     if ( bInsCol && !CanInsertCol( aColRange ) )            // Zellen am Rand ?
    1732           0 :         bOk = false;
    1733           3 :     if ( bInsRow && !CanInsertRow( aRowRange ) )            // Zellen am Rand ?
    1734           0 :         bOk = false;
    1735             : 
    1736           3 :     if ( bInsCol || bDelCol )
    1737             :     {
    1738           3 :         aColRange.aEnd.SetCol(MAXCOL);
    1739           3 :         if ( HasPartOfMerged(aColRange) )
    1740           0 :             bOk = false;
    1741             :     }
    1742           3 :     if ( bInsRow || bDelRow )
    1743             :     {
    1744           3 :         aRowRange.aEnd.SetRow(MAXROW);
    1745           3 :         if ( HasPartOfMerged(aRowRange) )
    1746           0 :             bOk = false;
    1747             :     }
    1748             : 
    1749           3 :     return bOk;
    1750             : }
    1751             : 
    1752             : 
    1753           1 : void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear )
    1754             : {
    1755           1 :     if (bClear)
    1756           1 :         DeleteAreaTab( rOld, IDF_ALL );
    1757             : 
    1758             :     bool bInsCol,bDelCol,bInsRow,bDelRow;
    1759           1 :     ScRange aColRange,aRowRange;
    1760           1 :     lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
    1761             : 
    1762           1 :     if ( bInsCol )
    1763           0 :         InsertCol( aColRange );         // Spalten zuerst einfuegen
    1764           1 :     if ( bInsRow )
    1765           0 :         InsertRow( aRowRange );
    1766             : 
    1767           1 :     if ( bDelRow )
    1768           0 :         DeleteRow( aRowRange );         // Zeilen zuerst loeschen
    1769           1 :     if ( bDelCol )
    1770           0 :         DeleteCol( aColRange );
    1771             : 
    1772             :     //  Referenzen um eingefuegte Zeilen erweitern
    1773             : 
    1774           1 :     if ( bInsCol || bInsRow )
    1775             :     {
    1776           0 :         ScRange aGrowSource = rOld;
    1777           0 :         aGrowSource.aEnd.SetCol(std::min( rOld.aEnd.Col(), rNew.aEnd.Col() ));
    1778           0 :         aGrowSource.aEnd.SetRow(std::min( rOld.aEnd.Row(), rNew.aEnd.Row() ));
    1779           0 :         SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0;
    1780           0 :         SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0;
    1781           0 :         UpdateGrow( aGrowSource, nGrowX, nGrowY );
    1782             :     }
    1783           1 : }
    1784             : 
    1785             : 
    1786         152 : void ScDocument::DeleteArea(SCCOL nCol1, SCROW nRow1,
    1787             :                             SCCOL nCol2, SCROW nRow2,
    1788             :                             const ScMarkData& rMark, sal_uInt16 nDelFlag)
    1789             : {
    1790         152 :     PutInOrder( nCol1, nCol2 );
    1791         152 :     PutInOrder( nRow1, nRow2 );
    1792         152 :     bool bOldAutoCalc = GetAutoCalc();
    1793         152 :     SetAutoCalc( false );   // avoid multiple calculations
    1794         365 :     for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
    1795         213 :         if (maTabs[i])
    1796         213 :             if ( rMark.GetTableSelect(i) || bIsUndo )
    1797         152 :                 maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
    1798         152 :     SetAutoCalc( bOldAutoCalc );
    1799         152 : }
    1800             : 
    1801             : 
    1802         983 : void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
    1803             :                                 SCCOL nCol2, SCROW nRow2,
    1804             :                                 SCTAB nTab, sal_uInt16 nDelFlag)
    1805             : {
    1806         983 :     PutInOrder( nCol1, nCol2 );
    1807         983 :     PutInOrder( nRow1, nRow2 );
    1808         983 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    1809             :     {
    1810         979 :         bool bOldAutoCalc = GetAutoCalc();
    1811         979 :         SetAutoCalc( false );   // avoid multiple calculations
    1812         979 :         maTabs[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
    1813         979 :         SetAutoCalc( bOldAutoCalc );
    1814             :     }
    1815         983 : }
    1816             : 
    1817             : 
    1818          12 : void ScDocument::DeleteAreaTab( const ScRange& rRange, sal_uInt16 nDelFlag )
    1819             : {
    1820          24 :     for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ )
    1821          12 :         DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
    1822          12 :                        rRange.aEnd.Col(),   rRange.aEnd.Row(),
    1823          36 :                        nTab, nDelFlag );
    1824          12 : }
    1825             : 
    1826             : 
    1827          18 : void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSelection,
    1828             :                                 bool bColInfo, bool bRowInfo )
    1829             : {
    1830          18 :     if (bIsUndo)
    1831             :     {
    1832          18 :         Clear();
    1833             : 
    1834          18 :         xPoolHelper = pSrcDoc->xPoolHelper;
    1835             : 
    1836             : 
    1837          18 :         OUString aString;
    1838          37 :         for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++)
    1839          19 :             if ( rTabSelection.GetTableSelect( nTab ) )
    1840             :             {
    1841          18 :                 ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
    1842          18 :                 if (nTab < static_cast<SCTAB>(maTabs.size()))
    1843           0 :                     maTabs[nTab] = pTable;
    1844             :                 else
    1845          18 :                     maTabs.push_back(pTable);
    1846             :             }
    1847             :             else
    1848             :             {
    1849           1 :                 if (nTab < static_cast<SCTAB>(maTabs.size()))
    1850           0 :                     maTabs[nTab]=NULL;
    1851             :                 else
    1852           1 :                     maTabs.push_back(NULL);
    1853          18 :             }
    1854             :     }
    1855             :     else
    1856             :     {
    1857             :         OSL_FAIL("InitUndo");
    1858             :     }
    1859          18 : }
    1860             : 
    1861             : 
    1862         856 : void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2,
    1863             :                                 bool bColInfo, bool bRowInfo )
    1864             : {
    1865         856 :     if (bIsUndo)
    1866             :     {
    1867         856 :         Clear();
    1868             : 
    1869             :         // Undo document shares its pooled resources with the source document.
    1870         856 :         xPoolHelper = pSrcDoc->xPoolHelper;
    1871         856 :         mpCellStringPool = pSrcDoc->mpCellStringPool;
    1872             : 
    1873         856 :         if (pSrcDoc->pShell->GetMedium())
    1874         856 :             maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
    1875             : 
    1876         856 :         OUString aString;
    1877         856 :         if ( nTab2 >= static_cast<SCTAB>(maTabs.size()))
    1878         856 :             maTabs.resize(nTab2 + 1, NULL);
    1879        1736 :         for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
    1880             :         {
    1881         880 :             ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
    1882         880 :             maTabs[nTab] = pTable;
    1883         856 :         }
    1884             :     }
    1885             :     else
    1886             :     {
    1887             :         OSL_FAIL("InitUndo");
    1888             :     }
    1889         856 : }
    1890             : 
    1891             : 
    1892          35 : void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, bool bColInfo, bool bRowInfo )
    1893             : {
    1894          35 :     if (bIsUndo)
    1895             :     {
    1896          35 :         OUString aString;
    1897          35 :         if (nTab2 >= static_cast<SCTAB>(maTabs.size()))
    1898             :         {
    1899          19 :             maTabs.resize(nTab2+1,NULL);
    1900             :         }
    1901         104 :         for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
    1902          69 :             if (!maTabs[nTab])
    1903             :             {
    1904          25 :                 maTabs[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
    1905          35 :             }
    1906             : 
    1907             :     }
    1908             :     else
    1909             :     {
    1910             :         OSL_FAIL("InitUndo");
    1911             :     }
    1912          35 : }
    1913             : 
    1914             : 
    1915           0 : void ScDocument::SetCutMode( bool bVal )
    1916             : {
    1917           0 :     if (bIsClip)
    1918           0 :         GetClipParam().mbCutMode = bVal;
    1919             :     else
    1920             :     {
    1921             :         OSL_FAIL("SetCutMode without bIsClip");
    1922             :     }
    1923           0 : }
    1924             : 
    1925             : 
    1926          33 : bool ScDocument::IsCutMode()
    1927             : {
    1928          33 :     if (bIsClip)
    1929          33 :         return GetClipParam().mbCutMode;
    1930             :     else
    1931             :     {
    1932             :         OSL_FAIL("IsCutMode without bIsClip");
    1933           0 :         return false;
    1934             :     }
    1935             : }
    1936             : 
    1937             : 
    1938         299 : void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
    1939             :                             SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
    1940             :                             sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
    1941             :                             const ScMarkData* pMarks, bool bColRowFlags )
    1942             : {
    1943         299 :     PutInOrder( nCol1, nCol2 );
    1944         299 :     PutInOrder( nRow1, nRow2 );
    1945         299 :     PutInOrder( nTab1, nTab2 );
    1946         299 :     if( pDestDoc->aDocName.isEmpty() )
    1947         228 :         pDestDoc->aDocName = aDocName;
    1948         299 :     if (ValidTab(nTab1) && ValidTab(nTab2))
    1949             :     {
    1950         299 :         sc::CopyToDocContext aCxt(*pDestDoc);
    1951         299 :         bool bOldAutoCalc = pDestDoc->GetAutoCalc();
    1952         299 :         pDestDoc->SetAutoCalc( false );     // avoid multiple calculations
    1953         299 :         SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
    1954         603 :         for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
    1955             :         {
    1956         304 :             if (maTabs[i] && pDestDoc->maTabs[i])
    1957         302 :                 maTabs[i]->CopyToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
    1958         302 :                                       bOnlyMarked, pDestDoc->maTabs[i], pMarks,
    1959         906 :                                       false, bColRowFlags );
    1960             :         }
    1961         299 :         pDestDoc->SetAutoCalc( bOldAutoCalc );
    1962             :     }
    1963         299 : }
    1964             : 
    1965             : 
    1966           0 : void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
    1967             :                             SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
    1968             :                             sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
    1969             :                             const ScMarkData* pMarks)
    1970             : {
    1971           0 :     PutInOrder( nCol1, nCol2 );
    1972           0 :     PutInOrder( nRow1, nRow2 );
    1973           0 :     PutInOrder( nTab1, nTab2 );
    1974           0 :     if (ValidTab(nTab1) && ValidTab(nTab2))
    1975             :     {
    1976           0 :         bool bOldAutoCalc = pDestDoc->GetAutoCalc();
    1977           0 :         pDestDoc->SetAutoCalc( false );     // avoid multiple calculations
    1978           0 :         if (nTab1 > 0)
    1979           0 :             CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
    1980             : 
    1981           0 :         sc::CopyToDocContext aCxt(*pDestDoc);
    1982             :         OSL_ASSERT( nTab2 < static_cast<SCTAB>(maTabs.size()) && nTab2 < static_cast<SCTAB>(pDestDoc->maTabs.size()));
    1983           0 :         for (SCTAB i = nTab1; i <= nTab2; i++)
    1984             :         {
    1985           0 :             if (maTabs[i] && pDestDoc->maTabs[i])
    1986           0 :                 maTabs[i]->UndoToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
    1987           0 :                                     bOnlyMarked, pDestDoc->maTabs[i], pMarks);
    1988             :         }
    1989             : 
    1990           0 :         if (nTab2 < MAXTAB)
    1991           0 :             CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, false, pDestDoc, pMarks );
    1992           0 :         pDestDoc->SetAutoCalc( bOldAutoCalc );
    1993             :     }
    1994           0 : }
    1995             : 
    1996             : 
    1997         677 : void ScDocument::CopyToDocument(const ScRange& rRange,
    1998             :                             sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
    1999             :                             const ScMarkData* pMarks, bool bColRowFlags)
    2000             : {
    2001         677 :     ScRange aNewRange = rRange;
    2002         677 :     aNewRange.Justify();
    2003             : 
    2004         677 :     if( pDestDoc->aDocName.isEmpty() )
    2005         677 :         pDestDoc->aDocName = aDocName;
    2006         677 :     bool bOldAutoCalc = pDestDoc->GetAutoCalc();
    2007         677 :     pDestDoc->SetAutoCalc( false );     // avoid multiple calculations
    2008         677 :     sc::CopyToDocContext aCxt(*pDestDoc);
    2009         677 :     SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
    2010        1348 :     for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab() && i < nMinSizeBothTabs; i++)
    2011             :     {
    2012         671 :         if (!TableExists(i) || !pDestDoc->TableExists(i))
    2013           1 :             continue;
    2014             : 
    2015        1340 :         maTabs[i]->CopyToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
    2016         670 :                                aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
    2017         670 :                                nFlags, bOnlyMarked, pDestDoc->maTabs[i],
    2018        3350 :                                pMarks, false, bColRowFlags);
    2019             :     }
    2020         677 :     pDestDoc->SetAutoCalc( bOldAutoCalc );
    2021         677 : }
    2022             : 
    2023             : 
    2024           7 : void ScDocument::UndoToDocument(const ScRange& rRange,
    2025             :                             sal_uInt16 nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
    2026             :                             const ScMarkData* pMarks)
    2027             : {
    2028           7 :     sc::AutoCalcSwitch aAutoCalcSwitch(*this, false);
    2029             : 
    2030           7 :     ScRange aNewRange = rRange;
    2031           7 :     aNewRange.Justify();
    2032           7 :     SCTAB nTab1 = aNewRange.aStart.Tab();
    2033           7 :     SCTAB nTab2 = aNewRange.aEnd.Tab();
    2034             : 
    2035          14 :     sc::CopyToDocContext aCxt(*pDestDoc);
    2036           7 :     if (nTab1 > 0)
    2037           2 :         CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
    2038             : 
    2039           7 :     SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
    2040          14 :     for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
    2041             :     {
    2042           7 :         if (maTabs[i] && pDestDoc->maTabs[i])
    2043          14 :             maTabs[i]->UndoToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
    2044           7 :                                     aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
    2045          28 :                                     nFlags, bOnlyMarked, pDestDoc->maTabs[i], pMarks);
    2046             :     }
    2047             : 
    2048           7 :     if (nTab2 < static_cast<SCTAB>(maTabs.size()))
    2049          14 :         CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,maTabs.size(), IDF_FORMULA, false, pDestDoc, pMarks );
    2050           7 : }
    2051             : 
    2052             : // bUseRangeForVBA added for VBA api support to allow content of a specified
    2053             : // range to be copied ( e.g. don't use marked data but the just the range
    2054             : // specified by rClipParam
    2055          38 : void ScDocument::CopyToClip(const ScClipParam& rClipParam,
    2056             :                             ScDocument* pClipDoc, const ScMarkData* pMarks,
    2057             :                             bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions, bool bUseRangeForVBA )
    2058             : {
    2059             :     OSL_ENSURE( !bUseRangeForVBA && ( bAllTabs ||  pMarks ), "CopyToClip: ScMarkData fails" );
    2060             : 
    2061          38 :     if (bIsClip)
    2062          38 :         return;
    2063             : 
    2064          38 :     if (!pClipDoc)
    2065             :     {
    2066             :         OSL_TRACE("CopyToClip: no ClipDoc");
    2067           0 :         pClipDoc = SC_MOD()->GetClipDoc();
    2068             :     }
    2069             : 
    2070          38 :     if (pShell->GetMedium())
    2071             :     {
    2072          38 :         pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
    2073             :         // for unsaved files use the title name and adjust during save of file
    2074          38 :         if (pClipDoc->maFileURL.isEmpty())
    2075          20 :             pClipDoc->maFileURL = pShell->GetName();
    2076             :     }
    2077             :     else
    2078             :     {
    2079           0 :         pClipDoc->maFileURL = pShell->GetName();
    2080             :     }
    2081             : 
    2082             :     //init maTabNames
    2083         113 :     for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
    2084             :     {
    2085          75 :         if( *itr )
    2086             :         {
    2087          75 :             OUString aTabName;
    2088          75 :             (*itr)->GetName(aTabName);
    2089          75 :             pClipDoc->maTabNames.push_back(aTabName);
    2090             :         }
    2091             :         else
    2092           0 :             pClipDoc->maTabNames.push_back(OUString());
    2093             :     }
    2094             : 
    2095          38 :     pClipDoc->aDocName = aDocName;
    2096          38 :     pClipDoc->SetClipParam(rClipParam);
    2097          38 :     ScRange aClipRange = rClipParam.getWholeRange();
    2098          38 :     SCTAB nTab = aClipRange.aStart.Tab();
    2099          38 :     SCTAB i = 0;
    2100          38 :     SCTAB nEndTab =  static_cast<SCTAB>(maTabs.size());
    2101             : 
    2102          38 :     if ( bUseRangeForVBA )
    2103             :     {
    2104           0 :         pClipDoc->ResetClip( this, nTab );
    2105           0 :         i = nTab;
    2106           0 :         nEndTab = nTab + 1;
    2107             :     }
    2108             :     else
    2109          38 :         pClipDoc->ResetClip(this, pMarks);
    2110             : 
    2111          38 :     sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags, bCloneNoteCaptions);
    2112          38 :     CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
    2113             : 
    2114         113 :     for ( ; i < nEndTab; ++i)
    2115             :     {
    2116          75 :         if (!maTabs[i] || i >= static_cast<SCTAB>(pClipDoc->maTabs.size()) || !pClipDoc->maTabs[i])
    2117          38 :             continue;
    2118             : 
    2119          37 :         if ( !bUseRangeForVBA && ( pMarks && !pMarks->GetTableSelect(i) ) )
    2120           0 :             continue;
    2121             : 
    2122          37 :         maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, pClipDoc->maTabs[i]);
    2123             : 
    2124          37 :         if (pDrawLayer && bIncludeObjects)
    2125             :         {
    2126             :             //  also copy drawing objects
    2127             :             Rectangle aObjRect = GetMMRect(
    2128          14 :                 aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
    2129          14 :             pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
    2130             :         }
    2131             :     }
    2132             : 
    2133             :     // Make sure to mark overlapped cells.
    2134          38 :     pClipDoc->ExtendMerge(aClipRange, true);
    2135             : }
    2136             : 
    2137           3 : void ScDocument::CopyStaticToDocument(const ScRange& rSrcRange, SCTAB nDestTab, ScDocument* pDestDoc)
    2138             : {
    2139           3 :     if (!pDestDoc)
    2140           0 :         return;
    2141             : 
    2142           3 :     ScTable* pSrcTab = rSrcRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) ? maTabs[rSrcRange.aStart.Tab()] : NULL;
    2143           3 :     ScTable* pDestTab = nDestTab < static_cast<SCTAB>(pDestDoc->maTabs.size()) ? pDestDoc->maTabs[nDestTab] : NULL;
    2144             : 
    2145           3 :     if (!pSrcTab || !pDestTab)
    2146           0 :         return;
    2147             : 
    2148             :     pSrcTab->CopyStaticToDocument(
    2149           3 :         rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(), pDestTab);
    2150             : }
    2151             : 
    2152           1 : void ScDocument::CopyCellToDocument( const ScAddress& rSrcPos, const ScAddress& rDestPos, ScDocument& rDestDoc )
    2153             : {
    2154           1 :     if (!TableExists(rSrcPos.Tab()) || !rDestDoc.TableExists(rDestPos.Tab()))
    2155           1 :         return;
    2156             : 
    2157           1 :     ScTable& rSrcTab = *maTabs[rSrcPos.Tab()];
    2158           1 :     ScTable& rDestTab = *rDestDoc.maTabs[rDestPos.Tab()];
    2159             : 
    2160           1 :     rSrcTab.CopyCellToDocument(rSrcPos.Col(), rSrcPos.Row(), rDestPos.Col(), rDestPos.Row(), rDestTab);
    2161             : }
    2162             : 
    2163           0 : void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
    2164             :                                 SCCOL nCol2, SCROW nRow2,
    2165             :                                 SCTAB nTab, ScDocument* pClipDoc)
    2166             : {
    2167           0 :     if (!bIsClip)
    2168             :     {
    2169           0 :         if (!pClipDoc)
    2170             :         {
    2171             :             OSL_TRACE("CopyTabToClip: no ClipDoc");
    2172           0 :             pClipDoc = SC_MOD()->GetClipDoc();
    2173             :         }
    2174             : 
    2175           0 :         if (pShell->GetMedium())
    2176             :         {
    2177           0 :             pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
    2178             :             // for unsaved files use the title name and adjust during save of file
    2179           0 :             if (pClipDoc->maFileURL.isEmpty())
    2180           0 :                 pClipDoc->maFileURL = pShell->GetName();
    2181             :         }
    2182             :         else
    2183             :         {
    2184           0 :             pClipDoc->maFileURL = pShell->GetName();
    2185             :         }
    2186             : 
    2187             :         //init maTabNames
    2188           0 :         for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
    2189             :         {
    2190           0 :             if( *itr )
    2191             :             {
    2192           0 :                 OUString aTabName;
    2193           0 :                 (*itr)->GetName(aTabName);
    2194           0 :                 pClipDoc->maTabNames.push_back(aTabName);
    2195             :             }
    2196             :             else
    2197           0 :                 pClipDoc->maTabNames.push_back(OUString());
    2198             :         }
    2199             : 
    2200           0 :         PutInOrder( nCol1, nCol2 );
    2201           0 :         PutInOrder( nRow1, nRow2 );
    2202             : 
    2203           0 :         ScClipParam& rClipParam = pClipDoc->GetClipParam();
    2204           0 :         pClipDoc->aDocName = aDocName;
    2205           0 :         rClipParam.maRanges.RemoveAll();
    2206           0 :         rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
    2207           0 :         pClipDoc->ResetClip( this, nTab );
    2208             : 
    2209           0 :         sc::CopyToClipContext aCxt(*pClipDoc, false, true);
    2210           0 :         if (nTab < static_cast<SCTAB>(maTabs.size()) && nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()))
    2211           0 :             if (maTabs[nTab] && pClipDoc->maTabs[nTab])
    2212           0 :                 maTabs[nTab]->CopyToClip(aCxt, nCol1, nRow1, nCol2, nRow2, pClipDoc->maTabs[nTab]);
    2213             : 
    2214           0 :         pClipDoc->GetClipParam().mbCutMode = false;
    2215             :     }
    2216           0 : }
    2217             : 
    2218             : 
    2219           1 : void ScDocument::TransposeClip( ScDocument* pTransClip, sal_uInt16 nFlags, bool bAsLink )
    2220             : {
    2221             :     OSL_ENSURE( bIsClip && pTransClip && pTransClip->bIsClip,
    2222             :                     "TransposeClip with wrong Document" );
    2223             : 
    2224             :         //  initialisieren
    2225             :         //  -> pTransClip muss vor dem Original-Dokument geloescht werden!
    2226             : 
    2227           1 :     pTransClip->ResetClip(this, (ScMarkData*)NULL);     // alle
    2228             : 
    2229             :         //  Bereiche uebernehmen
    2230             : 
    2231           1 :     if (pRangeName)
    2232             :     {
    2233           0 :         pTransClip->GetRangeName()->clear();
    2234           0 :         ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
    2235           0 :         for (; itr != itrEnd; ++itr)
    2236             :         {
    2237           0 :             sal_uInt16 nIndex = itr->second->GetIndex();
    2238           0 :             ScRangeData* pData = new ScRangeData(*itr->second);
    2239           0 :             if (pTransClip->pRangeName->insert(pData))
    2240           0 :                 pData->SetIndex(nIndex);
    2241             :         }
    2242             :     }
    2243             : 
    2244             :     // The data
    2245             : 
    2246           1 :     ScRange aClipRange = GetClipParam().getWholeRange();
    2247           1 :     if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
    2248             :     {
    2249           2 :         for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
    2250           1 :             if (maTabs[i])
    2251             :             {
    2252             :                 OSL_ENSURE( pTransClip->maTabs[i], "TransposeClip: Table not there" );
    2253           2 :                 maTabs[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
    2254           1 :                                             aClipRange.aEnd.Col(), aClipRange.aEnd.Row(),
    2255           4 :                                             pTransClip->maTabs[i], nFlags, bAsLink );
    2256             : 
    2257           1 :                 if ( pDrawLayer && ( nFlags & IDF_OBJECTS ) )
    2258             :                 {
    2259             :                     //  Drawing objects are copied to the new area without transposing.
    2260             :                     //  CopyFromClip is used to adjust the objects to the transposed block's
    2261             :                     //  cell range area.
    2262             :                     //  (pDrawLayer in the original clipboard document is set only if there
    2263             :                     //  are drawing objects to copy)
    2264             : 
    2265           0 :                     pTransClip->InitDrawLayer();
    2266           0 :                     Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
    2267           0 :                                                         aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i );
    2268             :                     Rectangle aDestRect = pTransClip->GetMMRect( 0, 0,
    2269           0 :                             static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
    2270           0 :                             static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i );
    2271           0 :                     pTransClip->pDrawLayer->CopyFromClip( pDrawLayer, i, aSourceRect, ScAddress(0,0,i), aDestRect );
    2272             :                 }
    2273             :             }
    2274             : 
    2275           1 :         pTransClip->SetClipParam(GetClipParam());
    2276           1 :         pTransClip->GetClipParam().transpose();
    2277             :     }
    2278             :     else
    2279             :     {
    2280             :         OSL_TRACE("TransposeClip: Too big");
    2281             :     }
    2282             : 
    2283             :         //  Dies passiert erst beim Einfuegen...
    2284             : 
    2285           1 :     GetClipParam().mbCutMode = false;
    2286           1 : }
    2287             : 
    2288             : namespace {
    2289             : 
    2290           5 : void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, const std::set<sal_uInt16>& rUsedNames)
    2291             : {
    2292           5 :     pClipRangeName->clear();
    2293           5 :     ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
    2294          11 :     for (; itr != itrEnd; ++itr)        //! DB-Bereiche Pivot-Bereiche auch !!!
    2295             :     {
    2296           6 :         sal_uInt16 nIndex = itr->second->GetIndex();
    2297           6 :         bool bInUse = (rUsedNames.count(nIndex) > 0);
    2298           6 :         if (!bInUse)
    2299           5 :             continue;
    2300             : 
    2301           1 :         ScRangeData* pData = new ScRangeData(*itr->second);
    2302           1 :         if (pClipRangeName->insert(pData))
    2303           1 :             pData->SetIndex(nIndex);
    2304             :     }
    2305           5 : }
    2306             : 
    2307             : }
    2308             : 
    2309          38 : void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
    2310             : {
    2311          38 :     if (!pRangeName || pRangeName->empty())
    2312          71 :         return;
    2313             : 
    2314           5 :     std::set<sal_uInt16> aUsedNames;        // indexes of named ranges that are used in the copied cells
    2315           5 :     SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pClipDoc->maTabs.size()));
    2316          10 :     for (SCTAB i = 0; i < nMinSizeBothTabs; ++i)
    2317           5 :         if (maTabs[i] && pClipDoc->maTabs[i])
    2318           5 :             if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
    2319           5 :                 maTabs[i]->FindRangeNamesInUse(
    2320           5 :                     rClipRange.aStart.Col(), rClipRange.aStart.Row(),
    2321          15 :                     rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
    2322             : 
    2323           5 :     copyUsedNamesToClip(pClipDoc->GetRangeName(), pRangeName, aUsedNames);
    2324             : }
    2325             : 
    2326          60 : ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
    2327          60 :         mpDoc(pDoc)
    2328             : {
    2329          60 :     mpDoc->MergeNumberFormatter(pSrcDoc);
    2330          60 : }
    2331             : 
    2332          60 : ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
    2333             : {
    2334          60 :     mpDoc->pFormatExchangeList = NULL;
    2335          60 : }
    2336             : 
    2337       28040 : void ScDocument::ClearFormulaContext()
    2338             : {
    2339       28040 :     mpFormulaGroupCxt.reset();
    2340       28040 : }
    2341             : 
    2342       69722 : SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos )
    2343             : {
    2344       69722 :     ScTable* pTab = FetchTable(rPos.Tab());
    2345       69722 :     if (!pTab)
    2346           0 :         return NULL;
    2347             : 
    2348       69722 :     return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
    2349             : }
    2350             : 
    2351          14 : const SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos ) const
    2352             : {
    2353          14 :     const ScTable* pTab = FetchTable(rPos.Tab());
    2354          14 :     if (!pTab)
    2355           0 :         return NULL;
    2356             : 
    2357          14 :     return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
    2358             : }
    2359             : 
    2360          72 : void ScDocument::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength )
    2361             : {
    2362          72 :     ScTable* pTab = FetchTable(rTopPos.Tab());
    2363          72 :     if (!pTab || nLength <= 0)
    2364          72 :         return;
    2365             : 
    2366          72 :     pTab->DeleteBroadcasters(rBlockPos, rTopPos.Col(), rTopPos.Row(), rTopPos.Row()+nLength-1);
    2367             : }
    2368             : 
    2369           0 : bool ScDocument::HasBroadcaster( SCTAB nTab, SCCOL nCol ) const
    2370             : {
    2371           0 :     const ScTable* pTab = FetchTable(nTab);
    2372           0 :     if (!pTab)
    2373           0 :         return false;
    2374             : 
    2375           0 :     return pTab->HasBroadcaster(nCol);
    2376             : }
    2377             : 
    2378             : #if DEBUG_COLUMN_STORAGE
    2379             : void ScDocument::DumpFormulaGroups( SCTAB nTab, SCCOL nCol ) const
    2380             : {
    2381             :     const ScTable* pTab = FetchTable(nTab);
    2382             :     if (!pTab)
    2383             :         return;
    2384             : 
    2385             :     pTab->DumpFormulaGroups(nCol);
    2386             : }
    2387             : #endif
    2388             : 
    2389      355096 : bool ScDocument::TableExists( SCTAB nTab ) const
    2390             : {
    2391      355096 :     return ValidTab(nTab) && static_cast<size_t>(nTab) < maTabs.size() && maTabs[nTab];
    2392             : }
    2393             : 
    2394      116963 : ScTable* ScDocument::FetchTable( SCTAB nTab )
    2395             : {
    2396      116963 :     if (!TableExists(nTab))
    2397           4 :         return NULL;
    2398             : 
    2399      116959 :     return maTabs[nTab];
    2400             : }
    2401             : 
    2402        1133 : const ScTable* ScDocument::FetchTable( SCTAB nTab ) const
    2403             : {
    2404        1133 :     if (!TableExists(nTab))
    2405           0 :         return NULL;
    2406             : 
    2407        1133 :     return maTabs[nTab];
    2408             : }
    2409             : 
    2410          60 : void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
    2411             : {
    2412          60 :     SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
    2413          60 :     SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
    2414          60 :     if (pOtherFormatter && pOtherFormatter != pThisFormatter)
    2415             :     {
    2416             :         SvNumberFormatterIndexTable* pExchangeList =
    2417           7 :                  pThisFormatter->MergeFormatter(*(pOtherFormatter));
    2418           7 :         if (!pExchangeList->empty())
    2419           5 :             pFormatExchangeList = pExchangeList;
    2420             :     }
    2421          60 : }
    2422             : 
    2423         526 : ScClipParam& ScDocument::GetClipParam()
    2424             : {
    2425         526 :     if (!mpClipParam.get())
    2426          19 :         mpClipParam.reset(new ScClipParam);
    2427             : 
    2428         526 :     return *mpClipParam;
    2429             : }
    2430             : 
    2431          41 : void ScDocument::SetClipParam(const ScClipParam& rParam)
    2432             : {
    2433          41 :     mpClipParam.reset(new ScClipParam(rParam));
    2434          41 : }
    2435             : 
    2436         810 : bool ScDocument::IsClipboardSource() const
    2437             : {
    2438         810 :     ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
    2439         810 :     return pClipDoc && pClipDoc->xPoolHelper.is() &&
    2440         810 :             xPoolHelper->GetDocPool() == pClipDoc->xPoolHelper->GetDocPool();
    2441             : }
    2442             : 
    2443             : 
    2444          57 : void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
    2445             :                                         SCCOL nCol2, SCROW nRow2,
    2446             :                                         const ScMarkData& rMark, sal_uInt16 nInsFlag )
    2447             : {
    2448          57 :     if (nInsFlag & IDF_CONTENTS)
    2449             :     {
    2450          41 :         sc::StartListeningContext aCxt(*this);
    2451          41 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    2452          41 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    2453          79 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    2454          38 :             if (maTabs[*itr])
    2455          79 :                 maTabs[*itr]->StartListeningInArea(aCxt, nCol1, nRow1, nCol2, nRow2);
    2456             :     }
    2457          57 : }
    2458             : 
    2459             : 
    2460          57 : void ScDocument::BroadcastFromClip( SCCOL nCol1, SCROW nRow1,
    2461             :                                     SCCOL nCol2, SCROW nRow2,
    2462             :                                     const ScMarkData& rMark, sal_uInt16 nInsFlag )
    2463             : {
    2464          57 :     if (nInsFlag & IDF_CONTENTS)
    2465             :     {
    2466          41 :         ScBulkBroadcast aBulkBroadcast( GetBASM());
    2467          41 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    2468          41 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    2469          79 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    2470          38 :             if (maTabs[*itr])
    2471          79 :                 maTabs[*itr]->BroadcastInArea( nCol1, nRow1, nCol2, nRow2 );
    2472             :     }
    2473          57 : }
    2474             : 
    2475      115940 : bool ScDocument::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol )
    2476             : {
    2477      115940 :     if (!TableExists(nTab))
    2478           0 :         return false;
    2479             : 
    2480      115940 :     return maTabs[nTab]->InitColumnBlockPosition(rBlockPos, nCol);
    2481             : }
    2482             : 
    2483          59 : void ScDocument::CopyBlockFromClip(
    2484             :     sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    2485             :     const ScMarkData& rMark, SCsCOL nDx, SCsROW nDy )
    2486             : {
    2487          59 :     TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
    2488          59 :     SCTAB nTabEnd = rCxt.getTabEnd();
    2489          59 :     SCTAB nClipTab = 0;
    2490         115 :     for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
    2491             :     {
    2492          56 :         if (maTabs[i] && rMark.GetTableSelect(i) )
    2493             :         {
    2494          56 :             while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
    2495             : 
    2496          56 :             maTabs[i]->CopyFromClip(
    2497         112 :                 rCxt, nCol1, nRow1, nCol2, nRow2, nDx, nDy, rClipTabs[nClipTab]);
    2498             : 
    2499          56 :             if (rCxt.getClipDoc()->pDrawLayer && (rCxt.getInsertFlag() & IDF_OBJECTS))
    2500             :             {
    2501             :                 //  also copy drawing objects
    2502             : 
    2503             :                 // drawing layer must be created before calling CopyFromClip
    2504             :                 // (ScDocShell::MakeDrawLayer also does InitItems etc.)
    2505             :                 OSL_ENSURE( pDrawLayer, "CopyBlockFromClip: No drawing layer" );
    2506           1 :                 if ( pDrawLayer )
    2507             :                 {
    2508             :                     //  For GetMMRect, the row heights in the target document must already be valid
    2509             :                     //  (copied in an extra step before pasting, or updated after pasting cells, but
    2510             :                     //  before pasting objects).
    2511             : 
    2512             :                     Rectangle aSourceRect = rCxt.getClipDoc()->GetMMRect(
    2513           0 :                                     nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab );
    2514           0 :                     Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i );
    2515           0 :                     pDrawLayer->CopyFromClip(rCxt.getClipDoc()->pDrawLayer, nClipTab, aSourceRect,
    2516           0 :                                                 ScAddress( nCol1, nRow1, i ), aDestRect );
    2517             :                 }
    2518             :             }
    2519             : 
    2520          56 :             nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
    2521             :         }
    2522             :     }
    2523          59 :     if (rCxt.getInsertFlag() & IDF_CONTENTS)
    2524             :     {
    2525          43 :         nClipTab = 0;
    2526          83 :         for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
    2527             :         {
    2528          40 :             if (maTabs[i] && rMark.GetTableSelect(i) )
    2529             :             {
    2530          40 :                 while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
    2531          40 :                 SCsTAB nDz = ((SCsTAB)i) - nClipTab;
    2532             : 
    2533             :                 //  ranges of consecutive selected tables (in clipboard and dest. doc)
    2534             :                 //  must be handled in one UpdateReference call
    2535          40 :                 SCTAB nFollow = 0;
    2536         120 :                 while ( i + nFollow < nTabEnd
    2537           0 :                         && rMark.GetTableSelect( i + nFollow + 1 )
    2538           0 :                         && nClipTab + nFollow < MAXTAB
    2539          40 :                         && rClipTabs[(nClipTab + nFollow + 1) % static_cast<SCTAB>(rClipTabs.size())] )
    2540           0 :                     ++nFollow;
    2541             : 
    2542          40 :                 sc::RefUpdateContext aRefCxt(*this);
    2543          40 :                 aRefCxt.maRange = ScRange(nCol1, nRow1, i, nCol2, nRow2, i+nFollow);
    2544          40 :                 aRefCxt.mnColDelta = nDx;
    2545          40 :                 aRefCxt.mnRowDelta = nDy;
    2546          40 :                 aRefCxt.mnTabDelta = nDz;
    2547          40 :                 if (rCxt.getClipDoc()->GetClipParam().mbCutMode)
    2548             :                 {
    2549           9 :                     bool bOldInserting = IsInsertingFromOtherDoc();
    2550           9 :                     SetInsertingFromOtherDoc( true);
    2551           9 :                     aRefCxt.meMode = URM_MOVE;
    2552           9 :                     UpdateReference(aRefCxt, rCxt.getUndoDoc(), false);
    2553           9 :                     SetInsertingFromOtherDoc( bOldInserting);
    2554             :                 }
    2555             :                 else
    2556             :                 {
    2557          31 :                     aRefCxt.meMode = URM_COPY;
    2558          31 :                     UpdateReference(aRefCxt, rCxt.getUndoDoc(), false);
    2559             :                 }
    2560             : 
    2561          40 :                 nClipTab = (nClipTab+nFollow+1) % (static_cast<SCTAB>(rClipTabs.size()));
    2562          40 :                 i = sal::static_int_cast<SCTAB>( i + nFollow );
    2563             :             }
    2564             :         }
    2565             :     }
    2566          59 : }
    2567             : 
    2568             : 
    2569          34 : void ScDocument::CopyNonFilteredFromClip(
    2570             :     sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
    2571             :     const ScMarkData& rMark, SCsCOL nDx, SCROW & rClipStartRow )
    2572             : {
    2573             :     //  call CopyBlockFromClip for ranges of consecutive non-filtered rows
    2574             :     //  nCol1/nRow1 etc. is in target doc
    2575             : 
    2576             :     //  filtered state is taken from first used table in clipboard (as in GetClipArea)
    2577          34 :     SCTAB nFlagTab = 0;
    2578          34 :     TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
    2579          68 :     while ( nFlagTab < static_cast<SCTAB>(rClipTabs.size()) && !rClipTabs[nFlagTab] )
    2580           0 :         ++nFlagTab;
    2581             : 
    2582          34 :     SCROW nSourceRow = rClipStartRow;
    2583          34 :     SCROW nSourceEnd = 0;
    2584          34 :     if (!rCxt.getClipDoc()->GetClipParam().maRanges.empty())
    2585          34 :         nSourceEnd = rCxt.getClipDoc()->GetClipParam().maRanges.front()->aEnd.Row();
    2586          34 :     SCROW nDestRow = nRow1;
    2587             : 
    2588         102 :     while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
    2589             :     {
    2590             :         // skip filtered rows
    2591          34 :         nSourceRow = rCxt.getClipDoc()->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab);
    2592             : 
    2593          34 :         if ( nSourceRow <= nSourceEnd )
    2594             :         {
    2595             :             // look for more non-filtered rows following
    2596          34 :             SCROW nLastRow = nSourceRow;
    2597          34 :             rCxt.getClipDoc()->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow);
    2598          34 :             SCROW nFollow = nLastRow - nSourceRow;
    2599             : 
    2600          34 :             if (nFollow > nSourceEnd - nSourceRow)
    2601          34 :                 nFollow = nSourceEnd - nSourceRow;
    2602          34 :             if (nFollow > nRow2 - nDestRow)
    2603           0 :                 nFollow = nRow2 - nDestRow;
    2604             : 
    2605          34 :             SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow;
    2606             :             CopyBlockFromClip(
    2607          34 :                 rCxt, nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy);
    2608             : 
    2609          34 :             nSourceRow += nFollow + 1;
    2610          34 :             nDestRow += nFollow + 1;
    2611             :         }
    2612             :     }
    2613          34 :     rClipStartRow = nSourceRow;
    2614          34 : }
    2615             : 
    2616             : 
    2617          57 : void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
    2618             :                                 sal_uInt16 nInsFlag,
    2619             :                                 ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut,
    2620             :                                 bool bAsLink, bool bIncludeFiltered, bool bSkipAttrForEmpty,
    2621             :                                 const ScRangeList * pDestRanges )
    2622             : {
    2623          57 :     if (bIsClip)
    2624           1 :         return;
    2625             : 
    2626          57 :     if (!pClipDoc)
    2627             :     {
    2628             :         OSL_FAIL("CopyFromClip: no ClipDoc");
    2629           0 :         pClipDoc = SC_MOD()->GetClipDoc();
    2630             :     }
    2631             : 
    2632          57 :     if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
    2633           1 :         return;
    2634             : 
    2635          56 :     sc::AutoCalcSwitch aACSwitch(*this, false); // temporarily turn off auto calc.
    2636             : 
    2637         112 :     NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
    2638             : 
    2639          56 :     SCCOL nAllCol1 = rDestRange.aStart.Col();
    2640          56 :     SCROW nAllRow1 = rDestRange.aStart.Row();
    2641          56 :     SCCOL nAllCol2 = rDestRange.aEnd.Col();
    2642          56 :     SCROW nAllRow2 = rDestRange.aEnd.Row();
    2643             : 
    2644          56 :     SCCOL nXw = 0;
    2645          56 :     SCROW nYw = 0;
    2646          56 :     ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
    2647         112 :     for (SCTAB nTab = 0; nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()); nTab++)    // find largest merge overlap
    2648          56 :         if (pClipDoc->maTabs[nTab])                   // all sheets of the clipboard content
    2649             :         {
    2650          56 :             SCCOL nThisEndX = aClipRange.aEnd.Col();
    2651          56 :             SCROW nThisEndY = aClipRange.aEnd.Row();
    2652          56 :             pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
    2653             :                                     aClipRange.aStart.Row(),
    2654         112 :                                     nThisEndX, nThisEndY, nTab );
    2655             :             // only extra value from ExtendMerge
    2656          56 :             nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
    2657          56 :             nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
    2658          56 :             if ( nThisEndX > nXw )
    2659           0 :                 nXw = nThisEndX;
    2660          56 :             if ( nThisEndY > nYw )
    2661           0 :                 nYw = nThisEndY;
    2662             :         }
    2663             : 
    2664             :     SCCOL nDestAddX;
    2665             :     SCROW nDestAddY;
    2666          56 :     pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered );
    2667          56 :     nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX );
    2668          56 :     nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY );   // ClipArea, plus ExtendMerge value
    2669             : 
    2670             :     /*  Decide which contents to delete before copying. Delete all
    2671             :         contents if nInsFlag contains any real content flag.
    2672             :         #i102056# Notes are pasted from clipboard in a second pass,
    2673             :         together with the special flag IDF_ADDNOTES that states to not
    2674             :         overwrite/delete existing cells but to insert the notes into
    2675             :         these cells. In this case, just delete old notes from the
    2676             :         destination area. */
    2677          56 :     sal_uInt16 nDelFlag = IDF_NONE;
    2678          56 :     if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) )
    2679           0 :         nDelFlag |= IDF_NOTE;
    2680          56 :     else if ( nInsFlag & IDF_CONTENTS )
    2681          40 :         nDelFlag |= IDF_CONTENTS;
    2682             : 
    2683          56 :     if (nInsFlag & IDF_ATTRIB)
    2684          39 :         nDelFlag |= IDF_ATTRIB;
    2685             : 
    2686         112 :     sc::CopyFromClipContext aCxt(*this, pRefUndoDoc, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
    2687          56 :     std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
    2688          56 :     aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
    2689          56 :     aCxt.setDeleteFlag(nDelFlag);
    2690             : 
    2691         112 :     ScRangeList aLocalRangeList;
    2692          56 :     if (!pDestRanges)
    2693             :     {
    2694          56 :         aLocalRangeList.Append( rDestRange);
    2695          56 :         pDestRanges = &aLocalRangeList;
    2696             :     }
    2697             : 
    2698          56 :     bInsertingFromOtherDoc = true;  // kein Broadcast/Listener aufbauen bei Insert
    2699             : 
    2700          56 :     SCCOL nClipStartCol = aClipRange.aStart.Col();
    2701          56 :     SCROW nClipStartRow = aClipRange.aStart.Row();
    2702          56 :     SCROW nClipEndRow = aClipRange.aEnd.Row();
    2703         112 :     for ( size_t nRange = 0; nRange < pDestRanges->size(); ++nRange )
    2704             :     {
    2705          56 :         const ScRange* pRange = (*pDestRanges)[nRange];
    2706          56 :         SCCOL nCol1 = pRange->aStart.Col();
    2707          56 :         SCROW nRow1 = pRange->aStart.Row();
    2708          56 :         SCCOL nCol2 = pRange->aEnd.Col();
    2709          56 :         SCROW nRow2 = pRange->aEnd.Row();
    2710             : 
    2711          56 :         if (bSkipAttrForEmpty)
    2712             :         {
    2713             :             // Delete cells in the destination only if their corresponding clip cells are not empty.
    2714           1 :             aCxt.setDestRange(nCol1, nRow1, nCol2, nRow2);
    2715           1 :             DeleteBeforeCopyFromClip(aCxt, rMark);
    2716             :         }
    2717             :         else
    2718          55 :             DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag);
    2719             : 
    2720          56 :         if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2))
    2721           2 :             continue;
    2722             : 
    2723          54 :         SCCOL nC1 = nCol1;
    2724          54 :         SCROW nR1 = nRow1;
    2725          54 :         SCCOL nC2 = nC1 + nXw;
    2726          54 :         if (nC2 > nCol2)
    2727           0 :             nC2 = nCol2;
    2728          54 :         SCROW nR2 = nR1 + nYw;
    2729          54 :         if (nR2 > nRow2)
    2730           0 :             nR2 = nRow2;
    2731             : 
    2732          54 :         const SCCOLROW nThreshold = 8192;
    2733          54 :         bool bPreallocatePattern = ((nInsFlag & IDF_ATTRIB) && (nRow2 - nRow1 > nThreshold));
    2734          54 :         std::vector< SCTAB > vTables;
    2735             : 
    2736          54 :         if (bPreallocatePattern)
    2737             :         {
    2738           0 :             for (SCTAB i = aCxt.getTabStart(); i <= aCxt.getTabEnd(); ++i)
    2739           0 :                 if (maTabs[i] && rMark.GetTableSelect( i ) )
    2740           0 :                     vTables.push_back( i );
    2741             :         }
    2742             : 
    2743          56 :         do
    2744             :         {
    2745             :             // Pasting is done column-wise, when pasting to a filtered
    2746             :             // area this results in partitioning and we have to
    2747             :             // remember and reset the start row for each column until
    2748             :             // it can be advanced for the next chunk of unfiltered
    2749             :             // rows.
    2750          56 :             SCROW nSaveClipStartRow = nClipStartRow;
    2751          56 :             do
    2752             :             {
    2753          56 :                 nClipStartRow = nSaveClipStartRow;
    2754          56 :                 SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol;
    2755          56 :                 SCsROW nDy = ((SCsROW)nR1) - nClipStartRow;
    2756          56 :                 if ( bIncludeFiltered )
    2757             :                 {
    2758             :                     CopyBlockFromClip(
    2759          22 :                         aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nDy);
    2760          22 :                     nClipStartRow += nR2 - nR1 + 1;
    2761             :                 }
    2762             :                 else
    2763             :                 {
    2764             :                     CopyNonFilteredFromClip(
    2765          34 :                         aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow);
    2766             :                 }
    2767          56 :                 nC1 = nC2 + 1;
    2768          56 :                 nC2 = std::min((SCCOL)(nC1 + nXw), nCol2);
    2769          56 :             } while (nC1 <= nCol2);
    2770          56 :             if (nClipStartRow > nClipEndRow)
    2771          55 :                 nClipStartRow = aClipRange.aStart.Row();
    2772          56 :             nC1 = nCol1;
    2773          56 :             nC2 = nC1 + nXw;
    2774          56 :             if (nC2 > nCol2)
    2775           0 :                 nC2 = nCol2;
    2776             : 
    2777             :             // Preallocate pattern memory once if further chunks are to be pasted.
    2778          56 :             if (bPreallocatePattern && (nR2+1) <= nRow2)
    2779             :             {
    2780           0 :                 SCROW nR3 = nR2 + 1;
    2781           0 :                 for (size_t j = 0; j < vTables.size(); ++j)
    2782             :                 {
    2783           0 :                     SCTAB nTab = vTables[j];
    2784           0 :                     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
    2785             :                     {
    2786             :                         // Pattern count of the first chunk pasted.
    2787           0 :                         SCSIZE nChunk = GetPatternCount( nTab, nCol, nR1, nR2);
    2788             :                         // If it is only one pattern per chunk and chunks are
    2789             :                         // pasted consecutively then it will get its range
    2790             :                         // enlarged for each chunk and no further allocation
    2791             :                         // happens. For non-consecutive chunks we're out of
    2792             :                         // luck in this case.
    2793           0 :                         if (nChunk > 1)
    2794             :                         {
    2795           0 :                             SCSIZE nNeeded = nChunk * (nRow2 - nR3 + 1) / (nYw + 1);
    2796           0 :                             SCSIZE nRemain = GetPatternCount( nTab, nCol, nR3, nRow2);
    2797           0 :                             if (nNeeded > nRemain)
    2798             :                             {
    2799           0 :                                 SCSIZE nCurr = GetPatternCount( nTab, nCol);
    2800           0 :                                 ReservePatternCount( nTab, nCol, nCurr + nNeeded);
    2801             :                             }
    2802             :                         }
    2803             :                     }
    2804             :                 }
    2805           0 :                 bPreallocatePattern = false;
    2806             :             }
    2807             : 
    2808          56 :             nR1 = nR2 + 1;
    2809          56 :             nR2 = std::min((SCROW)(nR1 + nYw), nRow2);
    2810          56 :         } while (nR1 <= nRow2);
    2811          54 :     }
    2812             : 
    2813          56 :     bInsertingFromOtherDoc = false;
    2814             : 
    2815             :     // Listener aufbauen nachdem alles inserted wurde
    2816          56 :     StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
    2817             :     // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
    2818          56 :     BroadcastFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
    2819          56 :     if (bResetCut)
    2820         109 :         pClipDoc->GetClipParam().mbCutMode = false;
    2821             : }
    2822             : 
    2823           1 : void ScDocument::CopyMultiRangeFromClip(
    2824             :     const ScAddress& rDestPos, const ScMarkData& rMark, sal_uInt16 nInsFlag, ScDocument* pClipDoc,
    2825             :     bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
    2826             : {
    2827           1 :     if (bIsClip)
    2828           0 :         return;
    2829             : 
    2830           1 :     if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
    2831             :         // There is nothing in the clip doc to copy.
    2832           0 :         return;
    2833             : 
    2834             :     // Right now, we don't allow pasting into filtered rows, so we don't even handle it here.
    2835             : 
    2836           1 :     sc::AutoCalcSwitch aACSwitch(*this, false); // turn of auto calc temporarily.
    2837           2 :     NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
    2838             : 
    2839           1 :     ScRange aDestRange;
    2840           1 :     rMark.GetMarkArea(aDestRange);
    2841             : 
    2842           1 :     bInsertingFromOtherDoc = true;  // kein Broadcast/Listener aufbauen bei Insert
    2843             : 
    2844           1 :     SCCOL nCol1 = rDestPos.Col();
    2845           1 :     SCROW nRow1 = rDestPos.Row();
    2846           1 :     ScClipParam& rClipParam = pClipDoc->GetClipParam();
    2847             : 
    2848           1 :     if (!bSkipAttrForEmpty)
    2849             :     {
    2850             :         // Do the deletion first.
    2851           1 :         sal_uInt16 nDelFlag = IDF_CONTENTS;
    2852           1 :         SCCOL nColSize = rClipParam.getPasteColSize();
    2853           1 :         SCROW nRowSize = rClipParam.getPasteRowSize();
    2854             : 
    2855           1 :         DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag);
    2856             :     }
    2857             : 
    2858           2 :     sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
    2859           1 :     std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
    2860           1 :     aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
    2861             : 
    2862           4 :     for (size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i)
    2863             :     {
    2864           3 :         ScRange* p = rClipParam.maRanges[i];
    2865             : 
    2866           3 :         SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
    2867           3 :         SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
    2868           3 :         SCsROW nDy = static_cast<SCsROW>(nRow1 - p->aStart.Row());
    2869           3 :         SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
    2870           3 :         SCROW nEndRow = nRow1 + nRowCount - 1;
    2871             : 
    2872           3 :         CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy);
    2873             : 
    2874           3 :         switch (rClipParam.meDirection)
    2875             :         {
    2876             :             case ScClipParam::Row:
    2877             :                 // Begin row for the next range being pasted.
    2878           3 :                 nRow1 += nRowCount;
    2879           3 :             break;
    2880             :             case ScClipParam::Column:
    2881           0 :                 nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
    2882           0 :             break;
    2883             :             default:
    2884             :                 ;
    2885             :         }
    2886             :     }
    2887             : 
    2888           1 :     bInsertingFromOtherDoc = false;
    2889             : 
    2890             :     // Listener aufbauen nachdem alles inserted wurde
    2891           1 :     StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
    2892           2 :                            aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
    2893             :     // nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
    2894           1 :     BroadcastFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
    2895           2 :                       aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
    2896             : 
    2897           1 :     if (bResetCut)
    2898           2 :         pClipDoc->GetClipParam().mbCutMode = false;
    2899             : }
    2900             : 
    2901          16 : void ScDocument::SetClipArea( const ScRange& rArea, bool bCut )
    2902             : {
    2903          16 :     if (bIsClip)
    2904             :     {
    2905          16 :         ScClipParam& rClipParam = GetClipParam();
    2906          16 :         rClipParam.maRanges.RemoveAll();
    2907          16 :         rClipParam.maRanges.Append(rArea);
    2908          16 :         rClipParam.mbCutMode = bCut;
    2909             :     }
    2910             :     else
    2911             :     {
    2912             :         OSL_FAIL("SetClipArea: No Clip");
    2913             :     }
    2914          16 : }
    2915             : 
    2916             : 
    2917         112 : void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, bool bIncludeFiltered)
    2918             : {
    2919         112 :     if (!bIsClip)
    2920             :     {
    2921             :         OSL_FAIL("GetClipArea: No Clip");
    2922           0 :         return;
    2923             :     }
    2924             : 
    2925         112 :     ScRangeList& rClipRanges = GetClipParam().maRanges;
    2926         112 :     if (rClipRanges.empty())
    2927             :         // No clip range.  Bail out.
    2928           0 :         return;
    2929             : 
    2930         112 :     ScRange* p = rClipRanges.front();
    2931         112 :     SCCOL nStartCol = p->aStart.Col();
    2932         112 :     SCCOL nEndCol   = p->aEnd.Col();
    2933         112 :     SCROW nStartRow = p->aStart.Row();
    2934         112 :     SCROW nEndRow   = p->aEnd.Row();
    2935         112 :     for ( size_t i = 1, n = rClipRanges.size(); i < n; ++i )
    2936             :     {
    2937           0 :         p = rClipRanges[ i ];
    2938           0 :         if (p->aStart.Col() < nStartCol)
    2939           0 :             nStartCol = p->aStart.Col();
    2940           0 :         if (p->aStart.Row() < nStartRow)
    2941           0 :             nStartRow = p->aStart.Row();
    2942           0 :         if (p->aEnd.Col() > nEndCol)
    2943           0 :             nEndCol = p->aEnd.Col();
    2944           0 :         if (p->aEnd.Row() < nEndRow)
    2945           0 :             nEndRow = p->aEnd.Row();
    2946             :     }
    2947             : 
    2948         112 :     nClipX = nEndCol - nStartCol;
    2949             : 
    2950         112 :     if ( bIncludeFiltered )
    2951          48 :         nClipY = nEndRow - nStartRow;
    2952             :     else
    2953             :     {
    2954             :         //  count non-filtered rows
    2955             :         //  count on first used table in clipboard
    2956          64 :         SCTAB nCountTab = 0;
    2957         128 :         while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
    2958           0 :             ++nCountTab;
    2959             : 
    2960          64 :         SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab);
    2961             : 
    2962          64 :         if ( nResult > 0 )
    2963          64 :             nClipY = nResult - 1;
    2964             :         else
    2965           0 :             nClipY = 0;                 // always return at least 1 row
    2966             :     }
    2967             : }
    2968             : 
    2969             : 
    2970          27 : void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
    2971             : {
    2972          27 :     if (bIsClip)
    2973             :     {
    2974          27 :         ScRangeList& rClipRanges = GetClipParam().maRanges;
    2975          27 :         if ( !rClipRanges.empty() )
    2976             :         {
    2977          27 :             nClipX = rClipRanges.front()->aStart.Col();
    2978          27 :             nClipY = rClipRanges.front()->aStart.Row();
    2979             :         }
    2980             :     }
    2981             :     else
    2982             :     {
    2983             :         OSL_FAIL("GetClipStart: No Clip");
    2984             :     }
    2985          27 : }
    2986             : 
    2987             : 
    2988          18 : bool ScDocument::HasClipFilteredRows()
    2989             : {
    2990             :     //  count on first used table in clipboard
    2991          18 :     SCTAB nCountTab = 0;
    2992          36 :     while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
    2993           0 :         ++nCountTab;
    2994             : 
    2995          18 :     ScRangeList& rClipRanges = GetClipParam().maRanges;
    2996          18 :     if ( rClipRanges.empty() )
    2997           0 :         return false;
    2998             : 
    2999          36 :     for ( size_t i = 0, n = rClipRanges.size(); i < n; ++i )
    3000             :     {
    3001          18 :         ScRange* p = rClipRanges[ i ];
    3002          18 :         bool bAnswer = maTabs[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row());
    3003          18 :         if (bAnswer)
    3004           0 :             return true;
    3005             :     }
    3006          18 :     return false;
    3007             : }
    3008             : 
    3009             : 
    3010           1 : void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, bool bSkipEmpty,
    3011             :                                     ScDocument* pSrcDoc )
    3012             : {
    3013           1 :     SCTAB nTab1 = rRange.aStart.Tab();
    3014           1 :     SCTAB nTab2 = rRange.aEnd.Tab();
    3015           1 :     sc::MixDocContext aCxt(*this);
    3016           1 :     SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pSrcDoc->maTabs.size()));
    3017           2 :     for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
    3018             :     {
    3019           1 :         ScTable* pTab = FetchTable(i);
    3020           1 :         const ScTable* pSrcTab = pSrcDoc->FetchTable(i);
    3021           1 :         if (!pTab || !pSrcTab)
    3022           0 :             continue;
    3023             : 
    3024             :         pTab->MixData(
    3025           2 :             aCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
    3026           3 :             nFunction, bSkipEmpty, pSrcTab);
    3027           1 :     }
    3028           1 : }
    3029             : 
    3030             : 
    3031           0 : void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
    3032             :                                 sal_uInt16 nFlags, sal_uInt16 nFunction,
    3033             :                                 bool bSkipEmpty, bool bAsLink )
    3034             : {
    3035           0 :     sal_uInt16 nDelFlags = nFlags;
    3036           0 :     if (nDelFlags & IDF_CONTENTS)
    3037           0 :         nDelFlags |= IDF_CONTENTS;          // immer alle Inhalte oder keine loeschen!
    3038             : 
    3039           0 :     SCTAB nSrcTab = rSrcArea.aStart.Tab();
    3040             : 
    3041           0 :     if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
    3042             :     {
    3043           0 :         SCCOL nStartCol = rSrcArea.aStart.Col();
    3044           0 :         SCROW nStartRow = rSrcArea.aStart.Row();
    3045           0 :         SCCOL nEndCol = rSrcArea.aEnd.Col();
    3046           0 :         SCROW nEndRow = rSrcArea.aEnd.Row();
    3047           0 :         boost::scoped_ptr<ScDocument> pMixDoc;
    3048           0 :         bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
    3049             : 
    3050           0 :         bool bOldAutoCalc = GetAutoCalc();
    3051           0 :         SetAutoCalc( false );                   // avoid multiple calculations
    3052             : 
    3053           0 :         sc::CopyToDocContext aCxt(*this);
    3054           0 :         sc::MixDocContext aMixDocCxt(*this);
    3055             : 
    3056           0 :         SCTAB nCount = static_cast<SCTAB>(maTabs.size());
    3057           0 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    3058           0 :         for (; itr != itrEnd && *itr < nCount; ++itr)
    3059           0 :             if ( *itr!=nSrcTab && maTabs[*itr])
    3060             :             {
    3061           0 :                 SCTAB i = *itr;
    3062           0 :                 if (bDoMix)
    3063             :                 {
    3064           0 :                     if (!pMixDoc)
    3065             :                     {
    3066           0 :                         pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
    3067           0 :                         pMixDoc->InitUndo( this, i, i );
    3068             :                     }
    3069             :                     else
    3070           0 :                         pMixDoc->AddUndoTab( i, i );
    3071             : 
    3072             :                     // context used for copying content to the temporary mix document.
    3073           0 :                     sc::CopyToDocContext aMixCxt(*pMixDoc);
    3074           0 :                     maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
    3075           0 :                                             IDF_CONTENTS, false, pMixDoc->maTabs[i] );
    3076             :                 }
    3077           0 :                 maTabs[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
    3078           0 :                 maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
    3079           0 :                                                  nFlags, false, maTabs[i], NULL, bAsLink );
    3080             : 
    3081           0 :                 if (bDoMix)
    3082           0 :                     maTabs[i]->MixData(aMixDocCxt, nStartCol,nStartRow, nEndCol,nEndRow,
    3083           0 :                                         nFunction, bSkipEmpty, pMixDoc->maTabs[i] );
    3084             :             }
    3085             : 
    3086           0 :         SetAutoCalc( bOldAutoCalc );
    3087             :     }
    3088             :     else
    3089             :     {
    3090             :         OSL_FAIL("wrong table");
    3091             :     }
    3092           0 : }
    3093             : 
    3094             : 
    3095           0 : void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark,
    3096             :                                 sal_uInt16 nFlags, sal_uInt16 nFunction,
    3097             :                                 bool bSkipEmpty, bool bAsLink )
    3098             : {
    3099           0 :     sal_uInt16 nDelFlags = nFlags;
    3100           0 :     if (nDelFlags & IDF_CONTENTS)
    3101           0 :         nDelFlags |= IDF_CONTENTS;          // immer alle Inhalte oder keine loeschen!
    3102             : 
    3103           0 :     if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
    3104             :     {
    3105           0 :         boost::scoped_ptr<ScDocument> pMixDoc;
    3106           0 :         bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
    3107             : 
    3108           0 :         bool bOldAutoCalc = GetAutoCalc();
    3109           0 :         SetAutoCalc( false );                   // avoid multiple calculations
    3110             : 
    3111           0 :         ScRange aArea;
    3112           0 :         rMark.GetMultiMarkArea( aArea );
    3113           0 :         SCCOL nStartCol = aArea.aStart.Col();
    3114           0 :         SCROW nStartRow = aArea.aStart.Row();
    3115           0 :         SCCOL nEndCol = aArea.aEnd.Col();
    3116           0 :         SCROW nEndRow = aArea.aEnd.Row();
    3117             : 
    3118           0 :         sc::CopyToDocContext aCxt(*this);
    3119           0 :         sc::MixDocContext aMixDocCxt(*this);
    3120           0 :         SCTAB nCount = static_cast<SCTAB>(maTabs.size());
    3121           0 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    3122           0 :         for (; itr != itrEnd && *itr < nCount; ++itr)
    3123           0 :             if ( *itr!=nSrcTab && maTabs[*itr] )
    3124             :             {
    3125           0 :                 SCTAB i = *itr;
    3126           0 :                 if (bDoMix)
    3127             :                 {
    3128           0 :                     if (!pMixDoc)
    3129             :                     {
    3130           0 :                         pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
    3131           0 :                         pMixDoc->InitUndo( this, i, i );
    3132             :                     }
    3133             :                     else
    3134           0 :                         pMixDoc->AddUndoTab( i, i );
    3135             : 
    3136           0 :                     sc::CopyToDocContext aMixCxt(*pMixDoc);
    3137           0 :                     maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
    3138           0 :                                             IDF_CONTENTS, true, pMixDoc->maTabs[i], &rMark );
    3139             :                 }
    3140             : 
    3141           0 :                 maTabs[i]->DeleteSelection( nDelFlags, rMark );
    3142           0 :                 maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
    3143           0 :                                              nFlags, true, maTabs[i], &rMark, bAsLink );
    3144             : 
    3145           0 :                 if (bDoMix)
    3146           0 :                     maTabs[i]->MixMarked(aMixDocCxt, rMark, nFunction, bSkipEmpty, pMixDoc->maTabs[i]);
    3147             :             }
    3148             : 
    3149           0 :         SetAutoCalc( bOldAutoCalc );
    3150             :     }
    3151             :     else
    3152             :     {
    3153             :         OSL_FAIL("wrong table");
    3154             :     }
    3155           0 : }
    3156             : 
    3157             : 
    3158        5484 : bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString,
    3159             :                             ScSetStringParam* pParam )
    3160             : {
    3161        5484 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3162        5484 :         return maTabs[nTab]->SetString( nCol, nRow, nTab, rString, pParam );
    3163             :     else
    3164           0 :         return false;
    3165             : }
    3166             : 
    3167        2206 : bool ScDocument::SetString(
    3168             :     const ScAddress& rPos, const OUString& rString, ScSetStringParam* pParam )
    3169             : {
    3170        2206 :     return SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rString, pParam);
    3171             : }
    3172             : 
    3173         187 : void ScDocument::SetEditText( const ScAddress& rPos, EditTextObject* pEditText )
    3174             : {
    3175         187 :     if (!TableExists(rPos.Tab()))
    3176             :     {
    3177           0 :         delete pEditText;
    3178         187 :         return;
    3179             :     }
    3180             : 
    3181         187 :     maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), pEditText);
    3182             : }
    3183             : 
    3184           0 : void ScDocument::SetEditText( const ScAddress& rPos, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
    3185             : {
    3186           0 :     if (!TableExists(rPos.Tab()))
    3187           0 :         return;
    3188             : 
    3189           0 :     maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEditText, pEditPool);
    3190             : }
    3191             : 
    3192           0 : void ScDocument::SetEditText( const ScAddress& rPos, const OUString& rStr )
    3193             : {
    3194           0 :     if (!TableExists(rPos.Tab()))
    3195           0 :         return;
    3196             : 
    3197           0 :     ScFieldEditEngine& rEngine = GetEditEngine();
    3198           0 :     rEngine.SetText(rStr);
    3199           0 :     maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
    3200             : }
    3201             : 
    3202          11 : SCROW ScDocument::GetFirstEditTextRow( const ScRange& rRange ) const
    3203             : {
    3204          11 :     const ScTable* pTab = FetchTable(rRange.aStart.Tab());
    3205          11 :     if (!pTab)
    3206           0 :         return -1;
    3207             : 
    3208          11 :     return pTab->GetFirstEditTextRow(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
    3209             : }
    3210             : 
    3211         944 : void ScDocument::SetTextCell( const ScAddress& rPos, const OUString& rStr )
    3212             : {
    3213         944 :     if (!TableExists(rPos.Tab()))
    3214         944 :         return;
    3215             : 
    3216         944 :     if (ScStringUtil::isMultiline(rStr))
    3217             :     {
    3218           0 :         ScFieldEditEngine& rEngine = GetEditEngine();
    3219           0 :         rEngine.SetText(rStr);
    3220           0 :         maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
    3221             :     }
    3222             :     else
    3223             :     {
    3224         944 :         ScSetStringParam aParam;
    3225         944 :         aParam.setTextInput();
    3226         944 :         maTabs[rPos.Tab()]->SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rStr, &aParam);
    3227             :     }
    3228             : }
    3229             : 
    3230         490 : void ScDocument::SetEmptyCell( const ScAddress& rPos )
    3231             : {
    3232         490 :     if (!TableExists(rPos.Tab()))
    3233         490 :         return;
    3234             : 
    3235         490 :     maTabs[rPos.Tab()]->SetEmptyCell(rPos.Col(), rPos.Row());
    3236             : }
    3237             : 
    3238        2259 : void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal )
    3239             : {
    3240        2259 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    3241        2259 :         if (maTabs[nTab])
    3242        2259 :             maTabs[nTab]->SetValue( nCol, nRow, rVal );
    3243        2259 : }
    3244             : 
    3245       23873 : void ScDocument::SetValue( const ScAddress& rPos, double fVal )
    3246             : {
    3247       23873 :     if (!TableExists(rPos.Tab()))
    3248       23873 :         return;
    3249             : 
    3250       23873 :     maTabs[rPos.Tab()]->SetValue(rPos.Col(), rPos.Row(), fVal);
    3251             : }
    3252             : 
    3253        8876 : OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    3254             : {
    3255        8876 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    3256             :     {
    3257        8876 :         OUString aStr;
    3258        8876 :         maTabs[nTab]->GetString(nCol, nRow, aStr);
    3259        8876 :         return aStr;
    3260             :     }
    3261             :     else
    3262           0 :         return EMPTY_OUSTRING;
    3263             : }
    3264             : 
    3265        5701 : OUString ScDocument::GetString( const ScAddress& rPos ) const
    3266             : {
    3267        5701 :     if (!TableExists(rPos.Tab()))
    3268           0 :         return EMPTY_OUSTRING;
    3269             : 
    3270        5701 :     OUString aStr;
    3271        5701 :     maTabs[rPos.Tab()]->GetString(rPos.Col(), rPos.Row(), aStr);
    3272        5701 :     return aStr;
    3273             : }
    3274             : 
    3275           5 : double* ScDocument::GetValueCell( const ScAddress& rPos )
    3276             : {
    3277           5 :     if (!TableExists(rPos.Tab()))
    3278           0 :         return NULL;
    3279             : 
    3280           5 :     return maTabs[rPos.Tab()]->GetValueCell(rPos.Col(), rPos.Row());
    3281             : }
    3282             : 
    3283          24 : svl::SharedString ScDocument::GetSharedString( const ScAddress& rPos ) const
    3284             : {
    3285          24 :     if (!TableExists(rPos.Tab()))
    3286           0 :         return svl::SharedString();
    3287             : 
    3288          24 :     return maTabs[rPos.Tab()]->GetSharedString(rPos.Col(), rPos.Row());
    3289             : }
    3290             : 
    3291          20 : sc::FormulaGroupContext& ScDocument::GetFormulaGroupContext()
    3292             : {
    3293          20 :     if (!mpFormulaGroupCxt)
    3294           7 :         mpFormulaGroupCxt.reset(new sc::FormulaGroupContext);
    3295             : 
    3296          20 :     return *mpFormulaGroupCxt;
    3297             : }
    3298             : 
    3299        2614 : void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString )
    3300             : {
    3301        2614 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3302        2614 :         maTabs[nTab]->GetInputString( nCol, nRow, rString );
    3303             :     else
    3304           0 :         rString = OUString();
    3305        2614 : }
    3306             : 
    3307         299 : sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, OUString& rString )
    3308             : {
    3309             :     // Used in formulas (add-in parameters etc), so it must use the same semantics as
    3310             :     // ScInterpreter::GetCellString: always format values as numbers.
    3311             :     // The return value is the error code.
    3312             : 
    3313         299 :     ScRefCellValue aCell;
    3314         299 :     aCell.assign(*this, rPos);
    3315         299 :     if (aCell.isEmpty())
    3316             :     {
    3317           0 :         rString = EMPTY_OUSTRING;
    3318           0 :         return 0;
    3319             :     }
    3320             : 
    3321         299 :     sal_uInt16 nErr = 0;
    3322         598 :     OUString aStr;
    3323         299 :     SvNumberFormatter* pFormatter = GetFormatTable();
    3324         299 :     switch (aCell.meType)
    3325             :     {
    3326             :         case CELLTYPE_STRING:
    3327             :         case CELLTYPE_EDIT:
    3328         299 :             aStr = aCell.getString(this);
    3329         299 :         break;
    3330             :         case CELLTYPE_FORMULA:
    3331             :         {
    3332           0 :             ScFormulaCell* pFCell = aCell.mpFormula;
    3333           0 :             nErr = pFCell->GetErrCode();
    3334           0 :             if (pFCell->IsValue())
    3335             :             {
    3336           0 :                 double fVal = pFCell->GetValue();
    3337             :                 sal_uInt32 nIndex = pFormatter->GetStandardFormat(
    3338             :                                     NUMBERFORMAT_NUMBER,
    3339           0 :                                     ScGlobal::eLnge);
    3340           0 :                 pFormatter->GetInputLineString(fVal, nIndex, aStr);
    3341             :             }
    3342             :             else
    3343           0 :                 aStr = pFCell->GetString().getString();
    3344             :         }
    3345           0 :         break;
    3346             :         case CELLTYPE_VALUE:
    3347             :         {
    3348           0 :             double fVal = aCell.mfValue;
    3349             :             sal_uInt32 nIndex = pFormatter->GetStandardFormat(
    3350             :                                     NUMBERFORMAT_NUMBER,
    3351           0 :                                     ScGlobal::eLnge);
    3352           0 :             pFormatter->GetInputLineString(fVal, nIndex, aStr);
    3353             :         }
    3354           0 :         break;
    3355             :         default:
    3356             :             ;
    3357             :     }
    3358             : 
    3359         299 :     rString = aStr;
    3360         598 :     return nErr;
    3361             : }
    3362             : 
    3363             : 
    3364         436 : void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) const
    3365             : {
    3366         436 :     if (TableExists(nTab))
    3367         436 :         rValue = maTabs[nTab]->GetValue( nCol, nRow );
    3368             :     else
    3369           0 :         rValue = 0.0;
    3370         436 : }
    3371             : 
    3372          68 : const EditTextObject* ScDocument::GetEditText( const ScAddress& rPos ) const
    3373             : {
    3374          68 :     SCTAB nTab = rPos.Tab();
    3375          68 :     if (!TableExists(nTab))
    3376           0 :         return NULL;
    3377             : 
    3378          68 :     return maTabs[nTab]->GetEditText(rPos.Col(), rPos.Row());
    3379             : }
    3380             : 
    3381           0 : void ScDocument::RemoveEditTextCharAttribs( const ScAddress& rPos, const ScPatternAttr& rAttr )
    3382             : {
    3383           0 :     if (!TableExists(rPos.Tab()))
    3384           0 :         return;
    3385             : 
    3386           0 :     return maTabs[rPos.Tab()]->RemoveEditTextCharAttribs(rPos.Col(), rPos.Row(), rAttr);
    3387             : }
    3388             : 
    3389       10019 : double ScDocument::GetValue( const ScAddress& rPos ) const
    3390             : {
    3391       10019 :     SCTAB nTab = rPos.Tab();
    3392       10019 :     if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3393       10019 :         return maTabs[nTab]->GetValue(rPos.Col(), rPos.Row());
    3394           0 :     return 0.0;
    3395             : }
    3396             : 
    3397         177 : double ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    3398             : {
    3399         177 :     ScAddress aAdr(nCol, nRow, nTab); return GetValue(aAdr);
    3400             : }
    3401             : 
    3402         900 : void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
    3403             :                                   sal_uInt32& rFormat ) const
    3404             : {
    3405         900 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    3406         900 :         if (maTabs[nTab])
    3407             :         {
    3408         900 :             rFormat = maTabs[nTab]->GetNumberFormat( nCol, nRow );
    3409        1800 :             return ;
    3410             :         }
    3411           0 :     rFormat = 0;
    3412             : }
    3413             : 
    3414           5 : sal_uInt32 ScDocument::GetNumberFormat( const ScRange& rRange ) const
    3415             : {
    3416           5 :     SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
    3417           5 :     SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
    3418           5 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
    3419             : 
    3420           5 :     if (!ValidTab(nTab1) || !ValidTab(nTab2) || !maTabs[nTab1] || !maTabs[nTab2])
    3421           0 :         return 0;
    3422             : 
    3423           5 :     sal_uInt32 nFormat = 0;
    3424           5 :     bool bFirstItem = true;
    3425          10 :     for (SCTAB nTab = nTab1; nTab <= nTab2 && nTab < static_cast<SCTAB>(maTabs.size()) ; ++nTab)
    3426          10 :         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
    3427             :         {
    3428           5 :             sal_uInt32 nThisFormat = maTabs[nTab]->GetNumberFormat(nCol, nRow1, nRow2);
    3429           5 :             if (bFirstItem)
    3430             :             {
    3431           5 :                 nFormat = nThisFormat;
    3432           5 :                 bFirstItem = false;
    3433             :             }
    3434           0 :             else if (nThisFormat != nFormat)
    3435           0 :                 return 0;
    3436             :         }
    3437             : 
    3438           5 :     return nFormat;
    3439             : }
    3440             : 
    3441       11219 : sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
    3442             : {
    3443       11219 :     SCTAB nTab = rPos.Tab();
    3444       11219 :     if ( maTabs[nTab] )
    3445       11219 :         return maTabs[nTab]->GetNumberFormat( rPos );
    3446           0 :     return 0;
    3447             : }
    3448             : 
    3449         836 : void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat )
    3450             : {
    3451         836 :     if (!TableExists(rPos.Tab()))
    3452         836 :         return;
    3453             : 
    3454         836 :     maTabs[rPos.Tab()]->SetNumberFormat(rPos.Col(), rPos.Row(), nNumberFormat);
    3455             : }
    3456             : 
    3457        3122 : void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
    3458             :             const ScAddress& rPos ) const
    3459             : {
    3460        3122 :     SCTAB nTab = rPos.Tab();
    3461        3122 :     if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3462             :     {
    3463        3122 :         nIndex = maTabs[nTab]->GetNumberFormat( rPos );
    3464        3122 :         nType = GetFormatTable()->GetType( nIndex );
    3465             :     }
    3466             :     else
    3467             :     {
    3468           0 :         nType = NUMBERFORMAT_UNDEFINED;
    3469           0 :         nIndex = 0;
    3470             :     }
    3471        3122 : }
    3472             : 
    3473             : 
    3474          43 : void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rFormula ) const
    3475             : {
    3476          43 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3477          43 :             maTabs[nTab]->GetFormula( nCol, nRow, rFormula );
    3478             :     else
    3479           0 :         rFormula = OUString();
    3480          43 : }
    3481             : 
    3482             : 
    3483           0 : const ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos ) const
    3484             : {
    3485           0 :     if (!TableExists(rPos.Tab()))
    3486           0 :         return NULL;
    3487             : 
    3488           0 :     return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
    3489             : }
    3490             : 
    3491        1558 : ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos )
    3492             : {
    3493        1558 :     if (!TableExists(rPos.Tab()))
    3494           0 :         return NULL;
    3495             : 
    3496        1558 :     return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
    3497             : }
    3498             : 
    3499       19190 : CellType ScDocument::GetCellType( const ScAddress& rPos ) const
    3500             : {
    3501       19190 :     SCTAB nTab = rPos.Tab();
    3502       19190 :     if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3503       19190 :         return maTabs[nTab]->GetCellType( rPos );
    3504           0 :     return CELLTYPE_NONE;
    3505             : }
    3506             : 
    3507             : 
    3508          20 : void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab,
    3509             :         CellType& rCellType ) const
    3510             : {
    3511          20 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    3512          20 :         rCellType = maTabs[nTab]->GetCellType( nCol, nRow );
    3513             :     else
    3514           0 :         rCellType = CELLTYPE_NONE;
    3515          20 : }
    3516             : 
    3517           4 : bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    3518             : {
    3519           4 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3520           4 :             return maTabs[nTab]->HasStringData( nCol, nRow );
    3521             :     else
    3522           0 :         return false;
    3523             : }
    3524             : 
    3525             : 
    3526        2756 : bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    3527             : {
    3528        2756 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3529        2756 :             return maTabs[nTab]->HasValueData( nCol, nRow );
    3530             :     else
    3531           0 :         return false;
    3532             : }
    3533             : 
    3534           0 : bool ScDocument::HasValueData( const ScAddress& rPos ) const
    3535             : {
    3536           0 :     return HasValueData(rPos.Col(), rPos.Row(), rPos.Tab());
    3537             : }
    3538             : 
    3539           0 : bool ScDocument::HasStringCells( const ScRange& rRange ) const
    3540             : {
    3541             :     //  true, wenn String- oder Editzellen im Bereich
    3542             : 
    3543           0 :     SCCOL nStartCol = rRange.aStart.Col();
    3544           0 :     SCROW nStartRow = rRange.aStart.Row();
    3545           0 :     SCTAB nStartTab = rRange.aStart.Tab();
    3546           0 :     SCCOL nEndCol = rRange.aEnd.Col();
    3547           0 :     SCROW nEndRow = rRange.aEnd.Row();
    3548           0 :     SCTAB nEndTab = rRange.aEnd.Tab();
    3549             : 
    3550           0 :     for ( SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
    3551           0 :         if ( maTabs[nTab] && maTabs[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
    3552           0 :             return true;
    3553             : 
    3554           0 :     return false;
    3555             : }
    3556             : 
    3557             : 
    3558           0 : bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    3559             : {
    3560           0 :     sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
    3561           0 :     if( nValidation )
    3562             :     {
    3563           0 :         const ScValidationData* pData = GetValidationEntry( nValidation );
    3564           0 :         if( pData && pData->HasSelectionList() )
    3565           0 :             return true;
    3566             :     }
    3567           0 :     return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) );
    3568             : }
    3569             : 
    3570             : 
    3571         409 : void ScDocument::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
    3572             : {
    3573         409 :     bool bOldAutoCalc = GetAutoCalc();
    3574         409 :     bAutoCalc = false;      // keine Mehrfachberechnung
    3575             :     {   // scope for bulk broadcast
    3576         409 :         ScBulkBroadcast aBulkBroadcast( GetBASM());
    3577         409 :         TableContainer::iterator it = maTabs.begin();
    3578        1093 :         for (;it != maTabs.end(); ++it)
    3579         684 :             if (*it)
    3580        1093 :                 (*it)->SetAllFormulasDirty(rCxt);
    3581             :     }
    3582             : 
    3583             :     //  Charts werden zwar auch ohne AutoCalc im Tracking auf Dirty gesetzt,
    3584             :     //  wenn alle Formeln dirty sind, werden die Charts aber nicht mehr erwischt
    3585             :     //  (#45205#) - darum alle Charts nochmal explizit
    3586         409 :     if (pChartListenerCollection)
    3587         409 :         pChartListenerCollection->SetDirty();
    3588             : 
    3589         409 :     SetAutoCalc( bOldAutoCalc );
    3590         409 : }
    3591             : 
    3592             : 
    3593         144 : void ScDocument::SetDirty( const ScRange& rRange )
    3594             : {
    3595         144 :     bool bOldAutoCalc = GetAutoCalc();
    3596         144 :     bAutoCalc = false;      // keine Mehrfachberechnung
    3597             :     {   // scope for bulk broadcast
    3598         144 :         ScBulkBroadcast aBulkBroadcast( GetBASM());
    3599         144 :         SCTAB nTab2 = rRange.aEnd.Tab();
    3600         288 :         for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
    3601         288 :             if (maTabs[i]) maTabs[i]->SetDirty( rRange );
    3602             :     }
    3603         144 :     SetAutoCalc( bOldAutoCalc );
    3604         144 : }
    3605             : 
    3606             : 
    3607          44 : void ScDocument::SetTableOpDirty( const ScRange& rRange )
    3608             : {
    3609          44 :     bool bOldAutoCalc = GetAutoCalc();
    3610          44 :     bAutoCalc = false;      // no multiple recalculation
    3611          44 :     SCTAB nTab2 = rRange.aEnd.Tab();
    3612          88 :     for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
    3613          44 :         if (maTabs[i]) maTabs[i]->SetTableOpDirty( rRange );
    3614          44 :     SetAutoCalc( bOldAutoCalc );
    3615          44 : }
    3616             : 
    3617        1664 : void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
    3618             : {
    3619        1664 :     if (!GetAutoCalc())
    3620           0 :         return;
    3621             : 
    3622        1664 :     mpFormulaGroupCxt.reset();
    3623             : 
    3624        3381 :     for (size_t nPos=0, nRangeCount = rRanges.size(); nPos < nRangeCount; nPos++)
    3625             :     {
    3626        1717 :         const ScRange& rRange = *rRanges[nPos];
    3627        3434 :         for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
    3628             :         {
    3629        1717 :             ScTable* pTab = FetchTable(nTab);
    3630        1717 :             if (!pTab)
    3631           0 :                 return;
    3632             : 
    3633             :             pTab->InterpretDirtyCells(
    3634        1717 :                 rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
    3635             :         }
    3636             :     }
    3637             : 
    3638        1664 :     mpFormulaGroupCxt.reset();
    3639             : }
    3640             : 
    3641             : 
    3642       21264 : void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
    3643             : {
    3644       21264 :     if ( !aTableOpList.empty() )
    3645             :     {
    3646       21087 :         ScInterpreterTableOpParams* p = &aTableOpList.back();
    3647       21087 :         if ( p->bCollectNotifications )
    3648             :         {
    3649       21087 :             if ( p->bRefresh )
    3650             :             {   // refresh pointers only
    3651       20903 :                 p->aNotifiedFormulaCells.push_back( pCell );
    3652             :             }
    3653             :             else
    3654             :             {   // init both, address and pointer
    3655         184 :                 p->aNotifiedFormulaCells.push_back( pCell );
    3656         184 :                 p->aNotifiedFormulaPos.push_back( pCell->aPos );
    3657             :             }
    3658             :         }
    3659             :     }
    3660       21264 : }
    3661             : 
    3662             : 
    3663         189 : void ScDocument::CalcAll()
    3664             : {
    3665         189 :     ClearFormulaContext();
    3666         189 :     ClearLookupCaches();    // Ensure we don't deliver zombie data.
    3667         189 :     sc::AutoCalcSwitch aSwitch(*this, true);
    3668         189 :     TableContainer::iterator it = maTabs.begin();
    3669         523 :     for (; it != maTabs.end(); ++it)
    3670         334 :         if (*it)
    3671         334 :             (*it)->SetDirtyVar();
    3672         523 :     for (it = maTabs.begin(); it != maTabs.end(); ++it)
    3673         334 :         if (*it)
    3674         334 :             (*it)->CalcAll();
    3675         189 :     ClearFormulaTree();
    3676         189 : }
    3677             : 
    3678             : 
    3679          11 : void ScDocument::CompileAll()
    3680             : {
    3681          11 :     sc::CompileFormulaContext aCxt(this);
    3682          11 :     TableContainer::iterator it = maTabs.begin();
    3683          24 :     for (; it != maTabs.end(); ++it)
    3684          13 :         if (*it)
    3685          13 :             (*it)->CompileAll(aCxt);
    3686             : 
    3687          11 :     sc::SetFormulaDirtyContext aFormulaDirtyCxt;
    3688          11 :     SetAllFormulasDirty(aFormulaDirtyCxt);
    3689          11 : }
    3690             : 
    3691             : 
    3692         107 : void ScDocument::CompileXML()
    3693             : {
    3694         107 :     bool bOldAutoCalc = GetAutoCalc();
    3695         107 :     SetAutoCalc( false );
    3696             :     ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(
    3697         107 :                 STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() );
    3698             : 
    3699         214 :     sc::CompileFormulaContext aCxt(this);
    3700             : 
    3701             :     // set AutoNameCache to speed up automatic name lookup
    3702             :     OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" );
    3703         107 :     pAutoNameCache = new ScAutoNameCache( this );
    3704             : 
    3705         107 :     if (pRangeName)
    3706          11 :         pRangeName->CompileUnresolvedXML(aCxt);
    3707             : 
    3708         107 :     TableContainer::iterator it = maTabs.begin();
    3709         328 :     for (; it != maTabs.end(); ++it)
    3710         221 :         if (*it)
    3711         221 :             (*it)->CompileXML(aCxt, aProgress);
    3712             : 
    3713         107 :     DELETEZ( pAutoNameCache );  // valid only during CompileXML, where cell contents don't change
    3714             : 
    3715         107 :     if ( pValidationList )
    3716           1 :         pValidationList->CompileXML();
    3717             : 
    3718         214 :     SetAutoCalc( bOldAutoCalc );
    3719         107 : }
    3720             : 
    3721           0 : bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode)
    3722             : {
    3723           0 :     bool bCompiled = false;
    3724           0 :     sc::CompileFormulaContext aCxt(this);
    3725           0 :     TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
    3726           0 :     for (; it != itEnd; ++it)
    3727             :     {
    3728           0 :         ScTable* pTab = *it;
    3729           0 :         if (!pTab)
    3730           0 :             continue;
    3731             : 
    3732           0 :         if (pTab->CompileErrorCells(aCxt, nErrCode))
    3733           0 :             bCompiled = true;
    3734             :     }
    3735             : 
    3736           0 :     return bCompiled;
    3737             : }
    3738             : 
    3739          66 : void ScDocument::CalcAfterLoad()
    3740             : {
    3741          66 :     if (bIsClip)    // Excel-Dateien werden aus dem Clipboard in ein Clip-Doc geladen
    3742          66 :         return;     // dann wird erst beim Einfuegen in das richtige Doc berechnet
    3743             : 
    3744          66 :     bCalcingAfterLoad = true;
    3745          66 :     sc::CompileFormulaContext aCxt(this);
    3746             :     {
    3747          66 :         TableContainer::iterator it = maTabs.begin();
    3748         259 :         for (; it != maTabs.end(); ++it)
    3749         193 :             if (*it)
    3750         193 :                 (*it)->CalcAfterLoad(aCxt);
    3751         259 :         for (it = maTabs.begin(); it != maTabs.end(); ++it)
    3752         193 :             if (*it)
    3753         193 :                 (*it)->SetDirtyAfterLoad();
    3754             :     }
    3755          66 :     bCalcingAfterLoad = false;
    3756             : 
    3757          66 :     SetDetectiveDirty(false);   // noch keine wirklichen Aenderungen
    3758             : 
    3759             :     // #i112436# If formula cells are already dirty, they don't broadcast further changes.
    3760             :     // So the source ranges of charts must be interpreted even if they are not visible,
    3761             :     // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
    3762          66 :     if (pChartListenerCollection)
    3763             :     {
    3764          66 :         const ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners();
    3765          66 :         ScChartListenerCollection::ListenersType::const_iterator it = rListeners.begin(), itEnd = rListeners.end();
    3766         110 :         for (; it != itEnd; ++it)
    3767             :         {
    3768          44 :             const ScChartListener* p = it->second;
    3769          44 :             InterpretDirtyCells(*p->GetRangeList());
    3770             :         }
    3771          66 :     }
    3772             : }
    3773             : 
    3774             : 
    3775        2286 : sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
    3776             : {
    3777        2286 :     SCTAB nTab = rPos.Tab();
    3778        2286 :     if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3779        2286 :         return maTabs[nTab]->GetErrCode( rPos );
    3780           0 :     return 0;
    3781             : }
    3782             : 
    3783             : 
    3784        1579 : void ScDocument::ResetChanged( const ScRange& rRange )
    3785             : {
    3786        1579 :     SCTAB nTabSize = static_cast<SCTAB>(maTabs.size());
    3787        1579 :     SCTAB nTab1 = rRange.aStart.Tab();
    3788        1579 :     SCTAB nTab2 = rRange.aEnd.Tab();
    3789        3856 :     for (SCTAB nTab = nTab1; nTab1 <= nTab2 && nTab < nTabSize; ++nTab)
    3790        2277 :         if (maTabs[nTab])
    3791        2277 :             maTabs[nTab]->ResetChanged(rRange);
    3792        1579 : }
    3793             : 
    3794             : 
    3795             : //  Spaltenbreiten / Zeilenhoehen   --------------------------------------
    3796             : 
    3797       13396 : void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
    3798             : {
    3799       13396 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3800       13396 :         maTabs[nTab]->SetColWidth( nCol, nNewWidth );
    3801       13396 : }
    3802             : 
    3803      277504 : void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
    3804             : {
    3805      277504 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3806      277504 :         maTabs[nTab]->SetColWidthOnly( nCol, nNewWidth );
    3807      277504 : }
    3808             : 
    3809           1 : void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight )
    3810             : {
    3811           1 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3812           1 :         maTabs[nTab]->SetRowHeight( nRow, nNewHeight );
    3813           1 : }
    3814             : 
    3815             : 
    3816           5 : void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
    3817             : {
    3818           5 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3819           5 :         maTabs[nTab]->SetRowHeightRange
    3820          10 :             ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
    3821           5 : }
    3822             : 
    3823        4212 : void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
    3824             : {
    3825        4212 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3826        4212 :         maTabs[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight );
    3827        4212 : }
    3828             : 
    3829         141 : void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bManual )
    3830             : {
    3831         141 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3832         141 :         maTabs[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
    3833         141 : }
    3834             : 
    3835             : 
    3836      584077 : sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
    3837             : {
    3838      584077 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3839      584077 :         return maTabs[nTab]->GetColWidth( nCol, bHiddenAsZero );
    3840             :     OSL_FAIL("wrong table number");
    3841           0 :     return 0;
    3842             : }
    3843             : 
    3844             : 
    3845         575 : sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const
    3846             : {
    3847         575 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3848         575 :         return maTabs[nTab]->GetOriginalWidth( nCol );
    3849             :     OSL_FAIL("wrong table number");
    3850           0 :     return 0;
    3851             : }
    3852             : 
    3853             : 
    3854           0 : sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const
    3855             : {
    3856           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3857           0 :         return maTabs[nTab]->GetCommonWidth( nEndCol );
    3858             :     OSL_FAIL("Wrong table number");
    3859           0 :     return 0;
    3860             : }
    3861             : 
    3862             : 
    3863       53079 : sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const
    3864             : {
    3865       53079 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3866       53079 :         return maTabs[nTab]->GetOriginalHeight( nRow );
    3867             :     OSL_FAIL("Wrong table number");
    3868           0 :     return 0;
    3869             : }
    3870             : 
    3871             : 
    3872    58174847 : sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
    3873             : {
    3874    58174847 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3875    58174847 :         return maTabs[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero );
    3876             :     OSL_FAIL("Wrong sheet number");
    3877           0 :     return 0;
    3878             : }
    3879             : 
    3880             : 
    3881       61428 : sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
    3882             : {
    3883       61428 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3884       61428 :         return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero );
    3885             :     OSL_FAIL("Wrong sheet number");
    3886           0 :     return 0;
    3887             : }
    3888             : 
    3889             : 
    3890        5674 : sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
    3891             : {
    3892        5674 :     if (nStartRow == nEndRow)
    3893        2143 :         return GetRowHeight( nStartRow, nTab, bHiddenAsZero );  // faster for a single row
    3894             : 
    3895             :     // check bounds because this method replaces former for(i=start;i<=end;++i) loops
    3896        3531 :     if (nStartRow > nEndRow)
    3897        1513 :         return 0;
    3898             : 
    3899        2018 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3900        2018 :         return maTabs[nTab]->GetRowHeight( nStartRow, nEndRow, bHiddenAsZero );
    3901             : 
    3902             :     OSL_FAIL("wrong sheet number");
    3903           0 :     return 0;
    3904             : }
    3905             : 
    3906        1588 : SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const
    3907             : {
    3908        1588 :     return maTabs[nTab]->GetRowForHeight(nHeight);
    3909             : }
    3910             : 
    3911       33697 : sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
    3912             :         SCTAB nTab, double fScale ) const
    3913             : {
    3914             :     // faster for a single row
    3915       33697 :     if (nStartRow == nEndRow)
    3916         115 :         return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale);
    3917             : 
    3918             :     // check bounds because this method replaces former for(i=start;i<=end;++i) loops
    3919       33582 :     if (nStartRow > nEndRow)
    3920       33580 :         return 0;
    3921             : 
    3922           2 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3923           2 :         return maTabs[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale);
    3924             : 
    3925             :     OSL_FAIL("wrong sheet number");
    3926           0 :     return 0;
    3927             : }
    3928             : 
    3929          64 : SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const
    3930             : {
    3931          64 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3932          64 :         return maTabs[nTab]->GetHiddenRowCount( nRow );
    3933             :     OSL_FAIL("wrong table number");
    3934           0 :     return 0;
    3935             : }
    3936             : 
    3937             : 
    3938        1239 : sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
    3939             : {
    3940        1239 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3941        1239 :         return maTabs[nTab]->GetColOffset( nCol, bHiddenAsZero );
    3942             :     OSL_FAIL("wrong table number");
    3943           0 :     return 0;
    3944             : }
    3945             : 
    3946             : 
    3947        1239 : sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
    3948             : {
    3949        1239 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3950        1239 :         return maTabs[nTab]->GetRowOffset( nRow, bHiddenAsZero );
    3951             :     OSL_FAIL("wrong table number");
    3952           0 :     return 0;
    3953             : }
    3954             : 
    3955             : 
    3956          89 : sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev,
    3957             :                                        double nPPTX, double nPPTY,
    3958             :                                        const Fraction& rZoomX, const Fraction& rZoomY,
    3959             :                                        bool bFormula, const ScMarkData* pMarkData,
    3960             :                                        const ScColWidthParam* pParam )
    3961             : {
    3962          89 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3963          89 :         return maTabs[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
    3964         178 :             rZoomX, rZoomY, bFormula, pMarkData, pParam );
    3965             :     OSL_FAIL("wrong table number");
    3966           0 :     return 0;
    3967             : }
    3968             : 
    3969             : 
    3970           0 : long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab,
    3971             :                                     OutputDevice* pDev,
    3972             :                                     double nPPTX, double nPPTY,
    3973             :                                     const Fraction& rZoomX, const Fraction& rZoomY,
    3974             :                                     bool bWidth, bool bTotalSize )
    3975             : {
    3976           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    3977           0 :         return maTabs[nTab]->GetNeededSize
    3978           0 :                 ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
    3979             :     OSL_FAIL("wrong table number");
    3980           0 :     return 0;
    3981             : }
    3982             : 
    3983             : 
    3984        1525 : bool ScDocument::SetOptimalHeight( sc::RowHeightContext& rCxt, SCROW nStartRow, SCROW nEndRow, SCTAB nTab )
    3985             : {
    3986        1525 :     ScTable* pTab = FetchTable(nTab);
    3987        1525 :     if (!pTab)
    3988           4 :         return false;
    3989             : 
    3990        1521 :     return pTab->SetOptimalHeight(rCxt, nStartRow, nEndRow);
    3991             : }
    3992             : 
    3993             : 
    3994           0 : void ScDocument::UpdateAllRowHeights( sc::RowHeightContext& rCxt, const ScMarkData* pTabMark )
    3995             : {
    3996             :     // one progress across all (selected) sheets
    3997             : 
    3998           0 :     sal_uLong nCellCount = 0;
    3999           0 :     for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
    4000           0 :         if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
    4001           0 :             nCellCount += maTabs[nTab]->GetWeightedCount();
    4002             : 
    4003           0 :     ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount );
    4004             : 
    4005           0 :     sal_uLong nProgressStart = 0;
    4006           0 :     for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
    4007           0 :         if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
    4008             :         {
    4009           0 :             maTabs[nTab]->SetOptimalHeightOnly(rCxt, 0, MAXROW, &aProgress, nProgressStart);
    4010           0 :             maTabs[nTab]->SetDrawPageSize(true, true);
    4011           0 :             nProgressStart += maTabs[nTab]->GetWeightedCount();
    4012           0 :         }
    4013           0 : }
    4014             : 
    4015             : //  Spalten-/Zeilen-Flags   ----------------------------------------------
    4016             : 
    4017             : 
    4018       12746 : void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, bool bShow)
    4019             : {
    4020       12746 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4021       12746 :         maTabs[nTab]->ShowCol( nCol, bShow );
    4022       12746 : }
    4023             : 
    4024             : 
    4025           0 : void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, bool bShow)
    4026             : {
    4027           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4028           0 :         maTabs[nTab]->ShowRow( nRow, bShow );
    4029           0 : }
    4030             : 
    4031             : 
    4032          51 : void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow)
    4033             : {
    4034          51 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4035          51 :         maTabs[nTab]->ShowRows( nRow1, nRow2, bShow );
    4036          51 : }
    4037             : 
    4038             : 
    4039           0 : void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags )
    4040             : {
    4041           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4042           0 :         maTabs[nTab]->SetRowFlags( nRow, nNewFlags );
    4043           0 : }
    4044             : 
    4045             : 
    4046          11 : void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags )
    4047             : {
    4048          11 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4049          11 :         maTabs[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags );
    4050          11 : }
    4051             : 
    4052             : 
    4053           0 : sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const
    4054             : {
    4055           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4056           0 :         return maTabs[nTab]->GetColFlags( nCol );
    4057             :     OSL_FAIL("wrong table number");
    4058           0 :     return 0;
    4059             : }
    4060             : 
    4061        1960 : sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const
    4062             : {
    4063        1960 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4064        1960 :         return maTabs[nTab]->GetRowFlags( nRow );
    4065             :     OSL_FAIL("wrong table number");
    4066           0 :     return 0;
    4067             : }
    4068             : 
    4069           0 : const ScBitMaskCompressedArray< SCROW, sal_uInt8> & ScDocument::GetRowFlagsArray(
    4070             :         SCTAB nTab ) const
    4071             : {
    4072             :     const ScBitMaskCompressedArray< SCROW, sal_uInt8> * pFlags;
    4073           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4074           0 :         pFlags = maTabs[nTab]->GetRowFlagsArray();
    4075             :     else
    4076             :     {
    4077             :         OSL_FAIL("wrong sheet number");
    4078           0 :         pFlags = 0;
    4079             :     }
    4080           0 :     if (!pFlags)
    4081             :     {
    4082             :         OSL_FAIL("no row flags at sheet");
    4083           0 :         static ScBitMaskCompressedArray< SCROW, sal_uInt8> aDummy( MAXROW, 0);
    4084           0 :         pFlags = &aDummy;
    4085             :     }
    4086           0 :     return *pFlags;
    4087             : }
    4088             : 
    4089          44 : void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
    4090             : {
    4091          44 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4092          44 :         return;
    4093          44 :     maTabs[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual);
    4094             : }
    4095             : 
    4096          44 : void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
    4097             : {
    4098          44 :     if (!ValidTab(nTab) || !maTabs[nTab])
    4099          44 :         return;
    4100             : 
    4101          44 :     maTabs[nTab]->GetAllColBreaks(rBreaks, bPage, bManual);
    4102             : }
    4103             : 
    4104       17279 : ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const
    4105             : {
    4106       17279 :     ScBreakType nType = BREAK_NONE;
    4107       17279 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
    4108           0 :         return nType;
    4109             : 
    4110       17279 :     if (maTabs[nTab]->HasRowPageBreak(nRow))
    4111           4 :         nType |= BREAK_PAGE;
    4112             : 
    4113       17279 :     if (maTabs[nTab]->HasRowManualBreak(nRow))
    4114           3 :         nType |= BREAK_MANUAL;
    4115             : 
    4116       17279 :     return nType;
    4117             : }
    4118             : 
    4119       39183 : ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const
    4120             : {
    4121       39183 :     ScBreakType nType = BREAK_NONE;
    4122       39183 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
    4123           0 :         return nType;
    4124             : 
    4125       39183 :     if (maTabs[nTab]->HasColPageBreak(nCol))
    4126          44 :         nType |= BREAK_PAGE;
    4127             : 
    4128       39183 :     if (maTabs[nTab]->HasColManualBreak(nCol))
    4129          11 :         nType |= BREAK_MANUAL;
    4130             : 
    4131       39183 :     return nType;
    4132             : }
    4133             : 
    4134           1 : void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
    4135             : {
    4136           1 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
    4137           1 :         return;
    4138             : 
    4139           1 :     maTabs[nTab]->SetRowBreak(nRow, bPage, bManual);
    4140             : }
    4141             : 
    4142           1 : void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
    4143             : {
    4144           1 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
    4145           1 :         return;
    4146             : 
    4147           1 :     maTabs[nTab]->SetColBreak(nCol, bPage, bManual);
    4148             : }
    4149             : 
    4150           1 : void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
    4151             : {
    4152           1 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
    4153           1 :         return;
    4154             : 
    4155           1 :     maTabs[nTab]->RemoveRowBreak(nRow, bPage, bManual);
    4156             : }
    4157             : 
    4158           1 : void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
    4159             : {
    4160           1 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
    4161           1 :         return;
    4162             : 
    4163           1 :     maTabs[nTab]->RemoveColBreak(nCol, bPage, bManual);
    4164             : }
    4165             : 
    4166           6 : Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
    4167             : {
    4168           6 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4169           0 :         return Sequence<TablePageBreakData>();
    4170             : 
    4171           6 :     return maTabs[nTab]->GetRowBreakData();
    4172             : }
    4173             : 
    4174     8117099 : bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
    4175             : {
    4176     8117099 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4177           0 :         return false;
    4178             : 
    4179     8117099 :     return maTabs[nTab]->RowHidden(nRow, pFirstRow, pLastRow);
    4180             : }
    4181             : 
    4182           0 : bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4183             : {
    4184           0 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4185           0 :         return false;
    4186             : 
    4187           0 :     return maTabs[nTab]->HasHiddenRows(nStartRow, nEndRow);
    4188             : }
    4189             : 
    4190      195029 : bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
    4191             : {
    4192      195029 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4193             :     {
    4194           0 :         if (pFirstCol)
    4195           0 :             *pFirstCol = nCol;
    4196           0 :         if (pLastCol)
    4197           0 :             *pLastCol = nCol;
    4198           0 :         return false;
    4199             :     }
    4200             : 
    4201      195029 :     return maTabs[nTab]->ColHidden(nCol, pFirstCol, pLastCol);
    4202             : }
    4203             : 
    4204          36 : void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden)
    4205             : {
    4206          36 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4207          36 :         return;
    4208             : 
    4209          36 :     maTabs[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden);
    4210             : }
    4211             : 
    4212           1 : void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
    4213             : {
    4214           1 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4215           1 :         return;
    4216             : 
    4217           1 :     maTabs[nTab]->SetColHidden(nStartCol, nEndCol, bHidden);
    4218             : }
    4219             : 
    4220         162 : SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4221             : {
    4222         162 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4223           0 :         return ::std::numeric_limits<SCROW>::max();;
    4224             : 
    4225         162 :     return maTabs[nTab]->FirstVisibleRow(nStartRow, nEndRow);
    4226             : }
    4227             : 
    4228           0 : SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4229             : {
    4230           0 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4231           0 :         return ::std::numeric_limits<SCROW>::max();;
    4232             : 
    4233           0 :     return maTabs[nTab]->LastVisibleRow(nStartRow, nEndRow);
    4234             : }
    4235             : 
    4236          38 : SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4237             : {
    4238          38 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4239           0 :         return 0;
    4240             : 
    4241          38 :     return maTabs[nTab]->CountVisibleRows(nStartRow, nEndRow);
    4242             : }
    4243             : 
    4244     4194639 : bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
    4245             : {
    4246     4194639 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4247           0 :         return false;
    4248             : 
    4249     4194639 :     return maTabs[nTab]->RowFiltered(nRow, pFirstRow, pLastRow);
    4250             : }
    4251             : 
    4252         908 : bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4253             : {
    4254         908 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4255           0 :         return false;
    4256             : 
    4257         908 :     return maTabs[nTab]->HasFilteredRows(nStartRow, nEndRow);
    4258             : }
    4259             : 
    4260          21 : bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
    4261             : {
    4262          21 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4263           0 :         return false;
    4264             : 
    4265          21 :     return maTabs[nTab]->ColFiltered(nCol, pFirstCol, pLastCol);
    4266             : }
    4267             : 
    4268          39 : void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered)
    4269             : {
    4270          39 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4271          39 :         return;
    4272             : 
    4273          39 :     maTabs[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered);
    4274             : }
    4275             : 
    4276             : 
    4277          34 : SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4278             : {
    4279          34 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4280           0 :         return ::std::numeric_limits<SCROW>::max();;
    4281             : 
    4282          34 :     return maTabs[nTab]->FirstNonFilteredRow(nStartRow, nEndRow);
    4283             : }
    4284             : 
    4285           0 : SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4286             : {
    4287           0 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4288           0 :         return ::std::numeric_limits<SCROW>::max();;
    4289             : 
    4290           0 :     return maTabs[nTab]->LastNonFilteredRow(nStartRow, nEndRow);
    4291             : }
    4292             : 
    4293          65 : SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
    4294             : {
    4295          65 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4296           0 :         return 0;
    4297             : 
    4298          65 :     return maTabs[nTab]->CountNonFilteredRows(nStartRow, nEndRow);
    4299             : }
    4300             : 
    4301           7 : bool ScDocument::IsManualRowHeight(SCROW nRow, SCTAB nTab) const
    4302             : {
    4303           7 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4304           0 :         return false;
    4305             : 
    4306           7 :     return maTabs[nTab]->IsManualRowHeight(nRow);
    4307             : }
    4308             : 
    4309          22 : void ScDocument::SyncColRowFlags()
    4310             : {
    4311          22 :     TableContainer::iterator it = maTabs.begin();
    4312          54 :     for (; it != maTabs.end(); ++it)
    4313             :     {
    4314          32 :         if (*it)
    4315          32 :             (*it)->SyncColRowFlags();
    4316             :     }
    4317          22 : }
    4318             : 
    4319          44 : SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const
    4320             : {
    4321          44 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4322          44 :         return maTabs[nTab]->GetLastFlaggedRow();
    4323           0 :     return 0;
    4324             : }
    4325             : 
    4326             : 
    4327          22 : SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const
    4328             : {
    4329          22 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4330          22 :         return maTabs[nTab]->GetLastChangedCol();
    4331           0 :     return 0;
    4332             : }
    4333             : 
    4334          22 : SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const
    4335             : {
    4336          22 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4337          22 :         return maTabs[nTab]->GetLastChangedRow();
    4338           0 :     return 0;
    4339             : }
    4340             : 
    4341             : 
    4342          29 : SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const
    4343             : {
    4344          29 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4345             :     {
    4346          29 :         sal_uInt8 nStartFlags = maTabs[nTab]->GetColFlags(nStart);
    4347          29 :         sal_uInt16 nStartWidth = maTabs[nTab]->GetOriginalWidth(nStart);
    4348       22528 :         for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++)
    4349             :         {
    4350       67518 :             if (((nStartFlags & CR_MANUALBREAK) != (maTabs[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) ||
    4351       45005 :                 (nStartWidth != maTabs[nTab]->GetOriginalWidth(nCol)) ||
    4352       22499 :                 ((nStartFlags & CR_HIDDEN) != (maTabs[nTab]->GetColFlags(nCol) & CR_HIDDEN)) )
    4353           7 :                 return nCol;
    4354             :         }
    4355          22 :         return MAXCOL+1;
    4356             :     }
    4357           0 :     return 0;
    4358             : }
    4359             : 
    4360          49 : SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const
    4361             : {
    4362          49 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4363           0 :         return 0;
    4364             : 
    4365          49 :     const ScBitMaskCompressedArray<SCROW, sal_uInt8>* pRowFlagsArray = maTabs[nTab]->GetRowFlagsArray();
    4366          49 :     if (!pRowFlagsArray)
    4367           0 :         return 0;
    4368             : 
    4369          49 :     if (!maTabs[nTab]->mpRowHeights || !maTabs[nTab]->mpHiddenRows)
    4370           0 :         return 0;
    4371             : 
    4372             :     size_t nIndex;          // ignored
    4373             :     SCROW nFlagsEndRow;
    4374             :     SCROW nHiddenEndRow;
    4375             :     SCROW nHeightEndRow;
    4376             :     sal_uInt8 nFlags;
    4377             :     bool bHidden;
    4378             :     sal_uInt16 nHeight;
    4379          49 :     sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow);
    4380          49 :     bool bStartHidden = bHidden = maTabs[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow);
    4381          49 :     sal_uInt16 nStartHeight = nHeight = maTabs[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false);
    4382             :     SCROW nRow;
    4383          98 :     while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW)
    4384             :     {
    4385          27 :         if (nFlagsEndRow < nRow)
    4386           0 :             nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow);
    4387          27 :         if (nHiddenEndRow < nRow)
    4388           0 :             bHidden = maTabs[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow);
    4389          27 :         if (nHeightEndRow < nRow)
    4390          27 :             nHeight = maTabs[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false);
    4391             : 
    4392          54 :         if (((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) ||
    4393          54 :             ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) ||
    4394          27 :             (bStartHidden != bHidden) ||
    4395          27 :             (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) ||
    4396          54 :             (!bCareManualSize && ((nStartHeight != nHeight))))
    4397          27 :             return nRow;
    4398             :     }
    4399             : 
    4400          22 :     return MAXROW+1;
    4401             : }
    4402             : 
    4403        2129 : bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault)
    4404             : {
    4405        2129 :     bool bRet(false);
    4406        2129 :     nDefault = 0;
    4407        2129 :     ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow);
    4408             :     SCCOL nColumn;
    4409             :     SCROW nStartRow;
    4410             :     SCROW nEndRow;
    4411        2129 :     const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
    4412        2129 :     if (nEndRow < nLastRow)
    4413             :     {
    4414          24 :         ScDefaultAttrSet aSet;
    4415          24 :         ScDefaultAttrSet::iterator aItr = aSet.end();
    4416         128 :         while (pAttr)
    4417             :         {
    4418          80 :             ScDefaultAttr aAttr(pAttr);
    4419          80 :             aItr = aSet.find(aAttr);
    4420          80 :             if (aItr == aSet.end())
    4421             :             {
    4422          71 :                 aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
    4423          71 :                 aAttr.nFirst = nStartRow;
    4424          71 :                 aSet.insert(aAttr);
    4425             :             }
    4426             :             else
    4427             :             {
    4428           9 :                 aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1);
    4429           9 :                 aAttr.nFirst = aItr->nFirst;
    4430           9 :                 aSet.erase(aItr);
    4431           9 :                 aSet.insert(aAttr);
    4432             :             }
    4433          80 :             pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
    4434             :         }
    4435          24 :         ScDefaultAttrSet::iterator aDefaultItr = aSet.begin();
    4436          24 :         aItr = aDefaultItr;
    4437          24 :         ++aItr;
    4438          95 :         while (aItr != aSet.end())
    4439             :         {
    4440             :             // for entries with equal count, use the one with the lowest start row,
    4441             :             // don't use the random order of pointer comparisons
    4442          96 :             if ( aItr->nCount > aDefaultItr->nCount ||
    4443          60 :                  ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) )
    4444          10 :                 aDefaultItr = aItr;
    4445          47 :             ++aItr;
    4446             :         }
    4447          24 :         nDefault = aDefaultItr->nFirst;
    4448          24 :         bRet = true;
    4449             :     }
    4450             :     else
    4451        2105 :         bRet = true;
    4452        2129 :     return bRet;
    4453             : }
    4454             : 
    4455        8985 : void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
    4456             : {
    4457        8985 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4458        8985 :         maTabs[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
    4459        8985 : }
    4460             : 
    4461             : 
    4462        9046 : void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
    4463             : {
    4464        9046 :     if ( ValidTab(nTab) && maTabs[nTab] )
    4465        9046 :         maTabs[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
    4466        9046 : }
    4467             : 
    4468             : 
    4469             : //  Attribute   ----------------------------------------------------------
    4470             : 
    4471             : 
    4472       10508 : const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
    4473             : {
    4474       10508 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4475             :     {
    4476       10508 :         const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich );
    4477       10508 :         if (pTemp)
    4478       10508 :             return pTemp;
    4479             :         else
    4480             :         {
    4481             :             OSL_FAIL( "Attribut Null" );
    4482             :         }
    4483             :     }
    4484           0 :     return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich );
    4485             : }
    4486             : 
    4487        1223 : const SfxPoolItem* ScDocument::GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const
    4488             : {
    4489        1223 :     return GetAttr(rPos.Col(), rPos.Row(), rPos.Tab(), nWhich);
    4490             : }
    4491             : 
    4492       15362 : const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    4493             : {
    4494       15362 :     if (TableExists(nTab))
    4495       15362 :         return maTabs[nTab]->GetPattern( nCol, nRow );
    4496           0 :     return NULL;
    4497             : }
    4498             : 
    4499           2 : const ScPatternAttr* ScDocument::GetPattern( const ScAddress& rPos ) const
    4500             : {
    4501           2 :     if (TableExists(rPos.Tab()))
    4502           2 :         return maTabs[rPos.Tab()]->GetPattern(rPos.Col(), rPos.Row());
    4503             : 
    4504           0 :     return NULL;
    4505             : }
    4506             : 
    4507       30464 : const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
    4508             : {
    4509       30464 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4510       30464 :         return maTabs[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow );
    4511           0 :     return NULL;
    4512             : }
    4513             : 
    4514             : 
    4515        2717 : void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr )
    4516             : {
    4517        2717 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4518        2717 :         maTabs[nTab]->ApplyAttr( nCol, nRow, rAttr );
    4519        2717 : }
    4520             : 
    4521             : 
    4522           9 : void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr )
    4523             : {
    4524           9 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4525           9 :         maTabs[nTab]->ApplyPattern( nCol, nRow, rAttr );
    4526           9 : }
    4527             : 
    4528             : 
    4529         834 : void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow,
    4530             :                         SCCOL nEndCol, SCROW nEndRow,
    4531             :                         const ScMarkData& rMark,
    4532             :                         const ScPatternAttr& rAttr,
    4533             :                         ScEditDataArray* pDataArray )
    4534             : {
    4535         834 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4536         834 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4537        1668 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    4538         834 :         if (maTabs[*itr])
    4539         834 :             maTabs[*itr]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr, pDataArray );
    4540         834 : }
    4541             : 
    4542             : 
    4543         100 : void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
    4544             :                         SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr )
    4545             : {
    4546         100 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4547         100 :         if (maTabs[nTab])
    4548         100 :             maTabs[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
    4549         100 : }
    4550             : 
    4551       30282 : bool ScDocument::SetAttrEntries(SCCOL nCol, SCTAB nTab, ScAttrEntry* pData, SCSIZE nSize)
    4552             : {
    4553       30282 :     if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
    4554           0 :         return false;
    4555             : 
    4556       30282 :     return maTabs[nTab]->SetAttrEntries(nCol, pData, nSize);
    4557             : }
    4558             : 
    4559           0 : void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
    4560             :         const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
    4561             : {
    4562           0 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4563           0 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4564           0 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    4565           0 :         if (maTabs[*itr])
    4566           0 :             maTabs[*itr]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
    4567           0 : }
    4568             : 
    4569         675 : void ScDocument::AddCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
    4570             : {
    4571         675 :     if(!(static_cast<size_t>(nTab) < maTabs.size()))
    4572           0 :         return;
    4573             : 
    4574         675 :     if(!maTabs[nTab])
    4575           0 :         return;
    4576             : 
    4577         675 :     maTabs[nTab]->AddCondFormatData(rRange, nIndex);
    4578             : }
    4579             : 
    4580           0 : void ScDocument::RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
    4581             : {
    4582           0 :     if(!(static_cast<size_t>(nTab) < maTabs.size()))
    4583           0 :         return;
    4584             : 
    4585           0 :     if(!maTabs[nTab])
    4586           0 :         return;
    4587             : 
    4588           0 :     maTabs[nTab]->RemoveCondFormatData(rRange, nIndex);
    4589             : }
    4590             : 
    4591             : 
    4592           0 : void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle)
    4593             : {
    4594           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4595           0 :         if (maTabs[nTab])
    4596           0 :             maTabs[nTab]->ApplyStyle( nCol, nRow, rStyle );
    4597           0 : }
    4598             : 
    4599             : 
    4600         650 : void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow,
    4601             :                         SCCOL nEndCol, SCROW nEndRow,
    4602             :                         const ScMarkData& rMark,
    4603             :                         const ScStyleSheet& rStyle)
    4604             : {
    4605         650 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4606         650 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4607        1300 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    4608         650 :         if (maTabs[*itr])
    4609         650 :             maTabs[*itr]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
    4610         650 : }
    4611             : 
    4612             : 
    4613        1067 : void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow,
    4614             :                         SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle)
    4615             : {
    4616        1067 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4617        1067 :         if (maTabs[nTab])
    4618        1067 :             maTabs[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
    4619        1067 : }
    4620             : 
    4621             : 
    4622         849 : void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
    4623             : {
    4624             :     // ApplySelectionStyle needs multi mark
    4625         849 :     if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
    4626             :     {
    4627         650 :         ScRange aRange;
    4628         650 :         rMark.GetMarkArea( aRange );
    4629         650 :         ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
    4630        1300 :                           aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
    4631             :     }
    4632             :     else
    4633             :     {
    4634         199 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4635         199 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4636         398 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    4637         199 :             if ( maTabs[*itr] )
    4638         199 :                     maTabs[*itr]->ApplySelectionStyle( rStyle, rMark );
    4639             :     }
    4640         849 : }
    4641             : 
    4642             : 
    4643           0 : void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
    4644             :                     const SvxBorderLine* pLine, bool bColorOnly )
    4645             : {
    4646           0 :     if ( bColorOnly && !pLine )
    4647           0 :         return;
    4648             : 
    4649           0 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4650           0 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4651           0 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    4652           0 :         if (maTabs[*itr])
    4653           0 :             maTabs[*itr]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
    4654             : }
    4655             : 
    4656             : 
    4657          55 : const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    4658             : {
    4659          55 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4660          55 :         return maTabs[nTab]->GetStyle(nCol, nRow);
    4661             :     else
    4662           0 :         return NULL;
    4663             : }
    4664             : 
    4665             : 
    4666         175 : const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
    4667             : {
    4668         175 :     bool    bEqual = true;
    4669             :     bool    bFound;
    4670             : 
    4671         175 :     const ScStyleSheet* pStyle = NULL;
    4672             :     const ScStyleSheet* pNewStyle;
    4673             : 
    4674         175 :     if ( rMark.IsMultiMarked() )
    4675             :     {
    4676          14 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4677          14 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4678          28 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    4679          14 :             if (maTabs[*itr])
    4680             :             {
    4681          14 :                 pNewStyle = maTabs[*itr]->GetSelectionStyle( rMark, bFound );
    4682          14 :                 if (bFound)
    4683             :                 {
    4684          14 :                     if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
    4685           0 :                         bEqual = false;                                             // unterschiedliche
    4686          14 :                     pStyle = pNewStyle;
    4687             :                 }
    4688             :             }
    4689             :     }
    4690         175 :     if ( rMark.IsMarked() )
    4691             :     {
    4692         161 :         ScRange aRange;
    4693         161 :         rMark.GetMarkArea( aRange );
    4694         322 :         for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual && i < static_cast<SCTAB>(maTabs.size()); i++)
    4695         161 :             if (maTabs[i] && rMark.GetTableSelect(i))
    4696             :             {
    4697         161 :                 pNewStyle = maTabs[i]->GetAreaStyle( bFound,
    4698         161 :                                         aRange.aStart.Col(), aRange.aStart.Row(),
    4699         483 :                                         aRange.aEnd.Col(),   aRange.aEnd.Row()   );
    4700         161 :                 if (bFound)
    4701             :                 {
    4702         161 :                     if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
    4703           0 :                         bEqual = false;                                             // unterschiedliche
    4704         161 :                     pStyle = pNewStyle;
    4705             :                 }
    4706             :             }
    4707             :     }
    4708             : 
    4709         175 :     return bEqual ? pStyle : NULL;
    4710             : }
    4711             : 
    4712             : 
    4713        4310 : void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
    4714             :                                     OutputDevice* pDev,
    4715             :                                     double nPPTX, double nPPTY,
    4716             :                                     const Fraction& rZoomX, const Fraction& rZoomY )
    4717             : {
    4718        4310 :     TableContainer::iterator it = maTabs.begin();
    4719        8620 :     for (; it != maTabs.end(); ++it)
    4720        4310 :         if (*it)
    4721        4310 :             (*it)->StyleSheetChanged
    4722        8620 :                 ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
    4723             : 
    4724        4310 :     if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
    4725             :     {
    4726             :         //  update attributes for all note objects
    4727        1399 :         ScDetectiveFunc::UpdateAllComments( *this );
    4728             :     }
    4729        4310 : }
    4730             : 
    4731             : 
    4732           0 : bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
    4733             : {
    4734           0 :     if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN )
    4735             :     {
    4736           0 :         if ( bGatherAllStyles )
    4737             :         {
    4738           0 :             SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(),
    4739           0 :                     SFX_STYLE_FAMILY_PARA );
    4740           0 :             for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle;
    4741             :                                            pStyle = aIter.Next() )
    4742             :             {
    4743           0 :                 const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle );
    4744           0 :                 if ( pScStyle )
    4745           0 :                     pScStyle->SetUsage( ScStyleSheet::NOTUSED );
    4746           0 :             }
    4747             :         }
    4748             : 
    4749           0 :         bool bIsUsed = false;
    4750             : 
    4751           0 :         TableContainer::const_iterator it = maTabs.begin();
    4752           0 :         for (; it != maTabs.end(); ++it)
    4753           0 :             if (*it)
    4754             :             {
    4755           0 :                 if ( (*it)->IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
    4756             :                 {
    4757           0 :                     if ( !bGatherAllStyles )
    4758           0 :                         return true;
    4759           0 :                     bIsUsed = true;
    4760             :                 }
    4761             :             }
    4762             : 
    4763           0 :         if ( bGatherAllStyles )
    4764           0 :             bStyleSheetUsageInvalid = false;
    4765             : 
    4766           0 :         return bIsUsed;
    4767             :     }
    4768             : 
    4769           0 :     return rStyle.GetUsage() == ScStyleSheet::USED;
    4770             : }
    4771             : 
    4772             : 
    4773        1153 : bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow,
    4774             :                         SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
    4775             : {
    4776        1153 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4777        1152 :         if (maTabs[nTab])
    4778        1152 :             return maTabs[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
    4779             : 
    4780             :     OSL_FAIL("ApplyFlags: wrong table");
    4781           1 :     return false;
    4782             : }
    4783             : 
    4784             : 
    4785         301 : bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow,
    4786             :                         SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
    4787             : {
    4788         301 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4789         300 :         if (maTabs[nTab])
    4790         300 :             return maTabs[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
    4791             : 
    4792             :     OSL_FAIL("RemoveFlags: wrong table");
    4793           1 :     return false;
    4794             : }
    4795             : 
    4796             : 
    4797           6 : void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr,
    4798             :                                 bool bPutToPool )
    4799             : {
    4800           6 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    4801           6 :         if (maTabs[nTab])
    4802           6 :             maTabs[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
    4803           6 : }
    4804             : 
    4805             : 
    4806           0 : void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
    4807             :                                 bool bPutToPool )
    4808             : {
    4809           0 :     SCTAB nTab = rPos.Tab();
    4810           0 :     if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    4811           0 :         maTabs[nTab]->SetPattern( rPos, rAttr, bPutToPool );
    4812           0 : }
    4813             : 
    4814             : 
    4815       11390 : ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, bool bDeep )
    4816             : {
    4817       11390 :     ScMergePatternState aState;
    4818             : 
    4819       11390 :     if ( rMark.IsMultiMarked() )                                // multi selection
    4820             :     {
    4821         189 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4822         189 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4823         378 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    4824         189 :             if (maTabs[*itr])
    4825         189 :                 maTabs[*itr]->MergeSelectionPattern( aState, rMark, bDeep );
    4826             :     }
    4827       11390 :     if ( rMark.IsMarked() )                                     // simle selection
    4828             :     {
    4829       11201 :         ScRange aRange;
    4830       11201 :         rMark.GetMarkArea(aRange);
    4831       11201 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4832       11201 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4833       22402 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    4834       11201 :             if (maTabs[*itr])
    4835       11201 :                 maTabs[*itr]->MergePatternArea( aState,
    4836       11201 :                                 aRange.aStart.Col(), aRange.aStart.Row(),
    4837       33603 :                                 aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
    4838             :     }
    4839             : 
    4840             :     OSL_ENSURE( aState.pItemSet, "SelectionPattern Null" );
    4841       11390 :     if (aState.pItemSet)
    4842       11390 :         return new ScPatternAttr( aState.pItemSet );
    4843             :     else
    4844           0 :         return new ScPatternAttr( GetPool() );      // empty
    4845             : }
    4846             : 
    4847             : 
    4848        5378 : const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, bool bDeep )
    4849             : {
    4850        5378 :     delete pSelectionAttr;
    4851        5378 :     pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
    4852        5378 :     return pSelectionAttr;
    4853             : }
    4854             : 
    4855             : 
    4856          44 : void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
    4857             :                                     SvxBoxItem&     rLineOuter,
    4858             :                                     SvxBoxInfoItem& rLineInner )
    4859             : {
    4860          44 :     rLineOuter.SetLine(NULL, BOX_LINE_TOP);
    4861          44 :     rLineOuter.SetLine(NULL, BOX_LINE_BOTTOM);
    4862          44 :     rLineOuter.SetLine(NULL, BOX_LINE_LEFT);
    4863          44 :     rLineOuter.SetLine(NULL, BOX_LINE_RIGHT);
    4864          44 :     rLineOuter.SetDistance(0);
    4865             : 
    4866          44 :     rLineInner.SetLine(NULL, BOXINFO_LINE_HORI);
    4867          44 :     rLineInner.SetLine(NULL, BOXINFO_LINE_VERT);
    4868          44 :     rLineInner.SetTable(true);
    4869          44 :     rLineInner.SetDist(true);
    4870          44 :     rLineInner.SetMinDist(false);
    4871             : 
    4872          44 :     ScLineFlags aFlags;
    4873             : 
    4874          44 :     if (rMark.IsMarked())
    4875             :     {
    4876          44 :         ScRange aRange;
    4877          44 :         rMark.GetMarkArea(aRange);
    4878          44 :         rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() );
    4879          44 :         rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() );
    4880          44 :         SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    4881          44 :         ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    4882          88 :         for (; itr != itrEnd && *itr < nMax; ++itr)
    4883          44 :             if (maTabs[*itr])
    4884          44 :                 maTabs[*itr]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
    4885          44 :                                           aRange.aStart.Col(), aRange.aStart.Row(),
    4886         132 :                                           aRange.aEnd.Col(),   aRange.aEnd.Row() );
    4887             :     }
    4888             : 
    4889             :         //  Don't care Status auswerten
    4890             : 
    4891          44 :     rLineInner.SetValid( VALID_LEFT,   ( aFlags.nLeft != SC_LINE_DONTCARE ) );
    4892          44 :     rLineInner.SetValid( VALID_RIGHT,  ( aFlags.nRight != SC_LINE_DONTCARE ) );
    4893          44 :     rLineInner.SetValid( VALID_TOP,    ( aFlags.nTop != SC_LINE_DONTCARE ) );
    4894          44 :     rLineInner.SetValid( VALID_BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
    4895          44 :     rLineInner.SetValid( VALID_HORI,   ( aFlags.nHori != SC_LINE_DONTCARE ) );
    4896          44 :     rLineInner.SetValid( VALID_VERT,   ( aFlags.nVert != SC_LINE_DONTCARE ) );
    4897          44 : }
    4898             : 
    4899             : 
    4900       25354 : bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
    4901             :                             SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) const
    4902             : {
    4903       25354 :     if ( nMask & HASATTR_ROTATE )
    4904             :     {
    4905             :         //  Attribut im Dokument ueberhaupt verwendet?
    4906             :         //  (wie in fillinfo)
    4907             : 
    4908       17287 :         ScDocumentPool* pPool = xPoolHelper->GetDocPool();
    4909             : 
    4910       17287 :         bool bAnyItem = false;
    4911       17287 :         sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
    4912       44587 :         for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
    4913             :         {
    4914       27829 :             const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem );
    4915       27829 :             if ( pItem )
    4916             :             {
    4917             :                 // 90 or 270 degrees is former SvxOrientationItem - only look for other values
    4918             :                 // (see ScPatternAttr::GetCellOrientation)
    4919       27685 :                 sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue();
    4920       27685 :                 if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
    4921             :                 {
    4922         529 :                     bAnyItem = true;
    4923         529 :                     break;
    4924             :                 }
    4925             :             }
    4926             :         }
    4927       17287 :         if (!bAnyItem)
    4928       16758 :             nMask &= ~HASATTR_ROTATE;
    4929             :     }
    4930             : 
    4931       25354 :     if ( nMask & HASATTR_RTL )
    4932             :     {
    4933             :         //  first check if right-to left is in the pool at all
    4934             :         //  (the same item is used in cell and page format)
    4935             : 
    4936           0 :         ScDocumentPool* pPool = xPoolHelper->GetDocPool();
    4937             : 
    4938           0 :         bool bHasRtl = false;
    4939           0 :         sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR );
    4940           0 :         for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++)
    4941             :         {
    4942           0 :             const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem );
    4943           0 :             if ( pItem && ((const SvxFrameDirectionItem*)pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP )
    4944             :             {
    4945           0 :                 bHasRtl = true;
    4946           0 :                 break;
    4947             :             }
    4948             :         }
    4949           0 :         if (!bHasRtl)
    4950           0 :             nMask &= ~HASATTR_RTL;
    4951             :     }
    4952             : 
    4953       25354 :     if (!nMask)
    4954           0 :         return false;
    4955             : 
    4956       25354 :     bool bFound = false;
    4957       50697 :     for (SCTAB i=nTab1; i<=nTab2 && !bFound && i < static_cast<SCTAB>(maTabs.size()); i++)
    4958       25343 :         if (maTabs[i])
    4959             :         {
    4960       25343 :             if ( nMask & HASATTR_RTL )
    4961             :             {
    4962           0 :                 if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L )       // sheet default
    4963           0 :                     bFound = true;
    4964             :             }
    4965       25343 :             if ( nMask & HASATTR_RIGHTORCENTER )
    4966             :             {
    4967             :                 //  On a RTL sheet, don't start to look for the default left value
    4968             :                 //  (which is then logically right), instead always assume true.
    4969             :                 //  That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
    4970             : 
    4971        8298 :                 if ( IsLayoutRTL(i) )
    4972           0 :                     bFound = true;
    4973             :             }
    4974             : 
    4975       25343 :             if ( !bFound )
    4976       25343 :                 bFound = maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
    4977             :         }
    4978             : 
    4979       25354 :     return bFound;
    4980             : }
    4981             : 
    4982        8450 : bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) const
    4983             : {
    4984       16900 :     return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
    4985       16900 :                       rRange.aEnd.Col(),   rRange.aEnd.Row(),   rRange.aEnd.Tab(),
    4986       42250 :                       nMask );
    4987             : }
    4988             : 
    4989         352 : void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
    4990             :                                 SCCOL nX1, SCCOL nX2 ) const
    4991             : {
    4992         352 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    4993         352 :         maTabs[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
    4994             :     else
    4995             :     {
    4996             :         OSL_FAIL("FindMaxRotCol: wrong table");
    4997             :     }
    4998         352 : }
    4999             : 
    5000         183 : void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab,
    5001             :                         const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
    5002             :                         const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
    5003             : {
    5004             :     //! Seitengrenzen fuer Druck beruecksichtigen !!!!!
    5005             : 
    5006         183 :     const SvxBoxItem* pThisAttr = (const SvxBoxItem*) GetEffItem( nCol, nRow, nTab, ATTR_BORDER );
    5007             :     OSL_ENSURE(pThisAttr,"where is the attribute?");
    5008             : 
    5009         183 :     const SvxBorderLine* pLeftLine   = pThisAttr->GetLeft();
    5010         183 :     const SvxBorderLine* pTopLine    = pThisAttr->GetTop();
    5011         183 :     const SvxBorderLine* pRightLine  = pThisAttr->GetRight();
    5012         183 :     const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
    5013             : 
    5014         183 :     if ( nCol > 0 )
    5015             :     {
    5016             :         const SvxBorderLine* pOther = ((const SvxBoxItem*)
    5017         160 :                                 GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
    5018         160 :         if ( ScHasPriority( pOther, pLeftLine ) )
    5019          17 :             pLeftLine = pOther;
    5020             :     }
    5021         183 :     if ( nRow > 0 )
    5022             :     {
    5023             :         const SvxBorderLine* pOther = ((const SvxBoxItem*)
    5024         177 :                                 GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
    5025         177 :         if ( ScHasPriority( pOther, pTopLine ) )
    5026          16 :             pTopLine = pOther;
    5027             :     }
    5028         183 :     if ( nCol < MAXCOL )
    5029             :     {
    5030             :         const SvxBorderLine* pOther = ((const SvxBoxItem*)
    5031         183 :                                 GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
    5032         183 :         if ( ScHasPriority( pOther, pRightLine ) )
    5033          18 :             pRightLine = pOther;
    5034             :     }
    5035         183 :     if ( nRow < MAXROW )
    5036             :     {
    5037             :         const SvxBorderLine* pOther = ((const SvxBoxItem*)
    5038         183 :                                 GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
    5039         183 :         if ( ScHasPriority( pOther, pBottomLine ) )
    5040          17 :             pBottomLine = pOther;
    5041             :     }
    5042             : 
    5043         183 :     if (ppLeft)
    5044         135 :         *ppLeft = pLeftLine;
    5045         183 :     if (ppTop)
    5046         183 :         *ppTop = pTopLine;
    5047         183 :     if (ppRight)
    5048         135 :         *ppRight = pRightLine;
    5049         183 :     if (ppBottom)
    5050         135 :         *ppBottom = pBottomLine;
    5051         183 : }
    5052             : 
    5053         156 : bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
    5054             :                                         SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const
    5055             : {
    5056         156 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    5057         156 :         if (maTabs[nTab])
    5058         156 :             return maTabs[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes );
    5059             : 
    5060             :     OSL_FAIL("wrong table number");
    5061           0 :     return false;
    5062             : }
    5063             : 
    5064             : 
    5065           0 : void ScDocument::LockTable(SCTAB nTab)
    5066             : {
    5067           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5068           0 :         maTabs[nTab]->LockTable();
    5069             :     else
    5070             :     {
    5071             :         OSL_FAIL("wrong table number");
    5072             :     }
    5073           0 : }
    5074             : 
    5075             : 
    5076           0 : void ScDocument::UnlockTable(SCTAB nTab)
    5077             : {
    5078           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5079           0 :         maTabs[nTab]->UnlockTable();
    5080             :     else
    5081             :     {
    5082             :         OSL_FAIL("wrong table number");
    5083             :     }
    5084           0 : }
    5085             : 
    5086             : 
    5087        2338 : bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
    5088             :                                         SCCOL nEndCol, SCROW nEndRow,
    5089             :                                         bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
    5090             : {
    5091             :     // import into read-only document is possible
    5092        2338 :     if (!bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly())
    5093             :     {
    5094           0 :         if ( pOnlyNotBecauseOfMatrix )
    5095           0 :             *pOnlyNotBecauseOfMatrix = false;
    5096           0 :         return false;
    5097             :     }
    5098             : 
    5099        2338 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    5100        2338 :         if (maTabs[nTab])
    5101        2338 :             return maTabs[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
    5102        4676 :                 nEndRow, pOnlyNotBecauseOfMatrix );
    5103             : 
    5104             :     OSL_FAIL("wrong table number");
    5105           0 :     if ( pOnlyNotBecauseOfMatrix )
    5106           0 :         *pOnlyNotBecauseOfMatrix = false;
    5107           0 :     return false;
    5108             : }
    5109             : 
    5110             : 
    5111         683 : bool ScDocument::IsSelectionEditable( const ScMarkData& rMark,
    5112             :             bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
    5113             : {
    5114             :     // import into read-only document is possible
    5115         683 :     if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
    5116             :     {
    5117           0 :         if ( pOnlyNotBecauseOfMatrix )
    5118           0 :             *pOnlyNotBecauseOfMatrix = false;
    5119           0 :         return false;
    5120             :     }
    5121             : 
    5122         683 :     ScRange aRange;
    5123         683 :     rMark.GetMarkArea(aRange);
    5124             : 
    5125         683 :     bool bOk = true;
    5126         683 :     bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
    5127         683 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5128         683 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5129        1366 :     for (; itr != itrEnd && *itr < nMax && (bOk || bMatrix); ++itr)
    5130             :     {
    5131         683 :         if ( maTabs[*itr] )
    5132             :         {
    5133         683 :             if (rMark.IsMarked())
    5134             :             {
    5135        1866 :                 if ( !maTabs[*itr]->IsBlockEditable( aRange.aStart.Col(),
    5136         622 :                         aRange.aStart.Row(), aRange.aEnd.Col(),
    5137        2488 :                         aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
    5138             :                 {
    5139           0 :                     bOk = false;
    5140           0 :                     if ( pOnlyNotBecauseOfMatrix )
    5141           0 :                         bMatrix = *pOnlyNotBecauseOfMatrix;
    5142             :                 }
    5143             :             }
    5144         683 :             if (rMark.IsMultiMarked())
    5145             :             {
    5146          61 :                 if ( !maTabs[*itr]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
    5147             :                 {
    5148           0 :                     bOk = false;
    5149           0 :                     if ( pOnlyNotBecauseOfMatrix )
    5150           0 :                         bMatrix = *pOnlyNotBecauseOfMatrix;
    5151             :                 }
    5152             :             }
    5153             :         }
    5154             :     }
    5155             : 
    5156         683 :     if ( pOnlyNotBecauseOfMatrix )
    5157         683 :         *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
    5158             : 
    5159         683 :     return bOk;
    5160             : }
    5161             : 
    5162             : 
    5163          13 : bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow,
    5164             :                                 SCCOL nEndCol, SCROW nEndRow,
    5165             :                                 const ScMarkData& rMark ) const
    5166             : {
    5167          13 :     bool bOk = true;
    5168          13 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5169          13 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5170          26 :     for (; itr != itrEnd && *itr < nMax && bOk; ++itr)
    5171          13 :         if (maTabs[*itr])
    5172          13 :             if (maTabs[*itr]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
    5173           0 :                 bOk = false;
    5174             : 
    5175          13 :     return !bOk;
    5176             : }
    5177             : 
    5178          20 : bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix )
    5179             : {
    5180             :     //  if rCell is part of a matrix formula, return its complete range
    5181             : 
    5182          20 :     ScFormulaCell* pFCell = GetFormulaCell(rCellPos);
    5183          20 :     if (!pFCell)
    5184             :         // not a formula cell.  Bail out.
    5185           0 :         return false;
    5186             : 
    5187          20 :     ScAddress aOrigin = rCellPos;
    5188          20 :     if (!pFCell->GetMatrixOrigin(aOrigin))
    5189             :         // Failed to get the address of the matrix origin.
    5190           4 :         return false;
    5191             : 
    5192          16 :     if (aOrigin != rCellPos)
    5193             :     {
    5194          13 :         pFCell = GetFormulaCell(aOrigin);
    5195          13 :         if (!pFCell)
    5196             :             // The matrix origin cell is not a formula cell !?  Something is up...
    5197           0 :             return false;
    5198             :     }
    5199             : 
    5200             :     SCCOL nSizeX;
    5201             :     SCROW nSizeY;
    5202          16 :     pFCell->GetMatColsRows(nSizeX, nSizeY);
    5203          16 :     if (nSizeX <= 0 || nSizeY <= 0)
    5204             :     {
    5205             :         // GetMatrixEdge computes also dimensions of the matrix
    5206             :         // if not already done (may occur if document is loaded
    5207             :         // from old file format).
    5208             :         // Needs an "invalid" initialized address.
    5209           0 :         aOrigin.SetInvalid();
    5210           0 :         pFCell->GetMatrixEdge(aOrigin);
    5211           0 :         pFCell->GetMatColsRows(nSizeX, nSizeY);
    5212             :     }
    5213             : 
    5214          16 :     if (nSizeX <= 0 || nSizeY <= 0)
    5215             :         // Matrix size is still invalid. Give up.
    5216           0 :         return false;
    5217             : 
    5218          16 :     ScAddress aEnd( aOrigin.Col() + nSizeX - 1,
    5219          32 :                     aOrigin.Row() + nSizeY - 1,
    5220          64 :                     aOrigin.Tab() );
    5221             : 
    5222          16 :     rMatrix.aStart = aOrigin;
    5223          16 :     rMatrix.aEnd = aEnd;
    5224             : 
    5225          16 :     return true;
    5226             : }
    5227             : 
    5228             : 
    5229         206 : bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
    5230             :                                 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) const
    5231             : {
    5232         206 :     bool bFound = false;
    5233         206 :     if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) )
    5234             :     {
    5235         206 :         if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5236             :         {
    5237             :             SCCOL nCol;
    5238         206 :             SCCOL nOldCol = rStartCol;
    5239         206 :             SCROW nOldRow = rStartRow;
    5240        1480 :             for (nCol=nOldCol; nCol<=nEndCol; nCol++)
    5241        2551 :                 while (((ScMergeFlagAttr*)GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
    5242             :                             IsVerOverlapped())
    5243           3 :                     --rStartRow;
    5244             : 
    5245             :             //!     weiterreichen ?
    5246             : 
    5247         206 :             ScAttrArray* pAttrArray = maTabs[nTab]->aCol[nOldCol].pAttrArray;
    5248             :             SCSIZE nIndex;
    5249         206 :             pAttrArray->Search( nOldRow, nIndex );
    5250         206 :             SCROW nAttrPos = nOldRow;
    5251         654 :             while (nAttrPos<=nEndRow)
    5252             :             {
    5253             :                 OSL_ENSURE( nIndex < pAttrArray->nCount, "Wrong index in AttrArray" );
    5254             : 
    5255         484 :                 if (((ScMergeFlagAttr&)pAttrArray->pData[nIndex].pPattern->
    5256         242 :                         GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
    5257             :                 {
    5258           5 :                     SCROW nLoopEndRow = std::min( nEndRow, pAttrArray->pData[nIndex].nRow );
    5259          10 :                     for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
    5260             :                     {
    5261           5 :                         SCCOL nTempCol = nOldCol;
    5262           5 :                         do
    5263           5 :                             --nTempCol;
    5264           5 :                         while (((ScMergeFlagAttr*)GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
    5265             :                                 ->IsHorOverlapped());
    5266           5 :                         if (nTempCol < rStartCol)
    5267           5 :                             rStartCol = nTempCol;
    5268             :                     }
    5269             :                 }
    5270         242 :                 nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
    5271         242 :                 ++nIndex;
    5272             :             }
    5273             :         }
    5274             :     }
    5275             :     else
    5276             :     {
    5277             :         OSL_FAIL("ExtendOverlapped: invalid range");
    5278             :     }
    5279             : 
    5280         206 :     return bFound;
    5281             : }
    5282             : 
    5283          32 : bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
    5284             :                               SCCOL& rEndCol, SCROW& rEndRow,
    5285             :                               const ScMarkData& rMark, bool bRefresh )
    5286             : {
    5287             :     // use all selected sheets from rMark
    5288             : 
    5289          32 :     bool bFound = false;
    5290          32 :     SCCOL nOldEndCol = rEndCol;
    5291          32 :     SCROW nOldEndRow = rEndRow;
    5292             : 
    5293          32 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5294          32 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5295          64 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    5296          32 :         if ( maTabs[*itr] )
    5297             :         {
    5298          32 :             SCCOL nThisEndCol = nOldEndCol;
    5299          32 :             SCROW nThisEndRow = nOldEndRow;
    5300          32 :             if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, *itr, bRefresh ) )
    5301           0 :                 bFound = true;
    5302          32 :             if ( nThisEndCol > rEndCol )
    5303           0 :                 rEndCol = nThisEndCol;
    5304          32 :             if ( nThisEndRow > rEndRow )
    5305           0 :                 rEndRow = nThisEndRow;
    5306             :         }
    5307             : 
    5308          32 :     return bFound;
    5309             : }
    5310             : 
    5311             : 
    5312        9197 : bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
    5313             :                               SCCOL& rEndCol,  SCROW& rEndRow,
    5314             :                               SCTAB nTab, bool bRefresh )
    5315             : {
    5316        9197 :     bool bFound = false;
    5317        9197 :     if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) )
    5318             :     {
    5319        9197 :         if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5320        9197 :             bFound = maTabs[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh );
    5321             : 
    5322        9197 :         if (bRefresh)
    5323         165 :             RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
    5324             :     }
    5325             :     else
    5326             :     {
    5327             :         OSL_FAIL("ExtendMerge: invalid range");
    5328             :     }
    5329             : 
    5330        9197 :     return bFound;
    5331             : }
    5332             : 
    5333             : 
    5334         321 : bool ScDocument::ExtendMerge( ScRange& rRange, bool bRefresh )
    5335             : {
    5336         321 :     bool bFound = false;
    5337         321 :     SCTAB nStartTab = rRange.aStart.Tab();
    5338         321 :     SCTAB nEndTab   = rRange.aEnd.Tab();
    5339         321 :     SCCOL nEndCol   = rRange.aEnd.Col();
    5340         321 :     SCROW nEndRow   = rRange.aEnd.Row();
    5341             : 
    5342         321 :     PutInOrder( nStartTab, nEndTab );
    5343         641 :     for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
    5344             :     {
    5345         320 :         SCCOL nExtendCol = rRange.aEnd.Col();
    5346         320 :         SCROW nExtendRow = rRange.aEnd.Row();
    5347         640 :         if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
    5348             :                          nExtendCol,          nExtendRow,
    5349         640 :                          nTab, bRefresh ) )
    5350             :         {
    5351          23 :             bFound = true;
    5352          23 :             if (nExtendCol > nEndCol) nEndCol = nExtendCol;
    5353          23 :             if (nExtendRow > nEndRow) nEndRow = nExtendRow;
    5354             :         }
    5355             :     }
    5356             : 
    5357         321 :     rRange.aEnd.SetCol(nEndCol);
    5358         321 :     rRange.aEnd.SetRow(nEndRow);
    5359             : 
    5360         321 :     return bFound;
    5361             : }
    5362             : 
    5363           1 : bool ScDocument::ExtendTotalMerge( ScRange& rRange ) const
    5364             : {
    5365             :     //  Bereich genau dann auf zusammengefasste Zellen erweitern, wenn
    5366             :     //  dadurch keine neuen nicht-ueberdeckten Zellen getroffen werden
    5367             : 
    5368           1 :     bool bRet = false;
    5369           1 :     ScRange aExt = rRange;
    5370             :     // ExtendMerge() is non-const, but called withouth refresh.
    5371           1 :     if (const_cast<ScDocument*>(this)->ExtendMerge( aExt, false))
    5372             :     {
    5373           0 :         if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
    5374             :         {
    5375           0 :             ScRange aTest = aExt;
    5376           0 :             aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
    5377           0 :             if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
    5378           0 :                 aExt.aEnd.SetRow(rRange.aEnd.Row());
    5379             :         }
    5380           0 :         if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
    5381             :         {
    5382           0 :             ScRange aTest = aExt;
    5383           0 :             aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
    5384           0 :             if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
    5385           0 :                 aExt.aEnd.SetCol(rRange.aEnd.Col());
    5386             :         }
    5387             : 
    5388           0 :         bRet = ( aExt.aEnd != rRange.aEnd );
    5389           0 :         rRange = aExt;
    5390             :     }
    5391           1 :     return bRet;
    5392             : }
    5393             : 
    5394         175 : bool ScDocument::ExtendOverlapped( ScRange& rRange ) const
    5395             : {
    5396         175 :     bool bFound = false;
    5397         175 :     SCTAB nStartTab = rRange.aStart.Tab();
    5398         175 :     SCTAB nEndTab   = rRange.aEnd.Tab();
    5399         175 :     SCCOL nStartCol = rRange.aStart.Col();
    5400         175 :     SCROW nStartRow = rRange.aStart.Row();
    5401             : 
    5402         175 :     PutInOrder( nStartTab, nEndTab );
    5403         350 :     for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
    5404             :     {
    5405         175 :         SCCOL nExtendCol = rRange.aStart.Col();
    5406         175 :         SCROW nExtendRow = rRange.aStart.Row();
    5407             :         ExtendOverlapped( nExtendCol, nExtendRow,
    5408         175 :                                 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
    5409         175 :         if (nExtendCol < nStartCol)
    5410             :         {
    5411           5 :             nStartCol = nExtendCol;
    5412           5 :             bFound = true;
    5413             :         }
    5414         175 :         if (nExtendRow < nStartRow)
    5415             :         {
    5416           2 :             nStartRow = nExtendRow;
    5417           2 :             bFound = true;
    5418             :         }
    5419             :     }
    5420             : 
    5421         175 :     rRange.aStart.SetCol(nStartCol);
    5422         175 :     rRange.aStart.SetRow(nStartRow);
    5423             : 
    5424         175 :     return bFound;
    5425             : }
    5426             : 
    5427         188 : bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
    5428             :                                     SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
    5429             : {
    5430             :     SCTAB nDBTab;
    5431             :     SCCOL nDBStartCol;
    5432             :     SCROW nDBStartRow;
    5433             :     SCCOL nDBEndCol;
    5434             :     SCROW nDBEndRow;
    5435             : 
    5436             :     //      Autofilter loeschen
    5437             : 
    5438         188 :     bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
    5439             : 
    5440             :     //      Autofilter setzen
    5441             : 
    5442         188 :     const ScDBData* pData = NULL;
    5443         188 :     ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
    5444         188 :     ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
    5445         188 :     for (; itr != itrEnd; ++itr)
    5446             :     {
    5447           0 :         if (itr->HasAutoFilter())
    5448             :         {
    5449           0 :             itr->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
    5450           0 :             if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
    5451           0 :                                     nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
    5452             :             {
    5453           0 :                 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
    5454           0 :                                     nDBTab, SC_MF_AUTO ))
    5455           0 :                     bChange = true;
    5456             :             }
    5457             :         }
    5458             :     }
    5459         188 :     if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5460         188 :         pData = maTabs[nTab]->GetAnonymousDBData();
    5461             :     else
    5462           0 :         pData=NULL;
    5463         188 :     if (pData)
    5464             :     {
    5465          14 :         if (pData->HasAutoFilter())
    5466             :         {
    5467           0 :             pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
    5468           0 :             if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
    5469           0 :                                     nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
    5470             :             {
    5471           0 :                 if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
    5472           0 :                                     nDBTab, SC_MF_AUTO ))
    5473           0 :                     bChange = true;
    5474             :             }
    5475             :         }
    5476             :     }
    5477         188 :     return bChange;
    5478             : }
    5479             : 
    5480          75 : void ScDocument::SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const
    5481             : {
    5482         150 :     while (IsHorOverlapped(rCol, rRow, nTab))
    5483           0 :         --rCol;
    5484         150 :     while (IsVerOverlapped(rCol, rRow, nTab))
    5485           0 :         --rRow;
    5486          75 : }
    5487             : 
    5488          86 : bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    5489             : {
    5490             :     const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
    5491          86 :                                         GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
    5492          86 :     if (pAttr)
    5493          86 :         return pAttr->IsHorOverlapped();
    5494             :     else
    5495             :     {
    5496             :         OSL_FAIL("Overlapped: Attr==0");
    5497           0 :         return false;
    5498             :     }
    5499             : }
    5500             : 
    5501             : 
    5502          86 : bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
    5503             : {
    5504             :     const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*)
    5505          86 :                                         GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG );
    5506          86 :     if (pAttr)
    5507          86 :         return pAttr->IsVerOverlapped();
    5508             :     else
    5509             :     {
    5510             :         OSL_FAIL("Overlapped: Attr==0");
    5511           0 :         return false;
    5512             :     }
    5513             : }
    5514             : 
    5515             : 
    5516           4 : void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
    5517             :                                       const SvxBoxItem* pLineOuter,
    5518             :                                       const SvxBoxInfoItem* pLineInner )
    5519             : {
    5520           4 :     ScRangeList aRangeList;
    5521           4 :     rMark.FillRangeListWithMarks( &aRangeList, false );
    5522           4 :     size_t nRangeCount = aRangeList.size();
    5523           4 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5524           4 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5525           8 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    5526             :     {
    5527           4 :         if (maTabs[*itr])
    5528             :         {
    5529           8 :             for ( size_t j=0; j < nRangeCount; j++ )
    5530             :             {
    5531           4 :                 ScRange aRange = *aRangeList[ j ];
    5532           4 :                 maTabs[*itr]->ApplyBlockFrame( pLineOuter, pLineInner,
    5533           4 :                     aRange.aStart.Col(), aRange.aStart.Row(),
    5534          12 :                     aRange.aEnd.Col(),   aRange.aEnd.Row() );
    5535             :             }
    5536             :         }
    5537           4 :     }
    5538           4 : }
    5539             : 
    5540             : 
    5541         892 : void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
    5542             :                                     const SvxBoxItem* pLineOuter,
    5543             :                                     const SvxBoxInfoItem* pLineInner )
    5544             : {
    5545         892 :     SCTAB nStartTab = rRange.aStart.Tab();
    5546         892 :     SCTAB nEndTab = rRange.aStart.Tab();
    5547        1784 :     for (SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
    5548         892 :         if (maTabs[nTab])
    5549         892 :             maTabs[nTab]->ApplyBlockFrame( pLineOuter, pLineInner,
    5550         892 :                                          rRange.aStart.Col(), rRange.aStart.Row(),
    5551        2676 :                                          rRange.aEnd.Col(),   rRange.aEnd.Row() );
    5552         892 : }
    5553             : 
    5554             : 
    5555        1475 : void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark, ScEditDataArray* pDataArray )
    5556             : {
    5557        1475 :     const SfxItemSet* pSet = &rAttr.GetItemSet();
    5558        1475 :     bool bSet = false;
    5559             :     sal_uInt16 i;
    5560       56676 :     for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
    5561       55201 :         if (pSet->GetItemState(i) == SFX_ITEM_SET)
    5562         966 :             bSet = true;
    5563             : 
    5564        1475 :     if (bSet)
    5565             :     {
    5566             :         // ApplySelectionCache needs multi mark
    5567         966 :         if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
    5568             :         {
    5569         834 :             ScRange aRange;
    5570         834 :             rMark.GetMarkArea( aRange );
    5571         834 :             ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
    5572        1668 :                               aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr, pDataArray );
    5573             :         }
    5574             :         else
    5575             :         {
    5576         132 :             SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet );
    5577         132 :             SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5578         132 :             ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5579         264 :             for (; itr != itrEnd && *itr < nMax; ++itr)
    5580         132 :                 if (maTabs[*itr])
    5581         264 :                     maTabs[*itr]->ApplySelectionCache( &aCache, rMark, pDataArray );
    5582             :         }
    5583             :     }
    5584        1475 : }
    5585             : 
    5586             : 
    5587           6 : void ScDocument::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
    5588             : {
    5589           6 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5590           6 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5591          12 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    5592           6 :         if (maTabs[*itr])
    5593           6 :             maTabs[*itr]->ChangeSelectionIndent( bIncrement, rMark );
    5594           6 : }
    5595             : 
    5596             : 
    5597           0 : void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
    5598             : {
    5599           0 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5600           0 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5601           0 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    5602           0 :         if (maTabs[*itr])
    5603           0 :             maTabs[*itr]->ClearSelectionItems( pWhich, rMark );
    5604           0 : }
    5605             : 
    5606             : 
    5607          86 : void ScDocument::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark, bool bBroadcast )
    5608             : {
    5609          86 :     SCTAB nMax = static_cast<SCTAB>(maTabs.size());
    5610          86 :     ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
    5611         172 :     for (; itr != itrEnd && *itr < nMax; ++itr)
    5612          86 :         if (maTabs[*itr])
    5613          86 :             maTabs[*itr]->DeleteSelection(nDelFlag, rMark, bBroadcast);
    5614          86 : }
    5615             : 
    5616             : 
    5617           0 : void ScDocument::DeleteSelectionTab(
    5618             :     SCTAB nTab, sal_uInt16 nDelFlag, const ScMarkData& rMark, bool bBroadcast )
    5619             : {
    5620           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5621           0 :         maTabs[nTab]->DeleteSelection(nDelFlag, rMark, bBroadcast);
    5622             :     else
    5623             :     {
    5624             :         OSL_FAIL("wrong table");
    5625             :     }
    5626           0 : }
    5627             : 
    5628             : 
    5629     2027864 : ScPatternAttr* ScDocument::GetDefPattern() const
    5630             : {
    5631     2027864 :     return (ScPatternAttr*) &xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN);
    5632             : }
    5633             : 
    5634             : 
    5635     2512363 : ScDocumentPool* ScDocument::GetPool()
    5636             : {
    5637     2512363 :     return xPoolHelper->GetDocPool();
    5638             : }
    5639             : 
    5640       51001 : ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
    5641             : {
    5642       51001 :     return xPoolHelper->GetStylePool();
    5643             : }
    5644             : 
    5645             : 
    5646        3248 : SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
    5647             :                             SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir )
    5648             : {
    5649        3248 :     PutInOrder(nStartCol, nEndCol);
    5650        3248 :     PutInOrder(nStartRow, nEndRow);
    5651        3248 :     PutInOrder(nStartTab, nEndTab);
    5652        3248 :     if (ValidTab(nStartTab) && nStartTab < static_cast<SCTAB>(maTabs.size()))
    5653             :     {
    5654        3248 :         if (maTabs[nStartTab])
    5655        3248 :             return maTabs[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
    5656             :         else
    5657           0 :             return 0;
    5658             :     }
    5659             :     else
    5660           0 :         return 0;
    5661             : }
    5662             : 
    5663             : 
    5664          26 : void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, ScMoveDirection eDirection ) const
    5665             : {
    5666          26 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5667          26 :         maTabs[nTab]->FindAreaPos( rCol, rRow, eDirection );
    5668          26 : }
    5669             : 
    5670             : 
    5671           0 : void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
    5672             :                                 bool bMarked, bool bUnprotected, const ScMarkData& rMark ) const
    5673             : {
    5674             :     OSL_ENSURE( !nMovX || !nMovY, "GetNextPos: only X or Y" );
    5675             : 
    5676           0 :     ScMarkData aCopyMark = rMark;
    5677           0 :     aCopyMark.SetMarking(false);
    5678           0 :     aCopyMark.MarkToMulti();
    5679             : 
    5680           0 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5681           0 :         maTabs[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
    5682           0 : }
    5683             : 
    5684             : 
    5685             : //  Datei-Operationen
    5686             : 
    5687         387 : void ScDocument::UpdStlShtPtrsFrmNms()
    5688             : {
    5689         387 :     ScPatternAttr::pDoc = this;
    5690             : 
    5691         387 :     ScDocumentPool* pPool = xPoolHelper->GetDocPool();
    5692             : 
    5693         387 :     sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
    5694             :     ScPatternAttr* pPattern;
    5695         387 :     for (sal_uInt32 i=0; i<nCount; i++)
    5696             :     {
    5697           0 :         pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
    5698           0 :         if (pPattern)
    5699           0 :             pPattern->UpdateStyleSheet();
    5700             :     }
    5701         387 :     ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).UpdateStyleSheet();
    5702         387 : }
    5703             : 
    5704             : 
    5705           0 : void ScDocument::StylesToNames()
    5706             : {
    5707           0 :     ScPatternAttr::pDoc = this;
    5708             : 
    5709           0 :     ScDocumentPool* pPool = xPoolHelper->GetDocPool();
    5710             : 
    5711           0 :     sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
    5712             :     ScPatternAttr* pPattern;
    5713           0 :     for (sal_uInt32 i=0; i<nCount; i++)
    5714             :     {
    5715           0 :         pPattern = (ScPatternAttr*)pPool->GetItem2(ATTR_PATTERN, i);
    5716           0 :         if (pPattern)
    5717           0 :             pPattern->StyleToName();
    5718             :     }
    5719           0 :     ((ScPatternAttr&)pPool->GetDefaultItem(ATTR_PATTERN)).StyleToName();
    5720           0 : }
    5721             : 
    5722             : 
    5723          32 : sal_uLong ScDocument::GetCellCount() const
    5724             : {
    5725          32 :     sal_uLong nCellCount = 0L;
    5726             : 
    5727          32 :     TableContainer::const_iterator it = maTabs.begin();
    5728          68 :     for (; it != maTabs.end(); ++it)
    5729          36 :         if ( *it )
    5730          36 :             nCellCount += (*it)->GetCellCount();
    5731             : 
    5732          32 :     return nCellCount;
    5733             : }
    5734             : 
    5735           0 : sal_uLong ScDocument::GetCodeCount() const
    5736             : {
    5737           0 :     sal_uLong nCodeCount = 0;
    5738             : 
    5739           0 :     TableContainer::const_iterator it = maTabs.begin();
    5740           0 :     for (; it != maTabs.end(); ++it)
    5741           0 :         if ( *it )
    5742           0 :             nCodeCount += (*it)->GetCodeCount();
    5743             : 
    5744           0 :     return nCodeCount;
    5745             : }
    5746             : 
    5747             : 
    5748         107 : void ScDocument::PageStyleModified( SCTAB nTab, const OUString& rNewName )
    5749             : {
    5750         107 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5751         107 :         maTabs[nTab]->PageStyleModified( rNewName );
    5752         107 : }
    5753             : 
    5754             : 
    5755         282 : void ScDocument::SetPageStyle( SCTAB nTab, const OUString& rName )
    5756             : {
    5757         282 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5758         282 :         maTabs[nTab]->SetPageStyle( rName );
    5759         282 : }
    5760             : 
    5761             : 
    5762       28005 : const OUString ScDocument::GetPageStyle( SCTAB nTab ) const
    5763             : {
    5764       28005 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5765       28005 :         return maTabs[nTab]->GetPageStyle();
    5766             : 
    5767           0 :     return OUString();
    5768             : }
    5769             : 
    5770             : 
    5771         308 : void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize )
    5772             : {
    5773         308 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5774         308 :         maTabs[nTab]->SetPageSize( rSize );
    5775         308 : }
    5776             : 
    5777        1908 : Size ScDocument::GetPageSize( SCTAB nTab ) const
    5778             : {
    5779        1908 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5780        1908 :         return maTabs[nTab]->GetPageSize();
    5781             : 
    5782             :     OSL_FAIL("invalid tab");
    5783           0 :     return Size();
    5784             : }
    5785             : 
    5786             : 
    5787         264 : void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
    5788             : {
    5789         264 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5790         264 :         maTabs[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
    5791         264 : }
    5792             : 
    5793          30 : void ScDocument::InvalidatePageBreaks(SCTAB nTab)
    5794             : {
    5795          30 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5796          30 :         maTabs[nTab]->InvalidatePageBreaks();
    5797          30 : }
    5798             : 
    5799        1206 : void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea )
    5800             : {
    5801        1206 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5802        1206 :         maTabs[nTab]->UpdatePageBreaks( pUserArea );
    5803        1206 : }
    5804             : 
    5805           0 : void ScDocument::RemoveManualBreaks( SCTAB nTab )
    5806             : {
    5807           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5808           0 :         maTabs[nTab]->RemoveManualBreaks();
    5809           0 : }
    5810             : 
    5811           0 : bool ScDocument::HasManualBreaks( SCTAB nTab ) const
    5812             : {
    5813           0 :     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
    5814           0 :         return maTabs[nTab]->HasManualBreaks();
    5815             : 
    5816             :     OSL_FAIL("invalid tab");
    5817           0 :     return false;
    5818             : }
    5819             : 
    5820             : 
    5821           0 : void ScDocument::GetDocStat( ScDocStat& rDocStat )
    5822             : {
    5823           0 :     rDocStat.nTableCount = GetTableCount();
    5824           0 :     rDocStat.aDocName    = aDocName;
    5825           0 :     rDocStat.nCellCount  = GetCellCount();
    5826           0 : }
    5827             : 
    5828             : 
    5829         340 : bool ScDocument::HasPrintRange()
    5830             : {
    5831         340 :     bool bResult = false;
    5832             : 
    5833         340 :     TableContainer::iterator it = maTabs.begin();
    5834         680 :     for (; it != maTabs.end() && !bResult; ++it)
    5835         340 :         if ( *it )
    5836         340 :             bResult = (*it)->IsPrintEntireSheet() || ((*it)->GetPrintRangeCount() > 0);
    5837             : 
    5838         340 :     return bResult;
    5839             : }
    5840             : 
    5841             : 
    5842         612 : bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const
    5843             : {
    5844         612 :     return (ValidTab(nTab) ) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsPrintEntireSheet();
    5845             : }
    5846             : 
    5847             : 
    5848         395 : sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab )
    5849             : {
    5850         395 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5851         395 :         return maTabs[nTab]->GetPrintRangeCount();
    5852             : 
    5853           0 :     return 0;
    5854             : }
    5855             : 
    5856             : 
    5857         296 : const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos )
    5858             : {
    5859         296 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5860         296 :         return maTabs[nTab]->GetPrintRange(nPos);
    5861             : 
    5862           0 :     return NULL;
    5863             : }
    5864             : 
    5865             : 
    5866         386 : const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab )
    5867             : {
    5868         386 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5869         386 :         return maTabs[nTab]->GetRepeatColRange();
    5870             : 
    5871           0 :     return NULL;
    5872             : }
    5873             : 
    5874             : 
    5875         392 : const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab )
    5876             : {
    5877         392 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5878         392 :         return maTabs[nTab]->GetRepeatRowRange();
    5879             : 
    5880           0 :     return NULL;
    5881             : }
    5882             : 
    5883             : 
    5884          49 : void ScDocument::ClearPrintRanges( SCTAB nTab )
    5885             : {
    5886          49 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5887          49 :         maTabs[nTab]->ClearPrintRanges();
    5888          49 : }
    5889             : 
    5890             : 
    5891           8 : void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew )
    5892             : {
    5893           8 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5894           8 :         maTabs[nTab]->AddPrintRange( rNew );
    5895           8 : }
    5896             : 
    5897             : 
    5898          11 : void ScDocument::SetPrintEntireSheet( SCTAB nTab )
    5899             : {
    5900          11 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5901          11 :         maTabs[nTab]->SetPrintEntireSheet();
    5902          11 : }
    5903             : 
    5904             : 
    5905           1 : void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew )
    5906             : {
    5907           1 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5908           1 :         maTabs[nTab]->SetRepeatColRange( pNew );
    5909           1 : }
    5910             : 
    5911             : 
    5912           5 : void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew )
    5913             : {
    5914           5 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5915           5 :         maTabs[nTab]->SetRepeatRowRange( pNew );
    5916           5 : }
    5917             : 
    5918             : 
    5919         106 : ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
    5920             : {
    5921         106 :     SCTAB nCount = static_cast<SCTAB>(maTabs.size());
    5922         106 :     ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
    5923         285 :     for (SCTAB i=0; i<nCount; i++)
    5924         179 :         if (maTabs[i])
    5925         179 :             maTabs[i]->FillPrintSaver( pNew->GetTabData(i) );
    5926         106 :     return pNew;
    5927             : }
    5928             : 
    5929             : 
    5930           1 : void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
    5931             : {
    5932           1 :     SCTAB nCount = rSaver.GetTabCount();
    5933           3 :     for (SCTAB i=0; i<nCount && i < static_cast<SCTAB>(maTabs.size()); i++)
    5934           2 :         if (maTabs[i])
    5935           2 :             maTabs[i]->RestorePrintRanges( rSaver.GetTabData(i) );
    5936           1 : }
    5937             : 
    5938             : 
    5939           2 : bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
    5940             : {
    5941             :     //  Die Seitennummern-Zaehlung faengt bei einer Tabelle neu an, wenn eine
    5942             :     //  andere Vorlage als bei der vorherigen gesetzt ist (nur Namen vergleichen)
    5943             :     //  und eine Seitennummer angegeben ist (nicht 0)
    5944             : 
    5945           2 :     if ( nTab + 1 < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab+1] )
    5946             :     {
    5947           2 :         OUString aNew = maTabs[nTab+1]->GetPageStyle();
    5948           2 :         if ( aNew != maTabs[nTab]->GetPageStyle() )
    5949             :         {
    5950           0 :             SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE );
    5951           0 :             if ( pStyle )
    5952             :             {
    5953           0 :                 const SfxItemSet& rSet = pStyle->GetItemSet();
    5954           0 :                 sal_uInt16 nFirst = ((const SfxUInt16Item&)rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
    5955           0 :                 if ( nFirst != 0 )
    5956           0 :                     return true;        // Seitennummer in neuer Vorlage angegeben
    5957             :             }
    5958           2 :         }
    5959             :     }
    5960             : 
    5961           2 :     return false;       // sonst nicht
    5962             : }
    5963             : 
    5964       42697 : SfxUndoManager* ScDocument::GetUndoManager()
    5965             : {
    5966       42697 :     if (!mpUndoManager)
    5967             :     {
    5968             :         // to support enhanced text edit for draw objects, use an SdrUndoManager
    5969         394 :         mpUndoManager = new SdrUndoManager;
    5970             :     }
    5971             : 
    5972       42697 :     return mpUndoManager;
    5973             : }
    5974             : 
    5975          76 : ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
    5976             : {
    5977          76 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    5978          76 :         return new ScRowBreakIterator(maTabs[nTab]->maRowPageBreaks);
    5979           0 :     return NULL;
    5980             : }
    5981             : 
    5982           9 : void ScDocument::AddSubTotalCell(ScFormulaCell* pCell)
    5983             : {
    5984           9 :     maSubTotalCells.insert(pCell);
    5985           9 : }
    5986             : 
    5987        5730 : void ScDocument::RemoveSubTotalCell(ScFormulaCell* pCell)
    5988             : {
    5989        5730 :     maSubTotalCells.erase(pCell);
    5990        5730 : }
    5991             : 
    5992             : namespace {
    5993             : 
    5994           0 : bool lcl_hasDirtyRange(ScFormulaCell* pCell, const ScRange& rDirtyRange)
    5995             : {
    5996           0 :     ScDetectiveRefIter aRefIter(pCell);
    5997           0 :     ScRange aRange;
    5998           0 :     while (aRefIter.GetNextRef(aRange))
    5999             :     {
    6000           0 :         if (aRange.Intersects(rDirtyRange))
    6001           0 :             return true;
    6002             :     }
    6003           0 :     return false;
    6004             : }
    6005             : 
    6006             : }
    6007             : 
    6008          14 : void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
    6009             : {
    6010             :     // to update the list by skipping cells that no longer contain subtotal function.
    6011          14 :     set<ScFormulaCell*> aNewSet;
    6012             : 
    6013          14 :     bool bOldRecalc = GetAutoCalc();
    6014          14 :     SetAutoCalc(false);
    6015          14 :     set<ScFormulaCell*>::iterator itr = maSubTotalCells.begin(), itrEnd = maSubTotalCells.end();
    6016          14 :     for (; itr != itrEnd; ++itr)
    6017             :     {
    6018           0 :         ScFormulaCell* pCell = *itr;
    6019           0 :         if (pCell->IsSubTotal())
    6020             :         {
    6021           0 :             aNewSet.insert(pCell);
    6022           0 :             if (lcl_hasDirtyRange(pCell, rDirtyRange))
    6023           0 :                 pCell->SetDirty();
    6024             :         }
    6025             :     }
    6026             : 
    6027          14 :     SetAutoCalc(bOldRecalc);
    6028          14 :     maSubTotalCells.swap(aNewSet); // update the list.
    6029          14 : }
    6030             : 
    6031           5 : void ScDocument::MarkSubTotalCells( sc::ColumnSpanSet& rSet, const ScRange& rRange, bool bVal ) const
    6032             : {
    6033          10 :     for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
    6034             :     {
    6035           5 :         const ScTable* pTab = FetchTable(nTab);
    6036           5 :         if (!pTab)
    6037           0 :             continue;
    6038             : 
    6039             :         pTab->MarkSubTotalCells(
    6040           5 :             rSet, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), bVal);
    6041             :     }
    6042           5 : }
    6043             : 
    6044           1 : sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const
    6045             : {
    6046           1 :     SCTAB nTab = rPos.Tab();
    6047           1 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    6048           1 :         return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row());
    6049             : 
    6050           0 :     return 0;
    6051             : }
    6052             : 
    6053       19219 : sal_uInt8 ScDocument::GetScriptType( const ScAddress& rPos ) const
    6054             : {
    6055       19219 :     SCTAB nTab = rPos.Tab();
    6056       19219 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    6057       19219 :         return maTabs[nTab]->GetScriptType(rPos.Col(), rPos.Row());
    6058             : 
    6059           0 :     return 0;
    6060             : }
    6061             : 
    6062        3070 : void ScDocument::SetScriptType( const ScAddress& rPos, sal_uInt8 nType )
    6063             : {
    6064        3070 :     SCTAB nTab = rPos.Tab();
    6065        3070 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
    6066        3070 :         maTabs[nTab]->SetScriptType(rPos.Col(), rPos.Row(), nType);
    6067        3070 : }
    6068             : 
    6069       16772 : void ScDocument::EnableUndo( bool bVal )
    6070             : {
    6071             :     // The undo manager increases lock count every time undo is disabled.
    6072             :     // Because of this, we shouldn't disable undo unless it's currently
    6073             :     // enabled, or else re-enabling it may not actually re-enable undo unless
    6074             :     // the lock count becomes zero.
    6075             : 
    6076       16772 :     if (bVal != GetUndoManager()->IsUndoEnabled())
    6077             :     {
    6078       16280 :         GetUndoManager()->EnableUndo(bVal);
    6079       16280 :         if( pDrawLayer ) pDrawLayer->EnableUndo(bVal);
    6080             :     }
    6081             : 
    6082       16772 :     mbUndoEnabled = bVal;
    6083       16772 : }
    6084             : 
    6085           0 : bool ScDocument::IsUserInteractionEnabled() const
    6086             : {
    6087           0 :     return mbUserInteractionEnabled;
    6088             : }
    6089             : 
    6090         151 : void ScDocument::EnableUserInteraction( bool bVal )
    6091             : {
    6092         151 :     mbUserInteractionEnabled = bVal;
    6093         151 : }
    6094             : 
    6095         165 : bool ScDocument::IsInVBAMode() const
    6096             : {
    6097         165 :     if (!pShell)
    6098           0 :         return false;
    6099             : 
    6100             :     try
    6101             :     {
    6102             :         uno::Reference<script::vba::XVBACompatibility> xVBA(
    6103         165 :             pShell->GetBasicContainer(), uno::UNO_QUERY);
    6104             : 
    6105         165 :         return xVBA.is() && xVBA->getVBACompatibilityMode();
    6106             :     }
    6107           0 :     catch (const lang::NotInitializedException&) {}
    6108             : 
    6109           0 :     return false;
    6110             : }
    6111             : 
    6112         702 : ScPostIt* ScDocument::GetNote(const ScAddress& rPos)
    6113             : {
    6114         702 :     return GetNote(rPos.Col(), rPos.Row(), rPos.Tab());
    6115             : }
    6116             : 
    6117      168469 : ScPostIt* ScDocument::GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab)
    6118             : {
    6119      168469 :     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
    6120      168469 :         return maTabs[nTab]->aCol[nCol].GetCellNote(nRow);
    6121             :     else
    6122           0 :         return NULL;
    6123             : 
    6124             : }
    6125             : 
    6126          59 : void ScDocument::SetNote(const ScAddress& rPos, ScPostIt* pNote)
    6127             : {
    6128          59 :     return SetNote(rPos.Col(), rPos.Row(), rPos.Tab(), pNote);
    6129             : }
    6130             : 
    6131          59 : void ScDocument::SetNote(SCCOL nCol, SCROW nRow, SCTAB nTab, ScPostIt* pNote)
    6132             : {
    6133          59 :     return maTabs[nTab]->aCol[nCol].SetCellNote(nRow, pNote);
    6134             : }
    6135             : 
    6136         119 : bool ScDocument::HasNote(const ScAddress& rPos)
    6137             : {
    6138         119 :     return HasNote(rPos.Col(), rPos.Row(), rPos.Tab());
    6139             : }
    6140         128 : bool ScDocument::HasNote(SCCOL nCol, SCROW nRow, SCTAB nTab)
    6141             : {
    6142         128 :     ScPostIt* pNote = maTabs[nTab]->aCol[nCol].GetCellNote(nRow);
    6143         128 :     return pNote != NULL;
    6144             : }
    6145           3 : bool ScDocument::HasColNotes(SCCOL nCol, SCTAB nTab)
    6146             : {
    6147           3 :     return maTabs[nTab]->aCol[nCol].HasCellNotes();
    6148             : }
    6149             : 
    6150           0 : bool ScDocument::HasTabNotes(SCTAB nTab)
    6151             : {
    6152           0 :     bool hasNotes = false;
    6153           0 :     for (SCCOL nCol=0; nCol<MAXCOLCOUNT && !hasNotes; ++nCol)
    6154           0 :         hasNotes = HasColNotes(nCol, nTab);
    6155             : 
    6156           0 :     return hasNotes;
    6157             : }
    6158             : 
    6159          12 : ScPostIt* ScDocument::ReleaseNote(const ScAddress& rPos)
    6160             : {
    6161          12 :     ScTable* pTab = FetchTable(rPos.Tab());
    6162          12 :     if (!pTab)
    6163           0 :         return NULL;
    6164             : 
    6165          12 :     return pTab->ReleaseNote(rPos.Col(), rPos.Row());
    6166             : }
    6167             : 
    6168          25 : ScPostIt* ScDocument::GetOrCreateNote(const ScAddress& rPos)
    6169             : {
    6170          25 :     if (HasNote(rPos))
    6171           0 :         return GetNote(rPos);
    6172             :     else
    6173          25 :         return CreateNote(rPos);
    6174             : }
    6175          25 : ScPostIt* ScDocument::CreateNote(const ScAddress& rPos)
    6176             : {
    6177          25 :     ScPostIt* pPostIt = new ScPostIt(*this, rPos, false);
    6178          25 :     SetNote(rPos, pPostIt);
    6179          25 :     return pPostIt;
    6180             : }
    6181             : 
    6182        1050 : size_t ScDocument::GetNoteCount( SCTAB nTab, SCCOL nCol ) const
    6183             : {
    6184        1050 :     const ScTable* pTab = FetchTable(nTab);
    6185        1050 :     if (!pTab)
    6186           0 :         return 0;
    6187             : 
    6188        1050 :     return pTab->GetNoteCount(nCol);
    6189             : }
    6190             : 
    6191          19 : void ScDocument::CreateAllNoteCaptions()
    6192             : {
    6193          19 :     TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
    6194          42 :     for (; it != itEnd; ++it)
    6195             :     {
    6196          23 :         ScTable* p = *it;
    6197          23 :         if (p)
    6198          23 :             p->CreateAllNoteCaptions();
    6199             :     }
    6200          19 : }
    6201             : 
    6202           7 : void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges )
    6203             : {
    6204          14 :     for (size_t i = 0, n = rRanges.size(); i < n; ++i)
    6205             :     {
    6206           7 :         const ScRange* p = rRanges[i];
    6207           7 :         const ScAddress& s = p->aStart;
    6208           7 :         const ScAddress& e = p->aEnd;
    6209          14 :         for (SCTAB nTab = s.Tab(); nTab <= e.Tab(); ++nTab)
    6210             :         {
    6211           7 :             ScTable* pTab = FetchTable(nTab);
    6212           7 :             if (!pTab)
    6213           0 :                 continue;
    6214             : 
    6215           7 :             pTab->ForgetNoteCaptions(s.Col(), s.Row(), e.Col(), e.Row());
    6216             :         }
    6217             :     }
    6218           7 : }
    6219             : 
    6220           6 : ScAddress ScDocument::GetNotePosition( size_t nIndex ) const
    6221             : {
    6222           7 :     for (size_t nTab = 0; nTab < maTabs.size(); ++nTab)
    6223             :     {
    6224        1051 :         for (SCCOL nCol=0; nCol<MAXCOLCOUNT; nCol++)
    6225             :         {
    6226        1050 :             size_t nColNoteCount = GetNoteCount(nTab, nCol);
    6227        1050 :             if (!nColNoteCount)
    6228        1035 :                 continue;
    6229             : 
    6230          15 :             if (nIndex >= nColNoteCount)
    6231             :             {
    6232          10 :                 nIndex -= nColNoteCount;
    6233          10 :                 continue;
    6234             :             }
    6235             : 
    6236           5 :             SCROW nRow = GetNotePosition(nTab, nCol, nIndex);
    6237           5 :             if (nRow >= 0)
    6238           5 :                 return ScAddress(nCol, nRow, nTab);
    6239             : 
    6240             :             OSL_FAIL("note not found");
    6241           0 :             return ScAddress(ScAddress::INITIALIZE_INVALID);
    6242             :         }
    6243             :     }
    6244             : 
    6245             :     OSL_FAIL("note not found");
    6246           1 :     return ScAddress(ScAddress::INITIALIZE_INVALID);
    6247             : }
    6248             : 
    6249           5 : SCROW ScDocument::GetNotePosition( SCTAB nTab, SCCOL nCol, size_t nIndex ) const
    6250             : {
    6251           5 :     const ScTable* pTab = FetchTable(nTab);
    6252           5 :     if (!pTab)
    6253           0 :         return -1;
    6254             : 
    6255           5 :     return pTab->GetNotePosition(nCol, nIndex);
    6256             : }
    6257             : 
    6258          44 : void ScDocument::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
    6259             : {
    6260         148 :     for (size_t nTab = 0; nTab < maTabs.size(); ++nTab)
    6261             :     {
    6262         104 :         const ScTable* pTab = maTabs[nTab];
    6263         104 :         if (!pTab)
    6264           0 :             continue;
    6265             : 
    6266         104 :         pTab->GetAllNoteEntries(rNotes);
    6267             :     }
    6268          44 : }
    6269             : 
    6270          12 : void ScDocument::GetNotesInRange( const ScRangeList& rRange, std::vector<sc::NoteEntry>& rNotes ) const
    6271             : {
    6272          24 :     for( size_t i = 0; i < rRange.size(); ++i)
    6273             :     {
    6274          12 :         const ScRange* pRange = rRange[i];
    6275          24 :         for( SCTAB nTab = pRange->aStart.Tab(); nTab <= pRange->aEnd.Tab(); ++nTab )
    6276             :         {
    6277          12 :             maTabs[nTab]->GetNotesInRange( *pRange, rNotes );
    6278             :         }
    6279             :     }
    6280          12 : }
    6281             : 
    6282           0 : bool ScDocument::ContainsNotesInRange( const ScRangeList& rRange ) const
    6283             : {
    6284           0 :     for( size_t i = 0; i < rRange.size(); ++i)
    6285             :     {
    6286           0 :         const ScRange* pRange = rRange[i];
    6287           0 :         for( SCTAB nTab = pRange->aStart.Tab(); nTab < pRange->aEnd.Tab(); ++nTab )
    6288             :         {
    6289           0 :             bool bContainsNote = maTabs[nTab]->ContainsNotesInRange( *pRange );
    6290           0 :             if(bContainsNote)
    6291           0 :                 return true;
    6292             :         }
    6293             :     }
    6294             : 
    6295           0 :     return false;
    6296             : }
    6297             : 
    6298          88 : void ScDocument::SetAutoNameCache(  ScAutoNameCache* pCache )
    6299             : {
    6300          88 :     delete pAutoNameCache;
    6301          88 :     pAutoNameCache = pCache;
    6302         190 : }
    6303             : 
    6304             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10