LCOV - code coverage report
Current view: top level - sc/source/core/data - document.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 2597 3395 76.5 %
Date: 2015-06-13 12:38:46 Functions: 315 363 86.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11