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: 584 1029 56.8 %
Date: 2012-12-17 Functions: 62 88 70.5 %
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        9816 : 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        9816 :              nScript != 0 );
      54             : }
      55             : 
      56      722944 : ScColumn::ScColumn() :
      57             :     nCol( 0 ),
      58             :     pAttrArray( NULL ),
      59      722944 :     pDocument( NULL )
      60             : {
      61      722944 : }
      62             : 
      63             : 
      64     1126400 : ScColumn::~ScColumn()
      65             : {
      66      563200 :     FreeAll();
      67      563200 :     delete pAttrArray;
      68      563200 : }
      69             : 
      70             : 
      71      722944 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
      72             : {
      73      722944 :     nCol = nNewCol;
      74      722944 :     nTab = nNewTab;
      75      722944 :     pDocument = pDoc;
      76      722944 :     pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
      77      722944 : }
      78             : 
      79             : 
      80           0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
      81             : {
      82           0 :     return pAttrArray->GetNextUnprotected(nRow, bUp);
      83             : }
      84             : 
      85             : 
      86      247436 : 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      247436 :     if ( maItems.empty() )
      90      246174 :         return 0;
      91        1262 :     if ( nRow1 == nRow2 )
      92             :     {
      93             :         SCSIZE nIndex;
      94        1116 :         if ( Search( nRow1, nIndex ) )
      95             :         {
      96         662 :             ScBaseCell* pCell = maItems[nIndex].pCell;
      97         662 :             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        1116 :         return 0;
     105             :     }
     106             :     else
     107             :     {
     108         146 :         ScAddress aOrg( ScAddress::INITIALIZE_INVALID );
     109         146 :         bool bOpen = false;
     110         146 :         sal_uInt16 nEdges = 0;
     111             :         SCSIZE nIndex;
     112         146 :         Search( nRow1, nIndex );
     113        1284 :         while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nRow2 )
     114             :         {
     115         992 :             ScBaseCell* pCell = maItems[nIndex].pCell;
     116         992 :             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         992 :             nIndex++;
     138             :         }
     139         146 :         if ( bOpen )
     140           0 :             nEdges |= 32;           // not closed, matrix continues
     141         146 :         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      343626 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     221             : {
     222      343626 :     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        3006 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
     248             :                             SCCOL& rPaintCol, SCROW& rPaintRow,
     249             :                             bool bRefresh )
     250             : {
     251        3006 :     return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
     252             : }
     253             : 
     254             : 
     255       57344 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
     256             : {
     257             :     SCROW nTop;
     258             :     SCROW nBottom;
     259             : 
     260       57344 :     if ( rMark.IsMultiMarked() )
     261             :     {
     262       57344 :         const ScMarkArray* pArray = rMark.GetArray() + nCol;
     263       57344 :         if ( pArray->HasMarks() )
     264             :         {
     265         234 :             ScMarkArrayIter aMarkIter( pArray );
     266         808 :             while (aMarkIter.Next( nTop, nBottom ))
     267         574 :                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
     268             :         }
     269             :     }
     270       57344 : }
     271             : 
     272             : 
     273       45168 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
     274             : {
     275       45168 :     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
     276       45168 : }
     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        1880 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
     288             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
     289             : {
     290        1880 :     pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
     291        1880 : }
     292             : 
     293             : 
     294        9183 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
     295             : {
     296        9183 :     return pAttrArray->GetPattern( nRow );
     297             : }
     298             : 
     299             : 
     300        5170 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
     301             : {
     302        5170 :     return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
     303             : }
     304             : 
     305             : 
     306        2048 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
     307             : {
     308        2048 :     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     309        2048 :     const ScPatternAttr* pMaxPattern = 0;
     310        2048 :     size_t nMaxCount = 0;
     311             : 
     312        2048 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
     313             :     const ScPatternAttr* pPattern;
     314        2048 :     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
     315             : 
     316        6176 :     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
     317             :     {
     318        2080 :         size_t& rnCount = aAttrMap[ pPattern ];
     319        2080 :         rnCount += (nAttrRow2 - nAttrRow1 + 1);
     320        2080 :         if( rnCount > nMaxCount )
     321             :         {
     322        2080 :             pMaxPattern = pPattern;
     323        2080 :             nMaxCount = rnCount;
     324             :         }
     325             :     }
     326             : 
     327        2048 :     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       21294 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
     348             : {
     349       21294 :     return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
     350             : }
     351             : 
     352             : 
     353       49152 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
     354             : {
     355       49152 :     SCROW nTop = 0;
     356       49152 :     SCROW nBottom = 0;
     357       49152 :     bool bFound = false;
     358             : 
     359       49152 :     if ( rMark.IsMultiMarked() )
     360             :     {
     361       49152 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     362       98548 :         while (aMarkIter.Next( nTop, nBottom ))
     363             :         {
     364         244 :             pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
     365         244 :             bFound = true;
     366       49152 :         }
     367             :     }
     368             : 
     369       49152 :     if (!bFound)
     370       48960 :         return -1;
     371         192 :     else if (nTop==0 && nBottom==MAXROW)
     372           0 :         return 0;
     373             :     else
     374         192 :         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        6144 : void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
     407             : {
     408             :     SCROW nTop;
     409             :     SCROW nBottom;
     410             : 
     411        6144 :     if ( rMark.IsMultiMarked() )
     412             :     {
     413        6144 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     414       12302 :         while (aMarkIter.Next( nTop, nBottom ))
     415        6158 :             DeleteArea(nTop, nBottom, nDelFlag);
     416             :     }
     417        6144 : }
     418             : 
     419             : 
     420          58 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
     421             : {
     422          58 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     423          58 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     424             : 
     425          58 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
     426             : 
     427             :     //  true = alten Eintrag behalten
     428             : 
     429          58 :     ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, true );
     430          58 :     ScDocumentPool::CheckRef( *pPattern );
     431          58 :     ScDocumentPool::CheckRef( *pNewPattern );
     432             : 
     433          58 :     if (pNewPattern != pPattern)
     434          58 :       pAttrArray->SetPattern( nRow, pNewPattern );
     435          58 : }
     436             : 
     437             : 
     438       36894 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
     439             :                                  ScEditDataArray* pDataArray )
     440             : {
     441       36894 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     442       36894 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     443       36894 :     pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
     444       36894 : }
     445             : 
     446       42616 : bool ScColumn::SetAttrEntries(ScAttrEntry* pData, SCSIZE nSize)
     447             : {
     448       42616 :     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          98 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     478             : {
     479          98 :     pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
     480          98 : }
     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        4292 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
     502             : {
     503        4292 :     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
     504        4292 : }
     505             : 
     506             : 
     507      169984 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
     508             : {
     509             :     SCROW nTop;
     510             :     SCROW nBottom;
     511             : 
     512      169984 :     if ( rMark.IsMultiMarked() )
     513             :     {
     514      169984 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     515      341172 :         while (aMarkIter.Next( nTop, nBottom ))
     516      171188 :             pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
     517             :     }
     518      169984 : }
     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        8196 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
     583             : {
     584        8196 :     rFound = false;
     585             : 
     586        8196 :     bool bEqual = true;
     587             : 
     588        8196 :     const ScStyleSheet* pStyle = NULL;
     589             :     const ScStyleSheet* pNewStyle;
     590             : 
     591        8196 :     ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
     592             :     SCROW nRow;
     593             :     SCROW nDummy;
     594             :     const ScPatternAttr* pPattern;
     595       24588 :     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     596             :     {
     597        8196 :         pNewStyle = pPattern->GetStyleSheet();
     598        8196 :         rFound = true;
     599        8196 :         if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     600           0 :             bEqual = false;                                             // unterschiedliche
     601        8196 :         pStyle = pNewStyle;
     602             :     }
     603             : 
     604        8196 :     return bEqual ? pStyle : NULL;
     605             : }
     606             : 
     607     5715968 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
     608             : {
     609     5715968 :     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
     610     5715968 : }
     611             : 
     612           0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
     613             : {
     614           0 :     return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
     615             : }
     616             : 
     617             : 
     618        8430 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     619             : {
     620        8430 :     return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
     621             : }
     622             : 
     623             : 
     624        6594 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     625             : {
     626        6594 :     return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
     627             : }
     628             : 
     629             : 
     630           4 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
     631             : {
     632           4 :     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
     633           4 : }
     634             : 
     635             : 
     636         102 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
     637             : {
     638         102 :     pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
     639         102 : }
     640             : 
     641             : 
     642          14 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
     643             :                                 const ScPatternAttr& rPatAttr, bool bPutToPool )
     644             : {
     645          14 :     pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
     646          14 : }
     647             : 
     648             : 
     649        2344 : 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        2344 :     ScDocumentPool* pDocPool = pDocument->GetPool();
     655             : 
     656        2344 :     const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
     657        2344 :     ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
     658        2344 :     pTemp->GetItemSet().Put(rAttr);
     659        2344 :     const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
     660             : 
     661        2344 :     if ( pNewPattern != pOldPattern )
     662        2318 :         pAttrArray->SetPattern( nRow, pNewPattern );
     663             :     else
     664          26 :         pDocPool->Remove( *pNewPattern );       // ausser Spesen nichts gewesen
     665             : 
     666        2344 :     delete pTemp;
     667             : 
     668             :         // alte Version mit SfxItemPoolCache:
     669        2344 : }
     670             : 
     671             : #ifdef _MSC_VER
     672             : #pragma optimize ( "", off )
     673             : #endif
     674             : 
     675             : 
     676     1801090 : bool ScColumn::Search( SCROW nRow, SCSIZE& nIndex ) const
     677             : {
     678     1801090 :     if ( maItems.empty() )
     679             :     {
     680     1745650 :         nIndex = 0;
     681     1745650 :         return false;
     682             :     }
     683       55440 :     SCROW nMinRow = maItems[0].nRow;
     684       55440 :     if ( nRow <= nMinRow )
     685             :     {
     686        8982 :         nIndex = 0;
     687        8982 :         return nRow == nMinRow;
     688             :     }
     689       46458 :     SCROW nMaxRow = maItems.back().nRow;
     690       46458 :     if ( nRow >= nMaxRow )
     691             :     {
     692        9382 :         if ( nRow == nMaxRow )
     693             :         {
     694        4132 :             nIndex = maItems.size() - 1;
     695        4132 :             return true;
     696             :         }
     697             :         else
     698             :         {
     699        5250 :             nIndex = maItems.size();
     700        5250 :             return false;
     701             :         }
     702             :     }
     703             : 
     704             :     long nOldLo, nOldHi;
     705       37076 :     long    nLo     = nOldLo = 0;
     706       37076 :     long    nHi     = nOldHi = Min(static_cast<long>(maItems.size())-1, static_cast<long>(nRow) );
     707       37076 :     long    i       = 0;
     708       37076 :     bool    bFound  = false;
     709             :     // quite continuous distribution? => interpolating search
     710       37076 :     bool    bInterpol = (static_cast<SCSIZE>(nMaxRow - nMinRow) < maItems.size() * 2);
     711             :     SCROW   nR;
     712             : 
     713      127140 :     while ( !bFound && nLo <= nHi )
     714             :     {
     715       52988 :         if ( !bInterpol || nHi - nLo < 3 )
     716       14140 :             i = (nLo+nHi) / 2;          // no effort, no division by zero
     717             :         else
     718             :         {   // interpolating search
     719       38848 :             long nLoRow = maItems[nLo].nRow;     // no unsigned underflow upon substraction
     720             :             i = nLo + (long)((long)(nRow - nLoRow) * (nHi - nLo)
     721       38848 :                 / (maItems[nHi].nRow - nLoRow));
     722       38848 :             if ( i < 0 || static_cast<SCSIZE>(i) >= maItems.size() )
     723             :             {   // oops ...
     724          52 :                 i = (nLo+nHi) / 2;
     725          52 :                 bInterpol = false;
     726             :             }
     727             :         }
     728       52988 :         nR = maItems[i].nRow;
     729       52988 :         if ( nR < nRow )
     730             :         {
     731       13886 :             nLo = i+1;
     732       13886 :             if ( bInterpol )
     733             :             {
     734       11220 :                 if ( nLo <= nOldLo )
     735         136 :                     bInterpol = false;
     736             :                 else
     737       11084 :                     nOldLo = nLo;
     738             :             }
     739             :         }
     740             :         else
     741             :         {
     742       39102 :             if ( nR > nRow )
     743             :             {
     744        3996 :                 nHi = i-1;
     745        3996 :                 if ( bInterpol )
     746             :                 {
     747        2018 :                     if ( nHi >= nOldHi )
     748           2 :                         bInterpol = false;
     749             :                     else
     750        2016 :                         nOldHi = nHi;
     751             :                 }
     752             :             }
     753             :             else
     754       35106 :                 bFound = true;
     755             :         }
     756             :     }
     757       37076 :     if (bFound)
     758       35106 :         nIndex = static_cast<SCSIZE>(i);
     759             :     else
     760        1970 :         nIndex = static_cast<SCSIZE>(nLo); // rear index
     761       37076 :     return bFound;
     762             : }
     763             : 
     764             : #ifdef _MSC_VER
     765             : #pragma optimize ( "", on )
     766             : #endif
     767             : 
     768             : 
     769       19568 : ScBaseCell* ScColumn::GetCell( SCROW nRow ) const
     770             : {
     771             :     SCSIZE nIndex;
     772       19568 :     if (Search(nRow, nIndex))
     773       17438 :         return maItems[nIndex].pCell;
     774        2130 :     return NULL;
     775             : }
     776             : 
     777             : 
     778         592 : void ScColumn::Resize( SCSIZE nSize )
     779             : {
     780         592 :     if (nSize > sal::static_int_cast<SCSIZE>(MAXROWCOUNT))
     781           0 :         nSize = MAXROWCOUNT;
     782         592 :     if (nSize < maItems.size())
     783           0 :         nSize = maItems.size();
     784             : 
     785         592 :     maItems.reserve(nSize);
     786         592 : }
     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           8 : 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           8 :     ScBaseCell* pCell1 = 0;
     817             :     SCSIZE nIndex1;
     818           8 :     if ( Search( nRow1, nIndex1 ) )
     819           8 :         pCell1 = maItems[nIndex1].pCell;
     820             : 
     821           8 :     ScBaseCell* pCell2 = 0;
     822             :     SCSIZE nIndex2;
     823           8 :     if ( Search( nRow2, nIndex2 ) )
     824           8 :         pCell2 = maItems[nIndex2].pCell;
     825             : 
     826             :     // no cells found, nothing to do
     827           8 :     if ( !pCell1 && !pCell2 )
     828             :         return ;
     829             : 
     830             :     // swap variables if first cell is empty, to save some code below
     831           8 :     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           8 :     ScAddress aPos1( nCol, nRow1, nTab );
     841           8 :     ScAddress aPos2( nCol, nRow2, nTab );
     842             : 
     843           8 :     CellType eType1 = pCell1->GetCellType();
     844           8 :     CellType eType2 = pCell2 ? pCell2->GetCellType() : CELLTYPE_NONE;
     845             : 
     846           8 :     ScFormulaCell* pFmlaCell1 = (eType1 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell1 ) : 0;
     847           8 :     ScFormulaCell* pFmlaCell2 = (eType2 == CELLTYPE_FORMULA) ? static_cast< ScFormulaCell* >( pCell2 ) : 0;
     848             : 
     849             :     // simple swap if no formula cells present
     850           8 :     if ( !pFmlaCell1 && !pFmlaCell2 )
     851             :     {
     852             :         // remember cell broadcasters, must remain at old position
     853           8 :         SvtBroadcaster* pBC1 = pCell1->ReleaseBroadcaster();
     854             : 
     855           8 :         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           8 :             maItems[nIndex1].pCell = pCell2;
     860           8 :             maItems[nIndex2].pCell = pCell1;
     861             : 
     862           8 :             SvtBroadcaster* pBC2 = pCell2->ReleaseBroadcaster();
     863           8 :             pCell1->TakeBroadcaster( pBC2 );
     864           8 :             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           4 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
    1024             : {
    1025           4 :     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           4 :         return true;
    1044             : }
    1045             : 
    1046             : 
    1047       10242 : bool ScColumn::TestInsertRow( SCSIZE nSize ) const
    1048             : {
    1049             :     //  AttrArray only looks for merged cells
    1050             : 
    1051       10242 :     if ( !maItems.empty() )
    1052           2 :         return ( nSize <= sal::static_int_cast<SCSIZE>(MAXROW) &&
    1053           2 :                  maItems[maItems.size()-1].nRow <= MAXROW-(SCROW)nSize && pAttrArray->TestInsertRow( nSize ) );
    1054             :     else
    1055       10240 :         return pAttrArray->TestInsertRow( nSize );
    1056             : }
    1057             : 
    1058             : 
    1059       10242 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
    1060             : {
    1061       10242 :     pAttrArray->InsertRow( nStartRow, nSize );
    1062             : 
    1063             :     //! Search
    1064             : 
    1065       10242 :     if ( maItems.empty() )
    1066             :         return;
    1067             : 
    1068             :     SCSIZE i;
    1069           2 :     Search( nStartRow, i );
    1070           2 :     if ( i >= maItems.size() )
    1071             :         return ;
    1072             : 
    1073           2 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1074           2 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1075             : 
    1076           2 :     SCSIZE nNewCount = maItems.size();
    1077           2 :     bool bCountChanged = false;
    1078           2 :     ScAddress aAdr( nCol, 0, nTab );
    1079           2 :     ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL );    // only areas (ScBaseCell* == NULL)
    1080           2 :     ScAddress& rAddress = aHint.GetAddress();
    1081             :     // for sparse occupation use single broadcasts, not ranges
    1082           4 :     bool bSingleBroadcasts = (((maItems.back().nRow - maItems[i].nRow) /
    1083           4 :                 (maItems.size() - i)) > 1);
    1084           2 :     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           2 :         rAddress.SetRow( maItems[i].nRow );
    1114           2 :         ScRange aRange( rAddress );
    1115           4 :         for ( ; i < maItems.size(); i++)
    1116             :         {
    1117           2 :             SCROW nNewRow = (maItems[i].nRow += nSize);
    1118           2 :             ScBaseCell* pCell = maItems[i].pCell;
    1119           2 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1120           0 :                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
    1121           2 :             if ( nNewRow > MAXROW && !bCountChanged )
    1122             :             {
    1123           0 :                 nNewCount = i;
    1124           0 :                 bCountChanged = true;
    1125           0 :                 aRange.aEnd.SetRow( MAXROW );
    1126             :             }
    1127             :         }
    1128           2 :         if ( !bCountChanged )
    1129           2 :             aRange.aEnd.SetRow( maItems.back().nRow );
    1130           2 :         pDocument->AreaBroadcastInRange( aRange, aHint );
    1131             :     }
    1132             : 
    1133           2 :     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           2 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1163             : }
    1164             : 
    1165             : 
    1166          10 : void ScColumn::CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, bool bKeepScenarioFlags) const
    1167             : {
    1168             :     pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
    1169          10 :                             bKeepScenarioFlags ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
    1170             : 
    1171             :     SCSIZE i;
    1172          10 :     SCSIZE nBlockCount = 0;
    1173          10 :     SCSIZE nStartIndex = 0, nEndIndex = 0;
    1174          38 :     for (i = 0; i < maItems.size(); i++)
    1175          28 :         if ((maItems[i].nRow >= nRow1) && (maItems[i].nRow <= nRow2))
    1176             :         {
    1177          28 :             if (!nBlockCount)
    1178          10 :                 nStartIndex = i;
    1179          28 :             nEndIndex = i;
    1180          28 :             ++nBlockCount;
    1181             : 
    1182             :             //  im Clipboard muessen interpretierte Zellen stehen, um andere Formate
    1183             :             //  (Text, Grafik...) erzueugen zu koennen
    1184             : 
    1185          28 :             if ( maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
    1186             :             {
    1187          24 :                 ScFormulaCell* pFCell = (ScFormulaCell*) maItems[i].pCell;
    1188          24 :                 if (pFCell->GetDirty() && pDocument->GetAutoCalc())
    1189          18 :                     pFCell->Interpret();
    1190             :             }
    1191             :         }
    1192             : 
    1193          10 :     if (nBlockCount)
    1194             :     {
    1195          10 :         rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
    1196          10 :         ScAddress aOwnPos( nCol, 0, nTab );
    1197          10 :         ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
    1198          38 :         for (i = nStartIndex; i <= nEndIndex; i++)
    1199             :         {
    1200          28 :             aOwnPos.SetRow( maItems[i].nRow );
    1201          28 :             aDestPos.SetRow( maItems[i].nRow );
    1202          28 :             ScBaseCell* pNewCell = maItems[i].pCell->Clone( *rColumn.pDocument, aDestPos, SC_CLONECELL_DEFAULT );
    1203          28 :             rColumn.Append( aDestPos.Row(), pNewCell );
    1204             :         }
    1205             :     }
    1206          10 : }
    1207             : 
    1208             : 
    1209       18858 : void ScColumn::CopyToColumn(
    1210             :     SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
    1211             :     const ScMarkData* pMarkData, bool bAsLink) const
    1212             : {
    1213       18858 :     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       18858 :         return;
    1232             :     }
    1233             : 
    1234       18858 :     if ( (nFlags & IDF_ATTRIB) != 0 )
    1235             :     {
    1236       12686 :         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       12686 :             pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
    1252             :     }
    1253             : 
    1254             : 
    1255       18858 :     if ((nFlags & IDF_CONTENTS) != 0)
    1256             :     {
    1257             :         SCSIZE i;
    1258       18832 :         SCSIZE nBlockCount = 0;
    1259       18832 :         SCSIZE nStartIndex = 0, nEndIndex = 0;
    1260       20962 :         for (i = 0; i < maItems.size(); i++)
    1261        2130 :             if ((maItems[i].nRow >= nRow1) && (maItems[i].nRow <= nRow2))
    1262             :             {
    1263        1782 :                 if (!nBlockCount)
    1264         386 :                     nStartIndex = i;
    1265        1782 :                 nEndIndex = i;
    1266        1782 :                 ++nBlockCount;
    1267             :             }
    1268             : 
    1269       18832 :         if (nBlockCount)
    1270             :         {
    1271         386 :             rColumn.Resize( rColumn.GetCellCount() + nBlockCount );
    1272         386 :             ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab );
    1273        2168 :             for (i = nStartIndex; i <= nEndIndex; i++)
    1274             :             {
    1275        1782 :                 aDestPos.SetRow( maItems[i].nRow );
    1276             :                 ScBaseCell* pNew = bAsLink ?
    1277           0 :                     CreateRefCell( rColumn.pDocument, aDestPos, i, nFlags ) :
    1278        1782 :                     CloneCell( i, nFlags, *rColumn.pDocument, aDestPos );
    1279             : 
    1280        1782 :                 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        1620 :                     if (pNew->GetCellType() == CELLTYPE_STRING)
    1286             :                     {
    1287         446 :                         rtl::OUString aStr = static_cast<ScStringCell*>(pNew)->GetString();
    1288         446 :                         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         446 :                             rColumn.Insert(maItems[i].nRow, pNew);
    1294             :                     }
    1295             :                     else
    1296        1174 :                         rColumn.Insert(maItems[i].nRow, pNew);
    1297             :                 }
    1298             :             }
    1299             :         }
    1300             :     }
    1301             : }
    1302             : 
    1303             : 
    1304          12 : void ScColumn::UndoToColumn(
    1305             :     SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
    1306             :     const ScMarkData* pMarkData) const
    1307             : {
    1308          12 :     if (nRow1 > 0)
    1309          12 :         CopyToColumn( 0, nRow1-1, IDF_FORMULA, false, rColumn );
    1310             : 
    1311          12 :     CopyToColumn( nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData );      //! bMarked ????
    1312             : 
    1313          12 :     if (nRow2 < MAXROW)
    1314          12 :         CopyToColumn( nRow2+1, MAXROW, IDF_FORMULA, false, rColumn );
    1315          12 : }
    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        6130 : void ScColumn::SwapCol(ScColumn& rCol)
    1442             : {
    1443        6130 :     maItems.swap(rCol.maItems);
    1444             : 
    1445        6130 :     ScAttrArray* pTempAttr = rCol.pAttrArray;
    1446        6130 :     rCol.pAttrArray = pAttrArray;
    1447        6130 :     pAttrArray = pTempAttr;
    1448             : 
    1449             :     // AttrArray muss richtige Spaltennummer haben
    1450        6130 :     pAttrArray->SetCol(nCol);
    1451        6130 :     rCol.pAttrArray->SetCol(rCol.nCol);
    1452             : 
    1453             :     SCSIZE i;
    1454        6130 :     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        6130 :     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        6130 : }
    1467             : 
    1468        4080 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
    1469             : {
    1470        4080 :     pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
    1471             : 
    1472        4080 :     if (maItems.empty())
    1473             :         // No cells to move.
    1474        4080 :         return;
    1475             : 
    1476           4 :     ::std::vector<SCROW> aRows;
    1477             :     SCSIZE i;
    1478           4 :     Search( nStartRow, i);  // i points to start row or position thereafter
    1479           4 :     SCSIZE nStartPos = i;
    1480             :     // First, copy the cell instances to the new column.
    1481           8 :     for ( ; i < maItems.size() && maItems[i].nRow <= nEndRow; ++i)
    1482             :     {
    1483           4 :         SCROW nRow = maItems[i].nRow;
    1484           4 :         aRows.push_back( nRow);
    1485           4 :         rCol.Insert( nRow, maItems[i].pCell);
    1486             :     }
    1487           4 :     SCSIZE nStopPos = i;
    1488           4 :     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           4 :         EntryPosPairs aEntries;
    1494             :         {
    1495           4 :             bool bFirst = true;
    1496           4 :             nStopPos = 0;
    1497          36 :             for (::std::vector<SCROW>::const_iterator it( aRows.begin());
    1498          28 :                     it != aRows.end() && nStopPos < maItems.size(); ++it,
    1499             :                     ++nStopPos)
    1500             :             {
    1501           4 :                 if (!bFirst && *it != maItems[nStopPos].nRow)
    1502             :                 {
    1503           0 :                     aEntries.push_back( PosPair(nStartPos, nStopPos));
    1504           0 :                     bFirst = true;
    1505             :                 }
    1506           4 :                 if (bFirst && Search( *it, nStartPos))
    1507             :                 {
    1508           4 :                     bFirst = false;
    1509           4 :                     nStopPos = nStartPos;
    1510             :                 }
    1511             :             }
    1512           4 :             if (!bFirst && nStartPos < nStopPos)
    1513           4 :                 aEntries.push_back( PosPair(nStartPos, nStopPos));
    1514             :         }
    1515             :         // Broadcast changes
    1516           4 :         ScAddress aAdr( nCol, 0, nTab );
    1517           4 :         ScHint aHint( SC_HINT_DYING, aAdr, NULL );  // areas only
    1518           4 :         ScAddress& rAddress = aHint.GetAddress();
    1519           4 :         ScNoteCell* pNoteCell = new ScNoteCell;     // Dummy like in DeleteRange
    1520             : 
    1521             :         // must iterate backwards, because indexes of following cells become invalid
    1522          24 :         for (EntryPosPairs::reverse_iterator it( aEntries.rbegin());
    1523          16 :                 it != aEntries.rend(); ++it)
    1524             :         {
    1525           4 :             nStartPos = (*it).first;
    1526           4 :             nStopPos = (*it).second;
    1527           8 :             for (i=nStartPos; i<nStopPos; ++i)
    1528           4 :                 maItems[i].pCell = pNoteCell; // Assign the dumpy cell instance to all slots.
    1529           8 :             for (i=nStartPos; i<nStopPos; ++i)
    1530             :             {
    1531           4 :                 rAddress.SetRow( maItems[i].nRow );
    1532           4 :                 pDocument->AreaBroadcast( aHint );
    1533             :             }
    1534             :             // Erase the slots containing pointers to the dummy cell instance.
    1535           4 :             maItems.erase(maItems.begin() + nStartPos, maItems.begin() + nStopPos);
    1536             :         }
    1537           4 :         pNoteCell->Delete(); // Delete the dummy cell instance.
    1538           4 :     }
    1539             : }
    1540             : 
    1541       47114 : 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       47114 :     bool bUpdated = false;
    1546       47114 :     if ( !maItems.empty() )
    1547             :     {
    1548             :         ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
    1549          36 :                         ScAddress( nCol2, nRow2, nTab2 ) );
    1550          36 :         if ( eUpdateRefMode == URM_COPY && nRow1 == nRow2 )
    1551             :         {   // z.B. eine einzelne Zelle aus dem Clipboard eingefuegt
    1552             :             SCSIZE nIndex;
    1553           6 :             if ( Search( nRow1, nIndex ) )
    1554             :             {
    1555           6 :                 ScFormulaCell* pCell = (ScFormulaCell*) maItems[nIndex].pCell;
    1556           6 :                 if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1557             :                     bUpdated |= pCell->UpdateReference(
    1558           2 :                         eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
    1559           6 :             }
    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          30 :             if ( eUpdateRefMode == URM_COPY )
    1568             :             {
    1569             :                 SCSIZE i;
    1570          18 :                 Search( nRow1, i );
    1571          66 :                 for ( ; i < maItems.size(); i++ )
    1572             :                 {
    1573          48 :                     SCROW nRow = maItems[i].nRow;
    1574          48 :                     if ( nRow > nRow2 )
    1575           0 :                         break;
    1576          48 :                     ScBaseCell* pCell = maItems[i].pCell;
    1577          48 :                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1578             :                     {
    1579             :                         bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
    1580          32 :                             eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
    1581          32 :                         if ( nRow != maItems[i].nRow )
    1582           0 :                             Search( nRow, i );  // Listener removed/inserted?
    1583             :                     }
    1584             :                 }
    1585             :             }
    1586             :             else
    1587             :             {
    1588          12 :                 SCSIZE i = 0;
    1589          28 :                 for ( ; i < maItems.size(); i++ )
    1590             :                 {
    1591          16 :                     ScBaseCell* pCell = maItems[i].pCell;
    1592          16 :                     if( pCell->GetCellType() == CELLTYPE_FORMULA)
    1593             :                     {
    1594           8 :                         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           8 :                         ScAddress aUndoPos( nCol, nRow, nTab );
    1598             :                         bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
    1599           8 :                             eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
    1600           8 :                         if ( nRow != maItems[i].nRow )
    1601           0 :                             Search( nRow, i );  // Listener removed/inserted?
    1602             :                     }
    1603             :                 }
    1604             :             }
    1605             :         }
    1606             :     }
    1607       47114 :     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       53248 : void ScColumn::UpdateInsertTab(SCTAB nInsPos, SCTAB nNewSheets)
    1647             : {
    1648       53248 :     if (nTab >= nInsPos)
    1649             :     {
    1650       38912 :         nTab += nNewSheets;
    1651       38912 :         pAttrArray->SetTab(nTab);
    1652             :     }
    1653             : 
    1654       53248 :     UpdateInsertTabOnlyCells(nInsPos, nNewSheets);
    1655       53248 : }
    1656             : 
    1657       53248 : void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
    1658             : {
    1659       53248 :     if (maItems.empty())
    1660      106460 :         return;
    1661             : 
    1662         112 :     for (size_t i = 0; i < maItems.size(); ++i)
    1663             :     {
    1664          76 :         switch (maItems[i].pCell->GetCellType())
    1665             :         {
    1666             :             case CELLTYPE_FORMULA:
    1667             :             {
    1668          12 :                 SCROW nRow = maItems[i].nRow;
    1669          12 :                 ScFormulaCell* p = static_cast<ScFormulaCell*>(maItems[i].pCell);
    1670          12 :                 p->UpdateInsertTab(nInsPos, nNewSheets);
    1671          12 :                 if (nRow != maItems[i].nRow)
    1672           0 :                     Search(nRow, i);      // Listener deleted/inserted?
    1673             :             }
    1674          12 :             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        6144 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
    1688             : {
    1689        6144 :     if (maItems.empty())
    1690       12288 :         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      167936 : void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* pRefUndo, SCTAB nSheets)
    1718             : {
    1719      167936 :     if (nTab > nDelPos)
    1720             :     {
    1721       28672 :         nTab -= nSheets;
    1722       28672 :         pAttrArray->SetTab(nTab);
    1723             :     }
    1724             : 
    1725      167936 :     if (maItems.empty())
    1726      335628 :         return;
    1727             : 
    1728        1476 :     for (size_t i = 0; i < maItems.size(); ++i)
    1729             :     {
    1730        1232 :         switch (maItems[i].pCell->GetCellType())
    1731             :         {
    1732             :             case CELLTYPE_FORMULA:
    1733             :             {
    1734         120 :                 SCROW nRow = maItems[i].nRow;
    1735         120 :                 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         120 :                 ScBaseCell* pSave = pRefUndo ? pOld->Clone( *pDocument ) : 0;
    1740             : 
    1741         120 :                 bool bChanged = pOld->UpdateDeleteTab(nDelPos, bIsMove, nSheets);
    1742         120 :                 if ( nRow != maItems[i].nRow )
    1743           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    1744             : 
    1745         120 :                 if (pRefUndo)
    1746             :                 {
    1747          10 :                     if (bChanged)
    1748          10 :                         pRefUndo->Insert( nRow, pSave );
    1749           0 :                     else if(pSave)
    1750           0 :                         pSave->Delete();
    1751             :                 }
    1752             :             }
    1753         120 :             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       20480 : void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
    1767             : {
    1768       20480 :     nTab = nTabNo;
    1769       20480 :     pAttrArray->SetTab( nTabNo );
    1770       20480 :     if (maItems.empty())
    1771       40928 :         return;
    1772             : 
    1773         236 :     for (size_t i = 0; i < maItems.size(); ++i)
    1774             :     {
    1775         204 :         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      204800 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
    1800             : {
    1801      204800 :     if ( !maItems.empty() )
    1802        1316 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1803             :         {
    1804        1098 :             ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1805        1098 :             if( p->GetCellType() == CELLTYPE_FORMULA )
    1806             :             {
    1807         116 :                 SCROW nRow = maItems[i].nRow;
    1808         116 :                 p->UpdateCompile( bForceIfNameInUse );
    1809         116 :                 if ( nRow != maItems[i].nRow )
    1810           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    1811             :             }
    1812             :         }
    1813      204800 : }
    1814             : 
    1815             : 
    1816        2048 : void ScColumn::SetTabNo(SCTAB nNewTab)
    1817             : {
    1818        2048 :     nTab = nNewTab;
    1819        2048 :     pAttrArray->SetTab( nNewTab );
    1820        2048 :     if ( !maItems.empty() )
    1821          40 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1822             :         {
    1823          26 :             ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1824          26 :             if( p->GetCellType() == CELLTYPE_FORMULA )
    1825          10 :                 p->aPos.SetTab( nNewTab );
    1826             :         }
    1827        2048 : }
    1828             : 
    1829           6 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
    1830             : {
    1831           6 :     if ( !maItems.empty() )
    1832          12 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1833          18 :             if ((maItems[i].nRow >= nRow1) &&
    1834           6 :                 (maItems[i].nRow <= nRow2) &&
    1835           6 :                 (maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA))
    1836           2 :                     ((ScFormulaCell*)maItems[i].pCell)->FindRangeNamesInUse(rIndexes);
    1837           6 : }
    1838             : 
    1839      188416 : void ScColumn::SetDirtyVar()
    1840             : {
    1841      194580 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1842             :     {
    1843        6164 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1844        6164 :         if( p->GetCellType() == CELLTYPE_FORMULA )
    1845        1132 :             p->SetDirtyVar();
    1846             :     }
    1847      188416 : }
    1848             : 
    1849             : 
    1850      520192 : void ScColumn::SetDirty()
    1851             : {
    1852             :     // wird nur dokumentweit verwendet, kein FormulaTrack
    1853      520192 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1854      520192 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1855      526526 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1856             :     {
    1857        6334 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1858        6334 :         if( p->GetCellType() == CELLTYPE_FORMULA )
    1859             :         {
    1860         122 :             p->SetDirtyVar();
    1861         122 :             if ( !pDocument->IsInFormulaTree( p ) )
    1862         102 :                 pDocument->PutInFormulaTree( p );
    1863             :         }
    1864             :     }
    1865      520192 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1866      520192 : }
    1867             : 
    1868             : 
    1869        2062 : void ScColumn::SetDirty( const ScRange& rRange )
    1870             : {   // broadcastet alles innerhalb eines Range, mit FormulaTrack
    1871        2062 :     if ( maItems.empty() )
    1872        2062 :         return ;
    1873          28 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1874          28 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1875          28 :     SCROW nRow2 = rRange.aEnd.Row();
    1876          28 :     ScAddress aPos( nCol, 0, nTab );
    1877          28 :     ScHint aHint( SC_HINT_DATACHANGED, aPos, NULL );
    1878             :     SCROW nRow;
    1879             :     SCSIZE nIndex;
    1880          28 :     Search( rRange.aStart.Row(), nIndex );
    1881          96 :     while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRow2 )
    1882             :     {
    1883          40 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1884          40 :         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1885          10 :             ((ScFormulaCell*)pCell)->SetDirty();
    1886             :         else
    1887             :         {
    1888          30 :             aHint.GetAddress().SetRow( nRow );
    1889          30 :             aHint.SetCell( pCell );
    1890          30 :             pDocument->Broadcast( aHint );
    1891             :         }
    1892          40 :         nIndex++;
    1893             :     }
    1894          28 :     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      180224 : void ScColumn::SetDirtyAfterLoad()
    1928             : {
    1929      180224 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1930      180224 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1931      235926 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1932             :     {
    1933       55702 :         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       55702 :         if ( p->GetCellType() == CELLTYPE_FORMULA )
    1939        4866 :             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      180224 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1957      180224 : }
    1958             : 
    1959             : 
    1960       38912 : void ScColumn::SetRelNameDirty()
    1961             : {
    1962       38912 :     bool bOldAutoCalc = pDocument->GetAutoCalc();
    1963       38912 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
    1964       38928 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1965             :     {
    1966          16 :         ScFormulaCell* p = (ScFormulaCell*) maItems[i].pCell;
    1967          16 :         if( p->GetCellType() == CELLTYPE_FORMULA && p->HasRelNameReference() )
    1968           0 :             p->SetDirty();
    1969             :     }
    1970       38912 :     pDocument->SetAutoCalc( bOldAutoCalc );
    1971       38912 : }
    1972             : 
    1973             : 
    1974      188416 : void ScColumn::CalcAll()
    1975             : {
    1976      188416 :     if ( !maItems.empty() )
    1977        6702 :         for (SCSIZE i=0; i<maItems.size(); i++)
    1978             :         {
    1979        6164 :             ScBaseCell* pCell = maItems[i].pCell;
    1980        6164 :             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        1132 :                 ((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      188416 : }
    1999             : 
    2000             : 
    2001        6144 : void ScColumn::CompileAll()
    2002             : {
    2003        6144 :     if ( !maItems.empty() )
    2004          62 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2005             :         {
    2006          40 :             ScBaseCell* pCell = maItems[i].pCell;
    2007          40 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2008             :             {
    2009          12 :                 SCROW nRow = maItems[i].nRow;
    2010             :                 // fuer unbedingtes kompilieren
    2011             :                 // bCompile=true und pCode->nError=0
    2012          12 :                 ((ScFormulaCell*)pCell)->GetCode()->SetCodeError( 0 );
    2013          12 :                 ((ScFormulaCell*)pCell)->SetCompile( true );
    2014          12 :                 ((ScFormulaCell*)pCell)->CompileTokenArray();
    2015          12 :                 if ( nRow != maItems[i].nRow )
    2016           0 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    2017             :             }
    2018             :         }
    2019        6144 : }
    2020             : 
    2021             : 
    2022      161792 : void ScColumn::CompileXML( ScProgress& rProgress )
    2023             : {
    2024      161792 :     if ( !maItems.empty() )
    2025        4886 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2026             :         {
    2027        4418 :             ScBaseCell* pCell = maItems[i].pCell;
    2028        4418 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2029             :             {
    2030         824 :                 SCROW nRow = maItems[i].nRow;
    2031         824 :                 ((ScFormulaCell*)pCell)->CompileXML( rProgress );
    2032         824 :                 if ( nRow != maItems[i].nRow )
    2033           4 :                     Search( nRow, i );      // Listener geloescht/eingefuegt?
    2034             :             }
    2035             :         }
    2036      161792 : }
    2037             : 
    2038             : 
    2039      180224 : void ScColumn::CalcAfterLoad()
    2040             : {
    2041      180224 :     if ( !maItems.empty() )
    2042       56940 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    2043             :         {
    2044       55702 :             ScBaseCell* pCell = maItems[i].pCell;
    2045       55702 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    2046        4866 :                 ((ScFormulaCell*)pCell)->CalcAfterLoad();
    2047             :         }
    2048      180224 : }
    2049             : 
    2050             : 
    2051         320 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
    2052             : {
    2053         320 :     if ( !maItems.empty() )
    2054             :     {
    2055             :         SCSIZE nIndex;
    2056          24 :         Search(nStartRow,nIndex);
    2057          82 :         while (nIndex<maItems.size() && maItems[nIndex].nRow <= nEndRow)
    2058             :         {
    2059          34 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    2060          34 :             if (pCell->GetCellType() == CELLTYPE_FORMULA)
    2061          10 :                 ((ScFormulaCell*)pCell)->ResetChanged();
    2062          34 :             ++nIndex;
    2063             :         }
    2064             :     }
    2065         320 : }
    2066             : 
    2067             : 
    2068      819628 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst) const
    2069             : {
    2070             :     //  used in GetOptimalHeight - ambiguous script type counts as edit cell
    2071             : 
    2072      819628 :     SCROW nRow = 0;
    2073             :     SCSIZE nIndex;
    2074      819628 :     Search(nStartRow,nIndex);
    2075     1649072 :     while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEndRow) : false )
    2076             :     {
    2077        9908 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    2078        9908 :         CellType eCellType = pCell->GetCellType();
    2079       19742 :         if ( eCellType == CELLTYPE_EDIT ||
    2080        9816 :              IsAmbiguousScriptNonZero( pDocument->GetScriptType(nCol, nRow, nTab, pCell) ) ||
    2081          18 :              ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) )
    2082             :         {
    2083          92 :             rFirst = nRow;
    2084          92 :             return true;
    2085             :         }
    2086        9816 :         ++nIndex;
    2087             :     }
    2088             : 
    2089      819536 :     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