LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - column.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 534 1029 51.9 %
Date: 2012-12-27 Functions: 59 88 67.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <map>
      21             : 
      22             : #include <svl/poolcach.hxx>
      23             : #include <svl/zforlist.hxx>
      24             : #include <editeng/scripttypeitem.hxx>
      25             : #include <string.h>
      26             : 
      27             : #include "scitems.hxx"
      28             : #include "column.hxx"
      29             : #include "cell.hxx"
      30             : #include "document.hxx"
      31             : #include "docpool.hxx"
      32             : #include "attarray.hxx"
      33             : #include "patattr.hxx"
      34             : #include "compiler.hxx"
      35             : #include "brdcst.hxx"
      36             : #include "markdata.hxx"
      37             : #include "detfunc.hxx"          // for Notes in Sort/Swap
      38             : #include "postit.hxx"
      39             : 
      40             : //#pragma optimize ( "", off )
      41             : //  nur Search ohne Optimierung!
      42             : 
      43             : // STATIC DATA -----------------------------------------------------------
      44             : using ::editeng::SvxBorderLine;
      45             : using namespace formula;
      46             : 
      47        4908 : inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
      48             : {
      49             :     //! move to a header file
      50             :     return ( nScript != SCRIPTTYPE_LATIN &&
      51             :              nScript != SCRIPTTYPE_ASIAN &&
      52             :              nScript != SCRIPTTYPE_COMPLEX &&
      53        4908 :              nScript != 0 );
      54             : }
      55             : 
      56      276480 : ScColumn::ScColumn() :
      57             :     nCol( 0 ),
      58             :     pAttrArray( NULL ),
      59      276480 :     pDocument( NULL )
      60             : {
      61      276480 : }
      62             : 
      63             : 
      64      409600 : ScColumn::~ScColumn()
      65             : {
      66      204800 :     FreeAll();
      67      204800 :     delete pAttrArray;
      68      204800 : }
      69             : 
      70             : 
      71      276480 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
      72             : {
      73      276480 :     nCol = nNewCol;
      74      276480 :     nTab = nNewTab;
      75      276480 :     pDocument = pDoc;
      76      276480 :     pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
      77      276480 : }
      78             : 
      79             : 
      80           0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
      81             : {
      82           0 :     return pAttrArray->GetNextUnprotected(nRow, bUp);
      83             : }
      84             : 
      85             : 
      86      123055 : sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
      87             : {
      88             :     // nothing:0, inside:1, bottom:2, left:4, top:8, right:16, open:32
      89      123055 :     if ( maItems.empty() )
      90      123049 :         return 0;
      91           6 :     if ( nRow1 == nRow2 )
      92             :     {
      93             :         SCSIZE nIndex;
      94           6 :         if ( Search( nRow1, nIndex ) )
      95             :         {
      96           4 :             ScBaseCell* pCell = maItems[nIndex].pCell;
      97           4 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA
      98           0 :                 && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
      99             :             {
     100           0 :                 ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
     101           0 :                 return ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
     102             :             }
     103             :         }
     104           6 :         return 0;
     105             :     }
     106             :     else
     107             :     {
     108           0 :         ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
     109           0 :         bool bOpen = false;
     110           0 :         sal_uInt16 nEdges = 0;
     111             :         SCSIZE nIndex;
     112           0 :         Search( nRow1, nIndex );
     113           0 :         while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nRow2 )
     114             :         {
     115           0 :             ScBaseCell* pCell = maItems[nIndex].pCell;
     116           0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA
     117           0 :                 && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
     118             :             {
     119           0 :                 nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
     120           0 :                 if ( nEdges )
     121             :                 {
     122           0 :                     if ( nEdges & 8 )
     123           0 :                         bOpen = true;       // top edge opens, keep on looking
     124           0 :                     else if ( !bOpen )
     125           0 :                         return nEdges | 32; // there's something that wasn't opened
     126           0 :                     else if ( nEdges & 1 )
     127           0 :                         return nEdges;      // inside
     128             :                     // (nMask & 16 and  (4 and not 16)) or
     129             :                     // (nMask & 4  and (16 and not 4))
     130           0 :                     if ( ((nMask & 16) && (nEdges & 4)  && !(nEdges & 16))
     131           0 :                         || ((nMask & 4)  && (nEdges & 16) && !(nEdges & 4)) )
     132           0 :                         return nEdges;      // only left/right edge
     133           0 :                     if ( nEdges & 2 )
     134           0 :                         bOpen = false;      // bottom edge closes
     135             :                 }
     136             :             }
     137           0 :             nIndex++;
     138             :         }
     139           0 :         if ( bOpen )
     140           0 :             nEdges |= 32;           // not closed, matrix continues
     141           0 :         return nEdges;
     142             :     }
     143             : }
     144             : 
     145             : 
     146           0 : bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
     147             : {
     148           0 :     if ( rMark.IsMultiMarked() )
     149             :     {
     150           0 :         bool bFound = false;
     151             : 
     152           0 :         ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
     153           0 :         ScAddress aCurOrg( ScAddress::INITIALIZE_INVALID );
     154             :         SCROW nTop, nBottom;
     155           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     156           0 :         while ( !bFound && aMarkIter.Next( nTop, nBottom ) )
     157             :         {
     158           0 :             bool bOpen = false;
     159             :             sal_uInt16 nEdges;
     160             :             SCSIZE nIndex;
     161           0 :             Search( nTop, nIndex );
     162           0 :             while ( !bFound && nIndex < maItems.size() && maItems[nIndex].nRow <= nBottom )
     163             :             {
     164           0 :                 ScBaseCell* pCell = maItems[nIndex].pCell;
     165           0 :                 if ( pCell->GetCellType() == CELLTYPE_FORMULA
     166           0 :                     && ((ScFormulaCell*)pCell)->GetMatrixFlag() )
     167             :                 {
     168           0 :                     nEdges = ((ScFormulaCell*)pCell)->GetMatrixEdge( aOrg );
     169           0 :                     if ( nEdges )
     170             :                     {
     171           0 :                         if ( nEdges & 8 )
     172           0 :                             bOpen = true;   // top edge opens, keep on looking
     173           0 :                         else if ( !bOpen )
     174           0 :                             return true;    // there's something that wasn't opened
     175           0 :                         else if ( nEdges & 1 )
     176           0 :                             bFound = true;  // inside, all selected?
     177             :                         // (4 and not 16) or (16 and not 4)
     178           0 :                         if ( (((nEdges & 4) | 16) ^ ((nEdges & 16) | 4)) )
     179           0 :                             bFound = true;  // only left/right edge, all selected?
     180           0 :                         if ( nEdges & 2 )
     181           0 :                             bOpen = false;  // bottom edge closes
     182             : 
     183           0 :                         if ( bFound )
     184             :                         {   // all selected?
     185           0 :                             if ( aCurOrg != aOrg )
     186             :                             {   // new matrix to check?
     187           0 :                                 aCurOrg = aOrg;
     188             :                                 ScFormulaCell* pFCell;
     189           0 :                                 if ( ((ScFormulaCell*)pCell)->GetMatrixFlag()
     190             :                                         == MM_REFERENCE )
     191           0 :                                     pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
     192             :                                 else
     193           0 :                                     pFCell = (ScFormulaCell*)pCell;
     194             :                                 SCCOL nC;
     195             :                                 SCROW nR;
     196           0 :                                 pFCell->GetMatColsRows( nC, nR );
     197             :                                 ScRange aRange( aOrg, ScAddress(
     198           0 :                                     aOrg.Col() + nC - 1, aOrg.Row() + nR - 1,
     199           0 :                                     aOrg.Tab() ) );
     200           0 :                                 if ( rMark.IsAllMarked( aRange ) )
     201           0 :                                     bFound = false;
     202             :                             }
     203             :                             else
     204           0 :                                 bFound = false;     // done already
     205             :                         }
     206             :                     }
     207             :                 }
     208           0 :                 nIndex++;
     209             :             }
     210           0 :             if ( bOpen )
     211           0 :                 return true;
     212             :         }
     213           0 :         return bFound;
     214             :     }
     215             :     else
     216           0 :         return false;
     217             : }
     218             : 
     219             : 
     220       50882 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     221             : {
     222       50882 :     return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
     223             : }
     224             : 
     225             : 
     226           0 : bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
     227             : {
     228           0 :     bool bFound = false;
     229             : 
     230             :     SCROW nTop;
     231             :     SCROW nBottom;
     232             : 
     233           0 :     if (rMark.IsMultiMarked())
     234             :     {
     235           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     236           0 :         while (aMarkIter.Next( nTop, nBottom ) && !bFound)
     237             :         {
     238           0 :             if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
     239           0 :                 bFound = true;
     240           0 :         }
     241             :     }
     242             : 
     243           0 :     return bFound;
     244             : }
     245             : 
     246             : 
     247        1415 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
     248             :                             SCCOL& rPaintCol, SCROW& rPaintRow,
     249             :                             bool bRefresh )
     250             : {
     251        1415 :     return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
     252             : }
     253             : 
     254             : 
     255       22528 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
     256             : {
     257             :     SCROW nTop;
     258             :     SCROW nBottom;
     259             : 
     260       22528 :     if ( rMark.IsMultiMarked() )
     261             :     {
     262       22528 :         const ScMarkArray* pArray = rMark.GetArray() + nCol;
     263       22528 :         if ( pArray->HasMarks() )
     264             :         {
     265          94 :             ScMarkArrayIter aMarkIter( pArray );
     266         323 :             while (aMarkIter.Next( nTop, nBottom ))
     267         229 :                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
     268             :         }
     269             :     }
     270       22528 : }
     271             : 
     272             : 
     273       21672 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
     274             : {
     275       21672 :     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
     276       21672 : }
     277             : 
     278             : 
     279           0 : void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     280             :                             ScLineFlags& rFlags,
     281             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
     282             : {
     283           0 :     pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
     284           0 : }
     285             : 
     286             : 
     287         390 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
     288             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
     289             : {
     290         390 :     pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
     291         390 : }
     292             : 
     293             : 
     294        4427 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
     295             : {
     296        4427 :     return pAttrArray->GetPattern( nRow );
     297             : }
     298             : 
     299             : 
     300        2398 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
     301             : {
     302        2398 :     return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
     303             : }
     304             : 
     305             : 
     306        1024 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
     307             : {
     308        1024 :     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     309        1024 :     const ScPatternAttr* pMaxPattern = 0;
     310        1024 :     size_t nMaxCount = 0;
     311             : 
     312        1024 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
     313             :     const ScPatternAttr* pPattern;
     314        1024 :     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
     315             : 
     316        3088 :     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
     317             :     {
     318        1040 :         size_t& rnCount = aAttrMap[ pPattern ];
     319        1040 :         rnCount += (nAttrRow2 - nAttrRow1 + 1);
     320        1040 :         if( rnCount > nMaxCount )
     321             :         {
     322        1040 :             pMaxPattern = pPattern;
     323        1040 :             nMaxCount = rnCount;
     324             :         }
     325             :     }
     326             : 
     327        1024 :     return pMaxPattern;
     328             : }
     329             : 
     330           0 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
     331             : {
     332             :     SCROW nPatStartRow, nPatEndRow;
     333           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     334           0 :     sal_uInt32 nFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     335           0 :     while (nEndRow > nPatEndRow)
     336             :     {
     337           0 :         nStartRow = nPatEndRow + 1;
     338           0 :         pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     339           0 :         sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     340           0 :         if (nFormat != nTmpFormat)
     341           0 :             return 0;
     342             :     }
     343           0 :     return nFormat;
     344             : }
     345             : 
     346             : 
     347        9990 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
     348             : {
     349        9990 :     return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
     350             : }
     351             : 
     352             : 
     353       21504 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
     354             : {
     355       21504 :     SCROW nTop = 0;
     356       21504 :     SCROW nBottom = 0;
     357       21504 :     bool bFound = false;
     358             : 
     359       21504 :     if ( rMark.IsMultiMarked() )
     360             :     {
     361       21504 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     362       43109 :         while (aMarkIter.Next( nTop, nBottom ))
     363             :         {
     364         101 :             pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
     365         101 :             bFound = true;
     366       21504 :         }
     367             :     }
     368             : 
     369       21504 :     if (!bFound)
     370       21426 :         return -1;
     371          78 :     else if (nTop==0 && nBottom==MAXROW)
     372           0 :         return 0;
     373             :     else
     374          78 :         return nBottom;
     375             : }
     376             : 
     377             : 
     378           0 : void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
     379             : {
     380             :     SCROW nTop;
     381             :     SCROW nBottom;
     382             : 
     383           0 :     if ( pAttrArray && rMark.IsMultiMarked() )
     384             :     {
     385           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     386           0 :         while (aMarkIter.Next( nTop, nBottom ))
     387           0 :             pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
     388             :     }
     389           0 : }
     390             : 
     391             : 
     392           0 : void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
     393             : {
     394             :     SCROW nTop;
     395             :     SCROW nBottom;
     396             : 
     397           0 :     if ( pAttrArray && rMark.IsMultiMarked() )
     398             :     {
     399           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     400           0 :         while (aMarkIter.Next( nTop, nBottom ))
     401           0 :             pAttrArray->ClearItems(nTop, nBottom, pWhich);
     402             :     }
     403           0 : }
     404             : 
     405             : 
     406        2048 : void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
     407             : {
     408             :     SCROW nTop;
     409             :     SCROW nBottom;
     410             : 
     411        2048 :     if ( rMark.IsMultiMarked() )
     412             :     {
     413        2048 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     414        4102 :         while (aMarkIter.Next( nTop, nBottom ))
     415        2054 :             DeleteArea(nTop, nBottom, nDelFlag);
     416             :     }
     417        2048 : }
     418             : 
     419             : 
     420          29 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
     421             : {
     422          29 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     423          29 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     424             : 
     425          29 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
     426             : 
     427             :     //  true = alten Eintrag behalten
     428             : 
     429          29 :     ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, true );
     430          29 :     ScDocumentPool::CheckRef( *pPattern );
     431          29 :     ScDocumentPool::CheckRef( *pNewPattern );
     432             : 
     433          29 :     if (pNewPattern != pPattern)
     434          29 :       pAttrArray->SetPattern( nRow, pNewPattern );
     435          29 : }
     436             : 
     437             : 
     438       17596 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
     439             :                                  ScEditDataArray* pDataArray )
     440             : {
     441       17596 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     442       17596 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     443       17596 :     pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
     444       17596 : }
     445             : 
     446       20535 : bool ScColumn::SetAttrEntries(ScAttrEntry* pData, SCSIZE nSize)
     447             : {
     448       20535 :     return pAttrArray->SetAttrEntries(pData, nSize);
     449             : }
     450             : 
     451           0 : void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
     452             :         const ScPatternAttr& rPattern, short nNewType )
     453             : {
     454           0 :     const SfxItemSet* pSet = &rPattern.GetItemSet();
     455           0 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     456           0 :     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
     457           0 :     SCROW nEndRow = rRange.aEnd.Row();
     458           0 :     for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
     459             :     {
     460             :         SCROW nRow1, nRow2;
     461             :         const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
     462           0 :             nRow1, nRow2, nRow );
     463           0 :         sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
     464           0 :         short nOldType = pFormatter->GetType( nFormat );
     465           0 :         if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
     466           0 :             nRow = nRow2;
     467             :         else
     468             :         {
     469           0 :             SCROW nNewRow1 = Max( nRow1, nRow );
     470           0 :             SCROW nNewRow2 = Min( nRow2, nEndRow );
     471           0 :             pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
     472           0 :             nRow = nNewRow2;
     473             :         }
     474           0 :     }
     475           0 : }
     476             : 
     477          49 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     478             : {
     479          49 :     pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
     480          49 : }
     481             : 
     482           0 : void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     483             : {
     484           0 :     pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex );
     485           0 : }
     486             : 
     487             : 
     488           0 : void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
     489             : {
     490           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
     491           0 :     ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
     492           0 :     if (pNewPattern)
     493             :     {
     494           0 :         pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
     495           0 :         pAttrArray->SetPattern(nRow, pNewPattern, true);
     496           0 :         delete pNewPattern;
     497             :     }
     498           0 : }
     499             : 
     500             : 
     501         643 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
     502             : {
     503         643 :     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
     504         643 : }
     505             : 
     506             : 
     507       68608 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
     508             : {
     509             :     SCROW nTop;
     510             :     SCROW nBottom;
     511             : 
     512       68608 :     if ( rMark.IsMultiMarked() )
     513             :     {
     514       68608 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     515      137708 :         while (aMarkIter.Next( nTop, nBottom ))
     516       69100 :             pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
     517             :     }
     518       68608 : }
     519             : 
     520             : 
     521           0 : void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
     522             :                                     const SvxBorderLine* pLine, bool bColorOnly )
     523             : {
     524           0 :     if ( bColorOnly && !pLine )
     525           0 :         return;
     526             : 
     527             :     SCROW nTop;
     528             :     SCROW nBottom;
     529             : 
     530           0 :     if (rMark.IsMultiMarked())
     531             :     {
     532           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     533           0 :         while (aMarkIter.Next( nTop, nBottom ))
     534           0 :             pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
     535             :     }
     536             : }
     537             : 
     538             : 
     539           0 : const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
     540             : {
     541           0 :     return pAttrArray->GetPattern( nRow )->GetStyleSheet();
     542             : }
     543             : 
     544             : 
     545           0 : const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
     546             : {
     547           0 :     rFound = false;
     548           0 :     if (!rMark.IsMultiMarked())
     549             :     {
     550             :         OSL_FAIL("ScColumn::GetSelectionStyle ohne Selektion");
     551           0 :         return NULL;
     552             :     }
     553             : 
     554           0 :     bool bEqual = true;
     555             : 
     556           0 :     const ScStyleSheet* pStyle = NULL;
     557             :     const ScStyleSheet* pNewStyle;
     558             : 
     559           0 :     ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     560             :     SCROW nTop;
     561             :     SCROW nBottom;
     562           0 :     while (bEqual && aMarkIter.Next( nTop, nBottom ))
     563             :     {
     564           0 :         ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
     565             :         SCROW nRow;
     566             :         SCROW nDummy;
     567             :         const ScPatternAttr* pPattern;
     568           0 :         while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     569             :         {
     570           0 :             pNewStyle = pPattern->GetStyleSheet();
     571           0 :             rFound = true;
     572           0 :             if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     573           0 :                 bEqual = false;                                             // unterschiedliche
     574           0 :             pStyle = pNewStyle;
     575             :         }
     576             :     }
     577             : 
     578           0 :     return bEqual ? pStyle : NULL;
     579             : }
     580             : 
     581             : 
     582        4096 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
     583             : {
     584        4096 :     rFound = false;
     585             : 
     586        4096 :     bool bEqual = true;
     587             : 
     588        4096 :     const ScStyleSheet* pStyle = NULL;
     589             :     const ScStyleSheet* pNewStyle;
     590             : 
     591        4096 :     ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
     592             :     SCROW nRow;
     593             :     SCROW nDummy;
     594             :     const ScPatternAttr* pPattern;
     595       12288 :     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     596             :     {
     597        4096 :         pNewStyle = pPattern->GetStyleSheet();
     598        4096 :         rFound = true;
     599        4096 :         if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     600           0 :             bEqual = false;                                             // unterschiedliche
     601        4096 :         pStyle = pNewStyle;
     602             :     }
     603             : 
     604        4096 :     return bEqual ? pStyle : NULL;
     605             : }
     606             : 
     607     2400256 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
     608             : {
     609     2400256 :     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
     610     2400256 : }
     611             : 
     612           0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
     613             : {
     614           0 :     return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
     615             : }
     616             : 
     617             : 
     618        3991 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     619             : {
     620        3991 :     return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
     621             : }
     622             : 
     623             : 
     624        3189 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     625             : {
     626        3189 :     return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
     627             : }
     628             : 
     629             : 
     630           2 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
     631             : {
     632           2 :     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
     633           2 : }
     634             : 
     635             : 
     636          51 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
     637             : {
     638          51 :     pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
     639          51 : }
     640             : 
     641             : 
     642           7 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
     643             :                                 const ScPatternAttr& rPatAttr, bool bPutToPool )
     644             : {
     645           7 :     pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
     646           7 : }
     647             : 
     648             : 
     649        1172 : void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
     650             : {
     651             :     //  um nur ein neues SetItem zu erzeugen, brauchen wir keinen SfxItemPoolCache.
     652             :     //! Achtung: der SfxItemPoolCache scheint zuviele Refs fuer das neue SetItem zu erzeugen ??
     653             : 
     654        1172 :     ScDocumentPool* pDocPool = pDocument->GetPool();
     655             : 
     656        1172 :     const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
     657        1172 :     ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
     658        1172 :     pTemp->GetItemSet().Put(rAttr);
     659        1172 :     const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
     660             : 
     661        1172 :     if ( pNewPattern != pOldPattern )
     662        1159 :         pAttrArray->SetPattern( nRow, pNewPattern );
     663             :     else
     664          13 :         pDocPool->Remove( *pNewPattern );       // ausser Spesen nichts gewesen
     665             : 
     666        1172 :     delete pTemp;
     667             : 
     668             :         // alte Version mit SfxItemPoolCache:
     669        1172 : }
     670             : 
     671             : #ifdef _MSC_VER
     672             : #pragma optimize ( "", off )
     673             : #endif
     674             : 
     675             : 
     676      578665 : bool ScColumn::Search( SCROW nRow, SCSIZE& nIndex ) const
     677             : {
     678      578665 :     if ( maItems.empty() )
     679             :     {
     680      554269 :         nIndex = 0;
     681      554269 :         return false;
     682             :     }
     683       24396 :     SCROW nMinRow = maItems[0].nRow;
     684       24396 :     if ( nRow <= nMinRow )
     685             :     {
     686        2741 :         nIndex = 0;
     687        2741 :         return nRow == nMinRow;
     688             :     }
     689       21655 :     SCROW nMaxRow = maItems.back().nRow;
     690       21655 :     if ( nRow >= nMaxRow )
     691             :     {
     692        3933 :         if ( nRow == nMaxRow )
     693             :         {
     694        1578 :             nIndex = maItems.size() - 1;
     695        1578 :             return true;
     696             :         }
     697             :         else
     698             :         {
     699        2355 :             nIndex = maItems.size();
     700        2355 :             return false;
     701             :         }
     702             :     }
     703             : 
     704             :     long nOldLo, nOldHi;
     705       17722 :     long    nLo     = nOldLo = 0;
     706       17722 :     long    nHi     = nOldHi = Min(static_cast<long>(maItems.size())-1, static_cast<long>(nRow) );
     707       17722 :     long    i       = 0;
     708       17722 :     bool    bFound  = false;
     709             :     // quite continuous distribution? => interpolating search
     710       17722 :     bool    bInterpol = (static_cast<SCSIZE>(nMaxRow - nMinRow) < maItems.size() * 2);
     711             :     SCROW   nR;
     712             : 
     713       60085 :     while ( !bFound && nLo <= nHi )
     714             :     {
     715       24641 :         if ( !bInterpol || nHi - nLo < 3 )
     716        5570 :             i = (nLo+nHi) / 2;          // no effort, no division by zero
     717             :         else
     718             :         {   // interpolating search
     719       19071 :             long nLoRow = maItems[nLo].nRow;     // no unsigned underflow upon substraction
     720             :             i = nLo + (long)((long)(nRow - nLoRow) * (nHi - nLo)
     721       19071 :                 / (maItems[nHi].nRow - nLoRow));
     722       19071 :             if ( i < 0 || static_cast<SCSIZE>(i) >= maItems.size() )
     723             :             {   // oops ...
     724           0 :                 i = (nLo+nHi) / 2;
     725           0 :                 bInterpol = false;
     726             :             }
     727             :         }
     728       24641 :         nR = maItems[i].nRow;
     729       24641 :         if ( nR < nRow )
     730             :         {
     731        6107 :             nLo = i+1;
     732        6107 :             if ( bInterpol )
     733             :             {
     734        5342 :                 if ( nLo <= nOldLo )
     735          41 :                     bInterpol = false;
     736             :                 else
     737        5301 :                     nOldLo = nLo;
     738             :             }
     739             :         }
     740             :         else
     741             :         {
     742       18534 :             if ( nR > nRow )
     743             :             {
     744        1522 :                 nHi = i-1;
     745        1522 :                 if ( bInterpol )
     746             :                 {
     747         927 :                     if ( nHi >= nOldHi )
     748           1 :                         bInterpol = false;
     749             :                     else
     750         926 :                         nOldHi = nHi;
     751             :                 }
     752             :             }
     753             :             else
     754       17012 :                 bFound = true;
     755             :         }
     756             :     }
     757       17722 :     if (bFound)
     758       17012 :         nIndex = static_cast<SCSIZE>(i);
     759             :     else
     760         710 :         nIndex = static_cast<SCSIZE>(nLo); // rear index
     761       17722 :     return bFound;
     762             : }
     763             : 
     764             : #ifdef _MSC_VER
     765             : #pragma optimize ( "", on )
     766             : #endif
     767             : 
     768             : 
     769        9349 : ScBaseCell* ScColumn::GetCell( SCROW nRow ) const
     770             : {
     771             :     SCSIZE nIndex;
     772        9349 :     if (Search(nRow, nIndex))
     773        8468 :         return maItems[nIndex].pCell;
     774         881 :     return NULL;
     775             : }
     776             : 
     777             : 
     778         109 : void ScColumn::Resize( SCSIZE nSize )
     779             : {
     780         109 :     if (nSize > sal::static_int_cast<SCSIZE>(MAXROWCOUNT))
     781           0 :         nSize = MAXROWCOUNT;
     782         109 :     if (nSize < maItems.size())
     783           0 :         nSize = maItems.size();
     784             : 
     785         109 :     maItems.reserve(nSize);
     786         109 : }
     787             : 
     788             : //  SwapRow zum Sortieren
     789             : 
     790             : namespace {
     791             : 
     792             : /** Moves broadcaster from old cell to new cell if exists, otherwise creates a new note cell. */
     793           0 : void lclTakeBroadcaster( ScBaseCell*& rpCell, SvtBroadcaster* pBC )
     794             : {
     795           0 :     if( pBC )
     796             :     {
     797           0 :         if( rpCell )
     798           0 :             rpCell->TakeBroadcaster( pBC );
     799             :         else
     800           0 :             rpCell = new ScNoteCell( pBC );
     801             :     }
     802           0 : }
     803             : 
     804             : } // namespace
     805             : 
     806           4 : void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
     807             : {
     808             :     /*  Simple swap of cell pointers does not work if broadcasters exist (crash
     809             :         if cell broadcasts directly or indirectly to itself). While swapping
     810             :         the cells, broadcasters have to remain at old positions! */
     811             : 
     812             :     /*  While cloning cells, do not clone notes, but move note pointers to new
     813             :         cells. This prevents creation of new caption drawing objects for every
     814             :         swap operation while sorting. */
     815             : 
     816           4 :     ScBaseCell* pCell1 = 0;
     817             :     SCSIZE nIndex1;
     818           4 :     if ( Search( nRow1, nIndex1 ) )
     819           4 :         pCell1 = maItems[nIndex1].pCell;
     820             : 
     821           4 :     ScBaseCell* pCell2 = 0;
     822             :     SCSIZE nIndex2;
     823           4 :     if ( Search( nRow2, nIndex2 ) )
     824           4 :         pCell2 = maItems[nIndex2].pCell;
     825             : 
     826             :     // no cells found, nothing to do
     827           4 :     if ( !pCell1 && !pCell2 )
     828             :         return ;
     829             : 
     830             :     // swap variables if first cell is empty, to save some code below
     831           4 :     if ( !pCell1 )
     832             :     {
     833           0 :         ::std::swap( nRow1, nRow2 );
     834           0 :         ::std::swap( nIndex1, nIndex2 );
     835           0 :         ::std::swap( pCell1, pCell2 );
     836             :     }
     837             : 
     838             :     // from here: first cell (pCell1, nIndex1) exists always
     839             : 
     840           4 :     ScAddress aPos1( nCol, nRow1, nTab );
     841           4 :     ScAddress aPos2( nCol, nRow2, nTab );
     842             : 
     843           4 :     CellType eType1 = pCell1->GetCellType();
     844           4 :     CellType eType2 = pCell2 ? pCell2->GetCellType() : CELLTYPE_NONE;
     845             : 
     846           4 :     ScFormulaCell* pFmlaCell1 = (eType1 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
     847           4 :     ScFormulaCell* pFmlaCell2 = (eType2 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;
     848             : 
     849             :     // simple swap if no formula cells present
     850           4 :     if ( !pFmlaCell1 && !pFmlaCell2 )
     851             :     {
     852             :         // remember cell broadcasters, must remain at old position
     853           4 :         SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
     854             : 
     855           4 :         if ( pCell2 )
     856             :         {
     857             :             /*  Both cells exist, no formula cells involved, a simple swap can
     858             :                 be performed (but keep broadcasters and notes at old position). */
     859           4 :             maItems[nIndex1].pCell = pCell2;
     860           4 :             maItems[nIndex2].pCell = pCell1;
     861             : 
     862           4 :             SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster();
     863           4 :             pCell1->TakeBroadcaster( pBC2 );
     864           4 :             pCell2->TakeBroadcaster( pBC1 );
     865             :         }
     866             :         else
     867             :         {
     868           0 :             ScNoteCell* pDummyCell = pBC1 ? new ScNoteCell( pBC1 ) : 0;
     869           0 :             if ( pDummyCell )
     870             :             {
     871             :                 // insert dummy note cell (without note) containing old broadcaster
     872           0 :                 maItems[nIndex1].pCell = pDummyCell;
     873             :             }
     874             :             else
     875             :             {
     876             :                 // remove ColEntry at old position
     877           0 :                 maItems.erase( maItems.begin() + nIndex1 );
     878             :             }
     879             : 
     880             :             // insert ColEntry at new position
     881           0 :             Insert( nRow2, pCell1 );
     882             :         }
     883             : 
     884             :         return;
     885             :     }
     886             : 
     887             :     // from here: at least one of the cells is a formula cell
     888             : 
     889             :     /*  Never move any array formulas. Disabling sort if parts of array
     890             :         formulas are contained is done at UI. */
     891           0 :     if ( (pFmlaCell1 && (pFmlaCell1->GetMatrixFlag() != 0)) || (pFmlaCell2 && (pFmlaCell2->GetMatrixFlag() != 0)) )
     892             :         return;
     893             : 
     894             :     // do not swap, if formulas are equal
     895           0 :     if ( pFmlaCell1 && pFmlaCell2 )
     896             :     {
     897           0 :         ScTokenArray* pCode1 = pFmlaCell1->GetCode();
     898           0 :         ScTokenArray* pCode2 = pFmlaCell2->GetCode();
     899             : 
     900           0 :         if (pCode1->GetLen() == pCode2->GetLen())       // nicht-UPN
     901             :         {
     902           0 :             bool bEqual = true;
     903           0 :             sal_uInt16 nLen = pCode1->GetLen();
     904           0 :             FormulaToken** ppToken1 = pCode1->GetArray();
     905           0 :             FormulaToken** ppToken2 = pCode2->GetArray();
     906           0 :             for (sal_uInt16 i=0; i<nLen; i++)
     907             :             {
     908           0 :                 if ( !ppToken1[i]->TextEqual(*(ppToken2[i])) ||
     909           0 :                         ppToken1[i]->Is3DRef() || ppToken2[i]->Is3DRef() )
     910             :                 {
     911           0 :                     bEqual = false;
     912           0 :                     break;
     913             :                 }
     914             :             }
     915             : 
     916             :             // do not swap formula cells with equal formulas
     917           0 :             if (bEqual)
     918             :             {
     919             :                 return;
     920             :             }
     921             :         }
     922             :     }
     923             : 
     924             :     /*  Create clone of pCell1 at position of pCell2 (pCell1 exists always, see
     925             :         variable swapping above). Do not clone the note, but move pointer of
     926             :         old note to new cell. */
     927           0 :     ScBaseCell* pNew2 = pCell1->Clone( *pDocument, aPos2, SC_CLONECELL_ADJUST3DREL );
     928             : 
     929             :     /*  Create clone of pCell2 at position of pCell1. Do not clone the note,
     930             :         but move pointer of old note to new cell. */
     931           0 :     ScBaseCell* pNew1 = 0;
     932           0 :     if ( pCell2 )
     933             :     {
     934           0 :         pNew1 = pCell2->Clone( *pDocument, aPos1, SC_CLONECELL_ADJUST3DREL );
     935             :     }
     936             : 
     937             :     // move old broadcasters new cells at the same old position
     938           0 :     SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
     939           0 :     lclTakeBroadcaster( pNew1, pBC1 );
     940           0 :     SvtBroadcaster* pBC2 = pCell2 ? pCell2->ReleaseBroadcaster() : 0;
     941           0 :     lclTakeBroadcaster( pNew2, pBC2 );
     942             : 
     943             :     /*  Insert the new cells. Old cell has to be deleted, if there is no new
     944             :         cell (call to Insert deletes old cell by itself). */
     945           0 :     if ( !pNew1 )
     946           0 :         Delete( nRow1 );            // deletes pCell1
     947             :     else
     948           0 :         Insert( nRow1, pNew1 );     // deletes pCell1, inserts pNew1
     949             : 
     950           0 :     if ( pCell2 && !pNew2 )
     951           0 :         Delete( nRow2 );            // deletes pCell2
     952           0 :     else if ( pNew2 )
     953           0 :         Insert( nRow2, pNew2 );     // deletes pCell2 (if existing), inserts pNew2
     954             : }
     955             : 
     956             : 
     957           0 : void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol)
     958             : {
     959           0 :     ScBaseCell* pCell1 = 0;
     960             :     SCSIZE nIndex1;
     961           0 :     if ( Search( nRow, nIndex1 ) )
     962           0 :         pCell1 = maItems[nIndex1].pCell;
     963             : 
     964           0 :     ScBaseCell* pCell2 = 0;
     965             :     SCSIZE nIndex2;
     966           0 :     if ( rCol.Search( nRow, nIndex2 ) )
     967           0 :         pCell2 = rCol.maItems[nIndex2].pCell;
     968             : 
     969             :     // reverse call if own cell is missing (ensures own existing cell in following code)
     970           0 :     if( !pCell1 )
     971             :     {
     972           0 :         if( pCell2 )
     973           0 :             rCol.SwapCell( nRow, *this );
     974           0 :         return;
     975             :     }
     976             : 
     977             :     // from here: own cell (pCell1, nIndex1) exists always
     978             : 
     979           0 :     ScFormulaCell* pFmlaCell1 = (pCell1->GetCellType() == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
     980           0 :     ScFormulaCell* pFmlaCell2 = (pCell2 && (pCell2->GetCellType() == CELLTYPE_FORMULA)) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;
     981             : 
     982           0 :     if ( pCell2 )
     983             :     {
     984             :         // Tauschen
     985           0 :         maItems[nIndex1].pCell = pCell2;
     986           0 :         rCol.maItems[nIndex2].pCell = pCell1;
     987             :         // Referenzen aktualisieren
     988           0 :         SCsCOL dx = rCol.nCol - nCol;
     989           0 :         if ( pFmlaCell1 )
     990             :         {
     991             :             ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
     992           0 :                             ScAddress( rCol.nCol, MAXROW, nTab ) );
     993           0 :             pFmlaCell1->aPos.SetCol( rCol.nCol );
     994           0 :             pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
     995             :         }
     996           0 :         if ( pFmlaCell2 )
     997             :         {
     998             :             ScRange aRange( ScAddress( nCol, 0, nTab ),
     999           0 :                             ScAddress( nCol, MAXROW, nTab ) );
    1000           0 :             pFmlaCell2->aPos.SetCol( nCol );
    1001           0 :             pFmlaCell2->UpdateReference(URM_MOVE, aRange, -dx, 0, 0);
    1002             :         }
    1003             :     }
    1004             :     else
    1005             :     {
    1006             :         // Loeschen
    1007           0 :         maItems.erase(maItems.begin() + nIndex1);
    1008             :         // Referenzen aktualisieren
    1009           0 :         SCsCOL dx = rCol.nCol - nCol;
    1010           0 :         if ( pFmlaCell1 )
    1011             :         {
    1012             :             ScRange aRange( ScAddress( rCol.nCol, 0, nTab ),
    1013           0 :                             ScAddress( rCol.nCol, MAXROW, nTab ) );
    1014           0 :             pFmlaCell1->aPos.SetCol( rCol.nCol );
    1015           0 :             pFmlaCell1->UpdateReference(URM_MOVE, aRange, dx, 0, 0);
    1016             :         }
    1017             :         // Einfuegen
    1018           0 :         rCol.Insert(nRow, pCell1);
    1019             :     }
    1020             : }
    1021             : 
    1022             : 
    1023           2 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
    1024             : {
    1025           2 :     if (!IsEmpty())
    1026             :     {
    1027           0 :         bool bTest = true;
    1028           0 :         if ( !maItems.empty() )
    1029           0 :             for (SCSIZE i=0; (i<maItems.size()) && bTest; i++)
    1030           0 :                 bTest = (maItems[i].nRow < nStartRow) || (maItems[i].nRow > nEndRow)
    1031           0 :                         || maItems[i].pCell->IsBlank();
    1032             : 
    1033             :         //  AttrArray testet nur zusammengefasste
    1034             : 
    1035           0 :         if ((bTest) && (pAttrArray))
    1036           0 :             bTest = pAttrArray->TestInsertCol(nStartRow, nEndRow);
    1037             : 
    1038             :         //!     rausgeschobene Attribute bei Undo beruecksichtigen
    1039             : 
    1040           0 :         return bTest;
    1041             :     }
    1042             :     else
    1043           2 :         return true;
    1044             : }
    1045             : 
    1046             : 
    1047        5121 : bool ScColumn::TestInsertRow( SCSIZE nSize ) const
    1048             : {
    1049             :     //  AttrArray only looks for merged cells
    1050             : 
    1051        5121 :     if ( !maItems.empty() )
    1052           1 :         return ( nSize <= sal::static_int_cast<SCSIZE>(MAXROW) &&
    1053           1 :                  maItems[maItems.size()-1].nRow <= MAXROW-(SCROW)nSize && pAttrArray->TestInsertRow( nSize ) );
    1054             :     else
    1055        5120 :         return pAttrArray->TestInsertRow( nSize );
    1056             : }
    1057             : 
    1058             : 
    1059        5121 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
    1060             : {
    1061        5121 :     pAttrArray->InsertRow( nStartRow, nSize );
    1062             : 
    1063             :     //! Search
    1064             : 
    1065        5121 :     if ( maItems.empty() )
    1066             :         return;
    1067             : 
    1068             :     SCSIZE i;
    1069           1 :     Search( nStartRow, i );
    1070           1 :     if ( i >= maItems.size() )
    1071             :         return ;
    1072             : 
    1073           1 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1074           1 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1075             : 
    1076           1 :     SCSIZE nNewCount = maItems.size();
    1077           1 :     bool bCountChanged = false;
    1078           1 :     ScAddress aAdr( nCol, 0, nTab );
    1079           1 :     ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL );    // only areas (ScBaseCell* == NULL)
    1080           1 :     ScAddress& rAddress = aHint.GetAddress();
    1081             :     // for sparse occupation use single broadcasts, not ranges
    1082           2 :     bool bSingleBroadcasts = (((maItems.back().nRow - maItems[i].nRow) /
    1083           2 :                 (maItems.size() - i)) > 1);
    1084           1 :     if ( bSingleBroadcasts )
    1085             :     {
    1086           0 :         SCROW nLastBroadcast = MAXROW+1;
    1087           0 :         for ( ; i < maItems.size(); i++)
    1088             :         {
    1089           0 :             SCROW nOldRow = maItems[i].nRow;
    1090             :             // Change source broadcaster
    1091           0 :             if ( nLastBroadcast != nOldRow )
    1092             :             {   // Do not broadcast a direct sequence twice
    1093           0 :                 rAddress.SetRow( nOldRow );
    1094           0 :                 pDocument->AreaBroadcast( aHint );
    1095             :             }
    1096           0 :             SCROW nNewRow = (maItems[i].nRow += nSize);
    1097             :             // Change target broadcaster
    1098           0 :             rAddress.SetRow( nNewRow );
    1099           0 :             pDocument->AreaBroadcast( aHint );
    1100           0 :             nLastBroadcast = nNewRow;
    1101           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1102           0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1103           0 :                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
    1104           0 :             if ( nNewRow > MAXROW && !bCountChanged )
    1105             :             {
    1106           0 :                 nNewCount = i;
    1107           0 :                 bCountChanged = true;
    1108             :             }
    1109             :         }
    1110             :     }
    1111             :     else
    1112             :     {
    1113           1 :         rAddress.SetRow( maItems[i].nRow );
    1114           1 :         ScRange aRange( rAddress );
    1115           2 :         for ( ; i < maItems.size(); i++)
    1116             :         {
    1117           1 :             SCROW nNewRow = (maItems[i].nRow += nSize);
    1118           1 :             ScBaseCell* pCell = maItems[i].pCell;
    1119           1 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1120           0 :                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
    1121           1 :             if ( nNewRow > MAXROW && !bCountChanged )
    1122             :             {
    1123           0 :                 nNewCount = i;
    1124           0 :                 bCountChanged = true;
    1125           0 :                 aRange.aEnd.SetRow( MAXROW );
    1126             :             }
    1127             :         }
    1128           1 :         if ( !bCountChanged )
    1129           1 :             aRange.aEnd.SetRow( maItems.back().nRow );
    1130           1 :         pDocument->AreaBroadcastInRange( aRange, aHint );
    1131             :     }
    1132             : 
    1133           1 :     if (bCountChanged)
    1134             :     {
    1135           0 :         SCSIZE nDelCount = maItems.size() - nNewCount;
    1136           0 :         ScBaseCell** ppDelCells = new ScBaseCell*[nDelCount];
    1137           0 :         SCROW* pDelRows = new SCROW[nDelCount];
    1138           0 :         for (i = 0; i < nDelCount; i++)
    1139             :         {
    1140           0 :             ppDelCells[i] = maItems[nNewCount+i].pCell;
    1141           0 :             pDelRows[i] = maItems[nNewCount+i].nRow;
    1142             :         }
    1143           0 :         maItems.resize( nNewCount );
    1144             : 
    1145           0 :         for (i = 0; i < nDelCount; i++)
    1146             :         {
    1147           0 :             ScBaseCell* pCell = ppDelCells[i];
    1148             :             OSL_ENSURE( pCell->IsBlank(), "sichtbare Zelle weggeschoben" );
    1149           0 :             SvtBroadcaster* pBC = pCell->GetBroadcaster();
    1150           0 :             if (pBC)
    1151             :             {
    1152           0 :                 MoveListeners( *pBC, pDelRows[i] - nSize );
    1153           0 :                 pCell->DeleteBroadcaster();
    1154           0 :                 pCell->Delete();
    1155             :             }
    1156             :         }
    1157             : 
    1158           0 :         delete [] pDelRows;
    1159           0 :         delete [] ppDelCells;
    1160             :     }
    1161             : 
    1162           1 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1163             : }
    1164             : 
    1165             : 
    1166           5 : void ScColumn::CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, bool bKeepScenarioFlags) const
    1167             : {
    1168             :     pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
    1169           5 :                             bKeepScenarioFlags ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
    1170             : 
    1171             :     SCSIZE i;
    1172           5 :     SCSIZE nBlockCount = 0;
    1173           5 :     SCSIZE nStartIndex = 0, nEndIndex = 0;
    1174          19 :     for (i = 0; i < maItems.size(); i++)
    1175          14 :         if ((maItems[i].nRow >= nRow1) && (maItems[i].nRow <= nRow2))
    1176             :         {
    1177          14 :             if (!nBlockCount)
    1178           5 :                 nStartIndex = i;
    1179          14 :             nEndIndex = i;
    1180          14 :             ++nBlockCount;
    1181             : 
    1182             :             //  im Clipboard muessen interpretierte Zellen stehen, um andere Formate
    1183             :             //  (Text, Grafik...) erzueugen zu koennen
    1184             : 
    1185          14 :             if ( maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
    1186             :             {
    1187          12 :                 ScFormulaCell* pFCell = (ScFormulaCell*) maItems[i].pCell;
    1188          12 :                 if (pFCell->GetDirty() && pDocument->GetAutoCalc())
    1189           9 :                     pFCell->Interpret();
    1190             :             }
    1191             :         }
    1192             : 
    1193           5 :     if (nBlockCount)
    1194             :     {
    1195           5 :         rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
    1196           5 :         ScAddress aOwnPos( nCol, 0, nTab );
    1197           5 :         ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
    1198          19 :         for (i = nStartIndex; i <= nEndIndex; i++)
    1199             :         {
    1200          14 :             aOwnPos.SetRow( maItems[i].nRow );
    1201          14 :             aDestPos.SetRow( maItems[i].nRow );
    1202          14 :             ScBaseCell* pNewCell = maItems[i].pCell->Clone( *rColumn.pDocument, aDestPos, SC_CLONECELL_DEFAULT );
    1203          14 :             rColumn.Append( aDestPos.Row(), pNewCell );
    1204             :         }
    1205             :     }
    1206           5 : }
    1207             : 
    1208             : 
    1209        5143 : void ScColumn::CopyToColumn(
    1210             :     SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
    1211             :     const ScMarkData* pMarkData, bool bAsLink) const
    1212             : {
    1213        5143 :     if (bMarked)
    1214             :     {
    1215             :         SCROW nStart, nEnd;
    1216           0 :         if (pMarkData && pMarkData->IsMultiMarked())
    1217             :         {
    1218           0 :             ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
    1219             : 
    1220           0 :             while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
    1221             :             {
    1222           0 :                 if ( nEnd >= nRow1 )
    1223             :                     CopyToColumn( Max(nRow1,nStart), Min(nRow2,nEnd),
    1224           0 :                                     nFlags, false, rColumn, pMarkData, bAsLink );
    1225           0 :             }
    1226             :         }
    1227             :         else
    1228             :         {
    1229             :             OSL_FAIL("CopyToColumn: bMarked, aber keine Markierung");
    1230             :         }
    1231        5143 :         return;
    1232             :     }
    1233             : 
    1234        5143 :     if ( (nFlags & IDF_ATTRIB) != 0 )
    1235             :     {
    1236        3089 :         if ( (nFlags & IDF_STYLES) != IDF_STYLES )
    1237             :         {   // StyleSheets im Zieldokument bleiben erhalten
    1238             :             // z.B. DIF und RTF Clipboard-Import
    1239           0 :             for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
    1240             :             {
    1241             :                 const ScStyleSheet* pStyle =
    1242           0 :                     rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
    1243           0 :                 const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
    1244           0 :                 ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
    1245           0 :                 pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
    1246           0 :                 rColumn.pAttrArray->SetPattern( nRow, pNewPattern, true );
    1247           0 :                 delete pNewPattern;
    1248             :             }
    1249             :         }
    1250             :         else
    1251        3089 :             pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
    1252             :     }
    1253             : 
    1254             : 
    1255        5143 :     if ((nFlags & IDF_CONTENTS) != 0)
    1256             :     {
    1257             :         SCSIZE i;
    1258        5138 :         SCSIZE nBlockCount = 0;
    1259        5138 :         SCSIZE nStartIndex = 0, nEndIndex = 0;
    1260        5150 :         for (i = 0; i < maItems.size(); i++)
    1261          12 :             if ((maItems[i].nRow >= nRow1) && (maItems[i].nRow <= nRow2))
    1262             :             {
    1263           6 :                 if (!nBlockCount)
    1264           6 :                     nStartIndex = i;
    1265           6 :                 nEndIndex = i;
    1266           6 :                 ++nBlockCount;
    1267             :             }
    1268             : 
    1269        5138 :         if (nBlockCount)
    1270             :         {
    1271           6 :             rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
    1272           6 :             ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
    1273          12 :             for (i = nStartIndex; i <= nEndIndex; i++)
    1274             :             {
    1275           6 :                 aDestPos.SetRow( maItems[i].nRow );
    1276             :                 ScBaseCell* pNew = bAsLink ?
    1277           0 :                     CreateRefCell( rColumn.pDocument, aDestPos, i, nFlags ) :
    1278           6 :                     CloneCell( i, nFlags, *rColumn.pDocument, aDestPos );
    1279             : 
    1280           6 :                 if (pNew)
    1281             :                 {
    1282             :                     // Special case to allow removing of cell instances.  A
    1283             :                     // string cell with empty content is used to indicate an
    1284             :                     // empty cell.
    1285           6 :                     if (pNew->GetCellType() == CELLTYPE_STRING)
    1286             :                     {
    1287           2 :                         rtl::OUString aStr = static_cast<ScStringCell*>(pNew)->GetString();
    1288           2 :                         if (aStr.isEmpty())
    1289             :                             // A string cell with empty string.  Delete the cell itself.
    1290           0 :                             rColumn.Delete(maItems[i].nRow);
    1291             :                         else
    1292             :                             // non-empty string cell
    1293           2 :                             rColumn.Insert(maItems[i].nRow, pNew);
    1294             :                     }
    1295             :                     else
    1296           4 :                         rColumn.Insert(maItems[i].nRow, pNew);
    1297             :                 }
    1298             :             }
    1299             :         }
    1300             :     }
    1301             : }
    1302             : 
    1303             : 
    1304           6 : void ScColumn::UndoToColumn(
    1305             :     SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
    1306             :     const ScMarkData* pMarkData) const
    1307             : {
    1308           6 :     if (nRow1 > 0)
    1309           6 :         CopyToColumn( 0, nRow1-1, IDF_FORMULA, false, rColumn );
    1310             : 
    1311           6 :     CopyToColumn( nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData );      //! bMarked ????
    1312             : 
    1313           6 :     if (nRow2 < MAXROW)
    1314           6 :         CopyToColumn( nRow2+1, MAXROW, IDF_FORMULA, false, rColumn );
    1315           6 : }
    1316             : 
    1317             : 
    1318           0 : void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
    1319             : {
    1320           0 :     ScDocument& rDestDoc = *rDestCol.pDocument;
    1321           0 :     ScAddress aOwnPos( nCol, 0, nTab );
    1322           0 :     ScAddress aDestPos( rDestCol.nCol, 0, rDestCol.nTab );
    1323             : 
    1324           0 :     SCSIZE nPosCount = rPosCol.maItems.size();
    1325           0 :     for (SCSIZE nPosIndex = 0; nPosIndex < nPosCount; nPosIndex++)
    1326             :     {
    1327           0 :         aOwnPos.SetRow( rPosCol.maItems[nPosIndex].nRow );
    1328           0 :         aDestPos.SetRow( aOwnPos.Row() );
    1329             :         SCSIZE nThisIndex;
    1330           0 :         if ( Search( aDestPos.Row(), nThisIndex ) )
    1331             :         {
    1332           0 :             ScBaseCell* pNew = maItems[nThisIndex].pCell->Clone( rDestDoc, aDestPos );
    1333           0 :             rDestCol.Insert( aDestPos.Row(), pNew );
    1334             :         }
    1335             :     }
    1336             : 
    1337           0 : }
    1338             : 
    1339             : 
    1340           0 : void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
    1341             : {
    1342             :     //  Dies ist die Szenario-Tabelle, die Daten werden hineinkopiert
    1343             : 
    1344           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1345           0 :     SCROW nStart = -1, nEnd = -1;
    1346           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1347           0 :     while (pPattern)
    1348             :     {
    1349           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1350             :         {
    1351           0 :             DeleteArea( nStart, nEnd, IDF_CONTENTS );
    1352             :             ((ScColumn&)rSrcCol).
    1353           0 :                 CopyToColumn( nStart, nEnd, IDF_CONTENTS, false, *this );
    1354             : 
    1355             :             //  UpdateUsed nicht noetig, schon in TestCopyScenario passiert
    1356             : 
    1357           0 :             SCsTAB nDz = nTab - rSrcCol.nTab;
    1358             :             UpdateReference(URM_COPY, nCol, nStart, nTab,
    1359             :                                       nCol, nEnd,   nTab,
    1360           0 :                                       0, 0, nDz, NULL);
    1361           0 :             UpdateCompile();
    1362             :         }
    1363             : 
    1364             :         //! CopyToColumn "const" machen !!!
    1365             : 
    1366           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1367             :     }
    1368           0 : }
    1369             : 
    1370             : 
    1371           0 : void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
    1372             : {
    1373             :     //  Dies ist die Szenario-Tabelle, die Daten werden in die andere kopiert
    1374             : 
    1375           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1376           0 :     SCROW nStart = -1, nEnd = -1;
    1377           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1378           0 :     while (pPattern)
    1379             :     {
    1380           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1381             :         {
    1382           0 :             rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
    1383             :             ((ScColumn*)this)->
    1384           0 :                 CopyToColumn( nStart, nEnd, IDF_CONTENTS, false, rDestCol );
    1385             : 
    1386             :             //  UpdateUsed nicht noetig, schon in TestCopyScenario passiert
    1387             : 
    1388           0 :             SCsTAB nDz = rDestCol.nTab - nTab;
    1389             :             rDestCol.UpdateReference(URM_COPY, rDestCol.nCol, nStart, rDestCol.nTab,
    1390             :                                                rDestCol.nCol, nEnd,   rDestCol.nTab,
    1391           0 :                                                0, 0, nDz, NULL);
    1392           0 :             rDestCol.UpdateCompile();
    1393             :         }
    1394             : 
    1395             :         //! CopyToColumn "const" machen !!!
    1396             : 
    1397           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1398             :     }
    1399           0 : }
    1400             : 
    1401             : 
    1402           0 : bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
    1403             : {
    1404           0 :     bool bOk = true;
    1405           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1406           0 :     SCROW nStart = 0, nEnd = 0;
    1407           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1408           0 :     while (pPattern && bOk)
    1409             :     {
    1410           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1411           0 :             if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
    1412           0 :                 bOk = false;
    1413             : 
    1414           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1415             :     }
    1416           0 :     return bOk;
    1417             : }
    1418             : 
    1419             : 
    1420           0 : void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
    1421             : {
    1422           0 :     ScRange aRange( nCol, 0, nTab );
    1423             : 
    1424           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1425           0 :     SCROW nStart = -1, nEnd = -1;
    1426           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1427           0 :     while (pPattern)
    1428             :     {
    1429           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1430             :         {
    1431           0 :             aRange.aStart.SetRow( nStart );
    1432           0 :             aRange.aEnd.SetRow( nEnd );
    1433           0 :             rDestMark.SetMultiMarkArea( aRange, true );
    1434             :         }
    1435             : 
    1436           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1437             :     }
    1438           0 : }
    1439             : 
    1440             : 
    1441        3065 : void ScColumn::SwapCol(ScColumn& rCol)
    1442             : {
    1443        3065 :     maItems.swap(rCol.maItems);
    1444             : 
    1445        3065 :     ScAttrArray* pTempAttr = rCol.pAttrArray;
    1446        3065 :     rCol.pAttrArray = pAttrArray;
    1447        3065 :     pAttrArray = pTempAttr;
    1448             : 
    1449             :     // AttrArray muss richtige Spaltennummer haben
    1450        3065 :     pAttrArray->SetCol(nCol);
    1451        3065 :     rCol.pAttrArray->SetCol(rCol.nCol);
    1452             : 
    1453             :     SCSIZE i;
    1454        3065 :     for (i = 0; i < maItems.size(); i++)
    1455             :     {
    1456           0 :         ScFormulaCell* pCell = (ScFormulaCell*) maItems[i].pCell;
    1457           0 :         if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1458           0 :             pCell->aPos.SetCol(nCol);
    1459             :     }
    1460        3065 :     for (i = 0; i < rCol.maItems.size(); i++)
    1461             :     {
    1462           0 :         ScFormulaCell* pCell = (ScFormulaCell*) rCol.maItems[i].pCell;
    1463           0 :         if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1464           0 :             pCell->aPos.SetCol(rCol.nCol);
    1465             :     }
    1466        3065 : }
    1467             : 
    1468        2040 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
    1469             : {
    1470        2040 :     pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
    1471             : 
    1472        2040 :     if (maItems.empty())
    1473             :         // No cells to move.
    1474        2040 :         return;
    1475             : 
    1476           2 :     ::std::vector<SCROW> aRows;
    1477             :     SCSIZE i;
    1478           2 :     Search( nStartRow, i);  // i points to start row or position thereafter
    1479           2 :     SCSIZE nStartPos = i;
    1480             :     // First, copy the cell instances to the new column.
    1481           4 :     for ( ; i < maItems.size() && maItems[i].nRow <= nEndRow; ++i)
    1482             :     {
    1483           2 :         SCROW nRow = maItems[i].nRow;
    1484           2 :         aRows.push_back( nRow);
    1485           2 :         rCol.Insert( nRow, maItems[i].pCell);
    1486             :     }
    1487           2 :     SCSIZE nStopPos = i;
    1488           2 :     if (nStartPos < nStopPos)
    1489             :     {
    1490             :         // Create list of ranges of cell entry positions
    1491             :         typedef ::std::pair<SCSIZE,SCSIZE> PosPair;
    1492             :         typedef ::std::vector<PosPair> EntryPosPairs;
    1493           2 :         EntryPosPairs aEntries;
    1494             :         {
    1495           2 :             bool bFirst = true;
    1496           2 :             nStopPos = 0;
    1497          18 :             for (::std::vector<SCROW>::const_iterator it( aRows.begin());
    1498          14 :                     it != aRows.end() && nStopPos < maItems.size(); ++it,
    1499             :                     ++nStopPos)
    1500             :             {
    1501           2 :                 if (!bFirst && *it != maItems[nStopPos].nRow)
    1502             :                 {
    1503           0 :                     aEntries.push_back( PosPair(nStartPos, nStopPos));
    1504           0 :                     bFirst = true;
    1505             :                 }
    1506           2 :                 if (bFirst && Search( *it, nStartPos))
    1507             :                 {
    1508           2 :                     bFirst = false;
    1509           2 :                     nStopPos = nStartPos;
    1510             :                 }
    1511             :             }
    1512           2 :             if (!bFirst && nStartPos < nStopPos)
    1513           2 :                 aEntries.push_back( PosPair(nStartPos, nStopPos));
    1514             :         }
    1515             :         // Broadcast changes
    1516           2 :         ScAddress aAdr( nCol, 0, nTab );
    1517           2 :         ScHint aHint( SC_HINT_DYING, aAdr, NULL );  // areas only
    1518           2 :         ScAddress& rAddress = aHint.GetAddress();
    1519           2 :         ScNoteCell* pNoteCell = new ScNoteCell;     // Dummy like in DeleteRange
    1520             : 
    1521             :         // must iterate backwards, because indexes of following cells become invalid
    1522          12 :         for (EntryPosPairs::reverse_iterator it( aEntries.rbegin());
    1523           8 :                 it != aEntries.rend(); ++it)
    1524             :         {
    1525           2 :             nStartPos = (*it).first;
    1526           2 :             nStopPos = (*it).second;
    1527           4 :             for (i=nStartPos; i<nStopPos; ++i)
    1528           2 :                 maItems[i].pCell = pNoteCell; // Assign the dumpy cell instance to all slots.
    1529           4 :             for (i=nStartPos; i<nStopPos; ++i)
    1530             :             {
    1531           2 :                 rAddress.SetRow( maItems[i].nRow );
    1532           2 :                 pDocument->AreaBroadcast( aHint );
    1533             :             }
    1534             :             // Erase the slots containing pointers to the dummy cell instance.
    1535           2 :             maItems.erase(maItems.begin() + nStartPos, maItems.begin() + nStopPos);
    1536             :         }
    1537           2 :         pNoteCell->Delete(); // Delete the dummy cell instance.
    1538           2 :     }
    1539             : }
    1540             : 
    1541       22533 : bool ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
    1542             :              SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
    1543             :              ScDocument* pUndoDoc )
    1544             : {
    1545       22533 :     bool bUpdated = false;
    1546       22533 :     if ( !maItems.empty() )
    1547             :     {
    1548             :         ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
    1549          11 :                         ScAddress( nCol2, nRow2, nTab2 ) );
    1550          11 :         if ( eUpdateRefMode == URM_COPY && nRow1 == nRow2 )
    1551             :         {   // z.B. eine einzelne Zelle aus dem Clipboard eingefuegt
    1552             :             SCSIZE nIndex;
    1553           3 :             if ( Search( nRow1, nIndex ) )
    1554             :             {
    1555           3 :                 ScFormulaCell* pCell = (ScFormulaCell*) maItems[nIndex].pCell;
    1556           3 :                 if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1557             :                     bUpdated |= pCell->UpdateReference(
    1558           1 :                         eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
    1559           3 :             }
    1560             :         }
    1561             :         else
    1562             :         {
    1563             :             // For performance reasons two loop bodies instead of
    1564             :             // testing for update mode in each iteration.
    1565             :             // Anyways, this is still a bottleneck on large arrays with few
    1566             :             // formulas cells.
    1567           8 :             if ( eUpdateRefMode == URM_COPY )
    1568             :             {
    1569             :                 SCSIZE i;
    1570           2 :                 Search( nRow1, i );
    1571          13 :                 for ( ; i < maItems.size(); i++ )
    1572             :                 {
    1573          11 :                     SCROW nRow = maItems[i].nRow;
    1574          11 :                     if ( nRow > nRow2 )
    1575           0 :                         break;
    1576          11 :                     ScBaseCell* pCell = maItems[i].pCell;
    1577          11 :                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1578             :                     {
    1579             :                         bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
    1580          11 :                             eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
    1581          11 :                         if ( nRow != maItems[i].nRow )
    1582           0 :                             Search( nRow, i );  // Listener removed/inserted?
    1583             :                     }
    1584             :                 }
    1585             :             }
    1586             :             else
    1587             :             {
    1588           6 :                 SCSIZE i = 0;
    1589          14 :                 for ( ; i < maItems.size(); i++ )
    1590             :                 {
    1591           8 :                     ScBaseCell* pCell = maItems[i].pCell;
    1592           8 :                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1593             :                     {
    1594           4 :                         SCROW nRow = maItems[i].nRow;
    1595             :                         // When deleting rows on several sheets, the formula's position may be updated with the first call,
    1596             :                         // so the undo position must be passed from here.
    1597           4 :                         ScAddress aUndoPos( nCol, nRow, nTab );
    1598             :                         bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
    1599           4 :                             eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
    1600           4 :                         if ( nRow != maItems[i].nRow )
    1601           0 :                             Search( nRow, i );  // Listener removed/inserted?
    1602             :                     }
    1603             :                 }
    1604             :             }
    1605             :         }
    1606             :     }
    1607       22533 :     return bUpdated;
    1608             : }
    1609             : 
    1610             : 
    1611           0 : void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
    1612             :                                     ScDocument* pUndoDoc )
    1613             : {
    1614           0 :     if ( !maItems.empty() )
    1615           0 :         for (SCSIZE i=0; i<maItems.size(); i++)
    1616             :         {
    1617           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1618           0 :             if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1619             :             {
    1620           0 :                 SCROW nRow = maItems[i].nRow;
    1621           0 :                 ((ScFormulaCell*)pCell)->UpdateTranspose( rSource, rDest, pUndoDoc );
    1622           0 :                 if ( nRow != maItems[i].nRow )
    1623           0 :                     Search( nRow, i );              // Listener geloescht/eingefuegt?
    1624             :             }
    1625             :         }
    1626           0 : }
    1627             : 
    1628             : 
    1629           0 : void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
    1630             : {
    1631           0 :     if ( !maItems.empty() )
    1632           0 :         for (SCSIZE i=0; i<maItems.size(); i++)
    1633             :         {
    1634           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1635           0 :             if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1636             :             {
    1637           0 :                 SCROW nRow = maItems[i].nRow;
    1638           0 :                 ((ScFormulaCell*)pCell)->UpdateGrow( rArea, nGrowX, nGrowY );
    1639           0 :                 if ( nRow != maItems[i].nRow )
    1640           0 :                     Search( nRow, i );              // Listener geloescht/eingefuegt?
    1641             :             }
    1642             :         }
    1643           0 : }
    1644             : 
    1645             : 
    1646       24576 : void ScColumn::UpdateInsertTab(SCTAB nInsPos, SCTAB nNewSheets)
    1647             : {
    1648       24576 :     if (nTab >= nInsPos)
    1649             :     {
    1650       17408 :         nTab += nNewSheets;
    1651       17408 :         pAttrArray->SetTab(nTab);
    1652             :     }
    1653             : 
    1654       24576 :     UpdateInsertTabOnlyCells(nInsPos, nNewSheets);
    1655       24576 : }
    1656             : 
    1657       24576 : void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
    1658             : {
    1659       24576 :     if (maItems.empty())
    1660       49140 :         return;
    1661             : 
    1662          27 :     for (size_t i = 0; i < maItems.size(); ++i)
    1663             :     {
    1664          15 :         switch (maItems[i].pCell->GetCellType())
    1665             :         {
    1666             :             case CELLTYPE_FORMULA:
    1667             :             {
    1668           6 :                 SCROW nRow = maItems[i].nRow;
    1669           6 :                 ScFormulaCell* p = static_cast<ScFormulaCell*>(maItems[i].pCell);
    1670           6 :                 p->UpdateInsertTab(nInsPos, nNewSheets);
    1671           6 :                 if (nRow != maItems[i].nRow)
    1672           0 :                     Search(nRow, i);      // Listener deleted/inserted?
    1673             :             }
    1674           6 :             break;
    1675             :             case CELLTYPE_EDIT:
    1676             :             {
    1677           0 :                 ScEditCell* p = static_cast<ScEditCell*>(maItems[i].pCell);
    1678           0 :                 p->UpdateFields(nTab);
    1679             :             }
    1680           0 :             break;
    1681             :             default:
    1682             :                 ;
    1683             :         }
    1684             :     }
    1685             : }
    1686             : 
    1687        3072 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
    1688             : {
    1689        3072 :     if (maItems.empty())
    1690        6144 :         return;
    1691             : 
    1692           0 :     for (size_t i = 0; i < maItems.size(); ++i)
    1693             :     {
    1694           0 :         switch (maItems[i].pCell->GetCellType())
    1695             :         {
    1696             :             case CELLTYPE_FORMULA:
    1697             :             {
    1698           0 :                 SCROW nRow = maItems[i].nRow;
    1699           0 :                 ScFormulaCell* p = static_cast<ScFormulaCell*>(maItems[i].pCell);
    1700           0 :                 p->UpdateInsertTabAbs(nNewPos);
    1701           0 :                 if (nRow != maItems[i].nRow)
    1702           0 :                     Search(nRow, i);      // Listener deleted/inserted?
    1703             :             }
    1704           0 :             break;
    1705             :             case CELLTYPE_EDIT:
    1706             :             {
    1707           0 :                 ScEditCell* p = static_cast<ScEditCell*>(maItems[i].pCell);
    1708           0 :                 p->UpdateFields(nTab);
    1709             :             }
    1710           0 :             break;
    1711             :             default:
    1712             :                 ;
    1713             :         }
    1714             :     }
    1715             : }
    1716             : 
    1717       80896 : void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* pRefUndo, SCTAB nSheets)
    1718             : {
    1719       80896 :     if (nTab > nDelPos)
    1720             :     {
    1721       13312 :         nTab -= nSheets;
    1722       13312 :         pAttrArray->SetTab(nTab);
    1723             :     }
    1724             : 
    1725       80896 :     if (maItems.empty())
    1726      161679 :         return;
    1727             : 
    1728         712 :     for (size_t i = 0; i < maItems.size(); ++i)
    1729             :     {
    1730         599 :         switch (maItems[i].pCell->GetCellType())
    1731             :         {
    1732             :             case CELLTYPE_FORMULA:
    1733             :             {
    1734          55 :                 SCROW nRow = maItems[i].nRow;
    1735          55 :                 ScFormulaCell* pOld = static_cast<ScFormulaCell*>(maItems[i].pCell);
    1736             : 
    1737             :                 /*  Do not copy cell note to the undo document. Undo will copy
    1738             :                     back the formula cell while keeping the original note. */
    1739          55 :                 ScBaseCell* pSave = pRefUndo ? pOld->Clone( *pDocument ) : 0;
    1740             : 
    1741          55 :                 bool bChanged = pOld->UpdateDeleteTab(nDelPos, bIsMove, nSheets);
    1742          55 :                 if ( nRow != maItems[i].nRow )
    1743           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    1744             : 
    1745          55 :                 if (pRefUndo)
    1746             :                 {
    1747           0 :                     if (bChanged)
    1748           0 :                         pRefUndo->Insert( nRow, pSave );
    1749           0 :                     else if(pSave)
    1750           0 :                         pSave->Delete();
    1751             :                 }
    1752             :             }
    1753          55 :             break;
    1754             :             case CELLTYPE_EDIT:
    1755             :             {
    1756           0 :                 ScEditCell* p = static_cast<ScEditCell*>(maItems[i].pCell);
    1757           0 :                 p->UpdateFields(nTab);
    1758             :             }
    1759           0 :             break;
    1760             :             default:
    1761             :                 ;
    1762             :         }
    1763             :     }
    1764             : }
    1765             : 
    1766       10240 : void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
    1767             : {
    1768       10240 :     nTab = nTabNo;
    1769       10240 :     pAttrArray->SetTab( nTabNo );
    1770       10240 :     if (maItems.empty())
    1771       20464 :         return;
    1772             : 
    1773         118 :     for (size_t i = 0; i < maItems.size(); ++i)
    1774             :     {
    1775         102 :         switch (maItems[i].pCell->GetCellType())
    1776             :         {
    1777             :             case CELLTYPE_FORMULA:
    1778             :             {
    1779           0 :                 ScFormulaCell* p = static_cast<ScFormulaCell*>(maItems[i].pCell);
    1780           0 :                 SCROW nRow = maItems[i].nRow;
    1781           0 :                 p->UpdateMoveTab(nOldPos, nNewPos, nTabNo);
    1782           0 :                 if (nRow != maItems[i].nRow)
    1783           0 :                     Search(nRow, i);      // Listener deleted/inserted?
    1784             :             }
    1785           0 :             break;
    1786             :             case CELLTYPE_EDIT:
    1787             :             {
    1788           0 :                 ScEditCell* p = static_cast<ScEditCell*>(maItems[i].pCell);
    1789           0 :                 p->UpdateFields(nTab);
    1790             :             }
    1791           0 :             break;
    1792             :             default:
    1793             :                 ;
    1794             :         }
    1795             :     }
    1796             : }
    1797             : 
    1798             : 
    1799       97280 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
    1800             : {
    1801       97280 :     if ( !maItems.empty() )
    1802         603 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1803             :         {
    1804         509 :             ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1805         509 :             if( p->GetCellType() == CELLTYPE_FORMULA )
    1806             :             {
    1807          53 :                 SCROW nRow = maItems[i].nRow;
    1808          53 :                 p->UpdateCompile( bForceIfNameInUse );
    1809          53 :                 if ( nRow != maItems[i].nRow )
    1810           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    1811             :             }
    1812             :         }
    1813       97280 : }
    1814             : 
    1815             : 
    1816           0 : void ScColumn::SetTabNo(SCTAB nNewTab)
    1817             : {
    1818           0 :     nTab = nNewTab;
    1819           0 :     pAttrArray->SetTab( nNewTab );
    1820           0 :     if ( !maItems.empty() )
    1821           0 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1822             :         {
    1823           0 :             ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1824           0 :             if( p->GetCellType() == CELLTYPE_FORMULA )
    1825           0 :                 p->aPos.SetTab( nNewTab );
    1826             :         }
    1827           0 : }
    1828             : 
    1829           3 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
    1830             : {
    1831           3 :     if ( !maItems.empty() )
    1832           6 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1833           9 :             if ((maItems[i].nRow >= nRow1) &&
    1834           3 :                 (maItems[i].nRow <= nRow2) &&
    1835           3 :                 (maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
    1836           1 :                     ((ScFormulaCell*)maItems[i].pCell)->FindRangeNamesInUse(rIndexes);
    1837           3 : }
    1838             : 
    1839       94208 : void ScColumn::SetDirtyVar()
    1840             : {
    1841       97290 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1842             :     {
    1843        3082 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1844        3082 :         if( p->GetCellType() == CELLTYPE_FORMULA )
    1845         566 :             p->SetDirtyVar();
    1846             :     }
    1847       94208 : }
    1848             : 
    1849             : 
    1850      254976 : void ScColumn::SetDirty()
    1851             : {
    1852             :     // wird nur dokumentweit verwendet, kein FormulaTrack
    1853      254976 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1854      254976 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1855      258103 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1856             :     {
    1857        3127 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1858        3127 :         if( p->GetCellType() == CELLTYPE_FORMULA )
    1859             :         {
    1860          56 :             p->SetDirtyVar();
    1861          56 :             if ( !pDocument->IsInFormulaTree( p ) )
    1862          46 :                 pDocument->PutInFormulaTree( p );
    1863             :         }
    1864             :     }
    1865      254976 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1866      254976 : }
    1867             : 
    1868             : 
    1869           0 : void ScColumn::SetDirty( const ScRange& rRange )
    1870             : {   // broadcastet alles innerhalb eines Range, mit FormulaTrack
    1871           0 :     if ( maItems.empty() )
    1872           0 :         return ;
    1873           0 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1874           0 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1875           0 :     SCROW nRow2 = rRange.aEnd.Row();
    1876           0 :     ScAddress aPos( nCol, 0, nTab );
    1877           0 :     ScHint aHint( SC_HINT_DATACHANGED, aPos, NULL );
    1878             :     SCROW nRow;
    1879             :     SCSIZE nIndex;
    1880           0 :     Search( rRange.aStart.Row(), nIndex );
    1881           0 :     while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRow2 )
    1882             :     {
    1883           0 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1884           0 :         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1885           0 :             ((ScFormulaCell*)pCell)->SetDirty();
    1886             :         else
    1887             :         {
    1888           0 :             aHint.GetAddress().SetRow( nRow );
    1889           0 :             aHint.SetCell( pCell );
    1890           0 :             pDocument->Broadcast( aHint );
    1891             :         }
    1892           0 :         nIndex++;
    1893             :     }
    1894           0 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1895             : }
    1896             : 
    1897             : 
    1898           0 : void ScColumn::SetTableOpDirty( const ScRange& rRange )
    1899             : {
    1900           0 :     if ( maItems.empty() )
    1901           0 :         return ;
    1902           0 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1903           0 :     pDocument->SetAutoCalc( false );    // no multiple recalculation
    1904           0 :     SCROW nRow2 = rRange.aEnd.Row();
    1905           0 :     ScAddress aPos( nCol, 0, nTab );
    1906           0 :     ScHint aHint( SC_HINT_TABLEOPDIRTY, aPos, NULL );
    1907             :     SCROW nRow;
    1908             :     SCSIZE nIndex;
    1909           0 :     Search( rRange.aStart.Row(), nIndex );
    1910           0 :     while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRow2 )
    1911             :     {
    1912           0 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1913           0 :         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1914           0 :             ((ScFormulaCell*)pCell)->SetTableOpDirty();
    1915             :         else
    1916             :         {
    1917           0 :             aHint.GetAddress().SetRow( nRow );
    1918           0 :             aHint.SetCell( pCell );
    1919           0 :             pDocument->Broadcast( aHint );
    1920             :         }
    1921           0 :         nIndex++;
    1922             :     }
    1923           0 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1924             : }
    1925             : 
    1926             : 
    1927       83968 : void ScColumn::SetDirtyAfterLoad()
    1928             : {
    1929       83968 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1930       83968 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1931      111818 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1932             :     {
    1933       27850 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1934             : #if 1
    1935             :         // Simply set dirty and append to FormulaTree, without broadcasting,
    1936             :         // which is a magnitude faster. This is used to calculate the entire
    1937             :         // document, e.g. when loading alien file formats.
    1938       27850 :         if ( p->GetCellType() == CELLTYPE_FORMULA )
    1939        2433 :             p->SetDirtyAfterLoad();
    1940             : #else
    1941             : /* This was used with the binary file format that stored results, where only
    1942             :  * newly compiled and volatile functions and their dependents had to be
    1943             :  * recalculated, which was faster then. Since that was moved to 'binfilter' to
    1944             :  * convert to an XML file this isn't needed anymore, and not used for other
    1945             :  * file formats. Kept for reference in case mechanism needs to be reactivated
    1946             :  * for some file formats, we'd have to introduce a controlling parameter to
    1947             :  * this method here then.
    1948             : */
    1949             : 
    1950             :         // If the cell was alsready dirty because of CalcAfterLoad,
    1951             :         // FormulaTracking has to take place.
    1952             :         if ( p->GetCellType() == CELLTYPE_FORMULA && p->GetDirty() )
    1953             :             p->SetDirty();
    1954             : #endif
    1955             :     }
    1956       83968 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1957       83968 : }
    1958             : 
    1959             : 
    1960       19456 : void ScColumn::SetRelNameDirty()
    1961             : {
    1962       19456 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1963       19456 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1964       19464 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1965             :     {
    1966           8 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1967           8 :         if( p->GetCellType() == CELLTYPE_FORMULA && p->HasRelNameReference() )
    1968           0 :             p->SetDirty();
    1969             :     }
    1970       19456 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1971       19456 : }
    1972             : 
    1973             : 
    1974       94208 : void ScColumn::CalcAll()
    1975             : {
    1976       94208 :     if ( !maItems.empty() )
    1977        3351 :         for (SCSIZE i=0; i<maItems.size(); i++)
    1978             :         {
    1979        3082 :             ScBaseCell* pCell = maItems[i].pCell;
    1980        3082 :             if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1981             :             {
    1982             : #if OSL_DEBUG_LEVEL > 1
    1983             :                 // nach F9 ctrl-F9: ueberprueft die Berechnung per FormulaTree
    1984             :                 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
    1985             :                 double nOldVal, nNewVal;
    1986             :                 nOldVal = pFCell->GetValue();
    1987             : #endif
    1988         566 :                 ((ScFormulaCell*)pCell)->Interpret();
    1989             : #if OSL_DEBUG_LEVEL > 1
    1990             :                 if ( pFCell->GetCode()->IsRecalcModeNormal() )
    1991             :                     nNewVal = pFCell->GetValue();
    1992             :                 else
    1993             :                     nNewVal = nOldVal;  // random(), jetzt() etc.
    1994             :                 OSL_ENSURE( nOldVal==nNewVal, "CalcAll: nOldVal != nNewVal" );
    1995             : #endif
    1996             :             }
    1997             :         }
    1998       94208 : }
    1999             : 
    2000             : 
    2001        2048 : void ScColumn::CompileAll()
    2002             : {
    2003        2048 :     if ( !maItems.empty() )
    2004          11 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2005             :         {
    2006           7 :             ScBaseCell* pCell = maItems[i].pCell;
    2007           7 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2008             :             {
    2009           1 :                 SCROW nRow = maItems[i].nRow;
    2010             :                 // fuer unbedingtes kompilieren
    2011             :                 // bCompile=true und pCode->nError=0
    2012           1 :                 ((ScFormulaCell*)pCell)->GetCode()->SetCodeError( 0 );
    2013           1 :                 ((ScFormulaCell*)pCell)->SetCompile( true );
    2014           1 :                 ((ScFormulaCell*)pCell)->CompileTokenArray();
    2015           1 :                 if ( nRow != maItems[i].nRow )
    2016           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    2017             :             }
    2018             :         }
    2019        2048 : }
    2020             : 
    2021             : 
    2022       51200 : void ScColumn::CompileXML( ScProgress& rProgress )
    2023             : {
    2024       51200 :     if ( !maItems.empty() )
    2025        1985 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2026             :         {
    2027        1820 :             ScBaseCell* pCell = maItems[i].pCell;
    2028        1820 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2029             :             {
    2030         404 :                 SCROW nRow = maItems[i].nRow;
    2031         404 :                 ((ScFormulaCell*)pCell)->CompileXML( rProgress );
    2032         404 :                 if ( nRow != maItems[i].nRow )
    2033           2 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    2034             :             }
    2035             :         }
    2036       51200 : }
    2037             : 
    2038             : 
    2039       83968 : void ScColumn::CalcAfterLoad()
    2040             : {
    2041       83968 :     if ( !maItems.empty() )
    2042       28468 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2043             :         {
    2044       27850 :             ScBaseCell* pCell = maItems[i].pCell;
    2045       27850 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2046        2433 :                 ((ScFormulaCell*)pCell)->CalcAfterLoad();
    2047             :         }
    2048       83968 : }
    2049             : 
    2050             : 
    2051           0 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
    2052             : {
    2053           0 :     if ( !maItems.empty() )
    2054             :     {
    2055             :         SCSIZE nIndex;
    2056           0 :         Search(nStartRow,nIndex);
    2057           0 :         while (nIndex<maItems.size() && maItems[nIndex].nRow <= nEndRow)
    2058             :         {
    2059           0 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    2060           0 :             if (pCell->GetCellType() == CELLTYPE_FORMULA)
    2061           0 :                 ((ScFormulaCell*)pCell)->ResetChanged();
    2062           0 :             ++nIndex;
    2063             :         }
    2064             :     }
    2065           0 : }
    2066             : 
    2067             : 
    2068      263382 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst) const
    2069             : {
    2070             :     //  used in GetOptimalHeight - ambiguous script type counts as edit cell
    2071             : 
    2072      263382 :     SCROW nRow = 0;
    2073             :     SCSIZE nIndex;
    2074      263382 :     Search(nStartRow,nIndex);
    2075      531672 :     while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEndRow) : false )
    2076             :     {
    2077        4939 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    2078        4939 :         CellType eCellType = pCell->GetCellType();
    2079        9856 :         if ( eCellType == CELLTYPE_EDIT ||
    2080        4908 :              IsAmbiguousScriptNonZero( pDocument->GetScriptType(nCol, nRow, nTab, pCell) ) ||
    2081           9 :              ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) )
    2082             :         {
    2083          31 :             rFirst = nRow;
    2084          31 :             return true;
    2085             :         }
    2086        4908 :         ++nIndex;
    2087             :     }
    2088             : 
    2089      263351 :     return false;
    2090             : }
    2091             : 
    2092             : 
    2093           0 : SCsROW ScColumn::SearchStyle(
    2094             :     SCsROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, bool bInSelection,
    2095             :     const ScMarkData& rMark) const
    2096             : {
    2097           0 :     if (bInSelection)
    2098             :     {
    2099           0 :         if (rMark.IsMultiMarked())
    2100           0 :             return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, rMark.GetArray()+nCol);
    2101             :         else
    2102           0 :             return -1;
    2103             :     }
    2104             :     else
    2105           0 :         return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
    2106             : }
    2107             : 
    2108             : 
    2109           0 : bool ScColumn::SearchStyleRange(
    2110             :     SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
    2111             :     bool bInSelection, const ScMarkData& rMark) const
    2112             : {
    2113           0 :     if (bInSelection)
    2114             :     {
    2115           0 :         if (rMark.IsMultiMarked())
    2116             :             return pAttrArray->SearchStyleRange(
    2117           0 :                 rRow, rEndRow, pSearchStyle, bUp, rMark.GetArray() + nCol);
    2118             :         else
    2119           0 :             return false;
    2120             :     }
    2121             :     else
    2122           0 :         return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
    2123             : }
    2124             : 
    2125             : 
    2126             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10