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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "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           0 : inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
      66             : {
      67             :     //! move to a header file
      68           0 :     return ( nScript != SCRIPTTYPE_LATIN &&
      69           0 :              nScript != SCRIPTTYPE_ASIAN &&
      70           0 :              nScript != SCRIPTTYPE_COMPLEX &&
      71           0 :              nScript != 0 );
      72             : }
      73             : 
      74             : }
      75             : 
      76           0 : ScNeededSizeOptions::ScNeededSizeOptions() :
      77           0 :     pPattern(NULL), bFormula(false), bSkipMerged(true), bGetFont(true), bTotalSize(false)
      78             : {
      79           0 : }
      80             : 
      81           0 : 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           0 :     mbDirtyGroups(true)
      91             : {
      92           0 : }
      93             : 
      94             : 
      95           0 : ScColumn::~ScColumn()
      96             : {
      97           0 :     FreeAll();
      98           0 :     delete pAttrArray;
      99           0 : }
     100             : 
     101             : 
     102           0 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
     103             : {
     104           0 :     nCol = nNewCol;
     105           0 :     nTab = nNewTab;
     106           0 :     pDocument = pDoc;
     107           0 :     pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
     108           0 : }
     109             : 
     110             : 
     111           0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
     112             : {
     113           0 :     return pAttrArray->GetNextUnprotected(nRow, bUp);
     114             : }
     115             : 
     116             : 
     117           0 : sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     118             : {
     119             :     using namespace sc;
     120             : 
     121           0 :     if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
     122           0 :         return 0;
     123             : 
     124           0 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     125             : 
     126           0 :     if (nRow1 == nRow2)
     127             :     {
     128           0 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     129           0 :         if (aPos.first->type != sc::element_type_formula)
     130           0 :             return 0;
     131             : 
     132           0 :         const ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
     133           0 :         if (!pCell->GetMatrixFlag())
     134           0 :             return 0;
     135             : 
     136           0 :         return pCell->GetMatrixEdge(aOrigin);
     137             :     }
     138             : 
     139           0 :     bool bOpen = false;
     140           0 :     sal_uInt16 nEdges = 0;
     141             : 
     142           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     143           0 :     sc::CellStoreType::const_iterator it = aPos.first;
     144           0 :     size_t nOffset = aPos.second;
     145           0 :     SCROW nRow = nRow1;
     146           0 :     for (;it != maCells.end() && nRow <= nRow2; ++it, nOffset = 0)
     147             :     {
     148           0 :         if (it->type != sc::element_type_formula)
     149             :         {
     150             :             // Skip this block.
     151           0 :             nRow += it->size - nOffset;
     152           0 :             continue;
     153             :         }
     154             : 
     155           0 :         size_t nRowsToRead = nRow2 - nRow + 1;
     156           0 :         size_t nEnd = std::min(it->size, nRowsToRead);
     157           0 :         sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
     158           0 :         std::advance(itCell, nOffset);
     159           0 :         for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
     160             :         {
     161             :             // Loop inside the formula block.
     162           0 :             const ScFormulaCell* pCell = *itCell;
     163           0 :             if (!pCell->GetMatrixFlag())
     164           0 :                 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           0 :         nRow += nEnd;
     187             :     }
     188           0 :     if (bOpen)
     189           0 :         nEdges |= MatrixEdgeOpen; // not closed, matrix continues
     190             : 
     191           0 :     return nEdges;
     192             : }
     193             : 
     194             : 
     195           0 : bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
     196             : {
     197             :     using namespace sc;
     198             : 
     199           0 :     if (!rMark.IsMultiMarked())
     200           0 :         return false;
     201             : 
     202           0 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     203           0 :     ScAddress aCurOrigin = aOrigin;
     204             : 
     205           0 :     bool bOpen = false;
     206           0 :     ScRangeList aRanges = rMark.GetMarkedRanges();
     207           0 :     for (size_t i = 0, n = aRanges.size(); i < n; ++i)
     208             :     {
     209           0 :         const ScRange& r = *aRanges[i];
     210           0 :         if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab)
     211           0 :             continue;
     212             : 
     213           0 :         if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol)
     214           0 :             continue;
     215             : 
     216           0 :         SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row();
     217           0 :         SCROW nRow = nTop;
     218           0 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     219           0 :         sc::CellStoreType::const_iterator it = aPos.first;
     220           0 :         size_t nOffset = aPos.second;
     221             : 
     222           0 :         for (;it != maCells.end() && nRow <= nBottom; ++it, nOffset = 0)
     223             :         {
     224           0 :             if (it->type != sc::element_type_formula)
     225             :             {
     226             :                 // Skip this block.
     227           0 :                 nRow += it->size - nOffset;
     228           0 :                 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           0 :     if (bOpen)
     301           0 :         return true;
     302             : 
     303           0 :     return false;
     304             : }
     305             : 
     306             : 
     307           0 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     308             : {
     309           0 :     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           0 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
     335             :                             SCCOL& rPaintCol, SCROW& rPaintRow,
     336             :                             bool bRefresh )
     337             : {
     338           0 :     return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
     339             : }
     340             : 
     341             : 
     342           0 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
     343             : {
     344             :     SCROW nTop;
     345             :     SCROW nBottom;
     346             : 
     347           0 :     if ( rMark.IsMultiMarked() )
     348             :     {
     349           0 :         const ScMarkArray* pArray = rMark.GetArray() + nCol;
     350           0 :         if ( pArray->HasMarks() )
     351             :         {
     352           0 :             ScMarkArrayIter aMarkIter( pArray );
     353           0 :             while (aMarkIter.Next( nTop, nBottom ))
     354           0 :                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
     355             :         }
     356             :     }
     357           0 : }
     358             : 
     359             : 
     360           0 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
     361             : {
     362           0 :     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
     363           0 : }
     364             : 
     365             : 
     366           0 : void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     367             :                             ScLineFlags& rFlags,
     368             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
     369             : {
     370           0 :     pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
     371           0 : }
     372             : 
     373             : 
     374           0 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
     375             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
     376             : {
     377           0 :     pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
     378           0 : }
     379             : 
     380             : 
     381           0 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
     382             : {
     383           0 :     return pAttrArray->GetPattern( nRow );
     384             : }
     385             : 
     386             : 
     387           0 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
     388             : {
     389           0 :     return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
     390             : }
     391             : 
     392             : 
     393           0 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
     394             : {
     395           0 :     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     396           0 :     const ScPatternAttr* pMaxPattern = 0;
     397           0 :     size_t nMaxCount = 0;
     398             : 
     399           0 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
     400             :     const ScPatternAttr* pPattern;
     401           0 :     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
     402             : 
     403           0 :     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
     404             :     {
     405           0 :         size_t& rnCount = aAttrMap[ pPattern ];
     406           0 :         rnCount += (nAttrRow2 - nAttrRow1 + 1);
     407           0 :         if( rnCount > nMaxCount )
     408             :         {
     409           0 :             pMaxPattern = pPattern;
     410           0 :             nMaxCount = rnCount;
     411             :         }
     412             :     }
     413             : 
     414           0 :     return pMaxPattern;
     415             : }
     416             : 
     417           0 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
     418             : {
     419             :     SCROW nPatStartRow, nPatEndRow;
     420           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     421           0 :     sal_uInt32 nFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     422           0 :     while (nEndRow > nPatEndRow)
     423             :     {
     424           0 :         nStartRow = nPatEndRow + 1;
     425           0 :         pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     426           0 :         sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     427           0 :         if (nFormat != nTmpFormat)
     428           0 :             return 0;
     429             :     }
     430           0 :     return nFormat;
     431             : }
     432             : 
     433             : 
     434           0 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
     435             : {
     436           0 :     return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
     437             : }
     438             : 
     439             : 
     440           0 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
     441             : {
     442           0 :     SCROW nTop = 0;
     443           0 :     SCROW nBottom = 0;
     444           0 :     bool bFound = false;
     445             : 
     446           0 :     if ( rMark.IsMultiMarked() )
     447             :     {
     448           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     449           0 :         while (aMarkIter.Next( nTop, nBottom ))
     450             :         {
     451           0 :             pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
     452           0 :             bFound = true;
     453           0 :         }
     454             :     }
     455             : 
     456           0 :     if (!bFound)
     457           0 :         return -1;
     458           0 :     else if (nTop==0 && nBottom==MAXROW)
     459           0 :         return 0;
     460             :     else
     461           0 :         return nBottom;
     462             : }
     463             : 
     464             : 
     465           0 : void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
     466             : {
     467             :     SCROW nTop;
     468             :     SCROW nBottom;
     469             : 
     470           0 :     if ( pAttrArray && rMark.IsMultiMarked() )
     471             :     {
     472           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     473           0 :         while (aMarkIter.Next( nTop, nBottom ))
     474           0 :             pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
     475             :     }
     476           0 : }
     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           0 : void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark, bool bBroadcast )
     493             : {
     494             :     SCROW nTop;
     495             :     SCROW nBottom;
     496             : 
     497           0 :     if ( rMark.IsMultiMarked() )
     498             :     {
     499           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     500           0 :         while (aMarkIter.Next( nTop, nBottom ))
     501           0 :             DeleteArea(nTop, nBottom, nDelFlag, bBroadcast);
     502             :     }
     503           0 : }
     504             : 
     505             : 
     506           0 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
     507             : {
     508           0 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     509           0 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     510             : 
     511           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
     512             : 
     513             :     //  true = keep old content
     514             : 
     515           0 :     ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, true );
     516           0 :     ScDocumentPool::CheckRef( *pPattern );
     517           0 :     ScDocumentPool::CheckRef( *pNewPattern );
     518             : 
     519           0 :     if (pNewPattern != pPattern)
     520           0 :       pAttrArray->SetPattern( nRow, pNewPattern );
     521           0 : }
     522             : 
     523             : 
     524           0 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
     525             :                                  ScEditDataArray* pDataArray )
     526             : {
     527           0 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     528           0 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     529           0 :     pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
     530           0 : }
     531             : 
     532           0 : bool ScColumn::SetAttrEntries(ScAttrEntry* pData, SCSIZE nSize)
     533             : {
     534           0 :     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           0 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     564             : {
     565           0 :     pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
     566           0 : }
     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           0 : void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
     575             : {
     576           0 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
     577           0 :     ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
     578           0 :     if (pNewPattern)
     579             :     {
     580           0 :         pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
     581           0 :         pAttrArray->SetPattern(nRow, pNewPattern, true);
     582           0 :         delete pNewPattern;
     583             :     }
     584           0 : }
     585             : 
     586             : 
     587           0 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
     588             : {
     589           0 :     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
     590           0 : }
     591             : 
     592             : 
     593           0 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
     594             : {
     595             :     SCROW nTop;
     596             :     SCROW nBottom;
     597             : 
     598           0 :     if ( rMark.IsMultiMarked() )
     599             :     {
     600           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     601           0 :         while (aMarkIter.Next( nTop, nBottom ))
     602           0 :             pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
     603             :     }
     604           0 : }
     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           0 : const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
     626             : {
     627           0 :     return pAttrArray->GetPattern( nRow )->GetStyleSheet();
     628             : }
     629             : 
     630             : 
     631           0 : const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
     632             : {
     633           0 :     rFound = false;
     634           0 :     if (!rMark.IsMultiMarked())
     635             :     {
     636             :         OSL_FAIL("No selection in ScColumn::GetSelectionStyle");
     637           0 :         return NULL;
     638             :     }
     639             : 
     640           0 :     bool bEqual = true;
     641             : 
     642           0 :     const ScStyleSheet* pStyle = NULL;
     643             :     const ScStyleSheet* pNewStyle;
     644             : 
     645           0 :     ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     646             :     SCROW nTop;
     647             :     SCROW nBottom;
     648           0 :     while (bEqual && aMarkIter.Next( nTop, nBottom ))
     649             :     {
     650           0 :         ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
     651             :         SCROW nRow;
     652             :         SCROW nDummy;
     653             :         const ScPatternAttr* pPattern;
     654           0 :         while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     655             :         {
     656           0 :             pNewStyle = pPattern->GetStyleSheet();
     657           0 :             rFound = true;
     658           0 :             if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     659           0 :                 bEqual = false;                                             // difference
     660           0 :             pStyle = pNewStyle;
     661             :         }
     662             :     }
     663             : 
     664           0 :     return bEqual ? pStyle : NULL;
     665             : }
     666             : 
     667             : 
     668           0 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
     669             : {
     670           0 :     rFound = false;
     671             : 
     672           0 :     bool bEqual = true;
     673             : 
     674           0 :     const ScStyleSheet* pStyle = NULL;
     675             :     const ScStyleSheet* pNewStyle;
     676             : 
     677           0 :     ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
     678             :     SCROW nRow;
     679             :     SCROW nDummy;
     680             :     const ScPatternAttr* pPattern;
     681           0 :     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     682             :     {
     683           0 :         pNewStyle = pPattern->GetStyleSheet();
     684           0 :         rFound = true;
     685           0 :         if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     686           0 :             bEqual = false;                                             // difference
     687           0 :         pStyle = pNewStyle;
     688             :     }
     689             : 
     690           0 :     return bEqual ? pStyle : NULL;
     691             : }
     692             : 
     693           0 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
     694             : {
     695           0 :     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
     696           0 : }
     697             : 
     698           0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
     699             : {
     700           0 :     return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
     701             : }
     702             : 
     703             : 
     704           0 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     705             : {
     706           0 :     return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
     707             : }
     708             : 
     709             : 
     710           0 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     711             : {
     712           0 :     return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
     713             : }
     714             : 
     715             : 
     716           0 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
     717             : {
     718           0 :     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
     719           0 : }
     720             : 
     721             : 
     722           0 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
     723             : {
     724           0 :     pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
     725           0 : }
     726             : 
     727             : 
     728           0 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
     729             :                                 const ScPatternAttr& rPatAttr, bool bPutToPool )
     730             : {
     731           0 :     pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
     732           0 : }
     733             : 
     734             : 
     735           0 : 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           0 :     ScDocumentPool* pDocPool = pDocument->GetPool();
     741             : 
     742           0 :     const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
     743           0 :     ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
     744           0 :     pTemp->GetItemSet().Put(rAttr);
     745           0 :     const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
     746             : 
     747           0 :     if ( pNewPattern != pOldPattern )
     748           0 :         pAttrArray->SetPattern( nRow, pNewPattern );
     749             :     else
     750           0 :         pDocPool->Remove( *pNewPattern );       // free up resources
     751             : 
     752           0 :     delete pTemp;
     753           0 : }
     754             : 
     755           0 : ScDocument& ScColumn::GetDoc()
     756             : {
     757           0 :     return *pDocument;
     758             : }
     759             : 
     760           0 : const ScDocument& ScColumn::GetDoc() const
     761             : {
     762           0 :     return *pDocument;
     763             : }
     764             : 
     765           0 : ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const
     766             : {
     767           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     768           0 :     if (aPos.first == maCells.end())
     769           0 :         return ScRefCellValue();
     770             : 
     771           0 :     return GetCellValue(aPos.first, aPos.second);
     772             : }
     773             : 
     774           0 : ScRefCellValue ScColumn::GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ) const
     775             : {
     776           0 :     ScRefCellValue aVal; // Defaults to empty cell.
     777           0 :     switch (itPos->type)
     778             :     {
     779             :         case sc::element_type_numeric:
     780             :             // Numeric cell
     781           0 :             aVal.mfValue = sc::numeric_block::at(*itPos->data, nOffset);
     782           0 :             aVal.meType = CELLTYPE_VALUE;
     783           0 :         break;
     784             :         case sc::element_type_string:
     785             :             // String cell
     786           0 :             aVal.mpString = &sc::string_block::at(*itPos->data, nOffset);
     787           0 :             aVal.meType = CELLTYPE_STRING;
     788           0 :         break;
     789             :         case sc::element_type_edittext:
     790             :             // Edit cell
     791           0 :             aVal.mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
     792           0 :             aVal.meType = CELLTYPE_EDIT;
     793           0 :         break;
     794             :         case sc::element_type_formula:
     795             :             // Formula cell
     796           0 :             aVal.mpFormula = sc::formula_block::at(*itPos->data, nOffset);
     797           0 :             aVal.meType = CELLTYPE_FORMULA;
     798           0 :         break;
     799             :         default:
     800             :             ;
     801             :     }
     802             : 
     803           0 :     return aVal;
     804             : }
     805             : 
     806             : namespace {
     807             : 
     808           0 : ScFormulaCell* cloneFormulaCell(ScDocument* pDoc, const ScAddress& rNewPos, ScFormulaCell& rOldCell)
     809             : {
     810           0 :     ScFormulaCell* pNew = new ScFormulaCell(rOldCell, *pDoc, rNewPos, SC_CLONECELL_ADJUST3DREL);
     811           0 :     rOldCell.EndListeningTo(pDoc);
     812           0 :     pNew->StartListeningTo(pDoc);
     813           0 :     pNew->SetDirty();
     814           0 :     return pNew;
     815             : }
     816             : 
     817             : }
     818             : 
     819           0 : void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
     820             : {
     821           0 :     if (nRow1 == nRow2)
     822             :         // Nothing to swap.
     823           0 :         return;
     824             : 
     825             :     // Ensure that nRow1 < nRow2.
     826           0 :     if (nRow2 < nRow1)
     827           0 :         std::swap(nRow1, nRow2);
     828             : 
     829             :     // Broadcasters (if exist) should NOT be swapped.
     830             : 
     831           0 :     sc::CellStoreType::position_type aPos1 = maCells.position(nRow1);
     832           0 :     if (aPos1.first == maCells.end())
     833           0 :         return;
     834             : 
     835           0 :     sc::CellStoreType::position_type aPos2 = maCells.position(aPos1.first, nRow2);
     836           0 :     if (aPos2.first == maCells.end())
     837           0 :         return;
     838             : 
     839           0 :     std::vector<SCROW> aRows;
     840           0 :     aRows.reserve(2);
     841           0 :     aRows.push_back(nRow1);
     842           0 :     aRows.push_back(nRow2);
     843             : 
     844           0 :     sc::CellStoreType::iterator it1 = aPos1.first, it2 = aPos2.first;
     845             : 
     846           0 :     if (it1->type == it2->type)
     847             :     {
     848             :         // Both positions are of the same type. Do a simple value swap.
     849           0 :         switch (it1->type)
     850             :         {
     851             :             case sc::element_type_empty:
     852             :                 // Both are empty. Nothing to swap.
     853           0 :                 return;
     854             :             case sc::element_type_numeric:
     855             :                 std::swap(
     856           0 :                     sc::numeric_block::at(*it1->data, aPos1.second),
     857           0 :                     sc::numeric_block::at(*it2->data, aPos2.second));
     858           0 :             break;
     859             :             case sc::element_type_string:
     860             :                 std::swap(
     861           0 :                     sc::string_block::at(*it1->data, aPos1.second),
     862           0 :                     sc::string_block::at(*it2->data, aPos2.second));
     863           0 :             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           0 :                 sc::formula_block::iterator itf1 = sc::formula_block::begin(*it1->data);
     873           0 :                 sc::formula_block::iterator itf2 = sc::formula_block::begin(*it2->data);
     874           0 :                 std::advance(itf1, aPos1.second);
     875           0 :                 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           0 :                 if(!(*itf1)->SwapWithinGroup(*itf2))
     880             :                 {
     881             :                     // otherwise we need to really move the formula &
     882             :                     // re-write dependencies etc.
     883           0 :                     boost::scoped_ptr<ScFormulaCell> pOld1(*itf1);
     884           0 :                     boost::scoped_ptr<ScFormulaCell> pOld2(*itf2);
     885             : 
     886           0 :                     DetachFormulaCell(aPos1, **itf1);
     887           0 :                     DetachFormulaCell(aPos2, **itf2);
     888           0 :                     ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2);
     889           0 :                     ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1);
     890           0 :                     *itf1 = pNew1;
     891           0 :                     *itf2 = pNew2;
     892             : 
     893           0 :                     ActivateNewFormulaCell(aPos1, *pNew1);
     894           0 :                     ActivateNewFormulaCell(aPos2, *pNew2);
     895             :                 }
     896             :             }
     897           0 :             break;
     898             :             default:
     899             :                 ;
     900             :         }
     901             : 
     902           0 :         SwapCellTextAttrs(nRow1, nRow2);
     903           0 :         SwapCellNotes(nRow1, nRow2);
     904           0 :         CellStorageModified();
     905           0 :         BroadcastCells(aRows, SC_HINT_DATACHANGED);
     906           0 :         return;
     907             :     }
     908             : 
     909             :     // The two cells are of different types.
     910             : 
     911           0 :     ScRefCellValue aCell1 = GetCellValue(aPos1.first, aPos1.second);
     912           0 :     ScRefCellValue aCell2 = GetCellValue(aPos2.first, aPos2.second);
     913             : 
     914             :     // Make sure to put cells in row 1 first then row 2!
     915             : 
     916           0 :     if (aCell1.meType == CELLTYPE_NONE)
     917             :     {
     918             :         // cell 1 is empty and cell 2 is not.
     919           0 :         switch (aCell2.meType)
     920             :         {
     921             :             case CELLTYPE_VALUE:
     922           0 :                 it1 = maCells.set(it1, nRow1, aCell2.mfValue); // it2 becomes invalid.
     923           0 :                 maCells.set_empty(it1, nRow2, nRow2);
     924           0 :             break;
     925             :             case CELLTYPE_STRING:
     926           0 :                 it1 = maCells.set(it1, nRow1, *aCell2.mpString);
     927           0 :                 maCells.set_empty(it1, nRow2, nRow2);
     928           0 :             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           0 :         SwapCellTextAttrs(nRow1, nRow2);
     952           0 :         SwapCellNotes(nRow1, nRow2);
     953           0 :         CellStorageModified();
     954           0 :         BroadcastCells(aRows, SC_HINT_DATACHANGED);
     955           0 :         return;
     956             :     }
     957             : 
     958           0 :     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           0 :     switch (aCell1.meType)
    1005             :     {
    1006             :         case CELLTYPE_VALUE:
    1007             :         {
    1008           0 :             switch (aCell2.meType)
    1009             :             {
    1010             :                 case CELLTYPE_STRING:
    1011           0 :                     it1 = maCells.set(it1, nRow1, *aCell2.mpString);
    1012           0 :                 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           0 :             maCells.set(it1, nRow2, aCell1.mfValue);
    1035             : 
    1036             :         }
    1037           0 :         break;
    1038             :         case CELLTYPE_STRING:
    1039             :         {
    1040           0 :             svl::SharedString aStr = *aCell1.mpString; // make a copy.
    1041           0 :             switch (aCell2.meType)
    1042             :             {
    1043             :                 case CELLTYPE_VALUE:
    1044           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mfValue);
    1045           0 :                 break;
    1046             :                 case CELLTYPE_EDIT:
    1047             :                 {
    1048           0 :                     it1 = maCells.set(
    1049           0 :                         it1, nRow1, const_cast<EditTextObject*>(aCell2.mpEditText));
    1050             :                     EditTextObject* p;
    1051           0 :                     it1 = maCells.release(it1, nRow2, p); // prevent it being overwritten.
    1052             :                 }
    1053           0 :                 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           0 :             maCells.set(it1, nRow2, aStr);
    1069             :         }
    1070           0 :         break;
    1071             :         case CELLTYPE_EDIT:
    1072             :         {
    1073             :             EditTextObject* p;
    1074           0 :             it1 = maCells.release(it1, nRow1, p);
    1075             : 
    1076           0 :             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           0 :                     it1 = maCells.set(it1, nRow1, *aCell2.mpString);
    1083           0 :                 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           0 :             maCells.set(it1, nRow2, const_cast<EditTextObject*>(aCell1.mpEditText));
    1098             :         }
    1099           0 :         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           0 :     SwapCellTextAttrs(nRow1, nRow2);
    1133           0 :     SwapCellNotes(nRow1, nRow2);
    1134           0 :     CellStorageModified();
    1135           0 :     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           0 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
    1199             : {
    1200           0 :     if (IsEmpty())
    1201           0 :         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           0 : bool ScColumn::TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const
    1222             : {
    1223             :     //  AttrArray only looks for merged cells
    1224             :     {
    1225           0 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
    1226           0 :         sc::CellStoreType::const_iterator it = aPos.first;
    1227           0 :         if (it->type == sc::element_type_empty && maCells.block_size() == 1)
    1228             :             // The entire cell array is empty.
    1229           0 :             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           0 :     size_t nLastNonEmptyRow = MAXROW;
    1236           0 :     sc::CellStoreType::const_reverse_iterator it = maCells.rbegin();
    1237           0 :     if (it->type == sc::element_type_empty)
    1238           0 :         nLastNonEmptyRow -= it->size;
    1239             : 
    1240           0 :     if (nLastNonEmptyRow < static_cast<size_t>(nStartRow))
    1241             :         // No cells would get pushed out.
    1242           0 :         return pAttrArray->TestInsertRow(nSize);
    1243             : 
    1244           0 :     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           0 :     return pAttrArray->TestInsertRow(nSize);
    1249             : }
    1250             : 
    1251             : 
    1252           0 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
    1253             : {
    1254           0 :     pAttrArray->InsertRow( nStartRow, nSize );
    1255             : 
    1256           0 :     maCellNotes.insert_empty(nStartRow, nSize);
    1257           0 :     maCellNotes.resize(MAXROWCOUNT);
    1258             : 
    1259           0 :     maBroadcasters.insert_empty(nStartRow, nSize);
    1260           0 :     maBroadcasters.resize(MAXROWCOUNT);
    1261             : 
    1262           0 :     maCellTextAttrs.insert_empty(nStartRow, nSize);
    1263           0 :     maCellTextAttrs.resize(MAXROWCOUNT);
    1264             : 
    1265           0 :     maCells.insert_empty(nStartRow, nSize);
    1266           0 :     maCells.resize(MAXROWCOUNT);
    1267             : 
    1268           0 :     CellStorageModified();
    1269             : 
    1270             :     // We *probably* don't need to broadcast here since the parent call seems
    1271             :     // to take care of it.
    1272           0 : }
    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           0 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1285             :     {
    1286           0 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1287           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1288           0 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1289           0 :     }
    1290             : 
    1291           0 :     void duplicateNotes(SCROW nStartRow, size_t nDataSize )
    1292             :     {
    1293           0 :         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestPos, false);
    1294           0 :     }
    1295             : 
    1296             : public:
    1297           0 :     CopyToClipHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, bool bCopyNotes) :
    1298           0 :         mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mbCopyNotes(bCopyNotes)
    1299             :     {
    1300           0 :         if (mpDestPos)
    1301           0 :             maDestPos = *mpDestPos;
    1302             :         else
    1303           0 :             mrDestCol.InitBlockPosition(maDestPos);
    1304           0 :     }
    1305             : 
    1306           0 :     ~CopyToClipHandler()
    1307             :     {
    1308           0 :         if (mpDestPos)
    1309           0 :             *mpDestPos = maDestPos;
    1310           0 :     }
    1311             : 
    1312           0 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1313             :     {
    1314           0 :         size_t nTopRow = aNode.position + nOffset;
    1315             : 
    1316           0 :         bool bSet = true;
    1317             : 
    1318           0 :         switch (aNode.type)
    1319             :         {
    1320             :             case sc::element_type_numeric:
    1321             :             {
    1322           0 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1323           0 :                 std::advance(it, nOffset);
    1324           0 :                 sc::numeric_block::const_iterator itEnd = it;
    1325           0 :                 std::advance(itEnd, nDataSize);
    1326           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
    1327             :             }
    1328           0 :             break;
    1329             :             case sc::element_type_string:
    1330             :             {
    1331           0 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
    1332           0 :                 std::advance(it, nOffset);
    1333           0 :                 sc::string_block::const_iterator itEnd = it;
    1334           0 :                 std::advance(itEnd, nDataSize);
    1335           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
    1336             : 
    1337             :             }
    1338           0 :             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           0 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
    1358           0 :                 std::advance(it, nOffset);
    1359           0 :                 sc::formula_block::const_iterator itEnd = it;
    1360           0 :                 std::advance(itEnd, nDataSize);
    1361             : 
    1362           0 :                 std::vector<ScFormulaCell*> aCloned;
    1363           0 :                 aCloned.reserve(nDataSize);
    1364           0 :                 ScAddress aDestPos(mrDestCol.GetCol(), nTopRow, mrDestCol.GetTab());
    1365           0 :                 for (; it != itEnd; ++it, aDestPos.IncRow())
    1366             :                 {
    1367           0 :                     const ScFormulaCell& rOld = **it;
    1368           0 :                     if (rOld.GetDirty() && mrSrcCol.GetDoc().GetAutoCalc())
    1369           0 :                         const_cast<ScFormulaCell&>(rOld).Interpret();
    1370             : 
    1371           0 :                     aCloned.push_back(new ScFormulaCell(rOld, mrDestCol.GetDoc(), aDestPos));
    1372             :                 }
    1373             : 
    1374             :                 // Group the cloned formula cells.
    1375           0 :                 if (!aCloned.empty())
    1376           0 :                     sc::SharedFormulaUtil::groupFormulaCells(aCloned.begin(), aCloned.end());
    1377             : 
    1378           0 :                 sc::CellStoreType& rDestCells = mrDestCol.GetCellStore();
    1379           0 :                 maDestPos.miCellPos = rDestCells.set(
    1380           0 :                     maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
    1381             : 
    1382             :                 // Merge adjacent formula cell groups (if applicable).
    1383             :                 sc::CellStoreType::position_type aPos =
    1384           0 :                     rDestCells.position(maDestPos.miCellPos, nTopRow);
    1385           0 :                 maDestPos.miCellPos = aPos.first;
    1386           0 :                 sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    1387           0 :                 size_t nLastRow = nTopRow + nDataSize;
    1388           0 :                 if (nLastRow < static_cast<size_t>(MAXROW))
    1389             :                 {
    1390           0 :                     aPos = rDestCells.position(maDestPos.miCellPos, nLastRow+1);
    1391           0 :                     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    1392           0 :                 }
    1393             :             }
    1394           0 :             break;
    1395             :             default:
    1396           0 :                 bSet = false;
    1397             :         }
    1398             : 
    1399           0 :         if (bSet)
    1400           0 :             setDefaultAttrsToDest(nTopRow, nDataSize);
    1401             : 
    1402           0 :         if (mbCopyNotes)
    1403           0 :             duplicateNotes(nTopRow, nDataSize);
    1404           0 :     }
    1405             : };
    1406             : 
    1407             : }
    1408             : 
    1409           0 : void ScColumn::CopyToClip(
    1410             :     sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const
    1411             : {
    1412             :     pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
    1413           0 :                           rCxt.isKeepScenarioFlags() ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
    1414             : 
    1415           0 :     CopyToClipHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), rCxt.isCloneNotes());
    1416           0 :     sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1417             : 
    1418           0 :     rColumn.CellStorageModified();
    1419           0 : }
    1420             : 
    1421           0 : void ScColumn::CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol)
    1422             : {
    1423           0 :     if (nRow1 > nRow2)
    1424           0 :         return;
    1425             : 
    1426           0 :     sc::ColumnBlockPosition aDestPos;
    1427           0 :     CopyCellTextAttrsToDocument(nRow1, nRow2, rDestCol);
    1428           0 :     CopyCellNotesToDocument(nRow1, nRow2, rDestCol);
    1429             : 
    1430             :     // First, clear the destination column for the specified row range.
    1431           0 :     rDestCol.maCells.set_empty(nRow1, nRow2);
    1432             : 
    1433           0 :     aDestPos.miCellPos = rDestCol.maCells.begin();
    1434             : 
    1435           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
    1436           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    1437           0 :     size_t nOffset = aPos.second;
    1438           0 :     size_t nDataSize = 0;
    1439           0 :     size_t nCurRow = nRow1;
    1440             : 
    1441           0 :     for (; it != maCells.end() && nCurRow <= static_cast<size_t>(nRow2); ++it, nOffset = 0, nCurRow += nDataSize)
    1442             :     {
    1443           0 :         bool bLastBlock = false;
    1444           0 :         nDataSize = it->size - nOffset;
    1445           0 :         if (nCurRow + nDataSize - 1 > static_cast<size_t>(nRow2))
    1446             :         {
    1447             :             // Truncate the block to copy to clipboard.
    1448           0 :             nDataSize = nRow2 - nCurRow + 1;
    1449           0 :             bLastBlock = true;
    1450             :         }
    1451             : 
    1452           0 :         switch (it->type)
    1453             :         {
    1454             :             case sc::element_type_numeric:
    1455             :             {
    1456           0 :                 sc::numeric_block::const_iterator itData = sc::numeric_block::begin(*it->data);
    1457           0 :                 std::advance(itData, nOffset);
    1458           0 :                 sc::numeric_block::const_iterator itDataEnd = itData;
    1459           0 :                 std::advance(itDataEnd, nDataSize);
    1460           0 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1461             :             }
    1462           0 :             break;
    1463             :             case sc::element_type_string:
    1464             :             {
    1465           0 :                 sc::string_block::const_iterator itData = sc::string_block::begin(*it->data);
    1466           0 :                 std::advance(itData, nOffset);
    1467           0 :                 sc::string_block::const_iterator itDataEnd = itData;
    1468           0 :                 std::advance(itDataEnd, nDataSize);
    1469           0 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1470             :             }
    1471           0 :             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           0 :                 sc::formula_block::const_iterator itData = sc::formula_block::begin(*it->data);
    1494           0 :                 std::advance(itData, nOffset);
    1495           0 :                 sc::formula_block::const_iterator itDataEnd = itData;
    1496           0 :                 std::advance(itDataEnd, nDataSize);
    1497             : 
    1498             :                 // Interpret and convert to raw values.
    1499           0 :                 for (SCROW i = 0; itData != itDataEnd; ++itData, ++i)
    1500             :                 {
    1501           0 :                     SCROW nRow = nCurRow + i;
    1502             : 
    1503           0 :                     ScFormulaCell& rFC = const_cast<ScFormulaCell&>(**itData);
    1504           0 :                     if (rFC.GetDirty() && pDocument->GetAutoCalc())
    1505           0 :                         rFC.Interpret();
    1506             : 
    1507           0 :                     if (rFC.GetErrCode())
    1508             :                         // Skip cells with error.
    1509           0 :                         break;
    1510             : 
    1511           0 :                     if (rFC.IsValue())
    1512           0 :                         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           0 :             break;
    1522             :             default:
    1523             :                 ;
    1524             :         }
    1525             : 
    1526           0 :         if (bLastBlock)
    1527           0 :             break;
    1528             :     }
    1529             : 
    1530           0 :     rDestCol.CellStorageModified();
    1531             : }
    1532             : 
    1533           0 : void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol )
    1534             : {
    1535           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nSrcRow);
    1536           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    1537           0 :     bool bSet = true;
    1538           0 :     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           0 :             rDestCol.maCells.set(nDestRow, sc::string_block::at(*it->data, aPos.second));
    1545           0 :         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           0 :     if (bSet)
    1575             :     {
    1576           0 :         rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
    1577           0 :         ScPostIt* pNote = maCellNotes.get<ScPostIt*>(nSrcRow);
    1578           0 :         rDestCol.maCellNotes.set(nDestRow, pNote);
    1579           0 :         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           0 :     rDestCol.CellStorageModified();
    1589           0 : }
    1590             : 
    1591             : namespace {
    1592             : 
    1593           0 : bool canCopyValue(const ScDocument& rDoc, const ScAddress& rPos, sal_uInt16 nFlags)
    1594             : {
    1595           0 :     sal_uInt32 nNumIndex = static_cast<const SfxUInt32Item*>(rDoc.GetAttr(rPos, ATTR_VALUE_FORMAT))->GetValue();
    1596           0 :     short nType = rDoc.GetFormatTable()->GetType(nNumIndex);
    1597           0 :     if ((nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME))
    1598           0 :         return ((nFlags & IDF_DATETIME) != 0);
    1599             : 
    1600           0 :     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           0 :     void setDefaultAttrToDest(size_t nRow)
    1733             :     {
    1734           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1735           0 :             maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
    1736           0 :     }
    1737             : 
    1738           0 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1739             :     {
    1740           0 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1741           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1742           0 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1743           0 :     }
    1744             : 
    1745           0 :     void cloneFormulaCell(size_t nRow, ScFormulaCell& rSrcCell)
    1746             :     {
    1747           0 :         ScAddress aDestPos(mrDestCol.GetCol(), nRow, mrDestCol.GetTab());
    1748             : 
    1749           0 :         bool bCloneValue          = (mnCopyFlags & IDF_VALUE) != 0;
    1750           0 :         bool bCloneDateTime       = (mnCopyFlags & IDF_DATETIME) != 0;
    1751           0 :         bool bCloneString         = (mnCopyFlags & IDF_STRING) != 0;
    1752           0 :         bool bCloneSpecialBoolean = (mnCopyFlags & IDF_SPECIAL_BOOLEAN) != 0;
    1753           0 :         bool bCloneFormula        = (mnCopyFlags & IDF_FORMULA) != 0;
    1754             : 
    1755           0 :         bool bForceFormula = false;
    1756             : 
    1757           0 :         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           0 :         if (bForceFormula || bCloneFormula)
    1771             :         {
    1772             :             // Clone as formula cell.
    1773           0 :             ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos);
    1774           0 :             pCell->SetDirtyVar();
    1775           0 :             mrDestCol.SetFormulaCell(maDestPos, nRow, pCell);
    1776           0 :             setDefaultAttrToDest(nRow);
    1777           0 :             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           0 :     void duplicateNotes(SCROW nStartRow, size_t nDataSize, bool bCloneCaption )
    1838             :     {
    1839           0 :         mrSrcCol.DuplicateNotes(nStartRow, nDataSize, mrDestCol, maDestPos, bCloneCaption);
    1840           0 :     }
    1841             : 
    1842             : public:
    1843           0 :     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           0 :         mnCopyFlags(nCopyFlags)
    1847             :     {
    1848           0 :         if (mpDestPos)
    1849           0 :             maDestPos = *mpDestPos;
    1850           0 :     }
    1851             : 
    1852           0 :     ~CopyByCloneHandler()
    1853             :     {
    1854           0 :         if (mpDestPos)
    1855           0 :             *mpDestPos = maDestPos;
    1856           0 :     }
    1857             : 
    1858           0 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1859             :     {
    1860           0 :         size_t nRow = aNode.position + nOffset;
    1861             : 
    1862           0 :         if (mnCopyFlags & (IDF_NOTE|IDF_ADDNOTES))
    1863             :         {
    1864           0 :             bool bCloneCaption = (mnCopyFlags & IDF_NOCAPTIONS) == 0;
    1865           0 :             duplicateNotes(nRow, nDataSize, bCloneCaption );
    1866             :         }
    1867             : 
    1868           0 :         switch (aNode.type)
    1869             :         {
    1870             :             case sc::element_type_numeric:
    1871             :             {
    1872           0 :                 if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == 0)
    1873           0 :                     return;
    1874             : 
    1875           0 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1876           0 :                 std::advance(it, nOffset);
    1877           0 :                 sc::numeric_block::const_iterator itEnd = it;
    1878           0 :                 std::advance(itEnd, nDataSize);
    1879             : 
    1880           0 :                 ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
    1881           0 :                 for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
    1882             :                 {
    1883           0 :                     if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
    1884           0 :                         continue;
    1885             : 
    1886           0 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, *it);
    1887           0 :                     setDefaultAttrToDest(nRow);
    1888             :                 }
    1889             :             }
    1890           0 :             break;
    1891             :             case sc::element_type_string:
    1892             :             {
    1893           0 :                 if (!(mnCopyFlags & IDF_STRING))
    1894           0 :                     return;
    1895             : 
    1896           0 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
    1897           0 :                 std::advance(it, nOffset);
    1898           0 :                 sc::string_block::const_iterator itEnd = it;
    1899           0 :                 std::advance(itEnd, nDataSize);
    1900             : 
    1901           0 :                 for (; it != itEnd; ++it, ++nRow)
    1902             :                 {
    1903           0 :                     const svl::SharedString& rStr = *it;
    1904           0 :                     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           0 :                         if (mpSharedStringPool)
    1915             :                         {
    1916             :                             // Re-intern the string if source is a different document.
    1917           0 :                             svl::SharedString aInterned = mpSharedStringPool->intern( rStr.getString());
    1918           0 :                             maDestPos.miCellPos =
    1919           0 :                                 mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aInterned);
    1920             :                         }
    1921             :                         else
    1922             :                         {
    1923           0 :                             maDestPos.miCellPos =
    1924           0 :                                 mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rStr);
    1925             :                         }
    1926           0 :                         setDefaultAttrToDest(nRow);
    1927             :                     }
    1928             :                 }
    1929             :             }
    1930           0 :             break;
    1931             :             case sc::element_type_edittext:
    1932             :             {
    1933           0 :                 if (!(mnCopyFlags & IDF_STRING))
    1934           0 :                     return;
    1935             : 
    1936           0 :                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
    1937           0 :                 std::advance(it, nOffset);
    1938           0 :                 sc::edittext_block::const_iterator itEnd = it;
    1939           0 :                 std::advance(itEnd, nDataSize);
    1940             : 
    1941           0 :                 std::vector<EditTextObject*> aCloned;
    1942           0 :                 aCloned.reserve(nDataSize);
    1943           0 :                 for (; it != itEnd; ++it)
    1944           0 :                     aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
    1945             : 
    1946           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1947           0 :                     maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end());
    1948             : 
    1949           0 :                 setDefaultAttrsToDest(nRow, nDataSize);
    1950             :             }
    1951           0 :             break;
    1952             :             case sc::element_type_formula:
    1953             :             {
    1954           0 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
    1955           0 :                 std::advance(it, nOffset);
    1956           0 :                 sc::formula_block::const_iterator itEnd = it;
    1957           0 :                 std::advance(itEnd, nDataSize);
    1958             : 
    1959           0 :                 for (; it != itEnd; ++it, ++nRow)
    1960           0 :                     cloneFormulaCell(nRow, const_cast<ScFormulaCell&>(**it));
    1961             :             }
    1962           0 :             break;
    1963             :             default:
    1964             :                 ;
    1965             :         }
    1966             :     }
    1967             : };
    1968             : 
    1969             : }
    1970             : 
    1971           0 : 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           0 :     if (bMarked)
    1977             :     {
    1978             :         SCROW nStart, nEnd;
    1979           0 :         if (pMarkData && pMarkData->IsMultiMarked())
    1980             :         {
    1981           0 :             ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
    1982             : 
    1983           0 :             while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
    1984             :             {
    1985           0 :                 if ( nEnd >= nRow1 )
    1986           0 :                     CopyToColumn(rCxt, std::max(nRow1,nStart), std::min(nRow2,nEnd),
    1987           0 :                                     nFlags, false, rColumn, pMarkData, bAsLink );
    1988           0 :             }
    1989             :         }
    1990             :         else
    1991             :         {
    1992             :             OSL_FAIL("CopyToColumn: bMarked, but no mark");
    1993             :         }
    1994           0 :         return;
    1995             :     }
    1996             : 
    1997           0 :     if ( (nFlags & IDF_ATTRIB) != 0 )
    1998             :     {
    1999           0 :         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           0 :             pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
    2015             :     }
    2016             : 
    2017           0 :     if ((nFlags & IDF_CONTENTS) != 0)
    2018             :     {
    2019           0 :         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           0 :                 (pDocument->GetPool() != rColumn.pDocument->GetPool()) ?
    2030           0 :                 &rColumn.pDocument->GetSharedStringPool() : NULL;
    2031             :             CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags,
    2032           0 :                     pSharedStringPool);
    2033           0 :             sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    2034             :         }
    2035             : 
    2036           0 :         rColumn.CellStorageModified();
    2037             :     }
    2038             : }
    2039             : 
    2040             : 
    2041           0 : 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           0 :     if (nRow1 > 0)
    2046           0 :         CopyToColumn(rCxt, 0, nRow1-1, IDF_FORMULA, false, rColumn);
    2047             : 
    2048           0 :     CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData);      //! bMarked ????
    2049             : 
    2050           0 :     if (nRow2 < MAXROW)
    2051           0 :         CopyToColumn(rCxt, nRow2+1, MAXROW, IDF_FORMULA, false, rColumn);
    2052           0 : }
    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           0 : void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
    2162             : {
    2163           0 :     ScRange aRange( nCol, 0, nTab );
    2164             : 
    2165           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    2166           0 :     SCROW nStart = -1, nEnd = -1;
    2167           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    2168           0 :     while (pPattern)
    2169             :     {
    2170           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    2171             :         {
    2172           0 :             aRange.aStart.SetRow( nStart );
    2173           0 :             aRange.aEnd.SetRow( nEnd );
    2174           0 :             rDestMark.SetMultiMarkArea( aRange, true );
    2175             :         }
    2176             : 
    2177           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    2178             :     }
    2179           0 : }
    2180             : 
    2181             : namespace {
    2182             : 
    2183           0 : void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
    2184             : {
    2185           0 :     sc::CellStoreType::iterator it = rCells.begin(), itEnd = rCells.end();
    2186           0 :     for (; it != itEnd; ++it)
    2187             :     {
    2188           0 :         if (it->type != sc::element_type_formula)
    2189           0 :             continue;
    2190             : 
    2191           0 :         sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
    2192           0 :         sc::formula_block::iterator itCellEnd = sc::formula_block::end(*it->data);
    2193           0 :         for (; itCell != itCellEnd; ++itCell)
    2194             :         {
    2195           0 :             ScFormulaCell& rCell = **itCell;
    2196           0 :             rCell.aPos.SetCol(nCol);
    2197             :         }
    2198             :     }
    2199           0 : }
    2200             : 
    2201             : }
    2202             : 
    2203           0 : void ScColumn::UpdateNoteCaptions()
    2204             : {
    2205           0 :     sc::CellNoteStoreType::const_iterator itBlk = maCellNotes.begin(), itBlkEnd = maCellNotes.end();
    2206           0 :     sc::cellnote_block::const_iterator itData, itDataEnd;
    2207             : 
    2208           0 :     SCROW curRow = 0;
    2209           0 :     for (;itBlk!=itBlkEnd;++itBlk)
    2210             :     {
    2211           0 :         if (itBlk->data)
    2212             :         {
    2213             :             // non empty block
    2214           0 :             itData = sc::cellnote_block::begin(*itBlk->data);
    2215           0 :             itDataEnd = sc::cellnote_block::end(*itBlk->data);
    2216           0 :             for(;itData!=itDataEnd; ++itData)
    2217             :             {
    2218           0 :                 ScPostIt* pNote = *itData;
    2219           0 :                 pNote->UpdateCaptionPos(ScAddress(nCol, curRow, nTab));
    2220           0 :                 curRow +=1;
    2221             :             }
    2222             :         }
    2223             :         else
    2224             :         {
    2225             :             // empty block
    2226           0 :             curRow += itBlk->size;
    2227             :         }
    2228             :     }
    2229           0 : }
    2230             : 
    2231           0 : void ScColumn::SwapCol(ScColumn& rCol)
    2232             : {
    2233           0 :     maBroadcasters.swap(rCol.maBroadcasters);
    2234           0 :     maCells.swap(rCol.maCells);
    2235           0 :     maCellTextAttrs.swap(rCol.maCellTextAttrs);
    2236           0 :     maCellNotes.swap(rCol.maCellNotes);
    2237             : 
    2238             :     // notes update caption
    2239           0 :     UpdateNoteCaptions();
    2240           0 :     rCol.UpdateNoteCaptions();
    2241             : 
    2242           0 :     ScAttrArray* pTempAttr = rCol.pAttrArray;
    2243           0 :     rCol.pAttrArray = pAttrArray;
    2244           0 :     pAttrArray = pTempAttr;
    2245             : 
    2246             :     // AttrArray needs to have the right column number
    2247           0 :     pAttrArray->SetCol(nCol);
    2248           0 :     rCol.pAttrArray->SetCol(rCol.nCol);
    2249             : 
    2250           0 :     std::swap(mbDirtyGroups, rCol.mbDirtyGroups);
    2251             : 
    2252             :     // Reset column positions in formula cells.
    2253           0 :     resetColumnPosition(maCells, nCol);
    2254           0 :     resetColumnPosition(rCol.maCells, rCol.nCol);
    2255             : 
    2256           0 :     CellStorageModified();
    2257           0 :     rCol.CellStorageModified();
    2258           0 : }
    2259             : 
    2260           0 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
    2261             : {
    2262           0 :     pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
    2263             : 
    2264             :     // Mark the non-empty cells within the specified range, for later broadcasting.
    2265           0 :     sc::SingleColumnSpanSet aNonEmpties;
    2266           0 :     aNonEmpties.scan(*this, nStartRow, nEndRow);
    2267           0 :     sc::SingleColumnSpanSet::SpansType aRanges;
    2268           0 :     aNonEmpties.getSpans(aRanges);
    2269             : 
    2270             :     // Split the formula grouping at the top and bottom boundaries.
    2271           0 :     sc::CellStoreType::position_type aPos = maCells.position(nStartRow);
    2272           0 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    2273           0 :     aPos = maCells.position(aPos.first, nEndRow+1);
    2274           0 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    2275             : 
    2276             :     // Do the same with the destination column.
    2277           0 :     aPos = rCol.maCells.position(nStartRow);
    2278           0 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    2279           0 :     aPos = rCol.maCells.position(aPos.first, nEndRow+1);
    2280           0 :     sc::SharedFormulaUtil::splitFormulaCellGroup(aPos);
    2281             : 
    2282             :     // Move the broadcasters to the destination column.
    2283           0 :     maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
    2284           0 :     maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
    2285           0 :     maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
    2286             : 
    2287             :     // move the notes to the destination column
    2288           0 :     maCellNotes.transfer(nStartRow, nEndRow, rCol.maCellNotes, nStartRow);
    2289           0 :     UpdateNoteCaptions();
    2290             : 
    2291             :     // Re-group transferred formula cells.
    2292           0 :     aPos = rCol.maCells.position(nStartRow);
    2293           0 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2294           0 :     aPos = rCol.maCells.position(aPos.first, nEndRow+1);
    2295           0 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2296             : 
    2297           0 :     CellStorageModified();
    2298           0 :     rCol.CellStorageModified();
    2299             : 
    2300             :     // Broadcast on moved ranges. Area-broadcast only.
    2301           0 :     ScHint aHint(SC_HINT_DATACHANGED, ScAddress(nCol, 0, nTab));
    2302           0 :     ScAddress& rPos = aHint.GetAddress();
    2303           0 :     sc::SingleColumnSpanSet::SpansType::const_iterator itRange = aRanges.begin(), itRangeEnd = aRanges.end();
    2304           0 :     for (; itRange != itRangeEnd; ++itRange)
    2305             :     {
    2306           0 :         for (SCROW nRow = itRange->mnRow1; nRow <= itRange->mnRow2; ++nRow)
    2307             :         {
    2308           0 :             rPos.SetRow(nRow);
    2309           0 :             pDocument->AreaBroadcast(aHint);
    2310             :         }
    2311           0 :     }
    2312           0 : }
    2313             : 
    2314             : namespace {
    2315             : 
    2316             : class SubTotalCellPicker
    2317             : {
    2318             :     sc::ColumnSpanSet& mrSet;
    2319             :     SCTAB mnTab;
    2320             :     SCCOL mnCol;
    2321             :     bool mbVal;
    2322             : public:
    2323           0 :     SubTotalCellPicker(sc::ColumnSpanSet& rSet, SCTAB nTab, SCCOL nCol, bool bVal) :
    2324           0 :         mrSet(rSet), mnTab(nTab), mnCol(nCol), mbVal(bVal) {}
    2325             : 
    2326           0 :     void operator() (size_t nRow, const ScFormulaCell* pCell)
    2327             :     {
    2328           0 :         if (pCell->IsSubTotal())
    2329           0 :             mrSet.set(mnTab, mnCol, nRow, mbVal);
    2330           0 :     }
    2331             : };
    2332             : 
    2333             : }
    2334             : 
    2335           0 : void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nRow2, bool bVal ) const
    2336             : {
    2337           0 :     SubTotalCellPicker aFunc(rSet, nTab, nCol, bVal);
    2338           0 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    2339           0 : }
    2340             : 
    2341             : namespace {
    2342             : 
    2343           0 : class SharedTopFormulaCellPicker : std::unary_function<sc::CellStoreType::value_type, void>
    2344             : {
    2345             : public:
    2346           0 :     virtual ~SharedTopFormulaCellPicker() {}
    2347             : 
    2348           0 :     void operator() ( sc::CellStoreType::value_type& node )
    2349             :     {
    2350           0 :         if (node.type != sc::element_type_formula)
    2351           0 :             return;
    2352             : 
    2353           0 :         size_t nTopRow = node.position;
    2354             : 
    2355           0 :         sc::formula_block::iterator itBeg = sc::formula_block::begin(*node.data);
    2356           0 :         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           0 :         for (sc::formula_block::iterator it = itBeg; it != itEnd; ++it)
    2361             :         {
    2362           0 :             ScFormulaCell* pCell = *it;
    2363           0 :             size_t nRow = nTopRow + std::distance(itBeg, it);
    2364           0 :             if (!pCell->IsShared())
    2365             :             {
    2366           0 :                 processNonShared(pCell, nRow);
    2367           0 :                 continue;
    2368             :             }
    2369             : 
    2370           0 :             if (pCell->IsSharedTop())
    2371             :             {
    2372           0 :                 ScFormulaCell** pp = &(*it);
    2373           0 :                 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           0 :                 size_t nOffsetToLast = pCell->GetSharedLength() - 1;
    2378           0 :                 std::advance(it, nOffsetToLast);
    2379             :             }
    2380             :         }
    2381             :     }
    2382             : 
    2383           0 :     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           0 :     UpdateRefOnCopy(const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc) :
    2395           0 :         mrCxt(rCxt), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2396             : 
    2397           0 :     bool isUpdated() const { return mbUpdated; }
    2398             : 
    2399           0 :     void operator() (sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    2400             :     {
    2401           0 :         if (node.type != sc::element_type_formula)
    2402           0 :             return;
    2403             : 
    2404           0 :         sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
    2405           0 :         std::advance(it, nOffset);
    2406           0 :         sc::formula_block::iterator itEnd = it;
    2407           0 :         std::advance(itEnd, nDataSize);
    2408             : 
    2409           0 :         for (; it != itEnd; ++it)
    2410             :         {
    2411           0 :             ScFormulaCell& rCell = **it;
    2412           0 :             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           0 :     void updateRefOnShift( sc::FormulaGroupEntry& rGroup )
    2426             :     {
    2427           0 :         if (!rGroup.mbShared)
    2428             :         {
    2429           0 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2430           0 :             mbUpdated |= rGroup.mpCell->UpdateReferenceOnShift(*mpCxt, mpUndoDoc, &aUndoPos);
    2431           0 :             return;
    2432             :         }
    2433             : 
    2434             :         // Update references of a formula group.
    2435           0 :         ScFormulaCell** pp = rGroup.mpCells;
    2436           0 :         ScFormulaCell** ppEnd = pp + rGroup.mnLength;
    2437           0 :         ScFormulaCell* pTop = *pp;
    2438           0 :         ScTokenArray* pCode = pTop->GetCode();
    2439           0 :         boost::scoped_ptr<ScTokenArray> pOldCode(pCode->Clone());
    2440           0 :         ScAddress aOldPos = pTop->aPos;
    2441             : 
    2442             :         // Run this before the position gets updated.
    2443           0 :         sc::RefUpdateResult aRes = pCode->AdjustReferenceOnShift(*mpCxt, aOldPos);
    2444             : 
    2445           0 :         if (pTop->UpdatePosOnShift(*mpCxt))
    2446             :         {
    2447             :             // Update the positions of all formula cells.
    2448           0 :             for (++pp; pp != ppEnd; ++pp) // skip the top cell.
    2449             :             {
    2450           0 :                 ScFormulaCell* pFC = *pp;
    2451           0 :                 pFC->aPos.Move(mpCxt->mnColDelta, mpCxt->mnRowDelta, mpCxt->mnTabDelta);
    2452             :             }
    2453             : 
    2454           0 :             if (pCode->IsRecalcModeOnRefMove())
    2455           0 :                 aRes.mbValueChanged = true;
    2456             :         }
    2457             : 
    2458           0 :         if (aRes.mbReferenceModified)
    2459             :         {
    2460           0 :             sc::StartListeningContext aStartCxt(mpCxt->mrDoc);
    2461           0 :             sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
    2462             :             aEndCxt.setPositionDelta(
    2463           0 :                 ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
    2464             : 
    2465           0 :             for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
    2466             :             {
    2467           0 :                 ScFormulaCell* p = *pp;
    2468           0 :                 p->EndListeningTo(aEndCxt);
    2469           0 :                 p->SetNeedsListening(true);
    2470             :             }
    2471             : 
    2472           0 :             mbUpdated = true;
    2473             : 
    2474           0 :             fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
    2475             :         }
    2476             : 
    2477           0 :         if (aRes.mbValueChanged)
    2478             :         {
    2479           0 :             for (pp = rGroup.mpCells; pp != ppEnd; ++pp)
    2480             :             {
    2481           0 :                 ScFormulaCell* p = *pp;
    2482           0 :                 p->SetNeedsDirty(true);
    2483             :             }
    2484           0 :         }
    2485             :     }
    2486             : 
    2487           0 :     void updateRefOnMove( sc::FormulaGroupEntry& rGroup )
    2488             :     {
    2489           0 :         if (!rGroup.mbShared)
    2490             :         {
    2491           0 :             ScAddress aUndoPos(mnCol, rGroup.mnRow, mnTab);
    2492           0 :             mbUpdated |= rGroup.mpCell->UpdateReferenceOnMove(*mpCxt, mpUndoDoc, &aUndoPos);
    2493           0 :             return;
    2494             :         }
    2495             : 
    2496             :         // Update references of a formula group.
    2497           0 :         ScFormulaCell** pp = rGroup.mpCells;
    2498           0 :         ScFormulaCell** ppEnd = pp + rGroup.mnLength;
    2499           0 :         ScFormulaCell* pTop = *pp;
    2500           0 :         ScTokenArray* pCode = pTop->GetCode();
    2501           0 :         boost::scoped_ptr<ScTokenArray> pOldCode(pCode->Clone());
    2502             : 
    2503           0 :         ScAddress aPos = pTop->aPos;
    2504           0 :         ScAddress aOldPos = aPos;
    2505             : 
    2506           0 :         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           0 :         bool bRecalcOnMove = pCode->IsRecalcModeOnRefMove();
    2520           0 :         if (bRecalcOnMove)
    2521           0 :             bRecalcOnMove = aPos != aOldPos;
    2522             : 
    2523           0 :         sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMove(*mpCxt, aOldPos, aPos);
    2524             : 
    2525           0 :         if (aRes.mbReferenceModified || aRes.mbNameModified || bRecalcOnMove)
    2526             :         {
    2527           0 :             sc::AutoCalcSwitch(mpCxt->mrDoc, false);
    2528             : 
    2529           0 :             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           0 :                 ScCompiler aComp(&mpCxt->mrDoc, aPos, *pCode);
    2535           0 :                 aComp.SetGrammar(mpCxt->mrDoc.GetGrammar());
    2536           0 :                 aComp.CompileTokenArray();
    2537             :             }
    2538             : 
    2539             :             // Perform end-listening, start-listening, and dirtying on all
    2540             :             // formula cells in the group.
    2541             : 
    2542           0 :             sc::StartListeningContext aStartCxt(mpCxt->mrDoc);
    2543             : 
    2544           0 :             sc::EndListeningContext aEndCxt(mpCxt->mrDoc, pOldCode.get());
    2545             :             aEndCxt.setPositionDelta(
    2546           0 :                 ScAddress(-mpCxt->mnColDelta, -mpCxt->mnRowDelta, -mpCxt->mnTabDelta));
    2547             : 
    2548           0 :             for (; pp != ppEnd; ++pp)
    2549             :             {
    2550           0 :                 ScFormulaCell* p = *pp;
    2551           0 :                 p->EndListeningTo(aEndCxt);
    2552           0 :                 p->StartListeningTo(aStartCxt);
    2553           0 :                 p->SetDirty();
    2554             :             }
    2555             : 
    2556           0 :             fillUndoDoc(aOldPos, rGroup.mnLength, *pOldCode);
    2557           0 :         }
    2558             :     }
    2559             : 
    2560           0 :     void fillUndoDoc( const ScAddress& rOldPos, SCROW nLength, const ScTokenArray& rOldCode )
    2561             :     {
    2562           0 :         if (!mpUndoDoc || nLength <= 0)
    2563           0 :             return;
    2564             : 
    2565             :         // Insert the old formula group into the undo document.
    2566           0 :         ScAddress aUndoPos = rOldPos;
    2567           0 :         ScFormulaCell* pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, rOldCode.Clone());
    2568             : 
    2569           0 :         if (nLength == 1)
    2570             :         {
    2571           0 :             mpUndoDoc->SetFormulaCell(aUndoPos, pFC);
    2572           0 :             return;
    2573             :         }
    2574             : 
    2575           0 :         std::vector<ScFormulaCell*> aCells;
    2576           0 :         aCells.reserve(nLength);
    2577           0 :         ScFormulaCellGroupRef xGroup = pFC->CreateCellGroup(nLength, false);
    2578           0 :         aCells.push_back(pFC);
    2579           0 :         aUndoPos.IncRow();
    2580           0 :         for (SCROW i = 1; i < nLength; ++i, aUndoPos.IncRow())
    2581             :         {
    2582           0 :             pFC = new ScFormulaCell(mpUndoDoc, aUndoPos, xGroup);
    2583           0 :             aCells.push_back(pFC);
    2584             :         }
    2585             : 
    2586           0 :         if (!mpUndoDoc->SetFormulaCells(rOldPos, aCells))
    2587             :             // Insertion failed.  Delete all formula cells.
    2588           0 :             std::for_each(aCells.begin(), aCells.end(), ScDeleteObjectByPtr<ScFormulaCell>());
    2589             :     }
    2590             : 
    2591             : public:
    2592           0 :     UpdateRefOnNonCopy(
    2593             :         SCCOL nCol, SCTAB nTab, const sc::RefUpdateContext* pCxt,
    2594             :         ScDocument* pUndoDoc) :
    2595             :         mnCol(nCol), mnTab(nTab), mpCxt(pCxt),
    2596           0 :         mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2597             : 
    2598           0 :     void operator() ( sc::FormulaGroupEntry& rGroup )
    2599             :     {
    2600           0 :         switch (mpCxt->meMode)
    2601             :         {
    2602             :             case URM_INSDEL:
    2603           0 :                 updateRefOnShift(rGroup);
    2604           0 :                 return;
    2605             :             case URM_MOVE:
    2606           0 :                 updateRefOnMove(rGroup);
    2607           0 :                 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           0 :     bool isUpdated() const { return mbUpdated; }
    2631             : };
    2632             : 
    2633           0 : class UpdateRefGroupBoundChecker : public SharedTopFormulaCellPicker
    2634             : {
    2635             :     const sc::RefUpdateContext& mrCxt;
    2636             :     std::vector<SCROW>& mrBounds;
    2637             : 
    2638             : public:
    2639           0 :     UpdateRefGroupBoundChecker(const sc::RefUpdateContext& rCxt, std::vector<SCROW>& rBounds) :
    2640           0 :         mrCxt(rCxt), mrBounds(rBounds) {}
    2641             : 
    2642           0 :     virtual ~UpdateRefGroupBoundChecker() {}
    2643             : 
    2644           0 :     virtual void processSharedTop( ScFormulaCell** ppCells, size_t /*nRow*/, size_t /*nLength*/ ) SAL_OVERRIDE
    2645             :     {
    2646             :         // Check its tokens and record its reference boundaries.
    2647           0 :         ScFormulaCell& rCell = **ppCells;
    2648           0 :         const ScTokenArray& rCode = *rCell.GetCode();
    2649             :         rCode.CheckRelativeReferenceBounds(
    2650           0 :             mrCxt, rCell.aPos, rCell.GetSharedLength(), mrBounds);
    2651           0 :     }
    2652             : };
    2653             : 
    2654           0 : class FormulaGroupPicker : public SharedTopFormulaCellPicker
    2655             : {
    2656             :     std::vector<sc::FormulaGroupEntry>& mrGroups;
    2657             : 
    2658             : public:
    2659           0 :     FormulaGroupPicker( std::vector<sc::FormulaGroupEntry>& rGroups ) : mrGroups(rGroups) {}
    2660             : 
    2661           0 :     virtual ~FormulaGroupPicker() {}
    2662             : 
    2663           0 :     virtual void processNonShared( ScFormulaCell* pCell, size_t nRow ) SAL_OVERRIDE
    2664             :     {
    2665           0 :         mrGroups.push_back(sc::FormulaGroupEntry(pCell, nRow));
    2666           0 :     }
    2667             : 
    2668           0 :     virtual void processSharedTop( ScFormulaCell** ppCells, size_t nRow, size_t nLength ) SAL_OVERRIDE
    2669             :     {
    2670           0 :         mrGroups.push_back(sc::FormulaGroupEntry(ppCells, nRow, nLength));
    2671           0 :     }
    2672             : };
    2673             : 
    2674             : }
    2675             : 
    2676           0 : 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           0 :     UpdateRefOnCopy aHandler(rCxt, pUndoDoc);
    2683           0 :     sc::CellStoreType::position_type aPos = maCells.position(rCxt.maRange.aStart.Row());
    2684           0 :     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           0 :     sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2689           0 :     if (rCxt.maRange.aEnd.Row() < MAXROW)
    2690             :     {
    2691           0 :         aPos = maCells.position(aPos.first, rCxt.maRange.aEnd.Row()+1);
    2692           0 :         sc::SharedFormulaUtil::joinFormulaCellAbove(aPos);
    2693             :     }
    2694             : 
    2695           0 :     return aHandler.isUpdated();
    2696             : }
    2697             : 
    2698           0 : bool ScColumn::UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc )
    2699             : {
    2700           0 :     if (rCxt.meMode == URM_COPY)
    2701           0 :         return UpdateReferenceOnCopy(rCxt, pUndoDoc);
    2702             : 
    2703           0 :     if (IsEmptyData() || pDocument->IsClipOrUndo())
    2704             :         // Cells in this column are all empty, or clip or undo doc. No update needed.
    2705           0 :         return false;
    2706             : 
    2707           0 :     std::vector<SCROW> aBounds;
    2708             : 
    2709           0 :     bool bThisColShifted = (rCxt.maRange.aStart.Tab() <= nTab && nTab <= rCxt.maRange.aEnd.Tab() &&
    2710           0 :                             rCxt.maRange.aStart.Col() <= nCol && nCol <= rCxt.maRange.aEnd.Col());
    2711           0 :     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           0 :         if (rCxt.mnRowDelta < 0)
    2719             :         {
    2720           0 :             nSplitPos = rCxt.maRange.aStart.Row() + rCxt.mnRowDelta;
    2721           0 :             if (ValidRow(nSplitPos))
    2722           0 :                 aBounds.push_back(nSplitPos);
    2723             :         }
    2724           0 :         nSplitPos = rCxt.maRange.aStart.Row();
    2725           0 :         if (ValidRow(nSplitPos))
    2726             :         {
    2727           0 :             aBounds.push_back(nSplitPos);
    2728           0 :             nSplitPos = rCxt.maRange.aEnd.Row() + 1;
    2729           0 :             if (ValidRow(nSplitPos))
    2730           0 :                 aBounds.push_back(nSplitPos);
    2731             :         }
    2732             :     }
    2733             : 
    2734             :     // Check the row positions at which the group must be split per relative
    2735             :     // references.
    2736           0 :     UpdateRefGroupBoundChecker aBoundChecker(rCxt, aBounds);
    2737           0 :     std::for_each(maCells.begin(), maCells.end(), aBoundChecker);
    2738             : 
    2739             :     // Do the actual splitting.
    2740           0 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
    2741             : 
    2742             :     // Collect all formula groups.
    2743           0 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
    2744             : 
    2745             :     // Process all collected formula groups.
    2746           0 :     UpdateRefOnNonCopy aHandler(nCol, nTab, &rCxt, pUndoDoc);
    2747           0 :     aHandler = std::for_each(aGroups.begin(), aGroups.end(), aHandler);
    2748           0 :     if (aHandler.isUpdated())
    2749           0 :         rCxt.maRegroupCols.set(nTab, nCol);
    2750             : 
    2751           0 :     return aHandler.isUpdated();
    2752             : }
    2753             : 
    2754           0 : std::vector<sc::FormulaGroupEntry> ScColumn::GetFormulaGroupEntries()
    2755             : {
    2756           0 :     std::vector<sc::FormulaGroupEntry> aGroups;
    2757           0 :     std::for_each(maCells.begin(), maCells.end(), FormulaGroupPicker(aGroups));
    2758           0 :     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           0 :     InsertTabUpdater(sc::RefUpdateInsertTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2819             :         mrCxt(rCxt),
    2820             :         mrTextAttrs(rTextAttrs),
    2821             :         miAttrPos(rTextAttrs.begin()),
    2822             :         mnTab(nTab),
    2823           0 :         mbModified(false) {}
    2824             : 
    2825           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2826             :     {
    2827           0 :         pCell->UpdateInsertTab(mrCxt);
    2828           0 :         mbModified = true;
    2829           0 :     }
    2830             : 
    2831           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2832             :     {
    2833           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2834           0 :         aUpdater.updateTableFields(mnTab);
    2835           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2836           0 :         mbModified = true;
    2837           0 :     }
    2838             : 
    2839           0 :     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           0 :     DeleteTabUpdater(sc::RefUpdateDeleteTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2851             :         mrCxt(rCxt),
    2852             :         mrTextAttrs(rTextAttrs),
    2853             :         miAttrPos(rTextAttrs.begin()),
    2854             :         mnTab(nTab),
    2855           0 :         mbModified(false) {}
    2856             : 
    2857           0 :     void operator() (size_t, ScFormulaCell* pCell)
    2858             :     {
    2859           0 :         pCell->UpdateDeleteTab(mrCxt);
    2860           0 :         mbModified = true;
    2861           0 :     }
    2862             : 
    2863           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2864             :     {
    2865           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2866           0 :         aUpdater.updateTableFields(mnTab);
    2867           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2868           0 :         mbModified = true;
    2869           0 :     }
    2870             : 
    2871           0 :     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           0 :     InsertAbsTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nNewPos) :
    2883             :         mrTextAttrs(rTextAttrs),
    2884             :         miAttrPos(rTextAttrs.begin()),
    2885             :         mnTab(nTab),
    2886             :         mnNewPos(nNewPos),
    2887           0 :         mbModified(false) {}
    2888             : 
    2889           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2890             :     {
    2891           0 :         pCell->UpdateInsertTabAbs(mnNewPos);
    2892           0 :         mbModified = true;
    2893           0 :     }
    2894             : 
    2895           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2896             :     {
    2897           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2898           0 :         aUpdater.updateTableFields(mnTab);
    2899           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2900           0 :         mbModified = true;
    2901           0 :     }
    2902             : 
    2903           0 :     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           0 :     MoveTabUpdater(sc::RefUpdateMoveTabContext& rCxt, sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab) :
    2915             :         mrCxt(rCxt),
    2916             :         mrTextAttrs(rTextAttrs),
    2917             :         miAttrPos(rTextAttrs.begin()),
    2918             :         mnTab(nTab),
    2919           0 :         mbModified(false) {}
    2920             : 
    2921           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2922             :     {
    2923           0 :         pCell->UpdateMoveTab(mrCxt, mnTab);
    2924           0 :         mbModified = true;
    2925           0 :     }
    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           0 :     bool isModified() const { return mbModified; }
    2936             : };
    2937             : 
    2938             : class UpdateCompileHandler
    2939             : {
    2940             :     bool mbForceIfNameInUse:1;
    2941             : public:
    2942           0 :     UpdateCompileHandler(bool bForceIfNameInUse) :
    2943           0 :         mbForceIfNameInUse(bForceIfNameInUse) {}
    2944             : 
    2945           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2946             :     {
    2947           0 :         pCell->UpdateCompile(mbForceIfNameInUse);
    2948           0 :     }
    2949             : };
    2950             : 
    2951             : class TabNoSetter
    2952             : {
    2953             :     SCTAB mnTab;
    2954             : public:
    2955           0 :     TabNoSetter(SCTAB nTab) : mnTab(nTab) {}
    2956             : 
    2957           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2958             :     {
    2959           0 :         pCell->aPos.SetTab(mnTab);
    2960           0 :     }
    2961             : };
    2962             : 
    2963             : class UsedRangeNameFinder
    2964             : {
    2965             :     std::set<sal_uInt16>& mrIndexes;
    2966             : public:
    2967           0 :     UsedRangeNameFinder(std::set<sal_uInt16>& rIndexes) : mrIndexes(rIndexes) {}
    2968             : 
    2969           0 :     void operator() (size_t /*nRow*/, const ScFormulaCell* pCell)
    2970             :     {
    2971           0 :         pCell->FindRangeNamesInUse(mrIndexes);
    2972           0 :     }
    2973             : };
    2974             : 
    2975             : struct SetDirtyVarHandler
    2976             : {
    2977           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2978             :     {
    2979           0 :         p->SetDirtyVar();
    2980           0 :     }
    2981             : };
    2982             : 
    2983             : class SetDirtyHandler
    2984             : {
    2985             :     ScDocument& mrDoc;
    2986             :     const sc::SetFormulaDirtyContext& mrCxt;
    2987             : public:
    2988           0 :     SetDirtyHandler( ScDocument& rDoc, const sc::SetFormulaDirtyContext& rCxt ) :
    2989           0 :         mrDoc(rDoc), mrCxt(rCxt) {}
    2990             : 
    2991           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2992             :     {
    2993           0 :         if (mrCxt.mbClearTabDeletedFlag)
    2994             :         {
    2995           0 :             if (!p->IsShared() || p->IsSharedTop())
    2996             :             {
    2997           0 :                 ScTokenArray* pCode = p->GetCode();
    2998             :                 pCode->ClearTabDeleted(
    2999           0 :                     p->aPos, mrCxt.mnTabDeletedStart, mrCxt.mnTabDeletedEnd);
    3000             :             }
    3001             :         }
    3002             : 
    3003           0 :         p->SetDirtyVar();
    3004           0 :         if (!mrDoc.IsInFormulaTree(p))
    3005           0 :             mrDoc.PutInFormulaTree(p);
    3006           0 :     }
    3007             : };
    3008             : 
    3009           0 : class SetDirtyOnRangeHandler
    3010             : {
    3011             :     sc::SingleColumnSpanSet maValueRanges;
    3012             :     ScColumn& mrColumn;
    3013             : public:
    3014           0 :     SetDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    3015             : 
    3016           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    3017             :     {
    3018           0 :         p->SetDirty();
    3019           0 :     }
    3020             : 
    3021           0 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    3022             :     {
    3023           0 :         if (type == sc::element_type_empty)
    3024             :             // Ignore empty blocks.
    3025           0 :             return;
    3026             : 
    3027             :         // Non-formula cells.
    3028           0 :         SCROW nRow1 = nTopRow;
    3029           0 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    3030           0 :         maValueRanges.set(nRow1, nRow2, true);
    3031             :     }
    3032             : 
    3033           0 :     void broadcast()
    3034             :     {
    3035           0 :         std::vector<SCROW> aRows;
    3036           0 :         maValueRanges.getRows(aRows);
    3037           0 :         mrColumn.BroadcastCells(aRows, SC_HINT_DATACHANGED);
    3038           0 :     }
    3039             : };
    3040             : 
    3041           0 : class SetTableOpDirtyOnRangeHandler
    3042             : {
    3043             :     sc::SingleColumnSpanSet maValueRanges;
    3044             :     ScColumn& mrColumn;
    3045             : public:
    3046           0 :     SetTableOpDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    3047             : 
    3048           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    3049             :     {
    3050           0 :         p->SetTableOpDirty();
    3051           0 :     }
    3052             : 
    3053           0 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    3054             :     {
    3055           0 :         if (type == sc::element_type_empty)
    3056             :             // Ignore empty blocks.
    3057           0 :             return;
    3058             : 
    3059             :         // Non-formula cells.
    3060           0 :         SCROW nRow1 = nTopRow;
    3061           0 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    3062           0 :         maValueRanges.set(nRow1, nRow2, true);
    3063             :     }
    3064             : 
    3065           0 :     void broadcast()
    3066             :     {
    3067           0 :         std::vector<SCROW> aRows;
    3068           0 :         maValueRanges.getRows(aRows);
    3069           0 :         mrColumn.BroadcastCells(aRows, SC_HINT_TABLEOPDIRTY);
    3070           0 :     }
    3071             : };
    3072             : 
    3073             : struct SetDirtyAfterLoadHandler
    3074             : {
    3075           0 :     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           0 :         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           0 :     }
    3098             : };
    3099             : 
    3100             : struct SetDirtyIfPostponedHandler
    3101             : {
    3102           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    3103             :     {
    3104           0 :         if (pCell->IsPostponedDirty() || pCell->HasRelNameReference())
    3105           0 :             pCell->SetDirty();
    3106           0 :     }
    3107             : };
    3108             : 
    3109             : struct CalcAllHandler
    3110             : {
    3111           0 :     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           0 :         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           0 :     }
    3128             : };
    3129             : 
    3130             : class CompileAllHandler
    3131             : {
    3132             :     sc::CompileFormulaContext& mrCxt;
    3133             : public:
    3134           0 :     CompileAllHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {}
    3135             : 
    3136           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    3137             :     {
    3138             :         // for unconditional compilation
    3139             :         // bCompile=true and pCode->nError=0
    3140           0 :         pCell->GetCode()->SetCodeError(0);
    3141           0 :         pCell->SetCompile(true);
    3142           0 :         pCell->CompileTokenArray(mrCxt);
    3143           0 :     }
    3144             : };
    3145             : 
    3146             : class CompileXMLHandler
    3147             : {
    3148             :     sc::CompileFormulaContext& mrCxt;
    3149             :     ScProgress& mrProgress;
    3150             :     const ScColumn& mrCol;
    3151             : public:
    3152           0 :     CompileXMLHandler( sc::CompileFormulaContext& rCxt, ScProgress& rProgress, const ScColumn& rCol) :
    3153             :         mrCxt(rCxt),
    3154             :         mrProgress(rProgress),
    3155           0 :         mrCol(rCol) {}
    3156             : 
    3157           0 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    3158             :     {
    3159           0 :         sal_uInt32 nFormat = mrCol.GetNumberFormat(nRow);
    3160           0 :         if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
    3161             :             // Non-default number format is set.
    3162           0 :             pCell->SetNeedNumberFormat(false);
    3163           0 :         else if (pCell->NeedsNumberFormat())
    3164           0 :             pCell->SetDirtyVar();
    3165             : 
    3166           0 :         if (pCell->GetMatrixFlag())
    3167           0 :             pCell->SetDirtyVar();
    3168             : 
    3169           0 :         pCell->CompileXML(mrCxt, mrProgress);
    3170           0 :     }
    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           0 :     CalcAfterLoadHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {}
    3220             : 
    3221           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    3222             :     {
    3223           0 :         pCell->CalcAfterLoad(mrCxt);
    3224           0 :     }
    3225             : };
    3226             : 
    3227             : struct ResetChangedHandler
    3228             : {
    3229           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    3230             :     {
    3231           0 :         pCell->SetChanged(false);
    3232           0 :     }
    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           0 :     FindEditCellsHandler(ScColumn& rColumn, sc::CellTextAttrStoreType& rAttrs,
    3246             :             sc::CellStoreType::iterator rCellItr) :
    3247           0 :         mrColumn(rColumn), miAttrPos(rAttrs.begin()), miCellPos(rCellItr) {}
    3248             : 
    3249           0 :     bool operator() (size_t, const EditTextObject*)
    3250             :     {
    3251           0 :         return true;
    3252             :     }
    3253             : 
    3254           0 :     bool operator() (size_t nRow, const ScFormulaCell* p)
    3255             :     {
    3256           0 :         sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
    3257           0 :         if (IsAmbiguousScriptNonZero(nScriptType))
    3258           0 :             return true;
    3259             : 
    3260           0 :         return const_cast<ScFormulaCell*>(p)->IsMultilineResult();
    3261             :     }
    3262             : 
    3263           0 :     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           0 :         if (node.type == sc::element_type_empty)
    3268           0 :             return RetType(0, false);
    3269             : 
    3270           0 :         for (size_t i = 0; i < nDataSize; ++i)
    3271             :         {
    3272           0 :             SCROW nRow = node.position + i + nOffset;
    3273           0 :             sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow, miCellPos);
    3274           0 :             if (IsAmbiguousScriptNonZero(nScriptType))
    3275             :                 // Return the offset from the first row.
    3276           0 :                 return RetType(i+nOffset, true);
    3277             :         }
    3278             : 
    3279           0 :         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           0 : void ScColumn::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt )
    3301             : {
    3302           0 :     if (nTab >= rCxt.mnInsertPos)
    3303             :     {
    3304           0 :         nTab += rCxt.mnSheets;
    3305           0 :         pAttrArray->SetTab(nTab);
    3306             :     }
    3307             : 
    3308           0 :     UpdateInsertTabOnlyCells(rCxt);
    3309           0 : }
    3310             : 
    3311           0 : void ScColumn::UpdateInsertTabOnlyCells( sc::RefUpdateInsertTabContext& rCxt )
    3312             : {
    3313           0 :     InsertTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    3314           0 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3315           0 :     if (aFunc.isModified())
    3316           0 :         CellStorageModified();
    3317           0 : }
    3318             : 
    3319           0 : void ScColumn::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt )
    3320             : {
    3321           0 :     if (nTab > rCxt.mnDeletePos)
    3322             :     {
    3323           0 :         nTab -= rCxt.mnSheets;
    3324           0 :         pAttrArray->SetTab(nTab);
    3325             :     }
    3326             : 
    3327           0 :     DeleteTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    3328           0 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3329           0 :     if (aFunc.isModified())
    3330           0 :         CellStorageModified();
    3331           0 : }
    3332             : 
    3333           0 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
    3334             : {
    3335           0 :     InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
    3336           0 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3337           0 :     if (aFunc.isModified())
    3338           0 :         CellStorageModified();
    3339           0 : }
    3340             : 
    3341           0 : void ScColumn::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo )
    3342             : {
    3343           0 :     nTab = nTabNo;
    3344           0 :     pAttrArray->SetTab( nTabNo );
    3345             : 
    3346           0 :     MoveTabUpdater aFunc(rCxt, maCellTextAttrs, nTab);
    3347           0 :     sc::ProcessFormulaEditText(maCells, aFunc);
    3348           0 :     if (aFunc.isModified())
    3349           0 :         CellStorageModified();
    3350           0 : }
    3351             : 
    3352             : 
    3353           0 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
    3354             : {
    3355           0 :     UpdateCompileHandler aFunc(bForceIfNameInUse);
    3356           0 :     sc::ProcessFormula(maCells, aFunc);
    3357           0 : }
    3358             : 
    3359             : 
    3360           0 : void ScColumn::SetTabNo(SCTAB nNewTab)
    3361             : {
    3362           0 :     nTab = nNewTab;
    3363           0 :     pAttrArray->SetTab( nNewTab );
    3364             : 
    3365           0 :     TabNoSetter aFunc(nTab);
    3366           0 :     sc::ProcessFormula(maCells, aFunc);
    3367           0 : }
    3368             : 
    3369           0 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
    3370             : {
    3371           0 :     UsedRangeNameFinder aFunc(rIndexes);
    3372           0 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    3373           0 : }
    3374             : 
    3375           0 : void ScColumn::SetDirtyVar()
    3376             : {
    3377             :     SetDirtyVarHandler aFunc;
    3378           0 :     sc::ProcessFormula(maCells, aFunc);
    3379           0 : }
    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           0 : void ScColumn::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
    3397             : {
    3398             :     // is only done documentwide, no FormulaTracking
    3399           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3400           0 :     SetDirtyHandler aFunc(*pDocument, rCxt);
    3401           0 :     sc::ProcessFormula(maCells, aFunc);
    3402           0 : }
    3403             : 
    3404           0 : void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2 )
    3405             : {
    3406             :     // broadcasts everything within the range, with FormulaTracking
    3407           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3408             : 
    3409           0 :     SetDirtyOnRangeHandler aHdl(*this);
    3410           0 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    3411           0 :     aHdl.broadcast();
    3412           0 : }
    3413             : 
    3414           0 : void ScColumn::SetTableOpDirty( const ScRange& rRange )
    3415             : {
    3416           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3417             : 
    3418           0 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
    3419           0 :     SetTableOpDirtyOnRangeHandler aHdl(*this);
    3420           0 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    3421           0 :     aHdl.broadcast();
    3422           0 : }
    3423             : 
    3424           0 : void ScColumn::SetDirtyAfterLoad()
    3425             : {
    3426           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3427             :     SetDirtyAfterLoadHandler aFunc;
    3428           0 :     sc::ProcessFormula(maCells, aFunc);
    3429           0 : }
    3430             : 
    3431             : namespace {
    3432             : 
    3433           0 : class RecalcOnRefMoveCollector
    3434             : {
    3435             :     std::vector<SCROW> maDirtyRows;
    3436             : public:
    3437           0 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    3438             :     {
    3439           0 :         if (pCell->GetDirty() && pCell->GetCode()->IsRecalcModeOnRefMove())
    3440           0 :             maDirtyRows.push_back(nRow);
    3441           0 :     }
    3442             : 
    3443           0 :     const std::vector<SCROW>& getDirtyRows() const
    3444             :     {
    3445           0 :         return maDirtyRows;
    3446             :     }
    3447             : };
    3448             : 
    3449             : }
    3450             : 
    3451           0 : void ScColumn::SetDirtyIfPostponed()
    3452             : {
    3453           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3454             :     SetDirtyIfPostponedHandler aFunc;
    3455           0 :     sc::ProcessFormula(maCells, aFunc);
    3456           0 : }
    3457             : 
    3458           0 : void ScColumn::BroadcastRecalcOnRefMove()
    3459             : {
    3460           0 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    3461           0 :     RecalcOnRefMoveCollector aFunc;
    3462           0 :     sc::ProcessFormula(maCells, aFunc);
    3463           0 :     BroadcastCells(aFunc.getDirtyRows(), SC_HINT_DATACHANGED);
    3464           0 : }
    3465             : 
    3466             : namespace {
    3467             : 
    3468             : class BroadcastRefMovedHandler
    3469             : {
    3470             :     const sc::RefMovedHint& mrHint;
    3471             : public:
    3472           0 :     BroadcastRefMovedHandler( const sc::RefMovedHint& rHint ) : mrHint(rHint) {}
    3473             : 
    3474           0 :     void operator() ( size_t, SvtBroadcaster* p )
    3475             :     {
    3476           0 :         p->Broadcast(mrHint);
    3477           0 :     }
    3478             : };
    3479             : 
    3480             : }
    3481             : 
    3482           0 : void ScColumn::BroadcastRefMoved( const sc::RefMovedHint& rHint )
    3483             : {
    3484           0 :     const ScRange& rRange = rHint.getRange();
    3485           0 :     SCROW nRow1 = rRange.aStart.Row();
    3486           0 :     SCROW nRow2 = rRange.aEnd.Row();
    3487             : 
    3488             :     // Notify all listeners within specified rows.
    3489           0 :     BroadcastRefMovedHandler aFunc(rHint);
    3490           0 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
    3491           0 : }
    3492             : 
    3493             : namespace {
    3494             : 
    3495           0 : class TransferListenersHandler
    3496             : {
    3497             : public:
    3498             :     typedef std::vector<SvtListener*> ListenersType;
    3499           0 :     struct Entry
    3500             :     {
    3501             :         size_t mnRow;
    3502             :         ListenersType maListeners;
    3503             :     };
    3504             :     typedef std::vector<Entry> ListenerListType;
    3505             : 
    3506           0 :     void swapListeners( std::vector<Entry>& rListenerList )
    3507             :     {
    3508           0 :         maListenerList.swap(rListenerList);
    3509           0 :     }
    3510             : 
    3511           0 :     void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
    3512             :     {
    3513             :         assert(pBroadcaster);
    3514             : 
    3515             :         // It's important to make a copy here.
    3516           0 :         SvtBroadcaster::ListenersType aLis = pBroadcaster->GetAllListeners();
    3517           0 :         if (aLis.empty())
    3518             :             // No listeners to transfer.
    3519           0 :             return;
    3520             : 
    3521           0 :         Entry aEntry;
    3522           0 :         aEntry.mnRow = nRow;
    3523             : 
    3524           0 :         SvtBroadcaster::ListenersType::iterator it = aLis.begin(), itEnd = aLis.end();
    3525           0 :         for (; it != itEnd; ++it)
    3526             :         {
    3527           0 :             SvtListener* pLis = *it;
    3528           0 :             pLis->EndListening(*pBroadcaster);
    3529           0 :             aEntry.maListeners.push_back(pLis);
    3530             :         }
    3531             : 
    3532           0 :         maListenerList.push_back(aEntry);
    3533             : 
    3534             :         // At this point, the source broadcaster should have no more listeners.
    3535           0 :         assert(!pBroadcaster->HasListeners());
    3536             :     }
    3537             : 
    3538             : private:
    3539             :     ListenerListType maListenerList;
    3540             : };
    3541             : 
    3542           0 : class RemoveEmptyBroadcasterHandler
    3543             : {
    3544             :     sc::ColumnSpanSet maSet;
    3545             :     ScDocument& mrDoc;
    3546             :     SCCOL mnCol;
    3547             :     SCTAB mnTab;
    3548             : 
    3549             : public:
    3550           0 :     RemoveEmptyBroadcasterHandler( ScDocument& rDoc, SCCOL nCol, SCTAB nTab ) :
    3551           0 :         maSet(false), mrDoc(rDoc), mnCol(nCol), mnTab(nTab) {}
    3552             : 
    3553           0 :     void operator() ( size_t nRow, SvtBroadcaster* pBroadcaster )
    3554             :     {
    3555           0 :         if (!pBroadcaster->HasListeners())
    3556           0 :             maSet.set(mnTab, mnCol, nRow, true);
    3557           0 :     }
    3558             : 
    3559           0 :     void purge()
    3560             :     {
    3561           0 :         sc::PurgeListenerAction aAction(mrDoc);
    3562           0 :         maSet.executeAction(aAction);
    3563           0 :     }
    3564             : };
    3565             : 
    3566             : }
    3567             : 
    3568           0 : void ScColumn::TransferListeners(
    3569             :     ScColumn& rDestCol, SCROW nRow1, SCROW nRow2, SCROW nRowDelta )
    3570             : {
    3571           0 :     if (nRow2 < nRow1)
    3572           0 :         return;
    3573             : 
    3574           0 :     if (!ValidRow(nRow1) || !ValidRow(nRow2))
    3575           0 :         return;
    3576             : 
    3577           0 :     if (nRowDelta <= 0 && !ValidRow(nRow1+nRowDelta))
    3578           0 :         return;
    3579             : 
    3580           0 :     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           0 :     TransferListenersHandler aFunc;
    3586           0 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
    3587             : 
    3588           0 :     TransferListenersHandler::ListenerListType aListenerList;
    3589           0 :     aFunc.swapListeners(aListenerList);
    3590             : 
    3591             :     // Re-register listeners with their destination broadcasters.
    3592           0 :     sc::BroadcasterStoreType::iterator itDestPos = rDestCol.maBroadcasters.begin();
    3593           0 :     TransferListenersHandler::ListenerListType::iterator it = aListenerList.begin(), itEnd = aListenerList.end();
    3594           0 :     for (; it != itEnd; ++it)
    3595             :     {
    3596           0 :         TransferListenersHandler::Entry& rEntry = *it;
    3597             : 
    3598           0 :         SCROW nDestRow = rEntry.mnRow + nRowDelta;
    3599             : 
    3600             :         sc::BroadcasterStoreType::position_type aPos =
    3601           0 :             rDestCol.maBroadcasters.position(itDestPos, nDestRow);
    3602             : 
    3603           0 :         itDestPos = aPos.first;
    3604           0 :         SvtBroadcaster* pDestBrd = NULL;
    3605           0 :         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           0 :             pDestBrd = new SvtBroadcaster;
    3615           0 :             itDestPos = rDestCol.maBroadcasters.set(itDestPos, nDestRow, pDestBrd);
    3616             :         }
    3617             : 
    3618             :         // Transfer all listeners from the source to the destination.
    3619           0 :         SvtBroadcaster::ListenersType::iterator it2 = rEntry.maListeners.begin(), it2End = rEntry.maListeners.end();
    3620           0 :         for (; it2 != it2End; ++it2)
    3621             :         {
    3622           0 :             SvtListener* pLis = *it2;
    3623           0 :             pLis->StartListening(*pDestBrd);
    3624             :         }
    3625             :     }
    3626             : 
    3627             :     // Remove any broadcasters that have no listeners.
    3628           0 :     RemoveEmptyBroadcasterHandler aFuncRemoveEmpty(*pDocument, nCol, nTab);
    3629           0 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFuncRemoveEmpty);
    3630           0 :     aFuncRemoveEmpty.purge();
    3631             : }
    3632             : 
    3633           0 : void ScColumn::CalcAll()
    3634             : {
    3635             :     CalcAllHandler aFunc;
    3636           0 :     sc::ProcessFormula(maCells, aFunc);
    3637           0 : }
    3638             : 
    3639           0 : void ScColumn::CompileAll( sc::CompileFormulaContext& rCxt )
    3640             : {
    3641           0 :     CompileAllHandler aFunc(rCxt);
    3642           0 :     sc::ProcessFormula(maCells, aFunc);
    3643           0 : }
    3644             : 
    3645           0 : void ScColumn::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress )
    3646             : {
    3647           0 :     CompileXMLHandler aFunc(rCxt, rProgress, *this);
    3648           0 :     sc::ProcessFormula(maCells, aFunc);
    3649           0 :     RegroupFormulaCells();
    3650           0 : }
    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           0 : void ScColumn::CalcAfterLoad( sc::CompileFormulaContext& rCxt )
    3660             : {
    3661           0 :     CalcAfterLoadHandler aFunc(rCxt);
    3662           0 :     sc::ProcessFormula(maCells, aFunc);
    3663           0 : }
    3664             : 
    3665           0 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
    3666             : {
    3667             :     ResetChangedHandler aFunc;
    3668           0 :     sc::ProcessFormula(maCells.begin(), maCells, nStartRow, nEndRow, aFunc);
    3669           0 : }
    3670             : 
    3671           0 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
    3672             : {
    3673             :     //  used in GetOptimalHeight - ambiguous script type counts as edit cell
    3674             : 
    3675           0 :     FindEditCellsHandler aFunc(*this, maCellTextAttrs, maCells.begin());
    3676             :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos =
    3677           0 :         sc::FindFormulaEditText(maCells, nStartRow, nEndRow, aFunc);
    3678             : 
    3679           0 :     if (aPos.first == maCells.end())
    3680           0 :         return false;
    3681             : 
    3682           0 :     rFirst = aPos.first->position + aPos.second;
    3683           0 :     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           0 : }
    3718             : 
    3719             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10