LCOV - code coverage report
Current view: top level - sc/source/core/data - column.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1259 1805 69.8 %
Date: 2014-04-11 Functions: 189 229 82.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10