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

Generated by: LCOV version 1.10