LCOV - code coverage report
Current view: top level - sc/source/core/data - column.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1239 1680 73.8 %
Date: 2015-06-13 12:38:46 Functions: 197 237 83.1 %
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 "column.hxx"
      21             : #include "scitems.hxx"
      22             : #include "formulacell.hxx"
      23             : #include "document.hxx"
      24             : #include "docpool.hxx"
      25             : #include "attarray.hxx"
      26             : #include "patattr.hxx"
      27             : #include "compiler.hxx"
      28             : #include "brdcst.hxx"
      29             : #include "markdata.hxx"
      30             : #include "detfunc.hxx"
      31             : #include "postit.hxx"
      32             : #include "globalnames.hxx"
      33             : #include "cellvalue.hxx"
      34             : #include "tokenarray.hxx"
      35             : #include "cellform.hxx"
      36             : #include "clipcontext.hxx"
      37             : #include "types.hxx"
      38             : #include "editutil.hxx"
      39             : #include "mtvcellfunc.hxx"
      40             : #include "columnspanset.hxx"
      41             : #include "scopetools.hxx"
      42             : #include "sharedformula.hxx"
      43             : #include "refupdatecontext.hxx"
      44             : #include <listenercontext.hxx>
      45             : #include <refhint.hxx>
      46             : #include <stlalgorithm.hxx>
      47             : #include <formulagroup.hxx>
      48             : 
      49             : #include <svl/poolcach.hxx>
      50             : #include <svl/zforlist.hxx>
      51             : #include <svl/sharedstringpool.hxx>
      52             : #include <editeng/scripttypeitem.hxx>
      53             : #include <editeng/fieldupdater.hxx>
      54             : #include <osl/diagnose.h>
      55             : 
      56             : #include <cstring>
      57             : #include <map>
      58             : #include <cstdio>
      59             : #include <boost/checked_delete.hpp>
      60             : #include <boost/scoped_ptr.hpp>
      61             : 
      62             : using ::editeng::SvxBorderLine;
      63             : using namespace formula;
      64             : 
      65             : namespace {
      66             : 
      67       31896 : inline bool IsAmbiguousScriptNonZero( SvtScriptType nScript )
      68             : {
      69             :     //TODO: move to a header file
      70         173 :     return ( nScript != SvtScriptType::LATIN &&
      71         173 :              nScript != SvtScriptType::ASIAN &&
      72       32069 :              nScript != SvtScriptType::COMPLEX &&
      73       31896 :              nScript != SvtScriptType::NONE );
      74             : }
      75             : 
      76             : }
      77             : 
      78      129328 : ScNeededSizeOptions::ScNeededSizeOptions() :
      79      129328 :     pPattern(NULL), bFormula(false), bSkipMerged(true), bGetFont(true), bTotalSize(false)
      80             : {
      81      129328 : }
      82             : 
      83     2458624 : ScColumn::ScColumn() :
      84             :     maCellTextAttrs(MAXROWCOUNT),
      85             :     maCellNotes(MAXROWCOUNT),
      86             :     maBroadcasters(MAXROWCOUNT),
      87             :     maCells(MAXROWCOUNT),
      88             :     nCol( 0 ),
      89             :     nTab( 0 ),
      90             :     pAttrArray( NULL ),
      91             :     pDocument( NULL ),
      92     2458624 :     mbDirtyGroups(true)
      93             : {
      94     2458624 : }
      95             : 
      96     4874240 : ScColumn::~ScColumn()
      97             : {
      98     2437120 :     FreeAll();
      99     2437120 :     delete pAttrArray;
     100     2437120 : }
     101             : 
     102     2458624 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
     103             : {
     104     2458624 :     nCol = nNewCol;
     105     2458624 :     nTab = nNewTab;
     106     2458624 :     pDocument = pDoc;
     107     2458624 :     pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
     108     2458624 : }
     109             : 
     110           0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
     111             : {
     112           0 :     return pAttrArray->GetNextUnprotected(nRow, bUp);
     113             : }
     114             : 
     115      121505 : sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     116             : {
     117             :     using namespace sc;
     118             : 
     119      121505 :     if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
     120           0 :         return 0;
     121             : 
     122      121505 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     123             : 
     124      121505 :     if (nRow1 == nRow2)
     125             :     {
     126      120510 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     127      120510 :         if (aPos.first->type != sc::element_type_formula)
     128      120379 :             return 0;
     129             : 
     130         131 :         const ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
     131         131 :         if (!pCell->GetMatrixFlag())
     132         129 :             return 0;
     133             : 
     134           2 :         return pCell->GetMatrixEdge(aOrigin);
     135             :     }
     136             : 
     137         995 :     bool bOpen = false;
     138         995 :     sal_uInt16 nEdges = 0;
     139             : 
     140         995 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     141         995 :     sc::CellStoreType::const_iterator it = aPos.first;
     142         995 :     size_t nOffset = aPos.second;
     143         995 :     SCROW nRow = nRow1;
     144        2858 :     for (;it != maCells.end() && nRow <= nRow2; ++it, nOffset = 0)
     145             :     {
     146        1863 :         if (it->type != sc::element_type_formula)
     147             :         {
     148             :             // Skip this block.
     149        1803 :             nRow += it->size - nOffset;
     150        1803 :             continue;
     151             :         }
     152             : 
     153          60 :         size_t nRowsToRead = nRow2 - nRow + 1;
     154          60 :         size_t nEnd = std::min(it->size, nOffset+nRowsToRead); // last row + 1
     155          60 :         sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
     156          60 :         std::advance(itCell, nOffset);
     157         225 :         for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
     158             :         {
     159             :             // Loop inside the formula block.
     160         165 :             const ScFormulaCell* pCell = *itCell;
     161         165 :             if (!pCell->GetMatrixFlag())
     162         163 :                 continue;
     163             : 
     164           2 :             nEdges = pCell->GetMatrixEdge(aOrigin);
     165           2 :             if (!nEdges)
     166           0 :                 continue;
     167             : 
     168           2 :             if (nEdges & MatrixEdgeTop)
     169           1 :                 bOpen = true;       // top edge opens, keep on looking
     170           1 :             else if (!bOpen)
     171           0 :                 return nEdges | MatrixEdgeOpen; // there's something that wasn't opened
     172           1 :             else if (nEdges & MatrixEdgeInside)
     173           0 :                 return nEdges;      // inside
     174             :             // (nMask & 16 and  (4 and not 16)) or
     175             :             // (nMask & 4  and (16 and not 4))
     176           4 :             if (((nMask & MatrixEdgeRight) && (nEdges & MatrixEdgeLeft)  && !(nEdges & MatrixEdgeRight)) ||
     177           4 :                 ((nMask & MatrixEdgeLeft)  && (nEdges & MatrixEdgeRight) && !(nEdges & MatrixEdgeLeft)))
     178           0 :                 return nEdges;      // only left/right edge
     179             : 
     180           2 :             if (nEdges & MatrixEdgeBottom)
     181           1 :                 bOpen = false;      // bottom edge closes
     182             :         }
     183             : 
     184          60 :         nRow += nEnd;
     185             :     }
     186         995 :     if (bOpen)
     187           0 :         nEdges |= MatrixEdgeOpen; // not closed, matrix continues
     188             : 
     189         995 :     return nEdges;
     190             : }
     191             : 
     192         374 : bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
     193             : {
     194             :     using namespace sc;
     195             : 
     196         374 :     if (!rMark.IsMultiMarked())
     197           0 :         return false;
     198             : 
     199         374 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     200         374 :     ScAddress aCurOrigin = aOrigin;
     201             : 
     202         374 :     bool bOpen = false;
     203         374 :     ScRangeList aRanges = rMark.GetMarkedRanges();
     204        1792 :     for (size_t i = 0, n = aRanges.size(); i < n; ++i)
     205             :     {
     206        1418 :         const ScRange& r = *aRanges[i];
     207        1418 :         if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab)
     208        1044 :             continue;
     209             : 
     210        1418 :         if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol)
     211        1044 :             continue;
     212             : 
     213         374 :         SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row();
     214         374 :         SCROW nRow = nTop;
     215         374 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     216         374 :         sc::CellStoreType::const_iterator it = aPos.first;
     217         374 :         size_t nOffset = aPos.second;
     218             : 
     219         748 :         for (;it != maCells.end() && nRow <= nBottom; ++it, nOffset = 0)
     220             :         {
     221         374 :             if (it->type != sc::element_type_formula)
     222             :             {
     223             :                 // Skip this block.
     224         374 :                 nRow += it->size - nOffset;
     225         374 :                 continue;
     226             :             }
     227             : 
     228             :             // This is a formula cell block.
     229           0 :             size_t nRowsToRead = nBottom - nRow + 1;
     230           0 :             size_t nEnd = std::min(it->size, nRowsToRead);
     231           0 :             sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
     232           0 :             std::advance(itCell, nOffset);
     233           0 :             for (size_t j = nOffset; j < nEnd; ++itCell, ++j)
     234             :             {
     235             :                 // Loop inside the formula block.
     236           0 :                 const ScFormulaCell* pCell = *itCell;
     237           0 :                 if (!pCell->GetMatrixFlag())
     238             :                     // cell is not a part of a matrix.
     239           0 :                     continue;
     240             : 
     241           0 :                 sal_uInt16 nEdges = pCell->GetMatrixEdge(aOrigin);
     242           0 :                 if (!nEdges)
     243           0 :                     continue;
     244             : 
     245           0 :                 bool bFound = false;
     246             : 
     247           0 :                 if (nEdges & MatrixEdgeTop)
     248           0 :                     bOpen = true;   // top edge opens, keep on looking
     249           0 :                 else if (!bOpen)
     250           0 :                     return true;    // there's something that wasn't opened
     251           0 :                 else if (nEdges & MatrixEdgeInside)
     252           0 :                     bFound = true;  // inside, all selected?
     253             : 
     254           0 :                 if ((((nEdges & MatrixEdgeLeft) | MatrixEdgeRight) ^ ((nEdges & MatrixEdgeRight) | MatrixEdgeLeft)))
     255             :                     // either left or right, but not both.
     256           0 :                     bFound = true;  // only left/right edge, all selected?
     257             : 
     258           0 :                 if (nEdges & MatrixEdgeBottom)
     259           0 :                     bOpen = false;  // bottom edge closes
     260             : 
     261           0 :                 if (bFound)
     262             :                 {
     263             :                     // Check if the matrix is inside the selection in its entirety.
     264             :                     //
     265             :                     // TODO: It's more efficient to skip the matrix range if
     266             :                     // it's within selection, to avoid checking it again and
     267             :                     // again.
     268             : 
     269           0 :                     if (aCurOrigin != aOrigin)
     270             :                     {   // new matrix to check?
     271           0 :                         aCurOrigin = aOrigin;
     272             :                         const ScFormulaCell* pFCell;
     273           0 :                         if (pCell->GetMatrixFlag() == MM_REFERENCE)
     274           0 :                             pFCell = pDocument->GetFormulaCell(aOrigin);
     275             :                         else
     276           0 :                             pFCell = pCell;
     277             : 
     278             :                         SCCOL nC;
     279             :                         SCROW nR;
     280           0 :                         pFCell->GetMatColsRows(nC, nR);
     281           0 :                         ScRange aRange(aOrigin, ScAddress(aOrigin.Col()+nC-1, aOrigin.Row()+nR-1, aOrigin.Tab()));
     282           0 :                         if (rMark.IsAllMarked(aRange))
     283           0 :                             bFound = false;
     284             :                     }
     285             :                     else
     286           0 :                         bFound = false;     // done already
     287             :                 }
     288             : 
     289           0 :                 if (bFound)
     290           0 :                     return true;
     291             :             }
     292             : 
     293           0 :             nRow += nEnd;
     294             :         }
     295             :     }
     296             : 
     297         374 :     if (bOpen)
     298           0 :         return true;
     299             : 
     300         374 :     return false;
     301             : }
     302             : 
     303    15949553 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     304             : {
     305    15949553 :     return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
     306             : }
     307             : 
     308           0 : bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
     309             : {
     310           0 :     bool bFound = false;
     311             : 
     312             :     SCROW nTop;
     313             :     SCROW nBottom;
     314             : 
     315           0 :     if (rMark.IsMultiMarked())
     316             :     {
     317           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     318           0 :         while (aMarkIter.Next( nTop, nBottom ) && !bFound)
     319             :         {
     320           0 :             if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
     321           0 :                 bFound = true;
     322           0 :         }
     323             :     }
     324             : 
     325           0 :     return bFound;
     326             : }
     327             : 
     328       12380 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
     329             :                             SCCOL& rPaintCol, SCROW& rPaintRow,
     330             :                             bool bRefresh )
     331             : {
     332       12380 :     return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
     333             : }
     334             : 
     335      303104 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
     336             : {
     337             :     SCROW nTop;
     338             :     SCROW nBottom;
     339             : 
     340      303104 :     if ( rMark.IsMultiMarked() )
     341             :     {
     342      303104 :         const ScMarkArray* pArray = rMark.GetArray() + nCol;
     343      303104 :         if ( pArray->HasMarks() )
     344             :         {
     345       30237 :             ScMarkArrayIter aMarkIter( pArray );
     346       91529 :             while (aMarkIter.Next( nTop, nBottom ))
     347       61292 :                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
     348             :         }
     349             :     }
     350      303104 : }
     351             : 
     352       72372 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
     353             : {
     354       72372 :     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
     355       72372 : }
     356             : 
     357         206 : void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     358             :                             ScLineFlags& rFlags,
     359             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
     360             : {
     361         206 :     pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
     362         206 : }
     363             : 
     364        1908 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
     365             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
     366             : {
     367        1908 :     pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
     368        1908 : }
     369             : 
     370       46539 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
     371             : {
     372       46539 :     return pAttrArray->GetPattern( nRow );
     373             : }
     374             : 
     375       14330 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
     376             : {
     377       14330 :     return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
     378             : }
     379             : 
     380      109824 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
     381             : {
     382      109824 :     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     383      109824 :     const ScPatternAttr* pMaxPattern = 0;
     384      109824 :     size_t nMaxCount = 0;
     385             : 
     386      109824 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
     387             :     const ScPatternAttr* pPattern;
     388      109824 :     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
     389             : 
     390      331388 :     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
     391             :     {
     392      111740 :         size_t& rnCount = aAttrMap[ pPattern ];
     393      111740 :         rnCount += (nAttrRow2 - nAttrRow1 + 1);
     394      111740 :         if( rnCount > nMaxCount )
     395             :         {
     396      110826 :             pMaxPattern = pPattern;
     397      110826 :             nMaxCount = rnCount;
     398             :         }
     399             :     }
     400             : 
     401      109824 :     return pMaxPattern;
     402             : }
     403             : 
     404           0 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
     405             : {
     406             :     SCROW nPatStartRow, nPatEndRow;
     407           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     408           0 :     sal_uInt32 nFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     409           0 :     while (nEndRow > nPatEndRow)
     410             :     {
     411           0 :         nStartRow = nPatEndRow + 1;
     412           0 :         pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     413           0 :         sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     414           0 :         if (nFormat != nTmpFormat)
     415           0 :             return 0;
     416             :     }
     417           0 :     return nFormat;
     418             : }
     419             : 
     420       60852 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
     421             : {
     422       60852 :     return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
     423             : }
     424             : 
     425      210944 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
     426             : {
     427      210944 :     SCROW nTop = 0;
     428      210944 :     SCROW nBottom = 0;
     429      210944 :     bool bFound = false;
     430             : 
     431      210944 :     if ( rMark.IsMultiMarked() )
     432             :     {
     433      210944 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     434      429866 :         while (aMarkIter.Next( nTop, nBottom ))
     435             :         {
     436        7978 :             pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
     437        7978 :             bFound = true;
     438      210944 :         }
     439             :     }
     440             : 
     441      210944 :     if (!bFound)
     442      203546 :         return -1;
     443        7398 :     else if (nTop==0 && nBottom==MAXROW)
     444        4070 :         return 0;
     445             :     else
     446        3328 :         return nBottom;
     447             : }
     448             : 
     449        6144 : void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
     450             : {
     451             :     SCROW nTop;
     452             :     SCROW nBottom;
     453             : 
     454        6144 :     if ( pAttrArray && rMark.IsMultiMarked() )
     455             :     {
     456        6144 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     457       12314 :         while (aMarkIter.Next( nTop, nBottom ))
     458        6170 :             pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
     459             :     }
     460        6144 : }
     461             : 
     462           0 : void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
     463             : {
     464             :     SCROW nTop;
     465             :     SCROW nBottom;
     466             : 
     467           0 :     if ( pAttrArray && rMark.IsMultiMarked() )
     468             :     {
     469           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     470           0 :         while (aMarkIter.Next( nTop, nBottom ))
     471           0 :             pAttrArray->ClearItems(nTop, nBottom, pWhich);
     472             :     }
     473           0 : }
     474             : 
     475       95232 : void ScColumn::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast )
     476             : {
     477             :     SCROW nTop;
     478             :     SCROW nBottom;
     479             : 
     480       95232 :     if ( rMark.IsMultiMarked() )
     481             :     {
     482       94208 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     483      188606 :         while (aMarkIter.Next( nTop, nBottom ))
     484       94398 :             DeleteArea(nTop, nBottom, nDelFlag, bBroadcast);
     485             :     }
     486       95232 : }
     487             : 
     488         137 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
     489             : {
     490         137 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     491         137 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     492             : 
     493         137 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
     494             : 
     495             :     //  true = keep old content
     496             : 
     497         137 :     const ScPatternAttr* pNewPattern = static_cast<const ScPatternAttr*>( &aCache.ApplyTo( *pPattern, true ) );
     498         137 :     ScDocumentPool::CheckRef( *pPattern );
     499         137 :     ScDocumentPool::CheckRef( *pNewPattern );
     500             : 
     501         137 :     if (pNewPattern != pPattern)
     502         137 :       pAttrArray->SetPattern( nRow, pNewPattern );
     503         137 : }
     504             : 
     505      113615 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
     506             :                                  ScEditDataArray* pDataArray )
     507             : {
     508      113615 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     509      113615 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     510      113615 :     pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
     511      113615 : }
     512             : 
     513           0 : void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
     514             :         const ScPatternAttr& rPattern, short nNewType )
     515             : {
     516           0 :     const SfxItemSet* pSet = &rPattern.GetItemSet();
     517           0 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     518           0 :     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
     519           0 :     SCROW nEndRow = rRange.aEnd.Row();
     520           0 :     for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
     521             :     {
     522             :         SCROW nRow1, nRow2;
     523             :         const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
     524           0 :             nRow1, nRow2, nRow );
     525           0 :         sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
     526           0 :         short nOldType = pFormatter->GetType( nFormat );
     527           0 :         if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
     528           0 :             nRow = nRow2;
     529             :         else
     530             :         {
     531           0 :             SCROW nNewRow1 = std::max( nRow1, nRow );
     532           0 :             SCROW nNewRow2 = std::min( nRow2, nEndRow );
     533           0 :             pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
     534           0 :             nRow = nNewRow2;
     535             :         }
     536           0 :     }
     537           0 : }
     538             : 
     539        4343 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     540             : {
     541        4343 :     pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
     542        4343 : }
     543             : 
     544        2065 : void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     545             : {
     546        2065 :     pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex );
     547        2065 : }
     548             : 
     549           2 : void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
     550             : {
     551           2 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
     552           2 :     boost::scoped_ptr<ScPatternAttr> pNewPattern(new ScPatternAttr(*pPattern));
     553           2 :     if (pNewPattern)
     554             :     {
     555           2 :         pNewPattern->SetStyleSheet(const_cast<ScStyleSheet*>(&rStyle));
     556           2 :         pAttrArray->SetPattern(nRow, pNewPattern.get(), true);
     557           2 :     }
     558           2 : }
     559             : 
     560      393015 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
     561             : {
     562      393015 :     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, const_cast<ScStyleSheet*>(&rStyle));
     563      393015 : }
     564             : 
     565      293888 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
     566             : {
     567             :     SCROW nTop;
     568             :     SCROW nBottom;
     569             : 
     570      293888 :     if ( rMark.IsMultiMarked() )
     571             :     {
     572      293888 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     573      599143 :         while (aMarkIter.Next( nTop, nBottom ))
     574      305255 :             pAttrArray->ApplyStyleArea(nTop, nBottom, const_cast<ScStyleSheet*>(&rStyle));
     575             :     }
     576      293888 : }
     577             : 
     578           0 : void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
     579             :                                     const SvxBorderLine* pLine, bool bColorOnly )
     580             : {
     581           0 :     if ( bColorOnly && !pLine )
     582           0 :         return;
     583             : 
     584             :     SCROW nTop;
     585             :     SCROW nBottom;
     586             : 
     587           0 :     if (rMark.IsMultiMarked())
     588             :     {
     589           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     590           0 :         while (aMarkIter.Next( nTop, nBottom ))
     591           0 :             pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
     592             :     }
     593             : }
     594             : 
     595          92 : const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
     596             : {
     597          92 :     return pAttrArray->GetPattern( nRow )->GetStyleSheet();
     598             : }
     599             : 
     600       22528 : const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
     601             : {
     602       22528 :     rFound = false;
     603       22528 :     if (!rMark.IsMultiMarked())
     604             :     {
     605             :         OSL_FAIL("No selection in ScColumn::GetSelectionStyle");
     606           0 :         return NULL;
     607             :     }
     608             : 
     609       22528 :     bool bEqual = true;
     610             : 
     611       22528 :     const ScStyleSheet* pStyle = NULL;
     612             :     const ScStyleSheet* pNewStyle;
     613             : 
     614       22528 :     ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     615             :     SCROW nTop;
     616             :     SCROW nBottom;
     617       67626 :     while (bEqual && aMarkIter.Next( nTop, nBottom ))
     618             :     {
     619       22570 :         ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
     620             :         SCROW nRow;
     621             :         SCROW nDummy;
     622             :         const ScPatternAttr* pPattern;
     623       67710 :         while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     624             :         {
     625       22570 :             pNewStyle = pPattern->GetStyleSheet();
     626       22570 :             rFound = true;
     627       22570 :             if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     628           0 :                 bEqual = false;                                             // difference
     629       22570 :             pStyle = pNewStyle;
     630             :         }
     631             :     }
     632             : 
     633       22528 :     return bEqual ? pStyle : NULL;
     634             : }
     635             : 
     636       45340 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
     637             : {
     638       45340 :     rFound = false;
     639             : 
     640       45340 :     bool bEqual = true;
     641             : 
     642       45340 :     const ScStyleSheet* pStyle = NULL;
     643             :     const ScStyleSheet* pNewStyle;
     644             : 
     645       45340 :     ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
     646             :     SCROW nRow;
     647             :     SCROW nDummy;
     648             :     const ScPatternAttr* pPattern;
     649      136100 :     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     650             :     {
     651       45420 :         pNewStyle = pPattern->GetStyleSheet();
     652       45420 :         rFound = true;
     653       45420 :         if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     654           0 :             bEqual = false;                                             // difference
     655       45420 :         pStyle = pNewStyle;
     656             :     }
     657             : 
     658       45340 :     return bEqual ? pStyle : NULL;
     659             : }
     660             : 
     661     6942720 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
     662             : {
     663     6942720 :     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
     664     6942720 : }
     665             : 
     666           0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
     667             : {
     668           0 :     return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
     669             : }
     670             : 
     671        5486 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     672             : {
     673        5486 :     return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
     674             : }
     675             : 
     676       18226 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     677             : {
     678       18226 :     return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
     679             : }
     680             : 
     681         159 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
     682             : {
     683         159 :     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
     684         159 : }
     685             : 
     686         163 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
     687             : {
     688         163 :     pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
     689         163 : }
     690             : 
     691          34 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
     692             :                                 const ScPatternAttr& rPatAttr, bool bPutToPool )
     693             : {
     694          34 :     pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
     695          34 : }
     696             : 
     697        3054 : void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
     698             : {
     699             :     //  in order to only create a new SetItem, we don't need SfxItemPoolCache.
     700             :     //TODO: Warning: SfxItemPoolCache seems to create to many Refs for the new SetItem ??
     701             : 
     702        3054 :     ScDocumentPool* pDocPool = pDocument->GetPool();
     703             : 
     704        3054 :     const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
     705        3054 :     boost::scoped_ptr<ScPatternAttr> pTemp(new ScPatternAttr(*pOldPattern));
     706        3054 :     pTemp->GetItemSet().Put(rAttr);
     707        3054 :     const ScPatternAttr* pNewPattern = static_cast<const ScPatternAttr*>( &pDocPool->Put( *pTemp ) );
     708             : 
     709        3054 :     if ( pNewPattern != pOldPattern )
     710        2739 :         pAttrArray->SetPattern( nRow, pNewPattern );
     711             :     else
     712         315 :         pDocPool->Remove( *pNewPattern );       // free up resources
     713        3054 : }
     714             : 
     715      343961 : ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const
     716             : {
     717      343961 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     718      343961 :     if (aPos.first == maCells.end())
     719           0 :         return ScRefCellValue();
     720             : 
     721      343961 :     return GetCellValue(aPos.first, aPos.second);
     722             : }
     723             : 
     724         749 : ScRefCellValue ScColumn::GetCellValue( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const
     725             : {
     726         749 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow);
     727         749 :     if (aPos.first == maCells.end())
     728           0 :         return ScRefCellValue();
     729             : 
     730         749 :     rBlockPos.miCellPos = aPos.first; // Store this for next call.
     731         749 :     return GetCellValue(aPos.first, aPos.second);
     732             : }
     733             : 
     734      371107 : ScRefCellValue ScColumn::GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
     735             : {
     736      371107 :     ScRefCellValue aVal; // Defaults to empty cell.
     737      371107 :     switch (itPos->type)
     738             :     {
     739             :         case sc::element_type_numeric:
     740             :             // Numeric cell
     741       54895 :             aVal.mfValue = sc::numeric_block::at(*itPos->data, nOffset);
     742       54895 :             aVal.meType = CELLTYPE_VALUE;
     743       54895 :         break;
     744             :         case sc::element_type_string:
     745             :             // String cell
     746       23472 :             aVal.mpString = &sc::string_block::at(*itPos->data, nOffset);
     747       23472 :             aVal.meType = CELLTYPE_STRING;
     748       23472 :         break;
     749             :         case sc::element_type_edittext:
     750             :             // Edit cell
     751         923 :             aVal.mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
     752         923 :             aVal.meType = CELLTYPE_EDIT;
     753         923 :         break;
     754             :         case sc::element_type_formula:
     755             :             // Formula cell
     756       28728 :             aVal.mpFormula = sc::formula_block::at(*itPos->data, nOffset);
     757       28728 :             aVal.meType = CELLTYPE_FORMULA;
     758       28728 :         break;
     759             :         default:
     760             :             ;
     761             :     }
     762             : 
     763      371107 :     return aVal;
     764             : }
     765             : 
     766          17 : const sc::CellTextAttr* ScColumn::GetCellTextAttr( SCROW nRow ) const
     767             : {
     768          17 :     sc::ColumnBlockConstPosition aBlockPos;
     769          17 :     aBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
     770          17 :     return GetCellTextAttr(aBlockPos, nRow);
     771             : }
     772             : 
     773         616 : const sc::CellTextAttr* ScColumn::GetCellTextAttr( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const
     774             : {
     775         616 :     sc::CellTextAttrStoreType::const_position_type aPos = maCellTextAttrs.position(rBlockPos.miCellTextAttrPos, nRow);
     776         616 :     if (aPos.first == maCellTextAttrs.end())
     777           0 :         return NULL;
     778             : 
     779         616 :     rBlockPos.miCellTextAttrPos = aPos.first;
     780             : 
     781         616 :     if (aPos.first->type != sc::element_type_celltextattr)
     782          10 :         return NULL;
     783             : 
     784         606 :     return &sc::celltextattr_block::at(*aPos.first->data, aPos.second);
     785             : }
     786             : 
     787          60 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
     788             : {
     789          60 :     if (IsEmpty())
     790          60 :         return true;
     791             : 
     792             :     // Return false if we have any non-empty cells between nStartRow and nEndRow inclusive.
     793           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
     794           0 :     sc::CellStoreType::const_iterator it = aPos.first;
     795           0 :     if (it->type != sc::element_type_empty)
     796           0 :         return false;
     797             : 
     798             :     // Get the length of the remaining empty segment.
     799           0 :     size_t nLen = it->size - aPos.second;
     800           0 :     SCROW nNextNonEmptyRow = nStartRow + nLen;
     801           0 :     if (nNextNonEmptyRow <= nEndRow)
     802           0 :         return false;
     803             : 
     804             :     //  AttrArray only looks for merged cells
     805             : 
     806           0 :     return pAttrArray == nullptr || pAttrArray->TestInsertCol(nStartRow, nEndRow);
     807             : }
     808             : 
     809       46089 : bool ScColumn::TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const
     810             : {
     811             :     //  AttrArray only looks for merged cells
     812             :     {
     813       46089 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
     814       46089 :         sc::CellStoreType::const_iterator it = aPos.first;
     815       46089 :         if (it->type == sc::element_type_empty && maCells.block_size() == 1)
     816             :             // The entire cell array is empty.
     817       46019 :             return pAttrArray->TestInsertRow(nSize);
     818             :     }
     819             : 
     820             :     // See if there would be any non-empty cell that gets pushed out.
     821             : 
     822             :     // Find the position of the last non-empty cell below nStartRow.
     823          70 :     size_t nLastNonEmptyRow = MAXROW;
     824          70 :     sc::CellStoreType::const_reverse_iterator it = maCells.rbegin();
     825          70 :     if (it->type == sc::element_type_empty)
     826          70 :         nLastNonEmptyRow -= it->size;
     827             : 
     828          70 :     if (nLastNonEmptyRow < static_cast<size_t>(nStartRow))
     829             :         // No cells would get pushed out.
     830          21 :         return pAttrArray->TestInsertRow(nSize);
     831             : 
     832          49 :     if (nLastNonEmptyRow + nSize > static_cast<size_t>(MAXROW))
     833             :         // At least one cell would get pushed out. Not good.
     834           0 :         return false;
     835             : 
     836          49 :     return pAttrArray->TestInsertRow(nSize);
     837             : }
     838             : 
     839       46089 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
     840             : {
     841       46089 :     pAttrArray->InsertRow( nStartRow, nSize );
     842             : 
     843       46089 :     maCellNotes.insert_empty(nStartRow, nSize);
     844       46089 :     maCellNotes.resize(MAXROWCOUNT);
     845             : 
     846       46089 :     maBroadcasters.insert_empty(nStartRow, nSize);
     847       46089 :     maBroadcasters.resize(MAXROWCOUNT);
     848             : 
     849       46089 :     maCellTextAttrs.insert_empty(nStartRow, nSize);
     850       46089 :     maCellTextAttrs.resize(MAXROWCOUNT);
     851             : 
     852       46089 :     maCells.insert_empty(nStartRow, nSize);
     853       46089 :     maCells.resize(MAXROWCOUNT);
     854             : 
     855       46089 :     CellStorageModified();
     856             : 
     857             :     // We *probably* don't need to broadcast here since the parent call seems
     858             :     // to take care of it.
     859       46089 : }
     860             : 
     861             : namespace {
     862             : 
     863             : class CopyToClipHandler
     864             : {
     865             :     const ScColumn& mrSrcCol;
     866             :     ScColumn& mrDestCol;
     867             :     sc::ColumnBlockPosition maDestPos;
     868             :     sc::ColumnBlockPosition* mpDestPos;
     869             :     bool mbCopyNotes;
     870             : 
     871          81 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
     872             :     {
     873          81 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
     874         162 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
     875         162 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
     876          81 :     }
     877             : 
     878         105 :     void duplicateNotes(SCROW nStartRow, size_t nDataSize )
     879             :     {
     880         105 :         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestPos, false);
     881         105 :     }
     882             : 
     883             : public:
     884          80 :     CopyToClipHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, bool bCopyNotes) :
     885          80 :         mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mbCopyNotes(bCopyNotes)
     886             :     {
     887          80 :         if (mpDestPos)
     888          80 :             maDestPos = *mpDestPos;
     889             :         else
     890           0 :             mrDestCol.InitBlockPosition(maDestPos);
     891          80 :     }
     892             : 
     893          80 :     ~CopyToClipHandler()
     894             :     {
     895          80 :         if (mpDestPos)
     896          80 :             *mpDestPos = maDestPos;
     897          80 :     }
     898             : 
     899         105 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
     900             :     {
     901         105 :         size_t nTopRow = aNode.position + nOffset;
     902             : 
     903         105 :         bool bSet = true;
     904             : 
     905         105 :         switch (aNode.type)
     906             :         {
     907             :             case sc::element_type_numeric:
     908             :             {
     909          37 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
     910          37 :                 std::advance(it, nOffset);
     911          37 :                 sc::numeric_block::const_iterator itEnd = it;
     912          37 :                 std::advance(itEnd, nDataSize);
     913          37 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
     914             :             }
     915          37 :             break;
     916             :             case sc::element_type_string:
     917             :             {
     918          21 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
     919          21 :                 std::advance(it, nOffset);
     920          21 :                 sc::string_block::const_iterator itEnd = it;
     921          21 :                 std::advance(itEnd, nDataSize);
     922          21 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
     923             : 
     924             :             }
     925          21 :             break;
     926             :             case sc::element_type_edittext:
     927             :             {
     928           0 :                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
     929           0 :                 std::advance(it, nOffset);
     930           0 :                 sc::edittext_block::const_iterator itEnd = it;
     931           0 :                 std::advance(itEnd, nDataSize);
     932             : 
     933           0 :                 std::vector<EditTextObject*> aCloned;
     934           0 :                 aCloned.reserve(nDataSize);
     935           0 :                 for (; it != itEnd; ++it)
     936           0 :                     aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
     937             : 
     938           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
     939           0 :                     maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
     940             :             }
     941           0 :             break;
     942             :             case sc::element_type_formula:
     943             :             {
     944          23 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
     945          23 :                 std::advance(it, nOffset);
     946          23 :                 sc::formula_block::const_iterator itEnd = it;
     947          23 :                 std::advance(itEnd, nDataSize);
     948             : 
     949          23 :                 std::vector<ScFormulaCell*> aCloned;
     950          23 :                 aCloned.reserve(nDataSize);
     951          23 :                 ScAddress aDestPos(mrDestCol.GetCol(), nTopRow, mrDestCol.GetTab());
     952          63 :                 for (; it != itEnd; ++it, aDestPos.IncRow())
     953             :                 {
     954          40 :                     const ScFormulaCell& rOld = **it;
     955          40 :                     if (rOld.GetDirty() && mrSrcCol.GetDoc().GetAutoCalc())
     956          16 :                         const_cast<ScFormulaCell&>(rOld).Interpret();
     957             : 
     958          40 :                     aCloned.push_back(new ScFormulaCell(rOld, mrDestCol.GetDoc(), aDestPos));
     959             :                 }
     960             : 
     961             :                 // Group the cloned formula cells.
     962          23 :                 if (!aCloned.empty())
     963          23 :                     sc::SharedFormulaUtil::groupFormulaCells(aCloned.begin(), aCloned.end());
     964             : 
     965          23 :                 sc::CellStoreType& rDestCells = mrDestCol.GetCellStore();
     966          46 :                 maDestPos.miCellPos = rDestCells.set(
     967          23 :                     maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
     968             : 
     969             :                 // Merge adjacent formula cell groups (if applicable).
     970             :                 sc::CellStoreType::position_type aPos =
     971          23 :                     rDestCells.position(maDestPos.miCellPos, nTopRow);
     972          23 :                 maDestPos.miCellPos = aPos.first;
     973          23 :                 sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
     974          23 :                 size_t nLastRow = nTopRow + nDataSize;
     975          23 :                 if (nLastRow < static_cast<size_t>(MAXROW))
     976             :                 {
     977          23 :                     aPos = rDestCells.position(maDestPos.miCellPos, nLastRow+1);
     978          23 :                     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
     979          23 :                 }
     980             :             }
     981          23 :             break;
     982             :             default:
     983          24 :                 bSet = false;
     984             :         }
     985             : 
     986         105 :         if (bSet)
     987          81 :             setDefaultAttrsToDest(nTopRow, nDataSize);
     988             : 
     989         105 :         if (mbCopyNotes)
     990         105 :             duplicateNotes(nTopRow, nDataSize);
     991         105 :     }
     992             : };
     993             : 
     994             : class CopyTextAttrToClipHandler
     995             : {
     996             :     sc::CellTextAttrStoreType& mrDestAttrs;
     997             :     sc::CellTextAttrStoreType::iterator miPos;
     998             : 
     999             : public:
    1000          80 :     CopyTextAttrToClipHandler( sc::CellTextAttrStoreType& rAttrs ) :
    1001          80 :         mrDestAttrs(rAttrs), miPos(mrDestAttrs.begin()) {}
    1002             : 
    1003          94 :     void operator() ( const sc::CellTextAttrStoreType::value_type& aNode, size_t nOffset, size_t nDataSize )
    1004             :     {
    1005          94 :         if (aNode.type != sc::element_type_celltextattr)
    1006         118 :             return;
    1007             : 
    1008          70 :         sc::celltextattr_block::const_iterator it = sc::celltextattr_block::begin(*aNode.data);
    1009          70 :         std::advance(it, nOffset);
    1010          70 :         sc::celltextattr_block::const_iterator itEnd = it;
    1011          70 :         std::advance(itEnd, nDataSize);
    1012             : 
    1013          70 :         size_t nPos = aNode.position + nOffset;
    1014          70 :         miPos = mrDestAttrs.set(miPos, nPos, it, itEnd);
    1015             :     }
    1016             : };
    1017             : 
    1018             : 
    1019             : }
    1020             : 
    1021          80 : void ScColumn::CopyToClip(
    1022             :     sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const
    1023             : {
    1024             :     pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
    1025          80 :                           rCxt.isKeepScenarioFlags() ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
    1026             : 
    1027             :     {
    1028          80 :         CopyToClipHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), rCxt.isCloneNotes());
    1029          80 :         sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1030             :     }
    1031             : 
    1032             :     {
    1033          80 :         CopyTextAttrToClipHandler aFunc(rColumn.maCellTextAttrs);
    1034          80 :         sc::ParseBlock(maCellTextAttrs.begin(), maCellTextAttrs, aFunc, nRow1, nRow2);
    1035             :     }
    1036             : 
    1037          80 :     rColumn.CellStorageModified();
    1038          80 : }
    1039             : 
    1040           6 : void ScColumn::CopyStaticToDocument(
    1041             :     SCROW nRow1, SCROW nRow2, const SvNumberFormatterMergeMap& rMap, ScColumn& rDestCol )
    1042             : {
    1043           6 :     if (nRow1 > nRow2)
    1044           6 :         return;
    1045             : 
    1046           6 :     sc::ColumnBlockPosition aDestPos;
    1047           6 :     CopyCellTextAttrsToDocument(nRow1, nRow2, rDestCol);
    1048           6 :     CopyCellNotesToDocument(nRow1, nRow2, rDestCol);
    1049             : 
    1050             :     // First, clear the destination column for the specified row range.
    1051           6 :     rDestCol.maCells.set_empty(nRow1, nRow2);
    1052             : 
    1053           6 :     aDestPos.miCellPos = rDestCol.maCells.begin();
    1054             : 
    1055           6 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
    1056           6 :     sc::CellStoreType::const_iterator it = aPos.first;
    1057           6 :     size_t nOffset = aPos.second;
    1058           6 :     size_t nDataSize = 0;
    1059           6 :     size_t nCurRow = nRow1;
    1060             : 
    1061           9 :     for (; it != maCells.end() && nCurRow <= static_cast<size_t>(nRow2); ++it, nOffset = 0, nCurRow += nDataSize)
    1062             :     {
    1063           7 :         bool bLastBlock = false;
    1064           7 :         nDataSize = it->size - nOffset;
    1065           7 :         if (nCurRow + nDataSize - 1 > static_cast<size_t>(nRow2))
    1066             :         {
    1067             :             // Truncate the block to copy to clipboard.
    1068           4 :             nDataSize = nRow2 - nCurRow + 1;
    1069           4 :             bLastBlock = true;
    1070             :         }
    1071             : 
    1072           7 :         switch (it->type)
    1073             :         {
    1074             :             case sc::element_type_numeric:
    1075             :             {
    1076           4 :                 sc::numeric_block::const_iterator itData = sc::numeric_block::begin(*it->data);
    1077           4 :                 std::advance(itData, nOffset);
    1078           4 :                 sc::numeric_block::const_iterator itDataEnd = itData;
    1079           4 :                 std::advance(itDataEnd, nDataSize);
    1080           4 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1081             :             }
    1082           4 :             break;
    1083             :             case sc::element_type_string:
    1084             :             {
    1085           1 :                 sc::string_block::const_iterator itData = sc::string_block::begin(*it->data);
    1086           1 :                 std::advance(itData, nOffset);
    1087           1 :                 sc::string_block::const_iterator itDataEnd = itData;
    1088           1 :                 std::advance(itDataEnd, nDataSize);
    1089           1 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1090             :             }
    1091           1 :             break;
    1092             :             case sc::element_type_edittext:
    1093             :             {
    1094           0 :                 sc::edittext_block::const_iterator itData = sc::edittext_block::begin(*it->data);
    1095           0 :                 std::advance(itData, nOffset);
    1096           0 :                 sc::edittext_block::const_iterator itDataEnd = itData;
    1097           0 :                 std::advance(itDataEnd, nDataSize);
    1098             : 
    1099             :                 // Convert to simple strings.
    1100           0 :                 std::vector<svl::SharedString> aConverted;
    1101           0 :                 aConverted.reserve(nDataSize);
    1102           0 :                 for (; itData != itDataEnd; ++itData)
    1103             :                 {
    1104           0 :                     const EditTextObject& rObj = **itData;
    1105           0 :                     svl::SharedString aSS = pDocument->GetSharedStringPool().intern(ScEditUtil::GetString(rObj, pDocument));
    1106           0 :                     aConverted.push_back(aSS);
    1107           0 :                 }
    1108           0 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, aConverted.begin(), aConverted.end());
    1109             :             }
    1110           0 :             break;
    1111             :             case sc::element_type_formula:
    1112             :             {
    1113           1 :                 sc::formula_block::const_iterator itData = sc::formula_block::begin(*it->data);
    1114           1 :                 std::advance(itData, nOffset);
    1115           1 :                 sc::formula_block::const_iterator itDataEnd = itData;
    1116           1 :                 std::advance(itDataEnd, nDataSize);
    1117             : 
    1118             :                 // Interpret and convert to raw values.
    1119           2 :                 for (SCROW i = 0; itData != itDataEnd; ++itData, ++i)
    1120             :                 {
    1121           1 :                     SCROW nRow = nCurRow + i;
    1122             : 
    1123           1 :                     ScFormulaCell& rFC = const_cast<ScFormulaCell&>(**itData);
    1124           1 :                     if (rFC.GetDirty() && pDocument->GetAutoCalc())
    1125           0 :                         rFC.Interpret();
    1126             : 
    1127           1 :                     if (rFC.GetErrCode())
    1128             :                         // Skip cells with error.
    1129           0 :                         break;
    1130             : 
    1131           1 :                     if (rFC.IsValue())
    1132           1 :                         aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetValue());
    1133             :                     else
    1134             :                     {
    1135           0 :                         svl::SharedString aSS = rFC.GetString();
    1136           0 :                         if (aSS.isValid())
    1137           0 :                             aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, aSS);
    1138             :                     }
    1139             :                 }
    1140             :             }
    1141           1 :             break;
    1142             :             default:
    1143             :                 ;
    1144             :         }
    1145             : 
    1146           7 :         if (bLastBlock)
    1147           4 :             break;
    1148             :     }
    1149             : 
    1150             :     // Dont' forget to copy the number formats over.  Charts may reference them.
    1151          17 :     for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
    1152             :     {
    1153          11 :         sal_uInt32 nNumFmt = GetNumberFormat(nRow);
    1154          11 :         SvNumberFormatterMergeMap::const_iterator itNum = rMap.find(nNumFmt);
    1155          11 :         if (itNum != rMap.end())
    1156           3 :             nNumFmt = itNum->second;
    1157             : 
    1158          11 :         rDestCol.SetNumberFormat(nRow, nNumFmt);
    1159             :     }
    1160             : 
    1161           6 :     rDestCol.CellStorageModified();
    1162             : }
    1163             : 
    1164           1 : void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol )
    1165             : {
    1166           1 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nSrcRow);
    1167           1 :     sc::CellStoreType::const_iterator it = aPos.first;
    1168           1 :     bool bSet = true;
    1169           1 :     switch (it->type)
    1170             :     {
    1171             :         case sc::element_type_numeric:
    1172           0 :             rDestCol.maCells.set(nDestRow, sc::numeric_block::at(*it->data, aPos.second));
    1173           0 :         break;
    1174             :         case sc::element_type_string:
    1175           1 :             rDestCol.maCells.set(nDestRow, sc::string_block::at(*it->data, aPos.second));
    1176           1 :         break;
    1177             :         case sc::element_type_edittext:
    1178             :         {
    1179           0 :             EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second);
    1180           0 :             if (pDocument == rDestCol.pDocument)
    1181           0 :                 rDestCol.maCells.set(nDestRow, p->Clone());
    1182             :             else
    1183           0 :                 rDestCol.maCells.set(nDestRow, ScEditUtil::Clone(*p, *rDestCol.pDocument));
    1184             :         }
    1185           0 :         break;
    1186             :         case sc::element_type_formula:
    1187             :         {
    1188           0 :             ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
    1189           0 :             if (p->GetDirty() && pDocument->GetAutoCalc())
    1190           0 :                 p->Interpret();
    1191             : 
    1192           0 :             ScAddress aDestPos = p->aPos;
    1193           0 :             aDestPos.SetRow(nDestRow);
    1194           0 :             ScFormulaCell* pNew = new ScFormulaCell(*p, *rDestCol.pDocument, aDestPos);
    1195           0 :             rDestCol.SetFormulaCell(nDestRow, pNew);
    1196             :         }
    1197           0 :         break;
    1198             :         case sc::element_type_empty:
    1199             :         default:
    1200             :             // empty
    1201           0 :             rDestCol.maCells.set_empty(nDestRow, nDestRow);
    1202           0 :             bSet = false;
    1203             :     }
    1204             : 
    1205           1 :     if (bSet)
    1206             :     {
    1207           1 :         rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
    1208           1 :         ScPostIt* pNote = maCellNotes.get<ScPostIt*>(nSrcRow);
    1209           1 :         rDestCol.maCellNotes.set(nDestRow, pNote);
    1210           1 :         if (pNote)
    1211           0 :             pNote->UpdateCaptionPos(ScAddress(rDestCol.nCol, nDestRow, rDestCol.nTab));
    1212             :     }
    1213             :     else
    1214             :     {
    1215           0 :         rDestCol.maCellTextAttrs.set_empty(nDestRow, nDestRow);
    1216           0 :         rDestCol.maCellNotes.set_empty(nDestRow, nDestRow);
    1217             :     }
    1218             : 
    1219           1 :     rDestCol.CellStorageModified();
    1220           1 : }
    1221             : 
    1222             : namespace {
    1223             : 
    1224        1346 : bool canCopyValue(const ScDocument& rDoc, const ScAddress& rPos, InsertDeleteFlags nFlags)
    1225             : {
    1226        1346 :     sal_uInt32 nNumIndex = static_cast<const SfxUInt32Item*>(rDoc.GetAttr(rPos, ATTR_VALUE_FORMAT))->GetValue();
    1227        1346 :     short nType = rDoc.GetFormatTable()->GetType(nNumIndex);
    1228        1346 :     if ((nType == css::util::NumberFormat::DATE) || (nType == css::util::NumberFormat::TIME) || (nType == css::util::NumberFormat::DATETIME))
    1229           0 :         return ((nFlags & IDF_DATETIME) != IDF_NONE);
    1230             : 
    1231        1346 :     return (nFlags & IDF_VALUE) != IDF_NONE;
    1232             : }
    1233             : 
    1234             : class CopyAsLinkHandler
    1235             : {
    1236             :     const ScColumn& mrSrcCol;
    1237             :     ScColumn& mrDestCol;
    1238             :     sc::ColumnBlockPosition maDestPos;
    1239             :     sc::ColumnBlockPosition* mpDestPos;
    1240             :     InsertDeleteFlags mnCopyFlags;
    1241             : 
    1242             :     sc::StartListeningType meListenType;
    1243             : 
    1244           0 :     void setDefaultAttrToDest(size_t nRow)
    1245             :     {
    1246           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1247           0 :             maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
    1248           0 :     }
    1249             : 
    1250           0 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1251             :     {
    1252           0 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1253           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1254           0 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1255           0 :     }
    1256             : 
    1257           0 :     ScFormulaCell* createRefCell(size_t nRow)
    1258             :     {
    1259             :         ScSingleRefData aRef;
    1260           0 :         aRef.InitAddress(ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab())); // Absolute reference.
    1261           0 :         aRef.SetFlag3D(true);
    1262             : 
    1263           0 :         ScTokenArray aArr;
    1264           0 :         aArr.AddSingleReference(aRef);
    1265           0 :         return new ScFormulaCell(&mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), aArr);
    1266             :     }
    1267             : 
    1268           0 :     void createRefBlock(const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1269             :     {
    1270           0 :         size_t nTopRow = aNode.position + nOffset;
    1271             : 
    1272           0 :         for (size_t i = 0; i < nDataSize; ++i)
    1273             :         {
    1274           0 :             SCROW nRow = nTopRow + i;
    1275           0 :             mrDestCol.SetFormulaCell(maDestPos, nRow, createRefCell(nRow), meListenType);
    1276             :         }
    1277             : 
    1278           0 :         setDefaultAttrsToDest(nTopRow, nDataSize);
    1279           0 :     }
    1280             : 
    1281           0 :     void duplicateNotes(SCROW nStartRow, size_t nDataSize, bool bCloneCaption )
    1282             :     {
    1283           0 :         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestPos, bCloneCaption);
    1284           0 :     }
    1285             : 
    1286             : public:
    1287           0 :     CopyAsLinkHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, InsertDeleteFlags nCopyFlags) :
    1288             :         mrSrcCol(rSrcCol),
    1289             :         mrDestCol(rDestCol),
    1290             :         mpDestPos(pDestPos),
    1291             :         mnCopyFlags(nCopyFlags),
    1292           0 :         meListenType(sc::SingleCellListening)
    1293             :     {
    1294           0 :         if (mpDestPos)
    1295           0 :             maDestPos = *mpDestPos;
    1296           0 :     }
    1297             : 
    1298           0 :     ~CopyAsLinkHandler()
    1299             :     {
    1300           0 :         if (mpDestPos)
    1301           0 :             *mpDestPos = maDestPos;
    1302           0 :     }
    1303             : 
    1304           0 :     void setStartListening( bool b )
    1305             :     {
    1306           0 :         meListenType = b ? sc::SingleCellListening : sc::NoListening;
    1307           0 :     }
    1308             : 
    1309           0 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1310             :     {
    1311           0 :         size_t nRow = aNode.position + nOffset;
    1312             : 
    1313           0 :         if (mnCopyFlags & (IDF_NOTE|IDF_ADDNOTES))
    1314             :         {
    1315           0 :             bool bCloneCaption = (mnCopyFlags & IDF_NOCAPTIONS) == IDF_NONE;
    1316           0 :             duplicateNotes(nRow, nDataSize, bCloneCaption );
    1317             :         }
    1318             : 
    1319           0 :         switch (aNode.type)
    1320             :         {
    1321             :             case sc::element_type_numeric:
    1322             :             {
    1323           0 :                 if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == IDF_NONE)
    1324           0 :                     return;
    1325             : 
    1326           0 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1327           0 :                 std::advance(it, nOffset);
    1328           0 :                 sc::numeric_block::const_iterator itEnd = it;
    1329           0 :                 std::advance(itEnd, nDataSize);
    1330             : 
    1331           0 :                 ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
    1332           0 :                 for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
    1333             :                 {
    1334           0 :                     if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
    1335           0 :                         continue;
    1336             : 
    1337           0 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, createRefCell(nRow));
    1338           0 :                     setDefaultAttrToDest(nRow);
    1339             :                 }
    1340             :             }
    1341           0 :             break;
    1342             :             case sc::element_type_string:
    1343             :             case sc::element_type_edittext:
    1344             :             {
    1345           0 :                 if (!(mnCopyFlags & IDF_STRING))
    1346           0 :                     return;
    1347             : 
    1348           0 :                 createRefBlock(aNode, nOffset, nDataSize);
    1349             :             }
    1350           0 :             break;
    1351             :             case sc::element_type_formula:
    1352             :             {
    1353           0 :                 if (!(mnCopyFlags & IDF_FORMULA))
    1354           0 :                     return;
    1355             : 
    1356           0 :                 createRefBlock(aNode, nOffset, nDataSize);
    1357             :             }
    1358           0 :             break;
    1359             :             default:
    1360             :                 ;
    1361             :         }
    1362             :     }
    1363             : };
    1364             : 
    1365             : class CopyByCloneHandler
    1366             : {
    1367             :     const ScColumn& mrSrcCol;
    1368             :     ScColumn& mrDestCol;
    1369             :     sc::ColumnBlockPosition maDestPos;
    1370             :     sc::ColumnBlockPosition* mpDestPos;
    1371             :     svl::SharedStringPool* mpSharedStringPool;
    1372             :     InsertDeleteFlags mnCopyFlags;
    1373             : 
    1374             :     sc::StartListeningType meListenType;
    1375             : 
    1376        2651 :     void setDefaultAttrToDest(size_t nRow)
    1377             :     {
    1378        5302 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1379        2651 :             maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
    1380        2651 :     }
    1381             : 
    1382           4 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1383             :     {
    1384           4 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1385           8 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1386           8 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1387           4 :     }
    1388             : 
    1389         265 :     void cloneFormulaCell(size_t nRow, ScFormulaCell& rSrcCell)
    1390             :     {
    1391         265 :         ScAddress aDestPos(mrDestCol.GetCol(), nRow, mrDestCol.GetTab());
    1392             : 
    1393         265 :         bool bCloneValue          = (mnCopyFlags & IDF_VALUE) != IDF_NONE;
    1394         265 :         bool bCloneDateTime       = (mnCopyFlags & IDF_DATETIME) != IDF_NONE;
    1395         265 :         bool bCloneString         = (mnCopyFlags & IDF_STRING) != IDF_NONE;
    1396         265 :         bool bCloneSpecialBoolean = (mnCopyFlags & IDF_SPECIAL_BOOLEAN) != IDF_NONE;
    1397         265 :         bool bCloneFormula        = (mnCopyFlags & IDF_FORMULA) != IDF_NONE;
    1398             : 
    1399         265 :         bool bForceFormula = false;
    1400             : 
    1401         265 :         if (bCloneSpecialBoolean)
    1402             :         {
    1403             :             // See if the formula consists of =TRUE() or =FALSE().
    1404           0 :             ScTokenArray* pCode = rSrcCell.GetCode();
    1405           0 :             if (pCode && pCode->GetLen() == 1)
    1406             :             {
    1407           0 :                 const formula::FormulaToken* p = pCode->First();
    1408           0 :                 if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
    1409             :                     // This is a boolean formula.
    1410           0 :                     bForceFormula = true;
    1411             :             }
    1412             :         }
    1413             : 
    1414         265 :         if (bForceFormula || bCloneFormula)
    1415             :         {
    1416             :             // Clone as formula cell.
    1417         265 :             ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos);
    1418         265 :             pCell->SetDirtyVar();
    1419         265 :             mrDestCol.SetFormulaCell(maDestPos, nRow, pCell, meListenType);
    1420         265 :             setDefaultAttrToDest(nRow);
    1421         530 :             return;
    1422             :         }
    1423             : 
    1424           0 :         if (mrDestCol.GetDoc().IsUndo())
    1425           0 :             return;
    1426             : 
    1427           0 :         if (bCloneValue)
    1428             :         {
    1429           0 :             sal_uInt16 nErr = rSrcCell.GetErrCode();
    1430           0 :             if (nErr)
    1431             :             {
    1432             :                 // error codes are cloned with values
    1433           0 :                 ScFormulaCell* pErrCell = new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos);
    1434           0 :                 pErrCell->SetErrCode(nErr);
    1435           0 :                 mrDestCol.SetFormulaCell(maDestPos, nRow, pErrCell, meListenType);
    1436           0 :                 setDefaultAttrToDest(nRow);
    1437           0 :                 return;
    1438             :             }
    1439             :         }
    1440             : 
    1441           0 :         if (bCloneValue || bCloneDateTime)
    1442             :         {
    1443           0 :             if (rSrcCell.IsValue())
    1444             :             {
    1445           0 :                 if (canCopyValue(mrSrcCol.GetDoc(), ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab()), mnCopyFlags))
    1446             :                 {
    1447           0 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1448           0 :                         maDestPos.miCellPos, nRow, rSrcCell.GetValue());
    1449           0 :                     setDefaultAttrToDest(nRow);
    1450             :                 }
    1451             : 
    1452           0 :                 return;
    1453             :             }
    1454             :         }
    1455             : 
    1456           0 :         if (bCloneString)
    1457             :         {
    1458           0 :             svl::SharedString aStr = rSrcCell.GetString();
    1459           0 :             if (aStr.isEmpty())
    1460             :                 // Don't create empty string cells.
    1461           0 :                 return;
    1462             : 
    1463           0 :             if (rSrcCell.IsMultilineResult())
    1464             :             {
    1465             :                 // Clone as an edit text object.
    1466           0 :                 EditEngine& rEngine = mrDestCol.GetDoc().GetEditEngine();
    1467           0 :                 rEngine.SetText(aStr.getString());
    1468           0 :                 maDestPos.miCellPos =
    1469           0 :                     mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rEngine.CreateTextObject());
    1470             :             }
    1471             :             else
    1472             :             {
    1473           0 :                 maDestPos.miCellPos =
    1474           0 :                     mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aStr);
    1475             :             }
    1476             : 
    1477           0 :             setDefaultAttrToDest(nRow);
    1478             :         }
    1479             :     }
    1480             : 
    1481       91344 :     void duplicateNotes(SCROW nStartRow, size_t nDataSize, bool bCloneCaption )
    1482             :     {
    1483       91344 :         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestPos, bCloneCaption);
    1484       91344 :     }
    1485             : 
    1486             : public:
    1487      192683 :     CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos,
    1488             :             InsertDeleteFlags nCopyFlags, svl::SharedStringPool* pSharedStringPool) :
    1489             :         mrSrcCol(rSrcCol),
    1490             :         mrDestCol(rDestCol),
    1491             :         mpDestPos(pDestPos),
    1492             :         mpSharedStringPool(pSharedStringPool),
    1493             :         mnCopyFlags(nCopyFlags),
    1494      192683 :         meListenType(sc::SingleCellListening)
    1495             :     {
    1496      192683 :         if (mpDestPos)
    1497      192683 :             maDestPos = *mpDestPos;
    1498      192683 :     }
    1499             : 
    1500      192683 :     ~CopyByCloneHandler()
    1501             :     {
    1502      192683 :         if (mpDestPos)
    1503      192683 :             *mpDestPos = maDestPos;
    1504      192683 :     }
    1505             : 
    1506      192683 :     void setStartListening( bool b )
    1507             :     {
    1508      192683 :         meListenType = b ? sc::SingleCellListening : sc::NoListening;
    1509      192683 :     }
    1510             : 
    1511      194570 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1512             :     {
    1513      194570 :         size_t nRow = aNode.position + nOffset;
    1514             : 
    1515      194570 :         if (mnCopyFlags & (IDF_NOTE|IDF_ADDNOTES))
    1516             :         {
    1517       91344 :             bool bCloneCaption = (mnCopyFlags & IDF_NOCAPTIONS) == IDF_NONE;
    1518       91344 :             duplicateNotes(nRow, nDataSize, bCloneCaption );
    1519             :         }
    1520             : 
    1521      194570 :         switch (aNode.type)
    1522             :         {
    1523             :             case sc::element_type_numeric:
    1524             :             {
    1525         854 :                 if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == IDF_NONE)
    1526         148 :                     return;
    1527             : 
    1528         706 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1529         706 :                 std::advance(it, nOffset);
    1530         706 :                 sc::numeric_block::const_iterator itEnd = it;
    1531         706 :                 std::advance(itEnd, nDataSize);
    1532             : 
    1533         706 :                 ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
    1534        2052 :                 for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
    1535             :                 {
    1536        1346 :                     if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
    1537           0 :                         continue;
    1538             : 
    1539        1346 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, *it);
    1540        1346 :                     setDefaultAttrToDest(nRow);
    1541             :                 }
    1542             :             }
    1543         706 :             break;
    1544             :             case sc::element_type_string:
    1545             :             {
    1546         558 :                 if (!(mnCopyFlags & IDF_STRING))
    1547         102 :                     return;
    1548             : 
    1549         456 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
    1550         456 :                 std::advance(it, nOffset);
    1551         456 :                 sc::string_block::const_iterator itEnd = it;
    1552         456 :                 std::advance(itEnd, nDataSize);
    1553             : 
    1554        1496 :                 for (; it != itEnd; ++it, ++nRow)
    1555             :                 {
    1556        1040 :                     const svl::SharedString& rStr = *it;
    1557        1040 :                     if (rStr.isEmpty())
    1558             :                     {
    1559             :                         // String cell with empty value is used to special-case cell value removal.
    1560           0 :                         maDestPos.miCellPos = mrDestCol.GetCellStore().set_empty(
    1561           0 :                             maDestPos.miCellPos, nRow, nRow);
    1562           0 :                         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set_empty(
    1563           0 :                             maDestPos.miCellTextAttrPos, nRow, nRow);
    1564             :                     }
    1565             :                     else
    1566             :                     {
    1567        1040 :                         if (mpSharedStringPool)
    1568             :                         {
    1569             :                             // Re-intern the string if source is a different document.
    1570          52 :                             svl::SharedString aInterned = mpSharedStringPool->intern( rStr.getString());
    1571         156 :                             maDestPos.miCellPos =
    1572         156 :                                 mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aInterned);
    1573             :                         }
    1574             :                         else
    1575             :                         {
    1576        2964 :                             maDestPos.miCellPos =
    1577        1976 :                                 mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rStr);
    1578             :                         }
    1579        1040 :                         setDefaultAttrToDest(nRow);
    1580             :                     }
    1581             :                 }
    1582             :             }
    1583         456 :             break;
    1584             :             case sc::element_type_edittext:
    1585             :             {
    1586           4 :                 if (!(mnCopyFlags & IDF_STRING))
    1587           0 :                     return;
    1588             : 
    1589           4 :                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
    1590           4 :                 std::advance(it, nOffset);
    1591           4 :                 sc::edittext_block::const_iterator itEnd = it;
    1592           4 :                 std::advance(itEnd, nDataSize);
    1593             : 
    1594           4 :                 std::vector<EditTextObject*> aCloned;
    1595           4 :                 aCloned.reserve(nDataSize);
    1596          12 :                 for (; it != itEnd; ++it)
    1597           8 :                     aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
    1598             : 
    1599           8 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1600           4 :                     maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end());
    1601             : 
    1602           4 :                 setDefaultAttrsToDest(nRow, nDataSize);
    1603             :             }
    1604           4 :             break;
    1605             :             case sc::element_type_formula:
    1606             :             {
    1607         156 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
    1608         156 :                 std::advance(it, nOffset);
    1609         156 :                 sc::formula_block::const_iterator itEnd = it;
    1610         156 :                 std::advance(itEnd, nDataSize);
    1611             : 
    1612         421 :                 for (; it != itEnd; ++it, ++nRow)
    1613         265 :                     cloneFormulaCell(nRow, const_cast<ScFormulaCell&>(**it));
    1614             :             }
    1615         156 :             break;
    1616             :             default:
    1617             :                 ;
    1618             :         }
    1619             :     }
    1620             : };
    1621             : 
    1622             : }
    1623             : 
    1624      195717 : void ScColumn::CopyToColumn(
    1625             :     sc::CopyToDocContext& rCxt,
    1626             :     SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked, ScColumn& rColumn,
    1627             :     const ScMarkData* pMarkData, bool bAsLink) const
    1628             : {
    1629      195717 :     if (bMarked)
    1630             :     {
    1631             :         SCROW nStart, nEnd;
    1632        1462 :         if (pMarkData && pMarkData->IsMultiMarked())
    1633             :         {
    1634        1462 :             ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
    1635             : 
    1636        3376 :             while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
    1637             :             {
    1638         452 :                 if ( nEnd >= nRow1 )
    1639         904 :                     CopyToColumn(rCxt, std::max(nRow1,nStart), std::min(nRow2,nEnd),
    1640        1356 :                                     nFlags, false, rColumn, pMarkData, bAsLink );
    1641        1462 :             }
    1642             :         }
    1643             :         else
    1644             :         {
    1645             :             OSL_FAIL("CopyToColumn: bMarked, but no mark");
    1646             :         }
    1647      197179 :         return;
    1648             :     }
    1649             : 
    1650      194255 :     if ( (nFlags & IDF_ATTRIB) != IDF_NONE )
    1651             :     {
    1652       95559 :         if ( (nFlags & IDF_STYLES) != IDF_STYLES )
    1653             :         {   // keep the StyleSheets in the target document
    1654             :             // e.g. DIF and RTF Clipboard-Import
    1655           0 :             for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
    1656             :             {
    1657             :                 const ScStyleSheet* pStyle =
    1658           0 :                     rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
    1659           0 :                 const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
    1660           0 :                 boost::scoped_ptr<ScPatternAttr> pNewPattern(new ScPatternAttr( *pPattern ));
    1661           0 :                 pNewPattern->SetStyleSheet( const_cast<ScStyleSheet*>(pStyle) );
    1662           0 :                 rColumn.pAttrArray->SetPattern( nRow, pNewPattern.get(), true );
    1663           0 :             }
    1664             :         }
    1665             :         else
    1666       95559 :             pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
    1667             :     }
    1668             : 
    1669      194255 :     if ((nFlags & IDF_CONTENTS) != IDF_NONE)
    1670             :     {
    1671      192683 :         if (bAsLink)
    1672             :         {
    1673           0 :             CopyAsLinkHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
    1674           0 :             aFunc.setStartListening(rCxt.isStartListening());
    1675           0 :             sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1676             :         }
    1677             :         else
    1678             :         {
    1679             :             // Compare the ScDocumentPool* to determine if we are copying
    1680             :             // within the same document. If not, re-intern shared strings.
    1681             :             svl::SharedStringPool* pSharedStringPool =
    1682      192683 :                 (pDocument->GetPool() != rColumn.pDocument->GetPool()) ?
    1683      192683 :                 &rColumn.pDocument->GetSharedStringPool() : NULL;
    1684             :             CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags,
    1685      192683 :                     pSharedStringPool);
    1686      192683 :             aFunc.setStartListening(rCxt.isStartListening());
    1687      192683 :             sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1688             :         }
    1689             : 
    1690      192683 :         rColumn.CellStorageModified();
    1691             :     }
    1692             : }
    1693             : 
    1694          16 : void ScColumn::UndoToColumn(
    1695             :     sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, InsertDeleteFlags nFlags, bool bMarked,
    1696             :     ScColumn& rColumn, const ScMarkData* pMarkData ) const
    1697             : {
    1698          16 :     if (nRow1 > 0)
    1699           7 :         CopyToColumn(rCxt, 0, nRow1-1, IDF_FORMULA, false, rColumn);
    1700             : 
    1701          16 :     CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData);      //TODO: bMarked ????
    1702             : 
    1703          16 :     if (nRow2 < MAXROW)
    1704          16 :         CopyToColumn(rCxt, nRow2+1, MAXROW, IDF_FORMULA, false, rColumn);
    1705          16 : }
    1706             : 
    1707           0 : void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
    1708             : {
    1709             :     // Copy cells from this column to the destination column only for those
    1710             :     // rows that are present in the position column (rPosCol).
    1711             : 
    1712             :     // First, mark all the non-empty cell ranges from the position column.
    1713           0 :     sc::SingleColumnSpanSet aRangeSet;
    1714           0 :     aRangeSet.scan(rPosCol);
    1715             : 
    1716             :     // Now, copy cells from this column to the destination column for those
    1717             :     // marked row ranges.
    1718           0 :     sc::SingleColumnSpanSet::SpansType aRanges;
    1719           0 :     aRangeSet.getSpans(aRanges);
    1720             : 
    1721           0 :     bool bCopyNotes = true;
    1722           0 :     CopyToClipHandler aFunc(*this, rDestCol, NULL, bCopyNotes);
    1723           0 :     sc::CellStoreType::const_iterator itPos = maCells.begin();
    1724           0 :     sc::SingleColumnSpanSet::SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
    1725           0 :     for (; it != itEnd; ++it)
    1726           0 :         itPos = sc::ParseBlock(itPos, maCells, aFunc, it->mnRow1, it->mnRow2);
    1727             : 
    1728           0 :     rDestCol.CellStorageModified();
    1729           0 : }
    1730             : 
    1731           0 : void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
    1732             : {
    1733             :     //  This is the scenario table, the data is copied into it
    1734           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1735           0 :     SCROW nStart = -1, nEnd = -1;
    1736           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1737           0 :     while (pPattern)
    1738             :     {
    1739           0 :         if ( static_cast<const ScMergeFlagAttr&>(pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1740             :         {
    1741           0 :             DeleteArea( nStart, nEnd, IDF_CONTENTS );
    1742           0 :             sc::CopyToDocContext aCxt(*pDocument);
    1743             :             ((ScColumn&)rSrcCol).
    1744           0 :                 CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, *this);
    1745             : 
    1746             :             //  UpdateUsed not needed, already done in TestCopyScenario (obsolete comment ?)
    1747             : 
    1748           0 :             sc::RefUpdateContext aRefCxt(*pDocument);
    1749           0 :             aRefCxt.meMode = URM_COPY;
    1750           0 :             aRefCxt.maRange = ScRange(nCol, nStart, nTab, nCol, nEnd, nTab);
    1751           0 :             aRefCxt.mnTabDelta = nTab - rSrcCol.nTab;
    1752           0 :             UpdateReferenceOnCopy(aRefCxt, NULL);
    1753           0 :             UpdateCompile();
    1754             :         }
    1755             : 
    1756             :         //TODO: make CopyToColumn "const" !!! (obsolete comment ?)
    1757             : 
    1758           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1759             :     }
    1760           0 : }
    1761             : 
    1762           0 : void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
    1763             : {
    1764             :     //  This is the scenario table, the data is copied to the other
    1765           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1766           0 :     SCROW nStart = -1, nEnd = -1;
    1767           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1768           0 :     while (pPattern)
    1769             :     {
    1770           0 :         if ( static_cast<const ScMergeFlagAttr&>(pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1771             :         {
    1772           0 :             rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
    1773           0 :             sc::CopyToDocContext aCxt(*rDestCol.pDocument);
    1774           0 :             CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, rDestCol);
    1775             : 
    1776             :             //  UpdateUsed not needed, is already done in TestCopyScenario (obsolete comment ?)
    1777             : 
    1778           0 :             sc::RefUpdateContext aRefCxt(*pDocument);
    1779           0 :             aRefCxt.meMode = URM_COPY;
    1780           0 :             aRefCxt.maRange = ScRange(rDestCol.nCol, nStart, rDestCol.nTab, rDestCol.nCol, nEnd, rDestCol.nTab);
    1781           0 :             aRefCxt.mnTabDelta = rDestCol.nTab - nTab;
    1782           0 :             rDestCol.UpdateReferenceOnCopy(aRefCxt, NULL);
    1783           0 :             rDestCol.UpdateCompile();
    1784             :         }
    1785             : 
    1786             :         //TODO: make CopyToColumn "const" !!! (obsolete comment ?)
    1787             : 
    1788           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1789             :     }
    1790           0 : }
    1791             : 
    1792           0 : bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
    1793             : {
    1794           0 :     bool bOk = true;
    1795           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1796           0 :     SCROW nStart = 0, nEnd = 0;
    1797           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1798           0 :     while (pPattern && bOk)
    1799             :     {
    1800           0 :         if ( static_cast<const ScMergeFlagAttr&>(pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1801           0 :             if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
    1802           0 :                 bOk = false;
    1803             : 
    1804           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1805             :     }
    1806           0 :     return bOk;
    1807             : }
    1808             : 
    1809        3072 : void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
    1810             : {
    1811        3072 :     ScRange aRange( nCol, 0, nTab );
    1812             : 
    1813        3072 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1814        3072 :     SCROW nStart = -1, nEnd = -1;
    1815        3072 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1816        9258 :     while (pPattern)
    1817             :     {
    1818        3114 :         if ( static_cast<const ScMergeFlagAttr&>(pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1819             :         {
    1820          42 :             aRange.aStart.SetRow( nStart );
    1821          42 :             aRange.aEnd.SetRow( nEnd );
    1822          42 :             rDestMark.SetMultiMarkArea( aRange, true );
    1823             :         }
    1824             : 
    1825        3114 :         pPattern = aAttrIter.Next( nStart, nEnd );
    1826             :     }
    1827        3072 : }
    1828             : 
    1829             : namespace {
    1830             : 
    1831      161300 : void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
    1832             : {
    1833      161300 :     sc::CellStoreType::iterator it = rCells.begin(), itEnd = rCells.end();
    1834      322766 :     for (; it != itEnd; ++it)
    1835             :     {
    1836      161466 :         if (it->type != sc::element_type_formula)
    1837      161417 :             continue;
    1838             : 
    1839          49 :         sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
    1840          49 :         sc::formula_block::iterator itCellEnd = sc::formula_block::end(*it->data);
    1841         115 :         for (; itCell != itCellEnd; ++itCell)
    1842             :         {
    1843          66 :             ScFormulaCell& rCell = **itCell;
    1844          66 :             rCell.aPos.SetCol(nCol);
    1845             :         }
    1846             :     }
    1847      161300 : }
    1848             : 
    1849             : class NoteCaptionUpdater
    1850             : {
    1851             :     SCCOL mnCol;
    1852             :     SCTAB mnTab;
    1853             : public:
    1854      175680 :     NoteCaptionUpdater( SCCOL nCol, SCTAB nTab ) : mnCol(nCol), mnTab(nTab) {}
    1855             : 
    1856           3 :     void operator() ( size_t nRow, ScPostIt* p )
    1857             :     {
    1858           3 :         p->UpdateCaptionPos(ScAddress(mnCol,nRow,mnTab));
    1859           3 :     }
    1860             : };
    1861             : 
    1862             : }
    1863             : 
    1864      175680 : void ScColumn::UpdateNoteCaptions( SCROW nRow1, SCROW nRow2 )
    1865             : {
    1866      175680 :     NoteCaptionUpdater aFunc(nCol, nTab);
    1867      175680 :     sc::ProcessNote(maCellNotes.begin(), maCellNotes, nRow1, nRow2, aFunc);
    1868      175680 : }
    1869             : 
    1870       80650 : void ScColumn::SwapCol(ScColumn& rCol)
    1871             : {
    1872       80650 :     maBroadcasters.swap(rCol.maBroadcasters);
    1873       80650 :     maCells.swap(rCol.maCells);
    1874       80650 :     maCellTextAttrs.swap(rCol.maCellTextAttrs);
    1875       80650 :     maCellNotes.swap(rCol.maCellNotes);
    1876             : 
    1877             :     // notes update caption
    1878       80650 :     UpdateNoteCaptions(0, MAXROW);
    1879       80650 :     rCol.UpdateNoteCaptions(0, MAXROW);
    1880             : 
    1881       80650 :     ScAttrArray* pTempAttr = rCol.pAttrArray;
    1882       80650 :     rCol.pAttrArray = pAttrArray;
    1883       80650 :     pAttrArray = pTempAttr;
    1884             : 
    1885             :     // AttrArray needs to have the right column number
    1886       80650 :     pAttrArray->SetCol(nCol);
    1887       80650 :     rCol.pAttrArray->SetCol(rCol.nCol);
    1888             : 
    1889       80650 :     std::swap(mbDirtyGroups, rCol.mbDirtyGroups);
    1890             : 
    1891             :     // Reset column positions in formula cells.
    1892       80650 :     resetColumnPosition(maCells, nCol);
    1893       80650 :     resetColumnPosition(rCol.maCells, rCol.nCol);
    1894             : 
    1895       80650 :     CellStorageModified();
    1896       80650 :     rCol.CellStorageModified();
    1897       80650 : }
    1898             : 
    1899       14267 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
    1900             : {
    1901       14267 :     pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
    1902             : 
    1903             :     // Mark the non-empty cells within the specified range, for later broadcasting.
    1904       14267 :     sc::SingleColumnSpanSet aNonEmpties;
    1905       14267 :     aNonEmpties.scan(*this, nStartRow, nEndRow);
    1906       28534 :     sc::SingleColumnSpanSet::SpansType aRanges;
    1907       14267 :     aNonEmpties.getSpans(aRanges);
    1908             : 
    1909             :     // Split the formula grouping at the top and bottom boundaries.
    1910       14267 :     sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
    1911       14267 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    1912       14267 :     aPos = maCells.position(aPos.first, nEndRow+1);
    1913       14267 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    1914             : 
    1915             :     // Do the same with the destination column.
    1916       14267 :     aPos = rCol.maCells.position(nStartRow);
    1917       14267 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    1918       14267 :     aPos = rCol.maCells.position(aPos.first, nEndRow+1);
    1919       14267 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    1920             : 
    1921             :     // Move the broadcasters to the destination column.
    1922       14267 :     maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
    1923       14267 :     maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
    1924       14267 :     maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
    1925             : 
    1926             :     // move the notes to the destination column
    1927       14267 :     maCellNotes.transfer(nStartRow, nEndRow, rCol.maCellNotes, nStartRow);
    1928       14267 :     UpdateNoteCaptions(0, MAXROW);
    1929             : 
    1930             :     // Re-group transferred formula cells.
    1931       14267 :     aPos = rCol.maCells.position(nStartRow);
    1932       14267 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    1933       14267 :     aPos = rCol.maCells.position(aPos.first, nEndRow+1);
    1934       14267 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    1935             : 
    1936       14267 :     CellStorageModified();
    1937       14267 :     rCol.CellStorageModified();
    1938             : 
    1939             :     // Broadcast on moved ranges. Area-broadcast only.
    1940       28534 :     ScHint aHint(SC_HINT_DATACHANGED, ScAddress(nCol, 0, nTab));
    1941       14267 :     ScAddress& rPos = aHint.GetAddress();
    1942       14267 :     sc::SingleColumnSpanSet::SpansType::const_iterator itRange = aRanges.begin(), itRangeEnd = aRanges.end();
    1943       14278 :     for (; itRange != itRangeEnd; ++itRange)
    1944             :     {
    1945          24 :         for (SCROW nRow = itRange->mnRow1; nRow <= itRange->mnRow2; ++nRow)
    1946             :         {
    1947          13 :             rPos.SetRow(nRow);
    1948          13 :             pDocument->AreaBroadcast(aHint);
    1949             :         }
    1950       14267 :     }
    1951       14267 : }
    1952             : 
    1953             : namespace {
    1954             : 
    1955      354327 : class SharedTopFormulaCellPicker : std::unary_function<sc::CellStoreType::value_type, void>
    1956             : {
    1957             : public:
    1958      354327 :     virtual ~SharedTopFormulaCellPicker() {}
    1959             : 
    1960      179364 :     void operator() ( sc::CellStoreType::value_type& node )
    1961             :     {
    1962      179364 :         if (node.type != sc::element_type_formula)
    1963      358356 :             return;
    1964             : 
    1965         372 :         size_t nTopRow = node.position;
    1966             : 
    1967         372 :         sc::formula_block::iterator itBeg = sc::formula_block::begin(*node.data);
    1968         372 :         sc::formula_block::iterator itEnd = sc::formula_block::end(*node.data);
    1969             : 
    1970             :         // Only pick shared formula cells that are the top cells of their
    1971             :         // respective shared ranges.
    1972         909 :         for (sc::formula_block::iterator it = itBeg; it != itEnd; ++it)
    1973             :         {
    1974         537 :             ScFormulaCell* pCell = *it;
    1975         537 :             size_t nRow = nTopRow + std::distance(itBeg, it);
    1976         537 :             if (!pCell->IsShared())
    1977             :             {
    1978         419 :                 processNonShared(pCell, nRow);
    1979         419 :                 continue;
    1980             :             }
    1981             : 
    1982         118 :             if (pCell->IsSharedTop())
    1983             :             {
    1984         118 :                 ScFormulaCell** pp = &(*it);
    1985         118 :                 processSharedTop(pp, nRow, pCell->GetSharedLength());
    1986             : 
    1987             :                 // Move to the last cell in the group, to get incremented to
    1988             :                 // the next cell in the next iteration.
    1989         118 :                 size_t nOffsetToLast = pCell->GetSharedLength() - 1;
    1990         118 :                 std::advance(it, nOffsetToLast);
    1991             :             }
    1992             :         }
    1993             :     }
    1994             : 
    1995         194 :     virtual void processNonShared( ScFormulaCell* /*pCell*/, size_t /*nRow*/ ) {}
    1996           0 :     virtual void processSharedTop( ScFormulaCell** /*ppCells*/, size_t /*nRow*/, size_t /*nLength*/ ) {}
    1997             : };
    1998             : 
    1999             : class UpdateRefOnCopy
    2000             : {
    2001             :     const sc::RefUpdateContext& mrCxt;
    2002             :     ScDocument* mpUndoDoc;
    2003             :     bool mbUpdated;
    2004             : 
    2005             : public:
    2006       18537 :     UpdateRefOnCopy(const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc) :
    2007       18537 :         mrCxt(rCxt), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2008             : 
    2009       18537 :     bool isUpdated() const { return mbUpdated; }
    2010             : 
    2011       18759 :     void operator() (sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    2012             :     {
    2013       18759 :         if (node.type != sc::element_type_formula)
    2014       37458 :             return;
    2015             : 
    2016          60 :         sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
    2017          60 :         std::advance(it, nOffset);
    2018          60 :         sc::formula_block::iterator itEnd = it;
    2019          60 :         std::advance(itEnd, nDataSize);
    2020             : 
    2021         138 :         for (; it != itEnd; ++it)
    2022             :         {
    2023          78 :             ScFormulaCell& rCell = **it;
    2024          78 :             mbUpdated |= rCell.UpdateReference(mrCxt, mpUndoDoc);
    2025             :         }
    2026             :     }
    2027             : };
    2028             : 
    2029             : class UpdateRefOnNonCopy : std::unary_function<sc::FormulaGroupEntry, void>
    2030             : {
    2031             :     SCCOL mnCol;
    2032             :     SCROW mnTab;
    2033             :     const sc::RefUpdateContext* mpCxt;
    2034             :     ScDocument* mpUndoDoc;
    2035             :     bool mbUpdated;
    2036             : 
    2037           2 :     void recompileTokenArray( ScFormulaCell& rTopCell )
    2038             :     {
    2039             :         // We need to re-compile the token array when a range name is
    2040             :         // modified, to correctly reflect the new references in the
    2041             :         // name.
    2042           2 :         ScCompiler aComp(&mpCxt->mrDoc, rTopCell.aPos, *rTopCell.GetCode());
    2043           2 :         aComp.SetGrammar(mpCxt->mrDoc.GetGrammar());
    2044           2 :         aComp.CompileTokenArray();
    2045           2 :     }
    2046             : 
    2047         222 :     void updateRefOnShift( sc::FormulaGroupEntry& rGroup )
    2048             :     {
    2049         222 :         if (!rGroup.mbShared)
    2050             :         {
    2051         174 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2052         174 :             mbUpdated |= rGroup.mpCell->UpdateReferenceOnShift(*mpCxt, mpUndoDoc, &aUndoPos);
    2053         396 :             return;
    2054             :         }
    2055             : 
    2056             :         // Update references of a formula group.
    2057          48 :         ScFormulaCell** pp = rGroup.mpCells;
    2058          48 :         ScFormulaCell** ppEnd = pp + rGroup.mnLength;
    2059          48 :         ScFormulaCell* pTop = *pp;
    2060          48 :         ScTokenArray* pCode = pTop->GetCode();
    2061          48 :         boost::scoped_ptr<ScTokenArray> pOldCode(pCode->Clone());
    2062          48 :         ScAddress aOldPos = pTop->aPos;
    2063             : 
    2064             :         // Run this before the position gets updated.
    2065          48 :         sc::RefUpdateResult aRes = pCode->AdjustReferenceOnShift(*mpCxt, aOldPos);
    2066             : 
    2067          48 :         if (pTop->UpdatePosOnShift(*mpCxt))
    2068             :         {
    2069             :             // Update the positions of all formula cells.
    2070          90 :             for (++pp; pp != ppEnd; ++pp) // skip the top cell.
    2071             :             {
    2072          64 :                 ScFormulaCell* pFC = *pp;
    2073          64 :                 pFC->aPos.Move(mpCxt->mnColDelta, mpCxt->mnRowDelta, mpCxt->mnTabDelta);
    2074             :             }
    2075             : 
    2076          26 :             if (pCode->IsRecalcModeOnRefMove())
    2077           0 :                 aRes.mbValueChanged = true;
    2078             :         }
    2079          22 :         else if (aRes.mbReferenceModified && pCode->IsRecalcModeOnRefMove())
    2080             :         {
    2081             :             // The cell itself hasn't shifted. But it may have ROW or COLUMN
    2082             :             // referencing another cell that has.
    2083           1 :             aRes.mbValueChanged = true;
    2084             :         }
    2085             : 
    2086          48 :         if (aRes.mbNameModified)
    2087           1 :             recompileTokenArray(*pTop);
    2088             : 
    2089          48 :         if (aRes.mbReferenceModified || aRes.mbNameModified)
    2090             :         {
    2091          28 :             sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
    2092             :             aEndCxt.setPositionDelta(
    2093          28 :                 ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
    2094             : 
    2095         122 :             for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
    2096             :             {
    2097          94 :                 ScFormulaCell* p = *pp;
    2098          94 :                 p->EndListeningTo(aEndCxt);
    2099          94 :                 p->SetNeedsListening(true);
    2100             :             }
    2101             : 
    2102          28 :             mbUpdated = true;
    2103             : 
    2104          28 :             fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
    2105             :         }
    2106             : 
    2107          48 :         if (aRes.mbValueChanged)
    2108             :         {
    2109          30 :             for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
    2110             :             {
    2111          20 :                 ScFormulaCell* p = *pp;
    2112          20 :                 p->SetNeedsDirty(true);
    2113             :             }
    2114          48 :         }
    2115             :     }
    2116             : 
    2117          34 :     void updateRefOnMove( sc::FormulaGroupEntry& rGroup )
    2118             :     {
    2119          34 :         if (!rGroup.mbShared)
    2120             :         {
    2121          29 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2122          29 :             mbUpdated |= rGroup.mpCell->UpdateReferenceOnMove(*mpCxt, mpUndoDoc, &aUndoPos);
    2123          63 :             return;
    2124             :         }
    2125             : 
    2126             :         // Update references of a formula group.
    2127           5 :         ScFormulaCell** pp = rGroup.mpCells;
    2128           5 :         ScFormulaCell** ppEnd = pp + rGroup.mnLength;
    2129           5 :         ScFormulaCell* pTop = *pp;
    2130           5 :         ScTokenArray* pCode = pTop->GetCode();
    2131           5 :         boost::scoped_ptr<ScTokenArray> pOldCode(pCode->Clone());
    2132             : 
    2133           5 :         ScAddress aPos = pTop->aPos;
    2134           5 :         ScAddress aOldPos = aPos;
    2135             : 
    2136           5 :         if (mpCxt->maRange.In(aPos))
    2137             :         {
    2138             :             // The cell is being moved or copied to a new position. The
    2139             :             // position has already been updated prior to this call.
    2140             :             // Determine its original position before the move which will be
    2141             :             // used to adjust relative references later.
    2142             : 
    2143             :             aOldPos.Set(
    2144           0 :                 aPos.Col() - mpCxt->mnColDelta,
    2145           0 :                 aPos.Row() - mpCxt->mnRowDelta,
    2146           0 :                 aPos.Tab() - mpCxt->mnTabDelta);
    2147             :         }
    2148             : 
    2149           5 :         bool bRecalcOnMove = pCode->IsRecalcModeOnRefMove();
    2150           5 :         if (bRecalcOnMove)
    2151           0 :             bRecalcOnMove = aPos != aOldPos;
    2152             : 
    2153           5 :         sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos);
    2154             : 
    2155           5 :         if (aRes.mbReferenceModified || aRes.mbNameModified || bRecalcOnMove)
    2156             :         {
    2157           4 :             sc::AutoCalcSwitch(mpCxt->mrDoc, false);
    2158             : 
    2159           4 :             if (aRes.mbNameModified)
    2160           1 :                 recompileTokenArray(*pTop);
    2161             : 
    2162             :             // Perform end-listening, start-listening, and dirtying on all
    2163             :             // formula cells in the group.
    2164             : 
    2165             :             // Make sure that the start and end listening contexts share the
    2166             :             // same block position set, else an invalid iterator may ensue.
    2167             :             boost::shared_ptr<sc::ColumnBlockPositionSet> pPosSet(
    2168           4 :                 new sc::ColumnBlockPositionSet(mpCxt->mrDoc));
    2169             : 
    2170           8 :             sc::StartListeningContext aStartCxt(mpCxt->mrDoc, pPosSet);
    2171           8 :             sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pPosSet, pOldCode.get());
    2172             : 
    2173             :             aEndCxt.setPositionDelta(
    2174           4 :                 ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
    2175             : 
    2176          13 :             for (; pp != ppEnd; ++pp)
    2177             :             {
    2178           9 :                 ScFormulaCell* p = *pp;
    2179           9 :                 p->EndListeningTo(aEndCxt);
    2180           9 :                 p->StartListeningTo(aStartCxt);
    2181           9 :                 p->SetDirty();
    2182             :             }
    2183             : 
    2184           8 :             fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
    2185           5 :         }
    2186             :     }
    2187             : 
    2188          32 :     void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode )
    2189             :     {
    2190          32 :         if (!mpUndoDoc || nLength <= 0)
    2191          52 :             return;
    2192             : 
    2193             :         // Insert the old formula group into the undo document.
    2194           6 :         ScAddress aUndoPos = rOldPos;
    2195           6 :         ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, rOldCode.Clone());
    2196             : 
    2197           6 :         if (nLength == 1)
    2198             :         {
    2199           0 :             mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
    2200           0 :             return;
    2201             :         }
    2202             : 
    2203           6 :         std::vector<ScFormulaCell*> aCells;
    2204           6 :         aCells.reserve(nLength);
    2205          12 :         ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
    2206           6 :         aCells.push_back(pFC);
    2207           6 :         aUndoPos.IncRow();
    2208          28 :         for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow())
    2209             :         {
    2210          22 :             pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup);
    2211          22 :             aCells.push_back(pFC);
    2212             :         }
    2213             : 
    2214           6 :         if (!mpUndoDoc->SetFormulaCells(rOldPos, aCells))
    2215             :             // Insertion failed.  Delete all formula cells.
    2216           6 :             std::for_each(aCells.begin(), aCells.end(), boost::checked_deleter<ScFormulaCell>());
    2217             :     }
    2218             : 
    2219             : public:
    2220         407 :     UpdateRefOnNonCopy(
    2221             :         SCCOL nCol, SCTAB nTab, const sc::RefUpdateContext* pCxt,
    2222             :         ScDocument* pUndoDoc) :
    2223             :         mnCol(nCol), mnTab(nTab), mpCxt(pCxt),
    2224         407 :         mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2225             : 
    2226         256 :     void operator() ( sc::FormulaGroupEntry& rGroup )
    2227             :     {
    2228         256 :         switch (mpCxt->meMode)
    2229             :         {
    2230             :             case URM_INSDEL:
    2231         222 :                 updateRefOnShift(rGroup);
    2232         222 :                 return;
    2233             :             case URM_MOVE:
    2234          34 :                 updateRefOnMove(rGroup);
    2235          34 :                 return;
    2236             :             default:
    2237             :                 ;
    2238             :         }
    2239             : 
    2240           0 :         if (rGroup.mbShared)
    2241             :         {
    2242           0 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2243           0 :             ScFormulaCell** pp = rGroup.mpCells;
    2244           0 :             ScFormulaCell** ppEnd = pp + rGroup.mnLength;
    2245           0 :             for (; pp != ppEnd; ++pp, aUndoPos.IncRow())
    2246             :             {
    2247           0 :                 ScFormulaCell* p = *pp;
    2248           0 :                 mbUpdated |= p->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
    2249             :             }
    2250             :         }
    2251             :         else
    2252             :         {
    2253           0 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2254           0 :             mbUpdated |= rGroup.mpCell->UpdateReference(*mpCxt, mpUndoDoc, &aUndoPos);
    2255             :         }
    2256             :     }
    2257             : 
    2258         814 :     bool isUpdated() const { return mbUpdated; }
    2259             : };
    2260             : 
    2261         814 : class UpdateRefGroupBoundChecker : public SharedTopFormulaCellPicker
    2262             : {
    2263             :     const sc::RefUpdateContext& mrCxt;
    2264             :     std::vector<SCROW>& mrBounds;
    2265             : 
    2266             : public:
    2267         407 :     UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
    2268         407 :         mrCxt(rCxt), mrBounds(rBounds) {}
    2269             : 
    2270        1221 :     virtual ~UpdateRefGroupBoundChecker() {}
    2271             : 
    2272          50 :     virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) SAL_OVERRIDE
    2273             :     {
    2274             :         // Check its tokens and record its reference boundaries.
    2275          50 :         ScFormulaCell& rCell = **ppCells;
    2276          50 :         const ScTokenArray& rCode = *rCell.GetCode();
    2277             :         rCode.CheckRelativeReferenceBounds(
    2278          50 :             mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
    2279          50 :     }
    2280             : };
    2281             : 
    2282          24 : class UpdateRefExpandGroupBoundChecker : public SharedTopFormulaCellPicker
    2283             : {
    2284             :     const sc::RefUpdateContext& mrCxt;
    2285             :     std::vector<SCROW>& mrBounds;
    2286             : 
    2287             : public:
    2288          12 :     UpdateRefExpandGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
    2289          12 :         mrCxt(rCxt), mrBounds(rBounds) {}
    2290             : 
    2291          36 :     virtual ~UpdateRefExpandGroupBoundChecker() {}
    2292             : 
    2293           1 :     virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) SAL_OVERRIDE
    2294             :     {
    2295             :         // Check its tokens and record its reference boundaries.
    2296           1 :         ScFormulaCell& rCell = **ppCells;
    2297           1 :         const ScTokenArray& rCode = *rCell.GetCode();
    2298             :         rCode.CheckExpandReferenceBounds(
    2299           1 :             mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
    2300           1 :     }
    2301             : };
    2302             : 
    2303      176535 : class FormulaGroupPicker : public SharedTopFormulaCellPicker
    2304             : {
    2305             :     std::vector<sc::FormulaGroupEntry>& mrGroups;
    2306             : 
    2307             : public:
    2308      176535 :     FormulaGroupPicker( std::vector<sc::FormulaGroupEntry>& rGroups ) : mrGroups(rGroups) {}
    2309             : 
    2310      353070 :     virtual ~FormulaGroupPicker() {}
    2311             : 
    2312         225 :     virtual void processNonShared( ScFormulaCell* pCell, size_t nRow ) SAL_OVERRIDE
    2313             :     {
    2314         225 :         mrGroups.push_back(sc::FormulaGroupEntry(pCell, nRow));
    2315         225 :     }
    2316             : 
    2317          67 :     virtual void processSharedTop( ScFormulaCell** ppCells, size_t nRow, size_t nLength ) SAL_OVERRIDE
    2318             :     {
    2319          67 :         mrGroups.push_back(sc::FormulaGroupEntry(ppCells, nRow, nLength));
    2320          67 :     }
    2321             : };
    2322             : 
    2323             : }
    2324             : 
    2325       18537 : bool ScColumn::UpdateReferenceOnCopy( const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc )
    2326             : {
    2327             :     // When copying, the range equals the destination range where cells
    2328             :     // are pasted, and the dx, dy, dz refer to the distance from the
    2329             :     // source range.
    2330             : 
    2331       18537 :     UpdateRefOnCopy aHandler(rCxt, pUndoDoc);
    2332       18537 :     sc::CellStoreType::position_type aPos = maCells.position(rCxt.maRange.aStart.Row());
    2333       18537 :     sc::ProcessBlock(aPos.first, maCells, aHandler, rCxt.maRange.aStart.Row(), rCxt.maRange.aEnd.Row());
    2334             : 
    2335             :     // The formula groups at the top and bottom boundaries are expected to
    2336             :     // have been split prior to this call. Here, we only do the joining.
    2337       18537 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2338       18537 :     if (rCxt.maRange.aEnd.Row() < MAXROW)
    2339             :     {
    2340         105 :         aPos = maCells.position(aPos.first, rCxt.maRange.aEnd.Row()+1);
    2341         105 :         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2342             :     }
    2343             : 
    2344       18537 :     return aHandler.isUpdated();
    2345             : }
    2346             : 
    2347      229481 : bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc )
    2348             : {
    2349      229481 :     if (rCxt.meMode == URM_COPY)
    2350       18537 :         return UpdateReferenceOnCopy(rCxt, pUndoDoc);
    2351             : 
    2352      210944 :     if (IsEmptyData() || pDocument->IsClipOrUndo())
    2353             :         // Cells in this column are all empty, or clip or undo doc. No update needed.
    2354      210537 :         return false;
    2355             : 
    2356         407 :     std::vector<SCROW> aBounds;
    2357             : 
    2358        1203 :     bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() &&
    2359        1075 :                             rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col());
    2360         407 :     if (bThisColShifted)
    2361             :     {
    2362             :         // Cells in this column is being shifted.  Split formula grouping at
    2363             :         // the top and bottom boundaries before they get shifted.
    2364             :         // Also, for deleted rows split at the top of the deleted area to adapt
    2365             :         // the affected group length.
    2366             :         SCROW nSplitPos;
    2367         252 :         if (rCxt.mnRowDelta < 0)
    2368             :         {
    2369          64 :             nSplitPos = rCxt.maRange.aStart.Row() + rCxt.mnRowDelta;
    2370          64 :             if (ValidRow(nSplitPos))
    2371          63 :                 aBounds.push_back(nSplitPos);
    2372             :         }
    2373         252 :         nSplitPos = rCxt.maRange.aStart.Row();
    2374         252 :         if (ValidRow(nSplitPos))
    2375             :         {
    2376         252 :             aBounds.push_back(nSplitPos);
    2377         252 :             nSplitPos = rCxt.maRange.aEnd.Row() + 1;
    2378         252 :             if (ValidRow(nSplitPos))
    2379          47 :                 aBounds.push_back(nSplitPos);
    2380             :         }
    2381             :     }
    2382             : 
    2383             :     // Check the row positions at which the group must be split per relative
    2384             :     // references.
    2385         814 :     UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
    2386         407 :     std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
    2387             : 
    2388             :     // If expand reference edges is on, splitting groups may happen anywhere
    2389             :     // where a reference points to an adjacent row of the insertion.
    2390         407 :     if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
    2391             :     {
    2392          12 :         UpdateRefExpandGroupBoundChecker aExpandChecker(rCxt, aBounds);
    2393          12 :         std::for_each(maCells.begin(), maCells.end(), aExpandChecker);
    2394             :     }
    2395             : 
    2396             :     // Do the actual splitting.
    2397         407 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
    2398             : 
    2399             :     // Collect all formula groups.
    2400         814 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
    2401             : 
    2402             :     // Process all collected formula groups.
    2403         407 :     UpdateRefOnNonCopy aHandler(nCol, nTab, &rCxt, pUndoDoc);
    2404         407 :     aHandler = std::for_each(aGroups.begin(), aGroups.end(), aHandler);
    2405         407 :     if (aHandler.isUpdated())
    2406         120 :         rCxt.maRegroupCols.set(nTab, nCol);
    2407             : 
    2408         814 :     return aHandler.isUpdated();
    2409             : }
    2410             : 
    2411      176535 : std::vector<sc::FormulaGroupEntry> ScColumn::GetFormulaGroupEntries()
    2412             : {
    2413      176535 :     std::vector<sc::FormulaGroupEntry> aGroups;
    2414      176535 :     std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
    2415      176535 :     return aGroups;
    2416             : }
    2417             : 
    2418             : namespace {
    2419             : 
    2420             : class UpdateTransHandler
    2421             : {
    2422             :     ScColumn& mrColumn;
    2423             :     sc::CellStoreType::iterator miPos;
    2424             :     ScRange maSource;
    2425             :     ScAddress maDest;
    2426             :     ScDocument* mpUndoDoc;
    2427             : public:
    2428           0 :     UpdateTransHandler(ScColumn& rColumn, const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
    2429             :         mrColumn(rColumn),
    2430           0 :         miPos(rColumn.GetCellStore().begin()),
    2431           0 :         maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
    2432             : 
    2433           0 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2434             :     {
    2435           0 :         sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
    2436           0 :         miPos = aPos.first;
    2437           0 :         sc::SharedFormulaUtil::unshareFormulaCell(aPos, *pCell);
    2438           0 :         pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
    2439           0 :         ScColumn::JoinNewFormulaCell(aPos, *pCell);
    2440           0 :     }
    2441             : };
    2442             : 
    2443             : class UpdateGrowHandler
    2444             : {
    2445             :     ScColumn& mrColumn;
    2446             :     sc::CellStoreType::iterator miPos;
    2447             :     ScRange maArea;
    2448             :     SCCOL mnGrowX;
    2449             :     SCROW mnGrowY;
    2450             : public:
    2451           0 :     UpdateGrowHandler(ScColumn& rColumn, const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
    2452             :         mrColumn(rColumn),
    2453           0 :         miPos(rColumn.GetCellStore().begin()),
    2454           0 :         maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
    2455             : 
    2456           0 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2457             :     {
    2458           0 :         sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
    2459           0 :         miPos = aPos.first;
    2460           0 :         sc::SharedFormulaUtil::unshareFormulaCell(aPos, *pCell);
    2461           0 :         pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
    2462           0 :         ScColumn::JoinNewFormulaCell(aPos, *pCell);
    2463           0 :     }
    2464             : };
    2465             : 
    2466             : class InsertTabUpdater
    2467             : {
    2468             :     sc::RefUpdateInsertTabContext& mrCxt;
    2469             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2470             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2471             :     SCTAB mnTab;
    2472             :     bool mbModified;
    2473             : 
    2474             : public:
    2475      151552 :     InsertTabUpdater(sc::RefUpdateInsertTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2476             :         mrCxt(rCxt),
    2477             :         mrTextAttrs(rTextAttrs),
    2478             :         miAttrPos(rTextAttrs.begin()),
    2479             :         mnTab(nTab),
    2480      151552 :         mbModified(false) {}
    2481             : 
    2482         269 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2483             :     {
    2484         269 :         pCell->UpdateInsertTab(mrCxt);
    2485         269 :         mbModified = true;
    2486         269 :     }
    2487             : 
    2488           6 :     void operator() (size_t nRow, EditTextObject* pCell)
    2489             :     {
    2490           6 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2491           6 :         aUpdater.updateTableFields(mnTab);
    2492           6 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2493           6 :         mbModified = true;
    2494           6 :     }
    2495             : 
    2496      151552 :     bool isModified() const { return mbModified; }
    2497             : };
    2498             : 
    2499             : class DeleteTabUpdater
    2500             : {
    2501             :     sc::RefUpdateDeleteTabContext& mrCxt;
    2502             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2503             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2504             :     SCTAB mnTab;
    2505             :     bool mbModified;
    2506             : public:
    2507      254976 :     DeleteTabUpdater(sc::RefUpdateDeleteTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2508             :         mrCxt(rCxt),
    2509             :         mrTextAttrs(rTextAttrs),
    2510             :         miAttrPos(rTextAttrs.begin()),
    2511             :         mnTab(nTab),
    2512      254976 :         mbModified(false) {}
    2513             : 
    2514         275 :     void operator() (size_t, ScFormulaCell* pCell)
    2515             :     {
    2516         275 :         pCell->UpdateDeleteTab(mrCxt);
    2517         275 :         mbModified = true;
    2518         275 :     }
    2519             : 
    2520          12 :     void operator() (size_t nRow, EditTextObject* pCell)
    2521             :     {
    2522          12 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2523          12 :         aUpdater.updateTableFields(mnTab);
    2524          12 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2525          12 :         mbModified = true;
    2526          12 :     }
    2527             : 
    2528      254976 :     bool isModified() const { return mbModified; }
    2529             : };
    2530             : 
    2531             : class InsertAbsTabUpdater
    2532             : {
    2533             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2534             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2535             :     SCTAB mnTab;
    2536             :     SCTAB mnNewPos;
    2537             :     bool mbModified;
    2538             : public:
    2539        7168 :     InsertAbsTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nNewPos) :
    2540             :         mrTextAttrs(rTextAttrs),
    2541             :         miAttrPos(rTextAttrs.begin()),
    2542             :         mnTab(nTab),
    2543             :         mnNewPos(nNewPos),
    2544        7168 :         mbModified(false) {}
    2545             : 
    2546           3 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2547             :     {
    2548           3 :         pCell->UpdateInsertTabAbs(mnNewPos);
    2549           3 :         mbModified = true;
    2550           3 :     }
    2551             : 
    2552           6 :     void operator() (size_t nRow, EditTextObject* pCell)
    2553             :     {
    2554           6 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2555           6 :         aUpdater.updateTableFields(mnTab);
    2556           6 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2557           6 :         mbModified = true;
    2558           6 :     }
    2559             : 
    2560        7168 :     bool isModified() const { return mbModified; }
    2561             : };
    2562             : 
    2563             : class MoveTabUpdater
    2564             : {
    2565             :     sc::RefUpdateMoveTabContext& mrCxt;
    2566             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2567             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2568             :     SCTAB mnTab;
    2569             :     bool mbModified;
    2570             : public:
    2571       39936 :     MoveTabUpdater(sc::RefUpdateMoveTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2572             :         mrCxt(rCxt),
    2573             :         mrTextAttrs(rTextAttrs),
    2574             :         miAttrPos(rTextAttrs.begin()),
    2575             :         mnTab(nTab),
    2576       39936 :         mbModified(false) {}
    2577             : 
    2578          24 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2579             :     {
    2580          24 :         pCell->UpdateMoveTab(mrCxt, mnTab);
    2581          24 :         mbModified = true;
    2582          24 :     }
    2583             : 
    2584           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2585             :     {
    2586           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2587           0 :         aUpdater.updateTableFields(mnTab);
    2588           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2589           0 :         mbModified = true;
    2590           0 :     }
    2591             : 
    2592       39936 :     bool isModified() const { return mbModified; }
    2593             : };
    2594             : 
    2595             : class UpdateCompileHandler
    2596             : {
    2597             :     bool mbForceIfNameInUse:1;
    2598             : public:
    2599      412672 :     UpdateCompileHandler(bool bForceIfNameInUse) :
    2600      412672 :         mbForceIfNameInUse(bForceIfNameInUse) {}
    2601             : 
    2602         511 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2603             :     {
    2604         511 :         pCell->UpdateCompile(mbForceIfNameInUse);
    2605         511 :     }
    2606             : };
    2607             : 
    2608             : class TabNoSetter
    2609             : {
    2610             :     SCTAB mnTab;
    2611             : public:
    2612       13312 :     TabNoSetter(SCTAB nTab) : mnTab(nTab) {}
    2613             : 
    2614          50 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2615             :     {
    2616          50 :         pCell->aPos.SetTab(mnTab);
    2617          50 :     }
    2618             : };
    2619             : 
    2620             : class UsedRangeNameFinder
    2621             : {
    2622             :     std::set<sal_uInt16>& mrIndexes;
    2623             : public:
    2624          11 :     UsedRangeNameFinder(std::set<sal_uInt16>& rIndexes) : mrIndexes(rIndexes) {}
    2625             : 
    2626           1 :     void operator() (size_t /*nRow*/, const ScFormulaCell* pCell)
    2627             :     {
    2628           1 :         pCell->FindRangeNamesInUse(mrIndexes);
    2629           1 :     }
    2630             : };
    2631             : 
    2632             : struct SetDirtyVarHandler
    2633             : {
    2634        4300 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2635             :     {
    2636        4300 :         p->SetDirtyVar();
    2637        4300 :     }
    2638             : };
    2639             : 
    2640             : class SetDirtyHandler
    2641             : {
    2642             :     ScDocument& mrDoc;
    2643             :     const sc::SetFormulaDirtyContext& mrCxt;
    2644             : public:
    2645     1129472 :     SetDirtyHandler( ScDocument& rDoc, const sc::SetFormulaDirtyContext& rCxt ) :
    2646     1129472 :         mrDoc(rDoc), mrCxt(rCxt) {}
    2647             : 
    2648         563 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2649             :     {
    2650         563 :         if (mrCxt.mbClearTabDeletedFlag)
    2651             :         {
    2652           3 :             if (!p->IsShared() || p->IsSharedTop())
    2653             :             {
    2654           1 :                 ScTokenArray* pCode = p->GetCode();
    2655             :                 pCode->ClearTabDeleted(
    2656           1 :                     p->aPos, mrCxt.mnTabDeletedStart, mrCxt.mnTabDeletedEnd);
    2657             :             }
    2658             :         }
    2659             : 
    2660         563 :         p->SetDirtyVar();
    2661         563 :         if (!mrDoc.IsInFormulaTree(p))
    2662         140 :             mrDoc.PutInFormulaTree(p);
    2663         563 :     }
    2664             : };
    2665             : 
    2666       13751 : class SetDirtyOnRangeHandler
    2667             : {
    2668             :     sc::SingleColumnSpanSet maValueRanges;
    2669             :     ScColumn& mrColumn;
    2670             : public:
    2671       13751 :     SetDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    2672             : 
    2673         457 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2674             :     {
    2675         457 :         p->SetDirty();
    2676         457 :     }
    2677             : 
    2678       13753 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    2679             :     {
    2680       13753 :         if (type == sc::element_type_empty)
    2681             :             // Ignore empty blocks.
    2682       27118 :             return;
    2683             : 
    2684             :         // Non-formula cells.
    2685         388 :         SCROW nRow1 = nTopRow;
    2686         388 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    2687         388 :         maValueRanges.set(nRow1, nRow2, true);
    2688             :     }
    2689             : 
    2690       13455 :     void broadcast()
    2691             :     {
    2692       13455 :         std::vector<SCROW> aRows;
    2693       13455 :         maValueRanges.getRows(aRows);
    2694       13455 :         mrColumn.BroadcastCells(aRows, SC_HINT_DATACHANGED);
    2695       13455 :     }
    2696             : 
    2697         137 :     void fillBroadcastSpans( sc::ColumnSpanSet& rBroadcastSpans ) const
    2698             :     {
    2699         137 :         SCCOL nCol = mrColumn.GetCol();
    2700         137 :         SCTAB nTab = mrColumn.GetTab();
    2701         137 :         sc::SingleColumnSpanSet::SpansType aSpans;
    2702         137 :         maValueRanges.getSpans(aSpans);
    2703             : 
    2704         137 :         sc::SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
    2705         249 :         for (; it != itEnd; ++it)
    2706         249 :             rBroadcastSpans.set(nTab, nCol, it->mnRow1, it->mnRow2, true);
    2707         137 :     }
    2708             : };
    2709             : 
    2710          44 : class SetTableOpDirtyOnRangeHandler
    2711             : {
    2712             :     sc::SingleColumnSpanSet maValueRanges;
    2713             :     ScColumn& mrColumn;
    2714             : public:
    2715          44 :     SetTableOpDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    2716             : 
    2717           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2718             :     {
    2719           0 :         p->SetTableOpDirty();
    2720           0 :     }
    2721             : 
    2722          44 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    2723             :     {
    2724          44 :         if (type == sc::element_type_empty)
    2725             :             // Ignore empty blocks.
    2726          76 :             return;
    2727             : 
    2728             :         // Non-formula cells.
    2729          12 :         SCROW nRow1 = nTopRow;
    2730          12 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    2731          12 :         maValueRanges.set(nRow1, nRow2, true);
    2732             :     }
    2733             : 
    2734          44 :     void broadcast()
    2735             :     {
    2736          44 :         std::vector<SCROW> aRows;
    2737          44 :         maValueRanges.getRows(aRows);
    2738          44 :         mrColumn.BroadcastCells(aRows, SC_HINT_TABLEOPDIRTY);
    2739          44 :     }
    2740             : };
    2741             : 
    2742             : struct SetDirtyAfterLoadHandler
    2743             : {
    2744        3797 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2745             :     {
    2746             : #if 1
    2747             :         // Simply set dirty and append to FormulaTree, without broadcasting,
    2748             :         // which is a magnitude faster. This is used to calculate the entire
    2749             :         // document, e.g. when loading alien file formats.
    2750        3797 :         pCell->SetDirtyAfterLoad();
    2751             : #else
    2752             : /* This was used with the binary file format that stored results, where only
    2753             :  * newly compiled and volatile functions and their dependents had to be
    2754             :  * recalculated, which was faster then. Since that was moved to 'binfilter' to
    2755             :  * convert to an XML file this isn't needed anymore, and not used for other
    2756             :  * file formats. Kept for reference in case mechanism needs to be reactivated
    2757             :  * for some file formats, we'd have to introduce a controlling parameter to
    2758             :  * this method here then.
    2759             : */
    2760             : 
    2761             :         // If the cell was alsready dirty because of CalcAfterLoad,
    2762             :         // FormulaTracking has to take place.
    2763             :         if (pCell->GetDirty())
    2764             :             pCell->SetDirty();
    2765             : #endif
    2766        3797 :     }
    2767             : };
    2768             : 
    2769             : struct SetDirtyIfPostponedHandler
    2770             : {
    2771         314 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2772             :     {
    2773         314 :         if (pCell->IsPostponedDirty() || pCell->HasRelNameReference())
    2774          92 :             pCell->SetDirty();
    2775         314 :     }
    2776             : };
    2777             : 
    2778             : struct CalcAllHandler
    2779             : {
    2780        4300 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2781             :     {
    2782             : #if OSL_DEBUG_LEVEL > 1
    2783             :         // after F9 ctrl-F9: check the calculation for each FormulaTree
    2784             :         double nOldVal, nNewVal;
    2785             :         nOldVal = pCell->GetValue();
    2786             : #endif
    2787        4300 :         pCell->Interpret();
    2788             : #if OSL_DEBUG_LEVEL > 1
    2789             :         if (pCell->GetCode()->IsRecalcModeNormal())
    2790             :             nNewVal = pCell->GetValue();
    2791             :         else
    2792             :             nNewVal = nOldVal;  // random(), jetzt() etc.
    2793             : 
    2794             :         OSL_ENSURE(nOldVal == nNewVal, "CalcAll: nOldVal != nNewVal");
    2795             : #endif
    2796        4300 :     }
    2797             : };
    2798             : 
    2799             : class CompileAllHandler
    2800             : {
    2801             :     sc::CompileFormulaContext& mrCxt;
    2802             : public:
    2803       14336 :     CompileAllHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {}
    2804             : 
    2805          50 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2806             :     {
    2807             :         // for unconditional compilation
    2808             :         // bCompile=true and pCode->nError=0
    2809          50 :         pCell->GetCode()->SetCodeError(0);
    2810          50 :         pCell->SetCompile(true);
    2811          50 :         pCell->CompileTokenArray(mrCxt);
    2812          50 :     }
    2813             : };
    2814             : 
    2815             : class CompileXMLHandler
    2816             : {
    2817             :     sc::CompileFormulaContext& mrCxt;
    2818             :     ScProgress& mrProgress;
    2819             :     const ScColumn& mrCol;
    2820             : public:
    2821      338944 :     CompileXMLHandler( sc::CompileFormulaContext& rCxt, ScProgress& rProgress, const ScColumn& rCol) :
    2822             :         mrCxt(rCxt),
    2823             :         mrProgress(rProgress),
    2824      338944 :         mrCol(rCol) {}
    2825             : 
    2826        1603 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2827             :     {
    2828        1603 :         sal_uInt32 nFormat = mrCol.GetNumberFormat(nRow);
    2829        1603 :         if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
    2830             :             // Non-default number format is set.
    2831         328 :             pCell->SetNeedNumberFormat(false);
    2832        1275 :         else if (pCell->NeedsNumberFormat())
    2833         727 :             pCell->SetDirtyVar();
    2834             : 
    2835        1603 :         if (pCell->GetMatrixFlag())
    2836          98 :             pCell->SetDirtyVar();
    2837             : 
    2838        1603 :         pCell->CompileXML(mrCxt, mrProgress);
    2839        1603 :     }
    2840             : };
    2841             : 
    2842             : class CompileErrorCellsHandler
    2843             : {
    2844             :     sc::CompileFormulaContext& mrCxt;
    2845             :     ScColumn& mrColumn;
    2846             :     sc::CellStoreType::iterator miPos;
    2847             :     sal_uInt16 mnErrCode;
    2848             :     bool mbCompiled;
    2849             : public:
    2850           0 :     CompileErrorCellsHandler( sc::CompileFormulaContext& rCxt, ScColumn& rColumn, sal_uInt16 nErrCode ) :
    2851             :         mrCxt(rCxt),
    2852             :         mrColumn(rColumn),
    2853           0 :         miPos(mrColumn.GetCellStore().begin()),
    2854             :         mnErrCode(nErrCode),
    2855           0 :         mbCompiled(false)
    2856             :     {
    2857           0 :     }
    2858             : 
    2859           0 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2860             :     {
    2861           0 :         sal_uInt16 nCurError = pCell->GetRawError();
    2862           0 :         if (!nCurError)
    2863             :             // It's not an error cell. Skip it.
    2864           0 :             return;
    2865             : 
    2866           0 :         if (mnErrCode && nCurError != mnErrCode)
    2867             :             // Error code is specified, and it doesn't match. Skip it.
    2868           0 :             return;
    2869             : 
    2870           0 :         sc::CellStoreType::position_type aPos = mrColumn.GetCellStore().position(miPos, nRow);
    2871           0 :         miPos = aPos.first;
    2872           0 :         sc::SharedFormulaUtil::unshareFormulaCell(aPos, *pCell);
    2873           0 :         pCell->GetCode()->SetCodeError(0);
    2874           0 :         OUString aFormula = pCell->GetFormula(mrCxt);
    2875           0 :         pCell->Compile(mrCxt, aFormula, false);
    2876           0 :         ScColumn::JoinNewFormulaCell(aPos, *pCell);
    2877             : 
    2878           0 :         mbCompiled = true;
    2879             :     }
    2880             : 
    2881           0 :     bool isCompiled() const { return mbCompiled; }
    2882             : };
    2883             : 
    2884             : class CalcAfterLoadHandler
    2885             : {
    2886             :     sc::CompileFormulaContext& mrCxt;
    2887             :     bool mbStartListening;
    2888             : 
    2889             : public:
    2890      238592 :     CalcAfterLoadHandler( sc::CompileFormulaContext& rCxt, bool bStartListening ) :
    2891      238592 :         mrCxt(rCxt), mbStartListening(bStartListening) {}
    2892             : 
    2893        3797 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2894             :     {
    2895        3797 :         pCell->CalcAfterLoad(mrCxt, mbStartListening);
    2896        3797 :     }
    2897             : };
    2898             : 
    2899             : struct ResetChangedHandler
    2900             : {
    2901         407 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2902             :     {
    2903         407 :         pCell->SetChanged(false);
    2904         407 :     }
    2905             : };
    2906             : 
    2907             : /**
    2908             :  * Ambiguous script type counts as edit cell.
    2909             :  */
    2910             : class FindEditCellsHandler
    2911             : {
    2912             :     ScColumn& mrColumn;
    2913             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2914             :     sc::CellStoreType::iterator miCellPos;
    2915             : 
    2916             : public:
    2917      718653 :     FindEditCellsHandler(ScColumn& rCol) :
    2918             :         mrColumn(rCol),
    2919      718653 :         miAttrPos(rCol.GetCellAttrStore().begin()),
    2920     1437306 :         miCellPos(rCol.GetCellStore().begin()) {}
    2921             : 
    2922         107 :     bool operator() (size_t, const EditTextObject*)
    2923             :     {
    2924             :         // This is definitely an edit text cell.
    2925         107 :         return true;
    2926             :     }
    2927             : 
    2928         796 :     bool operator() (size_t nRow, const ScFormulaCell* p)
    2929             :     {
    2930             :         // With a formula cell, it's considered an edit text cell when either
    2931             :         // the result is multi-line or it has more than one script types.
    2932         796 :         SvtScriptType nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
    2933         796 :         if (IsAmbiguousScriptNonZero(nScriptType))
    2934           0 :             return true;
    2935             : 
    2936         796 :         return const_cast<ScFormulaCell*>(p)->IsMultilineResult();
    2937             :     }
    2938             : 
    2939             :     /**
    2940             :      * Callback for a block of other types.
    2941             :      */
    2942      719159 :     std::pair<size_t,bool> operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    2943             :     {
    2944             :         typedef std::pair<size_t,bool> RetType;
    2945             : 
    2946      719159 :         if (node.type == sc::element_type_empty)
    2947             :             // Ignore empty blocks.
    2948      716410 :             return RetType(0, false);
    2949             : 
    2950             :         // Check the script type of a non-empty element and see if it has
    2951             :         // multiple script types.
    2952       33847 :         for (size_t i = 0; i < nDataSize; ++i)
    2953             :         {
    2954       31100 :             SCROW nRow = node.position + i + nOffset;
    2955       31100 :             SvtScriptType nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
    2956       31100 :             if (IsAmbiguousScriptNonZero(nScriptType))
    2957             :                 // Return the offset from the first row.
    2958           2 :                 return RetType(i+nOffset, true);
    2959             :         }
    2960             : 
    2961             :         // No edit text cell found.
    2962        2747 :         return RetType(0, false);
    2963             :     }
    2964             : };
    2965             : 
    2966             : }
    2967             : 
    2968           0 : void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
    2969             :                                     ScDocument* pUndoDoc )
    2970             : {
    2971           0 :     UpdateTransHandler aFunc(*this, rSource, rDest, pUndoDoc);
    2972           0 :     sc::ProcessFormula(maCells, aFunc);
    2973           0 : }
    2974             : 
    2975           0 : void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
    2976             : {
    2977           0 :     UpdateGrowHandler aFunc(*this, rArea, nGrowX, nGrowY);
    2978           0 :     sc::ProcessFormula(maCells, aFunc);
    2979           0 : }
    2980             : 
    2981      151552 : void ScColumn::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
    2982             : {
    2983      151552 :     if (nTab >= rCxt.mnInsertPos)
    2984             :     {
    2985      135168 :         nTab += rCxt.mnSheets;
    2986      135168 :         pAttrArray->SetTab(nTab);
    2987             :     }
    2988             : 
    2989      151552 :     UpdateInsertTabOnlyCells(rCxt);
    2990      151552 : }
    2991             : 
    2992      151552 : void ScColumn::UpdateInsertTabOnlyCells( sc::RefUpdateInsertTabContext& rCxt )
    2993             : {
    2994      151552 :     InsertTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    2995      151552 :     sc::ProcessFormulaEditText(maCells, aFunc);
    2996      151552 :     if (aFunc.isModified())
    2997         246 :         CellStorageModified();
    2998      151552 : }
    2999             : 
    3000      254976 : void ScColumn::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
    3001             : {
    3002      254976 :     if (nTab > rCxt.mnDeletePos)
    3003             :     {
    3004       55296 :         nTab -= rCxt.mnSheets;
    3005       55296 :         pAttrArray->SetTab(nTab);
    3006             :     }
    3007             : 
    3008      254976 :     DeleteTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    3009      254976 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3010      254976 :     if (aFunc.isModified())
    3011         100 :         CellStorageModified();
    3012      254976 : }
    3013             : 
    3014        7168 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
    3015             : {
    3016        7168 :     InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
    3017        7168 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3018        7168 :     if (aFunc.isModified())
    3019           4 :         CellStorageModified();
    3020        7168 : }
    3021             : 
    3022       39936 : void ScColumn::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo )
    3023             : {
    3024       39936 :     nTab = nTabNo;
    3025       39936 :     pAttrArray->SetTab( nTabNo );
    3026             : 
    3027       39936 :     MoveTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    3028       39936 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3029       39936 :     if (aFunc.isModified())
    3030           9 :         CellStorageModified();
    3031       39936 : }
    3032             : 
    3033      412672 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
    3034             : {
    3035      412672 :     UpdateCompileHandler aFunc(bForceIfNameInUse);
    3036      412672 :     sc::ProcessFormula(maCells, aFunc);
    3037      412672 : }
    3038             : 
    3039       13312 : void ScColumn::SetTabNo(SCTAB nNewTab)
    3040             : {
    3041       13312 :     nTab = nNewTab;
    3042       13312 :     pAttrArray->SetTab( nNewTab );
    3043             : 
    3044       13312 :     TabNoSetter aFunc(nTab);
    3045       13312 :     sc::ProcessFormula(maCells, aFunc);
    3046       13312 : }
    3047             : 
    3048          11 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
    3049             : {
    3050          11 :     UsedRangeNameFinder aFunc(rIndexes);
    3051          11 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    3052          11 : }
    3053             : 
    3054      667648 : void ScColumn::SetDirtyVar()
    3055             : {
    3056             :     SetDirtyVarHandler aFunc;
    3057      667648 :     sc::ProcessFormula(maCells, aFunc);
    3058      667648 : }
    3059             : 
    3060           0 : bool ScColumn::IsFormulaDirty( SCROW nRow ) const
    3061             : {
    3062           0 :     if (!ValidRow(nRow))
    3063           0 :         return false;
    3064             : 
    3065           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
    3066           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    3067           0 :     if (it->type != sc::element_type_formula)
    3068             :         // This is not a formula cell block.
    3069           0 :         return false;
    3070             : 
    3071           0 :     const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
    3072           0 :     return p->GetDirty();
    3073             : }
    3074             : 
    3075     1129472 : void ScColumn::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
    3076             : {
    3077             :     // is only done documentwide, no FormulaTracking
    3078     1129472 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3079     1129472 :     SetDirtyHandler aFunc(*pDocument, rCxt);
    3080     1129472 :     sc::ProcessFormula(maCells, aFunc);
    3081     1129472 : }
    3082             : 
    3083         137 : void ScColumn::SetDirtyFromClip( SCROW nRow1, SCROW nRow2, sc::ColumnSpanSet& rBroadcastSpans )
    3084             : {
    3085             :     // Set all formula cells in the range dirty, and pick up all non-formula
    3086             :     // cells for later broadcasting.  We don't broadcast here.
    3087         137 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3088             : 
    3089         274 :     SetDirtyOnRangeHandler aHdl(*this);
    3090         137 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    3091         274 :     aHdl.fillBroadcastSpans(rBroadcastSpans);
    3092         137 : }
    3093             : 
    3094             : namespace {
    3095             : 
    3096             : class BroadcastBroadcastersHandler
    3097             : {
    3098             :     ScHint&     mrHint;
    3099             :     ScAddress&  mrAddress;
    3100             :     bool        mbBroadcasted;
    3101             : 
    3102             : public:
    3103         347 :     explicit BroadcastBroadcastersHandler( ScHint& rHint )
    3104             :         : mrHint(rHint)
    3105         347 :         , mrAddress(mrHint.GetAddress())
    3106         694 :         , mbBroadcasted(false)
    3107             :     {
    3108         347 :     }
    3109             : 
    3110         175 :     void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
    3111             :     {
    3112         175 :         mrAddress.SetRow(nRow);
    3113         175 :         pBroadcaster->Broadcast(mrHint);
    3114         175 :         mbBroadcasted = true;
    3115         175 :     }
    3116             : 
    3117         347 :     bool wasBroadcasted() { return mbBroadcasted; }
    3118             : };
    3119             : 
    3120             : }
    3121             : 
    3122         347 : bool ScColumn::BroadcastBroadcasters( SCROW nRow1, SCROW nRow2, ScHint& rHint )
    3123             : {
    3124         347 :     rHint.GetAddress().SetCol(nCol);
    3125         347 :     BroadcastBroadcastersHandler aBroadcasterHdl( rHint);
    3126         347 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aBroadcasterHdl);
    3127         347 :     return aBroadcasterHdl.wasBroadcasted();
    3128             : }
    3129             : 
    3130       13614 : void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2, BroadcastMode eMode )
    3131             : {
    3132             :     // broadcasts everything within the range, with FormulaTracking
    3133       13614 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3134             : 
    3135       13614 :     switch (eMode)
    3136             :     {
    3137             :         case BROADCAST_NONE:
    3138             :             {
    3139             :                 // Handler only used with formula cells.
    3140           1 :                 SetDirtyOnRangeHandler aHdl(*this);
    3141           1 :                 sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl);
    3142             :             }
    3143           1 :             break;
    3144             :         case BROADCAST_DATA_POSITIONS:
    3145             :             {
    3146             :                 // Handler used with both, formula and non-formula cells.
    3147       13455 :                 SetDirtyOnRangeHandler aHdl(*this);
    3148       13455 :                 sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    3149       13455 :                 aHdl.broadcast();
    3150             :             }
    3151       13455 :             break;
    3152             :         case BROADCAST_BROADCASTERS:
    3153             :             {
    3154             :                 // Handler only used with formula cells.
    3155         158 :                 SetDirtyOnRangeHandler aHdl(*this);
    3156         158 :                 sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl);
    3157             :                 // Broadcast all broadcasters in range.
    3158         316 :                 ScHint aHint( SC_HINT_DATACHANGED, ScAddress( nCol, nRow1, nTab));
    3159         316 :                 BroadcastBroadcasters( nRow1, nRow2, aHint);
    3160             :             }
    3161         158 :             break;
    3162       13614 :     }
    3163       13614 : }
    3164             : 
    3165          44 : void ScColumn::SetTableOpDirty( const ScRange& rRange )
    3166             : {
    3167          44 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3168             : 
    3169          44 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
    3170          88 :     SetTableOpDirtyOnRangeHandler aHdl(*this);
    3171          44 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    3172          88 :     aHdl.broadcast();
    3173          44 : }
    3174             : 
    3175      238592 : void ScColumn::SetDirtyAfterLoad()
    3176             : {
    3177      238592 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3178             :     SetDirtyAfterLoadHandler aFunc;
    3179      238592 :     sc::ProcessFormula(maCells, aFunc);
    3180      238592 : }
    3181             : 
    3182             : namespace {
    3183             : 
    3184      376832 : class RecalcOnRefMoveCollector
    3185             : {
    3186             :     std::vector<SCROW> maDirtyRows;
    3187             : public:
    3188         314 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    3189             :     {
    3190         314 :         if (pCell->GetDirty() && pCell->GetCode()->IsRecalcModeOnRefMove())
    3191          10 :             maDirtyRows.push_back(nRow);
    3192         314 :     }
    3193             : 
    3194      188416 :     const std::vector<SCROW>& getDirtyRows() const
    3195             :     {
    3196      188416 :         return maDirtyRows;
    3197             :     }
    3198             : };
    3199             : 
    3200             : }
    3201             : 
    3202      188416 : void ScColumn::SetDirtyIfPostponed()
    3203             : {
    3204      188416 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3205             :     SetDirtyIfPostponedHandler aFunc;
    3206      188416 :     sc::ProcessFormula(maCells, aFunc);
    3207      188416 : }
    3208             : 
    3209      188416 : void ScColumn::BroadcastRecalcOnRefMove()
    3210             : {
    3211      188416 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3212      376832 :     RecalcOnRefMoveCollector aFunc;
    3213      188416 :     sc::ProcessFormula(maCells, aFunc);
    3214      376832 :     BroadcastCells(aFunc.getDirtyRows(), SC_HINT_DATACHANGED);
    3215      188416 : }
    3216             : 
    3217             : namespace {
    3218             : 
    3219          14 : class TransferListenersHandler
    3220             : {
    3221             : public:
    3222             :     typedef std::vector<SvtListener*> ListenersType;
    3223          56 :     struct Entry
    3224             :     {
    3225             :         size_t mnRow;
    3226             :         ListenersType maListeners;
    3227             :     };
    3228             :     typedef std::vector<Entry> ListenerListType;
    3229             : 
    3230           7 :     void swapListeners( std::vector<Entry>& rListenerList )
    3231             :     {
    3232           7 :         maListenerList.swap(rListenerList);
    3233           7 :     }
    3234             : 
    3235          10 :     void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
    3236             :     {
    3237             :         assert(pBroadcaster);
    3238             : 
    3239             :         // It's important to make a copy here.
    3240          10 :         SvtBroadcaster::ListenersType aLis = pBroadcaster->GetAllListeners();
    3241          10 :         if (aLis.empty())
    3242             :             // No listeners to transfer.
    3243          10 :             return;
    3244             : 
    3245          20 :         Entry aEntry;
    3246          10 :         aEntry.mnRow = nRow;
    3247             : 
    3248          10 :         SvtBroadcaster::ListenersType::iterator it = aLis.begin(), itEnd = aLis.end();
    3249          25 :         for (; it != itEnd; ++it)
    3250             :         {
    3251          15 :             SvtListener* pLis = *it;
    3252          15 :             pLis->EndListening(*pBroadcaster);
    3253          15 :             aEntry.maListeners.push_back(pLis);
    3254             :         }
    3255             : 
    3256          10 :         maListenerList.push_back(aEntry);
    3257             : 
    3258             :         // At this point, the source broadcaster should have no more listeners.
    3259          10 :         assert(!pBroadcaster->HasListeners());
    3260             :     }
    3261             : 
    3262             : private:
    3263             :     ListenerListType maListenerList;
    3264             : };
    3265             : 
    3266           7 : class RemoveEmptyBroadcasterHandler
    3267             : {
    3268             :     sc::ColumnSpanSet maSet;
    3269             :     ScDocument& mrDoc;
    3270             :     SCCOL mnCol;
    3271             :     SCTAB mnTab;
    3272             : 
    3273             : public:
    3274           7 :     RemoveEmptyBroadcasterHandler( ScDocument& rDoc, SCCOL nCol, SCTAB nTab ) :
    3275           7 :         maSet(false), mrDoc(rDoc), mnCol(nCol), mnTab(nTab) {}
    3276             : 
    3277          10 :     void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
    3278             :     {
    3279          10 :         if (!pBroadcaster->HasListeners())
    3280           8 :             maSet.set(mnTab, mnCol, nRow, true);
    3281          10 :     }
    3282             : 
    3283           7 :     void purge()
    3284             :     {
    3285           7 :         sc::PurgeListenerAction aAction(mrDoc);
    3286           7 :         maSet.executeAction(aAction);
    3287           7 :     }
    3288             : };
    3289             : 
    3290             : }
    3291             : 
    3292           7 : void ScColumn::TransferListeners(
    3293             :     ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
    3294             : {
    3295           7 :     if (nRow2 < nRow1)
    3296           0 :         return;
    3297             : 
    3298           7 :     if (!ValidRow(nRow1) || !ValidRow(nRow2))
    3299           0 :         return;
    3300             : 
    3301           7 :     if (nRowDelta <= 0 && !ValidRow(nRow1+nRowDelta))
    3302           0 :         return;
    3303             : 
    3304           7 :     if (nRowDelta >= 0 && !ValidRow(nRow2+nRowDelta))
    3305           0 :         return;
    3306             : 
    3307             :     // Collect all listeners from the source broadcasters. The listeners will
    3308             :     // be removed from their broadcasters as they are collected.
    3309           7 :     TransferListenersHandler aFunc;
    3310           7 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
    3311             : 
    3312          14 :     TransferListenersHandler::ListenerListType aListenerList;
    3313           7 :     aFunc.swapListeners(aListenerList);
    3314             : 
    3315             :     // Re-register listeners with their destination broadcasters.
    3316           7 :     sc::BroadcasterStoreType::iterator itDestPos = rDestCol.maBroadcasters.begin();
    3317           7 :     TransferListenersHandler::ListenerListType::iterator it = aListenerList.begin(), itEnd = aListenerList.end();
    3318          17 :     for (; it != itEnd; ++it)
    3319             :     {
    3320          10 :         TransferListenersHandler::Entry& rEntry = *it;
    3321             : 
    3322          10 :         SCROW nDestRow = rEntry.mnRow + nRowDelta;
    3323             : 
    3324             :         sc::BroadcasterStoreType::position_type aPos =
    3325          10 :             rDestCol.maBroadcasters.position(itDestPos, nDestRow);
    3326             : 
    3327          10 :         itDestPos = aPos.first;
    3328          10 :         SvtBroadcaster* pDestBrd = NULL;
    3329          10 :         if (aPos.first->type == sc::element_type_broadcaster)
    3330             :         {
    3331             :             // Existing broadcaster.
    3332          10 :             pDestBrd = sc::broadcaster_block::at(*aPos.first->data, aPos.second);
    3333             :         }
    3334             :         else
    3335             :         {
    3336             :             // No existing broadcaster. Create a new one.
    3337             :             assert(aPos.first->type == sc::element_type_empty);
    3338           0 :             pDestBrd = new SvtBroadcaster;
    3339           0 :             itDestPos = rDestCol.maBroadcasters.set(itDestPos, nDestRow, pDestBrd);
    3340             :         }
    3341             : 
    3342             :         // Transfer all listeners from the source to the destination.
    3343          10 :         SvtBroadcaster::ListenersType::iterator it2 = rEntry.maListeners.begin(), it2End = rEntry.maListeners.end();
    3344          25 :         for (; it2 != it2End; ++it2)
    3345             :         {
    3346          15 :             SvtListener* pLis = *it2;
    3347          15 :             pLis->StartListening(*pDestBrd);
    3348             :         }
    3349             :     }
    3350             : 
    3351             :     // Remove any broadcasters that have no listeners.
    3352          14 :     RemoveEmptyBroadcasterHandler aFuncRemoveEmpty(*pDocument, nCol, nTab);
    3353           7 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFuncRemoveEmpty);
    3354          14 :     aFuncRemoveEmpty.purge();
    3355             : }
    3356             : 
    3357      667648 : void ScColumn::CalcAll()
    3358             : {
    3359             :     CalcAllHandler aFunc;
    3360      667648 :     sc::ProcessFormula(maCells, aFunc);
    3361      667648 : }
    3362             : 
    3363       14336 : void ScColumn::CompileAll( sc::CompileFormulaContext& rCxt )
    3364             : {
    3365       14336 :     CompileAllHandler aFunc(rCxt);
    3366       14336 :     sc::ProcessFormula(maCells, aFunc);
    3367       14336 : }
    3368             : 
    3369      338944 : void ScColumn::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress )
    3370             : {
    3371      338944 :     CompileXMLHandler aFunc(rCxt, rProgress, *this);
    3372      338944 :     sc::ProcessFormula(maCells, aFunc);
    3373      338944 :     RegroupFormulaCells();
    3374      338944 : }
    3375             : 
    3376           0 : bool ScColumn::CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode )
    3377             : {
    3378           0 :     CompileErrorCellsHandler aHdl(rCxt, *this, nErrCode);
    3379           0 :     sc::ProcessFormula(maCells, aHdl);
    3380           0 :     return aHdl.isCompiled();
    3381             : }
    3382             : 
    3383      238592 : void ScColumn::CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening )
    3384             : {
    3385      238592 :     CalcAfterLoadHandler aFunc(rCxt, bStartListening);
    3386      238592 :     sc::ProcessFormula(maCells, aFunc);
    3387      238592 : }
    3388             : 
    3389       31082 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
    3390             : {
    3391             :     ResetChangedHandler aFunc;
    3392       31082 :     sc::ProcessFormula(maCells.begin(), maCells, nStartRow, nEndRow, aFunc);
    3393       31082 : }
    3394             : 
    3395      718653 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
    3396             : {
    3397             :     //  used in GetOptimalHeight - ambiguous script type counts as edit cell
    3398             : 
    3399      718653 :     FindEditCellsHandler aFunc(*this);
    3400             :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos =
    3401      718653 :         sc::FindFormulaEditText(maCells, nStartRow, nEndRow, aFunc);
    3402             : 
    3403      718653 :     if (aPos.first == maCells.end())
    3404      718544 :         return false;
    3405             : 
    3406         109 :     rFirst = aPos.first->position + aPos.second;
    3407         109 :     return true;
    3408             : }
    3409             : 
    3410           0 : SCsROW ScColumn::SearchStyle(
    3411             :     SCsROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, bool bInSelection,
    3412             :     const ScMarkData& rMark) const
    3413             : {
    3414           0 :     if (bInSelection)
    3415             :     {
    3416           0 :         if (rMark.IsMultiMarked())
    3417           0 :             return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, rMark.GetArray()+nCol);
    3418             :         else
    3419           0 :             return -1;
    3420             :     }
    3421             :     else
    3422           0 :         return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
    3423             : }
    3424             : 
    3425           0 : bool ScColumn::SearchStyleRange(
    3426             :     SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
    3427             :     bool bInSelection, const ScMarkData& rMark) const
    3428             : {
    3429           0 :     if (bInSelection)
    3430             :     {
    3431           0 :         if (rMark.IsMultiMarked())
    3432             :             return pAttrArray->SearchStyleRange(
    3433           0 :                 rRow, rEndRow, pSearchStyle, bUp, rMark.GetArray() + nCol);
    3434             :         else
    3435           0 :             return false;
    3436             :     }
    3437             :     else
    3438           0 :         return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
    3439         156 : }
    3440             : 
    3441             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11